schematex 0.9.7 → 0.9.8

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 (172) hide show
  1. package/README.md +43 -3
  2. package/dist/ai/ai-sdk.cjs +23 -23
  3. package/dist/ai/ai-sdk.d.cts +3 -3
  4. package/dist/ai/ai-sdk.d.ts +3 -3
  5. package/dist/ai/ai-sdk.js +18 -18
  6. package/dist/ai/index.cjs +32 -32
  7. package/dist/ai/index.d.cts +4 -4
  8. package/dist/ai/index.d.ts +4 -4
  9. package/dist/ai/index.js +19 -19
  10. package/dist/{api-BOJJlNb1.d.ts → api-D_d-JklT.d.ts} +1 -1
  11. package/dist/{api-v9t1T1v6.d.cts → api-DnTyW-6F.d.cts} +1 -1
  12. package/dist/browser.cjs +24 -24
  13. package/dist/browser.d.cts +3 -3
  14. package/dist/browser.d.ts +3 -3
  15. package/dist/browser.js +18 -18
  16. package/dist/{chunk-6QZQTASC.cjs → chunk-246OJILS.cjs} +12 -12
  17. package/dist/{chunk-6QZQTASC.cjs.map → chunk-246OJILS.cjs.map} +1 -1
  18. package/dist/{chunk-JEMAOC2D.js → chunk-2IRYXK4M.js} +3 -3
  19. package/dist/{chunk-JEMAOC2D.js.map → chunk-2IRYXK4M.js.map} +1 -1
  20. package/dist/{chunk-ECHPMEZX.cjs → chunk-2LVU75P3.cjs} +145 -6
  21. package/dist/chunk-2LVU75P3.cjs.map +1 -0
  22. package/dist/{chunk-DVRB64CN.js → chunk-33BFUEYU.js} +143 -4
  23. package/dist/chunk-33BFUEYU.js.map +1 -0
  24. package/dist/{chunk-ITI3STJ6.cjs → chunk-3JN4762U.cjs} +4 -4
  25. package/dist/{chunk-ITI3STJ6.cjs.map → chunk-3JN4762U.cjs.map} +1 -1
  26. package/dist/{chunk-GAQ36VFD.cjs → chunk-4MANMKQ4.cjs} +4 -4
  27. package/dist/{chunk-GAQ36VFD.cjs.map → chunk-4MANMKQ4.cjs.map} +1 -1
  28. package/dist/{chunk-3K4WCRVI.js → chunk-4QLIFOKH.js} +1790 -550
  29. package/dist/chunk-4QLIFOKH.js.map +1 -0
  30. package/dist/{chunk-64LABNTF.js → chunk-7NO5LYLL.js} +3 -3
  31. package/dist/{chunk-64LABNTF.js.map → chunk-7NO5LYLL.js.map} +1 -1
  32. package/dist/{chunk-ENUM7GMZ.cjs → chunk-7OOUU6BL.cjs} +147 -2
  33. package/dist/chunk-7OOUU6BL.cjs.map +1 -0
  34. package/dist/{chunk-M26ORU4P.js → chunk-AETIGJXP.js} +3 -3
  35. package/dist/{chunk-M26ORU4P.js.map → chunk-AETIGJXP.js.map} +1 -1
  36. package/dist/{chunk-6X7MVZZT.cjs → chunk-BEPVTFXK.cjs} +1993 -752
  37. package/dist/chunk-BEPVTFXK.cjs.map +1 -0
  38. package/dist/{chunk-OJ3P4IC4.cjs → chunk-DLXDR2E7.cjs} +4 -4
  39. package/dist/{chunk-OJ3P4IC4.cjs.map → chunk-DLXDR2E7.cjs.map} +1 -1
  40. package/dist/{chunk-3J4DZPZC.js → chunk-EB7T5SEO.js} +3 -3
  41. package/dist/{chunk-3J4DZPZC.js.map → chunk-EB7T5SEO.js.map} +1 -1
  42. package/dist/{chunk-VY6UZYYL.cjs → chunk-F5RYWDWO.cjs} +15 -15
  43. package/dist/{chunk-VY6UZYYL.cjs.map → chunk-F5RYWDWO.cjs.map} +1 -1
  44. package/dist/{chunk-INVLJYAE.cjs → chunk-GTCGATOL.cjs} +4 -4
  45. package/dist/{chunk-INVLJYAE.cjs.map → chunk-GTCGATOL.cjs.map} +1 -1
  46. package/dist/{chunk-ZCHGIWJK.js → chunk-HIWJMJJB.js} +3 -3
  47. package/dist/{chunk-ZCHGIWJK.js.map → chunk-HIWJMJJB.js.map} +1 -1
  48. package/dist/{chunk-RDYACU2G.js → chunk-IHX6J4HF.js} +3 -3
  49. package/dist/{chunk-RDYACU2G.js.map → chunk-IHX6J4HF.js.map} +1 -1
  50. package/dist/{chunk-4MRVJI7G.js → chunk-JVNV2T2T.js} +147 -3
  51. package/dist/chunk-JVNV2T2T.js.map +1 -0
  52. package/dist/{chunk-SXOAAQNY.js → chunk-KUSW5I2P.js} +3 -3
  53. package/dist/{chunk-SXOAAQNY.js.map → chunk-KUSW5I2P.js.map} +1 -1
  54. package/dist/{chunk-35NGXDT2.cjs → chunk-KYE7CRED.cjs} +12 -12
  55. package/dist/{chunk-35NGXDT2.cjs.map → chunk-KYE7CRED.cjs.map} +1 -1
  56. package/dist/{chunk-II4GLKGF.js → chunk-MVTYPWHO.js} +3 -3
  57. package/dist/chunk-MVTYPWHO.js.map +1 -0
  58. package/dist/{chunk-N3HU635X.cjs → chunk-MXV3XJFH.cjs} +4 -4
  59. package/dist/chunk-MXV3XJFH.cjs.map +1 -0
  60. package/dist/{chunk-XCCXG6RR.js → chunk-NB7MFQCZ.js} +3 -3
  61. package/dist/{chunk-XCCXG6RR.js.map → chunk-NB7MFQCZ.js.map} +1 -1
  62. package/dist/{chunk-GYYYULBL.js → chunk-NP7N3DZG.js} +3 -3
  63. package/dist/{chunk-GYYYULBL.js.map → chunk-NP7N3DZG.js.map} +1 -1
  64. package/dist/{chunk-3PH2MQGN.js → chunk-P4U565XH.js} +3 -3
  65. package/dist/{chunk-3PH2MQGN.js.map → chunk-P4U565XH.js.map} +1 -1
  66. package/dist/{chunk-VYQXB2RC.cjs → chunk-QC2RICQ4.cjs} +12 -12
  67. package/dist/{chunk-VYQXB2RC.cjs.map → chunk-QC2RICQ4.cjs.map} +1 -1
  68. package/dist/{chunk-3WX24RCH.js → chunk-QMJHLDGY.js} +3 -3
  69. package/dist/{chunk-3WX24RCH.js.map → chunk-QMJHLDGY.js.map} +1 -1
  70. package/dist/{chunk-C4Y24X3U.cjs → chunk-T55OQILI.cjs} +4 -4
  71. package/dist/{chunk-C4Y24X3U.cjs.map → chunk-T55OQILI.cjs.map} +1 -1
  72. package/dist/{chunk-6ZD7TCWO.cjs → chunk-TFUVNQNA.cjs} +15 -15
  73. package/dist/{chunk-6ZD7TCWO.cjs.map → chunk-TFUVNQNA.cjs.map} +1 -1
  74. package/dist/{chunk-4AC6I7KJ.cjs → chunk-TXWVJAMR.cjs} +4 -4
  75. package/dist/{chunk-4AC6I7KJ.cjs.map → chunk-TXWVJAMR.cjs.map} +1 -1
  76. package/dist/{chunk-4OC3CTGE.cjs → chunk-UHRNFBWY.cjs} +4 -4
  77. package/dist/{chunk-4OC3CTGE.cjs.map → chunk-UHRNFBWY.cjs.map} +1 -1
  78. package/dist/{chunk-B4CMWA6Y.js → chunk-W4UVDMUC.js} +3 -3
  79. package/dist/{chunk-B4CMWA6Y.js.map → chunk-W4UVDMUC.js.map} +1 -1
  80. package/dist/{chunk-5ZQRHDMQ.cjs → chunk-YDEQZSPQ.cjs} +4 -4
  81. package/dist/{chunk-5ZQRHDMQ.cjs.map → chunk-YDEQZSPQ.cjs.map} +1 -1
  82. package/dist/{chunk-627GHE2N.cjs → chunk-YFPDZVB7.cjs} +5 -5
  83. package/dist/{chunk-627GHE2N.cjs.map → chunk-YFPDZVB7.cjs.map} +1 -1
  84. package/dist/{chunk-NKYR4PAS.js → chunk-YXEPF3SL.js} +3 -3
  85. package/dist/{chunk-NKYR4PAS.js.map → chunk-YXEPF3SL.js.map} +1 -1
  86. package/dist/{chunk-AXMBXAEA.js → chunk-ZRFKIERV.js} +3 -3
  87. package/dist/{chunk-AXMBXAEA.js.map → chunk-ZRFKIERV.js.map} +1 -1
  88. package/dist/{diagnostics-5bVLlGNj.d.cts → diagnostics-D2qkBfFx.d.cts} +1 -1
  89. package/dist/{diagnostics-5bVLlGNj.d.ts → diagnostics-D2qkBfFx.d.ts} +1 -1
  90. package/dist/diagrams/blockdiagram/index.cjs +6 -6
  91. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  92. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  93. package/dist/diagrams/blockdiagram/index.js +2 -2
  94. package/dist/diagrams/circuit/index.cjs +9 -9
  95. package/dist/diagrams/circuit/index.d.cts +1 -1
  96. package/dist/diagrams/circuit/index.d.ts +1 -1
  97. package/dist/diagrams/circuit/index.js +2 -2
  98. package/dist/diagrams/ecomap/index.cjs +7 -7
  99. package/dist/diagrams/ecomap/index.d.cts +1 -1
  100. package/dist/diagrams/ecomap/index.d.ts +1 -1
  101. package/dist/diagrams/ecomap/index.js +2 -2
  102. package/dist/diagrams/entity/index.cjs +6 -6
  103. package/dist/diagrams/entity/index.d.cts +1 -1
  104. package/dist/diagrams/entity/index.d.ts +1 -1
  105. package/dist/diagrams/entity/index.js +2 -2
  106. package/dist/diagrams/fishbone/index.cjs +8 -8
  107. package/dist/diagrams/fishbone/index.d.cts +1 -1
  108. package/dist/diagrams/fishbone/index.d.ts +1 -1
  109. package/dist/diagrams/fishbone/index.js +2 -2
  110. package/dist/diagrams/flowchart/index.cjs +8 -8
  111. package/dist/diagrams/flowchart/index.d.cts +2 -2
  112. package/dist/diagrams/flowchart/index.d.ts +2 -2
  113. package/dist/diagrams/flowchart/index.js +2 -2
  114. package/dist/diagrams/genogram/index.cjs +9 -9
  115. package/dist/diagrams/genogram/index.d.cts +1 -1
  116. package/dist/diagrams/genogram/index.d.ts +1 -1
  117. package/dist/diagrams/genogram/index.js +2 -2
  118. package/dist/diagrams/ladder/index.cjs +6 -6
  119. package/dist/diagrams/ladder/index.d.cts +1 -1
  120. package/dist/diagrams/ladder/index.d.ts +1 -1
  121. package/dist/diagrams/ladder/index.js +2 -2
  122. package/dist/diagrams/logic/index.cjs +8 -8
  123. package/dist/diagrams/logic/index.d.cts +1 -1
  124. package/dist/diagrams/logic/index.d.ts +1 -1
  125. package/dist/diagrams/logic/index.js +2 -2
  126. package/dist/diagrams/orgchart/index.cjs +8 -8
  127. package/dist/diagrams/orgchart/index.d.cts +1 -1
  128. package/dist/diagrams/orgchart/index.d.ts +1 -1
  129. package/dist/diagrams/orgchart/index.js +2 -2
  130. package/dist/diagrams/pedigree/index.cjs +7 -7
  131. package/dist/diagrams/pedigree/index.d.cts +1 -1
  132. package/dist/diagrams/pedigree/index.d.ts +1 -1
  133. package/dist/diagrams/pedigree/index.js +2 -2
  134. package/dist/diagrams/phylo/index.cjs +7 -7
  135. package/dist/diagrams/phylo/index.d.cts +1 -1
  136. package/dist/diagrams/phylo/index.d.ts +1 -1
  137. package/dist/diagrams/phylo/index.js +2 -2
  138. package/dist/diagrams/sld/index.cjs +8 -8
  139. package/dist/diagrams/sld/index.d.cts +1 -1
  140. package/dist/diagrams/sld/index.d.ts +1 -1
  141. package/dist/diagrams/sld/index.js +2 -2
  142. package/dist/diagrams/sociogram/index.cjs +6 -6
  143. package/dist/diagrams/sociogram/index.d.cts +1 -1
  144. package/dist/diagrams/sociogram/index.d.ts +1 -1
  145. package/dist/diagrams/sociogram/index.js +2 -2
  146. package/dist/diagrams/timing/index.d.cts +1 -1
  147. package/dist/diagrams/timing/index.d.ts +1 -1
  148. package/dist/diagrams/venn/index.cjs +9 -9
  149. package/dist/diagrams/venn/index.d.cts +1 -1
  150. package/dist/diagrams/venn/index.d.ts +1 -1
  151. package/dist/diagrams/venn/index.js +2 -2
  152. package/dist/{index-syc0E5Ss.d.ts → index-D9u0YRxL.d.ts} +1 -1
  153. package/dist/{index-Cmf4Rcve.d.cts → index-JZlLiE6K.d.cts} +1 -1
  154. package/dist/index.cjs +91 -87
  155. package/dist/index.d.cts +7 -5
  156. package/dist/index.d.ts +7 -5
  157. package/dist/index.js +22 -22
  158. package/dist/react.cjs +18 -18
  159. package/dist/react.d.cts +2 -2
  160. package/dist/react.d.ts +2 -2
  161. package/dist/react.js +17 -17
  162. package/dist/{tools-B98iarLm.d.cts → tools-DAKYNcPv.d.cts} +2 -2
  163. package/dist/{tools-CCZ1IcIN.d.ts → tools-DM0aLCbc.d.ts} +2 -2
  164. package/package.json +1 -1
  165. package/dist/chunk-3K4WCRVI.js.map +0 -1
  166. package/dist/chunk-4MRVJI7G.js.map +0 -1
  167. package/dist/chunk-6X7MVZZT.cjs.map +0 -1
  168. package/dist/chunk-DVRB64CN.js.map +0 -1
  169. package/dist/chunk-ECHPMEZX.cjs.map +0 -1
  170. package/dist/chunk-ENUM7GMZ.cjs.map +0 -1
  171. package/dist/chunk-II4GLKGF.js.map +0 -1
  172. package/dist/chunk-N3HU635X.cjs.map +0 -1
@@ -1,21 +1,21 @@
1
- import { orgchart } from './chunk-3J4DZPZC.js';
2
- import { circuit } from './chunk-RDYACU2G.js';
3
- import { blockdiagram } from './chunk-3PH2MQGN.js';
4
- import { ladder } from './chunk-B4CMWA6Y.js';
5
- import { sld } from './chunk-II4GLKGF.js';
6
- import { entity } from './chunk-JEMAOC2D.js';
7
- import { fishbone } from './chunk-GYYYULBL.js';
8
- import { venn } from './chunk-SXOAAQNY.js';
9
- import { flowchart, layoutFlowchart } from './chunk-AXMBXAEA.js';
10
- import { genogram } from './chunk-M26ORU4P.js';
11
- import { ecomap, estimateTextWidth } from './chunk-XCCXG6RR.js';
12
- import { pedigree } from './chunk-ZCHGIWJK.js';
1
+ import { orgchart } from './chunk-EB7T5SEO.js';
2
+ import { circuit } from './chunk-IHX6J4HF.js';
3
+ import { blockdiagram } from './chunk-P4U565XH.js';
4
+ import { ladder } from './chunk-W4UVDMUC.js';
5
+ import { sld } from './chunk-MVTYPWHO.js';
6
+ import { entity } from './chunk-2IRYXK4M.js';
7
+ import { fishbone } from './chunk-NP7N3DZG.js';
8
+ import { venn } from './chunk-KUSW5I2P.js';
9
+ import { flowchart, layoutFlowchart } from './chunk-ZRFKIERV.js';
10
+ import { genogram } from './chunk-AETIGJXP.js';
11
+ import { ecomap, estimateTextWidth } from './chunk-NB7MFQCZ.js';
12
+ import { pedigree } from './chunk-HIWJMJJB.js';
13
13
  import { parseFrontmatter } from './chunk-2KTQ75LN.js';
14
- import { phylo } from './chunk-3WX24RCH.js';
15
- import { sociogram } from './chunk-64LABNTF.js';
14
+ import { phylo } from './chunk-QMJHLDGY.js';
15
+ import { sociogram } from './chunk-7NO5LYLL.js';
16
16
  import { timing } from './chunk-MTIZIHWE.js';
17
- import { logic } from './chunk-NKYR4PAS.js';
18
- import { resolveBaseTheme, resolveTimelineTheme, resolveStateTheme, cssCustomProperties, resolvePetriTheme, resolveNetworkTheme, resolveUmlClassTheme, DEFAULT_FONT_FAMILY, FONT_SIZE, resolveReliabilityTheme, STROKE_WIDTH, resolveBowtieTheme, resolveMindmapTheme, resolveMatrixTheme, resolveBpmnTheme, resolveFloorplanTheme, TITLE, resolvePlaybookTheme } from './chunk-4MRVJI7G.js';
17
+ import { logic } from './chunk-YXEPF3SL.js';
18
+ import { resolveBaseTheme, resolveTimelineTheme, resolveStateTheme, cssCustomProperties, resolvePetriTheme, resolveNetworkTheme, resolveUmlClassTheme, DEFAULT_FONT_FAMILY, FONT_SIZE, resolveReliabilityTheme, STROKE_WIDTH, resolveBowtieTheme, resolveComparisonTheme, TITLE, resolveMindmapTheme, resolveMatrixTheme, resolveBpmnTheme, resolveFloorplanTheme, resolvePlaybookTheme } from './chunk-JVNV2T2T.js';
19
19
  import { QUOTE_PAIRS, stripQuotes, isOpenQuote, extractQuotedString, matchQuotedTitle } from './chunk-TO6PNBT3.js';
20
20
  import { el, escapeXml, group, rect, text, line, path, circle, polygon, title, desc, svgRoot, defs, multilineText } from './chunk-SYYBKDL7.js';
21
21
 
@@ -1613,8 +1613,8 @@ function renderDecisionTree(ast, config) {
1613
1613
  lx += nx * perpOffset * flip;
1614
1614
  ly += ny * perpOffset * flip;
1615
1615
  }
1616
- const charW = isProb ? 5.5 : 6.2;
1617
- const w = Math.max(e.label.length * charW + 10, 18);
1616
+ const charW2 = isProb ? 5.5 : 6.2;
1617
+ const w = Math.max(e.label.length * charW2 + 10, 18);
1618
1618
  const h = 14;
