@fasl-work/caos-app-shell 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -123,21 +123,21 @@ function validateArchitectureConfig(config) {
123
123
  const out = [];
124
124
  if (config.tabs.length < 5) out.push(`the architecture modal has ${config.tabs.length} tabs; ADR-0058 requires at least 5`);
125
125
  const known = new Set(SHELL_TOKENS);
126
- for (const t of config.tabs) {
127
- if (!t.en?.trim() || !t.es?.trim() || !t.body_en?.trim() || !t.body_es?.trim()) {
128
- out.push(`architecture tab "${t.id}" lacks a label or a body in one language`);
126
+ for (const t2 of config.tabs) {
127
+ if (!t2.en?.trim() || !t2.es?.trim() || !t2.body_en?.trim() || !t2.body_es?.trim()) {
128
+ out.push(`architecture tab "${t2.id}" lacks a label or a body in one language`);
129
129
  }
130
- const svg = t.svg.trim();
130
+ const svg = t2.svg.trim();
131
131
  if (!svg.startsWith("<svg")) {
132
- out.push(`architecture tab "${t.id}": the diagram must be an inline SVG string (import it with ?raw), not a URL`);
132
+ out.push(`architecture tab "${t2.id}": the diagram must be an inline SVG string (import it with ?raw), not a URL`);
133
133
  continue;
134
134
  }
135
135
  for (const name of new Set([...svg.matchAll(/var\((--[a-z0-9-]+)/gi)].map((x) => x[1]))) {
136
- if (!known.has(name)) out.push(`architecture tab "${t.id}" uses ${name}, which the shell does not define`);
136
+ if (!known.has(name)) out.push(`architecture tab "${t2.id}" uses ${name}, which the shell does not define`);
137
137
  }
138
138
  const hex = svg.replace(/url\(\s*#[^)]*\)/gi, "").replace(/href\s*=\s*["']#[^"']*["']/gi, "").match(/#[0-9a-f]{3,8}\b/gi);
139
139
  if (hex) {
140
- out.push(`architecture tab "${t.id}" uses hex colours (${[...new Set(hex)].slice(0, 3).join(", ")}); use shell tokens so it follows the theme`);
140
+ out.push(`architecture tab "${t2.id}" uses hex colours (${[...new Set(hex)].slice(0, 3).join(", ")}); use shell tokens so it follows the theme`);
141
141
  }
142
142
  }
143
143
  return out;
@@ -191,7 +191,7 @@ function ArchitectureModal({ config, onClose }) {
191
191
  if (opener?.isConnected) opener.focus();
192
192
  };
193
193
  }, []);
194
- const tab = tabs.find((t) => t.id === active) ?? tabs[0];
194
+ const tab = tabs.find((t2) => t2.id === active) ?? tabs[0];
195
195
  useEffect(() => {
196
196
  if (!tab) return;
197
197
  setErr(null);
@@ -245,19 +245,19 @@ function ArchitectureModal({ config, onClose }) {
245
245
  }
246
246
  )
247
247
  ] }),
248
- /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": title, style: { display: "flex", flexWrap: "wrap", gap: 4, padding: "8px 14px 0", borderBottom: "1px solid var(--color-border)" }, children: tabs.map((t) => {
249
- const sel = t.id === active;
248
+ /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": title, style: { display: "flex", flexWrap: "wrap", gap: 4, padding: "8px 14px 0", borderBottom: "1px solid var(--color-border)" }, children: tabs.map((t2) => {
249
+ const sel = t2.id === active;
250
250
  return /* @__PURE__ */ jsx(
251
251
  "button",
252
252
  {
253
- id: `${id}-${t.id}`,
253
+ id: `${id}-${t2.id}`,
254
254
  role: "tab",
255
255
  "aria-selected": sel,
256
256
  "aria-controls": `${id}-panel`,
257
257
  tabIndex: sel ? 0 : -1,
258
- onClick: () => setActive(t.id),
258
+ onClick: () => setActive(t2.id),
259
259
  onKeyDown: (event) => {
260
- const index = tabs.indexOf(t);
260
+ const index = tabs.indexOf(t2);
261
261
  const next = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : event.key === "ArrowRight" ? (index + 1) % tabs.length : event.key === "ArrowLeft" ? (index - 1 + tabs.length) % tabs.length : -1;
262
262
  if (next < 0) return;
263
263
  event.preventDefault();
@@ -275,9 +275,9 @@ function ArchitectureModal({ config, onClose }) {
275
275
  color: sel ? "var(--color-accent-fg, #fff)" : "var(--color-fg-subtle)",
276
276
  fontWeight: sel ? 600 : 400
277
277
  },
278
- children: es ? t.es : t.en
278
+ children: es ? t2.es : t2.en
279
279
  },
280
- t.id
280
+ t2.id
281
281
  );
282
282
  }) }),
