@popcorn245/cornfield-components 0.52.0 → 0.52.1

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,25 +1,25 @@
1
1
  import { t as e } from "./rolldown-runtime-CGnMp29N.js";
2
- import { Cn as t, Dt as n, Et as r, Ft as i, Gt as a, Kt as o, Lt as s, Ot as c, St as l, Tn as u, Tt as d, Wt as f, _n as p, _t as m, an as h, bt as g, en as _, in as v, kn as y, kt as b, ln as x, nn as S, rn as C, tn as w, un as T, vt as E, wn as D, wt as ee, xt as te, yn as O, yt as ne } from "./engine-HIgX35hE.js";
3
- import { a as k, c as re, d as ie, i as ae, n as A, o as oe, u as se } from "./sheets-TFCL_dIn.js";
4
- var j = 0;
5
- function M(e, t = 5) {
2
+ import { At as t, Ct as n, Dn as r, Dt as i, En as a, Et as o, Jt as s, Kt as c, Lt as l, Ot as u, St as d, Tn as f, an as p, bt as m, dn as h, fn as g, in as _, jn as v, jt as y, kt as b, nn as x, on as S, qt as C, rn as ee, sn as w, wt as T, xn as E, xt as D, yn as O, yt as k, zt as A } from "./engine-BmXtSISH.js";
3
+ import { a as j, c as te, d as ne, i as re, n as M, o as ie, u as ae } from "./sheets-D-sMZzSs.js";
4
+ var N = 0;
5
+ function P(e, t = 5) {
6
6
  if (e.length <= t + 1) return e.join("");
7
- let n = `hx-more-${++j}`, r = e.length - t;
7
+ let n = `hx-more-${++N}`, r = e.length - t;
8
8
  return `${e.slice(0, t).join("")}<div class="hx-more" id="${n}" hidden>${e.slice(t).join("")}</div><button data-corn="more" data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-textact hx-more-btn" data-more="${n}" data-rest="${r}" aria-expanded="false" aria-controls="${n}">and ${r} more</button>`;
9
9
  }
10
- function ce(e) {
10
+ function oe(e) {
11
11
  let t = e.closest && e.closest("[data-more]");
12
12
  if (!t) return !1;
13
13
  let n = t.previousElementSibling, r = n && n.id === t.dataset.more ? n : null, i = t.getAttribute("aria-expanded") !== "true";
14
14
  return r && (r.hidden = !i), t.setAttribute("aria-expanded", String(i)), t.textContent = i ? "Show fewer" : `and ${t.dataset.rest} more`, !0;
15
15
  }
16
16
  // ../explorer/engine/flow-ui.js
17
- function le(e, t) {
18
- let { state: n } = e, r = (e) => (n.nodes.find((t) => t.id === e) || { label: e }).label, i = n.edges.filter((e) => e.kind === "flow" && (e.from === t.id || e.to === t.id)), a = (e, t, n) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${e}</div><div class="hx-fact-v">${M(t.map((e) => `<div class="hx-line"><span><span class="hx-name">${f(r(n ? e.to : e.from))}</span> · ${f(e.label)}${e.status === "live" ? "" : " <span class=\"hx-warn\">(proposed)</span>"}</span></div>`))}</div></div>` : "";
17
+ function se(e, t) {
18
+ let { state: n } = e, r = (e) => (n.nodes.find((t) => t.id === e) || { label: e }).label, i = n.edges.filter((e) => e.kind === "flow" && (e.from === t.id || e.to === t.id)), a = (e, t, n) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${e}</div><div class="hx-fact-v">${P(t.map((e) => `<div class="hx-line"><span><span class="hx-name">${c(r(n ? e.to : e.from))}</span> · ${c(e.label)}${e.status === "live" ? "" : " <span class=\"hx-warn\">(proposed)</span>"}</span></div>`))}</div></div>` : "";
19
19
  return a("Sends to", i.filter((e) => e.from === t.id), !0) + a("Gets from", i.filter((e) => e.to === t.id && e.from !== t.id), !1);
20
20
  }
21
21
  // ../explorer/corn-state.js
22
- var N = Object.freeze([
22
+ var F = Object.freeze([
23
23
  "open",
24
24
  "merged",
25
25
  "closed",
@@ -40,7 +40,7 @@ var N = Object.freeze([
40
40
  "removed",
41
41
  "edit",
42
42
  "sent-back"
43
- ]), P = Object.freeze([
43
+ ]), I = Object.freeze([
44
44
  "added",
45
45
  "changed",
46
46
  "removed",
@@ -55,7 +55,7 @@ Object.freeze([
55
55
  "failed",
56
56
  "stopped"
57
57
  ]);
58
- var ue = Object.freeze({
58
+ var ce = Object.freeze({
59
59
  quiet: "waiting",
60
60
  "stop-requested": "stopped",
61
61
  neutral: "done",
@@ -76,20 +76,20 @@ var ue = Object.freeze({
76
76
  error: "failure",
77
77
  idle: "running"
78
78
  });
79
- function F(e) {
79
+ function L(e) {
80
80
  let t = String(e || "");
81
- return ue[t] || (N.includes(t) && !P.includes(t) ? t : "");
81
+ return ce[t] || (F.includes(t) && !I.includes(t) ? t : "");
82
82
  }
83
- function de(e) {
83
+ function le(e) {
84
84
  let t = String(e || "");
85
- return P.includes(t) ? t : "";
85
+ return I.includes(t) ? t : "";
86
86
  }
87
- function I(e) {
88
- let t = de(e);
87
+ function R(e) {
88
+ let t = le(e);
89
89
  return t ? ` data-corn-state="${t}"` : "";
90
90
  }
91
- function L(e) {
92
- let t = F(e);
91
+ function z(e) {
92
+ let t = L(e);
93
93
  return t ? ` data-corn-state="${t}"` : "";
94
94
  }
95
95
  Object.freeze({
@@ -119,7 +119,7 @@ Object.freeze({
119
119
  quiet: "waiting",
120
120
  "stop-requested": "stopped"
121
121
  });
122
- function fe(e) {
122
+ function ue(e) {
123
123
  let t = Math.max(0, Math.round(e / 1e3));
124
124
  return t < 60 ? `${t} s` : t < 3600 ? `${Math.floor(t / 60)} min` : `${Math.floor(t / 3600)} h`;
125
125
  }
@@ -183,32 +183,32 @@ Object.freeze([
183
183
  local: "draft",
184
184
  unknown: "failure"
185
185
  });
186
- function pe(e) {
186
+ function de(e) {
187
187
  let t = e && e.report && typeof e.report.note == "string" ? e.report.note.replace(/\s+/g, " ").trim() : "", n = t.length > 90 ? `${t.slice(0, 89).trimEnd()}\u2026` : t;
188
188
  return `A run is waiting on you${n ? `: ${n}` : ""}`;
189
189
  }
190
190
  // ../explorer/proposal-model.js
191
- var me = [
191
+ var fe = [
192
192
  "before",
193
193
  "diff",
194
194
  "after"
195
- ], he = [
195
+ ], pe = [
196
196
  "added",
197
197
  "changed",
198
198
  "removed"
199
199
  ];
200
- function ge(e) {
201
- let t = _e({
200
+ function me(e) {
201
+ let t = he({
202
202
  ...e,
203
203
  scenarios: 0
204
204
  }).filter((e) => e.mark).map((e) => e.text.replace(/^\+/, ""));
205
205
  return t.length ? t.join(" · ") : "No changes";
206
206
  }
207
- function _e(e) {
207
+ function he(e) {
208
208
  let t = (t) => e?.[t] || 0, n = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, r = (r) => {
209
209
  let i = e?.nodes?.[r] || 0, a = e?.edges?.[r] || 0;
210
210
  return !e?.nodes || i + a !== t(r) ? `${r === "added" ? "+" : ""}${t(r)} ${r}` : `${[i && n(i, "node"), a && n(a, "edge")].filter(Boolean).join(", ")} ${r}`;
211
- }, i = he.filter((e) => t(e) > 0).map((e) => ({
211
+ }, i = pe.filter((e) => t(e) > 0).map((e) => ({
212
212
  mark: e,
213
213
  text: r(e)
214
214
  }));
@@ -220,15 +220,15 @@ function _e(e) {
220
220
  text: "No changes"
221
221
  }];
222
222
  }
223
- var ve = (e) => `${e === "before" ? "Before" : e === "after" ? "After" : "Diff"} view`, ye = (e, t) => `${t}, ${String(e).toLowerCase()}. The map is on it.`, R = /^[A-Za-z0-9][A-Za-z0-9._-]*$/, be = 200, xe = (e) => typeof e == "string" && e.length <= be && R.test(e);
224
- function Se(e) {
223
+ var ge = (e) => `${e === "before" ? "Before" : e === "after" ? "After" : "Diff"} view`, _e = (e, t) => `${t}, ${String(e).toLowerCase()}. The map is on it.`, ve = /^[A-Za-z0-9][A-Za-z0-9._-]*$/, ye = 200, be = (e) => typeof e == "string" && e.length <= ye && ve.test(e);
224
+ function xe(e) {
225
225
  let t = String(e ?? ""), n = t.length > 60 ? `${t.slice(0, 59)}\u2026` : t;
226
226
  return n.trim() ? `\u201c${n}\u201d is not a proposal's name.` : "That is not a proposal's name.";
227
227
  }
228
- function Ce(e) {
228
+ function Se(e) {
229
229
  return e == null ? "" : typeof e == "string" ? e : JSON.stringify(e);
230
230
  }
231
- var we = [
231
+ var Ce = [
232
232
  "mark",
233
233
  "editOp",
234
234
  "before",
@@ -243,48 +243,48 @@ var we = [
243
243
  "from",
244
244
  "to"
245
245
  ];
246
- function Te(e) {
247
- return b(e) === "added" ? Object.keys(e).filter((t) => !we.includes(t) && e[t] !== void 0).map((t) => ({
246
+ function we(e) {
247
+ return y(e) === "added" ? Object.keys(e).filter((t) => !Ce.includes(t) && e[t] !== void 0).map((t) => ({
248
248
  field: t,
249
249
  before: "",
250
- after: Ce(e[t])
250
+ after: Se(e[t])
251
251
  })) : e.mark === "changed" && e.before ? Object.keys(e.before).map((t) => ({
252
252
  field: t,
253
- before: Ce(e.before[t]),
254
- after: Ce(e[t])
253
+ before: Se(e.before[t]),
254
+ after: Se(e[t])
255
255
  })) : [];
256
256
  }
257
- var z = {
257
+ var B = {
258
258
  added: "Added",
259
259
  changed: "Changed",
260
260
  removed: "Removed",
261
261
  edit: "Your edit"
262
262
  };
263
- function Ee(e) {
264
- if (!c(e)) return "";
265
- let t = Te(e).map((t) => e.mark === "changed" ? `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${f(t.field)}</span><span class="hx-change-before">${f(t.before) || "<em>nothing</em>"}</span><span class="hx-change-arrow" aria-hidden="true">→</span><span class="hx-change-after">${f(t.after) || "<em>nothing</em>"}</span></div>` : `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${f(t.field)}</span><span class="hx-change-after">${f(t.after)}</span></div>`).join("");
266
- return `<div class="hx-sec hx-proposal-sec hx-proposal-sec--${f(e.mark)}" data-proposal-mark="${f(e.mark)}" data-corn="section">
267
- <strong class="hx-strong"><span class="hx-mark-dot hx-mark-dot--${f(e.mark)}" data-corn="mark-dot"${I(e.mark)}></span>${f(e.mark === "edit" ? `${e.editOp === "removed" ? "Removed" : "Added"} by your edit` : `${z[e.mark] || e.mark} by this proposal`)}</strong>
268
- ${e.why ? `<div class="hx-why">${f(e.why)}</div>` : ""}
269
- ${t}
263
+ function Te(e) {
264
+ if (!t(e)) return "";
265
+ let n = we(e).map((t) => e.mark === "changed" ? `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${c(t.field)}</span><span class="hx-change-before">${c(t.before) || "<em>nothing</em>"}</span><span class="hx-change-arrow" aria-hidden="true">→</span><span class="hx-change-after">${c(t.after) || "<em>nothing</em>"}</span></div>` : `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${c(t.field)}</span><span class="hx-change-after">${c(t.after)}</span></div>`).join("");
266
+ return `<div class="hx-sec hx-proposal-sec hx-proposal-sec--${c(e.mark)}" data-proposal-mark="${c(e.mark)}" data-corn="section">
267
+ <strong class="hx-strong"><span class="hx-mark-dot hx-mark-dot--${c(e.mark)}" data-corn="mark-dot"${R(e.mark)}></span>${c(e.mark === "edit" ? `${e.editOp === "removed" ? "Removed" : "Added"} by your edit` : `${B[e.mark] || e.mark} by this proposal`)}</strong>
268
+ ${e.why ? `<div class="hx-why">${c(e.why)}</div>` : ""}
269
+ ${n}
270
270
  </div>`;
271
271
  }
272
- var De = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`;
273
- function Oe(e) {
272
+ var Ee = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`;
273
+ function De(e) {
274
274
  if (!Array.isArray(e) || e.length === 0) return "no checks";
275
275
  let t = (t) => e.filter((e) => t.includes(e.state)).length, n = t(["failure"]), r = t(["cancelled"]), i = t(["running", "queued"]), a = [];
276
- return n && a.push(`${De(n, "check")} failed`), r && a.push(`${De(r, "check")} cancelled`), i && a.push(`${De(i, "check")} running`), a.length ? a.join(", ") : e.length === 1 ? "1 check passed" : `all ${e.length} checks passed`;
276
+ return n && a.push(`${Ee(n, "check")} failed`), r && a.push(`${Ee(r, "check")} cancelled`), i && a.push(`${Ee(i, "check")} running`), a.length ? a.join(", ") : e.length === 1 ? "1 check passed" : `all ${e.length} checks passed`;
277
277
  }
278
- function B(e) {
278
+ function V(e) {
279
279
  let t = typeof e == "string" ? /^pull\/([1-9]\d{0,8})$/.exec(e) : null;
280
280
  return t ? Number(t[1]) : null;
281
281
  }
282
- function ke(e) {
283
- let t = B(e);
282
+ function Oe(e) {
283
+ let t = V(e);
284
284
  return t ? `PR #${t}` : !e || e === "checkout" ? "the checkout" : `worktree ${e}`;
285
285
  }
286
- function Ae(e, t = null, n = null) {
287
- let r = B(e);
286
+ function ke(e, t = null, n = null) {
287
+ let r = V(e);
288
288
  if (!r) {
289
289
  let t = !e || e === "checkout" ? "in the checkout" : `in worktree ${e}`;
290
290
  return {
@@ -295,30 +295,30 @@ function Ae(e, t = null, n = null) {
295
295
  };
296
296
  }
297
297
  let i = [`PR #${r}`], a = t ? t.state === "merged" || t.state === "closed" ? t.state : typeof t.draft == "boolean" ? t.draft ? "draft" : "open" : "" : "";
298
- return a && i.push(a), Array.isArray(n) && i.push(Oe(n)), {
298
+ return a && i.push(a), Array.isArray(n) && i.push(De(n)), {
299
299
  text: i.join(" · "),
300
300
  href: t && typeof t.url == "string" ? t.url : null,
301
301
  state: a,
302
302
  label: `Reviewing spec pull request: ${i.join(", ")}`
303
303
  };
304
304
  }
305
- function je(e, t, n = null) {
306
- return t ? B(t) || t === "checkout" || n && n.has(t) && R.test(t) ? `There is no proposal called ${e} in ${ke(t)}.` : `There is no proposal called ${e}. This link's source is not a PR, the checkout or a worktree.` : `There is no proposal called ${e}.`;
305
+ function Ae(e, t, n = null) {
306
+ return t ? V(t) || t === "checkout" || n && n.has(t) && ve.test(t) ? `There is no proposal called ${e} in ${Oe(t)}.` : `There is no proposal called ${e}. This link's source is not a PR, the checkout or a worktree.` : `There is no proposal called ${e}.`;
307
307
  }
308
- function Me(e) {
308
+ function je(e) {
309
309
  let t = new URLSearchParams(e || "");
310
310
  if (!t.has("proposal")) return null;
311
311
  let n = t.get("proposal") || "";
312
- return R.test(n) ? null : n.trim() ? `This link does not name a proposal: ${Se(n)}` : "This link does not name a proposal.";
312
+ return ve.test(n) ? null : n.trim() ? `This link does not name a proposal: ${xe(n)}` : "This link does not name a proposal.";
313
313
  }
314
- function Ne(e, t, n) {
315
- return Array.isArray(e) ? e.filter((e) => e && e.slug === t && e.source !== n && !e.error).sort((e, t) => +!!B(t.source) - !!B(e.source)).map((e) => ({
314
+ function Me(e, t, n) {
315
+ return Array.isArray(e) ? e.filter((e) => e && e.slug === t && e.source !== n && !e.error).sort((e, t) => +!!V(t.source) - !!V(e.source)).map((e) => ({
316
316
  slug: e.slug,
317
317
  source: e.source,
318
- label: B(e.source) ? `Open the copy in PR #${B(e.source)}${e.pull && e.pull.draft ? " (draft)" : ""}` : `Open the copy ${e.source === "checkout" ? "in the checkout" : `in worktree ${e.source}`}`
318
+ label: V(e.source) ? `Open the copy in PR #${V(e.source)}${e.pull && e.pull.draft ? " (draft)" : ""}` : `Open the copy ${e.source === "checkout" ? "in the checkout" : `in worktree ${e.source}`}`
319
319
  })) : [];
320
320
  }
321
- function Pe(e, t = !1) {
321
+ function Ne(e, t = !1) {
322
322
  let n = Array.isArray(e) ? e : [];
323
323
  if (!n.length) return "";
324
324
  let r = (e) => n.filter((t) => t && e.includes(t.op)).length, i = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, a = [];
@@ -343,7 +343,7 @@ function Pe(e, t = !1) {
343
343
  return s > 0 && a.push(i(s, "other edit")), `yours: ${a.join(", ")}${t ? " (hidden)" : ""}`;
344
344
  }
345
345
  // ../core/proposal.js
346
- var Fe = [
346
+ var Pe = [
347
347
  "version",
348
348
  "spec",
349
349
  "title",
@@ -352,18 +352,18 @@ var Fe = [
352
352
  "edges",
353
353
  "mockups",
354
354
  "scenarios"
355
- ], Ie = [
355
+ ], Fe = [
356
356
  "node",
357
357
  "path",
358
358
  "title"
359
- ], Le = [
359
+ ], Ie = [
360
360
  "png",
361
361
  "jpg",
362
362
  "jpeg",
363
363
  "webp",
364
364
  "svg",
365
365
  "html"
366
- ], Re = [
366
+ ], Le = [
367
367
  "id",
368
368
  "title",
369
369
  "steps",
@@ -371,7 +371,7 @@ var Fe = [
371
371
  "linkNodes",
372
372
  "actor",
373
373
  "down"
374
- ], ze = [
374
+ ], Re = [
375
375
  "node",
376
376
  "edge",
377
377
  "text",
@@ -380,23 +380,23 @@ var Fe = [
380
380
  "at",
381
381
  "check",
382
382
  "expect"
383
- ], Be = [
383
+ ], ze = [
384
384
  "GET",
385
385
  "POST",
386
386
  "PUT",
387
387
  "PATCH",
388
388
  "DELETE"
389
- ], Ve = [
389
+ ], Be = [
390
390
  "read",
391
391
  "write",
392
392
  "delete"
393
- ], He = [
393
+ ], Ve = [
394
394
  "own",
395
395
  "household",
396
396
  "others",
397
397
  "shared-read",
398
398
  "shared-write"
399
- ], Ue = ["allowed", "refused"], We = /^[a-z0-9]+(?:-[a-z0-9]+)*$/, V = `live-room-<id>, live-floor-<id> or live-device-<kind>-<id> (kind one of ${m.join(", ")})`, Ge = [
399
+ ], He = ["allowed", "refused"], Ue = /^[a-z0-9]+(?:-[a-z0-9]+)*$/, We = `live-room-<id>, live-floor-<id> or live-device-<kind>-<id> (kind one of ${k.join(", ")})`, Ge = [
400
400
  "add",
401
401
  "change",
402
402
  "remove"
@@ -425,7 +425,7 @@ function Ze(e) {
425
425
  if (t.some((e) => e === "" || e === "." || e === "..")) return "\"path\" stays inside the proposals folder: no \"..\", no \".\" and no empty parts.";
426
426
  if (t.some((e) => e.startsWith("."))) return "\"path\" has a hidden part (one that starts with a dot).";
427
427
  let n = t[t.length - 1].split(".").length > 1 ? t[t.length - 1].split(".").pop().toLowerCase() : "";
428
- return Le.includes(n) ? null : `A mockup is one of: ${Le.join(", ")}.`;
428
+ return Ie.includes(n) ? null : `A mockup is one of: ${Ie.join(", ")}.`;
429
429
  }
430
430
  function Qe(e) {
431
431
  if (!H(e) || !Array.isArray(e.mockups)) return [];
@@ -447,7 +447,7 @@ var $e = (e) => ({
447
447
  to: e.id
448
448
  });
449
449
  function et(e, t) {
450
- let i = [], a = (e, t, n) => i.push(n ? {
450
+ let r = [], a = (e, t, n) => r.push(n ? {
451
451
  path: e,
452
452
  message: t,
453
453
  state: n
@@ -455,10 +455,10 @@ function et(e, t) {
455
455
  path: e,
456
456
  message: t
457
457
  });
458
- if (!H(t)) return a("", "A proposal is a JSON object."), i;
459
- for (let e of Object.keys(t)) Fe.includes(e) || a(e, `Unknown key "${e}". A proposal has: ${Fe.join(", ")}.`);
458
+ if (!H(t)) return a("", "A proposal is a JSON object."), r;
459
+ for (let e of Object.keys(t)) Pe.includes(e) || a(e, `Unknown key "${e}". A proposal has: ${Pe.join(", ")}.`);
460
460
  t.version !== 1 && a("version", `"version" must be the number 1 (got ${JSON.stringify(t.version)}).`), U(t.title) || a("title", "\"title\" must be a non-empty string."), U(t.summary) || a("summary", "\"summary\" must be a non-empty string: the one sentence the maintainer reads first."), t.spec !== void 0 && !U(t.spec) && a("spec", "\"spec\" must be the spec number as a string, like \"0013\".");
461
- let o = (e) => {
461
+ let s = (e) => {
462
462
  let n = t[e];
463
463
  if (n === void 0) return {
464
464
  add: [],
@@ -474,112 +474,112 @@ function et(e, t) {
474
474
  for (let t of Object.keys(n)) Ge.includes(t) || a(`${e}.${t}`, `Unknown key "${t}" in "${e}". Use add, change or remove.`);
475
475
  for (let t of Ge) n[t] === void 0 ? r[t] = [] : Array.isArray(n[t]) ? r[t] = n[t] : (a(`${e}.${t}`, `"${e}.${t}" must be a list.`), r[t] = []);
476
476
  return r;
477
- }, s = o("nodes"), c = o("edges"), u = new Map(G(e?.nodes).map((e) => [e.id, e])), f = new Set(G(e?.edges).map(K)), p = /* @__PURE__ */ new Map();
478
- s.add.forEach((e, t) => {
479
- H(e) && U(e.id) && !p.has(e.id) && p.set(e.id, t);
477
+ }, c = s("nodes"), l = s("edges"), f = new Map(G(e?.nodes).map((e) => [e.id, e])), p = new Set(G(e?.edges).map(K)), h = /* @__PURE__ */ new Map();
478
+ c.add.forEach((e, t) => {
479
+ H(e) && U(e.id) && !h.has(e.id) && h.set(e.id, t);
480
480
  });
481
- let h = new Set(s.remove.filter((e) => H(e) && U(e.id)).map((e) => e.id)), _ = (e) => u.has(e) || p.has(e), v = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Map();
482
- s.add.forEach((e, t) => {
483
- let n = `nodes.add[${t}]`;
484
- if (!H(e)) return a(n, "An added node is an object with an id, a label and a type.");
485
- U(e.id) ? u.has(e.id) ? a(`${n}.id`, `Node "${e.id}" already exists in the map. Use nodes.change to change it.`, "exists") : v.has(e.id) && a(`${n}.id`, `Node "${e.id}" is added twice.`) : a(`${n}.id`, "An added node needs an \"id\"."), U(e.id) && v.add(e.id), U(e.label) || a(`${n}.label`, "An added node needs a \"label\"."), U(e.type) ? l[e.type] ? e.type === "page" && U(e.label) && (e.label.startsWith("/") || a(`${n}.label`, `A page label "${e.label}" must start with a slash route (like "/meals"), as topology validate demands.`), e.label.includes(".html") && a(`${n}.label`, `A page label "${e.label}" must not contain ".html".`)) : a(`${n}.type`, `Unknown node type "${e.type}". Valid types: ${Object.keys(l).join(", ")}.`) : a(`${n}.type`, "An added node needs a \"type\".");
486
- for (let t of Ke) t in e && a(`${n}.${t}`, `"${t}" is set when the proposal is applied; leave it out.`);
487
- if (e.type === "device" && !m.includes(e.kind) && a(`${n}.kind`, `A device needs "kind", one of: ${m.join(", ")}.`), e.type === "external" && e.kind !== void 0 && !ne.includes(e.kind) && a(`${n}.kind`, `An external's "kind" is one of: ${ne.join(", ")} (or none, until the registry draws it).`), U(e.id) && l[e.type] && d(e)) {
488
- let t = r(e.id), i = e.type === "device" ? `live-device-${m.includes(e.kind) ? e.kind : "<kind>"}-<id>` : `live-${e.type}-<id>`;
489
- !t || t.type !== e.type ? a(`${n}.id`, [
481
+ let g = new Set(c.remove.filter((e) => H(e) && U(e.id)).map((e) => e.id)), _ = (e) => f.has(e) || h.has(e), v = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Map();
482
+ c.add.forEach((e, t) => {
483
+ let r = `nodes.add[${t}]`;
484
+ if (!H(e)) return a(r, "An added node is an object with an id, a label and a type.");
485
+ U(e.id) ? f.has(e.id) ? a(`${r}.id`, `Node "${e.id}" already exists in the map. Use nodes.change to change it.`, "exists") : v.has(e.id) && a(`${r}.id`, `Node "${e.id}" is added twice.`) : a(`${r}.id`, "An added node needs an \"id\"."), U(e.id) && v.add(e.id), U(e.label) || a(`${r}.label`, "An added node needs a \"label\"."), U(e.type) ? T[e.type] ? e.type === "page" && U(e.label) && (e.label.startsWith("/") || a(`${r}.label`, `A page label "${e.label}" must start with a slash route (like "/meals"), as topology validate demands.`), e.label.includes(".html") && a(`${r}.label`, `A page label "${e.label}" must not contain ".html".`)) : a(`${r}.type`, `Unknown node type "${e.type}". Valid types: ${Object.keys(T).join(", ")}.`) : a(`${r}.type`, "An added node needs a \"type\".");
486
+ for (let t of Ke) t in e && a(`${r}.${t}`, `"${t}" is set when the proposal is applied; leave it out.`);
487
+ if (e.type === "device" && !k.includes(e.kind) && a(`${r}.kind`, `A device needs "kind", one of: ${k.join(", ")}.`), e.type === "external" && e.kind !== void 0 && !D.includes(e.kind) && a(`${r}.kind`, `An external's "kind" is one of: ${D.join(", ")} (or none, until the registry draws it).`), U(e.id) && T[e.type] && i(e)) {
488
+ let t = u(e.id), i = e.type === "device" ? `live-device-${k.includes(e.kind) ? e.kind : "<kind>"}-<id>` : `live-${e.type}-<id>`;
489
+ !t || t.type !== e.type ? a(`${r}.id`, [
490
490
  "floor",
491
491
  "room",
492
492
  "device"
493
- ].includes(e.type) ? `"${e.id}" is a ${e.type} only the live layer draws${e.type === "device" ? " (no code file derives it)" : ""}: its id must be ${i}.` : `"${e.id}" starts with "${te}", which only the live layer's floors, rooms and devices use (${V}).`) : t.kind && m.includes(e.kind) && t.kind !== e.kind && a(`${n}.kind`, `"${e.id}" names the kind "${t.kind}" but the node says "${e.kind}".`);
493
+ ].includes(e.type) ? `"${e.id}" is a ${e.type} only the live layer draws${e.type === "device" ? " (no code file derives it)" : ""}: its id must be ${i}.` : `"${e.id}" starts with "${n}", which only the live layer's floors, rooms and devices use (${We}).`) : t.kind && k.includes(e.kind) && t.kind !== e.kind && a(`${r}.kind`, `"${e.id}" names the kind "${t.kind}" but the node says "${e.kind}".`);
494
494
  }
495
- e.parent !== void 0 && (U(e.parent) ? e.parent === e.id ? a(`${n}.parent`, "A node cannot be its own parent.") : _(e.parent) ? h.has(e.parent) ? a(`${n}.parent`, `Parent "${e.parent}" is a node this proposal removes.`) : U(e.id) && y.set(K($e(e)), `nodes.add[${t}].parent`) : a(`${n}.parent`, `Parent "${e.parent}" is in neither the map nor the added nodes.`, "dangling") : a(`${n}.parent`, "\"parent\" must be the id of a node."));
495
+ e.parent !== void 0 && (U(e.parent) ? e.parent === e.id ? a(`${r}.parent`, "A node cannot be its own parent.") : _(e.parent) ? g.has(e.parent) ? a(`${r}.parent`, `Parent "${e.parent}" is a node this proposal removes.`) : U(e.id) && y.set(K($e(e)), `nodes.add[${t}].parent`) : a(`${r}.parent`, `Parent "${e.parent}" is in neither the map nor the added nodes.`, "dangling") : a(`${r}.parent`, "\"parent\" must be the id of a node."));
496
496
  });
497
- let b = /* @__PURE__ */ new Set();
498
- s.change.forEach((e, t) => {
497
+ let x = /* @__PURE__ */ new Set();
498
+ c.change.forEach((e, t) => {
499
499
  let n = `nodes.change[${t}]`;
500
500
  if (!H(e)) return a(n, "A changed node is an object with an id, a set and a why.");
501
- if (U(e.id) ? p.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: change its entry in nodes.add instead.`) : u.has(e.id) ? b.has(e.id) && a(`${n}.id`, `Node "${e.id}" is changed twice: merge the two sets.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be changed.`, "missing-target") : a(`${n}.id`, "A changed node needs an \"id\"."), U(e.id) && b.add(e.id), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
501
+ if (U(e.id) ? h.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: change its entry in nodes.add instead.`) : f.has(e.id) ? x.has(e.id) && a(`${n}.id`, `Node "${e.id}" is changed twice: merge the two sets.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be changed.`, "missing-target") : a(`${n}.id`, "A changed node needs an \"id\"."), U(e.id) && x.add(e.id), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
502
502
  else {
503
503
  "id" in e.set && a(`${n}.set.id`, "A change cannot set \"id\": it names the node."), "parent" in e.set && a(`${n}.set.parent`, "\"parent\" is not a node field: remove the ownership edge and add a new one.");
504
504
  for (let t of qe) t in e.set && a(`${n}.set.${t}`, `"${t}" is set when the proposal is applied; leave it out of "set".`);
505
- "type" in e.set && !l[e.set.type] && a(`${n}.set.type`, `Unknown node type "${e.set.type}". Valid types: ${Object.keys(l).join(", ")}.`);
505
+ "type" in e.set && !T[e.set.type] && a(`${n}.set.type`, `Unknown node type "${e.set.type}". Valid types: ${Object.keys(T).join(", ")}.`);
506
506
  }
507
507
  U(e.why) || a(`${n}.why`, "A change needs a \"why\": the reason the maintainer reads.");
508
508
  });
509
- let x = /* @__PURE__ */ new Set();
510
- s.remove.forEach((e, t) => {
509
+ let S = /* @__PURE__ */ new Set();
510
+ c.remove.forEach((e, t) => {
511
511
  let n = `nodes.remove[${t}]`;
512
512
  if (!H(e)) return a(n, "A removed node is an object with an id and a why.");
513
- U(e.id) ? p.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: drop its entry from nodes.add instead of removing it.`) : u.has(e.id) ? x.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is removed twice.`) : b.has(e.id) && a(`${n}.id`, `Node "${e.id}" is both changed and removed.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be removed.`, "missing-target") : a(`${n}.id`, "A removed node needs an \"id\"."), U(e.id) && x.add(e.id), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
513
+ U(e.id) ? h.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: drop its entry from nodes.add instead of removing it.`) : f.has(e.id) ? S.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is removed twice.`) : x.has(e.id) && a(`${n}.id`, `Node "${e.id}" is both changed and removed.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be removed.`, "missing-target") : a(`${n}.id`, "A removed node needs an \"id\"."), U(e.id) && S.add(e.id), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
514
514
  });
515
- let S = new Map(s.change.filter((e) => H(e) && U(e.id) && H(e.set)).map((e) => [e.id, e.set])), C = new Map(s.add.filter((e) => H(e) && U(e.id)).map((e) => [e.id, e])), w = (e) => C.get(e) || (u.has(e) ? {
516
- ...u.get(e),
517
- ...S.get(e) || {}
518
- } : void 0), T = (e, t) => {
515
+ let C = new Map(c.change.filter((e) => H(e) && U(e.id) && H(e.set)).map((e) => [e.id, e.set])), ee = new Map(c.add.filter((e) => H(e) && U(e.id)).map((e) => [e.id, e])), w = (e) => ee.get(e) || (f.has(e) ? {
516
+ ...f.get(e),
517
+ ...C.get(e) || {}
518
+ } : void 0), E = (e, t) => {
519
519
  U(e.from) || a(`${t}.from`, "An edge needs a \"from\" node id."), U(e.to) || a(`${t}.to`, "An edge needs a \"to\" node id.");
520
520
  let n = U(e.from) && U(e.to);
521
- return e.kind !== void 0 && !E.includes(e.kind) && (a(`${t}.kind`, `Unknown edge kind "${e.kind}". Valid kinds: ${E.join(", ")} (or none, for ownership).`), n = !1), e.kind === "flow" ? g.includes(e.flow) || (a(`${t}.flow`, `A flow edge needs "flow", one of: ${g.join(", ")}.`), n = !1) : e.flow !== void 0 && a(`${t}.flow`, "\"flow\" only goes on an edge of kind \"flow\"."), n ? K(e) : null;
522
- }, D = (e) => `${e.from} -> ${e.to}${e.kind ? ` (${e.kind === "flow" ? `flow ${e.flow}` : e.kind})` : " (ownership)"}`, O = new Map([...y]);
523
- c.add.forEach((e, t) => {
521
+ return e.kind !== void 0 && !m.includes(e.kind) && (a(`${t}.kind`, `Unknown edge kind "${e.kind}". Valid kinds: ${m.join(", ")} (or none, for ownership).`), n = !1), e.kind === "flow" ? d.includes(e.flow) || (a(`${t}.flow`, `A flow edge needs "flow", one of: ${d.join(", ")}.`), n = !1) : e.flow !== void 0 && a(`${t}.flow`, "\"flow\" only goes on an edge of kind \"flow\"."), n ? K(e) : null;
522
+ }, O = (e) => `${e.from} -> ${e.to}${e.kind ? ` (${e.kind === "flow" ? `flow ${e.flow}` : e.kind})` : " (ownership)"}`, A = new Map([...y]);
523
+ l.add.forEach((e, t) => {
524
524
  let n = `edges.add[${t}]`;
525
525
  if (!H(e)) return a(n, "An added edge is an object with from, to and optionally a kind.");
526
- let r = T(e, n);
526
+ let r = E(e, n);
527
527
  for (let t of Ke) t in e && a(`${n}.${t}`, `"${t}" is set when the proposal is applied; leave it out.`);
528
- for (let t of ["from", "to"]) U(e[t]) && (_(e[t]) ? h.has(e[t]) && a(`${n}.${t}`, `Node "${e[t]}" is a node this proposal removes, so an edge cannot be added to it.`) : a(`${n}.${t}`, `Node "${e[t]}" is in neither the map nor the added nodes.`, "dangling"));
529
- let i = w(e.from), o = w(e.to);
530
- if (i && o) {
531
- for (let t of ["when", "side"]) if (e[t] !== void 0) for (let r of ee({
528
+ for (let t of ["from", "to"]) U(e[t]) && (_(e[t]) ? g.has(e[t]) && a(`${n}.${t}`, `Node "${e[t]}" is a node this proposal removes, so an edge cannot be added to it.`) : a(`${n}.${t}`, `Node "${e[t]}" is in neither the map nor the added nodes.`, "dangling"));
529
+ let i = w(e.from), s = w(e.to);
530
+ if (i && s) {
531
+ for (let t of ["when", "side"]) if (e[t] !== void 0) for (let r of o({
532
532
  kind: e.kind,
533
533
  [t]: e[t]
534
- }, i, o)) a(`${n}.${t}`, `The edge ${r}`);
534
+ }, i, s)) a(`${n}.${t}`, `The edge ${r}`);
535
535
  }
536
- r && (f.has(r) ? a(n, `Edge ${D(e)} already exists in the map.`, "exists") : O.has(r) && a(n, `Edge ${D(e)} is already added by ${O.get(r)}.`), O.set(r, O.get(r) || n));
536
+ r && (p.has(r) ? a(n, `Edge ${O(e)} already exists in the map.`, "exists") : A.has(r) && a(n, `Edge ${O(e)} is already added by ${A.get(r)}.`), A.set(r, A.get(r) || n));
537
537
  });
538
- let k = /* @__PURE__ */ new Map(), re = (e, t, n) => {
539
- let r = T(e, t);
540
- return r ? (f.has(r) ? k.has(r) ? a(t, `Edge ${D(e)} is already ${k.get(r)} by this proposal.`) : k.set(r, n === "change" ? "changed" : "removed") : a(t, `Edge ${D(e)} does not exist in the map, so it cannot be ${n === "change" ? "changed" : "removed"}.`, "missing-target"), r) : null;
538
+ let j = /* @__PURE__ */ new Map(), te = (e, t, n) => {
539
+ let r = E(e, t);
540
+ return r ? (p.has(r) ? j.has(r) ? a(t, `Edge ${O(e)} is already ${j.get(r)} by this proposal.`) : j.set(r, n === "change" ? "changed" : "removed") : a(t, `Edge ${O(e)} does not exist in the map, so it cannot be ${n === "change" ? "changed" : "removed"}.`, "missing-target"), r) : null;
541
541
  };
542
- c.change.forEach((e, t) => {
542
+ l.change.forEach((e, t) => {
543
543
  let n = `edges.change[${t}]`;
544
544
  if (!H(e)) return a(n, "A changed edge is an object with from, to, set and why.");
545
- if (re(e, n, "change"), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
545
+ if (te(e, n, "change"), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
546
546
  else {
547
547
  for (let t of Je) t in e.set && a(`${n}.set.${t}`, `A change cannot set "${t}": it names the edge. Remove the edge and add a new one.`);
548
548
  for (let t of qe) t in e.set && a(`${n}.set.${t}`, `"${t}" is set when the proposal is applied; leave it out of "set".`);
549
549
  }
550
550
  U(e.why) || a(`${n}.why`, "A change needs a \"why\".");
551
- }), c.remove.forEach((e, t) => {
551
+ }), l.remove.forEach((e, t) => {
552
552
  let n = `edges.remove[${t}]`;
553
553
  if (!H(e)) return a(n, "A removed edge is an object with from, to and why.");
554
- re(e, n, "remove"), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
554
+ te(e, n, "remove"), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
555
555
  });
556
- function ie(e, t) {
557
- if (!U(e) || !We.test(e)) return a(t, `"actor" must be a persona id: lower-case words joined by dashes, like "child" (got ${JSON.stringify(e)}).`);
558
- let r = n(e);
559
- _(r) || a(t, `Actor "${e}" is no persona: "${r}" is in neither the map nor the added nodes.`, "dangling");
556
+ function ne(e, t) {
557
+ if (!U(e) || !Ue.test(e)) return a(t, `"actor" must be a persona id: lower-case words joined by dashes, like "child" (got ${JSON.stringify(e)}).`);
558
+ let n = b(e);
559
+ _(n) || a(t, `Actor "${e}" is no persona: "${n}" is in neither the map nor the added nodes.`, "dangling");
560
560
  }
561
- function ae(e, t) {
562
- if (!U(e)) return a(t, `"at" must be a node id or a live id (${V}).`);
563
- _(e) || r(e) || (e.startsWith("live-") ? a(t, `"${e}" is not a live id: write ${V}.`) : a(t, `Step happens nowhere: "${e}" is in neither the map nor the added nodes, and is not a live id.`, "dangling"));
561
+ function re(e, t) {
562
+ if (!U(e)) return a(t, `"at" must be a node id or a live id (${We}).`);
563
+ _(e) || u(e) || (e.startsWith("live-") ? a(t, `"${e}" is not a live id: write ${We}.`) : a(t, `Step happens nowhere: "${e}" is in neither the map nor the added nodes, and is not a live id.`, "dangling"));
564
564
  }
565
- let A = "A check is { route, method } or { table, op, row? }";
566
- function oe(e, t) {
567
- if (!H(e)) return a(t, `${A}.`);
565
+ let M = "A check is { route, method } or { table, op, row? }";
566
+ function ie(e, t) {
567
+ if (!H(e)) return a(t, `${M}.`);
568
568
  let n = "route" in e || "method" in e, r = "table" in e || "op" in e || "row" in e;
569
- if (n && r) return a(t, `${A}: either one, not both.`);
570
- if (!n && !r) return a(t, `${A}.`);
569
+ if (n && r) return a(t, `${M}: either one, not both.`);
570
+ if (!n && !r) return a(t, `${M}.`);
571
571
  let i = n ? ["route", "method"] : [
572
572
  "table",
573
573
  "op",
574
574
  "row"
575
575
  ];
576
576
  for (let r of Object.keys(e)) i.includes(r) || a(`${t}.${r}`, `Unknown key "${r}" in a ${n ? "route" : "table"} check. It has: ${i.join(", ")}.`);
577
- n ? (U(e.route) && e.route.startsWith("/") || a(`${t}.route`, "\"route\" must be a path starting with a slash, as the map labels it (\"/api/v1/rooms/[id]\") or a concrete one."), Be.includes(e.method) || a(`${t}.method`, `"method" must be one of: ${Be.join(", ")}.`)) : (U(e.table) || a(`${t}.table`, "\"table\" must be the SQL table name."), Ve.includes(e.op) || a(`${t}.op`, `"op" must be one of: ${Ve.join(", ")}.`), e.row !== void 0 && !He.includes(e.row) && a(`${t}.row`, `"row" must be one of: ${He.join(", ")}.`));
577
+ n ? (U(e.route) && e.route.startsWith("/") || a(`${t}.route`, "\"route\" must be a path starting with a slash, as the map labels it (\"/api/v1/rooms/[id]\") or a concrete one."), ze.includes(e.method) || a(`${t}.method`, `"method" must be one of: ${ze.join(", ")}.`)) : (U(e.table) || a(`${t}.table`, "\"table\" must be the SQL table name."), Be.includes(e.op) || a(`${t}.op`, `"op" must be one of: ${Be.join(", ")}.`), e.row !== void 0 && !Ve.includes(e.row) && a(`${t}.row`, `"row" must be one of: ${Ve.join(", ")}.`));
578
578
  }
579
- function se(e, t) {
580
- Array.isArray(e) ? e.forEach((e, n) => oe(e, `${t}[${n}]`)) : oe(e, t);
579
+ function ae(e, t) {
580
+ Array.isArray(e) ? e.forEach((e, n) => ie(e, `${t}[${n}]`)) : ie(e, t);
581
581
  }
582
- function j(e, t) {
582
+ function N(e, t) {
583
583
  if (!Array.isArray(e)) return a(t, "\"down\" must be a list of the cloud node ids the scenario takes down.");
584
584
  if (e.length === 0) return a(t, "\"down\" needs at least one cloud node id; leave it out for a scenario that is no outage.");
585
585
  let n = /* @__PURE__ */ new Set();
@@ -589,53 +589,53 @@ function et(e, t) {
589
589
  if (n.has(e)) return a(i, `"${e}" is down twice.`);
590
590
  n.add(e);
591
591
  let o = w(e);
592
- if (!o) return a(i, `Down node "${e}" is in neither the map nor the added nodes.`, h.has(e) ? "missing-target" : "dangling");
592
+ if (!o) return a(i, `Down node "${e}" is in neither the map nor the added nodes.`, g.has(e) ? "missing-target" : "dangling");
593
593
  if (o.type !== "external" || o.kind !== "cloud") {
594
594
  let t = o.type === "external" ? o.kind === void 0 ? "an external with no kind" : `an external of kind ${o.kind}` : `a ${o.type}`;
595
595
  a(i, `"${e}" is ${t}: only an external of kind cloud can be down (a container, a stack or a machine is the House view's; the public web is never down as a whole).`);
596
596
  }
597
597
  });
598
598
  }
599
- let M = new Set(c.remove.filter((e) => H(e) && U(e.from) && U(e.to)).map(K)), ce = (e, t) => M.has(e) || h.has(t.from) || h.has(t.to);
599
+ let P = new Set(l.remove.filter((e) => H(e) && U(e.from) && U(e.to)).map(K)), oe = (e, t) => P.has(e) || g.has(t.from) || g.has(t.to);
600
600
  t.scenarios !== void 0 && !Array.isArray(t.scenarios) && a("scenarios", "\"scenarios\" must be a list.");
601
- let le = /* @__PURE__ */ new Set();
601
+ let se = /* @__PURE__ */ new Set();
602
602
  if (G(t.scenarios).forEach((e, t) => {
603
603
  let n = `scenarios[${t}]`;
604
604
  if (!H(e)) return a(n, "A scenario is an object with an id, a title and steps.");
605
- U(e.id) ? le.has(e.id) && a(`${n}.id`, `Scenario id "${e.id}" is used twice.`) : a(`${n}.id`, "A scenario needs an \"id\"."), U(e.id) && le.add(e.id), U(e.title) || a(`${n}.title`, "A scenario needs a \"title\".");
606
- for (let t of Object.keys(e)) Re.includes(t) || a(`${n}.${t}`, `Unknown key "${t}" in a scenario. A scenario has: ${Re.join(", ")}.`);
607
- if (e.stepMs !== void 0 && !Ye(e.stepMs) && a(`${n}.stepMs`, "\"stepMs\" must be a positive number of milliseconds."), e.linkNodes !== void 0 && typeof e.linkNodes != "boolean" && a(`${n}.linkNodes`, "\"linkNodes\" must be true or false."), e.actor !== void 0 && ie(e.actor, `${n}.actor`), e.down !== void 0 && j(e.down, `${n}.down`), !Array.isArray(e.steps)) return a(`${n}.steps`, "\"steps\" must be a list.");
605
+ U(e.id) ? se.has(e.id) && a(`${n}.id`, `Scenario id "${e.id}" is used twice.`) : a(`${n}.id`, "A scenario needs an \"id\"."), U(e.id) && se.add(e.id), U(e.title) || a(`${n}.title`, "A scenario needs a \"title\".");
606
+ for (let t of Object.keys(e)) Le.includes(t) || a(`${n}.${t}`, `Unknown key "${t}" in a scenario. A scenario has: ${Le.join(", ")}.`);
607
+ if (e.stepMs !== void 0 && !Ye(e.stepMs) && a(`${n}.stepMs`, "\"stepMs\" must be a positive number of milliseconds."), e.linkNodes !== void 0 && typeof e.linkNodes != "boolean" && a(`${n}.linkNodes`, "\"linkNodes\" must be true or false."), e.actor !== void 0 && ne(e.actor, `${n}.actor`), e.down !== void 0 && N(e.down, `${n}.down`), !Array.isArray(e.steps)) return a(`${n}.steps`, "\"steps\" must be a list.");
608
608
  if (e.steps.length === 0) return a(`${n}.steps`, "A scenario needs at least one step.");
609
609
  e.steps.forEach((t, r) => {
610
610
  let i = `${n}.steps[${r}]`;
611
611
  if (!H(t)) return a(i, "A step is an object with a \"node\" or an \"edge\", and some \"text\".");
612
- for (let e of Object.keys(t)) ze.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a step. A step has "node" or "edge", and "text"; optionally ${ze.slice(3).join(", ")}.`);
613
- if (U(t.text) || a(`${i}.text`, "A step needs \"text\": what happens at this point."), t.ms !== void 0 && !Ye(t.ms) && a(`${i}.ms`, "\"ms\" must be a positive number of milliseconds."), t.actor !== void 0 && ie(t.actor, `${i}.actor`), t.at !== void 0 && ae(t.at, `${i}.at`), t.check !== void 0 && se(t.check, `${i}.check`), t.expect !== void 0 && (Ue.includes(t.expect) ? t.actor === void 0 && e.actor === void 0 && a(`${i}.expect`, "\"expect\" needs an actor, on the step or its scenario: a step with no actor is never checked.") : a(`${i}.expect`, `"expect" must be one of: ${Ue.join(", ")}.`)), t.node === void 0 == (t.edge === void 0) && a(i, "A step points at exactly one of \"node\" or \"edge\"."), t.node !== void 0 && (U(t.node) ? _(t.node) || a(`${i}.node`, `Step points at nothing: node "${t.node}" is in neither the map nor the added nodes.`, h.has(t.node) ? "missing-target" : "dangling") : a(`${i}.node`, "\"node\" must be a node id.")), t.edge !== void 0) {
612
+ for (let e of Object.keys(t)) Re.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a step. A step has "node" or "edge", and "text"; optionally ${Re.slice(3).join(", ")}.`);
613
+ if (U(t.text) || a(`${i}.text`, "A step needs \"text\": what happens at this point."), t.ms !== void 0 && !Ye(t.ms) && a(`${i}.ms`, "\"ms\" must be a positive number of milliseconds."), t.actor !== void 0 && ne(t.actor, `${i}.actor`), t.at !== void 0 && re(t.at, `${i}.at`), t.check !== void 0 && ae(t.check, `${i}.check`), t.expect !== void 0 && (He.includes(t.expect) ? t.actor === void 0 && e.actor === void 0 && a(`${i}.expect`, "\"expect\" needs an actor, on the step or its scenario: a step with no actor is never checked.") : a(`${i}.expect`, `"expect" must be one of: ${He.join(", ")}.`)), t.node === void 0 == (t.edge === void 0) && a(i, "A step points at exactly one of \"node\" or \"edge\"."), t.node !== void 0 && (U(t.node) ? _(t.node) || a(`${i}.node`, `Step points at nothing: node "${t.node}" is in neither the map nor the added nodes.`, g.has(t.node) ? "missing-target" : "dangling") : a(`${i}.node`, "\"node\" must be a node id.")), t.edge !== void 0) {
614
614
  if (!H(t.edge)) return a(`${i}.edge`, "\"edge\" must be an object with from and to.");
615
- let e = T(t.edge, `${i}.edge`);
616
- e && !f.has(e) && !O.has(e) && a(`${i}.edge`, `Step points at nothing: edge ${D(t.edge)} is in neither the map nor the added edges.`, ce(e, t.edge) ? "missing-target" : "dangling");
615
+ let e = E(t.edge, `${i}.edge`);
616
+ e && !p.has(e) && !A.has(e) && a(`${i}.edge`, `Step points at nothing: edge ${O(t.edge)} is in neither the map nor the added edges.`, oe(e, t.edge) ? "missing-target" : "dangling");
617
617
  }
618
618
  });
619
619
  }), t.mockups !== void 0 && !Array.isArray(t.mockups)) a("mockups", "\"mockups\" must be a list.");
620
620
  else if (Array.isArray(t.mockups)) {
621
621
  t.mockups.length > 40 && a("mockups", "At most 40 mockups in one proposal.");
622
622
  let e = /* @__PURE__ */ new Set([
623
- ...p.keys(),
624
- ...h,
625
- ...s.change.filter((e) => H(e) && U(e.id)).map((e) => e.id)
623
+ ...h.keys(),
624
+ ...g,
625
+ ...c.change.filter((e) => H(e) && U(e.id)).map((e) => e.id)
626
626
  ]), n = /* @__PURE__ */ new Set();
627
627
  t.mockups.forEach((t, r) => {
628
628
  let i = `mockups[${r}]`;
629
629
  if (!H(t)) return a(i, "A mockup is an object with a node, a path and a title.");
630
- for (let e of Object.keys(t)) Ie.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a mockup. A mockup has: ${Ie.join(", ")}.`);
630
+ for (let e of Object.keys(t)) Fe.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a mockup. A mockup has: ${Fe.join(", ")}.`);
631
631
  U(t.title) || a(`${i}.title`, "A mockup needs a \"title\": what the screen is. It is also its alt text.");
632
632
  let o = Ze(t.path);
633
633
  o ? a(`${i}.path`, o) : n.has(`${t.node}|${t.path}`) ? a(i, `Mockup "${t.path}" is listed twice for node "${t.node}".`) : n.add(`${t.node}|${t.path}`), U(t.node) ? e.has(t.node) || a(`${i}.node`, `Mockup is beside node "${t.node}", which this proposal does not add, change or remove. Name a node the proposal touches.`) : a(`${i}.node`, "A mockup needs the \"node\" it belongs to.");
634
634
  });
635
635
  }
636
- return i;
636
+ return r;
637
637
  }
638
- var tt = l.external;
638
+ var tt = T.external;
639
639
  function nt(e, t) {
640
640
  let n = e.nodes.map((e) => ({
641
641
  ...e,
@@ -652,7 +652,7 @@ function nt(e, t) {
652
652
  add: G(t[e]?.add),
653
653
  change: G(t[e]?.change),
654
654
  remove: G(t[e]?.remove)
655
- }), s = o("nodes"), c = o("edges"), u = (e, t, n) => {
655
+ }), s = o("nodes"), c = o("edges"), l = (e, t, n) => {
656
656
  let r = {}, i = (t, n) => {
657
657
  Xe(e[t], n) || (r[t] = e[t] === void 0 ? null : e[t], e[t] = W(n));
658
658
  };
@@ -662,10 +662,10 @@ function nt(e, t) {
662
662
  for (let e of s.change) {
663
663
  let t = i.get(e.id);
664
664
  if (!t) continue;
665
- let n = { ...e.set }, r = l[n.type];
666
- r && ("color" in n || (n.color = r.color), "r" in n || (n.r = r.r)), u(t, n, e.why);
665
+ let n = { ...e.set }, r = T[n.type];
666
+ r && ("color" in n || (n.color = r.color), "r" in n || (n.r = r.r)), l(t, n, e.why);
667
667
  }
668
- for (let e of c.change) for (let t of a.get(K(e)) || []) u(t, e.set, e.why);
668
+ for (let e of c.change) for (let t of a.get(K(e)) || []) l(t, e.set, e.why);
669
669
  for (let e of c.remove) for (let t of a.get(K(e)) || []) delete t.before, t.mark = "removed", t.why = e.why;
670
670
  for (let e of s.remove) {
671
671
  let t = i.get(e.id);
@@ -674,7 +674,7 @@ function nt(e, t) {
674
674
  for (let t of r) (t.from === e.id || t.to === e.id) && t.mark !== "removed" && (delete t.before, t.mark = "removed", t.why = e.why);
675
675
  }
676
676
  }
677
- let d = [], f = (e) => {
677
+ let u = [], d = (e) => {
678
678
  let t = a.get(K(e));
679
679
  t ? t.forEach((e) => {
680
680
  e.mark === "none" && (e.mark = "added");
@@ -684,78 +684,78 @@ function nt(e, t) {
684
684
  });
685
685
  };
686
686
  for (let e of s.add) {
687
- let { parent: t, ...r } = W(e), a = l[e.type] || tt, o = i.get(e.id);
687
+ let { parent: t, ...r } = W(e), a = T[e.type] || tt, o = i.get(e.id);
688
688
  o ? o.mark === "none" && (o.mark = "added") : n.push({
689
689
  ...r,
690
690
  color: a.color,
691
691
  r: e.r ?? a.r,
692
692
  mark: "added"
693
- }), t && d.push({
693
+ }), t && u.push({
694
694
  from: t,
695
695
  to: e.id
696
696
  });
697
697
  }
698
- for (let e of d) f(e);
699
- for (let e of c.add) f(e);
698
+ for (let e of u) d(e);
699
+ for (let e of c.add) d(e);
700
700
  return {
701
701
  nodes: n,
702
702
  edges: r
703
703
  };
704
704
  }
705
705
  function rt(e, t) {
706
- let n = new Map(e.nodes.map((e) => [e.id, e])), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
706
+ let n = new Map(e.nodes.map((e) => [e.id, e])), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
707
707
  for (let t of e.edges) {
708
708
  let e = K(t);
709
709
  r.has(e) || r.set(e, t);
710
710
  let n = `${t.from}|${t.to}`;
711
- i.has(n) || i.set(n, /* @__PURE__ */ new Set()), i.get(n).add(e), !t.kind && !t.dashed && (a.has(t.to) || a.set(t.to, /* @__PURE__ */ new Set()), a.get(t.to).add(t.from));
711
+ a.has(n) || a.set(n, /* @__PURE__ */ new Set()), a.get(n).add(e), !t.kind && !t.dashed && (o.has(t.to) || o.set(t.to, /* @__PURE__ */ new Set()), o.get(t.to).add(t.from));
712
712
  }
713
- let o = (e, t) => Object.entries(t || {}).every(([t, n]) => Xe(e[t], n)), s = (e, n) => G(t?.[e]?.[n]), c = new Set(s("nodes", "add").filter((e) => H(e) && d(e)).map((e) => e.id)), l = (e) => c.has(e) || typeof e == "string" && e.startsWith("live-"), u = [], f = (e, t, n, r) => u.push({
713
+ let s = (e, t) => Object.entries(t || {}).every(([t, n]) => Xe(e[t], n)), c = (e, n) => G(t?.[e]?.[n]), l = new Set(c("nodes", "add").filter((e) => H(e) && i(e)).map((e) => e.id)), u = (e) => l.has(e) || typeof e == "string" && e.startsWith("live-"), d = [], f = (e, t, n, r) => d.push({
714
714
  kind: e,
715
715
  op: t,
716
716
  key: n,
717
717
  status: r
718
718
  });
719
- for (let e of s("nodes", "add")) {
720
- if (c.has(e.id)) {
719
+ for (let e of c("nodes", "add")) {
720
+ if (l.has(e.id)) {
721
721
  f("node", "add", e.id, "live");
722
722
  continue;
723
723
  }
724
724
  let t = n.get(e.id);
725
- f("node", "add", e.id, t ? t.type !== e.type || e.parent && !a.get(e.id)?.has(e.parent) ? "diverged" : "landed" : "pending");
725
+ f("node", "add", e.id, t ? t.type !== e.type || e.parent && !o.get(e.id)?.has(e.parent) ? "diverged" : "landed" : "pending");
726
726
  }
727
- for (let e of s("nodes", "change")) {
727
+ for (let e of c("nodes", "change")) {
728
728
  let t = n.get(e.id);
729
- f("node", "change", e.id, t ? o(t, e.set) ? "landed" : "pending" : "diverged");
729
+ f("node", "change", e.id, t ? s(t, e.set) ? "landed" : "pending" : "diverged");
730
730
  }
731
- for (let e of s("nodes", "remove")) f("node", "remove", e.id, n.has(e.id) ? "pending" : "landed");
732
- for (let e of s("edges", "add")) {
731
+ for (let e of c("nodes", "remove")) f("node", "remove", e.id, n.has(e.id) ? "pending" : "landed");
732
+ for (let e of c("edges", "add")) {
733
733
  let t = K(e);
734
- if (l(e.from) || l(e.to)) {
734
+ if (u(e.from) || u(e.to)) {
735
735
  f("edge", "add", t, "live");
736
736
  continue;
737
737
  }
738
- let n = [...i.get(`${e.from}|${e.to}`) || []].some((e) => e !== t);
738
+ let n = [...a.get(`${e.from}|${e.to}`) || []].some((e) => e !== t);
739
739
  f("edge", "add", t, r.has(t) ? "landed" : n ? "diverged" : "pending");
740
740
  }
741
- for (let e of s("edges", "change")) {
741
+ for (let e of c("edges", "change")) {
742
742
  let t = K(e), n = r.get(t);
743
- f("edge", "change", t, n ? o(n, e.set) ? "landed" : "pending" : "diverged");
743
+ f("edge", "change", t, n ? s(n, e.set) ? "landed" : "pending" : "diverged");
744
744
  }
745
- for (let e of s("edges", "remove")) {
745
+ for (let e of c("edges", "remove")) {
746
746
  let t = K(e);
747
747
  f("edge", "remove", t, r.has(t) ? "pending" : "landed");
748
748
  }
749
749
  let p = {
750
- total: u.length,
750
+ total: d.length,
751
751
  pending: 0,
752
752
  landed: 0,
753
753
  diverged: 0,
754
754
  live: 0
755
755
  };
756
- for (let e of u) p[e.status]++;
756
+ for (let e of d) p[e.status]++;
757
757
  return {
758
- items: u,
758
+ items: d,
759
759
  summary: p
760
760
  };
761
761
  }
@@ -805,8 +805,8 @@ function ut(e, t, n, r, i = {}) {
805
805
  function dt(e) {
806
806
  if (!e.length) return "";
807
807
  let t = e.map((e) => `<li class="hx-mockup-item" data-corn="row">
808
- <button data-corn-kind="secondary" type="button" class="hx-btn hx-mockup-open" data-mockup="${e.index}" aria-haspopup="dialog">${f(e.title)}<span class="hx-sr-only"> (${e.type === "page" ? "page" : "image"}, opens in a window)</span></button>
809
- <span class="hx-mockup-state hx-mockup-state--${f(e.state)}" data-corn="state-pill"${L(e.state)}>${f(st(e.state))}</span>
808
+ <button data-corn-kind="secondary" type="button" class="hx-btn hx-mockup-open" data-mockup="${e.index}" aria-haspopup="dialog">${c(e.title)}<span class="hx-sr-only"> (${e.type === "page" ? "page" : "image"}, opens in a window)</span></button>
809
+ <span class="hx-mockup-state hx-mockup-state--${c(e.state)}" data-corn="state-pill"${z(e.state)}>${c(st(e.state))}</span>
810
810
  </li>`).join("");
811
811
  return `<div class="hx-sec hx-mockups" data-mockups data-corn="section">
812
812
  <h3 class="hx-sec-title" id="hx-mockups-h">${e.length === 1 ? "Mockup" : "Mockups"}</h3>
@@ -826,7 +826,7 @@ function mt(e, t, n, r = 0) {
826
826
  }
827
827
  function ht(e, t, { padding: n = 40, minZoom: r = pt } = {}) {
828
828
  if (e.length < 2) return e;
829
- let i = O(n, t), a = (t.width - i * 2) / r, o = (t.height - i * 2) / r, s = e.map(p), c = (t, n) => e.filter((e, r) => s[r].left >= t && s[r].right <= t + a && s[r].top >= n && s[r].bottom <= n + o), l = s.map((e) => e.left), u = s.map((e) => e.top), d = [], f = e.length <= 120 ? l.flatMap((e) => u.map((t) => [e, t])) : s.map((e) => [e.left, e.top]);
829
+ let i = E(n, t), a = (t.width - i * 2) / r, o = (t.height - i * 2) / r, s = e.map(O), c = (t, n) => e.filter((e, r) => s[r].left >= t && s[r].right <= t + a && s[r].top >= n && s[r].bottom <= n + o), l = s.map((e) => e.left), u = s.map((e) => e.top), d = [], f = e.length <= 120 ? l.flatMap((e) => u.map((t) => [e, t])) : s.map((e) => [e.left, e.top]);
830
830
  for (let [t, n] of f) {
831
831
  if (d.length === e.length) break;
832
832
  let r = c(t, n);
@@ -864,24 +864,24 @@ var vt = {
864
864
  return t === 1 ? n[0] : n[1];
865
865
  };
866
866
  function bt(e, t, n) {
867
- let r = new Map(t.map((e) => [e.id, e])), a = new Map(Object.keys(i).map((e) => [e, /* @__PURE__ */ new Map()]));
867
+ let r = new Map(t.map((e) => [e.id, e])), i = new Map(Object.keys(l).map((e) => [e, /* @__PURE__ */ new Map()]));
868
868
  for (let t of n) {
869
869
  if (t.kind !== "calls" || t.to !== e.id) continue;
870
- let n = a.get(s(t)), i = r.get(t.from) || {
870
+ let n = i.get(A(t)), a = r.get(t.from) || {
871
871
  id: t.from,
872
872
  label: t.from,
873
873
  type: "node"
874
874
  }, o = n.get(t.from) || {
875
875
  id: t.from,
876
- label: String(i.label || t.from),
877
- type: i.type,
876
+ label: String(a.label || t.from),
877
+ type: a.type,
878
878
  vias: [],
879
879
  browser: !1
880
880
  };
881
881
  t.label && !o.vias.includes(t.label) && o.vias.push(t.label), t.side === "browser" && (o.browser = !0), n.set(t.from, o);
882
882
  }
883
- let o = [];
884
- for (let [e, t] of a) {
883
+ let a = [];
884
+ for (let [e, t] of i) {
885
885
  if (t.size === 0) continue;
886
886
  let n = /* @__PURE__ */ new Map();
887
887
  for (let { vias: e, ...r } of t.values()) n.has(r.type) || n.set(r.type, []), n.get(r.type).push({
@@ -892,33 +892,33 @@ function bt(e, t, n) {
892
892
  type: e,
893
893
  noun: yt(e, 1),
894
894
  items: t.sort((e, t) => e.label.localeCompare(t.label))
895
- })).sort((e, t) => t.items.length - e.items.length || e.type.localeCompare(t.type)), { title: a, color: s } = i[e];
896
- o.push({
895
+ })).sort((e, t) => t.items.length - e.items.length || e.type.localeCompare(t.type)), { title: i, color: o } = l[e];
896
+ a.push({
897
897
  when: e,
898
- title: a,
899
- color: s,
898
+ title: i,
899
+ color: o,
900
900
  count: t.size,
901
901
  types: r
902
902
  });
903
903
  }
904
- return o;
904
+ return a;
905
905
  }
906
906
  var xt = {
907
907
  run: "Breaks now",
908
908
  deploy: "Breaks on deploy",
909
909
  renew: "Breaks on renewal"
910
- }, J = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${f(e)}</div><div class="hx-fact-v">${M(t)}</div></div>` : "", Y = (e) => `<div class="hx-line">${e}</div>`, X = (e) => `<span class="hx-name">${f(e)}</span>`;
910
+ }, J = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(e)}</div><div class="hx-fact-v">${P(t)}</div></div>` : "", Y = (e) => `<div class="hx-line">${e}</div>`, X = (e) => `<span class="hx-name">${c(e)}</span>`;
911
911
  function St(e, t) {
912
912
  let n = e.browser ? " <span class=\"hx-cloud-browser\">(browser)</span>" : "", r = [t ? yt(e.type, 1) : "", e.via].filter(Boolean);
913
- return Y(`<span>${X(e.label)}${n}${r.length ? `<span class="hx-faint"> · ${f(r.join(" · "))}</span>` : ""}</span>`);
913
+ return Y(`<span>${X(e.label)}${n}${r.length ? `<span class="hx-faint"> · ${c(r.join(" · "))}</span>` : ""}</span>`);
914
914
  }
915
- var Ct = (e) => `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-cloud-play" data-action="play-outage" data-id="${f(e.id)}">Play: ${f(String(e.label || e.id))} is down</button>`;
915
+ var Ct = (e) => `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-cloud-play" data-action="play-outage" data-id="${c(e.id)}">Play: ${c(String(e.label || e.id))} is down</button>`;
916
916
  function wt(e, t, n) {
917
917
  let r = new Map(t.map((e) => [e.id, e])), i = (e) => String((r.get(e) || { label: e }).label || e), a = e.kind === "web", o = a ? [] : e.roles || [], s = bt(e, t, n).map((e) => {
918
918
  let t = e.types.length > 1;
919
919
  return J(xt[e.when], e.types.flatMap((e) => e.items.map((e) => St(e, t))));
920
- }).join("") || J("Used by", [Y("<span class=\"hx-faint\">Nothing on the map uses it.</span>")]), c = n.filter((t) => t.kind === "calls" && t.from === e.id && (r.get(t.to) || {}).type === "external").map((e) => Y(`<span>${X(i(e.to))}${e.label ? `<span class="hx-faint"> · ${f(e.label)}</span>` : ""}</span>`)), l = n.filter((t) => t.kind === "delivers" && t.from === e.id).map((e) => Y(X(i(e.to))));
921
- return (a ? "" : J("Plan", [Y(f(_t(e.plan) || q.unknown))])) + J("Roles", o.length ? [Y(f(o.join(", ")))] : []) + J("If it's down", [Y(f(e.breaks || "Not described yet."))]) + s + J("Relies on", c) + J("Pushes to", l) + (a ? "" : Ct(e));
920
+ }).join("") || J("Used by", [Y("<span class=\"hx-faint\">Nothing on the map uses it.</span>")]), l = n.filter((t) => t.kind === "calls" && t.from === e.id && (r.get(t.to) || {}).type === "external").map((e) => Y(`<span>${X(i(e.to))}${e.label ? `<span class="hx-faint"> · ${c(e.label)}</span>` : ""}</span>`)), u = n.filter((t) => t.kind === "delivers" && t.from === e.id).map((e) => Y(X(i(e.to))));
921
+ return (a ? "" : J("Plan", [Y(c(_t(e.plan) || q.unknown))])) + J("Roles", o.length ? [Y(c(o.join(", ")))] : []) + J("If it's down", [Y(c(e.breaks || "Not described yet."))]) + s + J("Relies on", l) + J("Pushes to", u) + (a ? "" : Ct(e));
922
922
  }
923
923
  // ../explorer/file-url.js
924
924
  var Tt = {
@@ -948,7 +948,7 @@ function At(e, t, n, r = !0) {
948
948
  kt(e).set(t, {
949
949
  text: n,
950
950
  ok: r
951
- }), a(e, n);
951
+ }), C(e, n);
952
952
  }
953
953
  function jt(e, t) {
954
954
  kt(e).delete(t);
@@ -971,7 +971,7 @@ var Nt = [
971
971
  "runs-on",
972
972
  "uses",
973
973
  "extends"
974
- ], Pt = (e) => Object.hasOwn(C, e) ? C[e].panel : String(e);
974
+ ], Pt = (e) => Object.hasOwn(p, e) ? p[e].panel : String(e);
975
975
  function Ft(e) {
976
976
  let t = (e) => {
977
977
  let t = Nt.indexOf(e);
@@ -986,7 +986,7 @@ function Ft(e) {
986
986
  function It(e, t) {
987
987
  let n = [], r = /* @__PURE__ */ new Set();
988
988
  for (let i of e.edges) {
989
- if (h(i) !== t) continue;
989
+ if (w(i) !== t) continue;
990
990
  let a = i.from === e.selectedId, o = a ? i.to : i.from;
991
991
  r.has(o) || (r.add(o), n.push({
992
992
  id: o,
@@ -1005,7 +1005,7 @@ var Rt = /* @__PURE__ */ e({
1005
1005
  diffPillWords: () => Gt,
1006
1006
  markup: () => Kt,
1007
1007
  mount: () => Xt
1008
- }), Z = (e) => `<code class="hx-code">${f(e)}</code>`, Q = (e) => `<div class="hx-line">${e}</div>`, zt = {
1008
+ }), Z = (e) => `<code class="hx-code">${c(e)}</code>`, Q = (e) => `<div class="hx-line">${e}</div>`, zt = {
1009
1009
  "Uses design tokens": "Tokens",
1010
1010
  "Loaded by the server per request": "Loaded by",
1011
1011
  "Domains served (Caddyfile → service)": "Domains",
@@ -1021,7 +1021,7 @@ var Rt = /* @__PURE__ */ e({
1021
1021
  }, Bt = /^(?:Defines )?\d+ (?:CSS )?(variable|service)\(s\)$/, Vt = (e) => {
1022
1022
  let t = e.replace(/:$/, ""), n = Bt.exec(t);
1023
1023
  return n ? n[1] === "service" ? "Services" : t.startsWith("Defines") ? "Defines" : "Variables" : zt[t] || t;
1024
- }, $ = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${f(Vt(e))}</div><div class="hx-fact-v">${M(t)}</div></div>` : "", Ht = (e) => `<div class="hx-chips">${M(e.map((e) => `<code class="hx-var">${f(e)}</code>`))}</div>`;
1024
+ }, $ = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(Vt(e))}</div><div class="hx-fact-v">${P(t)}</div></div>` : "", Ht = (e) => `<div class="hx-chips">${P(e.map((e) => `<code class="hx-var">${c(e)}</code>`))}</div>`;
1025
1025
  function Ut(e) {
1026
1026
  if (e.type === "external" && e.kind) return e.kind === "web" ? "Public web" : "Cloud";
1027
1027
  let t = e.type.charAt(0).toUpperCase() + e.type.slice(1);
@@ -1038,7 +1038,7 @@ function Gt(e, t) {
1038
1038
  if (!n || n === "none") return "";
1039
1039
  if (n === "edit") return `${e.editOp === "removed" ? "Removed" : "Added"} by your edit`;
1040
1040
  let r = t && typeof t.title == "string" ? t.title : "";
1041
- return r ? `${z[n] || n} by ${r}` : `${z[n] || n} by this proposal`;
1041
+ return r ? `${B[n] || n} by ${r}` : `${B[n] || n} by this proposal`;
1042
1042
  }
1043
1043
  var Kt = () => ({
1044
1044
  drawer: "<aside id=\"spec-drawer\" class=\"hx-drawer glass\" aria-label=\"Node details\" inert data-corn=\"node-panel\"><div class=\"hx-drawer-body\"><div class=\"hx-drawer-head\"><div class=\"hx-drawer-id\"><p class=\"hx-kicker\"><span id=\"drawer-badge\" data-corn=\"badge\">Atom</span><span id=\"drawer-host\" data-corn=\"node-host\"></span><span id=\"drawer-diff\" class=\"hx-diffpill\" data-corn=\"diff-pill\" hidden></span></p><h2 id=\"drawer-title\" class=\"hx-drawer-title\" data-corn=\"node-title\">&lt;pop-button&gt;</h2></div><button type=\"button\" class=\"hx-close\" data-action=\"close-drawer\" aria-label=\"Close\" data-corn-kind=\"icon\">✕</button></div><p id=\"drawer-description\" class=\"hx-lead\" hidden></p><div class=\"hx-block\"><div id=\"drawer-meta-list\" class=\"hx-meta\"></div></div></div><div class=\"hx-drawer-foot\" data-corn=\"node-foot\"><a data-corn=\"open-link\" id=\"drawer-file-btn\" data-corn-kind=\"primary\" class=\"hx-open\" href=\"#\" target=\"_blank\" rel=\"noreferrer\" hidden>Open file ↗</a><a data-corn=\"open-link\" id=\"drawer-open-btn\" data-corn-kind=\"primary\" class=\"hx-open\" href=\"#\" target=\"_blank\" rel=\"noreferrer\" hidden>Open route ↗</a><button data-corn-kind=\"secondary\" type=\"button\" id=\"drawer-run-btn\" class=\"hx-btn hx-foot-btn\" data-action=\"start-run\" data-corn-string=\"startRun\" hidden>Start a run</button><button data-corn-kind=\"quiet\" type=\"button\" class=\"hx-btn hx-btn--quiet hx-foot-btn\" data-action=\"copy-spec\" data-corn-string=\"copySpec\">Copy Spec</button><p id=\"copy-spec-result\" class=\"hx-forge-result\" data-corn=\"result\" hidden></p></div></aside>",
@@ -1059,16 +1059,16 @@ async function Jt(e, t) {
1059
1059
  }, Ot);
1060
1060
  }
1061
1061
  function Yt(e) {
1062
- let { state: t } = e, n = (e) => t.nodes.find((t) => t.id === e), r = (e) => (n(e) || { label: e }).label, i = (e) => `<span class="hx-name">${f(r(e))}</span>`, a = (e, n, r) => t.edges.filter((t) => t.kind === e && t[n] === r);
1062
+ let { state: t } = e, n = (e) => t.nodes.find((t) => t.id === e), r = (e) => (n(e) || { label: e }).label, i = (e) => `<span class="hx-name">${c(r(e))}</span>`, a = (e, n, r) => t.edges.filter((t) => t.kind === e && t[n] === r);
1063
1063
  function o(e) {
1064
- let o = t.edges.filter((e) => e.kind === "reads"), s = t.edges.filter((e) => e.kind === "writes"), c = t.edges.filter((t) => t.kind === "uses" && t.from === e.id), l = $("Extends:", t.edges.filter((t) => t.kind === "extends" && t.from === e.id).map((e) => Q(i(e.to)))) + $("Uses design tokens:", c.map((e) => Q(`${i(e.to)} · ${e.vars.length}${Ht(e.vars)}`))) + (e.type !== "token" && e.vars ? $(`Defines ${e.vars.length} CSS variable(s):`, [Ht(e.vars)]) : "");
1064
+ let o = t.edges.filter((e) => e.kind === "reads"), s = t.edges.filter((e) => e.kind === "writes"), l = t.edges.filter((t) => t.kind === "uses" && t.from === e.id), u = $("Extends:", t.edges.filter((t) => t.kind === "extends" && t.from === e.id).map((e) => Q(i(e.to)))) + $("Uses design tokens:", l.map((e) => Q(`${i(e.to)} · ${e.vars.length}${Ht(e.vars)}`))) + (e.type !== "token" && e.vars ? $(`Defines ${e.vars.length} CSS variable(s):`, [Ht(e.vars)]) : "");
1065
1065
  if (e.type === "app") {
1066
- let n = e.deployed ? Q(`${/^https?:\/\//.test(e.url) ? `<a data-corn="text-link" class="hx-link" href="${f(e.url)}" target="_blank" rel="noreferrer">${f(e.url)}</a>` : Z(e.url)} → ${(e.upstreams || []).map(Z).join(" ")}${e.stack ? ` <span class="hx-faint">[${f(e.stack)}]</span>` : ""}`) : Q("Not deployed by any stack in this repo"), r = t.edges.filter((t) => t.kind === "runs-on" && t.from === e.id).map((e) => Q(`${i(e.to)}${(e.mappings || []).map((e) => `<div class="hx-faint">${Z(e.host)} → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}</div>`).join("")}`));
1067
- return $("Served:", [n]) + $("Runs on:", r) + $("Loaded by the server per request:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + l;
1066
+ let n = e.deployed ? Q(`${/^https?:\/\//.test(e.url) ? `<a data-corn="text-link" class="hx-link" href="${c(e.url)}" target="_blank" rel="noreferrer">${c(e.url)}</a>` : Z(e.url)} → ${(e.upstreams || []).map(Z).join(" ")}${e.stack ? ` <span class="hx-faint">[${c(e.stack)}]</span>` : ""}`) : Q("Not deployed by any stack in this repo"), r = t.edges.filter((t) => t.kind === "runs-on" && t.from === e.id).map((e) => Q(`${i(e.to)}${(e.mappings || []).map((e) => `<div class="hx-faint">${Z(e.host)} → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}</div>`).join("")}`));
1067
+ return $("Served:", [n]) + $("Runs on:", r) + $("Loaded by the server per request:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + u;
1068
1068
  }
1069
1069
  if (e.type === "token") {
1070
1070
  let n = t.edges.filter((t) => t.kind === "uses" && t.to === e.id);
1071
- return $(`${e.vars.length} variable(s):`, [Ht(e.vars)]) + $("Used by:", n.map((e) => Q(`${i(e.from)} · ${f(e.vars.join(" "))}`)));
1071
+ return $(`${e.vars.length} variable(s):`, [Ht(e.vars)]) + $("Used by:", n.map((e) => Q(`${i(e.from)} · ${c(e.vars.join(" "))}`)));
1072
1072
  }
1073
1073
  if ([
1074
1074
  "atom",
@@ -1076,60 +1076,60 @@ function Yt(e) {
1076
1076
  "core"
1077
1077
  ].includes(e.type)) {
1078
1078
  let n = t.edges.filter((t) => t.dashed && t.to === e.id).map((e) => Q(i(e.from)));
1079
- return (e.table ? $("Record of:", [Q(`${f(e.model)} · table ${Z(e.table)}`)]) : "") + $("Rendered by:", n) + l;
1079
+ return (e.table ? $("Record of:", [Q(`${c(e.model)} · table ${Z(e.table)}`)]) : "") + $("Rendered by:", n) + u;
1080
1080
  }
1081
- if (e.type === "stack") return $("Domains served (Caddyfile → service):", t.edges.filter((t) => t.kind === "runs-on" && t.to === e.id).flatMap((e) => (e.mappings || []).map((e) => Q(`<span class="hx-name">${f(e.host)}</span> → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}`)))) + $(`${(e.services || []).length} service(s):`, (e.services || []).map((e) => Q(`<span class="hx-name">${f(e.name)}</span>${e.image ? ` <span class="hx-faint">${f(e.image)}</span>` : ""}${e.ports.length ? `<div>${e.ports.map(Z).join(" ")}</div>` : ""}${e.volumes.length ? `<div class="hx-faint">${e.volumes.map(f).join("<br>")}</div>` : ""}`))) + $("Compose file:", [Q(Z(e.file))]);
1081
+ if (e.type === "stack") return $("Domains served (Caddyfile → service):", t.edges.filter((t) => t.kind === "runs-on" && t.to === e.id).flatMap((e) => (e.mappings || []).map((e) => Q(`<span class="hx-name">${c(e.host)}</span> → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}`)))) + $(`${(e.services || []).length} service(s):`, (e.services || []).map((e) => Q(`<span class="hx-name">${c(e.name)}</span>${e.image ? ` <span class="hx-faint">${c(e.image)}</span>` : ""}${e.ports.length ? `<div>${e.ports.map(Z).join(" ")}</div>` : ""}${e.volumes.length ? `<div class="hx-faint">${e.volumes.map(c).join("<br>")}</div>` : ""}`))) + $("Compose file:", [Q(Z(e.file))]);
1082
1082
  if (e.type === "table") {
1083
- let t = o.filter((t) => t.from === e.id), a = s.filter((t) => t.to === e.id), c = t.filter((e) => (n(e.to) || {}).render?.rom === "bake");
1084
- return (e.model ? $("Model:", [Q(f(e.model))]) : "") + $("Read by:", t.map((e) => Q(`${i(e.to)} · ${e.keys.map(Z).join(" ")}`))) + $("Written by:", a.map((e) => Q(`${i(e.from)} · ${f(e.label)}`))) + (c.length ? $("Baked pages:", [Q(`a write here re-bakes <span class="hx-rom hx-bold">${c.length}</span> file(s): ${c.map((e) => f(r(e.to))).join(", ")}`)]) : "");
1083
+ let t = o.filter((t) => t.from === e.id), a = s.filter((t) => t.to === e.id), l = t.filter((e) => (n(e.to) || {}).render?.rom === "bake");
1084
+ return (e.model ? $("Model:", [Q(c(e.model))]) : "") + $("Read by:", t.map((e) => Q(`${i(e.to)} · ${e.keys.map(Z).join(" ")}`))) + $("Written by:", a.map((e) => Q(`${i(e.from)} · ${c(e.label)}`))) + (l.length ? $("Baked pages:", [Q(`a write here re-bakes <span class="hx-rom hx-bold">${l.length}</span> file(s): ${l.map((e) => c(r(e.to))).join(", ")}`)]) : "");
1085
1085
  }
1086
1086
  if (e.type === "service") {
1087
- let t = (e, t) => `${i(e[t])}${e.label && e.label !== "imports" ? ` · ${f(e.label)}` : ""}`;
1088
- return (e.summary && !String(e.desc || "").includes(e.summary) ? $("Summary:", [Q(`<span class="hx-faint">${f(e.summary)}</span>`)]) : "") + $("Started by:", [...(e.triggers || []).map((e) => Q(f(e))), ...a("triggers", "to", e.id).map((e) => Q(t(e, "from")))]) + $("Jobs:", (e.jobs || []).map((e) => Q(`${Z(e.name)} · cron ${Z(e.cron)}`))) + $("Runs:", a("triggers", "from", e.id).map((e) => Q(t(e, "to")))) + $("Calls:", a("calls", "from", e.id).map((e) => Q(t(e, "to")))) + $("Called by:", a("calls", "to", e.id).map((e) => Q(t(e, "from")))) + $("Reads tables:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + $("Writes tables:", s.filter((t) => t.from === e.id).map((e) => Q(i(e.to)))) + $("Mechanisms:", (e.mechanisms || []).map((e) => Q(f(e))));
1087
+ let t = (e, t) => `${i(e[t])}${e.label && e.label !== "imports" ? ` · ${c(e.label)}` : ""}`;
1088
+ return (e.summary && !String(e.desc || "").includes(e.summary) ? $("Summary:", [Q(`<span class="hx-faint">${c(e.summary)}</span>`)]) : "") + $("Started by:", [...(e.triggers || []).map((e) => Q(c(e))), ...a("triggers", "to", e.id).map((e) => Q(t(e, "from")))]) + $("Jobs:", (e.jobs || []).map((e) => Q(`${Z(e.name)} · cron ${Z(e.cron)}`))) + $("Runs:", a("triggers", "from", e.id).map((e) => Q(t(e, "to")))) + $("Calls:", a("calls", "from", e.id).map((e) => Q(t(e, "to")))) + $("Called by:", a("calls", "to", e.id).map((e) => Q(t(e, "from")))) + $("Reads tables:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + $("Writes tables:", s.filter((t) => t.from === e.id).map((e) => Q(i(e.to)))) + $("Mechanisms:", (e.mechanisms || []).map((e) => Q(c(e))));
1089
1089
  }
1090
1090
  if (e.type === "container" && e.selfHosted) {
1091
- let a = (e, t) => `${i(e[t])}${e.label && e.label !== "calls" ? ` · ${f(e.label)}` : ""}`, o = t.edges.filter((t) => t.to === e.id && (t.kind === "calls" || t.kind === "flow" && t.flow === "api")), s = (e) => o.filter((t) => n(t.from)?.type === e).map((e) => Q(a(e, "from"))), c = new Set(t.nodes.filter((t) => t.type === "container" && t.stack === e.stack).map((e) => e.id));
1092
- return $("Self-hosted:", [Q(f(e.summary || ""))]) + $("Called by services:", s("service")) + $("Called by endpoints:", s("page")) + $("Called by apps:", s("app")) + $("Pushes to (webhook):", t.edges.filter((e) => e.kind === "delivers" && c.has(e.from) && n(e.to)?.type === "page").map((t) => Q(`${i(t.to)}${t.from === e.id ? "" : ` <span class="hx-faint">from ${f(r(t.from))}</span>`}`)));
1091
+ let a = (e, t) => `${i(e[t])}${e.label && e.label !== "calls" ? ` · ${c(e.label)}` : ""}`, o = t.edges.filter((t) => t.to === e.id && (t.kind === "calls" || t.kind === "flow" && t.flow === "api")), s = (e) => o.filter((t) => n(t.from)?.type === e).map((e) => Q(a(e, "from"))), l = new Set(t.nodes.filter((t) => t.type === "container" && t.stack === e.stack).map((e) => e.id));
1092
+ return $("Self-hosted:", [Q(c(e.summary || ""))]) + $("Called by services:", s("service")) + $("Called by endpoints:", s("page")) + $("Called by apps:", s("app")) + $("Pushes to (webhook):", t.edges.filter((e) => e.kind === "delivers" && l.has(e.from) && n(e.to)?.type === "page").map((t) => Q(`${i(t.to)}${t.from === e.id ? "" : ` <span class="hx-faint">from ${c(r(t.from))}</span>`}`)));
1093
1093
  }
1094
1094
  if (e.type === "external" && e.kind) return wt(e, t.nodes, t.edges);
1095
1095
  if (e.type === "external") {
1096
1096
  let t = (t) => a("calls", "to", e.id).filter((e) => n(e.from)?.type === t);
1097
- return $("System:", [Q(`${f(e.summary || "")}${e.host ? `<div class="hx-faint">Runs here as ${Z(e.host)}</div>` : "<div class=\"hx-faint\">Not run by this stack</div>"}`)]) + $("Client modules:", (e.modules || []).map((e) => Q(Z(e)))) + $("Called by services:", t("service").map((e) => Q(i(e.from)))) + $("Called by endpoints:", t("page").map((e) => Q(i(e.from)))) + $("Pushes to (webhook):", a("delivers", "from", e.id).map((e) => Q(i(e.to))));
1097
+ return $("System:", [Q(`${c(e.summary || "")}${e.host ? `<div class="hx-faint">Runs here as ${Z(e.host)}</div>` : "<div class=\"hx-faint\">Not run by this stack</div>"}`)]) + $("Client modules:", (e.modules || []).map((e) => Q(Z(e)))) + $("Called by services:", t("service").map((e) => Q(i(e.from)))) + $("Called by endpoints:", t("page").map((e) => Q(i(e.from)))) + $("Pushes to (webhook):", a("delivers", "from", e.id).map((e) => Q(i(e.to))));
1098
1098
  }
1099
1099
  if (e.type === "page") {
1100
1100
  let n = e.render, r = t.edges.filter((t) => t.dashed && t.from === e.id).map((e) => Q(i(e.to)));
1101
- return (e.methods ? $("Methods:", [Q(e.methods.map(Z).join(" "))]) : "") + (e.render_fn ? $("Rendered by:", [Q(`${Z(e.render_fn)} · ${f(e.file)}`)]) : "") + $("Calls outside:", a("calls", "from", e.id).map((e) => Q(i(e.to)))) + $("Pushed to by:", a("delivers", "to", e.id).map((e) => Q(`${i(e.from)} · ${f(e.label)}`))) + $("Starts:", a("triggers", "from", e.id).map((e) => Q(`${i(e.to)} · ${f(e.label)}`))) + $("Renders:", r) + $("Reads:", o.filter((t) => t.to === e.id).map((e) => Q(`${i(e.from)} · ${e.keys.map(Z).join(" ")}`))) + $("Writes:", s.filter((t) => t.from === e.id).map((e) => Q(`${i(e.to)} · ${f(e.label)}`))) + (n ? $("Render:", [Q(`today: ${Z(n.now)} · ROM: ${n.rom === "bake" ? "<span class=\"hx-rom hx-bold\">bake</span>" : "<span class=\"hx-faint\">skip (per request)</span>"}${n.note ? `<div class="hx-faint">${f(n.note)}</div>` : ""}`)]) : "");
1101
+ return (e.methods ? $("Methods:", [Q(e.methods.map(Z).join(" "))]) : "") + (e.render_fn ? $("Rendered by:", [Q(`${Z(e.render_fn)} · ${c(e.file)}`)]) : "") + $("Calls outside:", a("calls", "from", e.id).map((e) => Q(i(e.to)))) + $("Pushed to by:", a("delivers", "to", e.id).map((e) => Q(`${i(e.from)} · ${c(e.label)}`))) + $("Starts:", a("triggers", "from", e.id).map((e) => Q(`${i(e.to)} · ${c(e.label)}`))) + $("Renders:", r) + $("Reads:", o.filter((t) => t.to === e.id).map((e) => Q(`${i(e.from)} · ${e.keys.map(Z).join(" ")}`))) + $("Writes:", s.filter((t) => t.from === e.id).map((e) => Q(`${i(e.to)} · ${c(e.label)}`))) + (n ? $("Render:", [Q(`today: ${Z(n.now)} · ROM: ${n.rom === "bake" ? "<span class=\"hx-rom hx-bold\">bake</span>" : "<span class=\"hx-faint\">skip (per request)</span>"}${n.note ? `<div class="hx-faint">${c(n.note)}</div>` : ""}`)]) : "");
1102
1102
  }
1103
1103
  return "";
1104
1104
  }
1105
1105
  function s(t) {
1106
1106
  let n = e.ask("threads:index", t.id);
1107
1107
  if (!n) return "";
1108
- let r = n.threads, i = n.start ? `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-textact" data-thread-start="${f(t.id)}" aria-label="Start a thread about this: opens the New idea form for ${f(n.forge)}, with this node mentioned">Start a thread about this</button>` : "";
1108
+ let r = n.threads, i = n.start ? `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-textact" data-thread-start="${c(t.id)}" aria-label="Start a thread about this: opens the New idea form for ${c(n.forge)}, with this node mentioned">Start a thread about this</button>` : "";
1109
1109
  return !r || !r.length ? i : `<div class="hx-sec-block" data-corn="section"><h3 class="hx-sec-title">Threads</h3><ul class="hx-rows">${r.map((e) => {
1110
1110
  let t = Number(e.comments) || 0;
1111
- return `<li><button type="button" class="hx-row hx-thread-open" data-thread-open="${f(e.number)}" data-corn="row" aria-label="Open thread #${f(e.number)}, ${f(e.title)}, ${t} ${t === 1 ? "comment" : "comments"}, in the issues and pull requests panel"><span class="hx-row-title">${f(e.title)}</span><span class="hx-row-meta">#${f(e.number)} · ${t}</span></button></li>`;
1111
+ return `<li><button type="button" class="hx-row hx-thread-open" data-thread-open="${c(e.number)}" data-corn="row" aria-label="Open thread #${c(e.number)}, ${c(e.title)}, ${t} ${t === 1 ? "comment" : "comments"}, in the issues and pull requests panel"><span class="hx-row-title">${c(e.title)}</span><span class="hx-row-meta">#${c(e.number)} · ${t}</span></button></li>`;
1112
1112
  }).join("")}</ul>${i}</div>`;
1113
1113
  }
1114
- function c(e) {
1115
- let n = b(e);
1114
+ function l(e) {
1115
+ let n = y(e);
1116
1116
  if (!Gt(e, t.proposal)) return "";
1117
- let r = (e, t) => `<div class="hx-diff-k">${f(e)}</div><div class="hx-diff-v">${t}</div>`, i = [r("id", f(e.id))], a = t.edges.find((t) => !t.kind && !t.dashed && t.to === e.id);
1118
- a && i.push(r("parent", f(a.from)));
1119
- let o = t.edges.filter((t) => t.from === e.id || t.to === e.id), s = o.filter((e) => b(e) === "added").length, c = o.filter((e) => b(e) === "removed").length;
1120
- if ((s || c) && i.push(r("edges", f([s ? `+${s}` : "", c ? `−${c}` : ""].filter(Boolean).join(" ")))), n === "changed") for (let t of Te(e)) i.push(r(t.field, `<span class="hx-change-before">${f(t.before) || "<em>nothing</em>"}</span> <span aria-hidden="true">→</span><span class="hx-sr-only"> became </span> <span class="hx-change-after">${f(t.after) || "<em>nothing</em>"}</span>`));
1121
- return `<div class="hx-sec-block" data-proposal-mark="${f(e.mark)}" data-corn="section"><h3 class="hx-sec-title">In this proposal</h3>${e.why ? `<p class="hx-why">${f(e.why)}</p>` : ""}<div class="hx-diff hx-diff--${f(n)}" data-corn="diff-block"${I(e.mark)}>${i.join("")}</div></div>`;
1117
+ let r = (e, t) => `<div class="hx-diff-k">${c(e)}</div><div class="hx-diff-v">${t}</div>`, i = [r("id", c(e.id))], a = t.edges.find((t) => !t.kind && !t.dashed && t.to === e.id);
1118
+ a && i.push(r("parent", c(a.from)));
1119
+ let o = t.edges.filter((t) => t.from === e.id || t.to === e.id), s = o.filter((e) => y(e) === "added").length, l = o.filter((e) => y(e) === "removed").length;
1120
+ if ((s || l) && i.push(r("edges", c([s ? `+${s}` : "", l ? `−${l}` : ""].filter(Boolean).join(" ")))), n === "changed") for (let t of we(e)) i.push(r(t.field, `<span class="hx-change-before">${c(t.before) || "<em>nothing</em>"}</span> <span aria-hidden="true">→</span><span class="hx-sr-only"> became </span> <span class="hx-change-after">${c(t.after) || "<em>nothing</em>"}</span>`));
1121
+ return `<div class="hx-sec-block" data-proposal-mark="${c(e.mark)}" data-corn="section"><h3 class="hx-sec-title">In this proposal</h3>${e.why ? `<p class="hx-why">${c(e.why)}</p>` : ""}<div class="hx-diff hx-diff--${c(n)}" data-corn="diff-block"${R(e.mark)}>${i.join("")}</div></div>`;
1122
1122
  }
1123
1123
  return {
1124
1124
  dataSummary: o,
1125
1125
  threadsSection: s,
1126
- diffSection: c,
1126
+ diffSection: l,
1127
1127
  nameOf: r,
1128
1128
  nodeById: n
1129
1129
  };
1130
1130
  }
1131
- function Xt(e, n, r = {}) {
1132
- let { state: i } = n, s = u(n), c = Yt(n), l = r.inline === !0, d = [...D(n, e, Kt().drawer, r.slots, "drawer"), ...l ? D(n, e, `<p class="hx-panel-empty" data-corn="empty">${f(y(n, "nodePanelEmpty"))}</p>`, null, "empty") : D(n, e, Kt().backdrop, r.slots, "backdrop")], p = (e) => {
1131
+ function Xt(e, t, n = {}) {
1132
+ let { state: i } = t, o = r(t), l = Yt(t), u = n.inline === !0, d = [...a(t, e, Kt().drawer, n.slots, "drawer"), ...u ? a(t, e, `<p class="hx-panel-empty" data-corn="empty">${c(v(t, "nodePanelEmpty"))}</p>`, null, "empty") : a(t, e, Kt().backdrop, n.slots, "backdrop")], p = (e) => {
1133
1133
  for (let t of d) {
1134
1134
  if (t.id === e) return t;
1135
1135
  let n = t.querySelector(`[id="${e}"]`);
@@ -1137,155 +1137,155 @@ function Xt(e, n, r = {}) {
1137
1137
  }
1138
1138
  return null;
1139
1139
  };
1140
- s.keepParts(...d);
1141
- let m = p("spec-drawer"), h = l ? { hidden: !0 } : p("drawer-backdrop"), g = l ? d.find((e) => e.matches("[data-corn=\"empty\"]")) : null, b = (e) => {
1142
- g && (g.hidden = !e);
1143
- }, C = !1, E = () => v(i.selectedNode, n.viewEdges(), {
1140
+ o.keepParts(...d);
1141
+ let m = p("spec-drawer"), y = u ? { hidden: !0 } : p("drawer-backdrop"), b = u ? d.find((e) => e.matches("[data-corn=\"empty\"]")) : null, w = (e) => {
1142
+ b && (b.hidden = !e);
1143
+ }, T = !1, E = () => S(i.selectedNode, t.viewEdges(), {
1144
1144
  throughChildren: i.throughChildren,
1145
1145
  kind: i.selectedKind
1146
1146
  });
1147
- function ee(e) {
1148
- let t = E();
1149
- if (!t || !t.kinds.size) return "";
1150
- let r = Ft(t).map(({ kind: e, count: n, word: r }) => `<button type="button" class="hx-lines-kind" data-corn="lines-kind" data-corn-kind="quiet" data-lines-kind="${f(e)}" data-focus-key="kind:${f(e)}" aria-pressed="${t.kind === e}">${f(r)} <span class="hx-lines-count" data-corn="count">${n}</span></button>`).join(""), a = t.kind ? It(t, t.kind).map((e) => `<button type="button" class="hx-linkbtn" data-corn="node-link" data-action="select-node" data-id="${f(e.id)}"><span class="hx-sr-only">${e.out ? "to " : "from "}</span><span aria-hidden="true">${e.out ? "→" : "←"}</span> ${f(c.nameOf(e.id))}</button>`) : [], o = a.length ? `<div class="hx-lines-list">${M(a, 12)}</div>` : "", s = v(e, n.viewEdges(), { throughChildren: !1 }).childIds.size > 0 ? `<label class="hx-lines-switch"><input type="checkbox" data-corn="lines-switch" data-lines-switch data-focus-key="switch"${i.throughChildren ? " checked" : ""}> <span>${f(y(n, "throughChildren"))}</span></label>` : "", { connected: l, off: u } = S(n);
1151
- return `<div class="hx-sec-block hx-lines" id="drawer-lines" data-corn="lines-by-kind"><h3 class="hx-sec-title">Lines</h3><div class="hx-chips" role="group" aria-label="Lit lines by kind">${r}</div>${o}${s}<div class="hx-lines-reach"><span data-lines-reach>${f(Lt(l, u))}</span> <button type="button" data-corn="frame-button" data-corn-kind="secondary" class="hx-btn hx-btn--secondary" data-action="frame-selection" data-focus-key="frame">${f(y(n, "frame"))}</button></div></div>`;
1147
+ function D(e) {
1148
+ let n = E();
1149
+ if (!n || !n.kinds.size) return "";
1150
+ let r = Ft(n).map(({ kind: e, count: t, word: r }) => `<button type="button" class="hx-lines-kind" data-corn="lines-kind" data-corn-kind="quiet" data-lines-kind="${c(e)}" data-focus-key="kind:${c(e)}" aria-pressed="${n.kind === e}">${c(r)} <span class="hx-lines-count" data-corn="count">${t}</span></button>`).join(""), a = n.kind ? It(n, n.kind).map((e) => `<button type="button" class="hx-linkbtn" data-corn="node-link" data-action="select-node" data-id="${c(e.id)}"><span class="hx-sr-only">${e.out ? "to " : "from "}</span><span aria-hidden="true">${e.out ? "→" : "←"}</span> ${c(l.nameOf(e.id))}</button>`) : [], o = a.length ? `<div class="hx-lines-list">${P(a, 12)}</div>` : "", s = S(e, t.viewEdges(), { throughChildren: !1 }).childIds.size > 0 ? `<label class="hx-lines-switch"><input type="checkbox" data-corn="lines-switch" data-lines-switch data-focus-key="switch"${i.throughChildren ? " checked" : ""}> <span>${c(v(t, "throughChildren"))}</span></label>` : "", { connected: u, off: d } = _(t);
1151
+ return `<div class="hx-sec-block hx-lines" id="drawer-lines" data-corn="lines-by-kind"><h3 class="hx-sec-title">Lines</h3><div class="hx-chips" role="group" aria-label="Lit lines by kind">${r}</div>${o}${s}<div class="hx-lines-reach"><span data-lines-reach>${c(Lt(u, d))}</span> <button type="button" data-corn="frame-button" data-corn-kind="secondary" class="hx-btn hx-btn--secondary" data-action="frame-selection" data-focus-key="frame">${c(v(t, "frame"))}</button></div></div>`;
1152
1152
  }
1153
- function te() {
1153
+ function O() {
1154
1154
  let e = p("drawer-lines");
1155
1155
  if (!e || !i.selectedNode) return;
1156
- let r = n.active(), a = r && e.contains(r) ? r.dataset.focusKey : "", o = n.doc.createElement("div");
1157
- o.innerHTML = ee(i.selectedNode), t(o);
1158
- let s = o.firstElementChild;
1159
- if (s ? e.replaceWith(s) : e.remove(), a) {
1160
- let e = p("drawer-lines"), t = e && [...e.querySelectorAll("[data-focus-key]")].find((e) => e.dataset.focusKey === a);
1156
+ let n = t.active(), r = n && e.contains(n) ? n.dataset.focusKey : "", a = t.doc.createElement("div");
1157
+ a.innerHTML = D(i.selectedNode), f(a);
1158
+ let o = a.firstElementChild;
1159
+ if (o ? e.replaceWith(o) : e.remove(), r) {
1160
+ let e = p("drawer-lines"), t = e && [...e.querySelectorAll("[data-focus-key]")].find((e) => e.dataset.focusKey === r);
1161
1161
  t && t.focus();
1162
1162
  }
1163
1163
  }
1164
- function O(e) {
1165
- let t = e.target.closest && e.target.closest("[data-lines-kind]");
1166
- if (!t || !i.selectedNode) return !1;
1167
- let r = t.dataset.linesKind;
1168
- i.selectedKind = i.selectedKind === r ? null : r, n.touchScene(), n.map.render(), te();
1169
- let o = E();
1170
- return a(n, o && o.kind ? `Showing ${Pt(o.kind).toLowerCase()} only: ${o.edges.length} ${o.edges.length === 1 ? "line" : "lines"}` : "Showing every kind of line"), !0;
1164
+ function k(e) {
1165
+ let n = e.target.closest && e.target.closest("[data-lines-kind]");
1166
+ if (!n || !i.selectedNode) return !1;
1167
+ let r = n.dataset.linesKind;
1168
+ i.selectedKind = i.selectedKind === r ? null : r, t.touchScene(), t.map.render(), O();
1169
+ let a = E();
1170
+ return C(t, a && a.kind ? `Showing ${Pt(a.kind).toLowerCase()} only: ${a.edges.length} ${a.edges.length === 1 ? "line" : "lines"}` : "Showing every kind of line"), !0;
1171
1171
  }
1172
- function ne(e) {
1173
- let t = e.target.closest && e.target.closest("[data-lines-switch]");
1174
- if (!t || !i.selectedNode) return;
1175
- i.throughChildren = !!t.checked, i.selectedKind = null, n.touchScene(), n.map.render(), te();
1172
+ function A(e) {
1173
+ let n = e.target.closest && e.target.closest("[data-lines-switch]");
1174
+ if (!n || !i.selectedNode) return;
1175
+ i.throughChildren = !!n.checked, i.selectedKind = null, t.touchScene(), t.map.render(), O();
1176
1176
  let r = E();
1177
- a(n, `${i.throughChildren ? "Including" : "Not including"} its children's lines: ${r ? r.connectedNodeIds.size - 1 : 0} connected`);
1177
+ C(t, `${i.throughChildren ? "Including" : "Not including"} its children's lines: ${r ? r.connectedNodeIds.size - 1 : 0} connected`);
1178
1178
  }
1179
- let j = p("drawer-meta-list");
1180
- s.listen(j, "click", (e) => {
1181
- O(e) || ce(e.target);
1182
- }), s.listen(j, "change", ne), s.own(n.map.onPaint(() => {
1179
+ let N = p("drawer-meta-list");
1180
+ o.listen(N, "click", (e) => {
1181
+ k(e) || oe(e.target);
1182
+ }), o.listen(N, "change", A), o.own(t.map.onPaint(() => {
1183
1183
  if (!i.selectedNode) return;
1184
1184
  let e = m.querySelector("[data-lines-reach]");
1185
1185
  if (!e) return;
1186
- let { connected: t, off: r } = S(n), a = Lt(t, r);
1186
+ let { connected: n, off: r } = _(t), a = Lt(n, r);
1187
1187
  e.textContent !== a && (e.textContent = a);
1188
1188
  }));
1189
- function N() {
1189
+ function F() {
1190
1190
  let e = p("drawer-threads");
1191
- e && i.selectedNode && (e.innerHTML = c.threadsSection(i.selectedNode), t(e));
1191
+ e && i.selectedNode && (e.innerHTML = l.threadsSection(i.selectedNode), f(e));
1192
1192
  }
1193
- function P(e, { frame: r = !1 } = {}) {
1194
- if (!e || C) return;
1195
- let a = p("drawer-title");
1196
- a.textContent = e.tag ? `<${e.tag}>` : e.label, a.classList.toggle("hx-mono", e.type === "page" || !!e.tag), p("drawer-badge").textContent = Ut(e);
1197
- let o = Wt(e);
1198
- p("drawer-host").textContent = o ? ` · ${o}` : "";
1199
- let s = Gt(e, i.proposal), u = p("drawer-diff");
1200
- u.textContent = s, u.hidden = !s;
1201
- let d = de(s ? e.mark : "");
1202
- d ? u.dataset.cornState = d : delete u.dataset.cornState;
1203
- let f = p("drawer-description");
1204
- f.textContent = e.desc || "", f.hidden = !e.desc;
1205
- let g = `${e.file ? $("File", [Z(e.file)]) : ""}${le(n, e)}${c.dataSummary(e)}`, _ = n.ask("live:section", e) || "";
1206
- j.innerHTML = `${ee(e)}${g ? `<div class="hx-facts">${g}</div>` : ""}
1207
- <div id="drawer-live">${_}</div>
1193
+ function I(e, { frame: n = !1 } = {}) {
1194
+ if (!e || T) return;
1195
+ let r = p("drawer-title");
1196
+ r.textContent = e.tag ? `<${e.tag}>` : e.label, r.classList.toggle("hx-mono", e.type === "page" || !!e.tag), p("drawer-badge").textContent = Ut(e);
1197
+ let a = Wt(e);
1198
+ p("drawer-host").textContent = a ? ` · ${a}` : "";
1199
+ let o = Gt(e, i.proposal), s = p("drawer-diff");
1200
+ s.textContent = o, s.hidden = !o;
1201
+ let c = le(o ? e.mark : "");
1202
+ c ? s.dataset.cornState = c : delete s.dataset.cornState;
1203
+ let d = p("drawer-description");
1204
+ d.textContent = e.desc || "", d.hidden = !e.desc;
1205
+ let h = `${e.file ? $("File", [Z(e.file)]) : ""}${se(t, e)}${l.dataSummary(e)}`, g = t.ask("live:section", e) || "";
1206
+ N.innerHTML = `${D(e)}${h ? `<div class="hx-facts">${h}</div>` : ""}
1207
+ <div id="drawer-live">${g}</div>
1208
1208
  ${ft(i, e.id)}
1209
- <div id="drawer-threads">${c.threadsSection(e)}</div>
1210
- ${c.diffSection(e)}`, t(j), n.emit("threads:ensure"), n.emit("live:hydrate", p("drawer-live"));
1211
- let v = p("drawer-file-btn"), x = p("drawer-open-btn"), S = e.file && i.forge ? Dt(i.forge, e.file, i.forge.baseBranch) : null;
1212
- v.hidden = !S, S ? v.href = S : v.removeAttribute("href");
1213
- let w = !!(e.url && /^https?:\/\//.test(e.url));
1214
- w ? x.href = e.url : x.removeAttribute("href"), x.hidden = !w, x.className = S ? "hx-btn hx-btn--quiet hx-foot-btn" : "hx-open", S ? x.dataset.cornKind = "quiet" : x.dataset.cornKind = "primary", x.textContent = `${y(n, "openRoute")} ↗`, v.textContent = `${y(n, "openFile")} ↗`, p("drawer-run-btn").hidden = !(i.proposalSlug && n.ask("forge:can-start")), m.classList.add("drawer-open"), m.inert = !1, h.hidden = !1, b(!1), l || se(n, "drawer"), !r && !l && F(), n.emit("node:painted", { node: e });
1209
+ <div id="drawer-threads">${l.threadsSection(e)}</div>
1210
+ ${l.diffSection(e)}`, f(N), t.emit("threads:ensure"), t.emit("live:hydrate", p("drawer-live"));
1211
+ let _ = p("drawer-file-btn"), b = p("drawer-open-btn"), x = e.file && i.forge ? Dt(i.forge, e.file, i.forge.baseBranch) : null;
1212
+ _.hidden = !x, x ? _.href = x : _.removeAttribute("href");
1213
+ let S = !!(e.url && /^https?:\/\//.test(e.url));
1214
+ S ? b.href = e.url : b.removeAttribute("href"), b.hidden = !S, b.className = x ? "hx-btn hx-btn--quiet hx-foot-btn" : "hx-open", x ? b.dataset.cornKind = "quiet" : b.dataset.cornKind = "primary", b.textContent = `${v(t, "openRoute")} ↗`, _.textContent = `${v(t, "openFile")} ↗`, p("drawer-run-btn").hidden = !(i.proposalSlug && t.ask("forge:can-start")), m.classList.add("drawer-open"), m.inert = !1, y.hidden = !1, w(!1), u || ae(t, "drawer"), !n && !u && L(), t.emit("node:painted", { node: e });
1215
1215
  }
1216
- function ue(e) {
1217
- if (!e || C) return;
1218
- let n = (e, t) => t ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${f(e)}</div><div class="hx-fact-v">${f(t)}</div></div>` : "", r = n("Kind", e.kind || (e.dashed ? "usage" : "ownership")) + n("Flow", e.flow) + n("Label", e.label) + n("Reads", Array.isArray(e.keys) ? e.keys.join(", ") : ""), i = p("drawer-title");
1219
- i.textContent = `${c.nameOf(e.from)} → ${c.nameOf(e.to)}`, i.classList.remove("hx-mono"), p("drawer-badge").textContent = "Edge", p("drawer-host").textContent = "", p("drawer-diff").hidden = !0;
1220
- let a = p("drawer-description");
1221
- a.textContent = "", a.hidden = !0, j.innerHTML = `${r ? `<div class="hx-facts">${r}</div>` : ""}
1216
+ function ce(e) {
1217
+ if (!e || T) return;
1218
+ let t = (e, t) => t ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(e)}</div><div class="hx-fact-v">${c(t)}</div></div>` : "", n = t("Kind", e.kind || (e.dashed ? "usage" : "ownership")) + t("Flow", e.flow) + t("Label", e.label) + t("Reads", Array.isArray(e.keys) ? e.keys.join(", ") : ""), r = p("drawer-title");
1219
+ r.textContent = `${l.nameOf(e.from)} → ${l.nameOf(e.to)}`, r.classList.remove("hx-mono"), p("drawer-badge").textContent = "Edge", p("drawer-host").textContent = "", p("drawer-diff").hidden = !0;
1220
+ let i = p("drawer-description");
1221
+ i.textContent = "", i.hidden = !0, N.innerHTML = `${n ? `<div class="hx-facts">${n}</div>` : ""}
1222
1222
  <div class="hx-facts">
1223
- <div class="hx-fact" data-corn="section"><div class="hx-fact-k">From</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${f(e.from)}">${f(c.nameOf(e.from))}</button></div></div>
1224
- <div class="hx-fact" data-corn="section"><div class="hx-fact-k">To</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${f(e.to)}">${f(c.nameOf(e.to))}</button></div></div>
1225
- </div>${Ee(e)}`, t(j), p("drawer-open-btn").hidden = !0, p("drawer-file-btn").hidden = !0, p("drawer-run-btn").hidden = !0, m.classList.add("drawer-open"), m.inert = !1, h.hidden = !1, b(!1);
1223
+ <div class="hx-fact" data-corn="section"><div class="hx-fact-k">From</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${c(e.from)}">${c(l.nameOf(e.from))}</button></div></div>
1224
+ <div class="hx-fact" data-corn="section"><div class="hx-fact-k">To</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${c(e.to)}">${c(l.nameOf(e.to))}</button></div></div>
1225
+ </div>${Te(e)}`, f(N), p("drawer-open-btn").hidden = !0, p("drawer-file-btn").hidden = !0, p("drawer-run-btn").hidden = !0, m.classList.add("drawer-open"), m.inert = !1, y.hidden = !1, w(!1);
1226
1226
  }
1227
- function F() {
1227
+ function L() {
1228
1228
  let e = i.selectedNode;
1229
- if (!e || !i.width || !x(n) || C) return;
1230
- let t = T(n), r = gt(i.camera, e, {
1229
+ if (!e || !i.width || !h(t) || T) return;
1230
+ let n = g(t), r = gt(i.camera, e, {
1231
1231
  left: 0,
1232
1232
  top: 0,
1233
1233
  right: i.width,
1234
- bottom: i.height - t
1234
+ bottom: i.height - n
1235
1235
  }, e.r * i.camera.zoom + 16);
1236
- r && (Object.assign(i.camera, r), n.map.render());
1236
+ r && (Object.assign(i.camera, r), t.map.render());
1237
1237
  }
1238
- function I() {
1239
- m.classList.remove("drawer-open"), m.inert = !0, h.hidden = !0, b(!0), l || A(n, "drawer");
1238
+ function R() {
1239
+ m.classList.remove("drawer-open"), m.inert = !0, y.hidden = !0, w(!0), u || M(t, "drawer");
1240
1240
  }
1241
- function L() {
1242
- i.proposalSlug && n.emit("forge:start", {
1241
+ function z() {
1242
+ i.proposalSlug && t.emit("forge:start", {
1243
1243
  slug: i.proposalSlug,
1244
1244
  returnTo: "#drawer-run-btn"
1245
1245
  });
1246
1246
  }
1247
- s.own(() => clearTimeout(qt(n).timer));
1248
- let fe = {
1249
- "close-drawer": () => _(n, { source: "tap" }),
1250
- "copy-spec": () => Jt(n, p("copy-spec-result")),
1251
- "start-run": () => L(),
1252
- "select-node": (e) => w(n, c.nodeById(e.dataset.id), {
1247
+ o.own(() => clearTimeout(qt(t).timer));
1248
+ let ue = {
1249
+ "close-drawer": () => x(t, { source: "tap" }),
1250
+ "copy-spec": () => Jt(t, p("copy-spec-result")),
1251
+ "start-run": () => z(),
1252
+ "select-node": (e) => ee(t, l.nodeById(e.dataset.id), {
1253
1253
  frame: !0,
1254
1254
  source: "link"
1255
1255
  }),
1256
- "frame-selection": () => o(n)
1256
+ "frame-selection": () => s(t)
1257
1257
  };
1258
- return s.listen(m, "click", (e) => {
1258
+ return o.listen(m, "click", (e) => {
1259
1259
  let t = e.target.closest && e.target.closest("[data-action]");
1260
1260
  if (!t) return;
1261
- let n = fe[t.dataset.action];
1262
- n && n(t), t.dataset.action === "close-drawer" && i.canvas && s.timeout(() => i.canvas.focus(), 0);
1263
- }), s.listen(m, "click", (e) => {
1264
- let t = e.target.closest && e.target.closest("[data-thread-open]");
1265
- t ? n.emit("thread:open", { number: Number(t.dataset.threadOpen) }) : e.target.closest && e.target.closest("[data-thread-start]") && i.selectedNode && n.emit("thread:start", { node: i.selectedNode });
1266
- }), s.on("threads:changed", () => N()), l || s.listen(h, "click", (e) => {
1267
- x(n) ? k(n, e) : _(n, { source: "tap" });
1268
- }, !0), s.listen(m, "keydown", (e) => {
1269
- e.key !== "Escape" || e.defaultPrevented || e.target.closest && e.target.closest("select, input, textarea") || (e.preventDefault(), _(n, { source: "keyboard" }), i.canvas && i.canvas.focus(), a(n, "Panel closed"));
1270
- }), s.on("panel:present", () => !0), s.on("panel:covers", () => !l && !C && !m.hidden && m.classList.contains("drawer-open") ? { right: m.offsetWidth } : void 0), s.on("node:show", ({ node: e, frame: t }) => P(e, { frame: t })), s.on("node:close", I), s.on("node:show-edge", ({ edge: e }) => ue(e)), s.on("node:focus", () => {
1261
+ let n = ue[t.dataset.action];
1262
+ n && n(t), t.dataset.action === "close-drawer" && i.canvas && o.timeout(() => i.canvas.focus(), 0);
1263
+ }), o.listen(m, "click", (e) => {
1264
+ let n = e.target.closest && e.target.closest("[data-thread-open]");
1265
+ n ? t.emit("thread:open", { number: Number(n.dataset.threadOpen) }) : e.target.closest && e.target.closest("[data-thread-start]") && i.selectedNode && t.emit("thread:start", { node: i.selectedNode });
1266
+ }), o.on("threads:changed", () => F()), u || o.listen(y, "click", (e) => {
1267
+ h(t) ? j(t, e) : x(t, { source: "tap" });
1268
+ }, !0), o.listen(m, "keydown", (e) => {
1269
+ e.key !== "Escape" || e.defaultPrevented || e.target.closest && e.target.closest("select, input, textarea") || (e.preventDefault(), x(t, { source: "keyboard" }), i.canvas && i.canvas.focus(), C(t, "Panel closed"));
1270
+ }), o.on("panel:present", () => !0), o.on("panel:covers", () => !u && !T && !m.hidden && m.classList.contains("drawer-open") ? { right: m.offsetWidth } : void 0), o.on("node:show", ({ node: e, frame: t }) => I(e, { frame: t })), o.on("node:close", R), o.on("node:show-edge", ({ edge: e }) => ce(e)), o.on("node:focus", () => {
1271
1271
  let e = p("drawer-title");
1272
1272
  if (!e) return;
1273
- let t = n.active();
1274
- l && t && t !== e && typeof t.matches == "function" && t.matches("[data-corn=\"node-title\"]") || (e.setAttribute("tabindex", "-1"), e.focus());
1275
- }), l || (s.own(oe(n, () => F())), ae(n), re(n, "drawer", m, { stub: () => ({ title: p("drawer-title") && p("drawer-title").textContent || "Node" }) }), s.own(() => ie(n, "drawer"))), i.selectedNode && P(i.selectedNode, { frame: !1 }), s.own(() => {
1276
- C = !0, d.forEach((e) => e.remove());
1273
+ let n = t.active();
1274
+ u && n && n !== e && typeof n.matches == "function" && n.matches("[data-corn=\"node-title\"]") || (e.setAttribute("tabindex", "-1"), e.focus());
1275
+ }), u || (o.own(ie(t, () => L())), re(t), te(t, "drawer", m, { stub: () => ({ title: p("drawer-title") && p("drawer-title").textContent || "Node" }) }), o.own(() => ne(t, "drawer"))), i.selectedNode && I(i.selectedNode, { frame: !1 }), o.own(() => {
1276
+ T = !0, d.forEach((e) => e.remove());
1277
1277
  }), {
1278
1278
  elements: d,
1279
- show: P,
1280
- close: I,
1281
- repaintThreads: N,
1282
- copySpec: () => Jt(n, p("copy-spec-result")),
1283
- startRun: L,
1284
- keepSelectedInView: F,
1279
+ show: I,
1280
+ close: R,
1281
+ repaintThreads: F,
1282
+ copySpec: () => Jt(t, p("copy-spec-result")),
1283
+ startRun: z,
1284
+ keepSelectedInView: L,
1285
1285
  update(e) {
1286
- e && "node" in e ? e.node ? w(n, e.node, { source: "api" }) : _(n, { source: "api" }) : i.selectedNode && m.classList.contains("drawer-open") && P(i.selectedNode, { frame: !1 });
1286
+ e && "node" in e ? e.node ? ee(t, e.node, { source: "api" }) : x(t, { source: "api" }) : i.selectedNode && m.classList.contains("drawer-open") && I(i.selectedNode, { frame: !1 });
1287
1287
  },
1288
- destroy: () => s.destroy()
1288
+ destroy: () => o.destroy()
1289
1289
  };
1290
1290
  }
1291
- export { I as A, B as C, pe as D, Pe as E, fe as O, Ne as S, ve as T, xe as _, pt as a, Se as b, nt as c, at as d, he as f, ge as g, _e as h, yt as i, F as k, K as l, me as m, Rt as n, mt as o, z as p, bt as r, ht as s, Xt as t, it as u, ye as v, Ae as w, je as x, Me as y };
1291
+ export { R as A, V as C, de as D, Ne as E, ue as O, Me as S, ge as T, be as _, pt as a, xe as b, nt as c, at as d, pe as f, me as g, he as h, yt as i, L as k, K as l, fe as m, Rt as n, mt as o, B as p, bt as r, ht as s, Xt as t, it as u, _e as v, ke as w, Ae as x, je as y };