@diagrammo/dgmo 0.30.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +21 -3
  2. package/dist/advanced.cjs +560 -269
  3. package/dist/advanced.d.cts +27 -2
  4. package/dist/advanced.d.ts +27 -2
  5. package/dist/advanced.js +559 -269
  6. package/dist/auto.cjs +558 -270
  7. package/dist/auto.js +93 -93
  8. package/dist/auto.mjs +558 -270
  9. package/dist/cli.cjs +144 -143
  10. package/dist/index.cjs +557 -269
  11. package/dist/index.js +557 -269
  12. package/package.json +1 -1
  13. package/src/advanced.ts +3 -0
  14. package/src/boxes-and-lines/layout-search.ts +214 -0
  15. package/src/boxes-and-lines/layout.ts +4 -0
  16. package/src/boxes-and-lines/parser.ts +78 -0
  17. package/src/boxes-and-lines/renderer.ts +57 -5
  18. package/src/boxes-and-lines/types.ts +9 -0
  19. package/src/c4/renderer.ts +7 -5
  20. package/src/chart-types.ts +2 -2
  21. package/src/class/renderer.ts +4 -2
  22. package/src/cli-banner.ts +107 -0
  23. package/src/cli.ts +13 -0
  24. package/src/colors.ts +22 -0
  25. package/src/er/renderer.ts +4 -2
  26. package/src/graph/flowchart-renderer.ts +4 -2
  27. package/src/graph/state-renderer.ts +4 -2
  28. package/src/infra/renderer.ts +8 -4
  29. package/src/journey-map/parser.ts +15 -1
  30. package/src/journey-map/renderer.ts +1 -1
  31. package/src/kanban/renderer.ts +1 -1
  32. package/src/map/renderer.ts +27 -14
  33. package/src/mindmap/renderer.ts +5 -3
  34. package/src/org/renderer.ts +67 -120
  35. package/src/palettes/color-utils.ts +7 -2
  36. package/src/pert/renderer.ts +13 -8
  37. package/src/raci/renderer.ts +1 -1
  38. package/src/sitemap/renderer.ts +35 -37
  39. package/src/utils/card.ts +183 -0
  40. package/src/utils/tag-groups.ts +10 -10
  41. package/src/utils/visual-conventions.ts +61 -0
package/dist/auto.mjs CHANGED
@@ -318,7 +318,7 @@ function resolveColorWithDiagnostic(color, line11, diagnostics, palette) {
318
318
  );
319
319
  return void 0;
320
320
  }