283
283
  /* @__PURE__ */ jsxs("div", { id: `${id}-panel`, role: "tabpanel", "aria-labelledby": `${id}-${tab.id}`, "data-arch-lang": es ? "es" : "en", "data-tab": tab.id, "data-state": err ? "missing" : svg === null ? "loading" : "ready", style: { overflowY: "auto", minHeight: 0, padding: "14px 16px 18px" }, children: [
@@ -522,14 +522,14 @@ function createVizLoop(frame, options, deps) {
522
522
  handle = null;
523
523
  }
524
524
  };
525
- function tick(t) {
525
+ function tick(t2) {
526
526
  handle = null;
527
527
  if (baseline) {
528
- last = t;
528
+ last = t2;
529
529
  baseline = false;
530
530
  }
531
- const dt = t - last;
532
- last = t;
531
+ const dt = t2 - last;
532
+ last = t2;
533
533
  elapsed += dt;
534
534
  let e = elapsed;
535
535
  const capped = durationMs != null && e >= durationMs;
@@ -712,7 +712,7 @@ function CaseSelector(props) {
712
712
  className,
713
713
  layout = "chips"
714
714
  } = props;
715
- const t = { ...TEXT[lang], ...text };
715
+ const t2 = { ...TEXT[lang], ...text };
716
716
  const baseId = useId();
717
717
  const param = typeof deepLink === "string" ? deepLink : "case";
718
718
  const linkPending = useRef(Boolean(deepLink));
@@ -735,8 +735,8 @@ function CaseSelector(props) {
735
735
  const modified = cases.find((c) => c.id === modifiedFromId) ?? null;
736
736
  return /* @__PURE__ */ jsxs("div", { className: `cs${className ? ` ${className}` : ""}`, role: "group", "aria-label": ariaLabel ?? "Case selector", children: [
737
737
  source && lanes.length > 1 && /* @__PURE__ */ jsxs("div", { className: "cs-source", children: [
738
- /* @__PURE__ */ jsx("span", { className: "cs-source-label", children: t.source }),
739
- /* @__PURE__ */ jsx("div", { className: "cs-source-tabs", role: "tablist", "aria-label": t.source, children: lanes.map((k) => /* @__PURE__ */ jsx(
738
+ /* @__PURE__ */ jsx("span", { className: "cs-source-label", children: t2.source }),
739
+ /* @__PURE__ */ jsx("div", { className: "cs-source-tabs", role: "tablist", "aria-label": t2.source, children: lanes.map((k) => /* @__PURE__ */ jsx(
740
740
  "button",
741
741
  {
742
742
  type: "button",
@@ -744,12 +744,12 @@ function CaseSelector(props) {
744
744
  "aria-selected": source === k,
745
745
  className: source === k ? "subtab active" : "subtab",
746
746
  onClick: () => onSourceChange?.(k),
747
- children: k === "synthetic" ? t.synthetic : k === "real" ? t.real : t.uploaded
747
+ children: k === "synthetic" ? t2.synthetic : k === "real" ? t2.real : t2.uploaded
748
748
  },
749
749
  k
750
750
  )) })
751
751
  ] }),
752
- source && source !== "synthetic" && /* @__PURE__ */ jsx("p", { className: "cs-locked banner", children: lockedNote ?? t.lockedNote }),
752
+ source && source !== "synthetic" && /* @__PURE__ */ jsx("p", { className: "cs-locked banner", children: lockedNote ?? t2.lockedNote }),
753
753
  layout === "select" && /* @__PURE__ */ jsx(
754
754
  "select",
755
755
  {
@@ -788,11 +788,11 @@ function CaseSelector(props) {
788
788
  ] }, g.category || "_")),
789
789
  modified && /* @__PURE__ */ jsxs("div", { className: "cs-modified", children: [
790
790
  /* @__PURE__ */ jsxs("span", { className: "badge accent", children: [
791
- t.modifiedPrefix,
791
+ t2.modifiedPrefix,
792
792
  " ",
793
793
  /* @__PURE__ */ jsx("strong", { children: modified.name })
794
794
  ] }),
795
- onResetToCanonical && /* @__PURE__ */ jsx("button", { type: "button", className: "cs-reset", onClick: onResetToCanonical, children: t.reset })
795
+ onResetToCanonical && /* @__PURE__ */ jsx("button", { type: "button", className: "cs-reset", onClick: onResetToCanonical, children: t2.reset })
796
796
  ] })
797
797
  ] });
798
798
  }
@@ -957,7 +957,7 @@ function Tabs({ tabs, initial, value, onChange, ariaLabel }) {
957
957
  document.getElementById(`${baseId}-tab-${target.id}`)?.focus();
958
958
  }
959
959
  }
960
- const current = tabs.find((t) => t.id === active) ?? tabs[0];
960
+ const current = tabs.find((t2) => t2.id === active) ?? tabs[0];
961
961
  return /* @__PURE__ */ jsxs("div", { className: "tabs", children: [
962
962
  /* @__PURE__ */ jsx("div", { className: "tablist", role: "tablist", "aria-label": ariaLabel, ref: rowRef, children: tabs.map((tab, idx) => {
963
963
  const selected = tab.id === current?.id;
@@ -1025,7 +1025,7 @@ function SubTabs({ tabs, initial, value, onChange, ariaLabel, orientation = "hor
1025
1025
  document.getElementById(`${baseId}-subtab-${target.id}`)?.focus();
1026
1026
  }
1027
1027
  }
1028
- const current = tabs.find((t) => t.id === active) ?? tabs[0];
1028
+ const current = tabs.find((t2) => t2.id === active) ?? tabs[0];
1029
1029
  return /* @__PURE__ */ jsxs("div", { className: vertical ? "subtabs subtabs-vertical" : "subtabs", children: [
1030
1030
  /* @__PURE__ */ jsx(
1031
1031
  "div",
@@ -1076,7 +1076,7 @@ function TabGroups({ groups, value, onChange, ariaLabel }) {
1076
1076
  const [own, setOwn] = useState({ group: groups[0]?.id ?? "" });
1077
1077
  const sel = value ?? own;
1078
1078
  const group = groups.find((g) => g.id === sel.group) ?? groups[0];
1079
- const tabOf = (g, wanted) => g.tabs.find((t) => t.id === wanted)?.id ?? g.tabs[0]?.id ?? "";
1079
+ const tabOf = (g, wanted) => g.tabs.find((t2) => t2.id === wanted)?.id ?? g.tabs[0]?.id ?? "";
1080
1080
  function set(next) {
1081
1081
  if (value === void 0) setOwn(next);
1082
1082
  onChange?.(next);
@@ -1137,7 +1137,7 @@ function Figure({ caption, children }) {
1137
1137
  ] });
1138
1138
  }
1139
1139
  var DOC_AREAS = {
1140
- "/introduction": ["initiative", "outcomes", "positioning", "credibility", "problem", "principles", "math", "pipeline", "honesty"],
1140
+ "/introduction": ["problem", "principles", "math", "pipeline", "honesty"],
1141
1141
  "/methodology": ["method"],
1142
1142
  "/implementation": ["architecture", "reproducibility", "engine", "lanes", "contract", "deployment"],
1143
1143
  "/experiments": ["question", "metrics", "protocol", "datasets"],
@@ -1206,12 +1206,498 @@ function Stat({ value, unit, source }) {
1206
1206
  ] })
1207
1207
  ] });
1208
1208
  }
1209
+
1210
+ // src/content/executive.schema.json
1211
+ var executive_schema_default = {
1212
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1213
+ $id: "https://github.com/fsantibanezleal/CAOS_APP_SHELL/blob/main/src/content/executive.schema.json",
1214
+ title: "CAOS executive view data, version 1.0.0",
1215
+ description: "The one data file a CAOS product fills for the executive view of its Introduction (content/executive.json). Every text is { en, es }; nothing outside these fields is allowed. The writing limits (30 words per sentence, an answer of at most 2 sentences, one sentence for initiative, vision, statement, exec_problem and caption, no equation, no inline citation), the four_cs rule (absent until FOUR_CS names the 4 C's) and the sources-by-field rule are checked by validateExecutive in executive.ts, on top of this structure.",
1216
+ type: "object",
1217
+ additionalProperties: false,
1218
+ required: ["executive", "organisation", "initiative", "why_now", "vision", "outcomes", "dialogue", "illustrations", "sources"],
1219
+ properties: {
1220
+ executive: { $ref: "#/$defs/text", description: "One C-suite role, never a list." },
1221
+ organisation: { $ref: "#/$defs/text", description: "One industry and one context, never several regions." },
1222
+ initiative: { $ref: "#/$defs/text", description: "One sentence: what that executive owns and must achieve." },
1223
+ why_now: {
1224
+ type: "object",
1225
+ additionalProperties: false,
1226
+ required: ["figure", "deadline"],
1227
+ properties: {
1228
+ figure: { $ref: "#/$defs/figure" },
1229
+ deadline: { $ref: "#/$defs/text", description: "One date or deadline, for example 'by 1 December 2026'." }
1230
+ }
1231
+ },
1232
+ vision: { $ref: "#/$defs/text", description: "One sentence: what changes for the executive's business. Comes first in section 2." },
1233
+ outcomes: {
1234
+ type: "array",
1235
+ minItems: 3,
1236
+ maxItems: 5,
1237
+ items: {
1238
+ type: "object",
1239
+ additionalProperties: false,
1240
+ required: ["capability", "outcome", "proof"],
1241
+ properties: {
1242
+ capability: { $ref: "#/$defs/text", description: "What the product does, in plain words." },
1243
+ outcome: { $ref: "#/$defs/text", description: "The business result, non-technical." },
1244
+ proof: {
1245
+ type: "object",
1246
+ additionalProperties: false,
1247
+ required: ["value", "unit", "statement"],
1248
+ properties: {
1249
+ value: { $ref: "#/$defs/text" },
1250
+ unit: { $ref: "#/$defs/text" },
1251
+ statement: { $ref: "#/$defs/text", description: "A one-line statement of the proof point." }
1252
+ }
1253
+ }
1254
+ }
1255
+ }
1256
+ },
1257
+ four_cs: {
1258
+ type: "array",
1259
+ minItems: 4,
1260
+ maxItems: 4,
1261
+ description: "Exactly 4 rows in the owner's order. Absent while FOUR_CS is empty; required, with c equal to the name, once it holds 4 names.",
1262
+ items: {
1263
+ type: "object",
1264
+ additionalProperties: false,
1265
+ required: ["c", "exec_problem"],
1266
+ properties: {
1267
+ c: { $ref: "#/$defs/text" },
1268
+ exec_problem: { $ref: "#/$defs/text", description: "One sentence tying the C to this executive's problem." }
1269
+ }
1270
+ }
1271
+ },
1272
+ dialogue: {
1273
+ type: "array",
1274
+ minItems: 3,
1275
+ maxItems: 5,
1276
+ items: {
1277
+ type: "object",
1278
+ additionalProperties: false,
1279
+ required: ["question", "answer"],
1280
+ properties: {
1281
+ question: { $ref: "#/$defs/text", description: "A business question that executive asks." },
1282
+ answer: { $ref: "#/$defs/text", description: "At most 2 sentences." }
1283
+ }
1284
+ }
1285
+ },
1286
+ illustrations: {
1287
+ type: "object",
1288
+ additionalProperties: false,
1289
+ required: ["initiative", "problem", "solution"],
1290
+ properties: {
1291
+ initiative: { $ref: "#/$defs/illustration" },
1292
+ problem: { $ref: "#/$defs/illustration" },
1293
+ solution: { $ref: "#/$defs/illustration" }
1294
+ }
1295
+ },
1296
+ sources: {
1297
+ type: "array",
1298
+ minItems: 1,
1299
+ description: "The source of every figure (why_now.figure and each outcomes[i].proof), by field path; shown as numbered notes, never inline.",
1300
+ items: {
1301
+ type: "object",
1302
+ additionalProperties: false,
1303
+ required: ["field", "source"],
1304
+ properties: {
1305
+ field: { type: "string", minLength: 1 },
1306
+ source: { $ref: "#/$defs/text" }
1307
+ }
1308
+ }
1309
+ }
1310
+ },
1311
+ $defs: {
1312
+ text: {
1313
+ type: "object",
1314
+ additionalProperties: false,
1315
+ required: ["en", "es"],
1316
+ properties: {
1317
+ en: { type: "string", minLength: 1 },
1318
+ es: { type: "string", minLength: 1 }
1319
+ }
1320
+ },
1321
+ figure: {
1322
+ type: "object",
1323
+ additionalProperties: false,
1324
+ required: ["value", "unit"],
1325
+ properties: {
1326
+ value: { $ref: "#/$defs/text" },
1327
+ unit: { $ref: "#/$defs/text" }
1328
+ }
1329
+ },
1330
+ illustration: {
1331
+ type: "object",
1332
+ additionalProperties: false,
1333
+ required: ["file", "caption"],
1334
+ properties: {
1335
+ file: {
1336
+ description: "The inline SVG: one path, or one path per language.",
1337
+ anyOf: [
1338
+ { type: "string", minLength: 1 },
1339
+ {
1340
+ type: "object",
1341
+ additionalProperties: false,
1342
+ required: ["en", "es"],
1343
+ properties: { en: { type: "string", minLength: 1 }, es: { type: "string", minLength: 1 } }
1344
+ }
1345
+ ]
1346
+ },
1347
+ caption: { $ref: "#/$defs/text", description: "One sentence saying what the reader should take from the illustration." }
1348
+ }
1349
+ }
1350
+ }
1351
+ };
1352
+
1353
+ // src/content/executive.ts
1354
+ var EXECUTIVE_SCHEMA_VERSION = "1.0.0";
1355
+ var FOUR_CS = [];
1356
+ var EXEC_LIMITS = {
1357
+ maxWords: 30,
1358
+ maxAnswerSentences: 2,
1359
+ /** An equation or a TeX marker: a dollar sign, `\(`, `\[` or a backslash command. */
1360
+ equation: /\$|\\\(|\\\[|\\[a-zA-Z]+/,
1361
+ /** An inline citation: `(Source`, `[1]`, `(ECB`, or a parenthesised author-year such as `(Smith et al., 2019)`. */
1362
+ citations: [/\(\s*Source/i, /\[\d+\]/, /\(\s*ECB/, /\(\w[^()]*\d{4}\)/]};
1363
+ function sentencesOf(text) {
1364
+ return text.split(/(?<=[.?!])\s+/).map((s) => s.trim()).filter(Boolean);
1365
+ }
1366
+ function wordsIn(text) {
1367
+ return text.split(/\s+/).filter((w) => /[\p{L}\p{N}]/u.test(w)).length;
1368
+ }
1369
+ var ROOT = executive_schema_default;
1370
+ var typeOf = (v) => v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
1371
+ var join = (base, key) => base ? `${base}.${key}` : key;
1372
+ function resolve(node) {
1373
+ if (typeof node.$ref !== "string") return node;
1374
+ const name = node.$ref.replace("#/$defs/", "");
1375
+ return { ...ROOT.$defs[name], ...node.description ? { description: node.description } : {} };
1376
+ }
1377
+ function check(value, rawNode, path, out) {
1378
+ const node = resolve(rawNode);
1379
+ if (node.anyOf) {
1380
+ const ok = node.anyOf.some((alt) => {
1381
+ const sub = [];
1382
+ check(value, alt, path, sub);
1383
+ return sub.length === 0;
1384
+ });
1385
+ if (!ok) out.push({ path, message: `matches none of the allowed forms (${node.anyOf.map((a) => resolve(a).type).join(" or ")})` });
1386
+ return;
1387
+ }
1388
+ const t2 = typeOf(value);
1389
+ if (node.type && t2 !== node.type) {
1390
+ out.push({ path, message: `must be ${node.type === "object" ? "an object" : node.type === "array" ? "an array" : `a ${node.type}`}, not ${t2 === "undefined" ? "missing" : t2 === "array" ? "an array" : t2 === "object" ? "an object" : `a ${t2}`}` });
1391
+ return;
1392
+ }
1393
+ if (node.type === "string" && typeof value === "string" && node.minLength && value.trim().length < node.minLength) {
1394
+ out.push({ path, message: "must not be empty" });
1395
+ }
1396
+ if (node.type === "array") {
1397
+ const list = value;
1398
+ if (node.minItems !== void 0 && list.length < node.minItems) out.push({ path, message: `needs at least ${node.minItems} item(s), has ${list.length}` });
1399
+ if (node.maxItems !== void 0 && list.length > node.maxItems) out.push({ path, message: `allows at most ${node.maxItems} item(s), has ${list.length}` });
1400
+ if (node.items) list.forEach((item, i) => check(item, node.items, `${path}[${i}]`, out));
1401
+ }
1402
+ if (node.type === "object") {
1403
+ const obj = value;
1404
+ for (const key of node.required ?? []) {
1405
+ if (!(key in obj) || obj[key] === void 0) out.push({ path: join(path, key), message: "is required and missing" });
1406
+ }
1407
+ const props = node.properties ?? {};
1408
+ for (const key of Object.keys(obj)) {
1409
+ if (props[key]) check(obj[key], props[key], join(path, key), out);
1410
+ else if (node.additionalProperties === false) out.push({ path: join(path, key), message: "is not a field of the executive view (nothing else is allowed)" });
1411
+ }
1412
+ }
1413
+ }
1414
+ function textFields(d) {
1415
+ const out = [
1416
+ { path: "executive", text: d.executive },
1417
+ { path: "organisation", text: d.organisation },
1418
+ { path: "initiative", text: d.initiative, sentences: 1 },
1419
+ { path: "why_now.figure.value", text: d.why_now.figure.value },
1420
+ { path: "why_now.figure.unit", text: d.why_now.figure.unit },
1421
+ { path: "why_now.deadline", text: d.why_now.deadline },
1422
+ { path: "vision", text: d.vision, sentences: 1 }
1423
+ ];
1424
+ d.outcomes.forEach((o, i) => {
1425
+ out.push({ path: `outcomes[${i}].capability`, text: o.capability }, { path: `outcomes[${i}].outcome`, text: o.outcome });
1426
+ out.push({ path: `outcomes[${i}].proof.value`, text: o.proof.value }, { path: `outcomes[${i}].proof.unit`, text: o.proof.unit }, { path: `outcomes[${i}].proof.statement`, text: o.proof.statement, sentences: 1 });
1427
+ });
1428
+ (d.four_cs ?? []).forEach((r, i) => out.push({ path: `four_cs[${i}].c`, text: r.c }, { path: `four_cs[${i}].exec_problem`, text: r.exec_problem, sentences: 1 }));
1429
+ d.dialogue.forEach((q, i) => out.push({ path: `dialogue[${i}].question`, text: q.question }, { path: `dialogue[${i}].answer`, text: q.answer, sentences: EXEC_LIMITS.maxAnswerSentences }));
1430
+ for (const name of ["initiative", "problem", "solution"]) out.push({ path: `illustrations.${name}.caption`, text: d.illustrations[name].caption, sentences: 1 });
1431
+ return out;
1432
+ }
1433
+ function figureFields(d) {
1434
+ return ["why_now.figure", ...d.outcomes.map((_, i) => `outcomes[${i}].proof`)];
1435
+ }
1436
+ function writingProblems(text, maxSentences) {
1437
+ const out = [];
1438
+ const sentences = sentencesOf(text);
1439
+ for (const s of sentences) {
1440
+ const n = wordsIn(s);
1441
+ if (n > EXEC_LIMITS.maxWords) out.push(`a sentence of ${n} words; the limit is ${EXEC_LIMITS.maxWords}`);
1442
+ }
1443
+ if (maxSentences !== void 0 && sentences.length > maxSentences) {
1444
+ out.push(maxSentences === 1 ? `must be one sentence, has ${sentences.length}` : `has ${sentences.length} sentences; the limit is ${maxSentences}`);
1445
+ }
1446
+ if (EXEC_LIMITS.equation.test(text)) out.push("holds an equation or a TeX marker; the executive view holds none");
1447
+ if (EXEC_LIMITS.citations.some((re) => re.test(text))) out.push('holds an inline citation; give the source in "sources"');
1448
+ return out;
1449
+ }
1450
+ function validateExecutive(data, opts = {}) {
1451
+ const fourCs = opts.fourCs ?? FOUR_CS;
1452
+ const out = [];
1453
+ const root = { ...ROOT, required: ROOT.required.filter((k) => k !== "four_cs") };
1454
+ check(data, root, "", out);
1455
+ const structural = out.length;
1456
+ const d = data;
1457
+ if (d && typeof d === "object" && !Array.isArray(d)) {
1458
+ if (fourCs.length === 0) {
1459
+ if ("four_cs" in d) out.push({ path: "four_cs", message: "is not allowed yet: the 4 C's are not named (FOUR_CS is empty), so the view shows section 3 as pending" });
1460
+ } else if (!("four_cs" in d)) {
1461
+ out.push({ path: "four_cs", message: `is required: the 4 C's are named (${fourCs.join(", ")})` });
1462
+ } else {
1463
+ const rows = Array.isArray(d.four_cs) ? d.four_cs : [];
1464
+ if (rows.length === 4) {
1465
+ rows.forEach((r, i) => {
1466
+ if (r?.c && r.c.en !== fourCs[i]) out.push({ path: `four_cs[${i}].c`, message: `must be "${fourCs[i]}" (the ${i + 1}${["st", "nd", "rd", "th"][i]} C, in the owner's order), not "${r.c.en}"` });
1467
+ });
1468
+ }
1469
+ }
1470
+ }
1471
+ if (structural > 0) return out;
1472
+ if (!d || typeof d !== "object") return out;
1473
+ const full = d;
1474
+ for (const f of textFields(full)) {
1475
+ for (const lang of ["en", "es"]) {
1476
+ const text = f.text?.[lang];
1477
+ if (typeof text !== "string") continue;
1478
+ for (const m of writingProblems(text, f.sentences)) out.push({ path: `${f.path}.${lang}`, message: m });
1479
+ }
1480
+ }
1481
+ const wanted = figureFields(full);
1482
+ const seen = /* @__PURE__ */ new Set();
1483
+ full.sources.forEach((s, i) => {
1484
+ if (!wanted.includes(s.field)) out.push({ path: `sources[${i}].field`, message: `"${s.field}" is not a figure of this view (the figures are ${wanted.join(", ")})` });
1485
+ else if (seen.has(s.field)) out.push({ path: `sources[${i}].field`, message: `"${s.field}" already has a source` });
1486
+ seen.add(s.field);
1487
+ });
1488
+ const missing = wanted.filter((f) => !seen.has(f));
1489
+ if (missing.length > 0) out.push({ path: "sources", message: `no source for ${missing.join(", ")}` });
1490
+ return out;
1491
+ }
1492
+ var SECTION_TITLES = [
1493
+ { en: "Industry & Exec Tailoring", es: "Industria y foco ejecutivo" },
1494
+ { en: "AI Transformation Story", es: "Historia de transformaci\xF3n con IA" },
1495
+ { en: "4Cs Positioning", es: "Posicionamiento 4C" },
1496
+ { en: "Delivery & Credibility", es: "Entrega y credibilidad" }
1497
+ ];
1498
+ var SECTION_QUESTIONS = [
1499
+ { en: "Built for a C-suite exec?", es: "\xBFPensado para un ejecutivo de primer nivel?" },
1500
+ { en: "Outcomes, not a feature tour", es: "Resultados, no un recorrido de funciones" },
1501
+ { en: "Value story, not features dump", es: "Historia de valor, no lista de funciones" },
1502
+ { en: "Trust them in front of a CxO?", es: "\xBFConfiar\xEDa en ellos frente a un ejecutivo?" }
1503
+ ];
1504
+ var PENDING_FOUR_CS = {
1505
+ en: "Pending: the 4 C's are defined by the product owner",
1506
+ es: "Pendiente: las 4 C las define el responsable del producto"
1507
+ };
1209
1508
  function Question({ question, answer }) {
1210
1509
  return /* @__PURE__ */ jsxs("div", { className: "caos-qa", "data-qa": "", children: [
1211
1510
  /* @__PURE__ */ jsx("p", { className: "caos-qa-question", "data-question": "", children: question }),
1212
1511
  /* @__PURE__ */ jsx("div", { className: "caos-qa-answer", "data-answer": "", children: answer })
1213
1512
  ] });
1214
1513
  }
1514
+ var UI = {
1515
+ executive: { en: "Executive", es: "Ejecutivo" },
1516
+ organisation: { en: "Organisation", es: "Organizaci\xF3n" },
1517
+ whyNow: { en: "Why now", es: "Por qu\xE9 ahora" },
1518
+ does: { en: "What it does", es: "Qu\xE9 hace" },
1519
+ result: { en: "Business result", es: "Resultado de negocio" },
1520
+ proof: { en: "Proof", es: "Prueba" },
1521
+ sources: { en: "Sources", es: "Fuentes" },
1522
+ source: { en: "Source", es: "Fuente" },
1523
+ errorTitle: { en: "The executive view data is not valid", es: "Los datos de la vista ejecutiva no son v\xE1lidos" },
1524
+ errorLead: {
1525
+ en: "Fix content/executive.json against executive.schema.json; the view shows nothing until it is valid.",
1526
+ es: "Corrija content/executive.json seg\xFAn executive.schema.json; la vista no muestra nada hasta que sea v\xE1lido."
1527
+ },
1528
+ loading: { en: "Loading the illustration", es: "Cargando la ilustraci\xF3n" },
1529
+ missing: { en: "The illustration file did not load", es: "No carg\xF3 el archivo de la ilustraci\xF3n" }
1530
+ };
1531
+ var t = (text, lang) => text[lang];
1532
+ function cleanSvg(text) {
1533
+ const doc = new DOMParser().parseFromString(text, "image/svg+xml");
1534
+ const root = doc.documentElement;
1535
+ if (!root || root.localName !== "svg" || doc.querySelector("parsererror")) return null;
1536
+ for (const bad of Array.from(doc.querySelectorAll("script, foreignObject"))) bad.remove();
1537
+ for (const el of Array.from(doc.querySelectorAll("*"))) {
1538
+ for (const attr of Array.from(el.attributes)) {
1539
+ if (/^on/i.test(attr.name) || /^(xlink:)?href$/i.test(attr.name) && /^\s*javascript:/i.test(attr.value)) el.removeAttribute(attr.name);
1540
+ }
1541
+ }
1542
+ root.removeAttribute("width");
1543
+ root.removeAttribute("height");
1544
+ if (!root.getAttribute("viewBox")) return null;
1545
+ if (!root.getAttribute("role")) root.setAttribute("role", "img");
1546
+ return new XMLSerializer().serializeToString(root);
1547
+ }
1548
+ function Illustration({ name, spec, base, lang }) {
1549
+ const file = typeof spec.file === "string" ? spec.file : spec.file[lang];
1550
+ const url = /^([a-z]+:)?\/\//i.test(file) || file.startsWith("/") ? file : `${base}${file}`;
1551
+ const [loaded, setLoaded] = useState({ status: "loading" });
1552
+ useEffect(() => {
1553
+ let live = true;
1554
+ setLoaded({ status: "loading" });
1555
+ fetch(url).then((r) => {
1556
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
1557
+ return r.text();
1558
+ }).then((text) => {
1559
+ const svg = cleanSvg(text);
1560
+ if (!svg) throw new Error("not an SVG document with a viewBox");
1561
+ if (live) setLoaded({ status: "ready", svg });
1562
+ }).catch((e) => {
1563
+ if (live) setLoaded({ status: "error", why: e.message });
1564
+ });
1565
+ return () => {
1566
+ live = false;
1567
+ };
1568
+ }, [url]);
1569
+ return /* @__PURE__ */ jsxs(
1570
+ "figure",
1571
+ {
1572
+ className: "figure caos-exec-fig",
1573
+ "data-exec-illustration": name,
1574
+ "data-lang": lang,
1575
+ "data-exec-file": file,
1576
+ "data-state": loaded.status === "ready" ? void 0 : loaded.status,
1577
+ children: [
1578
+ loaded.status === "ready" ? /* @__PURE__ */ jsx("div", { className: "caos-exec-art", dangerouslySetInnerHTML: { __html: loaded.svg } }) : loaded.status === "error" ? /* @__PURE__ */ jsxs("p", { className: "caos-exec-fig-error", role: "alert", children: [
1579
+ t(UI.missing, lang),
1580
+ ": ",
1581
+ /* @__PURE__ */ jsx("code", { children: file }),
1582
+ " (",
1583
+ loaded.why,
1584
+ ")"
1585
+ ] }) : /* @__PURE__ */ jsx("div", { className: "caos-exec-art caos-exec-art-wait", "aria-busy": "true", "aria-label": t(UI.loading, lang) }),
1586
+ /* @__PURE__ */ jsx("figcaption", { className: "figure-caption", "data-exec-field": `illustrations.${name}.caption`, children: t(spec.caption, lang) })
1587
+ ]
1588
+ }
1589
+ );
1590
+ }
1591
+ var Label = ({ children }) => /* @__PURE__ */ jsx("span", { className: "caos-exec-label", children });
1592
+ function Section({ n, lang, children }) {
1593
+ return /* @__PURE__ */ jsxs("section", { className: "caos-exec-section", "data-exec-section": n, "aria-label": t(SECTION_TITLES[n - 1], lang), children: [
1594
+ /* @__PURE__ */ jsx("h2", { children: t(SECTION_TITLES[n - 1], lang) }),
1595
+ /* @__PURE__ */ jsx("p", { className: "caos-exec-question", "data-exec-question": "", children: t(SECTION_QUESTIONS[n - 1], lang) }),
1596
+ children
1597
+ ] });
1598
+ }
1599
+ function ExecutiveView({ data, base }) {
1600
+ return /* @__PURE__ */ jsx(ExecutiveViewBody, { data, base, fourCs: FOUR_CS });
1601
+ }
1602
+ function ExecutiveViewBody({ data, base = "/", fourCs, lang: forced }) {
1603
+ const stored = useShellLang();
1604
+ const lang = forced ?? stored;
1605
+ const problems = validateExecutive(data, { fourCs });
1606
+ if (problems.length > 0) {
1607
+ return /* @__PURE__ */ jsxs(
1608
+ "div",
1609
+ {
1610
+ className: "caos-exec caos-exec-error",
1611
+ "data-executive-view": "",
1612
+ "data-executive-schema": EXECUTIVE_SCHEMA_VERSION,
1613
+ "data-executive-valid": "false",
1614
+ "data-executive-errors": problems.map((p) => `${p.path || "(file)"}: ${p.message}`).join(" | "),
1615
+ "data-state": "error",
1616
+ role: "alert",
1617
+ children: [
1618
+ /* @__PURE__ */ jsx("h2", { children: t(UI.errorTitle, lang) }),
1619
+ /* @__PURE__ */ jsx("p", { children: t(UI.errorLead, lang) }),
1620
+ /* @__PURE__ */ jsx("ul", { children: problems.map((p, i) => /* @__PURE__ */ jsxs("li", { children: [
1621
+ /* @__PURE__ */ jsx("code", { children: p.path || "(file)" }),
1622
+ ": ",
1623
+ p.message
1624
+ ] }, i)) })
1625
+ ]
1626
+ }
1627
+ );
1628
+ }
1629
+ const d = data;
1630
+ const figures = figureFields(d);
1631
+ const note = (field2) => figures.indexOf(field2) + 1;
1632
+ const sourceOf = (field2) => d.sources.find((s) => s.field === field2);
1633
+ const Cite2 = ({ field: field2 }) => /* @__PURE__ */ jsx("sup", { className: "caos-exec-cite", children: /* @__PURE__ */ jsx("a", { href: `#exec-note-${note(field2)}`, "aria-label": `${t(UI.source, lang)} ${note(field2)}`, children: note(field2) }) });
1634
+ const field = (path, text) => /* @__PURE__ */ jsx("span", { "data-exec-field": path, children: t(text, lang) });
1635
+ return /* @__PURE__ */ jsxs("div", { className: "caos-exec", "data-executive-view": "", "data-executive-schema": EXECUTIVE_SCHEMA_VERSION, "data-executive-valid": "true", children: [
1636
+ /* @__PURE__ */ jsxs(Section, { n: 1, lang, children: [
1637
+ /* @__PURE__ */ jsxs("dl", { className: "caos-exec-facts", children: [
1638
+ /* @__PURE__ */ jsxs("div", { children: [
1639
+ /* @__PURE__ */ jsx("dt", { children: t(UI.executive, lang) }),
1640
+ /* @__PURE__ */ jsx("dd", { "data-exec-field": "executive", children: t(d.executive, lang) })
1641
+ ] }),
1642
+ /* @__PURE__ */ jsxs("div", { children: [
1643
+ /* @__PURE__ */ jsx("dt", { children: t(UI.organisation, lang) }),
1644
+ /* @__PURE__ */ jsx("dd", { "data-exec-field": "organisation", children: t(d.organisation, lang) })
1645
+ ] })
1646
+ ] }),
1647
+ /* @__PURE__ */ jsx("p", { className: "caos-exec-initiative", "data-exec-field": "initiative", children: t(d.initiative, lang) }),
1648
+ /* @__PURE__ */ jsx(Illustration, { name: "initiative", spec: d.illustrations.initiative, base, lang }),
1649
+ /* @__PURE__ */ jsxs("p", { className: "caos-exec-whynow", "data-exec-line": "why_now", children: [
1650
+ /* @__PURE__ */ jsx(Label, { children: t(UI.whyNow, lang) }),
1651
+ " ",
1652
+ /* @__PURE__ */ jsx("strong", { className: "caos-exec-value", "data-exec-field": "why_now.figure.value", children: t(d.why_now.figure.value, lang) }),
1653
+ " ",
1654
+ field("why_now.figure.unit", d.why_now.figure.unit),
1655
+ " ",
1656
+ /* @__PURE__ */ jsx("span", { className: "caos-exec-sep", children: "\xB7" }),
1657
+ " ",
1658
+ field("why_now.deadline", d.why_now.deadline),
1659
+ /* @__PURE__ */ jsx(Cite2, { field: "why_now.figure" })
1660
+ ] }),
1661
+ /* @__PURE__ */ jsx(Illustration, { name: "problem", spec: d.illustrations.problem, base, lang })
1662
+ ] }),
1663
+ /* @__PURE__ */ jsxs(Section, { n: 2, lang, children: [
1664
+ /* @__PURE__ */ jsx("p", { className: "caos-exec-vision", "data-exec-field": "vision", children: t(d.vision, lang) }),
1665
+ /* @__PURE__ */ jsx(Illustration, { name: "solution", spec: d.illustrations.solution, base, lang }),
1666
+ /* @__PURE__ */ jsx("ul", { className: "caos-exec-outcomes", children: d.outcomes.map((o, i) => /* @__PURE__ */ jsxs("li", { className: "caos-exec-outcome", "data-exec-outcome": i, children: [
1667
+ /* @__PURE__ */ jsxs("div", { children: [
1668
+ /* @__PURE__ */ jsx(Label, { children: t(UI.does, lang) }),
1669
+ " ",
1670
+ field(`outcomes[${i}].capability`, o.capability)
1671
+ ] }),
1672
+ /* @__PURE__ */ jsxs("div", { children: [
1673
+ /* @__PURE__ */ jsx(Label, { children: t(UI.result, lang) }),
1674
+ " ",
1675
+ field(`outcomes[${i}].outcome`, o.outcome)
1676
+ ] }),
1677
+ /* @__PURE__ */ jsxs("div", { className: "caos-exec-proof", children: [
1678
+ /* @__PURE__ */ jsx(Label, { children: t(UI.proof, lang) }),
1679
+ " ",
1680
+ /* @__PURE__ */ jsx("strong", { className: "caos-exec-value", "data-exec-field": `outcomes[${i}].proof.value`, children: t(o.proof.value, lang) }),
1681
+ " ",
1682
+ field(`outcomes[${i}].proof.unit`, o.proof.unit),
1683
+ ". ",
1684
+ field(`outcomes[${i}].proof.statement`, o.proof.statement),
1685
+ /* @__PURE__ */ jsx(Cite2, { field: `outcomes[${i}].proof` })
1686
+ ] })
1687
+ ] }, i)) })
1688
+ ] }),
1689
+ /* @__PURE__ */ jsx(Section, { n: 3, lang, children: fourCs.length === 0 ? /* @__PURE__ */ jsx("p", { className: "caos-exec-pending", "data-state": "unavailable", "data-exec-pending": "", children: t(PENDING_FOUR_CS, lang) }) : /* @__PURE__ */ jsx("ul", { className: "caos-exec-cs", children: d.four_cs.map((r, i) => /* @__PURE__ */ jsxs("li", { "data-exec-c": i, children: [
1690
+ /* @__PURE__ */ jsx("strong", { "data-exec-field": `four_cs[${i}].c`, children: t(r.c, lang) }),
1691
+ " ",
1692
+ field(`four_cs[${i}].exec_problem`, r.exec_problem)
1693
+ ] }, i)) }) }),
1694
+ /* @__PURE__ */ jsx(Section, { n: 4, lang, children: d.dialogue.map((q, i) => /* @__PURE__ */ jsx(Question, { question: field(`dialogue[${i}].question`, q.question), answer: /* @__PURE__ */ jsx("p", { children: field(`dialogue[${i}].answer`, q.answer) }) }, i)) }),
1695
+ /* @__PURE__ */ jsxs("aside", { className: "caos-exec-notes-wrap", "aria-label": t(UI.sources, lang), children: [
1696
+ /* @__PURE__ */ jsx("h3", { className: "caos-exec-notes-title", children: t(UI.sources, lang) }),
1697
+ /* @__PURE__ */ jsx("ol", { className: "caos-exec-notes", "data-exec-notes": "", children: figures.map((f, i) => /* @__PURE__ */ jsx("li", { id: `exec-note-${i + 1}`, children: t(sourceOf(f).source, lang) }, f)) })
1698
+ ] })
1699
+ ] });
1700
+ }
1215
1701
  function replaceQueryParam(param, value) {
1216
1702
  if (typeof window === "undefined") return;
1217
1703
  const next = withCaseParam(window.location.search, value, param);
@@ -1236,7 +1722,7 @@ function viewParamOf(option) {
1236
1722
  }
1237
1723
  function SurfacePage({ title, lede, actions, tabs, value, onChange, deepLinkView = true, ariaLabel, instrument, children }) {
1238
1724
  const lang = useShellLang();
1239
- const [open, select] = useUrlView((tabs ?? []).map((t) => t.id), tabs ? viewParamOf(deepLinkView) : null, value, onChange);
1725
+ const [open, select] = useUrlView((tabs ?? []).map((t2) => t2.id), tabs ? viewParamOf(deepLinkView) : null, value, onChange);
1240
1726
  const head = title !== void 0 || lede !== void 0 || actions !== void 0;
1241
1727
  return /* @__PURE__ */ jsxs("div", { className: "page-body wide caos-surface", "data-surface": "", children: [
1242
1728
  head && /* @__PURE__ */ jsxs("div", { className: "caos-surface-head", children: [
@@ -1388,9 +1874,9 @@ function BarChart({ title, data, axis, orientation = "horizontal", values = true
1388
1874
  const barH = Math.min(rowH * 0.5, 40);
1389
1875
  drawing = /* @__PURE__ */ jsxs("svg", { width, height: drawnHeight, role: "img", "aria-label": name, "data-chart": "", "data-chart-kind": "bars", children: [
1390
1876
  /* @__PURE__ */ jsx("title", { children: name }),
1391
- ticks.map((t, i) => /* @__PURE__ */ jsxs("g", { children: [
1392
- /* @__PURE__ */ jsx("line", { x1: sx(t), x2: sx(t), y1: top, y2: plotBottom, stroke: "var(--color-border)", strokeWidth: t === 0 ? 1.4 : 1 }),
1393
- /* @__PURE__ */ jsx("text", { x: sx(t), y: plotBottom + 6 + LINE - 2, textAnchor: i === 0 && sx(t) - textWidth(tickLabels[i], PX) / 2 < 0 ? "start" : i === ticks.length - 1 && sx(t) + textWidth(tickLabels[i], PX) / 2 > width ? "end" : "middle", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
1877
+ ticks.map((t2, i) => /* @__PURE__ */ jsxs("g", { children: [
1878
+ /* @__PURE__ */ jsx("line", { x1: sx(t2), x2: sx(t2), y1: top, y2: plotBottom, stroke: "var(--color-border)", strokeWidth: t2 === 0 ? 1.4 : 1 }),
1879
+ /* @__PURE__ */ jsx("text", { x: sx(t2), y: plotBottom + 6 + LINE - 2, textAnchor: i === 0 && sx(t2) - textWidth(tickLabels[i], PX) / 2 < 0 ? "start" : i === ticks.length - 1 && sx(t2) + textWidth(tickLabels[i], PX) / 2 > width ? "end" : "middle", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
1394
1880
  ] }, `t${i}`)),
1395
1881
  /* @__PURE__ */ jsx("text", { x: x0 + (x1 - x0) / 2, y: plotBottom + 6 + LINE + 4 + LINE - 2, textAnchor: "middle", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: axisTitle }),
1396
1882
  data.map((d, i) => {
@@ -1444,9 +1930,9 @@ function BarChart({ title, data, axis, orientation = "horizontal", values = true
1444
1930
  drawing = /* @__PURE__ */ jsxs("svg", { width, height: h, role: "img", "aria-label": name, "data-chart": "", "data-chart-kind": "bars", children: [
1445
1931
  /* @__PURE__ */ jsx("title", { children: name }),
1446
1932
  /* @__PURE__ */ jsx("text", { x: 0, y: LINE - 2, textAnchor: "start", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: axisTitle }),
1447
- ticks.map((t, i) => /* @__PURE__ */ jsxs("g", { children: [
1448
- /* @__PURE__ */ jsx("line", { x1: left, x2: width - right, y1: sy(t), y2: sy(t), stroke: "var(--color-border)", strokeWidth: t === 0 ? 1.4 : 1 }),
1449
- /* @__PURE__ */ jsx("text", { x: left - 6, y: sy(t) + 4, textAnchor: "end", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
1933
+ ticks.map((t2, i) => /* @__PURE__ */ jsxs("g", { children: [
1934
+ /* @__PURE__ */ jsx("line", { x1: left, x2: width - right, y1: sy(t2), y2: sy(t2), stroke: "var(--color-border)", strokeWidth: t2 === 0 ? 1.4 : 1 }),
1935
+ /* @__PURE__ */ jsx("text", { x: left - 6, y: sy(t2) + 4, textAnchor: "end", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
1450
1936
  ] }, `t${i}`)),
1451
1937
  data.map((d, i) => {
1452
1938
  const cx = left + band * i + band / 2;
@@ -1637,7 +2123,7 @@ function CaseWorkbench(props) {
1637
2123
  `CaseWorkbench: ${tabs.length} groups; at most ${MAX_WORKBENCH_GROUPS} peers, then group by question (ADR-0071 rule 5)`
1638
2124
  );
1639
2125
  }
1640
- const [openGroup, selectGroup] = useUrlView(tabs.map((t) => t.id), viewParamOf(deepLinkView), group, onGroupChange);
2126
+ const [openGroup, selectGroup] = useUrlView(tabs.map((t2) => t2.id), viewParamOf(deepLinkView), group, onGroupChange);
1641
2127
  const railHead = cases || variants ? /* @__PURE__ */ jsxs(Fragment, { children: [
1642
2128
  cases && /* @__PURE__ */ jsx(CaseSelector, { lang, ...cases }),
1643
2129
  variants && /* @__PURE__ */ jsx(VariantBar, { ...variants })
@@ -1865,4 +2351,4 @@ function ViewsRow({ children, shares }) {
1865
2351
  }) });
1866
2352
  }
1867
2353
 
1868
- export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, Equation, Figure, FocusShell, Gauge, Glossary, InlineMath, Knob, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, firstAppearance, fitLabel, fontFamily, groupByCategory, isStale, makeStateKey, niceStep, niceTicks, readCaseParam, replaceQueryParam, sourcesPresent, textWidth, usePausedViz, useUrlView, useWorkbenchState, validateArchitectureConfig, viewParamOf, widestLabel, withCaseParam };
2354
+ export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, EXECUTIVE_SCHEMA_VERSION, Equation, ExecutiveView, FOUR_CS, Figure, FocusShell, Gauge, Glossary, InlineMath, Knob, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, firstAppearance, fitLabel, fontFamily, groupByCategory, isStale, makeStateKey, niceStep, niceTicks, readCaseParam, replaceQueryParam, sourcesPresent, textWidth, usePausedViz, useUrlView, useWorkbenchState, validateArchitectureConfig, validateExecutive, viewParamOf, widestLabel, withCaseParam };