1619
1619
  inner.push(rect({
1620
1620
  x: lx - w / 2,
@@ -7603,8 +7603,8 @@ function renderBox(box2) {
7603
7603
  );
7604
7604
  }
7605
7605
  function approxLineWidth(line2) {
7606
- const charW = line2.style === "label" || line2.style === "count" ? 7.4 : 6.4;
7607
- return line2.text.length * charW;
7606
+ const charW2 = line2.style === "label" || line2.style === "count" ? 7.4 : 6.4;
7607
+ return line2.text.length * charW2;
7608
7608
  }
7609
7609
  function renderPrismaLayout(layout, config) {
7610
7610
  const t = resolveBaseTheme(config?.theme ?? "default");
@@ -8271,35 +8271,35 @@ function ellipsePerimeterPoint(cx, cy, rx, ry, tx, ty) {
8271
8271
  function isWideGlyph(cp) {
8272
8272
  return cp >= 12288 && cp <= 40959 || cp >= 44032 && cp <= 55203 || cp >= 65280 && cp <= 65519;
8273
8273
  }
8274
- function estimateTextWidth2(s, charW) {
8274
+ function estimateTextWidth2(s, charW2) {
8275
8275
  let w = 0;
8276
8276
  for (const ch of s) {
8277
- w += isWideGlyph(ch.codePointAt(0) ?? 0) ? charW * 1.7 : charW;
8277
+ w += isWideGlyph(ch.codePointAt(0) ?? 0) ? charW2 * 1.7 : charW2;
8278
8278
  }
8279
8279
  return w;
8280
8280
  }
8281
8281
  function sizeEllipse(uc) {
8282
- const C2 = USECASE_CONST;
8283
- const nameW = estimateTextWidth2(uc.name, C2.CHAR_W_NAME);
8282
+ const C3 = USECASE_CONST;
8283
+ const nameW = estimateTextWidth2(uc.name, C3.CHAR_W_NAME);
8284
8284
  let widest = nameW;
8285
8285
  if (uc.stereotype) {
8286
- widest = Math.max(widest, estimateTextWidth2(`\xAB${uc.stereotype}\xBB`, C2.CHAR_W_EXT));
8286
+ widest = Math.max(widest, estimateTextWidth2(`\xAB${uc.stereotype}\xBB`, C3.CHAR_W_EXT));
8287
8287
  }
8288
8288
  let stack = 0;
8289
- if (uc.stereotype) stack += C2.STEREO_LH;
8290
- stack += C2.NAME_LH;
8289
+ if (uc.stereotype) stack += C3.STEREO_LH;
8290
+ stack += C3.NAME_LH;
8291
8291
  const hasExt = uc.extensionPoints.length > 0;
8292
8292
  if (hasExt) {
8293
8293
  stack += 8;
8294
- stack += C2.EXTPOINT_LH;
8295
- stack += uc.extensionPoints.length * C2.EXTPOINT_LH;
8296
- widest = Math.max(widest, estimateTextWidth2(C2.EXT_HEADER, C2.CHAR_W_EXT));
8294
+ stack += C3.EXTPOINT_LH;
8295
+ stack += uc.extensionPoints.length * C3.EXTPOINT_LH;
8296
+ widest = Math.max(widest, estimateTextWidth2(C3.EXT_HEADER, C3.CHAR_W_EXT));
8297
8297
  for (const ep of uc.extensionPoints) {
8298
- widest = Math.max(widest, estimateTextWidth2(ep, C2.CHAR_W_EXT) + 16);
8298
+ widest = Math.max(widest, estimateTextWidth2(ep, C3.CHAR_W_EXT) + 16);
8299
8299
  }
8300
8300
  }
8301
- const rx = Math.max(C2.MIN_RX, widest / 2 * Math.SQRT2 + C2.ELLIPSE_PAD_X);
8302
- const ry = Math.max(C2.MIN_RY, stack / 2 * Math.SQRT2 + C2.ELLIPSE_PAD_Y);
8301
+ const rx = Math.max(C3.MIN_RX, widest / 2 * Math.SQRT2 + C3.ELLIPSE_PAD_X);
8302
+ const ry = Math.max(C3.MIN_RY, stack / 2 * Math.SQRT2 + C3.ELLIPSE_PAD_Y);
8303
8303
  const result = {
8304
8304
  rx: Math.round(rx),
8305
8305
  ry: Math.round(ry)
@@ -8384,7 +8384,7 @@ function classifyActorSides(ast) {
8384
8384
  return sides;
8385
8385
  }
8386
8386
  function layoutUsecase(ast) {
8387
- const C2 = USECASE_CONST;
8387
+ const C3 = USECASE_CONST;
8388
8388
  const ucIds = new Set(ast.usecases.map((u) => u.id));
8389
8389
  const actorById = new Map(ast.actors.map((a) => [a.id, a]));
8390
8390
  const sizes = /* @__PURE__ */ new Map();
@@ -8447,18 +8447,18 @@ function layoutUsecase(ast) {
8447
8447
  }
8448
8448
  }
8449
8449
  const colMaxRx = columns.map(
8450
- (col) => col.reduce((m, u) => Math.max(m, sizes.get(u.id).rx), C2.MIN_RX)
8450
+ (col) => col.reduce((m, u) => Math.max(m, sizes.get(u.id).rx), C3.MIN_RX)
8451
8451
  );
8452
8452
  const colCenterX = [];
8453
8453
  let cursorX = 0;
8454
8454
  for (let d = 0; d <= maxDepth; d++) {
8455
8455
  cursorX += colMaxRx[d];
8456
8456
  colCenterX[d] = cursorX;
8457
- cursorX += colMaxRx[d] + C2.COL_GAP;
8457
+ cursorX += colMaxRx[d] + C3.COL_GAP;
8458
8458
  }
8459
- let maxRy = C2.MIN_RY;
8459
+ let maxRy = C3.MIN_RY;
8460
8460
  for (const s of sizes.values()) maxRy = Math.max(maxRy, s.ry);
8461
- const rowPitch = Math.max(C2.ROW_PITCH, 2 * maxRy + C2.ROW_GAP_MIN);
8461
+ const rowPitch = Math.max(C3.ROW_PITCH, 2 * maxRy + C3.ROW_GAP_MIN);
8462
8462
  const ellipses = [];
8463
8463
  const ellById = /* @__PURE__ */ new Map();
8464
8464
  for (let d = 0; d <= maxDepth; d++) {
@@ -8481,7 +8481,7 @@ function layoutUsecase(ast) {
8481
8481
  for (let i = 1; i < colE.length; i++) {
8482
8482
  const prev = colE[i - 1];
8483
8483
  const cur = colE[i];
8484
- const minGap = prev.ry + cur.ry + C2.ROW_GAP_MIN;
8484
+ const minGap = prev.ry + cur.ry + C3.ROW_GAP_MIN;
8485
8485
  if (cur.cy - prev.cy < minGap) {
8486
8486
  cur.cy = prev.cy + minGap;
8487
8487
  if (cur.dividerY !== void 0) cur.dividerY = cur.cy + 6;
@@ -8502,10 +8502,10 @@ function layoutUsecase(ast) {
8502
8502
  ucMaxY = 100;
8503
8503
  }
8504
8504
  const hasSubject = !!ast.system;
8505
- const subjLeft = ucMinX - C2.SUBJECT_PAD;
8506
- const subjRight = ucMaxX + C2.SUBJECT_PAD;
8507
- const subjTop = ucMinY - C2.SUBJECT_TOP_PAD;
8508
- const subjBottom = ucMaxY + C2.SUBJECT_BOTTOM_PAD;
8505
+ const subjLeft = ucMinX - C3.SUBJECT_PAD;
8506
+ const subjRight = ucMaxX + C3.SUBJECT_PAD;
8507
+ const subjTop = ucMinY - C3.SUBJECT_TOP_PAD;
8508
+ const subjBottom = ucMaxY + C3.SUBJECT_BOTTOM_PAD;
8509
8509
  const leftActors = ast.actors.filter((a) => sides.get(a.id) === "left");
8510
8510
  const rightActors = ast.actors.filter((a) => sides.get(a.id) === "right");
8511
8511
  const actorBoxes = [];
@@ -8513,17 +8513,17 @@ function layoutUsecase(ast) {
8513
8513
  const subjCenterY = (subjTop + subjBottom) / 2;
8514
8514
  function placeStack(actors, side) {
8515
8515
  if (actors.length === 0) return;
8516
- const totalH = (actors.length - 1) * C2.ACTOR_PITCH;
8516
+ const totalH = (actors.length - 1) * C3.ACTOR_PITCH;
8517
8517
  let cy = subjCenterY - totalH / 2;
8518
8518
  for (const a of actors) {
8519
8519
  const isRect = a.kind === "external" || a.kind === "system";
8520
- const w = isRect ? C2.EXTERNAL_W : C2.ACTOR_W;
8521
- const h = isRect ? C2.EXTERNAL_H : C2.ACTOR_H;
8520
+ const w = isRect ? C3.EXTERNAL_W : C3.ACTOR_W;
8521
+ const h = isRect ? C3.EXTERNAL_H : C3.ACTOR_H;
8522
8522
  let x;
8523
8523
  if (side === "left") {
8524
- x = subjLeft - C2.ACTOR_GAP - w;
8524
+ x = subjLeft - C3.ACTOR_GAP - w;
8525
8525
  } else {
8526
- x = subjRight + C2.ACTOR_GAP;
8526
+ x = subjRight + C3.ACTOR_GAP;
8527
8527
  }
8528
8528
  const y = cy - h / 2;
8529
8529
  const anchorX = side === "left" ? x + w : x;
@@ -8540,7 +8540,7 @@ function layoutUsecase(ast) {
8540
8540
  };
8541
8541
  actorBoxes.push(box2);
8542
8542
  actorById2.set(a.id, box2);
8543
- cy += C2.ACTOR_PITCH;
8543
+ cy += C3.ACTOR_PITCH;
8544
8544
  }
8545
8545
  }
8546
8546
  placeStack(leftActors, "left");
@@ -8559,11 +8559,11 @@ function layoutUsecase(ast) {
8559
8559
  minX = Math.min(minX, left);
8560
8560
  maxX = Math.max(maxX, right);
8561
8561
  minY = Math.min(minY, b.y);
8562
- maxY = Math.max(maxY, b.y + b.height + C2.ACTOR_LABEL_H);
8562
+ maxY = Math.max(maxY, b.y + b.height + C3.ACTOR_LABEL_H);
8563
8563
  }
8564
- const titleSpace = ast.title ? C2.TITLE_H : 0;
8565
- const offsetX = C2.MARGIN - minX;
8566
- const offsetY = C2.MARGIN + titleSpace - minY;
8564
+ const titleSpace = ast.title ? C3.TITLE_H : 0;
8565
+ const offsetX = C3.MARGIN - minX;
8566
+ const offsetY = C3.MARGIN + titleSpace - minY;
8567
8567
  const translate = (px, py) => ({ x: px + offsetX, y: py + offsetY });
8568
8568
  for (const e of ellipses) {
8569
8569
  const p = translate(e.cx, e.cy);
@@ -8584,8 +8584,8 @@ function layoutUsecase(ast) {
8584
8584
  height: subjBottom - subjTop
8585
8585
  } : void 0;
8586
8586
  if (subject && ast.system) subject.name = ast.system;
8587
- const width = maxX - minX + 2 * C2.MARGIN;
8588
- const height = maxY - minY + 2 * C2.MARGIN + titleSpace;
8587
+ const width = maxX - minX + 2 * C3.MARGIN;
8588
+ const height = maxY - minY + 2 * C3.MARGIN + titleSpace;
8589
8589
  const edges = [];
8590
8590
  const trees = [];
8591
8591
  const genByParent = /* @__PURE__ */ new Map();
@@ -8625,7 +8625,7 @@ function layoutUsecase(ast) {
8625
8625
  return { x, y };
8626
8626
  }
8627
8627
  for (const [parentId, rels] of genByParent) {
8628
- const useTree = ast.generalizationTree && rels.length >= C2.GEN_TREE_THRESHOLD;
8628
+ const useTree = ast.generalizationTree && rels.length >= C3.GEN_TREE_THRESHOLD;
8629
8629
  const allActors = actorById2.has(parentId) && rels.every((r7) => actorById2.has(r7.source));
8630
8630
  if (allActors) {
8631
8631
  const side = sides.get(parentId) ?? "left";
@@ -8677,8 +8677,8 @@ function layoutUsecase(ast) {
8677
8677
  const dirX = avgX - parent.cx;
8678
8678
  const dirY = avgY - parent.cy;
8679
8679
  const len = Math.hypot(dirX, dirY) || 1;
8680
- const jx = pPt.x + dirX / len * C2.GEN_JUNCTION_OFFSET;
8681
- const jy = pPt.y + dirY / len * C2.GEN_JUNCTION_OFFSET;
8680
+ const jx = pPt.x + dirX / len * C3.GEN_JUNCTION_OFFSET;
8681
+ const jy = pPt.y + dirY / len * C3.GEN_JUNCTION_OFFSET;
8682
8682
  const legPaths = [];
8683
8683
  for (const r7 of rels) {
8684
8684
  const cPt = perimeter(r7.source, jx, jy);
@@ -10113,7 +10113,7 @@ function routeEdge2(s, t, direction) {
10113
10113
  return { d, labelX: mid, labelY: (sy + ty) / 2 };
10114
10114
  }
10115
10115
  function layoutNetwork(ast, schedule) {
10116
- const C2 = PERT_CONST;
10116
+ const C3 = PERT_CONST;
10117
10117
  const { rank, maxRank } = assignRanks(ast);
10118
10118
  const layers = orderLayers(ast, schedule, rank, maxRank);
10119
10119
  const dir = ast.direction;
@@ -10122,16 +10122,16 @@ function layoutNetwork(ast, schedule) {
10122
10122
  const colExtent = layers.map((layer) => {
10123
10123
  const n = layer.length;
10124
10124
  if (n === 0) return 0;
10125
- const unit = dir === "TB" ? C2.BOX_W : C2.BOX_H;
10126
- const gap = dir === "TB" ? C2.H_GAP : C2.V_GAP;
10125
+ const unit = dir === "TB" ? C3.BOX_W : C3.BOX_H;
10126
+ const gap = dir === "TB" ? C3.H_GAP : C3.V_GAP;
10127
10127
  return n * unit + (n - 1) * gap;
10128
10128
  });
10129
10129
  const maxExtent = Math.max(0, ...colExtent);
10130
10130
  const hasSentinels = ast.showSentinels;
10131
- const sentLead = hasSentinels ? C2.SENT_R * 2 + C2.H_GAP : 0;
10132
- const titleH = ast.title ? C2.TITLE_H : 0;
10133
- const originPrimary = dir === "TB" ? C2.PAD + titleH + sentLead : C2.PAD + sentLead;
10134
- const originCross = dir === "TB" ? C2.PAD : C2.PAD + titleH;
10131
+ const sentLead = hasSentinels ? C3.SENT_R * 2 + C3.H_GAP : 0;
10132
+ const titleH = ast.title ? C3.TITLE_H : 0;
10133
+ const originPrimary = dir === "TB" ? C3.PAD + titleH + sentLead : C3.PAD + sentLead;
10134
+ const originCross = dir === "TB" ? C3.PAD : C3.PAD + titleH;
10135
10135
  const boxes = [];
10136
10136
  const boxById = /* @__PURE__ */ new Map();
10137
10137
  for (let r7 = 0; r7 <= maxRank; r7++) {
@@ -10142,20 +10142,20 @@ function layoutNetwork(ast, schedule) {
10142
10142
  for (const id of layer) {
10143
10143
  const t = byId.get(id);
10144
10144
  const computed = schedule.computed.get(id);
10145
- const w = t.milestone ? C2.MS_W : C2.BOX_W;
10146
- const h = C2.BOX_H;
10145
+ const w = t.milestone ? C3.MS_W : C3.BOX_W;
10146
+ const h = C3.BOX_H;
10147
10147
  let x;
10148
10148
  let y;
10149
10149
  if (dir === "TB") {
10150
- const rankPos = originPrimary + r7 * (C2.BOX_H + C2.H_GAP);
10151
- x = cursor + (C2.BOX_W - w) / 2;
10150
+ const rankPos = originPrimary + r7 * (C3.BOX_H + C3.H_GAP);
10151
+ x = cursor + (C3.BOX_W - w) / 2;
10152
10152
  y = rankPos;
10153
- cursor += C2.BOX_W + C2.H_GAP;
10153
+ cursor += C3.BOX_W + C3.H_GAP;
10154
10154
  } else {
10155
- const rankPos = originPrimary + r7 * (C2.BOX_W + C2.H_GAP);
10156
- x = rankPos + (C2.BOX_W - w) / 2;
10155
+ const rankPos = originPrimary + r7 * (C3.BOX_W + C3.H_GAP);
10156
+ x = rankPos + (C3.BOX_W - w) / 2;
10157
10157
  y = cursor;
10158
- cursor += C2.BOX_H + C2.V_GAP;
10158
+ cursor += C3.BOX_H + C3.V_GAP;
10159
10159
  }
10160
10160
  const box2 = {
10161
10161
  id,
@@ -10202,11 +10202,11 @@ function layoutNetwork(ast, schedule) {
10202
10202
  const sentinels = [];
10203
10203
  if (hasSentinels) {
10204
10204
  const contentMidCross = originCross + maxExtent / 2;
10205
- const startPrimary = C2.PAD + C2.SENT_R;
10206
- const finishPrimary = maxPrimary + C2.H_GAP + C2.SENT_R;
10205
+ const startPrimary = C3.PAD + C3.SENT_R;
10206
+ const finishPrimary = maxPrimary + C3.H_GAP + C3.SENT_R;
10207
10207
  const place = (primary) => dir === "TB" ? { cx: contentMidCross, cy: primary } : { cx: primary, cy: contentMidCross };
10208
- sentinels.push({ id: "__start__", label: "Start", r: C2.SENT_R, ...place(startPrimary) });
10209
- sentinels.push({ id: "__finish__", label: "Finish", r: C2.SENT_R, ...place(finishPrimary) });
10208
+ sentinels.push({ id: "__start__", label: "Start", r: C3.SENT_R, ...place(startPrimary) });
10209
+ sentinels.push({ id: "__finish__", label: "Finish", r: C3.SENT_R, ...place(finishPrimary) });
10210
10210
  const usedAsPred = /* @__PURE__ */ new Set();
10211
10211
  for (const t of ast.tasks) for (const dep of t.deps) usedAsPred.add(dep.pred);
10212
10212
  const startSent = sentinels[0];
@@ -10220,19 +10220,19 @@ function layoutNetwork(ast, schedule) {
10220
10220
  edges.push(sentinelEdge(finishSent, b, dir, false, schedule.computed.get(t.id)));
10221
10221
  }
10222
10222
  }
10223
- maxPrimary = finishPrimary + C2.SENT_R;
10223
+ maxPrimary = finishPrimary + C3.SENT_R;
10224
10224
  }
10225
10225
  const crossEnd = Math.max(maxCross, originCross + maxExtent);
10226
10226
  let width;
10227
10227
  let footerY;
10228
10228
  if (dir === "TB") {
10229
- width = crossEnd + C2.PAD;
10229
+ width = crossEnd + C3.PAD;
10230
10230
  footerY = maxPrimary + 14;
10231
10231
  } else {
10232
- width = maxPrimary + C2.PAD;
10232
+ width = maxPrimary + C3.PAD;
10233
10233
  footerY = crossEnd + 14;
10234
10234
  }
10235
- const height = footerY + C2.FOOTER_H;
10235
+ const height = footerY + C3.FOOTER_H;
10236
10236
  return {
10237
10237
  width: Math.ceil(width),
10238
10238
  height: Math.ceil(height),
@@ -10310,7 +10310,7 @@ function buildDependencyEdges(ast, schedule, boxById, dir) {
10310
10310
  return edges;
10311
10311
  }
10312
10312
  function layoutSwimlane2(ast, schedule) {
10313
- const C2 = PERT_CONST;
10313
+ const C3 = PERT_CONST;
10314
10314
  const { rank, maxRank } = assignRanks(ast);
10315
10315
  const byId = /* @__PURE__ */ new Map();
10316
10316
  for (const t of ast.tasks) byId.set(t.id, t);
@@ -10341,9 +10341,9 @@ function layoutSwimlane2(ast, schedule) {
10341
10341
  return declIndex.get(a) - declIndex.get(b);
10342
10342
  });
10343
10343
  }
10344
- const titleH = ast.title ? C2.TITLE_H : 0;
10345
- const topY = C2.PAD + titleH;
10346
- const colX = (r7) => C2.LANE_LABEL_W + C2.PAD + r7 * (C2.BOX_W + C2.H_GAP);
10344
+ const titleH = ast.title ? C3.TITLE_H : 0;
10345
+ const topY = C3.PAD + titleH;
10346
+ const colX = (r7) => C3.LANE_LABEL_W + C3.PAD + r7 * (C3.BOX_W + C3.H_GAP);
10347
10347
  const lanes = [];
10348
10348
  const laneY = /* @__PURE__ */ new Map();
10349
10349
  const laneH = /* @__PURE__ */ new Map();
@@ -10354,7 +10354,7 @@ function layoutSwimlane2(ast, schedule) {
10354
10354
  const arr = cell.get(key(lane, r7));
10355
10355
  if (arr) stack = Math.max(stack, arr.length);
10356
10356
  }
10357
- const bandH = stack * C2.BOX_H + (stack - 1) * C2.V_GAP + 2 * C2.LANE_PAD;
10357
+ const bandH = stack * C3.BOX_H + (stack - 1) * C3.V_GAP + 2 * C3.LANE_PAD;
10358
10358
  laneY.set(lane, cursor);
10359
10359
  laneH.set(lane, bandH);
10360
10360
  lanes.push({ name: lane, y: cursor, height: bandH, alt: i % 2 === 1 });
@@ -10369,13 +10369,13 @@ function layoutSwimlane2(ast, schedule) {
10369
10369
  for (let r7 = 0; r7 <= maxRank; r7++) {
10370
10370
  const arr = cell.get(key(lane, r7));
10371
10371
  if (!arr) continue;
10372
- const colInnerH = arr.length * C2.BOX_H + (arr.length - 1) * C2.V_GAP;
10372
+ const colInnerH = arr.length * C3.BOX_H + (arr.length - 1) * C3.V_GAP;
10373
10373
  const y0 = bandTop + (bandH - colInnerH) / 2;
10374
10374
  arr.forEach((id, idx) => {
10375
10375
  const t = byId.get(id);
10376
- const w = t.milestone ? C2.MS_W : C2.BOX_W;
10377
- const x = colX(r7) + (C2.BOX_W - w) / 2;
10378
- const y = y0 + idx * (C2.BOX_H + C2.V_GAP);
10376
+ const w = t.milestone ? C3.MS_W : C3.BOX_W;
10377
+ const x = colX(r7) + (C3.BOX_W - w) / 2;
10378
+ const y = y0 + idx * (C3.BOX_H + C3.V_GAP);
10379
10379
  const box2 = {
10380
10380
  id,
10381
10381
  task: t,
@@ -10383,7 +10383,7 @@ function layoutSwimlane2(ast, schedule) {
10383
10383
  x,
10384
10384
  y,
10385
10385
  width: w,
10386
- height: C2.BOX_H,
10386
+ height: C3.BOX_H,
10387
10387
  milestone: t.milestone,
10388
10388
  rank: r7
10389
10389
  };
@@ -10393,9 +10393,9 @@ function layoutSwimlane2(ast, schedule) {
10393
10393
  }
10394
10394
  }
10395
10395
  const edges = buildDependencyEdges(ast, schedule, boxById, "LR");
10396
- const width = colX(maxRank) + C2.BOX_W + C2.PAD;
10396
+ const width = colX(maxRank) + C3.BOX_W + C3.PAD;
10397
10397
  const footerY = contentBottom + 14;
10398
- const height = footerY + C2.FOOTER_H;
10398
+ const height = footerY + C3.FOOTER_H;
10399
10399
  return {
10400
10400
  width: Math.ceil(width),
10401
10401
  height: Math.ceil(height),
@@ -10413,20 +10413,20 @@ function layoutSwimlane2(ast, schedule) {
10413
10413
  };
10414
10414
  }
10415
10415
  function layoutTimescaled(ast, schedule) {
10416
- const C2 = PERT_CONST;
10416
+ const C3 = PERT_CONST;
10417
10417
  const T = schedule.projectDuration || 1;
10418
10418
  const pxPerUnit = Math.min(56, Math.max(16, 1300 / T));
10419
- const titleH = ast.title ? C2.TITLE_H : 0;
10420
- const leftPad = C2.PAD;
10421
- const topPad = C2.PAD + titleH + 14;
10419
+ const titleH = ast.title ? C3.TITLE_H : 0;
10420
+ const leftPad = C3.PAD;
10421
+ const topPad = C3.PAD + titleH + 14;
10422
10422
  const intervals = ast.tasks.map((t) => {
10423
10423
  const c = schedule.computed.get(t.id);
10424
10424
  if (t.milestone) {
10425
10425
  const cx = leftPad + c.es * pxPerUnit;
10426
- return { id: t.id, x: cx - C2.TS_MS_W / 2, w: C2.TS_MS_W };
10426
+ return { id: t.id, x: cx - C3.TS_MS_W / 2, w: C3.TS_MS_W };
10427
10427
  }
10428
10428
  const x = leftPad + c.es * pxPerUnit;
10429
- const w = Math.max(C2.TS_MIN_W, t.duration * pxPerUnit);
10429
+ const w = Math.max(C3.TS_MIN_W, t.duration * pxPerUnit);
10430
10430
  return { id: t.id, x, w };
10431
10431
  });
10432
10432
  intervals.sort((a, b) => a.x - b.x || a.w - b.w);
@@ -10435,7 +10435,7 @@ function layoutTimescaled(ast, schedule) {
10435
10435
  for (const iv of intervals) {
10436
10436
  let placed = -1;
10437
10437
  for (let l = 0; l < laneRight.length; l++) {
10438
- if (iv.x >= laneRight[l] + C2.TS_GAP) {
10438
+ if (iv.x >= laneRight[l] + C3.TS_GAP) {
10439
10439
  placed = l;
10440
10440
  break;
10441
10441
  }
@@ -10457,7 +10457,7 @@ function layoutTimescaled(ast, schedule) {
10457
10457
  for (const t of ast.tasks) {
10458
10458
  const iv = intervalById.get(t.id);
10459
10459
  const lane = laneOf.get(t.id);
10460
- const y = topPad + lane * (C2.TS_BOX_H + C2.TS_LANE_GAP);
10460
+ const y = topPad + lane * (C3.TS_BOX_H + C3.TS_LANE_GAP);
10461
10461
  const box2 = {
10462
10462
  id: t.id,
10463
10463
  task: t,
@@ -10465,7 +10465,7 @@ function layoutTimescaled(ast, schedule) {
10465
10465
  x: iv.x,
10466
10466
  y,
10467
10467
  width: iv.w,
10468
- height: C2.TS_BOX_H,
10468
+ height: C3.TS_BOX_H,
10469
10469
  milestone: t.milestone,
10470
10470
  rank: 0
10471
10471
  };
@@ -10493,7 +10493,7 @@ function layoutTimescaled(ast, schedule) {
10493
10493
  edges.push(edge);
10494
10494
  }
10495
10495
  }
10496
- const contentBottom = topPad + laneCount * C2.TS_BOX_H + (laneCount - 1) * C2.TS_LANE_GAP;
10496
+ const contentBottom = topPad + laneCount * C3.TS_BOX_H + (laneCount - 1) * C3.TS_LANE_GAP;
10497
10497
  const axisBaseline = contentBottom + 22;
10498
10498
  const timeEnd = leftPad + T * pxPerUnit;
10499
10499
  let maxRight = timeEnd;
@@ -10509,8 +10509,8 @@ function layoutTimescaled(ast, schedule) {
10509
10509
  major: Math.abs(rounded % majorStep) < 1e-9
10510
10510
  });
10511
10511
  }
10512
- const width = Math.ceil(Math.max(maxRight, timeEnd) + C2.PAD);
10513
- const height = Math.ceil(axisBaseline + C2.AXIS_H + C2.FOOTER_H);
10512
+ const width = Math.ceil(Math.max(maxRight, timeEnd) + C3.PAD);
10513
+ const height = Math.ceil(axisBaseline + C3.AXIS_H + C3.FOOTER_H);
10514
10514
  return {
10515
10515
  width,
10516
10516
  height,
@@ -12163,7 +12163,7 @@ var SequenceLayout = class {
12163
12163
  left = mid - 20;
12164
12164
  right = mid + 20;
12165
12165
  }
12166
- const frame = {
12166
+ const frame2 = {
12167
12167
  op,
12168
12168
  x: left,
12169
12169
  y: frameTop,
@@ -12171,8 +12171,8 @@ var SequenceLayout = class {
12171
12171
  height: frameBottom - frameTop,
12172
12172
  operands: operandGeom
12173
12173
  };
12174
- if (messageSet && messageSet.length) frame.messageSet = messageSet;
12175
- this.fragments.push(frame);
12174
+ if (messageSet && messageSet.length) frame2.messageSet = messageSet;
12175
+ this.fragments.push(frame2);
12176
12176
  this.noteRight(left, right - left);
12177
12177
  this.y = frameBottom;
12178
12178
  }
@@ -12840,7 +12840,7 @@ var PETRI_CONST = {
12840
12840
  CHAR_W: 6.2
12841
12841
  };
12842
12842
  function layoutPetri(ast) {
12843
- const C2 = PETRI_CONST;
12843
+ const C3 = PETRI_CONST;
12844
12844
  const dir = ast.direction;
12845
12845
  const warnings = [...ast.warnings];
12846
12846
  const kindOf = /* @__PURE__ */ new Map();
@@ -12924,10 +12924,10 @@ function layoutPetri(ast) {
12924
12924
  }
12925
12925
  }
12926
12926
  const sizeOf5 = (id) => {
12927
- if (kindOf.get(id) === "place") return { halfW: C2.PLACE_R, halfH: C2.PLACE_R, r: C2.PLACE_R };
12927
+ if (kindOf.get(id) === "place") return { halfW: C3.PLACE_R, halfH: C3.PLACE_R, r: C3.PLACE_R };
12928
12928
  const tr = ast.transitions.find((t) => t.id === id);
12929
- const long = tr.kind === "timed" ? C2.TRANS_BOX_H : C2.TRANS_BAR_H;
12930
- const thin = tr.kind === "timed" ? C2.TRANS_BOX_W : C2.TRANS_BAR_W;
12929
+ const long = tr.kind === "timed" ? C3.TRANS_BOX_H : C3.TRANS_BAR_H;
12930
+ const thin = tr.kind === "timed" ? C3.TRANS_BOX_W : C3.TRANS_BAR_W;
12931
12931
  const halfW = dir === "lr" ? thin / 2 : long / 2;
12932
12932
  const halfH = dir === "lr" ? long / 2 : thin / 2;
12933
12933
  return { halfW, halfH, r: 0 };
@@ -12941,15 +12941,15 @@ function layoutPetri(ast) {
12941
12941
  return dir === "lr" ? s.halfH : s.halfW;
12942
12942
  };
12943
12943
  const layerHalf = layers.map((arr) => Math.max(0, ...arr.map(flowHalf)));
12944
- const slot = Math.max(0, ...ids.map(crossHalf)) * 2 + C2.RANK_GAP;
12944
+ const slot = Math.max(0, ...ids.map(crossHalf)) * 2 + C3.RANK_GAP;
12945
12945
  const maxCount = Math.max(1, ...layers.map((a) => a.length));
12946
- const crossCenter = C2.MARGIN + C2.LABEL_LINE_H * 2 + maxCount * slot / 2;
12946
+ const crossCenter = C3.MARGIN + C3.LABEL_LINE_H * 2 + maxCount * slot / 2;
12947
12947
  const flowCenter = [];
12948
- let acc = C2.MARGIN + C2.LABEL_LINE_H * 2;
12948
+ let acc = C3.MARGIN + C3.LABEL_LINE_H * 2;
12949
12949
  for (let L = 0; L < layers.length; L++) {
12950
12950
  acc += layerHalf[L];
12951
12951
  flowCenter[L] = acc;
12952
- acc += layerHalf[L] + C2.LAYER_GAP;
12952
+ acc += layerHalf[L] + C3.LAYER_GAP;
12953
12953
  }
12954
12954
  const geom = /* @__PURE__ */ new Map();
12955
12955
  layers.forEach((arr, L) => {
@@ -13032,12 +13032,12 @@ function layoutPetri(ast) {
13032
13032
  if (dir === "lr") {
13033
13033
  const pA = boundary(A, 0, 1);
13034
13034
  const pB = boundary(B, 0, 1);
13035
- const bowY = bandMaxCross + C2.BACKEDGE_BOW;
13035
+ const bowY = bandMaxCross + C3.BACKEDGE_BOW;
13036
13036
  points = [pA, { x: pA.x, y: bowY }, { x: pB.x, y: bowY }, pB];
13037
13037
  } else {
13038
13038
  const pA = boundary(A, 1, 0);
13039
13039
  const pB = boundary(B, 1, 0);
13040
- const bowX = bandMaxCross + C2.BACKEDGE_BOW;
13040
+ const bowX = bandMaxCross + C3.BACKEDGE_BOW;
13041
13041
  points = [pA, { x: bowX, y: pA.y }, { x: bowX, y: pB.y }, pB];
13042
13042
  }
13043
13043
  }
@@ -13048,8 +13048,8 @@ function layoutPetri(ast) {
13048
13048
  const ddx = p1.x - p0.x;
13049
13049
  const ddy = p1.y - p0.y;
13050
13050
  const dl = Math.hypot(ddx, ddy) || 1;
13051
- const labelX = mx - ddy / dl * C2.ARC_WEIGHT_OFFSET;
13052
- const labelY = my + ddx / dl * C2.ARC_WEIGHT_OFFSET;
13051
+ const labelX = mx - ddy / dl * C3.ARC_WEIGHT_OFFSET;
13052
+ const labelY = my + ddx / dl * C3.ARC_WEIGHT_OFFSET;
13053
13053
  return { arc: a, type: a.type, weight: a.weight, points, reversed, labelX, labelY };
13054
13054
  });
13055
13055
  const hasIncoming = (pid2) => ast.arcs.some((a) => a.to === pid2);
@@ -13086,24 +13086,24 @@ function layoutPetri(ast) {
13086
13086
  bb.maxY = Math.max(bb.maxY, y0, y1);
13087
13087
  };
13088
13088
  const addPt = (p) => addBox(p.x, p.y, p.x, p.y);
13089
- const labelW = (s) => s ? s.length * C2.CHAR_W : 0;
13089
+ const labelW = (s) => s ? s.length * C3.CHAR_W : 0;
13090
13090
  for (const pb of placeBoxes) {
13091
13091
  addBox(pb.cx - pb.r, pb.cy - pb.r, pb.cx + pb.r, pb.cy + pb.r);
13092
13092
  const lw = Math.max(labelW(pb.place.id), labelW(pb.place.label)) / 2;
13093
- addBox(pb.cx - lw, pb.cy - pb.r - C2.LABEL_LINE_H * 2, pb.cx + lw, pb.cy);
13094
- if (pb.place.capacity !== void 0) addBox(pb.cx, pb.cy + pb.r, pb.cx + 24, pb.cy + pb.r + C2.LABEL_LINE_H);
13093
+ addBox(pb.cx - lw, pb.cy - pb.r - C3.LABEL_LINE_H * 2, pb.cx + lw, pb.cy);
13094
+ if (pb.place.capacity !== void 0) addBox(pb.cx, pb.cy + pb.r, pb.cx + 24, pb.cy + pb.r + C3.LABEL_LINE_H);
13095
13095
  }
13096
13096
  for (const tb of transBoxes) {
13097
13097
  addBox(tb.cx - tb.w / 2, tb.cy - tb.h / 2, tb.cx + tb.w / 2, tb.cy + tb.h / 2);
13098
13098
  const lw = Math.max(labelW(tb.transition.id), labelW(tb.transition.label)) / 2;
13099
- addBox(tb.cx - lw, tb.cy - tb.h / 2 - C2.LABEL_LINE_H * 2, tb.cx + lw, tb.cy);
13099
+ addBox(tb.cx - lw, tb.cy - tb.h / 2 - C3.LABEL_LINE_H * 2, tb.cx + lw, tb.cy);
13100
13100
  }
13101
13101
  for (const ag of arcGeoms) {
13102
13102
  ag.points.forEach(addPt);
13103
13103
  if (ag.weight > 1) addBox(ag.labelX - 6, ag.labelY - 8, ag.labelX + 6, ag.labelY + 4);
13104
13104
  }
13105
- const dx = C2.MARGIN - bb.minX;
13106
- const dy = C2.MARGIN - bb.minY;
13105
+ const dx = C3.MARGIN - bb.minX;
13106
+ const dy = C3.MARGIN - bb.minY;
13107
13107
  const shift = (p) => ({ x: p.x + dx, y: p.y + dy });
13108
13108
  placeBoxes.forEach((pb) => {
13109
13109
  pb.cx += dx;
@@ -13118,8 +13118,8 @@ function layoutPetri(ast) {
13118
13118
  ag.labelX += dx;
13119
13119
  ag.labelY += dy;
13120
13120
  });
13121
- const width = bb.maxX - bb.minX + 2 * C2.MARGIN;
13122
- const height = bb.maxY - bb.minY + 2 * C2.MARGIN;
13121
+ const width = bb.maxX - bb.minX + 2 * C3.MARGIN;
13122
+ const height = bb.maxY - bb.minY + 2 * C3.MARGIN;
13123
13123
  const subclass = detectSubclass(ast);
13124
13124
  return {
13125
13125
  width: Math.round(width),
@@ -17727,7 +17727,7 @@ var FAULTTREE_CONST = {
17727
17727
  TITLE_H: 34
17728
17728
  };
17729
17729
  function eventBox(label) {
17730
- const C2 = FAULTTREE_CONST;
17730
+ const C3 = FAULTTREE_CONST;
17731
17731
  const words = label.split(/\s+/).filter(Boolean);
17732
17732
  const lines = [];
17733
17733
  let cur = "";
@@ -17745,11 +17745,11 @@ function eventBox(label) {
17745
17745
  else if (cur && lines.length === 2) lines[1] = `${lines[1]} ${cur}`;
17746
17746
  if (lines.length === 0) lines.push(label);
17747
17747
  const longest = Math.max(...lines.map((l) => l.length), 1);
17748
- const width = Math.min(C2.EVENT_MAX_W, Math.max(C2.EVENT_MIN_W, Math.ceil(longest * C2.CHAR_W) + 2 * C2.EVENT_PAD_X));
17748
+ const width = Math.min(C3.EVENT_MAX_W, Math.max(C3.EVENT_MIN_W, Math.ceil(longest * C3.CHAR_W) + 2 * C3.EVENT_PAD_X));
17749
17749
  return { width, lines };
17750
17750
  }
17751
17751
  function layoutFaultTree(ast) {
17752
- const C2 = FAULTTREE_CONST;
17752
+ const C3 = FAULTTREE_CONST;
17753
17753
  const analysis = analyseFaultTree(ast);
17754
17754
  const byId = new Map(ast.events.map((e) => [e.id, e]));
17755
17755
  const refCount = /* @__PURE__ */ new Map();
@@ -17765,13 +17765,13 @@ function layoutFaultTree(ast) {
17765
17765
  case "intermediate":
17766
17766
  return eventBox(label).width;
17767
17767
  case "basic":
17768
- return 2 * C2.BASIC_R;
17768
+ return 2 * C3.BASIC_R;
17769
17769
  case "undeveloped":
17770
- return C2.DIAMOND_W;
17770
+ return C3.DIAMOND_W;
17771
17771
  case "house":
17772
- return C2.HOUSE_W;
17772
+ return C3.HOUSE_W;
17773
17773
  case "condition":
17774
- return C2.COND_W;
17774
+ return C3.COND_W;
17775
17775
  }
17776
17776
  };
17777
17777
  const build = (eventId, depth, onPath) => {
@@ -17818,9 +17818,9 @@ function layoutFaultTree(ast) {
17818
17818
  }
17819
17819
  let x = originX;
17820
17820
  for (const c of n.children) {
17821
- x += place(c, x) + C2.SIBLING_GAP;
17821
+ x += place(c, x) + C3.SIBLING_GAP;
17822
17822
  }
17823
- const childrenWidth = x - originX - C2.SIBLING_GAP;
17823
+ const childrenWidth = x - originX - C3.SIBLING_GAP;
17824
17824
  if (n.width <= childrenWidth) {
17825
17825
  n.cx = (n.children[0].cx + n.children[n.children.length - 1].cx) / 2;
17826
17826
  return childrenWidth;
@@ -17830,24 +17830,24 @@ function layoutFaultTree(ast) {
17830
17830
  n.cx = originX + n.width / 2;
17831
17831
  return n.width;
17832
17832
  };
17833
- const baseY = C2.CANVAS_PAD + (ast.title ? C2.TITLE_H : 0) + (ast.analysis.probability ? 18 : 0);
17834
- place(root, C2.CANVAS_PAD);
17835
- const ROW_PITCH = C2.EVENT_H + C2.GATE_GAP + C2.GATE_H + C2.LEVEL_GAP;
17833
+ const baseY = C3.CANVAS_PAD + (ast.title ? C3.TITLE_H : 0) + (ast.analysis.probability ? 18 : 0);
17834
+ place(root, C3.CANVAS_PAD);
17835
+ const ROW_PITCH = C3.EVENT_H + C3.GATE_GAP + C3.GATE_H + C3.LEVEL_GAP;
17836
17836
  const rowY = (depth) => baseY + depth * ROW_PITCH;
17837
- const centerY = (n) => n.topY + C2.EVENT_H / 2;
17837
+ const centerY = (n) => n.topY + C3.EVENT_H / 2;
17838
17838
  const halfH = (role) => {
17839
17839
  switch (role) {
17840
17840
  case "top":
17841
17841
  case "intermediate":
17842
- return C2.EVENT_H / 2;
17842
+ return C3.EVENT_H / 2;
17843
17843
  case "basic":
17844
- return C2.BASIC_R;
17844
+ return C3.BASIC_R;
17845
17845
  case "undeveloped":
17846
- return C2.DIAMOND_W / 2;
17846
+ return C3.DIAMOND_W / 2;
17847
17847
  case "house":
17848
- return C2.HOUSE_H / 2;
17848
+ return C3.HOUSE_H / 2;
17849
17849
  case "condition":
17850
- return C2.COND_H / 2;
17850
+ return C3.COND_H / 2;
17851
17851
  }
17852
17852
  };
17853
17853
  const topAnchorY = (n) => n.role === "top" || n.role === "intermediate" ? n.topY : centerY(n) - halfH(n.role);
@@ -17861,7 +17861,7 @@ function layoutFaultTree(ast) {
17861
17861
  cx: n.cx,
17862
17862
  topY: n.topY,
17863
17863
  width: n.width,
17864
- height: n.role === "top" || n.role === "intermediate" ? C2.EVENT_H : 2 * halfH(n.role),
17864
+ height: n.role === "top" || n.role === "intermediate" ? C3.EVENT_H : 2 * halfH(n.role),
17865
17865
  depth: n.depth,
17866
17866
  shared: n.shared
17867
17867
  };
@@ -17869,28 +17869,28 @@ function layoutFaultTree(ast) {
17869
17869
  (instancesByEvent.get(n.eventId) ?? instancesByEvent.set(n.eventId, []).get(n.eventId)).push(lay);
17870
17870
  if (n.gate && n.children.length > 0) {
17871
17871
  const gx = n.cx;
17872
- const gy = n.topY + C2.EVENT_H + C2.GATE_GAP + C2.GATE_H / 2;
17872
+ const gy = n.topY + C3.EVENT_H + C3.GATE_GAP + C3.GATE_H / 2;
17873
17873
  const glay = {
17874
17874
  gate: n.gate,
17875
17875
  ownerInstanceId: n.instanceId,
17876
17876
  cx: gx,
17877
17877
  cy: gy,
17878
- width: C2.GATE_W,
17879
- height: C2.GATE_H
17878
+ width: C3.GATE_W,
17879
+ height: C3.GATE_H
17880
17880
  };
17881
17881
  if ((n.gate.kind === "inhibit" || n.gate.kind === "pand") && (n.gate.condition || n.gate.order)) {
17882
17882
  const condEv = n.gate.condition ? byId.get(n.gate.condition) : void 0;
17883
17883
  const text2 = n.gate.order ? n.gate.order.join(" \u227A ") : condEv?.label ?? n.gate.condition ?? "";
17884
17884
  glay.cond = {
17885
- x: gx + C2.GATE_W / 2 + C2.COND_GAP + C2.COND_W / 2,
17885
+ x: gx + C3.GATE_W / 2 + C3.COND_GAP + C3.COND_W / 2,
17886
17886
  y: gy,
17887
- w: C2.COND_W,
17888
- h: C2.COND_H,
17887
+ w: C3.COND_W,
17888
+ h: C3.COND_H,
17889
17889
  text: text2
17890
17890
  };
17891
17891
  }
17892
17892
  gates.push(glay);
17893
- const gateBaseY = gy + C2.GATE_H / 2;
17893
+ const gateBaseY = gy + C3.GATE_H / 2;
17894
17894
  for (const c of n.children) {
17895
17895
  c.topY = rowY(c.depth);
17896
17896
  const childTop = topAnchorY(c);
@@ -17908,7 +17908,7 @@ function layoutFaultTree(ast) {
17908
17908
  const cutSetBoxes = [];
17909
17909
  let boxIndex = 0;
17910
17910
  const visualBounds = (e) => {
17911
- const cy = e.topY + C2.EVENT_H / 2;
17911
+ const cy = e.topY + C3.EVENT_H / 2;
17912
17912
  const hw = e.width / 2;
17913
17913
  const hh = halfH(e.role);
17914
17914
  return { minX: e.cx - hw, maxX: e.cx + hw, minY: cy - hh, maxY: cy + hh };
@@ -17922,7 +17922,7 @@ function layoutFaultTree(ast) {
17922
17922
  maxX2 = Math.max(maxX2, b.maxX);
17923
17923
  maxY2 = Math.max(maxY2, b.maxY);
17924
17924
  }
17925
- const pad = C2.CUTSET_PAD + idx % 3 * C2.CUTSET_OFFSET_STEP;
17925
+ const pad = C3.CUTSET_PAD + idx % 3 * C3.CUTSET_OFFSET_STEP;
17926
17926
  return {
17927
17927
  cutSet: cs,
17928
17928
  index: idx,
@@ -17953,7 +17953,7 @@ function layoutFaultTree(ast) {
17953
17953
  ownerInstanceId: inst.instanceId,
17954
17954
  name: tr.name,
17955
17955
  x: inst.cx,
17956
- y: inst.topY + C2.EVENT_H + C2.GATE_GAP
17956
+ y: inst.topY + C3.EVENT_H + C3.GATE_GAP
17957
17957
  });
17958
17958
  }
17959
17959
  let maxX = 0, maxY = 0;
@@ -17967,7 +17967,7 @@ function layoutFaultTree(ast) {
17967
17967
  if (e.role === "basic" || e.role === "undeveloped" || e.role === "house") {
17968
17968
  const hasLabel = !!e.event.label && e.event.label !== e.event.id;
17969
17969
  const hasProb = ast.analysis.probability && e.event.prob !== void 0;
17970
- if (hasLabel || hasProb) bump(b.maxX, b.maxY + (hasLabel && hasProb ? C2.CAP_GAP + C2.CAP_LINE_H + 8 : C2.CAP_GAP + 6));
17970
+ if (hasLabel || hasProb) bump(b.maxX, b.maxY + (hasLabel && hasProb ? C3.CAP_GAP + C3.CAP_LINE_H + 8 : C3.CAP_GAP + 6));
17971
17971
  }
17972
17972
  }
17973
17973
  for (const g of gates) {
@@ -17976,7 +17976,7 @@ function layoutFaultTree(ast) {
17976
17976
  }
17977
17977
  for (const box2 of cutSetBoxes) bump(box2.x + box2.width, box2.y + box2.height);
17978
17978
  for (const t of transfers) bump(t.x + 22, t.y + 30);
17979
- if (ast.title) bump(C2.CANVAS_PAD + ast.title.length * 8.5, 0);
17979
+ if (ast.title) bump(C3.CANVAS_PAD + ast.title.length * 8.5, 0);
17980
17980
  if (ast.analysis.probability) {
17981
17981
  const top = events.find((e) => e.role === "top");
17982
17982
  if (top) bump(top.cx + 95, 0);
@@ -17989,8 +17989,8 @@ function layoutFaultTree(ast) {
17989
17989
  edges,
17990
17990
  cutSetBoxes,
17991
17991
  transfers,
17992
- width: Math.ceil(maxX + C2.CANVAS_PAD),
17993
- height: Math.ceil(maxY + C2.CANVAS_PAD)
17992
+ width: Math.ceil(maxX + C3.CANVAS_PAD),
17993
+ height: Math.ceil(maxY + C3.CANVAS_PAD)
17994
17994
  };
17995
17995
  }
17996
17996
  function r(n) {
@@ -18516,40 +18516,40 @@ var BOWTIE_CONST = {
18516
18516
  LEGEND_H: 30
18517
18517
  };
18518
18518
  function dropBottom(barrier) {
18519
- const C2 = BOWTIE_CONST;
18520
- if (barrier.escalations.length === 0) return C2.NODE_H / 2;
18521
- let cursor = C2.EF_DROP;
18522
- let lastBottom = C2.NODE_H / 2;
18519
+ const C3 = BOWTIE_CONST;
18520
+ if (barrier.escalations.length === 0) return C3.NODE_H / 2;
18521
+ let cursor = C3.EF_DROP;
18522
+ let lastBottom = C3.NODE_H / 2;
18523
18523
  for (const esc of barrier.escalations) {
18524
- lastBottom = cursor + C2.NODE_H / 2;
18525
- cursor += C2.NODE_H + C2.EF_GAP;
18524
+ lastBottom = cursor + C3.NODE_H / 2;
18525
+ cursor += C3.NODE_H + C3.EF_GAP;
18526
18526
  for (const _ef of esc.barriers) {
18527
- lastBottom = cursor + C2.NODE_H / 2;
18528
- cursor += C2.NODE_H + C2.EF_GAP;
18527
+ lastBottom = cursor + C3.NODE_H / 2;
18528
+ cursor += C3.NODE_H + C3.EF_GAP;
18529
18529
  }
18530
18530
  }
18531
18531
  return lastBottom;
18532
18532
  }
18533
18533
  function bandLayout(lines) {
18534
- const C2 = BOWTIE_CONST;
18535
- const below = lines.map((l) => Math.max(...l.barriers.map(dropBottom), C2.NODE_H / 2));
18534
+ const C3 = BOWTIE_CONST;
18535
+ const below = lines.map((l) => Math.max(...l.barriers.map(dropBottom), C3.NODE_H / 2));
18536
18536
  const rel = [];
18537
18537
  for (let k = 0; k < lines.length; k++) {
18538
18538
  if (k === 0) {
18539
18539
  rel.push(0);
18540
18540
  continue;
18541
18541
  }
18542
- const pitch = Math.max(C2.ROW_BAND_H, below[k - 1] + C2.ROW_GAP + C2.NODE_H / 2);
18542
+ const pitch = Math.max(C3.ROW_BAND_H, below[k - 1] + C3.ROW_GAP + C3.NODE_H / 2);
18543
18543
  rel.push(rel[k - 1] + pitch);
18544
18544
  }
18545
18545
  const last = lines.length - 1;
18546
18546
  const blockMid = lines.length ? rel[last] / 2 : 0;
18547
- const aboveExtent = lines.length ? blockMid + C2.NODE_H / 2 : 0;
18547
+ const aboveExtent = lines.length ? blockMid + C3.NODE_H / 2 : 0;
18548
18548
  const belowExtent = lines.length ? rel[last] - blockMid + below[last] : 0;
18549
18549
  return { rel, below, blockMid, aboveExtent, belowExtent };
18550
18550
  }
18551
18551
  function layoutBowtie(ast) {
18552
- const C2 = BOWTIE_CONST;
18552
+ const C3 = BOWTIE_CONST;
18553
18553
  const boxes = [];
18554
18554
  const lines = [];
18555
18555
  const escalationLines = [];
@@ -18557,42 +18557,42 @@ function layoutBowtie(ast) {
18557
18557
  const conseqLines = ast.consequences.map((c) => ({ id: c.id, label: c.label, barriers: c.barriers }));
18558
18558
  const left = bandLayout(threatLines);
18559
18559
  const right = bandLayout(conseqLines);
18560
- const aboveCy = Math.max(left.aboveExtent, right.aboveExtent, C2.TOPEVENT_R);
18560
+ const aboveCy = Math.max(left.aboveExtent, right.aboveExtent, C3.TOPEVENT_R);
18561
18561
  const maxLeftChain = Math.max(0, ...threatLines.map((l) => l.barriers.length));
18562
- const innerOffset = C2.TOPEVENT_R + C2.CENTER_GUTTER + C2.BARRIER_W / 2;
18563
- const cx = C2.PAGE_PAD + C2.NODE_W / 2 + maxLeftChain * C2.WING_X_STEP + innerOffset;
18564
- const titleZone = ast.title ? C2.TITLE_H : 0;
18565
- const hazardReserve = ast.hazard ? C2.NODE_H + C2.HAZARD_GAP : 0;
18566
- const cy = C2.PAGE_PAD + titleZone + hazardReserve + aboveCy;
18567
- const topEvent = { cx, cy, r: C2.TOPEVENT_R, label: ast.topEvent };
18562
+ const innerOffset = C3.TOPEVENT_R + C3.CENTER_GUTTER + C3.BARRIER_W / 2;
18563
+ const cx = C3.PAGE_PAD + C3.NODE_W / 2 + maxLeftChain * C3.WING_X_STEP + innerOffset;
18564
+ const titleZone = ast.title ? C3.TITLE_H : 0;
18565
+ const hazardReserve = ast.hazard ? C3.NODE_H + C3.HAZARD_GAP : 0;
18566
+ const cy = C3.PAGE_PAD + titleZone + hazardReserve + aboveCy;
18567
+ const topEvent = { cx, cy, r: C3.TOPEVENT_R, label: ast.topEvent };
18568
18568
  let hazardTie;
18569
18569
  if (ast.hazard) {
18570
- const hcy = C2.PAGE_PAD + titleZone + C2.NODE_H / 2;
18571
- boxes.push({ id: "hazard", role: "hazard", label: ast.hazard, cx, cy: hcy, width: C2.HAZARD_W, height: C2.NODE_H });
18572
- hazardTie = { x: cx, y1: hcy + C2.NODE_H / 2, y2: cy - C2.TOPEVENT_R };
18570
+ const hcy = C3.PAGE_PAD + titleZone + C3.NODE_H / 2;
18571
+ boxes.push({ id: "hazard", role: "hazard", label: ast.hazard, cx, cy: hcy, width: C3.HAZARD_W, height: C3.NODE_H });
18572
+ hazardTie = { x: cx, y1: hcy + C3.NODE_H / 2, y2: cy - C3.TOPEVENT_R };
18573
18573
  }
18574
18574
  const emitWing = (wing, band, side) => {
18575
- const innerX = side === "prevent" ? cx - C2.TOPEVENT_R - C2.CENTER_GUTTER - C2.BARRIER_W / 2 : cx + C2.TOPEVENT_R + C2.CENTER_GUTTER + C2.BARRIER_W / 2;
18575
+ const innerX = side === "prevent" ? cx - C3.TOPEVENT_R - C3.CENTER_GUTTER - C3.BARRIER_W / 2 : cx + C3.TOPEVENT_R + C3.CENTER_GUTTER + C3.BARRIER_W / 2;
18576
18576
  wing.forEach((line2, k) => {
18577
18577
  const by = cy + (band.rel[k] - band.blockMid);
18578
18578
  const n = line2.barriers.length;
18579
18579
  const barrierX = line2.barriers.map((_b, j) => {
18580
18580
  if (side === "prevent") {
18581
18581
  const stepsFromInner = n - 1 - j;
18582
- return innerX - stepsFromInner * C2.WING_X_STEP;
18582
+ return innerX - stepsFromInner * C3.WING_X_STEP;
18583
18583
  }
18584
- return innerX + j * C2.WING_X_STEP;
18584
+ return innerX + j * C3.WING_X_STEP;
18585
18585
  });
18586
18586
  const outerBarrierX = side === "prevent" ? Math.min(...barrierX) : Math.max(...barrierX);
18587
- const headX = side === "prevent" ? outerBarrierX - C2.WING_X_STEP : outerBarrierX + C2.WING_X_STEP;
18587
+ const headX = side === "prevent" ? outerBarrierX - C3.WING_X_STEP : outerBarrierX + C3.WING_X_STEP;
18588
18588
  boxes.push({
18589
18589
  id: line2.id,
18590
18590
  role: side === "prevent" ? "threat" : "consequence",
18591
18591
  label: line2.label,
18592
18592
  cx: headX,
18593
18593
  cy: by,
18594
- width: C2.NODE_W,
18595
- height: C2.NODE_H
18594
+ width: C3.NODE_W,
18595
+ height: C3.NODE_H
18596
18596
  });
18597
18597
  line2.barriers.forEach((b, j) => {
18598
18598
  const bx = barrierX[j];
@@ -18602,71 +18602,71 @@ function layoutBowtie(ast) {
18602
18602
  label: b.label,
18603
18603
  cx: bx,
18604
18604
  cy: by,
18605
- width: C2.BARRIER_W,
18606
- height: C2.NODE_H,
18605
+ width: C3.BARRIER_W,
18606
+ height: C3.NODE_H,
18607
18607
  side,
18608
18608
  lineId: line2.id,
18609
18609
  order: j
18610
18610
  });
18611
18611
  if (b.escalations.length) {
18612
- let cursor = C2.EF_DROP;
18613
- let connectFromY = by + C2.NODE_H / 2;
18612
+ let cursor = C3.EF_DROP;
18613
+ let connectFromY = by + C3.NODE_H / 2;
18614
18614
  for (const esc of b.escalations) {
18615
18615
  const escCy = by + cursor;
18616
- escalationLines.push({ x: bx, y1: connectFromY, y2: escCy - C2.NODE_H / 2 });
18616
+ escalationLines.push({ x: bx, y1: connectFromY, y2: escCy - C3.NODE_H / 2 });
18617
18617
  boxes.push({
18618
18618
  id: esc.id,
18619
18619
  role: "escalation",
18620
18620
  label: esc.label,
18621
18621
  cx: bx,
18622
18622
  cy: escCy,
18623
- width: C2.NODE_W,
18624
- height: C2.NODE_H,
18623
+ width: C3.NODE_W,
18624
+ height: C3.NODE_H,
18625
18625
  lineId: line2.id,
18626
18626
  barrierId: b.id
18627
18627
  });
18628
- connectFromY = escCy + C2.NODE_H / 2;
18629
- cursor += C2.NODE_H + C2.EF_GAP;
18628
+ connectFromY = escCy + C3.NODE_H / 2;
18629
+ cursor += C3.NODE_H + C3.EF_GAP;
18630
18630
  for (const ef of esc.barriers) {
18631
18631
  const efCy = by + cursor;
18632
- escalationLines.push({ x: bx, y1: connectFromY, y2: efCy - C2.NODE_H / 2 });
18632
+ escalationLines.push({ x: bx, y1: connectFromY, y2: efCy - C3.NODE_H / 2 });
18633
18633
  boxes.push({
18634
18634
  id: ef.id,
18635
18635
  role: "ef-barrier",
18636
18636
  label: ef.label,
18637
18637
  cx: bx,
18638
18638
  cy: efCy,
18639
- width: C2.BARRIER_W,
18640
- height: C2.NODE_H,
18639
+ width: C3.BARRIER_W,
18640
+ height: C3.NODE_H,
18641
18641
  lineId: line2.id,
18642
18642
  escalationId: esc.id
18643
18643
  });
18644
- connectFromY = efCy + C2.NODE_H / 2;
18645
- cursor += C2.NODE_H + C2.EF_GAP;
18644
+ connectFromY = efCy + C3.NODE_H / 2;
18645
+ cursor += C3.NODE_H + C3.EF_GAP;
18646
18646
  }
18647
18647
  }
18648
18648
  }
18649
18649
  });
18650
18650
  const dy = by - cy;
18651
- const clampedDy = Math.max(-48, Math.min(C2.TOPEVENT_R - 4, dy));
18652
- const knotDx = Math.sqrt(Math.max(0, C2.TOPEVENT_R * C2.TOPEVENT_R - clampedDy * clampedDy));
18651
+ const clampedDy = Math.max(-48, Math.min(C3.TOPEVENT_R - 4, dy));
18652
+ const knotDx = Math.sqrt(Math.max(0, C3.TOPEVENT_R * C3.TOPEVENT_R - clampedDy * clampedDy));
18653
18653
  const pts = [];
18654
18654
  if (side === "prevent") {
18655
- pts.push([headX + C2.NODE_W / 2, by]);
18655
+ pts.push([headX + C3.NODE_W / 2, by]);
18656
18656
  const ordered = [...line2.barriers].map((_b, j) => barrierX[j]).sort((a, b) => a - b);
18657
18657
  for (const bx of ordered) {
18658
- pts.push([bx - C2.BARRIER_W / 2, by]);
18659
- pts.push([bx + C2.BARRIER_W / 2, by]);
18658
+ pts.push([bx - C3.BARRIER_W / 2, by]);
18659
+ pts.push([bx + C3.BARRIER_W / 2, by]);
18660
18660
  }
18661
18661
  pts.push([cx - knotDx, cy + clampedDy]);
18662
18662
  } else {
18663
18663
  pts.push([cx + knotDx, cy + clampedDy]);
18664
18664
  const ordered = [...line2.barriers].map((_b, j) => barrierX[j]).sort((a, b) => a - b);
18665
18665
  for (const bx of ordered) {
18666
- pts.push([bx - C2.BARRIER_W / 2, by]);
18667
- pts.push([bx + C2.BARRIER_W / 2, by]);
18666
+ pts.push([bx - C3.BARRIER_W / 2, by]);
18667
+ pts.push([bx + C3.BARRIER_W / 2, by]);
18668
18668
  }
18669
- pts.push([headX - C2.NODE_W / 2, by]);
18669
+ pts.push([headX - C3.NODE_W / 2, by]);
18670
18670
  }
18671
18671
  const path2 = pts.map((p, idx) => `${idx === 0 ? "M" : "L"} ${r3(p[0])} ${r3(p[1])}`).join(" ");
18672
18672
  const ax = side === "prevent" ? cx - knotDx : cx + knotDx;
@@ -18681,9 +18681,9 @@ function layoutBowtie(ast) {
18681
18681
  maxY = Math.max(maxY, y);
18682
18682
  };
18683
18683
  for (const b of boxes) bump(b.cx + b.width / 2, b.cy + b.height / 2);
18684
- bump(cx + C2.TOPEVENT_R, cy + C2.TOPEVENT_R);
18685
- if (ast.title) bump(C2.PAGE_PAD + ast.title.length * 9, 0);
18686
- const legendBand = ast.legend === "off" ? 0 : C2.LEGEND_H;
18684
+ bump(cx + C3.TOPEVENT_R, cy + C3.TOPEVENT_R);
18685
+ if (ast.title) bump(C3.PAGE_PAD + ast.title.length * 9, 0);
18686
+ const legendBand = ast.legend === "off" ? 0 : C3.LEGEND_H;
18687
18687
  return {
18688
18688
  ast,
18689
18689
  topEvent,
@@ -18691,8 +18691,8 @@ function layoutBowtie(ast) {
18691
18691
  lines,
18692
18692
  escalationLines,
18693
18693
  ...hazardTie ? { hazardTie } : {},
18694
- width: Math.ceil(maxX + C2.PAGE_PAD),
18695
- height: Math.ceil(maxY + C2.PAGE_PAD + legendBand)
18694
+ width: Math.ceil(maxX + C3.PAGE_PAD),
18695
+ height: Math.ceil(maxY + C3.PAGE_PAD + legendBand)
18696
18696
  };
18697
18697
  }
18698
18698
  function r3(n) {
@@ -19183,7 +19183,7 @@ var EVENTTREE_CONST = {
19183
19183
  LEAF_LINE_H: 14
19184
19184
  };
19185
19185
  function layoutEventTree(ast) {
19186
- const C2 = EVENTTREE_CONST;
19186
+ const C3 = EVENTTREE_CONST;
19187
19187
  const analysis = analyseEventTree(ast);
19188
19188
  const seqs = analysis.sequences;
19189
19189
  const root = { children: [], y: 0, rowLo: 0, rowHi: 0 };
@@ -19215,15 +19215,15 @@ function layoutEventTree(ast) {
19215
19215
  };
19216
19216
  assignRows(root);
19217
19217
  const rowCount = Math.max(nextRow, 1);
19218
- const titleH = ast.title ? C2.TITLE_H : 0;
19219
- const headerY = C2.CANVAS_PAD + titleH + C2.HEADER_H * 0.6;
19220
- const bodyTopY = C2.CANVAS_PAD + titleH + C2.HEADER_H;
19221
- const rowY = (row) => bodyTopY + C2.ROW_H / 2 + row * C2.ROW_H;
19222
- const ieX2 = C2.IE_LEFT + C2.IE_STUB;
19223
- const gridX = (col) => ieX2 + (col + 1) * C2.COL_W;
19218
+ const titleH = ast.title ? C3.TITLE_H : 0;
19219
+ const headerY = C3.CANVAS_PAD + titleH + C3.HEADER_H * 0.6;
19220
+ const bodyTopY = C3.CANVAS_PAD + titleH + C3.HEADER_H;
19221
+ const rowY = (row) => bodyTopY + C3.ROW_H / 2 + row * C3.ROW_H;
19222
+ const ieX2 = C3.IE_LEFT + C3.IE_STUB;
19223
+ const gridX = (col) => ieX2 + (col + 1) * C3.COL_W;
19224
19224
  const nFns = ast.functions.length;
19225
19225
  const lastGridX = nFns > 0 ? gridX(nFns - 1) : ieX2;
19226
- const outcomeX = lastGridX + C2.OUTCOME_GAP;
19226
+ const outcomeX = lastGridX + C3.OUTCOME_GAP;
19227
19227
  const assignY = (n) => {
19228
19228
  for (const c of n.children) assignY(c);
19229
19229
  n.y = (rowY(n.rowLo) + rowY(n.rowHi)) / 2;
@@ -19246,7 +19246,7 @@ function layoutEventTree(ast) {
19246
19246
  path: path2,
19247
19247
  // Label sits above the horizontal run leading into this node.
19248
19248
  labelX: (riserX + parentX) / 2,
19249
- labelY: c.y + C2.FORK_LABEL_DY
19249
+ labelY: c.y + C3.FORK_LABEL_DY
19250
19250
  });
19251
19251
  walk(c, x, c.y);
19252
19252
  }
@@ -19280,7 +19280,7 @@ function layoutEventTree(ast) {
19280
19280
  headers.push({
19281
19281
  kind: "initiating",
19282
19282
  label: "Initiating Event",
19283
- cx: C2.IE_LEFT + C2.IE_STUB / 2
19283
+ cx: C3.IE_LEFT + C3.IE_STUB / 2
19284
19284
  });
19285
19285
  ast.functions.forEach((fn, col) => {
19286
19286
  headers.push({
@@ -19290,16 +19290,16 @@ function layoutEventTree(ast) {
19290
19290
  gridX: gridX(col)
19291
19291
  });
19292
19292
  });
19293
- headers.push({ kind: "outcome", label: "Outcome", cx: outcomeX + C2.OUTCOME_W * 0.32 });
19294
- headers.push({ kind: "frequency", label: "Frequency", cx: outcomeX + C2.OUTCOME_W * 0.82 });
19295
- const gridBottom = rowY(rowCount - 1) + C2.ROW_H / 2;
19293
+ headers.push({ kind: "outcome", label: "Outcome", cx: outcomeX + C3.OUTCOME_W * 0.32 });
19294
+ headers.push({ kind: "frequency", label: "Frequency", cx: outcomeX + C3.OUTCOME_W * 0.82 });
19295
+ const gridBottom = rowY(rowCount - 1) + C3.ROW_H / 2;
19296
19296
  const gridLines = ast.functions.map((_, col) => ({
19297
19297
  x: gridX(col),
19298
19298
  y1: bodyTopY,
19299
19299
  y2: gridBottom
19300
19300
  }));
19301
- const width = outcomeX + C2.OUTCOME_W + C2.CANVAS_PAD;
19302
- const height = gridBottom + C2.CANVAS_PAD;
19301
+ const width = outcomeX + C3.OUTCOME_W + C3.CANVAS_PAD;
19302
+ const height = gridBottom + C3.CANVAS_PAD;
19303
19303
  return {
19304
19304
  ast,
19305
19305
  analysis,
@@ -19307,10 +19307,10 @@ function layoutEventTree(ast) {
19307
19307
  forks,
19308
19308
  leaves,
19309
19309
  initiating: {
19310
- x1: C2.IE_LEFT,
19310
+ x1: C3.IE_LEFT,
19311
19311
  x2: ieX2,
19312
19312
  y: root.y,
19313
- labelX: C2.IE_LEFT,
19313
+ labelX: C3.IE_LEFT,
19314
19314
  labelY: root.y - 10,
19315
19315
  freqY: root.y + 16
19316
19316
  },
@@ -20061,7 +20061,7 @@ var FMEA_CONST = {
20061
20061
  AP_COL_W: 46
20062
20062
  };
20063
20063
  function buildColumnSpecs(hasActions, rank) {
20064
- const C2 = FMEA_CONST;
20064
+ const C3 = FMEA_CONST;
20065
20065
  const specs = [
20066
20066
  { key: "no", label: "#", width: 28, align: "middle", numeric: true, field: (r7) => String(r7.index) },
20067
20067
  {
@@ -20082,9 +20082,9 @@ function buildColumnSpecs(hasActions, rank) {
20082
20082
  numeric: false,
20083
20083
  field: (r7) => r7.effects.length > 1 ? r7.effects.join("; ") : r7.effect
20084
20084
  },
20085
- { key: "sev", label: "S", width: C2.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.sev) },
20085
+ { key: "sev", label: "S", width: C3.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.sev) },
20086
20086
  { key: "cause", label: "Cause(s)", width: 120, align: "start", numeric: false, field: (r7) => r7.cause },
20087
- { key: "occ", label: "O", width: C2.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.occ) },
20087
+ { key: "occ", label: "O", width: C3.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.occ) },
20088
20088
  {
20089
20089
  key: "controls",
20090
20090
  label: "Current Controls",
@@ -20093,9 +20093,9 @@ function buildColumnSpecs(hasActions, rank) {
20093
20093
  numeric: false,
20094
20094
  field: (r7) => controlsText(r7)
20095
20095
  },
20096
- { key: "det", label: "D", width: C2.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.det) },
20097
- { key: "rpn", label: "RPN", width: C2.RPN_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.rpn) },
20098
- { key: "ap", label: "AP", width: C2.AP_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => r7.ap }
20096
+ { key: "det", label: "D", width: C3.NUM_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.det) },
20097
+ { key: "rpn", label: "RPN", width: C3.RPN_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => String(r7.rpn) },
20098
+ { key: "ap", label: "AP", width: C3.AP_COL_W, align: "middle", band: "before", numeric: true, field: (r7) => r7.ap }
20099
20099
  ];
20100
20100
  if (hasActions) {
20101
20101
  specs.push(
@@ -20111,7 +20111,7 @@ function buildColumnSpecs(hasActions, rank) {
20111
20111
  {
20112
20112
  key: "rsev",
20113
20113
  label: "S",
20114
- width: C2.NUM_COL_W,
20114
+ width: C3.NUM_COL_W,
20115
20115
  align: "middle",
20116
20116
  band: "after",
20117
20117
  numeric: true,
@@ -20121,7 +20121,7 @@ function buildColumnSpecs(hasActions, rank) {
20121
20121
  {
20122
20122
  key: "rocc",
20123
20123
  label: "O",
20124
- width: C2.NUM_COL_W,
20124
+ width: C3.NUM_COL_W,
20125
20125
  align: "middle",
20126
20126
  band: "after",
20127
20127
  numeric: true,
@@ -20131,7 +20131,7 @@ function buildColumnSpecs(hasActions, rank) {
20131
20131
  {
20132
20132
  key: "rdet",
20133
20133
  label: "D",
20134
- width: C2.NUM_COL_W,
20134
+ width: C3.NUM_COL_W,
20135
20135
  align: "middle",
20136
20136
  band: "after",
20137
20137
  numeric: true,
@@ -20141,7 +20141,7 @@ function buildColumnSpecs(hasActions, rank) {
20141
20141
  {
20142
20142
  key: "rrpn",
20143
20143
  label: "RPN",
20144
- width: C2.RPN_COL_W,
20144
+ width: C3.RPN_COL_W,
20145
20145
  align: "middle",
20146
20146
  band: "after",
20147
20147
  numeric: true,
@@ -20151,7 +20151,7 @@ function buildColumnSpecs(hasActions, rank) {
20151
20151
  {
20152
20152
  key: "rap",
20153
20153
  label: "AP",
20154
- width: C2.AP_COL_W,
20154
+ width: C3.AP_COL_W,
20155
20155
  align: "middle",
20156
20156
  band: "after",
20157
20157
  numeric: true,
@@ -20223,15 +20223,15 @@ function apRiskClass(ap) {
20223
20223
  return "ap-low";
20224
20224
  }
20225
20225
  function layoutFmea(ast, analysisIn) {
20226
- const C2 = FMEA_CONST;
20226
+ const C3 = FMEA_CONST;
20227
20227
  const analysis = analysisIn ?? analyseFmea(ast);
20228
20228
  const specs = buildColumnSpecs(analysis.hasActions, ast.rank);
20229
20229
  const metaKeys = Object.keys(ast.metadata);
20230
20230
  const legendLines = (ast.target !== void 0 || ast.acceptable !== void 0 ? 1 : 0) + (ast.flag ? 1 : 0);
20231
20231
  const metaRows = Math.ceil(metaKeys.length / 2) + legendLines;
20232
- const titleH = ast.title ? C2.TITLE_H : 0;
20233
- const metaH = metaRows > 0 ? metaRows * C2.META_LINE_H + 6 : 0;
20234
- const startX = C2.CANVAS_PAD;
20232
+ const titleH = ast.title ? C3.TITLE_H : 0;
20233
+ const metaH = metaRows > 0 ? metaRows * C3.META_LINE_H + 6 : 0;
20234
+ const startX = C3.CANVAS_PAD;
20235
20235
  let x = startX;
20236
20236
  const columns = [];
20237
20237
  const colX = {};
@@ -20250,15 +20250,15 @@ function layoutFmea(ast, analysisIn) {
20250
20250
  }
20251
20251
  const tableW = x - startX;
20252
20252
  const hasBands = analysis.hasActions;
20253
- const bandH = hasBands ? C2.BAND_H : 0;
20254
- const topY = C2.CANVAS_PAD + titleH + metaH;
20253
+ const bandH = hasBands ? C3.BAND_H : 0;
20254
+ const topY = C3.CANVAS_PAD + titleH + metaH;
20255
20255
  const bandY = topY;
20256
20256
  const headerY = topY + bandH;
20257
- const bodyY = headerY + C2.HEADER_H;
20257
+ const bodyY = headerY + C3.HEADER_H;
20258
20258
  const cells = [];
20259
20259
  const rowHeights = [];
20260
20260
  const rowY = [];
20261
- const innerW = (s) => s.width - C2.CELL_PAD_X * 2;
20261
+ const innerW = (s) => s.width - C3.CELL_PAD_X * 2;
20262
20262
  const wrapped = analysis.rows.map(
20263
20263
  (row) => specs.map((s) => ({ spec: s, row, lines: wrapText3(s.field(row), innerW(s)) }))
20264
20264
  );
@@ -20274,7 +20274,7 @@ function layoutFmea(ast, analysisIn) {
20274
20274
  return w.lines.length;
20275
20275
  });
20276
20276
  const maxLines = Math.max(1, ...lineCounts);
20277
- const h = Math.max(C2.ROW_MIN_H, maxLines * C2.LINE_H + C2.CELL_PAD_Y * 2);
20277
+ const h = Math.max(C3.ROW_MIN_H, maxLines * C3.LINE_H + C3.CELL_PAD_Y * 2);
20278
20278
  rowHeights.push(h);
20279
20279
  });
20280
20280
  let yCursor = bodyY;
@@ -20324,14 +20324,14 @@ function layoutFmea(ast, analysisIn) {
20324
20324
  if (before) bands.push({ label: "BEFORE ACTION", x: before.x, width: before.w, y: bandY, height: bandH });
20325
20325
  if (after) bands.push({ label: "AFTER ACTION", x: after.x, width: after.w, y: bandY, height: bandH });
20326
20326
  }
20327
- const totalH = (rowY.length ? rowY[rowY.length - 1] + rowHeights[rowHeights.length - 1] : bodyY) + C2.CANVAS_PAD;
20328
- const width = tableW + C2.CANVAS_PAD * 2;
20327
+ const totalH = (rowY.length ? rowY[rowY.length - 1] + rowHeights[rowHeights.length - 1] : bodyY) + C3.CANVAS_PAD;
20328
+ const width = tableW + C3.CANVAS_PAD * 2;
20329
20329
  return {
20330
20330
  ast,
20331
20331
  analysis,
20332
20332
  columns,
20333
20333
  headerY,
20334
- headerH: C2.HEADER_H,
20334
+ headerH: C3.HEADER_H,
20335
20335
  bodyY,
20336
20336
  rowHeights,
20337
20337
  rowY,
@@ -21054,11 +21054,11 @@ var RBD_CONST = {
21054
21054
  HEADER_H: 26
21055
21055
  };
21056
21056
  function blockWidth(label) {
21057
- const C2 = RBD_CONST;
21058
- return Math.min(C2.BLOCK_MAX_W, Math.max(C2.BLOCK_MIN_W, Math.ceil(label.length * C2.CHAR_W) + 2 * C2.PAD_X));
21057
+ const C3 = RBD_CONST;
21058
+ return Math.min(C3.BLOCK_MAX_W, Math.max(C3.BLOCK_MIN_W, Math.ceil(label.length * C3.CHAR_W) + 2 * C3.PAD_X));
21059
21059
  }
21060
21060
  function layoutRbd(ast) {
21061
- const C2 = RBD_CONST;
21061
+ const C3 = RBD_CONST;
21062
21062
  const analysis = analyseRbd(ast);
21063
21063
  const spof = new Set(analysis.blocks.filter((b) => b.isSpof).map((b) => b.id));
21064
21064
  const rById = new Map(analysis.blocks.map((b) => [b.id, b.R]));
@@ -21068,18 +21068,18 @@ function layoutRbd(ast) {
21068
21068
  const marks = [];
21069
21069
  const measure = (s) => {
21070
21070
  if (s.kind === "block") {
21071
- return { s, w: blockWidth(s.label ?? s.id), h: C2.BLOCK_H, children: [] };
21071
+ return { s, w: blockWidth(s.label ?? s.id), h: C3.BLOCK_H, children: [] };
21072
21072
  }
21073
21073
  const children = s.children.map(measure);
21074
- if (children.length === 0) return { s, w: C2.BLOCK_MIN_W, h: C2.BLOCK_H, children };
21074
+ if (children.length === 0) return { s, w: C3.BLOCK_MIN_W, h: C3.BLOCK_H, children };
21075
21075
  if (s.kind === "series") {
21076
- const w2 = children.reduce((acc, c) => acc + c.w, 0) + C2.H_GAP * (children.length - 1);
21076
+ const w2 = children.reduce((acc, c) => acc + c.w, 0) + C3.H_GAP * (children.length - 1);
21077
21077
  const h2 = Math.max(...children.map((c) => c.h));
21078
21078
  return { s, w: w2, h: h2, children };
21079
21079
  }
21080
21080
  const innerW = Math.max(...children.map((c) => c.w));
21081
- const w = innerW + 2 * C2.SPLIT_STUB;
21082
- const h = children.reduce((acc, c) => acc + c.h, 0) + C2.V_GAP * (children.length - 1);
21081
+ const w = innerW + 2 * C3.SPLIT_STUB;
21082
+ const h = children.reduce((acc, c) => acc + c.h, 0) + C3.V_GAP * (children.length - 1);
21083
21083
  return { s, w, h, children };
21084
21084
  };
21085
21085
  const place = (m, x, yc2) => {
@@ -21089,9 +21089,9 @@ function layoutRbd(ast) {
21089
21089
  blocks.push({
21090
21090
  block: s,
21091
21091
  x,
21092
- y: yc2 - C2.BLOCK_H / 2,
21092
+ y: yc2 - C3.BLOCK_H / 2,
21093
21093
  width: m.w,
21094
- height: C2.BLOCK_H,
21094
+ height: C3.BLOCK_H,
21095
21095
  ...r7 !== void 0 ? { R: r7 } : {},
21096
21096
  isSpof: spof.has(s.id),
21097
21097
  critical: analysis.criticalBlock === s.id
@@ -21109,14 +21109,14 @@ function layoutRbd(ast) {
21109
21109
  if (prevExit !== null) wires.push({ path: `M ${r6(prevExit)} ${r6(yc2)} L ${r6(ep2.entryX)} ${r6(yc2)}` });
21110
21110
  prevExit = ep2.exitX;
21111
21111
  lastExit = ep2.exitX;
21112
- cursor = ep2.exitX + C2.H_GAP;
21112
+ cursor = ep2.exitX + C3.H_GAP;
21113
21113
  });
21114
21114
  return { entryX: firstEntry, exitX: lastExit };
21115
21115
  }
21116
21116
  const innerW = Math.max(...m.children.map((c) => c.w));
21117
- const splitX = x + C2.NODE_R;
21118
- const mergeX = x + m.w - C2.NODE_R;
21119
- const childBandX = x + C2.SPLIT_STUB;
21117
+ const splitX = x + C3.NODE_R;
21118
+ const mergeX = x + m.w - C3.NODE_R;
21119
+ const childBandX = x + C3.SPLIT_STUB;
21120
21120
  nodes.push({ kind: "split", x: splitX, y: yc2 });
21121
21121
  nodes.push({ kind: "join", x: mergeX, y: yc2 });
21122
21122
  let runY = yc2 - m.h / 2;
@@ -21126,7 +21126,7 @@ function layoutRbd(ast) {
21126
21126
  const ep2 = place(cm, childStartX, childYc);
21127
21127
  wires.push({ path: `M ${r6(splitX)} ${r6(yc2)} L ${r6(splitX)} ${r6(childYc)} L ${r6(ep2.entryX)} ${r6(childYc)}` });
21128
21128
  wires.push({ path: `M ${r6(ep2.exitX)} ${r6(childYc)} L ${r6(mergeX)} ${r6(childYc)} L ${r6(mergeX)} ${r6(yc2)}` });
21129
- runY += cm.h + C2.V_GAP;
21129
+ runY += cm.h + C3.V_GAP;
21130
21130
  }
21131
21131
  if (s.kind === "kofn") {
21132
21132
  marks.push({ x: mergeX + 6, y: yc2 - m.h / 2 - 6, text: `${s.k}/${s.n ?? m.children.length}` });
@@ -21134,12 +21134,12 @@ function layoutRbd(ast) {
21134
21134
  return { entryX: splitX, exitX: mergeX };
21135
21135
  };
21136
21136
  const rootM = measure(ast.root);
21137
- const headerH = (ast.title ? C2.TITLE_H : 0) + C2.HEADER_H;
21138
- const yc = C2.CANVAS_PAD + headerH + rootM.h / 2;
21139
- const originX = C2.CANVAS_PAD + C2.TERM_STUB;
21137
+ const headerH = (ast.title ? C3.TITLE_H : 0) + C3.HEADER_H;
21138
+ const yc = C3.CANVAS_PAD + headerH + rootM.h / 2;
21139
+ const originX = C3.CANVAS_PAD + C3.TERM_STUB;
21140
21140
  const ep = place(rootM, originX, yc);
21141
- const inX = C2.CANVAS_PAD;
21142
- const outX = ep.exitX + C2.TERM_STUB;
21141
+ const inX = C3.CANVAS_PAD;
21142
+ const outX = ep.exitX + C3.TERM_STUB;
21143
21143
  nodes.push({ kind: "in", x: inX, y: yc });
21144
21144
  nodes.push({ kind: "out", x: outX, y: yc });
21145
21145
  wires.push({ path: `M ${r6(inX)} ${r6(yc)} L ${r6(ep.entryX)} ${r6(yc)}` });
@@ -21149,7 +21149,7 @@ function layoutRbd(ast) {
21149
21149
  for (const b of blocks) {
21150
21150
  maxX = Math.max(maxX, b.x + b.width);
21151
21151
  const capLines = (b.R !== void 0 ? 1 : 0) + (b.block.label && b.block.label !== b.block.id ? 1 : 0);
21152
- maxY = Math.max(maxY, b.y + b.height + (capLines > 0 ? C2.CAP_GAP + capLines * C2.CAP_LINE_H : 0));
21152
+ maxY = Math.max(maxY, b.y + b.height + (capLines > 0 ? C3.CAP_GAP + capLines * C3.CAP_LINE_H : 0));
21153
21153
  }
21154
21154
  for (const mk of marks) maxX = Math.max(maxX, mk.x + 24);
21155
21155
  return {
@@ -21159,8 +21159,8 @@ function layoutRbd(ast) {
21159
21159
  nodes,
21160
21160
  wires,
21161
21161
  marks,
21162
- width: Math.ceil(maxX + C2.CANVAS_PAD),
21163
- height: Math.ceil(maxY + C2.CANVAS_PAD)
21162
+ width: Math.ceil(maxX + C3.CANVAS_PAD),
21163
+ height: Math.ceil(maxY + C3.CANVAS_PAD)
21164
21164
  };
21165
21165
  }
21166
21166
  function r6(n) {
@@ -21359,6 +21359,1245 @@ var rbd = {
21359
21359
  }
21360
21360
  };
21361
21361
 
21362
+ // src/diagrams/comparison/parser.ts
21363
+ var ComparisonParseError = class extends Error {
21364
+ constructor(message, line2) {
21365
+ super(line2 ? `Line ${line2}: ${message}` : message);
21366
+ this.line = line2;
21367
+ this.name = "ComparisonParseError";
21368
+ }
21369
+ line;
21370
+ };
21371
+ var MODES = [
21372
+ "tchart",
21373
+ "pros-cons",
21374
+ "matrix",
21375
+ "decision",
21376
+ "double-bubble"
21377
+ ];
21378
+ function parseComparison(text2) {
21379
+ const ast = {
21380
+ type: "comparison",
21381
+ mode: "tchart",
21382
+ columns: [],
21383
+ pros: [],
21384
+ cons: [],
21385
+ options: [],
21386
+ criteria: [],
21387
+ legend: "on",
21388
+ warnings: []
21389
+ };
21390
+ const rawLines = text2.split(/\r?\n/);
21391
+ let i = 0;
21392
+ let explicitMode;
21393
+ while (i < rawLines.length) {
21394
+ const t = stripComment8(rawLines[i] ?? "").trim();
21395
+ if (t === "") {
21396
+ i++;
21397
+ continue;
21398
+ }
21399
+ const h = /^(comparison|compare|vs|tchart|t-chart|pugh|decision-matrix|decisionmatrix)\b(.*)$/i.exec(t);
21400
+ if (h) {
21401
+ const head = h[1].toLowerCase();
21402
+ if (head === "tchart" || head === "t-chart") explicitMode = "tchart";
21403
+ else if (head === "pugh" || head === "decision-matrix" || head === "decisionmatrix")
21404
+ explicitMode = "decision";
21405
+ const q = matchQuoted6(h[2].trim());
21406
+ if (q) ast.title = q.value;
21407
+ i++;
21408
+ }
21409
+ break;
21410
+ }
21411
+ let curColumn = null;
21412
+ let curCriterion = null;
21413
+ let colCount = 0;
21414
+ let optCount = 0;
21415
+ let critCount = 0;
21416
+ const bubble = { left: "", right: "", shared: [], leftOnly: [], rightOnly: [] };
21417
+ for (; i < rawLines.length; i++) {
21418
+ const t = stripComment8(rawLines[i] ?? "").trim();
21419
+ if (t === "") continue;
21420
+ const lineNo = i + 1;
21421
+ if (/^mode\s*:/i.test(t)) {
21422
+ const v = afterColon6(t).toLowerCase().replace(/\s+/g, "-");
21423
+ const m = normaliseMode(v);
21424
+ if (m) explicitMode = m;
21425
+ else ast.warnings.push(`Line ${lineNo}: unknown mode "${afterColon6(t)}" \u2014 using ${explicitMode ?? "inferred"}.`);
21426
+ continue;
21427
+ }
21428
+ if (/^legend\s*:/i.test(t)) {
21429
+ const v = afterColon6(t).toLowerCase();
21430
+ if (v === "on" || v === "off") ast.legend = v;
21431
+ continue;
21432
+ }
21433
+ if (/^baseline\s*:/i.test(t)) {
21434
+ const q = matchQuoted6(afterColon6(t));
21435
+ ast.baseline = q ? q.value : afterColon6(t);
21436
+ continue;
21437
+ }
21438
+ if (/^(title|subject)\s*:/i.test(t)) {
21439
+ const q = matchQuoted6(afterColon6(t));
21440
+ const val = q ? q.value : afterColon6(t);
21441
+ if (/^subject/i.test(t)) ast.subject = val;
21442
+ else if (!ast.title) ast.title = val;
21443
+ continue;
21444
+ }
21445
+ if (/^theme\s*:/i.test(t)) continue;
21446
+ if (curCriterion) {
21447
+ const ref = cellPrefix(t);
21448
+ if (ref !== null) {
21449
+ const valTok = t.slice(t.indexOf(":") + 1).trim();
21450
+ const opt = findOption(ast.options, ref);
21451
+ if (!opt) {
21452
+ ast.warnings.push(
21453
+ `Line ${lineNo}: "${ref}" is not a declared option \u2014 add \`option "${ref}"\` or fix the name.`
21454
+ );
21455
+ } else {
21456
+ curCriterion.cells[opt.id] = parseCellValue(valTok);
21457
+ }
21458
+ continue;
21459
+ }
21460
+ }
21461
+ const kw = /^([a-z][a-z-]*)\b/i.exec(t);
21462
+ const keyword = kw ? kw[1].toLowerCase() : "";
21463
+ const rest = kw ? t.slice(kw[0].length).trim() : t;
21464
+ switch (keyword) {
21465
+ case "column":
21466
+ case "col": {
21467
+ const label = requireLabel2(rest, keyword, lineNo);
21468
+ curColumn = { id: `col${++colCount}`, label, items: [] };
21469
+ ast.columns.push(curColumn);
21470
+ curCriterion = null;
21471
+ break;
21472
+ }
21473
+ case "item": {
21474
+ const label = requireLabel2(rest, keyword, lineNo);
21475
+ if (!curColumn) {
21476
+ ast.warnings.push(`Line ${lineNo}: \`item\` before any \`column\` \u2014 ignored.`);
21477
+ } else curColumn.items.push(label);
21478
+ break;
21479
+ }
21480
+ case "pro": {
21481
+ ast.pros.push(requireLabel2(rest, keyword, lineNo));
21482
+ break;
21483
+ }
21484
+ case "con": {
21485
+ ast.cons.push(requireLabel2(rest, keyword, lineNo));
21486
+ break;
21487
+ }
21488
+ case "option":
21489
+ case "opt": {
21490
+ const label = requireLabel2(rest, keyword, lineNo);
21491
+ ast.options.push({ id: `o${++optCount}`, label });
21492
+ curCriterion = null;
21493
+ break;
21494
+ }
21495
+ case "criterion":
21496
+ case "criteria":
21497
+ case "row": {
21498
+ curCriterion = parseCriterion(rest, `c${++critCount}`, keyword, lineNo, ast.options, ast.warnings, lineNo);
21499
+ ast.criteria.push(curCriterion);
21500
+ curColumn = null;
21501
+ break;
21502
+ }
21503
+ case "left":
21504
+ bubble.left = requireLabel2(rest, keyword, lineNo);
21505
+ break;
21506
+ case "right":
21507
+ bubble.right = requireLabel2(rest, keyword, lineNo);
21508
+ break;
21509
+ case "shared":
21510
+ case "both":
21511
+ bubble.shared.push(requireLabel2(rest, keyword, lineNo));
21512
+ break;
21513
+ case "left-only":
21514
+ case "leftonly":
21515
+ bubble.leftOnly.push(requireLabel2(rest, keyword, lineNo));
21516
+ break;
21517
+ case "right-only":
21518
+ case "rightonly":
21519
+ bubble.rightOnly.push(requireLabel2(rest, keyword, lineNo));
21520
+ break;
21521
+ default: {
21522
+ const bullet = /^[-*•]\s+(.*)$/.exec(t);
21523
+ if (bullet && curColumn) {
21524
+ curColumn.items.push(unquoteLoose(bullet[1].trim()));
21525
+ } else if (bullet) {
21526
+ ast.warnings.push(`Line ${lineNo}: bullet "${truncate7(t, 60)}" before any \`column\` \u2014 ignored.`);
21527
+ } else {
21528
+ ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate7(t, 80)}"`);
21529
+ }
21530
+ }
21531
+ }
21532
+ }
21533
+ if (bubble.left || bubble.right || bubble.shared.length) {
21534
+ ast.bubble = bubble;
21535
+ }
21536
+ ast.mode = explicitMode ?? inferMode(ast);
21537
+ validate4(ast);
21538
+ return ast;
21539
+ }
21540
+ function parseCriterion(rest, id, keyword, lineNo, options, warnings, ln) {
21541
+ const pipeIdx = rest.indexOf("|");
21542
+ let head = pipeIdx >= 0 ? rest.slice(0, pipeIdx).trim() : rest;
21543
+ const cells = {};
21544
+ let weight;
21545
+ const wm = /\b(?:weight|w)\s*[:=]\s*(\d+(?:\.\d+)?)/i.exec(head);
21546
+ if (wm) {
21547
+ weight = Number(wm[1]);
21548
+ head = head.slice(0, wm.index).trim() + head.slice(wm.index + wm[0].length).trim();
21549
+ head = head.trim();
21550
+ }
21551
+ const label = requireLabel2(head, keyword, lineNo);
21552
+ if (pipeIdx >= 0) {
21553
+ const parts = rest.slice(pipeIdx + 1).split("|").map((p) => p.trim());
21554
+ parts.forEach((p, k) => {
21555
+ const opt = options[k];
21556
+ if (!opt) {
21557
+ if (p) warnings.push(`Line ${ln}: pipe value "${p}" has no matching option (only ${options.length} declared).`);
21558
+ return;
21559
+ }
21560
+ if (p) cells[opt.id] = parseCellValue(p);
21561
+ });
21562
+ }
21563
+ const crit = { id, label, cells };
21564
+ if (weight !== void 0) crit.weight = weight;
21565
+ return crit;
21566
+ }
21567
+ function parseCellValue(tok) {
21568
+ const raw = tok;
21569
+ const q = matchQuoted6(tok);
21570
+ if (q) return { text: q.value, raw };
21571
+ const low = tok.toLowerCase();
21572
+ if (/^(yes|y|true|✓|✔|check)$/.test(low)) return { glyph: "yes", raw };
21573
+ if (/^(no|n|false|✗|✘|x|cross)$/.test(low)) return { glyph: "no", raw };
21574
+ if (/^(partial|part|~|maybe|some|half)$/.test(low)) return { glyph: "partial", raw };
21575
+ if (/^(na|n\/a|-|—|none)$/.test(low)) return { glyph: "na", raw };
21576
+ const num4 = Number(tok);
21577
+ if (tok !== "" && !Number.isNaN(num4)) return { score: num4, raw };
21578
+ return { text: tok, raw };
21579
+ }
21580
+ function inferMode(ast) {
21581
+ if (ast.bubble) return "double-bubble";
21582
+ if (ast.pros.length || ast.cons.length) return "pros-cons";
21583
+ if (ast.options.length || ast.criteria.length) {
21584
+ const anyScore = ast.criteria.some(
21585
+ (c) => Object.values(c.cells).some((v) => typeof v.score === "number")
21586
+ );
21587
+ const anyWeight = ast.criteria.some((c) => c.weight !== void 0);
21588
+ return anyScore || anyWeight || ast.baseline ? "decision" : "matrix";
21589
+ }
21590
+ return "tchart";
21591
+ }
21592
+ function normaliseMode(v) {
21593
+ if (v === "ychart" || v === "y-chart") return "tchart";
21594
+ if (v === "proscons" || v === "pro-con" || v === "pros-and-cons") return "pros-cons";
21595
+ if (v === "pugh" || v === "decision-matrix") return "decision";
21596
+ if (v === "doublebubble" || v === "double-bubble" || v === "compare-contrast") return "double-bubble";
21597
+ return MODES.includes(v) ? v : void 0;
21598
+ }
21599
+ function validate4(ast) {
21600
+ switch (ast.mode) {
21601
+ case "tchart": {
21602
+ if (ast.columns.length === 0) {
21603
+ throw new ComparisonParseError(
21604
+ `a tchart needs at least one \`column "\u2026"\` \u2014 declare the columns you want to compare.`
21605
+ );
21606
+ }
21607
+ break;
21608
+ }
21609
+ case "pros-cons": {
21610
+ if (ast.pros.length === 0 && ast.cons.length === 0) {
21611
+ throw new ComparisonParseError(
21612
+ `a pros-cons needs at least one \`pro "\u2026"\` or \`con "\u2026"\` line.`
21613
+ );
21614
+ }
21615
+ break;
21616
+ }
21617
+ case "matrix":
21618
+ case "decision": {
21619
+ if (ast.options.length === 0) {
21620
+ throw new ComparisonParseError(
21621
+ `a ${ast.mode} matrix needs at least one \`option "\u2026"\` \u2014 declare the options (columns) you are comparing.`
21622
+ );
21623
+ }
21624
+ if (ast.criteria.length === 0) {
21625
+ throw new ComparisonParseError(
21626
+ `a ${ast.mode} matrix needs at least one \`criterion "\u2026"\` \u2014 declare the criteria (rows) to compare on.`
21627
+ );
21628
+ }
21629
+ if (ast.mode === "decision") {
21630
+ const anyScore = ast.criteria.some(
21631
+ (c) => Object.values(c.cells).some((v) => typeof v.score === "number")
21632
+ );
21633
+ if (!anyScore) {
21634
+ ast.warnings.push(
21635
+ `decision mode but no numeric scores found \u2014 add \`Option: <number>\` lines under each criterion, or switch to \`mode: matrix\`.`
21636
+ );
21637
+ }
21638
+ if (ast.baseline) {
21639
+ const ok = ast.options.some((o) => o.label === ast.baseline || o.id === ast.baseline);
21640
+ if (!ok) {
21641
+ ast.warnings.push(
21642
+ `baseline "${ast.baseline}" is not one of the declared options \u2014 ignored.`
21643
+ );
21644
+ delete ast.baseline;
21645
+ }
21646
+ }
21647
+ }
21648
+ break;
21649
+ }
21650
+ case "double-bubble": {
21651
+ if (!ast.bubble || !ast.bubble.left || !ast.bubble.right) {
21652
+ throw new ComparisonParseError(
21653
+ `a double-bubble needs both a \`left "\u2026"\` and a \`right "\u2026"\` centre to compare.`
21654
+ );
21655
+ }
21656
+ break;
21657
+ }
21658
+ }
21659
+ }
21660
+ var RESERVED_KEYWORDS = /* @__PURE__ */ new Set([
21661
+ "comparison",
21662
+ "compare",
21663
+ "vs",
21664
+ "tchart",
21665
+ "t-chart",
21666
+ "pugh",
21667
+ "decision-matrix",
21668
+ "decisionmatrix",
21669
+ "mode",
21670
+ "legend",
21671
+ "baseline",
21672
+ "title",
21673
+ "subject",
21674
+ "theme",
21675
+ "column",
21676
+ "col",
21677
+ "item",
21678
+ "pro",
21679
+ "con",
21680
+ "option",
21681
+ "opt",
21682
+ "criterion",
21683
+ "criteria",
21684
+ "row",
21685
+ "left",
21686
+ "right",
21687
+ "shared",
21688
+ "both",
21689
+ "left-only",
21690
+ "leftonly",
21691
+ "right-only",
21692
+ "rightonly"
21693
+ ]);
21694
+ function cellPrefix(t) {
21695
+ const ci = t.indexOf(":");
21696
+ if (ci <= 0) return null;
21697
+ const pre = t.slice(0, ci).trim();
21698
+ if (!pre) return null;
21699
+ const firstWord2 = (pre.split(/\s+/)[0] ?? "").toLowerCase();
21700
+ if (RESERVED_KEYWORDS.has(firstWord2)) return null;
21701
+ return pre;
21702
+ }
21703
+ function findOption(options, ref) {
21704
+ const r7 = ref.toLowerCase();
21705
+ return options.find((o) => o.label.toLowerCase() === r7 || o.id.toLowerCase() === r7);
21706
+ }
21707
+ function requireLabel2(s, keyword, lineNo) {
21708
+ const q = matchQuoted6(s);
21709
+ if (q) return q.value;
21710
+ const bare = s.trim();
21711
+ if (!bare) throw new ComparisonParseError(`\`${keyword}\` needs a label`, lineNo);
21712
+ return bare;
21713
+ }
21714
+ function unquoteLoose(s) {
21715
+ const q = matchQuoted6(s);
21716
+ return q && q.length === s.length ? q.value : s;
21717
+ }
21718
+ function matchQuoted6(s) {
21719
+ if (!s) return void 0;
21720
+ const open = s[0];
21721
+ if (open !== '"' && open !== "\u300C" && open !== "\u201C" && open !== "\u300E") return void 0;
21722
+ const close = closingQuote6(open);
21723
+ const end = s.indexOf(close, 1);
21724
+ if (end < 0) return void 0;
21725
+ return { value: s.slice(1, end), length: end + 1 };
21726
+ }
21727
+ function closingQuote6(open) {
21728
+ return open === "\u300C" ? "\u300D" : open === "\u300E" ? "\u300F" : open === "\u201C" ? "\u201D" : '"';
21729
+ }
21730
+ function afterColon6(s) {
21731
+ const i = s.indexOf(":");
21732
+ return i < 0 ? "" : s.slice(i + 1).trim();
21733
+ }
21734
+ function stripComment8(line2) {
21735
+ let inQ = false;
21736
+ let qc = "";
21737
+ for (let i = 0; i < line2.length; i++) {
21738
+ const ch = line2[i];
21739
+ if (inQ) {
21740
+ if (ch === qc) inQ = false;
21741
+ continue;
21742
+ }
21743
+ if (ch === '"' || ch === "\u300C" || ch === "\u201C" || ch === "\u300E") {
21744
+ inQ = true;
21745
+ qc = closingQuote6(ch);
21746
+ continue;
21747
+ }
21748
+ if (ch === "#") return line2.slice(0, i);
21749
+ if (ch === "/" && line2[i + 1] === "/") return line2.slice(0, i);
21750
+ }
21751
+ return line2;
21752
+ }
21753
+ function truncate7(s, n) {
21754
+ return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
21755
+ }
21756
+
21757
+ // src/diagrams/comparison/compute.ts
21758
+ function scoreOf(v) {
21759
+ if (!v) return 0;
21760
+ if (typeof v.score === "number") return v.score;
21761
+ if (v.glyph === "yes") return 1;
21762
+ if (v.glyph === "partial") return 0.5;
21763
+ if (v.glyph === "no" || v.glyph === "na") return 0;
21764
+ return 0;
21765
+ }
21766
+ function computeDecision(ast) {
21767
+ const totals = {};
21768
+ const totalWeight = ast.criteria.reduce((s, c) => s + (c.weight ?? 1), 0);
21769
+ for (const opt of ast.options) {
21770
+ let sum = 0;
21771
+ for (const crit of ast.criteria) {
21772
+ const w = crit.weight ?? 1;
21773
+ sum += w * scoreOf(crit.cells[opt.id]);
21774
+ }
21775
+ totals[opt.id] = round7(sum);
21776
+ }
21777
+ const sorted = [...ast.options].sort((a, b) => totals[b.id] - totals[a.id]);
21778
+ const ranks = {};
21779
+ let lastTotal = Number.POSITIVE_INFINITY;
21780
+ let lastRank = 0;
21781
+ sorted.forEach((opt, i) => {
21782
+ const t = totals[opt.id];
21783
+ if (t < lastTotal) {
21784
+ lastRank = i + 1;
21785
+ lastTotal = t;
21786
+ }
21787
+ ranks[opt.id] = lastRank;
21788
+ });
21789
+ const winnerId = sorted.length ? sorted[0].id : "";
21790
+ const maxTotal = sorted.length ? totals[winnerId] : 0;
21791
+ const result = { totals, ranks, winnerId, maxTotal, totalWeight };
21792
+ if (ast.baseline) {
21793
+ const base = ast.options.find(
21794
+ (o) => o.id === ast.baseline || o.label === ast.baseline
21795
+ );
21796
+ if (base) {
21797
+ const baseTotal = totals[base.id];
21798
+ const deltas = {};
21799
+ for (const opt of ast.options) deltas[opt.id] = round7(totals[opt.id] - baseTotal);
21800
+ result.deltas = deltas;
21801
+ }
21802
+ }
21803
+ return result;
21804
+ }
21805
+ function decisionCaption(ast, r7) {
21806
+ if (!ast.options.length) return "Decision matrix: no options.";
21807
+ const winner = ast.options.find((o) => o.id === r7.winnerId);
21808
+ const tiedIds = ast.options.filter((o) => r7.ranks[o.id] === 1).map((o) => o.id);
21809
+ if (tiedIds.length > 1) {
21810
+ const names = tiedIds.map((id) => ast.options.find((o) => o.id === id)?.label).filter(Boolean).map((n) => `"${n}"`).join(" / ");
21811
+ return `Tie at the top: ${names} (weighted score ${fmt3(r7.maxTotal)} of ${ast.options.length} options).`;
21812
+ }
21813
+ return `Winner: "${winner?.label ?? r7.winnerId}" \u2014 weighted score ${fmt3(
21814
+ r7.maxTotal
21815
+ )}, highest of ${ast.options.length} option${ast.options.length === 1 ? "" : "s"}.`;
21816
+ }
21817
+ function round7(n) {
21818
+ return Math.round(n * 1e3) / 1e3;
21819
+ }
21820
+ function fmt3(n) {
21821
+ const r7 = Math.round(n * 100) / 100;
21822
+ return Number.isInteger(r7) ? String(r7) : String(r7);
21823
+ }
21824
+
21825
+ // src/diagrams/comparison/layout.ts
21826
+ var COMPARISON_CONST = {
21827
+ PAGE_PAD: 24,
21828
+ TITLE_H: 40,
21829
+ CAPTION_H: 30,
21830
+ HEADER_MIN_H: 36,
21831
+ ROW_MIN_H: 34,
21832
+ CELL_PAD_X: 12,
21833
+ CELL_PAD_Y: 8,
21834
+ LINE_H: 16,
21835
+ COL_MIN_W: 140,
21836
+ COL_MAX_W: 264,
21837
+ MARK_COL_MIN_W: 92,
21838
+ MARK_COL_MAX_W: 190,
21839
+ ROWHEAD_MIN_W: 120,
21840
+ ROWHEAD_MAX_W: 230,
21841
+ FONT: 12,
21842
+ HEADER_FONT: 13,
21843
+ // double-bubble — larger, rounder bubbles with generous spacing
21844
+ CENTER_RX: 70,
21845
+ CENTER_RY: 58,
21846
+ SHARED_RX: 60,
21847
+ SHARED_RY: 46,
21848
+ UNIQUE_RX: 70,
21849
+ UNIQUE_RY: 46,
21850
+ BUBBLE_VGAP: 22,
21851
+ // tchart
21852
+ TCHART_COL_GAP: 22,
21853
+ // pros-cons
21854
+ PC_COL_W: 322,
21855
+ PC_COL_GAP: 30,
21856
+ PC_PILL_H: 40,
21857
+ PC_ROW_MIN_H: 40,
21858
+ PC_BADGE_R: 11
21859
+ };
21860
+ function charW(ch, fontSize) {
21861
+ const cp = ch.codePointAt(0) ?? 0;
21862
+ if (cp >= 11904 && cp <= 40959) return fontSize;
21863
+ if (cp >= 44032 && cp <= 55203) return fontSize;
21864
+ if (cp >= 65280 && cp <= 65519) return fontSize;
21865
+ if (ch === " ") return fontSize * 0.3;
21866
+ if (/[ilj.,:'!|]/.test(ch)) return fontSize * 0.3;
21867
+ if (/[mwMW]/.test(ch)) return fontSize * 0.85;
21868
+ return fontSize * 0.56;
21869
+ }
21870
+ function measureText(s, fontSize) {
21871
+ let w = 0;
21872
+ for (const ch of s) w += charW(ch, fontSize);
21873
+ return w;
21874
+ }
21875
+ function wrapToWidth(s, maxW, fontSize) {
21876
+ if (!s) return [""];
21877
+ const hasSpaces = /\s/.test(s.trim());
21878
+ const tokens = hasSpaces ? s.split(/\s+/).filter(Boolean) : [...s];
21879
+ const sep = hasSpaces ? " " : "";
21880
+ const lines = [];
21881
+ let cur = "";
21882
+ for (const tok of tokens) {
21883
+ const trial = cur ? cur + sep + tok : tok;
21884
+ if (cur && measureText(trial, fontSize) > maxW) {
21885
+ lines.push(cur);
21886
+ cur = tok;
21887
+ } else {
21888
+ cur = trial;
21889
+ }
21890
+ }
21891
+ if (cur) lines.push(cur);
21892
+ return lines.length ? lines : [""];
21893
+ }
21894
+ var C2 = COMPARISON_CONST;
21895
+ function layoutComparison(ast) {
21896
+ switch (ast.mode) {
21897
+ case "tchart":
21898
+ return layoutColumns(ast);
21899
+ case "pros-cons":
21900
+ return layoutProsCons(ast);
21901
+ case "matrix":
21902
+ case "decision":
21903
+ return layoutGrid(ast);
21904
+ case "double-bubble":
21905
+ return layoutDoubleBubble(ast);
21906
+ }
21907
+ }
21908
+ function frame(ast) {
21909
+ const pad = C2.PAGE_PAD;
21910
+ const top = pad + (ast.title ? C2.TITLE_H : 0);
21911
+ return { top, pad };
21912
+ }
21913
+ function layoutColumns(ast) {
21914
+ const { top, pad } = frame(ast);
21915
+ const cells = [];
21916
+ const connectors = [];
21917
+ const frames = [];
21918
+ const gap = C2.TCHART_COL_GAP;
21919
+ const headGap = 10;
21920
+ const cardPadBottom = 12;
21921
+ const textLeft = 16;
21922
+ const colWidths = ast.columns.map((col) => {
21923
+ const headW = measureText(col.label, C2.HEADER_FONT) + 2 * C2.CELL_PAD_X;
21924
+ const itemW = Math.max(
21925
+ 0,
21926
+ ...col.items.map((it) => measureText(it, C2.FONT) + textLeft + 16)
21927
+ );
21928
+ return clamp(Math.max(headW, itemW, C2.COL_MIN_W), C2.COL_MIN_W, C2.COL_MAX_W);
21929
+ });
21930
+ const headerLines = ast.columns.map(
21931
+ (col, i) => wrapToWidth(col.label, colWidths[i] - 2 * C2.CELL_PAD_X, C2.HEADER_FONT)
21932
+ );
21933
+ const headerH = Math.max(
21934
+ C2.HEADER_MIN_H,
21935
+ ...headerLines.map((l) => l.length * C2.LINE_H + 2 * C2.CELL_PAD_Y)
21936
+ );
21937
+ const colRows = ast.columns.map(
21938
+ (col, i) => col.items.map((it) => {
21939
+ const lines = wrapToWidth(it, colWidths[i] - textLeft - 14, C2.FONT);
21940
+ return { lines, h: Math.max(C2.ROW_MIN_H, lines.length * C2.LINE_H + 2 * C2.CELL_PAD_Y) };
21941
+ })
21942
+ );
21943
+ const itemsTop = top + headerH + headGap;
21944
+ const naturalH = colRows.map(
21945
+ (rows) => headerH + headGap + rows.reduce((s, r7) => s + r7.h, 0) + cardPadBottom
21946
+ );
21947
+ const cardH = Math.max(headerH + 44, ...naturalH);
21948
+ let x = pad;
21949
+ ast.columns.forEach((_col, i) => {
21950
+ const w = colWidths[i];
21951
+ frames.push({ x, y: top, w, h: cardH, rx: 12, variant: "card" });
21952
+ cells.push({
21953
+ x,
21954
+ y: top,
21955
+ w,
21956
+ h: headerH,
21957
+ lines: headerLines[i],
21958
+ variant: "colHeader",
21959
+ align: "middle",
21960
+ bold: true,
21961
+ paletteIndex: i,
21962
+ roundedTop: true
21963
+ });
21964
+ let cy = itemsTop;
21965
+ colRows[i].forEach((r7, k) => {
21966
+ cells.push({ x, y: cy, w, h: r7.h, lines: r7.lines, variant: "body", align: "start", bare: true });
21967
+ if (k < colRows[i].length - 1) {
21968
+ connectors.push({ x1: x + 14, y1: cy + r7.h, x2: x + w - 14, y2: cy + r7.h, light: true });
21969
+ }
21970
+ cy += r7.h;
21971
+ });
21972
+ x += w + gap;
21973
+ });
21974
+ const totalW = x - pad - gap;
21975
+ return {
21976
+ ast,
21977
+ mode: ast.mode,
21978
+ cells,
21979
+ ellipses: [],
21980
+ connectors,
21981
+ frames,
21982
+ width: Math.ceil(totalW + 2 * pad),
21983
+ height: Math.ceil(top + cardH + pad)
21984
+ };
21985
+ }
21986
+ function layoutProsCons(ast) {
21987
+ const { top, pad } = frame(ast);
21988
+ const cells = [];
21989
+ const connectors = [];
21990
+ const colW = C2.PC_COL_W;
21991
+ const leftX = pad;
21992
+ const rightX = pad + colW + C2.PC_COL_GAP;
21993
+ const badgeRoom = 2 * C2.PC_BADGE_R + 14;
21994
+ const pillH = C2.PC_PILL_H;
21995
+ const pill = (label, colX, kind) => {
21996
+ const pw = clamp(measureText(label, C2.HEADER_FONT) + badgeRoom + 30, 130, colW);
21997
+ cells.push({
21998
+ x: colX + (colW - pw) / 2,
21999
+ y: top,
22000
+ w: pw,
22001
+ h: pillH,
22002
+ lines: [label],
22003
+ variant: kind === "pro" ? "pillPos" : "pillNeg",
22004
+ align: "middle",
22005
+ bold: true,
22006
+ rx: pillH / 2,
22007
+ badge: { glyph: kind === "pro" ? "yes" : "no", tone: kind === "pro" ? "pos" : "neg" }
22008
+ });
22009
+ };
22010
+ pill("PROS", leftX, "pro");
22011
+ pill("CONS", rightX, "con");
22012
+ const itemsTop = top + pillH + 14;
22013
+ const itemCell = (txt, x, y, kind) => {
22014
+ const lines = wrapToWidth(txt, colW - badgeRoom - 14, C2.FONT);
22015
+ const h = Math.max(C2.PC_ROW_MIN_H, lines.length * C2.LINE_H + 2 * C2.CELL_PAD_Y);
22016
+ return {
22017
+ x,
22018
+ y,
22019
+ w: colW,
22020
+ h,
22021
+ lines,
22022
+ variant: kind,
22023
+ align: "start",
22024
+ bare: true,
22025
+ badge: { glyph: kind === "pro" ? "yes" : "no", tone: kind === "pro" ? "pos" : "neg" }
22026
+ };
22027
+ };
22028
+ let ly = itemsTop;
22029
+ for (const p of ast.pros) {
22030
+ const cell = itemCell(p, leftX, ly, "pro");
22031
+ cells.push(cell);
22032
+ ly += cell.h;
22033
+ }
22034
+ let ry = itemsTop;
22035
+ for (const c of ast.cons) {
22036
+ const cell = itemCell(c, rightX, ry, "con");
22037
+ cells.push(cell);
22038
+ ry += cell.h;
22039
+ }
22040
+ const bottom = Math.max(ly, ry);
22041
+ const dx = leftX + colW + C2.PC_COL_GAP / 2;
22042
+ connectors.push({ x1: dx, y1: itemsTop, x2: dx, y2: bottom - 6 });
22043
+ return {
22044
+ ast,
22045
+ mode: ast.mode,
22046
+ cells,
22047
+ ellipses: [],
22048
+ connectors,
22049
+ width: colW * 2 + C2.PC_COL_GAP + 2 * pad,
22050
+ height: Math.ceil(bottom + pad)
22051
+ };
22052
+ }
22053
+ function layoutGrid(ast) {
22054
+ const { top, pad } = frame(ast);
22055
+ const cells = [];
22056
+ const isDecision = ast.mode === "decision";
22057
+ const decision = isDecision ? computeDecision(ast) : void 0;
22058
+ const cellText = (oid, cid) => {
22059
+ const v = ast.criteria.find((c) => c.id === cid).cells[oid];
22060
+ if (!v) return { lines: [], variant: "body" };
22061
+ if (v.glyph) {
22062
+ const variant = v.glyph === "yes" ? "pos" : v.glyph === "no" ? "neg" : v.glyph === "partial" ? "warn" : "body";
22063
+ return { lines: v.glyph === "na" ? ["\u2014"] : [], glyph: v.glyph === "na" ? void 0 : v.glyph, variant };
22064
+ }
22065
+ if (typeof v.score === "number") return { lines: [fmt3(v.score)], variant: "body" };
22066
+ return { lines: v.text ? [v.text] : [], variant: "body" };
22067
+ };
22068
+ const rowHeadW = clamp(
22069
+ Math.max(
22070
+ C2.ROWHEAD_MIN_W,
22071
+ ...ast.criteria.map((c) => measureText(c.label, C2.FONT) + 2 * C2.CELL_PAD_X + (isDecision ? 30 : 0)),
22072
+ measureText(isDecision ? "Weighted total" : "", C2.FONT) + 2 * C2.CELL_PAD_X
22073
+ ),
22074
+ C2.ROWHEAD_MIN_W,
22075
+ C2.ROWHEAD_MAX_W
22076
+ );
22077
+ const optW = ast.options.map((o) => {
22078
+ const headW = measureText(o.label, C2.HEADER_FONT) + 2 * C2.CELL_PAD_X;
22079
+ const bodyW = Math.max(
22080
+ 0,
22081
+ ...ast.criteria.map((c) => {
22082
+ const ct = cellText(o.id, c.id);
22083
+ return Math.max(0, ...ct.lines.map((l) => measureText(l, C2.FONT))) + 2 * C2.CELL_PAD_X;
22084
+ })
22085
+ );
22086
+ return clamp(Math.max(headW, bodyW, C2.MARK_COL_MIN_W), C2.MARK_COL_MIN_W, C2.MARK_COL_MAX_W);
22087
+ });
22088
+ const headLines = ast.options.map(
22089
+ (o, i) => wrapToWidth(o.label, optW[i] - 2 * C2.CELL_PAD_X, C2.HEADER_FONT)
22090
+ );
22091
+ const headerH = Math.max(C2.HEADER_MIN_H, ...headLines.map((l) => l.length * C2.LINE_H + 2 * C2.CELL_PAD_Y));
22092
+ cells.push({
22093
+ x: pad,
22094
+ y: top,
22095
+ w: rowHeadW,
22096
+ h: headerH,
22097
+ lines: ast.title ? [] : [],
22098
+ variant: "corner",
22099
+ align: "start"
22100
+ });
22101
+ let hx = pad + rowHeadW;
22102
+ const colX = [];
22103
+ ast.options.forEach((o, i) => {
22104
+ colX.push(hx);
22105
+ const isBase = isDecision && ast.baseline && (o.label === ast.baseline || o.id === ast.baseline);
22106
+ cells.push({
22107
+ x: hx,
22108
+ y: top,
22109
+ w: optW[i],
22110
+ h: headerH,
22111
+ lines: headLines[i],
22112
+ variant: isBase ? "baseline" : "colHeader",
22113
+ align: "middle",
22114
+ bold: true,
22115
+ tag: isBase ? "datum" : void 0
22116
+ });
22117
+ hx += optW[i];
22118
+ });
22119
+ const gridW = rowHeadW + optW.reduce((a, b) => a + b, 0);
22120
+ let ry = top + headerH;
22121
+ for (const crit of ast.criteria) {
22122
+ const labelLines = wrapToWidth(crit.label, rowHeadW - 2 * C2.CELL_PAD_X - (isDecision ? 26 : 0), C2.FONT);
22123
+ const bodyLineCounts = ast.options.map((o) => {
22124
+ const ct = cellText(o.id, crit.id);
22125
+ const wrapped = ct.lines.flatMap(
22126
+ (l, idx) => idx === 0 ? wrapToWidth(l, optW[ast.options.indexOf(o)] - 2 * C2.CELL_PAD_X, C2.FONT) : [l]
22127
+ );
22128
+ return wrapped.length;
22129
+ });
22130
+ const rowH = Math.max(
22131
+ C2.ROW_MIN_H,
22132
+ labelLines.length * C2.LINE_H + 2 * C2.CELL_PAD_Y,
22133
+ ...bodyLineCounts.map((n) => n * C2.LINE_H + 2 * C2.CELL_PAD_Y)
22134
+ );
22135
+ cells.push({
22136
+ x: pad,
22137
+ y: ry,
22138
+ w: rowHeadW,
22139
+ h: rowH,
22140
+ lines: labelLines,
22141
+ variant: "rowHeader",
22142
+ align: "start",
22143
+ tag: isDecision ? `\xD7${fmt3(crit.weight ?? 1)}` : void 0
22144
+ });
22145
+ ast.options.forEach((o, i) => {
22146
+ const ct = cellText(o.id, crit.id);
22147
+ const wrapped = ct.lines.length ? wrapToWidth(ct.lines[0], optW[i] - 2 * C2.CELL_PAD_X, C2.FONT) : [];
22148
+ cells.push({
22149
+ x: colX[i],
22150
+ y: ry,
22151
+ w: optW[i],
22152
+ h: rowH,
22153
+ lines: wrapped,
22154
+ variant: ct.variant,
22155
+ glyph: ct.glyph,
22156
+ align: "middle"
22157
+ });
22158
+ });
22159
+ ry += rowH;
22160
+ }
22161
+ let caption;
22162
+ if (isDecision && decision) {
22163
+ const totalH = C2.ROW_MIN_H;
22164
+ cells.push({
22165
+ x: pad,
22166
+ y: ry,
22167
+ w: rowHeadW,
22168
+ h: totalH,
22169
+ lines: ["Weighted total"],
22170
+ variant: "rowHeader",
22171
+ align: "start",
22172
+ bold: true
22173
+ });
22174
+ ast.options.forEach((o, i) => {
22175
+ const isWin = decision.ranks[o.id] === 1;
22176
+ cells.push({
22177
+ x: colX[i],
22178
+ y: ry,
22179
+ w: optW[i],
22180
+ h: totalH,
22181
+ lines: [fmt3(decision.totals[o.id])],
22182
+ variant: isWin ? "winner" : "total",
22183
+ align: "middle",
22184
+ bold: true,
22185
+ tag: `#${decision.ranks[o.id]}`
22186
+ });
22187
+ });
22188
+ ry += totalH;
22189
+ if (decision.deltas) {
22190
+ const dH = C2.ROW_MIN_H;
22191
+ cells.push({
22192
+ x: pad,
22193
+ y: ry,
22194
+ w: rowHeadW,
22195
+ h: dH,
22196
+ lines: ["vs datum"],
22197
+ variant: "rowHeader",
22198
+ align: "start"
22199
+ });
22200
+ ast.options.forEach((o, i) => {
22201
+ const d = decision.deltas[o.id];
22202
+ const s = d > 0 ? `+${fmt3(d)}` : fmt3(d);
22203
+ cells.push({
22204
+ x: colX[i],
22205
+ y: ry,
22206
+ w: optW[i],
22207
+ h: dH,
22208
+ lines: [s],
22209
+ variant: d > 0 ? "pos" : d < 0 ? "neg" : "body",
22210
+ align: "middle"
22211
+ });
22212
+ });
22213
+ ry += dH;
22214
+ }
22215
+ caption = decisionCaption(ast, decision);
22216
+ }
22217
+ const captionH = caption ? C2.CAPTION_H : 0;
22218
+ const result = {
22219
+ ast,
22220
+ mode: ast.mode,
22221
+ cells,
22222
+ ellipses: [],
22223
+ connectors: [],
22224
+ width: gridW + 2 * pad,
22225
+ height: ry + captionH + pad
22226
+ };
22227
+ if (decision) result.decision = decision;
22228
+ if (caption) result.caption = caption;
22229
+ return result;
22230
+ }
22231
+ function layoutDoubleBubble(ast) {
22232
+ const { top, pad } = frame(ast);
22233
+ const b = ast.bubble;
22234
+ const rawE = [];
22235
+ const rawC = [];
22236
+ const dxCS = C2.CENTER_RX + 72 + C2.SHARED_RX;
22237
+ const lcx = -dxCS;
22238
+ const rcx = dxCS;
22239
+ rawE.push({ cx: lcx, cy: 0, rx: C2.CENTER_RX, ry: C2.CENTER_RY, lines: wrapToWidth(b.left, C2.CENTER_RX * 1.4, C2.HEADER_FONT), variant: "center", side: "left" });
22240
+ rawE.push({ cx: rcx, cy: 0, rx: C2.CENTER_RX, ry: C2.CENTER_RY, lines: wrapToWidth(b.right, C2.CENTER_RX * 1.4, C2.HEADER_FONT), variant: "center", side: "right" });
22241
+ const sN = b.shared.length;
22242
+ const sStep = 2 * C2.SHARED_RY + C2.BUBBLE_VGAP;
22243
+ const sTotal = sN > 0 ? (sN - 1) * sStep : 0;
22244
+ b.shared.forEach((s, i) => {
22245
+ const sy = -sTotal / 2 + i * sStep;
22246
+ rawE.push({ cx: 0, cy: sy, rx: C2.SHARED_RX, ry: C2.SHARED_RY, lines: wrapToWidth(s, C2.SHARED_RX * 1.6, C2.FONT), variant: "shared" });
22247
+ rawC.push({ x1: lcx, y1: 0, x2: 0, y2: sy });
22248
+ rawC.push({ x1: rcx, y1: 0, x2: 0, y2: sy });
22249
+ });
22250
+ const placeFan = (items, cx, centreDeg, side) => {
22251
+ const n = items.length;
22252
+ if (n === 0) return;
22253
+ const half = Math.min(82, 30 + 17 * (n - 1));
22254
+ const stepDeg = n > 1 ? 2 * half / (n - 1) : 0;
22255
+ const stepRad = stepDeg * Math.PI / 180;
22256
+ const needChord = 2 * C2.UNIQUE_RY + 18;
22257
+ const rOrbit = Math.max(
22258
+ C2.CENTER_RX + 104,
22259
+ n > 1 ? needChord / (2 * Math.sin(stepRad / 2)) : C2.CENTER_RX + 104
22260
+ );
22261
+ items.forEach((it, i) => {
22262
+ const aDeg = n > 1 ? centreDeg - half + stepDeg * i : centreDeg;
22263
+ const a = aDeg * Math.PI / 180;
22264
+ const bx = cx + rOrbit * Math.cos(a);
22265
+ const by = rOrbit * Math.sin(a);
22266
+ rawE.push({ cx: bx, cy: by, rx: C2.UNIQUE_RX, ry: C2.UNIQUE_RY, lines: wrapToWidth(it, C2.UNIQUE_RX * 1.5, C2.FONT), variant: "unique", side });
22267
+ rawC.push({ x1: cx, y1: 0, x2: bx, y2: by });
22268
+ });
22269
+ };
22270
+ placeFan(b.leftOnly, lcx, 180, "left");
22271
+ placeFan(b.rightOnly, rcx, 0, "right");
22272
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
22273
+ for (const e of rawE) {
22274
+ minX = Math.min(minX, e.cx - e.rx);
22275
+ maxX = Math.max(maxX, e.cx + e.rx);
22276
+ minY = Math.min(minY, e.cy - e.ry);
22277
+ maxY = Math.max(maxY, e.cy + e.ry);
22278
+ }
22279
+ const offX = pad - minX;
22280
+ const offY = top - minY;
22281
+ const ellipses = rawE.map((e) => ({
22282
+ cx: round8(e.cx + offX),
22283
+ cy: round8(e.cy + offY),
22284
+ rx: e.rx,
22285
+ ry: e.ry,
22286
+ lines: e.lines,
22287
+ variant: e.variant,
22288
+ ...e.side ? { side: e.side } : {}
22289
+ }));
22290
+ const connectors = rawC.map((c) => ({
22291
+ x1: round8(c.x1 + offX),
22292
+ y1: round8(c.y1 + offY),
22293
+ x2: round8(c.x2 + offX),
22294
+ y2: round8(c.y2 + offY)
22295
+ }));
22296
+ return {
22297
+ ast,
22298
+ mode: ast.mode,
22299
+ cells: [],
22300
+ ellipses,
22301
+ connectors,
22302
+ width: Math.ceil(maxX - minX + 2 * pad),
22303
+ height: Math.ceil(maxY - minY + top + pad)
22304
+ };
22305
+ }
22306
+ function clamp(v, lo, hi) {
22307
+ return Math.max(lo, Math.min(hi, v));
22308
+ }
22309
+ function round8(n) {
22310
+ return Math.round(n * 10) / 10;
22311
+ }
22312
+
22313
+ // src/diagrams/comparison/renderer.ts
22314
+ function ellipse(attrs) {
22315
+ return el("ellipse", attrs);
22316
+ }
22317
+ function renderComparison(text2, config) {
22318
+ return renderComparisonLayout(layoutComparison(parseComparison(text2)), config);
22319
+ }
22320
+ function renderComparisonLayout(layout, config) {
22321
+ const themeName = config?.theme ?? "default";
22322
+ const t = resolveComparisonTheme(themeName);
22323
+ const fontFamily = config?.fontFamily ?? DEFAULT_FONT_FAMILY;
22324
+ const pad = config?.padding ?? 0;
22325
+ const { ast } = layout;
22326
+ const width = layout.width + pad * 2;
22327
+ const height = layout.height + pad * 2;
22328
+ const a11y = ast.title ?? `Comparison (${ast.mode})`;
22329
+ const style = el(
22330
+ "style",
22331
+ {},
22332
+ `
22333
+ .sx-cmp-bg { fill: ${t.bg}; }
22334
+ .sx-cmp-title { fill: ${t.text}; font-size: ${TITLE.size}px; font-weight: ${TITLE.weight}; }
22335
+ .sx-cmp-caption { fill: ${t.captionText}; font-size: ${FONT_SIZE.label}px; font-style: italic; }
22336
+ .sx-cmp-tag { fill: ${t.tagText}; font-size: ${FONT_SIZE.small}px; }
22337
+ .sx-cmp-rect { stroke: ${t.gridStroke}; stroke-width: ${STROKE_WIDTH.thin}; }
22338
+ .sx-cmp-txt { font-size: ${FONT_SIZE.label}px; }
22339
+ .sx-cmp-rect-corner { fill: ${t.rowHeaderFill}; stroke: ${t.gridStroke}; }
22340
+ .sx-cmp-rect-colHeader { fill: ${t.headerFill}; stroke: ${t.headerStroke}; }
22341
+ .sx-cmp-txt-colHeader { fill: ${t.headerText}; font-size: ${FONT_SIZE.label}px; font-weight: 700; }
22342
+ ${t.columnColors.map((c, i) => `.sx-cmp-ch-${i} { fill: ${c}; stroke: none; }`).join("\n")}
22343
+ .sx-cmp-cht { fill: ${t.columnText}; font-size: ${FONT_SIZE.label}px; font-weight: 700; }
22344
+ .sx-cmp-nostroke { stroke: none; }
22345
+ .sx-cmp-rect-baseline { fill: ${t.baselineFill}; stroke: ${t.gridStroke}; }
22346
+ .sx-cmp-txt-baseline { fill: ${t.cellText}; font-weight: 700; }
22347
+ .sx-cmp-rect-rowHeader { fill: ${t.rowHeaderFill}; stroke: ${t.gridStroke}; }
22348
+ .sx-cmp-txt-rowHeader { fill: ${t.cellText}; font-weight: 600; }
22349
+ .sx-cmp-rect-body { fill: ${t.cellFill}; stroke: ${t.gridStroke}; }
22350
+ .sx-cmp-rect-body-z { fill: ${t.cellAltFill}; stroke: ${t.gridStroke}; }
22351
+ .sx-cmp-txt-body { fill: ${t.cellText}; }
22352
+ .sx-cmp-bullet { fill: ${t.headerFill}; }
22353
+ .sx-cmp-rect-pos { fill: ${t.posFill}; stroke: ${t.gridStroke}; }
22354
+ .sx-cmp-txt-pos { fill: ${t.posText}; font-weight: 600; }
22355
+ .sx-cmp-rect-neg { fill: ${t.negFill}; stroke: ${t.gridStroke}; }
22356
+ .sx-cmp-txt-neg { fill: ${t.negText}; font-weight: 600; }
22357
+ .sx-cmp-rect-warn { fill: ${t.warnFill}; stroke: ${t.gridStroke}; }
22358
+ .sx-cmp-txt-warn { fill: ${t.warnText}; font-weight: 600; }
22359
+ .sx-cmp-txt-pro { fill: ${t.cellText}; }
22360
+ .sx-cmp-txt-con { fill: ${t.cellText}; }
22361
+ .sx-cmp-rect-pillPos { fill: ${t.pillPosFill}; stroke: none; }
22362
+ .sx-cmp-rect-pillNeg { fill: ${t.pillNegFill}; stroke: none; }
22363
+ .sx-cmp-txt-pillPos, .sx-cmp-txt-pillNeg { fill: ${t.pillText}; font-weight: 700; letter-spacing: 0.5px; }
22364
+ .sx-cmp-badge-pos { fill: ${t.pillPosFill}; }
22365
+ .sx-cmp-badge-neg { fill: ${t.pillNegFill}; }
22366
+ .sx-cmp-badge-glyph { fill: ${t.badgeText}; font-size: 13px; font-weight: 700; }
22367
+ .sx-cmp-rect-total { fill: ${t.totalFill}; stroke: ${t.gridStroke}; }
22368
+ .sx-cmp-txt-total { fill: ${t.cellText}; font-weight: 700; }
22369
+ .sx-cmp-rect-winner { fill: ${t.winnerFill}; stroke: ${t.winnerStroke}; stroke-width: ${STROKE_WIDTH.thick}; }
22370
+ .sx-cmp-txt-winner { fill: ${t.winnerText}; font-weight: 700; }
22371
+ .sx-cmp-glyph { font-size: 15px; font-weight: 700; }
22372
+ .sx-cmp-card { fill: ${t.cardFill}; stroke: ${t.cardStroke}; stroke-width: ${STROKE_WIDTH.thin}; }
22373
+ .sx-cmp-conn { fill: none; stroke: ${t.connectorStroke}; stroke-width: ${STROKE_WIDTH.normal}; }
22374
+ .sx-cmp-conn-light { fill: none; stroke: ${t.rowDivider}; stroke-width: ${STROKE_WIDTH.thin}; }
22375
+ .sx-cmp-ell { stroke: ${t.dbStroke}; stroke-width: ${STROKE_WIDTH.normal}; }
22376
+ .sx-cmp-ell-center-left { fill: ${t.dbLeftCenterFill}; }
22377
+ .sx-cmp-ell-center-right { fill: ${t.dbRightCenterFill}; }
22378
+ .sx-cmp-ell-shared { fill: ${t.dbSharedFill}; }
22379
+ .sx-cmp-ell-unique-left { fill: ${t.dbLeftFill}; }
22380
+ .sx-cmp-ell-unique-right { fill: ${t.dbRightFill}; }
22381
+ .sx-cmp-ltxt-center-left { fill: ${t.dbLeftCenterText}; font-size: ${FONT_SIZE.label}px; font-weight: 700; }
22382
+ .sx-cmp-ltxt-center-right { fill: ${t.dbRightCenterText}; font-size: ${FONT_SIZE.label}px; font-weight: 700; }
22383
+ .sx-cmp-ltxt-shared { fill: ${t.dbSharedText}; font-size: ${FONT_SIZE.label}px; font-weight: 600; }
22384
+ .sx-cmp-ltxt-unique-left { fill: ${t.dbLeftText}; font-size: ${FONT_SIZE.small}px; }
22385
+ .sx-cmp-ltxt-unique-right { fill: ${t.dbRightText}; font-size: ${FONT_SIZE.small}px; }
22386
+ `.trim()
22387
+ );
22388
+ const children = [
22389
+ title(a11y),
22390
+ desc(summarise7(layout)),
22391
+ style,
22392
+ rect({ x: 0, y: 0, width, height, class: "sx-cmp-bg" })
22393
+ ];
22394
+ const inner = [];
22395
+ if (ast.title) {
22396
+ inner.push(
22397
+ text(
22398
+ { x: layout.width / 2, y: TITLE.y, class: "sx-cmp-title", "font-family": fontFamily, "text-anchor": "middle" },
22399
+ ast.title
22400
+ )
22401
+ );
22402
+ }
22403
+ for (const f of layout.frames ?? []) {
22404
+ inner.push(rect({ x: f.x, y: f.y, width: f.w, height: f.h, rx: f.rx, class: "sx-cmp-card" }));
22405
+ }
22406
+ for (const c of layout.connectors) {
22407
+ inner.push(line({ x1: c.x1, y1: c.y1, x2: c.x2, y2: c.y2, class: c.light ? "sx-cmp-conn-light" : "sx-cmp-conn" }));
22408
+ }
22409
+ const colN = t.columnColors.length;
22410
+ for (const cell of layout.cells) {
22411
+ inner.push(renderCell(cell, fontFamily, colN));
22412
+ }
22413
+ for (const e of layout.ellipses) {
22414
+ const key = e.variant === "center" || e.variant === "unique" ? `${e.variant}-${e.side ?? "left"}` : e.variant;
22415
+ const cls = `sx-cmp-ell sx-cmp-ell-${key}`;
22416
+ const txtCls = `sx-cmp-ltxt-${key}`;
22417
+ inner.push(
22418
+ group({ class: "sx-cmp-bubble", "data-role": e.variant, ...e.side ? { "data-side": e.side } : {} }, [
22419
+ ellipse({ cx: e.cx, cy: e.cy, rx: e.rx, ry: e.ry, class: cls }),
22420
+ multilineText(
22421
+ { x: e.cx, y: e.cy, class: txtCls, "font-family": fontFamily, "text-anchor": "middle", "dominant-baseline": "middle" },
22422
+ e.lines.join("<br/>"),
22423
+ C_LINE_H
22424
+ )
22425
+ ])
22426
+ );
22427
+ }
22428
+ if (layout.caption) {
22429
+ inner.push(
22430
+ text(
22431
+ { x: layout.width / 2, y: layout.height - 12, class: "sx-cmp-caption", "font-family": fontFamily, "text-anchor": "middle" },
22432
+ layout.caption
22433
+ )
22434
+ );
22435
+ }
22436
+ children.push(
22437
+ group({ transform: pad ? `translate(${pad}, ${pad})` : void 0, "font-family": fontFamily }, inner)
22438
+ );
22439
+ return svgRoot(
22440
+ {
22441
+ width,
22442
+ height,
22443
+ viewBox: `0 0 ${width} ${height}`,
22444
+ role: "img",
22445
+ "aria-label": a11y,
22446
+ "data-diagram-type": "comparison",
22447
+ "data-mode": ast.mode
22448
+ },
22449
+ children
22450
+ );
22451
+ }
22452
+ var C_LINE_H = 14;
22453
+ function renderCell(cell, fontFamily, colN) {
22454
+ const parts = [];
22455
+ const colHeaderClass = cell.variant === "colHeader" && cell.paletteIndex !== void 0 ? `sx-cmp-ch-${cell.paletteIndex % Math.max(1, colN)}` : void 0;
22456
+ if (!cell.bare) {
22457
+ if (cell.roundedTop) {
22458
+ parts.push(
22459
+ path({
22460
+ d: roundedTopRectPath(cell.x, cell.y, cell.w, cell.h, cell.rx ?? 12),
22461
+ class: colHeaderClass ?? "sx-cmp-rect-colHeader"
22462
+ })
22463
+ );
22464
+ } else {
22465
+ const rectVariant = cell.zebra && cell.variant === "body" ? "body-z" : cell.variant;
22466
+ const rectClass = colHeaderClass ? `sx-cmp-rect ${colHeaderClass}` : `sx-cmp-rect sx-cmp-rect-${rectVariant}${cell.noStroke ? " sx-cmp-nostroke" : ""}`;
22467
+ parts.push(
22468
+ rect({ x: cell.x, y: cell.y, width: cell.w, height: cell.h, rx: cell.rx, class: rectClass })
22469
+ );
22470
+ }
22471
+ }
22472
+ const txtClass = colHeaderClass ? "sx-cmp-txt sx-cmp-cht" : `sx-cmp-txt sx-cmp-txt-${cell.variant}`;
22473
+ const cy = cell.y + cell.h / 2;
22474
+ const br = 11;
22475
+ const drawBadge = (bcx) => {
22476
+ parts.push(circle({ cx: bcx, cy, r: br, class: `sx-cmp-badge-${cell.badge.tone}` }));
22477
+ parts.push(
22478
+ text(
22479
+ { x: bcx, y: cy + 0.5, class: "sx-cmp-badge-glyph", "font-family": fontFamily, "text-anchor": "middle", "dominant-baseline": "middle" },
22480
+ cell.badge.glyph === "yes" ? "\u2713" : "\u2717"
22481
+ )
22482
+ );
22483
+ };
22484
+ if (cell.align === "start") {
22485
+ let tx = cell.x + 12;
22486
+ if (cell.badge) {
22487
+ const bcx = cell.x + 12 + br;
22488
+ drawBadge(bcx);
22489
+ tx = bcx + br + 10;
22490
+ } else if (cell.tag === "\u2022") {
22491
+ parts.push(circle({ cx: cell.x + 14, cy, r: 2.6, class: "sx-cmp-bullet" }));
22492
+ tx = cell.x + 24;
22493
+ }
22494
+ if (cell.lines.length) {
22495
+ parts.push(
22496
+ multilineText(
22497
+ { x: tx, y: cy, class: txtClass, "font-family": fontFamily, "dominant-baseline": "middle" },
22498
+ cell.lines.join("<br/>"),
22499
+ C_LINE_H
22500
+ )
22501
+ );
22502
+ }
22503
+ } else if (cell.badge) {
22504
+ const bcx = cell.x + 18 + br;
22505
+ drawBadge(bcx);
22506
+ const labelCx = (bcx + br + 6 + (cell.x + cell.w - 12)) / 2;
22507
+ parts.push(
22508
+ multilineText(
22509
+ { x: labelCx, y: cy, class: txtClass, "font-family": fontFamily, "text-anchor": "middle", "dominant-baseline": "middle" },
22510
+ cell.lines.join("<br/>"),
22511
+ C_LINE_H
22512
+ )
22513
+ );
22514
+ } else if (cell.glyph && cell.lines.length === 0) {
22515
+ parts.push(
22516
+ text(
22517
+ { x: cell.x + cell.w / 2, y: cy, class: `sx-cmp-glyph ${glyphTextClass(cell.glyph)}`, "font-family": fontFamily, "text-anchor": "middle", "dominant-baseline": "middle" },
22518
+ glyphChar(cell.glyph)
22519
+ )
22520
+ );
22521
+ } else if (cell.lines.length) {
22522
+ parts.push(
22523
+ multilineText(
22524
+ { x: cell.x + cell.w / 2, y: cy, class: txtClass, "font-family": fontFamily, "text-anchor": "middle", "dominant-baseline": "middle" },
22525
+ cell.lines.join("<br/>"),
22526
+ C_LINE_H
22527
+ )
22528
+ );
22529
+ }
22530
+ if (cell.tag && cell.tag !== "\u2022") {
22531
+ if (cell.variant === "baseline") {
22532
+ parts.push(
22533
+ text(
22534
+ { x: cell.x + cell.w / 2, y: cell.y + cell.h - 5, class: "sx-cmp-tag", "font-family": fontFamily, "text-anchor": "middle" },
22535
+ cell.tag
22536
+ )
22537
+ );
22538
+ } else {
22539
+ parts.push(
22540
+ text(
22541
+ { x: cell.x + cell.w - 5, y: cell.y + 13, class: "sx-cmp-tag", "font-family": fontFamily, "text-anchor": "end" },
22542
+ cell.tag
22543
+ )
22544
+ );
22545
+ }
22546
+ }
22547
+ const attrs = { class: "sx-cmp-cell-g", "data-variant": cell.variant };
22548
+ if (cell.glyph) attrs["data-glyph"] = cell.glyph;
22549
+ return group(attrs, parts);
22550
+ }
22551
+ function roundedTopRectPath(x, y, w, h, r7) {
22552
+ const rr = Math.max(0, Math.min(r7, w / 2, h));
22553
+ return `M ${x} ${y + h} L ${x} ${y + rr} Q ${x} ${y} ${x + rr} ${y} L ${x + w - rr} ${y} Q ${x + w} ${y} ${x + w} ${y + rr} L ${x + w} ${y + h} Z`;
22554
+ }
22555
+ function glyphChar(g) {
22556
+ return g === "yes" ? "\u2713" : g === "no" ? "\u2717" : g === "partial" ? "~" : "\u2014";
22557
+ }
22558
+ function glyphTextClass(g) {
22559
+ return g === "yes" ? "sx-cmp-txt-pos" : g === "no" ? "sx-cmp-txt-neg" : g === "partial" ? "sx-cmp-txt-warn" : "sx-cmp-txt-body";
22560
+ }
22561
+ function summarise7(layout) {
22562
+ const { ast } = layout;
22563
+ const parts = [];
22564
+ switch (ast.mode) {
22565
+ case "tchart":
22566
+ parts.push(`T-chart comparing ${ast.columns.length} column${plural2(ast.columns.length)}: ${ast.columns.map((c) => `"${c.label}"`).join(", ")}.`);
22567
+ break;
22568
+ case "pros-cons":
22569
+ parts.push(`Pros/cons${ast.subject ? ` for "${ast.subject}"` : ""}: ${ast.pros.length} pro${plural2(ast.pros.length)}, ${ast.cons.length} con${plural2(ast.cons.length)}.`);
22570
+ break;
22571
+ case "matrix":
22572
+ parts.push(`Comparison matrix: ${ast.options.length} option${plural2(ast.options.length)} \xD7 ${ast.criteria.length} criteria.`);
22573
+ break;
22574
+ case "decision":
22575
+ parts.push(`Decision matrix: ${ast.options.length} option${plural2(ast.options.length)} \xD7 ${ast.criteria.length} weighted criteria.`);
22576
+ if (layout.caption) parts.push(layout.caption);
22577
+ break;
22578
+ case "double-bubble":
22579
+ parts.push(`Double-bubble comparing "${ast.bubble?.left}" and "${ast.bubble?.right}": ${ast.bubble?.shared.length ?? 0} shared, ${ast.bubble?.leftOnly.length ?? 0}/${ast.bubble?.rightOnly.length ?? 0} unique.`);
22580
+ break;
22581
+ }
22582
+ for (const w of ast.warnings) parts.push(w);
22583
+ return parts.join(" ");
22584
+ }
22585
+ function plural2(n) {
22586
+ return n === 1 ? "" : "s";
22587
+ }
22588
+
22589
+ // src/diagrams/comparison/index.ts
22590
+ var comparison = {
22591
+ type: "comparison",
22592
+ detect(text2) {
22593
+ return /^\s*(comparison|compare|vs|tchart|t-chart|pugh|decision-matrix|decisionmatrix)\b/i.test(text2);
22594
+ },
22595
+ parse: parseComparison,
22596
+ render(text2, config) {
22597
+ return renderComparison(text2, config);
22598
+ }
22599
+ };
22600
+
21362
22601
  // src/diagrams/causalloop/parser.ts
21363
22602
  var CausalLoopParseError = class extends Error {
21364
22603
  constructor(message, line2) {
@@ -21381,7 +22620,7 @@ function parseCausalLoop(text2) {
21381
22620
  let i = 0;
21382
22621
  let headerSeen = false;
21383
22622
  for (; i < lines.length; i++) {
21384
- const t = stripComment8(lines[i] ?? "").trim();
22623
+ const t = stripComment9(lines[i] ?? "").trim();
21385
22624
  if (t === "") continue;
21386
22625
  const h = /^(causalloop|cld)\b(.*)$/i.exec(t);
21387
22626
  if (h) {
@@ -21402,7 +22641,7 @@ function parseCausalLoop(text2) {
21402
22641
  );
21403
22642
  }
21404
22643
  for (; i < lines.length; i++) {
21405
- const t = stripComment8(lines[i] ?? "").trim();
22644
+ const t = stripComment9(lines[i] ?? "").trim();
21406
22645
  if (t === "") continue;
21407
22646
  const lineNo = i + 1;
21408
22647
  const lm = /^layout\s*:\s*(\S+)/i.exec(t);
@@ -21424,9 +22663,9 @@ function parseCausalLoop(text2) {
21424
22663
  parseLinkLine(ast, t, lineNo);
21425
22664
  continue;
21426
22665
  }
21427
- ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate7(t, 80)}"`);
22666
+ ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate8(t, 80)}"`);
21428
22667
  }
21429
- validate4(ast);
22668
+ validate5(ast);
21430
22669
  return ast;
21431
22670
  }
21432
22671
  function parseVarLine(ast, rest, lineNo) {
@@ -21438,7 +22677,7 @@ function parseLoopLine(ast, rest, lineNo) {
21438
22677
  const m = /^([RB]\d+)\s+(.+)$/i.exec(rest);
21439
22678
  if (!m) {
21440
22679
  throw new CausalLoopParseError(
21441
- `'loop' needs a loop id (e.g. R1, B1) and a phrase, got "${truncate7(rest, 60)}"`,
22680
+ `'loop' needs a loop id (e.g. R1, B1) and a phrase, got "${truncate8(rest, 60)}"`,
21442
22681
  lineNo
21443
22682
  );
21444
22683
  }
@@ -21449,7 +22688,7 @@ function parseLoopLine(ast, rest, lineNo) {
21449
22688
  function parseLinkLine(ast, t, lineNo) {
21450
22689
  const arrowIdx = topLevelArrow(t);
21451
22690
  if (arrowIdx < 0) {
21452
- throw new CausalLoopParseError(`malformed link (expected '->'): "${truncate7(t, 60)}"`, lineNo);
22691
+ throw new CausalLoopParseError(`malformed link (expected '->'): "${truncate8(t, 60)}"`, lineNo);
21453
22692
  }
21454
22693
  const fromRaw = t.slice(0, arrowIdx).trim();
21455
22694
  let rhs = t.slice(arrowIdx + 2).trim();
@@ -21491,7 +22730,7 @@ function parseLinkLine(ast, t, lineNo) {
21491
22730
  if (label) link.label = label;
21492
22731
  ast.links.push(link);
21493
22732
  }
21494
- function validate4(ast) {
22733
+ function validate5(ast) {
21495
22734
  if (ast.links.length === 0) {
21496
22735
  throw new CausalLoopParseError(
21497
22736
  "a causal loop diagram needs at least one causal link (A -> B : +)"
@@ -21571,7 +22810,7 @@ function stripLeadingQuoted(s) {
21571
22810
  return void 0;
21572
22811
  }
21573
22812
  }
21574
- function stripComment8(line2) {
22813
+ function stripComment9(line2) {
21575
22814
  let i = 0;
21576
22815
  while (i < line2.length) {
21577
22816
  const ch = line2[i];
@@ -21587,7 +22826,7 @@ function stripComment8(line2) {
21587
22826
  }
21588
22827
  return line2;
21589
22828
  }
21590
- function truncate7(s, n) {
22829
+ function truncate8(s, n) {
21591
22830
  return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
21592
22831
  }
21593
22832
 
@@ -21744,17 +22983,17 @@ var CAUSALLOOP_CONST = {
21744
22983
  };
21745
22984
  function layoutCausalLoop(ast) {
21746
22985
  const analysis = analyseCausalLoop(ast);
21747
- const C2 = CAUSALLOOP_CONST;
22986
+ const C3 = CAUSALLOOP_CONST;
21748
22987
  const nodes = /* @__PURE__ */ new Map();
21749
22988
  for (const v of ast.variables) {
21750
- const halfW = Math.max(20, v.label.length * C2.CHAR_W / 2);
22989
+ const halfW = Math.max(20, v.label.length * C3.CHAR_W / 2);
21751
22990
  nodes.set(v.id, {
21752
22991
  id: v.id,
21753
22992
  label: v.label,
21754
22993
  cx: 0,
21755
22994
  cy: 0,
21756
22995
  halfW,
21757
- halfH: C2.LABEL_H / 2
22996
+ halfH: C3.LABEL_H / 2
21758
22997
  });
21759
22998
  }
21760
22999
  const ringIds = ringOrder(ast, analysis);
@@ -21764,9 +23003,9 @@ function layoutCausalLoop(ast) {
21764
23003
  let cy0 = 0;
21765
23004
  let ringR = 0;
21766
23005
  if (ringIds.length > 0) {
21767
- ringR = Math.max(C2.MIN_RING_R, C2.RING_GAP * ringIds.length / (2 * Math.PI));
21768
- cx0 = C2.CANVAS_PAD + ringR + maxHalfW(ringIds, nodes);
21769
- cy0 = C2.CANVAS_PAD + ringR + C2.LABEL_H;
23006
+ ringR = Math.max(C3.MIN_RING_R, C3.RING_GAP * ringIds.length / (2 * Math.PI));
23007
+ cx0 = C3.CANVAS_PAD + ringR + maxHalfW(ringIds, nodes);
23008
+ cy0 = C3.CANVAS_PAD + ringR + C3.LABEL_H;
21770
23009
  const step = 2 * Math.PI / ringIds.length;
21771
23010
  ringIds.forEach((id, i) => {
21772
23011
  const ang = -Math.PI / 2 + i * step;
@@ -21776,14 +23015,14 @@ function layoutCausalLoop(ast) {
21776
23015
  });
21777
23016
  }
21778
23017
  if (openIds.length > 0) {
21779
- const rowY = ringIds.length > 0 ? cy0 + ringR + C2.OPEN_ROW_GAP : C2.CANVAS_PAD + C2.LABEL_H;
21780
- let x = C2.CANVAS_PAD;
23018
+ const rowY = ringIds.length > 0 ? cy0 + ringR + C3.OPEN_ROW_GAP : C3.CANVAS_PAD + C3.LABEL_H;
23019
+ let x = C3.CANVAS_PAD;
21781
23020
  for (const id of openIds) {
21782
23021
  const node = nodes.get(id);
21783
23022
  x += node.halfW;
21784
23023
  node.cx = x;
21785
23024
  node.cy = rowY;
21786
- x += node.halfW + C2.OPEN_ROW_GAP;
23025
+ x += node.halfW + C3.OPEN_ROW_GAP;
21787
23026
  }
21788
23027
  }
21789
23028
  const center = { x: cx0, y: cy0 };
@@ -21811,8 +23050,8 @@ function layoutCausalLoop(ast) {
21811
23050
  maxX = Math.max(maxX, l.polarityX + 12);
21812
23051
  maxY = Math.max(maxY, l.polarityY + 12);
21813
23052
  }
21814
- const width = Math.ceil(maxX + C2.CANVAS_PAD);
21815
- const height = Math.ceil(maxY + C2.CANVAS_PAD);
23053
+ const width = Math.ceil(maxX + C3.CANVAS_PAD);
23054
+ const height = Math.ceil(maxY + C3.CANVAS_PAD);
21816
23055
  return {
21817
23056
  ast,
21818
23057
  analysis,
@@ -21850,7 +23089,7 @@ function ringOrder(ast, analysis) {
21850
23089
  return order;
21851
23090
  }
21852
23091
  function layoutLink(l, idx, nodes, center, ringSet, pairIndex) {
21853
- const C2 = CAUSALLOOP_CONST;
23092
+ const C3 = CAUSALLOOP_CONST;
21854
23093
  const a = nodes.get(l.from);
21855
23094
  const b = nodes.get(l.to);
21856
23095
  if (l.from === l.to) {
@@ -21878,17 +23117,17 @@ function layoutLink(l, idx, nodes, center, ringSet, pairIndex) {
21878
23117
  ny = ux;
21879
23118
  }
21880
23119
  const side = pairIndex % 2 === 0 ? 1 : -1;
21881
- const bow = dist * C2.CURVE_BOW * side;
23120
+ const bow = dist * C3.CURVE_BOW * side;
21882
23121
  const ctrlX = mx + nx * bow;
21883
23122
  const ctrlY = my + ny * bow;
21884
- const path2 = `M ${fmt3(start.x)} ${fmt3(start.y)} Q ${fmt3(ctrlX)} ${fmt3(ctrlY)} ${fmt3(end.x)} ${fmt3(end.y)}`;
23123
+ const path2 = `M ${fmt4(start.x)} ${fmt4(start.y)} Q ${fmt4(ctrlX)} ${fmt4(ctrlY)} ${fmt4(end.x)} ${fmt4(end.y)}`;
21885
23124
  let tx = end.x - ctrlX;
21886
23125
  let ty = end.y - ctrlY;
21887
23126
  const tn = Math.hypot(tx, ty) || 1;
21888
23127
  tx /= tn;
21889
23128
  ty /= tn;
21890
- const polarityX = end.x - tx * C2.HEAD_OFFSET + nx * side * 10;
21891
- const polarityY = end.y - ty * C2.HEAD_OFFSET + ny * side * 10;
23129
+ const polarityX = end.x - tx * C3.HEAD_OFFSET + nx * side * 10;
23130
+ const polarityY = end.y - ty * C3.HEAD_OFFSET + ny * side * 10;
21892
23131
  const result = {
21893
23132
  linkIndex: idx,
21894
23133
  from: l.from,
@@ -21925,9 +23164,9 @@ function selfLink(l, idx, a) {
21925
23164
  const x1 = a.cx - a.halfW * 0.4;
21926
23165
  const x2 = a.cx + a.halfW * 0.4;
21927
23166
  const loopTop = topY - 34;
21928
- const path2 = `M ${fmt3(x1)} ${fmt3(topY)} C ${fmt3(x1 - 12)} ${fmt3(loopTop)} ${fmt3(
23167
+ const path2 = `M ${fmt4(x1)} ${fmt4(topY)} C ${fmt4(x1 - 12)} ${fmt4(loopTop)} ${fmt4(
21929
23168
  x2 + 12
21930
- )} ${fmt3(loopTop)} ${fmt3(x2)} ${fmt3(topY)}`;
23169
+ )} ${fmt4(loopTop)} ${fmt4(x2)} ${fmt4(topY)}`;
21931
23170
  const result = {
21932
23171
  linkIndex: idx,
21933
23172
  from: l.from,
@@ -21954,7 +23193,7 @@ function boxExit(node, ux, uy) {
21954
23193
  return { x: node.cx + ux * t, y: node.cy + uy * t };
21955
23194
  }
21956
23195
  function layoutGlyph(loop, nodes, center) {
21957
- const C2 = CAUSALLOOP_CONST;
23196
+ const C3 = CAUSALLOOP_CONST;
21958
23197
  const pts = loop.variables.map((id) => nodes.get(id));
21959
23198
  let sx = 0;
21960
23199
  let sy = 0;
@@ -21994,10 +23233,10 @@ function layoutGlyph(loop, nodes, center) {
21994
23233
  loop,
21995
23234
  cx: gx,
21996
23235
  cy: gy,
21997
- r: C2.GLYPH_R,
23236
+ r: C3.GLYPH_R,
21998
23237
  clockwise,
21999
23238
  phraseX: gx,
22000
- phraseY: gy + C2.GLYPH_R + 13
23239
+ phraseY: gy + C3.GLYPH_R + 13
22001
23240
  };
22002
23241
  }
22003
23242
  function maxHalfW(ids, nodes) {
@@ -22005,7 +23244,7 @@ function maxHalfW(ids, nodes) {
22005
23244
  for (const id of ids) m = Math.max(m, nodes.get(id).halfW);
22006
23245
  return m;
22007
23246
  }
22008
- function fmt3(n) {
23247
+ function fmt4(n) {
22009
23248
  return (Math.round(n * 100) / 100).toString();
22010
23249
  }
22011
23250
 
@@ -22052,7 +23291,7 @@ function renderCausalLoopLayout(layout, config) {
22052
23291
  );
22053
23292
  const children = [
22054
23293
  title(a11y),
22055
- desc(summarise7(layout)),
23294
+ desc(summarise8(layout)),
22056
23295
  styleBlock,
22057
23296
  el("rect", { x: 0, y: 0, width, height, class: "sx-cld-bg" })
22058
23297
  ];
@@ -22160,9 +23399,9 @@ function arrowhead(x, y, tx, ty) {
22160
23399
  const by = y - ty * len;
22161
23400
  const px = -ty;
22162
23401
  const py = tx;
22163
- const p1 = `${fmt4(bx + px * wide)},${fmt4(by + py * wide)}`;
22164
- const p2 = `${fmt4(bx - px * wide)},${fmt4(by - py * wide)}`;
22165
- const tip = `${fmt4(x)},${fmt4(y)}`;
23402
+ const p1 = `${fmt5(bx + px * wide)},${fmt5(by + py * wide)}`;
23403
+ const p2 = `${fmt5(bx - px * wide)},${fmt5(by - py * wide)}`;
23404
+ const tip = `${fmt5(x)},${fmt5(y)}`;
22166
23405
  return polygon({ points: `${tip} ${p1} ${p2}`, class: "sx-cld-arrow" });
22167
23406
  }
22168
23407
  function renderGlyph(g) {
@@ -22176,7 +23415,7 @@ function renderGlyph(g) {
22176
23415
  const ey = g.cy + r7 * Math.sin(endAng);
22177
23416
  const largeArc = 1;
22178
23417
  const sweepFlag = g.clockwise ? 1 : 0;
22179
- const arc = `M ${fmt4(sx)} ${fmt4(sy)} A ${r7} ${r7} 0 ${largeArc} ${sweepFlag} ${fmt4(ex)} ${fmt4(ey)}`;
23418
+ const arc = `M ${fmt5(sx)} ${fmt5(sy)} A ${r7} ${r7} 0 ${largeArc} ${sweepFlag} ${fmt5(ex)} ${fmt5(ey)}`;
22180
23419
  const dir = g.clockwise ? 1 : -1;
22181
23420
  const tx = -Math.sin(endAng) * dir;
22182
23421
  const ty = Math.cos(endAng) * dir;
@@ -22217,11 +23456,11 @@ function glyphArrow(x, y, tx, ty) {
22217
23456
  const by = y - ty * len;
22218
23457
  const px = -ty;
22219
23458
  const py = tx;
22220
- const p1 = `${fmt4(bx + px * wide)},${fmt4(by + py * wide)}`;
22221
- const p2 = `${fmt4(bx - px * wide)},${fmt4(by - py * wide)}`;
22222
- return polygon({ points: `${fmt4(x)},${fmt4(y)} ${p1} ${p2}`, class: "sx-cld-glyph-head" });
23459
+ const p1 = `${fmt5(bx + px * wide)},${fmt5(by + py * wide)}`;
23460
+ const p2 = `${fmt5(bx - px * wide)},${fmt5(by - py * wide)}`;
23461
+ return polygon({ points: `${fmt5(x)},${fmt5(y)} ${p1} ${p2}`, class: "sx-cld-glyph-head" });
22223
23462
  }
22224
- function summarise7(layout) {
23463
+ function summarise8(layout) {
22225
23464
  const { ast, analysis } = layout;
22226
23465
  const parts = [
22227
23466
  `Causal loop diagram${ast.title ? ` "${ast.title}"` : ""}: ${ast.variables.length} variable${ast.variables.length === 1 ? "" : "s"}, ${ast.links.length} causal link${ast.links.length === 1 ? "" : "s"}.`
@@ -22247,7 +23486,7 @@ function summarise7(layout) {
22247
23486
  for (const w of ast.warnings) parts.push(w);
22248
23487
  return parts.join(" ");
22249
23488
  }
22250
- function fmt4(n) {
23489
+ function fmt5(n) {
22251
23490
  return (Math.round(n * 100) / 100).toString();
22252
23491
  }
22253
23492
 
@@ -22475,11 +23714,11 @@ function analyseMarkov(ast) {
22475
23714
  if (Math.abs(sum - 1) > ROW_SUM_TOL) {
22476
23715
  if (ast.normalize) {
22477
23716
  for (let j = 0; j < n; j++) P[i][j] /= sum;
22478
- notes.push(`State "${order[i]}" out-edges summed to ${round7(sum)}; normalised to 1 (normalize: true).`);
23717
+ notes.push(`State "${order[i]}" out-edges summed to ${round9(sum)}; normalised to 1 (normalize: true).`);
22479
23718
  } else {
22480
23719
  const st = ast.states[i];
22481
23720
  throw new MarkovParseError(
22482
- `state "${order[i]}": outgoing probabilities sum to ${round7(sum)}, must be 1.0 \u2014 fix the values or set "normalize: true"`,
23721
+ `state "${order[i]}": outgoing probabilities sum to ${round9(sum)}, must be 1.0 \u2014 fix the values or set "normalize: true"`,
22483
23722
  st.line
22484
23723
  );
22485
23724
  }
@@ -22523,17 +23762,17 @@ function classifyStates(P, order, ast) {
22523
23762
  if (indexOf[s] !== -1) continue;
22524
23763
  const work = [{ v: s, pi: 0 }];
22525
23764
  while (work.length > 0) {
22526
- const frame = work[work.length - 1];
22527
- const v = frame.v;
22528
- if (frame.pi === 0) {
23765
+ const frame2 = work[work.length - 1];
23766
+ const v = frame2.v;
23767
+ if (frame2.pi === 0) {
22529
23768
  indexOf[v] = lowlink[v] = counter++;
22530
23769
  stack.push(v);
22531
23770
  onStack[v] = true;
22532
23771
  }
22533
23772
  let recursed = false;
22534
- while (frame.pi < adj[v].length) {
22535
- const w = adj[v][frame.pi];
22536
- frame.pi++;
23773
+ while (frame2.pi < adj[v].length) {
23774
+ const w = adj[v][frame2.pi];
23775
+ frame2.pi++;
22537
23776
  if (indexOf[w] === -1) {
22538
23777
  work.push({ v: w, pi: 0 });
22539
23778
  recursed = true;
@@ -22812,7 +24051,7 @@ function invert(mat) {
22812
24051
  }
22813
24052
  return A.map((row) => row.slice(m));
22814
24053
  }
22815
- function round7(x) {
24054
+ function round9(x) {
22816
24055
  return Math.round(x * 1e6) / 1e6;
22817
24056
  }
22818
24057
 
@@ -22836,7 +24075,7 @@ var MARKOV_CONST = {
22836
24075
  };
22837
24076
  function layoutMarkov(ast) {
22838
24077
  const analysis = analyseMarkov(ast);
22839
- const C2 = MARKOV_CONST;
24078
+ const C3 = MARKOV_CONST;
22840
24079
  const states = ast.states;
22841
24080
  states.length;
22842
24081
  const classOf = analysis.classification?.byState;
@@ -22849,9 +24088,9 @@ function layoutMarkov(ast) {
22849
24088
  let width = 0;
22850
24089
  let height = 0;
22851
24090
  if (ast.layout === "layered" && analysis.classification) {
22852
- ({ width, height } = placeLayered(ast, analysis.classification, centres, C2));
24091
+ ({ width, height } = placeLayered(ast, analysis.classification, centres, C3));
22853
24092
  } else {
22854
- ({ width, height } = placeRing(states.map((s) => s.id), centres, C2));
24093
+ ({ width, height } = placeRing(states.map((s) => s.id), centres, C3));
22855
24094
  }
22856
24095
  const ringCenter = { x: width / 2, y: height / 2 };
22857
24096
  const boxes = states.map((st) => {
@@ -22863,7 +24102,7 @@ function layoutMarkov(ast) {
22863
24102
  state: st,
22864
24103
  cx: c.x,
22865
24104
  cy: c.y,
22866
- r: C2.STATE_R,
24105
+ r: C3.STATE_R,
22867
24106
  isAbsorbing
22868
24107
  };
22869
24108
  if (tag) box2.classTag = tag;
@@ -22875,18 +24114,18 @@ function layoutMarkov(ast) {
22875
24114
  for (const tr of ast.transitions) present.add(arcKey(tr.from, tr.to));
22876
24115
  const arcs = ast.transitions.map((tr) => {
22877
24116
  if (tr.self) {
22878
- return selfLoopGeom(tr, centres.get(tr.from), ringCenter, ast.layout, C2);
24117
+ return selfLoopGeom(tr, centres.get(tr.from), ringCenter, ast.layout, C3);
22879
24118
  }
22880
24119
  const a = centres.get(tr.from);
22881
24120
  const b = centres.get(tr.to);
22882
24121
  const hasReverse = present.has(arcKey(tr.to, tr.from));
22883
24122
  const sign = hasReverse ? tr.from < tr.to ? 1 : -1 : 1;
22884
- const bow = hasReverse ? C2.BOW : C2.SOLO_BOW;
22885
- return curvedArcGeom(tr, a, b, sign * bow, C2);
24123
+ const bow = hasReverse ? C3.BOW : C3.SOLO_BOW;
24124
+ return curvedArcGeom(tr, a, b, sign * bow, C3);
22886
24125
  });
22887
24126
  return {
22888
24127
  width,
22889
- height: height + (ast.title ? C2.TITLE_BAND : 0),
24128
+ height: height + (ast.title ? C3.TITLE_BAND : 0),
22890
24129
  ...ast.title ? { title: ast.title } : {},
22891
24130
  states: boxes,
22892
24131
  arcs,
@@ -22894,28 +24133,28 @@ function layoutMarkov(ast) {
22894
24133
  ast
22895
24134
  };
22896
24135
  }
22897
- function placeRing(ids, centres, C2) {
24136
+ function placeRing(ids, centres, C3) {
22898
24137
  const n = ids.length;
22899
24138
  if (n === 1) {
22900
- const cx = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
22901
- const cy = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
24139
+ const cx = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
24140
+ const cy = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
22902
24141
  centres.set(ids[0], { x: cx, y: cy });
22903
24142
  const dim2 = 2 * cx;
22904
24143
  return { width: dim2, height: dim2 };
22905
24144
  }
22906
24145
  if (n === 2) {
22907
- const cy = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
22908
- const dx = 2 * C2.STATE_R + C2.RING_GAP + 60;
22909
- const cx02 = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
24146
+ const cy = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
24147
+ const dx = 2 * C3.STATE_R + C3.RING_GAP + 60;
24148
+ const cx02 = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
22910
24149
  centres.set(ids[0], { x: cx02, y: cy });
22911
24150
  centres.set(ids[1], { x: cx02 + dx, y: cy });
22912
- const width = cx02 + dx + C2.STATE_R + C2.LOOP_OUT + C2.PADDING;
22913
- const height = cy + C2.STATE_R + C2.LOOP_OUT + C2.PADDING;
24151
+ const width = cx02 + dx + C3.STATE_R + C3.LOOP_OUT + C3.PADDING;
24152
+ const height = cy + C3.STATE_R + C3.LOOP_OUT + C3.PADDING;
22914
24153
  return { width, height };
22915
24154
  }
22916
- const minArc = 2 * C2.STATE_R + C2.RING_GAP;
22917
- const radius = Math.max(minArc / (2 * Math.sin(Math.PI / n)), 2 * C2.STATE_R);
22918
- const margin = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
24155
+ const minArc = 2 * C3.STATE_R + C3.RING_GAP;
24156
+ const radius = Math.max(minArc / (2 * Math.sin(Math.PI / n)), 2 * C3.STATE_R);
24157
+ const margin = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
22919
24158
  const cx0 = margin + radius;
22920
24159
  const cy0 = margin + radius;
22921
24160
  ids.forEach((id, i) => {
@@ -22928,7 +24167,7 @@ function placeRing(ids, centres, C2) {
22928
24167
  const dim = 2 * (radius + margin);
22929
24168
  return { width: dim, height: dim };
22930
24169
  }
22931
- function placeLayered(ast, classification, centres, C2) {
24170
+ function placeLayered(ast, classification, centres, C3) {
22932
24171
  const tier = (id) => {
22933
24172
  const k = classification.byState[id];
22934
24173
  if (k === "absorbing") return 2;
@@ -22938,18 +24177,18 @@ function placeLayered(ast, classification, centres, C2) {
22938
24177
  const cols = [[], [], []];
22939
24178
  for (const st of ast.states) cols[tier(st.id)].push(st.id);
22940
24179
  const maxRows = Math.max(1, ...cols.map((c) => c.length));
22941
- const margin = C2.PADDING + C2.STATE_R + C2.LOOP_OUT;
24180
+ const margin = C3.PADDING + C3.STATE_R + C3.LOOP_OUT;
22942
24181
  cols.forEach((col, ci) => {
22943
- const x = margin + ci * C2.TIER_DX;
22944
- const totalH = (col.length - 1) * C2.TIER_DY;
22945
- const startY = margin + ((maxRows - 1) * C2.TIER_DY - totalH) / 2;
22946
- col.forEach((id, ri) => centres.set(id, { x, y: startY + ri * C2.TIER_DY }));
24182
+ const x = margin + ci * C3.TIER_DX;
24183
+ const totalH = (col.length - 1) * C3.TIER_DY;
24184
+ const startY = margin + ((maxRows - 1) * C3.TIER_DY - totalH) / 2;
24185
+ col.forEach((id, ri) => centres.set(id, { x, y: startY + ri * C3.TIER_DY }));
22947
24186
  });
22948
- const width = margin + 2 * C2.TIER_DX + C2.STATE_R + C2.LOOP_OUT + C2.PADDING;
22949
- const height = margin + (maxRows - 1) * C2.TIER_DY + C2.STATE_R + C2.LOOP_OUT + C2.PADDING;
24187
+ const width = margin + 2 * C3.TIER_DX + C3.STATE_R + C3.LOOP_OUT + C3.PADDING;
24188
+ const height = margin + (maxRows - 1) * C3.TIER_DY + C3.STATE_R + C3.LOOP_OUT + C3.PADDING;
22950
24189
  return { width, height };
22951
24190
  }
22952
- function curvedArcGeom(tr, a, b, bow, C2) {
24191
+ function curvedArcGeom(tr, a, b, bow, C3) {
22953
24192
  const dx = b.x - a.x;
22954
24193
  const dy = b.y - a.y;
22955
24194
  const len = Math.hypot(dx, dy) || 1;
@@ -22962,8 +24201,8 @@ function curvedArcGeom(tr, a, b, bow, C2) {
22962
24201
  x: (a.x + b.x) / 2 + nx * bow,
22963
24202
  y: (a.y + b.y) / 2 + ny * bow
22964
24203
  };
22965
- const start = aimToBoundary(a, mid, C2.STATE_R);
22966
- const end = aimToBoundary(b, mid, C2.STATE_R);
24204
+ const start = aimToBoundary(a, mid, C3.STATE_R);
24205
+ const end = aimToBoundary(b, mid, C3.STATE_R);
22967
24206
  const c1 = { x: (start.x + mid.x) / 2, y: (start.y + mid.y) / 2 };
22968
24207
  const c2 = { x: (end.x + mid.x) / 2, y: (end.y + mid.y) / 2 };
22969
24208
  return {
@@ -22980,7 +24219,7 @@ function aimToBoundary(centre, target, r7) {
22980
24219
  const len = Math.hypot(dx, dy) || 1;
22981
24220
  return { x: centre.x + dx / len * r7, y: centre.y + dy / len * r7 };
22982
24221
  }
22983
- function selfLoopGeom(tr, c, ringCenter, layout, C2) {
24222
+ function selfLoopGeom(tr, c, ringCenter, layout, C3) {
22984
24223
  let ox = c.x - ringCenter.x;
22985
24224
  let oy = c.y - ringCenter.y;
22986
24225
  if (layout === "layered" || ox === 0 && oy === 0) {
@@ -22992,26 +24231,26 @@ function selfLoopGeom(tr, c, ringCenter, layout, C2) {
22992
24231
  const uy = oy / ol;
22993
24232
  const tx = -uy;
22994
24233
  const ty = ux;
22995
- const spread = C2.STATE_R * 0.6;
24234
+ const spread = C3.STATE_R * 0.6;
22996
24235
  const foot1 = {
22997
- x: c.x + ux * C2.STATE_R * 0.85 - tx * spread,
22998
- y: c.y + uy * C2.STATE_R * 0.85 - ty * spread
24236
+ x: c.x + ux * C3.STATE_R * 0.85 - tx * spread,
24237
+ y: c.y + uy * C3.STATE_R * 0.85 - ty * spread
22999
24238
  };
23000
24239
  const foot2 = {
23001
- x: c.x + ux * C2.STATE_R * 0.85 + tx * spread,
23002
- y: c.y + uy * C2.STATE_R * 0.85 + ty * spread
24240
+ x: c.x + ux * C3.STATE_R * 0.85 + tx * spread,
24241
+ y: c.y + uy * C3.STATE_R * 0.85 + ty * spread
23003
24242
  };
23004
24243
  const apex = {
23005
- x: c.x + ux * (C2.STATE_R + C2.LOOP_OUT),
23006
- y: c.y + uy * (C2.STATE_R + C2.LOOP_OUT)
24244
+ x: c.x + ux * (C3.STATE_R + C3.LOOP_OUT),
24245
+ y: c.y + uy * (C3.STATE_R + C3.LOOP_OUT)
23007
24246
  };
23008
24247
  const ctrl1 = {
23009
- x: foot1.x + ux * C2.LOOP_OUT - tx * C2.LOOP_R,
23010
- y: foot1.y + uy * C2.LOOP_OUT - ty * C2.LOOP_R
24248
+ x: foot1.x + ux * C3.LOOP_OUT - tx * C3.LOOP_R,
24249
+ y: foot1.y + uy * C3.LOOP_OUT - ty * C3.LOOP_R
23011
24250
  };
23012
24251
  const ctrl2 = {
23013
- x: foot2.x + ux * C2.LOOP_OUT + tx * C2.LOOP_R,
23014
- y: foot2.y + uy * C2.LOOP_OUT + ty * C2.LOOP_R
24252
+ x: foot2.x + ux * C3.LOOP_OUT + tx * C3.LOOP_R,
24253
+ y: foot2.y + uy * C3.LOOP_OUT + ty * C3.LOOP_R
23015
24254
  };
23016
24255
  return {
23017
24256
  transition: tr,
@@ -23088,7 +24327,7 @@ function renderState2(sb) {
23088
24327
  parts.push(
23089
24328
  text(
23090
24329
  { class: "sx-markov-pi", x: sb.cx, y: sb.cy + sb.r + 14, "text-anchor": "middle" },
23091
- `\u03C0=${fmt5(sb.pi)}`
24330
+ `\u03C0=${fmt6(sb.pi)}`
23092
24331
  )
23093
24332
  );
23094
24333
  }
@@ -23097,7 +24336,7 @@ function renderState2(sb) {
23097
24336
  "data-id": sb.state.id
23098
24337
  };
23099
24338
  if (sb.classTag) attrs["data-class"] = sb.classTag;
23100
- if (sb.pi !== void 0) attrs["data-pi"] = fmt5(sb.pi);
24339
+ if (sb.pi !== void 0) attrs["data-pi"] = fmt6(sb.pi);
23101
24340
  return group(attrs, parts);
23102
24341
  }
23103
24342
  function arcPath2(ag) {
@@ -23110,7 +24349,7 @@ function renderArc3(ag) {
23110
24349
  path({ class: cls, d: arcPath2(ag), "marker-end": "url(#sx-markov-head)" }),
23111
24350
  text(
23112
24351
  { class: "sx-markov-prob", x: ag.labelX, y: ag.labelY + 3, "text-anchor": "middle" },
23113
- fmt5(ag.transition.probability)
24352
+ fmt6(ag.transition.probability)
23114
24353
  )
23115
24354
  ];
23116
24355
  return group(
@@ -23118,7 +24357,7 @@ function renderArc3(ag) {
23118
24357
  class: ag.self ? "sx-markov-arc-g sx-markov-arc-self-g" : "sx-markov-arc-g",
23119
24358
  "data-from": ag.transition.from,
23120
24359
  "data-to": ag.transition.to,
23121
- "data-prob": fmt5(ag.transition.probability)
24360
+ "data-prob": fmt6(ag.transition.probability)
23122
24361
  },
23123
24362
  parts
23124
24363
  );
@@ -23139,11 +24378,11 @@ function buildDesc(layout) {
23139
24378
  }
23140
24379
  if (a.stationary) {
23141
24380
  if (a.stationary.unique) {
23142
- const entries = layout.analysis.order.filter((id) => a.stationary.pi[id] !== void 0).map((id) => `${id}=${fmt5(a.stationary.pi[id])}`);
24381
+ const entries = layout.analysis.order.filter((id) => a.stationary.pi[id] !== void 0).map((id) => `${id}=${fmt6(a.stationary.pi[id])}`);
23143
24382
  out.push(`Stationary \u03C0: { ${entries.join(", ")} }.`);
23144
24383
  } else if (a.stationary.perClass.length) {
23145
24384
  const blocks = a.stationary.perClass.map((pc2) => {
23146
- const e = pc2.states.map((id) => `${id}=${fmt5(pc2.pi[id])}`).join(", ");
24385
+ const e = pc2.states.map((id) => `${id}=${fmt6(pc2.pi[id])}`).join(", ");
23147
24386
  return `{ ${e} }`;
23148
24387
  });
23149
24388
  out.push(`Stationary \u03C0 (per recurrent class, not globally unique): ${blocks.join("; ")}.`);
@@ -23151,10 +24390,10 @@ function buildDesc(layout) {
23151
24390
  }
23152
24391
  if (a.absorbing) {
23153
24392
  const ab = a.absorbing;
23154
- const tParts = ab.transient.map((id, i) => `${id}=${fmt5(ab.t[i])}`);
24393
+ const tParts = ab.transient.map((id, i) => `${id}=${fmt6(ab.t[i])}`);
23155
24394
  out.push(`Expected steps to absorption t: { ${tParts.join(", ")} }.`);
23156
24395
  const bRows = ab.transient.map((from, i) => {
23157
- const probs = ab.absorbing.map((to, j) => `${to}=${fmt5(ab.B[i][j])}`).join(", ");
24396
+ const probs = ab.absorbing.map((to, j) => `${to}=${fmt6(ab.B[i][j])}`).join(", ");
23158
24397
  return `${from}\u2192(${probs})`;
23159
24398
  });
23160
24399
  out.push(`Absorption probabilities B: ${bRows.join("; ")}.`);
@@ -23210,7 +24449,7 @@ function renderMarkov(textOrAst, config) {
23210
24449
  const layout = layoutMarkov(ast);
23211
24450
  return renderMarkovLayout(layout, config);
23212
24451
  }
23213
- function fmt5(x) {
24452
+ function fmt6(x) {
23214
24453
  if (!Number.isFinite(x)) return String(x);
23215
24454
  const r7 = Math.round(x * 1e3) / 1e3;
23216
24455
  return String(r7);
@@ -23256,7 +24495,7 @@ function parseGitGraph(text2) {
23256
24495
  i = skipBlankAndDirectives(rawLines, i, ast);
23257
24496
  let headerSeen = false;
23258
24497
  while (i < rawLines.length) {
23259
- const t = stripComment9(rawLines[i] ?? "").trim();
24498
+ const t = stripComment10(rawLines[i] ?? "").trim();
23260
24499
  if (t === "") {
23261
24500
  i++;
23262
24501
  continue;
@@ -23264,7 +24503,7 @@ function parseGitGraph(text2) {
23264
24503
  const h = /^gitgraph\b\s*:?\s*(.*)$/i.exec(t);
23265
24504
  if (!h) {
23266
24505
  throw new GitGraphParseError(
23267
- `expected a 'gitGraph' header, got: ${truncate8(t)}`,
24506
+ `expected a 'gitGraph' header, got: ${truncate9(t)}`,
23268
24507
  i + 1
23269
24508
  );
23270
24509
  }
@@ -23283,7 +24522,7 @@ function parseGitGraph(text2) {
23283
24522
  throw new GitGraphParseError("empty gitGraph (no header)");
23284
24523
  }
23285
24524
  for (; i < rawLines.length; i++) {
23286
- const t = stripComment9(rawLines[i] ?? "").trim();
24525
+ const t = stripComment10(rawLines[i] ?? "").trim();
23287
24526
  if (t === "") continue;
23288
24527
  if (/^%%\{/.test(t)) {
23289
24528
  applyInit(t, ast);
@@ -23292,7 +24531,7 @@ function parseGitGraph(text2) {
23292
24531
  const op = parseOperation2(t, i + 1);
23293
24532
  if (op) ast.operations.push(op);
23294
24533
  }
23295
- validate5(ast);
24534
+ validate6(ast);
23296
24535
  return ast;
23297
24536
  }
23298
24537
  function parseOperation2(line2, lineNo) {
@@ -23334,7 +24573,7 @@ function parseOptions(rest, lineNo) {
23334
24573
  const keyMatch = /^([A-Za-z]+)\s*:/.exec(s.slice(i));
23335
24574
  if (!keyMatch) {
23336
24575
  throw new GitGraphParseError(
23337
- `unexpected token near '${truncate8(s.slice(i))}' (expected key: value)`,
24576
+ `unexpected token near '${truncate9(s.slice(i))}' (expected key: value)`,
23338
24577
  lineNo
23339
24578
  );
23340
24579
  }
@@ -23449,7 +24688,7 @@ function parseCherryPick(rest, lineNo) {
23449
24688
  }
23450
24689
  return { kind: "cherry-pick", id: o.id, tag: o.tag, parent: o.parent, line: lineNo };
23451
24690
  }
23452
- function validate5(ast) {
24691
+ function validate6(ast) {
23453
24692
  const firstOp = ast.operations[0];
23454
24693
  if (firstOp && firstOp.kind !== "commit" && firstOp.kind !== "branch") ;
23455
24694
  }
@@ -23470,7 +24709,7 @@ function parseFrontmatter2(lines, start, ast) {
23470
24709
  function skipBlankAndDirectives(lines, start, ast) {
23471
24710
  let i = start;
23472
24711
  for (; i < lines.length; i++) {
23473
- const t = stripComment9(lines[i] ?? "").trim();
24712
+ const t = stripComment10(lines[i] ?? "").trim();
23474
24713
  if (t === "") continue;
23475
24714
  if (/^%%\{/.test(t)) {
23476
24715
  applyInit(t, ast);
@@ -23503,7 +24742,7 @@ function applyConfigLines(lines, ast) {
23503
24742
  if (tv && !/^(LR|TB|BT)$/i.test(tv)) ast.title = tv;
23504
24743
  }
23505
24744
  }
23506
- function stripComment9(line2) {
24745
+ function stripComment10(line2) {
23507
24746
  const idx = line2.indexOf("%%");
23508
24747
  if (idx >= 0 && line2.slice(idx, idx + 3) !== "%%{") {
23509
24748
  return line2.slice(0, idx);
@@ -23513,7 +24752,7 @@ function stripComment9(line2) {
23513
24752
  function isQuote(ch) {
23514
24753
  return ch === '"' || ch === "'" || ch === "\u201C" || ch === "\u2018" || ch === "\u300C" || ch === "\u300E" || ch === "\xAB";
23515
24754
  }
23516
- function truncate8(s) {
24755
+ function truncate9(s) {
23517
24756
  return s.length > 40 ? `${s.slice(0, 40)}\u2026` : s;
23518
24757
  }
23519
24758
 
@@ -23719,18 +24958,18 @@ function assignLanes(ast, state2) {
23719
24958
  }
23720
24959
  function layoutGitGraph(ast) {
23721
24960
  const replay = replayGitGraph(ast);
23722
- const C2 = GITGRAPH_CONST;
24961
+ const C3 = GITGRAPH_CONST;
23723
24962
  const branchByName = new Map(replay.branches.map((b) => [b.name, b]));
23724
24963
  const laneCount = replay.branches.length;
23725
24964
  const commitCount = replay.commits.length;
23726
- const headBand = ast.showBranches ? C2.PILL_GUTTER : C2.LEAD_IN;
23727
- const timeAt = (s) => headBand + C2.LEAD_IN + s * C2.TIME_STEP;
23728
- const crossAt = (l) => C2.PAD + C2.TAG_BAND + C2.LANE_GAP / 2 + l * C2.LANE_GAP;
24965
+ const headBand = ast.showBranches ? C3.PILL_GUTTER : C3.LEAD_IN;
24966
+ const timeAt = (s) => headBand + C3.LEAD_IN + s * C3.TIME_STEP;
24967
+ const crossAt = (l) => C3.PAD + C3.TAG_BAND + C3.LANE_GAP / 2 + l * C3.LANE_GAP;
23729
24968
  const timeSpan = commitCount > 0 ? timeAt(commitCount - 1) : timeAt(0);
23730
24969
  const crossSpan = crossAt(Math.max(0, laneCount - 1));
23731
24970
  const isVertical = ast.orientation === "TB" || ast.orientation === "BT";
23732
- const timeMax = timeSpan + C2.TIME_STEP / 2 + (ast.showCommitLabel ? C2.LABEL_BAND : C2.PAD);
23733
- const crossMax = crossSpan + C2.LANE_GAP / 2 + C2.PAD;
24971
+ const timeMax = timeSpan + C3.TIME_STEP / 2 + (ast.showCommitLabel ? C3.LABEL_BAND : C3.PAD);
24972
+ const crossMax = crossSpan + C3.LANE_GAP / 2 + C3.PAD;
23734
24973
  const width = isVertical ? crossMax : timeMax;
23735
24974
  const height = isVertical ? timeMax : crossMax;
23736
24975
  const place = (t, c) => {
@@ -23761,12 +25000,12 @@ function layoutGitGraph(ast) {
23761
25000
  }
23762
25001
  const firstOwn = own[0];
23763
25002
  const isTrunk = !firstOwn || firstOwn.parents.length === 0;
23764
- const startT = isTrunk ? timeAt(startSeq) - C2.TIME_STEP / 2 : timeAt(startSeq);
25003
+ const startT = isTrunk ? timeAt(startSeq) - C3.TIME_STEP / 2 : timeAt(startSeq);
23765
25004
  const endT = timeAt(endSeq);
23766
25005
  const c = crossAt(info.lane);
23767
25006
  const head = place(startT, c);
23768
25007
  const tail = place(endT, c);
23769
- const pillT = headBand - C2.LEAD_IN / 2;
25008
+ const pillT = headBand - C3.LEAD_IN / 2;
23770
25009
  const pillPos = place(pillT, c);
23771
25010
  return {
23772
25011
  info,
@@ -23890,7 +25129,7 @@ function renderGitGraphLayout(layout, config) {
23890
25129
  const styleBlock = buildStyle2(pal, ast.showBranches);
23891
25130
  const children = [
23892
25131
  title(a11y),
23893
- desc(summarise8(layout)),
25132
+ desc(summarise9(layout)),
23894
25133
  styleBlock,
23895
25134
  rect({ x: 0, y: 0, width, height, class: "sx-gg-bg" })
23896
25135
  ];
@@ -24140,7 +25379,7 @@ ${laneRules}
24140
25379
  function num2(n) {
24141
25380
  return Number.isInteger(n) ? String(n) : n.toFixed(2);
24142
25381
  }
24143
- function summarise8(layout) {
25382
+ function summarise9(layout) {
24144
25383
  const c = layout.replay.commits.length;
24145
25384
  const b = layout.replay.branches.length;
24146
25385
  const merges = layout.replay.commits.filter((n) => n.isMerge).length;
@@ -24432,7 +25671,7 @@ function parseEpc(text2) {
24432
25671
  let i = 0;
24433
25672
  let headerSeen = false;
24434
25673
  while (i < rawLines.length) {
24435
- const t = stripComment10(rawLines[i] ?? "").trim();
25674
+ const t = stripComment11(rawLines[i] ?? "").trim();
24436
25675
  if (t === "") {
24437
25676
  i++;
24438
25677
  continue;
@@ -24440,7 +25679,7 @@ function parseEpc(text2) {
24440
25679
  const h = /^epc\b(.*)$/i.exec(t);
24441
25680
  if (h) {
24442
25681
  const after = h[1].trim();
24443
- const q = matchQuoted6(after);
25682
+ const q = matchQuoted7(after);
24444
25683
  if (q) ast.title = q.value;
24445
25684
  headerSeen = true;
24446
25685
  i++;
@@ -24451,11 +25690,11 @@ function parseEpc(text2) {
24451
25690
  }
24452
25691
  if (!headerSeen) return finish(ast);
24453
25692
  for (; i < rawLines.length; i++) {
24454
- const t = stripComment10(rawLines[i] ?? "").trim();
25693
+ const t = stripComment11(rawLines[i] ?? "").trim();
24455
25694
  if (t === "") continue;
24456
25695
  const lineNo = i + 1;
24457
25696
  if (/^layout\s*:/i.test(t)) {
24458
- const v = afterColon6(t).toLowerCase();
25697
+ const v = afterColon7(t).toLowerCase();
24459
25698
  if (v === "tb" || v === "lr") ast.direction = v;
24460
25699
  else ast.warnings.push(`Line ${lineNo}: unknown layout "${v}" \u2014 using "tb".`);
24461
25700
  continue;
@@ -24469,7 +25708,7 @@ function parseEpc(text2) {
24469
25708
  parseDeclLine(ast, kw[1].toLowerCase(), t.slice(kw[0].length).trim(), lineNo);
24470
25709
  continue;
24471
25710
  }
24472
- ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate9(t, 80)}"`);
25711
+ ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate10(t, 80)}"`);
24473
25712
  }
24474
25713
  return finish(ast);
24475
25714
  }
@@ -24503,13 +25742,13 @@ function parseEdgeLine(ast, line2, lineNo) {
24503
25742
  const colon = topLevelColon(body);
24504
25743
  if (colon >= 0) {
24505
25744
  const labelPart = body.slice(colon + 1).trim();
24506
- const q = matchQuoted6(labelPart);
25745
+ const q = matchQuoted7(labelPart);
24507
25746
  edgeLabel2 = q ? q.value : labelPart;
24508
25747
  body = body.slice(0, colon).trim();
24509
25748
  }
24510
25749
  const parts = splitArrow(body).map((p) => p.trim()).filter((p) => p.length > 0);
24511
25750
  if (parts.length < 2) {
24512
- throw new EpcParseError(`an edge needs at least two nodes around '->', got "${truncate9(line2, 60)}"`, lineNo);
25751
+ throw new EpcParseError(`an edge needs at least two nodes around '->', got "${truncate10(line2, 60)}"`, lineNo);
24513
25752
  }
24514
25753
  for (const p of parts) {
24515
25754
  if (!isId2(p)) throw new EpcParseError(`invalid node reference "${p}" in edge`, lineNo);
@@ -24546,11 +25785,11 @@ function ensureRef(ast, id, _lineNo) {
24546
25785
  }
24547
25786
  function parseIdAndLabel3(s, lineNo) {
24548
25787
  const m = /^([A-Za-z_]\w*)/.exec(s.trim());
24549
- if (!m) throw new EpcParseError(`expected a node id, got "${truncate9(s, 40)}"`, lineNo);
25788
+ if (!m) throw new EpcParseError(`expected a node id, got "${truncate10(s, 40)}"`, lineNo);
24550
25789
  const id = m[1];
24551
25790
  const rest = s.trim().slice(id.length).trim();
24552
25791
  if (rest === "") return { id };
24553
- const q = matchQuoted6(rest);
25792
+ const q = matchQuoted7(rest);
24554
25793
  if (q) return { id, label: q.value };
24555
25794
  return { id, label: rest };
24556
25795
  }
@@ -24573,7 +25812,7 @@ function splitArrow(s) {
24573
25812
  }
24574
25813
  if (ch === '"' || ch === "\u300C" || ch === "\u201C") {
24575
25814
  inQ = true;
24576
- qc = closingQuote6(ch);
25815
+ qc = closingQuote7(ch);
24577
25816
  buf += ch;
24578
25817
  continue;
24579
25818
  }
@@ -24598,30 +25837,30 @@ function topLevelColon(s) {
24598
25837
  }
24599
25838
  if (ch === '"' || ch === "\u300C" || ch === "\u201C") {
24600
25839
  inQ = true;
24601
- qc = closingQuote6(ch);
25840
+ qc = closingQuote7(ch);
24602
25841
  continue;
24603
25842
  }
24604
25843
  if (ch === ":") return i;
24605
25844
  }
24606
25845
  return -1;
24607
25846
  }
24608
- function matchQuoted6(s) {
25847
+ function matchQuoted7(s) {
24609
25848
  if (!s) return void 0;
24610
25849
  const open = s[0];
24611
25850
  if (open !== '"' && open !== "\u300C" && open !== "\u201C") return void 0;
24612
- const close = closingQuote6(open);
25851
+ const close = closingQuote7(open);
24613
25852
  const end = s.indexOf(close, 1);
24614
25853
  if (end < 0) return void 0;
24615
25854
  return { value: s.slice(1, end), length: end + 1 };
24616
25855
  }
24617
- function closingQuote6(open) {
25856
+ function closingQuote7(open) {
24618
25857
  return open === "\u300C" ? "\u300D" : open === "\u201C" ? "\u201D" : '"';
24619
25858
  }
24620
- function afterColon6(s) {
25859
+ function afterColon7(s) {
24621
25860
  const i = s.indexOf(":");
24622
25861
  return i < 0 ? "" : s.slice(i + 1).trim();
24623
25862
  }
24624
- function stripComment10(line2) {
25863
+ function stripComment11(line2) {
24625
25864
  let inQ = false, qc = "";
24626
25865
  for (let i = 0; i < line2.length; i++) {
24627
25866
  const ch = line2[i];
@@ -24631,7 +25870,7 @@ function stripComment10(line2) {
24631
25870
  }
24632
25871
  if (ch === '"' || ch === "\u300C" || ch === "\u201C") {
24633
25872
  inQ = true;
24634
- qc = closingQuote6(ch);
25873
+ qc = closingQuote7(ch);
24635
25874
  continue;
24636
25875
  }
24637
25876
  if (ch === "#") return line2.slice(0, i);
@@ -24639,7 +25878,7 @@ function stripComment10(line2) {
24639
25878
  }
24640
25879
  return line2;
24641
25880
  }
24642
- function truncate9(s, n) {
25881
+ function truncate10(s, n) {
24643
25882
  return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
24644
25883
  }
24645
25884
 
@@ -24981,7 +26220,7 @@ function renderEpcLayout(layout, config) {
24981
26220
  );
24982
26221
  const children = [
24983
26222
  title(a11y),
24984
- desc(summarise9(layout)),
26223
+ desc(summarise10(layout)),
24985
26224
  styleBlock,
24986
26225
  defs([
24987
26226
  el("marker", {
@@ -25125,7 +26364,7 @@ function renderEdge6(e) {
25125
26364
  parts
25126
26365
  );
25127
26366
  }
25128
- function summarise9(layout) {
26367
+ function summarise10(layout) {
25129
26368
  const { ast, analysis } = layout;
25130
26369
  const counts = { event: 0, function: 0, connector: 0 };
25131
26370
  for (const n of ast.nodes) counts[n.kind]++;
@@ -25220,12 +26459,12 @@ function parseIdef0(text2) {
25220
26459
  let i = 0;
25221
26460
  let headerSeen = false;
25222
26461
  for (; i < rawLines.length; i++) {
25223
- const t = stripComment11(rawLines[i] ?? "").trim();
26462
+ const t = stripComment12(rawLines[i] ?? "").trim();
25224
26463
  if (t === "") continue;
25225
26464
  const h = /^idef0\b(.*)$/i.exec(t);
25226
26465
  if (h) {
25227
26466
  const after = h[1].trim();
25228
- const q = matchQuoted7(after);
26467
+ const q = matchQuoted8(after);
25229
26468
  if (q) ast.title = q.value;
25230
26469
  headerSeen = true;
25231
26470
  i++;
@@ -25236,7 +26475,7 @@ function parseIdef0(text2) {
25236
26475
  throw new Idef0ParseError(`an idef0 diagram must start with the 'idef0' keyword`);
25237
26476
  }
25238
26477
  for (; i < rawLines.length; i++) {
25239
- const t = stripComment11(rawLines[i] ?? "").trim();
26478
+ const t = stripComment12(rawLines[i] ?? "").trim();
25240
26479
  if (t === "") continue;
25241
26480
  const lineNo = i + 1;
25242
26481
  const nodeM = /^node\s+(.+)$/i.exec(t);
@@ -25247,7 +26486,7 @@ function parseIdef0(text2) {
25247
26486
  const metaM = /^(purpose|viewpoint)\b\s*(.*)$/i.exec(t);
25248
26487
  if (metaM) {
25249
26488
  const key = metaM[1].toLowerCase();
25250
- const q = matchQuoted7(metaM[2].trim());
26489
+ const q = matchQuoted8(metaM[2].trim());
25251
26490
  ast[key] = q ? q.value : metaM[2].trim();
25252
26491
  continue;
25253
26492
  }
@@ -25265,17 +26504,17 @@ function parseIdef0(text2) {
25265
26504
  parseFlowArrow(ast, t, lineNo);
25266
26505
  continue;
25267
26506
  }
25268
- ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate10(t, 80)}"`);
26507
+ ast.warnings.push(`Line ${lineNo}: unrecognised line: "${truncate11(t, 80)}"`);
25269
26508
  }
25270
26509
  return ast;
25271
26510
  }
25272
26511
  function parseFunction2(ast, rest, lineNo) {
25273
26512
  const idM = /^([A-Za-z_]\w*)/.exec(rest);
25274
- if (!idM) throw new Idef0ParseError(`function needs an id, got "${truncate10(rest, 40)}"`, lineNo);
26513
+ if (!idM) throw new Idef0ParseError(`function needs an id, got "${truncate11(rest, 40)}"`, lineNo);
25275
26514
  const id = idM[1];
25276
26515
  let tail = rest.slice(id.length).trim();
25277
26516
  let name = id;
25278
- const q = matchQuoted7(tail);
26517
+ const q = matchQuoted8(tail);
25279
26518
  if (q) {
25280
26519
  name = q.value;
25281
26520
  tail = tail.slice(q.length).trim();
@@ -25297,11 +26536,11 @@ function parseFunction2(ast, rest, lineNo) {
25297
26536
  }
25298
26537
  function parseRoleArrow(ast, role, rest, lineNo) {
25299
26538
  const idM = /^([A-Za-z_]\w*)/.exec(rest);
25300
- if (!idM) throw new Idef0ParseError(`${role} needs a box id, got "${truncate10(rest, 40)}"`, lineNo);
26539
+ if (!idM) throw new Idef0ParseError(`${role} needs a box id, got "${truncate11(rest, 40)}"`, lineNo);
25301
26540
  const boxId = idM[1];
25302
26541
  let tail = rest.slice(boxId.length).trim();
25303
26542
  let label = "";
25304
- const q = matchQuoted7(tail);
26543
+ const q = matchQuoted8(tail);
25305
26544
  if (q) {
25306
26545
  label = q.value;
25307
26546
  tail = tail.slice(q.length).trim();
@@ -25327,10 +26566,10 @@ function parseFlowArrow(ast, t, lineNo) {
25327
26566
  const lhs = t.slice(0, arrowIdx).trim();
25328
26567
  let rhs = t.slice(arrowIdx + 2).trim();
25329
26568
  const srcM = /^([A-Za-z_]\w*)$/.exec(lhs);
25330
- if (!srcM) throw new Idef0ParseError(`flow arrow source must be a box id, got "${truncate10(lhs, 40)}"`, lineNo);
26569
+ if (!srcM) throw new Idef0ParseError(`flow arrow source must be a box id, got "${truncate11(lhs, 40)}"`, lineNo);
25331
26570
  const srcId = srcM[1];
25332
26571
  const tgtM = /^([A-Za-z_]\w*)(?:\.([a-z]+))?/i.exec(rhs);
25333
- if (!tgtM) throw new Idef0ParseError(`flow arrow target must be a box id, got "${truncate10(rhs, 40)}"`, lineNo);
26572
+ if (!tgtM) throw new Idef0ParseError(`flow arrow target must be a box id, got "${truncate11(rhs, 40)}"`, lineNo);
25334
26573
  const tgtId = tgtM[1];
25335
26574
  const roleWord = tgtM[2]?.toLowerCase();
25336
26575
  let role = "input";
@@ -25351,7 +26590,7 @@ function parseFlowArrow(ast, t, lineNo) {
25351
26590
  }
25352
26591
  rhs = rhs.slice(tgtM[0].length).trim();
25353
26592
  let label = "";
25354
- const q = matchQuoted7(rhs);
26593
+ const q = matchQuoted8(rhs);
25355
26594
  if (q) {
25356
26595
  label = q.value;
25357
26596
  rhs = rhs.slice(q.length).trim();
@@ -25374,19 +26613,19 @@ function parseFlowArrow(ast, t, lineNo) {
25374
26613
  function consumeTunnel(s) {
25375
26614
  return /\(\s*tunnel\s*\)/i.test(s);
25376
26615
  }
25377
- function matchQuoted7(s) {
26616
+ function matchQuoted8(s) {
25378
26617
  if (!s) return void 0;
25379
26618
  const open = s[0];
25380
26619
  if (open !== '"' && open !== "\u300C" && open !== "\u201C") return void 0;
25381
- const close = closingQuote7(open);
26620
+ const close = closingQuote8(open);
25382
26621
  const end = s.indexOf(close, 1);
25383
26622
  if (end < 0) return void 0;
25384
26623
  return { value: s.slice(1, end), length: end + 1 };
25385
26624
  }
25386
- function closingQuote7(open) {
26625
+ function closingQuote8(open) {
25387
26626
  return open === "\u300C" ? "\u300D" : open === "\u201C" ? "\u201D" : '"';
25388
26627
  }
25389
- function stripComment11(line2) {
26628
+ function stripComment12(line2) {
25390
26629
  let inQ = false;
25391
26630
  let qc = "";
25392
26631
  for (let i = 0; i < line2.length; i++) {
@@ -25397,14 +26636,14 @@ function stripComment11(line2) {
25397
26636
  }
25398
26637
  if (ch === '"' || ch === "\u300C" || ch === "\u201C") {
25399
26638
  inQ = true;
25400
- qc = closingQuote7(ch);
26639
+ qc = closingQuote8(ch);
25401
26640
  continue;
25402
26641
  }
25403
26642
  if (ch === "#") return line2.slice(0, i);
25404
26643
  }
25405
26644
  return line2;
25406
26645
  }
25407
- function truncate10(s, n) {
26646
+ function truncate11(s, n) {
25408
26647
  return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
25409
26648
  }
25410
26649
 
@@ -25562,22 +26801,22 @@ var IDEF0_CONST = {
25562
26801
  };
25563
26802
  function layoutIdef0(astIn) {
25564
26803
  const ast = analyseIdef0(astIn);
25565
- const C2 = IDEF0_CONST;
25566
- const ox = C2.MARGIN;
25567
- const oy = C2.MARGIN + C2.TITLE_H;
26804
+ const C3 = IDEF0_CONST;
26805
+ const ox = C3.MARGIN;
26806
+ const oy = C3.MARGIN + C3.TITLE_H;
25568
26807
  const boxes = ast.boxes.map((box2, idx) => ({
25569
26808
  box: box2,
25570
- x: ox + idx * C2.STEP_X,
25571
- y: oy + idx * C2.STEP_Y,
25572
- width: C2.BOX_W,
25573
- height: C2.BOX_H
26809
+ x: ox + idx * C3.STEP_X,
26810
+ y: oy + idx * C3.STEP_Y,
26811
+ width: C3.BOX_W,
26812
+ height: C3.BOX_H
25574
26813
  }));
25575
26814
  const boxIndex = new Map(boxes.map((b, i) => [b.box.id, i]));
25576
26815
  const lastBox = boxes[boxes.length - 1];
25577
- const contentRight = lastBox.x + C2.BOX_W;
25578
- const contentBottom = lastBox.y + C2.BOX_H;
25579
- const width = contentRight + C2.MARGIN;
25580
- const height = contentBottom + C2.MARGIN + C2.TITLEBLOCK_H;
26816
+ const contentRight = lastBox.x + C3.BOX_W;
26817
+ const contentBottom = lastBox.y + C3.BOX_H;
26818
+ const width = contentRight + C3.MARGIN;
26819
+ const height = contentBottom + C3.MARGIN + C3.TITLEBLOCK_H;
25581
26820
  const arrows = ast.arrows.map(
25582
26821
  (arrow2) => routeArrow(arrow2, boxes, boxIndex)
25583
26822
  );
@@ -25596,7 +26835,7 @@ function sidePoint(b, side) {
25596
26835
  }
25597
26836
  }
25598
26837
  function routeArrow(arrow2, boxes, boxIndex) {
25599
- const C2 = IDEF0_CONST;
26838
+ const C3 = IDEF0_CONST;
25600
26839
  const targetSide = ICOM_SIDE[arrow2.role];
25601
26840
  const fromBoundary = arrow2.from.kind === "boundary";
25602
26841
  const toBoundary = arrow2.to.kind === "boundary";
@@ -25629,10 +26868,10 @@ function routeArrow(arrow2, boxes, boxIndex) {
25629
26868
  margin: false
25630
26869
  };
25631
26870
  }
25632
- const marginY = C2.MARGIN / 2 + C2.TITLE_H;
26871
+ const marginY = C3.MARGIN / 2 + C3.TITLE_H;
25633
26872
  let d;
25634
26873
  if (targetSide === "left") {
25635
- const approachX = end.x - C2.FEEDBACK_LEADIN;
26874
+ const approachX = end.x - C3.FEEDBACK_LEADIN;
25636
26875
  d = `M ${start.x} ${start.y} L ${start.x + 20} ${start.y} L ${start.x + 20} ${marginY} L ${approachX} ${marginY} L ${approachX} ${end.y} L ${end.x} ${end.y}`;
25637
26876
  } else {
25638
26877
  d = `M ${start.x} ${start.y} L ${start.x + 20} ${start.y} L ${start.x + 20} ${marginY} L ${end.x} ${marginY} L ${end.x} ${end.y}`;
@@ -25646,7 +26885,7 @@ function routeArrow(arrow2, boxes, boxIndex) {
25646
26885
  };
25647
26886
  }
25648
26887
  function routeBoundary(arrow2, boxes, boxIndex, targetSide, fromBoundary) {
25649
- const C2 = IDEF0_CONST;
26888
+ const C3 = IDEF0_CONST;
25650
26889
  const boxEnd = fromBoundary ? arrow2.to : arrow2.from;
25651
26890
  const b = boxes[boxIndex.get(boxEnd.boxId)];
25652
26891
  const side = fromBoundary ? targetSide : "right";
@@ -25654,16 +26893,16 @@ function routeBoundary(arrow2, boxes, boxIndex, targetSide, fromBoundary) {
25654
26893
  let stub;
25655
26894
  switch (side) {
25656
26895
  case "left":
25657
- stub = { x: edge.x - C2.STUB, y: edge.y };
26896
+ stub = { x: edge.x - C3.STUB, y: edge.y };
25658
26897
  break;
25659
26898
  case "top":
25660
- stub = { x: edge.x, y: edge.y - C2.STUB };
26899
+ stub = { x: edge.x, y: edge.y - C3.STUB };
25661
26900
  break;
25662
26901
  case "right":
25663
- stub = { x: edge.x + C2.STUB, y: edge.y };
26902
+ stub = { x: edge.x + C3.STUB, y: edge.y };
25664
26903
  break;
25665
26904
  case "bottom":
25666
- stub = { x: edge.x, y: edge.y + C2.STUB };
26905
+ stub = { x: edge.x, y: edge.y + C3.STUB };
25667
26906
  break;
25668
26907
  }
25669
26908
  let path2;
@@ -25738,7 +26977,7 @@ function renderIdef0Layout(layout, config) {
25738
26977
  );
25739
26978
  const children = [
25740
26979
  title(a11y),
25741
- desc(summarise10(layout)),
26980
+ desc(summarise11(layout)),
25742
26981
  styleBlock,
25743
26982
  rect({ x: 0, y: 0, width, height, class: "sx-idef0-bg" })
25744
26983
  ];
@@ -25896,7 +27135,7 @@ function renderTitleBlock(width, height, node, title2) {
25896
27135
  text({ x: c2 + 6, y: y + 13, class: "sx-idef0-tb-key" }, "NUMBER")
25897
27136
  ]);
25898
27137
  }
25899
- function summarise10(layout) {
27138
+ function summarise11(layout) {
25900
27139
  const { ast } = layout;
25901
27140
  const counts = {};
25902
27141
  for (const a of ast.arrows) counts[a.role] = (counts[a.role] ?? 0) + 1;
@@ -25966,7 +27205,7 @@ function normalizeQuotes3(text2) {
25966
27205
  for (const ch of text2) out += QUOTE_FOLD.get(ch) ?? ch;
25967
27206
  return out;
25968
27207
  }
25969
- function stripComment12(line2) {
27208
+ function stripComment13(line2) {
25970
27209
  let inQuote = false;
25971
27210
  for (let i = 0; i < line2.length; i++) {
25972
27211
  const ch = line2[i];
@@ -26010,7 +27249,7 @@ function parseThreatModel(text2) {
26010
27249
  let i = 0;
26011
27250
  let headerSeen = false;
26012
27251
  for (; i < rawLines.length; i++) {
26013
- const t = stripComment12(rawLines[i] ?? "").trim();
27252
+ const t = stripComment13(rawLines[i] ?? "").trim();
26014
27253
  if (t === "") continue;
26015
27254
  const h = /^(threatmodel|stride)\b(.*)$/i.exec(t);
26016
27255
  if (h) {
@@ -26029,7 +27268,7 @@ function parseThreatModel(text2) {
26029
27268
  }
26030
27269
  for (; i < rawLines.length; i++) {
26031
27270
  const lineNo = i + 1;
26032
- const t = stripComment12(rawLines[i] ?? "").trim();
27271
+ const t = stripComment13(rawLines[i] ?? "").trim();
26033
27272
  if (t === "") continue;
26034
27273
  const titleM = /^title\s*:\s*(.+)$/i.exec(t);
26035
27274
  if (titleM) {
@@ -26123,7 +27362,7 @@ function parseThreatModel(text2) {
26123
27362
  );
26124
27363
  }
26125
27364
  resolveEndpoints(ast, byId);
26126
- validate6(ast, byId);
27365
+ validate7(ast, byId);
26127
27366
  return ast;
26128
27367
  }
26129
27368
  function resolveEndpoints(ast, byId) {
@@ -26146,7 +27385,7 @@ function resolveEndpoints(ast, byId) {
26146
27385
  b.members = b.members.map(canon);
26147
27386
  }
26148
27387
  }
26149
- function validate6(ast, byId) {
27388
+ function validate7(ast, byId) {
26150
27389
  for (const f of ast.flows) {
26151
27390
  const s = byId.get(f.source)?.node;
26152
27391
  const tg = byId.get(f.target)?.node;
@@ -26557,7 +27796,7 @@ function renderThreatModelLayout(layout, config) {
26557
27796
  ]);
26558
27797
  const children = [
26559
27798
  title(a11y),
26560
- desc(summarise11(layout)),
27799
+ desc(summarise12(layout)),
26561
27800
  styleBlock,
26562
27801
  markerDefs,
26563
27802
  rect({ x: 0, y: 0, width, height, class: "sx-tm-bg" })
@@ -26673,8 +27912,8 @@ ${n.label}` : n.label;
26673
27912
  }
26674
27913
  function strideBadge(n, fontFamily) {
26675
27914
  const letters = n.stride.categories.join("");
26676
- const charW = 7;
26677
- const bw = letters.length * charW + 10;
27915
+ const charW2 = 7;
27916
+ const bw = letters.length * charW2 + 10;
26678
27917
  const bh = 15;
26679
27918
  const bx = n.cx - bw / 2;
26680
27919
  const by = n.y - bh - 4;
@@ -26703,7 +27942,7 @@ function strideBadge(n, fontFamily) {
26703
27942
  }
26704
27943
  function renderFlow(f, fontFamily) {
26705
27944
  const pts = f.points;
26706
- const d = "M " + pts.map((p) => `${round8(p.x)} ${round8(p.y)}`).join(" L ");
27945
+ const d = "M " + pts.map((p) => `${round10(p.x)} ${round10(p.y)}`).join(" L ");
26707
27946
  const crossing = f.crossesBoundary ? "true" : void 0;
26708
27947
  const marker = f.crossesBoundary ? "url(#sx-tm-mk-x)" : "url(#sx-tm-mk)";
26709
27948
  const labelHaloW = f.label.length * 5.4 + 8;
@@ -26771,10 +28010,10 @@ function arrowMarker2(id, cls, crossing) {
26771
28010
  ]
26772
28011
  );
26773
28012
  }
26774
- function round8(n) {
28013
+ function round10(n) {
26775
28014
  return Math.round(n * 100) / 100;
26776
28015
  }
26777
- function summarise11(layout) {
28016
+ function summarise12(layout) {
26778
28017
  const a = layout.analysis;
26779
28018
  const counts = {
26780
28019
  external: layout.nodes.filter((n) => n.kind === "external").length,
@@ -26986,7 +28225,7 @@ function parseWeldSpec(raw) {
26986
28225
  function emptyJoint() {
26987
28226
  return { around: false, field: false };
26988
28227
  }
26989
- function stripComment13(line2) {
28228
+ function stripComment14(line2) {
26990
28229
  const hash = line2.indexOf("#");
26991
28230
  if (hash >= 0 && (line2.slice(0, hash).match(/["'“‘]/g)?.length ?? 0) % 2 === 0) {
26992
28231
  return line2.slice(0, hash);
@@ -27015,7 +28254,7 @@ function parseJointBody(body, joint) {
27015
28254
  }
27016
28255
  function parseWelding(text2) {
27017
28256
  const ast = { type: "welding", standard: "aws", joints: [], warnings: [] };
27018
- const src = text2.split(/\r?\n/).map(stripComment13).join("\n");
28257
+ const src = text2.split(/\r?\n/).map(stripComment14).join("\n");
27019
28258
  const headEnd = src.search(/\bjoint\b/i);
27020
28259
  const headerScope = headEnd >= 0 ? src.slice(0, headEnd) : src;
27021
28260
  const header = headerScope.match(/welding\b([^\n]*)/i);
@@ -27083,9 +28322,9 @@ function layoutWelding(ast) {
27083
28322
  var W = 18;
27084
28323
  var H = 15;
27085
28324
  function pl(points, cls) {
27086
- return polygon({ points: points.map((p) => `${round9(p[0])},${round9(p[1])}`).join(" "), class: cls, fill: "none" });
28325
+ return polygon({ points: points.map((p) => `${round11(p[0])},${round11(p[1])}`).join(" "), class: cls, fill: "none" });
27087
28326
  }
27088
- function round9(n) {
28327
+ function round11(n) {
27089
28328
  return Math.round(n * 100) / 100;
27090
28329
  }
27091
28330
  function weldGlyph(type, cx, y, dir, cls) {
@@ -27101,7 +28340,7 @@ function weldGlyph(type, cx, y, dir, cls) {
27101
28340
  line({ x1: cx + 3, y1: y, x2: cx + 3, y2: yb, class: cls })
27102
28341
  ];
27103
28342
  case "vgroove":
27104
- return [path({ d: `M ${round9(x0)} ${round9(yb)} L ${round9(cx)} ${round9(y)} L ${round9(x1)} ${round9(yb)}`, class: cls, fill: "none" })];
28343
+ return [path({ d: `M ${round11(x0)} ${round11(yb)} L ${round11(cx)} ${round11(y)} L ${round11(x1)} ${round11(yb)}`, class: cls, fill: "none" })];
27105
28344
  case "bevel":
27106
28345
  return [
27107
28346
  line({ x1: cx - 4, y1: y, x2: cx - 4, y2: yb, class: cls }),
@@ -27110,7 +28349,7 @@ function weldGlyph(type, cx, y, dir, cls) {
27110
28349
  case "ugroove":
27111
28350
  return [
27112
28351
  path({
27113
- d: `M ${round9(x0)} ${round9(y)} L ${round9(x0)} ${round9(y + dir * H * 0.45)} Q ${round9(x0)} ${round9(yb)} ${round9(cx)} ${round9(yb)} Q ${round9(x1)} ${round9(yb)} ${round9(x1)} ${round9(y + dir * H * 0.45)} L ${round9(x1)} ${round9(y)}`,
28352
+ d: `M ${round11(x0)} ${round11(y)} L ${round11(x0)} ${round11(y + dir * H * 0.45)} Q ${round11(x0)} ${round11(yb)} ${round11(cx)} ${round11(yb)} Q ${round11(x1)} ${round11(yb)} ${round11(x1)} ${round11(y + dir * H * 0.45)} L ${round11(x1)} ${round11(y)}`,
27114
28353
  class: cls,
27115
28354
  fill: "none"
27116
28355
  })
@@ -27118,20 +28357,20 @@ function weldGlyph(type, cx, y, dir, cls) {
27118
28357
  case "jgroove":
27119
28358
  return [
27120
28359
  path({
27121
- d: `M ${round9(cx - 4)} ${round9(y)} L ${round9(cx - 4)} ${round9(y + dir * H * 0.45)} Q ${round9(cx - 4)} ${round9(yb)} ${round9(x1)} ${round9(yb)}`,
28360
+ d: `M ${round11(cx - 4)} ${round11(y)} L ${round11(cx - 4)} ${round11(y + dir * H * 0.45)} Q ${round11(cx - 4)} ${round11(yb)} ${round11(x1)} ${round11(yb)}`,
27122
28361
  class: cls,
27123
28362
  fill: "none"
27124
28363
  })
27125
28364
  ];
27126
28365
  case "flarev":
27127
28366
  return [
27128
- path({ d: `M ${round9(x0)} ${round9(yb)} Q ${round9(cx - 2)} ${round9(yb)} ${round9(cx)} ${round9(y)}`, class: cls, fill: "none" }),
27129
- path({ d: `M ${round9(x1)} ${round9(yb)} Q ${round9(cx + 2)} ${round9(yb)} ${round9(cx)} ${round9(y)}`, class: cls, fill: "none" })
28367
+ path({ d: `M ${round11(x0)} ${round11(yb)} Q ${round11(cx - 2)} ${round11(yb)} ${round11(cx)} ${round11(y)}`, class: cls, fill: "none" }),
28368
+ path({ d: `M ${round11(x1)} ${round11(yb)} Q ${round11(cx + 2)} ${round11(yb)} ${round11(cx)} ${round11(y)}`, class: cls, fill: "none" })
27130
28369
  ];
27131
28370
  case "flarebevel":
27132
28371
  return [
27133
28372
  line({ x1: cx - 4, y1: y, x2: cx - 4, y2: yb, class: cls }),
27134
- path({ d: `M ${round9(cx - 4)} ${round9(y)} Q ${round9(x1)} ${round9(y)} ${round9(x1)} ${round9(yb)}`, class: cls, fill: "none" })
28373
+ path({ d: `M ${round11(cx - 4)} ${round11(y)} Q ${round11(x1)} ${round11(y)} ${round11(x1)} ${round11(yb)}`, class: cls, fill: "none" })
27135
28374
  ];
27136
28375
  case "plug":
27137
28376
  case "slot": {
@@ -27149,12 +28388,12 @@ function weldGlyph(type, cx, y, dir, cls) {
27149
28388
  case "backing": {
27150
28389
  const rr = W * 0.45;
27151
28390
  const sweep = dir > 0 ? 1 : 0;
27152
- return [path({ d: `M ${round9(cx - rr)} ${round9(y)} A ${round9(rr)} ${round9(rr)} 0 0 ${sweep} ${round9(cx + rr)} ${round9(y)}`, class: cls, fill: "none" })];
28391
+ return [path({ d: `M ${round11(cx - rr)} ${round11(y)} A ${round11(rr)} ${round11(rr)} 0 0 ${sweep} ${round11(cx + rr)} ${round11(y)}`, class: cls, fill: "none" })];
27153
28392
  }
27154
28393
  case "surfacing": {
27155
28394
  const r7 = W / 4;
27156
28395
  const yy = y + dir * 3;
27157
- const bump = (off) => path({ d: `M ${round9(cx - W / 2)} ${round9(off)} a ${round9(r7)} ${round9(r7)} 0 0 ${dir > 0 ? 1 : 0} ${round9(W / 2)} 0 a ${round9(r7)} ${round9(r7)} 0 0 ${dir > 0 ? 1 : 0} ${round9(W / 2)} 0`, class: cls, fill: "none" });
28396
+ const bump = (off) => path({ d: `M ${round11(cx - W / 2)} ${round11(off)} a ${round11(r7)} ${round11(r7)} 0 0 ${dir > 0 ? 1 : 0} ${round11(W / 2)} 0 a ${round11(r7)} ${round11(r7)} 0 0 ${dir > 0 ? 1 : 0} ${round11(W / 2)} 0`, class: cls, fill: "none" });
27158
28397
  return [bump(y), bump(yy)];
27159
28398
  }
27160
28399
  case "edge":
@@ -27172,7 +28411,7 @@ function contourGlyph(contour, cx, y, dir, cls) {
27172
28411
  }
27173
28412
  const bulge = contour === "convex" ? dir : -dir;
27174
28413
  return path({
27175
- d: `M ${round9(cx - half)} ${round9(yy)} Q ${round9(cx)} ${round9(yy + bulge * 5)} ${round9(cx + half)} ${round9(yy)}`,
28414
+ d: `M ${round11(cx - half)} ${round11(yy)} Q ${round11(cx)} ${round11(yy + bulge * 5)} ${round11(cx + half)} ${round11(yy)}`,
27176
28415
  class: cls,
27177
28416
  fill: "none"
27178
28417
  });
@@ -31017,7 +32256,7 @@ var ErdParseError = class extends Error {
31017
32256
  }
31018
32257
  lineNumber;
31019
32258
  };
31020
- function stripComment14(s) {
32259
+ function stripComment15(s) {
31021
32260
  let out = "";
31022
32261
  let inQuote = false;
31023
32262
  for (let i = 0; i < s.length; i++) {
@@ -31071,7 +32310,7 @@ function parseCardToken(raw, side) {
31071
32310
  }
31072
32311
  function lex(text2) {
31073
32312
  return text2.split(/\r?\n/).map((raw, i) => ({
31074
- text: stripComment14(raw).trim(),
32313
+ text: stripComment15(raw).trim(),
31075
32314
  lineNumber: i + 1
31076
32315
  })).filter((l) => l.text.length > 0);
31077
32316
  }
@@ -31449,8 +32688,8 @@ var ERD_CONST = {
31449
32688
  EDGE_BEND_STAGGER: 10
31450
32689
  };
31451
32690
  function measureEntity(ent) {
31452
- const C2 = ERD_CONST;
31453
- const headerWidth = C2.ENTITY_PADDING_X * 2 + ent.name.length * C2.CHAR_W_HEADER;
32691
+ const C3 = ERD_CONST;
32692
+ const headerWidth = C3.ENTITY_PADDING_X * 2 + ent.name.length * C3.CHAR_W_HEADER;
31454
32693
  let widest = headerWidth;
31455
32694
  const rows = [];
31456
32695
  for (let i = 0; i < ent.attributes.length; i++) {
@@ -31458,14 +32697,14 @@ function measureEntity(ent) {
31458
32697
  const namePart = a.name;
31459
32698
  const typePart = a.type ?? "";
31460
32699
  const markerCount = (a.pk ? 1 : 0) + (a.fk ? 1 : 0) + (a.uk ? 1 : 0) + (a.notNull && !a.pk ? 1 : 0);
31461
- const markerWidth = markerCount * (C2.CHAR_W_MARKER * 2.4 + 4);
31462
- const w = C2.ENTITY_PADDING_X * 2 + namePart.length * C2.CHAR_W_ROW + (typePart ? C2.TYPE_GAP + typePart.length * C2.CHAR_W_ROW : 0) + markerWidth;
32700
+ const markerWidth = markerCount * (C3.CHAR_W_MARKER * 2.4 + 4);
32701
+ const w = C3.ENTITY_PADDING_X * 2 + namePart.length * C3.CHAR_W_ROW + (typePart ? C3.TYPE_GAP + typePart.length * C3.CHAR_W_ROW : 0) + markerWidth;
31463
32702
  if (w > widest) widest = w;
31464
- const yCenter = C2.HEADER_HEIGHT + i * C2.ROW_HEIGHT + C2.ROW_HEIGHT / 2;
32703
+ const yCenter = C3.HEADER_HEIGHT + i * C3.ROW_HEIGHT + C3.ROW_HEIGHT / 2;
31465
32704
  rows.push({ attribute: a, yCenter });
31466
32705
  }
31467
- const width = Math.max(widest, C2.ENTITY_MIN_WIDTH);
31468
- const height = C2.HEADER_HEIGHT + ent.attributes.length * C2.ROW_HEIGHT + C2.ROW_PAD_Y;
32706
+ const width = Math.max(widest, C3.ENTITY_MIN_WIDTH);
32707
+ const height = C3.HEADER_HEIGHT + ent.attributes.length * C3.ROW_HEIGHT + C3.ROW_PAD_Y;
31469
32708
  return { width, height, rows };
31470
32709
  }
31471
32710
  function buildColumnAssignment(ast) {
@@ -31562,15 +32801,15 @@ function reorderByBarycenter(layerToEnts, layers, refs) {
31562
32801
  sweep("down");
31563
32802
  }
31564
32803
  function assignYCoordinates(orderedLayers, measured, neighbors) {
31565
- const C2 = ERD_CONST;
32804
+ const C3 = ERD_CONST;
31566
32805
  const placed = /* @__PURE__ */ new Map();
31567
32806
  for (const ls of orderedLayers) {
31568
- let prevBottom = C2.PADDING - C2.ROW_GAP;
32807
+ let prevBottom = C3.PADDING - C3.ROW_GAP;
31569
32808
  for (let i = 0; i < ls.ids.length; i++) {
31570
32809
  const id = ls.ids[i];
31571
32810
  const m = measured.get(id);
31572
32811
  const ns = neighbors.get(id);
31573
- let target = C2.PADDING;
32812
+ let target = C3.PADDING;
31574
32813
  if (ns) {
31575
32814
  const placedNeighborCenters = [];
31576
32815
  for (const n of ns) {
@@ -31584,7 +32823,7 @@ function assignYCoordinates(orderedLayers, measured, neighbors) {
31584
32823
  target = med - m.height / 2;
31585
32824
  }
31586
32825
  }
31587
- const y = Math.max(target, prevBottom + C2.ROW_GAP);
32826
+ const y = Math.max(target, prevBottom + C3.ROW_GAP);
31588
32827
  placed.set(id, {
31589
32828
  id,
31590
32829
  y,
@@ -31597,7 +32836,7 @@ function assignYCoordinates(orderedLayers, measured, neighbors) {
31597
32836
  }
31598
32837
  for (let li = orderedLayers.length - 1; li >= 0; li--) {
31599
32838
  const ls = orderedLayers[li];
31600
- let prevBottom = C2.PADDING - C2.ROW_GAP;
32839
+ let prevBottom = C3.PADDING - C3.ROW_GAP;
31601
32840
  for (let i = 0; i < ls.ids.length; i++) {
31602
32841
  const id = ls.ids[i];
31603
32842
  const slot = placed.get(id);
@@ -31616,7 +32855,7 @@ function assignYCoordinates(orderedLayers, measured, neighbors) {
31616
32855
  target = med - slot.height / 2;
31617
32856
  }
31618
32857
  }
31619
- const lower = prevBottom + C2.ROW_GAP;
32858
+ const lower = prevBottom + C3.ROW_GAP;
31620
32859
  const newY = Math.max(lower, Math.min(slot.y, target));
31621
32860
  slot.y = newY;
31622
32861
  prevBottom = newY + slot.height;
@@ -31627,7 +32866,7 @@ function assignYCoordinates(orderedLayers, measured, neighbors) {
31627
32866
  return out;
31628
32867
  }
31629
32868
  function layoutErd(ast) {
31630
- const C2 = ERD_CONST;
32869
+ const C3 = ERD_CONST;
31631
32870
  const isLR = ast.direction === "LR";
31632
32871
  const measured = /* @__PURE__ */ new Map();
31633
32872
  for (const e of ast.entities) {
@@ -31675,30 +32914,30 @@ function layoutErd(ast) {
31675
32914
  const orderingCoord = assignYCoordinates(orderedLayers, measureForOrdering, neighbors);
31676
32915
  const placed = [];
31677
32916
  if (isLR) {
31678
- let cursorX = C2.PADDING;
32917
+ let cursorX = C3.PADDING;
31679
32918
  for (const ls of layerSizes) {
31680
32919
  for (const id of ls.ids) {
31681
32920
  const m = measured.get(id);
31682
32921
  const x = cursorX + (ls.maxWidth - m.width) / 2;
31683
- const y = orderingCoord.get(id) ?? C2.PADDING;
32922
+ const y = orderingCoord.get(id) ?? C3.PADDING;
31684
32923
  placed.push({
31685
32924
  entity: m.ent,
31686
32925
  x,
31687
32926
  y,
31688
32927
  width: m.width,
31689
32928
  height: m.height,
31690
- headerHeight: C2.HEADER_HEIGHT,
32929
+ headerHeight: C3.HEADER_HEIGHT,
31691
32930
  rows: m.rows
31692
32931
  });
31693
32932
  }
31694
- cursorX += ls.maxWidth + C2.COL_GAP;
32933
+ cursorX += ls.maxWidth + C3.COL_GAP;
31695
32934
  }
31696
32935
  } else {
31697
- let cursorY = C2.PADDING;
32936
+ let cursorY = C3.PADDING;
31698
32937
  for (const ls of layerSizes) {
31699
32938
  for (const id of ls.ids) {
31700
32939
  const m = measured.get(id);
31701
- const x = orderingCoord.get(id) ?? C2.PADDING;
32940
+ const x = orderingCoord.get(id) ?? C3.PADDING;
31702
32941
  const y = cursorY + (ls.maxHeight - m.height) / 2;
31703
32942
  placed.push({
31704
32943
  entity: m.ent,
@@ -31706,11 +32945,11 @@ function layoutErd(ast) {
31706
32945
  y,
31707
32946
  width: m.width,
31708
32947
  height: m.height,
31709
- headerHeight: C2.HEADER_HEIGHT,
32948
+ headerHeight: C3.HEADER_HEIGHT,
31710
32949
  rows: m.rows
31711
32950
  });
31712
32951
  }
31713
- cursorY += ls.maxHeight + C2.ROW_GAP;
32952
+ cursorY += ls.maxHeight + C3.ROW_GAP;
31714
32953
  }
31715
32954
  }
31716
32955
  let maxX = 0;
@@ -31719,8 +32958,8 @@ function layoutErd(ast) {
31719
32958
  if (e.x + e.width > maxX) maxX = e.x + e.width;
31720
32959
  if (e.y + e.height > maxY) maxY = e.y + e.height;
31721
32960
  }
31722
- const width = maxX + C2.PADDING;
31723
- const height = maxY + C2.PADDING;
32961
+ const width = maxX + C3.PADDING;
32962
+ const height = maxY + C3.PADDING;
31724
32963
  const placedById = new Map(placed.map((p) => [p.entity.id, p]));
31725
32964
  const edges = [];
31726
32965
  const bendBucketUses = /* @__PURE__ */ new Map();
@@ -31757,7 +32996,7 @@ function rowYByColumn(e, col) {
31757
32996
  return e.y + e.height / 2;
31758
32997
  }
31759
32998
  function routeOrthogonal(a, b, fromCol, toCol, bendBucketUses) {
31760
- const C2 = ERD_CONST;
32999
+ const C3 = ERD_CONST;
31761
33000
  const aCenterX = a.x + a.width / 2;
31762
33001
  const bCenterX = b.x + b.width / 2;
31763
33002
  const aCenterY = a.y + a.height / 2;
@@ -31781,14 +33020,14 @@ function routeOrthogonal(a, b, fromCol, toCol, bendBucketUses) {
31781
33020
  const useIdx = bendBucketUses.get(bucketKey) ?? 0;
31782
33021
  bendBucketUses.set(bucketKey, useIdx + 1);
31783
33022
  const sign = useIdx % 2 === 0 ? 1 : -1;
31784
- const stagger = Math.ceil(useIdx / 2) * C2.EDGE_BEND_STAGGER * sign;
33023
+ const stagger = Math.ceil(useIdx / 2) * C3.EDGE_BEND_STAGGER * sign;
31785
33024
  const midX = baseMidX + stagger;
31786
33025
  const path2 = `M ${aAnchor.x} ${aAnchor.y} L ${midX} ${aAnchor.y} L ${midX} ${bAnchor.y} L ${bAnchor.x} ${bAnchor.y}`;
31787
33026
  return {
31788
33027
  path: path2,
31789
33028
  fromAnchor: { x: aAnchor.x, y: aAnchor.y, side: aSide },
31790
33029
  toAnchor: { x: bAnchor.x, y: bAnchor.y, side: bSide },
31791
- labelAt: { x: midX, y: (aAnchor.y + bAnchor.y) / 2 - C2.LABEL_OFFSET }
33030
+ labelAt: { x: midX, y: (aAnchor.y + bAnchor.y) / 2 - C3.LABEL_OFFSET }
31792
33031
  };
31793
33032
  } else {
31794
33033
  const baseMidY = (aAnchor.y + bAnchor.y) / 2;
@@ -31796,14 +33035,14 @@ function routeOrthogonal(a, b, fromCol, toCol, bendBucketUses) {
31796
33035
  const useIdx = bendBucketUses.get(bucketKey) ?? 0;
31797
33036
  bendBucketUses.set(bucketKey, useIdx + 1);
31798
33037
  const sign = useIdx % 2 === 0 ? 1 : -1;
31799
- const stagger = Math.ceil(useIdx / 2) * C2.EDGE_BEND_STAGGER * sign;
33038
+ const stagger = Math.ceil(useIdx / 2) * C3.EDGE_BEND_STAGGER * sign;
31800
33039
  const midY = baseMidY + stagger;
31801
33040
  const path2 = `M ${aAnchor.x} ${aAnchor.y} L ${aAnchor.x} ${midY} L ${bAnchor.x} ${midY} L ${bAnchor.x} ${bAnchor.y}`;
31802
33041
  return {
31803
33042
  path: path2,
31804
33043
  fromAnchor: { x: aAnchor.x, y: aAnchor.y, side: aSide },
31805
33044
  toAnchor: { x: bAnchor.x, y: bAnchor.y, side: bSide },
31806
- labelAt: { x: (aAnchor.x + bAnchor.x) / 2, y: midY - C2.LABEL_OFFSET }
33045
+ labelAt: { x: (aAnchor.x + bAnchor.x) / 2, y: midY - C3.LABEL_OFFSET }
31807
33046
  };
31808
33047
  }
31809
33048
  }
@@ -31854,7 +33093,7 @@ function attrMarkers(a) {
31854
33093
  return out;
31855
33094
  }
31856
33095
  function renderEntity(e) {
31857
- const C2 = ERD_CONST;
33096
+ const C3 = ERD_CONST;
31858
33097
  const body = [];
31859
33098
  body.push(
31860
33099
  rect({
@@ -31890,9 +33129,9 @@ function renderEntity(e) {
31890
33129
  body.push(
31891
33130
  line({
31892
33131
  x1: e.x,
31893
- y1: e.y + e.headerHeight + i * C2.ROW_HEIGHT,
33132
+ y1: e.y + e.headerHeight + i * C3.ROW_HEIGHT,
31894
33133
  x2: e.x + e.width,
31895
- y2: e.y + e.headerHeight + i * C2.ROW_HEIGHT,
33134
+ y2: e.y + e.headerHeight + i * C3.ROW_HEIGHT,
31896
33135
  class: "lt-erd-row-divider"
31897
33136
  })
31898
33137
  );
@@ -31900,7 +33139,7 @@ function renderEntity(e) {
31900
33139
  body.push(
31901
33140
  text(
31902
33141
  {
31903
- x: e.x + C2.ENTITY_PADDING_X,
33142
+ x: e.x + C3.ENTITY_PADDING_X,
31904
33143
  y: cy,
31905
33144
  class: a.pk ? "lt-erd-attr-name-pk" : "lt-erd-attr-name"
31906
33145
  },
@@ -31911,7 +33150,7 @@ function renderEntity(e) {
31911
33150
  const markerW = 26;
31912
33151
  const markerGap = 4;
31913
33152
  const markersBlockW = markers6.length * markerW + (markers6.length - 1) * markerGap;
31914
- const markersStartX = e.x + e.width - C2.ENTITY_PADDING_X - markersBlockW;
33153
+ const markersStartX = e.x + e.width - C3.ENTITY_PADDING_X - markersBlockW;
31915
33154
  if (a.type) {
31916
33155
  body.push(
31917
33156
  text(
@@ -31959,25 +33198,25 @@ function renderEntity(e) {
31959
33198
  );
31960
33199
  }
31961
33200
  function renderGlyph2(ax, ay, dirX, dirY, card) {
31962
- const C2 = ERD_CONST;
33201
+ const C3 = ERD_CONST;
31963
33202
  const px = -dirY;
31964
33203
  const py = dirX;
31965
- const barDist = C2.GLYPH_OFFSET;
33204
+ const barDist = C3.GLYPH_OFFSET;
31966
33205
  const barX = ax + dirX * barDist;
31967
33206
  const barY = ay + dirY * barDist;
31968
33207
  const footTipX = ax;
31969
33208
  const footTipY = ay;
31970
- const footBaseX = ax + dirX * C2.GLYPH_FOOT_LEN;
31971
- const footBaseY = ay + dirY * C2.GLYPH_FOOT_LEN;
33209
+ const footBaseX = ax + dirX * C3.GLYPH_FOOT_LEN;
33210
+ const footBaseY = ay + dirY * C3.GLYPH_FOOT_LEN;
31972
33211
  const parts = [];
31973
33212
  switch (card) {
31974
33213
  case "one-mandatory": {
31975
33214
  parts.push(
31976
33215
  line({
31977
- x1: barX + px * C2.GLYPH_BAR_HALF,
31978
- y1: barY + py * C2.GLYPH_BAR_HALF,
31979
- x2: barX - px * C2.GLYPH_BAR_HALF,
31980
- y2: barY - py * C2.GLYPH_BAR_HALF,
33216
+ x1: barX + px * C3.GLYPH_BAR_HALF,
33217
+ y1: barY + py * C3.GLYPH_BAR_HALF,
33218
+ x2: barX - px * C3.GLYPH_BAR_HALF,
33219
+ y2: barY - py * C3.GLYPH_BAR_HALF,
31981
33220
  class: "lt-erd-glyph"
31982
33221
  })
31983
33222
  );
@@ -31988,7 +33227,7 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
31988
33227
  circle({
31989
33228
  cx: barX,
31990
33229
  cy: barY,
31991
- r: C2.GLYPH_CIRCLE_R,
33230
+ r: C3.GLYPH_CIRCLE_R,
31992
33231
  class: "lt-erd-glyph-circle"
31993
33232
  })
31994
33233
  );
@@ -31997,10 +33236,10 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
31997
33236
  case "many-mandatory": {
31998
33237
  parts.push(
31999
33238
  line({
32000
- x1: barX + px * C2.GLYPH_BAR_HALF,
32001
- y1: barY + py * C2.GLYPH_BAR_HALF,
32002
- x2: barX - px * C2.GLYPH_BAR_HALF,
32003
- y2: barY - py * C2.GLYPH_BAR_HALF,
33239
+ x1: barX + px * C3.GLYPH_BAR_HALF,
33240
+ y1: barY + py * C3.GLYPH_BAR_HALF,
33241
+ x2: barX - px * C3.GLYPH_BAR_HALF,
33242
+ y2: barY - py * C3.GLYPH_BAR_HALF,
32004
33243
  class: "lt-erd-glyph"
32005
33244
  })
32006
33245
  );
@@ -32011,8 +33250,8 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
32011
33250
  line({
32012
33251
  x1: footBaseX,
32013
33252
  y1: footBaseY,
32014
- x2: footTipX + px * C2.GLYPH_BAR_HALF,
32015
- y2: footTipY + py * C2.GLYPH_BAR_HALF,
33253
+ x2: footTipX + px * C3.GLYPH_BAR_HALF,
33254
+ y2: footTipY + py * C3.GLYPH_BAR_HALF,
32016
33255
  class: "lt-erd-glyph"
32017
33256
  })
32018
33257
  );
@@ -32020,8 +33259,8 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
32020
33259
  line({
32021
33260
  x1: footBaseX,
32022
33261
  y1: footBaseY,
32023
- x2: footTipX - px * C2.GLYPH_BAR_HALF,
32024
- y2: footTipY - py * C2.GLYPH_BAR_HALF,
33262
+ x2: footTipX - px * C3.GLYPH_BAR_HALF,
33263
+ y2: footTipY - py * C3.GLYPH_BAR_HALF,
32025
33264
  class: "lt-erd-glyph"
32026
33265
  })
32027
33266
  );
@@ -32032,7 +33271,7 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
32032
33271
  circle({
32033
33272
  cx: barX,
32034
33273
  cy: barY,
32035
- r: C2.GLYPH_CIRCLE_R,
33274
+ r: C3.GLYPH_CIRCLE_R,
32036
33275
  class: "lt-erd-glyph-circle"
32037
33276
  })
32038
33277
  );
@@ -32043,8 +33282,8 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
32043
33282
  line({
32044
33283
  x1: footBaseX,
32045
33284
  y1: footBaseY,
32046
- x2: footTipX + px * C2.GLYPH_BAR_HALF,
32047
- y2: footTipY + py * C2.GLYPH_BAR_HALF,
33285
+ x2: footTipX + px * C3.GLYPH_BAR_HALF,
33286
+ y2: footTipY + py * C3.GLYPH_BAR_HALF,
32048
33287
  class: "lt-erd-glyph"
32049
33288
  })
32050
33289
  );
@@ -32052,8 +33291,8 @@ function renderGlyph2(ax, ay, dirX, dirY, card) {
32052
33291
  line({
32053
33292
  x1: footBaseX,
32054
33293
  y1: footBaseY,
32055
- x2: footTipX - px * C2.GLYPH_BAR_HALF,
32056
- y2: footTipY - py * C2.GLYPH_BAR_HALF,
33294
+ x2: footTipX - px * C3.GLYPH_BAR_HALF,
33295
+ y2: footTipY - py * C3.GLYPH_BAR_HALF,
32057
33296
  class: "lt-erd-glyph"
32058
33297
  })
32059
33298
  );
@@ -32198,7 +33437,7 @@ var BreadboardParseError = class extends Error {
32198
33437
  }
32199
33438
  lineNumber;
32200
33439
  };
32201
- function stripComment15(s) {
33440
+ function stripComment16(s) {
32202
33441
  let out = "";
32203
33442
  let inQuote = false;
32204
33443
  for (let i = 0; i < s.length; i++) {
@@ -32219,7 +33458,7 @@ function unquote8(v) {
32219
33458
  }
32220
33459
  function lex2(text2) {
32221
33460
  return text2.split(/\r?\n/).map((raw, i) => ({
32222
- text: stripComment15(raw).trimEnd().replace(/^\s+/, ""),
33461
+ text: stripComment16(raw).trimEnd().replace(/^\s+/, ""),
32223
33462
  lineNumber: i + 1
32224
33463
  })).filter((l) => l.text.length > 0);
32225
33464
  }
@@ -34160,7 +35399,7 @@ function layerPool(ast, pool, colByObj) {
34160
35399
  }
34161
35400
  }
34162
35401
  }
34163
- function fmt6(n) {
35402
+ function fmt7(n) {
34164
35403
  return (Math.round(n * 100) / 100).toString();
34165
35404
  }
34166
35405
  function routeSequenceFlow(f, objCenter, objById) {
@@ -34181,11 +35420,11 @@ function routeSequenceFlow(f, objCenter, objById) {
34181
35420
  let labelAnchor;
34182
35421
  if (Math.abs(dx) >= Math.abs(dy)) {
34183
35422
  const midX = (from.x + to.x) / 2;
34184
- path2 = `M ${fmt6(from.x)} ${fmt6(from.y)} L ${fmt6(midX)} ${fmt6(from.y)} L ${fmt6(midX)} ${fmt6(to.y)} L ${fmt6(to.x)} ${fmt6(to.y)}`;
35423
+ path2 = `M ${fmt7(from.x)} ${fmt7(from.y)} L ${fmt7(midX)} ${fmt7(from.y)} L ${fmt7(midX)} ${fmt7(to.y)} L ${fmt7(to.x)} ${fmt7(to.y)}`;
34185
35424
  labelAnchor = { x: midX, y: (from.y + to.y) / 2 - 6 };
34186
35425
  } else {
34187
35426
  const midY = (from.y + to.y) / 2;
34188
- path2 = `M ${fmt6(from.x)} ${fmt6(from.y)} L ${fmt6(from.x)} ${fmt6(midY)} L ${fmt6(to.x)} ${fmt6(midY)} L ${fmt6(to.x)} ${fmt6(to.y)}`;
35427
+ path2 = `M ${fmt7(from.x)} ${fmt7(from.y)} L ${fmt7(from.x)} ${fmt7(midY)} L ${fmt7(to.x)} ${fmt7(midY)} L ${fmt7(to.x)} ${fmt7(to.y)}`;
34189
35428
  labelAnchor = { x: (from.x + to.x) / 2, y: midY - 6 };
34190
35429
  }
34191
35430
  return { flow: f, path: path2, labelAnchor };
@@ -34208,7 +35447,7 @@ function routeMessageFlow(f, objCenter, poolByLabel) {
34208
35447
  const A = endpoint(f.from);
34209
35448
  const B = endpoint(f.to);
34210
35449
  const midY = (A.y + B.y) / 2;
34211
- const path2 = `M ${fmt6(A.x)} ${fmt6(A.y)} L ${fmt6(A.x)} ${fmt6(midY)} L ${fmt6(B.x)} ${fmt6(midY)} L ${fmt6(B.x)} ${fmt6(B.y)}`;
35450
+ const path2 = `M ${fmt7(A.x)} ${fmt7(A.y)} L ${fmt7(A.x)} ${fmt7(midY)} L ${fmt7(B.x)} ${fmt7(midY)} L ${fmt7(B.x)} ${fmt7(B.y)}`;
34212
35451
  return { flow: f, path: path2, labelAnchor: { x: (A.x + B.x) / 2, y: midY - 6 } };
34213
35452
  }
34214
35453
 
@@ -41158,6 +42397,7 @@ var plugins = [
41158
42397
  eventtree,
41159
42398
  fmea,
41160
42399
  rbd,
42400
+ comparison,
41161
42401
  causalloop,
41162
42402
  markov,
41163
42403
  gitgraph,
@@ -41314,6 +42554,6 @@ function renderWithPlugin(prepared, plugin, config) {
41314
42554
  return plugin.render(prepared, renderConfig);
41315
42555
  }
41316
42556
 
41317
- export { FLOORPLAN_SYMBOLS, GEOMETRY, bowtie2 as bowtie, causalloop, decisiontree, drawDeviceIcon, epc, eventtree, faulttree, fmea, gitgraph, iconSize, idef0, markov, network, parse, parseResult, pert, petri, pid, prisma, rbd, render, renderEquip, renderPreview, renderResult, sequence, state, threatmodel, timeline, umlclass, usecase, welding };
41318
- //# sourceMappingURL=chunk-3K4WCRVI.js.map
41319
- //# sourceMappingURL=chunk-3K4WCRVI.js.map
42557
+ export { FLOORPLAN_SYMBOLS, GEOMETRY, bowtie2 as bowtie, causalloop, comparison, decisiontree, drawDeviceIcon, epc, eventtree, faulttree, fmea, gitgraph, iconSize, idef0, markov, network, parse, parseResult, pert, petri, pid, prisma, rbd, render, renderEquip, renderPreview, renderResult, sequence, state, threatmodel, timeline, umlclass, usecase, welding };
42558
+ //# sourceMappingURL=chunk-4QLIFOKH.js.map
42559
+ //# sourceMappingURL=chunk-4QLIFOKH.js.map