321
- var nord, colorNames, RECOGNIZED_COLOR_NAMES, seriesColors;
321
+ var nord, colorNames, RECOGNIZED_COLOR_NAMES, CATEGORICAL_COLOR_ORDER, seriesColors;
322
322
  var init_colors = __esm({
323
323
  "src/colors.ts"() {
324
324
  "use strict";
@@ -376,6 +376,16 @@ var init_colors = __esm({
376
376
  "black",
377
377
  "white"
378
378
  ]);
379
+ CATEGORICAL_COLOR_ORDER = Object.freeze([
380
+ "red",
381
+ "green",
382
+ "blue",
383
+ "yellow",
384
+ "teal",
385
+ "purple",
386
+ "orange",
387
+ "cyan"
388
+ ]);
379
389
  seriesColors = [
380
390
  nord.nord10,
381
391
  // blue
@@ -1229,11 +1239,7 @@ var init_tag_groups = __esm({
1229
1239
  init_diagnostics();
1230
1240
  init_colors();
1231
1241
  AUTO_TAG_COLOR_SENTINEL = "";
1232
- autoTagColorCycle = Object.freeze(
1233
- RECOGNIZED_COLOR_NAMES.filter(
1234
- (n) => n !== "gray" && n !== "black" && n !== "white"
1235
- )
1236
- );
1242
+ autoTagColorCycle = CATEGORICAL_COLOR_ORDER;
1237
1243
  TAG_BLOCK_NOCOLON_RE = /^tag\s+/i;
1238
1244
  VALID_TAG_IDENT_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
1239
1245
  }
@@ -3023,7 +3029,7 @@ function shapeFill(palette, intent, isDark, opts) {
3023
3029
  }
3024
3030
  function getSeriesColors(palette) {
3025
3031
  const c = palette.colors;
3026
- return [c.blue, c.green, c.yellow, c.orange, c.purple, c.red, c.teal, c.cyan];
3032
+ return CATEGORICAL_COLOR_ORDER.map((name) => c[name]);
3027
3033
  }
3028
3034
  function getSegmentColors(palette, count) {
3029
3035
  if (count <= 0) return [];
@@ -3076,6 +3082,7 @@ var POLITICAL_TINT_BANDS;
3076
3082
  var init_color_utils = __esm({
3077
3083
  "src/palettes/color-utils.ts"() {
3078
3084
  "use strict";
3085
+ init_colors();
3079
3086
  POLITICAL_TINT_BANDS = {
3080
3087
  light: [32, 48, 64, 80],
3081
3088
  dark: [44, 58, 72, 86]
@@ -11457,7 +11464,7 @@ var init_chart_types = __esm({
11457
11464
  },
11458
11465
  {
11459
11466
  id: "map",
11460
- description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
11467
+ description: "Geographic map: a value or count per country, state, or region (choropleth); points of interest; routes. Use when categories are real-world places."
11461
11468
  },
11462
11469
  // ── Tier 3 — Specialized analytical charts ────────────────
11463
11470
  {
@@ -11474,7 +11481,7 @@ var init_chart_types = __esm({
11474
11481
  },
11475
11482
  {
11476
11483
  id: "slope",
11477
- description: "Change between two periods"
11484
+ description: "Change for multiple things between exactly two periods"
11478
11485
  },
11479
11486
  {
11480
11487
  id: "sankey",
@@ -18930,6 +18937,7 @@ function parseBoxesAndLines(content, palette) {
18930
18937
  const nodes = [];
18931
18938
  const edges = [];
18932
18939
  const groups = [];
18940
+ const nodePositions = /* @__PURE__ */ new Map();
18933
18941
  const result = {
18934
18942
  type: "boxes-and-lines",
18935
18943
  title: null,
@@ -18963,6 +18971,8 @@ function parseBoxesAndLines(content, palette) {
18963
18971
  }
18964
18972
  const groupStack = [];
18965
18973
  let contentStarted = false;
18974
+ let inLayoutBlock = false;
18975
+ const LAYOUT_ENTRY_RE = /^(.+?):\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*$/;
18966
18976
  let currentTagGroup = null;
18967
18977
  const metaAliasMap = /* @__PURE__ */ new Map();
18968
18978
  const nameAliasMap = /* @__PURE__ */ new Map();
@@ -19164,6 +19174,42 @@ function parseBoxesAndLines(content, palette) {
19164
19174
  if (currentTagGroup && indent === 0) {
19165
19175
  currentTagGroup = null;
19166
19176
  }
19177
+ if (!inLayoutBlock && indent === 0 && trimmed === "layout") {
19178
+ let isBlock = false;
19179
+ for (let j = i + 1; j < lines.length; j++) {
19180
+ const peek = lines[j];
19181
+ if (!peek.trim()) continue;
19182
+ isBlock = measureIndent2(peek) > 0 && LAYOUT_ENTRY_RE.test(peek.trim());
19183
+ break;
19184
+ }
19185
+ if (isBlock) {
19186
+ flushDescription();
19187
+ closeGroupsToIndent(0);
19188
+ inLayoutBlock = true;
19189
+ continue;
19190
+ }
19191
+ }
19192
+ if (inLayoutBlock) {
19193
+ if (indent > 0) {
19194
+ const lm = trimmed.match(LAYOUT_ENTRY_RE);
19195
+ if (lm) {
19196
+ nodePositions.set(lm[1].trim(), {
19197
+ x: Number(lm[2]),
19198
+ y: Number(lm[3])
19199
+ });
19200
+ } else {
19201
+ result.diagnostics.push(
19202
+ makeDgmoError(
19203
+ lineNum,
19204
+ `Invalid layout entry "${trimmed}" \u2014 expected "<node-id>: <x>, <y>"`,
19205
+ "warning"
19206
+ )
19207
+ );
19208
+ }
19209
+ continue;
19210
+ }
19211
+ inLayoutBlock = false;
19212
+ }
19167
19213
  if (descState !== null) {
19168
19214
  if (indent > descState.indent) {
19169
19215
  if (trimmed.includes("->") || trimmed.includes("<->")) {
@@ -19416,6 +19462,22 @@ function parseBoxesAndLines(content, palette) {
19416
19462
  );
19417
19463
  }
19418
19464
  finalizeAutoTagColors(result.tagGroups);
19465
+ if (nodePositions.size > 0) {
19466
+ const nodeLabelSet = new Set(result.nodes.map((n) => n.label));
19467
+ for (const id of nodePositions.keys()) {
19468
+ if (!nodeLabelSet.has(id)) {
19469
+ pushWarning(0, `layout entry for unknown node "${id}" (ignored)`);
19470
+ }
19471
+ }
19472
+ const unpositioned = result.nodes.filter((n) => !nodePositions.has(n.label)).map((n) => n.label);
19473
+ if (unpositioned.length > 0) {
19474
+ pushWarning(
19475
+ 0,
19476
+ `layout block is partial \u2014 ${unpositioned.length} node(s) without coordinates (${unpositioned.slice(0, 5).join(", ")}${unpositioned.length > 5 ? "\u2026" : ""}); ignoring the block and auto-laying-out`
19477
+ );
19478
+ }
19479
+ result.nodePositions = nodePositions;
19480
+ }
19419
19481
  if (result.tagGroups.length > 0) {
19420
19482
  injectDefaultTagMetadata(result.nodes, result.tagGroups);
19421
19483
  validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
@@ -21516,7 +21578,18 @@ function parseJourneyMap(content, palette) {
21516
21578
  }
21517
21579
  }
21518
21580
  } else {
21519
- personaName = afterKeyword;
21581
+ const colorMatch = afterKeyword.match(/^(.+?)\s+color:\s*(\S+)$/i);
21582
+ if (colorMatch) {
21583
+ personaName = colorMatch[1].trim();
21584
+ personaColor = resolveColorWithDiagnostic(
21585
+ colorMatch[2],
21586
+ lineNumber,
21587
+ result.diagnostics,
21588
+ palette
21589
+ ) ?? void 0;
21590
+ } else {
21591
+ personaName = afterKeyword;
21592
+ }
21520
21593
  }
21521
21594
  if (!personaName) {
21522
21595
  return fail(lineNumber, "persona requires a name");
@@ -24457,6 +24530,63 @@ var init_export_container = __esm({
24457
24530
  }
24458
24531
  });
24459
24532
 
24533
+ // src/utils/card.ts
24534
+ function renderNodeCard(container, opts) {
24535
+ const rect = container.append("rect").attr("x", 0).attr("y", 0).attr("width", opts.width).attr("height", opts.height).attr("rx", opts.rx).attr("fill", opts.fill).attr("stroke", opts.stroke).attr("stroke-width", opts.strokeWidth);
24536
+ if (opts.dashed) {
24537
+ rect.attr("stroke-dasharray", "6 3");
24538
+ }
24539
+ container.append("text").attr("x", opts.width / 2).attr("y", opts.headerHeight / 2 + opts.labelFontSize / 2 - 2).attr("text-anchor", "middle").attr("fill", opts.labelColor).attr("font-size", opts.labelFontSize).attr("font-weight", "bold").text(opts.label);
24540
+ const meta = opts.meta;
24541
+ if (!meta || meta.rows.length === 0) return;
24542
+ container.append("line").attr("x1", 0).attr("y1", opts.headerHeight).attr("x2", opts.width).attr("y2", opts.headerHeight).attr("stroke", meta.separatorColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
24543
+ const keyX = meta.keyX ?? 10;
24544
+ const maxKeyWidth = Math.max(
24545
+ ...meta.rows.map(([key]) => measureText(`${key}: `, meta.fontSize))
24546
+ );
24547
+ const valueX = keyX + maxKeyWidth;
24548
+ const metaStartY = opts.headerHeight + meta.separatorGap + meta.fontSize;
24549
+ for (let i = 0; i < meta.rows.length; i++) {
24550
+ const [displayKey, value] = meta.rows[i];
24551
+ const rowY = metaStartY + i * meta.lineHeight;
24552
+ container.append("text").attr("x", keyX).attr("y", rowY).attr("fill", meta.textColor).attr("font-size", meta.fontSize).text(`${displayKey}: `);
24553
+ container.append("text").attr("x", valueX).attr("y", rowY).attr("fill", meta.textColor).attr("font-size", meta.fontSize).text(value);
24554
+ }
24555
+ }
24556
+ function renderCollapseBar(container, opts) {
24557
+ container.append("clipPath").attr("id", opts.clipId).append("rect").attr("width", opts.width).attr("height", opts.height).attr("rx", opts.rx);
24558
+ container.append("rect").attr("x", opts.inset).attr("y", opts.height - opts.barHeight).attr("width", opts.width - opts.inset * 2).attr("height", opts.barHeight).attr("fill", opts.fill).attr("clip-path", `url(#${opts.clipId})`).attr("class", opts.className);
24559
+ }
24560
+ var init_card = __esm({
24561
+ "src/utils/card.ts"() {
24562
+ "use strict";
24563
+ init_text_measure();
24564
+ }
24565
+ });
24566
+
24567
+ // src/utils/visual-conventions.ts
24568
+ var NODE_STROKE_WIDTH, EDGE_STROKE_WIDTH, CARD_RADIUS, CONTAINER_RADIUS, COLLAPSE_BAR_INSET, HEADER_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT2, SEPARATOR_GAP2, COLLAPSE_BAR_HEIGHT, CONTAINER_HEADER_HEIGHT, CONTAINER_LABEL_FONT_SIZE, CONTAINER_META_FONT_SIZE, CONTAINER_META_LINE_HEIGHT2;
24569
+ var init_visual_conventions = __esm({
24570
+ "src/utils/visual-conventions.ts"() {
24571
+ "use strict";
24572
+ NODE_STROKE_WIDTH = 1.5;
24573
+ EDGE_STROKE_WIDTH = 1.5;
24574
+ CARD_RADIUS = 6;
24575
+ CONTAINER_RADIUS = 8;
24576
+ COLLAPSE_BAR_INSET = 0;
24577
+ HEADER_HEIGHT2 = 28;
24578
+ LABEL_FONT_SIZE2 = 13;
24579
+ META_FONT_SIZE2 = 11;
24580
+ META_LINE_HEIGHT2 = 16;
24581
+ SEPARATOR_GAP2 = 6;
24582
+ COLLAPSE_BAR_HEIGHT = 6;
24583
+ CONTAINER_HEADER_HEIGHT = 28;
24584
+ CONTAINER_LABEL_FONT_SIZE = 13;
24585
+ CONTAINER_META_FONT_SIZE = 11;
24586
+ CONTAINER_META_LINE_HEIGHT2 = 16;
24587
+ }
24588
+ });
24589
+
24460
24590
  // src/org/renderer.ts
24461
24591
  var renderer_exports = {};
24462
24592
  __export(renderer_exports, {
@@ -24615,9 +24745,16 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
24615
24745
  }
24616
24746
  }
24617
24747
  if (!exportDims && c.hiddenCount && c.hiddenCount > 0) {
24618
- const clipId = `clip-${c.nodeId}`;
24619
- cG.append("clipPath").attr("id", clipId).append("rect").attr("width", c.width).attr("height", c.height).attr("rx", sContainerRadius);
24620
- cG.append("rect").attr("x", sCollapseBarInset).attr("y", c.height - sCollapseBarHeight).attr("width", c.width - sCollapseBarInset * 2).attr("height", sCollapseBarHeight).attr("fill", containerStroke(palette, colorOff ? void 0 : c.color)).attr("clip-path", `url(#${clipId})`).attr("class", "org-collapse-bar");
24748
+ renderCollapseBar(cG, {
24749
+ width: c.width,
24750
+ height: c.height,
24751
+ barHeight: sCollapseBarHeight,
24752
+ inset: sCollapseBarInset,
24753
+ rx: sContainerRadius,
24754
+ fill: containerStroke(palette, colorOff ? void 0 : c.color),
24755
+ clipId: `clip-${c.nodeId}`,
24756
+ className: "org-collapse-bar"
24757
+ });
24621
24758
  }
24622
24759
  if (!exportDims && c.hasChildren && !rootNodeIds.has(c.nodeId)) {
24623
24760
  const iconSize = 14;
@@ -24668,42 +24805,48 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
24668
24805
  solid
24669
24806
  );
24670
24807
  const stroke2 = nodeStroke(palette, colorOff ? void 0 : node.color);
24671
- const rect = nodeG.append("rect").attr("x", 0).attr("y", 0).attr("width", node.width).attr("height", node.height).attr("rx", sCardRadius).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", sNodeStrokeWidth);
24672
- if (node.isContainer) {
24673
- rect.attr("stroke-dasharray", "6 3");
24674
- }
24675
24808
  const labelColor = contrastText(
24676
24809
  fill2,
24677
24810
  palette.textOnFillLight,
24678
24811
  palette.textOnFillDark
24679
24812
  );
24680
- nodeG.append("text").attr("x", node.width / 2).attr("y", sHeaderHeight / 2 + sLabelFontSize / 2 - 2).attr("text-anchor", "middle").attr("fill", labelColor).attr("font-size", sLabelFontSize).attr("font-weight", "bold").text(node.label);
24681
24813
  const metaEntries = Object.entries(node.metadata);
24682
- if (metaEntries.length > 0) {
24683
- nodeG.append("line").attr("x1", 0).attr("y1", sHeaderHeight).attr("x2", node.width).attr("y2", sHeaderHeight).attr("stroke", solid ? labelColor : stroke2).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
24684
- const metaDisplayKeys = metaEntries.map(
24685
- ([k]) => displayNames.get(k) ?? k
24686
- );
24687
- const maxKeyWidth = Math.max(
24688
- ...metaDisplayKeys.map((k) => measureText(`${k}: `, sMetaFontSize))
24689
- );
24690
- const valueX = 10 + maxKeyWidth;
24691
- const metaStartY = sHeaderHeight + sSeparatorGap + sMetaFontSize;
24692
- for (let i = 0; i < metaEntries.length; i++) {
24693
- const [, value] = metaEntries[i];
24694
- const displayKey = metaDisplayKeys[i];
24695
- const rowY = metaStartY + i * sMetaLineHeight;
24696
- nodeG.append("text").attr("x", 10).attr("y", rowY).attr("fill", labelColor).attr("font-size", sMetaFontSize).text(`${displayKey}: `);
24697
- nodeG.append("text").attr("x", valueX).attr("y", rowY).attr("fill", labelColor).attr("font-size", sMetaFontSize).text(value);
24814
+ renderNodeCard(nodeG, {
24815
+ width: node.width,
24816
+ height: node.height,
24817
+ rx: sCardRadius,
24818
+ fill: fill2,
24819
+ stroke: stroke2,
24820
+ strokeWidth: sNodeStrokeWidth,
24821
+ ...node.isContainer && { dashed: true },
24822
+ label: node.label,
24823
+ labelColor,
24824
+ labelFontSize: sLabelFontSize,
24825
+ headerHeight: sHeaderHeight,
24826
+ ...metaEntries.length > 0 && {
24827
+ meta: {
24828
+ rows: metaEntries.map(
24829
+ ([k, value]) => [displayNames.get(k) ?? k, value]
24830
+ ),
24831
+ fontSize: sMetaFontSize,
24832
+ lineHeight: sMetaLineHeight,
24833
+ separatorGap: sSeparatorGap,
24834
+ separatorColor: solid ? labelColor : stroke2,
24835
+ textColor: labelColor
24836
+ }
24698
24837
  }
24699
- }
24838
+ });
24700
24839
  if (!exportDims && node.hiddenCount && node.hiddenCount > 0) {
24701
- const clipId = `clip-${node.id}`;
24702
- nodeG.append("clipPath").attr("id", clipId).append("rect").attr("width", node.width).attr("height", node.height).attr("rx", sCardRadius);
24703
- nodeG.append("rect").attr("x", sCollapseBarInset).attr("y", node.height - sCollapseBarHeight).attr("width", node.width - sCollapseBarInset * 2).attr("height", sCollapseBarHeight).attr(
24704
- "fill",
24705
- solid ? labelColor : nodeStroke(palette, colorOff ? void 0 : node.color)
24706
- ).attr("clip-path", `url(#${clipId})`).attr("class", "org-collapse-bar");
24840
+ renderCollapseBar(nodeG, {
24841
+ width: node.width,
24842
+ height: node.height,
24843
+ barHeight: sCollapseBarHeight,
24844
+ inset: sCollapseBarInset,
24845
+ rx: sCardRadius,
24846
+ fill: solid ? labelColor : nodeStroke(palette, colorOff ? void 0 : node.color),
24847
+ clipId: `clip-${node.id}`,
24848
+ className: "org-collapse-bar"
24849
+ });
24707
24850
  }
24708
24851
  if (!exportDims && node.hasChildren && !rootNodeIds.has(node.id)) {
24709
24852
  const iconSize = 14;
@@ -24847,7 +24990,7 @@ function renderOrgForExport(content, theme, palette) {
24847
24990
  return extractExportSvg(container, theme);
24848
24991
  });
24849
24992
  }
24850
- var DIAGRAM_PADDING, MAX_SCALE, TITLE_HEIGHT, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT2, HEADER_HEIGHT2, SEPARATOR_GAP2, EDGE_STROKE_WIDTH, NODE_STROKE_WIDTH, CARD_RADIUS, CONTAINER_RADIUS, CONTAINER_LABEL_FONT_SIZE, CONTAINER_META_FONT_SIZE, CONTAINER_META_LINE_HEIGHT2, CONTAINER_HEADER_HEIGHT, COLLAPSE_BAR_HEIGHT, COLLAPSE_BAR_INSET, ANCESTOR_DOT_R, ANCESTOR_LABEL_FONT_SIZE, ANCESTOR_ROW_HEIGHT, ANCESTOR_TRAIL_BOTTOM_GAP, LEGEND_FIXED_GAP;
24993
+ var DIAGRAM_PADDING, MAX_SCALE, TITLE_HEIGHT, ANCESTOR_DOT_R, ANCESTOR_LABEL_FONT_SIZE, ANCESTOR_ROW_HEIGHT, ANCESTOR_TRAIL_BOTTOM_GAP, LEGEND_FIXED_GAP;
24851
24994
  var init_renderer = __esm({
24852
24995
  "src/org/renderer.ts"() {
24853
24996
  "use strict";
@@ -24860,27 +25003,14 @@ var init_renderer = __esm({
24860
25003
  init_layout();
24861
25004
  init_legend_constants();
24862
25005
  init_legend_integration();
25006
+ init_card();
24863
25007
  init_text_measure();
24864
25008
  init_legend_layout();
24865
25009
  init_title_constants();
25010
+ init_visual_conventions();
24866
25011
  DIAGRAM_PADDING = 20;
24867
25012
  MAX_SCALE = 3;
24868
25013
  TITLE_HEIGHT = 30;
24869
- LABEL_FONT_SIZE2 = 13;
24870
- META_FONT_SIZE2 = 11;
24871
- META_LINE_HEIGHT2 = 16;
24872
- HEADER_HEIGHT2 = 28;
24873
- SEPARATOR_GAP2 = 6;
24874
- EDGE_STROKE_WIDTH = 1.5;
24875
- NODE_STROKE_WIDTH = 1.5;
24876
- CARD_RADIUS = 6;
24877
- CONTAINER_RADIUS = 8;
24878
- CONTAINER_LABEL_FONT_SIZE = 13;
24879
- CONTAINER_META_FONT_SIZE = 11;
24880
- CONTAINER_META_LINE_HEIGHT2 = 16;
24881
- CONTAINER_HEADER_HEIGHT = 28;
24882
- COLLAPSE_BAR_HEIGHT = 6;
24883
- COLLAPSE_BAR_INSET = 0;
24884
25014
  ANCESTOR_DOT_R = 4;
24885
25015
  ANCESTOR_LABEL_FONT_SIZE = 11;
24886
25016
  ANCESTOR_ROW_HEIGHT = 22;
@@ -25664,21 +25794,21 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
25664
25794
  if (width <= 0 || height <= 0) return;
25665
25795
  const ctx = ScaleContext.identity();
25666
25796
  const sDiagramPadding = ctx.aesthetic(DIAGRAM_PADDING2);
25667
- const sLabelFontSize = ctx.text(LABEL_FONT_SIZE4);
25668
- const sMetaFontSize = ctx.text(META_FONT_SIZE4);
25669
- const sMetaLineHeight = ctx.structural(META_LINE_HEIGHT4);
25670
- const sHeaderHeight = ctx.structural(HEADER_HEIGHT4);
25671
- const sSeparatorGap = ctx.structural(SEPARATOR_GAP4);
25672
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH2);
25673
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH2);
25797
+ const sLabelFontSize = ctx.text(LABEL_FONT_SIZE2);
25798
+ const sMetaFontSize = ctx.text(META_FONT_SIZE2);
25799
+ const sMetaLineHeight = ctx.structural(META_LINE_HEIGHT2);
25800
+ const sHeaderHeight = ctx.structural(HEADER_HEIGHT2);
25801
+ const sSeparatorGap = ctx.structural(SEPARATOR_GAP2);
25802
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
25803
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
25674
25804
  const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE);
25675
- const sContainerLabelFontSize = ctx.text(CONTAINER_LABEL_FONT_SIZE3);
25676
- const sContainerMetaFontSize = ctx.text(CONTAINER_META_FONT_SIZE2);
25677
- const sContainerMetaLineHeight = ctx.structural(CONTAINER_META_LINE_HEIGHT4);
25678
- const sContainerHeaderHeight = ctx.structural(CONTAINER_HEADER_HEIGHT2);
25805
+ const sContainerLabelFontSize = ctx.text(CONTAINER_LABEL_FONT_SIZE);
25806
+ const sContainerMetaFontSize = ctx.text(CONTAINER_META_FONT_SIZE);
25807
+ const sContainerMetaLineHeight = ctx.structural(CONTAINER_META_LINE_HEIGHT2);
25808
+ const sContainerHeaderHeight = ctx.structural(CONTAINER_HEADER_HEIGHT);
25679
25809
  const sTitleFontSize = ctx.text(TITLE_FONT_SIZE);
25680
25810
  const sTitleHeight = ctx.structural(TITLE_HEIGHT2);
25681
- const sCollapseBarHeight = ctx.structural(COLLAPSE_BAR_HEIGHT2);
25811
+ const sCollapseBarHeight = ctx.structural(COLLAPSE_BAR_HEIGHT);
25682
25812
  const sLegendFixedGap = ctx.aesthetic(LEGEND_FIXED_GAP2);
25683
25813
  const hasLegend = layout.legend.length > 0;
25684
25814
  const layoutLegendShift = LEGEND_HEIGHT + LEGEND_GROUP_GAP;
@@ -25769,7 +25899,7 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
25769
25899
  }
25770
25900
  const fill2 = containerFill2(palette, isDark, c.color);
25771
25901
  const stroke2 = containerStroke2(palette, c.color);
25772
- cG.append("rect").attr("x", 0).attr("y", 0).attr("width", c.width).attr("height", c.height).attr("rx", CONTAINER_RADIUS2).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-opacity", 0.35).attr("stroke-width", sNodeStrokeWidth);
25902
+ cG.append("rect").attr("x", 0).attr("y", 0).attr("width", c.width).attr("height", c.height).attr("rx", CONTAINER_RADIUS).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-opacity", 0.35).attr("stroke-width", sNodeStrokeWidth);
25773
25903
  cG.append("text").attr("x", c.width / 2).attr("y", sContainerHeaderHeight / 2 + sContainerLabelFontSize / 2 - 2).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", sContainerLabelFontSize).attr("font-weight", "bold").text(c.label);
25774
25904
  const metaEntries = Object.entries(c.metadata);
25775
25905
  if (metaEntries.length > 0) {
@@ -25794,7 +25924,7 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
25794
25924
  }
25795
25925
  if (!exportDims && c.hiddenCount && c.hiddenCount > 0) {
25796
25926
  const clipId = `clip-${c.nodeId}`;
25797
- cG.append("clipPath").attr("id", clipId).append("rect").attr("width", c.width).attr("height", c.height).attr("rx", CONTAINER_RADIUS2);
25927
+ cG.append("clipPath").attr("id", clipId).append("rect").attr("width", c.width).attr("height", c.height).attr("rx", CONTAINER_RADIUS);
25798
25928
  cG.append("rect").attr("y", c.height - sCollapseBarHeight).attr("width", c.width).attr("height", sCollapseBarHeight).attr("fill", c.color ?? palette.primary).attr("opacity", 0.5).attr("clip-path", `url(#${clipId})`);
25799
25929
  cG.append("text").attr("x", c.width / 2).attr("y", c.height - sCollapseBarHeight - 6).attr("text-anchor", "middle").attr("fill", palette.textMuted).attr("font-size", sMetaFontSize).text(`+${c.hiddenCount}`);
25800
25930
  }
@@ -25833,13 +25963,23 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
25833
25963
  const solid = parsed.options["solid-fill"] === "on";
25834
25964
  const fill2 = nodeFill2(palette, isDark, node.color, solid);
25835
25965
  const stroke2 = nodeStroke2(palette, node.color);
25836
- nodeG.append("rect").attr("x", 0).attr("y", 0).attr("width", node.width).attr("height", node.height).attr("rx", CARD_RADIUS2).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", sNodeStrokeWidth);
25837
25966
  const labelColor = contrastText(
25838
25967
  fill2,
25839
25968
  palette.textOnFillLight,
25840
25969
  palette.textOnFillDark
25841
25970
  );
25842
- nodeG.append("text").attr("x", node.width / 2).attr("y", sHeaderHeight / 2 + sLabelFontSize / 2 - 2).attr("text-anchor", "middle").attr("fill", labelColor).attr("font-size", sLabelFontSize).attr("font-weight", "bold").text(node.label);
25971
+ renderNodeCard(nodeG, {
25972
+ width: node.width,
25973
+ height: node.height,
25974
+ rx: CARD_RADIUS,
25975
+ fill: fill2,
25976
+ stroke: stroke2,
25977
+ strokeWidth: sNodeStrokeWidth,
25978
+ label: node.label,
25979
+ labelColor,
25980
+ labelFontSize: sLabelFontSize,
25981
+ headerHeight: sHeaderHeight
25982
+ });
25843
25983
  const metaEntries = Object.entries(node.metadata);
25844
25984
  if (metaEntries.length > 0) {
25845
25985
  nodeG.append("line").attr("x1", 0).attr("y1", sHeaderHeight).attr("x2", node.width).attr("y2", sHeaderHeight).attr("stroke", solid ? labelColor : stroke2).attr("stroke-opacity", 0.3);
@@ -25874,7 +26014,7 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
25874
26014
  }
25875
26015
  if (!exportDims && node.hiddenCount && node.hiddenCount > 0) {
25876
26016
  const clipId = `clip-${node.id}`;
25877
- nodeG.append("clipPath").attr("id", clipId).append("rect").attr("width", node.width).attr("height", node.height).attr("rx", CARD_RADIUS2);
26017
+ nodeG.append("clipPath").attr("id", clipId).append("rect").attr("width", node.width).attr("height", node.height).attr("rx", CARD_RADIUS);
25878
26018
  nodeG.append("rect").attr("y", node.height - sCollapseBarHeight).attr("width", node.width).attr("height", sCollapseBarHeight).attr("fill", solid ? labelColor : node.color ?? palette.primary).attr("opacity", 0.5).attr("clip-path", `url(#${clipId})`);
25879
26019
  }
25880
26020
  }
@@ -26004,7 +26144,7 @@ async function renderSitemapForExport(content, theme, palette) {
26004
26144
  document.body.removeChild(container);
26005
26145
  return svgHtml;
26006
26146
  }
26007
- var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE4, META_FONT_SIZE4, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE3, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator, lineGeneratorLinear;
26147
+ var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, LEGEND_FIXED_GAP2, lineGenerator, lineGeneratorLinear;
26008
26148
  var init_renderer2 = __esm({
26009
26149
  "src/sitemap/renderer.ts"() {
26010
26150
  "use strict";
@@ -26017,27 +26157,15 @@ var init_renderer2 = __esm({
26017
26157
  init_legend_integration();
26018
26158
  init_legend_layout();
26019
26159
  init_scaling();
26160
+ init_card();
26020
26161
  init_title_constants();
26162
+ init_visual_conventions();
26021
26163
  DIAGRAM_PADDING2 = 20;
26022
26164
  MAX_SCALE2 = 3;
26023
26165
  TITLE_HEIGHT2 = 30;
26024
- LABEL_FONT_SIZE4 = 13;
26025
- META_FONT_SIZE4 = 11;
26026
- META_LINE_HEIGHT4 = 16;
26027
- HEADER_HEIGHT4 = 28;
26028
- SEPARATOR_GAP4 = 6;
26029
- EDGE_STROKE_WIDTH2 = 1.5;
26030
- NODE_STROKE_WIDTH2 = 1.5;
26031
- CARD_RADIUS2 = 6;
26032
- CONTAINER_RADIUS2 = 8;
26033
- CONTAINER_LABEL_FONT_SIZE3 = 13;
26034
- CONTAINER_META_FONT_SIZE2 = 11;
26035
- CONTAINER_META_LINE_HEIGHT4 = 16;
26036
- CONTAINER_HEADER_HEIGHT2 = 28;
26037
26166
  ARROWHEAD_W = 10;
26038
26167
  ARROWHEAD_H = 7;
26039
26168
  EDGE_LABEL_FONT_SIZE = 11;
26040
- COLLAPSE_BAR_HEIGHT2 = 6;
26041
26169
  LEGEND_FIXED_GAP2 = 8;
26042
26170
  lineGenerator = d3Shape2.line().x((d) => d.x).y((d) => d.y).curve(d3Shape2.curveBasis);
26043
26171
  lineGeneratorLinear = d3Shape2.line().x((d) => d.x).y((d) => d.y).curve(d3Shape2.curveLinear);
@@ -26205,7 +26333,7 @@ function renderKanban(container, parsed, palette, isDark, options) {
26205
26333
  const sCardMetaLineHeight = ctx.structural(CARD_META_LINE_HEIGHT);
26206
26334
  const sCardSeparatorGap = ctx.structural(CARD_SEPARATOR_GAP);
26207
26335
  const sCardGap = ctx.aesthetic(CARD_GAP);
26208
- const sCardRadius = ctx.structural(CARD_RADIUS3);
26336
+ const sCardRadius = ctx.structural(CARD_RADIUS);
26209
26337
  const sCardPaddingX = ctx.aesthetic(CARD_PADDING_X);
26210
26338
  const sCardPaddingY = ctx.aesthetic(CARD_PADDING_Y);
26211
26339
  const sCardStrokeWidth = ctx.structural(CARD_STROKE_WIDTH);
@@ -26585,7 +26713,7 @@ function computeSwimlaneLayout(parsed, buckets, baseLayout, collapsedLanes, coll
26585
26713
  const totalHeight = laneY - sLaneGap + sColumnPadding + sDiagramPadding;
26586
26714
  return { columnXs, lanes, totalWidth, totalHeight, startY };
26587
26715
  }
26588
- function renderSwimlaneBoard(svg, parsed, baseLayout, swimlaneGroup, palette, isDark, activeTagGroup, collapsedLanes, collapsedColumns, hiddenMetaGroups, sDiagramPadding = DIAGRAM_PADDING3, sTitleHeight = TITLE_HEIGHT3, sLaneHeaderWidth = LANE_HEADER_WIDTH, sColumnGap = COLUMN_GAP, sCollapsedColumnWidth = COLLAPSED_COLUMN_WIDTH, sColumnHeaderHeight = COLUMN_HEADER_HEIGHT, sColumnPadding = COLUMN_PADDING, sCardHeaderHeight = CARD_HEADER_HEIGHT, sCardPaddingY = CARD_PADDING_Y, sCardGap = CARD_GAP, sCollapsedLaneHeight = COLLAPSED_LANE_HEIGHT, sLaneGap = LANE_GAP, sCardSeparatorGap = CARD_SEPARATOR_GAP, sCardMetaLineHeight = CARD_META_LINE_HEIGHT, sColumnHeaderFontSize = COLUMN_HEADER_FONT_SIZE, sColumnRadius = COLUMN_RADIUS, sColumnHeaderRadius = COLUMN_HEADER_RADIUS, sWipFontSize = WIP_FONT_SIZE, sCardRadius = CARD_RADIUS3, sCardPaddingX = CARD_PADDING_X, sCardStrokeWidth = CARD_STROKE_WIDTH, sCardTitleFontSize = CARD_TITLE_FONT_SIZE, sCardMetaFontSize = CARD_META_FONT_SIZE) {
26716
+ function renderSwimlaneBoard(svg, parsed, baseLayout, swimlaneGroup, palette, isDark, activeTagGroup, collapsedLanes, collapsedColumns, hiddenMetaGroups, sDiagramPadding = DIAGRAM_PADDING3, sTitleHeight = TITLE_HEIGHT3, sLaneHeaderWidth = LANE_HEADER_WIDTH, sColumnGap = COLUMN_GAP, sCollapsedColumnWidth = COLLAPSED_COLUMN_WIDTH, sColumnHeaderHeight = COLUMN_HEADER_HEIGHT, sColumnPadding = COLUMN_PADDING, sCardHeaderHeight = CARD_HEADER_HEIGHT, sCardPaddingY = CARD_PADDING_Y, sCardGap = CARD_GAP, sCollapsedLaneHeight = COLLAPSED_LANE_HEIGHT, sLaneGap = LANE_GAP, sCardSeparatorGap = CARD_SEPARATOR_GAP, sCardMetaLineHeight = CARD_META_LINE_HEIGHT, sColumnHeaderFontSize = COLUMN_HEADER_FONT_SIZE, sColumnRadius = COLUMN_RADIUS, sColumnHeaderRadius = COLUMN_HEADER_RADIUS, sWipFontSize = WIP_FONT_SIZE, sCardRadius = CARD_RADIUS, sCardPaddingX = CARD_PADDING_X, sCardStrokeWidth = CARD_STROKE_WIDTH, sCardTitleFontSize = CARD_TITLE_FONT_SIZE, sCardMetaFontSize = CARD_META_FONT_SIZE) {
26589
26717
  const visibleColumns = parsed.columns.filter((c) => !isArchiveColumn(c.name));
26590
26718
  const buckets = bucketCardsBySwimlane(visibleColumns, swimlaneGroup);
26591
26719
  const grid = computeSwimlaneLayout(
@@ -26725,7 +26853,7 @@ function renderSwimlaneBoard(svg, parsed, baseLayout, swimlaneGroup, palette, is
26725
26853
  }
26726
26854
  }
26727
26855
  }
26728
- function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palette, isDark, hiddenMetaGroups, solid, sCardRadius = CARD_RADIUS3, sCardPaddingX = CARD_PADDING_X, sCardPaddingY = CARD_PADDING_Y, sCardStrokeWidth = CARD_STROKE_WIDTH, sCardTitleFontSize = CARD_TITLE_FONT_SIZE, sCardMetaFontSize = CARD_META_FONT_SIZE, sCardHeaderHeight = CARD_HEADER_HEIGHT, sCardSeparatorGap = CARD_SEPARATOR_GAP, sCardMetaLineHeight = CARD_META_LINE_HEIGHT) {
26856
+ function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palette, isDark, hiddenMetaGroups, solid, sCardRadius = CARD_RADIUS, sCardPaddingX = CARD_PADDING_X, sCardPaddingY = CARD_PADDING_Y, sCardStrokeWidth = CARD_STROKE_WIDTH, sCardTitleFontSize = CARD_TITLE_FONT_SIZE, sCardMetaFontSize = CARD_META_FONT_SIZE, sCardHeaderHeight = CARD_HEADER_HEIGHT, sCardSeparatorGap = CARD_SEPARATOR_GAP, sCardMetaLineHeight = CARD_META_LINE_HEIGHT) {
26729
26857
  const card = cardLayout.card;
26730
26858
  const resolvedColor = resolveCardTagColor(card, tagGroups, activeTagGroup);
26731
26859
  const tagMeta = resolveCardTagMeta(card, tagGroups, hiddenMetaGroups);
@@ -26775,7 +26903,7 @@ function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palet
26775
26903
  }
26776
26904
  }
26777
26905
  }
26778
- var DIAGRAM_PADDING3, COLUMN_GAP, COLUMN_HEADER_HEIGHT, COLUMN_PADDING, COLUMN_MIN_WIDTH, CARD_HEADER_HEIGHT, CARD_META_LINE_HEIGHT, CARD_SEPARATOR_GAP, CARD_GAP, CARD_RADIUS3, CARD_PADDING_X, CARD_PADDING_Y, CARD_STROKE_WIDTH, TITLE_HEIGHT3, COLUMN_HEADER_FONT_SIZE, CARD_TITLE_FONT_SIZE, CARD_META_FONT_SIZE, WIP_FONT_SIZE, COLUMN_RADIUS, COLUMN_HEADER_RADIUS, COLLAPSED_COLUMN_WIDTH, COLLAPSED_LANE_HEIGHT, LANE_HEADER_WIDTH, LANE_GAP;
26906
+ var DIAGRAM_PADDING3, COLUMN_GAP, COLUMN_HEADER_HEIGHT, COLUMN_PADDING, COLUMN_MIN_WIDTH, CARD_HEADER_HEIGHT, CARD_META_LINE_HEIGHT, CARD_SEPARATOR_GAP, CARD_GAP, CARD_PADDING_X, CARD_PADDING_Y, CARD_STROKE_WIDTH, TITLE_HEIGHT3, COLUMN_HEADER_FONT_SIZE, CARD_TITLE_FONT_SIZE, CARD_META_FONT_SIZE, WIP_FONT_SIZE, COLUMN_RADIUS, COLUMN_HEADER_RADIUS, COLLAPSED_COLUMN_WIDTH, COLLAPSED_LANE_HEIGHT, LANE_HEADER_WIDTH, LANE_GAP;
26779
26907
  var init_renderer3 = __esm({
26780
26908
  "src/kanban/renderer.ts"() {
26781
26909
  "use strict";
@@ -26789,6 +26917,7 @@ var init_renderer3 = __esm({
26789
26917
  init_legend_integration();
26790
26918
  init_scaling();
26791
26919
  init_text_measure();
26920
+ init_visual_conventions();
26792
26921
  init_title_constants();
26793
26922
  DIAGRAM_PADDING3 = 20;
26794
26923
  COLUMN_GAP = 16;
@@ -26799,7 +26928,6 @@ var init_renderer3 = __esm({
26799
26928
  CARD_META_LINE_HEIGHT = 14;
26800
26929
  CARD_SEPARATOR_GAP = 4;
26801
26930
  CARD_GAP = 8;
26802
- CARD_RADIUS3 = 6;
26803
26931
  CARD_PADDING_X = 10;
26804
26932
  CARD_PADDING_Y = 6;
26805
26933
  CARD_STROKE_WIDTH = 1.5;
@@ -27102,8 +27230,8 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
27102
27230
  const sClassFontSize = ctx.text(CLASS_FONT_SIZE2);
27103
27231
  const sMemberFontSize = ctx.text(MEMBER_FONT_SIZE2);
27104
27232
  const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE2);
27105
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH3);
27106
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH3);
27233
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
27234
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
27107
27235
  const sMemberLineHeight = ctx.structural(MEMBER_LINE_HEIGHT2);
27108
27236
  const sCompartmentPaddingY = ctx.structural(COMPARTMENT_PADDING_Y2);
27109
27237
  const sMemberPaddingX = ctx.structural(MEMBER_PADDING_X);
@@ -27362,7 +27490,7 @@ function renderClassDiagramForExport(content, theme, palette) {
27362
27490
  return extractExportSvg(container, theme);
27363
27491
  });
27364
27492
  }
27365
- var DIAGRAM_PADDING4, MAX_SCALE3, CLASS_FONT_SIZE2, MEMBER_FONT_SIZE2, EDGE_LABEL_FONT_SIZE2, EDGE_STROKE_WIDTH3, NODE_STROKE_WIDTH3, MEMBER_LINE_HEIGHT2, COMPARTMENT_PADDING_Y2, MEMBER_PADDING_X, CLASS_TYPE_MAP, CLASS_TYPE_ORDER, LEGEND_GROUP_NAME, lineGenerator2;
27493
+ var DIAGRAM_PADDING4, MAX_SCALE3, CLASS_FONT_SIZE2, MEMBER_FONT_SIZE2, EDGE_LABEL_FONT_SIZE2, MEMBER_LINE_HEIGHT2, COMPARTMENT_PADDING_Y2, MEMBER_PADDING_X, CLASS_TYPE_MAP, CLASS_TYPE_ORDER, LEGEND_GROUP_NAME, lineGenerator2;
27366
27494
  var init_renderer4 = __esm({
27367
27495
  "src/class/renderer.ts"() {
27368
27496
  "use strict";
@@ -27377,13 +27505,12 @@ var init_renderer4 = __esm({
27377
27505
  init_scaling();
27378
27506
  init_text_measure();
27379
27507
  init_note_box();
27508
+ init_visual_conventions();
27380
27509
  DIAGRAM_PADDING4 = 20;
27381
27510
  MAX_SCALE3 = 3;
27382
27511
  CLASS_FONT_SIZE2 = 13;
27383
27512
  MEMBER_FONT_SIZE2 = 11;
27384
27513
  EDGE_LABEL_FONT_SIZE2 = 11;
27385
- EDGE_STROKE_WIDTH3 = 1.5;
27386
- NODE_STROKE_WIDTH3 = 1.5;
27387
27514
  MEMBER_LINE_HEIGHT2 = 18;
27388
27515
  COMPARTMENT_PADDING_Y2 = 8;
27389
27516
  MEMBER_PADDING_X = 10;
@@ -27879,7 +28006,7 @@ function constraintIcon(constraint) {
27879
28006
  return "\u25CB";
27880
28007
  }
27881
28008
  }
27882
- function drawCardinality(g, point, prevPoint, cardinality, color, useLabels, edgeLabelFontSize = EDGE_LABEL_FONT_SIZE4, edgeStrokeWidth = EDGE_STROKE_WIDTH4) {
28009
+ function drawCardinality(g, point, prevPoint, cardinality, color, useLabels, edgeLabelFontSize = EDGE_LABEL_FONT_SIZE4, edgeStrokeWidth = EDGE_STROKE_WIDTH) {
27883
28010
  const dx = point.x - prevPoint.x;
27884
28011
  const dy = point.y - prevPoint.y;
27885
28012
  const len = Math.sqrt(dx * dx + dy * dy);
@@ -27939,8 +28066,8 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
27939
28066
  const sTableFontSize = ctx.text(TABLE_FONT_SIZE2);
27940
28067
  const sColumnFontSize = ctx.text(COLUMN_FONT_SIZE2);
27941
28068
  const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE4);
27942
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH4);
27943
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH4);
28069
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
28070
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
27944
28071
  const sMemberLineHeight = ctx.structural(MEMBER_LINE_HEIGHT4);
27945
28072
  const sCompartmentPaddingY = ctx.structural(COMPARTMENT_PADDING_Y4);
27946
28073
  const sMemberPaddingX = ctx.structural(MEMBER_PADDING_X2);
@@ -28218,7 +28345,7 @@ function renderERDiagramForExport(content, theme, palette) {
28218
28345
  document.body.removeChild(container);
28219
28346
  }
28220
28347
  }
28221
- var DIAGRAM_PADDING5, MAX_SCALE4, TABLE_FONT_SIZE2, COLUMN_FONT_SIZE2, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH4, NODE_STROKE_WIDTH4, MEMBER_LINE_HEIGHT4, COMPARTMENT_PADDING_Y4, MEMBER_PADDING_X2, lineGenerator3;
28348
+ var DIAGRAM_PADDING5, MAX_SCALE4, TABLE_FONT_SIZE2, COLUMN_FONT_SIZE2, EDGE_LABEL_FONT_SIZE4, MEMBER_LINE_HEIGHT4, COMPARTMENT_PADDING_Y4, MEMBER_PADDING_X2, lineGenerator3;
28222
28349
  var init_renderer5 = __esm({
28223
28350
  "src/er/renderer.ts"() {
28224
28351
  "use strict";
@@ -28235,13 +28362,12 @@ var init_renderer5 = __esm({
28235
28362
  init_parser9();
28236
28363
  init_layout4();
28237
28364
  init_classify();
28365
+ init_visual_conventions();
28238
28366
  DIAGRAM_PADDING5 = 20;
28239
28367
  MAX_SCALE4 = 3;
28240
28368
  TABLE_FONT_SIZE2 = 13;
28241
28369
  COLUMN_FONT_SIZE2 = 11;
28242
28370
  EDGE_LABEL_FONT_SIZE4 = 11;
28243
- EDGE_STROKE_WIDTH4 = 1.5;
28244
- NODE_STROKE_WIDTH4 = 1.5;
28245
28371
  MEMBER_LINE_HEIGHT4 = 18;
28246
28372
  COMPARTMENT_PADDING_Y4 = 8;
28247
28373
  MEMBER_PADDING_X2 = 10;
@@ -28471,9 +28597,9 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
28471
28597
  const sDiagramPadding = sctx.aesthetic(DIAGRAM_PADDING6);
28472
28598
  const sMinNodeFontSize = sctx.text(MIN_NODE_FONT_SIZE);
28473
28599
  const sEdgeLabelFontSize = sctx.text(EDGE_LABEL_FONT_SIZE5);
28474
- const sEdgeStrokeWidth = sctx.structural(EDGE_STROKE_WIDTH5);
28475
- const sNodeStrokeWidth = sctx.structural(NODE_STROKE_WIDTH5);
28476
- const sCollapseBarHeight = sctx.structural(COLLAPSE_BAR_HEIGHT3);
28600
+ const sEdgeStrokeWidth = sctx.structural(EDGE_STROKE_WIDTH);
28601
+ const sNodeStrokeWidth = sctx.structural(NODE_STROKE_WIDTH);
28602
+ const sCollapseBarHeight = sctx.structural(COLLAPSE_BAR_HEIGHT2);
28477
28603
  const sDescFontSize = sctx.text(DESC_FONT_SIZE);
28478
28604
  const sGroupLabelFontSize = sctx.text(GROUP_LABEL_FONT_SIZE);
28479
28605
  const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
@@ -28565,8 +28691,32 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
28565
28691
  const scaleX = width / (contentW + sDiagramPadding * 2);
28566
28692
  const scaleY = height / (contentH + sDiagramPadding * 2);
28567
28693
  const scale = Math.min(scaleX, scaleY, 3);
28568
- const offsetX = (width - contentW * scale) / 2;
28569
- const offsetY = sDiagramPadding + titleOffset + legendH;
28694
+ let centerShiftX = 0;
28695
+ let centerShiftY = 0;
28696
+ if (parsed.nodePositions && parsed.nodePositions.size > 0) {
28697
+ let bMinX = Infinity, bMinY = Infinity, bMaxX = -Infinity, bMaxY = -Infinity;
28698
+ const accB = (x, y) => {
28699
+ if (x < bMinX) bMinX = x;
28700
+ if (x > bMaxX) bMaxX = x;
28701
+ if (y < bMinY) bMinY = y;
28702
+ if (y > bMaxY) bMaxY = y;
28703
+ };
28704
+ for (const n of layout.nodes) {
28705
+ accB(n.x - n.width / 2, n.y - n.height / 2);
28706
+ accB(n.x + n.width / 2, n.y + n.height / 2);
28707
+ }
28708
+ for (const g of layout.groups) {
28709
+ accB(g.x - g.width / 2, g.y - g.height / 2);
28710
+ accB(g.x + g.width / 2, g.y + g.height / 2);
28711
+ }
28712
+ for (const e of layout.edges) for (const p of e.points) accB(p.x, p.y);
28713
+ if (Number.isFinite(bMinX)) {
28714
+ centerShiftX = (layout.width - bMaxX - bMinX) / 2;
28715
+ centerShiftY = (layout.height - bMaxY - bMinY) / 2;
28716
+ }
28717
+ }
28718
+ const offsetX = (width - contentW * scale) / 2 + centerShiftX * scale;
28719
+ const offsetY = sDiagramPadding + titleOffset + legendH + centerShiftY * scale;
28570
28720
  const svg = d3Selection11.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY).style("background", palette.bg);
28571
28721
  if (sctx.isBelowFloor) {
28572
28722
  svg.attr("width", "100%");
@@ -28702,7 +28852,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
28702
28852
  const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
28703
28853
  edgeGroups.set(i, edgeG);
28704
28854
  const markerId = `bl-arrow-${color.replace("#", "")}`;
28705
- const gen = parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
28855
+ const gen = le.straight ? lineGeneratorStraight : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
28706
28856
  const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", sEdgeStrokeWidth).attr("marker-end", `url(#${markerId})`);
28707
28857
  if (le.bidirectional) {
28708
28858
  const revId = `bl-arrow-rev-${color.replace("#", "")}`;
@@ -28983,7 +29133,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
28983
29133
  }
28984
29134
  });
28985
29135
  }
28986
- var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE5, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE, DESC_LINE_HEIGHT, MAX_DESC_LINES, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, RAMP_FLOOR, VALUE_FONT_SIZE, lineGeneratorLR, lineGeneratorTB;
29136
+ var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE5, NODE_RX, COLLAPSE_BAR_HEIGHT2, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE, DESC_LINE_HEIGHT, MAX_DESC_LINES, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, RAMP_FLOOR, VALUE_FONT_SIZE, lineGeneratorLR, lineGeneratorTB, lineGeneratorStraight;
28987
29137
  var init_renderer6 = __esm({
28988
29138
  "src/boxes-and-lines/renderer.ts"() {
28989
29139
  "use strict";
@@ -28999,14 +29149,13 @@ var init_renderer6 = __esm({
28999
29149
  init_wrapped_desc();
29000
29150
  init_scaling();
29001
29151
  init_text_measure();
29152
+ init_visual_conventions();
29002
29153
  DIAGRAM_PADDING6 = 20;
29003
29154
  NODE_FONT_SIZE = 11;
29004
29155
  MIN_NODE_FONT_SIZE = 9;
29005
29156
  EDGE_LABEL_FONT_SIZE5 = 11;
29006
- EDGE_STROKE_WIDTH5 = 1.5;
29007
- NODE_STROKE_WIDTH5 = 1.5;
29008
29157
  NODE_RX = 8;
29009
- COLLAPSE_BAR_HEIGHT3 = 4;
29158
+ COLLAPSE_BAR_HEIGHT2 = 4;
29010
29159
  ARROWHEAD_W2 = 5;
29011
29160
  ARROWHEAD_H2 = 4;
29012
29161
  DESC_FONT_SIZE = 10;
@@ -29020,6 +29169,7 @@ var init_renderer6 = __esm({
29020
29169
  VALUE_FONT_SIZE = 11;
29021
29170
  lineGeneratorLR = d3Shape5.line().x((d) => d.x).y((d) => d.y).curve(d3Shape5.curveBasis);
29022
29171
  lineGeneratorTB = d3Shape5.line().x((d) => d.x).y((d) => d.y).curve(d3Shape5.curveBasis);
29172
+ lineGeneratorStraight = d3Shape5.line().x((d) => d.x).y((d) => d.y).curve(d3Shape5.curveLinear);
29023
29173
  }
29024
29174
  });
29025
29175
 
@@ -30209,6 +30359,156 @@ function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
30209
30359
  return { x: rect.x + dx * s, y: rect.y + dy * s };
30210
30360
  };
30211
30361
  const isInsideRect = (p, rect) => Math.abs(p.x - rect.x) <= rect.w / 2 && Math.abs(p.y - rect.y) <= rect.h / 2;
30362
+ const pinned = parsed.nodePositions;
30363
+ const groupLabelSet = new Set(parsed.groups.map((g) => g.label));
30364
+ const groupsAreFlat = parsed.groups.every(
30365
+ (g) => !g.parentGroup && !g.children.some((c) => groupLabelSet.has(c))
30366
+ );
30367
+ const allOriginalGroupLabels = new Set(
30368
+ (collapseInfo?.originalGroups ?? parsed.groups).map((g) => g.label)
30369
+ );
30370
+ const collapsedAreFlatPinned = collapsedGroupLabels.size === 0 || pinned !== void 0 && collapseInfo !== void 0 && [...collapsedGroupLabels].every((label) => {
30371
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
30372
+ if (!og || og.parentGroup) return false;
30373
+ return og.children.every(
30374
+ (c) => pinned.has(c) && !allOriginalGroupLabels.has(c)
30375
+ );
30376
+ });
30377
+ const allPinned = pinned !== void 0 && (parsed.nodes.length > 0 || collapsedGroupLabels.size > 0) && parsed.nodes.every((n2) => pinned.has(n2.label)) && groupsAreFlat && collapsedAreFlatPinned;
30378
+ function placePinned(pins) {
30379
+ const collapsedPosByGid = /* @__PURE__ */ new Map();
30380
+ const collapsedBoxes = [];
30381
+ if (collapseInfo)
30382
+ for (const label of collapsedGroupLabels) {
30383
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
30384
+ if (!og) continue;
30385
+ let cx0 = Infinity, cy0 = Infinity, cx1 = -Infinity, cy1 = -Infinity;
30386
+ for (const c of og.children) {
30387
+ const p = pins.get(c);
30388
+ if (!p) continue;
30389
+ cx0 = Math.min(cx0, p.x);
30390
+ cx1 = Math.max(cx1, p.x);
30391
+ cy0 = Math.min(cy0, p.y);
30392
+ cy1 = Math.max(cy1, p.y);
30393
+ }
30394
+ if (!Number.isFinite(cx0)) continue;
30395
+ const cx = (cx0 + cx1) / 2;
30396
+ const cy = (cy0 + cy1) / 2;
30397
+ collapsedPosByGid.set(`__group_${label}`, { x: cx, y: cy });
30398
+ collapsedBoxes.push({
30399
+ label,
30400
+ lineNumber: og.lineNumber,
30401
+ childCount: collapseInfo.collapsedChildCounts.get(label) ?? og.children.length,
30402
+ x: cx,
30403
+ y: cy
30404
+ });
30405
+ }
30406
+ const posOf = (label) => pins.get(label) ?? collapsedPosByGid.get(label);
30407
+ const rectOf = (label) => {
30408
+ const p = posOf(label);
30409
+ const s = sizes.get(label) ?? { width: NODE_WIDTH, height: NODE_HEIGHT };
30410
+ return { x: p.x, y: p.y, w: s.width, h: s.height };
30411
+ };
30412
+ const nodes = parsed.nodes.map((n2) => {
30413
+ const r = rectOf(n2.label);
30414
+ return { label: n2.label, x: r.x, y: r.y, width: r.w, height: r.h };
30415
+ });
30416
+ const edges = parsed.edges.flatMap((e) => {
30417
+ const sp = posOf(e.source);
30418
+ const tp = posOf(e.target);
30419
+ if (!sp || !tp) return [];
30420
+ const srcRect = rectOf(e.source);
30421
+ const tgtRect = rectOf(e.target);
30422
+ const p0 = rectBorderPoint(srcRect, tp);
30423
+ const p1 = rectBorderPoint(tgtRect, sp);
30424
+ return [
30425
+ {
30426
+ source: e.source,
30427
+ target: e.target,
30428
+ ...e.label !== void 0 && { label: e.label },
30429
+ bidirectional: e.bidirectional,
30430
+ lineNumber: e.lineNumber,
30431
+ points: [p0, p1],
30432
+ yOffset: 0,
30433
+ parallelCount: 1,
30434
+ metadata: e.metadata,
30435
+ straight: true
30436
+ }
30437
+ ];
30438
+ });
30439
+ const GROUP_PAD = 16;
30440
+ const nodeByLabel = new Map(nodes.map((n2) => [n2.label, n2]));
30441
+ const groups = [];
30442
+ for (const grp of parsed.groups) {
30443
+ let gx0 = Infinity, gy0 = Infinity, gx1 = -Infinity, gy1 = -Infinity;
30444
+ for (const c of grp.children) {
30445
+ const n2 = nodeByLabel.get(c);
30446
+ if (!n2) continue;
30447
+ gx0 = Math.min(gx0, n2.x - n2.width / 2);
30448
+ gx1 = Math.max(gx1, n2.x + n2.width / 2);
30449
+ gy0 = Math.min(gy0, n2.y - n2.height / 2);
30450
+ gy1 = Math.max(gy1, n2.y + n2.height / 2);
30451
+ }
30452
+ if (!Number.isFinite(gx0)) continue;
30453
+ const x0 = gx0 - GROUP_PAD;
30454
+ const x1 = gx1 + GROUP_PAD;
30455
+ const y0 = gy0 - GROUP_LABEL_ZONE2;
30456
+ const y1 = gy1 + GROUP_PAD;
30457
+ groups.push({
30458
+ label: grp.label,
30459
+ lineNumber: grp.lineNumber,
30460
+ x: (x0 + x1) / 2,
30461
+ y: (y0 + y1) / 2,
30462
+ width: x1 - x0,
30463
+ height: y1 - y0,
30464
+ collapsed: false,
30465
+ childCount: grp.children.length
30466
+ });
30467
+ }
30468
+ for (const cb of collapsedBoxes) {
30469
+ groups.push({
30470
+ label: cb.label,
30471
+ lineNumber: cb.lineNumber,
30472
+ x: cb.x,
30473
+ y: cb.y,
30474
+ width: NODE_WIDTH,
30475
+ height: NODE_HEIGHT,
30476
+ collapsed: true,
30477
+ childCount: cb.childCount
30478
+ });
30479
+ }
30480
+ const M = 40;
30481
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
30482
+ const acc = (x, y) => {
30483
+ if (x < minX) minX = x;
30484
+ if (x > maxX) maxX = x;
30485
+ if (y < minY) minY = y;
30486
+ if (y > maxY) maxY = y;
30487
+ };
30488
+ for (const n2 of nodes) {
30489
+ acc(n2.x - n2.width / 2, n2.y - n2.height / 2);
30490
+ acc(n2.x + n2.width / 2, n2.y + n2.height / 2);
30491
+ }
30492
+ for (const e of edges) for (const p of e.points) acc(p.x, p.y);
30493
+ for (const gr of groups) {
30494
+ acc(gr.x - gr.width / 2, gr.y - gr.height / 2);
30495
+ acc(gr.x + gr.width / 2, gr.y + gr.height / 2);
30496
+ }
30497
+ const TOL = 2;
30498
+ const sx = minX < M - TOL ? M - minX : 0;
30499
+ const sy = minY < M - TOL ? M - minY : 0;
30500
+ const shifted = sx !== 0 || sy !== 0;
30501
+ return {
30502
+ nodes: shifted ? nodes.map((n2) => ({ ...n2, x: n2.x + sx, y: n2.y + sy })) : nodes,
30503
+ edges: shifted ? edges.map((e) => ({
30504
+ ...e,
30505
+ points: e.points.map((p) => ({ x: p.x + sx, y: p.y + sy }))
30506
+ })) : edges,
30507
+ groups: shifted ? groups.map((gr) => ({ ...gr, x: gr.x + sx, y: gr.y + sy })) : groups,
30508
+ width: maxX + sx + M,
30509
+ height: maxY + sy + M
30510
+ };
30511
+ }
30212
30512
  function place(cfg) {
30213
30513
  const r = cfg.seed === void 0 ? null : rng2(cfg.seed + 1);
30214
30514
  const ord = (a) => r ? shuffle(a, r) : a.slice();
@@ -30347,6 +30647,7 @@ function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
30347
30647
  height: gg.height ?? 600
30348
30648
  };
30349
30649
  }
30650
+ if (allPinned) return placePinned(pinned);
30350
30651
  const n = parsed.nodes.length;
30351
30652
  const seedCount = opts?.seeds ?? (n <= 12 ? 80 : n <= 22 ? 40 : n <= 35 ? 22 : 10);
30352
30653
  const REFINE_K = opts?.refineK ?? 6;
@@ -30541,7 +30842,7 @@ function computeNodeSize(node, reserveValueRow) {
30541
30842
  }
30542
30843
  totalRenderedLines = Math.min(totalRenderedLines, MAX_DESC_LINES2);
30543
30844
  const descriptionHeight = totalRenderedLines * DESC_FONT_SIZE2 * DESC_LINE_HEIGHT2;
30544
- const totalHeight = labelHeight + SEPARATOR_GAP5 + DESC_PADDING + descriptionHeight + DESC_PADDING + (reserveValueRow ? VALUE_ROW_H : 0);
30845
+ const totalHeight = labelHeight + SEPARATOR_GAP4 + DESC_PADDING + descriptionHeight + DESC_PADDING + (reserveValueRow ? VALUE_ROW_H : 0);
30545
30846
  return { width: w, height: Math.max(NODE_HEIGHT, totalHeight) };
30546
30847
  }
30547
30848
  async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
@@ -30670,7 +30971,7 @@ function applyParallelEdgeOffsets(layout) {
30670
30971
  }))
30671
30972
  };
30672
30973
  }
30673
- var MARGIN4, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP5, MAX_DESC_LINES2, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
30974
+ var MARGIN4, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
30674
30975
  var init_layout5 = __esm({
30675
30976
  "src/boxes-and-lines/layout.ts"() {
30676
30977
  "use strict";
@@ -30686,13 +30987,13 @@ var init_layout5 = __esm({
30686
30987
  DESC_FONT_SIZE2 = 10;
30687
30988
  DESC_LINE_HEIGHT2 = 1.4;
30688
30989
  DESC_PADDING = 8;
30689
- SEPARATOR_GAP5 = 4;
30990
+ SEPARATOR_GAP4 = 4;
30690
30991
  MAX_DESC_LINES2 = 6;
30691
30992
  MAX_LABEL_LINES = 3;
30692
30993
  LABEL_LINE_HEIGHT = 1.3;
30693
30994
  LABEL_PAD = 12;
30694
30995
  VALUE_ROW_FONT = 11;
30695
- VALUE_ROW_H = SEPARATOR_GAP5 + VALUE_ROW_FONT * DESC_LINE_HEIGHT2 + DESC_PADDING;
30996
+ VALUE_ROW_H = SEPARATOR_GAP4 + VALUE_ROW_FONT * DESC_LINE_HEIGHT2 + DESC_PADDING;
30696
30997
  }
30697
30998
  });
30698
30999
 
@@ -31454,11 +31755,11 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
31454
31755
  });
31455
31756
  }
31456
31757
  for (const edge of renderLayout.edges) {
31457
- mainG.append("path").attr("class", "mindmap-edge").attr("d", edge.path).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", EDGE_STROKE_WIDTH6).attr("stroke-opacity", 0.5);
31758
+ mainG.append("path").attr("class", "mindmap-edge").attr("d", edge.path).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", EDGE_STROKE_WIDTH).attr("stroke-opacity", 0.5);
31458
31759
  }
31459
31760
  for (const node of renderLayout.nodes) {
31460
31761
  const isRoot = node.radius === 0 && renderLayout.nodes.indexOf(node) === 0;
31461
- const strokeW = isRoot ? ROOT_STROKE_WIDTH : NODE_STROKE_WIDTH6;
31762
+ const strokeW = isRoot ? ROOT_STROKE_WIDTH : NODE_STROKE_WIDTH;
31462
31763
  const effectiveColor = options?.colorByDepth ? depthColor(node.depth, palette) : node.color;
31463
31764
  const fill2 = nodeFill4(
31464
31765
  palette,
@@ -31541,7 +31842,7 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
31541
31842
  const clipId = `collapse-clip-${node.id}`;
31542
31843
  const defs = mainG.append("defs");
31543
31844
  defs.append("clipPath").attr("id", clipId).append("rect").attr("x", node.x).attr("y", node.y).attr("width", node.width).attr("height", node.height).attr("rx", NODE_RADIUS).attr("ry", NODE_RADIUS);
31544
- nodeG.append("rect").attr("class", "collapse-bar").attr("x", node.x).attr("y", node.y + node.height - COLLAPSE_BAR_HEIGHT4).attr("width", node.width).attr("height", COLLAPSE_BAR_HEIGHT4).attr("fill", stroke2).attr("clip-path", `url(#${clipId})`);
31845
+ nodeG.append("rect").attr("class", "collapse-bar").attr("x", node.x).attr("y", node.y + node.height - COLLAPSE_BAR_HEIGHT).attr("width", node.width).attr("height", COLLAPSE_BAR_HEIGHT).attr("fill", stroke2).attr("clip-path", `url(#${clipId})`);
31545
31846
  }
31546
31847
  if (onClickItem) {
31547
31848
  nodeG.style("cursor", "pointer").on("click", (event) => {
@@ -31589,7 +31890,7 @@ function renderMindmapForExport(content, theme, palette) {
31589
31890
  return extractExportSvg(container, theme);
31590
31891
  });
31591
31892
  }
31592
- var DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT4, NODE_RADIUS, ROOT_STROKE_WIDTH, NODE_STROKE_WIDTH6, EDGE_STROKE_WIDTH6, COLLAPSE_BAR_HEIGHT4, DEPTH_COLOR_KEYS;
31893
+ var DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT4, NODE_RADIUS, ROOT_STROKE_WIDTH, DEPTH_COLOR_KEYS;
31593
31894
  var init_renderer7 = __esm({
31594
31895
  "src/mindmap/renderer.ts"() {
31595
31896
  "use strict";
@@ -31606,6 +31907,7 @@ var init_renderer7 = __esm({
31606
31907
  init_legend_layout();
31607
31908
  init_title_constants();
31608
31909
  init_scaling();
31910
+ init_visual_conventions();
31609
31911
  DIAGRAM_PADDING7 = 20;
31610
31912
  TITLE_HEIGHT4 = 30;
31611
31913
  SINGLE_LABEL_HEIGHT2 = 28;
@@ -31613,9 +31915,6 @@ var init_renderer7 = __esm({
31613
31915
  DESC_LINE_HEIGHT4 = 14;
31614
31916
  NODE_RADIUS = 6;
31615
31917
  ROOT_STROKE_WIDTH = 2.5;
31616
- NODE_STROKE_WIDTH6 = 1.5;
31617
- EDGE_STROKE_WIDTH6 = 1.5;
31618
- COLLAPSE_BAR_HEIGHT4 = 6;
31619
31918
  DEPTH_COLOR_KEYS = [
31620
31919
  "red",
31621
31920
  "orange",
@@ -32844,10 +33143,10 @@ function computeC4NodeDimensions(el, options) {
32844
33143
  const metaEntries = collectCardMetadata(el.metadata);
32845
33144
  if (metaEntries.length > 0) {
32846
33145
  height2 += DIVIDER_GAP;
32847
- height2 += metaEntries.length * META_LINE_HEIGHT5;
33146
+ height2 += metaEntries.length * META_LINE_HEIGHT4;
32848
33147
  const maxMetaWidth = Math.max(
32849
33148
  ...metaEntries.map(
32850
- (e) => measureText(`${e.key}: ${e.value}`, META_FONT_SIZE5) + CARD_H_PAD3 * 2
33149
+ (e) => measureText(`${e.key}: ${e.value}`, META_FONT_SIZE4) + CARD_H_PAD3 * 2
32851
33150
  )
32852
33151
  );
32853
33152
  if (maxMetaWidth > width) width = Math.min(MAX_NODE_WIDTH, maxMetaWidth);
@@ -34124,7 +34423,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
34124
34423
  height: totalHeight
34125
34424
  };
34126
34425
  }
34127
- var gNode, gEdge, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, NAME_FONT_SIZE, DESC_LINE_HEIGHT5, DESC_FONT_SIZE4, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT5, META_FONT_SIZE5, MARGIN6, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
34426
+ var gNode, gEdge, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, NAME_FONT_SIZE, DESC_LINE_HEIGHT5, DESC_FONT_SIZE4, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT4, META_FONT_SIZE4, MARGIN6, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
34128
34427
  var init_layout8 = __esm({
34129
34428
  "src/c4/layout.ts"() {
34130
34429
  "use strict";
@@ -34142,8 +34441,8 @@ var init_layout8 = __esm({
34142
34441
  DESC_FONT_SIZE4 = 11;
34143
34442
  CARD_V_PAD3 = 14;
34144
34443
  CARD_H_PAD3 = 20;
34145
- META_LINE_HEIGHT5 = 16;
34146
- META_FONT_SIZE5 = 11;
34444
+ META_LINE_HEIGHT4 = 16;
34445
+ META_FONT_SIZE4 = 11;
34147
34446
  MARGIN6 = 40;
34148
34447
  BOUNDARY_PAD = 40;
34149
34448
  GROUP_BOUNDARY_PAD = 24;
@@ -34266,7 +34565,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
34266
34565
  const bidir = hasBidirectionalMarkers(edge.arrowType);
34267
34566
  const pathD = lineGenerator4(edge.points);
34268
34567
  if (pathD) {
34269
- const pathEl = edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH7).attr("class", "c4-edge").attr("marker-end", "url(#c4-arrow-end)");
34568
+ const pathEl = edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH).attr("class", "c4-edge").attr("marker-end", "url(#c4-arrow-end)");
34270
34569
  if (dashed) {
34271
34570
  pathEl.attr("stroke-dasharray", "6 3");
34272
34571
  }
@@ -34332,7 +34631,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
34332
34631
  palette.textOnFillLight,
34333
34632
  palette.textOnFillDark
34334
34633
  );
34335
- nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS4).attr("ry", CARD_RADIUS4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH7);
34634
+ nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS).attr("ry", CARD_RADIUS).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH);
34336
34635
  let yPos = -h / 2 + CARD_V_PAD4;
34337
34636
  const typeLabel = `\xAB${node.type}\xBB`;
34338
34637
  nodeG.append("text").attr("x", 0).attr("y", yPos + TYPE_FONT_SIZE / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("fill", onFillText).attr("font-size", TYPE_FONT_SIZE).attr("font-style", "italic").text(typeLabel);
@@ -34376,7 +34675,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
34376
34675
  }
34377
34676
  if (node.drillable) {
34378
34677
  const clipId = `clip-drill-${node.id.replace(/\s+/g, "-")}`;
34379
- nodeG.append("clipPath").attr("id", clipId).append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS4);
34678
+ nodeG.append("clipPath").attr("id", clipId).append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS);
34380
34679
  nodeG.append("rect").attr("x", -w / 2).attr("y", h / 2 - DRILL_BAR_HEIGHT).attr("width", w).attr("height", DRILL_BAR_HEIGHT).attr("fill", solid ? onFillText : stroke2).attr("clip-path", `url(#${clipId})`).attr("class", "c4-drill-bar");
34381
34680
  }
34382
34681
  }
@@ -34436,14 +34735,14 @@ function drawCylinderCard(nodeG, w, h, fill2, stroke2, dashed) {
34436
34735
  `A ${w / 2} ${ry} 0 0 1 ${-w / 2} ${h / 2 - ry}`,
34437
34736
  "Z"
34438
34737
  ].join(" ");
34439
- const el = nodeG.append("path").attr("d", path).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH7);
34738
+ const el = nodeG.append("path").attr("d", path).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH);
34440
34739
  if (dashed) {
34441
34740
  el.attr("stroke-dasharray", "6 3");
34442
34741
  }
34443
- nodeG.append("ellipse").attr("cx", 0).attr("cy", -h / 2 + ry).attr("rx", w / 2).attr("ry", ry).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH7);
34742
+ nodeG.append("ellipse").attr("cx", 0).attr("cy", -h / 2 + ry).attr("rx", w / 2).attr("ry", ry).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH);
34444
34743
  }
34445
34744
  function drawCardRect(nodeG, w, h, fill2, stroke2, dashed) {
34446
- const el = nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS4).attr("ry", CARD_RADIUS4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH7);
34745
+ const el = nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS).attr("ry", CARD_RADIUS).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH);
34447
34746
  if (dashed) {
34448
34747
  el.attr("stroke-dasharray", "6 3");
34449
34748
  }
@@ -34463,7 +34762,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
34463
34762
  const bidir = hasBidirectionalMarkers(edge.arrowType);
34464
34763
  const pathD = lineGenerator4(edge.points);
34465
34764
  if (pathD) {
34466
- const pathEl = edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH7).attr("class", "c4-edge").attr("marker-end", "url(#c4-arrow-end)");
34765
+ const pathEl = edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH).attr("class", "c4-edge").attr("marker-end", "url(#c4-arrow-end)");
34467
34766
  if (dashed) {
34468
34767
  pathEl.attr("stroke-dasharray", "6 3");
34469
34768
  }
@@ -34958,13 +35257,13 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
34958
35257
  nodeG.append("line").attr("x1", -w / 2 + CARD_H_PAD4 / 2).attr("y1", yPos).attr("x2", w / 2 - CARD_H_PAD4 / 2).attr("y2", yPos).attr("stroke", solid ? onFillText : stroke2).attr("stroke-width", 0.5).attr("stroke-opacity", 0.4);
34959
35258
  yPos += DIVIDER_GAP2;
34960
35259
  const maxKeyWidth = Math.max(
34961
- ...metaEntries.map((e) => measureText(`${e.key}: `, META_FONT_SIZE6))
35260
+ ...metaEntries.map((e) => measureText(`${e.key}: `, META_FONT_SIZE2))
34962
35261
  );
34963
35262
  const valueX = -w / 2 + CARD_H_PAD4 + maxKeyWidth;
34964
35263
  for (const entry of metaEntries) {
34965
- nodeG.append("text").attr("x", -w / 2 + CARD_H_PAD4).attr("y", yPos + META_FONT_SIZE6 / 2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("fill", onFillText).attr("font-size", META_FONT_SIZE6).text(`${entry.key}:`);
34966
- nodeG.append("text").attr("x", valueX).attr("y", yPos + META_FONT_SIZE6 / 2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("fill", onFillText).attr("font-size", META_FONT_SIZE6).text(entry.value);
34967
- yPos += META_LINE_HEIGHT6;
35264
+ nodeG.append("text").attr("x", -w / 2 + CARD_H_PAD4).attr("y", yPos + META_FONT_SIZE2 / 2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("fill", onFillText).attr("font-size", META_FONT_SIZE2).text(`${entry.key}:`);
35265
+ nodeG.append("text").attr("x", valueX).attr("y", yPos + META_FONT_SIZE2 / 2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("fill", onFillText).attr("font-size", META_FONT_SIZE2).text(entry.value);
35266
+ yPos += META_LINE_HEIGHT2;
34968
35267
  }
34969
35268
  }
34970
35269
  } else {
@@ -34991,7 +35290,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
34991
35290
  }
34992
35291
  if (node.drillable) {
34993
35292
  const clipId = `clip-drill-${node.id.replace(/\s+/g, "-")}`;
34994
- nodeG.append("clipPath").attr("id", clipId).append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS4);
35293
+ nodeG.append("clipPath").attr("id", clipId).append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", CARD_RADIUS);
34995
35294
  nodeG.append("rect").attr("x", -w / 2).attr("y", h / 2 - DRILL_BAR_HEIGHT).attr("width", w).attr("height", DRILL_BAR_HEIGHT).attr("fill", solid ? onFillText : stroke2).attr("clip-path", `url(#${clipId})`).attr("class", "c4-drill-bar");
34996
35295
  }
34997
35296
  }
@@ -35120,7 +35419,7 @@ function renderC4DeploymentForExport(content, theme, palette) {
35120
35419
  document.body.removeChild(el);
35121
35420
  }
35122
35421
  }
35123
- var DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE6, TECH_FONT_SIZE, EDGE_STROKE_WIDTH7, NODE_STROKE_WIDTH7, CARD_RADIUS4, CARD_H_PAD4, CARD_V_PAD4, TYPE_LABEL_HEIGHT2, DIVIDER_GAP2, NAME_HEIGHT2, META_FONT_SIZE6, META_LINE_HEIGHT6, BOUNDARY_LABEL_FONT_SIZE, BOUNDARY_STROKE_WIDTH, BOUNDARY_RADIUS, DRILL_BAR_HEIGHT, CYLINDER_RY, PERSON_HEAD_R, PERSON_ARM_SPAN, PERSON_LEG_SPAN, PERSON_ICON_W, PERSON_SW, lineGenerator4;
35422
+ var DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE6, TECH_FONT_SIZE, CARD_H_PAD4, CARD_V_PAD4, TYPE_LABEL_HEIGHT2, DIVIDER_GAP2, NAME_HEIGHT2, BOUNDARY_LABEL_FONT_SIZE, BOUNDARY_STROKE_WIDTH, BOUNDARY_RADIUS, DRILL_BAR_HEIGHT, CYLINDER_RY, PERSON_HEAD_R, PERSON_ARM_SPAN, PERSON_LEG_SPAN, PERSON_ICON_W, PERSON_SW, lineGenerator4;
35124
35423
  var init_renderer9 = __esm({
35125
35424
  "src/c4/renderer.ts"() {
35126
35425
  "use strict";
@@ -35134,6 +35433,7 @@ var init_renderer9 = __esm({
35134
35433
  init_legend_constants();
35135
35434
  init_legend_integration();
35136
35435
  init_title_constants();
35436
+ init_visual_conventions();
35137
35437
  DIAGRAM_PADDING8 = 20;
35138
35438
  MAX_SCALE5 = 3;
35139
35439
  TITLE_HEIGHT6 = 30;
@@ -35143,16 +35443,11 @@ var init_renderer9 = __esm({
35143
35443
  DESC_LINE_HEIGHT6 = 16;
35144
35444
  EDGE_LABEL_FONT_SIZE6 = 11;
35145
35445
  TECH_FONT_SIZE = 10;
35146
- EDGE_STROKE_WIDTH7 = 1.5;
35147
- NODE_STROKE_WIDTH7 = 1.5;
35148
- CARD_RADIUS4 = 6;
35149
35446
  CARD_H_PAD4 = 20;
35150
35447
  CARD_V_PAD4 = 14;
35151
35448
  TYPE_LABEL_HEIGHT2 = 18;
35152
35449
  DIVIDER_GAP2 = 6;
35153
35450
  NAME_HEIGHT2 = 20;
35154
- META_FONT_SIZE6 = 11;
35155
- META_LINE_HEIGHT6 = 16;
35156
35451
  BOUNDARY_LABEL_FONT_SIZE = 12;
35157
35452
  BOUNDARY_STROKE_WIDTH = 1.5;
35158
35453
  BOUNDARY_RADIUS = 8;
@@ -35557,7 +35852,7 @@ function nodeFill6(palette, isDark, shape, nodeColor2, isEndTerminal, colorOff,
35557
35852
  function nodeStroke6(palette, shape, nodeColor2, isEndTerminal, colorOff) {
35558
35853
  return nodeColor2 ?? shapeDefaultColor(shape, palette, isEndTerminal, colorOff);
35559
35854
  }
35560
- function renderTerminal(g, node, palette, isDark, isEnd, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8) {
35855
+ function renderTerminal(g, node, palette, isDark, isEnd, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH) {
35561
35856
  const w = node.width;
35562
35857
  const h = node.height;
35563
35858
  const rx = h / 2;
@@ -35569,7 +35864,7 @@ function renderTerminal(g, node, palette, isDark, isEnd, colorOff, solid, sNodeS
35569
35864
  nodeStroke6(palette, node.shape, node.color, isEnd, colorOff)
35570
35865
  ).attr("stroke-width", sNodeStrokeWidth);
35571
35866
  }
35572
- function renderProcess(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8) {
35867
+ function renderProcess(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH) {
35573
35868
  const w = node.width;
35574
35869
  const h = node.height;
35575
35870
  g.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", 3).attr("ry", 3).attr(
@@ -35588,7 +35883,7 @@ function renderProcess(g, node, palette, isDark, colorOff, solid, sNodeStrokeWid
35588
35883
  nodeStroke6(palette, node.shape, node.color, void 0, colorOff)
35589
35884
  ).attr("stroke-width", sNodeStrokeWidth);
35590
35885
  }
35591
- function renderDecision(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8) {
35886
+ function renderDecision(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH) {
35592
35887
  const w = node.width / 2;
35593
35888
  const h = node.height / 2;
35594
35889
  const points = [`${0},${-h}`, `${w},${0}`, `${0},${h}`, `${-w},${0}`].join(
@@ -35610,7 +35905,7 @@ function renderDecision(g, node, palette, isDark, colorOff, solid, sNodeStrokeWi
35610
35905
  nodeStroke6(palette, node.shape, node.color, void 0, colorOff)
35611
35906
  ).attr("stroke-width", sNodeStrokeWidth);
35612
35907
  }
35613
- function renderIO(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8, sIoSkew = IO_SKEW) {
35908
+ function renderIO(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH, sIoSkew = IO_SKEW) {
35614
35909
  const w = node.width / 2;
35615
35910
  const h = node.height / 2;
35616
35911
  const sk = sIoSkew;
@@ -35636,7 +35931,7 @@ function renderIO(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth =
35636
35931
  nodeStroke6(palette, node.shape, node.color, void 0, colorOff)
35637
35932
  ).attr("stroke-width", sNodeStrokeWidth);
35638
35933
  }
35639
- function renderSubroutine(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8, sSubroutineInset = SUBROUTINE_INSET) {
35934
+ function renderSubroutine(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH, sSubroutineInset = SUBROUTINE_INSET) {
35640
35935
  const w = node.width;
35641
35936
  const h = node.height;
35642
35937
  const s = nodeStroke6(palette, node.shape, node.color, void 0, colorOff);
@@ -35654,7 +35949,7 @@ function renderSubroutine(g, node, palette, isDark, colorOff, solid, sNodeStroke
35654
35949
  g.append("line").attr("x1", -w / 2 + sSubroutineInset).attr("y1", -h / 2).attr("x2", -w / 2 + sSubroutineInset).attr("y2", h / 2).attr("stroke", innerStroke).attr("stroke-width", sNodeStrokeWidth);
35655
35950
  g.append("line").attr("x1", w / 2 - sSubroutineInset).attr("y1", -h / 2).attr("x2", w / 2 - sSubroutineInset).attr("y2", h / 2).attr("stroke", innerStroke).attr("stroke-width", sNodeStrokeWidth);
35656
35951
  }
35657
- function renderDocument(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8, sDocWaveHeight = DOC_WAVE_HEIGHT) {
35952
+ function renderDocument(g, node, palette, isDark, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH, sDocWaveHeight = DOC_WAVE_HEIGHT) {
35658
35953
  const w = node.width;
35659
35954
  const h = node.height;
35660
35955
  const waveH = sDocWaveHeight;
@@ -35685,7 +35980,7 @@ function renderDocument(g, node, palette, isDark, colorOff, solid, sNodeStrokeWi
35685
35980
  nodeStroke6(palette, node.shape, node.color, void 0, colorOff)
35686
35981
  ).attr("stroke-width", sNodeStrokeWidth);
35687
35982
  }
35688
- function renderNodeShape(g, node, palette, isDark, endTerminalIds, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH8, sIoSkew = IO_SKEW, sSubroutineInset = SUBROUTINE_INSET, sDocWaveHeight = DOC_WAVE_HEIGHT) {
35983
+ function renderNodeShape(g, node, palette, isDark, endTerminalIds, colorOff, solid, sNodeStrokeWidth = NODE_STROKE_WIDTH, sIoSkew = IO_SKEW, sSubroutineInset = SUBROUTINE_INSET, sDocWaveHeight = DOC_WAVE_HEIGHT) {
35689
35984
  switch (node.shape) {
35690
35985
  case "terminal":
35691
35986
  renderTerminal(
@@ -35772,8 +36067,8 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
35772
36067
  const sTitleY = ctx.structural(TITLE_Y);
35773
36068
  const sNodeFontSize = ctx.text(NODE_FONT_SIZE2);
35774
36069
  const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE7);
35775
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH8);
35776
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH8);
36070
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
36071
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
35777
36072
  const sArrowheadW = ctx.structural(ARROWHEAD_W3);
35778
36073
  const sArrowheadH = ctx.structural(ARROWHEAD_H3);
35779
36074
  const sIoSkew = ctx.structural(IO_SKEW);
@@ -35997,7 +36292,7 @@ function renderFlowchartForExport(content, theme, palette) {
35997
36292
  document.body.removeChild(container);
35998
36293
  }
35999
36294
  }
36000
- var DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2, EDGE_LABEL_FONT_SIZE7, EDGE_STROKE_WIDTH8, NODE_STROKE_WIDTH8, ARROWHEAD_W3, ARROWHEAD_H3, IO_SKEW, SUBROUTINE_INSET, DOC_WAVE_HEIGHT;
36295
+ var DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2, EDGE_LABEL_FONT_SIZE7, ARROWHEAD_W3, ARROWHEAD_H3, IO_SKEW, SUBROUTINE_INSET, DOC_WAVE_HEIGHT;
36001
36296
  var init_flowchart_renderer = __esm({
36002
36297
  "src/graph/flowchart-renderer.ts"() {
36003
36298
  "use strict";
@@ -36012,12 +36307,11 @@ var init_flowchart_renderer = __esm({
36012
36307
  init_scaling();
36013
36308
  init_text_measure();
36014
36309
  init_note_box();
36310
+ init_visual_conventions();
36015
36311
  DIAGRAM_PADDING9 = 20;
36016
36312
  MAX_SCALE6 = 3;
36017
36313
  NODE_FONT_SIZE2 = 13;
36018
36314
  EDGE_LABEL_FONT_SIZE7 = 11;
36019
- EDGE_STROKE_WIDTH8 = 1.5;
36020
- NODE_STROKE_WIDTH8 = 1.5;
36021
36315
  ARROWHEAD_W3 = 10;
36022
36316
  ARROWHEAD_H3 = 7;
36023
36317
  IO_SKEW = 15;
@@ -37002,7 +37296,7 @@ function hasRoles(node) {
37002
37296
  }
37003
37297
  function computeNodeWidth2(node, expanded, options) {
37004
37298
  const badgeVal = node.computedConcurrentInvocations === 0 && node.computedInstances > 1 ? node.computedInstances : 0;
37005
- const badgeWidth = badgeVal > 0 ? measureText(`${badgeVal}x`, META_FONT_SIZE7) + 2 * CHAR_WIDTH_RATIO * NODE_FONT_SIZE3 : 0;
37299
+ const badgeWidth = badgeVal > 0 ? measureText(`${badgeVal}x`, META_FONT_SIZE5) + 2 * CHAR_WIDTH_RATIO * NODE_FONT_SIZE3 : 0;
37006
37300
  const labelWidth2 = measureText(node.label, NODE_FONT_SIZE3) + badgeWidth + PADDING_X3;
37007
37301
  const allKeys = [];
37008
37302
  if (node.computedRps > 0) allKeys.push("RPS");
@@ -37049,7 +37343,7 @@ function computeNodeWidth2(node, expanded, options) {
37049
37343
  }
37050
37344
  if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2, labelWidth2);
37051
37345
  const keyColWidth = Math.max(
37052
- ...allKeys.map((k) => measureText(`${k}: `, META_FONT_SIZE7))
37346
+ ...allKeys.map((k) => measureText(`${k}: `, META_FONT_SIZE5))
37053
37347
  );
37054
37348
  let maxRowWidth = 0;
37055
37349
  if (node.computedRps > 0) {
@@ -37062,7 +37356,7 @@ function computeNodeWidth2(node, expanded, options) {
37062
37356
  const rpsVal = effectiveCap > 0 && !node.isEdge ? `${formatRpsShort(node.computedRps)} / ${formatRpsShort(effectiveCap)}` : formatRps(node.computedRps);
37063
37357
  maxRowWidth = Math.max(
37064
37358
  maxRowWidth,
37065
- keyColWidth + measureText(rpsVal, META_FONT_SIZE7)
37359
+ keyColWidth + measureText(rpsVal, META_FONT_SIZE5)
37066
37360
  );
37067
37361
  }
37068
37362
  if (expanded) {
@@ -37079,7 +37373,7 @@ function computeNodeWidth2(node, expanded, options) {
37079
37373
  const valStr = p.key === "max-rps" || p.key === "ratelimit-rps" ? formatRpsShort(numVal) : p.key === "latency-ms" || p.key === "cb-latency-threshold-ms" || p.key === "duration-ms" || p.key === "cold-start-ms" ? formatMs(numVal) : PCT_KEYS.includes(p.key) ? `${numVal}%` : String(p.value);
37080
37374
  maxRowWidth = Math.max(
37081
37375
  maxRowWidth,
37082
- keyColWidth + measureText(valStr, META_FONT_SIZE7)
37376
+ keyColWidth + measureText(valStr, META_FONT_SIZE5)
37083
37377
  );
37084
37378
  }
37085
37379
  }
@@ -37090,7 +37384,7 @@ function computeNodeWidth2(node, expanded, options) {
37090
37384
  if (ms > 0) {
37091
37385
  maxRowWidth = Math.max(
37092
37386
  maxRowWidth,
37093
- keyColWidth + measureText(formatMs(ms), META_FONT_SIZE7)
37387
+ keyColWidth + measureText(formatMs(ms), META_FONT_SIZE5)
37094
37388
  );
37095
37389
  }
37096
37390
  }
@@ -37101,37 +37395,37 @@ function computeNodeWidth2(node, expanded, options) {
37101
37395
  const combinedVal = `${formatMs(perc.p90)} / ${formatMs(threshold)}`;
37102
37396
  maxRowWidth = Math.max(
37103
37397
  maxRowWidth,
37104
- keyColWidth + measureText(combinedVal, META_FONT_SIZE7)
37398
+ keyColWidth + measureText(combinedVal, META_FONT_SIZE5)
37105
37399
  );
37106
37400
  }
37107
37401
  }
37108
37402
  if (node.computedUptime < 1) {
37109
37403
  maxRowWidth = Math.max(
37110
37404
  maxRowWidth,
37111
- keyColWidth + measureText(formatUptime(node.computedUptime), META_FONT_SIZE7)
37405
+ keyColWidth + measureText(formatUptime(node.computedUptime), META_FONT_SIZE5)
37112
37406
  );
37113
37407
  }
37114
37408
  if (node.computedAvailability < 1) {
37115
37409
  maxRowWidth = Math.max(
37116
37410
  maxRowWidth,
37117
- keyColWidth + measureText(formatUptime(node.computedAvailability), META_FONT_SIZE7)
37411
+ keyColWidth + measureText(formatUptime(node.computedAvailability), META_FONT_SIZE5)
37118
37412
  );
37119
37413
  }
37120
37414
  if (node.computedCbState === "open") {
37121
37415
  maxRowWidth = Math.max(
37122
37416
  maxRowWidth,
37123
- measureText("CB: OPEN", META_FONT_SIZE7) + 8
37417
+ measureText("CB: OPEN", META_FONT_SIZE5) + 8
37124
37418
  );
37125
37419
  }
37126
37420
  }
37127
- const DESC_MAX_WIDTH2 = 120 * CHAR_WIDTH_RATIO * META_FONT_SIZE7;
37421
+ const DESC_MAX_WIDTH2 = 120 * CHAR_WIDTH_RATIO * META_FONT_SIZE5;
37128
37422
  const descLines = expanded && node.description && !node.isEdge ? node.description : [];
37129
37423
  let descWidth = 0;
37130
37424
  for (const dl of descLines) {
37131
- const truncated = truncateText(dl, META_FONT_SIZE7, DESC_MAX_WIDTH2);
37425
+ const truncated = truncateText(dl, META_FONT_SIZE5, DESC_MAX_WIDTH2);
37132
37426
  descWidth = Math.max(
37133
37427
  descWidth,
37134
- measureText(truncated, META_FONT_SIZE7) + PADDING_X3
37428
+ measureText(truncated, META_FONT_SIZE5) + PADDING_X3
37135
37429
  );
37136
37430
  }
37137
37431
  return Math.max(MIN_NODE_WIDTH2, labelWidth2, maxRowWidth + 20, descWidth);
@@ -37141,17 +37435,17 @@ function computeNodeHeight2(node, expanded, options) {
37141
37435
  const computedCount = countComputedRows(node, expanded);
37142
37436
  const hasRps = node.computedRps > 0;
37143
37437
  const descLineCount = expanded && node.description && !node.isEdge ? node.description.length : 0;
37144
- const descH = descLineCount * META_LINE_HEIGHT7;
37438
+ const descH = descLineCount * META_LINE_HEIGHT5;
37145
37439
  if (propCount === 0 && computedCount === 0 && !hasRps)
37146
37440
  return NODE_HEADER_HEIGHT + descH + NODE_PAD_BOTTOM;
37147
37441
  let h = NODE_HEADER_HEIGHT + descH + NODE_SEPARATOR_GAP;
37148
37442
  const computedSectionCount = (hasRps ? 1 : 0) + computedCount;
37149
- h += computedSectionCount * META_LINE_HEIGHT7;
37443
+ h += computedSectionCount * META_LINE_HEIGHT5;
37150
37444
  if (computedSectionCount > 0 && propCount > 0) h += NODE_SEPARATOR_GAP;
37151
- h += propCount * META_LINE_HEIGHT7;
37445
+ h += propCount * META_LINE_HEIGHT5;
37152
37446
  if (hasRoles(node)) h += ROLE_DOT_ROW;
37153
37447
  h += NODE_PAD_BOTTOM;
37154
- if (node.id.startsWith("[")) h += COLLAPSE_BAR_HEIGHT5;
37448
+ if (node.id.startsWith("[")) h += COLLAPSE_BAR_HEIGHT3;
37155
37449
  return h;
37156
37450
  }
37157
37451
  function formatRps(rps) {
@@ -37486,20 +37780,20 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
37486
37780
  height: totalHeight
37487
37781
  };
37488
37782
  }
37489
- var MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT7, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT5, NODE_FONT_SIZE3, META_FONT_SIZE7, EDGE_LABEL_FONT_SIZE8, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP;
37783
+ var MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT5, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT3, NODE_FONT_SIZE3, META_FONT_SIZE5, EDGE_LABEL_FONT_SIZE8, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP;
37490
37784
  var init_layout10 = __esm({
37491
37785
  "src/infra/layout.ts"() {
37492
37786
  "use strict";
37493
37787
  init_text_measure();
37494
37788
  MIN_NODE_WIDTH2 = 140;
37495
37789
  NODE_HEADER_HEIGHT = 28;
37496
- META_LINE_HEIGHT7 = 14;
37790
+ META_LINE_HEIGHT5 = 14;
37497
37791
  NODE_SEPARATOR_GAP = 4;
37498
37792
  NODE_PAD_BOTTOM = 10;
37499
37793
  ROLE_DOT_ROW = 12;
37500
- COLLAPSE_BAR_HEIGHT5 = 6;
37794
+ COLLAPSE_BAR_HEIGHT3 = 6;
37501
37795
  NODE_FONT_SIZE3 = 13;
37502
- META_FONT_SIZE7 = 10;
37796
+ META_FONT_SIZE5 = 10;
37503
37797
  EDGE_LABEL_FONT_SIZE8 = 11;
37504
37798
  PADDING_X3 = 24;
37505
37799
  GROUP_PADDING2 = 20;
@@ -37605,19 +37899,19 @@ import * as d3Shape8 from "d3-shape";
37605
37899
  function buildScaledConstants(ctx) {
37606
37900
  return {
37607
37901
  sNodeFontSize: ctx.text(NODE_FONT_SIZE4),
37608
- sMetaFontSize: ctx.text(META_FONT_SIZE8),
37609
- sMetaLineHeight: ctx.structural(META_LINE_HEIGHT8),
37902
+ sMetaFontSize: ctx.text(META_FONT_SIZE6),
37903
+ sMetaLineHeight: ctx.structural(META_LINE_HEIGHT6),
37610
37904
  sEdgeLabelFontSize: ctx.text(EDGE_LABEL_FONT_SIZE9),
37611
37905
  sGroupLabelFontSize: ctx.text(GROUP_LABEL_FONT_SIZE2),
37612
37906
  sNodeBorderRadius: ctx.structural(NODE_BORDER_RADIUS),
37613
- sEdgeStrokeWidth: ctx.structural(EDGE_STROKE_WIDTH9),
37614
- sNodeStrokeWidth: ctx.structural(NODE_STROKE_WIDTH9),
37907
+ sEdgeStrokeWidth: ctx.structural(EDGE_STROKE_WIDTH),
37908
+ sNodeStrokeWidth: ctx.structural(NODE_STROKE_WIDTH),
37615
37909
  sOverloadStrokeWidth: ctx.structural(OVERLOAD_STROKE_WIDTH),
37616
37910
  sRoleDotRadius: ctx.structural(ROLE_DOT_RADIUS),
37617
37911
  sNodeSeparatorGap: ctx.structural(NODE_SEPARATOR_GAP2),
37618
37912
  sNodePadBottom: ctx.structural(NODE_PAD_BOTTOM2),
37619
- sCollapseBarHeight: ctx.structural(COLLAPSE_BAR_HEIGHT6),
37620
- sCollapseBarInset: ctx.structural(COLLAPSE_BAR_INSET2),
37913
+ sCollapseBarHeight: ctx.structural(COLLAPSE_BAR_HEIGHT),
37914
+ sCollapseBarInset: ctx.structural(COLLAPSE_BAR_INSET),
37621
37915
  sParticleR: ctx.structural(PARTICLE_R),
37622
37916
  sRejectParticleR: ctx.structural(PARTICLE_R),
37623
37917
  sRejectDropDistance: ctx.structural(REJECT_DROP_DISTANCE),
@@ -37941,7 +38235,7 @@ function isWarning(node) {
37941
38235
  return cap > 0 && node.computedRps / cap > 0.7;
37942
38236
  }
37943
38237
  function truncateDesc(text) {
37944
- return truncateText(text, META_FONT_SIZE8, DESC_MAX_WIDTH);
38238
+ return truncateText(text, META_FONT_SIZE6, DESC_MAX_WIDTH);
37945
38239
  }
37946
38240
  function sloLatencyColor(p90, slo) {
37947
38241
  const t = slo.latencyP90 ?? 0;
@@ -38420,7 +38714,7 @@ function renderNodes(svg, nodes, palette, isDark, animate, expandedNodeIds, acti
38420
38714
  if (!isNodeCollapsed) {
38421
38715
  const expanded = expandedNodeIds?.has(node.id) ?? false;
38422
38716
  const descLines = expanded && node.description && !node.isEdge ? node.description : [];
38423
- const descH = descLines.length * META_LINE_HEIGHT8;
38717
+ const descH = descLines.length * META_LINE_HEIGHT6;
38424
38718
  for (let di = 0; di < descLines.length; di++) {
38425
38719
  const rawLine = descLines[di];
38426
38720
  const processed = preprocessDescriptionLine(rawLine);
@@ -38428,7 +38722,7 @@ function renderNodes(svg, nodes, palette, isDark, animate, expandedNodeIds, acti
38428
38722
  const isTruncated = descTruncated !== processed;
38429
38723
  const textEl = g.append("text").attr("x", node.x).attr(
38430
38724
  "y",
38431
- y + NODE_HEADER_HEIGHT2 + di * META_LINE_HEIGHT8 + META_LINE_HEIGHT8 / 2 + sc.sMetaFontSize * 0.35
38725
+ y + NODE_HEADER_HEIGHT2 + di * META_LINE_HEIGHT6 + META_LINE_HEIGHT6 / 2 + sc.sMetaFontSize * 0.35
38432
38726
  ).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sc.sMetaFontSize).attr("fill", textFill);
38433
38727
  renderInlineText(textEl, descTruncated, palette, sc.sMetaFontSize);
38434
38728
  if (isTruncated) textEl.append("title").text(rawLine);
@@ -38946,7 +39240,7 @@ function parseAndLayoutInfra(content) {
38946
39240
  const layout = layoutInfra(computed);
38947
39241
  return { parsed, computed, layout };
38948
39242
  }
38949
- var NODE_FONT_SIZE4, META_FONT_SIZE8, META_LINE_HEIGHT8, EDGE_LABEL_FONT_SIZE9, GROUP_LABEL_FONT_SIZE2, NODE_BORDER_RADIUS, EDGE_STROKE_WIDTH9, NODE_STROKE_WIDTH9, OVERLOAD_STROKE_WIDTH, ROLE_DOT_RADIUS, NODE_HEADER_HEIGHT2, NODE_SEPARATOR_GAP2, NODE_PAD_BOTTOM2, COLLAPSE_BAR_HEIGHT6, COLLAPSE_BAR_INSET2, LEGEND_FIXED_GAP3, SPEED_BADGE_H_PAD, SPEED_BADGE_V_PAD, SPEED_BADGE_GAP, COLOR_HEALTHY, COLOR_WARNING, COLOR_OVERLOADED, FLOW_SPEED_MIN, FLOW_SPEED_MAX, PARTICLE_R, PARTICLE_COUNT_MIN, PARTICLE_COUNT_MAX, NODE_PULSE_SPEED, NODE_PULSE_OVERLOAD, REJECT_DROP_DISTANCE, REJECT_DURATION_MIN, REJECT_DURATION_MAX, REJECT_COUNT_MIN, REJECT_COUNT_MAX, PROP_DISPLAY, DESC_MAX_CHARS, DESC_MAX_WIDTH, RPS_FORMAT_KEYS, MS_FORMAT_KEYS, PCT_FORMAT_KEYS;
39243
+ var NODE_FONT_SIZE4, META_FONT_SIZE6, META_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE9, GROUP_LABEL_FONT_SIZE2, NODE_BORDER_RADIUS, OVERLOAD_STROKE_WIDTH, ROLE_DOT_RADIUS, NODE_HEADER_HEIGHT2, NODE_SEPARATOR_GAP2, NODE_PAD_BOTTOM2, LEGEND_FIXED_GAP3, SPEED_BADGE_H_PAD, SPEED_BADGE_V_PAD, SPEED_BADGE_GAP, COLOR_HEALTHY, COLOR_WARNING, COLOR_OVERLOADED, FLOW_SPEED_MIN, FLOW_SPEED_MAX, PARTICLE_R, PARTICLE_COUNT_MIN, PARTICLE_COUNT_MAX, NODE_PULSE_SPEED, NODE_PULSE_OVERLOAD, REJECT_DROP_DISTANCE, REJECT_DURATION_MIN, REJECT_DURATION_MAX, REJECT_COUNT_MIN, REJECT_COUNT_MAX, PROP_DISPLAY, DESC_MAX_CHARS, DESC_MAX_WIDTH, RPS_FORMAT_KEYS, MS_FORMAT_KEYS, PCT_FORMAT_KEYS;
38950
39244
  var init_renderer10 = __esm({
38951
39245
  "src/infra/renderer.ts"() {
38952
39246
  "use strict";
@@ -38965,21 +39259,18 @@ var init_renderer10 = __esm({
38965
39259
  init_legend_layout();
38966
39260
  init_title_constants();
38967
39261
  init_scaling();
39262
+ init_visual_conventions();
38968
39263
  NODE_FONT_SIZE4 = 13;
38969
- META_FONT_SIZE8 = 10;
38970
- META_LINE_HEIGHT8 = 14;
39264
+ META_FONT_SIZE6 = 10;
39265
+ META_LINE_HEIGHT6 = 14;
38971
39266
  EDGE_LABEL_FONT_SIZE9 = 11;
38972
39267
  GROUP_LABEL_FONT_SIZE2 = 14;
38973
39268
  NODE_BORDER_RADIUS = 8;
38974
- EDGE_STROKE_WIDTH9 = 1.5;
38975
- NODE_STROKE_WIDTH9 = 1.5;
38976
39269
  OVERLOAD_STROKE_WIDTH = 3;
38977
39270
  ROLE_DOT_RADIUS = 3;
38978
39271
  NODE_HEADER_HEIGHT2 = 28;
38979
39272
  NODE_SEPARATOR_GAP2 = 4;
38980
39273
  NODE_PAD_BOTTOM2 = 10;
38981
- COLLAPSE_BAR_HEIGHT6 = 6;
38982
- COLLAPSE_BAR_INSET2 = 0;
38983
39274
  LEGEND_FIXED_GAP3 = 16;
38984
39275
  SPEED_BADGE_H_PAD = 5;
38985
39276
  SPEED_BADGE_V_PAD = 3;
@@ -39018,7 +39309,7 @@ var init_renderer10 = __esm({
39018
39309
  partitions: "partitions"
39019
39310
  };
39020
39311
  DESC_MAX_CHARS = 120;
39021
- DESC_MAX_WIDTH = DESC_MAX_CHARS * CHAR_WIDTH_RATIO * META_FONT_SIZE8;
39312
+ DESC_MAX_WIDTH = DESC_MAX_CHARS * CHAR_WIDTH_RATIO * META_FONT_SIZE6;
39022
39313
  RPS_FORMAT_KEYS = /* @__PURE__ */ new Set(["max-rps", "ratelimit-rps"]);
39023
39314
  MS_FORMAT_KEYS = /* @__PURE__ */ new Set([
39024
39315
  "latency-ms",
@@ -40807,18 +41098,18 @@ function renderPert(container, resolved, layout, palette, isDark, options = {})
40807
41098
  const sLegendPillHeight = ctx.structural(LEGEND_PILL_HEIGHT);
40808
41099
  const sLegendBlockHeight = showTagLegend ? sLegendTopGap + sLegendPillHeight + sLegendBottomGap : 0;
40809
41100
  const sNodeRadius = ctx.structural(NODE_RADIUS2);
40810
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH10);
41101
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
40811
41102
  const sNodeFontSize = ctx.text(NODE_FONT_SIZE5);
40812
41103
  const sNodeCellFontSize = ctx.text(NODE_CELL_FONT_SIZE2);
40813
41104
  const sNodeTopRowHeight = ctx.structural(NODE_TOP_ROW_HEIGHT);
40814
41105
  const sNodeBottomRowHeight = ctx.structural(NODE_BOTTOM_ROW_HEIGHT);
40815
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH10);
41106
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
40816
41107
  const sArrowheadW = ctx.structural(ARROWHEAD_W4);
40817
41108
  const sArrowheadH = ctx.structural(ARROWHEAD_H4);
40818
- const sContainerRadius = ctx.structural(CONTAINER_RADIUS3);
40819
- const sContainerLabelFontSize = ctx.text(CONTAINER_LABEL_FONT_SIZE4);
40820
- const sContainerHeaderHeight = ctx.structural(CONTAINER_HEADER_HEIGHT3);
40821
- const sCollapseBarHeight = ctx.structural(COLLAPSE_BAR_HEIGHT7);
41109
+ const sContainerRadius = ctx.structural(CONTAINER_RADIUS);
41110
+ const sContainerLabelFontSize = ctx.text(CONTAINER_LABEL_FONT_SIZE);
41111
+ const sContainerHeaderHeight = ctx.structural(CONTAINER_HEADER_HEIGHT);
41112
+ const sCollapseBarHeight = ctx.structural(COLLAPSE_BAR_HEIGHT);
40822
41113
  const sPinIconW = ctx.structural(PIN_ICON_W);
40823
41114
  const sPinIconH = ctx.structural(PIN_ICON_H);
40824
41115
  const scaledWidth = layout.width + sDiagramPad * 2;
@@ -41385,7 +41676,7 @@ function renderGroups2(root, resolved, layout, palette, isDark, collapsedSet, si
41385
41676
  palette.textOnFillDark
41386
41677
  );
41387
41678
  const sNR = sc.nodeRadius ?? NODE_RADIUS2;
41388
- const sCBH = sc.collapseBarHeight ?? COLLAPSE_BAR_HEIGHT7;
41679
+ const sCBH = sc.collapseBarHeight ?? COLLAPSE_BAR_HEIGHT;
41389
41680
  drawTextbookCard(g, {
41390
41681
  width: grp.width,
41391
41682
  height: grp.height,
@@ -41419,10 +41710,10 @@ function renderGroups2(root, resolved, layout, palette, isDark, collapsedSet, si
41419
41710
  g.append("rect").attr("class", "pert-collapse-bar").attr("x", grp.x).attr("y", grp.y + grp.height - sCBH).attr("width", grp.width).attr("height", sCBH).attr("fill", cardBaseColor).attr("clip-path", `url(#${clipId})`);
41420
41711
  continue;
41421
41712
  }
41422
- const sCR = sc.containerRadius ?? CONTAINER_RADIUS3;
41423
- const sCLFS = sc.containerLabelFontSize ?? CONTAINER_LABEL_FONT_SIZE4;
41424
- const sCHH = sc.containerHeaderHeight ?? CONTAINER_HEADER_HEIGHT3;
41425
- const sNSW = sc.nodeStrokeWidth ?? NODE_STROKE_WIDTH10;
41713
+ const sCR = sc.containerRadius ?? CONTAINER_RADIUS;
41714
+ const sCLFS = sc.containerLabelFontSize ?? CONTAINER_LABEL_FONT_SIZE;
41715
+ const sCHH = sc.containerHeaderHeight ?? CONTAINER_HEADER_HEIGHT;
41716
+ const sNSW = sc.nodeStrokeWidth ?? NODE_STROKE_WIDTH;
41426
41717
  g.append("rect").attr("x", grp.x).attr("y", grp.y).attr("width", grp.width).attr("height", grp.height).attr("rx", sCR).attr("ry", sCR).attr("fill", containerFill3).attr("stroke", containerStroke3).attr("stroke-opacity", 0.35).attr("stroke-width", sNSW);
41427
41718
  g.append("text").attr("x", grp.x + grp.width / 2).attr("y", grp.y + sCHH / 2 + sCLFS / 2 - 2).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("fill", palette.text).attr("font-size", sCLFS).attr("font-weight", "bold").text(label);
41428
41719
  }
@@ -41475,7 +41766,7 @@ function renderEdges2(root, resolved, layout, palette, collapsedSet, sc = {}) {
41475
41766
  }
41476
41767
  const path = lineGenerator6(e.points);
41477
41768
  if (!path) continue;
41478
- const sESW = sc.edgeStrokeWidth ?? EDGE_STROKE_WIDTH10;
41769
+ const sESW = sc.edgeStrokeWidth ?? EDGE_STROKE_WIDTH;
41479
41770
  const sELFS = sc.edgeLabelFontSize ?? 10;
41480
41771
  layer.append("path").attr("class", "pert-edge").attr("d", path).attr("fill", "none").attr("stroke", bandColor(band, palette, palette.textMuted)).attr("stroke-width", sESW).attr("marker-end", `url(#${bandArrow(band)})`).attr("data-source", e.source).attr("data-target", e.target).attr("data-critical", String(isCritical)).attr("data-critical-path", String(isCritical)).attr("data-criticality-band", band ?? "");
41481
41772
  const parsedEdge = edgeByKey.get(`${e.source}->${e.target}`);
@@ -41657,7 +41948,7 @@ function computeDurationEmphasis(activities) {
41657
41948
  function drawTextbookCard(g, a) {
41658
41949
  const { width: w, height: h, x, y } = a;
41659
41950
  const sNR = a.sNodeRadius ?? NODE_RADIUS2;
41660
- const sNSW = a.sNodeStrokeWidth ?? NODE_STROKE_WIDTH10;
41951
+ const sNSW = a.sNodeStrokeWidth ?? NODE_STROKE_WIDTH;
41661
41952
  const sTRH = a.sNodeTopRowHeight ?? NODE_TOP_ROW_HEIGHT;
41662
41953
  const sBRH = a.sNodeBottomRowHeight ?? NODE_BOTTOM_ROW_HEIGHT;
41663
41954
  const sNFS = a.sNodeFontSize ?? NODE_FONT_SIZE5;
@@ -41756,7 +42047,7 @@ function drawTextbookCard(g, a) {
41756
42047
  function drawMilestonePill(g, a) {
41757
42048
  const { width: w, height: h, x, y } = a;
41758
42049
  const sNR = a.sNodeRadius ?? NODE_RADIUS2;
41759
- const sNSW = a.sNodeStrokeWidth ?? NODE_STROKE_WIDTH10;
42050
+ const sNSW = a.sNodeStrokeWidth ?? NODE_STROKE_WIDTH;
41760
42051
  const topRowH = a.sNodeTopRowHeight ?? NODE_TOP_ROW_HEIGHT;
41761
42052
  const botRowH = a.sNodeBottomRowHeight ?? NODE_BOTTOM_ROW_HEIGHT;
41762
42053
  const sNCFS = a.sNodeCellFontSize ?? NODE_CELL_FONT_SIZE2;
@@ -41889,7 +42180,7 @@ function renderCaptionBlock(svg, bullets, args) {
41889
42180
  palette.textOnFillDark
41890
42181
  );
41891
42182
  const block = svg.append("g").attr("class", "pert-caption-block").attr("data-pert-caption", "");
41892
- block.append("rect").attr("class", "pert-caption-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH10);
42183
+ block.append("rect").attr("class", "pert-caption-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH);
41893
42184
  block.append("text").attr("class", "pert-caption-header").attr("x", x + width / 2).attr("y", y + CAPTION_BOX_PADDING_Y + CAPTION_FONT_SIZE).attr("text-anchor", "middle").attr("fill", labelColor).attr("font-size", CAPTION_FONT_SIZE).attr("font-weight", "700").text("Summary");
41894
42185
  const textX = x + CAPTION_BOX_PADDING_X;
41895
42186
  const firstBaselineY = y + CAPTION_BOX_PADDING_Y + CAPTION_HEADER_BAND_HEIGHT + CAPTION_FONT_SIZE;
@@ -42006,7 +42297,7 @@ function renderTornadoBlock(svg, rows, args) {
42006
42297
  palette.textOnFillDark
42007
42298
  );
42008
42299
  const block = svg.append("g").attr("class", "pert-tornado-block").attr("data-pert-tornado", "");
42009
- block.append("rect").attr("class", "pert-tornado-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH10);
42300
+ block.append("rect").attr("class", "pert-tornado-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH);
42010
42301
  block.append("text").attr("class", "pert-tornado-header").attr("x", x + width / 2).attr("y", y + CAPTION_BOX_PADDING_Y + CAPTION_FONT_SIZE).attr("text-anchor", "middle").attr("fill", labelColor).attr("font-size", CAPTION_FONT_SIZE).attr("font-weight", "700").text("Activity Risk");
42011
42302
  const fmt = (v) => {
42012
42303
  const r = Math.round(v * 100) / 100;
@@ -42162,7 +42453,7 @@ function renderScurveBlock(svg, data, args) {
42162
42453
  palette.textOnFillDark
42163
42454
  );
42164
42455
  const block = svg.append("g").attr("class", "pert-scurve-block").attr("data-pert-scurve", "");
42165
- block.append("rect").attr("class", "pert-scurve-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH10);
42456
+ block.append("rect").attr("class", "pert-scurve-rect").attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("rx", NODE_RADIUS2).attr("ry", NODE_RADIUS2).attr("fill", fill2).attr("stroke", chromeStroke).attr("stroke-width", NODE_STROKE_WIDTH);
42166
42457
  const hasTitle = typeof title === "string" && title.length > 0;
42167
42458
  if (hasTitle) {
42168
42459
  const titleText = title.replace(/\.$/, "");
@@ -42346,7 +42637,7 @@ function formatScurveDate(iso) {
42346
42637
  if (month < 0 || month > 11 || isNaN(day)) return iso;
42347
42638
  return `${SCURVE_MONTH_NAMES[month]} ${day}`;
42348
42639
  }
42349
- var DIAGRAM_PADDING11, NODE_FONT_SIZE5, NODE_CELL_FONT_SIZE2, NODE_RADIUS2, NODE_STROKE_WIDTH10, NODE_TOP_ROW_HEIGHT, NODE_BOTTOM_ROW_HEIGHT, EDGE_STROKE_WIDTH10, ARROWHEAD_W4, ARROWHEAD_H4, CONTAINER_RADIUS3, CONTAINER_LABEL_FONT_SIZE4, CONTAINER_HEADER_HEIGHT3, COLLAPSE_BAR_HEIGHT7, DURATION_FADE_OPACITY, PIN_ICON_W, PIN_ICON_H, LEGEND_PILL_HEIGHT, LEGEND_TOP_GAP, LEGEND_BOTTOM_GAP, FIELD_LEGEND_HEADER_BAND_HEIGHT, FIELD_LEGEND_CELL_VPAD, FIELD_LEGEND_LABEL_FONT_SIZE, FIELD_LEGEND_DESC_FONT_SIZE, FIELD_LEGEND_DESC_LINE_HEIGHT, FIELD_LEGEND_LABEL_DESC_GAP, FIELD_LEGEND_CELLS, lineGenerator6, FIELD_LEGEND_MIN_W, SUB_BULLET_INDENT, CAPTION_HEADER_BAND_HEIGHT, TORNADO_TOP_N, TORNADO_ROW_HEIGHT, TORNADO_NAME_COL_W, TORNADO_BAR_FONT_SIZE, TORNADO_BAR_HEIGHT, SUMMARY_MIN_W, SUMMARY_MAX_W, ANALYSIS_GAP, COL1_VSTACK_GAP, TORNADO_MIN_W, SCURVE_MIN_W, SCURVE_BOX_HEIGHT, SCURVE_PLOT_PADDING_X, SCURVE_PLOT_PADDING_RIGHT, SCURVE_PLOT_PADDING_BOTTOM, SCURVE_TICK_FONT_SIZE, SCURVE_PERCENTILE_RADIUS, DAYS_PER_UNIT, SCURVE_MONTH_NAMES, UNIT_TO_DAYS_LOCAL2;
42640
+ var DIAGRAM_PADDING11, NODE_FONT_SIZE5, NODE_CELL_FONT_SIZE2, NODE_RADIUS2, NODE_TOP_ROW_HEIGHT, NODE_BOTTOM_ROW_HEIGHT, ARROWHEAD_W4, ARROWHEAD_H4, DURATION_FADE_OPACITY, PIN_ICON_W, PIN_ICON_H, LEGEND_PILL_HEIGHT, LEGEND_TOP_GAP, LEGEND_BOTTOM_GAP, FIELD_LEGEND_HEADER_BAND_HEIGHT, FIELD_LEGEND_CELL_VPAD, FIELD_LEGEND_LABEL_FONT_SIZE, FIELD_LEGEND_DESC_FONT_SIZE, FIELD_LEGEND_DESC_LINE_HEIGHT, FIELD_LEGEND_LABEL_DESC_GAP, FIELD_LEGEND_CELLS, lineGenerator6, FIELD_LEGEND_MIN_W, SUB_BULLET_INDENT, CAPTION_HEADER_BAND_HEIGHT, TORNADO_TOP_N, TORNADO_ROW_HEIGHT, TORNADO_NAME_COL_W, TORNADO_BAR_FONT_SIZE, TORNADO_BAR_HEIGHT, SUMMARY_MIN_W, SUMMARY_MAX_W, ANALYSIS_GAP, COL1_VSTACK_GAP, TORNADO_MIN_W, SCURVE_MIN_W, SCURVE_BOX_HEIGHT, SCURVE_PLOT_PADDING_X, SCURVE_PLOT_PADDING_RIGHT, SCURVE_PLOT_PADDING_BOTTOM, SCURVE_TICK_FONT_SIZE, SCURVE_PERCENTILE_RADIUS, DAYS_PER_UNIT, SCURVE_MONTH_NAMES, UNIT_TO_DAYS_LOCAL2;
42350
42641
  var init_renderer11 = __esm({
42351
42642
  "src/pert/renderer.ts"() {
42352
42643
  "use strict";
@@ -42362,20 +42653,15 @@ var init_renderer11 = __esm({
42362
42653
  init_analyzer();
42363
42654
  init_layout11();
42364
42655
  init_internal();
42656
+ init_visual_conventions();
42365
42657
  DIAGRAM_PADDING11 = 20;
42366
42658
  NODE_FONT_SIZE5 = 13;
42367
42659
  NODE_CELL_FONT_SIZE2 = 11;
42368
42660
  NODE_RADIUS2 = 6;
42369
- NODE_STROKE_WIDTH10 = 1.5;
42370
42661
  NODE_TOP_ROW_HEIGHT = 26;
42371
42662
  NODE_BOTTOM_ROW_HEIGHT = 26;
42372
- EDGE_STROKE_WIDTH10 = 1.5;
42373
42663
  ARROWHEAD_W4 = 10;
42374
42664
  ARROWHEAD_H4 = 7;
42375
- CONTAINER_RADIUS3 = 8;
42376
- CONTAINER_LABEL_FONT_SIZE4 = 13;
42377
- CONTAINER_HEADER_HEIGHT3 = 28;
42378
- COLLAPSE_BAR_HEIGHT7 = 6;
42379
42665
  DURATION_FADE_OPACITY = 0.55;
42380
42666
  PIN_ICON_W = 13;
42381
42667
  PIN_ICON_H = 13;
@@ -45367,8 +45653,8 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
45367
45653
  const sNodeFontSize = ctx.text(NODE_FONT_SIZE6);
45368
45654
  const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE10);
45369
45655
  const sGroupLabelFontSize = ctx.text(GROUP_LABEL_FONT_SIZE3);
45370
- const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH11);
45371
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH11);
45656
+ const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
45657
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
45372
45658
  const sArrowheadW = ctx.structural(ARROWHEAD_W5);
45373
45659
  const sArrowheadH = ctx.structural(ARROWHEAD_H5);
45374
45660
  const sPseudostateRadius = ctx.structural(PSEUDOSTATE_RADIUS);
@@ -45645,7 +45931,7 @@ function renderStateForExport(content, theme, palette) {
45645
45931
  document.body.removeChild(container);
45646
45932
  }
45647
45933
  }
45648
- var DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6, EDGE_LABEL_FONT_SIZE10, GROUP_LABEL_FONT_SIZE3, EDGE_STROKE_WIDTH11, NODE_STROKE_WIDTH11, ARROWHEAD_W5, ARROWHEAD_H5, PSEUDOSTATE_RADIUS, STATE_CORNER_RADIUS, GROUP_EXTRA_PADDING;
45934
+ var DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6, EDGE_LABEL_FONT_SIZE10, GROUP_LABEL_FONT_SIZE3, ARROWHEAD_W5, ARROWHEAD_H5, PSEUDOSTATE_RADIUS, STATE_CORNER_RADIUS, GROUP_EXTRA_PADDING;
45649
45935
  var init_state_renderer = __esm({
45650
45936
  "src/graph/state-renderer.ts"() {
45651
45937
  "use strict";
@@ -45660,13 +45946,12 @@ var init_state_renderer = __esm({
45660
45946
  init_scaling();
45661
45947
  init_text_measure();
45662
45948
  init_note_box();
45949
+ init_visual_conventions();
45663
45950
  DIAGRAM_PADDING12 = 20;
45664
45951
  MAX_SCALE7 = 3;
45665
45952
  NODE_FONT_SIZE6 = 13;
45666
45953
  EDGE_LABEL_FONT_SIZE10 = 11;
45667
45954
  GROUP_LABEL_FONT_SIZE3 = 11;
45668
- EDGE_STROKE_WIDTH11 = 1.5;
45669
- NODE_STROKE_WIDTH11 = 1.5;
45670
45955
  ARROWHEAD_W5 = 10;
45671
45956
  ARROWHEAD_H5 = 7;
45672
45957
  PSEUDOSTATE_RADIUS = 10;
@@ -47381,14 +47666,14 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
47381
47666
  const panelY = PADDING2;
47382
47667
  const textX = panelX + CARD_PADDING_X3;
47383
47668
  const clipId = "persona-clip";
47384
- defs.append("clipPath").attr("id", clipId).append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS5);
47669
+ defs.append("clipPath").attr("id", clipId).append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS);
47385
47670
  const personaFill = shapeFill(palette, personaColor, isDark, { solid });
47386
47671
  const onPersonaText = contrastText(
47387
47672
  personaFill,
47388
47673
  palette.textOnFillLight,
47389
47674
  palette.textOnFillDark
47390
47675
  );
47391
- personaG.append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS5).attr("fill", personaFill);
47676
+ personaG.append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS).attr("fill", personaFill);
47392
47677
  if (descLines.length > 0) {
47393
47678
  personaG.append("line").attr("x1", panelX + 1).attr("x2", panelX + panelWidth - silhouetteZone).attr("y1", panelY + titleRowH).attr("y2", panelY + titleRowH).attr("stroke", solid ? onPersonaText : personaColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
47394
47679
  }
@@ -47396,7 +47681,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
47396
47681
  const silY = panelY + panelHeight / 2 - 6;
47397
47682
  const silClip = personaG.append("g").attr("clip-path", `url(#${clipId})`);
47398
47683
  renderPersonaSilhouette(silClip, silX, silY, personaColor, palette, 1.2);
47399
- personaG.append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS5).attr("fill", "none").attr("stroke", personaColor).attr("stroke-width", CARD_STROKE_WIDTH2);
47684
+ personaG.append("rect").attr("x", panelX).attr("y", panelY).attr("width", panelWidth).attr("height", panelHeight).attr("rx", CARD_RADIUS).attr("fill", "none").attr("stroke", personaColor).attr("stroke-width", CARD_STROKE_WIDTH2);
47400
47685
  personaG.append("text").attr("x", textX).attr("y", panelY + CARD_PADDING_Y3 + FONT_SIZE_STEP).attr("font-size", FONT_SIZE_STEP).attr("font-weight", "500").attr("fill", onPersonaText).text(parsed.persona.name);
47401
47686
  for (let li = 0; li < descLines.length; li++) {
47402
47687
  const lineEl = personaG.append("text").attr("x", textX).attr("y", panelY + titleRowH + descLineH * (li + 1)).attr("font-size", FONT_SIZE_META).attr("fill", onPersonaText);
@@ -47636,7 +47921,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
47636
47921
  { solid }
47637
47922
  );
47638
47923
  const rowStroke = stepColor ?? palette.textMuted;
47639
- itemG.append("rect").attr("x", listX).attr("y", itemY).attr("width", cardW).attr("height", COLLAPSED_CARD_H).attr("rx", CARD_RADIUS5).attr("fill", rowFill).attr("stroke", rowStroke).attr("stroke-width", CARD_STROKE_WIDTH2);
47924
+ itemG.append("rect").attr("x", listX).attr("y", itemY).attr("width", cardW).attr("height", COLLAPSED_CARD_H).attr("rx", CARD_RADIUS).attr("fill", rowFill).attr("stroke", rowStroke).attr("stroke-width", CARD_STROKE_WIDTH2);
47640
47925
  const faceCx = listX + CARD_PADDING_X3 + COLLAPSED_FACE_R;
47641
47926
  const faceCy = itemY + COLLAPSED_CARD_H / 2;
47642
47927
  if (step.score !== void 0) {
@@ -47799,7 +48084,7 @@ function renderJourneyMap(container, parsed, palette, isDark, options) {
47799
48084
  const scoreColor = scoreToColor(score, palette);
47800
48085
  const tintedBg = mix(scoreColor, palette.surface, 20);
47801
48086
  const g = overlayG.append("g").attr("class", "journey-thought-hover");
47802
- g.append("rect").attr("x", bx).attr("y", by).attr("width", bw).attr("height", bh).attr("rx", CARD_RADIUS5).attr("fill", tintedBg).attr("stroke", scoreColor).attr("stroke-width", CARD_STROKE_WIDTH2);
48087
+ g.append("rect").attr("x", bx).attr("y", by).attr("width", bw).attr("height", bh).attr("rx", CARD_RADIUS).attr("fill", tintedBg).attr("stroke", scoreColor).attr("stroke-width", CARD_STROKE_WIDTH2);
47803
48088
  g.append("line").attr("x1", fcx).attr("y1", by + bh).attr("x2", fcx).attr("y2", fcy - FACE_RADIUS - 1).attr("stroke", scoreColor).attr("stroke-width", CARD_STROKE_WIDTH2);
47804
48089
  const centerX = bx + bw / 2;
47805
48090
  for (let i = 0; i < lines.length; i++) {
@@ -47956,7 +48241,7 @@ function renderStepCard(parent, sl, palette, isDark, activeGroup, tagGroups, onN
47956
48241
  palette.textOnFillLight,
47957
48242
  palette.textOnFillDark
47958
48243
  );
47959
- stepG.append("rect").attr("x", cx).attr("y", cy).attr("width", sl.width).attr("height", sl.height).attr("rx", CARD_RADIUS5).attr("fill", cardFill).attr("stroke", cardStroke).attr("stroke-width", CARD_STROKE_WIDTH2);
48244
+ stepG.append("rect").attr("x", cx).attr("y", cy).attr("width", sl.width).attr("height", sl.height).attr("rx", CARD_RADIUS).attr("fill", cardFill).attr("stroke", cardStroke).attr("stroke-width", CARD_STROKE_WIDTH2);
47960
48245
  const titleMaxW = sl.width - CARD_PADDING_X3 * 2;
47961
48246
  const titleLines = wrapTextToWidth(sl.step.title, FONT_SIZE_STEP, titleMaxW);
47962
48247
  for (let i = 0; i < titleLines.length; i++) {
@@ -48015,7 +48300,7 @@ function renderStepCard(parent, sl, palette, isDark, activeGroup, tagGroups, onN
48015
48300
  const stripFill = shapeFill(palette, stripColor, isDark, {
48016
48301
  ...solid !== void 0 && { solid }
48017
48302
  });
48018
- stepG.append("rect").attr("x", cx).attr("y", stripY).attr("width", sl.width).attr("height", TAG_STRIP_HEIGHT).attr("rx", CARD_RADIUS5).attr("fill", stripFill).attr("stroke", stripColor).attr("stroke-width", CARD_STROKE_WIDTH2);
48303
+ stepG.append("rect").attr("x", cx).attr("y", stripY).attr("width", sl.width).attr("height", TAG_STRIP_HEIGHT).attr("rx", CARD_RADIUS).attr("fill", stripFill).attr("stroke", stripColor).attr("stroke-width", CARD_STROKE_WIDTH2);
48019
48304
  const stripTextColor = contrastText(
48020
48305
  stripFill,
48021
48306
  palette.textOnFillLight,
@@ -48131,7 +48416,7 @@ function renderJourneyMapForExport(content, theme, palette) {
48131
48416
  }
48132
48417
  return svgEl.outerHTML;
48133
48418
  }
48134
- var DIAGRAM_PADDING13, PADDING2, CARD_RADIUS5, CARD_PADDING_X3, CARD_PADDING_Y3, CARD_HEADER_HEIGHT3, CARD_STROKE_WIDTH2, CARD_META_LINE_HEIGHT3, CARD_GAP_INTERNAL, COLUMN_RADIUS2, COLUMN_HEADER_HEIGHT2, COLUMN_PADDING3, FONT_SIZE_TITLE, FONT_SIZE_PHASE, FONT_SIZE_STEP, FONT_SIZE_META, GRID_LINE_OPACITY, CURVE_STROKE_WIDTH, FACE_RADIUS, DIM_HOVER, TITLE_LINE_HEIGHT, EMOTION_LABEL_MAX_WIDTH, EMOTION_LABEL_FONT_SIZE, ICON_THUMBS_DOWN, ICON_THUMBS_UP, ICON_THOUGHT;
48419
+ var DIAGRAM_PADDING13, PADDING2, CARD_PADDING_X3, CARD_PADDING_Y3, CARD_HEADER_HEIGHT3, CARD_STROKE_WIDTH2, CARD_META_LINE_HEIGHT3, CARD_GAP_INTERNAL, COLUMN_RADIUS2, COLUMN_HEADER_HEIGHT2, COLUMN_PADDING3, FONT_SIZE_TITLE, FONT_SIZE_PHASE, FONT_SIZE_STEP, FONT_SIZE_META, GRID_LINE_OPACITY, CURVE_STROKE_WIDTH, FACE_RADIUS, DIM_HOVER, TITLE_LINE_HEIGHT, EMOTION_LABEL_MAX_WIDTH, EMOTION_LABEL_FONT_SIZE, ICON_THUMBS_DOWN, ICON_THUMBS_UP, ICON_THOUGHT;
48135
48420
  var init_renderer14 = __esm({
48136
48421
  "src/journey-map/renderer.ts"() {
48137
48422
  "use strict";
@@ -48144,9 +48429,9 @@ var init_renderer14 = __esm({
48144
48429
  init_tag_groups();
48145
48430
  init_scaling();
48146
48431
  init_text_measure();
48432
+ init_visual_conventions();
48147
48433
  DIAGRAM_PADDING13 = 20;
48148
48434
  PADDING2 = DIAGRAM_PADDING13;
48149
- CARD_RADIUS5 = 6;
48150
48435
  CARD_PADDING_X3 = 10;
48151
48436
  CARD_PADDING_Y3 = 6;
48152
48437
  CARD_HEADER_HEIGHT3 = 24;
@@ -48223,7 +48508,7 @@ function computeCycleLayout(parsed, options) {
48223
48508
  const hasDesc = !hideDescriptions && node.description.length > 0;
48224
48509
  const labelWidth2 = Math.max(
48225
48510
  MIN_NODE_WIDTH4,
48226
- measureText(node.label, LABEL_FONT_SIZE5) + NODE_PAD_X * 2
48511
+ measureText(node.label, LABEL_FONT_SIZE4) + NODE_PAD_X * 2
48227
48512
  );
48228
48513
  if (circleNodes) {
48229
48514
  return computeCircleNodeDims(node, hasDesc);
@@ -48440,7 +48725,7 @@ function chooseDescribedRectDims(description, labelWidth2) {
48440
48725
  let bestScore = Infinity;
48441
48726
  for (let w = minW; w <= MAX_NODE_WIDTH3; w += DESC_WIDTH_STEP) {
48442
48727
  const wrapped2 = wrapDescForWidth(description, w);
48443
- const h = HEADER_HEIGHT5 + wrapped2.length * DESC_LINE_HEIGHT7 + DESC_PAD_Y;
48728
+ const h = HEADER_HEIGHT4 + wrapped2.length * DESC_LINE_HEIGHT7 + DESC_PAD_Y;
48444
48729
  const ratio = w / h;
48445
48730
  const score = Math.abs(Math.log(ratio / DESC_TARGET_RATIO));
48446
48731
  if (score < bestScore) {
@@ -48452,7 +48737,7 @@ function chooseDescribedRectDims(description, labelWidth2) {
48452
48737
  const wrapped = wrapDescForWidth(description, minW);
48453
48738
  return {
48454
48739
  width: minW,
48455
- height: HEADER_HEIGHT5 + wrapped.length * DESC_LINE_HEIGHT7 + DESC_PAD_Y,
48740
+ height: HEADER_HEIGHT4 + wrapped.length * DESC_LINE_HEIGHT7 + DESC_PAD_Y,
48456
48741
  wrappedDesc: wrapped
48457
48742
  };
48458
48743
  }
@@ -48465,7 +48750,7 @@ function wrapDescForWidth(description, nodeWidth) {
48465
48750
  );
48466
48751
  }
48467
48752
  function renderedDescNodeHeight(numLines, scale) {
48468
- const headerH = HEADER_HEIGHT5 * scale;
48753
+ const headerH = HEADER_HEIGHT4 * scale;
48469
48754
  const descFont = Math.max(
48470
48755
  RENDERER_DESC_FONT_MIN,
48471
48756
  Math.round(RENDERER_DESC_FONT * scale)
@@ -48800,7 +49085,7 @@ function buildEdgeArc(src, tgt, cx, cy, radius, isClockwise, arrowLength = 0) {
48800
49085
  const midAngle = srcExitAngle + dir * visibleSweep / 2;
48801
49086
  return { path, midAngle };
48802
49087
  }
48803
- var MIN_ARC_ANGLE, LABEL_FONT_SIZE5, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6, EDGE_LABEL_FONT_SIZE11, MIN_NODE_WIDTH4, MAX_NODE_WIDTH3, DESC_MIN_WIDTH, DESC_WIDTH_STEP, DESC_TARGET_RATIO, PLAIN_NODE_HEIGHT, HEADER_HEIGHT5, DESC_LINE_HEIGHT7, DESC_PAD_Y, NODE_PAD_X, MIN_CIRCLE_RADIUS, CIRCLE_PAD, RENDERER_DESC_FONT, RENDERER_DESC_FONT_MIN, RENDERER_DESC_LINE_H, RENDERER_DESC_LINE_H_MIN, EDGE_LABEL_MAX_WIDTH;
49088
+ var MIN_ARC_ANGLE, LABEL_FONT_SIZE4, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6, EDGE_LABEL_FONT_SIZE11, MIN_NODE_WIDTH4, MAX_NODE_WIDTH3, DESC_MIN_WIDTH, DESC_WIDTH_STEP, DESC_TARGET_RATIO, PLAIN_NODE_HEIGHT, HEADER_HEIGHT4, DESC_LINE_HEIGHT7, DESC_PAD_Y, NODE_PAD_X, MIN_CIRCLE_RADIUS, CIRCLE_PAD, RENDERER_DESC_FONT, RENDERER_DESC_FONT_MIN, RENDERER_DESC_LINE_H, RENDERER_DESC_LINE_H_MIN, EDGE_LABEL_MAX_WIDTH;
48804
49089
  var init_layout14 = __esm({
48805
49090
  "src/cycle/layout.ts"() {
48806
49091
  "use strict";
@@ -48808,7 +49093,7 @@ var init_layout14 = __esm({
48808
49093
  init_wrapped_desc();
48809
49094
  init_text_measure();
48810
49095
  MIN_ARC_ANGLE = 15 * Math.PI / 180;
48811
- LABEL_FONT_SIZE5 = 13;
49096
+ LABEL_FONT_SIZE4 = 13;
48812
49097
  CIRCLE_LABEL_FONT_SIZE = 16;
48813
49098
  DESC_FONT_SIZE6 = 11;
48814
49099
  EDGE_LABEL_FONT_SIZE11 = 11;
@@ -48818,7 +49103,7 @@ var init_layout14 = __esm({
48818
49103
  DESC_WIDTH_STEP = 20;
48819
49104
  DESC_TARGET_RATIO = 1.6;
48820
49105
  PLAIN_NODE_HEIGHT = 50;
48821
- HEADER_HEIGHT5 = 36;
49106
+ HEADER_HEIGHT4 = 36;
48822
49107
  DESC_LINE_HEIGHT7 = 16;
48823
49108
  DESC_PAD_Y = 14;
48824
49109
  NODE_PAD_X = 20;
@@ -52925,6 +53210,8 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
52925
53210
  const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY).style("background", layout.background);
52926
53211
  svg.append("rect").attr("width", width).attr("height", height).attr("fill", layout.background);
52927
53212
  const defs = svg.append("defs");
53213
+ const uid = mapInstanceCounter++;
53214
+ const nid = (base) => `${base}__m${uid}`;
52928
53215
  const arrowSize = (w) => Math.min(15, 7 + w * 0.95);
52929
53216
  const haloColor = palette.bg;
52930
53217
  const gRegions = svg.append("g").attr("class", "dgmo-map-regions");
@@ -52957,8 +53244,8 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
52957
53244
  for (const r of layout.regions) drawRegion(gRegions, r, 0.5);
52958
53245
  if (layout.relief.length && layout.reliefHatch) {
52959
53246
  const h = layout.reliefHatch;
52960
- const rangeClipId = "dgmo-relief-clip";
52961
- const landClipId = "dgmo-relief-land";
53247
+ const rangeClipId = nid("dgmo-relief-clip");
53248
+ const landClipId = nid("dgmo-relief-land");
52962
53249
  const rangeClip = defs.append("clipPath").attr("id", rangeClipId);
52963
53250
  for (const s of layout.relief) rangeClip.append("path").attr("d", s.d);
52964
53251
  const landClip = defs.append("clipPath").attr("id", landClipId);
@@ -52971,7 +53258,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
52971
53258
  }
52972
53259
  if (layout.coastlineStyle) {
52973
53260
  const cs = layout.coastlineStyle;
52974
- const maskId = "dgmo-map-water-mask";
53261
+ const maskId = nid("dgmo-map-water-mask");
52975
53262
  const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
52976
53263
  mask.append("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "white");
52977
53264
  const landD = layout.regions.filter((r) => r.id !== "lake").map((r) => r.d).join(" ");
@@ -52989,7 +53276,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
52989
53276
  appendWaterLines(
52990
53277
  gWater,
52991
53278
  defs,
52992
- "dgmo-map-coast",
53279
+ nid("dgmo-map-coast"),
52993
53280
  // Pass the canvas frame so edges collinear with it (the antimeridian on a
52994
53281
  // world map, regional clipExtent cuts) don't get ringed as fake coast —
52995
53282
  // land runs cleanly to the render-area edge.
@@ -53026,7 +53313,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53026
53313
  (l) => l.poiId !== void 0 && !l.hidden
53027
53314
  );
53028
53315
  if (poiLabels.length) {
53029
- const patchBlurId = "dgmo-map-label-patch-blur";
53316
+ const patchBlurId = nid("dgmo-map-label-patch-blur");
53030
53317
  defs.append("filter").attr("id", patchBlurId).attr("x", "-50%").attr("y", "-50%").attr("width", "200%").attr("height", "200%").append("feGaussianBlur").attr("in", "SourceGraphic").attr("stdDeviation", 2.5);
53031
53318
  const PAD = 8;
53032
53319
  const buildPatch = (labels, maskId, decoCluster) => {
@@ -53071,7 +53358,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53071
53358
  if (clusterUi) {
53072
53359
  buildPatch(
53073
53360
  poiLabels.filter((l) => l.clusterMember === void 0),
53074
- "dgmo-map-label-patch"
53361
+ nid("dgmo-map-label-patch")
53075
53362
  );
53076
53363
  const byCluster = /* @__PURE__ */ new Map();
53077
53364
  for (const l of poiLabels) {
@@ -53082,9 +53369,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53082
53369
  }
53083
53370
  let ci = 0;
53084
53371
  for (const [cid, labs] of byCluster)
53085
- buildPatch(labs, `dgmo-map-label-patch-c${ci++}`, cid);
53372
+ buildPatch(labs, nid(`dgmo-map-label-patch-c${ci++}`), cid);
53086
53373
  } else {
53087
- buildPatch(poiLabels, "dgmo-map-label-patch");
53374
+ buildPatch(poiLabels, nid("dgmo-map-label-patch"));
53088
53375
  }
53089
53376
  }
53090
53377
  if (layout.insets.length) {
@@ -53093,7 +53380,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53093
53380
  const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
53094
53381
  insetG.append("path").attr("d", d).attr("fill", layout.background).attr("stroke", mix(palette.text, palette.bg, 55)).attr("stroke-width", 1).attr("stroke-linejoin", "round");
53095
53382
  if (box.contextLand) {
53096
- const clipId = `dgmo-map-inset-clip-${bi}`;
53383
+ const clipId = nid(`dgmo-map-inset-clip-${bi}`);
53097
53384
  defs.append("clipPath").attr("id", clipId).append("path").attr("d", d);
53098
53385
  insetG.append("path").attr("d", box.contextLand.d).attr("fill", box.contextLand.fill).attr("clip-path", `url(#${clipId})`);
53099
53386
  }
@@ -53101,7 +53388,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53101
53388
  for (const r of layout.insetRegions) drawRegion(insetG, r, 0.5);
53102
53389
  if (layout.coastlineStyle) {
53103
53390
  const cs = layout.coastlineStyle;
53104
- const maskId = "dgmo-map-inset-water-mask";
53391
+ const maskId = nid("dgmo-map-inset-water-mask");
53105
53392
  const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
53106
53393
  const reach = Math.max(0, ...cs.lines.map((l) => l.d + l.thickness));
53107
53394
  for (const box of layout.insets) {
@@ -53110,7 +53397,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53110
53397
  }
53111
53398
  layout.insets.forEach((box, bi) => {
53112
53399
  if (box.contextLand)
53113
- mask.append("path").attr("d", box.contextLand.d).attr("fill", "black").attr("clip-path", `url(#dgmo-map-inset-clip-${bi})`);
53400
+ mask.append("path").attr("d", box.contextLand.d).attr("fill", "black").attr("clip-path", `url(#${nid(`dgmo-map-inset-clip-${bi}`)})`);
53114
53401
  });
53115
53402
  for (const r of layout.insetRegions)
53116
53403
  if (r.id !== "lake")
@@ -53118,7 +53405,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53118
53405
  for (const r of layout.insetRegions)
53119
53406
  if (r.id === "lake")
53120
53407
  mask.append("path").attr("d", r.d).attr("fill", "white");
53121
- const clipId = "dgmo-map-inset-water-clip";
53408
+ const clipId = nid("dgmo-map-inset-water-clip");
53122
53409
  const clip = defs.append("clipPath").attr("id", clipId);
53123
53410
  for (const box of layout.insets) {
53124
53411
  const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
@@ -53128,7 +53415,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53128
53415
  appendWaterLines(
53129
53416
  gInsetWater,
53130
53417
  defs,
53131
- "dgmo-map-inset-coast",
53418
+ nid("dgmo-map-inset-coast"),
53132
53419
  coastlineOuterRings(layout.insetRegions, cs.minExtent),
53133
53420
  cs,
53134
53421
  layout.background
@@ -53157,7 +53444,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
53157
53444
  }
53158
53445
  wireSync(p, leg.lineNumber);
53159
53446
  if (leg.arrow) {
53160
- const id = `dgmo-map-arrow-${i}`;
53447
+ const id = nid(`dgmo-map-arrow-${i}`);
53161
53448
  const s = arrowSize(leg.width);
53162
53449
  defs.append("marker").attr("id", id).attr("viewBox", "0 0 10 10").attr("refX", 10).attr("refY", 5).attr("markerUnits", "userSpaceOnUse").attr("markerWidth", s).attr("markerHeight", s).attr("orient", "auto-start-reverse").append("path").attr("d", "M0,0L10,5L0,10z").attr("fill", leg.color);
53163
53450
  p.attr("marker-end", `url(#${id})`);
@@ -53353,7 +53640,7 @@ function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize, italic
53353
53640
  }
53354
53641
  return t;
53355
53642
  }
53356
- var LABEL_FONT;
53643
+ var LABEL_FONT, mapInstanceCounter;
53357
53644
  var init_renderer16 = __esm({
53358
53645
  "src/map/renderer.ts"() {
53359
53646
  "use strict";
@@ -53365,6 +53652,7 @@ var init_renderer16 = __esm({
53365
53652
  init_legend_band();
53366
53653
  init_layout15();
53367
53654
  LABEL_FONT = 11;
53655
+ mapInstanceCounter = 0;
53368
53656
  }
53369
53657
  });
53370
53658
 
@@ -54296,7 +54584,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
54296
54584
  const sHMargin = ctx.aesthetic(H_MARGIN);
54297
54585
  const sVMargin = ctx.aesthetic(V_MARGIN3);
54298
54586
  const sTitleAreaHeight = ctx.structural(TITLE_AREA_HEIGHT4);
54299
- const sHeaderHeight = ctx.structural(HEADER_HEIGHT6);
54587
+ const sHeaderHeight = ctx.structural(HEADER_HEIGHT5);
54300
54588
  const sRowHeight = ctx.structural(ROW_HEIGHT);
54301
54589
  const sPhaseHeight = ctx.structural(PHASE_HEIGHT);
54302
54590
  const sTaskLabelMin = ctx.structural(TASK_LABEL_MIN);
@@ -54321,7 +54609,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
54321
54609
  const sLegendLetterFont = ctx.text(LEGEND_LETTER_FONT);
54322
54610
  const sViolationLineHeight = ctx.structural(VIOLATION_LINE_HEIGHT);
54323
54611
  const sStackTopGap = ctx.structural(STACK_TOP_GAP);
54324
- const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH12);
54612
+ const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
54325
54613
  const sNodeRadius = ctx.structural(NODE_RADIUS3);
54326
54614
  const innerWidth = Math.max(0, width - 2 * sHMargin);
54327
54615
  let roleColW = Math.max(
@@ -54867,7 +55155,7 @@ function parseQuotedSegments(message) {
54867
55155
  out.push({ text: message.slice(last), bold: false });
54868
55156
  return out;
54869
55157
  }
54870
- var MARKER_LABELS, TITLE_AREA_HEIGHT4, H_MARGIN, V_MARGIN3, LEGEND_HEIGHT2, LEGEND_CHIP_GAP, LEGEND_CHIP_LABEL_MIN, LEGEND_LETTER_CHIP_W, TITLE_LEGEND_GAP, LEGEND_LABEL_FONT, LEGEND_LETTER_FONT, HEADER_HEIGHT6, ROW_HEIGHT, PHASE_HEIGHT, TASK_LABEL_MIN, TASK_LABEL_MAX, ROLE_COL_MIN, ROLE_COL_MAX, CELL_PAD, VIOLATION_LINE_HEIGHT, STACK_TOP_GAP, DESC_FONT, COLUMN_RADIUS3, COLUMN_INSET, COLUMN_BOTTOM_PAD, MARKER_FONT, MARKER_FONT_WEIGHT, LABEL_FONT2, ROLE_HEADER_FONT, PHASE_FONT, TINT_PCT, NODE_STROKE_WIDTH12, NODE_RADIUS3, AUTO_ACCENTS, SLICE_GAP, NAME_LINE_HEIGHT, DESC_LINE_HEIGHT9;
55158
+ var MARKER_LABELS, TITLE_AREA_HEIGHT4, H_MARGIN, V_MARGIN3, LEGEND_HEIGHT2, LEGEND_CHIP_GAP, LEGEND_CHIP_LABEL_MIN, LEGEND_LETTER_CHIP_W, TITLE_LEGEND_GAP, LEGEND_LABEL_FONT, LEGEND_LETTER_FONT, HEADER_HEIGHT5, ROW_HEIGHT, PHASE_HEIGHT, TASK_LABEL_MIN, TASK_LABEL_MAX, ROLE_COL_MIN, ROLE_COL_MAX, CELL_PAD, VIOLATION_LINE_HEIGHT, STACK_TOP_GAP, DESC_FONT, COLUMN_RADIUS3, COLUMN_INSET, COLUMN_BOTTOM_PAD, MARKER_FONT, MARKER_FONT_WEIGHT, LABEL_FONT2, ROLE_HEADER_FONT, PHASE_FONT, TINT_PCT, NODE_RADIUS3, AUTO_ACCENTS, SLICE_GAP, NAME_LINE_HEIGHT, DESC_LINE_HEIGHT9;
54871
55159
  var init_renderer19 = __esm({
54872
55160
  "src/raci/renderer.ts"() {
54873
55161
  "use strict";
@@ -54878,6 +55166,7 @@ var init_renderer19 = __esm({
54878
55166
  init_variants();
54879
55167
  init_scaling();
54880
55168
  init_text_measure();
55169
+ init_visual_conventions();
54881
55170
  MARKER_LABELS = {
54882
55171
  raci: { R: "Responsible", A: "Accountable", C: "Consulted", I: "Informed" },
54883
55172
  rasci: {
@@ -54899,7 +55188,7 @@ var init_renderer19 = __esm({
54899
55188
  TITLE_LEGEND_GAP = 16;
54900
55189
  LEGEND_LABEL_FONT = 12;
54901
55190
  LEGEND_LETTER_FONT = 14;
54902
- HEADER_HEIGHT6 = 36;
55191
+ HEADER_HEIGHT5 = 36;
54903
55192
  ROW_HEIGHT = 36;
54904
55193
  PHASE_HEIGHT = 40;
54905
55194
  TASK_LABEL_MIN = 200;
@@ -54919,7 +55208,6 @@ var init_renderer19 = __esm({
54919
55208
  ROLE_HEADER_FONT = 12;
54920
55209
  PHASE_FONT = 13;
54921
55210
  TINT_PCT = 25;
54922
- NODE_STROKE_WIDTH12 = 1.5;
54923
55211
  NODE_RADIUS3 = 6;
54924
55212
  AUTO_ACCENTS = [
54925
55213
  "blue",
@@ -55520,11 +55808,11 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
55520
55808
  const lines = splitParticipantLabel(
55521
55809
  p.label,
55522
55810
  labelTextWidth(PARTICIPANT_BOX_WIDTH),
55523
- LABEL_FONT_SIZE6
55811
+ LABEL_FONT_SIZE5
55524
55812
  );
55525
55813
  if (lines.length === 0) continue;
55526
55814
  const widest = Math.max(
55527
- ...lines.map((l) => measureText(l, LABEL_FONT_SIZE6))
55815
+ ...lines.map((l) => measureText(l, LABEL_FONT_SIZE5))
55528
55816
  );
55529
55817
  const labelWidth2 = widest + 10;
55530
55818
  uniformBoxWidth = Math.max(uniformBoxWidth, labelWidth2);
@@ -55558,7 +55846,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
55558
55846
  const sSelfCallWidth = ctx.structural(SELF_CALL_WIDTH);
55559
55847
  const sNoteTextWidthMax = sNoteMaxW - sNotePadH * 2 - sNoteFold;
55560
55848
  const sNoteLaneMax = sGap - sActivationWidth - sNoteGap;
55561
- const sLabelFontSize = ctx.text(LABEL_FONT_SIZE6);
55849
+ const sLabelFontSize = ctx.text(LABEL_FONT_SIZE5);
55562
55850
  const sLabelTextWidth = labelTextWidth(sBoxW);
55563
55851
  const participantIndexMap = /* @__PURE__ */ new Map();
55564
55852
  participants.forEach((p, i) => participantIndexMap.set(p.id, i));
@@ -56695,7 +56983,7 @@ function buildNoteMessageMap(elements) {
56695
56983
  walk(elements);
56696
56984
  return map;
56697
56985
  }
56698
- function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tagAttr, solid, boxW = W, boxH = H, labelTextW = labelTextWidth(W), labelFontSize2 = LABEL_FONT_SIZE6) {
56986
+ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tagAttr, solid, boxW = W, boxH = H, labelTextW = labelTextWidth(W), labelFontSize2 = LABEL_FONT_SIZE5) {
56699
56987
  const g = svg.append("g").attr("transform", `translate(${cx}, ${cy})`).attr("class", "participant").attr("data-participant-id", participant.id);
56700
56988
  if (tagAttr) {
56701
56989
  g.attr(`data-tag-${tagAttr.key}`, tagAttr.value);
@@ -56743,7 +57031,7 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
56743
57031
  });
56744
57032
  }
56745
57033
  }
56746
- var PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, LABEL_FONT_SIZE6, TOP_MARGIN, TITLE_HEIGHT8, PARTICIPANT_Y_OFFSET, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W2, NOTE_FOLD2, NOTE_PAD_H2, NOTE_PAD_V2, NOTE_FONT_SIZE2, NOTE_LINE_H2, NOTE_GAP2, ACTIVATION_WIDTH, SELF_CALL_HEIGHT, SELF_CALL_WIDTH, ACTOR_LABEL_CLEARANCE, labelTextWidth, fill, stroke, SW, W, H;
57034
+ var PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, LABEL_FONT_SIZE5, TOP_MARGIN, TITLE_HEIGHT8, PARTICIPANT_Y_OFFSET, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W2, NOTE_FOLD2, NOTE_PAD_H2, NOTE_PAD_V2, NOTE_FONT_SIZE2, NOTE_LINE_H2, NOTE_GAP2, ACTIVATION_WIDTH, SELF_CALL_HEIGHT, SELF_CALL_WIDTH, ACTOR_LABEL_CLEARANCE, labelTextWidth, fill, stroke, SW, W, H;
56747
57035
  var init_renderer20 = __esm({
56748
57036
  "src/sequence/renderer.ts"() {
56749
57037
  "use strict";
@@ -56763,7 +57051,7 @@ var init_renderer20 = __esm({
56763
57051
  PARTICIPANT_GAP = 160;
56764
57052
  PARTICIPANT_BOX_WIDTH = 120;
56765
57053
  PARTICIPANT_BOX_HEIGHT = 50;
56766
- LABEL_FONT_SIZE6 = 13;
57054
+ LABEL_FONT_SIZE5 = 13;
56767
57055
  TOP_MARGIN = 20;
56768
57056
  TITLE_HEIGHT8 = 30;
56769
57057
  PARTICIPANT_Y_OFFSET = 10;
@@ -62205,7 +62493,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
62205
62493
 
62206
62494
  // src/auto/index.ts
62207
62495
  init_safe_href();
62208
- var VERSION = "0.30.0";
62496
+ var VERSION = "0.31.0";
62209
62497
  var DEFAULTS = {
62210
62498
  theme: "auto",
62211
62499
  palette: "slate",