@sagargupta1610/orrery 0.6.0 → 0.7.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // orrery 0.6.0 (MIT). Generated from src/ by scripts/build.mjs; do not edit.
2
+ // orrery 0.7.0 (MIT). Generated from src/ by scripts/build.mjs; do not edit.
3
3
  // Bundles yaml (ISC, Eemeli Aro). ELK (EPL-2.0) and resvg (MPL-2.0) load from ./vendor.
4
4
  import { createRequire as __sdwRequire } from "node:module";
5
5
  const require = __sdwRequire(import.meta.url);
@@ -50,24 +50,24 @@ var require_identity = __commonJS({
50
50
  var SCALAR = /* @__PURE__ */ Symbol.for("yaml.scalar");
51
51
  var SEQ = /* @__PURE__ */ Symbol.for("yaml.seq");
52
52
  var NODE_TYPE = /* @__PURE__ */ Symbol.for("yaml.node.type");
53
- var isAlias = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === ALIAS;
54
- var isDocument = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === DOC;
55
- var isMap = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === MAP;
56
- var isPair = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === PAIR;
57
- var isScalar = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === SCALAR;
58
- var isSeq = (node3) => !!node3 && typeof node3 === "object" && node3[NODE_TYPE] === SEQ;
59
- function isCollection(node3) {
60
- if (node3 && typeof node3 === "object")
61
- switch (node3[NODE_TYPE]) {
53
+ var isAlias = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === ALIAS;
54
+ var isDocument = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === DOC;
55
+ var isMap = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === MAP;
56
+ var isPair = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === PAIR;
57
+ var isScalar = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === SCALAR;
58
+ var isSeq = (node4) => !!node4 && typeof node4 === "object" && node4[NODE_TYPE] === SEQ;
59
+ function isCollection(node4) {
60
+ if (node4 && typeof node4 === "object")
61
+ switch (node4[NODE_TYPE]) {
62
62
  case MAP:
63
63
  case SEQ:
64
64
  return true;
65
65
  }
66
66
  return false;
67
67
  }
68
- function isNode(node3) {
69
- if (node3 && typeof node3 === "object")
70
- switch (node3[NODE_TYPE]) {
68
+ function isNode(node4) {
69
+ if (node4 && typeof node4 === "object")
70
+ switch (node4[NODE_TYPE]) {
71
71
  case ALIAS:
72
72
  case MAP:
73
73
  case SCALAR:
@@ -76,7 +76,7 @@ var require_identity = __commonJS({
76
76
  }
77
77
  return false;
78
78
  }
79
- var hasAnchor = (node3) => (isScalar(node3) || isCollection(node3)) && !!node3.anchor;
79
+ var hasAnchor = (node4) => (isScalar(node4) || isCollection(node4)) && !!node4.anchor;
80
80
  exports.ALIAS = ALIAS;
81
81
  exports.DOC = DOC;
82
82
  exports.MAP = MAP;
@@ -104,98 +104,98 @@ var require_visit = __commonJS({
104
104
  var BREAK = /* @__PURE__ */ Symbol("break visit");
105
105
  var SKIP = /* @__PURE__ */ Symbol("skip children");
106
106
  var REMOVE = /* @__PURE__ */ Symbol("remove node");
107
- function visit(node3, visitor) {
107
+ function visit(node4, visitor) {
108
108
  const visitor_ = initVisitor(visitor);
109
- if (identity.isDocument(node3)) {
110
- const cd = visit_(null, node3.contents, visitor_, Object.freeze([node3]));
109
+ if (identity.isDocument(node4)) {
110
+ const cd = visit_(null, node4.contents, visitor_, Object.freeze([node4]));
111
111
  if (cd === REMOVE)
112
- node3.contents = null;
112
+ node4.contents = null;
113
113
  } else
114
- visit_(null, node3, visitor_, Object.freeze([]));
114
+ visit_(null, node4, visitor_, Object.freeze([]));
115
115
  }
116
116
  visit.BREAK = BREAK;
117
117
  visit.SKIP = SKIP;
118
118
  visit.REMOVE = REMOVE;
119
- function visit_(key, node3, visitor, path) {
120
- const ctrl = callVisitor(key, node3, visitor, path);
119
+ function visit_(key, node4, visitor, path) {
120
+ const ctrl = callVisitor(key, node4, visitor, path);
121
121
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
122
122
  replaceNode(key, path, ctrl);
123
123
  return visit_(key, ctrl, visitor, path);
124
124
  }
125
125
  if (typeof ctrl !== "symbol") {
126
- if (identity.isCollection(node3)) {
127
- path = Object.freeze(path.concat(node3));
128
- for (let i = 0; i < node3.items.length; ++i) {
129
- const ci = visit_(i, node3.items[i], visitor, path);
126
+ if (identity.isCollection(node4)) {
127
+ path = Object.freeze(path.concat(node4));
128
+ for (let i = 0; i < node4.items.length; ++i) {
129
+ const ci = visit_(i, node4.items[i], visitor, path);
130
130
  if (typeof ci === "number")
131
131
  i = ci - 1;
132
132
  else if (ci === BREAK)
133
133
  return BREAK;
134
134
  else if (ci === REMOVE) {
135
- node3.items.splice(i, 1);
135
+ node4.items.splice(i, 1);
136
136
  i -= 1;
137
137
  }
138
138
  }
139
- } else if (identity.isPair(node3)) {
140
- path = Object.freeze(path.concat(node3));
141
- const ck = visit_("key", node3.key, visitor, path);
139
+ } else if (identity.isPair(node4)) {
140
+ path = Object.freeze(path.concat(node4));
141
+ const ck = visit_("key", node4.key, visitor, path);
142
142
  if (ck === BREAK)
143
143
  return BREAK;
144
144
  else if (ck === REMOVE)
145
- node3.key = null;
146
- const cv = visit_("value", node3.value, visitor, path);
145
+ node4.key = null;
146
+ const cv = visit_("value", node4.value, visitor, path);
147
147
  if (cv === BREAK)
148
148
  return BREAK;
149
149
  else if (cv === REMOVE)
150
- node3.value = null;
150
+ node4.value = null;
151
151
  }
152
152
  }
153
153
  return ctrl;
154
154
  }
155
- async function visitAsync(node3, visitor) {
155
+ async function visitAsync(node4, visitor) {
156
156
  const visitor_ = initVisitor(visitor);
157
- if (identity.isDocument(node3)) {
158
- const cd = await visitAsync_(null, node3.contents, visitor_, Object.freeze([node3]));
157
+ if (identity.isDocument(node4)) {
158
+ const cd = await visitAsync_(null, node4.contents, visitor_, Object.freeze([node4]));
159
159
  if (cd === REMOVE)
160
- node3.contents = null;
160
+ node4.contents = null;
161
161
  } else
162
- await visitAsync_(null, node3, visitor_, Object.freeze([]));
162
+ await visitAsync_(null, node4, visitor_, Object.freeze([]));
163
163
  }
164
164
  visitAsync.BREAK = BREAK;
165
165
  visitAsync.SKIP = SKIP;
166
166
  visitAsync.REMOVE = REMOVE;
167
- async function visitAsync_(key, node3, visitor, path) {
168
- const ctrl = await callVisitor(key, node3, visitor, path);
167
+ async function visitAsync_(key, node4, visitor, path) {
168
+ const ctrl = await callVisitor(key, node4, visitor, path);
169
169
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
170
170
  replaceNode(key, path, ctrl);
171
171
  return visitAsync_(key, ctrl, visitor, path);
172
172
  }
173
173
  if (typeof ctrl !== "symbol") {
174
- if (identity.isCollection(node3)) {
175
- path = Object.freeze(path.concat(node3));
176
- for (let i = 0; i < node3.items.length; ++i) {
177
- const ci = await visitAsync_(i, node3.items[i], visitor, path);
174
+ if (identity.isCollection(node4)) {
175
+ path = Object.freeze(path.concat(node4));
176
+ for (let i = 0; i < node4.items.length; ++i) {
177
+ const ci = await visitAsync_(i, node4.items[i], visitor, path);
178
178
  if (typeof ci === "number")
179
179
  i = ci - 1;
180
180
  else if (ci === BREAK)
181
181
  return BREAK;
182
182
  else if (ci === REMOVE) {
183
- node3.items.splice(i, 1);
183
+ node4.items.splice(i, 1);
184
184
  i -= 1;
185
185
  }
186
186
  }
187
- } else if (identity.isPair(node3)) {
188
- path = Object.freeze(path.concat(node3));
189
- const ck = await visitAsync_("key", node3.key, visitor, path);
187
+ } else if (identity.isPair(node4)) {
188
+ path = Object.freeze(path.concat(node4));
189
+ const ck = await visitAsync_("key", node4.key, visitor, path);
190
190
  if (ck === BREAK)
191
191
  return BREAK;
192
192
  else if (ck === REMOVE)
193
- node3.key = null;
194
- const cv = await visitAsync_("value", node3.value, visitor, path);
193
+ node4.key = null;
194
+ const cv = await visitAsync_("value", node4.value, visitor, path);
195
195
  if (cv === BREAK)
196
196
  return BREAK;
197
197
  else if (cv === REMOVE)
198
- node3.value = null;
198
+ node4.value = null;
199
199
  }
200
200
  }
201
201
  return ctrl;
@@ -218,32 +218,32 @@ var require_visit = __commonJS({
218
218
  }
219
219
  return visitor;
220
220
  }
221
- function callVisitor(key, node3, visitor, path) {
221
+ function callVisitor(key, node4, visitor, path) {
222
222
  if (typeof visitor === "function")
223
- return visitor(key, node3, path);
224
- if (identity.isMap(node3))
225
- return visitor.Map?.(key, node3, path);
226
- if (identity.isSeq(node3))
227
- return visitor.Seq?.(key, node3, path);
228
- if (identity.isPair(node3))
229
- return visitor.Pair?.(key, node3, path);
230
- if (identity.isScalar(node3))
231
- return visitor.Scalar?.(key, node3, path);
232
- if (identity.isAlias(node3))
233
- return visitor.Alias?.(key, node3, path);
223
+ return visitor(key, node4, path);
224
+ if (identity.isMap(node4))
225
+ return visitor.Map?.(key, node4, path);
226
+ if (identity.isSeq(node4))
227
+ return visitor.Seq?.(key, node4, path);
228
+ if (identity.isPair(node4))
229
+ return visitor.Pair?.(key, node4, path);
230
+ if (identity.isScalar(node4))
231
+ return visitor.Scalar?.(key, node4, path);
232
+ if (identity.isAlias(node4))
233
+ return visitor.Alias?.(key, node4, path);
234
234
  return void 0;
235
235
  }
236
- function replaceNode(key, path, node3) {
236
+ function replaceNode(key, path, node4) {
237
237
  const parent = path[path.length - 1];
238
238
  if (identity.isCollection(parent)) {
239
- parent.items[key] = node3;
239
+ parent.items[key] = node4;
240
240
  } else if (identity.isPair(parent)) {
241
241
  if (key === "key")
242
- parent.key = node3;
242
+ parent.key = node4;
243
243
  else
244
- parent.value = node3;
244
+ parent.value = node4;
245
245
  } else if (identity.isDocument(parent)) {
246
- parent.contents = node3;
246
+ parent.contents = node4;
247
247
  } else {
248
248
  const pt = identity.isAlias(parent) ? "alias" : "scalar";
249
249
  throw new Error(`Cannot replace node with ${pt} parent`);
@@ -403,9 +403,9 @@ var require_directives = __commonJS({
403
403
  let tagNames;
404
404
  if (doc && tagEntries.length > 0 && identity.isNode(doc.contents)) {
405
405
  const tags = {};
406
- visit.visit(doc.contents, (_key, node3) => {
407
- if (identity.isNode(node3) && node3.tag)
408
- tags[node3.tag] = true;
406
+ visit.visit(doc.contents, (_key, node4) => {
407
+ if (identity.isNode(node4) && node4.tag)
408
+ tags[node4.tag] = true;
409
409
  });
410
410
  tagNames = Object.keys(tags);
411
411
  } else
@@ -442,9 +442,9 @@ var require_anchors = __commonJS({
442
442
  function anchorNames(root) {
443
443
  const anchors = /* @__PURE__ */ new Set();
444
444
  visit.visit(root, {
445
- Value(_key, node3) {
446
- if (node3.anchor)
447
- anchors.add(node3.anchor);
445
+ Value(_key, node4) {
446
+ if (node4.anchor)
447
+ anchors.add(node4.anchor);
448
448
  }
449
449
  });
450
450
  return anchors;
@@ -648,20 +648,20 @@ var require_Alias = __commonJS({
648
648
  } else {
649
649
  nodes = [];
650
650
  visit.visit(doc, {
651
- Node: (_key, node3) => {
652
- if (identity.isAlias(node3) || identity.hasAnchor(node3))
653
- nodes.push(node3);
651
+ Node: (_key, node4) => {
652
+ if (identity.isAlias(node4) || identity.hasAnchor(node4))
653
+ nodes.push(node4);
654
654
  }
655
655
  });
656
656
  if (ctx)
657
657
  ctx.aliasResolveCache = nodes;
658
658
  }
659
659
  let found = void 0;
660
- for (const node3 of nodes) {
661
- if (node3 === this)
660
+ for (const node4 of nodes) {
661
+ if (node4 === this)
662
662
  break;
663
- if (node3.anchor === this.source)
664
- found = node3;
663
+ if (node4.anchor === this.source)
664
+ found = node4;
665
665
  }
666
666
  if (found && ctx) {
667
667
  const { anchors: anchors2, doc: doc2, maxAliasCount } = ctx;
@@ -710,22 +710,22 @@ var require_Alias = __commonJS({
710
710
  return src;
711
711
  }
712
712
  };
713
- function getAliasCount(doc, node3, anchors2) {
714
- if (identity.isAlias(node3)) {
715
- const source = node3.resolve(doc);
713
+ function getAliasCount(doc, node4, anchors2) {
714
+ if (identity.isAlias(node4)) {
715
+ const source = node4.resolve(doc);
716
716
  const anchor2 = anchors2 && source && anchors2.get(source);
717
717
  return anchor2 ? anchor2.count * anchor2.aliasCount : 0;
718
- } else if (identity.isCollection(node3)) {
718
+ } else if (identity.isCollection(node4)) {
719
719
  let count = 0;
720
- for (const item of node3.items) {
720
+ for (const item of node4.items) {
721
721
  const c = getAliasCount(doc, item, anchors2);
722
722
  if (c > count)
723
723
  count = c;
724
724
  }
725
725
  return count;
726
- } else if (identity.isPair(node3)) {
727
- const kc = getAliasCount(doc, node3.key, anchors2);
728
- const vc = getAliasCount(doc, node3.value, anchors2);
726
+ } else if (identity.isPair(node4)) {
727
+ const kc = getAliasCount(doc, node4.key, anchors2);
728
+ const vc = getAliasCount(doc, node4.value, anchors2);
729
729
  return Math.max(kc, vc);
730
730
  }
731
731
  return 1;
@@ -815,10 +815,10 @@ var require_createNode = __commonJS({
815
815
  value = value.toJSON();
816
816
  }
817
817
  if (!value || typeof value !== "object") {
818
- const node4 = new Scalar.Scalar(value);
818
+ const node5 = new Scalar.Scalar(value);
819
819
  if (ref)
820
- ref.node = node4;
821
- return node4;
820
+ ref.node = node5;
821
+ return node5;
822
822
  }
823
823
  tagObj = value instanceof Map ? schema[identity.MAP] : Symbol.iterator in Object(value) ? schema[identity.SEQ] : schema[identity.MAP];
824
824
  }
@@ -826,14 +826,14 @@ var require_createNode = __commonJS({
826
826
  onTagObj(tagObj);
827
827
  delete ctx.onTagObj;
828
828
  }
829
- const node3 = tagObj?.createNode ? tagObj.createNode(ctx.schema, value, ctx) : typeof tagObj?.nodeClass?.from === "function" ? tagObj.nodeClass.from(ctx.schema, value, ctx) : new Scalar.Scalar(value);
829
+ const node4 = tagObj?.createNode ? tagObj.createNode(ctx.schema, value, ctx) : typeof tagObj?.nodeClass?.from === "function" ? tagObj.nodeClass.from(ctx.schema, value, ctx) : new Scalar.Scalar(value);
830
830
  if (tagName)
831
- node3.tag = tagName;
831
+ node4.tag = tagName;
832
832
  else if (!tagObj.default)
833
- node3.tag = tagObj.tag;
833
+ node4.tag = tagObj.tag;
834
834
  if (ref)
835
- ref.node = node3;
836
- return node3;
835
+ ref.node = node4;
836
+ return node4;
837
837
  }
838
838
  exports.createNode = createNode;
839
839
  }
@@ -903,10 +903,10 @@ var require_Collection = __commonJS({
903
903
  this.add(value);
904
904
  else {
905
905
  const [key, ...rest] = path;
906
- const node3 = this.get(key, true);
907
- if (identity.isCollection(node3))
908
- node3.addIn(rest, value);
909
- else if (node3 === void 0 && this.schema)
906
+ const node4 = this.get(key, true);
907
+ if (identity.isCollection(node4))
908
+ node4.addIn(rest, value);
909
+ else if (node4 === void 0 && this.schema)
910
910
  this.set(key, collectionFromPath(this.schema, rest, value));
911
911
  else
912
912
  throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
@@ -920,9 +920,9 @@ var require_Collection = __commonJS({
920
920
  const [key, ...rest] = path;
921
921
  if (rest.length === 0)
922
922
  return this.delete(key);
923
- const node3 = this.get(key, true);
924
- if (identity.isCollection(node3))
925
- return node3.deleteIn(rest);
923
+ const node4 = this.get(key, true);
924
+ if (identity.isCollection(node4))
925
+ return node4.deleteIn(rest);
926
926
  else
927
927
  throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
928
928
  }
@@ -933,17 +933,17 @@ var require_Collection = __commonJS({
933
933
  */
934
934
  getIn(path, keepScalar) {
935
935
  const [key, ...rest] = path;
936
- const node3 = this.get(key, true);
936
+ const node4 = this.get(key, true);
937
937
  if (rest.length === 0)
938
- return !keepScalar && identity.isScalar(node3) ? node3.value : node3;
938
+ return !keepScalar && identity.isScalar(node4) ? node4.value : node4;
939
939
  else
940
- return identity.isCollection(node3) ? node3.getIn(rest, keepScalar) : void 0;
940
+ return identity.isCollection(node4) ? node4.getIn(rest, keepScalar) : void 0;
941
941
  }
942
942
  hasAllNullValues(allowScalar) {
943
- return this.items.every((node3) => {
944
- if (!identity.isPair(node3))
943
+ return this.items.every((node4) => {
944
+ if (!identity.isPair(node4))
945
945
  return false;
946
- const n3 = node3.value;
946
+ const n3 = node4.value;
947
947
  return n3 == null || allowScalar && identity.isScalar(n3) && n3.value == null && !n3.commentBefore && !n3.comment && !n3.tag;
948
948
  });
949
949
  }
@@ -954,8 +954,8 @@ var require_Collection = __commonJS({
954
954
  const [key, ...rest] = path;
955
955
  if (rest.length === 0)
956
956
  return this.has(key);
957
- const node3 = this.get(key, true);
958
- return identity.isCollection(node3) ? node3.hasIn(rest) : false;
957
+ const node4 = this.get(key, true);
958
+ return identity.isCollection(node4) ? node4.hasIn(rest) : false;
959
959
  }
960
960
  /**
961
961
  * Sets a value in this collection. For `!!set`, `value` needs to be a
@@ -966,10 +966,10 @@ var require_Collection = __commonJS({
966
966
  if (rest.length === 0) {
967
967
  this.set(key, value);
968
968
  } else {
969
- const node3 = this.get(key, true);
970
- if (identity.isCollection(node3))
971
- node3.setIn(rest, value);
972
- else if (node3 === void 0 && this.schema)
969
+ const node4 = this.get(key, true);
970
+ if (identity.isCollection(node4))
971
+ node4.setIn(rest, value);
972
+ else if (node4 === void 0 && this.schema)
973
973
  this.set(key, collectionFromPath(this.schema, rest, value));
974
974
  else
975
975
  throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
@@ -1495,16 +1495,16 @@ var require_stringify = __commonJS({
1495
1495
  }
1496
1496
  return tagObj;
1497
1497
  }
1498
- function stringifyProps(node3, tagObj, { anchors: anchors$1, doc }) {
1498
+ function stringifyProps(node4, tagObj, { anchors: anchors$1, doc }) {
1499
1499
  if (!doc.directives)
1500
1500
  return "";
1501
1501
  const props = [];
1502
- const anchor2 = (identity.isScalar(node3) || identity.isCollection(node3)) && node3.anchor;
1502
+ const anchor2 = (identity.isScalar(node4) || identity.isCollection(node4)) && node4.anchor;
1503
1503
  if (anchor2 && anchors.anchorIsValid(anchor2)) {
1504
1504
  anchors$1.add(anchor2);
1505
1505
  props.push(`&${anchor2}`);
1506
1506
  }
1507
- const tag = node3.tag ?? (tagObj.default ? null : tagObj.tag);
1507
+ const tag = node4.tag ?? (tagObj.default ? null : tagObj.tag);
1508
1508
  if (tag)
1509
1509
  props.push(doc.directives.tagString(tag));
1510
1510
  return props.join(" ");
@@ -1526,15 +1526,15 @@ var require_stringify = __commonJS({
1526
1526
  }
1527
1527
  }
1528
1528
  let tagObj = void 0;
1529
- const node3 = identity.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
1530
- tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node3));
1531
- const props = stringifyProps(node3, tagObj, ctx);
1529
+ const node4 = identity.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
1530
+ tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node4));
1531
+ const props = stringifyProps(node4, tagObj, ctx);
1532
1532
  if (props.length > 0)
1533
1533
  ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
1534
- const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node3, ctx, onComment, onChompKeep) : identity.isScalar(node3) ? stringifyString.stringifyString(node3, ctx, onComment, onChompKeep) : node3.toString(ctx, onComment, onChompKeep);
1534
+ const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node4, ctx, onComment, onChompKeep) : identity.isScalar(node4) ? stringifyString.stringifyString(node4, ctx, onComment, onChompKeep) : node4.toString(ctx, onComment, onChompKeep);
1535
1535
  if (!props)
1536
1536
  return str;
1537
- return identity.isScalar(node3) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
1537
+ return identity.isScalar(node4) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
1538
1538
  ${ctx.indent}${str}`;
1539
1539
  }
1540
1540
  exports.createStringifyContext = createStringifyContext;
@@ -1801,8 +1801,8 @@ var require_addPairToJSMap = __commonJS({
1801
1801
  if (identity.isNode(key) && ctx?.doc) {
1802
1802
  const strCtx = stringify2.createStringifyContext(ctx.doc, {});
1803
1803
  strCtx.anchors = /* @__PURE__ */ new Set();
1804
- for (const node3 of ctx.anchors.keys())
1805
- strCtx.anchors.add(node3.anchor);
1804
+ for (const node4 of ctx.anchors.keys())
1805
+ strCtx.anchors.add(node4.anchor);
1806
1806
  strCtx.inFlow = true;
1807
1807
  strCtx.inStringifyKey = true;
1808
1808
  const strKey = key.toString(strCtx);
@@ -2111,8 +2111,8 @@ var require_YAMLMap = __commonJS({
2111
2111
  }
2112
2112
  get(key, keepScalar) {
2113
2113
  const it = findPair(this.items, key);
2114
- const node3 = it?.value;
2115
- return (!keepScalar && identity.isScalar(node3) ? node3.value : node3) ?? void 0;
2114
+ const node4 = it?.value;
2115
+ return (!keepScalar && identity.isScalar(node4) ? node4.value : node4) ?? void 0;
2116
2116
  }
2117
2117
  has(key) {
2118
2118
  return !!findPair(this.items, key);
@@ -2425,9 +2425,9 @@ var require_float = __commonJS({
2425
2425
  format: "EXP",
2426
2426
  test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
2427
2427
  resolve: (str) => parseFloat(str),
2428
- stringify(node3) {
2429
- const num = Number(node3.value);
2430
- return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node3);
2428
+ stringify(node4) {
2429
+ const num = Number(node4.value);
2430
+ return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node4);
2431
2431
  }
2432
2432
  };
2433
2433
  var float = {
@@ -2436,11 +2436,11 @@ var require_float = __commonJS({
2436
2436
  tag: "tag:yaml.org,2002:float",
2437
2437
  test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
2438
2438
  resolve(str) {
2439
- const node3 = new Scalar.Scalar(parseFloat(str));
2439
+ const node4 = new Scalar.Scalar(parseFloat(str));
2440
2440
  const dot = str.indexOf(".");
2441
2441
  if (dot !== -1 && str[str.length - 1] === "0")
2442
- node3.minFractionDigits = str.length - dot - 1;
2443
- return node3;
2442
+ node4.minFractionDigits = str.length - dot - 1;
2443
+ return node4;
2444
2444
  },
2445
2445
  stringify: stringifyNumber.stringifyNumber
2446
2446
  };
@@ -2457,11 +2457,11 @@ var require_int = __commonJS({
2457
2457
  var stringifyNumber = require_stringifyNumber();
2458
2458
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
2459
2459
  var intResolve = (str, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix);
2460
- function intStringify(node3, radix, prefix) {
2461
- const { value } = node3;
2460
+ function intStringify(node4, radix, prefix) {
2461
+ const { value } = node4;
2462
2462
  if (intIdentify(value) && value >= 0)
2463
2463
  return prefix + value.toString(radix);
2464
- return stringifyNumber.stringifyNumber(node3);
2464
+ return stringifyNumber.stringifyNumber(node4);
2465
2465
  }
2466
2466
  var intOct = {
2467
2467
  identify: (value) => intIdentify(value) && value >= 0,
@@ -2470,7 +2470,7 @@ var require_int = __commonJS({
2470
2470
  format: "OCT",
2471
2471
  test: /^0o[0-7]+$/,
2472
2472
  resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt),
2473
- stringify: (node3) => intStringify(node3, 8, "0o")
2473
+ stringify: (node4) => intStringify(node4, 8, "0o")
2474
2474
  };
2475
2475
  var int = {
2476
2476
  identify: intIdentify,
@@ -2487,7 +2487,7 @@ var require_int = __commonJS({
2487
2487
  format: "HEX",
2488
2488
  test: /^0x[0-9a-fA-F]+$/,
2489
2489
  resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
2490
- stringify: (node3) => intStringify(node3, 16, "0x")
2490
+ stringify: (node4) => intStringify(node4, 16, "0x")
2491
2491
  };
2492
2492
  exports.int = int;
2493
2493
  exports.intHex = intHex;
@@ -2865,9 +2865,9 @@ var require_float2 = __commonJS({
2865
2865
  format: "EXP",
2866
2866
  test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
2867
2867
  resolve: (str) => parseFloat(str.replace(/_/g, "")),
2868
- stringify(node3) {
2869
- const num = Number(node3.value);
2870
- return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node3);
2868
+ stringify(node4) {
2869
+ const num = Number(node4.value);
2870
+ return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node4);
2871
2871
  }
2872
2872
  };
2873
2873
  var float = {
@@ -2876,14 +2876,14 @@ var require_float2 = __commonJS({
2876
2876
  tag: "tag:yaml.org,2002:float",
2877
2877
  test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
2878
2878
  resolve(str) {
2879
- const node3 = new Scalar.Scalar(parseFloat(str.replace(/_/g, "")));
2879
+ const node4 = new Scalar.Scalar(parseFloat(str.replace(/_/g, "")));
2880
2880
  const dot = str.indexOf(".");
2881
2881
  if (dot !== -1) {
2882
2882
  const f = str.substring(dot + 1).replace(/_/g, "");
2883
2883
  if (f[f.length - 1] === "0")
2884
- node3.minFractionDigits = f.length;
2884
+ node4.minFractionDigits = f.length;
2885
2885
  }
2886
- return node3;
2886
+ return node4;
2887
2887
  },
2888
2888
  stringify: stringifyNumber.stringifyNumber
2889
2889
  };
@@ -2922,13 +2922,13 @@ var require_int2 = __commonJS({
2922
2922
  const n3 = parseInt(str, radix);
2923
2923
  return sign === "-" ? -1 * n3 : n3;
2924
2924
  }
2925
- function intStringify(node3, radix, prefix) {
2926
- const { value } = node3;
2925
+ function intStringify(node4, radix, prefix) {
2926
+ const { value } = node4;
2927
2927
  if (intIdentify(value)) {
2928
2928
  const str = value.toString(radix);
2929
2929
  return value < 0 ? "-" + prefix + str.substr(1) : prefix + str;
2930
2930
  }
2931
- return stringifyNumber.stringifyNumber(node3);
2931
+ return stringifyNumber.stringifyNumber(node4);
2932
2932
  }
2933
2933
  var intBin = {
2934
2934
  identify: intIdentify,
@@ -2937,7 +2937,7 @@ var require_int2 = __commonJS({
2937
2937
  format: "BIN",
2938
2938
  test: /^[-+]?0b[0-1_]+$/,
2939
2939
  resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
2940
- stringify: (node3) => intStringify(node3, 2, "0b")
2940
+ stringify: (node4) => intStringify(node4, 2, "0b")
2941
2941
  };
2942
2942
  var intOct = {
2943
2943
  identify: intIdentify,
@@ -2946,7 +2946,7 @@ var require_int2 = __commonJS({
2946
2946
  format: "OCT",
2947
2947
  test: /^[-+]?0[0-7_]+$/,
2948
2948
  resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
2949
- stringify: (node3) => intStringify(node3, 8, "0")
2949
+ stringify: (node4) => intStringify(node4, 8, "0")
2950
2950
  };
2951
2951
  var int = {
2952
2952
  identify: intIdentify,
@@ -2963,7 +2963,7 @@ var require_int2 = __commonJS({
2963
2963
  format: "HEX",
2964
2964
  test: /^[-+]?0x[0-9a-fA-F_]+$/,
2965
2965
  resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
2966
- stringify: (node3) => intStringify(node3, 16, "0x")
2966
+ stringify: (node4) => intStringify(node4, 16, "0x")
2967
2967
  };
2968
2968
  exports.int = int;
2969
2969
  exports.intBin = intBin;
@@ -3073,13 +3073,13 @@ var require_timestamp = __commonJS({
3073
3073
  const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0));
3074
3074
  return sign === "-" ? num(-1) * res : res;
3075
3075
  }
3076
- function stringifySexagesimal(node3) {
3077
- let { value } = node3;
3076
+ function stringifySexagesimal(node4) {
3077
+ let { value } = node4;
3078
3078
  let num = (n3) => n3;
3079
3079
  if (typeof value === "bigint")
3080
3080
  num = (n3) => BigInt(n3);
3081
3081
  else if (isNaN(value) || !isFinite(value))
3082
- return stringifyNumber.stringifyNumber(node3);
3082
+ return stringifyNumber.stringifyNumber(node4);
3083
3083
  let sign = "";
3084
3084
  if (value < 0) {
3085
3085
  sign = "-";
@@ -3490,13 +3490,13 @@ var require_Document = __commonJS({
3490
3490
  * `name` will be used as a prefix for a new unique anchor.
3491
3491
  * If `name` is undefined, the generated anchor will use 'a' as a prefix.
3492
3492
  */
3493
- createAlias(node3, name) {
3494
- if (!node3.anchor) {
3493
+ createAlias(node4, name) {
3494
+ if (!node4.anchor) {
3495
3495
  const prev = anchors.anchorNames(this);
3496
- node3.anchor = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
3496
+ node4.anchor = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
3497
3497
  !name || prev.has(name) ? anchors.findNewAnchor(name || "a", prev) : name;
3498
3498
  }
3499
- return new Alias.Alias(node3.anchor);
3499
+ return new Alias.Alias(node4.anchor);
3500
3500
  }
3501
3501
  createNode(value, replacer, options) {
3502
3502
  let _replacer = void 0;
@@ -3528,11 +3528,11 @@ var require_Document = __commonJS({
3528
3528
  schema: this.schema,
3529
3529
  sourceObjects
3530
3530
  };
3531
- const node3 = createNode.createNode(value, tag, ctx);
3532
- if (flow && identity.isCollection(node3))
3533
- node3.flow = true;
3531
+ const node4 = createNode.createNode(value, tag, ctx);
3532
+ if (flow && identity.isCollection(node4))
3533
+ node4.flow = true;
3534
3534
  setAnchors();
3535
- return node3;
3535
+ return node4;
3536
3536
  }
3537
3537
  /**
3538
3538
  * Convert a key and a value into a `Pair` using the current schema,
@@ -4129,11 +4129,11 @@ var require_resolve_block_seq = __commonJS({
4129
4129
  continue;
4130
4130
  }
4131
4131
  }
4132
- const node3 = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
4132
+ const node4 = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, start, null, props, onError);
4133
4133
  if (ctx.schema.compat)
4134
4134
  utilFlowIndentCheck.flowIndentCheck(bs.indent, value, onError);
4135
- offset = node3.range[2];
4136
- seq.items.push(node3);
4135
+ offset = node4.range[2];
4136
+ seq.items.push(node4);
4137
4137
  }
4138
4138
  seq.range = [bs.offset, offset, commentEnd ?? offset];
4139
4139
  return seq;
@@ -4418,13 +4418,13 @@ var require_compose_collection = __commonJS({
4418
4418
  }
4419
4419
  let tag = ctx.schema.tags.find((t) => t.tag === tagName && t.collection === expType);
4420
4420
  if (!tag) {
4421
- const kt = ctx.schema.knownTags[tagName];
4422
- if (kt?.collection === expType) {
4423
- ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
4424
- tag = kt;
4421
+ const kt2 = ctx.schema.knownTags[tagName];
4422
+ if (kt2?.collection === expType) {
4423
+ ctx.schema.tags.push(Object.assign({}, kt2, { default: false }));
4424
+ tag = kt2;
4425
4425
  } else {
4426
- if (kt) {
4427
- onError(tagToken, "BAD_COLLECTION_TYPE", `${kt.tag} used for ${expType} collection, but expects ${kt.collection ?? "scalar"}`, true);
4426
+ if (kt2) {
4427
+ onError(tagToken, "BAD_COLLECTION_TYPE", `${kt2.tag} used for ${expType} collection, but expects ${kt2.collection ?? "scalar"}`, true);
4428
4428
  } else {
4429
4429
  onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, true);
4430
4430
  }
@@ -4433,12 +4433,12 @@ var require_compose_collection = __commonJS({
4433
4433
  }
4434
4434
  const coll = resolveCollection(CN, ctx, token, onError, tagName, tag);
4435
4435
  const res = tag.resolve?.(coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options) ?? coll;
4436
- const node3 = identity.isNode(res) ? res : new Scalar.Scalar(res);
4437
- node3.range = coll.range;
4438
- node3.tag = tagName;
4436
+ const node4 = identity.isNode(res) ? res : new Scalar.Scalar(res);
4437
+ node4.range = coll.range;
4438
+ node4.tag = tagName;
4439
4439
  if (tag?.format)
4440
- node3.format = tag.format;
4441
- return node3;
4440
+ node4.format = tag.format;
4441
+ return node4;
4442
4442
  }
4443
4443
  exports.composeCollection = composeCollection;
4444
4444
  }
@@ -4904,10 +4904,10 @@ var require_compose_scalar = __commonJS({
4904
4904
  for (const tag of matchWithTest)
4905
4905
  if (tag.test?.test(value))
4906
4906
  return tag;
4907
- const kt = schema.knownTags[tagName];
4908
- if (kt && !kt.collection) {
4909
- schema.tags.push(Object.assign({}, kt, { default: false, test: void 0 }));
4910
- return kt;
4907
+ const kt2 = schema.knownTags[tagName];
4908
+ if (kt2 && !kt2.collection) {
4909
+ schema.tags.push(Object.assign({}, kt2, { default: false, test: void 0 }));
4910
+ return kt2;
4911
4911
  }
4912
4912
  onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str");
4913
4913
  return schema[identity.SCALAR];
@@ -4973,11 +4973,11 @@ var require_compose_node = __commonJS({
4973
4973
  function composeNode(ctx, token, props, onError) {
4974
4974
  const atKey = ctx.atKey;
4975
4975
  const { spaceBefore, comment, anchor: anchor2, tag } = props;
4976
- let node3;
4976
+ let node4;
4977
4977
  let isSrcToken = true;
4978
4978
  switch (token.type) {
4979
4979
  case "alias":
4980
- node3 = composeAlias(ctx, token, onError);
4980
+ node4 = composeAlias(ctx, token, onError);
4981
4981
  if (anchor2 || tag)
4982
4982
  onError(token, "ALIAS_PROPS", "An alias node must not specify any properties");
4983
4983
  break;
@@ -4985,17 +4985,17 @@ var require_compose_node = __commonJS({
4985
4985
  case "single-quoted-scalar":
4986
4986
  case "double-quoted-scalar":
4987
4987
  case "block-scalar":
4988
- node3 = composeScalar.composeScalar(ctx, token, tag, onError);
4988
+ node4 = composeScalar.composeScalar(ctx, token, tag, onError);
4989
4989
  if (anchor2)
4990
- node3.anchor = anchor2.source.substring(1);
4990
+ node4.anchor = anchor2.source.substring(1);
4991
4991
  break;
4992
4992
  case "block-map":
4993
4993
  case "block-seq":
4994
4994
  case "flow-collection":
4995
4995
  try {
4996
- node3 = composeCollection.composeCollection(CN, ctx, token, props, onError);
4996
+ node4 = composeCollection.composeCollection(CN, ctx, token, props, onError);
4997
4997
  if (anchor2)
4998
- node3.anchor = anchor2.source.substring(1);
4998
+ node4.anchor = anchor2.source.substring(1);
4999
4999
  } catch (error) {
5000
5000
  const message = error instanceof Error ? error.message : String(error);
5001
5001
  onError(token, "RESOURCE_EXHAUSTION", message);
@@ -5007,24 +5007,24 @@ var require_compose_node = __commonJS({
5007
5007
  isSrcToken = false;
5008
5008
  }
5009
5009
  }
5010
- node3 ?? (node3 = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
5011
- if (anchor2 && node3.anchor === "")
5010
+ node4 ?? (node4 = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
5011
+ if (anchor2 && node4.anchor === "")
5012
5012
  onError(anchor2, "BAD_ALIAS", "Anchor cannot be an empty string");
5013
- if (atKey && ctx.options.stringKeys && (!identity.isScalar(node3) || typeof node3.value !== "string" || node3.tag && node3.tag !== "tag:yaml.org,2002:str")) {
5013
+ if (atKey && ctx.options.stringKeys && (!identity.isScalar(node4) || typeof node4.value !== "string" || node4.tag && node4.tag !== "tag:yaml.org,2002:str")) {
5014
5014
  const msg = "With stringKeys, all keys must be strings";
5015
5015
  onError(tag ?? token, "NON_STRING_KEY", msg);
5016
5016
  }
5017
5017
  if (spaceBefore)
5018
- node3.spaceBefore = true;
5018
+ node4.spaceBefore = true;
5019
5019
  if (comment) {
5020
5020
  if (token.type === "scalar" && token.source === "")
5021
- node3.comment = comment;
5021
+ node4.comment = comment;
5022
5022
  else
5023
- node3.commentBefore = comment;
5023
+ node4.commentBefore = comment;
5024
5024
  }
5025
5025
  if (ctx.options.keepSourceTokens && isSrcToken)
5026
- node3.srcToken = token;
5027
- return node3;
5026
+ node4.srcToken = token;
5027
+ return node4;
5028
5028
  }
5029
5029
  function composeEmptyNode(ctx, offset, before, pos, { spaceBefore, comment, anchor: anchor2, tag, end }, onError) {
5030
5030
  const token = {
@@ -5033,19 +5033,19 @@ var require_compose_node = __commonJS({
5033
5033
  indent: -1,
5034
5034
  source: ""
5035
5035
  };
5036
- const node3 = composeScalar.composeScalar(ctx, token, tag, onError);
5036
+ const node4 = composeScalar.composeScalar(ctx, token, tag, onError);
5037
5037
  if (anchor2) {
5038
- node3.anchor = anchor2.source.substring(1);
5039
- if (node3.anchor === "")
5038
+ node4.anchor = anchor2.source.substring(1);
5039
+ if (node4.anchor === "")
5040
5040
  onError(anchor2, "BAD_ALIAS", "Anchor cannot be an empty string");
5041
5041
  }
5042
5042
  if (spaceBefore)
5043
- node3.spaceBefore = true;
5043
+ node4.spaceBefore = true;
5044
5044
  if (comment) {
5045
- node3.comment = comment;
5046
- node3.range[2] = end;
5045
+ node4.comment = comment;
5046
+ node4.range[2] = end;
5047
5047
  }
5048
- return node3;
5048
+ return node4;
5049
5049
  }
5050
5050
  function composeAlias({ options }, { offset, source, end }, onError) {
5051
5051
  const alias = new Alias.Alias(source.substring(1));
@@ -7537,7 +7537,7 @@ function fromOcticons(data) {
7537
7537
  return { prefix: "octicon", icons };
7538
7538
  }
7539
7539
  var loadedLibrary = (pack) => loaded.get(pack);
7540
- function libraryIcon(set, name, mono = false) {
7540
+ function libraryIcon(set, name, mono2 = false) {
7541
7541
  const icon2 = set.icons[name] ?? set.icons[set.aliases?.[name]?.parent ?? ""];
7542
7542
  if (!icon2) return void 0;
7543
7543
  let body = icon2.body;
@@ -7548,7 +7548,7 @@ function libraryIcon(set, name, mono = false) {
7548
7548
  `$1sdwid_${id}`
7549
7549
  );
7550
7550
  }
7551
- if (mono) {
7551
+ if (mono2) {
7552
7552
  body = body.replaceAll("currentColor", "{{c}}");
7553
7553
  if (!/\bfill="/.test(body) || !body.includes("{{c}}")) body = `<g fill="{{c}}">${body}</g>`;
7554
7554
  }
@@ -7783,6 +7783,18 @@ function suggestIcons(id, limit = 3) {
7783
7783
  for (const [, rid] of ranked) if (!close.includes(rid)) close.push(rid);
7784
7784
  return close.slice(0, limit);
7785
7785
  }
7786
+ var WHITE_PAINT = /(?:fill|stroke|stop-color)(?:="|:\s*)(?:#fff(?:fff)?\b|white\b)/i;
7787
+ var LIGHT_TILES = /* @__PURE__ */ new Set(["aws:group-aws-cloud", "aws:group-aws-cloud-logo"]);
7788
+ function iconTone(id, theme) {
7789
+ const info = iconInfo(id);
7790
+ if (!info) throw new Error(`unknown icon ${id}`);
7791
+ const entry = packEntry(info);
7792
+ if (entry.m || entry.k) return "mono";
7793
+ if (LIGHT_TILES.has(info.id)) return "inverse";
7794
+ if (info.pack === "k8s" || info.pack === "aws" && info.type !== "resource") return "glyph";
7795
+ const body = theme === "dark" && entry.d ? entry.d : entry.b;
7796
+ return WHITE_PAINT.test(body) ? "two" : "shape";
7797
+ }
7786
7798
  var libEntries = /* @__PURE__ */ new Map();
7787
7799
  function libraryEntry(info, lib) {
7788
7800
  const done = libEntries.get(info.id);
@@ -7832,7 +7844,14 @@ function renderIcon(id, instance, paint) {
7832
7844
  const entry = packEntry(info);
7833
7845
  let body = paint.theme === "dark" && entry.d ? entry.d : entry.b;
7834
7846
  body = body.replaceAll("sdwid", `${instance}-`);
7835
- if (entry.m) {
7847
+ if (paint.mono && entry.m) body = body.replaceAll("{{c}}", paint.mono);
7848
+ else if (paint.mono && entry.k) {
7849
+ body = entry.b.replaceAll("sdwid", `${instance}-`).replace(
7850
+ /(fill|stroke|stop-color)="(?:#(?:[0-9a-fA-F]{3}){1,2}|black)"/g,
7851
+ `$1="${paint.mono}"`
7852
+ );
7853
+ body = `<g fill="${paint.mono}">${body}</g>`;
7854
+ } else if (entry.m) {
7836
7855
  let color = paint.color ?? entry.col ?? paint.ink;
7837
7856
  if (contrast(color, paint.background) < 2.2) color = paint.ink;
7838
7857
  if (BLACK_OR_WHITE.has(info.id))
@@ -8198,8 +8217,8 @@ function checkScene(scene, model, opts = {}) {
8198
8217
  }
8199
8218
  }
8200
8219
  }
8201
- const labels = scene.edges.filter((e) => e.labelBox).map((e) => ({ e, box: e.labelBox }));
8202
- for (const { e, box } of labels) {
8220
+ const labels2 = scene.edges.filter((e) => e.labelBox).map((e) => ({ e, box: e.labelBox }));
8221
+ for (const { e, box } of labels2) {
8203
8222
  for (const nb of nodeBoxes) {
8204
8223
  if (overlaps(box, nb.foot, -1)) {
8205
8224
  warn(
@@ -8213,10 +8232,10 @@ function checkScene(scene, model, opts = {}) {
8213
8232
  }
8214
8233
  }
8215
8234
  }
8216
- for (let i = 0; i < labels.length; i++) {
8217
- for (let j = i + 1; j < labels.length; j++) {
8218
- const a = labels[i];
8219
- const b = labels[j];
8235
+ for (let i = 0; i < labels2.length; i++) {
8236
+ for (let j = i + 1; j < labels2.length; j++) {
8237
+ const a = labels2[i];
8238
+ const b = labels2[j];
8220
8239
  if (a && b && overlaps(a.box, b.box, -1)) {
8221
8240
  warn(
8222
8241
  "DG202",
@@ -8429,7 +8448,7 @@ function checkScene(scene, model, opts = {}) {
8429
8448
  }
8430
8449
  const hits = (p, b) => p.round ? circleHitsBox(p.box, b) : overlaps(p.box, b, -EPS);
8431
8450
  const pillFixes = (p) => p.round ? ["shorten the edge label next to it", "use layout: { spacing: loose }"] : ["shorten the badge text", "use layout: { spacing: loose }"];
8432
- const pillWarn = (p, over, subject, box) => warn("DG211", `${p.what} covers ${over}`, {
8451
+ const pillWarn = (p, over2, subject, box) => warn("DG211", `${p.what} covers ${over2}`, {
8433
8452
  subject: { ...p.subject, ...subject },
8434
8453
  evidence: { badge: boxOf(p.box), over: boxOf(box) },
8435
8454
  fixes: pillFixes(p)
@@ -8640,55 +8659,76 @@ var THEME_TOKENS = {
8640
8659
  };
8641
8660
  var INK = "#0b1012";
8642
8661
  var PAPER = "#eef2f6";
8662
+ var BLUE = "#60a5fa";
8663
+ var DEEP = "#2563eb";
8664
+ var over = (fg, bg, alpha) => {
8665
+ const tint = bg === INK ? BLUE : DEEP;
8666
+ const busiest = mixHex(tint, mixHex(bg === INK ? "#ffffff" : INK, bg, 0.06), 0.14);
8667
+ return ensureContrast(mixHex(fg, bg, alpha), busiest);
8668
+ };
8643
8669
  var STAGE_TOKENS = {
8644
8670
  dark: {
8645
8671
  name: "dark",
8646
8672
  background: INK,
8647
- text: "#e6edf3",
8648
- muted: mixHex("#e6edf3", INK, 0.68),
8649
- edge: mixHex("#ffffff", INK, 0.42),
8650
- edgeLabel: mixHex("#e6edf3", INK, 0.86),
8651
- surface: mixHex("#ffffff", INK, 0.05),
8673
+ text: over("#ffffff", INK, 0.6),
8674
+ muted: over("#ffffff", INK, 0.5),
8675
+ edge: mixHex("#ffffff", INK, 0.25),
8676
+ edgeLabel: over("#ffffff", INK, 0.55),
8677
+ surface: INK,
8652
8678
  border: mixHex("#ffffff", INK, 0.16),
8653
8679
  zone: mixHex("#ffffff", INK, 0.03),
8654
- stepFill: INK,
8655
- stepText: "#e6edf3",
8680
+ stepFill: BLUE,
8681
+ stepText: INK,
8656
8682
  shadow: "#000000",
8657
- flow: "#60a5fa",
8683
+ flow: BLUE,
8658
8684
  stage: {
8685
+ line: "#ffffff",
8659
8686
  top: "#0e1a24",
8660
- tint: "#2563eb",
8661
- tintOpacity: 0.14,
8662
- dot: "#ffffff",
8663
- dotOpacity: 0.06,
8664
- wash: "#ffffff",
8665
- washOpacity: 0.035,
8666
- ring: "#60a5fa"
8687
+ tile: INK,
8688
+ tint: BLUE,
8689
+ onTint: INK,
8690
+ glyph: mixHex("#ffffff", INK, 0.55),
8691
+ header: over(BLUE, INK, 0.85),
8692
+ grid: 0.045,
8693
+ panel: 0.03,
8694
+ hair: 0.1,
8695
+ frame: 0.16,
8696
+ wire: 0.25,
8697
+ arrow: 0.4,
8698
+ wash: 0.12,
8699
+ glow: 1
8667
8700
  }
8668
8701
  },
8669
8702
  light: {
8670
8703
  name: "light",
8671
8704
  background: PAPER,
8672
- text: "#1f2933",
8673
- muted: mixHex("#1f2933", PAPER, 0.74),
8674
- edge: mixHex("#0b1012", PAPER, 0.56),
8675
- edgeLabel: "#2b3640",
8705
+ text: over(INK, PAPER, 0.66),
8706
+ muted: over(INK, PAPER, 0.58),
8707
+ edge: mixHex(INK, PAPER, 0.3),
8708
+ edgeLabel: over(INK, PAPER, 0.62),
8676
8709
  surface: "#ffffff",
8677
- border: mixHex("#0b1012", PAPER, 0.16),
8678
- zone: mixHex("#ffffff", PAPER, 0.6),
8679
- stepFill: INK,
8710
+ border: mixHex(INK, PAPER, 0.16),
8711
+ zone: mixHex(INK, PAPER, 0.03),
8712
+ stepFill: DEEP,
8680
8713
  stepText: "#ffffff",
8681
8714
  shadow: "#0f172a",
8682
- flow: "#2563eb",
8715
+ flow: DEEP,
8683
8716
  stage: {
8717
+ line: INK,
8684
8718
  top: "#ffffff",
8685
- tint: "#2563eb",
8686
- tintOpacity: 0.08,
8687
- dot: "#0b1012",
8688
- dotOpacity: 0.07,
8689
- wash: "#ffffff",
8690
- washOpacity: 0.7,
8691
- ring: "#2563eb"
8719
+ tile: "#ffffff",
8720
+ tint: DEEP,
8721
+ onTint: "#ffffff",
8722
+ glyph: mixHex(INK, "#ffffff", 0.6),
8723
+ header: over(DEEP, PAPER, 0.9),
8724
+ grid: 0.05,
8725
+ panel: 0.025,
8726
+ hair: 0.1,
8727
+ frame: 0.16,
8728
+ wire: 0.28,
8729
+ arrow: 0.45,
8730
+ wash: 0.08,
8731
+ glow: 0.5
8692
8732
  }
8693
8733
  }
8694
8734
  };
@@ -8698,24 +8738,26 @@ function tokensFor(scene) {
8698
8738
  var FONT_STACK = "Inter, 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, 'Helvetica Neue', Arial, sans-serif";
8699
8739
 
8700
8740
  // src/skins.ts
8701
- function neutral(hex) {
8702
- const c = parseHex(hex);
8703
- if (!c) return false;
8704
- return Math.max(...c) - Math.min(...c) < 26;
8705
- }
8706
8741
  function stageColors(scene) {
8707
8742
  const t = tokensFor(scene);
8708
8743
  const s = t.stage;
8709
8744
  if (!s) return scene;
8710
- const canvas = scene.background && scene.background !== "transparent" ? scene.background : t.background;
8711
- const washed = mixHex(s.wash, canvas, s.washOpacity);
8745
+ const canvas2 = scene.background && scene.background !== "transparent" ? scene.background : t.background;
8746
+ const panel = mixHex(s.line, canvas2, s.panel);
8712
8747
  for (const g of scene.groups) {
8713
- if (g.fill === "none" || !neutral(g.fill)) continue;
8714
- g.fill = washed;
8715
- const inner = g.inner && neutral(g.inner.fill);
8716
- if (g.inner && inner) g.inner.fill = washed;
8717
- g.wash = { color: s.wash, opacity: s.washOpacity, ...inner ? { inner: true } : {} };
8718
- g.labelColor = ensureContrast(g.labelColor, washed, 4.5);
8748
+ g.fill = g.dash || g.overlay ? "none" : panel;
8749
+ g.stroke = mixHex(s.line, canvas2, s.frame);
8750
+ if (g.inner) g.inner.fill = panel;
8751
+ g.labelColor = ensureContrast(g.depth === 0 ? s.header : t.text, panel);
8752
+ }
8753
+ for (const nd of scene.nodes) {
8754
+ nd.ink = void 0;
8755
+ nd.inkMuted = void 0;
8756
+ if (nd.look !== "shape" || !nd.color) continue;
8757
+ const lit2 = mixHex(nd.color, s.tile, 0.15);
8758
+ const fill2 = mixHex(nd.color, canvas2, scene.theme === "dark" ? 0.16 : 0.1);
8759
+ nd.ink = ensureContrast(ensureContrast(t.text, lit2), fill2);
8760
+ nd.inkMuted = ensureContrast(ensureContrast(t.muted, lit2), fill2);
8719
8761
  }
8720
8762
  return scene;
8721
8763
  }
@@ -9473,14 +9515,14 @@ async function layout(model, opts = {}) {
9473
9515
  for (const n3 of model.nodes) {
9474
9516
  const g = nodeGeometry(n3, horizontal);
9475
9517
  nodeGeom.set(n3.id, g);
9476
- const node3 = {
9518
+ const node4 = {
9477
9519
  id: n3.id,
9478
9520
  width: g.w,
9479
9521
  height: g.h,
9480
9522
  layoutOptions: { "elk.alignment": "CENTER" }
9481
9523
  };
9482
9524
  if (g.outside) {
9483
- node3.labels = [
9525
+ node4.labels = [
9484
9526
  {
9485
9527
  id: `${n3.id}__label`,
9486
9528
  text: n3.label,
@@ -9488,8 +9530,8 @@ async function layout(model, opts = {}) {
9488
9530
  height: g.outside.h
9489
9531
  }
9490
9532
  ];
9491
- node3.layoutOptions = {
9492
- ...node3.layoutOptions,
9533
+ node4.layoutOptions = {
9534
+ ...node4.layoutOptions,
9493
9535
  "elk.nodeLabels.placement": "OUTSIDE V_BOTTOM H_CENTER",
9494
9536
  "elk.spacing.labelNode": "6"
9495
9537
  };
@@ -9500,8 +9542,8 @@ async function layout(model, opts = {}) {
9500
9542
  const pill = badgePill(n3.badge, anchor2);
9501
9543
  const overhang = Math.ceil(pill.x + pill.w - g.w);
9502
9544
  if (overhang > 0)
9503
- node3.labels = [
9504
- ...node3.labels ?? [],
9545
+ node4.labels = [
9546
+ ...node4.labels ?? [],
9505
9547
  {
9506
9548
  id: `${n3.id}__badge`,
9507
9549
  text: n3.badge,
@@ -9513,7 +9555,7 @@ async function layout(model, opts = {}) {
9513
9555
  }
9514
9556
  ];
9515
9557
  }
9516
- elkNodes.set(n3.id, node3);
9558
+ elkNodes.set(n3.id, node4);
9517
9559
  }
9518
9560
  for (const grp of model.groups) groupGeom.set(grp.id, groupGeometry(grp));
9519
9561
  for (const grp of model.groups) {
@@ -9615,10 +9657,10 @@ async function layout(model, opts = {}) {
9615
9657
  }
9616
9658
  const stepW = e.step !== void 0 ? SIZES.step + 2 : 0;
9617
9659
  if (e.label || e.step !== void 0) {
9618
- const block = textBlock(e.label ?? "", SIZES.edgeLabel, SIZES.edgeLabelMax);
9619
- const w = Math.ceil((e.label ? block.width + 12 : 0) + stepW + (e.label && stepW ? 2 : 0));
9620
- const h = Math.ceil(Math.max(e.label ? block.height + 6 : 0, stepW ? SIZES.step : 0));
9621
- edgeLabels.set(e.id, { block, w, h, stepW });
9660
+ const block2 = textBlock(e.label ?? "", SIZES.edgeLabel, SIZES.edgeLabelMax);
9661
+ const w = Math.ceil((e.label ? block2.width + 12 : 0) + stepW + (e.label && stepW ? 2 : 0));
9662
+ const h = Math.ceil(Math.max(e.label ? block2.height + 6 : 0, stepW ? SIZES.step : 0));
9663
+ edgeLabels.set(e.id, { block: block2, w, h, stepW });
9622
9664
  elkEdge.labels = [
9623
9665
  {
9624
9666
  id: `${e.id}__label`,
@@ -9720,19 +9762,19 @@ async function layout(model, opts = {}) {
9720
9762
  const style2 = resolveGroupStyle(grp.type);
9721
9763
  if (!gg || !style2) return void 0;
9722
9764
  const strokeBase = grp.color ?? style2.stroke;
9723
- let stroke2 = strokeBase;
9724
- let fill = grp.fill === "none" ? "none" : grp.fill ?? style2.fill ?? "none";
9725
- if (overlay) fill = "none";
9765
+ let stroke3 = strokeBase;
9766
+ let fill2 = grp.fill === "none" ? "none" : grp.fill ?? style2.fill ?? "none";
9767
+ if (overlay) fill2 = "none";
9726
9768
  const ink = style2.labelColor === "ink" || !style2.labelColor;
9727
9769
  let labelColor = grp.color ?? (ink ? t.text : style2.labelColor ?? t.text);
9728
9770
  if (theme === "dark") {
9729
- if (luminance(strokeBase) < 0.04) stroke2 = "#c9d1d9";
9730
- else if (contrast(strokeBase, t.background) < 2) stroke2 = mixHex(strokeBase, "#ffffff", 0.55);
9731
- if (fill !== "none") fill = mixHex(fill, t.background, 0.14);
9771
+ if (luminance(strokeBase) < 0.04) stroke3 = "#c9d1d9";
9772
+ else if (contrast(strokeBase, t.background) < 2) stroke3 = mixHex(strokeBase, "#ffffff", 0.55);
9773
+ if (fill2 !== "none") fill2 = mixHex(fill2, t.background, 0.14);
9732
9774
  if (!grp.color && !ink && luminance(style2.labelColor ?? "#000000") < 0.04)
9733
9775
  labelColor = t.text;
9734
9776
  }
9735
- labelColor = ensureContrast(labelColor, fill === "none" ? t.background : fill, 4.5);
9777
+ labelColor = ensureContrast(labelColor, fill2 === "none" ? t.background : fill2, 4.5);
9736
9778
  const L = gg.label;
9737
9779
  let iconBox;
9738
9780
  let labelX;
@@ -9806,8 +9848,8 @@ async function layout(model, opts = {}) {
9806
9848
  },
9807
9849
  iconBox,
9808
9850
  icon: gg.icon,
9809
- stroke: stroke2,
9810
- fill,
9851
+ stroke: stroke3,
9852
+ fill: fill2,
9811
9853
  labelColor,
9812
9854
  dash: grp.dashed === false ? void 0 : style2.dash ?? (grp.dashed ? "6 4" : void 0),
9813
9855
  strokeWidth: style2.strokeWidth,
@@ -9841,7 +9883,7 @@ async function layout(model, opts = {}) {
9841
9883
  w: round(el.width ?? 0),
9842
9884
  h: round(el.height ?? 0)
9843
9885
  };
9844
- const node3 = {
9886
+ const node4 = {
9845
9887
  id: n3.id,
9846
9888
  look: n3.look,
9847
9889
  shape: n3.shape,
@@ -9864,31 +9906,31 @@ async function layout(model, opts = {}) {
9864
9906
  if (surface) {
9865
9907
  const ink = ensureContrast(t.text, surface, 4.5);
9866
9908
  const inkMuted = ensureContrast(t.muted, surface, 4.5);
9867
- if (ink !== t.text) node3.ink = ink;
9868
- if (inkMuted !== t.muted) node3.inkMuted = inkMuted;
9909
+ if (ink !== t.text) node4.ink = ink;
9910
+ if (inkMuted !== t.muted) node4.inkMuted = inkMuted;
9869
9911
  }
9870
9912
  const S = n3.iconSize;
9871
9913
  if (n3.look === "icon") {
9872
9914
  if (horizontal) {
9873
- node3.iconBox = { ...box };
9915
+ node4.iconBox = { ...box };
9874
9916
  const lab = el.labels?.[0];
9875
9917
  const lx = lab?.x !== void 0 ? lab.x : box.x + (S - (g.outside?.w ?? 0)) / 2;
9876
9918
  const ly = lab?.y !== void 0 ? lab.y + top : box.y + S + 6;
9877
9919
  const ow = g.outside?.w ?? g.label.width;
9878
- node3.labelBox = {
9920
+ node4.labelBox = {
9879
9921
  x: round(lx + (ow - g.label.width) / 2),
9880
9922
  y: round(ly),
9881
9923
  w: round(g.label.width),
9882
9924
  h: round(g.label.height)
9883
9925
  };
9884
9926
  } else {
9885
- node3.iconBox = {
9927
+ node4.iconBox = {
9886
9928
  x: round(box.x + (box.w - S) / 2),
9887
9929
  y: box.y,
9888
9930
  w: S,
9889
9931
  h: S
9890
9932
  };
9891
- node3.labelBox = {
9933
+ node4.labelBox = {
9892
9934
  x: round(box.x + (box.w - g.label.width) / 2),
9893
9935
  y: round(box.y + S + 6),
9894
9936
  w: round(g.label.width),
@@ -9896,9 +9938,9 @@ async function layout(model, opts = {}) {
9896
9938
  };
9897
9939
  }
9898
9940
  if (g.note) {
9899
- node3.noteBox = {
9900
- x: round(node3.labelBox.x + (g.label.width - g.note.width) / 2),
9901
- y: round(node3.labelBox.y + g.label.height + 2),
9941
+ node4.noteBox = {
9942
+ x: round(node4.labelBox.x + (g.label.width - g.note.width) / 2),
9943
+ y: round(node4.labelBox.y + g.label.height + 2),
9902
9944
  w: round(g.note.width),
9903
9945
  h: round(g.note.height)
9904
9946
  };
@@ -9907,7 +9949,7 @@ async function layout(model, opts = {}) {
9907
9949
  const textH = g.label.height + (g.note ? g.note.height + 2 : 0);
9908
9950
  const ix = box.x + 16;
9909
9951
  if (n3.icon)
9910
- node3.iconBox = {
9952
+ node4.iconBox = {
9911
9953
  x: round(ix),
9912
9954
  y: round(box.y + (box.h - S) / 2),
9913
9955
  w: S,
@@ -9915,14 +9957,14 @@ async function layout(model, opts = {}) {
9915
9957
  };
9916
9958
  const tx = n3.icon ? ix + S + 12 : box.x + 16;
9917
9959
  const ty = box.y + (box.h - textH) / 2;
9918
- node3.labelBox = {
9960
+ node4.labelBox = {
9919
9961
  x: round(tx),
9920
9962
  y: round(ty),
9921
9963
  w: round(g.label.width),
9922
9964
  h: round(g.label.height)
9923
9965
  };
9924
9966
  if (g.note)
9925
- node3.noteBox = {
9967
+ node4.noteBox = {
9926
9968
  x: round(tx),
9927
9969
  y: round(ty + g.label.height + 2),
9928
9970
  w: round(g.note.width),
@@ -9937,21 +9979,21 @@ async function layout(model, opts = {}) {
9937
9979
  const startX = box.x + (box.w - (textW + iconW)) / 2;
9938
9980
  const ty = box.y + extraTop + (innerH - textH) / 2;
9939
9981
  if (n3.icon)
9940
- node3.iconBox = {
9982
+ node4.iconBox = {
9941
9983
  x: round(startX),
9942
9984
  y: round(ty + (textH - 20) / 2),
9943
9985
  w: 20,
9944
9986
  h: 20
9945
9987
  };
9946
9988
  const tx = startX + iconW;
9947
- node3.labelBox = {
9989
+ node4.labelBox = {
9948
9990
  x: round(tx + (textW - g.label.width) / 2),
9949
9991
  y: round(ty),
9950
9992
  w: round(g.label.width),
9951
9993
  h: round(g.label.height)
9952
9994
  };
9953
9995
  if (g.note) {
9954
- node3.noteBox = {
9996
+ node4.noteBox = {
9955
9997
  x: round(tx + (textW - g.note.width) / 2),
9956
9998
  y: round(ty + g.label.height + 2),
9957
9999
  w: round(g.note.width),
@@ -9960,8 +10002,8 @@ async function layout(model, opts = {}) {
9960
10002
  }
9961
10003
  }
9962
10004
  if (n3.badge)
9963
- node3.badgeBox = badgePill(n3.badge, node3.iconBox && n3.look === "icon" ? node3.iconBox : box);
9964
- nodes.push(node3);
10005
+ node4.badgeBox = badgePill(n3.badge, node4.iconBox && n3.look === "icon" ? node4.iconBox : box);
10006
+ nodes.push(node4);
9965
10007
  }
9966
10008
  for (const grp of model.groups) {
9967
10009
  if (!grp.around?.length) continue;
@@ -10120,10 +10162,10 @@ async function layout(model, opts = {}) {
10120
10162
  for (const e of model.edges) {
10121
10163
  const edge3 = edges.find((x) => x.id === e.id);
10122
10164
  if (!free(e) || !edge3 || !e.label && e.step === void 0) continue;
10123
- const block = textBlock(e.label ?? "", SIZES.edgeLabel, SIZES.edgeLabelMax);
10165
+ const block2 = textBlock(e.label ?? "", SIZES.edgeLabel, SIZES.edgeLabelMax);
10124
10166
  const stepW = e.step !== void 0 ? SIZES.step + 2 : 0;
10125
- const w = Math.ceil((e.label ? block.width + 12 : 0) + stepW + (e.label && stepW ? 2 : 0));
10126
- const h = Math.ceil(Math.max(e.label ? block.height + 6 : 0, stepW ? SIZES.step : 0));
10167
+ const w = Math.ceil((e.label ? block2.width + 12 : 0) + stepW + (e.label && stepW ? 2 : 0));
10168
+ const h = Math.ceil(Math.max(e.label ? block2.height + 6 : 0, stepW ? SIZES.step : 0));
10127
10169
  const box = freeLabelBox(edge3.points, w, h, [
10128
10170
  ...footprints,
10129
10171
  ...edges.flatMap((x) => [x.labelBox, x.stepBox]),
@@ -10137,7 +10179,7 @@ async function layout(model, opts = {}) {
10137
10179
  h: SIZES.step
10138
10180
  };
10139
10181
  if (e.label) {
10140
- edge3.label = block;
10182
+ edge3.label = block2;
10141
10183
  edge3.labelBox = {
10142
10184
  x: round(box.x + stepW + (stepW ? 2 : 0)),
10143
10185
  y: box.y,
@@ -10275,11 +10317,11 @@ async function layout(model, opts = {}) {
10275
10317
  }
10276
10318
  width = Math.ceil(width);
10277
10319
  height = Math.ceil(height);
10278
- let legend3;
10320
+ let legend4;
10279
10321
  if (model.legend?.length) {
10280
- legend3 = placeLegend(model.legend, width, height);
10281
- width = Math.max(width, Math.ceil(legend3.box.w + SIZES.pad * 2));
10282
- height = Math.ceil(legend3.box.y + legend3.box.h + SIZES.pad);
10322
+ legend4 = placeLegend(model.legend, width, height);
10323
+ width = Math.max(width, Math.ceil(legend4.box.w + SIZES.pad * 2));
10324
+ height = Math.ceil(legend4.box.y + legend4.box.h + SIZES.pad);
10283
10325
  }
10284
10326
  const scene = {
10285
10327
  width,
@@ -10298,7 +10340,7 @@ async function layout(model, opts = {}) {
10298
10340
  nodes,
10299
10341
  groups,
10300
10342
  edges,
10301
- legend: legend3,
10343
+ legend: legend4,
10302
10344
  layoutFallback: fallback,
10303
10345
  description: describe(model)
10304
10346
  };
@@ -10350,8 +10392,8 @@ function fitIcons(scene) {
10350
10392
  if (w >= b.w - 0.01) continue;
10351
10393
  const x = round(b.x + (b.w - w) / 2);
10352
10394
  for (const e of scene.edges) {
10353
- const ends = [e.from === n3.id ? 0 : -1, e.to === n3.id ? e.points.length - 1 : -1];
10354
- for (const i of ends) {
10395
+ const ends2 = [e.from === n3.id ? 0 : -1, e.to === n3.id ? e.points.length - 1 : -1];
10396
+ for (const i of ends2) {
10355
10397
  const p = e.points[i];
10356
10398
  const next = e.points[i === 0 ? 1 : i - 1];
10357
10399
  if (!p || !next || Math.abs(next.y - p.y) > 0.5 || p.y < b.y || p.y > b.y + b.h) continue;
@@ -10383,7 +10425,7 @@ function stretchColumns(model, placed, edges) {
10383
10425
  box: { x: l.x ?? 0, y: l.y ?? 0, w: l.width, h: l.height }
10384
10426
  }))
10385
10427
  ]);
10386
- const labels = edges.flatMap(
10428
+ const labels2 = edges.flatMap(
10387
10429
  (e) => (e.labels ?? []).map((l) => ({
10388
10430
  x: l.x ?? 0,
10389
10431
  y: l.y ?? 0,
@@ -10428,7 +10470,7 @@ function stretchColumns(model, placed, edges) {
10428
10470
  if (s.w < 0.5) return true;
10429
10471
  const hit = (o) => overlaps2(s, { x: o.x, y: o.y, w: o.w || 0.01, h: o.h || 0.01 });
10430
10472
  if (items.some((it) => !related(it.id, el.id) && hit(it.box))) return false;
10431
- if (labels.some(hit)) return false;
10473
+ if (labels2.some(hit)) return false;
10432
10474
  return segments2.every(([p, q]) => {
10433
10475
  const [lo, hi] = [Math.min(p.x, q.x), Math.max(p.x, q.x)];
10434
10476
  const across = s.left ? lo <= s.x + 0.01 && hi > b.x + 0.5 : hi >= x1 - 0.01 && lo < s.x - 0.5;
@@ -10654,8 +10696,8 @@ function crossings(graph) {
10654
10696
  const s = e.sections?.[0];
10655
10697
  if (!s) return [];
10656
10698
  const pts = [s.startPoint, ...s.bendPoints ?? [], s.endPoint];
10657
- const ends = [nodeOf(e.sources[0]), nodeOf(e.targets[0])];
10658
- return [{ ends, segs: pts.slice(1).map((q, i) => [pts[i] ?? q, q]) }];
10699
+ const ends2 = [nodeOf(e.sources[0]), nodeOf(e.targets[0])];
10700
+ return [{ ends: ends2, segs: pts.slice(1).map((q, i) => [pts[i] ?? q, q]) }];
10659
10701
  });
10660
10702
  const cross = (a, b, c, d) => {
10661
10703
  const o = (p, q, r) => (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
@@ -10724,6 +10766,674 @@ function describe(model) {
10724
10766
  return parts.join(" ").replace(/\s+/g, " ").trim();
10725
10767
  }
10726
10768
 
10769
+ // src/render/stage.ts
10770
+ var DISPLAY = 880;
10771
+ var MONO = "'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace";
10772
+ var ADVANCE = 0.6;
10773
+ var fill = (c, a = 1) => `fill="${c}"${a < 1 ? ` fill-opacity="${a}"` : ""}`;
10774
+ var stroke = (c, a, w) => `stroke="${c}"${a < 1 ? ` stroke-opacity="${a}"` : ""} stroke-width="${n(w)}"`;
10775
+ var rect = (b, rx, paint, extra = "") => `<rect x="${n(b.x)}" y="${n(b.y)}" width="${n(b.w)}" height="${n(b.h)}"${rx ? ` rx="${n(rx)}"` : ""} ${paint}${extra}/>`;
10776
+ var LABEL = { size: 11.5, weight: 700, caps: true, track: 0.08 };
10777
+ var NOTE = { size: 10, weight: 400, caps: false, track: 0 };
10778
+ var EDGE = { size: 9.5, weight: 700, caps: true, track: 0.06 };
10779
+ var HEADER = { size: 11, weight: 700, caps: true, track: 0.1 };
10780
+ var TITLE = { size: 18, weight: 700, caps: true, track: 0.06 };
10781
+ var SUBTITLE = { size: 11.5, weight: 400, caps: false, track: 0 };
10782
+ var KEY = { size: 9.5, weight: 700, caps: true, track: 0.06 };
10783
+ var DIGIT = { size: 13, weight: 700, caps: true, track: 0 };
10784
+ var chars = (s) => [...s].length;
10785
+ function monoWidth(s, f, size = f.size) {
10786
+ const c = chars(s);
10787
+ return c ? size * (c * (ADVANCE + f.track) - f.track) : 0;
10788
+ }
10789
+ function sizeFor(lines, f, room, min = 8) {
10790
+ const widest = Math.max(1, ...lines.map(chars));
10791
+ const size = (room + f.size * f.track) / (widest * (ADVANCE + f.track));
10792
+ return Math.max(min, Math.floor(Math.min(f.size, size) * 4) / 4);
10793
+ }
10794
+ function common(fits, cap) {
10795
+ if (!fits.length) return cap;
10796
+ const sorted = [...fits].sort((a, b) => a - b);
10797
+ return Math.min(cap, sorted[Math.floor(sorted.length * 0.2)] ?? cap);
10798
+ }
10799
+ function mono(lines, f, size, at, color, anchor2, extra = "") {
10800
+ if (!lines.length) return "";
10801
+ const track = f.track * size;
10802
+ const x = at.x + (anchor2 === "middle" ? track / 2 : 0);
10803
+ const drop = (f.caps ? 0.355 : 0.33) * size;
10804
+ const spans = lines.map(
10805
+ (line, i) => `<tspan x="${n(x)}" y="${n(at.y + (i + 0.5) * at.lead + drop)}">${esc(f.caps ? line.toUpperCase() : line)}</tspan>`
10806
+ ).join("");
10807
+ const spacing = track ? ` letter-spacing="${n(track)}"` : "";
10808
+ const middle = anchor2 === "middle" ? ` text-anchor="middle"` : "";
10809
+ return `<text font-size="${n(size)}" font-weight="${f.weight}"${spacing} fill="${color}"${middle}${extra}>${spans}</text>`;
10810
+ }
10811
+ function block(b, box, f, size, color, anchor2 = "middle", extra = "") {
10812
+ const lead = b.lines.length ? box.h / b.lines.length : b.lead;
10813
+ const x = anchor2 === "middle" ? box.x + box.w / 2 : box.x;
10814
+ return mono(b.lines, f, size, { x, y: box.y, lead }, color, anchor2, extra);
10815
+ }
10816
+ var TONE_FIT = {
10817
+ glyph: 0.86,
10818
+ inverse: 0.86,
10819
+ two: 0.62,
10820
+ shape: 0.58,
10821
+ mono: 0.6
10822
+ };
10823
+ var LIGHT = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8929 3.0038 0.3032 0 -2.604";
10824
+ var DARK = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.8504 -2.8608 -0.2888 0 2.4";
10825
+ function toneFilter(ctx, tone, color) {
10826
+ const key = `${tone}|${color}`;
10827
+ let id = ctx.filters.get(key);
10828
+ if (id) return id;
10829
+ id = `${ctx.prefix}f${ctx.filters.size + 1}`;
10830
+ ctx.filters.set(key, id);
10831
+ const flood = `<feFlood flood-color="${color}"/>`;
10832
+ const body = tone === "glyph" ? `<feColorMatrix type="matrix" values="${LIGHT}" result="a"/>${flood}<feComposite in2="a" operator="in"/>` : tone === "inverse" ? `<feColorMatrix type="matrix" values="${DARK}" result="a"/>${flood}<feComposite in2="a" operator="in"/><feComposite in2="SourceAlpha" operator="in"/>` : tone === "two" ? `<feColorMatrix type="matrix" values="${LIGHT}" result="a"/><feFlood flood-color="${color}" flood-opacity="0.4"/><feComposite in2="SourceAlpha" operator="in" result="base"/>${flood}<feComposite in2="a" operator="in" result="hi"/><feMerge><feMergeNode in="base"/><feMergeNode in="hi"/></feMerge>` : `${flood}<feComposite in2="SourceAlpha" operator="in"/>`;
10833
+ ctx.defs.push(
10834
+ `<filter id="${id}" x="-0.1" y="-0.1" width="1.2" height="1.2" color-interpolation-filters="sRGB">${body}</filter>`
10835
+ );
10836
+ return id;
10837
+ }
10838
+ function glyph(ctx, id, box, color, scale = 1) {
10839
+ const tone = iconTone(id, ctx.t.name);
10840
+ const size = Math.min(box.w, box.h) * TONE_FIT[tone] * scale;
10841
+ const r = renderIcon(id, SYMBOL_ID, {
10842
+ theme: ctx.t.name,
10843
+ background: ctx.k.tile,
10844
+ ink: color,
10845
+ ...tone === "mono" ? { mono: color } : {}
10846
+ });
10847
+ let body = r.body;
10848
+ if (tone === "mono") {
10849
+ const weight = 1.5 * ctx.h * r.viewBox[2] / size;
10850
+ body = body.replace(
10851
+ /stroke-width="([\d.]+)"/g,
10852
+ (m, w) => Number(w) > weight ? `stroke-width="${n(weight)}"` : m
10853
+ );
10854
+ }
10855
+ const viewBox = r.viewBox.join(" ");
10856
+ const key = `${viewBox}|${body}`;
10857
+ let ref = ctx.symbols.get(key);
10858
+ if (!ref) {
10859
+ ref = `${ctx.prefix}s${ctx.symbols.size + 1}`;
10860
+ ctx.symbols.set(key, ref);
10861
+ ctx.defs.push(
10862
+ `<symbol id="${ref}" viewBox="${viewBox}" overflow="visible">${body.replaceAll(`${SYMBOL_ID}-`, `${ref}-`)}</symbol>`
10863
+ );
10864
+ }
10865
+ const paint = tone === "mono" ? "" : ` filter="url(#${toneFilter(ctx, tone, color)})"`;
10866
+ const x = box.x + (box.w - size) / 2;
10867
+ const y = box.y + (box.h - size) / 2;
10868
+ return `<use href="#${ref}" x="${n(x)}" y="${n(y)}" width="${n(size)}" height="${n(size)}"${paint}/>`;
10869
+ }
10870
+ var GROUPS_ON = 0.35;
10871
+ var TILES_ON = 0.7;
10872
+ var STORY_AT = 1.25;
10873
+ var SPEED = 320;
10874
+ var PAUSE = 0.24;
10875
+ var HOLD_FOR = 0.9;
10876
+ var RAMP = 0.18;
10877
+ var FADE = 0.15;
10878
+ var COMET = 26;
10879
+ var HOLD = 0.9;
10880
+ var GONE = 0.94;
10881
+ var SIDE_FLOWS = 2;
10882
+ var EASE = "0.65 0 0.35 1";
10883
+ var ends = (e) => e.arrow === "start" ? [e.to, e.from] : [e.from, e.to];
10884
+ function longestPath(edges) {
10885
+ const out = /* @__PURE__ */ new Map();
10886
+ const starts = [];
10887
+ for (const e of edges) {
10888
+ const [a, b] = ends(e);
10889
+ if (a === b) continue;
10890
+ out.set(a, [...out.get(a) ?? [], e]);
10891
+ if (!starts.includes(a)) starts.push(a);
10892
+ }
10893
+ const memo = /* @__PURE__ */ new Map();
10894
+ const open = /* @__PURE__ */ new Set();
10895
+ const from = (v) => {
10896
+ const known = memo.get(v);
10897
+ if (known) return known;
10898
+ open.add(v);
10899
+ let best2 = [];
10900
+ for (const e of out.get(v) ?? []) {
10901
+ const next = ends(e)[1];
10902
+ if (open.has(next)) continue;
10903
+ const path = [e, ...from(next)];
10904
+ if (path.length > best2.length) best2 = path;
10905
+ }
10906
+ open.delete(v);
10907
+ memo.set(v, best2);
10908
+ return best2;
10909
+ };
10910
+ let best = [];
10911
+ for (const v of starts) {
10912
+ const path = from(v);
10913
+ if (path.length > best.length) best = path;
10914
+ }
10915
+ return best;
10916
+ }
10917
+ function storyPlan(scene, h) {
10918
+ const animated = scene.animate === "relay" || scene.animate === "packets";
10919
+ const story = {
10920
+ animated,
10921
+ cycle: 0,
10922
+ hold: 0,
10923
+ gone: 0,
10924
+ runs: /* @__PURE__ */ new Map(),
10925
+ side: /* @__PURE__ */ new Map(),
10926
+ badges: /* @__PURE__ */ new Map(),
10927
+ focus: { x: scene.width * 0.6, y: scene.height * 0.45 }
10928
+ };
10929
+ const directed = scene.edges.filter((e) => e.arrow !== "none" && e.points.length > 1);
10930
+ const travel = (e) => Math.min(1, Math.max(0.4, length(e.points) / h / SPEED));
10931
+ const stepped = directed.filter((e) => e.step !== void 0);
10932
+ let t = STORY_AT;
10933
+ if (stepped.length) {
10934
+ const steps = [...new Set(stepped.map((e) => e.step ?? 0))].sort((a, b) => a - b);
10935
+ steps.forEach((step, i) => {
10936
+ let took = 0;
10937
+ for (const e of stepped.filter((x) => x.step === step)) {
10938
+ const tr = travel(e);
10939
+ const park = i < steps.length - 1 ? PAUSE : 0;
10940
+ const runs = e.arrow === "both" ? [
10941
+ { t0: t, t1: t + tr, reverse: false, park: PAUSE },
10942
+ { t0: t + tr + PAUSE, t1: t + 2 * tr + PAUSE, reverse: true, park }
10943
+ ] : [{ t0: t, t1: t + tr, reverse: e.arrow === "start", park }];
10944
+ story.runs.set(e.id, runs);
10945
+ story.badges.set(e.id, t);
10946
+ took = Math.max(took, (runs[runs.length - 1]?.t1 ?? t) - t);
10947
+ }
10948
+ t += took + PAUSE;
10949
+ });
10950
+ } else {
10951
+ const path = longestPath(directed);
10952
+ path.forEach((e, i) => {
10953
+ const tr = travel(e);
10954
+ const park = i < path.length - 1 ? PAUSE : 0;
10955
+ story.runs.set(e.id, [{ t0: t, t1: t + tr, reverse: e.arrow === "start", park }]);
10956
+ t += tr + PAUSE;
10957
+ });
10958
+ }
10959
+ const end = story.runs.size ? t - PAUSE : TILES_ON + RAMP;
10960
+ story.hold = end + HOLD_FOR;
10961
+ story.cycle = story.hold / HOLD;
10962
+ story.gone = story.cycle * GONE;
10963
+ const on = new Set(
10964
+ scene.edges.filter((e) => story.runs.has(e.id)).flatMap((e) => [e.from, e.to])
10965
+ );
10966
+ const side = directed.filter((e) => !story.runs.has(e.id)).sort((a, b) => Number(on.has(b.from) || on.has(b.to)) - Number(on.has(a.from) || on.has(a.to))).slice(0, SIDE_FLOWS);
10967
+ side.forEach((e, i) => {
10968
+ const tr = travel(e);
10969
+ const span = Math.max(0, end - STORY_AT);
10970
+ const t0 = Math.min(STORY_AT + span * (0.45 + 0.3 * i), story.hold - 0.2 - tr);
10971
+ story.side.set(e.id, {
10972
+ t0: Math.max(STORY_AT, t0),
10973
+ t1: Math.max(STORY_AT, t0) + tr,
10974
+ reverse: e.arrow === "start",
10975
+ park: 0
10976
+ });
10977
+ });
10978
+ const pts = scene.edges.filter((e) => story.runs.has(e.id)).flatMap((e) => e.points);
10979
+ if (pts.length) {
10980
+ const xs = pts.map((p) => p.x);
10981
+ const ys = pts.map((p) => p.y);
10982
+ story.focus = {
10983
+ x: (Math.min(...xs) + Math.max(...xs)) / 2,
10984
+ y: (Math.min(...ys) + Math.max(...ys)) / 2
10985
+ };
10986
+ }
10987
+ return story;
10988
+ }
10989
+ var loop = (ctx) => `dur="${secs(ctx.story.cycle)}" repeatCount="indefinite"`;
10990
+ var kt = (ctx, times) => keyTimes(times, ctx.story.cycle);
10991
+ function show(ctx, on, off) {
10992
+ const { cycle } = ctx.story;
10993
+ return `<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt(ctx, [0, on, on + RAMP, off - RAMP, off, cycle])}" ${loop(ctx)}/>`;
10994
+ }
10995
+ function lit(ctx, body, on, off = ctx.story.gone) {
10996
+ if (!body) return "";
10997
+ return ctx.story.animated ? `<g opacity="0">${body}${show(ctx, on, off)}</g>` : body;
10998
+ }
10999
+ function packet(ctx, d, run, color, r) {
11000
+ const { cycle } = ctx.story;
11001
+ const [a, b] = run.reverse ? ["1", "0"] : ["0", "1"];
11002
+ const gone = run.t1 + run.park + FADE;
11003
+ return `<circle r="${n(r)}" fill="${color}" opacity="0"><animateMotion path="${d}" ${loop(ctx)} calcMode="spline" keyPoints="${a};${a};${b};${b}" keyTimes="${kt(ctx, [0, run.t0, run.t1, cycle])}" keySplines="0 0 1 1;${EASE};0 0 1 1"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt(ctx, [0, run.t0 - FADE, run.t0, gone - FADE, gone, cycle])}" ${loop(ctx)}/></circle>`;
11004
+ }
11005
+ function comet(ctx, d, run, color, len) {
11006
+ const { cycle } = ctx.story;
11007
+ const f = Math.min(0.5, COMET / Math.max(1, len / ctx.h));
11008
+ const settle = run.t1 + f * (run.t1 - run.t0);
11009
+ const offsets = run.reverse ? [-1, -1, 0, f, f] : [f, f, f - 1, -1, -1];
11010
+ const times = kt(ctx, [0, run.t0, run.t1, settle, cycle]);
11011
+ return `<path d="${d}" fill="none" ${stroke(color, 0.6, 2.4 * ctx.h)} pathLength="1" stroke-dasharray="${n(f)} 2" stroke-dashoffset="${n(offsets[0] ?? 0)}" opacity="0"><animate attributeName="stroke-dashoffset" values="${offsets.map(n).join(";")}" keyTimes="${times}" calcMode="spline" keySplines="0 0 1 1;${EASE};0 0 1 1;0 0 1 1" ${loop(ctx)}/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt(ctx, [0, run.t0, run.t0 + 0.01, settle, settle + 0.01, cycle])}" ${loop(ctx)}/></path>`;
11012
+ }
11013
+ function canvas(ctx) {
11014
+ const { k, t, scene, h } = ctx;
11015
+ if (scene.background === "transparent") return "";
11016
+ const p = ctx.prefix;
11017
+ const W = scene.width;
11018
+ const H = scene.height;
11019
+ const cell = 20 * h;
11020
+ const { x: fx, y: fy } = ctx.story.focus;
11021
+ const reach = Math.max(
11022
+ ...[
11023
+ [0, 0],
11024
+ [W, 0],
11025
+ [0, H],
11026
+ [W, H]
11027
+ ].map(([x = 0, y = 0]) => Math.hypot(x - fx, y - fy))
11028
+ );
11029
+ ctx.defs.push(
11030
+ `<linearGradient id="${p}bg" x1="0" y1="0" x2="0.34" y2="0.94"><stop offset="0" stop-color="${k.top}"/><stop offset="0.6" stop-color="${t.background}"/></linearGradient><pattern id="${p}grid" width="${n(cell)}" height="${n(cell)}" patternUnits="userSpaceOnUse"><path d="M0 ${n(h / 2)}H${n(cell)}M${n(h / 2)} 0V${n(cell)}" fill="none" ${stroke(k.line, k.grid, h)}/></pattern><radialGradient id="${p}wash" gradientUnits="userSpaceOnUse" cx="${n(fx)}" cy="${n(fy)}" r="${n(reach * 0.6)}"><stop offset="0" stop-color="${k.tint}" stop-opacity="${k.wash}"/><stop offset="1" stop-color="${k.tint}" stop-opacity="0"/></radialGradient>`
11031
+ );
11032
+ const base = scene.background ?? `url(#${p}bg)`;
11033
+ return `<rect width="${W}" height="${H}" fill="${base}"/><rect width="${W}" height="${H}" fill="url(#${p}grid)"/><rect width="${W}" height="${H}" fill="url(#${p}wash)"/>`;
11034
+ }
11035
+ function groupFrame(ctx, g) {
11036
+ const { k, h } = ctx;
11037
+ const dash = g.dash ? ` stroke-dasharray="${n(3 * h)} ${n(3 * h)}"` : "";
11038
+ const rx = g.dash ? 0 : 2 * h;
11039
+ const panel = !g.dash && g.depth < 2 ? fill(k.line, k.panel) : `fill="none"`;
11040
+ const tint = g.depth === 0 ? fill(k.tint, (g.dash ? 0.04 : 0.03) * k.glow) : `fill="none"`;
11041
+ const base = rect(g.box, rx, `${panel} ${stroke(k.line, k.frame, h)}`, dash);
11042
+ const glow = rect(g.box, rx, `${tint} ${stroke(k.tint, g.dash ? 0.5 : 0.6, h)}`, dash);
11043
+ return base + lit(ctx, glow, GROUPS_ON);
11044
+ }
11045
+ function crosses(a, b, box) {
11046
+ let lo = 0;
11047
+ let hi = 1;
11048
+ const dx = b.x - a.x;
11049
+ const dy = b.y - a.y;
11050
+ const sides = [
11051
+ [-dx, a.x - box.x],
11052
+ [dx, box.x + box.w - a.x],
11053
+ [-dy, a.y - box.y],
11054
+ [dy, box.y + box.h - a.y]
11055
+ ];
11056
+ for (const [p, q] of sides) {
11057
+ if (p === 0) {
11058
+ if (q < 0) return false;
11059
+ continue;
11060
+ }
11061
+ const r = q / p;
11062
+ if (p < 0) lo = Math.max(lo, r);
11063
+ else hi = Math.min(hi, r);
11064
+ if (lo > hi) return false;
11065
+ }
11066
+ return true;
11067
+ }
11068
+ function groupHeader(ctx, g) {
11069
+ const { k, h } = ctx;
11070
+ const parts = [];
11071
+ if (g.icon && g.iconBox) {
11072
+ const b = g.iconBox;
11073
+ if (b.w >= 28) {
11074
+ parts.push(rect(b, 0, fill(k.line, k.frame)));
11075
+ parts.push(glyph(ctx, g.icon, b, mixHex(k.line, k.tile, 0.7), 0.85));
11076
+ parts.push(
11077
+ lit(ctx, rect(b, 0, fill(k.tint)) + glyph(ctx, g.icon, b, k.onTint, 0.85), GROUPS_ON)
11078
+ );
11079
+ } else {
11080
+ parts.push(glyph(ctx, g.icon, b, k.glyph, 1.5));
11081
+ parts.push(lit(ctx, glyph(ctx, g.icon, b, k.tint, 1.5), GROUPS_ON));
11082
+ }
11083
+ }
11084
+ if (g.label.lines.length) {
11085
+ const b = g.labelBox;
11086
+ const room = Math.max(b.w, g.box.x + g.box.w - b.x - 10 * h);
11087
+ const size = sizeFor(g.label.lines, HEADER, room, 8.5);
11088
+ const w = Math.max(...g.label.lines.map((l) => monoWidth(l, HEADER, size)));
11089
+ const chip = { x: b.x - 4, y: b.y - 1, w: w + 8, h: b.h + 2 };
11090
+ const crossed = ctx.scene.edges.some(
11091
+ (e) => e.points.some((p, i) => {
11092
+ const q = e.points[i + 1];
11093
+ return q !== void 0 && crosses(p, q, chip);
11094
+ })
11095
+ );
11096
+ if (crossed) parts.push(rect(chip, 3, fill(ctx.t.background)));
11097
+ parts.push(block(g.label, b, HEADER, size, g.labelColor, "start"));
11098
+ }
11099
+ return parts.join("");
11100
+ }
11101
+ var ARROW_LEN = 6;
11102
+ var ARROW_HALF = 4;
11103
+ function chevron(ctx, tip, from, color, alpha) {
11104
+ const len = ARROW_LEN * ctx.h;
11105
+ const half = ARROW_HALF * ctx.h;
11106
+ const d = Math.hypot(tip.x - from.x, tip.y - from.y) || 1;
11107
+ const ux = (tip.x - from.x) / d;
11108
+ const uy = (tip.y - from.y) / d;
11109
+ const bx = tip.x - ux * len;
11110
+ const by = tip.y - uy * len;
11111
+ return `<path d="M${n(bx - uy * half)} ${n(by + ux * half)} L${n(tip.x)} ${n(tip.y)} L${n(bx + uy * half)} ${n(by - ux * half)}" fill="none" ${stroke(color, alpha, ctx.h)} stroke-linecap="round" stroke-linejoin="round"/>`;
11112
+ }
11113
+ function wireOf(ctx, e) {
11114
+ const h = ctx.h;
11115
+ let pts = e.points;
11116
+ if (pts.length < 2) return void 0;
11117
+ const end = e.arrow === "end" || e.arrow === "both";
11118
+ const start = e.arrow === "start" || e.arrow === "both";
11119
+ const spline = ctx.scene.routing === "spline" && (pts.length - 1) % 3 === 0 && pts.length > 2;
11120
+ if (!spline) {
11121
+ if (end) pts = trim(pts, true, h / 2);
11122
+ if (start) pts = trim(pts, false, h / 2);
11123
+ }
11124
+ const width = e.line === "thick" ? 1.8 * h : h;
11125
+ const dash = e.line === "dashed" ? ` stroke-dasharray="${n(4 * h)} ${n(3 * h)}"` : e.line === "dotted" ? ` stroke-dasharray="${n(h)} ${n(2.5 * h)}"` : "";
11126
+ const o = e.points;
11127
+ const last = o[o.length - 1];
11128
+ const before = o[o.length - 2];
11129
+ const first = o[0];
11130
+ const second = o[1];
11131
+ return {
11132
+ d: edgePath(pts, ctx.scene.routing),
11133
+ len: length(pts),
11134
+ dash,
11135
+ width,
11136
+ heads: {
11137
+ ...end && last && before ? { end: [last, before] } : {},
11138
+ ...start && first && second ? { start: [first, second] } : {}
11139
+ }
11140
+ };
11141
+ }
11142
+ function edgeBase(ctx, e, w) {
11143
+ const { k } = ctx;
11144
+ const flow = ctx.scene.animate === "flow" ? ` class="sdw-flow${e.line === "solid" || e.line === "thick" ? " sdw-solid" : ""}"` : "";
11145
+ const heads = [w.heads.end, w.heads.start].map((hd) => hd ? chevron(ctx, hd[0], hd[1], k.line, k.arrow) : "").join("");
11146
+ return `<path d="${w.d}" fill="none" ${stroke(k.line, k.wire, w.width)} stroke-linecap="round" stroke-linejoin="round"${w.dash}${flow}/>${heads}`;
11147
+ }
11148
+ function edgeLit(ctx, e, w, runs) {
11149
+ const { story, h } = ctx;
11150
+ const color = e.color ?? ctx.k.tint;
11151
+ const width = (e.line === "thick" ? 1.8 : 1.2) * h;
11152
+ const first = runs[0];
11153
+ if (!first) return "";
11154
+ const parts = [];
11155
+ const line = `<path d="${w.d}" fill="none" ${stroke(color, 0.5, width)} stroke-linecap="round" stroke-linejoin="round"${w.dash}/>`;
11156
+ if (!story.animated) parts.push(line);
11157
+ else {
11158
+ const hide = first.reverse ? "-1" : "1";
11159
+ const reveal = `<animate attributeName="stroke-dashoffset" values="${hide};${hide};0;0" keyTimes="${kt(ctx, [0, first.t0, first.t1, story.cycle])}" calcMode="spline" keySplines="0 0 1 1;${EASE};0 0 1 1" ${loop(ctx)}/>`;
11160
+ const off = story.hold + RAMP;
11161
+ if (w.dash) {
11162
+ const id = `${ctx.prefix}m-${e.id}`;
11163
+ ctx.defs.push(
11164
+ `<mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${ctx.scene.width}" height="${ctx.scene.height}"><path d="${w.d}" fill="none" stroke="#ffffff" stroke-width="${n(width + 6 * h)}" pathLength="1" stroke-dasharray="1 1" stroke-dashoffset="${hide}">${reveal}</path></mask>`
11165
+ );
11166
+ parts.push(`<g mask="url(#${id})" opacity="0">${line}${show(ctx, first.t0, off)}</g>`);
11167
+ } else {
11168
+ parts.push(
11169
+ `<path d="${w.d}" fill="none" ${stroke(color, 0.5, width)} stroke-linecap="round" stroke-linejoin="round" pathLength="1" stroke-dasharray="1 1" stroke-dashoffset="${hide}" opacity="0">${reveal}${show(ctx, first.t0, off)}</path>`
11170
+ );
11171
+ }
11172
+ }
11173
+ for (const run of runs) {
11174
+ const hd = run.reverse ? w.heads.start : w.heads.end;
11175
+ if (hd) parts.push(lit(ctx, chevron(ctx, hd[0], hd[1], color, 0.7), run.t1, story.hold + RAMP));
11176
+ }
11177
+ return parts.join("");
11178
+ }
11179
+ function edgeLabel(ctx, e) {
11180
+ const { k, h, story } = ctx;
11181
+ const parts = [];
11182
+ const runs = story.runs.get(e.id);
11183
+ const on = runs?.[0]?.t0 ?? 0;
11184
+ if (e.labelBox && e.label?.lines.length) {
11185
+ const b = e.labelBox;
11186
+ const size = Math.min(ctx.sizes.edge, sizeFor(e.label.lines, EDGE, b.w - 8, 7));
11187
+ const w = Math.max(b.w, ...e.label.lines.map((l) => monoWidth(l, EDGE, size) + 8));
11188
+ const chip = { x: b.x + b.w / 2 - w / 2, y: b.y, w, h: b.h };
11189
+ parts.push(rect(chip, 3, `${fill(k.tile)} ${stroke(k.line, k.hair, h)}`));
11190
+ parts.push(block(e.label, b, EDGE, size, ctx.t.edgeLabel));
11191
+ if (runs) {
11192
+ const color = e.color ?? k.tint;
11193
+ parts.push(
11194
+ lit(
11195
+ ctx,
11196
+ rect(chip, 3, `${fill(k.tile)} ${stroke(color, 0.5, h)}`) + block(e.label, b, EDGE, size, color),
11197
+ on,
11198
+ story.hold + RAMP
11199
+ )
11200
+ );
11201
+ }
11202
+ }
11203
+ if (e.stepBox && e.step !== void 0) {
11204
+ const s = e.stepBox;
11205
+ const cx = s.x + s.w / 2;
11206
+ const cy = s.y + s.h / 2;
11207
+ const r = s.w / 2;
11208
+ const digit = (color, x, y) => mono(
11209
+ [String(e.step)],
11210
+ DIGIT,
11211
+ Math.min(DIGIT.size, r),
11212
+ { x, y: y - r, lead: 2 * r },
11213
+ color,
11214
+ "middle"
11215
+ );
11216
+ parts.push(
11217
+ `<circle cx="${n(cx)}" cy="${n(cy)}" r="${n(r)}" ${fill(k.tile)} ${stroke(k.line, k.frame, h)}/>`
11218
+ );
11219
+ parts.push(digit(ctx.t.text, cx, cy));
11220
+ const pop = `<circle r="${n(r)}" ${fill(e.color ?? k.tint)}/>${digit(k.onTint, 0, 0)}`;
11221
+ const at = story.badges.get(e.id);
11222
+ if (!story.animated) parts.push(`<g transform="translate(${n(cx)} ${n(cy)})">${pop}</g>`);
11223
+ else if (at !== void 0) {
11224
+ const times = kt(ctx, [0, at, at + RAMP, at + 2 * RAMP, story.hold, story.gone, story.cycle]);
11225
+ parts.push(
11226
+ `<g transform="translate(${n(cx)} ${n(cy)})"><g opacity="0">${pop}<animate attributeName="opacity" values="0;0;1;1;1;0;0" keyTimes="${times}" ${loop(ctx)}/><animateTransform attributeName="transform" type="scale" values="0.4;0.4;1.3;1;1;1;0.4" keyTimes="${times}" ${loop(ctx)}/></g></g>`
11227
+ );
11228
+ }
11229
+ }
11230
+ return parts.length ? `<g id="${ctx.prefix}el-${e.id}">${parts.join("")}</g>` : "";
11231
+ }
11232
+ function tile(ctx, nd, b) {
11233
+ const { k, h } = ctx;
11234
+ const rx = 0.17 * Math.min(b.w, b.h);
11235
+ const tint = nd.color ?? k.tint;
11236
+ return rect(b, rx, `${fill(k.tile)} ${stroke(k.line, k.frame, h)}`) + lit(ctx, rect(b, rx, `${fill(tint, 0.15)} ${stroke(tint, 0.65, h)}`), TILES_ON) + (nd.icon ? glyph(ctx, nd.icon, b, k.glyph) : "");
11237
+ }
11238
+ function badge(ctx, label, anchor2, placed) {
11239
+ const { k, h } = ctx;
11240
+ const size = 8.5;
11241
+ const w = placed?.w ?? Math.max(18, monoWidth(label, KEY, size) + 10);
11242
+ const bh = placed?.h ?? 16;
11243
+ const b = {
11244
+ x: placed?.x ?? anchor2.x + anchor2.w - w / 2 - 2,
11245
+ y: placed?.y ?? anchor2.y - 7,
11246
+ w: Math.max(w, monoWidth(label, KEY, size) + 10),
11247
+ h: bh
11248
+ };
11249
+ return rect(b, bh / 2, `${fill(k.tile)} ${stroke(k.line, k.frame, h)}`) + mono([label], KEY, size, { x: b.x + b.w / 2, y: b.y, lead: bh }, ctx.t.edgeLabel, "middle");
11250
+ }
11251
+ function labels(ctx, nd, anchor2, room) {
11252
+ const own = sizeFor(nd.label.lines, LABEL, room, 8);
11253
+ const parts = [
11254
+ block(
11255
+ nd.label,
11256
+ nd.labelBox,
11257
+ LABEL,
11258
+ Math.min(ctx.sizes.label, own),
11259
+ nd.ink ?? ctx.t.text,
11260
+ anchor2
11261
+ )
11262
+ ];
11263
+ if (nd.note && nd.noteBox)
11264
+ parts.push(
11265
+ block(
11266
+ nd.note,
11267
+ nd.noteBox,
11268
+ NOTE,
11269
+ Math.min(ctx.sizes.note, sizeFor(nd.note.lines, NOTE, room, 8)),
11270
+ nd.inkMuted ?? ctx.t.muted,
11271
+ anchor2
11272
+ )
11273
+ );
11274
+ return parts.join("");
11275
+ }
11276
+ function labelRoom(nd) {
11277
+ if (nd.look === "card") return nd.box.x + nd.box.w - nd.labelBox.x - 10;
11278
+ return Math.max(nd.labelBox.w, nd.look === "icon" ? nd.box.w : 0) + 14;
11279
+ }
11280
+ function node(ctx, nd) {
11281
+ const { k, h } = ctx;
11282
+ const parts = [];
11283
+ const room = labelRoom(nd);
11284
+ if (nd.look === "icon") {
11285
+ if (nd.iconBox) parts.push(tile(ctx, nd, nd.iconBox));
11286
+ parts.push(labels(ctx, nd, "middle", room));
11287
+ if (nd.badge && nd.iconBox) parts.push(badge(ctx, nd.badge, nd.iconBox, nd.badgeBox));
11288
+ } else if (nd.look === "card") {
11289
+ const tint = nd.color ?? k.tint;
11290
+ parts.push(rect(nd.box, 6, `${fill(k.tile)} ${stroke(k.line, k.frame, h)}`));
11291
+ parts.push(lit(ctx, rect(nd.box, 6, `${fill(tint, 0.15)} ${stroke(tint, 0.65, h)}`), TILES_ON));
11292
+ if (nd.icon && nd.iconBox) parts.push(tile(ctx, { ...nd, color: tint }, nd.iconBox));
11293
+ parts.push(labels(ctx, nd, "start", room));
11294
+ if (nd.badge) parts.push(badge(ctx, nd.badge, nd.box, nd.badgeBox));
11295
+ } else {
11296
+ const tint = nd.color ?? k.tint;
11297
+ parts.push(
11298
+ `<g ${fill(k.tile)} ${stroke(k.line, k.frame, h)}>${shapePath(nd.shape, nd.box)}</g>`
11299
+ );
11300
+ parts.push(
11301
+ lit(
11302
+ ctx,
11303
+ `<g ${fill(tint, 0.15)} ${stroke(tint, 0.65, h)}>${shapePath(nd.shape, nd.box)}</g>`,
11304
+ TILES_ON
11305
+ )
11306
+ );
11307
+ if (nd.icon && nd.iconBox) parts.push(glyph(ctx, nd.icon, nd.iconBox, k.glyph, 1.5));
11308
+ parts.push(labels(ctx, nd, "middle", room));
11309
+ if (nd.badge) parts.push(badge(ctx, nd.badge, nd.box, nd.badgeBox));
11310
+ }
11311
+ const inner = parts.join("");
11312
+ const body = nd.url ? `<a href="${esc(nd.url)}" xlink:href="${esc(nd.url)}" target="_blank">${inner}</a>` : inner;
11313
+ return `<g id="${ctx.prefix}n-${nd.id}">${body}</g>`;
11314
+ }
11315
+ function legend(ctx) {
11316
+ const l = ctx.scene.legend;
11317
+ if (!l?.items.length) return "";
11318
+ const { k, h } = ctx;
11319
+ const parts = [rect(l.box, 6, `${fill(k.tile)} ${stroke(k.line, k.hair, h)}`)];
11320
+ for (const item of l.items) {
11321
+ const s = item.swatch;
11322
+ const y = s.y + s.h / 2;
11323
+ const dash = item.line === "dashed" ? ` stroke-dasharray="${n(4 * h)} ${n(3 * h)}"` : item.line === "dotted" ? ` stroke-dasharray="${n(h)} ${n(2.5 * h)}"` : "";
11324
+ parts.push(
11325
+ `<path d="M${n(s.x)} ${n(y)} H${n(s.x + s.w)}" fill="none" ${stroke(k.line, k.arrow, item.line === "thick" ? 1.8 * h : h)} stroke-linecap="round"${dash}/>`
11326
+ );
11327
+ const b = item.labelBox;
11328
+ parts.push(
11329
+ block(
11330
+ item.label,
11331
+ b,
11332
+ KEY,
11333
+ sizeFor(item.label.lines, KEY, l.box.x + l.box.w - b.x - 10, 7),
11334
+ ctx.t.text,
11335
+ "start"
11336
+ )
11337
+ );
11338
+ }
11339
+ return `<g id="${ctx.prefix}legend">${parts.join("")}</g>`;
11340
+ }
11341
+ function renderStage(scene, opts = {}) {
11342
+ const t = tokensFor(scene);
11343
+ const k = t.stage;
11344
+ if (!k) throw new Error("renderStage needs the stage skin");
11345
+ const prefix = opts.idPrefix ? `${opts.idPrefix.replace(/[^A-Za-z0-9_-]/g, "")}-` : "";
11346
+ const h = 1 / Math.min(1, DISPLAY / Math.max(1, scene.width));
11347
+ const ctx = {
11348
+ t,
11349
+ k,
11350
+ prefix,
11351
+ scene,
11352
+ h,
11353
+ story: storyPlan(scene, h),
11354
+ sizes: {
11355
+ label: common(
11356
+ scene.nodes.map((nd) => sizeFor(nd.label.lines, LABEL, labelRoom(nd))),
11357
+ LABEL.size
11358
+ ),
11359
+ note: common(
11360
+ scene.nodes.flatMap((nd) => nd.note ? [sizeFor(nd.note.lines, NOTE, labelRoom(nd))] : []),
11361
+ NOTE.size
11362
+ ),
11363
+ edge: common(
11364
+ scene.edges.flatMap(
11365
+ (e) => e.label && e.labelBox ? [sizeFor(e.label.lines, EDGE, e.labelBox.w - 8, 7)] : []
11366
+ ),
11367
+ EDGE.size
11368
+ )
11369
+ },
11370
+ symbols: /* @__PURE__ */ new Map(),
11371
+ filters: /* @__PURE__ */ new Map(),
11372
+ defs: []
11373
+ };
11374
+ const { width: W, height: H } = scene;
11375
+ const titleId = `${prefix}sdw-title`;
11376
+ const descId = `${prefix}sdw-desc`;
11377
+ const out = [];
11378
+ out.push(
11379
+ `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${W}" height="${H}" viewBox="0 0 ${W} ${H}" role="img" aria-labelledby="${titleId} ${descId}" font-family="${esc(MONO)}">`
11380
+ );
11381
+ out.push(
11382
+ `<title id="${titleId}">${esc(scene.title?.lines.join(" ") ?? "Architecture diagram")}</title>`
11383
+ );
11384
+ out.push(`<desc id="${descId}">${esc(scene.description)}</desc>`);
11385
+ if (scene.animate === "flow") out.push(`<style>${FLOW_CSS}</style>`);
11386
+ const defsAt = out.length;
11387
+ out.push(canvas(ctx));
11388
+ if (scene.title && scene.titleBox) {
11389
+ const b = scene.titleBox;
11390
+ const size = sizeFor(scene.title.lines, TITLE, W - b.x - 24, 11);
11391
+ out.push(block(scene.title, b, TITLE, size, mixHex(k.line, t.background, 0.85), "start"));
11392
+ }
11393
+ if (scene.subtitle && scene.subtitleBox) {
11394
+ const b = scene.subtitleBox;
11395
+ const size = sizeFor(scene.subtitle.lines, SUBTITLE, W - b.x - 24, 9);
11396
+ out.push(block(scene.subtitle, b, SUBTITLE, size, t.text, "start"));
11397
+ }
11398
+ for (const g of scene.groups) out.push(`<g id="${prefix}g-${g.id}">${groupFrame(ctx, g)}</g>`);
11399
+ const wires = new Map(scene.edges.map((e) => [e.id, wireOf(ctx, e)]));
11400
+ for (const e of scene.edges) {
11401
+ const w = wires.get(e.id);
11402
+ if (!w) continue;
11403
+ const runs = ctx.story.runs.get(e.id);
11404
+ out.push(
11405
+ `<g id="${prefix}e-${e.id}">${edgeBase(ctx, e, w)}${runs ? edgeLit(ctx, e, w, runs) : ""}</g>`
11406
+ );
11407
+ }
11408
+ for (const e of scene.edges) {
11409
+ const label = edgeLabel(ctx, e);
11410
+ if (label) out.push(label);
11411
+ }
11412
+ for (const g of scene.groups) {
11413
+ const header = groupHeader(ctx, g);
11414
+ if (header) out.push(`<g id="${prefix}gh-${g.id}">${header}</g>`);
11415
+ }
11416
+ for (const nd of scene.nodes) out.push(node(ctx, nd));
11417
+ if (ctx.story.animated) {
11418
+ const moving = [];
11419
+ for (const e of scene.edges) {
11420
+ const w = wires.get(e.id);
11421
+ if (!w) continue;
11422
+ const color = e.color ?? k.tint;
11423
+ for (const run of ctx.story.runs.get(e.id) ?? [])
11424
+ moving.push(comet(ctx, w.d, run, color, w.len), packet(ctx, w.d, run, color, 2.5 * h));
11425
+ const side = ctx.story.side.get(e.id);
11426
+ if (side) moving.push(packet(ctx, w.d, side, color, 2 * h));
11427
+ }
11428
+ if (moving.length) out.push(`<g id="${prefix}story">${moving.join("")}</g>`);
11429
+ }
11430
+ out.push(legend(ctx));
11431
+ if (ctx.defs.length) out.splice(defsAt, 0, `<defs>${ctx.defs.join("")}</defs>`);
11432
+ out.push("</svg>");
11433
+ return `${out.filter(Boolean).join("\n")}
11434
+ `;
11435
+ }
11436
+
10727
11437
  // src/render/svg.ts
10728
11438
  var ASCENT = 0.96875;
10729
11439
  var DESCENT = 0.2412;
@@ -10734,14 +11444,14 @@ var n = (v) => {
10734
11444
  const r = Math.round(v * 100) / 100;
10735
11445
  return Object.is(r, -0) ? "0" : String(r);
10736
11446
  };
10737
- function text(block, box, color, anchor2 = "middle", extra = "") {
10738
- if (!block.lines.length) return "";
11447
+ function text(block2, box, color, anchor2 = "middle", extra = "") {
11448
+ if (!block2.lines.length) return "";
10739
11449
  const x = anchor2 === "middle" ? box.x + box.w / 2 : box.x;
10740
- const first = box.y + (block.lead - block.size * (ASCENT + DESCENT)) / 2 + block.size * ASCENT;
10741
- const weight = block.weight === 600 ? ` font-weight="600"` : "";
10742
- const tspans = block.lines.map((line, i) => `<tspan x="${n(x)}" y="${n(first + i * block.lead)}">${esc(line)}</tspan>`).join("");
11450
+ const first = box.y + (block2.lead - block2.size * (ASCENT + DESCENT)) / 2 + block2.size * ASCENT;
11451
+ const weight = block2.weight === 600 ? ` font-weight="600"` : "";
11452
+ const tspans = block2.lines.map((line, i) => `<tspan x="${n(x)}" y="${n(first + i * block2.lead)}">${esc(line)}</tspan>`).join("");
10743
11453
  const anchorAttr = anchor2 === "middle" ? ` text-anchor="middle"` : "";
10744
- return `<text font-size="${n(block.size)}"${weight} fill="${color}"${anchorAttr}${extra}>${tspans}</text>`;
11454
+ return `<text font-size="${n(block2.size)}"${weight} fill="${color}"${anchorAttr}${extra}>${tspans}</text>`;
10745
11455
  }
10746
11456
  var SYMBOL_ID = "SDWSYM";
10747
11457
  function icon(ctx, id, box, color, background) {
@@ -10763,13 +11473,11 @@ function icon(ctx, id, box, color, background) {
10763
11473
  }
10764
11474
  return `<use href="#${ref}" x="${n(box.x)}" y="${n(box.y)}" width="${n(box.w)}" height="${n(box.h)}"/>`;
10765
11475
  }
10766
- function groupFrame(g) {
11476
+ function groupFrame2(g) {
10767
11477
  const { box } = g;
10768
11478
  const dash = g.dash ? ` stroke-dasharray="${g.dash}"` : "";
10769
- const paint = (fill2, washed) => g.wash && washed ? `fill="${g.wash.color}" fill-opacity="${g.wash.opacity}"` : `fill="${fill2}"`;
10770
- const inner = g.inner ? `<rect x="${n(g.inner.box.x)}" y="${n(g.inner.box.y)}" width="${n(g.inner.box.w)}" height="${n(g.inner.box.h)}" rx="${Math.max(0, g.radius - 2)}" ${paint(g.inner.fill, g.wash?.inner)}/>` : "";
10771
- const fill = paint(g.fill, !!g.wash && !g.inner);
10772
- return `<rect x="${n(box.x)}" y="${n(box.y)}" width="${n(box.w)}" height="${n(box.h)}"${g.radius ? ` rx="${g.radius}"` : ""} ${fill} stroke="${g.stroke}" stroke-width="${g.strokeWidth}"${dash}/>${inner}`;
11479
+ const inner = g.inner ? `<rect x="${n(g.inner.box.x)}" y="${n(g.inner.box.y)}" width="${n(g.inner.box.w)}" height="${n(g.inner.box.h)}" rx="${Math.max(0, g.radius - 2)}" fill="${g.inner.fill}"/>` : "";
11480
+ return `<rect x="${n(box.x)}" y="${n(box.y)}" width="${n(box.w)}" height="${n(box.h)}"${g.radius ? ` rx="${g.radius}"` : ""} fill="${g.fill}" stroke="${g.stroke}" stroke-width="${g.strokeWidth}"${dash}/>${inner}`;
10773
11481
  }
10774
11482
  function surfaceBehind(ctx, g) {
10775
11483
  if (g.overlay) {
@@ -10789,7 +11497,7 @@ function surfaceBehind(ctx, g) {
10789
11497
  const bg = ctx.scene.background;
10790
11498
  return bg && bg !== "transparent" ? bg : ctx.t.background;
10791
11499
  }
10792
- function groupHeader(ctx, g) {
11500
+ function groupHeader2(ctx, g) {
10793
11501
  const parts = [];
10794
11502
  const surface = surfaceBehind(ctx, g);
10795
11503
  if (g.label.lines.length) {
@@ -10874,14 +11582,14 @@ function arrowHead(tip, from, len, half, color, open = false, width = 1.5) {
10874
11582
  ];
10875
11583
  return `<path d="M${pts.map(([x, y]) => `${n(x ?? 0)} ${n(y ?? 0)}`).join(" L")} Z" fill="${color}"/>`;
10876
11584
  }
10877
- function stroke(line) {
11585
+ function stroke2(line) {
10878
11586
  const width = line === "thick" ? 2.5 : 1.5;
10879
11587
  const dash = line === "dashed" ? ` stroke-dasharray="6 4"` : line === "dotted" ? ` stroke-dasharray="1.5 3.5" stroke-linecap="round"` : "";
10880
11588
  return { width, dash };
10881
11589
  }
10882
11590
  function edge(ctx, e, routing) {
10883
11591
  const color = e.color ?? ctx.t.edge;
10884
- const { width, dash } = stroke(e.line);
11592
+ const { width, dash } = stroke2(e.line);
10885
11593
  const len = e.line === "thick" ? 11 : 9;
10886
11594
  const half = e.line === "thick" ? 5.5 : 4.5;
10887
11595
  let pts = e.points;
@@ -10913,16 +11621,16 @@ function edge(ctx, e, routing) {
10913
11621
  if (start && firstPt && second)
10914
11622
  parts.push(arrowHead(firstPt, second, len, half, color, open, width));
10915
11623
  if (beat) {
10916
- const lit = ctx.relay.color;
11624
+ const lit2 = ctx.relay.color;
10917
11625
  const heads = [
10918
- end && last && beforeLast ? arrowHead(last, beforeLast, len, half, lit, open, width) : "",
10919
- start && firstPt && second ? arrowHead(firstPt, second, len, half, lit, open, width) : ""
11626
+ end && last && beforeLast ? arrowHead(last, beforeLast, len, half, lit2, open, width) : "",
11627
+ start && firstPt && second ? arrowHead(firstPt, second, len, half, lit2, open, width) : ""
10920
11628
  ].join("");
10921
11629
  parts.push(relayLine(ctx, e, d, heads, beat, width, dash));
10922
11630
  }
10923
11631
  return `<g id="${ctx.prefix}e-${e.id}">${parts.join("")}</g>`;
10924
11632
  }
10925
- function edgeLabel(ctx, e) {
11633
+ function edgeLabel2(ctx, e) {
10926
11634
  if (e.points.length < 2) return "";
10927
11635
  const parts = [];
10928
11636
  if (e.labelBox && e.label) {
@@ -10939,18 +11647,16 @@ function edgeLabel(ctx, e) {
10939
11647
  const cy = s.y + s.h / 2;
10940
11648
  const motion = ctx.motion.get(e.id) ?? relayMotion(ctx, e.id);
10941
11649
  if (motion?.stepped) parts.push(ping(ctx, cx, cy, s.w / 2, motion));
10942
- parts.push(
10943
- `<circle cx="${n(cx)}" cy="${n(cy)}" r="${n(s.w / 2)}" fill="${ctx.t.stepFill}"${ring(ctx)}/>`
10944
- );
11650
+ parts.push(`<circle cx="${n(cx)}" cy="${n(cy)}" r="${n(s.w / 2)}" fill="${ctx.t.stepFill}"/>`);
10945
11651
  parts.push(
10946
11652
  `<text x="${n(cx)}" y="${n(cy + 5)}" font-size="14" font-weight="700" fill="${ctx.t.stepText}" text-anchor="middle">${e.step}</text>`
10947
11653
  );
10948
11654
  }
10949
11655
  return parts.length ? `<g id="${ctx.prefix}el-${e.id}">${parts.join("")}</g>` : "";
10950
11656
  }
10951
- var SPEED = 150;
11657
+ var SPEED2 = 150;
10952
11658
  var REST = 0.9;
10953
- var FADE = 0.12;
11659
+ var FADE2 = 0.12;
10954
11660
  function length(points) {
10955
11661
  let total = 0;
10956
11662
  for (let i = 1; i < points.length; i++) {
@@ -10964,7 +11670,7 @@ function motionPlan(scene) {
10964
11670
  const plan = /* @__PURE__ */ new Map();
10965
11671
  if (scene.animate !== "packets") return plan;
10966
11672
  const moving = scene.edges.filter((e) => e.arrow !== "none" && e.points.length > 1);
10967
- const travel = (e) => Math.min(2.4, Math.max(0.6, length(e.points) / SPEED));
11673
+ const travel = (e) => Math.min(2.4, Math.max(0.6, length(e.points) / SPEED2));
10968
11674
  const stepped = moving.filter((e) => e.step !== void 0);
10969
11675
  const steps = [...new Set(stepped.map((e) => e.step ?? 0))].sort((a, b) => a - b);
10970
11676
  const slot = (e) => travel(e) * (e.arrow === "both" ? 2 : 1);
@@ -11002,21 +11708,13 @@ function packets(ctx, e, d, m) {
11002
11708
  const { cycle, start, travel } = m;
11003
11709
  const one = (reverse, from, shift = 0) => {
11004
11710
  const end = from + travel;
11005
- const fadeIn = from === 0 ? [0, FADE] : [0, from, from + FADE];
11711
+ const fadeIn = from === 0 ? [0, FADE2] : [0, from, from + FADE2];
11006
11712
  const opacity = from === 0 ? "0;1;1;0;0" : "0;0;1;1;0;0";
11007
- const fade = keyTimes([...fadeIn, end - FADE, end, cycle], cycle);
11713
+ const fade = keyTimes([...fadeIn, end - FADE2, end, cycle], cycle);
11008
11714
  const at = keyTimes([0, from, end, cycle], cycle);
11009
- const dot = (lag, body) => {
11010
- const begin = m.begin - shift + lag;
11011
- const loop = `dur="${secs(cycle)}" repeatCount="indefinite"${begin ? ` begin="${secs(begin)}"` : ""}`;
11012
- return `<g opacity="0">${body}<animateMotion path="${d}" ${loop} calcMode="linear" keyPoints="${reverse ? "1;1;0;0" : "0;0;1;1"}" keyTimes="${at}"/><animate attributeName="opacity" values="${opacity}" keyTimes="${fade}" ${loop}/></g>`;
11013
- };
11014
- if (ctx.scene.skin === "stage")
11015
- return dot(0.1, `<circle r="${n(r * 0.5)}" fill="${color}" fill-opacity="0.3"/>`) + dot(0.05, `<circle r="${n(r * 0.72)}" fill="${color}" fill-opacity="0.55"/>`) + dot(0, `<circle r="${r}" fill="${color}"/>`);
11016
- return dot(
11017
- 0,
11018
- `<circle r="${n(r * 2.3)}" fill="${color}" fill-opacity="0.22"/><circle r="${r}" fill="${color}"/>`
11019
- );
11715
+ const begin = m.begin - shift;
11716
+ const loop2 = `dur="${secs(cycle)}" repeatCount="indefinite"${begin ? ` begin="${secs(begin)}"` : ""}`;
11717
+ return `<g opacity="0"><circle r="${n(r * 2.3)}" fill="${color}" fill-opacity="0.22"/><circle r="${r}" fill="${color}"/><animateMotion path="${d}" ${loop2} calcMode="linear" keyPoints="${reverse ? "1;1;0;0" : "0;0;1;1"}" keyTimes="${at}"/><animate attributeName="opacity" values="${opacity}" keyTimes="${fade}" ${loop2}/></g>`;
11020
11718
  };
11021
11719
  if (e.arrow === "both")
11022
11720
  return m.stepped ? one(false, start) + one(true, start + travel) : one(false, start) + one(true, start, cycle / 2);
@@ -11024,19 +11722,19 @@ function packets(ctx, e, d, m) {
11024
11722
  }
11025
11723
  function ping(ctx, cx, cy, r, m) {
11026
11724
  const at = keyTimes([0, Math.max(0, m.start - 0.01), m.start, m.start + 0.6, m.cycle], m.cycle);
11027
- const loop = `dur="${secs(m.cycle)}" repeatCount="indefinite"`;
11028
- return `<circle cx="${n(cx)}" cy="${n(cy)}" r="${n(r)}" fill="none" stroke="${ctx.t.flow}" stroke-width="2" opacity="0"><animate attributeName="r" values="${n(r)};${n(r)};${n(r)};${n(r + 8)};${n(r + 8)}" keyTimes="${at}" ${loop}/><animate attributeName="opacity" values="0;0;0.7;0;0" keyTimes="${at}" ${loop}/></circle>`;
11725
+ const loop2 = `dur="${secs(m.cycle)}" repeatCount="indefinite"`;
11726
+ return `<circle cx="${n(cx)}" cy="${n(cy)}" r="${n(r)}" fill="none" stroke="${ctx.t.flow}" stroke-width="2" opacity="0"><animate attributeName="r" values="${n(r)};${n(r)};${n(r)};${n(r + 8)};${n(r + 8)}" keyTimes="${at}" ${loop2}/><animate attributeName="opacity" values="0;0;0.7;0;0" keyTimes="${at}" ${loop2}/></circle>`;
11029
11727
  }
11030
11728
  var FIRST = 0.3;
11031
11729
  var BEAT = 0.55;
11032
11730
  var DRAW = 0.45;
11033
- var HOLD = 1.2;
11731
+ var HOLD2 = 1.2;
11034
11732
  var END = 0.92;
11035
- var GONE = 0.95;
11733
+ var GONE2 = 0.95;
11036
11734
  var MAX_BEATS = 8;
11037
11735
  function relayPlan(scene, t) {
11038
11736
  const relay = {
11039
- color: t.stage?.ring ?? t.flow,
11737
+ color: t.flow,
11040
11738
  cycle: 0,
11041
11739
  edges: /* @__PURE__ */ new Map(),
11042
11740
  nodes: /* @__PURE__ */ new Map()
@@ -11078,7 +11776,7 @@ function relayPlan(scene, t) {
11078
11776
  const t0 = FIRST + b * BEAT;
11079
11777
  relay.edges.set(e.id, { t0, t1: t0 + DRAW, stepped: e.step !== void 0 });
11080
11778
  }
11081
- relay.cycle = Math.max(3, (FIRST + last * BEAT + DRAW + HOLD) / END);
11779
+ relay.cycle = Math.max(3, (FIRST + last * BEAT + DRAW + HOLD2) / END);
11082
11780
  const nodes = new Set(scene.nodes.map((nd) => nd.id));
11083
11781
  const leaves = /* @__PURE__ */ new Map();
11084
11782
  for (const e of drawn) {
@@ -11096,37 +11794,29 @@ function relayMotion(ctx, id) {
11096
11794
  }
11097
11795
  function relayLine(ctx, e, d, heads, b, width, dash) {
11098
11796
  const { cycle, color } = ctx.relay;
11099
- const loop = `dur="${secs(cycle)}" repeatCount="indefinite"`;
11100
- const kt = (times) => keyTimes(times, cycle);
11797
+ const loop2 = `dur="${secs(cycle)}" repeatCount="indefinite"`;
11798
+ const kt2 = (times) => keyTimes(times, cycle);
11101
11799
  const end = END * cycle;
11102
- const gone = GONE * cycle;
11800
+ const gone = GONE2 * cycle;
11103
11801
  const id = `${ctx.prefix}rm-${e.id}`;
11104
11802
  const reverse = e.arrow === "start";
11105
11803
  const hide = reverse ? "-1" : "1";
11106
11804
  ctx.defs.push(
11107
- `<mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${ctx.scene.width}" height="${ctx.scene.height}"><path d="${d}" fill="none" stroke="#ffffff" stroke-width="${n(width + 8)}" pathLength="1" stroke-dasharray="1 1" stroke-dashoffset="${hide}"><animate attributeName="stroke-dashoffset" values="${hide};${hide};0;0;${hide}" keyTimes="${kt([0, b.t0, b.t1, gone, cycle])}" ${loop}/></path></mask>`
11805
+ `<mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="0" width="${ctx.scene.width}" height="${ctx.scene.height}"><path d="${d}" fill="none" stroke="#ffffff" stroke-width="${n(width + 8)}" pathLength="1" stroke-dasharray="1 1" stroke-dashoffset="${hide}"><animate attributeName="stroke-dashoffset" values="${hide};${hide};0;0;${hide}" keyTimes="${kt2([0, b.t0, b.t1, gone, cycle])}" ${loop2}/></path></mask>`
11108
11806
  );
11109
- const show = (from) => `<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt([0, from, from + 0.05, end, gone, cycle])}" ${loop}/>`;
11807
+ const show2 = (from) => `<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt2([0, from, from + 0.05, end, gone, cycle])}" ${loop2}/>`;
11110
11808
  const r = e.line === "thick" ? 3.6 : 3;
11111
- return `<g mask="url(#${id})" opacity="0"><path d="${d}" fill="none" stroke="${color}" stroke-width="${width}" stroke-linejoin="round"${dash}/>${show(b.t0)}</g>` + (heads ? `<g opacity="0">${heads}${show(b.t1)}</g>` : "") + `<circle r="${r}" fill="${color}" opacity="0"><animateMotion path="${d}" ${loop} calcMode="linear" keyPoints="${reverse ? "1;1;0;0" : "0;0;1;1"}" keyTimes="${kt([0, b.t0, b.t1, cycle])}"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt([0, b.t0, b.t0 + 0.05, b.t1 - 0.05, b.t1, cycle])}" ${loop}/></circle>`;
11809
+ return `<g mask="url(#${id})" opacity="0"><path d="${d}" fill="none" stroke="${color}" stroke-width="${width}" stroke-linejoin="round"${dash}/>${show2(b.t0)}</g>` + (heads ? `<g opacity="0">${heads}${show2(b.t1)}</g>` : "") + `<circle r="${r}" fill="${color}" opacity="0"><animateMotion path="${d}" ${loop2} calcMode="linear" keyPoints="${reverse ? "1;1;0;0" : "0;0;1;1"}" keyTimes="${kt2([0, b.t0, b.t1, cycle])}"/><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${kt2([0, b.t0, b.t0 + 0.05, b.t1 - 0.05, b.t1, cycle])}" ${loop2}/></circle>`;
11112
11810
  }
11113
11811
  function plate(ctx, nd, at) {
11114
11812
  const { cycle, color } = ctx.relay;
11115
11813
  const icon2 = nd.look === "icon" && nd.iconBox ? nd.iconBox : void 0;
11116
11814
  const b = icon2 ?? nd.box;
11117
11815
  const pad = icon2 ? 7 : 4;
11118
- const loop = `dur="${secs(cycle)}" repeatCount="indefinite"`;
11119
- const times = keyTimes([0, at, at + 0.15, END * cycle, GONE * cycle, cycle], cycle);
11120
- return `<rect x="${n(b.x - pad)}" y="${n(b.y - pad)}" width="${n(b.w + 2 * pad)}" height="${n(b.h + 2 * pad)}" rx="${icon2 ? 10 : 12}" fill="${color}" fill-opacity="0.14" stroke="${color}" stroke-opacity="0.6" stroke-width="1" opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${times}" ${loop}/></rect>`;
11816
+ const loop2 = `dur="${secs(cycle)}" repeatCount="indefinite"`;
11817
+ const times = keyTimes([0, at, at + 0.15, END * cycle, GONE2 * cycle, cycle], cycle);
11818
+ return `<rect x="${n(b.x - pad)}" y="${n(b.y - pad)}" width="${n(b.w + 2 * pad)}" height="${n(b.h + 2 * pad)}" rx="${icon2 ? 10 : 12}" fill="${color}" fill-opacity="0.14" stroke="${color}" stroke-opacity="0.6" stroke-width="1" opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="${times}" ${loop2}/></rect>`;
11121
11819
  }
11122
- function stageCanvas(ctx, W, H, s) {
11123
- const p = ctx.prefix;
11124
- ctx.defs.push(
11125
- `<linearGradient id="${p}bg" x1="0" y1="0" x2="0.36" y2="1"><stop offset="0" stop-color="${s.top}"/><stop offset="0.6" stop-color="${ctx.t.background}"/></linearGradient><radialGradient id="${p}tint" cx="0.88" cy="0.04" r="0.7"><stop offset="0" stop-color="${s.tint}" stop-opacity="${s.tintOpacity}"/><stop offset="1" stop-color="${s.tint}" stop-opacity="0"/></radialGradient><pattern id="${p}dots" width="16" height="16" patternUnits="userSpaceOnUse"><circle cx="8" cy="8" r="0.9" fill="${s.dot}" fill-opacity="${s.dotOpacity}"/></pattern>`
11126
- );
11127
- return `<rect width="${W}" height="${H}" fill="url(#${p}bg)"/><rect width="${W}" height="${H}" fill="url(#${p}dots)"/><rect width="${W}" height="${H}" fill="url(#${p}tint)"/>`;
11128
- }
11129
- var ring = (ctx) => ctx.t.stage ? ` stroke="${ctx.t.stage.ring}" stroke-width="1.5"` : "";
11130
11820
  function shapePath(shape, b) {
11131
11821
  const { x, y, w, h } = b;
11132
11822
  switch (shape) {
@@ -11170,26 +11860,26 @@ function shapePath(shape, b) {
11170
11860
  return `<rect x="${n(x)}" y="${n(y)}" width="${n(w)}" height="${n(h)}" rx="12"/>`;
11171
11861
  }
11172
11862
  }
11173
- function badge(ctx, label, anchor2, placed) {
11863
+ function badge2(ctx, label, anchor2, placed) {
11174
11864
  const w = placed?.w ?? Math.max(18, 8 + label.length * 6.4);
11175
11865
  const h = placed?.h ?? 16;
11176
11866
  const x = placed?.x ?? anchor2.x + anchor2.w - w / 2 - 2;
11177
11867
  const y = placed?.y ?? anchor2.y - 7;
11178
- return `<rect x="${n(x)}" y="${n(y)}" width="${n(w)}" height="${n(h)}" rx="${n(h / 2)}" fill="${ctx.t.stepFill}"${ring(ctx)}/><text x="${n(x + w / 2)}" y="${n(y + h / 2 + 3.5)}" font-size="10" font-weight="600" fill="${ctx.t.stepText}" text-anchor="middle">${esc(label)}</text>`;
11868
+ return `<rect x="${n(x)}" y="${n(y)}" width="${n(w)}" height="${n(h)}" rx="${n(h / 2)}" fill="${ctx.t.stepFill}"/><text x="${n(x + w / 2)}" y="${n(y + h / 2 + 3.5)}" font-size="10" font-weight="600" fill="${ctx.t.stepText}" text-anchor="middle">${esc(label)}</text>`;
11179
11869
  }
11180
- function node(ctx, nd) {
11870
+ function node2(ctx, nd) {
11181
11871
  const parts = [];
11182
11872
  const bg = ctx.scene.background && ctx.scene.background !== "transparent" ? ctx.scene.background : ctx.t.background;
11183
11873
  if (nd.look === "icon") {
11184
11874
  if (nd.icon && nd.iconBox) parts.push(icon(ctx, nd.icon, nd.iconBox, nd.color));
11185
11875
  parts.push(text(nd.label, nd.labelBox, nd.ink ?? ctx.t.text));
11186
11876
  if (nd.note && nd.noteBox) parts.push(text(nd.note, nd.noteBox, nd.inkMuted ?? ctx.t.muted));
11187
- if (nd.badge && nd.iconBox) parts.push(badge(ctx, nd.badge, nd.iconBox, nd.badgeBox));
11877
+ if (nd.badge && nd.iconBox) parts.push(badge2(ctx, nd.badge, nd.iconBox, nd.badgeBox));
11188
11878
  } else if (nd.look === "card") {
11189
11879
  const b = nd.box;
11190
- const stroke2 = nd.color ?? ctx.t.border;
11880
+ const stroke3 = nd.color ?? ctx.t.border;
11191
11881
  parts.push(
11192
- `<rect x="${n(b.x)}" y="${n(b.y)}" width="${n(b.w)}" height="${n(b.h)}" rx="8" fill="${ctx.t.surface}" stroke="${stroke2}" stroke-width="1"/>`
11882
+ `<rect x="${n(b.x)}" y="${n(b.y)}" width="${n(b.w)}" height="${n(b.h)}" rx="8" fill="${ctx.t.surface}" stroke="${stroke3}" stroke-width="1"/>`
11193
11883
  );
11194
11884
  if (nd.color) {
11195
11885
  parts.push(
@@ -11199,30 +11889,30 @@ function node(ctx, nd) {
11199
11889
  if (nd.icon && nd.iconBox) parts.push(icon(ctx, nd.icon, nd.iconBox, void 0, ctx.t.surface));
11200
11890
  parts.push(text(nd.label, nd.labelBox, ctx.t.text, "start"));
11201
11891
  if (nd.note && nd.noteBox) parts.push(text(nd.note, nd.noteBox, ctx.t.muted, "start"));
11202
- if (nd.badge) parts.push(badge(ctx, nd.badge, nd.box, nd.badgeBox));
11892
+ if (nd.badge) parts.push(badge2(ctx, nd.badge, nd.box, nd.badgeBox));
11203
11893
  } else {
11204
- const stroke2 = nd.color ?? (ctx.t.name === "dark" ? "#6e7681" : "#8b95a1");
11205
- const fill = nd.color ? mixHex(nd.color, bg, ctx.t.name === "dark" ? 0.16 : 0.1) : ctx.t.surface;
11894
+ const stroke3 = nd.color ?? (ctx.t.name === "dark" ? "#6e7681" : "#8b95a1");
11895
+ const fill2 = nd.color ? mixHex(nd.color, bg, ctx.t.name === "dark" ? 0.16 : 0.1) : ctx.t.surface;
11206
11896
  parts.push(
11207
- `<g fill="${fill}" stroke="${stroke2}" stroke-width="1.25">${shapePath(nd.shape, nd.box)}</g>`
11897
+ `<g fill="${fill2}" stroke="${stroke3}" stroke-width="1.25">${shapePath(nd.shape, nd.box)}</g>`
11208
11898
  );
11209
- if (nd.icon && nd.iconBox) parts.push(icon(ctx, nd.icon, nd.iconBox, nd.color, fill));
11899
+ if (nd.icon && nd.iconBox) parts.push(icon(ctx, nd.icon, nd.iconBox, nd.color, fill2));
11210
11900
  parts.push(text(nd.label, nd.labelBox, nd.ink ?? ctx.t.text));
11211
11901
  if (nd.note && nd.noteBox) parts.push(text(nd.note, nd.noteBox, nd.inkMuted ?? ctx.t.muted));
11212
- if (nd.badge) parts.push(badge(ctx, nd.badge, nd.box, nd.badgeBox));
11902
+ if (nd.badge) parts.push(badge2(ctx, nd.badge, nd.box, nd.badgeBox));
11213
11903
  }
11214
11904
  const inner = parts.join("");
11215
11905
  const body = nd.url ? `<a href="${esc(nd.url)}" xlink:href="${esc(nd.url)}" target="_blank">${inner}</a>` : inner;
11216
11906
  return `<g id="${ctx.prefix}n-${nd.id}">${body}</g>`;
11217
11907
  }
11218
- function legend(ctx, l) {
11908
+ function legend2(ctx, l) {
11219
11909
  const b = l.box;
11220
11910
  const parts = [
11221
11911
  `<rect x="${n(b.x)}" y="${n(b.y)}" width="${n(b.w)}" height="${n(b.h)}" rx="6" fill="${ctx.t.surface}" stroke="${ctx.t.border}" stroke-width="1"/>`
11222
11912
  ];
11223
11913
  for (const item of l.items) {
11224
11914
  const s = item.swatch;
11225
- const { width, dash } = stroke(item.line);
11915
+ const { width, dash } = stroke2(item.line);
11226
11916
  const y = s.y + s.h / 2;
11227
11917
  parts.push(
11228
11918
  `<path d="M${n(s.x)} ${n(y)} H${n(s.x + s.w)}" fill="none" stroke="${ctx.t.edge}" stroke-width="${width}"${dash}/>`
@@ -11233,6 +11923,7 @@ function legend(ctx, l) {
11233
11923
  }
11234
11924
  var FLOW_CSS = `@keyframes sdw-flow{to{stroke-dashoffset:-20}}.sdw-flow{animation:sdw-flow 1.1s linear infinite}.sdw-solid{stroke-dasharray:7 3}`;
11235
11925
  function renderSvg(scene, opts = {}) {
11926
+ if (scene.skin === "stage") return renderStage(scene, opts);
11236
11927
  const t = tokensFor(scene);
11237
11928
  const prefix = opts.idPrefix ? `${opts.idPrefix.replace(/[^A-Za-z0-9_-]/g, "")}-` : "";
11238
11929
  const ctx = {
@@ -11257,29 +11948,28 @@ function renderSvg(scene, opts = {}) {
11257
11948
  out.push(`<desc id="${descId}">${esc(scene.description)}</desc>`);
11258
11949
  if (scene.animate === "flow") out.push(`<style>${FLOW_CSS}</style>`);
11259
11950
  const defsAt = out.length;
11260
- if (scene.background === void 0 && t.stage) out.push(stageCanvas(ctx, W, H, t.stage));
11261
- else if (scene.background !== "transparent") {
11951
+ if (scene.background !== "transparent") {
11262
11952
  out.push(`<rect width="${W}" height="${H}" fill="${scene.background ?? t.background}"/>`);
11263
11953
  }
11264
11954
  if (scene.title && scene.titleBox) out.push(text(scene.title, scene.titleBox, t.text, "start"));
11265
11955
  if (scene.subtitle && scene.subtitleBox)
11266
11956
  out.push(text(scene.subtitle, scene.subtitleBox, t.muted, "start"));
11267
- for (const g of scene.groups) out.push(`<g id="${ctx.prefix}g-${g.id}">${groupFrame(g)}</g>`);
11957
+ for (const g of scene.groups) out.push(`<g id="${ctx.prefix}g-${g.id}">${groupFrame2(g)}</g>`);
11268
11958
  for (const e of scene.edges) out.push(edge(ctx, e, scene.routing));
11269
11959
  for (const e of scene.edges) {
11270
- const label = edgeLabel(ctx, e);
11960
+ const label = edgeLabel2(ctx, e);
11271
11961
  if (label) out.push(label);
11272
11962
  }
11273
11963
  for (const g of scene.groups) {
11274
- const header = groupHeader(ctx, g);
11964
+ const header = groupHeader2(ctx, g);
11275
11965
  if (header) out.push(`<g id="${ctx.prefix}gh-${g.id}">${header}</g>`);
11276
11966
  }
11277
11967
  for (const nd of scene.nodes) {
11278
11968
  const at = ctx.relay.nodes.get(nd.id);
11279
11969
  if (at !== void 0) out.push(plate(ctx, nd, at));
11280
11970
  }
11281
- for (const nd of scene.nodes) out.push(node(ctx, nd));
11282
- if (scene.legend?.items.length) out.push(legend(ctx, scene.legend));
11971
+ for (const nd of scene.nodes) out.push(node2(ctx, nd));
11972
+ if (scene.legend?.items.length) out.push(legend2(ctx, scene.legend));
11283
11973
  if (ctx.defs.length) out.splice(defsAt, 0, `<defs>${ctx.defs.join("")}</defs>`);
11284
11974
  out.push("</svg>");
11285
11975
  return `${out.join("\n")}
@@ -11371,7 +12061,7 @@ var SHAPE_STYLE = {
11371
12061
  cloud: { ellipse: null, shape: "cloud" },
11372
12062
  stack: { rounded: 1, absoluteArcSize: 1, arcSize: 12, shadow: 0 }
11373
12063
  };
11374
- function node2(ctx, nd) {
12064
+ function node3(ctx, nd) {
11375
12065
  const id = `n-${nd.id}`;
11376
12066
  const parent = cellParent(nd.parent);
11377
12067
  const value = htmlLabel(nd.label.lines, nd.note?.lines, nd.inkMuted ?? ctx.t.muted);
@@ -11444,15 +12134,15 @@ function node2(ctx, nd) {
11444
12134
  });
11445
12135
  geom = geometry(nd.box, nd.parent, ctx);
11446
12136
  } else {
11447
- const stroke2 = nd.color ?? (ctx.t.name === "dark" ? "#6e7681" : "#8b95a1");
11448
- const fill = nd.color ? mixHex(nd.color, bg, ctx.t.name === "dark" ? 0.16 : 0.1) : ctx.t.surface;
11449
- const img = nd.icon ? iconData(ctx, nd.icon, nd.color, fill) : void 0;
12137
+ const stroke3 = nd.color ?? (ctx.t.name === "dark" ? "#6e7681" : "#8b95a1");
12138
+ const fill2 = nd.color ? mixHex(nd.color, bg, ctx.t.name === "dark" ? 0.16 : 0.1) : ctx.t.surface;
12139
+ const img = nd.icon ? iconData(ctx, nd.icon, nd.color, fill2) : void 0;
11450
12140
  s = style({
11451
12141
  ...SHAPE_STYLE[nd.shape],
11452
12142
  whiteSpace: "wrap",
11453
12143
  html: 1,
11454
- fillColor: fill,
11455
- strokeColor: stroke2,
12144
+ fillColor: fill2,
12145
+ strokeColor: stroke3,
11456
12146
  fontColor: ctx.t.text,
11457
12147
  fontSize: 13,
11458
12148
  fontStyle: 1,
@@ -11528,7 +12218,7 @@ function edge2(ctx, e, boxes) {
11528
12218
  );
11529
12219
  }
11530
12220
  }
11531
- function legend2(ctx, l) {
12221
+ function legend3(ctx, l) {
11532
12222
  const { box } = l;
11533
12223
  const local = (b) => ({ ...b, x: b.x - box.x, y: b.y - box.y });
11534
12224
  ctx.cells.push(
@@ -11560,10 +12250,10 @@ function renderDrawio(scene, name = "Diagram") {
11560
12250
  const vertical = scene.direction === "down" || scene.direction === "up";
11561
12251
  for (const nd of scene.nodes) {
11562
12252
  boxes.set(nd.id, nd.look === "icon" && nd.iconBox && !vertical ? nd.iconBox : nd.box);
11563
- node2(ctx, nd);
12253
+ node3(ctx, nd);
11564
12254
  }
11565
12255
  for (const e of scene.edges) edge2(ctx, e, boxes);
11566
- if (scene.legend?.items.length) legend2(ctx, scene.legend);
12256
+ if (scene.legend?.items.length) legend3(ctx, scene.legend);
11567
12257
  const bg = scene.background === "transparent" ? "none" : scene.background ?? t.background;
11568
12258
  return [
11569
12259
  `<mxfile host="orrery" agent="orrery" type="device">`,
@@ -11693,9 +12383,12 @@ async function load2() {
11693
12383
  }
11694
12384
  var fonts;
11695
12385
  function fontBuffers(extra) {
11696
- fonts ??= ["Inter-Regular.ttf", "Inter-SemiBold.ttf"].map(
11697
- (f) => new Uint8Array(readFileSync4(join6(fontsDir, f)))
11698
- );
12386
+ fonts ??= [
12387
+ "Inter-Regular.ttf",
12388
+ "Inter-SemiBold.ttf",
12389
+ "GeistMono-Regular.ttf",
12390
+ "GeistMono-Bold.ttf"
12391
+ ].map((f) => new Uint8Array(readFileSync4(join6(fontsDir, f))));
11699
12392
  return [...fonts, ...extra.map((f) => new Uint8Array(readFileSync4(f)))];
11700
12393
  }
11701
12394
  async function renderPng(svg, opts = {}) {
@@ -12832,8 +13525,8 @@ function measureFlow(c, diagnostics) {
12832
13525
  }
12833
13526
  const unconnected = diagnostics.filter((d) => d.code === "DG208");
12834
13527
  for (const d of unconnected) {
12835
- const node3 = String(d.subject?.node ?? "");
12836
- add("flow.unconnected", "minor", node3 ? [node3] : [], { node: node3 }, d.message, d.fixes ?? [], 3);
13528
+ const node4 = String(d.subject?.node ?? "");
13529
+ add("flow.unconnected", "minor", node4 ? [node4] : [], { node: node4 }, d.message, d.fixes ?? [], 3);
12837
13530
  }
12838
13531
  Object.assign(m, {
12839
13532
  hiddenHeads: hidden,
@@ -13236,10 +13929,10 @@ function measureGrid(c) {
13236
13929
  }
13237
13930
  function textItems(scene) {
13238
13931
  const t = tokensFor(scene);
13239
- const canvas = scene.background && scene.background !== "transparent" ? scene.background : t.background;
13932
+ const canvas2 = scene.background && scene.background !== "transparent" ? scene.background : t.background;
13240
13933
  const byDepth = [...scene.groups].sort((a, b) => a.depth - b.depth);
13241
13934
  const surfaceAt = (x, y) => {
13242
- let col = canvas;
13935
+ let col = canvas2;
13243
13936
  for (const g of byDepth) {
13244
13937
  if (g.fill !== "none" && inBox(x, y, g.box)) col = g.fill;
13245
13938
  if (g.inner && inBox(x, y, g.inner.box)) col = g.inner.fill;
@@ -13264,7 +13957,7 @@ function textItems(scene) {
13264
13957
  const parent = cur.parent;
13265
13958
  cur = parent ? scene.groups.find((x) => x.id === parent) : void 0;
13266
13959
  }
13267
- return canvas;
13960
+ return canvas2;
13268
13961
  };
13269
13962
  const out = [];
13270
13963
  const push = (id, what, fg, bgs, size, weight) => {
@@ -13274,14 +13967,14 @@ function textItems(scene) {
13274
13967
  out.push({ id, what, fg, bg, size, weight });
13275
13968
  };
13276
13969
  if (scene.title && scene.titleBox)
13277
- push("title", "title", t.text, [canvas], scene.title.size, scene.title.weight);
13970
+ push("title", "title", t.text, [canvas2], scene.title.size, scene.title.weight);
13278
13971
  if (scene.subtitle && scene.subtitleBox)
13279
- push("subtitle", "subtitle", t.muted, [canvas], scene.subtitle.size, scene.subtitle.weight);
13972
+ push("subtitle", "subtitle", t.muted, [canvas2], scene.subtitle.size, scene.subtitle.weight);
13280
13973
  for (const g of scene.groups)
13281
13974
  if (g.label.lines.length)
13282
13975
  push(g.id, "group label", g.labelColor, [behind(g)], g.label.size, g.label.weight);
13283
13976
  for (const n3 of scene.nodes) {
13284
- const shapeFill = n3.color ? mixHex(n3.color, canvas, scene.theme === "dark" ? 0.16 : 0.1) : t.surface;
13977
+ const shapeFill = n3.color ? mixHex(n3.color, canvas2, scene.theme === "dark" ? 0.16 : 0.1) : t.surface;
13285
13978
  const under = (b) => n3.look === "card" ? [t.surface] : n3.look === "shape" ? [shapeFill] : samples(b);
13286
13979
  const ink = n3.look === "card" ? t.text : n3.ink ?? t.text;
13287
13980
  const muted = n3.look === "card" ? t.muted : n3.inkMuted ?? t.muted;
@@ -13403,26 +14096,26 @@ function measureQuality(c, scenes) {
13403
14096
  ["split into an overview and detail diagrams", "collapse repeated nodes and use badge: x3"],
13404
14097
  (n3 - 25) * 2
13405
14098
  );
13406
- for (const node3 of scene.nodes) {
13407
- if (node3.label.lines.length > 3)
14099
+ for (const node4 of scene.nodes) {
14100
+ if (node4.label.lines.length > 3)
13408
14101
  add(
13409
14102
  "quality.long-label",
13410
14103
  "minor",
13411
- [node3.id],
13412
- { lines: node3.label.lines.length },
13413
- `the label of "${node3.id}" wraps to ${node3.label.lines.length} lines`,
14104
+ [node4.id],
14105
+ { lines: node4.label.lines.length },
14106
+ `the label of "${node4.id}" wraps to ${node4.label.lines.length} lines`,
13414
14107
  ["shorten the label and move detail into note"],
13415
14108
  3
13416
14109
  );
13417
- const text2 = c.model.nodes.find((x) => x.id === node3.id)?.label ?? "";
13418
- const broken = midWordBreak(text2, node3.label.lines);
14110
+ const text2 = c.model.nodes.find((x) => x.id === node4.id)?.label ?? "";
14111
+ const broken = midWordBreak(text2, node4.label.lines);
13419
14112
  if (broken)
13420
14113
  add(
13421
14114
  "quality.mid-word-break",
13422
14115
  "minor",
13423
- [node3.id],
14116
+ [node4.id],
13424
14117
  { at: broken },
13425
- `the label of "${node3.id}" breaks mid-word at "${broken}"`,
14118
+ `the label of "${node4.id}" breaks mid-word at "${broken}"`,
13426
14119
  ["use shorter words or a shorter label", "put a line break (\\n) where it should wrap"],
13427
14120
  3
13428
14121
  );
@@ -14012,18 +14705,42 @@ var OPS = [
14012
14705
  ["...", { line: "dotted", arrow: "none" }],
14013
14706
  ["--", { line: "solid", arrow: "none" }]
14014
14707
  ];
14015
- var OP_RE = new RegExp(
14016
- [
14017
- "-\\[([^\\]]*)\\]->",
14018
- "--\\[([^\\]]*)\\]-->",
14019
- ...OPS.map(([op]) => {
14020
- const esc2 = op.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14021
- return /[<>]/.test(op) ? esc2 : `(?<=\\s)${esc2}(?=\\s)`;
14022
- })
14023
- ].join("|"),
14024
- "g"
14025
- );
14026
- var hasOperator = (s) => new RegExp(OP_RE.source).test(` ${s} `);
14708
+ var LABELED = [
14709
+ ["-[", "]->", "solid"],
14710
+ ["--[", "]-->", "dashed"]
14711
+ ];
14712
+ var space = (c) => c !== void 0 && /\s/.test(c);
14713
+ function operatorAt(s, i) {
14714
+ for (const [open, close, line] of LABELED) {
14715
+ if (!s.startsWith(open, i)) continue;
14716
+ const end = s.indexOf("]", i + open.length);
14717
+ if (end >= 0 && s.startsWith(close, end))
14718
+ return {
14719
+ length: end + close.length - i,
14720
+ op: { line, arrow: "end", label: s.slice(i + open.length, end).trim() }
14721
+ };
14722
+ }
14723
+ for (const [text2, op] of OPS) {
14724
+ if (!s.startsWith(text2, i)) continue;
14725
+ if (/[<>]/.test(text2) || space(s[i - 1]) && space(s[i + text2.length]))
14726
+ return { length: text2.length, op };
14727
+ }
14728
+ return void 0;
14729
+ }
14730
+ function operators(s) {
14731
+ const found = [];
14732
+ for (let i = 0; i < s.length; ) {
14733
+ const hit = operatorAt(s, i);
14734
+ if (!hit) {
14735
+ i += 1;
14736
+ continue;
14737
+ }
14738
+ found.push({ index: i, ...hit });
14739
+ i += hit.length;
14740
+ }
14741
+ return found;
14742
+ }
14743
+ var hasOperator = (s) => operators(` ${s} `).length > 0;
14027
14744
  function labelColon(s) {
14028
14745
  let depth = 0;
14029
14746
  for (let i = 0; i < s.length; i++) {
@@ -14046,15 +14763,10 @@ function parseEdgeExpression(expr) {
14046
14763
  }
14047
14764
  const parts = [];
14048
14765
  let last = 0;
14049
- for (const m of body.matchAll(OP_RE)) {
14766
+ for (const m of operators(body)) {
14050
14767
  parts.push(body.slice(last, m.index).trim());
14051
- if (m[1] !== void 0) parts.push({ line: "solid", arrow: "end", label: m[1].trim() });
14052
- else if (m[2] !== void 0) parts.push({ line: "dashed", arrow: "end", label: m[2].trim() });
14053
- else {
14054
- const op = OPS.find(([o]) => o === m[0])?.[1];
14055
- if (op) parts.push({ ...op });
14056
- }
14057
- last = (m.index ?? 0) + m[0].length;
14768
+ parts.push({ ...m.op });
14769
+ last = m.index + m.length;
14058
14770
  }
14059
14771
  parts.push(body.slice(last).trim());
14060
14772
  if (parts.length < 3) return `no arrow found in "${expr}" (use ->, -->, <->, -- ...)`;
@@ -14182,7 +14894,7 @@ function parseSpec(source, filename = "diagram.yaml") {
14182
14894
  const background = hexColor(raw.background, "background", "", { where: "background" }, [
14183
14895
  "transparent"
14184
14896
  ]);
14185
- const legend3 = [];
14897
+ const legend4 = [];
14186
14898
  if (raw.legend !== void 0 && raw.legend !== null && !isObj(raw.legend)) {
14187
14899
  err("DG107", "legend must be a mapping of line style to meaning", {
14188
14900
  subject: { where: "legend" },
@@ -14205,7 +14917,7 @@ function parseSpec(source, filename = "diagram.yaml") {
14205
14917
  subject: { where: "legend", key },
14206
14918
  fixes: [`write ${line}: Asynchronous events`]
14207
14919
  });
14208
- } else legend3.push({ line, label });
14920
+ } else legend4.push({ line, label });
14209
14921
  }
14210
14922
  }
14211
14923
  const entries = (value, what) => {
@@ -14284,7 +14996,7 @@ function parseSpec(source, filename = "diagram.yaml") {
14284
14996
  const color = hexColor(pick(g, "color", GROUP_SYNONYMS), "color", `group "${id}"`, {
14285
14997
  group: id
14286
14998
  });
14287
- const fill = hexColor(pick(g, "fill", GROUP_SYNONYMS), "fill", `group "${id}"`, { group: id }, [
14999
+ const fill2 = hexColor(pick(g, "fill", GROUP_SYNONYMS), "fill", `group "${id}"`, { group: id }, [
14288
15000
  "none"
14289
15001
  ]);
14290
15002
  const dashed = pick(g, "dashed", GROUP_SYNONYMS);
@@ -14294,7 +15006,7 @@ function parseSpec(source, filename = "diagram.yaml") {
14294
15006
  label: str(pick(g, "label", GROUP_SYNONYMS)) ?? style2?.label ?? (style2 ? "" : id),
14295
15007
  parent: str(pick(g, "in", GROUP_SYNONYMS)),
14296
15008
  color,
14297
- fill,
15009
+ fill: fill2,
14298
15010
  icon: icon2,
14299
15011
  dashed: typeof dashed === "boolean" ? dashed : void 0
14300
15012
  });
@@ -14603,7 +15315,7 @@ function parseSpec(source, filename = "diagram.yaml") {
14603
15315
  ...animate ? { animate } : {},
14604
15316
  skin,
14605
15317
  background: background === "transparent" ? "transparent" : background,
14606
- ...legend3.length ? { legend: legend3 } : {},
15318
+ ...legend4.length ? { legend: legend4 } : {},
14607
15319
  nodes,
14608
15320
  groups,
14609
15321
  edges
@@ -14615,7 +15327,7 @@ function suggestIds(id, ids, kind) {
14615
15327
  }
14616
15328
 
14617
15329
  // src/cli.ts
14618
- var VERSION = true ? "0.6.0" : "dev";
15330
+ var VERSION = true ? "0.7.0" : "dev";
14619
15331
  var HELP = `orrery ${VERSION}: architecture and system design diagrams with official icons
14620
15332
 
14621
15333
  Usage: