compasso 0.4.0 → 0.5.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/README.md +115 -5
- package/dist/{chunk-ZBDABVIO.js → chunk-2NDET6O5.js} +3 -3
- package/dist/{chunk-ZBDABVIO.js.map → chunk-2NDET6O5.js.map} +1 -1
- package/dist/{chunk-Q6DVTCXD.js → chunk-3RGYLVTN.js} +18 -6
- package/dist/chunk-3RGYLVTN.js.map +1 -0
- package/dist/chunk-BM7UJBK5.js +680 -0
- package/dist/chunk-BM7UJBK5.js.map +1 -0
- package/dist/chunk-DVLWT565.js +372 -0
- package/dist/chunk-DVLWT565.js.map +1 -0
- package/dist/{chunk-F47C6ZEB.js → chunk-JBDA7E2O.js} +3 -3
- package/dist/{chunk-F47C6ZEB.js.map → chunk-JBDA7E2O.js.map} +1 -1
- package/dist/chunk-MIJTBYX2.js +982 -0
- package/dist/chunk-MIJTBYX2.js.map +1 -0
- package/dist/{chunk-JP4N42AY.js → chunk-PJHLWSGD.js} +3 -3
- package/dist/{chunk-JP4N42AY.js.map → chunk-PJHLWSGD.js.map} +1 -1
- package/dist/{chunk-LRHHUJFZ.js → chunk-RDH4XHA2.js} +3 -3
- package/dist/{chunk-LRHHUJFZ.js.map → chunk-RDH4XHA2.js.map} +1 -1
- package/dist/{chunk-UJVU7B44.js → chunk-WEHUSHVI.js} +31 -51
- package/dist/chunk-WEHUSHVI.js.map +1 -0
- package/dist/{chunk-RWPGGWO5.js → chunk-Z66YUOUM.js} +34 -10
- package/dist/chunk-Z66YUOUM.js.map +1 -0
- package/dist/core/index.cjs +247 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +94 -2
- package/dist/core/index.d.ts +94 -2
- package/dist/core/index.js +1 -1
- package/dist/ecomap/index.cjs +34 -11
- package/dist/ecomap/index.cjs.map +1 -1
- package/dist/ecomap/index.d.cts +12 -0
- package/dist/ecomap/index.d.ts +12 -0
- package/dist/ecomap/index.js +2 -2
- package/dist/fault-tree/index.d.cts +2 -2
- package/dist/fault-tree/index.d.ts +2 -2
- package/dist/fault-tree/index.js +2 -2
- package/dist/fishbone/index.js +2 -2
- package/dist/genogram/index.cjs +57 -7
- package/dist/genogram/index.cjs.map +1 -1
- package/dist/genogram/index.d.cts +22 -6
- package/dist/genogram/index.d.ts +22 -6
- package/dist/genogram/index.js +2 -2
- package/dist/geometry-P-XGqGe7.d.cts +8 -0
- package/dist/geometry-P-XGqGe7.d.ts +8 -0
- package/dist/grid-BMgUSly1.d.cts +79 -0
- package/dist/grid-BMgUSly1.d.ts +79 -0
- package/dist/index.cjs +2360 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +10 -8
- package/dist/{kinship-DqEklrDN.d.ts → kinship-BF90HyyS.d.ts} +1 -1
- package/dist/{kinship-Dy_ijjJV.d.cts → kinship-BOUss5cT.d.cts} +1 -1
- package/dist/{labels-RtFw9tX1.d.cts → labels-B0aOMbHy.d.cts} +12 -0
- package/dist/{labels-RtFw9tX1.d.ts → labels-B0aOMbHy.d.ts} +12 -0
- package/dist/labels-Br8yjc3C.d.cts +29 -0
- package/dist/labels-Br8yjc3C.d.ts +29 -0
- package/dist/{labels-DNqRkWuI.d.ts → labels-CuLbFyrz.d.ts} +1 -1
- package/dist/labels-D1v1RWZd.d.cts +97 -0
- package/dist/labels-D1v1RWZd.d.ts +97 -0
- package/dist/{labels-CBQ_3Ec9.d.cts → labels-DhQe7I8m.d.cts} +1 -1
- package/dist/layered-DmZluAqe.d.cts +72 -0
- package/dist/layered-DmZluAqe.d.ts +72 -0
- package/dist/locales/pt-br.cjs +53 -0
- package/dist/locales/pt-br.cjs.map +1 -1
- package/dist/locales/pt-br.d.cts +11 -5
- package/dist/locales/pt-br.d.ts +11 -5
- package/dist/locales/pt-br.js +50 -1
- package/dist/locales/pt-br.js.map +1 -1
- package/dist/org-chart/index.cjs +138 -94
- package/dist/org-chart/index.cjs.map +1 -1
- package/dist/org-chart/index.d.cts +24 -33
- package/dist/org-chart/index.d.ts +24 -33
- package/dist/org-chart/index.js +2 -2
- package/dist/pedigree/index.d.cts +6 -6
- package/dist/pedigree/index.d.ts +6 -6
- package/dist/pedigree/index.js +2 -2
- package/dist/phylo/index.d.cts +2 -2
- package/dist/phylo/index.d.ts +2 -2
- package/dist/phylo/index.js +2 -2
- package/dist/prisma/index.cjs +882 -0
- package/dist/prisma/index.cjs.map +1 -0
- package/dist/prisma/index.d.cts +174 -0
- package/dist/prisma/index.d.ts +174 -0
- package/dist/prisma/index.js +4 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/{text-DuO_PwYw.d.cts → text-DDVzpwPZ.d.cts} +1 -8
- package/dist/{text-DuO_PwYw.d.ts → text-DDVzpwPZ.d.ts} +1 -8
- package/dist/{types-BnMG7TCd.d.cts → types-jE2fdM1t.d.cts} +8 -0
- package/dist/{types-BnMG7TCd.d.ts → types-jE2fdM1t.d.ts} +8 -0
- package/dist/uml/index.cjs +1214 -0
- package/dist/uml/index.cjs.map +1 -0
- package/dist/uml/index.d.cts +189 -0
- package/dist/uml/index.d.ts +189 -0
- package/dist/uml/index.js +4 -0
- package/dist/uml/index.js.map +1 -0
- package/package.json +28 -2
- package/dist/chunk-O3BT2O42.js +0 -145
- package/dist/chunk-O3BT2O42.js.map +0 -1
- package/dist/chunk-Q6DVTCXD.js.map +0 -1
- package/dist/chunk-RWPGGWO5.js.map +0 -1
- package/dist/chunk-UJVU7B44.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/org-chart/types.ts","../../src/org-chart/labels.ts","../../src/org-chart/validate.ts","../../src/core/xml.ts","../../src/core/geometry.ts","../../src/core/text.ts","../../src/core/legend.ts","../../src/core/stroke.ts","../../src/org-chart/layout.ts","../../src/org-chart/svg.ts","../../src/org-chart/render.ts"],"names":["round","ORG_BOX_PAD_Y"],"mappings":"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","file":"index.cjs","sourcesContent":["// Org-chart input model — declared facts only. compasso draws EXACTLY who the caller\n// declares reports to whom: every reporting line carries its declared `kind` (the line\n// STYLE is a semantic claim only the author may make), every box is a declared position,\n// and the ROOT is never declared — it is READ from topology (a position that is no solid\n// edge's report). There is deliberately NO `level`/`depth`/`isManager`/`order` field on\n// the input: depth is derived from the declared solid edges, not trusted from a flag (the\n// honesty rule). Multi-root forests (holding cos, co-CEOs, pre-merger) are real and\n// tolerated, never an error.\n\n/**\n * CLOSED reporting vocabulary — a line is drawn ONLY for a declared relationship, styled\n * ONLY by a declared kind. No inference, no synthesis.\n * - \"line\" — solid PRIMARY reporting line; defines the tree spine (a node's row & parent).\n * - \"assistant\" — solid SIDE-STEM staff/EA role; STILL a structural child of exactly one\n * manager (it sets the report's row = manager.depth + 1 band), but drawn\n * beside the manager's stem above the line-report bus rather than packed\n * into the sibling rake.\n * - \"dotted\" — dashed secondary/matrix line. NON-STRUCTURAL: never defines a row or a\n * parent; an OVERLAY between two already-placed boxes (dotted-line-manager\n * convention).\n */\nexport const ORG_REPORT_KINDS = [\"line\", \"assistant\", \"dotted\"] as const;\nexport type OrgReportKind = (typeof ORG_REPORT_KINDS)[number];\n\n/**\n * CLOSED vacancy vocabulary. A box is vacant ONLY when DECLARED so — never inferred from\n * an empty name. A vacant box may legitimately carry a name (a departed incumbent or a\n * target hire); both are drawn.\n */\nexport const ORG_VACANCIES = [\"filled\", \"vacant\"] as const;\nexport type OrgVacancy = (typeof ORG_VACANCIES)[number];\n\n/**\n * A declared organizational position (one box). `name`/`title`/`subtitle` are verbatim\n * (always kept in the <title>); empty strings / nulls are drawn as declared.\n */\nexport interface OrgPosition {\n id: number;\n /** Verbatim person/role name — line 1 of the box. \"\" allowed (drawn empty; <title> intact). */\n name: string;\n /** Verbatim job title — line 2 (smaller). null = name-only box. */\n title: string | null;\n /**\n * OPTIONAL third line (department/unit), verbatim, measured into boxW like the others.\n * null = none. NOT a metrics/compensation field — that interpretive cut stands.\n */\n subtitle: string | null;\n /**\n * \"vacant\" → dashed box + inset open-seat frame + localized \"(vago)\" marker line.\n * A box is vacant ONLY when DECLARED so — never inferred from an empty name.\n * (validation defaults an absent value → \"filled\").\n */\n vacancy: OrgVacancy;\n /** Verbatim <title> override; defaults below (see svg.ts). */\n hover?: string;\n}\n\n/**\n * One row per DECLARED relationship, manager → report. There is no `order` column in\n * v0.4.0 — sibling order among reports is by ascending `reportId`.\n */\nexport interface OrgReport {\n id: number;\n /** Manager — drawn ABOVE. */\n managerId: number;\n /** Report — drawn BELOW (line) or side-stemmed (assistant). */\n reportId: number;\n /** Reporting-line kind (validation defaults an absent value → \"line\"). */\n kind: OrgReportKind;\n /** Verbatim relationship label (e.g. \"interim\", \"matrix\") for the <title>; null = none. */\n label?: string | null;\n}\n\n/** Input to the org-chart render pipeline — flat, id-referenced rows, never nested. */\nexport interface OrgChartInput {\n positions: OrgPosition[];\n reports: OrgReport[];\n}\n\n/**\n * Presentation-only derived box style (solid = filled, dashed = vacant). Computed in\n * render.ts / svg.ts from `vacancy` — NOT an input field.\n */\nexport type OrgBoxStyle = \"solid\" | \"dashed\";\n","// Display vocabularies — every human-readable string the org chart emits, gathered in\n// overridable packs so the diagram localizes without touching the engine. English\n// defaults here; `compasso/locales/pt-br` ships a Brazilian Portuguese pack.\n//\n// Split, mirroring fault-tree/genogram: `OrgChartTitleLabels` is woven into element/box\n// <title>s by the LAYOUT (verbatim-preserving — the localized kind word rides each line's\n// <title>, never the map); `OrgChartSvgLabels` is drawn by the EMITTER (legend, aria).\n// `reportKinds` is a `Record<OrgReportKind, string>` so a missing kind is a compile error\n// (`pnpm typecheck` is the completeness guard).\n\nimport type { OrgReportKind } from \"./types\";\n\n/** Labels woven into element/box <title>s by the LAYOUT (verbatim-preserving). */\nexport interface OrgChartTitleLabels {\n reportKinds: Record<OrgReportKind, string>;\n /** The \"(vacant)\" box marker line, drawn inside a vacant box. */\n vacant: string;\n}\n\nexport const ORG_CHART_TITLE_LABELS_EN: OrgChartTitleLabels = {\n reportKinds: { line: \"Reports to\", assistant: \"Assistant to\", dotted: \"Dotted-line report to\" },\n vacant: \"(vacant)\",\n};\n\n/** Labels drawn by the SVG EMITTER (legend entries, accessibility text). */\nexport interface OrgChartSvgLabels {\n legend: { line: string; assistant: string; dotted: string; vacant: string };\n ariaLabel: string;\n}\n\nexport const ORG_CHART_SVG_LABELS_EN: OrgChartSvgLabels = {\n legend: { line: \"Reports to\", assistant: \"Assistant\", dotted: \"Dotted-line / matrix\", vacant: \"Vacant position\" },\n ariaLabel: \"Organizational chart\",\n};\n","// Org-chart validation — REJECT, never repair. The genogram silently filters dangling\n// references because a family map is elicited incrementally; an org chart is an\n// AUTHORITATIVE artifact whose meaning is \"who answers to whom\", so drawing a structurally\n// invalid chart (a dropped line, a synthesized parent) misstates the hierarchy and is\n// worse than refusing. The honest escape hatch for a node with two real bosses is the\n// dotted line — keep ONE solid reporting line, make the rest kind:\"dotted\".\n//\n// Every problem is reported, not just the first: issues are aggregated, deduplicated and\n// sorted deterministically (by code, then message), each carrying a STABLE kebab-case\n// `code`. Validation runs in THREE phases, each gated on the previous being clean ENOUGH\n// for the next to be meaningful — not on \"zero issues so far\", so a defect in one phase\n// never silently hides an honest issue from a later one (the throw carries ALL real\n// issues, not just the first phase's):\n// (0) duplicate ids (per namespace — positions AND reports). The lookup maps are\n// first-occurrence-wins, so EVERY reference rule below would validate whichever\n// duplicate row was declared first — making the issue list depend on array order,\n// violating this function's documented order-invariance. When any duplicate-id issue\n// exists we report ONLY those and stop (the duplicate already forces a throw).\n// (1) reference / semantic rules: unknown manager/report endpoints, self-loops, a node\n// with ≥2 SOLID structural parents, and an assistant that itself manages a solid edge\n// (v0.4.0 scopes assistants as side-stem LEAVES — a non-leaf assistant would silently\n// drop its subtree, so we REJECT rather than repair). Evaluated once ids are unambiguous.\n// (2) graph rule (cycle over the SOLID-edge graph) — gated ONLY on the reference-\n// INTEGRITY subset that genuinely corrupts traversal: duplicate-id (ambiguous\n// first-wins node), unknown-manager / unknown-report (walks a phantom node), and\n// multiple-managers (the instance-tree build picks one of two solid parents and\n// would walk an ambiguous structure). `self-report` does NOT block: it references a\n// real, walkable node, and the DFS defensively skips `from === to` solid edges.\n//\n// Tolerated, by design (drawn as declared, never an error):\n// - FOREST — zero/one/many roots (no invented super-root, no inter-tree connector);\n// - dotted edges crossing between forest trees, dotted-only cycles, a dotted edge sharing\n// a solid pair's direction (dotted is NON-structural — never triggers cycle or\n// multiple-managers); a dotted edge into an already-solid-parented box is FINE;\n// - empty name/title/subtitle (drawn empty; the <title> is still present);\n// - a vacant box with a name (departed incumbent / target hire).\n\nimport type { OrgChartInput, OrgPosition, OrgReport } from \"./types\";\n\n/** Stable machine-readable issue codes (kebab-case; part of the public contract). */\nexport type OrgChartIssueCode =\n | \"duplicate-id\"\n | \"unknown-manager\"\n | \"unknown-report\"\n | \"self-report\"\n | \"multiple-managers\"\n | \"assistant-has-reports\"\n | \"too-many-matrix-edges\"\n | \"cycle\";\n\n/**\n * Routing capacity: the max number of dotted (matrix) connections one position can be an\n * endpoint of (as manager OR report). Each such edge must escape that box's edge to a\n * box-free column at a distinct (column, exit-y) slot; a finite box edge holds only finitely\n * many clean orthogonal exits, so beyond this the escape columns/exit-rows would collide.\n * 5 is the conservative bound proven collision-free even for the shortest single-line box —\n * a position with more matrix lines than this is rejected rather than misdrawn (the\n * reject-don't-repair doctrine). Realistic matrix orgs sit far below it.\n */\nexport const ORG_MAX_MATRIX_EDGES_PER_NODE = 5;\n\nexport interface OrgChartIssue {\n code: OrgChartIssueCode;\n message: string;\n}\n\n/** Thrown by computeOrgChartLayout / orgChartSvg on a structurally invalid chart. */\nexport class OrgChartValidationError extends Error {\n readonly issues: readonly OrgChartIssue[];\n\n constructor(issues: readonly OrgChartIssue[]) {\n super(`invalid org chart: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"OrgChartValidationError\";\n this.issues = issues;\n }\n}\n\n/** \"1 and 3\" / \"1, 2 and 3\" — deterministic listing for issue messages. */\nfunction listIds(ids: readonly number[]): string {\n if (ids.length === 1) return String(ids[0]);\n return `${ids.slice(0, -1).join(\", \")} and ${ids[ids.length - 1]}`;\n}\n\n/**\n * Deduplicate + deterministic order: by code, then message (byte comparison — stable\n * across engines; no locale-dependent collation). Shared by every phase that returns.\n */\nfunction sortIssues(issues: readonly OrgChartIssue[]): readonly OrgChartIssue[] {\n const unique = new Map<string, OrgChartIssue>();\n for (const issue of issues) unique.set(`${issue.code} ${issue.message}`, issue);\n return [...unique.values()].sort((a, b) =>\n a.code !== b.code ? (a.code < b.code ? -1 : 1) : a.message < b.message ? -1 : a.message > b.message ? 1 : 0,\n );\n}\n\n/**\n * Graph-phase gating set: the cycle DFS runs only when no reference-INTEGRITY issue\n * corrupts the traversal. duplicate-id / unknown-manager / unknown-report make a walked\n * node ambiguous or phantom; multiple-managers makes the instance-tree's \"pick one solid\n * parent\" build ambiguous. self-report does NOT block (real walkable node; the DFS skips\n * the self-loop defensively).\n */\nconst GRAPH_BLOCKING: ReadonlySet<OrgChartIssueCode> = new Set<OrgChartIssueCode>([\n \"duplicate-id\",\n \"unknown-manager\",\n \"unknown-report\",\n \"multiple-managers\",\n]);\n\n/**\n * Computes ALL validation issues for the input, deduplicated and deterministically sorted\n * (code, then message) — array order of `positions`/`reports` never changes the result.\n * Empty input (no positions AND no reports) is valid by definition (the renderer's\n * empty-but-valid SVG case) and reports no issues. A forest (zero/one/many roots) is\n * valid and never reported.\n */\nexport function orgChartIssues(input: OrgChartInput): readonly OrgChartIssue[] {\n if (input.positions.length === 0 && input.reports.length === 0) return [];\n\n const issues: OrgChartIssue[] = [];\n const push = (code: OrgChartIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── Phase 0: duplicate ids (per namespace — positions and reports are two namespaces;\n // hooks must be unique). Any duplicate makes the structure ambiguous, so this\n // short-circuits the rest (below). ─────────────────────────────────────────────────\n const positionById = new Map<number, OrgPosition>();\n const dupPositionIds = new Set<number>();\n for (const p of input.positions) {\n if (positionById.has(p.id)) dupPositionIds.add(p.id);\n else positionById.set(p.id, p);\n }\n for (const id of [...dupPositionIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate position id ${id}`);\n }\n const reportById = new Map<number, OrgReport>();\n const dupReportIds = new Set<number>();\n for (const r of input.reports) {\n if (reportById.has(r.id)) dupReportIds.add(r.id);\n else reportById.set(r.id, r);\n }\n for (const id of [...dupReportIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate report id ${id}`);\n }\n\n // Duplicate ids short-circuit everything else: the lookup maps above are\n // first-occurrence-wins, so every downstream reference rule would validate whichever\n // duplicate row happened to be declared first — making the issue list depend on the\n // ARRAY ORDER, in direct violation of this function's documented order-invariance. We\n // report ONLY the duplicate-id issues and stop (the structural defect already forces a\n // throw, and is present in every permutation).\n if (issues.length > 0) {\n return sortIssues(issues);\n }\n\n const reports = [...reportById.values()].sort((a, b) => a.id - b.id);\n\n // ── Phase 1: reference / semantic rules. ─────────────────────────────────────────────\n // Endpoints must reference declared positions; a box may not report to itself; a node\n // has exactly ONE structural parent. `solidParents` accumulates the SOLID (line|assistant)\n // parent edge ids per report position to fire multiple-managers regardless of kind mix.\n const solidParents = new Map<number, number[]>(); // reportId → solid edge ids\n const assistantReportEdge = new Map<number, number>(); // position → first assistant edge it is the report of\n const solidManagedEdges = new Map<number, number[]>(); // managerId → solid edge ids it manages\n const dottedDegree = new Map<number, number>(); // position → # dotted edges it is an endpoint of (mgr or rep)\n for (const r of reports) {\n const hasManager = positionById.has(r.managerId);\n const hasReport = positionById.has(r.reportId);\n if (!hasManager) {\n push(\"unknown-manager\", `report ${r.id} managerId ${r.managerId} is not a declared position`);\n }\n if (!hasReport) {\n push(\"unknown-report\", `report ${r.id} reportId ${r.reportId} is not a declared position`);\n }\n // R: a box reporting to itself is meaningless and self-loops layout — on ANY kind.\n if (r.managerId === r.reportId) {\n push(\"self-report\", `report ${r.id} has managerId === reportId (${r.managerId})`);\n }\n // A SOLID edge (line | assistant) is a structural parent — accumulate even when an\n // endpoint is unknown, so a node with two solid parents is still flagged (the codes\n // are independent facts). dotted is NON-structural and excluded here.\n if (r.kind !== \"dotted\") {\n const arr = solidParents.get(r.reportId) ?? [];\n arr.push(r.id);\n solidParents.set(r.reportId, arr);\n // Track each position's SOLID down-edges (it is the manager of) so a non-leaf\n // assistant — a position that is an assistant-report yet manages a solid edge — is\n // caught below. `reports` is id-sorted, so the lowest edge id lands first.\n const managed = solidManagedEdges.get(r.managerId) ?? [];\n managed.push(r.id);\n solidManagedEdges.set(r.managerId, managed);\n }\n // First (lowest-id) assistant edge that makes this position an assistant-report. A\n // self-loop assistant is excluded — `self-report` already carries that fact and the\n // position never legitimately becomes a side-stem leaf.\n if (r.kind === \"assistant\" && r.managerId !== r.reportId && !assistantReportEdge.has(r.reportId)) {\n assistantReportEdge.set(r.reportId, r.id);\n }\n // Per-position dotted (matrix) degree, for the routing-capacity cap below. A dotted edge\n // makes BOTH endpoints escape their box edge, so each declared endpoint counts once;\n // self-loops (already `self-report`) and phantom endpoints (already `unknown-*`) are\n // excluded — they never reach the router.\n if (r.kind === \"dotted\" && r.managerId !== r.reportId) {\n if (positionById.has(r.managerId)) dottedDegree.set(r.managerId, (dottedDegree.get(r.managerId) ?? 0) + 1);\n if (positionById.has(r.reportId)) dottedDegree.set(r.reportId, (dottedDegree.get(r.reportId) ?? 0) + 1);\n }\n }\n // multiple-managers fires whenever a position is the report of ≥2 SOLID edges, regardless\n // of kind — including one `line` parent AND one `assistant` parent (still two structural\n // parents; the instance-tree DFS would be ambiguous about which owns the row). There is\n // no \"which kind wins\" tiebreak — it is rejected. Escape hatch: keep one solid line, make\n // the rest kind:\"dotted\".\n for (const [reportId, edgeIds] of [...solidParents.entries()].sort((a, b) => a[0] - b[0])) {\n if (edgeIds.length > 1) {\n push(\n \"multiple-managers\",\n `position ${reportId} is the report of solid edges ${listIds(edgeIds.sort((a, b) => a - b))} — keep one solid line, make the rest kind \"dotted\"`,\n );\n }\n }\n\n // assistant-has-reports: v0.4.0 draws an assistant as a side-stem LEAF, so a position\n // that is an assistant-report AND manages a solid (line|assistant) edge would have its\n // entire subtree silently dropped. REJECT it (reject-don't-repair) — keep the lowest\n // managed solid edge id in the message so the author knows which line to recut. Ascending\n // position id for a deterministic, array-order-invariant list.\n for (const [positionId, assistEdgeId] of [...assistantReportEdge.entries()].sort((a, b) => a[0] - b[0])) {\n const managed = solidManagedEdges.get(positionId);\n if (managed !== undefined && managed.length > 0) {\n const firstManaged = Math.min(...managed);\n push(\n \"assistant-has-reports\",\n `position ${positionId} is an assistant (report of edge ${assistEdgeId}) but manages solid edge ${firstManaged} — assistants are leaves`,\n );\n }\n }\n\n // too-many-matrix-edges: a position that is an endpoint of more dotted (matrix) edges than\n // the router can place distinct box-free escape slots for (see ORG_MAX_MATRIX_EDGES_PER_NODE).\n // Reject rather than misdraw (overlapping/colliding lines). Ascending position id for a\n // deterministic, array-order-invariant list.\n for (const [positionId, count] of [...dottedDegree.entries()].sort((a, b) => a[0] - b[0])) {\n if (count > ORG_MAX_MATRIX_EDGES_PER_NODE) {\n push(\n \"too-many-matrix-edges\",\n `position ${positionId} has ${count} dotted (matrix) connections — at most ${ORG_MAX_MATRIX_EDGES_PER_NODE} are supported per position`,\n );\n }\n }\n\n // ── Phase 2: graph rule (cycle over the SOLID-edge graph). Gated ONLY on the reference-\n // INTEGRITY codes that corrupt the traversal itself (see GRAPH_BLOCKING). dotted edges\n // are EXCLUDED — a matrix back-link is legal and never a cycle. ─────────────────────\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // Adjacency manager → reports over SOLID edges only, in ascending reportId so the DFS\n // walks children deterministically (array-order-invariant). `from === to` self-loops\n // are skipped defensively (self-report carries that fact as its own code).\n const solidChildren = new Map<number, number[]>();\n for (const r of reports) {\n if (r.kind === \"dotted\") continue;\n if (r.managerId === r.reportId) continue;\n const arr = solidChildren.get(r.managerId) ?? [];\n arr.push(r.reportId);\n solidChildren.set(r.managerId, arr);\n }\n for (const arr of solidChildren.values()) arr.sort((a, b) => a - b);\n\n // Iterative coloring DFS, start nodes ascending; each distinct cycle is reported once,\n // rotated to start at its smallest position id so the message is identical for any\n // array order of the same input.\n const color = new Map<number, 0 | 1 | 2>(); // 0/absent=white, 1=gray, 2=black\n const seenCycles = new Set<string>();\n const dfs = (start: number): void => {\n const stack: { id: number; nextChild: number }[] = [{ id: start, nextChild: 0 }];\n color.set(start, 1);\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]!;\n const children = solidChildren.get(frame.id) ?? [];\n if (frame.nextChild >= children.length) {\n color.set(frame.id, 2);\n stack.pop();\n continue;\n }\n const child = children[frame.nextChild]!;\n frame.nextChild += 1;\n const c = color.get(child) ?? 0;\n if (c === 1) {\n // Back edge: the cycle is the stack slice from `child` down to the current frame.\n const from = stack.findIndex((f) => f.id === child);\n const cycle = stack.slice(from).map((f) => f.id);\n const minIdx = cycle.indexOf(Math.min(...cycle));\n const rotated = [...cycle.slice(minIdx), ...cycle.slice(0, minIdx)];\n const key = rotated.join(\">\");\n if (!seenCycles.has(key)) {\n seenCycles.add(key);\n push(\"cycle\", `cycle: ${[...rotated, rotated[0]!].join(\" → \")}`);\n }\n } else if (c === 0) {\n color.set(child, 1);\n stack.push({ id: child, nextChild: 0 });\n }\n }\n };\n for (const p of [...positionById.values()].sort((a, b) => a.id - b.id)) {\n if ((color.get(p.id) ?? 0) === 0) dfs(p.id);\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws OrgChartValidationError (carrying ALL issues) when the input is invalid. */\nexport function validateOrgChart(input: OrgChartInput): void {\n const issues = orgChartIssues(input);\n if (issues.length > 0) throw new OrgChartValidationError(issues);\n}\n","// XML/SVG escaping — every interpolated text in an emitted SVG MUST pass through\n// this. Diagram labels are typically user/author-controlled, and the SVG string may\n// be injected via innerHTML in a browser or embedded as vectors in a PDF — an\n// unescaped label is an XSS / `</svg>`-breakout vector on every surface at once.\n\n/** Escapes a string for use in SVG/XML text content AND attribute values. */\nexport function xmlEscape(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","// Shared geometry primitives.\n\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** \"M x y L x y …\" path data from a polyline. */\nexport function pathData(points: Point[]): string {\n return points.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x} ${p.y}`).join(\" \");\n}\n","// Pure, deterministic text metrics — no DOM, no canvas, no font files. Every layout\n// in this library reserves space from these estimates and every emitter draws with\n// the same constants, so what is proven collision-free is what is drawn.\n\n/**\n * Conservative per-character advance, as a fraction of the font size. The pure module\n * can't measure real glyphs (no DOM/canvas), so it estimates width = chars * font *\n * CHAR_W. It is deliberately a touch WIDER than Helvetica's ~0.5 average advance: a\n * layout reserves slightly more room than the text needs, so the real render always\n * fits inside its reserved box.\n */\nexport const CHAR_W = 0.6;\n\n/** Pure, deterministic width estimate for a single line of text at `fontPx`. */\nexport function estimateTextWidth(text: string, fontPx: number): number {\n return text.length * fontPx * CHAR_W;\n}\n\n/**\n * Wraps a label onto up to `maxLines` lines (default 2) so long labels don't sprawl.\n * Greedy word fill; each line capped at `perLine` chars (…-truncated only if a line\n * still overflows). The LAST allowed line absorbs every remaining word before the cap\n * applies — words are never dropped mid-label, only visibly elided. Pure + shared so\n * every renderer wraps identically. The full text is always kept elsewhere (the\n * node's `label`, an SVG <title>, or a side list), so nothing is silently lost.\n *\n * INVARIANT: with the default `maxLines` the output is byte-identical to the\n * historical two-line implementation (pinned by test/core/text.test.ts) — both\n * shipped renderers wrap through here.\n */\nexport function wrapLabel(label: string, perLine: number, maxLines = 2): string[] {\n if (label.length <= perLine) return [label];\n const cap = (s: string): string =>\n s.length > perLine ? s.slice(0, Math.max(1, perLine - 1)) + \"…\" : s;\n const lines: string[] = [\"\"];\n for (const word of label.split(/\\s+/)) {\n const last = lines.length - 1;\n const current = lines[last]!;\n if (current === \"\" || (current + \" \" + word).length <= perLine) {\n lines[last] = current === \"\" ? word : `${current} ${word}`;\n } else if (lines.length < maxLines) {\n lines.push(word);\n } else {\n lines[last] = `${current} ${word}`;\n }\n }\n // A trailing-whitespace \"word\" (\"a b \".split(/\\s+/) → [\"a\",\"b\",\"\"]) may open a line\n // it never fills; the historical code dropped that empty line, so this does too.\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return lines.map(cap);\n}\n\n/**\n * House \"balanced\" wrap policy (extracted verbatim from the ecomap's tie-label wrap,\n * itself mirroring the genogram's): per-line budget `min(26, max(14, ceil(len/2)+2))`\n * splits a medium label into two roughly even lines instead of one long + one short,\n * then the greedy `wrapLabel` fill (and its `maxLines` semantics) applies. The shipped\n * renderers keep their local copies for now — new modules consume this one; migrating\n * them is a separate provably-zero-change refactor.\n */\nexport function wrapLabelBalanced(label: string, maxLines?: number): string[] {\n const perLine = Math.min(26, Math.max(14, Math.ceil(label.length / 2) + 2));\n return wrapLabel(label, perLine, maxLines);\n}\n\n/** Caps a verbatim label for a COMPACT render (preview); full text kept by the caller. */\nexport function clampLabel(label: string, maxChars: number | undefined): string {\n if (maxChars === undefined || label.length <= maxChars) return label;\n return label.slice(0, Math.max(1, maxChars - 1)) + \"…\";\n}\n\n/** Font stack shared by every emitter; PDF embedders typically map it onto Helvetica. */\nexport const FONT_FAMILY = \"Helvetica, Arial, sans-serif\";\n","// Shared legend machinery — the exact row format the genogram and ecomap emitters\n// currently duplicate character-for-character (`<g data-compasso-legend=\"true\">` with\n// swatch-closure rows). Extracted so new diagram modules don't add a third copy;\n// the two shipped emitters keep their local blocks for now (migrating them is a\n// separate, provably-zero-change refactor — pinned byte-for-byte against the ecomap's\n// emitted legend in test/core/legend.test.ts).\n//\n// The caller stays in charge of the HONESTY RULE half: it decides WHICH entries exist\n// (used-keys-only) and what each swatch draws; this module only owns the row geometry,\n// the text emission (xmlEscape — labels may come from caller-supplied packs), and the\n// width/height bookkeeping both renderers compute identically.\n\nimport { FONT_FAMILY, estimateTextWidth } from \"./text\";\nimport { xmlEscape } from \"./xml\";\n\n// Row metrics shared by every legend in the library. Exported because swatch builders\n// need them (a line swatch spans LEGEND_SWATCH_W; a glyph swatch centers on it).\nexport const LEGEND_ROW_H = 18;\nexport const LEGEND_PAD = 16;\nexport const LEGEND_SWATCH_W = 22;\nexport const LEGEND_GAP = 14;\nexport const LEGEND_FONT = 11;\n\n// Legend text ink — the zinc glyph stroke both shipped emitters use for legend labels.\nconst LEGEND_TEXT_FILL = \"#52525b\";\n\nexport interface LegendEntry {\n /**\n * Swatch markup builder, called with the swatch's left x and the row's center y.\n * The builder owns its own escaping/rounding (it typically reuses the module's\n * glyph/line emitters); it should draw within LEGEND_SWATCH_W of x.\n */\n swatch: (x: number, yCenter: number) => string;\n /** Display label (escaped here; verbatim pack text in, escaped SVG out). */\n label: string;\n}\n\nexport interface LegendBlock {\n /** `<g data-compasso-legend=\"true\">…</g>` — empty string when there are no entries. */\n svg: string;\n /** Minimum canvas width the legend needs; callers take `max(width, block.width)`. */\n width: number;\n /** New total canvas height including the legend; callers assign it directly. */\n height: number;\n}\n\n/**\n * Emits the legend group for the given entries below `startY` (the diagram's current\n * height). Pure + deterministic; coordinates are interpolated exactly as the shipped\n * emitters do. Zero entries (used-keys-only found nothing) → no markup, zero width\n * contribution, height unchanged — safe to call unconditionally.\n */\nexport function legendBlock(entries: readonly LegendEntry[], startY: number): LegendBlock {\n if (entries.length === 0) return { svg: \"\", width: 0, height: startY };\n const rows = entries.map((entry, i) => {\n const rowCenterY = startY + i * LEGEND_ROW_H + LEGEND_ROW_H / 2;\n const textX = LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP;\n return (\n entry.swatch(LEGEND_PAD, rowCenterY) +\n `<text x=\"${textX}\" y=\"${rowCenterY + LEGEND_FONT * 0.32}\" font-family=\"${FONT_FAMILY}\" font-size=\"${LEGEND_FONT}\" fill=\"${LEGEND_TEXT_FILL}\">${xmlEscape(entry.label)}</text>`\n );\n });\n const widestLabel = entries.reduce((m, e) => Math.max(m, estimateTextWidth(e.label, LEGEND_FONT)), 0);\n return {\n svg: `<g data-compasso-legend=\"true\">${rows.join(\"\")}</g>`,\n width: LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP + widestLabel + LEGEND_PAD,\n height: startY + entries.length * LEGEND_ROW_H + LEGEND_PAD / 2,\n };\n}\n","// Edge line styles — a neutral, presentation-only style for a relationship line.\n// NOT a judgment: a deterministic, lexical hint derived from the author's own quality\n// word. The literal word always rides the element's <title>, so a style never replaces\n// what was said. Unknown/ambiguous quality → \"plain\".\n\nexport type EdgeLineStyle = \"plain\" | \"close\" | \"distant\" | \"conflict\" | \"cutoff\";\n\n/** Stroke attributes per style — shared by every renderer so SVG and PDF match. */\nexport interface EdgeStroke {\n width: number;\n /** SVG dash array / PDF dash pattern as [dash, gap]; null = solid. */\n dash: [number, number] | null;\n opacity: number;\n}\n\nexport const EDGE_STROKE: Record<EdgeLineStyle, EdgeStroke> = {\n plain: { width: 1.5, dash: null, opacity: 0.6 },\n close: { width: 3, dash: null, opacity: 0.85 },\n distant: { width: 1.5, dash: [4, 4], opacity: 0.55 },\n conflict: { width: 2, dash: [2, 2], opacity: 0.75 },\n cutoff: { width: 1.5, dash: [6, 5], opacity: 0.4 },\n};\n\n/**\n * A pluggable lexicon mapping free-text quality words onto line styles. Needles are\n * diacritic-free, lowercase substrings of the author's own words; `negations` are\n * whole words that flip the meaning of the very word a needle would match (\"not\n * close\"), so their presence makes the matcher abstain to \"plain\" rather than risk\n * an inverted visual. Locale packs (e.g. `compasso/locales/pt-br`) ship alternates.\n */\nexport interface QualityLexicon {\n buckets: readonly { style: Exclude<EdgeLineStyle, \"plain\">; needles: readonly string[] }[];\n negations: readonly string[];\n}\n\n// English default. Conservative stems: each needle is a substring match on the\n// normalized text, and the SINGLE-BUCKET rule below keeps competing signals honest.\n// \"no\" alone is deliberately NOT a negation: \"no contact\" is a genuine cutoff signal.\nexport const QUALITY_LEXICON_EN: QualityLexicon = {\n buckets: [\n {\n style: \"close\",\n needles: [\"close\", \"warm\", \"support\", \"lov\", \"affection\", \"caring\", \"tight\", \"harmon\", \"healthy\"],\n },\n {\n style: \"distant\",\n needles: [\"distant\", \"detach\", \"absent\", \"cold\", \"drift\"],\n },\n {\n style: \"conflict\",\n needles: [\"conflict\", \"fight\", \"tens\", \"difficult\", \"hostil\", \"violen\", \"abus\", \"aggress\", \"complicat\", \"toxic\", \"argu\"],\n },\n {\n style: \"cutoff\",\n needles: [\"estrang\", \"cut off\", \"cutoff\", \"no contact\", \"broken off\", \"sever\"],\n },\n ],\n negations: [\"not\", \"never\", \"no longer\", \"hardly\"],\n};\n\n/** Lowercase + strip diacritics so matching ignores accents. */\nexport function normalizeText(text: string): string {\n return text.normalize(\"NFD\").replace(/[̀-ͯ]/g, \"\").toLowerCase();\n}\n\nconst escapeRegExp = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * Maps a free-text relationship quality to a neutral line style. Deterministic and\n * conservative: returns a specific style ONLY when exactly one lexical bucket matches;\n * null/empty/ambiguous/negated/unknown all fall back to \"plain\". The caller still\n * keeps the verbatim quality word, so nothing the author said is ever lost.\n */\nexport function qualityLineStyle(\n quality: string | null,\n lexicon: QualityLexicon = QUALITY_LEXICON_EN,\n): EdgeLineStyle {\n if (quality === null) return \"plain\";\n const haystack = normalizeText(quality);\n if (haystack.trim() === \"\") return \"plain\";\n\n if (lexicon.negations.length > 0) {\n const negation = new RegExp(`\\\\b(${lexicon.negations.map(escapeRegExp).join(\"|\")})\\\\b`);\n if (negation.test(haystack)) return \"plain\";\n }\n\n const matched: EdgeLineStyle[] = [];\n for (const { style, needles } of lexicon.buckets) {\n if (needles.some((n) => haystack.includes(n))) matched.push(style);\n }\n return matched.length === 1 ? matched[0]! : \"plain\";\n}\n","// PURE org-chart layout — the single source of truth for box positioning and connector\n// routing. The emitter (./svg.ts) draws EXACTLY what this computes, so every surface\n// (web, PDF, image pipelines) stays pinned together and can never drift.\n//\n// It is deliberately PURE — no DOM, no Node APIs, no clock, no randomness — so the same\n// input always yields the same layout, byte for byte.\n//\n// HONESTY RULE: this module only POSITIONS what the caller declared. There is NO\n// `level`/`depth`/`order` field on the input — depth is READ from the declared solid\n// edges (line|assistant) and the root is READ from topology (a position that is no solid\n// edge's report). Validation (./validate.ts) THROWS on a structurally invalid chart\n// instead of repairing it — an org chart is an authoritative artifact and silently\n// altering who-answers-to-whom is synthesis. Forests (zero/one/many roots) are tolerated.\n//\n// LAYOUT — top-down rows, exactly as every org chart draws it: manager box, short stem\n// down to a sibling bus, drops to each line-report box. Horizontal placement is NAIVE\n// SUBTREE-SPAN PACKING (the fault-tree `pack` transposed top-down, NOT Reingold–Tilford\n// contours): every subtree carries asymmetric half-extents {halfL, halfR}; siblings are\n// placed with disjoint intervals ORG_SIBLING_GAP apart, the recursion makes the guarantee\n// global (a 5-line inductive overlap proof, re-verified by the test harness), at the cost\n// of some width on unbalanced trees. Label widths reserve REAL space because boxW comes\n// from estimateTextWidth over the wrapped lines and the emitter draws with the same core\n// metrics — what is proven is what is drawn.\n//\n// CORRIDOR-GROW INVARIANT (asserted in test/org-chart/layout.test.ts): a manager's\n// assistant stack hangs in the corridor between its row and the next; the corridor grows\n// to clear the tallest stack, so every manager box bottom AND every assistant box bottom\n// sits strictly ABOVE the child bus y (the fault-tree gate-clearance analog).\n//\n// DOTTED/MATRIX overlay → a reserved RIGHT-MARGIN GUTTER (the decisive graft): after the\n// solid tree is placed, each dotted edge routes as a 3-segment orthogonal elbow into a\n// per-edge lane at x > every box's right edge — box-free by construction.\n\nimport { clampLabel, estimateTextWidth, wrapLabelBalanced, type Point } from \"../core\";\nimport { ORG_CHART_TITLE_LABELS_EN, type OrgChartTitleLabels } from \"./labels\";\nimport { validateOrgChart } from \"./validate\";\nimport type { OrgBoxStyle, OrgChartInput, OrgPosition, OrgReport } from \"./types\";\n\nexport {\n OrgChartValidationError,\n orgChartIssues,\n validateOrgChart,\n type OrgChartIssue,\n type OrgChartIssueCode,\n} from \"./validate\";\n// Re-exported so the overlap harness (and decorating callers) measure with the EXACT\n// metrics the layout reserved space with — the shared-metrics contract.\nexport { estimateTextWidth };\nexport type { Point };\n\n// ── Type metrics (shared by layout AND the emitter, so geometry == render) ──────\n/** Name line font size (px). */\nexport const ORG_LABEL_FONT = 12;\n/** Title + subtitle + vacant marker font size (px). */\nexport const ORG_TITLE_FONT = 10;\n/** Line height for stacked label lines inside a box (px). */\nexport const ORG_LABEL_LINE_H = 14;\n\n// ── Geometry constants ───────────────────────────────────────────────────────────\n/** Canvas padding on every side. */\nconst PADDING = 32;\n/** Min horizontal air between two sibling subtree intervals. */\nconst ORG_SIBLING_GAP = 28;\n/** Min horizontal air between two forest trees. */\nconst ORG_TREE_GAP = 56;\n/** Base vertical band between a row and the next (the bus lives mid-way). */\nconst ORG_CORRIDOR = 30;\n/** Minimum box width (boxes never shrink below this even with tiny labels). */\nconst ORG_MIN_BOX_W = 120;\n/** Horizontal padding inside a box (each side). */\nconst ORG_BOX_PAD_X = 12;\n/** Vertical padding inside a box (each side). */\nconst ORG_BOX_PAD_Y = 9;\n/** Horizontal gap from a manager's stem to an assistant box (reserved into ownHalfL). */\nconst ORG_ASSIST_GAP = 24;\n/** Vertical gap between stacked assistant bands (and below the last one). */\nconst ORG_ASSIST_BAND_DROP = 14;\n/** Horizontal gap from the tree's right edge to the first dotted gutter lane. */\nconst ORG_MATRIX_GUTTER_GAP = 28;\n/** Horizontal pitch between adjacent dotted gutter lanes. */\nconst ORG_MATRIX_LANE_PITCH = 14;\n/** Horizontal step between adjacent escape-vertical lanes that share a column. The GLOBAL\n * greedy first-fit (STEP 6 / FIX 2) nudges any y-overlapping coincident vertical by\n * lane*ORG_MATRIX_ESCAPE_STEP in the endpoint's escape direction until its column is clear of\n * every already-placed vertical; box-freeness holds while lane*STEP stays inside the MEASURED\n * box-free band to that side (distance to the nearest real box edge overlapping the vertical's\n * y-span). The router asserts (escape-column-overflow) rather than misdraw if a nudge exceeds\n * the band. */\nconst ORG_MATRIX_ESCAPE_STEP = 2;\n\n// ── Namespaced element ids (one element kind per numeric block, fault-tree convention)\n// — every data-edge-id stays traceable to its source row. ───────────────────────\nexport const ORG_STEM_ID_BASE = 1_000_000; // + managerId (manager box bottom → bus level)\nexport const ORG_BUS_ID_BASE = 2_000_000; // + managerId (horizontal sibling bus)\nexport const ORG_DROP_ID_BASE = 3_000_000; // + reportId (bus → line-report box top)\nexport const ORG_ASSIST_ID_BASE = 4_000_000; // + reportId (side-stem elbow to assistant)\nexport const ORG_DOTTED_ID_BASE = 5_000_000; // + report.id (matrix gutter route)\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// A box's LEFT/RIGHT edge AS DRAWN. svg.ts draws the rect at left = round(node.cx −\n// node.boxW/2) from the EMITTED (rounded) node geometry (node.cx === round(cx), node.boxW\n// === round(boxW)); width is node.boxW. Any segment that attaches to a box edge (the assist\n// elbow, the dotted matrix stub) MUST target these exact values — deriving the edge from raw\n// cx/boxW (or from a sibling expression like managerCx − gap) rounds DIFFERENTLY and lands\n// the endpoint a sub-cent INSIDE the box (a real off-by-0.01 in the emitted SVG, flagged by\n// the overlap harness). boxW is an exact multiple of 0.01, so drawnLeft + boxW === the box's\n// own right edge. Box CENTERS (stem/drop x) already use round(cx) === node.cx and are fine.\nconst drawnLeftEdge = (cx: number, boxW: number): number => round(round(cx) - round(boxW) / 2);\nconst drawnRightEdge = (cx: number, boxW: number): number => drawnLeftEdge(cx, boxW) + round(boxW);\n\n// ── Positioned layout ─────────────────────────────────────────────────────────────\n\nexport type OrgElementKind = \"stem\" | \"bus\" | \"drop\" | \"assist\" | \"dotted\";\n\nexport interface OrgNode {\n positionId: number;\n /** Box center x. */\n cx: number;\n /** Box top y. */\n top: number;\n boxW: number;\n boxH: number;\n /** \"solid\" = filled, \"dashed\" = vacant (presentation-only derived value). */\n style: OrgBoxStyle;\n /** Wrapped display lines per family (drawn centered, stacked, by font size). */\n nameLines: string[];\n titleLines: string[];\n subtitleLines: string[];\n /** Localized \"(vago)\" marker line; null on filled boxes. */\n vacantMarker: string | null;\n /** True for side-branched assistant nodes (legend + harness use it). */\n isAssistant: boolean;\n /** Depth of the row this node lives in (assistant: its manager's row + 1 band). */\n depth: number;\n /** Verbatim <title> text. */\n title: string;\n}\n\nexport interface OrgElement {\n /** Namespaced id (ORG_*_ID_BASE + managerId / reportId / report.id). */\n edgeId: number;\n kind: OrgElementKind;\n /** ≥2 waypoints, every consecutive pair axis-aligned (H or V). */\n points: Point[];\n /** True only on \"dotted\" elements. */\n dashed: boolean;\n /** Verbatim <title> text (woven from the title-label pack). */\n title: string;\n}\n\nexport interface OrgChartLayout {\n width: number;\n height: number;\n nodes: OrgNode[];\n elements: OrgElement[];\n /** Forest order, ascending id. */\n rootPositionIds: number[];\n}\n\nexport interface OrgChartLayoutOptions {\n /** Cap each box's DISPLAY label (compact preview); verbatim text stays in `title`. */\n maxLabelChars?: number;\n /** Locale pack for box/element <title>s — English default; see locale packs. */\n titleLabels?: OrgChartTitleLabels;\n}\n\n// ── PURE span-packer (Judge-1 seam) ────────────────────────────────────────────────\n// Consumes ONLY half-extents + gap constants; returns the per-child offsets and the\n// subtree's own half-extents. ZERO references to OrgNode, assistant, vacancy, depth,\n// style or the rake — so a later lift to a shared core/tree.ts is a provably-zero-change\n// refactor (do NOT extract core/tree.ts in v0.4.0 — module-local per shipped precedent).\n// Unit-tested directly in test/org-chart/pack-subtree.test.ts.\n\n/** A node's own symmetric-or-asymmetric half-extents plus its children's half-extents. */\nexport interface PackNode {\n ownHalfL: number;\n ownHalfR: number;\n /** One entry per child, in placement order; empty = leaf. */\n children: { halfL: number; halfR: number }[];\n}\n\nexport interface PackGaps {\n siblingGap: number;\n}\n\nexport interface PackResult {\n /** Subtree half-extents (cover the ENTIRE subtree). */\n halfL: number;\n halfR: number;\n /** Center offset of each child relative to this node's center (parallel to children). */\n offsets: number[];\n}\n\n/**\n * Span-packs a node's children into disjoint horizontal intervals (the fault-tree `pack`\n * transposed top-down). Children c1..cn: x1 = 0; x_{i+1} = x_i + halfR_i + siblingGap +\n * halfL_{i+1}. Parent axis a = (x1 + xn)/2 — centered over its line-report block. The\n * returned offsets are each child's center MINUS the parent axis. Subtree halfL/halfR\n * extend ownHalf* to cover the children block. Pure + deterministic.\n */\nexport function packSubtree(node: PackNode, gaps: PackGaps): PackResult {\n const { ownHalfL, ownHalfR, children } = node;\n if (children.length === 0) {\n return { halfL: ownHalfL, halfR: ownHalfR, offsets: [] };\n }\n const xs: number[] = [0];\n for (let i = 1; i < children.length; i++) {\n xs.push(xs[i - 1]! + children[i - 1]!.halfR + gaps.siblingGap + children[i]!.halfL);\n }\n const first = children[0]!;\n const last = children[children.length - 1]!;\n const axis = (xs[0]! + xs[xs.length - 1]!) / 2;\n const offsets = xs.map((x) => x - axis);\n const halfL = Math.max(ownHalfL, axis - (xs[0]! - first.halfL));\n const halfR = Math.max(ownHalfR, xs[xs.length - 1]! + last.halfR - axis);\n return { halfL, halfR, offsets };\n}\n\n// ── Box measurement (via core text metrics; what is reserved is what is drawn) ──────\n\ninterface Measured {\n boxW: number;\n boxH: number;\n nameLines: string[];\n titleLines: string[];\n subtitleLines: string[];\n vacantMarker: string | null;\n}\n\nfunction measurePosition(\n position: OrgPosition,\n maxLabelChars: number | undefined,\n vacantWord: string,\n): Measured {\n const nameLines =\n position.name === \"\" ? [] : wrapLabelBalanced(clampLabel(position.name, maxLabelChars), 2);\n const titleLines =\n position.title === null ? [] : wrapLabelBalanced(clampLabel(position.title, maxLabelChars), 2);\n const subtitleLines =\n position.subtitle === null ? [] : wrapLabelBalanced(clampLabel(position.subtitle, maxLabelChars), 1);\n const vacantMarker = position.vacancy === \"vacant\" ? vacantWord : null;\n\n let innerW = 0;\n for (const l of nameLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_LABEL_FONT));\n for (const l of titleLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_TITLE_FONT));\n for (const l of subtitleLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_TITLE_FONT));\n if (vacantMarker !== null) innerW = Math.max(innerW, estimateTextWidth(vacantMarker, ORG_TITLE_FONT));\n\n const boxW = Math.max(ORG_MIN_BOX_W, innerW + ORG_BOX_PAD_X * 2);\n const lineCount =\n nameLines.length + titleLines.length + subtitleLines.length + (vacantMarker !== null ? 1 : 0);\n const boxH = ORG_BOX_PAD_Y * 2 + lineCount * ORG_LABEL_LINE_H;\n return { boxW, boxH, nameLines, titleLines, subtitleLines, vacantMarker };\n}\n\nfunction positionTitle(position: OrgPosition, vacantWord: string): string {\n if (position.hover !== undefined) return position.hover;\n if (position.title !== null) {\n return position.name === \"\" ? position.title : `${position.name} — ${position.title}`;\n }\n if (position.name !== \"\") return position.name;\n return vacantWord; // vacant box with no name & no title — append the vacant word\n}\n\n// ── Internal working node (one per declared position; org positions never repeat) ──\n\ninterface Inst {\n position: OrgPosition;\n m: Measured;\n style: OrgBoxStyle;\n title: string;\n depth: number;\n /** Line-report children (ascending reportId), placed into the sibling rake. */\n lineChildren: Inst[];\n /** Assistant children (ascending reportId), side-stemmed left of the stem. */\n assistants: { inst: Inst; report: OrgReport }[];\n /** Reserved left/right half-extents of THIS node's own box (+ assistant reservation). */\n ownHalfL: number;\n ownHalfR: number;\n /** Subtree half-extents after packing. */\n spanL: number;\n spanR: number;\n /** Offset of each line-child center relative to this node's center. */\n offsets: number[];\n /** Absolute box center x (resolved top-down). */\n cx: number;\n /** Report row that made this an assistant (for the assist element's title/id). */\n assistReport: OrgReport | null;\n /** Absolute box top y for an assistant (set during emit; line nodes use rowTop[depth]). */\n assistTop: number;\n}\n\n/**\n * Deterministic, overlap-proof org-chart layout (pure function of the inputs). Validates\n * first and THROWS OrgChartValidationError on a structurally invalid chart — never\n * sanitizes. Empty input (no positions AND no reports) yields an empty, padded layout.\n */\nexport function computeOrgChartLayout(\n input: OrgChartInput,\n opts: OrgChartLayoutOptions = {},\n): OrgChartLayout {\n if (input.positions.length === 0 && input.reports.length === 0) {\n return { width: PADDING * 2, height: PADDING * 2, nodes: [], elements: [], rootPositionIds: [] };\n }\n validateOrgChart(input);\n\n const titleLabels = opts.titleLabels ?? ORG_CHART_TITLE_LABELS_EN;\n const vacantWord = titleLabels.vacant;\n const positionById = new Map(input.positions.map((p) => [p.id, p]));\n\n // Solid (line|assistant) edges only define the tree. id-sort for order-independence;\n // sibling order among reports is by ascending reportId.\n const reports = [...input.reports].sort((a, b) => a.id - b.id);\n const solidReports = reports.filter((r) => r.kind !== \"dotted\");\n\n // Build per-manager child buckets (line-reports + assistants), each ascending reportId.\n const lineChildIds = new Map<number, OrgReport[]>();\n const assistChildIds = new Map<number, OrgReport[]>();\n const solidParentReportId = new Set<number>(); // positions that have a solid parent\n for (const r of solidReports) {\n solidParentReportId.add(r.reportId);\n const bucket = r.kind === \"assistant\" ? assistChildIds : lineChildIds;\n const arr = bucket.get(r.managerId) ?? [];\n arr.push(r);\n bucket.set(r.managerId, arr);\n }\n for (const arr of lineChildIds.values()) arr.sort((a, b) => a.reportId - b.reportId);\n for (const arr of assistChildIds.values()) arr.sort((a, b) => a.reportId - b.reportId);\n\n // Roots: positions that are no solid edge's reportId, ascending id (forest order).\n const rootPositionIds = input.positions\n .map((p) => p.id)\n .filter((id) => !solidParentReportId.has(id))\n .sort((a, b) => a - b);\n\n // ── Build the instance tree per root over solid edges (each position once). ────────\n const newInst = (position: OrgPosition, depth: number, assistReport: OrgReport | null): Inst => {\n const m = measurePosition(position, opts.maxLabelChars, vacantWord);\n return {\n position,\n m,\n style: position.vacancy === \"vacant\" ? \"dashed\" : \"solid\",\n title: positionTitle(position, vacantWord),\n depth,\n lineChildren: [],\n assistants: [],\n ownHalfL: m.boxW / 2,\n ownHalfR: m.boxW / 2,\n spanL: 0,\n spanR: 0,\n offsets: [],\n cx: 0,\n assistReport,\n assistTop: 0,\n };\n };\n\n const allInsts: Inst[] = [];\n const build = (positionId: number, depth: number, assistReport: OrgReport | null): Inst => {\n const position = positionById.get(positionId)!;\n const inst = newInst(position, depth, assistReport);\n allInsts.push(inst);\n // Assistants live in the manager's corridor band: same row index as a line-report\n // (depth+1) for measurement, but they do NOT advance the row — STEP 4 handles that.\n for (const r of assistChildIds.get(positionId) ?? []) {\n const a = build(r.reportId, depth + 1, r);\n inst.assistants.push({ inst: a, report: r });\n }\n for (const r of lineChildIds.get(positionId) ?? []) {\n inst.lineChildren.push(build(r.reportId, depth + 1, null));\n }\n return inst;\n };\n const roots = rootPositionIds.map((id) => build(id, 0, null));\n\n // ── STEP 3 — assistant side-stem reservation (per-side LEFT, before packing). An\n // assistant adds ORG_ASSIST_GAP + max(assistantBoxW) to the manager's ownHalfL.\n // Vertical stacking never widens further. ─────────────────────────────────────────\n for (const inst of allInsts) {\n if (inst.assistants.length > 0) {\n const widest = inst.assistants.reduce((m, a) => Math.max(m, a.inst.m.boxW), 0);\n inst.ownHalfL = inst.m.boxW / 2 + ORG_ASSIST_GAP + widest;\n }\n }\n\n // ── STEP 2 — horizontal span-pack (post-order) via the PURE packSubtree. ───────────\n const gaps: PackGaps = { siblingGap: ORG_SIBLING_GAP };\n const pack = (inst: Inst): void => {\n for (const c of inst.lineChildren) pack(c);\n const result = packSubtree(\n {\n ownHalfL: inst.ownHalfL,\n ownHalfR: inst.ownHalfR,\n children: inst.lineChildren.map((c) => ({ halfL: c.spanL, halfR: c.spanR })),\n },\n gaps,\n );\n inst.spanL = result.halfL;\n inst.spanR = result.halfR;\n inst.offsets = result.offsets;\n };\n for (const root of roots) pack(root);\n\n // Absolute centers, top-down; forest trees laid left→right ORG_TREE_GAP apart.\n let cursor = PADDING;\n for (const root of roots) {\n root.cx = cursor + root.spanL;\n const placeX = (inst: Inst): void => {\n inst.lineChildren.forEach((c, i) => {\n c.cx = inst.cx + inst.offsets[i]!;\n placeX(c);\n });\n };\n placeX(root);\n cursor = root.cx + root.spanR + ORG_TREE_GAP;\n }\n const canvasRight = roots.length === 0 ? PADDING : cursor - ORG_TREE_GAP; // last root's right edge\n\n // ── STEP 4 — vertical rows by declared depth, with the corridor grown for assistants.\n const rowInsts: Inst[][] = [];\n for (const inst of allInsts) (rowInsts[inst.depth] ??= []).push(inst);\n const depthCount = rowInsts.length;\n\n // Assistant stack height hanging below a manager (sum of assistant boxH + band drops).\n const assistStackH = (inst: Inst): number => {\n if (inst.assistants.length === 0) return 0;\n return (\n inst.assistants.reduce((s, a) => s + a.inst.m.boxH + ORG_ASSIST_BAND_DROP, 0) + ORG_ASSIST_BAND_DROP\n );\n };\n\n const rowH: number[] = [];\n for (let d = 0; d < depthCount; d++) {\n // Row height = tallest LINE-REPORT box in the row (assistants excluded — they hang\n // in the corridor band, not the row). Assistants share a depth index but are not\n // line-children of anyone, so filter them out here.\n const lineBoxes = (rowInsts[d] ?? []).filter((i) => i.assistReport === null);\n rowH.push(lineBoxes.reduce((m, i) => Math.max(m, i.m.boxH), 0));\n }\n\n // Assistant zone below row d: the tallest assistant stack hanging off any manager in\n // row d. Reserved ABOVE the corridor (the fault-tree gateZone analog) so the bus sits\n // CORRIDOR/2 below the BOTTOM of every assistant stack — every assistant box (and its\n // elbow) is strictly above the bus, and every drop (busY → next row) is below it.\n const assistZone: number[] = [];\n for (let d = 0; d < depthCount; d++) {\n let tallest = 0;\n for (const inst of rowInsts[d] ?? []) tallest = Math.max(tallest, assistStackH(inst));\n assistZone.push(tallest);\n }\n\n const rowTop: number[] = [PADDING];\n for (let d = 0; d < depthCount - 1; d++) {\n rowTop.push(rowTop[d]! + rowH[d]! + assistZone[d]! + ORG_CORRIDOR);\n }\n const busY = (d: number): number => rowTop[d + 1]! - ORG_CORRIDOR / 2;\n\n const last = depthCount - 1;\n // The last row's managers cannot have line-reports below them, but a leaf manager in\n // the last row carries no assistants of its own row index either (assistants share the\n // child's depth) — assistZone[last] folds any trailing assistant stack into the height.\n const height = Math.ceil(rowTop[last]! + rowH[last]! + assistZone[last]! + PADDING);\n\n // ── Emit nodes + solid rake elements (DFS order per root). ─────────────────────────\n const nodes: OrgNode[] = [];\n const elements: OrgElement[] = [];\n\n const reportTitle = (kind: OrgReport[\"kind\"], label: string | null | undefined): string => {\n const word = titleLabels.reportKinds[kind];\n return label !== null && label !== undefined ? `${word} · ${label}` : word;\n };\n\n const pushNode = (inst: Inst): void => {\n nodes.push({\n positionId: inst.position.id,\n cx: round(inst.cx),\n top: round(rowTop[inst.depth]!),\n boxW: round(inst.m.boxW),\n boxH: round(inst.m.boxH),\n style: inst.style,\n nameLines: inst.m.nameLines,\n titleLines: inst.m.titleLines,\n subtitleLines: inst.m.subtitleLines,\n vacantMarker: inst.m.vacantMarker,\n isAssistant: inst.assistReport !== null,\n depth: inst.depth,\n title: inst.title,\n });\n };\n\n const emit = (inst: Inst): void => {\n const d = inst.depth;\n\n // Assistants: top-aligned bands hanging in this manager's corridor (below its row),\n // each its own band-y, the box LEFT of the stem (right edge faces the stem), the\n // elbow a 2-segment orthogonal polyline staying in the reserved left gutter.\n let bandY = rowTop[d]! + rowH[d]! + ORG_ASSIST_BAND_DROP;\n for (const { inst: a, report } of inst.assistants) {\n // Reserved left gutter: stem at inst.cx; assistant box right edge ORG_ASSIST_GAP left.\n const assistRight = inst.cx - ORG_ASSIST_GAP;\n a.cx = assistRight - a.m.boxW / 2;\n // Position the assistant box top at the band-y; its row index (depth) is the same\n // band as a line-report but rowTop[depth] is the line-report row — override per box.\n const assistTop = bandY;\n a.assistTop = assistTop;\n const assistMidY = assistTop + a.m.boxH / 2;\n nodes.push({\n positionId: a.position.id,\n cx: round(a.cx),\n top: round(assistTop),\n boxW: round(a.m.boxW),\n boxH: round(a.m.boxH),\n style: a.style,\n nameLines: a.m.nameLines,\n titleLines: a.m.titleLines,\n subtitleLines: a.m.subtitleLines,\n vacantMarker: a.m.vacantMarker,\n isAssistant: true,\n depth: a.depth,\n title: a.title,\n });\n // Elbow: from the stem at the assistant's mid-y, horizontally LEFT to the box's\n // right edge (2 axis-aligned segments via 3 waypoints; first segment degenerate is\n // avoided because the stem x ≠ box-right x by ORG_ASSIST_GAP). The endpoint must land\n // on the assistant's DRAWN right edge — round(assistRight) (= managerCx − gap) rounds\n // a sub-cent off the box's own round(node.cx − node.boxW/2) edge (seed-103792 sliver).\n elements.push({\n edgeId: ORG_ASSIST_ID_BASE + report.reportId,\n kind: \"assist\",\n points: [\n { x: round(inst.cx), y: round(assistMidY) },\n { x: drawnRightEdge(a.cx, a.m.boxW), y: round(assistMidY) },\n ],\n dashed: false,\n title: reportTitle(\"assistant\", report.label),\n });\n bandY += a.m.boxH + ORG_ASSIST_BAND_DROP;\n }\n\n pushNode(inst);\n\n // Solid rake to line-reports (none → no stem/bus/drop).\n if (inst.lineChildren.length === 0) return;\n const by = busY(d);\n const boxBottom = rowTop[d]! + inst.m.boxH;\n\n // stem: manager box bottom-center → bus level. Vertical. (Lengthens to busY when the\n // box is shorter than its row's tallest — the row is top-aligned.)\n elements.push({\n edgeId: ORG_STEM_ID_BASE + inst.position.id,\n kind: \"stem\",\n points: [\n { x: round(inst.cx), y: round(boxBottom) },\n { x: round(inst.cx), y: round(by) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n });\n\n const childCxs = inst.lineChildren.map((c) => c.cx);\n // bus: only for ≥2 line-reports (a single report degenerates to stem + drop on one x).\n if (inst.lineChildren.length > 1) {\n elements.push({\n edgeId: ORG_BUS_ID_BASE + inst.position.id,\n kind: \"bus\",\n points: [\n { x: round(Math.min(...childCxs)), y: round(by) },\n { x: round(Math.max(...childCxs)), y: round(by) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n });\n }\n\n // drop: bus → each line-report box top-center. Vertical.\n for (const c of inst.lineChildren) {\n elements.push({\n edgeId: ORG_DROP_ID_BASE + c.position.id,\n kind: \"drop\",\n points: [\n { x: round(c.cx), y: round(by) },\n { x: round(c.cx), y: round(rowTop[c.depth]!) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n });\n }\n\n for (const c of inst.lineChildren) emit(c);\n };\n for (const root of roots) emit(root);\n\n // ── STEP 6 — dotted/matrix overlay → reserved RIGHT-MARGIN GUTTER (vertical lane) +\n // a bottom traverse channel (horizontal runs). The decisive graft is the gutter at\n // x > every box's right edge — box-free by construction for the vertical lane. The\n // horizontal runs that REACH the gutter cannot sit at a box's mid-y (they would\n // cross intervening same-row boxes — the \"distant columns of same row\" adversarial\n // case), so each endpoint ESCAPES its box to a box-free column, drops into a bottom\n // channel below every box, and traverses horizontally there. A box-free escape\n // column exists at the SUBTREE right edge (cx + spanR): descendants live inside\n // [cx−spanL, cx+spanR] so their interiors never cross that boundary x, and the next\n // sibling subtree starts ORG_SIBLING_GAP further right. A GLOBAL escape-vertical lane\n // allocation (below) keeps every coincident drop (a shared endpoint's fan, a same-column\n // rep/mgr pair, OR two distinct nodes whose subtree-right boundary equals the same x)\n // from double-drawing. Result is fully orthogonal AND box-free; the harness proves it.\n //\n // Escape geometry per node: the box edge a dotted stub exits and the box-free column it\n // escapes to, SIDE-AWARE. A packed LINE node escapes RIGHT: stub exits its right edge\n // (cx + boxW/2) to the subtree-boundary column (cx + spanR), box-free because descendants\n // live inside [cx−spanL, cx+spanR] and the next sibling starts ORG_SIBLING_GAP further\n // right. An ASSISTANT is NOT packed and sits LEFT of its manager's stem — its right edge\n // is INSIDE the main line-report column, so escaping right would pierce those boxes\n // (defect B). It escapes LEFT instead: stub exits its left edge (cx − boxW/2) into its\n // RESERVED left gutter (cleared in STEP 3 via ORG_ASSIST_GAP), a small box-free band.\n // `side` (+1 right / −1 left) makes the per-endpoint slot offset push AWAY from the box,\n // staying box-free in either gutter.\n interface Escape {\n side: 1 | -1;\n /** Box edge the stub exits (right edge when side=+1, left edge when side=−1). */\n boxEdge: number;\n /** Box-free escape column the stub reaches (with slot 0). */\n escCol: number;\n midY: number;\n boxH: number;\n }\n // FIX 1 — an assistant escapes at its MANAGER's subtree-LEFT boundary, not at its own\n // leftEdge−gap. The own-leftEdge column is box-free only inside the assistant's OWN\n // corridor band; descending to the bottom channel it crosses line-report/assistant boxes\n // in LOWER rows that sit at that x (root cause 1). The manager's WHOLE subtree lives\n // inside [managerCx−spanL, managerCx+spanR], so managerCx−spanL is to the LEFT of every\n // box in the manager's subtree — the strip there is the manager's reserved left gutter,\n // clear down the entire canvas (the next left sibling is ORG_SIBLING_GAP further left).\n // The box-exit stub still leaves the assistant's LEFT edge and runs left to that column\n // at the assistant's band-y (box-free: that row strip is the manager's left gutter).\n const instByPos = new Map(allInsts.map((i) => [i.position.id, i]));\n const escapeByPos = new Map<number, Escape>();\n for (const inst of allInsts) {\n const isAssist = inst.assistReport !== null;\n const boxTop = isAssist ? inst.assistTop : rowTop[inst.depth]!;\n // Attach the matrix stub at the box edges AS DRAWN (seed-7763 dotted#0 × box#p1 sliver).\n const leftEdge = drawnLeftEdge(inst.cx, inst.m.boxW);\n const rightEdge = drawnRightEdge(inst.cx, inst.m.boxW);\n if (isAssist) {\n const managerInst = instByPos.get(inst.assistReport!.managerId)!;\n escapeByPos.set(inst.position.id, {\n side: -1,\n boxEdge: leftEdge,\n escCol: managerInst.cx - managerInst.spanL,\n midY: boxTop + inst.m.boxH / 2,\n boxH: inst.m.boxH,\n });\n } else {\n escapeByPos.set(inst.position.id, {\n side: 1,\n boxEdge: rightEdge,\n escCol: inst.cx + inst.spanR,\n midY: boxTop + inst.m.boxH / 2,\n boxH: inst.m.boxH,\n });\n }\n }\n\n const nodeById = new Map(nodes.map((n) => [n.positionId, n]));\n const dottedReports = reports.filter(\n (r) => r.kind === \"dotted\" && nodeById.has(r.managerId) && nodeById.has(r.reportId) && r.managerId !== r.reportId,\n );\n // Bottom channel sits below the tallest box bottom in the whole canvas.\n let maxBoxBottom = PADDING;\n for (const n of nodes) maxBoxBottom = Math.max(maxBoxBottom, n.top + n.boxH);\n\n let laneCount = 0;\n let channelLanes = 0;\n if (dottedReports.length > 0) {\n // Right-gutter vertical lanes packed by the two endpoints' y-interval (ascending\n // report.id — dottedReports is already id-sorted). Non-overlapping edges share a lane.\n const laneOf = new Map<number, number>();\n laneCount = allocateLanes(\n dottedReports.map((r) => {\n const rep = escapeByPos.get(r.reportId)!;\n const mgr = escapeByPos.get(r.managerId)!;\n return {\n lo: Math.min(rep.midY, mgr.midY),\n hi: Math.max(rep.midY, mgr.midY),\n set: (lane: number) => laneOf.set(r.id, lane),\n };\n }),\n );\n // Each edge gets TWO bottom-channel y-lanes (report-side + manager-side traverse) so\n // the two horizontals never collinear-overlap each other; indexed by edge order.\n channelLanes = dottedReports.length * 2;\n const channelTop = maxBoxBottom + ORG_MATRIX_GUTTER_GAP;\n // Per-endpoint exit-Y slots: when ONE box is the endpoint of several dotted edges (a\n // node that is the dotted target of N managers — the matrix fan), each edge must exit\n // that box's edge at a DISTINCT y, else their horizontal stubs collinear-overlap.\n // Spread the exit y's around the box mid-y, bounded inside the box's edge.\n const exitSlot = new Map<number, number>(); // positionId → next slot index\n const nextExitY = (posId: number, mid: number, boxH: number): number => {\n const slot = exitSlot.get(posId) ?? 0;\n exitSlot.set(posId, slot + 1);\n if (slot === 0) return mid;\n // Alternate above/below the mid-y; stay within ±(boxH/2 − 6) of the box center.\n const step = Math.min(6, Math.max(2, (boxH / 2 - 6) / Math.max(1, Math.ceil(slot / 2))));\n const sign = slot % 2 === 1 ? -1 : 1;\n return mid + sign * Math.ceil(slot / 2) * step;\n };\n\n // ── Per-edge x-INDEPENDENT geometry, computed FIRST (the escape-column x is decided\n // globally afterwards). exitY spreads same-node rows; chY is unique per edge. ──────\n interface EdgeGeom {\n r: (typeof dottedReports)[number];\n i: number;\n repMidY: number;\n mgrMidY: number;\n repBoxEdge: number;\n mgrBoxEdge: number;\n repChY: number;\n mgrChY: number;\n laneX: number;\n repEscX: number; // filled by the global escape-vertical lane allocation\n mgrEscX: number;\n }\n const geoms: EdgeGeom[] = dottedReports.map((r, i) => {\n const rep = escapeByPos.get(r.reportId)!;\n const mgr = escapeByPos.get(r.managerId)!;\n return {\n r,\n i,\n repMidY: round(nextExitY(r.reportId, rep.midY, rep.boxH)),\n mgrMidY: round(nextExitY(r.managerId, mgr.midY, mgr.boxH)),\n repBoxEdge: round(rep.boxEdge),\n mgrBoxEdge: round(mgr.boxEdge),\n repChY: round(channelTop + (2 * i) * ORG_MATRIX_LANE_PITCH),\n mgrChY: round(channelTop + (2 * i + 1) * ORG_MATRIX_LANE_PITCH),\n laneX: round(canvasRight + ORG_MATRIX_GUTTER_GAP + laneOf.get(r.id)! * ORG_MATRIX_LANE_PITCH),\n repEscX: 0,\n mgrEscX: 0,\n };\n });\n\n // ── GLOBAL escape-vertical LANE ALLOCATION (replaces the per-position slot nudge and the\n // rep===mgr special-case — both subsumed). Every dotted edge owns TWO escape verticals\n // (report side, manager side); each draws over the y-interval [min(exitY,chY),\n // max(exitY,chY)]. We GROUP verticals by `${round(escCol)}:${side}` — same base column\n // AND same escape direction — then run allocateLanes over the group's y-intervals: a\n // vertical's column x = round(escCol + side*lane*STEP). Disjoint-y verticals share a lane\n // (same x, never a double-draw because they don't overlap); OVERLAPPING-y verticals get\n // distinct lanes (distinct x). This is overlap-proof for the escape-column class BY\n // CONSTRUCTION and uniformly subsumes the three observed failure modes: same-node fan\n // (same column, overlapping y → distinct lanes), same-column rep/mgr pair in a single-\n // child chain (the old fix-C special case), AND the cross-node coincidence (two distinct\n // nodes whose subtree-right boundary equals the same x — Root vs Boss C: base 448,\n // overlapping y → lanes 0 and 1).\n //\n // BOX-FREE BOUND (geometry-exact, MEASURED — not a fixed gap): a right-escaping (line) node's\n // base escCol = cx + spanR is the subtree's right boundary; all its descendant boxes live\n // inside [cx−spanL, cx+spanR], so the base column AND the band immediately to its right are\n // box-free until the NEXT box (an immediate right sibling subtree starts ORG_SIBLING_GAP away;\n // a pure right-leaning chain with no right sibling has the whole right margin clear). A left-\n // escaping assistant's base is leftEdge−ORG_ASSIST_ESCAPE_GAP, box-free leftward through its\n // reserved ORG_ASSIST_GAP gutter. Nudged columns march in `side` by lane*STEP, deeper into that\n // band. Rather than assume a fixed gutter width, we MEASURE the actual band per group: the\n // distance from escCol to the nearest real box edge on the escape side that vertically overlaps\n // the group's combined y-span (canvasRight/left-margin when none blocks). A coincident base\n // column is only produced by a right-leaning spine (each ancestor's cx+spanR equals the spine-\n // tip's right edge — many verticals, but their tip subtree is the RIGHTMOST so the margin to\n // their right is wide) or a fan into one node (per-node dotted degree capped at 5 in\n // validate.ts, ORG_MAX_MATRIX_EDGES_PER_NODE). The GUARANTEE: the deepest lane (lanes−1)*STEP\n // stays strictly inside the measured band, or we ASSERT (escape-column-overflow) rather than\n // misdraw. This is overlap-proof for the escape-column class BY CONSTRUCTION against the real\n // geometry; the harness is the oracle on every corpus case (incl. a depth-5 spine with 10\n // coincident verticals on one base column, which the wide margin absorbs).\n interface EscVert {\n escCol: number;\n side: 1 | -1;\n lo: number;\n hi: number;\n assign: (x: number) => void;\n }\n const verts: EscVert[] = [];\n for (const g of geoms) {\n const rep = escapeByPos.get(g.r.reportId)!;\n const mgr = escapeByPos.get(g.r.managerId)!;\n verts.push({\n escCol: rep.escCol,\n side: rep.side,\n lo: Math.min(g.repMidY, g.repChY),\n hi: Math.max(g.repMidY, g.repChY),\n assign: (x) => (g.repEscX = x),\n });\n verts.push({\n escCol: mgr.escCol,\n side: mgr.side,\n lo: Math.min(g.mgrMidY, g.mgrChY),\n hi: Math.max(g.mgrMidY, g.mgrChY),\n assign: (x) => (g.mgrEscX = x),\n });\n }\n // FIX 2 — GLOBAL greedy first-fit (replaces the per-group allocateLanes, which de-conflicted\n // only WITHIN one base-column group → a nudged column from group X could land on group Y's\n // column with overlapping y, double-drawing — root cause 2). Here NO two y-overlapping escape\n // verticals ever share a final x, across ALL groups. Each vertical starts at its base column and\n // steps in its escape `side` by ORG_MATRIX_ESCAPE_STEP until its x is clear of every already-placed\n // vertical it shares y with. Collinear-overlap = 0 BY CONSTRUCTION, globally (subsumes both the\n // per-group fan de-confliction AND the cross-group coincidence). Deterministic processing order\n // (edge id, then side) → byte-stable output. Box-free BAND is still measured per vertical and the\n // existing escape-column-overflow assertion fires rather than misdraw; with FIX 1 + the per-node\n // cap of 5 it should never fire on realistic input (the fuzzer confirms).\n //\n // The de-confliction nudge marches in the SAME direction the stub exits (`side`) — AWAY from the\n // node's box, into its box-free band. A LINE node's base column is its subtree-RIGHT boundary\n // (cx+spanR); everything to its right is clear out to canvasRight, so it nudges RIGHT. An ASSISTANT\n // escapes at its manager's subtree-LEFT boundary (managerCx−spanL, FIX 1); EVERY box in that\n // subtree lives to its right (a descendant box's left edge may sit EXACTLY on the boundary), so the\n // box-free room is to the LEFT — toward the canvas edge / the previous tree's gutter — and it nudges\n // LEFT. Nudging the assistant right would step straight into the leftmost descendant box, nudging\n // left stays in the clear margin. The box-exit stub runs from the assistant's left edge to the\n // (nudged) column at the assistant's band-y, box-free either way.\n const VERT_EPS = 0.01;\n // Stable processing order = edge id, then side (report-side before manager-side). `verts` is\n // built [rep0, mgr0, rep1, mgr1, …] over the id-sorted geoms, so the natural index ALREADY\n // encodes (edgeId asc, rep<mgr); make it explicit so a refactor of `verts` can't perturb it.\n const ordered = verts\n .map((v, idx) => ({ v, key: geoms[Math.floor(idx / 2)]!.r.id * 2 + (idx % 2) }))\n .sort((a, b) => a.key - b.key)\n .map((e) => e.v);\n const placed: { x: number; lo: number; hi: number }[] = [];\n const yOverlap = (aLo: number, aHi: number, bLo: number, bHi: number): boolean =>\n Math.min(aHi, bHi) - Math.max(aLo, bLo) > VERT_EPS;\n for (const v of ordered) {\n // Box-free band on the escape side, MEASURED from the real boxes that vertically overlap THIS\n // vertical's y-span: the candidate may march up to (but not into) the nearest box edge on that\n // side. The base column itself is box-free by construction (subtree-right boundary on the right;\n // manager's subtree-left boundary on the left). With no box in the way the band runs to the tree's\n // right edge (canvasRight) on the right, or to the CANVAS edge (x=0) on the left — NOT to PADDING,\n // because the leftmost tree's left boundary sits at PADDING yet the margin down to x=0 is clear.\n let band = v.side === 1 ? Math.max(canvasRight - v.escCol, ORG_MATRIX_GUTTER_GAP) : v.escCol;\n for (const n of nodes) {\n const bLeft = n.cx - n.boxW / 2;\n const bRight = n.cx + n.boxW / 2;\n if (n.top + n.boxH <= v.lo + VERT_EPS || n.top >= v.hi - VERT_EPS) continue; // no y-overlap\n if (v.side === 1 && bLeft > v.escCol + VERT_EPS) band = Math.min(band, bLeft - v.escCol);\n else if (v.side === -1 && bRight < v.escCol - VERT_EPS) band = Math.min(band, v.escCol - bRight);\n }\n let lane = 0;\n let candidate = round(v.escCol);\n // Step away from the box (in `side`) until the candidate column is clear of every placed vertical\n // that shares y with this one.\n while (placed.some((p) => Math.abs(p.x - candidate) < VERT_EPS && yOverlap(p.lo, p.hi, v.lo, v.hi))) {\n lane += 1;\n candidate = round(v.escCol + v.side * lane * ORG_MATRIX_ESCAPE_STEP);\n }\n // A lane-0 vertical sits on its base column — box-free BY CONSTRUCTION, so it needs no band\n // check. A NUDGED vertical must stay strictly inside the measured box-free band, else we assert\n // rather than misdraw.\n if (lane > 0 && lane * ORG_MATRIX_ESCAPE_STEP >= band - VERT_EPS) {\n throw new Error(\n `org-chart: escape-column-overflow — escape vertical nudged ${lane * ORG_MATRIX_ESCAPE_STEP}px from its base column exceeds the ${round(band)}px box-free band`,\n );\n }\n placed.push({ x: candidate, lo: v.lo, hi: v.hi });\n v.assign(candidate);\n }\n\n for (const g of geoms) {\n // 8 waypoints (box edge → escape column → channel → lane → channel → escape column →\n // box edge). Collapse a DEGENERATE first/last stub: a leaf line node's box edge IS its\n // escape column (boxW/2 === spanR with lane 0), so the box-exit and the down-escape\n // share an x → drop the duplicate point so \"every consecutive pair axis-aligned\" holds\n // by construction (no zero-length segment).\n elements.push({\n edgeId: ORG_DOTTED_ID_BASE + g.r.id,\n kind: \"dotted\",\n points: collapseDegenerate([\n { x: g.repBoxEdge, y: g.repMidY }, // out the report box's edge\n { x: g.repEscX, y: g.repMidY }, // → box-free escape column (in own gutter lane)\n { x: g.repEscX, y: g.repChY }, // → down into the bottom traverse channel\n { x: g.laneX, y: g.repChY }, // → across (below all boxes) to the right gutter lane\n { x: g.laneX, y: g.mgrChY }, // → down the right gutter (right of every box)\n { x: g.mgrEscX, y: g.mgrChY }, // → back across (below all boxes) to the manager column\n { x: g.mgrEscX, y: g.mgrMidY }, // → up the box-free escape column\n { x: g.mgrBoxEdge, y: g.mgrMidY }, // → into the manager box's edge\n ]),\n dashed: true,\n title: reportTitle(\"dotted\", g.r.label),\n });\n }\n }\n\n const width =\n dottedReports.length > 0\n ? Math.ceil(canvasRight + ORG_MATRIX_GUTTER_GAP + (laneCount - 1) * ORG_MATRIX_LANE_PITCH + ORG_MATRIX_GUTTER_GAP + PADDING)\n : Math.ceil(canvasRight + PADDING);\n\n // When dotted edges exist the bottom traverse channel hangs below every box; grow the\n // height to cover the deepest channel lane + padding (else solid-tree height stands).\n const finalHeight =\n channelLanes > 0\n ? Math.ceil(maxBoxBottom + ORG_MATRIX_GUTTER_GAP + (channelLanes - 1) * ORG_MATRIX_LANE_PITCH + PADDING)\n : height;\n\n return { width, height: finalHeight, nodes, elements, rootPositionIds };\n}\n\n/** Drop consecutive duplicate waypoints (a zero-length segment) so the routed polyline\n * keeps the \"≥2 waypoints, every consecutive pair axis-aligned over a positive length\"\n * contract by construction — e.g. a leaf line node whose box edge IS its escape column.\n * A two-point result is preserved even if degenerate (cannot happen here: the channel\n * detour guarantees ≥4 distinct points), so the OrgElement.points ≥2 invariant holds. */\nfunction collapseDegenerate(points: Point[]): Point[] {\n const out: Point[] = [];\n for (const p of points) {\n const prev = out[out.length - 1];\n if (prev === undefined || prev.x !== p.x || prev.y !== p.y) out.push(p);\n }\n return out;\n}\n\n/** Allocate lanes for a set of y-intervals: each takes the lowest lane free over its span\n * (touching at an endpoint does NOT count as overlap, so abutting edges may share). Mirror\n * of the genogram allocateLanes (src/genogram/layout.ts) — keeps the gutter narrow. */\nfunction allocateLanes(items: { lo: number; hi: number; set: (lane: number) => void }[]): number {\n const lanes: { lo: number; hi: number }[][] = [];\n for (const it of items) {\n let chosen = -1;\n for (let l = 0; l < lanes.length; l++) {\n if (lanes[l]!.every((o) => it.hi <= o.lo || it.lo >= o.hi)) {\n chosen = l;\n break;\n }\n }\n if (chosen === -1) {\n chosen = lanes.length;\n lanes.push([]);\n }\n lanes[chosen]!.push({ lo: it.lo, hi: it.hi });\n it.set(chosen);\n }\n return lanes.length;\n}\n","// Org-chart SVG emitter — turns a computed OrgChartLayout (./layout.ts) into a\n// SELF-CONTAINED SVG string. Pure (layout in, string out) and deterministic; it draws\n// EXACTLY what the layout computed (the overlap harness proves the layout; this emitter\n// is pinned to it).\n//\n// Hard requirements (house rules):\n// - XML-ESCAPING of EVERY interpolated text — names/titles/subtitles/titles are\n// author-controlled and the SVG may be injected via innerHTML or embedded in PDFs;\n// - LITERAL presentation attributes only (hex colors, explicit font-family): a\n// standalone SVG has no stylesheet, no currentColor, no <defs>/<marker>;\n// - every coordinate goes through round() — 2-decimal, byte-deterministic output.\n//\n// Notation (zinc ramp on white): box rect rx=2 (filled → solid stroke; vacant → dashed\n// stroke + a 3px-inset open-seat frame); centered stacked tspans differentiated by font\n// SIZE (name 12, title/subtitle/vacant 10), never weight; solid stem/bus/drop/assist\n// edges as #71717a w1.5 op .75; dotted via EDGE_STROKE.distant (dasharray 4,4 op .55).\n// NO markers/arrowheads — direction is encoded by manager-above/report-below.\n//\n// Hooks: `<g data-node-id=\"p<id>\">` per box (direct-child verbatim <title>);\n// `<g data-edge-id=\"<n>\">` per element (<title> first), namespaced ids from ./layout.ts.\n\nimport { EDGE_STROKE, FONT_FAMILY, legendBlock, pathData, xmlEscape, LEGEND_SWATCH_W, type LegendEntry } from \"../core\";\nimport {\n ORG_LABEL_FONT,\n ORG_LABEL_LINE_H,\n ORG_TITLE_FONT,\n type OrgChartLayout,\n type OrgElement,\n type OrgNode,\n} from \"./layout\";\nimport { ORG_CHART_SVG_LABELS_EN, type OrgChartSvgLabels } from \"./labels\";\n\n// Literal ink colors (zinc ramp on white — matches the genogram/ecomap/fault-tree emitters).\nconst GLYPH_STROKE = \"#52525b\";\nconst LABEL_FILL = \"#3f3f46\";\nconst EDGE_INK = \"#71717a\";\nconst GLYPH_ATTRS = `fill=\"transparent\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"2\"`;\nconst VACANT_DASH = `stroke-dasharray=\"6,4\"`;\n/** The dotted/matrix line presentation, reused from the core style table (NOT a judgment). */\nconst DOTTED = EDGE_STROKE.distant; // { width: 1.5, dash: [4, 4], opacity: 0.55 }\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// Box vertical padding (mirrors layout ORG_BOX_PAD_Y; the text baseline math needs it).\nconst ORG_BOX_PAD_Y = 9;\n\nexport interface OrgChartSvgOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary (legend/accessibility) — English default; see locale packs. */\n labels?: OrgChartSvgLabels;\n}\n\n// ── Box ─────────────────────────────────────────────────────────────────────────────\n\nfunction boxSvg(n: OrgNode): string {\n const left = round(n.cx - n.boxW / 2);\n const pieces: string[] = [`<title>${xmlEscape(n.title)}</title>`];\n\n // Rect: filled → solid stroke; vacant → dashed stroke + a 3px-inset open-seat frame.\n if (n.style === \"dashed\") {\n pieces.push(\n `<rect x=\"${left}\" y=\"${n.top}\" width=\"${n.boxW}\" height=\"${n.boxH}\" rx=\"2\" ${GLYPH_ATTRS} ${VACANT_DASH}/>`,\n );\n const ix = round(left + 3);\n const iy = round(n.top + 3);\n const iw = round(n.boxW - 6);\n const ih = round(n.boxH - 6);\n pieces.push(`<rect x=\"${ix}\" y=\"${iy}\" width=\"${iw}\" height=\"${ih}\" rx=\"2\" ${GLYPH_ATTRS} ${VACANT_DASH}/>`);\n } else {\n pieces.push(`<rect x=\"${left}\" y=\"${n.top}\" width=\"${n.boxW}\" height=\"${n.boxH}\" rx=\"2\" ${GLYPH_ATTRS}/>`);\n }\n\n // Centered stacked tspans: name (12) → title (10) → subtitle (10) → vacant marker (10).\n // Differentiated by font SIZE, not weight. Each text element groups one font size so\n // a single <text font-size> covers its tspans (baseline stepping by ORG_LABEL_LINE_H).\n let lineIndex = 0;\n const firstBaseline = (i: number): number =>\n round(n.top + ORG_BOX_PAD_Y + ORG_LABEL_LINE_H / 2 + i * ORG_LABEL_LINE_H + ORG_LABEL_FONT * 0.32);\n\n const textBlock = (lines: string[], font: number): string => {\n if (lines.length === 0) return \"\";\n const tspans = lines\n .map((line, i) => `<tspan x=\"${n.cx}\" y=\"${firstBaseline(lineIndex + i)}\">${xmlEscape(line)}</tspan>`)\n .join(\"\");\n lineIndex += lines.length;\n return `<text text-anchor=\"middle\" font-family=\"${FONT_FAMILY}\" font-size=\"${font}\" fill=\"${LABEL_FILL}\">${tspans}</text>`;\n };\n\n pieces.push(textBlock(n.nameLines, ORG_LABEL_FONT));\n pieces.push(textBlock(n.titleLines, ORG_TITLE_FONT));\n pieces.push(textBlock(n.subtitleLines, ORG_TITLE_FONT));\n if (n.vacantMarker !== null) pieces.push(textBlock([n.vacantMarker], ORG_TITLE_FONT));\n\n return `<g data-node-id=\"p${n.positionId}\">${pieces.filter((p) => p !== \"\").join(\"\")}</g>`;\n}\n\n// ── Connector elements ───────────────────────────────────────────────────────────────\n\nfunction elementSvg(el: OrgElement): string {\n const head = `<g data-edge-id=\"${el.edgeId}\"><title>${xmlEscape(el.title)}</title>`;\n if (el.dashed) {\n const dash = DOTTED.dash === null ? \"\" : ` stroke-dasharray=\"${DOTTED.dash[0]},${DOTTED.dash[1]}\"`;\n return (\n head +\n `<path d=\"${pathData(el.points)}\" fill=\"none\" stroke=\"${EDGE_INK}\" stroke-width=\"${DOTTED.width}\" stroke-opacity=\"${DOTTED.opacity}\"${dash}/></g>`\n );\n }\n // Solid stem/bus/drop = single segment <line>; assist = 2-segment <path>.\n if (el.points.length === 2) {\n const a = el.points[0]!;\n const b = el.points[1]!;\n return (\n head +\n `<line x1=\"${a.x}\" y1=\"${a.y}\" x2=\"${b.x}\" y2=\"${b.y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/></g>`\n );\n }\n return head + `<path d=\"${pathData(el.points)}\" fill=\"none\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/></g>`;\n}\n\n// ── Legend mini-swatches (scaled into the 22px swatch box) ─────────────────────────\n\nconst MINI_ATTRS = `fill=\"transparent\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"`;\n\nfunction lineSwatch(x: number, y: number): string {\n const x1 = round(x + 2);\n const x2 = round(x + LEGEND_SWATCH_W - 2);\n return `<line x1=\"${x1}\" y1=\"${y}\" x2=\"${x2}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n}\n\nfunction assistantSwatch(x: number, y: number): string {\n // A short stem + side-elbow into a small box (the side-stem convention in miniature).\n const stemX = round(x + LEGEND_SWATCH_W - 4);\n const boxX = round(x + 1);\n return (\n `<line x1=\"${stemX}\" y1=\"${round(y - 4)}\" x2=\"${stemX}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>` +\n `<line x1=\"${stemX}\" y1=\"${y}\" x2=\"${round(boxX + 8)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>` +\n `<rect x=\"${boxX}\" y=\"${round(y - 3.5)}\" width=\"8\" height=\"7\" rx=\"1\" ${MINI_ATTRS}/>`\n );\n}\n\nfunction dottedSwatch(x: number, y: number): string {\n const x1 = round(x + 2);\n const x2 = round(x + LEGEND_SWATCH_W - 2);\n const dash = DOTTED.dash === null ? \"\" : ` stroke-dasharray=\"${DOTTED.dash[0]},${DOTTED.dash[1]}\"`;\n return `<line x1=\"${x1}\" y1=\"${y}\" x2=\"${x2}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"${DOTTED.width}\" stroke-opacity=\"${DOTTED.opacity}\"${dash}/>`;\n}\n\nfunction vacantSwatch(x: number, y: number): string {\n const cx = round(x + LEGEND_SWATCH_W / 2);\n const bx = round(cx - 8);\n const by = round(y - 5);\n return (\n `<rect x=\"${bx}\" y=\"${by}\" width=\"16\" height=\"10\" rx=\"1\" ${MINI_ATTRS} stroke-dasharray=\"3,2\"/>` +\n `<rect x=\"${round(bx + 2)}\" y=\"${round(by + 2)}\" width=\"12\" height=\"6\" rx=\"1\" ${MINI_ATTRS} stroke-dasharray=\"3,2\"/>`\n );\n}\n\n/**\n * Emits a self-contained SVG for a computed org-chart layout. Pure + deterministic.\n * Coordinates come straight from the layout; all interpolated text is XML-escaped; all\n * presentation attributes are literal. The legend lists ONLY the features actually\n * present (a solid line, an assistant, a dotted edge, a vacant box), in canonical order.\n */\nexport function orgChartLayoutSvg(layout: OrgChartLayout, opts: OrgChartSvgOptions = {}): string {\n const labels = opts.labels ?? ORG_CHART_SVG_LABELS_EN;\n const parts: string[] = [];\n\n // Elements first, then boxes (boxes sit on top), then legend.\n for (const el of layout.elements) parts.push(elementSvg(el));\n for (const n of layout.nodes) parts.push(boxSvg(n));\n\n let width = layout.width;\n let height = layout.height;\n if (opts.legend !== false && layout.nodes.length > 0) {\n const hasSolid = layout.elements.some((e) => e.kind === \"stem\" || e.kind === \"bus\" || e.kind === \"drop\");\n const hasAssistant = layout.nodes.some((n) => n.isAssistant);\n const hasDotted = layout.elements.some((e) => e.kind === \"dotted\");\n const hasVacant = layout.nodes.some((n) => n.style === \"dashed\");\n const entries: LegendEntry[] = [];\n if (hasSolid) entries.push({ swatch: lineSwatch, label: labels.legend.line });\n if (hasAssistant) entries.push({ swatch: assistantSwatch, label: labels.legend.assistant });\n if (hasDotted) entries.push({ swatch: dottedSwatch, label: labels.legend.dotted });\n if (hasVacant) entries.push({ swatch: vacantSwatch, label: labels.legend.vacant });\n const block = legendBlock(entries, layout.height);\n if (block.svg !== \"\") {\n parts.push(block.svg);\n width = Math.max(width, block.width);\n height = block.height;\n }\n }\n\n const w = Math.ceil(width);\n const h = Math.ceil(height);\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${w} ${h}\" width=\"${w}\" height=\"${h}\" role=\"img\" aria-label=\"${xmlEscape(labels.ariaLabel)}\">` +\n parts.join(\"\") +\n `</svg>`\n );\n}\n","// One-call org-chart render: input → { svg, layout }. Thin, honest wiring: validate\n// (throw on a structurally invalid chart — never repair), compute the pure layout, emit.\n// Callers needing finer control use computeOrgChartLayout + orgChartLayoutSvg directly\n// (the layout result supports hit-testing / decorating the diagram).\n\nimport { computeOrgChartLayout, type OrgChartLayout, type OrgChartLayoutOptions } from \"./layout\";\nimport { orgChartLayoutSvg } from \"./svg\";\nimport type { OrgChartSvgLabels } from \"./labels\";\nimport type { OrgChartInput } from \"./types\";\n\nexport interface OrgChartRenderOptions extends OrgChartLayoutOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary for the emitter (legend/accessibility) — English default. */\n svgLabels?: OrgChartSvgLabels;\n}\n\nexport interface OrgChartRenderResult {\n /** Self-contained SVG (numeric width/height + matching viewBox — PDF-embedder safe). */\n svg: string;\n /** The computed layout, for callers that decorate or hit-test the diagram. */\n layout: OrgChartLayout;\n}\n\n/**\n * Renders an org-chart input to a self-contained SVG string. Deterministic: same data →\n * same SVG (array order never matters; sibling order among reports is the ascending\n * reportId). Throws OrgChartValidationError — carrying EVERY issue, deterministically\n * sorted — on a structurally invalid chart. Empty input yields an empty-but-valid SVG;\n * callers decide their own empty state.\n */\nexport function orgChartSvg(input: OrgChartInput, opts: OrgChartRenderOptions = {}): OrgChartRenderResult {\n const layout = computeOrgChartLayout(input, {\n ...(opts.maxLabelChars !== undefined ? { maxLabelChars: opts.maxLabelChars } : {}),\n ...(opts.titleLabels !== undefined ? { titleLabels: opts.titleLabels } : {}),\n });\n const svg = orgChartLayoutSvg(layout, {\n ...(opts.legend === false ? { legend: false } : {}),\n ...(opts.svgLabels !== undefined ? { labels: opts.svgLabels } : {}),\n });\n return { svg, layout };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/org-chart/types.ts","../../src/org-chart/labels.ts","../../src/org-chart/validate.ts","../../src/core/xml.ts","../../src/core/geometry.ts","../../src/core/text.ts","../../src/core/legend.ts","../../src/core/stroke.ts","../../src/core/annotation.ts","../../src/core/layered.ts","../../src/org-chart/layout.ts","../../src/org-chart/svg.ts","../../src/org-chart/render.ts"],"names":["round","ORG_BOX_PAD_Y"],"mappings":"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","file":"index.cjs","sourcesContent":["// Org-chart input model — declared facts only. compasso draws EXACTLY who the caller\n// declares reports to whom: every reporting line carries its declared `kind` (the line\n// STYLE is a semantic claim only the author may make), every box is a declared position,\n// and the ROOT is never declared — it is READ from topology (a position that is no solid\n// edge's report). There is deliberately NO `level`/`depth`/`isManager`/`order` field on\n// the input: depth is derived from the declared solid edges, not trusted from a flag (the\n// honesty rule). Multi-root forests (holding cos, co-CEOs, pre-merger) are real and\n// tolerated, never an error.\n\n/**\n * CLOSED reporting vocabulary — a line is drawn ONLY for a declared relationship, styled\n * ONLY by a declared kind. No inference, no synthesis.\n * - \"line\" — solid PRIMARY reporting line; defines the tree spine (a node's row & parent).\n * - \"assistant\" — solid SIDE-STEM staff/EA role; STILL a structural child of exactly one\n * manager (it sets the report's row = manager.depth + 1 band), but drawn\n * beside the manager's stem above the line-report bus rather than packed\n * into the sibling rake.\n * - \"dotted\" — dashed secondary/matrix line. NON-STRUCTURAL: never defines a row or a\n * parent; an OVERLAY between two already-placed boxes (dotted-line-manager\n * convention).\n */\nexport const ORG_REPORT_KINDS = [\"line\", \"assistant\", \"dotted\"] as const;\nexport type OrgReportKind = (typeof ORG_REPORT_KINDS)[number];\n\n/**\n * CLOSED vacancy vocabulary. A box is vacant ONLY when DECLARED so — never inferred from\n * an empty name. A vacant box may legitimately carry a name (a departed incumbent or a\n * target hire); both are drawn.\n */\nexport const ORG_VACANCIES = [\"filled\", \"vacant\"] as const;\nexport type OrgVacancy = (typeof ORG_VACANCIES)[number];\n\n/**\n * A declared organizational position (one box). `name`/`title`/`subtitle` are verbatim\n * (always kept in the <title>); empty strings / nulls are drawn as declared.\n */\nexport interface OrgPosition {\n id: number;\n /** Verbatim person/role name — line 1 of the box. \"\" allowed (drawn empty; <title> intact). */\n name: string;\n /** Verbatim job title — line 2 (smaller). null = name-only box. */\n title: string | null;\n /**\n * OPTIONAL third line (department/unit), verbatim, measured into boxW like the others.\n * null = none. NOT a metrics/compensation field — that interpretive cut stands.\n */\n subtitle: string | null;\n /**\n * \"vacant\" → dashed box + inset open-seat frame + localized \"(vago)\" marker line.\n * A box is vacant ONLY when DECLARED so — never inferred from an empty name.\n * (validation defaults an absent value → \"filled\").\n */\n vacancy: OrgVacancy;\n /** Verbatim <title> override; defaults below (see svg.ts). */\n hover?: string;\n /**\n * Caller-asserted annotation flag. compasso never decides what \"annotated\" MEANS —\n * it only draws a discreet dot at the box's upper-right when true. Default undefined\n * === not annotated (backward-compatible).\n */\n annotated?: boolean;\n}\n\n/**\n * One row per DECLARED relationship, manager → report. There is no `order` column in\n * v0.4.0 — sibling order among reports is by ascending `reportId`.\n */\nexport interface OrgReport {\n id: number;\n /** Manager — drawn ABOVE. */\n managerId: number;\n /** Report — drawn BELOW (line) or side-stemmed (assistant). */\n reportId: number;\n /** Reporting-line kind (validation defaults an absent value → \"line\"). */\n kind: OrgReportKind;\n /** Verbatim relationship label (e.g. \"interim\", \"matrix\") for the <title>; null = none. */\n label?: string | null;\n /**\n * Caller-asserted annotation flag. compasso never decides what \"annotated\" MEANS —\n * it only draws a discreet tick at the edge's midpoint when true. Default undefined\n * === not annotated (backward-compatible).\n */\n annotated?: boolean;\n}\n\n/** Input to the org-chart render pipeline — flat, id-referenced rows, never nested. */\nexport interface OrgChartInput {\n positions: OrgPosition[];\n reports: OrgReport[];\n}\n\n/**\n * Presentation-only derived box style (solid = filled, dashed = vacant). Computed in\n * render.ts / svg.ts from `vacancy` — NOT an input field.\n */\nexport type OrgBoxStyle = \"solid\" | \"dashed\";\n","// Display vocabularies — every human-readable string the org chart emits, gathered in\n// overridable packs so the diagram localizes without touching the engine. English\n// defaults here; `compasso/locales/pt-br` ships a Brazilian Portuguese pack.\n//\n// Split, mirroring fault-tree/genogram: `OrgChartTitleLabels` is woven into element/box\n// <title>s by the LAYOUT (verbatim-preserving — the localized kind word rides each line's\n// <title>, never the map); `OrgChartSvgLabels` is drawn by the EMITTER (legend, aria).\n// `reportKinds` is a `Record<OrgReportKind, string>` so a missing kind is a compile error\n// (`pnpm typecheck` is the completeness guard).\n\nimport type { OrgReportKind } from \"./types\";\n\n/** Labels woven into element/box <title>s by the LAYOUT (verbatim-preserving). */\nexport interface OrgChartTitleLabels {\n reportKinds: Record<OrgReportKind, string>;\n /** The \"(vacant)\" box marker line, drawn inside a vacant box. */\n vacant: string;\n}\n\nexport const ORG_CHART_TITLE_LABELS_EN: OrgChartTitleLabels = {\n reportKinds: { line: \"Reports to\", assistant: \"Assistant to\", dotted: \"Dotted-line report to\" },\n vacant: \"(vacant)\",\n};\n\n/** Labels drawn by the SVG EMITTER (legend entries, accessibility text). */\nexport interface OrgChartSvgLabels {\n legend: { line: string; assistant: string; dotted: string; vacant: string };\n ariaLabel: string;\n}\n\nexport const ORG_CHART_SVG_LABELS_EN: OrgChartSvgLabels = {\n legend: { line: \"Reports to\", assistant: \"Assistant\", dotted: \"Dotted-line / matrix\", vacant: \"Vacant position\" },\n ariaLabel: \"Organizational chart\",\n};\n","// Org-chart validation — REJECT, never repair. The genogram silently filters dangling\n// references because a family map is elicited incrementally; an org chart is an\n// AUTHORITATIVE artifact whose meaning is \"who answers to whom\", so drawing a structurally\n// invalid chart (a dropped line, a synthesized parent) misstates the hierarchy and is\n// worse than refusing. The honest escape hatch for a node with two real bosses is the\n// dotted line — keep ONE solid reporting line, make the rest kind:\"dotted\".\n//\n// Every problem is reported, not just the first: issues are aggregated, deduplicated and\n// sorted deterministically (by code, then message), each carrying a STABLE kebab-case\n// `code`. Validation runs in THREE phases, each gated on the previous being clean ENOUGH\n// for the next to be meaningful — not on \"zero issues so far\", so a defect in one phase\n// never silently hides an honest issue from a later one (the throw carries ALL real\n// issues, not just the first phase's):\n// (0) duplicate ids (per namespace — positions AND reports). The lookup maps are\n// first-occurrence-wins, so EVERY reference rule below would validate whichever\n// duplicate row was declared first — making the issue list depend on array order,\n// violating this function's documented order-invariance. When any duplicate-id issue\n// exists we report ONLY those and stop (the duplicate already forces a throw).\n// (1) reference / semantic rules: unknown manager/report endpoints, self-loops, a node\n// with ≥2 SOLID structural parents, and an assistant that itself manages a solid edge\n// (v0.4.0 scopes assistants as side-stem LEAVES — a non-leaf assistant would silently\n// drop its subtree, so we REJECT rather than repair). Evaluated once ids are unambiguous.\n// (2) graph rule (cycle over the SOLID-edge graph) — gated ONLY on the reference-\n// INTEGRITY subset that genuinely corrupts traversal: duplicate-id (ambiguous\n// first-wins node), unknown-manager / unknown-report (walks a phantom node), and\n// multiple-managers (the instance-tree build picks one of two solid parents and\n// would walk an ambiguous structure). `self-report` does NOT block: it references a\n// real, walkable node, and the DFS defensively skips `from === to` solid edges.\n//\n// Tolerated, by design (drawn as declared, never an error):\n// - FOREST — zero/one/many roots (no invented super-root, no inter-tree connector);\n// - dotted edges crossing between forest trees, dotted-only cycles, a dotted edge sharing\n// a solid pair's direction (dotted is NON-structural — never triggers cycle or\n// multiple-managers); a dotted edge into an already-solid-parented box is FINE;\n// - empty name/title/subtitle (drawn empty; the <title> is still present);\n// - a vacant box with a name (departed incumbent / target hire).\n\nimport type { OrgChartInput, OrgPosition, OrgReport } from \"./types\";\n\n/** Stable machine-readable issue codes (kebab-case; part of the public contract). */\nexport type OrgChartIssueCode =\n | \"duplicate-id\"\n | \"unknown-manager\"\n | \"unknown-report\"\n | \"self-report\"\n | \"multiple-managers\"\n | \"assistant-has-reports\"\n | \"too-many-matrix-edges\"\n | \"cycle\";\n\n/**\n * Routing capacity: the max number of dotted (matrix) connections one position can be an\n * endpoint of (as manager OR report). Each such edge must escape that box's edge to a\n * box-free column at a distinct (column, exit-y) slot; a finite box edge holds only finitely\n * many clean orthogonal exits, so beyond this the escape columns/exit-rows would collide.\n * 5 is the conservative bound proven collision-free even for the shortest single-line box —\n * a position with more matrix lines than this is rejected rather than misdrawn (the\n * reject-don't-repair doctrine). Realistic matrix orgs sit far below it.\n */\nexport const ORG_MAX_MATRIX_EDGES_PER_NODE = 5;\n\nexport interface OrgChartIssue {\n code: OrgChartIssueCode;\n message: string;\n}\n\n/** Thrown by computeOrgChartLayout / orgChartSvg on a structurally invalid chart. */\nexport class OrgChartValidationError extends Error {\n readonly issues: readonly OrgChartIssue[];\n\n constructor(issues: readonly OrgChartIssue[]) {\n super(`invalid org chart: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"OrgChartValidationError\";\n this.issues = issues;\n }\n}\n\n/** \"1 and 3\" / \"1, 2 and 3\" — deterministic listing for issue messages. */\nfunction listIds(ids: readonly number[]): string {\n if (ids.length === 1) return String(ids[0]);\n return `${ids.slice(0, -1).join(\", \")} and ${ids[ids.length - 1]}`;\n}\n\n/**\n * Deduplicate + deterministic order: by code, then message (byte comparison — stable\n * across engines; no locale-dependent collation). Shared by every phase that returns.\n */\nfunction sortIssues(issues: readonly OrgChartIssue[]): readonly OrgChartIssue[] {\n const unique = new Map<string, OrgChartIssue>();\n for (const issue of issues) unique.set(`${issue.code} ${issue.message}`, issue);\n return [...unique.values()].sort((a, b) =>\n a.code !== b.code ? (a.code < b.code ? -1 : 1) : a.message < b.message ? -1 : a.message > b.message ? 1 : 0,\n );\n}\n\n/**\n * Graph-phase gating set: the cycle DFS runs only when no reference-INTEGRITY issue\n * corrupts the traversal. duplicate-id / unknown-manager / unknown-report make a walked\n * node ambiguous or phantom; multiple-managers makes the instance-tree's \"pick one solid\n * parent\" build ambiguous. self-report does NOT block (real walkable node; the DFS skips\n * the self-loop defensively).\n */\nconst GRAPH_BLOCKING: ReadonlySet<OrgChartIssueCode> = new Set<OrgChartIssueCode>([\n \"duplicate-id\",\n \"unknown-manager\",\n \"unknown-report\",\n \"multiple-managers\",\n]);\n\n/**\n * Computes ALL validation issues for the input, deduplicated and deterministically sorted\n * (code, then message) — array order of `positions`/`reports` never changes the result.\n * Empty input (no positions AND no reports) is valid by definition (the renderer's\n * empty-but-valid SVG case) and reports no issues. A forest (zero/one/many roots) is\n * valid and never reported.\n */\nexport function orgChartIssues(input: OrgChartInput): readonly OrgChartIssue[] {\n if (input.positions.length === 0 && input.reports.length === 0) return [];\n\n const issues: OrgChartIssue[] = [];\n const push = (code: OrgChartIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── Phase 0: duplicate ids (per namespace — positions and reports are two namespaces;\n // hooks must be unique). Any duplicate makes the structure ambiguous, so this\n // short-circuits the rest (below). ─────────────────────────────────────────────────\n const positionById = new Map<number, OrgPosition>();\n const dupPositionIds = new Set<number>();\n for (const p of input.positions) {\n if (positionById.has(p.id)) dupPositionIds.add(p.id);\n else positionById.set(p.id, p);\n }\n for (const id of [...dupPositionIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate position id ${id}`);\n }\n const reportById = new Map<number, OrgReport>();\n const dupReportIds = new Set<number>();\n for (const r of input.reports) {\n if (reportById.has(r.id)) dupReportIds.add(r.id);\n else reportById.set(r.id, r);\n }\n for (const id of [...dupReportIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate report id ${id}`);\n }\n\n // Duplicate ids short-circuit everything else: the lookup maps above are\n // first-occurrence-wins, so every downstream reference rule would validate whichever\n // duplicate row happened to be declared first — making the issue list depend on the\n // ARRAY ORDER, in direct violation of this function's documented order-invariance. We\n // report ONLY the duplicate-id issues and stop (the structural defect already forces a\n // throw, and is present in every permutation).\n if (issues.length > 0) {\n return sortIssues(issues);\n }\n\n const reports = [...reportById.values()].sort((a, b) => a.id - b.id);\n\n // ── Phase 1: reference / semantic rules. ─────────────────────────────────────────────\n // Endpoints must reference declared positions; a box may not report to itself; a node\n // has exactly ONE structural parent. `solidParents` accumulates the SOLID (line|assistant)\n // parent edge ids per report position to fire multiple-managers regardless of kind mix.\n const solidParents = new Map<number, number[]>(); // reportId → solid edge ids\n const assistantReportEdge = new Map<number, number>(); // position → first assistant edge it is the report of\n const solidManagedEdges = new Map<number, number[]>(); // managerId → solid edge ids it manages\n const dottedDegree = new Map<number, number>(); // position → # dotted edges it is an endpoint of (mgr or rep)\n for (const r of reports) {\n const hasManager = positionById.has(r.managerId);\n const hasReport = positionById.has(r.reportId);\n if (!hasManager) {\n push(\"unknown-manager\", `report ${r.id} managerId ${r.managerId} is not a declared position`);\n }\n if (!hasReport) {\n push(\"unknown-report\", `report ${r.id} reportId ${r.reportId} is not a declared position`);\n }\n // R: a box reporting to itself is meaningless and self-loops layout — on ANY kind.\n if (r.managerId === r.reportId) {\n push(\"self-report\", `report ${r.id} has managerId === reportId (${r.managerId})`);\n }\n // A SOLID edge (line | assistant) is a structural parent — accumulate even when an\n // endpoint is unknown, so a node with two solid parents is still flagged (the codes\n // are independent facts). dotted is NON-structural and excluded here.\n if (r.kind !== \"dotted\") {\n const arr = solidParents.get(r.reportId) ?? [];\n arr.push(r.id);\n solidParents.set(r.reportId, arr);\n // Track each position's SOLID down-edges (it is the manager of) so a non-leaf\n // assistant — a position that is an assistant-report yet manages a solid edge — is\n // caught below. `reports` is id-sorted, so the lowest edge id lands first.\n const managed = solidManagedEdges.get(r.managerId) ?? [];\n managed.push(r.id);\n solidManagedEdges.set(r.managerId, managed);\n }\n // First (lowest-id) assistant edge that makes this position an assistant-report. A\n // self-loop assistant is excluded — `self-report` already carries that fact and the\n // position never legitimately becomes a side-stem leaf.\n if (r.kind === \"assistant\" && r.managerId !== r.reportId && !assistantReportEdge.has(r.reportId)) {\n assistantReportEdge.set(r.reportId, r.id);\n }\n // Per-position dotted (matrix) degree, for the routing-capacity cap below. A dotted edge\n // makes BOTH endpoints escape their box edge, so each declared endpoint counts once;\n // self-loops (already `self-report`) and phantom endpoints (already `unknown-*`) are\n // excluded — they never reach the router.\n if (r.kind === \"dotted\" && r.managerId !== r.reportId) {\n if (positionById.has(r.managerId)) dottedDegree.set(r.managerId, (dottedDegree.get(r.managerId) ?? 0) + 1);\n if (positionById.has(r.reportId)) dottedDegree.set(r.reportId, (dottedDegree.get(r.reportId) ?? 0) + 1);\n }\n }\n // multiple-managers fires whenever a position is the report of ≥2 SOLID edges, regardless\n // of kind — including one `line` parent AND one `assistant` parent (still two structural\n // parents; the instance-tree DFS would be ambiguous about which owns the row). There is\n // no \"which kind wins\" tiebreak — it is rejected. Escape hatch: keep one solid line, make\n // the rest kind:\"dotted\".\n for (const [reportId, edgeIds] of [...solidParents.entries()].sort((a, b) => a[0] - b[0])) {\n if (edgeIds.length > 1) {\n push(\n \"multiple-managers\",\n `position ${reportId} is the report of solid edges ${listIds(edgeIds.sort((a, b) => a - b))} — keep one solid line, make the rest kind \"dotted\"`,\n );\n }\n }\n\n // assistant-has-reports: v0.4.0 draws an assistant as a side-stem LEAF, so a position\n // that is an assistant-report AND manages a solid (line|assistant) edge would have its\n // entire subtree silently dropped. REJECT it (reject-don't-repair) — keep the lowest\n // managed solid edge id in the message so the author knows which line to recut. Ascending\n // position id for a deterministic, array-order-invariant list.\n for (const [positionId, assistEdgeId] of [...assistantReportEdge.entries()].sort((a, b) => a[0] - b[0])) {\n const managed = solidManagedEdges.get(positionId);\n if (managed !== undefined && managed.length > 0) {\n const firstManaged = Math.min(...managed);\n push(\n \"assistant-has-reports\",\n `position ${positionId} is an assistant (report of edge ${assistEdgeId}) but manages solid edge ${firstManaged} — assistants are leaves`,\n );\n }\n }\n\n // too-many-matrix-edges: a position that is an endpoint of more dotted (matrix) edges than\n // the router can place distinct box-free escape slots for (see ORG_MAX_MATRIX_EDGES_PER_NODE).\n // Reject rather than misdraw (overlapping/colliding lines). Ascending position id for a\n // deterministic, array-order-invariant list.\n for (const [positionId, count] of [...dottedDegree.entries()].sort((a, b) => a[0] - b[0])) {\n if (count > ORG_MAX_MATRIX_EDGES_PER_NODE) {\n push(\n \"too-many-matrix-edges\",\n `position ${positionId} has ${count} dotted (matrix) connections — at most ${ORG_MAX_MATRIX_EDGES_PER_NODE} are supported per position`,\n );\n }\n }\n\n // ── Phase 2: graph rule (cycle over the SOLID-edge graph). Gated ONLY on the reference-\n // INTEGRITY codes that corrupt the traversal itself (see GRAPH_BLOCKING). dotted edges\n // are EXCLUDED — a matrix back-link is legal and never a cycle. ─────────────────────\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // Adjacency manager → reports over SOLID edges only, in ascending reportId so the DFS\n // walks children deterministically (array-order-invariant). `from === to` self-loops\n // are skipped defensively (self-report carries that fact as its own code).\n const solidChildren = new Map<number, number[]>();\n for (const r of reports) {\n if (r.kind === \"dotted\") continue;\n if (r.managerId === r.reportId) continue;\n const arr = solidChildren.get(r.managerId) ?? [];\n arr.push(r.reportId);\n solidChildren.set(r.managerId, arr);\n }\n for (const arr of solidChildren.values()) arr.sort((a, b) => a - b);\n\n // Iterative coloring DFS, start nodes ascending; each distinct cycle is reported once,\n // rotated to start at its smallest position id so the message is identical for any\n // array order of the same input.\n const color = new Map<number, 0 | 1 | 2>(); // 0/absent=white, 1=gray, 2=black\n const seenCycles = new Set<string>();\n const dfs = (start: number): void => {\n const stack: { id: number; nextChild: number }[] = [{ id: start, nextChild: 0 }];\n color.set(start, 1);\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]!;\n const children = solidChildren.get(frame.id) ?? [];\n if (frame.nextChild >= children.length) {\n color.set(frame.id, 2);\n stack.pop();\n continue;\n }\n const child = children[frame.nextChild]!;\n frame.nextChild += 1;\n const c = color.get(child) ?? 0;\n if (c === 1) {\n // Back edge: the cycle is the stack slice from `child` down to the current frame.\n const from = stack.findIndex((f) => f.id === child);\n const cycle = stack.slice(from).map((f) => f.id);\n const minIdx = cycle.indexOf(Math.min(...cycle));\n const rotated = [...cycle.slice(minIdx), ...cycle.slice(0, minIdx)];\n const key = rotated.join(\">\");\n if (!seenCycles.has(key)) {\n seenCycles.add(key);\n push(\"cycle\", `cycle: ${[...rotated, rotated[0]!].join(\" → \")}`);\n }\n } else if (c === 0) {\n color.set(child, 1);\n stack.push({ id: child, nextChild: 0 });\n }\n }\n };\n for (const p of [...positionById.values()].sort((a, b) => a.id - b.id)) {\n if ((color.get(p.id) ?? 0) === 0) dfs(p.id);\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws OrgChartValidationError (carrying ALL issues) when the input is invalid. */\nexport function validateOrgChart(input: OrgChartInput): void {\n const issues = orgChartIssues(input);\n if (issues.length > 0) throw new OrgChartValidationError(issues);\n}\n","// XML/SVG escaping — every interpolated text in an emitted SVG MUST pass through\n// this. Diagram labels are typically user/author-controlled, and the SVG string may\n// be injected via innerHTML in a browser or embedded as vectors in a PDF — an\n// unescaped label is an XSS / `</svg>`-breakout vector on every surface at once.\n\n/** Escapes a string for use in SVG/XML text content AND attribute values. */\nexport function xmlEscape(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","// Shared geometry primitives.\n\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** \"M x y L x y …\" path data from a polyline. */\nexport function pathData(points: Point[]): string {\n return points.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x} ${p.y}`).join(\" \");\n}\n","// Pure, deterministic text metrics — no DOM, no canvas, no font files. Every layout\n// in this library reserves space from these estimates and every emitter draws with\n// the same constants, so what is proven collision-free is what is drawn.\n\n/**\n * Conservative per-character advance, as a fraction of the font size. The pure module\n * can't measure real glyphs (no DOM/canvas), so it estimates width = chars * font *\n * CHAR_W. It is deliberately a touch WIDER than Helvetica's ~0.5 average advance: a\n * layout reserves slightly more room than the text needs, so the real render always\n * fits inside its reserved box.\n */\nexport const CHAR_W = 0.6;\n\n/** Pure, deterministic width estimate for a single line of text at `fontPx`. */\nexport function estimateTextWidth(text: string, fontPx: number): number {\n return text.length * fontPx * CHAR_W;\n}\n\n/**\n * Wraps a label onto up to `maxLines` lines (default 2) so long labels don't sprawl.\n * Greedy word fill; each line capped at `perLine` chars (…-truncated only if a line\n * still overflows). The LAST allowed line absorbs every remaining word before the cap\n * applies — words are never dropped mid-label, only visibly elided. Pure + shared so\n * every renderer wraps identically. The full text is always kept elsewhere (the\n * node's `label`, an SVG <title>, or a side list), so nothing is silently lost.\n *\n * INVARIANT: with the default `maxLines` the output is byte-identical to the\n * historical two-line implementation (pinned by test/core/text.test.ts) — both\n * shipped renderers wrap through here.\n */\nexport function wrapLabel(label: string, perLine: number, maxLines = 2): string[] {\n if (label.length <= perLine) return [label];\n const cap = (s: string): string =>\n s.length > perLine ? s.slice(0, Math.max(1, perLine - 1)) + \"…\" : s;\n const lines: string[] = [\"\"];\n for (const word of label.split(/\\s+/)) {\n const last = lines.length - 1;\n const current = lines[last]!;\n if (current === \"\" || (current + \" \" + word).length <= perLine) {\n lines[last] = current === \"\" ? word : `${current} ${word}`;\n } else if (lines.length < maxLines) {\n lines.push(word);\n } else {\n lines[last] = `${current} ${word}`;\n }\n }\n // A trailing-whitespace \"word\" (\"a b \".split(/\\s+/) → [\"a\",\"b\",\"\"]) may open a line\n // it never fills; the historical code dropped that empty line, so this does too.\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return lines.map(cap);\n}\n\n/**\n * House \"balanced\" wrap policy (extracted verbatim from the ecomap's tie-label wrap,\n * itself mirroring the genogram's): per-line budget `min(26, max(14, ceil(len/2)+2))`\n * splits a medium label into two roughly even lines instead of one long + one short,\n * then the greedy `wrapLabel` fill (and its `maxLines` semantics) applies. The shipped\n * renderers keep their local copies for now — new modules consume this one; migrating\n * them is a separate provably-zero-change refactor.\n */\nexport function wrapLabelBalanced(label: string, maxLines?: number): string[] {\n const perLine = Math.min(26, Math.max(14, Math.ceil(label.length / 2) + 2));\n return wrapLabel(label, perLine, maxLines);\n}\n\n/** Caps a verbatim label for a COMPACT render (preview); full text kept by the caller. */\nexport function clampLabel(label: string, maxChars: number | undefined): string {\n if (maxChars === undefined || label.length <= maxChars) return label;\n return label.slice(0, Math.max(1, maxChars - 1)) + \"…\";\n}\n\n/** Font stack shared by every emitter; PDF embedders typically map it onto Helvetica. */\nexport const FONT_FAMILY = \"Helvetica, Arial, sans-serif\";\n","// Shared legend machinery — the exact row format the genogram and ecomap emitters\n// currently duplicate character-for-character (`<g data-compasso-legend=\"true\">` with\n// swatch-closure rows). Extracted so new diagram modules don't add a third copy;\n// the two shipped emitters keep their local blocks for now (migrating them is a\n// separate, provably-zero-change refactor — pinned byte-for-byte against the ecomap's\n// emitted legend in test/core/legend.test.ts).\n//\n// The caller stays in charge of the HONESTY RULE half: it decides WHICH entries exist\n// (used-keys-only) and what each swatch draws; this module only owns the row geometry,\n// the text emission (xmlEscape — labels may come from caller-supplied packs), and the\n// width/height bookkeeping both renderers compute identically.\n\nimport { FONT_FAMILY, estimateTextWidth } from \"./text\";\nimport { xmlEscape } from \"./xml\";\n\n// Row metrics shared by every legend in the library. Exported because swatch builders\n// need them (a line swatch spans LEGEND_SWATCH_W; a glyph swatch centers on it).\nexport const LEGEND_ROW_H = 18;\nexport const LEGEND_PAD = 16;\nexport const LEGEND_SWATCH_W = 22;\nexport const LEGEND_GAP = 14;\nexport const LEGEND_FONT = 11;\n\n// Legend text ink — the zinc glyph stroke both shipped emitters use for legend labels.\nconst LEGEND_TEXT_FILL = \"#52525b\";\n\nexport interface LegendEntry {\n /**\n * Swatch markup builder, called with the swatch's left x and the row's center y.\n * The builder owns its own escaping/rounding (it typically reuses the module's\n * glyph/line emitters); it should draw within LEGEND_SWATCH_W of x.\n */\n swatch: (x: number, yCenter: number) => string;\n /** Display label (escaped here; verbatim pack text in, escaped SVG out). */\n label: string;\n}\n\nexport interface LegendBlock {\n /** `<g data-compasso-legend=\"true\">…</g>` — empty string when there are no entries. */\n svg: string;\n /** Minimum canvas width the legend needs; callers take `max(width, block.width)`. */\n width: number;\n /** New total canvas height including the legend; callers assign it directly. */\n height: number;\n}\n\n/**\n * Emits the legend group for the given entries below `startY` (the diagram's current\n * height). Pure + deterministic; coordinates are interpolated exactly as the shipped\n * emitters do. Zero entries (used-keys-only found nothing) → no markup, zero width\n * contribution, height unchanged — safe to call unconditionally.\n */\nexport function legendBlock(entries: readonly LegendEntry[], startY: number): LegendBlock {\n if (entries.length === 0) return { svg: \"\", width: 0, height: startY };\n const rows = entries.map((entry, i) => {\n const rowCenterY = startY + i * LEGEND_ROW_H + LEGEND_ROW_H / 2;\n const textX = LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP;\n return (\n entry.swatch(LEGEND_PAD, rowCenterY) +\n `<text x=\"${textX}\" y=\"${rowCenterY + LEGEND_FONT * 0.32}\" font-family=\"${FONT_FAMILY}\" font-size=\"${LEGEND_FONT}\" fill=\"${LEGEND_TEXT_FILL}\">${xmlEscape(entry.label)}</text>`\n );\n });\n const widestLabel = entries.reduce((m, e) => Math.max(m, estimateTextWidth(e.label, LEGEND_FONT)), 0);\n return {\n svg: `<g data-compasso-legend=\"true\">${rows.join(\"\")}</g>`,\n width: LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP + widestLabel + LEGEND_PAD,\n height: startY + entries.length * LEGEND_ROW_H + LEGEND_PAD / 2,\n };\n}\n","// Edge line styles — a neutral, presentation-only style for a relationship line.\n// NOT a judgment: a deterministic, lexical hint derived from the author's own quality\n// word. The literal word always rides the element's <title>, so a style never replaces\n// what was said. Unknown/ambiguous quality → \"plain\".\n\nexport type EdgeLineStyle = \"plain\" | \"close\" | \"distant\" | \"conflict\" | \"cutoff\";\n\n/** Stroke attributes per style — shared by every renderer so SVG and PDF match. */\nexport interface EdgeStroke {\n width: number;\n /** SVG dash array / PDF dash pattern as [dash, gap]; null = solid. */\n dash: [number, number] | null;\n opacity: number;\n}\n\nexport const EDGE_STROKE: Record<EdgeLineStyle, EdgeStroke> = {\n plain: { width: 1.5, dash: null, opacity: 0.6 },\n close: { width: 3, dash: null, opacity: 0.85 },\n distant: { width: 1.5, dash: [4, 4], opacity: 0.55 },\n conflict: { width: 2, dash: [2, 2], opacity: 0.75 },\n cutoff: { width: 1.5, dash: [6, 5], opacity: 0.4 },\n};\n\n/**\n * A pluggable lexicon mapping free-text quality words onto line styles. Needles are\n * diacritic-free, lowercase substrings of the author's own words; `negations` are\n * whole words that flip the meaning of the very word a needle would match (\"not\n * close\"), so their presence makes the matcher abstain to \"plain\" rather than risk\n * an inverted visual. Locale packs (e.g. `compasso/locales/pt-br`) ship alternates.\n */\nexport interface QualityLexicon {\n buckets: readonly { style: Exclude<EdgeLineStyle, \"plain\">; needles: readonly string[] }[];\n negations: readonly string[];\n}\n\n// English default. Conservative stems: each needle is a substring match on the\n// normalized text, and the SINGLE-BUCKET rule below keeps competing signals honest.\n// \"no\" alone is deliberately NOT a negation: \"no contact\" is a genuine cutoff signal.\nexport const QUALITY_LEXICON_EN: QualityLexicon = {\n buckets: [\n {\n style: \"close\",\n needles: [\"close\", \"warm\", \"support\", \"lov\", \"affection\", \"caring\", \"tight\", \"harmon\", \"healthy\"],\n },\n {\n style: \"distant\",\n needles: [\"distant\", \"detach\", \"absent\", \"cold\", \"drift\"],\n },\n {\n style: \"conflict\",\n needles: [\"conflict\", \"fight\", \"tens\", \"difficult\", \"hostil\", \"violen\", \"abus\", \"aggress\", \"complicat\", \"toxic\", \"argu\"],\n },\n {\n style: \"cutoff\",\n needles: [\"estrang\", \"cut off\", \"cutoff\", \"no contact\", \"broken off\", \"sever\"],\n },\n ],\n negations: [\"not\", \"never\", \"no longer\", \"hardly\"],\n};\n\n/** Lowercase + strip diacritics so matching ignores accents. */\nexport function normalizeText(text: string): string {\n return text.normalize(\"NFD\").replace(/[̀-ͯ]/g, \"\").toLowerCase();\n}\n\nconst escapeRegExp = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * Maps a free-text relationship quality to a neutral line style. Deterministic and\n * conservative: returns a specific style ONLY when exactly one lexical bucket matches;\n * null/empty/ambiguous/negated/unknown all fall back to \"plain\". The caller still\n * keeps the verbatim quality word, so nothing the author said is ever lost.\n */\nexport function qualityLineStyle(\n quality: string | null,\n lexicon: QualityLexicon = QUALITY_LEXICON_EN,\n): EdgeLineStyle {\n if (quality === null) return \"plain\";\n const haystack = normalizeText(quality);\n if (haystack.trim() === \"\") return \"plain\";\n\n if (lexicon.negations.length > 0) {\n const negation = new RegExp(`\\\\b(${lexicon.negations.map(escapeRegExp).join(\"|\")})\\\\b`);\n if (negation.test(haystack)) return \"plain\";\n }\n\n const matched: EdgeLineStyle[] = [];\n for (const { style, needles } of lexicon.buckets) {\n if (needles.some((n) => haystack.includes(n))) matched.push(style);\n }\n return matched.length === 1 ? matched[0]! : \"plain\";\n}\n","// A discreet, NEUTRAL \"this element was annotated by the caller\" marker, shared by every\n// diagram family. compasso never decides what an annotation MEANS — the caller asserts the\n// `annotated` flag from its own domain knowledge and supplies the legend label; the library\n// only draws a standardised mark. Pure presentation: literal SVG primitives, no <defs>, no\n// <marker>, no CSS. The mark is a DECORATION drawn inside an element's existing <g> (like a\n// genogram deceased slash) — never a layout box or routed segment, so it cannot create or\n// hide an overlap. Ink is the shared zinc-600 glyph stroke (#52525b) for cross-family unity.\nimport { LEGEND_SWATCH_W } from \"./legend\";\nimport type { Point } from \"./geometry\";\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\nexport const ANNOTATION_INK = \"#52525b\";\nconst DOT_R = 3;\nconst TICK_HALF = 3;\n\n/**\n * A small filled dot marking an annotated NODE. Pass the point where it should sit — callers\n * place it at the node's upper-right (inset), the conventional \"has a note\" corner.\n */\nexport function annotationDot(cx: number, cy: number): string {\n return `<circle cx=\"${round(cx)}\" cy=\"${round(cy)}\" r=\"${DOT_R}\" fill=\"${ANNOTATION_INK}\" fill-opacity=\"0.6\"/>`;\n}\n\n/**\n * A short tick perpendicular to an annotated EDGE at the midpoint of its middle segment.\n * Org-chart / genogram polylines are axis-aligned, so the perpendicular is trivial; a tick on\n * a near-diagonal falls back to a vertical mark. Returns \"\" for a degenerate (<2-point) path.\n */\nexport function annotationTick(points: readonly Point[]): string {\n if (points.length < 2) return \"\";\n const i = Math.floor((points.length - 1) / 2);\n const a = points[i]!;\n const b = points[i + 1] ?? points[i]!;\n const mx = (a.x + b.x) / 2;\n const my = (a.y + b.y) / 2;\n const horizontal = Math.abs(a.y - b.y) <= Math.abs(a.x - b.x);\n const x1 = horizontal ? mx : mx - TICK_HALF;\n const x2 = horizontal ? mx : mx + TICK_HALF;\n const y1 = horizontal ? my - TICK_HALF : my;\n const y2 = horizontal ? my + TICK_HALF : my;\n return `<line x1=\"${round(x1)}\" y1=\"${round(y1)}\" x2=\"${round(x2)}\" y2=\"${round(y2)}\" stroke=\"${ANNOTATION_INK}\" stroke-width=\"1.5\"/>`;\n}\n\n/** Legend swatch for the annotation row: the same dot, centred in the swatch column. */\nexport function annotationSwatch(x: number, yCenter: number): string {\n return annotationDot(x + LEGEND_SWATCH_W / 2, yCenter);\n}\n","// Pure layout primitives shared across diagram families. Every function here is\n// deterministic and has zero references to any diagram-specific type (OrgNode,\n// GenogramPerson, etc.). Each was verified to have ≥2 real consumers before being\n// lifted; none is speculative.\n\n// ── packSubtree ────────────────────────────────────────────────────────────────\n// Moved VERBATIM from src/org-chart/layout.ts (was lines 180-223 before this lift).\n// See that file's \"PURE span-packer (Judge-1 seam)\" comment for the overlap-proof\n// and consumer notes.\n\n/** A node's own symmetric-or-asymmetric half-extents plus its children's half-extents. */\nexport interface PackNode {\n ownHalfL: number;\n ownHalfR: number;\n /** One entry per child, in placement order; empty = leaf. */\n children: { halfL: number; halfR: number }[];\n}\n\nexport interface PackGaps {\n siblingGap: number;\n}\n\nexport interface PackResult {\n /** Subtree half-extents (cover the ENTIRE subtree). */\n halfL: number;\n halfR: number;\n /** Center offset of each child relative to this node's center (parallel to children). */\n offsets: number[];\n}\n\n/**\n * Span-packs a node's children into disjoint horizontal intervals (the fault-tree `pack`\n * transposed top-down). Children c1..cn: x1 = 0; x_{i+1} = x_i + halfR_i + siblingGap +\n * halfL_{i+1}. Parent axis a = (x1 + xn)/2 — centered over its line-report block. The\n * returned offsets are each child's center MINUS the parent axis. Subtree halfL/halfR\n * extend ownHalf* to cover the children block. Pure + deterministic.\n */\nexport function packSubtree(node: PackNode, gaps: PackGaps): PackResult {\n const { ownHalfL, ownHalfR, children } = node;\n if (children.length === 0) {\n return { halfL: ownHalfL, halfR: ownHalfR, offsets: [] };\n }\n const xs: number[] = [0];\n for (let i = 1; i < children.length; i++) {\n xs.push(xs[i - 1]! + children[i - 1]!.halfR + gaps.siblingGap + children[i]!.halfL);\n }\n const first = children[0]!;\n const last = children[children.length - 1]!;\n const axis = (xs[0]! + xs[xs.length - 1]!) / 2;\n const offsets = xs.map((x) => x - axis);\n const halfL = Math.max(ownHalfL, axis - (xs[0]! - first.halfL));\n const halfR = Math.max(ownHalfR, xs[xs.length - 1]! + last.halfR - axis);\n return { halfL, halfR, offsets };\n}\n\n// ── allocateLanes ──────────────────────────────────────────────────────────────\n// Moved VERBATIM from src/org-chart/layout.ts (was lines 939-959 before this lift).\n// A byte-identical copy exists in src/genogram/layout.ts — that copy is NOT removed\n// this release (separate zero-change follow-up per the shipped migration discipline).\n\n/** Allocate lanes for a set of y-intervals: each takes the lowest lane free over its span\n * (touching at an endpoint does NOT count as overlap, so abutting edges may share). Mirror\n * of the genogram allocateLanes (src/genogram/layout.ts) — keeps the gutter narrow. */\nexport function allocateLanes(items: { lo: number; hi: number; set: (lane: number) => void }[]): number {\n const lanes: { lo: number; hi: number }[][] = [];\n for (const it of items) {\n let chosen = -1;\n for (let l = 0; l < lanes.length; l++) {\n if (lanes[l]!.every((o) => it.hi <= o.lo || it.lo >= o.hi)) {\n chosen = l;\n break;\n }\n }\n if (chosen === -1) {\n chosen = lanes.length;\n lanes.push([]);\n }\n lanes[chosen]!.push({ lo: it.lo, hi: it.hi });\n it.set(chosen);\n }\n return lanes.length;\n}\n\n// ── bandStack ──────────────────────────────────────────────────────────────────\n// NEW — captures the row-stacking recurrence verified duplicated in\n// org-chart/layout.ts (rowTop/busY) and fault-tree/layout.ts (gateZone).\n// `zoneH` generalises assistZone / gateZone (pass 0 when no side-zone exists).\n\nexport interface BandRow {\n /** Height of the content row itself (tallest box, etc.). */\n rowH: number;\n /** Height of the side-zone hanging BELOW the row and ABOVE the corridor\n * (assistant stack, gate zone, …). Pass 0 when there is no zone. */\n zoneH: number;\n}\n\nexport interface BandStackOpts {\n /** Canvas padding placed above row 0 and below the last row. */\n padding: number;\n /** Vertical gap between rows (the bus lives at busY = next rowTop − corridor/2). */\n corridor: number;\n}\n\nexport interface BandStackResult {\n /** rowTop[d] = y of the top edge of row d. rowTop[0] = padding. */\n rowTop: number[];\n /** y of the bus (connector horizontal bar) between row d and row d+1. */\n busY: (d: number) => number;\n /** Total canvas height (last row bottom + last zoneH + padding). */\n height: number;\n}\n\n/**\n * Stacks rows top-down with a corridor between them.\n *\n * Recurrence:\n * rowTop[0] = padding\n * rowTop[d+1] = rowTop[d] + rows[d].rowH + rows[d].zoneH + corridor\n * busY(d) = rowTop[d+1] − corridor / 2\n * height = rowTop[last] + rows[last].rowH + rows[last].zoneH + padding\n *\n * An empty `rows` array returns `{ rowTop: [], busY: () => 0, height: padding * 2 }`.\n * Pure + deterministic.\n */\nexport function bandStack(rows: BandRow[], opts: BandStackOpts): BandStackResult {\n const { padding, corridor } = opts;\n if (rows.length === 0) {\n return { rowTop: [], busY: () => 0, height: padding * 2 };\n }\n const rowTop: number[] = [padding];\n for (let d = 0; d < rows.length - 1; d++) {\n rowTop.push(rowTop[d]! + rows[d]!.rowH + rows[d]!.zoneH + corridor);\n }\n const last = rows.length - 1;\n const busY = (d: number): number => rowTop[d + 1]! - corridor / 2;\n const height = rowTop[last]! + rows[last]!.rowH + rows[last]!.zoneH + padding;\n return { rowTop, busY, height };\n}\n","// PURE org-chart layout — the single source of truth for box positioning and connector\n// routing. The emitter (./svg.ts) draws EXACTLY what this computes, so every surface\n// (web, PDF, image pipelines) stays pinned together and can never drift.\n//\n// It is deliberately PURE — no DOM, no Node APIs, no clock, no randomness — so the same\n// input always yields the same layout, byte for byte.\n//\n// HONESTY RULE: this module only POSITIONS what the caller declared. There is NO\n// `level`/`depth`/`order` field on the input — depth is READ from the declared solid\n// edges (line|assistant) and the root is READ from topology (a position that is no solid\n// edge's report). Validation (./validate.ts) THROWS on a structurally invalid chart\n// instead of repairing it — an org chart is an authoritative artifact and silently\n// altering who-answers-to-whom is synthesis. Forests (zero/one/many roots) are tolerated.\n//\n// LAYOUT — top-down rows, exactly as every org chart draws it: manager box, short stem\n// down to a sibling bus, drops to each line-report box. Horizontal placement is NAIVE\n// SUBTREE-SPAN PACKING (the fault-tree `pack` transposed top-down, NOT Reingold–Tilford\n// contours): every subtree carries asymmetric half-extents {halfL, halfR}; siblings are\n// placed with disjoint intervals ORG_SIBLING_GAP apart, the recursion makes the guarantee\n// global (a 5-line inductive overlap proof, re-verified by the test harness), at the cost\n// of some width on unbalanced trees. Label widths reserve REAL space because boxW comes\n// from estimateTextWidth over the wrapped lines and the emitter draws with the same core\n// metrics — what is proven is what is drawn.\n//\n// CORRIDOR-GROW INVARIANT (asserted in test/org-chart/layout.test.ts): a manager's\n// assistant stack hangs in the corridor between its row and the next; the corridor grows\n// to clear the tallest stack, so every manager box bottom AND every assistant box bottom\n// sits strictly ABOVE the child bus y (the fault-tree gate-clearance analog).\n//\n// DOTTED/MATRIX overlay → a reserved RIGHT-MARGIN GUTTER (the decisive graft): after the\n// solid tree is placed, each dotted edge routes as a 3-segment orthogonal elbow into a\n// per-edge lane at x > every box's right edge — box-free by construction.\n\nimport { clampLabel, estimateTextWidth, wrapLabelBalanced, type Point, packSubtree, allocateLanes, type PackNode, type PackGaps, type PackResult } from \"../core\";\nimport { ORG_CHART_TITLE_LABELS_EN, type OrgChartTitleLabels } from \"./labels\";\nimport { validateOrgChart } from \"./validate\";\nimport type { OrgBoxStyle, OrgChartInput, OrgPosition, OrgReport } from \"./types\";\n\nexport {\n OrgChartValidationError,\n orgChartIssues,\n validateOrgChart,\n type OrgChartIssue,\n type OrgChartIssueCode,\n} from \"./validate\";\n// Re-exported so the overlap harness (and decorating callers) measure with the EXACT\n// metrics the layout reserved space with — the shared-metrics contract.\nexport { estimateTextWidth };\nexport type { Point };\n\n// ── Type metrics (shared by layout AND the emitter, so geometry == render) ──────\n/** Name line font size (px). */\nexport const ORG_LABEL_FONT = 12;\n/** Title + subtitle + vacant marker font size (px). */\nexport const ORG_TITLE_FONT = 10;\n/** Line height for stacked label lines inside a box (px). */\nexport const ORG_LABEL_LINE_H = 14;\n\n// ── Geometry constants ───────────────────────────────────────────────────────────\n/** Canvas padding on every side. */\nconst PADDING = 32;\n/** Min horizontal air between two sibling subtree intervals. */\nconst ORG_SIBLING_GAP = 28;\n/** Min horizontal air between two forest trees. */\nconst ORG_TREE_GAP = 56;\n/** Base vertical band between a row and the next (the bus lives mid-way). */\nconst ORG_CORRIDOR = 30;\n/** Minimum box width (boxes never shrink below this even with tiny labels). */\nconst ORG_MIN_BOX_W = 120;\n/** Horizontal padding inside a box (each side). */\nconst ORG_BOX_PAD_X = 12;\n/** Vertical padding inside a box (each side). */\nconst ORG_BOX_PAD_Y = 9;\n/** Horizontal gap from a manager's stem to an assistant box (reserved into ownHalfL). */\nconst ORG_ASSIST_GAP = 24;\n/** Vertical gap between stacked assistant bands (and below the last one). */\nconst ORG_ASSIST_BAND_DROP = 14;\n/** Horizontal gap from the tree's right edge to the first dotted gutter lane. */\nconst ORG_MATRIX_GUTTER_GAP = 28;\n/** Horizontal pitch between adjacent dotted gutter lanes. */\nconst ORG_MATRIX_LANE_PITCH = 14;\n/** Horizontal step between adjacent escape-vertical lanes that share a column. The GLOBAL\n * greedy first-fit (STEP 6 / FIX 2) nudges any y-overlapping coincident vertical by\n * lane*ORG_MATRIX_ESCAPE_STEP in the endpoint's escape direction until its column is clear of\n * every already-placed vertical; box-freeness holds while lane*STEP stays inside the MEASURED\n * box-free band to that side (distance to the nearest real box edge overlapping the vertical's\n * y-span). The router asserts (escape-column-overflow) rather than misdraw if a nudge exceeds\n * the band. */\nconst ORG_MATRIX_ESCAPE_STEP = 2;\n\n// ── Namespaced element ids (one element kind per numeric block, fault-tree convention)\n// — every data-edge-id stays traceable to its source row. ───────────────────────\nexport const ORG_STEM_ID_BASE = 1_000_000; // + managerId (manager box bottom → bus level)\nexport const ORG_BUS_ID_BASE = 2_000_000; // + managerId (horizontal sibling bus)\nexport const ORG_DROP_ID_BASE = 3_000_000; // + reportId (bus → line-report box top)\nexport const ORG_ASSIST_ID_BASE = 4_000_000; // + reportId (side-stem elbow to assistant)\nexport const ORG_DOTTED_ID_BASE = 5_000_000; // + report.id (matrix gutter route)\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// A box's LEFT/RIGHT edge AS DRAWN. svg.ts draws the rect at left = round(node.cx −\n// node.boxW/2) from the EMITTED (rounded) node geometry (node.cx === round(cx), node.boxW\n// === round(boxW)); width is node.boxW. Any segment that attaches to a box edge (the assist\n// elbow, the dotted matrix stub) MUST target these exact values — deriving the edge from raw\n// cx/boxW (or from a sibling expression like managerCx − gap) rounds DIFFERENTLY and lands\n// the endpoint a sub-cent INSIDE the box (a real off-by-0.01 in the emitted SVG, flagged by\n// the overlap harness). boxW is an exact multiple of 0.01, so drawnLeft + boxW === the box's\n// own right edge. Box CENTERS (stem/drop x) already use round(cx) === node.cx and are fine.\nconst drawnLeftEdge = (cx: number, boxW: number): number => round(round(cx) - round(boxW) / 2);\nconst drawnRightEdge = (cx: number, boxW: number): number => drawnLeftEdge(cx, boxW) + round(boxW);\n\n// ── Positioned layout ─────────────────────────────────────────────────────────────\n\nexport type OrgElementKind = \"stem\" | \"bus\" | \"drop\" | \"assist\" | \"dotted\";\n\nexport interface OrgNode {\n positionId: number;\n /** Box center x. */\n cx: number;\n /** Box top y. */\n top: number;\n boxW: number;\n boxH: number;\n /** \"solid\" = filled, \"dashed\" = vacant (presentation-only derived value). */\n style: OrgBoxStyle;\n /** Wrapped display lines per family (drawn centered, stacked, by font size). */\n nameLines: string[];\n titleLines: string[];\n subtitleLines: string[];\n /** Localized \"(vago)\" marker line; null on filled boxes. */\n vacantMarker: string | null;\n /** True for side-branched assistant nodes (legend + harness use it). */\n isAssistant: boolean;\n /** Depth of the row this node lives in (assistant: its manager's row + 1 band). */\n depth: number;\n /** Verbatim <title> text. */\n title: string;\n /** True when the caller declared this position annotated. Drives the dot marker in svg.ts. */\n annotated: boolean;\n}\n\nexport interface OrgElement {\n /** Namespaced id (ORG_*_ID_BASE + managerId / reportId / report.id). */\n edgeId: number;\n kind: OrgElementKind;\n /** ≥2 waypoints, every consecutive pair axis-aligned (H or V). */\n points: Point[];\n /** True only on \"dotted\" elements. */\n dashed: boolean;\n /** Verbatim <title> text (woven from the title-label pack). */\n title: string;\n /** True when the source OrgReport was declared annotated. Drives the tick marker in svg.ts.\n * stem/bus: not 1:1 with a report — annotated:false by design (documented choice). */\n annotated: boolean;\n}\n\nexport interface OrgChartLayout {\n width: number;\n height: number;\n nodes: OrgNode[];\n elements: OrgElement[];\n /** Forest order, ascending id. */\n rootPositionIds: number[];\n}\n\nexport interface OrgChartLayoutOptions {\n /** Cap each box's DISPLAY label (compact preview); verbatim text stays in `title`. */\n maxLabelChars?: number;\n /** Locale pack for box/element <title>s — English default; see locale packs. */\n titleLabels?: OrgChartTitleLabels;\n}\n\n// ── PURE span-packer (Judge-1 seam) ────────────────────────────────────────────────\n// packSubtree, PackNode, PackGaps, PackResult — LIFTED to src/core/layered.ts.\n// Re-exported from there via src/core/index.ts and imported at the top of this file.\n// The seam comment, types and function are preserved verbatim in core/layered.ts.\n// Unit-tested directly in test/org-chart/pack-subtree.test.ts (imports from \"../../src/org-chart\").\n\n// Re-export so external callers that import from \"../../src/org-chart\" keep working.\nexport type { PackNode, PackGaps, PackResult };\nexport { packSubtree };\n\n// ── Box measurement (via core text metrics; what is reserved is what is drawn) ──────\n\ninterface Measured {\n boxW: number;\n boxH: number;\n nameLines: string[];\n titleLines: string[];\n subtitleLines: string[];\n vacantMarker: string | null;\n}\n\nfunction measurePosition(\n position: OrgPosition,\n maxLabelChars: number | undefined,\n vacantWord: string,\n): Measured {\n const nameLines =\n position.name === \"\" ? [] : wrapLabelBalanced(clampLabel(position.name, maxLabelChars), 2);\n const titleLines =\n position.title === null ? [] : wrapLabelBalanced(clampLabel(position.title, maxLabelChars), 2);\n const subtitleLines =\n position.subtitle === null ? [] : wrapLabelBalanced(clampLabel(position.subtitle, maxLabelChars), 1);\n const vacantMarker = position.vacancy === \"vacant\" ? vacantWord : null;\n\n let innerW = 0;\n for (const l of nameLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_LABEL_FONT));\n for (const l of titleLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_TITLE_FONT));\n for (const l of subtitleLines) innerW = Math.max(innerW, estimateTextWidth(l, ORG_TITLE_FONT));\n if (vacantMarker !== null) innerW = Math.max(innerW, estimateTextWidth(vacantMarker, ORG_TITLE_FONT));\n\n const boxW = Math.max(ORG_MIN_BOX_W, innerW + ORG_BOX_PAD_X * 2);\n const lineCount =\n nameLines.length + titleLines.length + subtitleLines.length + (vacantMarker !== null ? 1 : 0);\n const boxH = ORG_BOX_PAD_Y * 2 + lineCount * ORG_LABEL_LINE_H;\n return { boxW, boxH, nameLines, titleLines, subtitleLines, vacantMarker };\n}\n\nfunction positionTitle(position: OrgPosition, vacantWord: string): string {\n if (position.hover !== undefined) return position.hover;\n if (position.title !== null) {\n return position.name === \"\" ? position.title : `${position.name} — ${position.title}`;\n }\n if (position.name !== \"\") return position.name;\n return vacantWord; // vacant box with no name & no title — append the vacant word\n}\n\n// ── Internal working node (one per declared position; org positions never repeat) ──\n\ninterface Inst {\n position: OrgPosition;\n m: Measured;\n style: OrgBoxStyle;\n title: string;\n depth: number;\n /** Line-report children (ascending reportId), placed into the sibling rake. */\n lineChildren: Inst[];\n /** Assistant children (ascending reportId), side-stemmed left of the stem. */\n assistants: { inst: Inst; report: OrgReport }[];\n /** Reserved left/right half-extents of THIS node's own box (+ assistant reservation). */\n ownHalfL: number;\n ownHalfR: number;\n /** Subtree half-extents after packing. */\n spanL: number;\n spanR: number;\n /** Offset of each line-child center relative to this node's center. */\n offsets: number[];\n /** Absolute box center x (resolved top-down). */\n cx: number;\n /** Report row that made this an assistant (for the assist element's title/id). */\n assistReport: OrgReport | null;\n /** Absolute box top y for an assistant (set during emit; line nodes use rowTop[depth]). */\n assistTop: number;\n}\n\n/**\n * Deterministic, overlap-proof org-chart layout (pure function of the inputs). Validates\n * first and THROWS OrgChartValidationError on a structurally invalid chart — never\n * sanitizes. Empty input (no positions AND no reports) yields an empty, padded layout.\n */\nexport function computeOrgChartLayout(\n input: OrgChartInput,\n opts: OrgChartLayoutOptions = {},\n): OrgChartLayout {\n if (input.positions.length === 0 && input.reports.length === 0) {\n return { width: PADDING * 2, height: PADDING * 2, nodes: [], elements: [], rootPositionIds: [] };\n }\n validateOrgChart(input);\n\n const titleLabels = opts.titleLabels ?? ORG_CHART_TITLE_LABELS_EN;\n const vacantWord = titleLabels.vacant;\n const positionById = new Map(input.positions.map((p) => [p.id, p]));\n\n // Solid (line|assistant) edges only define the tree. id-sort for order-independence;\n // sibling order among reports is by ascending reportId.\n const reports = [...input.reports].sort((a, b) => a.id - b.id);\n const solidReports = reports.filter((r) => r.kind !== \"dotted\");\n\n // Build per-manager child buckets (line-reports + assistants), each ascending reportId.\n const lineChildIds = new Map<number, OrgReport[]>();\n const assistChildIds = new Map<number, OrgReport[]>();\n const solidParentReportId = new Set<number>(); // positions that have a solid parent\n for (const r of solidReports) {\n solidParentReportId.add(r.reportId);\n const bucket = r.kind === \"assistant\" ? assistChildIds : lineChildIds;\n const arr = bucket.get(r.managerId) ?? [];\n arr.push(r);\n bucket.set(r.managerId, arr);\n }\n for (const arr of lineChildIds.values()) arr.sort((a, b) => a.reportId - b.reportId);\n for (const arr of assistChildIds.values()) arr.sort((a, b) => a.reportId - b.reportId);\n\n // Roots: positions that are no solid edge's reportId, ascending id (forest order).\n const rootPositionIds = input.positions\n .map((p) => p.id)\n .filter((id) => !solidParentReportId.has(id))\n .sort((a, b) => a - b);\n\n // ── Build the instance tree per root over solid edges (each position once). ────────\n const newInst = (position: OrgPosition, depth: number, assistReport: OrgReport | null): Inst => {\n const m = measurePosition(position, opts.maxLabelChars, vacantWord);\n return {\n position,\n m,\n style: position.vacancy === \"vacant\" ? \"dashed\" : \"solid\",\n title: positionTitle(position, vacantWord),\n depth,\n lineChildren: [],\n assistants: [],\n ownHalfL: m.boxW / 2,\n ownHalfR: m.boxW / 2,\n spanL: 0,\n spanR: 0,\n offsets: [],\n cx: 0,\n assistReport,\n assistTop: 0,\n };\n };\n\n const allInsts: Inst[] = [];\n const build = (positionId: number, depth: number, assistReport: OrgReport | null): Inst => {\n const position = positionById.get(positionId)!;\n const inst = newInst(position, depth, assistReport);\n allInsts.push(inst);\n // Assistants live in the manager's corridor band: same row index as a line-report\n // (depth+1) for measurement, but they do NOT advance the row — STEP 4 handles that.\n for (const r of assistChildIds.get(positionId) ?? []) {\n const a = build(r.reportId, depth + 1, r);\n inst.assistants.push({ inst: a, report: r });\n }\n for (const r of lineChildIds.get(positionId) ?? []) {\n inst.lineChildren.push(build(r.reportId, depth + 1, null));\n }\n return inst;\n };\n const roots = rootPositionIds.map((id) => build(id, 0, null));\n\n // ── STEP 3 — assistant side-stem reservation (per-side LEFT, before packing). An\n // assistant adds ORG_ASSIST_GAP + max(assistantBoxW) to the manager's ownHalfL.\n // Vertical stacking never widens further. ─────────────────────────────────────────\n for (const inst of allInsts) {\n if (inst.assistants.length > 0) {\n const widest = inst.assistants.reduce((m, a) => Math.max(m, a.inst.m.boxW), 0);\n inst.ownHalfL = inst.m.boxW / 2 + ORG_ASSIST_GAP + widest;\n }\n }\n\n // ── STEP 2 — horizontal span-pack (post-order) via the PURE packSubtree. ───────────\n const gaps: PackGaps = { siblingGap: ORG_SIBLING_GAP };\n const pack = (inst: Inst): void => {\n for (const c of inst.lineChildren) pack(c);\n const result = packSubtree(\n {\n ownHalfL: inst.ownHalfL,\n ownHalfR: inst.ownHalfR,\n children: inst.lineChildren.map((c) => ({ halfL: c.spanL, halfR: c.spanR })),\n },\n gaps,\n );\n inst.spanL = result.halfL;\n inst.spanR = result.halfR;\n inst.offsets = result.offsets;\n };\n for (const root of roots) pack(root);\n\n // Absolute centers, top-down; forest trees laid left→right ORG_TREE_GAP apart.\n let cursor = PADDING;\n for (const root of roots) {\n root.cx = cursor + root.spanL;\n const placeX = (inst: Inst): void => {\n inst.lineChildren.forEach((c, i) => {\n c.cx = inst.cx + inst.offsets[i]!;\n placeX(c);\n });\n };\n placeX(root);\n cursor = root.cx + root.spanR + ORG_TREE_GAP;\n }\n const canvasRight = roots.length === 0 ? PADDING : cursor - ORG_TREE_GAP; // last root's right edge\n\n // ── STEP 4 — vertical rows by declared depth, with the corridor grown for assistants.\n const rowInsts: Inst[][] = [];\n for (const inst of allInsts) (rowInsts[inst.depth] ??= []).push(inst);\n const depthCount = rowInsts.length;\n\n // Assistant stack height hanging below a manager (sum of assistant boxH + band drops).\n const assistStackH = (inst: Inst): number => {\n if (inst.assistants.length === 0) return 0;\n return (\n inst.assistants.reduce((s, a) => s + a.inst.m.boxH + ORG_ASSIST_BAND_DROP, 0) + ORG_ASSIST_BAND_DROP\n );\n };\n\n const rowH: number[] = [];\n for (let d = 0; d < depthCount; d++) {\n // Row height = tallest LINE-REPORT box in the row (assistants excluded — they hang\n // in the corridor band, not the row). Assistants share a depth index but are not\n // line-children of anyone, so filter them out here.\n const lineBoxes = (rowInsts[d] ?? []).filter((i) => i.assistReport === null);\n rowH.push(lineBoxes.reduce((m, i) => Math.max(m, i.m.boxH), 0));\n }\n\n // Assistant zone below row d: the tallest assistant stack hanging off any manager in\n // row d. Reserved ABOVE the corridor (the fault-tree gateZone analog) so the bus sits\n // CORRIDOR/2 below the BOTTOM of every assistant stack — every assistant box (and its\n // elbow) is strictly above the bus, and every drop (busY → next row) is below it.\n const assistZone: number[] = [];\n for (let d = 0; d < depthCount; d++) {\n let tallest = 0;\n for (const inst of rowInsts[d] ?? []) tallest = Math.max(tallest, assistStackH(inst));\n assistZone.push(tallest);\n }\n\n const rowTop: number[] = [PADDING];\n for (let d = 0; d < depthCount - 1; d++) {\n rowTop.push(rowTop[d]! + rowH[d]! + assistZone[d]! + ORG_CORRIDOR);\n }\n const busY = (d: number): number => rowTop[d + 1]! - ORG_CORRIDOR / 2;\n\n const last = depthCount - 1;\n // The last row's managers cannot have line-reports below them, but a leaf manager in\n // the last row carries no assistants of its own row index either (assistants share the\n // child's depth) — assistZone[last] folds any trailing assistant stack into the height.\n const height = Math.ceil(rowTop[last]! + rowH[last]! + assistZone[last]! + PADDING);\n\n // ── Emit nodes + solid rake elements (DFS order per root). ─────────────────────────\n const nodes: OrgNode[] = [];\n const elements: OrgElement[] = [];\n\n const reportTitle = (kind: OrgReport[\"kind\"], label: string | null | undefined): string => {\n const word = titleLabels.reportKinds[kind];\n return label !== null && label !== undefined ? `${word} · ${label}` : word;\n };\n\n const pushNode = (inst: Inst): void => {\n nodes.push({\n positionId: inst.position.id,\n cx: round(inst.cx),\n top: round(rowTop[inst.depth]!),\n boxW: round(inst.m.boxW),\n boxH: round(inst.m.boxH),\n style: inst.style,\n nameLines: inst.m.nameLines,\n titleLines: inst.m.titleLines,\n subtitleLines: inst.m.subtitleLines,\n vacantMarker: inst.m.vacantMarker,\n isAssistant: inst.assistReport !== null,\n depth: inst.depth,\n title: inst.title,\n annotated: inst.position.annotated ?? false,\n });\n };\n\n const emit = (inst: Inst): void => {\n const d = inst.depth;\n\n // Assistants: top-aligned bands hanging in this manager's corridor (below its row),\n // each its own band-y, the box LEFT of the stem (right edge faces the stem), the\n // elbow a 2-segment orthogonal polyline staying in the reserved left gutter.\n let bandY = rowTop[d]! + rowH[d]! + ORG_ASSIST_BAND_DROP;\n for (const { inst: a, report } of inst.assistants) {\n // Reserved left gutter: stem at inst.cx; assistant box right edge ORG_ASSIST_GAP left.\n const assistRight = inst.cx - ORG_ASSIST_GAP;\n a.cx = assistRight - a.m.boxW / 2;\n // Position the assistant box top at the band-y; its row index (depth) is the same\n // band as a line-report but rowTop[depth] is the line-report row — override per box.\n const assistTop = bandY;\n a.assistTop = assistTop;\n const assistMidY = assistTop + a.m.boxH / 2;\n nodes.push({\n positionId: a.position.id,\n cx: round(a.cx),\n top: round(assistTop),\n boxW: round(a.m.boxW),\n boxH: round(a.m.boxH),\n style: a.style,\n nameLines: a.m.nameLines,\n titleLines: a.m.titleLines,\n subtitleLines: a.m.subtitleLines,\n vacantMarker: a.m.vacantMarker,\n isAssistant: true,\n depth: a.depth,\n title: a.title,\n annotated: a.position.annotated ?? false,\n });\n // Elbow: from the stem at the assistant's mid-y, horizontally LEFT to the box's\n // right edge (2 axis-aligned segments via 3 waypoints; first segment degenerate is\n // avoided because the stem x ≠ box-right x by ORG_ASSIST_GAP). The endpoint must land\n // on the assistant's DRAWN right edge — round(assistRight) (= managerCx − gap) rounds\n // a sub-cent off the box's own round(node.cx − node.boxW/2) edge (seed-103792 sliver).\n elements.push({\n edgeId: ORG_ASSIST_ID_BASE + report.reportId,\n kind: \"assist\",\n points: [\n { x: round(inst.cx), y: round(assistMidY) },\n { x: drawnRightEdge(a.cx, a.m.boxW), y: round(assistMidY) },\n ],\n dashed: false,\n title: reportTitle(\"assistant\", report.label),\n annotated: report.annotated ?? false,\n });\n bandY += a.m.boxH + ORG_ASSIST_BAND_DROP;\n }\n\n pushNode(inst);\n\n // Solid rake to line-reports (none → no stem/bus/drop).\n if (inst.lineChildren.length === 0) return;\n const by = busY(d);\n const boxBottom = rowTop[d]! + inst.m.boxH;\n\n // stem: manager box bottom-center → bus level. Vertical. (Lengthens to busY when the\n // box is shorter than its row's tallest — the row is top-aligned.)\n // stem/bus are not 1:1 with a single OrgReport — annotated:false by design (documented\n // in OrgElement.annotated). The drop IS 1:1 with the child's incoming line report.\n elements.push({\n edgeId: ORG_STEM_ID_BASE + inst.position.id,\n kind: \"stem\",\n points: [\n { x: round(inst.cx), y: round(boxBottom) },\n { x: round(inst.cx), y: round(by) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n annotated: false,\n });\n\n const childCxs = inst.lineChildren.map((c) => c.cx);\n // bus: only for ≥2 line-reports (a single report degenerates to stem + drop on one x).\n // bus is not 1:1 with a single OrgReport — annotated:false by design.\n if (inst.lineChildren.length > 1) {\n elements.push({\n edgeId: ORG_BUS_ID_BASE + inst.position.id,\n kind: \"bus\",\n points: [\n { x: round(Math.min(...childCxs)), y: round(by) },\n { x: round(Math.max(...childCxs)), y: round(by) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n annotated: false,\n });\n }\n\n // drop: bus → each line-report box top-center. Vertical.\n // drops are 1:1 with each child's incoming line report — propagate annotated.\n const lineReports = lineChildIds.get(inst.position.id) ?? [];\n const lineReportByChildId = new Map(lineReports.map((r) => [r.reportId, r]));\n for (const c of inst.lineChildren) {\n const lineReport = lineReportByChildId.get(c.position.id);\n elements.push({\n edgeId: ORG_DROP_ID_BASE + c.position.id,\n kind: \"drop\",\n points: [\n { x: round(c.cx), y: round(by) },\n { x: round(c.cx), y: round(rowTop[c.depth]!) },\n ],\n dashed: false,\n title: reportTitle(\"line\", null),\n annotated: lineReport?.annotated ?? false,\n });\n }\n\n for (const c of inst.lineChildren) emit(c);\n };\n for (const root of roots) emit(root);\n\n // ── STEP 6 — dotted/matrix overlay → reserved RIGHT-MARGIN GUTTER (vertical lane) +\n // a bottom traverse channel (horizontal runs). The decisive graft is the gutter at\n // x > every box's right edge — box-free by construction for the vertical lane. The\n // horizontal runs that REACH the gutter cannot sit at a box's mid-y (they would\n // cross intervening same-row boxes — the \"distant columns of same row\" adversarial\n // case), so each endpoint ESCAPES its box to a box-free column, drops into a bottom\n // channel below every box, and traverses horizontally there. A box-free escape\n // column exists at the SUBTREE right edge (cx + spanR): descendants live inside\n // [cx−spanL, cx+spanR] so their interiors never cross that boundary x, and the next\n // sibling subtree starts ORG_SIBLING_GAP further right. A GLOBAL escape-vertical lane\n // allocation (below) keeps every coincident drop (a shared endpoint's fan, a same-column\n // rep/mgr pair, OR two distinct nodes whose subtree-right boundary equals the same x)\n // from double-drawing. Result is fully orthogonal AND box-free; the harness proves it.\n //\n // Escape geometry per node: the box edge a dotted stub exits and the box-free column it\n // escapes to, SIDE-AWARE. A packed LINE node escapes RIGHT: stub exits its right edge\n // (cx + boxW/2) to the subtree-boundary column (cx + spanR), box-free because descendants\n // live inside [cx−spanL, cx+spanR] and the next sibling starts ORG_SIBLING_GAP further\n // right. An ASSISTANT is NOT packed and sits LEFT of its manager's stem — its right edge\n // is INSIDE the main line-report column, so escaping right would pierce those boxes\n // (defect B). It escapes LEFT instead: stub exits its left edge (cx − boxW/2) into its\n // RESERVED left gutter (cleared in STEP 3 via ORG_ASSIST_GAP), a small box-free band.\n // `side` (+1 right / −1 left) makes the per-endpoint slot offset push AWAY from the box,\n // staying box-free in either gutter.\n interface Escape {\n side: 1 | -1;\n /** Box edge the stub exits (right edge when side=+1, left edge when side=−1). */\n boxEdge: number;\n /** Box-free escape column the stub reaches (with slot 0). */\n escCol: number;\n midY: number;\n boxH: number;\n }\n // FIX 1 — an assistant escapes at its MANAGER's subtree-LEFT boundary, not at its own\n // leftEdge−gap. The own-leftEdge column is box-free only inside the assistant's OWN\n // corridor band; descending to the bottom channel it crosses line-report/assistant boxes\n // in LOWER rows that sit at that x (root cause 1). The manager's WHOLE subtree lives\n // inside [managerCx−spanL, managerCx+spanR], so managerCx−spanL is to the LEFT of every\n // box in the manager's subtree — the strip there is the manager's reserved left gutter,\n // clear down the entire canvas (the next left sibling is ORG_SIBLING_GAP further left).\n // The box-exit stub still leaves the assistant's LEFT edge and runs left to that column\n // at the assistant's band-y (box-free: that row strip is the manager's left gutter).\n const instByPos = new Map(allInsts.map((i) => [i.position.id, i]));\n const escapeByPos = new Map<number, Escape>();\n for (const inst of allInsts) {\n const isAssist = inst.assistReport !== null;\n const boxTop = isAssist ? inst.assistTop : rowTop[inst.depth]!;\n // Attach the matrix stub at the box edges AS DRAWN (seed-7763 dotted#0 × box#p1 sliver).\n const leftEdge = drawnLeftEdge(inst.cx, inst.m.boxW);\n const rightEdge = drawnRightEdge(inst.cx, inst.m.boxW);\n if (isAssist) {\n const managerInst = instByPos.get(inst.assistReport!.managerId)!;\n escapeByPos.set(inst.position.id, {\n side: -1,\n boxEdge: leftEdge,\n escCol: managerInst.cx - managerInst.spanL,\n midY: boxTop + inst.m.boxH / 2,\n boxH: inst.m.boxH,\n });\n } else {\n escapeByPos.set(inst.position.id, {\n side: 1,\n boxEdge: rightEdge,\n escCol: inst.cx + inst.spanR,\n midY: boxTop + inst.m.boxH / 2,\n boxH: inst.m.boxH,\n });\n }\n }\n\n const nodeById = new Map(nodes.map((n) => [n.positionId, n]));\n const dottedReports = reports.filter(\n (r) => r.kind === \"dotted\" && nodeById.has(r.managerId) && nodeById.has(r.reportId) && r.managerId !== r.reportId,\n );\n // Bottom channel sits below the tallest box bottom in the whole canvas.\n let maxBoxBottom = PADDING;\n for (const n of nodes) maxBoxBottom = Math.max(maxBoxBottom, n.top + n.boxH);\n\n let laneCount = 0;\n let channelLanes = 0;\n if (dottedReports.length > 0) {\n // Right-gutter vertical lanes packed by the two endpoints' y-interval (ascending\n // report.id — dottedReports is already id-sorted). Non-overlapping edges share a lane.\n const laneOf = new Map<number, number>();\n laneCount = allocateLanes(\n dottedReports.map((r) => {\n const rep = escapeByPos.get(r.reportId)!;\n const mgr = escapeByPos.get(r.managerId)!;\n return {\n lo: Math.min(rep.midY, mgr.midY),\n hi: Math.max(rep.midY, mgr.midY),\n set: (lane: number) => laneOf.set(r.id, lane),\n };\n }),\n );\n // Each edge gets TWO bottom-channel y-lanes (report-side + manager-side traverse) so\n // the two horizontals never collinear-overlap each other; indexed by edge order.\n channelLanes = dottedReports.length * 2;\n const channelTop = maxBoxBottom + ORG_MATRIX_GUTTER_GAP;\n // Per-endpoint exit-Y slots: when ONE box is the endpoint of several dotted edges (a\n // node that is the dotted target of N managers — the matrix fan), each edge must exit\n // that box's edge at a DISTINCT y, else their horizontal stubs collinear-overlap.\n // Spread the exit y's around the box mid-y, bounded inside the box's edge.\n const exitSlot = new Map<number, number>(); // positionId → next slot index\n const nextExitY = (posId: number, mid: number, boxH: number): number => {\n const slot = exitSlot.get(posId) ?? 0;\n exitSlot.set(posId, slot + 1);\n if (slot === 0) return mid;\n // Alternate above/below the mid-y; stay within ±(boxH/2 − 6) of the box center.\n const step = Math.min(6, Math.max(2, (boxH / 2 - 6) / Math.max(1, Math.ceil(slot / 2))));\n const sign = slot % 2 === 1 ? -1 : 1;\n return mid + sign * Math.ceil(slot / 2) * step;\n };\n\n // ── Per-edge x-INDEPENDENT geometry, computed FIRST (the escape-column x is decided\n // globally afterwards). exitY spreads same-node rows; chY is unique per edge. ──────\n interface EdgeGeom {\n r: (typeof dottedReports)[number];\n i: number;\n repMidY: number;\n mgrMidY: number;\n repBoxEdge: number;\n mgrBoxEdge: number;\n repChY: number;\n mgrChY: number;\n laneX: number;\n repEscX: number; // filled by the global escape-vertical lane allocation\n mgrEscX: number;\n }\n const geoms: EdgeGeom[] = dottedReports.map((r, i) => {\n const rep = escapeByPos.get(r.reportId)!;\n const mgr = escapeByPos.get(r.managerId)!;\n return {\n r,\n i,\n repMidY: round(nextExitY(r.reportId, rep.midY, rep.boxH)),\n mgrMidY: round(nextExitY(r.managerId, mgr.midY, mgr.boxH)),\n repBoxEdge: round(rep.boxEdge),\n mgrBoxEdge: round(mgr.boxEdge),\n repChY: round(channelTop + (2 * i) * ORG_MATRIX_LANE_PITCH),\n mgrChY: round(channelTop + (2 * i + 1) * ORG_MATRIX_LANE_PITCH),\n laneX: round(canvasRight + ORG_MATRIX_GUTTER_GAP + laneOf.get(r.id)! * ORG_MATRIX_LANE_PITCH),\n repEscX: 0,\n mgrEscX: 0,\n };\n });\n\n // ── GLOBAL escape-vertical LANE ALLOCATION (replaces the per-position slot nudge and the\n // rep===mgr special-case — both subsumed). Every dotted edge owns TWO escape verticals\n // (report side, manager side); each draws over the y-interval [min(exitY,chY),\n // max(exitY,chY)]. We GROUP verticals by `${round(escCol)}:${side}` — same base column\n // AND same escape direction — then run allocateLanes over the group's y-intervals: a\n // vertical's column x = round(escCol + side*lane*STEP). Disjoint-y verticals share a lane\n // (same x, never a double-draw because they don't overlap); OVERLAPPING-y verticals get\n // distinct lanes (distinct x). This is overlap-proof for the escape-column class BY\n // CONSTRUCTION and uniformly subsumes the three observed failure modes: same-node fan\n // (same column, overlapping y → distinct lanes), same-column rep/mgr pair in a single-\n // child chain (the old fix-C special case), AND the cross-node coincidence (two distinct\n // nodes whose subtree-right boundary equals the same x — Root vs Boss C: base 448,\n // overlapping y → lanes 0 and 1).\n //\n // BOX-FREE BOUND (geometry-exact, MEASURED — not a fixed gap): a right-escaping (line) node's\n // base escCol = cx + spanR is the subtree's right boundary; all its descendant boxes live\n // inside [cx−spanL, cx+spanR], so the base column AND the band immediately to its right are\n // box-free until the NEXT box (an immediate right sibling subtree starts ORG_SIBLING_GAP away;\n // a pure right-leaning chain with no right sibling has the whole right margin clear). A left-\n // escaping assistant's base is leftEdge−ORG_ASSIST_ESCAPE_GAP, box-free leftward through its\n // reserved ORG_ASSIST_GAP gutter. Nudged columns march in `side` by lane*STEP, deeper into that\n // band. Rather than assume a fixed gutter width, we MEASURE the actual band per group: the\n // distance from escCol to the nearest real box edge on the escape side that vertically overlaps\n // the group's combined y-span (canvasRight/left-margin when none blocks). A coincident base\n // column is only produced by a right-leaning spine (each ancestor's cx+spanR equals the spine-\n // tip's right edge — many verticals, but their tip subtree is the RIGHTMOST so the margin to\n // their right is wide) or a fan into one node (per-node dotted degree capped at 5 in\n // validate.ts, ORG_MAX_MATRIX_EDGES_PER_NODE). The GUARANTEE: the deepest lane (lanes−1)*STEP\n // stays strictly inside the measured band, or we ASSERT (escape-column-overflow) rather than\n // misdraw. This is overlap-proof for the escape-column class BY CONSTRUCTION against the real\n // geometry; the harness is the oracle on every corpus case (incl. a depth-5 spine with 10\n // coincident verticals on one base column, which the wide margin absorbs).\n interface EscVert {\n escCol: number;\n side: 1 | -1;\n lo: number;\n hi: number;\n assign: (x: number) => void;\n }\n const verts: EscVert[] = [];\n for (const g of geoms) {\n const rep = escapeByPos.get(g.r.reportId)!;\n const mgr = escapeByPos.get(g.r.managerId)!;\n verts.push({\n escCol: rep.escCol,\n side: rep.side,\n lo: Math.min(g.repMidY, g.repChY),\n hi: Math.max(g.repMidY, g.repChY),\n assign: (x) => (g.repEscX = x),\n });\n verts.push({\n escCol: mgr.escCol,\n side: mgr.side,\n lo: Math.min(g.mgrMidY, g.mgrChY),\n hi: Math.max(g.mgrMidY, g.mgrChY),\n assign: (x) => (g.mgrEscX = x),\n });\n }\n // FIX 2 — GLOBAL greedy first-fit (replaces the per-group allocateLanes, which de-conflicted\n // only WITHIN one base-column group → a nudged column from group X could land on group Y's\n // column with overlapping y, double-drawing — root cause 2). Here NO two y-overlapping escape\n // verticals ever share a final x, across ALL groups. Each vertical starts at its base column and\n // steps in its escape `side` by ORG_MATRIX_ESCAPE_STEP until its x is clear of every already-placed\n // vertical it shares y with. Collinear-overlap = 0 BY CONSTRUCTION, globally (subsumes both the\n // per-group fan de-confliction AND the cross-group coincidence). Deterministic processing order\n // (edge id, then side) → byte-stable output. Box-free BAND is still measured per vertical and the\n // existing escape-column-overflow assertion fires rather than misdraw; with FIX 1 + the per-node\n // cap of 5 it should never fire on realistic input (the fuzzer confirms).\n //\n // The de-confliction nudge marches in the SAME direction the stub exits (`side`) — AWAY from the\n // node's box, into its box-free band. A LINE node's base column is its subtree-RIGHT boundary\n // (cx+spanR); everything to its right is clear out to canvasRight, so it nudges RIGHT. An ASSISTANT\n // escapes at its manager's subtree-LEFT boundary (managerCx−spanL, FIX 1); EVERY box in that\n // subtree lives to its right (a descendant box's left edge may sit EXACTLY on the boundary), so the\n // box-free room is to the LEFT — toward the canvas edge / the previous tree's gutter — and it nudges\n // LEFT. Nudging the assistant right would step straight into the leftmost descendant box, nudging\n // left stays in the clear margin. The box-exit stub runs from the assistant's left edge to the\n // (nudged) column at the assistant's band-y, box-free either way.\n const VERT_EPS = 0.01;\n // Stable processing order = edge id, then side (report-side before manager-side). `verts` is\n // built [rep0, mgr0, rep1, mgr1, …] over the id-sorted geoms, so the natural index ALREADY\n // encodes (edgeId asc, rep<mgr); make it explicit so a refactor of `verts` can't perturb it.\n const ordered = verts\n .map((v, idx) => ({ v, key: geoms[Math.floor(idx / 2)]!.r.id * 2 + (idx % 2) }))\n .sort((a, b) => a.key - b.key)\n .map((e) => e.v);\n const placed: { x: number; lo: number; hi: number }[] = [];\n const yOverlap = (aLo: number, aHi: number, bLo: number, bHi: number): boolean =>\n Math.min(aHi, bHi) - Math.max(aLo, bLo) > VERT_EPS;\n for (const v of ordered) {\n // Box-free band on the escape side, MEASURED from the real boxes that vertically overlap THIS\n // vertical's y-span: the candidate may march up to (but not into) the nearest box edge on that\n // side. The base column itself is box-free by construction (subtree-right boundary on the right;\n // manager's subtree-left boundary on the left). With no box in the way the band runs to the tree's\n // right edge (canvasRight) on the right, or to the CANVAS edge (x=0) on the left — NOT to PADDING,\n // because the leftmost tree's left boundary sits at PADDING yet the margin down to x=0 is clear.\n let band = v.side === 1 ? Math.max(canvasRight - v.escCol, ORG_MATRIX_GUTTER_GAP) : v.escCol;\n for (const n of nodes) {\n const bLeft = n.cx - n.boxW / 2;\n const bRight = n.cx + n.boxW / 2;\n if (n.top + n.boxH <= v.lo + VERT_EPS || n.top >= v.hi - VERT_EPS) continue; // no y-overlap\n if (v.side === 1 && bLeft > v.escCol + VERT_EPS) band = Math.min(band, bLeft - v.escCol);\n else if (v.side === -1 && bRight < v.escCol - VERT_EPS) band = Math.min(band, v.escCol - bRight);\n }\n let lane = 0;\n let candidate = round(v.escCol);\n // Step away from the box (in `side`) until the candidate column is clear of every placed vertical\n // that shares y with this one.\n while (placed.some((p) => Math.abs(p.x - candidate) < VERT_EPS && yOverlap(p.lo, p.hi, v.lo, v.hi))) {\n lane += 1;\n candidate = round(v.escCol + v.side * lane * ORG_MATRIX_ESCAPE_STEP);\n }\n // A lane-0 vertical sits on its base column — box-free BY CONSTRUCTION, so it needs no band\n // check. A NUDGED vertical must stay strictly inside the measured box-free band, else we assert\n // rather than misdraw.\n if (lane > 0 && lane * ORG_MATRIX_ESCAPE_STEP >= band - VERT_EPS) {\n throw new Error(\n `org-chart: escape-column-overflow — escape vertical nudged ${lane * ORG_MATRIX_ESCAPE_STEP}px from its base column exceeds the ${round(band)}px box-free band`,\n );\n }\n placed.push({ x: candidate, lo: v.lo, hi: v.hi });\n v.assign(candidate);\n }\n\n for (const g of geoms) {\n // 8 waypoints (box edge → escape column → channel → lane → channel → escape column →\n // box edge). Collapse a DEGENERATE first/last stub: a leaf line node's box edge IS its\n // escape column (boxW/2 === spanR with lane 0), so the box-exit and the down-escape\n // share an x → drop the duplicate point so \"every consecutive pair axis-aligned\" holds\n // by construction (no zero-length segment).\n elements.push({\n edgeId: ORG_DOTTED_ID_BASE + g.r.id,\n kind: \"dotted\",\n points: collapseDegenerate([\n { x: g.repBoxEdge, y: g.repMidY }, // out the report box's edge\n { x: g.repEscX, y: g.repMidY }, // → box-free escape column (in own gutter lane)\n { x: g.repEscX, y: g.repChY }, // → down into the bottom traverse channel\n { x: g.laneX, y: g.repChY }, // → across (below all boxes) to the right gutter lane\n { x: g.laneX, y: g.mgrChY }, // → down the right gutter (right of every box)\n { x: g.mgrEscX, y: g.mgrChY }, // → back across (below all boxes) to the manager column\n { x: g.mgrEscX, y: g.mgrMidY }, // → up the box-free escape column\n { x: g.mgrBoxEdge, y: g.mgrMidY }, // → into the manager box's edge\n ]),\n dashed: true,\n title: reportTitle(\"dotted\", g.r.label),\n annotated: g.r.annotated ?? false,\n });\n }\n }\n\n const width =\n dottedReports.length > 0\n ? Math.ceil(canvasRight + ORG_MATRIX_GUTTER_GAP + (laneCount - 1) * ORG_MATRIX_LANE_PITCH + ORG_MATRIX_GUTTER_GAP + PADDING)\n : Math.ceil(canvasRight + PADDING);\n\n // When dotted edges exist the bottom traverse channel hangs below every box; grow the\n // height to cover the deepest channel lane + padding (else solid-tree height stands).\n const finalHeight =\n channelLanes > 0\n ? Math.ceil(maxBoxBottom + ORG_MATRIX_GUTTER_GAP + (channelLanes - 1) * ORG_MATRIX_LANE_PITCH + PADDING)\n : height;\n\n return { width, height: finalHeight, nodes, elements, rootPositionIds };\n}\n\n/** Drop consecutive duplicate waypoints (a zero-length segment) so the routed polyline\n * keeps the \"≥2 waypoints, every consecutive pair axis-aligned over a positive length\"\n * contract by construction — e.g. a leaf line node whose box edge IS its escape column.\n * A two-point result is preserved even if degenerate (cannot happen here: the channel\n * detour guarantees ≥4 distinct points), so the OrgElement.points ≥2 invariant holds. */\nfunction collapseDegenerate(points: Point[]): Point[] {\n const out: Point[] = [];\n for (const p of points) {\n const prev = out[out.length - 1];\n if (prev === undefined || prev.x !== p.x || prev.y !== p.y) out.push(p);\n }\n return out;\n}\n\n// allocateLanes — LIFTED to src/core/layered.ts; imported at the top of this file.\n","// Org-chart SVG emitter — turns a computed OrgChartLayout (./layout.ts) into a\n// SELF-CONTAINED SVG string. Pure (layout in, string out) and deterministic; it draws\n// EXACTLY what the layout computed (the overlap harness proves the layout; this emitter\n// is pinned to it).\n//\n// Hard requirements (house rules):\n// - XML-ESCAPING of EVERY interpolated text — names/titles/subtitles/titles are\n// author-controlled and the SVG may be injected via innerHTML or embedded in PDFs;\n// - LITERAL presentation attributes only (hex colors, explicit font-family): a\n// standalone SVG has no stylesheet, no currentColor, no <defs>/<marker>;\n// - every coordinate goes through round() — 2-decimal, byte-deterministic output.\n//\n// Notation (zinc ramp on white): box rect rx=2 (filled → solid stroke; vacant → dashed\n// stroke + a 3px-inset open-seat frame); centered stacked tspans differentiated by font\n// SIZE (name 12, title/subtitle/vacant 10), never weight; solid stem/bus/drop/assist\n// edges as #71717a w1.5 op .75; dotted via EDGE_STROKE.distant (dasharray 4,4 op .55).\n// NO markers/arrowheads — direction is encoded by manager-above/report-below.\n//\n// Hooks: `<g data-node-id=\"p<id>\">` per box (direct-child verbatim <title>);\n// `<g data-edge-id=\"<n>\">` per element (<title> first), namespaced ids from ./layout.ts.\n\nimport {\n annotationDot,\n annotationSwatch,\n annotationTick,\n EDGE_STROKE,\n FONT_FAMILY,\n legendBlock,\n pathData,\n xmlEscape,\n LEGEND_SWATCH_W,\n type LegendEntry,\n} from \"../core\";\nimport {\n ORG_LABEL_FONT,\n ORG_LABEL_LINE_H,\n ORG_TITLE_FONT,\n type OrgChartLayout,\n type OrgElement,\n type OrgNode,\n} from \"./layout\";\nimport { ORG_CHART_SVG_LABELS_EN, type OrgChartSvgLabels } from \"./labels\";\n\n// Literal ink colors (zinc ramp on white — matches the genogram/ecomap/fault-tree emitters).\nconst GLYPH_STROKE = \"#52525b\";\nconst LABEL_FILL = \"#3f3f46\";\nconst EDGE_INK = \"#71717a\";\nconst GLYPH_ATTRS = `fill=\"transparent\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"2\"`;\nconst VACANT_DASH = `stroke-dasharray=\"6,4\"`;\n/** The dotted/matrix line presentation, reused from the core style table (NOT a judgment). */\nconst DOTTED = EDGE_STROKE.distant; // { width: 1.5, dash: [4, 4], opacity: 0.55 }\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\n// Box vertical padding (mirrors layout ORG_BOX_PAD_Y; the text baseline math needs it).\nconst ORG_BOX_PAD_Y = 9;\n\nexport interface OrgChartSvgOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary (legend/accessibility) — English default; see locale packs. */\n labels?: OrgChartSvgLabels;\n /**\n * Legend label for the annotation row. When provided AND at least one node or element\n * is annotated, one legend row is appended (used-keys-only pattern). The library\n * supplies no default — the caller owns the wording (domain-agnostic).\n */\n annotationLabel?: string;\n}\n\n// ── Box ─────────────────────────────────────────────────────────────────────────────\n\nfunction boxSvg(n: OrgNode): string {\n const left = round(n.cx - n.boxW / 2);\n const pieces: string[] = [`<title>${xmlEscape(n.title)}</title>`];\n\n // Rect: filled → solid stroke; vacant → dashed stroke + a 3px-inset open-seat frame.\n if (n.style === \"dashed\") {\n pieces.push(\n `<rect x=\"${left}\" y=\"${n.top}\" width=\"${n.boxW}\" height=\"${n.boxH}\" rx=\"2\" ${GLYPH_ATTRS} ${VACANT_DASH}/>`,\n );\n const ix = round(left + 3);\n const iy = round(n.top + 3);\n const iw = round(n.boxW - 6);\n const ih = round(n.boxH - 6);\n pieces.push(`<rect x=\"${ix}\" y=\"${iy}\" width=\"${iw}\" height=\"${ih}\" rx=\"2\" ${GLYPH_ATTRS} ${VACANT_DASH}/>`);\n } else {\n pieces.push(`<rect x=\"${left}\" y=\"${n.top}\" width=\"${n.boxW}\" height=\"${n.boxH}\" rx=\"2\" ${GLYPH_ATTRS}/>`);\n }\n\n // Centered stacked tspans: name (12) → title (10) → subtitle (10) → vacant marker (10).\n // Differentiated by font SIZE, not weight. Each text element groups one font size so\n // a single <text font-size> covers its tspans (baseline stepping by ORG_LABEL_LINE_H).\n let lineIndex = 0;\n const firstBaseline = (i: number): number =>\n round(n.top + ORG_BOX_PAD_Y + ORG_LABEL_LINE_H / 2 + i * ORG_LABEL_LINE_H + ORG_LABEL_FONT * 0.32);\n\n const textBlock = (lines: string[], font: number): string => {\n if (lines.length === 0) return \"\";\n const tspans = lines\n .map((line, i) => `<tspan x=\"${n.cx}\" y=\"${firstBaseline(lineIndex + i)}\">${xmlEscape(line)}</tspan>`)\n .join(\"\");\n lineIndex += lines.length;\n return `<text text-anchor=\"middle\" font-family=\"${FONT_FAMILY}\" font-size=\"${font}\" fill=\"${LABEL_FILL}\">${tspans}</text>`;\n };\n\n pieces.push(textBlock(n.nameLines, ORG_LABEL_FONT));\n pieces.push(textBlock(n.titleLines, ORG_TITLE_FONT));\n pieces.push(textBlock(n.subtitleLines, ORG_TITLE_FONT));\n if (n.vacantMarker !== null) pieces.push(textBlock([n.vacantMarker], ORG_TITLE_FONT));\n\n // Annotation dot: upper-right corner of the glyph, inset 4px so it sits on/near the box.\n if (n.annotated) pieces.push(annotationDot(round(n.cx + n.boxW / 2) - 4, n.top + 4));\n\n return `<g data-node-id=\"p${n.positionId}\">${pieces.filter((p) => p !== \"\").join(\"\")}</g>`;\n}\n\n// ── Connector elements ───────────────────────────────────────────────────────────────\n\nfunction elementSvg(el: OrgElement): string {\n const head = `<g data-edge-id=\"${el.edgeId}\"><title>${xmlEscape(el.title)}</title>`;\n const tick = el.annotated ? annotationTick(el.points) : \"\";\n if (el.dashed) {\n const dash = DOTTED.dash === null ? \"\" : ` stroke-dasharray=\"${DOTTED.dash[0]},${DOTTED.dash[1]}\"`;\n return (\n head +\n `<path d=\"${pathData(el.points)}\" fill=\"none\" stroke=\"${EDGE_INK}\" stroke-width=\"${DOTTED.width}\" stroke-opacity=\"${DOTTED.opacity}\"${dash}/>${tick}</g>`\n );\n }\n // Solid stem/bus/drop = single segment <line>; assist = 2-segment <path>.\n if (el.points.length === 2) {\n const a = el.points[0]!;\n const b = el.points[1]!;\n return (\n head +\n `<line x1=\"${a.x}\" y1=\"${a.y}\" x2=\"${b.x}\" y2=\"${b.y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>${tick}</g>`\n );\n }\n return head + `<path d=\"${pathData(el.points)}\" fill=\"none\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>${tick}</g>`;\n}\n\n// ── Legend mini-swatches (scaled into the 22px swatch box) ─────────────────────────\n\nconst MINI_ATTRS = `fill=\"transparent\" stroke=\"${GLYPH_STROKE}\" stroke-width=\"1.5\"`;\n\nfunction lineSwatch(x: number, y: number): string {\n const x1 = round(x + 2);\n const x2 = round(x + LEGEND_SWATCH_W - 2);\n return `<line x1=\"${x1}\" y1=\"${y}\" x2=\"${x2}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>`;\n}\n\nfunction assistantSwatch(x: number, y: number): string {\n // A short stem + side-elbow into a small box (the side-stem convention in miniature).\n const stemX = round(x + LEGEND_SWATCH_W - 4);\n const boxX = round(x + 1);\n return (\n `<line x1=\"${stemX}\" y1=\"${round(y - 4)}\" x2=\"${stemX}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>` +\n `<line x1=\"${stemX}\" y1=\"${y}\" x2=\"${round(boxX + 8)}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"1.5\" stroke-opacity=\"0.75\"/>` +\n `<rect x=\"${boxX}\" y=\"${round(y - 3.5)}\" width=\"8\" height=\"7\" rx=\"1\" ${MINI_ATTRS}/>`\n );\n}\n\nfunction dottedSwatch(x: number, y: number): string {\n const x1 = round(x + 2);\n const x2 = round(x + LEGEND_SWATCH_W - 2);\n const dash = DOTTED.dash === null ? \"\" : ` stroke-dasharray=\"${DOTTED.dash[0]},${DOTTED.dash[1]}\"`;\n return `<line x1=\"${x1}\" y1=\"${y}\" x2=\"${x2}\" y2=\"${y}\" stroke=\"${EDGE_INK}\" stroke-width=\"${DOTTED.width}\" stroke-opacity=\"${DOTTED.opacity}\"${dash}/>`;\n}\n\nfunction vacantSwatch(x: number, y: number): string {\n const cx = round(x + LEGEND_SWATCH_W / 2);\n const bx = round(cx - 8);\n const by = round(y - 5);\n return (\n `<rect x=\"${bx}\" y=\"${by}\" width=\"16\" height=\"10\" rx=\"1\" ${MINI_ATTRS} stroke-dasharray=\"3,2\"/>` +\n `<rect x=\"${round(bx + 2)}\" y=\"${round(by + 2)}\" width=\"12\" height=\"6\" rx=\"1\" ${MINI_ATTRS} stroke-dasharray=\"3,2\"/>`\n );\n}\n\n/**\n * Emits a self-contained SVG for a computed org-chart layout. Pure + deterministic.\n * Coordinates come straight from the layout; all interpolated text is XML-escaped; all\n * presentation attributes are literal. The legend lists ONLY the features actually\n * present (a solid line, an assistant, a dotted edge, a vacant box), in canonical order.\n */\nexport function orgChartLayoutSvg(layout: OrgChartLayout, opts: OrgChartSvgOptions = {}): string {\n const labels = opts.labels ?? ORG_CHART_SVG_LABELS_EN;\n const parts: string[] = [];\n\n // Elements first, then boxes (boxes sit on top), then legend.\n for (const el of layout.elements) parts.push(elementSvg(el));\n for (const n of layout.nodes) parts.push(boxSvg(n));\n\n let width = layout.width;\n let height = layout.height;\n if (opts.legend !== false && layout.nodes.length > 0) {\n const hasSolid = layout.elements.some((e) => e.kind === \"stem\" || e.kind === \"bus\" || e.kind === \"drop\");\n const hasAssistant = layout.nodes.some((n) => n.isAssistant);\n const hasDotted = layout.elements.some((e) => e.kind === \"dotted\");\n const hasVacant = layout.nodes.some((n) => n.style === \"dashed\");\n const entries: LegendEntry[] = [];\n if (hasSolid) entries.push({ swatch: lineSwatch, label: labels.legend.line });\n if (hasAssistant) entries.push({ swatch: assistantSwatch, label: labels.legend.assistant });\n if (hasDotted) entries.push({ swatch: dottedSwatch, label: labels.legend.dotted });\n if (hasVacant) entries.push({ swatch: vacantSwatch, label: labels.legend.vacant });\n // Annotation row: only when label is provided AND at least one node or element is\n // annotated (used-keys-only pattern, consistent with the other legend rows).\n if (\n opts.annotationLabel !== undefined &&\n (layout.nodes.some((n) => n.annotated) || layout.elements.some((e) => e.annotated))\n ) {\n entries.push({ swatch: annotationSwatch, label: opts.annotationLabel });\n }\n const block = legendBlock(entries, layout.height);\n if (block.svg !== \"\") {\n parts.push(block.svg);\n width = Math.max(width, block.width);\n height = block.height;\n }\n }\n\n const w = Math.ceil(width);\n const h = Math.ceil(height);\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${w} ${h}\" width=\"${w}\" height=\"${h}\" role=\"img\" aria-label=\"${xmlEscape(labels.ariaLabel)}\">` +\n parts.join(\"\") +\n `</svg>`\n );\n}\n","// One-call org-chart render: input → { svg, layout }. Thin, honest wiring: validate\n// (throw on a structurally invalid chart — never repair), compute the pure layout, emit.\n// Callers needing finer control use computeOrgChartLayout + orgChartLayoutSvg directly\n// (the layout result supports hit-testing / decorating the diagram).\n\nimport { computeOrgChartLayout, type OrgChartLayout, type OrgChartLayoutOptions } from \"./layout\";\nimport { orgChartLayoutSvg } from \"./svg\";\nimport type { OrgChartSvgLabels } from \"./labels\";\nimport type { OrgChartInput } from \"./types\";\n\nexport interface OrgChartRenderOptions extends OrgChartLayoutOptions {\n /** Set false to suppress the legend (compact preview); default true. */\n legend?: boolean;\n /** Display vocabulary for the emitter (legend/accessibility) — English default. */\n svgLabels?: OrgChartSvgLabels;\n /**\n * Legend label for the annotation row. Forwarded to orgChartLayoutSvg. When provided\n * AND at least one node or element is annotated, a legend row is appended.\n * The library supplies no default — the caller owns the wording.\n */\n annotationLabel?: string;\n}\n\nexport interface OrgChartRenderResult {\n /** Self-contained SVG (numeric width/height + matching viewBox — PDF-embedder safe). */\n svg: string;\n /** The computed layout, for callers that decorate or hit-test the diagram. */\n layout: OrgChartLayout;\n}\n\n/**\n * Renders an org-chart input to a self-contained SVG string. Deterministic: same data →\n * same SVG (array order never matters; sibling order among reports is the ascending\n * reportId). Throws OrgChartValidationError — carrying EVERY issue, deterministically\n * sorted — on a structurally invalid chart. Empty input yields an empty-but-valid SVG;\n * callers decide their own empty state.\n */\nexport function orgChartSvg(input: OrgChartInput, opts: OrgChartRenderOptions = {}): OrgChartRenderResult {\n const layout = computeOrgChartLayout(input, {\n ...(opts.maxLabelChars !== undefined ? { maxLabelChars: opts.maxLabelChars } : {}),\n ...(opts.titleLabels !== undefined ? { titleLabels: opts.titleLabels } : {}),\n });\n const svg = orgChartLayoutSvg(layout, {\n ...(opts.legend === false ? { legend: false } : {}),\n ...(opts.svgLabels !== undefined ? { labels: opts.svgLabels } : {}),\n ...(opts.annotationLabel !== undefined ? { annotationLabel: opts.annotationLabel } : {}),\n });\n return { svg, layout };\n}\n"]}
|