@willcgage/module-schematic 0.49.4 → 0.49.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["a1"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @willcgage/module-schematic — the shared module operations-schematic (track-graph)\n * that the Module Repository authors and Free-Dispatcher imports.\n *\n * Topological, straightened-first: positions are 1-D inches along the module\n * (from endplate A), lanes are integer track indices (0 = primary main). This is\n * the single source of truth for both apps — the doc types, the lenient parser\n * (docs arrive as jsonb / unknown), the pure feature resolver both renderers\n * draw, the N-scale helpers, and the editor <-> doc state machine an authoring\n * UI binds to. See docs/module-schematic-format.md in the free-dispatcher repo.\n *\n * Framework-agnostic and side-effect-free so it can be unit-tested and consumed\n * from Next.js (server + client) and Electron alike.\n */\n\nexport type TrackConfig = \"single\" | \"double\";\nexport type TrackRole = \"main\" | \"siding\" | \"spur\" | \"yard\" | \"crossover\" | \"branch\";\nexport type TurnoutKind = \"left\" | \"right\" | \"wye\";\nexport type SignalFacing = \"AtoB\" | \"BtoA\";\nexport type SignalSide = \"above\" | \"below\";\n\nexport interface SchematicEndplateTrack {\n trackId: string;\n lane: number;\n config?: TrackConfig | null;\n}\nexport interface SchematicEndplate {\n id: string; // \"A\" (West) | \"B\" (East) | \"C\"… (branch, #170)\n label?: string | null;\n tracks?: SchematicEndplateTrack[];\n /** Branch endplates (#170): where a 3rd+ endplate sits — pos inches from A,\n * on the up (north/above) or down side. Absent = axial (A at 0, B at\n * lengthInches). Renderers draw a named connector arrow (the CATS/US&S\n * off-band idiom) until branch spines land. */\n at?: { pos: number; side: \"up\" | \"down\" };\n /** Manual pose override (#175 phase 1b) — the endplate's module-local track\n * point (x, y inches) + outward-normal heading (°). Hand-entered for shapes\n * the geometry fields can't derive (wye, freeform, loop); wins over\n * deriveEndplatePoses' derivation. */\n pose?: { x: number; y: number; heading: number };\n /** Free-moN endplate FACE width across the track, inches — the physical size\n * of the standard interface at this end. Free-moN spec: 12″ minimum, 24″\n * recommended. Absent = the recommended default (modules may differ end to\n * end, e.g. a transition). */\n widthInches?: number | null;\n /** Where this end's PRIMARY track (Main 1) crosses, as a signed distance from\n * the plate's CENTRE in inches — the standard's own framing (\"each track\n * 0.5625 inches from the center of the endplate\"). §2.0 requires only that\n * every track stay ≥4″ from either fascia; centring is a recommendation the\n * 20220628 revision relaxed, so an offset is legal — a transition SECTION\n * commonly offsets its single-track end so the through main lines up with one\n * of the two tracks at its double end. Absent = the recommended default\n * (single centred; double straddling at ∓ half the track spacing). */\n trackOffsetInches?: number | null;\n /** Branch endplates (#170) only — what the route reaching this endplate IS:\n * a secondary \"branch\" line, or a \"main\" (a diverging / split main). Drives\n * labels + drawn weight, not geometry. Absent = \"branch\". */\n kind?: \"branch\" | \"main\" | null;\n /** Branch endplates only — the id of the drawn diverging track that reaches\n * this endplate (its authored path ends at the plate face). Lets remove/\n * round-trip pair the endplate with its track. Absent = not yet connected. */\n trackId?: string | null;\n}\n\n/** Free-moN endplate face width, inches — the connection interface size. */\nexport const FREEMO_ENDPLATE_WIDTH_MIN_INCHES = 12;\n/** NB: our own default, NOT from the standard — §1.1 states only the 12″ minimum\n * (\"Endplates shall be 6 inches high and a minimum 12 inches wide\"). 24″ is\n * simply a common real-world width. Don't present it as required. */\nexport const FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = 24;\n/** Free-moN §2.0 **standard**: \"Double track endplates must have a track spacing\n * of 1.125 inches (1 1/8 inches). Track spacing shall be measured along the\n * track center line.\" The one definition both apps read. */\nexport const FREEMO_TRACK_SPACING_INCHES = 1.125;\n/** Free-moN §2.0 **standard**: track crossing an endplate must be \"not less than\n * 4 inches from either fascia\" (and perpendicular, straight and level for 4″). */\nexport const FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES = 4;\n\n/**\n * The authored face width for an endplate, or the recommended default when a\n * module hasn't authored one. The single source of truth both apps read so a\n * module's endplate size is drawn the same in the Repository and the layout.\n */\nexport function endplateWidthInches(\n ep: { widthInches?: number | null } | null | undefined,\n): number {\n const w = ep?.widthInches;\n return typeof w === \"number\" && w > 0\n ? w\n : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;\n}\nexport interface SchematicTrack {\n id: string;\n role: TrackRole;\n lane: number;\n from?: string;\n to?: string;\n fromPos?: number | null;\n toPos?: number | null;\n capacityFeet?: number | null;\n industryRef?: number | null;\n /** The module_tracks row this track is (single source of truth); null = new. */\n moduleTrackId?: number | null;\n /** Owner's track name, mirrored to module_tracks.track_name. */\n trackName?: string;\n /** Inside the balloon of a loop module (#165): pos still measures from\n * endplate A (past the throat = in the loop), lane is the ladder/arc index —\n * one record drives both the unrolled fan and a geometric render. */\n inLoop?: boolean;\n /** Authored 2-D path for this track (module-local inches, open path with\n * arcs) — the PHYSICAL shape a bent/rotated spur draws. Absent = derive from\n * the main centre-line + lane, as before. Physical view only; the operations\n * view stays positional (#2d-track). */\n path?: BenchworkPoint[] | null;\n}\nexport interface SchematicTurnout {\n id: string;\n pos: number;\n onTrack: string;\n divergeTrack: string;\n kind?: TurnoutKind;\n name?: string | null;\n address?: string | null;\n /** Frog number (\"size\") — #4, #6, #8, etc. Governs the diverging angle. */\n size?: number | null;\n /** A curved turnout — the diverging route bows into an arc (both routes curve\n * the same way) instead of leaving as a straight diagonal. Physical-render\n * only; the operations view stays topological. */\n curved?: boolean | null;\n /** Rotate the turnout 180° — the points face the other way along the track.\n * HAND is which turnout you own; how it's INSTALLED is a separate choice, and\n * the drawn orientation can't always be inferred from where the diverging\n * track happens to run. A siding at the far end of a module is the case that\n * forces it: the body has nowhere to go but back toward the module, so the\n * derived facing comes out backwards. */\n flipped?: boolean | null;\n}\nexport interface SchematicSignal {\n id: string;\n pos: number;\n /** Track the signal governs; absent = the primary main (lane 0). */\n track?: string;\n facing?: SignalFacing;\n kind?: \"mast\" | \"dwarf\";\n name?: string | null;\n aspects?: string[];\n /** Which side of the track the signal sits on (#122). */\n side?: SignalSide;\n /** Turnout this control point governs; absent = standalone block signal. */\n turnout?: string;\n}\nexport interface SchematicBlock {\n id: string;\n name: string;\n tracks?: string[];\n from: number;\n to: number;\n}\n/** A grade crossing / diamond (#170): two tracks cross with no route choice —\n * a conflict node, not a turnout. A connected diamond adds normal turnouts\n * alongside. Drawn as an X between the two tracks' lanes. */\nexport interface SchematicCrossing {\n id: string;\n pos: number;\n /** The two crossing tracks, by id. */\n tracks: [string, string];\n name?: string | null;\n}\n/**\n * A control point is an interlocking: a named group of one or more signals and\n * zero or more turnouts. A passing siding has two (West/East); a lone block\n * signal is a control point with one signal and no turnouts.\n */\nexport interface SchematicControlPoint {\n id: string;\n name?: string | null;\n turnouts?: string[];\n /** Crossings this interlocking protects (#170). */\n crossings?: string[];\n signals?: SchematicSignal[];\n}\n/** What a rendered industry shows beside its name: a car count, a length in\n * inches, or nothing (name only). Authored per industry. */\nexport type IndustryLabelMode = \"none\" | \"cars\" | \"inches\";\n\n/**\n * An industry — a rail-served customer that spots cars, authored as a SPAN on a\n * track (a spur/siding, or the main). Positional like everything else: it lives\n * in the same module-local inch frame and is rendered into the shared 2-D view,\n * offset to `side`. The span length gives its car capacity; the dispatcher and\n * crews read where cars set out. Mirrors a `freemon_industries` row.\n */\n/** One car-spot span of an industry on a track — an industry may have several\n * (a house track serving one customer across multiple spot tracks, #54). */\nexport interface IndustrySpot {\n track: string;\n fromPos: number;\n toPos: number;\n side?: SignalSide;\n}\n\nexport interface SchematicIndustry {\n id: string;\n name: string;\n /** Industry type value from the lookup (e.g. \"team_track\", \"grain\"). */\n type?: string | null;\n /** The primary track this industry spots cars on (a spur/siding id or main).\n * Additional spots (other tracks) live in `spots`. */\n track: string;\n /** The primary car-spot span along `track`, inches from endplate A. */\n fromPos: number;\n toPos: number;\n /** Extra car-spot spans on other tracks — the industry's house-track spots. */\n spots?: IndustrySpot[];\n /** Which side of the track the building + label sit on. */\n side?: SignalSide;\n /** Secondary readout at the label — a car count, a length, or none. */\n labelMode?: IndustryLabelMode;\n /** Car types this industry receives (car-type value strings). */\n carTypes?: string[];\n /** The `freemon_industries` row this is (single source of truth); null = new. */\n moduleIndustryId?: number | null;\n}\n\nexport interface ModuleSchematicDoc {\n version: number;\n module?: string;\n lengthInches?: number;\n /** Single-endplate turnback (balloon loop): the main enters at A, runs the\n * lead, and turns back — renderers draw a terminal bulb at the far end\n * instead of a second endplate. Also implied by a single-entry endplates\n * array (a category:\"loop\" module like Seaford). */\n loop?: boolean;\n /** Where the balloon returns (#165): \"same\" (default) turns back onto the\n * same main; \"main2\" is a directional return on a double-track main —\n * out on Main 1, back on Main 2 — drawn as a U joining the two lanes\n * (the transit terminal-loop idiom). */\n loopReturn?: \"same\" | \"main2\";\n /** Optional rendering override: \"bulb\" (abstract terminal), \"fan\" (interior\n * tracks unrolled as a ladder past the throat — the default when inLoop\n * tracks exist), \"geometric\" (drawn balloon, AL&E-style). */\n loopRender?: \"bulb\" | \"fan\" | \"geometric\";\n /** The two mains' positions are swapped: Main 1 draws above (lane 1), Main 2\n * on the centre line (lane 0). Absent/false = the default (Main 1 below).\n * Identities are unchanged — only which lane each is drawn in (#FMN-0043). */\n mainsSwapped?: boolean;\n endplates: SchematicEndplate[];\n tracks: SchematicTrack[];\n turnouts?: SchematicTurnout[];\n /** Grade crossings / diamonds (#170). */\n crossings?: SchematicCrossing[];\n controlPoints?: SchematicControlPoint[];\n /** Rail-served industries — car-spot spans on a track (#industries). */\n industries?: SchematicIndustry[];\n /** Benchwork FOOTPRINT outline — the module's physical board shape as a\n * polygon in module-local inches, in the same frame as the endplate poses\n * (endplate A's track point at the origin, the mainline along +x, perpendicular\n * +y up). Stored as an open ring; renderers close it. Absent = derive an\n * approximate band from the endplate widths. */\n outline?: BenchworkPoint[];\n /** Benchwork HOLE — an inner boundary punched out of `outline`, making the\n * board a DONUT (a return loop's open middle). Same frame as `outline`; stored\n * as an open ring, renderers close it. Absent = a solid board. */\n outlineInner?: BenchworkPoint[];\n /** Internal section joints — inches from endplate A where the module's boards\n * split into sections. Operationally one unit; these mark construction/transport\n * seams (exempt from the end-interface standards). Empty/absent = one section.\n * Describes only sections that are full-depth SLICES; a section with a shape\n * of its own lives in `sections` below. */\n sectionBreaks?: number[];\n /** The module's sections as real objects — named, each with a bench-work\n * outline of its own (#96 phase 2). A module is a kit: the same sections can\n * be set up in different combinations, so its footprint is the UNION of the\n * sections present rather than an independently authored shape.\n *\n * Needed because sections are not slices. Real modules hang a deep section\n * off the BACK of a shallow main band — a peninsula carrying an industry —\n * which no single position along the main can describe.\n *\n * Absent = the module keeps using its own `outline` exactly as before; this\n * is purely additive and nothing migrates on read. */\n sections?: SchematicSection[];\n /** @deprecated pre-grouping flat signals; read for back-compat. */\n signals?: SchematicSignal[];\n /** Authored mainline centre-line (module-local inches, open path with arcs).\n * Present = the owner drew the real shape; absent = derive from geometry.\n * Physical view only — the operations view stays derived (#2d-track). */\n mainPath?: BenchworkPoint[] | null;\n /** Authored centre-line for MAIN 2 on a double-track module (module-local\n * inches, open path with arcs). Present = the owner bent Main 2 to its real\n * shape; absent = derive it as a lane offset from Main 1. Physical view only\n * (#131). */\n main2Path?: BenchworkPoint[] | null;\n}\n\n/** A benchwork-outline vertex, module-local inches. The edge from this vertex\n * to the NEXT one is a straight line, unless `bulge` is set — then it's a\n * circular arc whose midpoint is offset `bulge` inches (signed: + bows to the\n * left of the P→next direction) perpendicular from the chord. */\nexport interface BenchworkPoint {\n x: number;\n y: number;\n bulge?: number;\n}\n\n/** NB: a module has NO compass direction of its own, deliberately. It has ends\n * A and B. Direction is a property of the LAYOUT — the same board can be\n * installed running either way round, or on either axis, so a compass label\n * stored here could only ever contradict the layout that placed it. Railroads\n * do the same thing with timetable direction: the railroad declares which way\n * is \"east\", not any one piece of track. Free-Dispatcher owns direction. */\n\n/** One bench-work section of a module (#96 phase 2). */\nexport interface SectionFootprint {\n id: string;\n name?: string;\n outline: { x: number; y: number }[];\n /** True when this shape is DERIVED from the section's span rather than\n * authored — a derived outline follows the board when it's resized, an\n * authored one stays exactly as drawn (#96 phase 2b). */\n derived: boolean;\n}\n\nexport interface SchematicSection {\n id: string;\n /** What the owner calls this board — \"west transition\", \"double #3\". */\n name?: string | null;\n /** This section's own footprint polygon, module-local inches, same frame as\n * the module outline. Absent = the section has no shape of its own yet (it's\n * described only by the joints in `sectionBreaks`). */\n outline?: BenchworkPoint[] | null;\n /** How far this board runs along the main, inches. The module's length is the\n * SUM of these — it isn't authored separately (#108). */\n lengthInches?: number | null;\n /** This board's own shape: straight | curve | corner_45 | corner_90 | offset |\n * dead_end. Geometry belongs to the SECTION, not the module — a module like\n * One Mile is 384″ of mostly-straight boards with two 24″ CURVED sections in\n * the middle, which no single module-level geometry can describe (#108).\n * Absent = straight. */\n geometryType?: string | null;\n /** Degrees turned, for curve/corner sections. */\n geometryDegrees?: number | null;\n /** Lateral jog, for offset sections. */\n geometryOffsetInches?: number | null;\n}\n\n/** The authored benchwork outline, or null when a module hasn't drawn one\n * (renderers then fall back to a band derived from the endplate widths). A\n * valid outline needs at least 3 points. Normalises each vertex to {x, y, bulge?}. */\nexport function benchworkOutline(\n doc: { outline?: BenchworkPoint[] | null } | null | undefined,\n): BenchworkPoint[] | null {\n const pts = (doc?.outline ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n return pts.length >= 3 ? pts : null;\n}\n\n/** The module's sections, normalised — id required, name trimmed away when\n * blank, outline kept only when it's a usable polygon (#96 phase 2). */\nexport function moduleSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): SchematicSection[] {\n return (doc?.sections ?? [])\n .filter((sec) => sec && typeof sec.id === \"string\" && sec.id !== \"\")\n .map((sec) => {\n const outline = benchworkOutline({ outline: sec.outline });\n const name = typeof sec.name === \"string\" ? sec.name.trim() : \"\";\n const len = sec.lengthInches;\n const deg = sec.geometryDegrees;\n const off = sec.geometryOffsetInches;\n return {\n id: sec.id,\n ...(name ? { name } : {}),\n ...(outline ? { outline } : {}),\n ...(typeof len === \"number\" && Number.isFinite(len) && len > 0\n ? { lengthInches: len }\n : {}),\n ...(sec.geometryType ? { geometryType: sec.geometryType } : {}),\n ...(typeof deg === \"number\" && Number.isFinite(deg) ? { geometryDegrees: deg } : {}),\n ...(typeof off === \"number\" && Number.isFinite(off) ? { geometryOffsetInches: off } : {}),\n };\n });\n}\n\n/** Every section outline that's actually a shape, arc-sampled for drawing.\n * Drawing all of them IS the module's footprint — the union of its sections.\n * No polygon boolean is computed: a renderer painting each ring gives the same\n * picture, and an approximate union would be worse than none. If something\n * ever needs a single ring (an export, a collision test), that's the point to\n * bring in real clipping. */\nexport function sectionFootprints(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n /** The module's spine and dimensions. Given these, a section with no\n * authored polygon gets a band derived from its own span, so every section\n * has a shape and a resized board reshapes with it (#96 phase 2b). Omit to\n * get authored outlines only. */\n derive?: {\n centerline: BenchworkPoint[];\n widthA: number;\n widthB: number;\n offsetA: number;\n offsetB: number;\n },\n): SectionFootprint[] {\n const spans = derive ? sectionSpans(doc) : [];\n const spanOf = new Map(spans.map((sp) => [sp.id, sp]));\n return moduleSections(doc)\n .map((sec): SectionFootprint | null => {\n const name = sec.name ? { name: sec.name } : {};\n if (sec.outline)\n return { id: sec.id, ...name, outline: sampleBenchworkOutline(sec.outline), derived: false };\n const sp = spanOf.get(sec.id);\n if (!sp || !derive) return null;\n const band = sectionBand(\n derive.centerline,\n sp.fromPos,\n sp.toPos,\n derive.widthA,\n derive.widthB,\n derive.offsetA,\n derive.offsetB,\n );\n return band.length >= 3 ? { id: sec.id, ...name, outline: band, derived: true } : null;\n })\n .filter((x): x is SectionFootprint => x !== null);\n}\n\n/**\n * Expand a benchwork outline (whose edges may be arcs) into a dense closed\n * polyline for rendering — the SAME sampling both the Repository preview and\n * Free-Dispatcher use, so a curve looks identical in both. Straight edges emit\n * just their start vertex; a bulged edge emits `segsPerArc` points along the\n * circular arc through the two endpoints and the bulged midpoint.\n */\nexport function sampleBenchworkOutline(\n pts: BenchworkPoint[],\n segsPerArc = 20,\n): { x: number; y: number }[] {\n const n = pts.length;\n if (n < 2) return pts.map((p) => ({ x: p.x, y: p.y }));\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i < n; i++) {\n const p0 = pts[i];\n const p1 = pts[(i + 1) % n];\n out.push({ x: p0.x, y: p0.y });\n const bulge = p0.bulge ?? 0;\n if (!bulge) continue; // straight edge\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n const c = Math.hypot(dx, dy);\n if (c < 1e-6) continue;\n // Arc midpoint = chord midpoint + left-normal * sagitta.\n const nx = -dy / c;\n const ny = dx / c;\n const mid = { x: (p0.x + p1.x) / 2 + nx * bulge, y: (p0.y + p1.y) / 2 + ny * bulge };\n const circ = circleThrough(p0, mid, p1);\n if (!circ) continue; // colinear → treat as straight\n const a0 = Math.atan2(p0.y - circ.cy, p0.x - circ.cx);\n const am = Math.atan2(mid.y - circ.cy, mid.x - circ.cx);\n const a1 = Math.atan2(p1.y - circ.cy, p1.x - circ.cx);\n // Sweep from a0 to a1 the way that passes through the midpoint angle.\n const sweep = arcSweep(a0, a1, am);\n for (let s = 1; s < segsPerArc; s++) {\n const a = a0 + (sweep * s) / segsPerArc;\n out.push({ x: circ.cx + circ.r * Math.cos(a), y: circ.cy + circ.r * Math.sin(a) });\n }\n }\n return out;\n}\n\n/**\n * Expand an OPEN track path (whose edges may be arcs) into a dense polyline —\n * the open-ended sibling of sampleBenchworkOutline (which closes the ring).\n * Used for authored track centre-lines (a drawn mainline or spur). The final\n * vertex is always emitted so the path reaches its end.\n */\nexport function samplePath(\n pts: BenchworkPoint[],\n segsPerArc = 20,\n): { x: number; y: number }[] {\n const n = pts.length;\n if (n < 2) return pts.map((p) => ({ x: p.x, y: p.y }));\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i < n - 1; i++) {\n const p0 = pts[i];\n const p1 = pts[i + 1];\n out.push({ x: p0.x, y: p0.y });\n const bulge = p0.bulge ?? 0;\n if (!bulge) continue; // straight edge\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n const c = Math.hypot(dx, dy);\n if (c < 1e-6) continue;\n const nx = -dy / c;\n const ny = dx / c;\n const mid = { x: (p0.x + p1.x) / 2 + nx * bulge, y: (p0.y + p1.y) / 2 + ny * bulge };\n const circ = circleThrough(p0, mid, p1);\n if (!circ) continue;\n const a0 = Math.atan2(p0.y - circ.cy, p0.x - circ.cx);\n const am = Math.atan2(mid.y - circ.cy, mid.x - circ.cx);\n const a1 = Math.atan2(p1.y - circ.cy, p1.x - circ.cx);\n const sweep = arcSweep(a0, a1, am);\n for (let s = 1; s < segsPerArc; s++) {\n const a = a0 + (sweep * s) / segsPerArc;\n out.push({ x: circ.cx + circ.r * Math.cos(a), y: circ.cy + circ.r * Math.sin(a) });\n }\n }\n out.push({ x: pts[n - 1].x, y: pts[n - 1].y });\n return out;\n}\n\n/** Normalise an authored track path from a doc, or null if it isn't a real path\n * (needs ≥ 2 valid points). Keeps per-vertex bulge. */\nexport function trackPath(\n path: BenchworkPoint[] | null | undefined,\n): BenchworkPoint[] | null {\n const pts = (path ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n return pts.length >= 2 ? pts : null;\n}\n\n/** Circle through three points, or null if (near-)colinear. */\nfunction circleThrough(\n a: { x: number; y: number },\n b: { x: number; y: number },\n c: { x: number; y: number },\n): { cx: number; cy: number; r: number } | null {\n const d = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y));\n if (Math.abs(d) < 1e-9) return null;\n const a2 = a.x * a.x + a.y * a.y;\n const b2 = b.x * b.x + b.y * b.y;\n const c2 = c.x * c.x + c.y * c.y;\n const cx = (a2 * (b.y - c.y) + b2 * (c.y - a.y) + c2 * (a.y - b.y)) / d;\n const cy = (a2 * (c.x - b.x) + b2 * (a.x - c.x) + c2 * (b.x - a.x)) / d;\n return { cx, cy, r: Math.hypot(a.x - cx, a.y - cy) };\n}\n\n/** Signed sweep from a0 to a1 that goes through the midpoint angle am. */\nfunction arcSweep(a0: number, a1: number, am: number): number {\n const norm = (x: number) => {\n let v = (x - a0) % (2 * Math.PI);\n if (v < 0) v += 2 * Math.PI;\n return v; // 0..2π, measured CCW from a0\n };\n const m = norm(am);\n const one = norm(a1);\n // If the midpoint is reached before a1 going CCW, sweep CCW (+); else CW (−).\n return m <= one ? one : one - 2 * Math.PI;\n}\n\n// ── Physical module footprint (shared by the Repository preview + Free-Dispatcher)\n// The single-module geometry both apps draw: the main track centre-line, the\n// derived benchwork band (an endplate-width ribbon, the fallback when no outline\n// is authored), the endplate FACES, and the authored outline (arcs sampled).\n// Module-local inches: endplate A's track point at the origin, mainline +x,\n// perpendicular +y up. Free-Dispatcher's composeFootprint stacks these per module\n// by the join graph; here we expose the per-module primitive so the Repository\n// renders the exact same board.\n\nconst DEG_FP = Math.PI / 180;\n\nexport interface ModuleFootprintInput {\n /** Mainline length (falls back to footprint length), inches. */\n lengthInches: number;\n geometryType?: string | null;\n geometryDegrees?: number | null;\n geometryOffsetInches?: number | null;\n /** Authored endplate face widths by id (\"A\"/\"B\"…), inches; default recommended. */\n endplateWidths?: Record<string, number>;\n /** Where each endplate's CENTRE sits relative to the main centre-line at that\n * end, inches (signed, along the +normal). Free-moN puts a **double**-track\n * plate's two tracks 9/16″ either side of its centre, so with Main 1 on the\n * centre-line the plate centre is half a track spacing up — pass\n * `FREEMO_TRACK_SPACING_INCHES / 2`. Single track crosses at the centre ⇒ 0\n * (the default), and an off-centre track is a signed value. */\n endplateTrackOffsets?: Record<string, number>;\n /** Authored benchwork outline (module-local inches), or absent for the band. */\n outline?: BenchworkPoint[] | null;\n /** Authored benchwork HOLE — the inner boundary punched out of `outline` to\n * make a donut. Absent/short = a solid board. */\n outlineInner?: BenchworkPoint[] | null;\n /** The module's sections (#96 phase 2). When any carries an outline, the\n * module's footprint is the union of those — `outline` is then ignored. */\n sections?: SchematicSection[] | null;\n /** Authored mainline centre-line (module-local inches, open path with arcs).\n * When present it wins over the geometry-derived centre-line — the owner drew\n * the real shape (#2d-track, physical view only). */\n mainPath?: BenchworkPoint[] | null;\n /** A balloon / return loop — the centre-line turns back on itself, so its far\n * end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */\n loop?: boolean;\n}\n\nexport interface OutlineFace {\n /** The endplate face's two corners + midpoint (the track point). */\n p1: BenchworkPoint;\n p2: BenchworkPoint;\n mid: BenchworkPoint;\n}\n\nexport interface ModuleFootprint {\n /** Main track centre-line A→B (arcs sampled). */\n centerline: BenchworkPoint[];\n /** Derived benchwork band (endplate-width ribbon); the outline fallback. */\n band: BenchworkPoint[];\n /** Endplate faces: [A end, B end]. */\n endplateFaces: OutlineFace[];\n /** Authored outline (arc-sampled closed ring) or null → render the band.\n * Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */\n outline: BenchworkPoint[] | null;\n /** Authored HOLE (arc-sampled closed ring) punched out of `outline` → a donut\n * board. Null = solid. Renderers fill `outline` with `outlineInner` cut out. */\n outlineInner: BenchworkPoint[] | null;\n /** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together\n * they are the module's footprint. Empty = this module doesn't use sections,\n * so fall back to `outline ?? band` exactly as before. */\n sectionOutlines: SectionFootprint[];\n}\n\n/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.\n * An authored `mainPath` wins — the owner drew the real shape; otherwise the\n * centre-line is derived from the geometry fields (length + type/degrees/offset). */\nexport function moduleCenterline(input: ModuleFootprintInput): BenchworkPoint[] {\n const drawn = trackPath(input.mainPath);\n if (drawn) return samplePath(drawn);\n // Sections own the shape when there are any (#108) — a multi-section module\n // has no single geometry, so its spine is its boards chained end to end.\n const chained = sectionedCenterline(input);\n if (chained.length >= 2) return chained;\n // No drawn main and no geometry → the owner hasn't established the mainline\n // yet. A fresh module opens as a blank board; the main is drawn as a layer,\n // not auto-derived. (Legacy modules carry a geometry, so they still derive.)\n if (!input.geometryType) return [];\n const L = input.lengthInches > 0 ? input.lengthInches : 24;\n const gt = input.geometryType;\n if (gt === \"dead_end\") return [{ x: 0, y: 0 }];\n if (gt === \"offset\") return [{ x: 0, y: 0 }, { x: L, y: input.geometryOffsetInches ?? 0 }];\n const turn =\n gt === \"corner_45\" ? 45 : gt === \"corner_90\" ? 90 : gt === \"curve\" ? (input.geometryDegrees ?? 0) : 0;\n if (turn === 0) return [{ x: 0, y: 0 }, { x: L, y: 0 }];\n const t = turn * DEG_FP;\n const r = L / t;\n const steps = 12;\n const pts: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) {\n const a = (t * i) / steps;\n pts.push({ x: r * Math.sin(a), y: r * (1 - Math.cos(a)) });\n }\n return pts;\n}\n\n/** One section's centre-line in ITS OWN frame — starting at the origin heading\n * +x — plus where it leaves off. Same geometry vocabulary the module level has\n * always used, just applied per board (#108). */\nfunction sectionCenterlineLocal(sec: SchematicSection): {\n points: BenchworkPoint[];\n endX: number;\n endY: number;\n endHeadingDeg: number;\n} {\n const L = typeof sec.lengthInches === \"number\" && sec.lengthInches > 0 ? sec.lengthInches : 0;\n const gt = sec.geometryType || \"straight\";\n if (L <= 0) return { points: [{ x: 0, y: 0 }], endX: 0, endY: 0, endHeadingDeg: 0 };\n if (gt === \"offset\") {\n const dy = sec.geometryOffsetInches ?? 0;\n // A jog returns to the original heading, so the next board carries on square.\n return { points: [{ x: 0, y: 0 }, { x: L, y: dy }], endX: L, endY: dy, endHeadingDeg: 0 };\n }\n const turn =\n gt === \"corner_45\" ? 45 : gt === \"corner_90\" ? 90 : gt === \"curve\" ? (sec.geometryDegrees ?? 0) : 0;\n if (turn === 0) return { points: [{ x: 0, y: 0 }, { x: L, y: 0 }], endX: L, endY: 0, endHeadingDeg: 0 };\n const t = turn * DEG_FP;\n const r = L / t; // constant-radius arc of arc-length L\n const steps = 12;\n const points: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) {\n const a = (t * i) / steps;\n points.push({ x: r * Math.sin(a), y: r * (1 - Math.cos(a)) });\n }\n const last = points[points.length - 1];\n return { points, endX: last.x, endY: last.y, endHeadingDeg: turn };\n}\n\n/** The module's length as the SUM of its sections, or null when it has none\n * (then the authored module length still speaks). */\nexport function moduleLengthFromSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): number | null {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return null;\n return secs.reduce((a, sec) => a + sec.lengthInches!, 0);\n}\n\n/** Where each section starts and ends along the main, inches from endplate A.\n * This is what `sectionBreaks` used to author by hand — now derived, so a\n * length is just a number you type and nothing steals from its neighbour. */\nexport function sectionSpans(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): { id: string; name?: string; fromPos: number; toPos: number }[] {\n let acc = 0;\n const out: { id: string; name?: string; fromPos: number; toPos: number }[] = [];\n for (const sec of moduleSections(doc)) {\n const L = typeof sec.lengthInches === \"number\" && sec.lengthInches > 0 ? sec.lengthInches : 0;\n if (L <= 0) continue;\n out.push({ id: sec.id, ...(sec.name ? { name: sec.name } : {}), fromPos: acc, toPos: acc + L });\n acc += L;\n }\n return out;\n}\n\n/** A position expressed against the board it sits on, rather than as inches\n * from endplate A (#109). */\nexport interface SectionRelativePos {\n sectionId: string;\n /** Inches from that section's own west end. */\n offsetInches: number;\n}\n\n/**\n * Section spans that ALWAYS cover the whole module. The owner's insight is\n * what makes #109 tractable: every module has at least one section, even if\n * that one section IS the whole module. So a module with no authored sections\n * gets a single implicit span 0→length, every position falls inside exactly\n * one span, and absolute ↔ relative becomes a total, lossless mapping with no\n * un-convertible module and no orphan positions.\n *\n * The last span is also stretched to the module length when the sections come\n * up short, so a position past the end still lands somewhere real.\n */\nexport function sectionSpansOrWhole(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n lengthInches: number,\n): { id: string; name?: string; fromPos: number; toPos: number }[] {\n const L = lengthInches > 0 ? lengthInches : 0;\n const spans = sectionSpans(doc);\n if (!spans.length) return [{ id: WHOLE_MODULE_SECTION_ID, fromPos: 0, toPos: L }];\n const out = spans.map((sp) => ({ ...sp }));\n const last = out[out.length - 1];\n if (L > last.toPos) last.toPos = L;\n return out;\n}\n\n/** The id a module with no authored sections uses for its single implicit one. */\nexport const WHOLE_MODULE_SECTION_ID = \"module\";\n\n/**\n * Absolute inches → the board it sits on plus an offset along it (#109).\n * Total: given spans from `sectionSpansOrWhole`, every position resolves.\n *\n * A position exactly ON a joint is assigned to the section that STARTS there,\n * at offset 0 — a joint is the west end of the next board, and that keeps the\n * mapping single-valued. The module's own east end is the exception: nothing\n * starts there, so it belongs to the last board.\n */\nexport function toSectionRelative(\n pos: number,\n spans: { id: string; fromPos: number; toPos: number }[],\n): SectionRelativePos | null {\n if (!spans.length) return null;\n const p = Math.max(spans[0].fromPos, Math.min(spans[spans.length - 1].toPos, pos));\n for (const sp of spans) {\n if (p >= sp.fromPos && p < sp.toPos)\n return { sectionId: sp.id, offsetInches: round3(p - sp.fromPos) };\n }\n const last = spans[spans.length - 1];\n return { sectionId: last.id, offsetInches: round3(last.toPos - last.fromPos) };\n}\n\n/** …and back. Null when the section is gone — which is the caller's cue that\n * the thing it positioned has lost its board (#96 phase 3). */\nexport function fromSectionRelative(\n rel: SectionRelativePos,\n spans: { id: string; fromPos: number; toPos: number }[],\n): number | null {\n const sp = spans.find((x) => x.id === rel.sectionId);\n if (!sp) return null;\n return round3(sp.fromPos + Math.max(0, Math.min(sp.toPos - sp.fromPos, rel.offsetInches)));\n}\n\n/** Re-derive an absolute position after the sections have moved: read it\n * against the OLD spans, write it against the NEW ones. This is the whole\n * point of #109 — reorder or resize a board and everything on it comes along\n * instead of silently pointing at a different board. */\nexport function remapPos(\n pos: number,\n before: { id: string; fromPos: number; toPos: number }[],\n after: { id: string; fromPos: number; toPos: number }[],\n): number | null {\n const rel = toSectionRelative(pos, before);\n return rel ? fromSectionRelative(rel, after) : null;\n}\n\n/** The joints implied by the sections — the interior boundaries, in inches from\n * endplate A. Replaces the authored `sectionBreaks` for a sectioned module. */\nexport function sectionBreaksFromSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): number[] {\n const spans = sectionSpans(doc);\n return spans.slice(0, -1).map((sp) => sp.toPos);\n}\n\n/** The module's centre-line built by CHAINING its sections — each board starts\n * where the previous one ended, at the heading it ended on. This is what makes\n * a module like One Mile expressible: straight boards with two 24″ curved ones\n * in the middle, which no single module-level geometry can describe (#108).\n * Returns [] when the module has no sections with lengths. */\n/** Where the chained boards finish, and on what heading — computed from the\n * section geometry itself rather than read off the sampled polyline. A curve\n * is sampled in steps, so the last chord lags the true tangent by half a step\n * (a 90° board sampled 12 ways reads 86.25°). That error would land straight\n * in endplate B's heading and throw off face-to-face snapping, so the exact\n * value is accumulated here instead. Null when there are no sections. */\nexport function sectionedEndPose(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): { x: number; y: number; heading: number } | null {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return null;\n let ox = 0;\n let oy = 0;\n let heading = 0;\n for (const sec of secs) {\n const local = sectionCenterlineLocal(sec);\n const c = Math.cos(heading * DEG_FP);\n const sn = Math.sin(heading * DEG_FP);\n ox += local.endX * c - local.endY * sn;\n oy += local.endX * sn + local.endY * c;\n heading += local.endHeadingDeg;\n }\n return { x: ox, y: oy, heading };\n}\n\nexport function sectionedCenterline(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): BenchworkPoint[] {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return [];\n const out: BenchworkPoint[] = [];\n let ox = 0;\n let oy = 0;\n let heading = 0; // degrees, +x at endplate A\n for (const sec of secs) {\n const local = sectionCenterlineLocal(sec);\n const c = Math.cos(heading * DEG_FP);\n const sn = Math.sin(heading * DEG_FP);\n for (let i = 0; i < local.points.length; i++) {\n // The first vertex of every board but the first repeats the previous\n // board's end point — skip it so the spine has no duplicate vertices.\n if (i === 0 && out.length) continue;\n const p = local.points[i];\n out.push({ x: ox + p.x * c - p.y * sn, y: oy + p.x * sn + p.y * c });\n }\n ox += local.endX * c - local.endY * sn;\n oy += local.endX * sn + local.endY * c;\n heading += local.endHeadingDeg;\n }\n return out;\n}\n\n/** Unit left normal of the local direction at each centre-line vertex. */\nfunction centerlineNormals(center: BenchworkPoint[]): BenchworkPoint[] {\n return center.map((_, i) => {\n const a = center[Math.max(0, i - 1)];\n const b = center[Math.min(center.length - 1, i + 1)];\n let dx = b.x - a.x;\n let dy = b.y - a.y;\n const len = Math.hypot(dx, dy) || 1;\n dx /= len;\n dy /= len;\n return { x: -dy, y: dx };\n });\n}\n\n/** Fraction 0→1 along the centre-line by arc length (A end = 0, B end = 1). */\nfunction centerlineFractions(center: BenchworkPoint[]): number[] {\n const cum = [0];\n for (let i = 1; i < center.length; i++)\n cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));\n const total = cum[cum.length - 1] || 1;\n return cum.map((d) => d / total);\n}\n\n/** Benchwork band: the centre-line offset ±half-width, tapering widthA→widthB. */\nexport function benchworkBand(\n center: BenchworkPoint[],\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): BenchworkPoint[] {\n if (center.length < 2) return [];\n const n = centerlineNormals(center);\n const f = centerlineFractions(center);\n const half = (i: number) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;\n // The board is centred on the plate centre, which need not be the main\n // centre-line — a double-track end sits half a track spacing up (#93).\n const off = (i: number) => offsetA * (1 - f[i]) + offsetB * f[i];\n const left = center.map((p, i) => ({\n x: p.x + n[i].x * (off(i) + half(i)),\n y: p.y + n[i].y * (off(i) + half(i)),\n }));\n const right = center.map((p, i) => ({\n x: p.x + n[i].x * (off(i) - half(i)),\n y: p.y + n[i].y * (off(i) - half(i)),\n }));\n return [...left, ...right.reverse()];\n}\n\n/** The sub-polyline of a centre-line between two arc-length positions, with\n * the cut ends interpolated so a slice starts and finishes exactly on them. */\nexport function sliceCenterline(\n center: BenchworkPoint[],\n fromPos: number,\n toPos: number,\n): BenchworkPoint[] {\n if (center.length < 2) return [];\n const cum = [0];\n for (let i = 1; i < center.length; i++)\n cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));\n const total = cum[cum.length - 1];\n const a = Math.max(0, Math.min(total, Math.min(fromPos, toPos)));\n const b = Math.max(0, Math.min(total, Math.max(fromPos, toPos)));\n if (b - a <= 0) return [];\n const at = (d: number): BenchworkPoint => {\n for (let i = 1; i < center.length; i++) {\n if (d <= cum[i] || i === center.length - 1) {\n const seg = cum[i] - cum[i - 1] || 1;\n const t = Math.max(0, Math.min(1, (d - cum[i - 1]) / seg));\n return {\n x: center[i - 1].x + (center[i].x - center[i - 1].x) * t,\n y: center[i - 1].y + (center[i].y - center[i - 1].y) * t,\n };\n }\n }\n return center[center.length - 1];\n };\n const out: BenchworkPoint[] = [at(a)];\n for (let i = 0; i < center.length; i++) {\n if (cum[i] > a && cum[i] < b) out.push({ x: center[i].x, y: center[i].y });\n }\n out.push(at(b));\n return out;\n}\n\n/** One section's bench-work as a band over its own stretch of centre-line —\n * the per-section equivalent of `benchworkBand` (#96 phase 2b). Width and\n * plate offset are interpolated from the module's ends exactly as the whole\n * band does, so a section's derived shape lines up with its neighbours.\n *\n * This is what makes an outline BELONG to the section: a section without an\n * authored polygon gets one derived from its span, so resizing the board\n * reshapes it instead of leaving a hand-drawn outline stranded. */\nexport function sectionBand(\n center: BenchworkPoint[],\n fromPos: number,\n toPos: number,\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): BenchworkPoint[] {\n const slice = sliceCenterline(center, fromPos, toPos);\n if (slice.length < 2) return [];\n // Fractions must be taken along the WHOLE module, not the slice, or every\n // section would taper from widthA to widthB over its own short length.\n let total = 0;\n for (let i = 1; i < center.length; i++)\n total += Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y);\n total = total || 1;\n const lo = Math.min(fromPos, toPos);\n let acc = 0;\n const fr: number[] = [0];\n for (let i = 1; i < slice.length; i++) {\n acc += Math.hypot(slice[i].x - slice[i - 1].x, slice[i].y - slice[i - 1].y);\n fr.push(acc);\n }\n const f = fr.map((d) => Math.max(0, Math.min(1, (lo + d) / total)));\n const n = centerlineNormals(slice);\n const half = (i: number) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;\n const off = (i: number) => offsetA * (1 - f[i]) + offsetB * f[i];\n const left = slice.map((p, i) => ({\n x: p.x + n[i].x * (off(i) + half(i)),\n y: p.y + n[i].y * (off(i) + half(i)),\n }));\n const right = slice.map((p, i) => ({\n x: p.x + n[i].x * (off(i) - half(i)),\n y: p.y + n[i].y * (off(i) - half(i)),\n }));\n return [...left, ...right.reverse()];\n}\n\n/** Two sections that physically meet, and how much edge they share. */\nexport interface SectionAdjacency {\n a: string;\n b: string;\n /** Inches of shared edge — a butt joint across a 24″ board reads ~24. */\n lengthInches: number;\n}\n\n/** Closed-ring edges of a polygon, including the wrap-around. */\nfunction ringEdges(pts: { x: number; y: number }[]): [\n { x: number; y: number },\n { x: number; y: number },\n][] {\n const out: [{ x: number; y: number }, { x: number; y: number }][] = [];\n for (let i = 0; i < pts.length; i++) out.push([pts[i], pts[(i + 1) % pts.length]]);\n return out;\n}\n\n/** How much of two near-collinear segments actually overlap, in inches. 0 when\n * they're skew, too far apart, or merely touching at a point. */\nfunction sharedEdgeLength(\n e1: [{ x: number; y: number }, { x: number; y: number }],\n e2: [{ x: number; y: number }, { x: number; y: number }],\n gap: number,\n angleDeg: number,\n): number {\n const ux = e1[1].x - e1[0].x;\n const uy = e1[1].y - e1[0].y;\n const ul = Math.hypot(ux, uy);\n const vx = e2[1].x - e2[0].x;\n const vy = e2[1].y - e2[0].y;\n const vl = Math.hypot(vx, vy);\n if (ul < 1e-6 || vl < 1e-6) return 0;\n const dx = ux / ul;\n const dy = uy / ul;\n // Parallel either way round — a shared joint has the two boards' edges\n // running in OPPOSITE directions, since each ring winds around its own board.\n const cross = Math.abs((dx * vy - dy * vx) / vl);\n if (cross > Math.sin((angleDeg * Math.PI) / 180)) return 0;\n // Both endpoints of e2 must lie within `gap` of e1's infinite line.\n const perp = (q: { x: number; y: number }) =>\n Math.abs((q.x - e1[0].x) * -dy + (q.y - e1[0].y) * dx);\n if (perp(e2[0]) > gap || perp(e2[1]) > gap) return 0;\n const proj = (q: { x: number; y: number }) => (q.x - e1[0].x) * dx + (q.y - e1[0].y) * dy;\n const t1 = proj(e2[0]);\n const t2 = proj(e2[1]);\n return Math.max(0, Math.min(ul, Math.max(t1, t2)) - Math.max(0, Math.min(t1, t2)));\n}\n\n/**\n * Which sections physically MEET, derived from shared polygon edges rather\n * than list order (#96 phase 2c).\n *\n * Order is the wrong model as soon as a module stops being a row of boards: a\n * peninsula hangs off the BACK of a shallow band over part of its length, so\n * it neighbours a board it isn't next to in any list. Geometry is the only\n * thing that knows.\n */\nexport function sectionAdjacency(\n footprints: SectionFootprint[],\n opts?: { gapInches?: number; angleDegrees?: number; minOverlapInches?: number },\n): SectionAdjacency[] {\n const gap = opts?.gapInches ?? 0.5;\n const angle = opts?.angleDegrees ?? 3;\n const min = opts?.minOverlapInches ?? 1;\n const edges = footprints.map((f) => ringEdges(f.outline));\n const out: SectionAdjacency[] = [];\n for (let i = 0; i < footprints.length; i++) {\n for (let j = i + 1; j < footprints.length; j++) {\n let total = 0;\n for (const e1 of edges[i])\n for (const e2 of edges[j]) total += sharedEdgeLength(e1, e2, gap, angle);\n if (total >= min)\n out.push({\n a: footprints[i].id,\n b: footprints[j].id,\n lengthInches: Math.round(total * 1000) / 1000,\n });\n }\n }\n return out;\n}\n\n/** The sections each one touches. */\nexport function sectionNeighbours(id: string, adj: SectionAdjacency[]): string[] {\n return adj.filter((x) => x.a === id || x.b === id).map((x) => (x.a === id ? x.b : x.a));\n}\n\n/**\n * Groups of sections that hang together, as connected components. One group\n * means the module is a single piece of bench work; more than one means some\n * board is floating free — an authoring mistake now, and the test #96 phase 3\n * needs before it can say whether dropping a section leaves the rest intact.\n */\nexport function sectionComponents(ids: string[], adj: SectionAdjacency[]): string[][] {\n const parent = new Map(ids.map((id) => [id, id]));\n const find = (x: string): string => {\n let r = x;\n while (parent.get(r) !== r) r = parent.get(r)!;\n while (parent.get(x) !== r) {\n const nx = parent.get(x)!;\n parent.set(x, r);\n x = nx;\n }\n return r;\n };\n for (const { a, b } of adj) {\n if (!parent.has(a) || !parent.has(b)) continue;\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n }\n const groups = new Map<string, string[]>();\n for (const id of ids) {\n const r = find(id);\n groups.set(r, [...(groups.get(r) ?? []), id]);\n }\n // Keep the caller's ordering so the first group is the one containing the\n // first section — the piece with endplate A on it.\n return [...groups.values()];\n}\n\n/** The two endplate faces (the band's flat ends): [A end at widthA, B end at widthB]. */\nexport function endplateFaceSegments(\n center: BenchworkPoint[],\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): OutlineFace[] {\n if (center.length < 2) return [];\n const n = centerlineNormals(center);\n // `mid` stays the TRACK point (what joints and drawn track key off); the face\n // spans ±w/2 about the PLATE centre, which a double-track end offsets (#93).\n const face = (i: number, w: number, o: number): OutlineFace => ({\n p1: { x: center[i].x + n[i].x * (o + w / 2), y: center[i].y + n[i].y * (o + w / 2) },\n p2: { x: center[i].x + n[i].x * (o - w / 2), y: center[i].y + n[i].y * (o - w / 2) },\n mid: { x: center[i].x, y: center[i].y },\n });\n return [face(0, widthA, offsetA), face(center.length - 1, widthB, offsetB)];\n}\n\n/**\n * The full single-module physical footprint: centre-line + derived band +\n * endplate faces + the authored outline (arc-sampled), all in module-local\n * inches. Renderers draw `outline ?? band`.\n */\nexport function moduleFootprint(input: ModuleFootprintInput): ModuleFootprint {\n const centerline = moduleCenterline(input);\n const widthA = endplateWidthFor(input.endplateWidths, \"A\");\n const widthB = endplateWidthFor(input.endplateWidths, \"B\");\n const authored = benchworkOutline(input);\n const offA = input.endplateTrackOffsets?.[\"A\"] ?? 0;\n const offB = input.endplateTrackOffsets?.[\"B\"] ?? 0;\n // A module built from shaped sections IS its sections — the whole-module\n // outline stops speaking for it, so don't hand back both and leave renderers\n // to guess which wins (#96 phase 2).\n const sectionOutlines = sectionFootprints(input, {\n centerline,\n widthA,\n widthB,\n offsetA: offA,\n offsetB: offB,\n });\n return {\n centerline,\n band: benchworkBand(centerline, widthA, widthB, offA, offB),\n // A loop's centre-line ends at the throat, not a far endplate — keep only\n // endplate A's face (the far face would be a spurious plate at the throat).\n endplateFaces: input.loop\n ? endplateFaceSegments(centerline, widthA, widthB, offA, offB).slice(0, 1)\n : endplateFaceSegments(centerline, widthA, widthB, offA, offB),\n outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),\n // The donut hole, arc-sampled — only when there's a solid outline to punch it\n // out of (a sectioned module isn't a donut). Renderers cut it from `outline`.\n outlineInner:\n sectionOutlines.length || !authored || !input.outlineInner || input.outlineInner.length < 3\n ? null\n : sampleBenchworkOutline(input.outlineInner),\n sectionOutlines,\n };\n}\n\n/**\n * The offset from the main centre-line to an endplate's CENTRE, inches — the\n * Free-moN geometry. A **double**-track end carries its two tracks 9/16″ either\n * side of the plate centre (§2.0 RP), and Main 1 sits on the centre-line, so the\n * plate centre is half a track spacing up. A single track crosses at the centre.\n */\nexport function endplateTrackOffsetFor(\n config: TrackConfig | \"none\" | undefined,\n authoredTrackOffset?: number | null,\n): number {\n const v = -endplateTrackOffsetInches(authoredTrackOffset, config);\n return v === 0 ? 0 : v; // never hand back -0 (it leaks into JSON and compares oddly)\n}\n\n/**\n * Where an endplate's PRIMARY track (Main 1) crosses, as a signed distance from\n * the plate's CENTRE — the standard's own framing. Authored value wins; absent\n * falls back to the §2.0 recommendations: a single track centred (0), a double\n * straddling so its two tracks land ∓ half the track spacing (Main 1 low).\n */\nexport function endplateTrackOffsetInches(\n authored: number | null | undefined,\n config: TrackConfig | \"none\" | undefined,\n): number {\n if (typeof authored === \"number\" && Number.isFinite(authored)) return authored;\n return config === \"double\" ? -FREEMO_TRACK_SPACING_INCHES / 2 : 0;\n}\n\n/** A Free-moN conformance problem with an endplate's width/track placement. */\nexport interface EndplateWidthIssue {\n /** \"narrow\" = below the 12″ minimum; \"clearance\" = a track too near a fascia. */\n code: \"narrow\" | \"clearance\";\n /** Plain-language problem, for the author. */\n message: string;\n /** The width that would satisfy this rule, inches. */\n requiredInches: number;\n}\n\n/**\n * Check an endplate against the two Free-moN **standards** that bound its width:\n *\n * - §1.1 \"Endplates shall be 6 inches high and a **minimum 12 inches wide**.\"\n * - §2.0 \"At the endplate, track shall cross near center on the width, **not less\n * than 4 inches from either fascia**.\"\n *\n * With the tracks centred (the §2.0 recommendation) a double-track end needs\n * 4 + 1.125 + 4 = 9.125″ for clearance alone, so the 12″ minimum governs — but an\n * **off-centre** track can breach the 4″ rule on a plate that is otherwise wide\n * enough, which is why both are checked. `trackOffsetInches` is the signed\n * distance from the plate's centre to the main's crossing point (0 = centred).\n */\nexport function checkEndplateWidth(input: {\n widthInches?: number | null;\n config?: TrackConfig | \"none\" | null;\n trackOffsetInches?: number | null;\n}): EndplateWidthIssue[] {\n const width = endplateWidthInches(input as { widthInches?: number | null });\n const issues: EndplateWidthIssue[] = [];\n if (width < FREEMO_ENDPLATE_WIDTH_MIN_INCHES) {\n issues.push({\n code: \"narrow\",\n message: `Endplate is ${round2(width)}″ wide — the standard requires at least ${FREEMO_ENDPLATE_WIDTH_MIN_INCHES}″.`,\n requiredInches: FREEMO_ENDPLATE_WIDTH_MIN_INCHES,\n });\n }\n // Track centres relative to the plate centre. `trackOffsetInches` locates\n // MAIN 1 (the same framing the authoring field and the renderer use); a\n // double end carries Main 2 one spacing further out, so check whichever of\n // the two sits nearest a fascia. Unauthored falls back to the §2.0 default,\n // which straddles the centre — so a plain double end still measures ±9/16″.\n const off = endplateTrackOffsetInches(input.trackOffsetInches, input.config ?? undefined);\n const centres =\n input.config === \"double\" ? [off, off + FREEMO_TRACK_SPACING_INCHES] : [off];\n const worst = Math.max(...centres.map((c) => Math.abs(c)));\n const clearance = width / 2 - worst;\n if (clearance < FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES) {\n const required = 2 * (worst + FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES);\n issues.push({\n code: \"clearance\",\n message:\n `Track sits ${round2(clearance)}″ from the fascia — the standard requires at least ` +\n `${FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES}″. Widen this end to ${round2(required)}″` +\n (off !== 0 ? \" or move the track back toward the centre.\" : \".\"),\n requiredInches: required,\n });\n }\n return issues;\n}\n\nconst round2 = (n: number) => Math.round(n * 100) / 100;\nconst round3 = (n: number) => Math.round(n * 1000) / 1000;\n\nfunction endplateWidthFor(widths: Record<string, number> | undefined, id: string): number {\n const w = widths?.[id];\n return typeof w === \"number\" && w > 0 ? w : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;\n}\n\n/** Whether a doc is a single-endplate turnback (explicit flag or one endplate). */\nexport function isLoopDoc(doc: ModuleSchematicDoc): boolean {\n return doc.loop === true || doc.endplates.length === 1;\n}\n\nexport const MAIN_TRACK_ID = \"main\";\n/** The second main on double-track modules — a real track entity so turnouts\n * and signals can attach to it (a spur off Main 2 must diverge from lane 1,\n * not draw a crossover from Main 1). Emitted by stateToDoc when either\n * endplate is double; legacy docs without it still parse. */\nexport const MAIN2_TRACK_ID = \"main2\";\n\n// North American N scale (1:160): 396 real inches → 5280 scale feet = one mile.\nexport const N_SCALE_RATIO = 160;\n/** Real inches on the module → scale feet of prototype track represented. */\nexport function inchesToScaleFeet(inches: number, ratio = N_SCALE_RATIO): number {\n return (inches * ratio) / 12;\n}\n/** Scale feet of prototype track → real inches on the module. */\nexport function scaleFeetToInches(feet: number, ratio = N_SCALE_RATIO): number {\n return (feet * 12) / ratio;\n}\n\n/** Length a spotted car occupies on N-scale track, inches. A 40-ft car body is\n * ~3.0″; ~3.3″ over the couplers — the real spacing a cut of cars takes. The\n * single constant every repo reads so a track's car count matches everywhere. */\nexport const N_CAR_LENGTH_INCHES = 3.3;\n\n/** How many cars fit in a span, from its drawn length — the derived capacity a\n * siding or an industry spot holds (never typed). */\nexport function carCapacity(\n fromPos: number,\n toPos: number,\n carLengthInches = N_CAR_LENGTH_INCHES,\n): number {\n if (!(carLengthInches > 0)) return 0;\n return Math.max(0, Math.floor(Math.abs(toPos - fromPos) / carLengthInches));\n}\n\n/** Parse a jsonb value into a schematic doc, or null if it isn't one. */\nexport function asModuleSchematic(x: unknown): ModuleSchematicDoc | null {\n if (!x || typeof x !== \"object\") return null;\n const d = x as Record<string, unknown>;\n if (typeof d.version !== \"number\") return null;\n if (!Array.isArray(d.endplates) || !Array.isArray(d.tracks)) return null;\n return d as unknown as ModuleSchematicDoc;\n}\n\n// ---- Editor state (a flatter shape an authoring form binds to) -------------\n\nexport interface EditorTrack {\n id: string;\n role: TrackRole;\n lane: number;\n fromPos: number;\n toPos: number;\n /** module_tracks row id (single source of truth), or null for a new track. */\n moduleTrackId: number | null;\n /** Owner's track name → module_tracks.track_name. */\n trackName: string;\n /** Inside the balloon of a loop module (#165). */\n inLoop?: boolean;\n /** Authored 2-D path (module-local inches) — a bent/rotated spur's real\n * shape. Absent = derive from the main + lane (#2d-track). */\n path?: BenchworkPoint[];\n}\n\n/** A module_tracks row as loaded for the editor. */\nexport interface ModuleTrackRow {\n id: number;\n track_name: string | null;\n capacity_scale_feet: number | null;\n}\nexport interface EditorTurnout {\n id: string;\n name: string;\n pos: number;\n onTrack: string;\n divergeTrack: string;\n kind: TurnoutKind;\n /** Frog number (\"size\") — #4, #6, #8, etc. Governs the diverging angle. */\n size?: number;\n /** Rotate the turnout 180° — the points face the other way (#turnout-flip). */\n flipped?: boolean;\n /** A curved turnout — the diverging route bows into an arc rather than a\n * straight diagonal. Physical-render only (the operations view is topological). */\n curved?: boolean;\n}\nexport interface EditorCpSignal {\n id: string;\n pos: number;\n track: string;\n facing: SignalFacing;\n side: SignalSide;\n}\nexport interface EditorControlPoint {\n id: string;\n name: string;\n turnouts: string[]; // turnout ids grouped under this control point\n /** Crossing ids this interlocking protects (#170). */\n crossings?: string[];\n signals: EditorCpSignal[];\n}\nexport interface EditorCrossing {\n id: string;\n name: string;\n pos: number;\n trackA: string;\n trackB: string;\n}\n/** An industry as the authoring form binds it — a car-spot span on a track. */\nexport interface EditorIndustry {\n id: string;\n name: string;\n type: string;\n track: string;\n fromPos: number;\n toPos: number;\n /** Extra car-spot spans on other tracks (house-track spots, #54). */\n spots: IndustrySpot[];\n side: SignalSide;\n labelMode: IndustryLabelMode;\n carTypes: string[];\n /** freemon_industries row (single source of truth), or null for a new one. */\n moduleIndustryId: number | null;\n}\n/** A 3rd+ endplate — a branch/junction connection off the module (#170).\n * A module may have several (e.g. a set carrying a second railroad through:\n * MoPac enters at one branch endplate and leaves at another). */\nexport interface EditorBranch {\n label: string;\n pos: number;\n side: \"up\" | \"down\";\n config: TrackConfig;\n /** What the route to this endplate is — a secondary \"branch\" or a diverging\n * \"main\". Drives labels/weight, not geometry. Default \"branch\". */\n kind?: \"branch\" | \"main\";\n /** The drawn diverging track that reaches this endplate (set when the owner\n * draws track to it; the plate is placed first, connected later). */\n trackId?: string | null;\n}\n/** Endplate B on a loop module: a standard endplate makes the balloon an\n * INTERCHANGE (a second route connects at the loop, e.g. Seaford); \"none\"\n * makes it a pure turnback. Non-loop modules always have a real B. */\nexport type EndplateBConfig = TrackConfig | \"none\";\n\nexport interface EditorState {\n lengthInches: number;\n /** Balloon loop: the main runs the lead and turns back; positions past the\n * throat are inside the balloon. Endplate B stays independently available —\n * present = interchange loop, \"none\" = pure turnback. */\n loop: boolean;\n /** Where the balloon returns: same main, or Main 2 (directional return on a\n * double-track main — drawn as a U joining the two lanes). */\n loopReturn: \"same\" | \"main2\";\n configA: TrackConfig;\n configB: EndplateBConfig;\n /** Swap the two mains' POSITIONS: Main 1 draws above (lane 1) and Main 2 on\n * the centre line (lane 0). The module decides which physical track is which\n * main — on some modules the upper track is the through/primary main\n * (#FMN-0043). Identities and references are unchanged; only the lanes swap. */\n mainsSwapped: boolean;\n extraTracks: EditorTrack[]; // sidings/spurs/…; the main track is implicit\n turnouts: EditorTurnout[];\n /** Grade crossings / diamonds (#170). */\n crossings: EditorCrossing[];\n /** Branch endplates C, D, … — junction connections (#170); empty = through\n * module. Emitted in order as endplates \"C\", \"D\", \"E\"… */\n branches: EditorBranch[];\n /** Manual endplate pose overrides by endplate id (#175 phase 1b). */\n poseOverrides: Record<string, { x: number; y: number; heading: number }>;\n /** Authored endplate face widths by endplate id, inches (Free-moN 12″ min,\n * 24″ recommended). Absent id = the recommended default. */\n endplateWidths: Record<string, number>;\n /** Authored per-endplate TRACK offsets by id — the primary track's signed\n * distance from the plate centre, inches. Absent id = the §2.0 default. */\n endplateTrackOffsets: Record<string, number>;\n /** Benchwork footprint outline — polygon vertices in module-local inches\n * (endplate A's track point at the origin, mainline +x, perpendicular +y up).\n * Empty = no authored outline (fall back to the endplate-width band). */\n outline: BenchworkPoint[];\n /** Benchwork HOLE (donut inner boundary), module-local inches. Empty = a solid\n * board. Set by the return-loop generator; punched out of `outline`. */\n outlineInner: BenchworkPoint[];\n /** Internal section joints — inches from endplate A where the boards split\n * into sections. Empty = a single section (#48). */\n sectionBreaks: number[];\n /** The module's sections as named objects, each optionally carrying its own\n * outline (#96 phase 2). Empty = fall back to `outline` + `sectionBreaks`. */\n sections: SchematicSection[];\n controlPoints: EditorControlPoint[];\n /** Rail-served industries — car-spot spans on a track (#industries). */\n industries: EditorIndustry[];\n /** Authored mainline centre-line (module-local inches) — empty = derive from\n * geometry. The owner-drawn real shape (#2d-track, physical view only). */\n mainPath: BenchworkPoint[];\n /** Authored Main 2 centre-line (double-track only) — empty = lane offset (#131). */\n main2Path: BenchworkPoint[];\n}\n\n/** Build the empty editor state for a module of the given length. */\nexport function emptyEditorState(lengthInches: number): EditorState {\n return {\n lengthInches: lengthInches > 0 ? lengthInches : 24,\n loop: false,\n loopReturn: \"same\",\n configA: \"single\",\n configB: \"single\",\n mainsSwapped: false,\n extraTracks: [],\n turnouts: [],\n crossings: [],\n branches: [],\n poseOverrides: {},\n endplateWidths: {},\n endplateTrackOffsets: {},\n outline: [],\n outlineInner: [],\n sectionBreaks: [],\n sections: [],\n controlPoints: [],\n industries: [],\n mainPath: [],\n main2Path: [],\n };\n}\n\n/** Main 2's doc track for a non-loop double module. Full length when both\n * endplates are double; on a transition module (one single, one double) it\n * runs between the mainline transition turnout (the one diverging to main2)\n * and the double end. */\n/**\n * A single↔double transition turnout connects Main 1 and Main 2 — where the\n * second main begins/ends. It may be authored either way round: on Main 1\n * diverging to Main 2, or on Main 2 diverging to Main 1 (both describe the same\n * junction). Recognise both so editing the direction doesn't drop the transition.\n */\nexport function isTransitionTurnout(t: {\n onTrack?: string;\n divergeTrack?: string;\n}): boolean {\n return (\n (t.onTrack === MAIN_TRACK_ID && t.divergeTrack === MAIN2_TRACK_ID) ||\n (t.onTrack === MAIN2_TRACK_ID && t.divergeTrack === MAIN_TRACK_ID)\n );\n}\n\n/**\n * Main 1's extent. Normally it's the through main, A→B. But on a transition\n * module where MAIN 2 is the surviving through main (the turnout sits ON Main 2\n * and diverges to Main 1, #FMN-0043), Main 1 is the one that ENDS — it must stop\n * at the turnout, or both mains draw endplate-to-endplate and the single-track\n * end shows two tracks reaching it.\n */\nfunction main1Track(state: EditorState): SchematicTrack {\n // Main 1 is the through mainline: always the full module, always on the\n // centre line. The swap moves MAIN 2 to the other side; Main 1 never moves\n // (Steve Branton, #131). A legacy doc where the turnout sits ON Main 2 (Main 2\n // was the through main) still truncates Main 1 so old modules don't break.\n const sw = state.turnouts.find(isTransitionTurnout);\n const legacyThroughMain2 =\n !!sw && sw.onTrack === MAIN2_TRACK_ID && sw.divergeTrack === MAIN_TRACK_ID;\n const isDouble = state.configA === \"double\" || state.configB === \"double\";\n const bothDouble = state.configA === \"double\" && state.configB === \"double\";\n if (!isDouble || bothDouble || !legacyThroughMain2) {\n return { id: MAIN_TRACK_ID, role: \"main\", lane: 0, from: \"A\", to: \"B\" };\n }\n return state.configA === \"double\"\n ? { id: MAIN_TRACK_ID, role: \"main\", lane: 0, fromPos: 0, toPos: sw!.pos }\n : { id: MAIN_TRACK_ID, role: \"main\", lane: 0, fromPos: sw!.pos, toPos: state.lengthInches };\n}\n\nfunction main2Track(state: EditorState): SchematicTrack {\n const bothDouble = state.configA === \"double\" && state.configB === \"double\";\n // EVERY turnout that opens Main 2, west to east — not just the first. A module\n // that's single at both ends with a double stretch in the middle (the ordinary\n // passing-siding module) has TWO, and Main 2 lives between them. Taking only\n // the first ran Main 2 on to the far endplate, so a single-track end drew two\n // tracks reaching it (#118).\n const sws = state.turnouts\n .filter((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID)\n .sort((a, b) => a.pos - b.pos);\n // Main 2 runs partial only when IT is the branch that ends (turnout diverges\n // TO Main 2). If the turnout sits ON Main 2 (Main 2 is the surviving through\n // main, #FMN-0043), Main 2 runs full and Main 1 is the one that ends.\n // Main 2's side: above Main 1 by default, below when swapped (Steve, #131).\n // Main 1 stays on the centre line; only Main 2 changes side.\n const lane = state.mainsSwapped ? -1 : 1;\n // A bent Main 2 draws along its authored path instead of a lane offset (#131).\n const authored = state.main2Path.length >= 2 ? { path: state.main2Path } : {};\n if (bothDouble || !sws.length) {\n return { id: MAIN2_TRACK_ID, role: \"main\", lane, from: \"A\", to: \"B\", ...authored };\n }\n const track = (fromPos: number, toPos: number): SchematicTrack => ({\n id: MAIN2_TRACK_ID,\n role: \"main\",\n lane,\n fromPos,\n toPos,\n ...authored,\n });\n // Double at A: Main 2 runs from A and ends at the turnout that closes it.\n if (state.configA === \"double\") return track(0, sws[0].pos);\n // Double at B: it begins where it FIRST appears and runs through to B.\n if (state.configB === \"double\") return track(sws[0].pos, state.lengthInches);\n // Single at both ends — the ordinary passing-siding module. Main 2 lives\n // between the outermost turnouts.\n if (sws.length >= 2) return track(sws[0].pos, sws[sws.length - 1].pos);\n // One turnout and neither end double: a half-drawn siding. Nothing says\n // where it ends, so let it run out rather than collapsing it to nothing.\n return track(sws[0].pos, state.lengthInches);\n}\n\n/**\n * Build the single↔double transition as one unit (like buildPassingSiding):\n * the mainline turnout where Main 2 begins/ends, grouped in a control point —\n * an \"End of Double Track\" is a classic CTC interlocking — with signals both\n * directions. Returns items to merge into the editor state.\n */\nexport function buildTransition(state: EditorState): {\n turnout: EditorTurnout;\n controlPoint: EditorControlPoint;\n} | null {\n const aDouble = state.configA === \"double\";\n const bDouble = state.configB === \"double\";\n if (state.loop || aDouble === bDouble) return null; // not a transition module\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const inset = Math.max(6, Math.round(len * 0.25));\n // The turnout sits toward the single end so the double track carries most\n // of the module; owner adjusts the position afterwards.\n const pos = aDouble ? len - inset : inset;\n\n const swId = nextId(\"sw\", state.turnouts.map((t) => t.id));\n const turnout: EditorTurnout = {\n id: swId,\n name: \"End of Double Track\",\n pos,\n // The turnout sits ON the through mainline (Main 1) and diverges TO Main 2,\n // the second main being added to start the double track — the modeller's\n // view of the junction, and the direction an owner authors it (Steve\n // Branton, #131). Main 1 runs the full module; Main 2 is the branch.\n onTrack: MAIN_TRACK_ID,\n divergeTrack: MAIN2_TRACK_ID,\n // Hand so the diverging leg lands on Main 2's side. Main 2 extends toward\n // the double end (sign −1 west / +1 east) and sits above (+1) or, when the\n // mains are swapped, below (−1). divergeSideForHand(left)=sign(toward),\n // (right)=−sign(toward), so pick the hand whose side matches Main 2's (#131).\n kind:\n (aDouble ? -1 : 1) === (state.mainsSwapped ? -1 : 1) ? \"left\" : \"right\",\n };\n\n const cpId = nextId(\"cp\", state.controlPoints.map((c) => c.id));\n const sig = (facing: SignalFacing): EditorCpSignal => ({\n id: `${cpId}-${facing}`,\n pos,\n track: MAIN_TRACK_ID,\n facing,\n side: facing === \"AtoB\" ? \"above\" : \"below\",\n });\n const controlPoint: EditorControlPoint = {\n id: cpId,\n name: \"End of Double Track\",\n turnouts: [swId],\n signals: [sig(\"AtoB\"), sig(\"BtoA\")],\n };\n return { turnout, controlPoint };\n}\n\n/** Attach manual pose overrides (#175 phase 1b) to endplates by id. */\nfunction withPoses(\n endplates: SchematicEndplate[],\n overrides: Record<string, { x: number; y: number; heading: number }>,\n): SchematicEndplate[] {\n return endplates.map((e) =>\n overrides[e.id] ? { ...e, pose: overrides[e.id] } : e,\n );\n}\n\n/** Attach authored endplate face widths by id; a non-positive/absent width is\n * left off so it falls back to the recommended default. */\nfunction withWidths(\n endplates: SchematicEndplate[],\n widths: Record<string, number>,\n offsets: Record<string, number> = {},\n): SchematicEndplate[] {\n return endplates.map((e) => {\n const w = widths[e.id];\n const o = offsets[e.id];\n let out = e;\n if (typeof w === \"number\" && w > 0) out = { ...out, widthInches: w };\n if (typeof o === \"number\" && Number.isFinite(o)) out = { ...out, trackOffsetInches: o };\n return out;\n });\n}\n\n/** Assemble a spec-conformant doc from the editor state. */\nexport function stateToDoc(\n state: EditorState,\n recordNumber: string,\n): ModuleSchematicDoc {\n return {\n version: 1,\n module: recordNumber,\n lengthInches: state.lengthInches,\n ...(state.loop ? { loop: true } : {}),\n ...(state.loop && state.loopReturn === \"main2\" ? { loopReturn: \"main2\" as const } : {}),\n ...(state.mainsSwapped ? { mainsSwapped: true } : {}),\n endplates: withWidths(\n withPoses(\n [\n ...(state.loop\n ? // Balloon loop: A is the entry. A standard endplate B on the balloon\n // makes it an INTERCHANGE (second route connects at the loop, e.g.\n // Seaford); configB \"none\" makes it a pure turnback.\n [\n { id: \"A\", label: \"Entry\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },\n ...(state.configB !== \"none\"\n ? [{ id: \"B\", label: \"Interchange\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configB }] }]\n : []),\n ]\n : [\n { id: \"A\", label: \"West\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },\n // Non-loop modules always have a real B (\"none\" never applies).\n {\n id: \"B\",\n label: \"East\",\n tracks: [\n {\n trackId: MAIN_TRACK_ID,\n lane: 0,\n config: state.configB === \"none\" ? \"single\" : state.configB,\n },\n ],\n },\n ]),\n // Branch endplates C, D, … — junction connections at pos, off one side\n // (#170). A set can carry several (e.g. a second railroad through).\n ...state.branches.map((b, i) => ({\n id: String.fromCharCode(67 + i), // C, D, E…\n label: b.label || `Branch ${i + 1}`,\n tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],\n at: { pos: b.pos, side: b.side },\n kind: b.kind ?? \"branch\",\n ...(b.trackId ? { trackId: b.trackId } : {}),\n })),\n ],\n state.poseOverrides,\n ),\n state.endplateWidths,\n state.endplateTrackOffsets,\n ),\n tracks: [\n state.loop\n ? // The main runs the lead from A and turns back at the balloon.\n { id: MAIN_TRACK_ID, role: \"main\" as const, lane: 0, fromPos: 0, toPos: state.lengthInches }\n : // Normally A→B; partial when MAIN 2 is the through main and Main 1 is\n // the one that ends at the transition turnout (#FMN-0043).\n main1Track(state),\n // Double track: Main 2 is a real entity so turnouts/signals can attach.\n // On a loop it exists only for a Main 2 directional return (the U joins\n // the two lanes at the balloon); a same-main loop's parallel lead legs\n // are ONE main. On a TRANSITION module (one endplate single, the other\n // double) Main 2 only runs from the mainline turnout to the double end —\n // the turnout that diverges to main2 is the single source of truth for\n // where the transition sits (fd#175 / FMN-0038).\n // …and on a module that's SINGLE at both ends but goes double in the\n // middle to form a siding: the turnouts are what make Main 2 exist, so a\n // pair of them is reason enough to emit it (#118). Without this the\n // second main simply wasn't in the doc, and neither the board nor the\n // dispatcher panel could draw it.\n ...(!state.loop &&\n (state.configA === \"double\" ||\n state.configB === \"double\" ||\n state.turnouts.some((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID))\n ? [main2Track(state)]\n : []),\n ...(state.loop && state.loopReturn === \"main2\"\n ? [{ id: MAIN2_TRACK_ID, role: \"main\" as const, lane: 1, fromPos: 0, toPos: state.lengthInches }]\n : []),\n ...state.extraTracks.map((t) => ({\n id: t.id,\n role: t.role,\n lane: t.lane,\n fromPos: t.fromPos,\n toPos: t.toPos,\n moduleTrackId: t.moduleTrackId,\n trackName: t.trackName || undefined,\n capacityFeet: Math.round(inchesToScaleFeet(Math.abs(t.toPos - t.fromPos))),\n ...(state.loop && t.inLoop ? { inLoop: true } : {}),\n ...(t.path && t.path.length >= 2 ? { path: t.path } : {}),\n })),\n ],\n turnouts: state.turnouts.map((t) => ({\n id: t.id,\n pos: t.pos,\n onTrack: t.onTrack,\n divergeTrack: t.divergeTrack,\n kind: t.kind,\n name: t.name || undefined,\n ...(t.size ? { size: t.size } : {}),\n ...(t.curved ? { curved: true } : {}),\n ...(t.flipped ? { flipped: true } : {}),\n })),\n ...(state.crossings.length > 0\n ? {\n crossings: state.crossings.map((x) => ({\n id: x.id,\n pos: x.pos,\n tracks: [x.trackA, x.trackB] as [string, string],\n name: x.name || undefined,\n })),\n }\n : {}),\n controlPoints: state.controlPoints.map((c) => ({\n id: c.id,\n name: c.name,\n turnouts: c.turnouts,\n ...(c.crossings?.length ? { crossings: c.crossings } : {}),\n signals: c.signals.map((s) => ({\n id: s.id,\n pos: s.pos,\n track: s.track,\n facing: s.facing,\n kind: \"mast\" as const,\n side: s.side,\n })),\n })),\n // Industries — car-spot spans on a track; only when any are authored.\n ...(state.industries.length > 0\n ? {\n industries: state.industries.map((ind) => ({\n id: ind.id,\n name: ind.name,\n ...(ind.type ? { type: ind.type } : {}),\n track: ind.track,\n fromPos: ind.fromPos,\n toPos: ind.toPos,\n ...(ind.spots?.length ? { spots: ind.spots } : {}),\n side: ind.side,\n ...(ind.labelMode && ind.labelMode !== \"none\"\n ? { labelMode: ind.labelMode }\n : {}),\n ...(ind.carTypes.length ? { carTypes: ind.carTypes } : {}),\n moduleIndustryId: ind.moduleIndustryId,\n })),\n }\n : {}),\n // Benchwork footprint outline (module-local inches); only when it's a real\n // ring (≥ 3 vertices).\n ...(state.outline.length >= 3 ? { outline: state.outline } : {}),\n // Benchwork hole (donut inner boundary), when it's a real ring.\n ...(state.outlineInner.length >= 3 ? { outlineInner: state.outlineInner } : {}),\n // Internal section joints (inches from A), when the module has more than one.\n ...(state.sectionBreaks.length ? { sectionBreaks: state.sectionBreaks } : {}),\n // Sections as objects — emitted only once the owner has some, so a module\n // that never used them keeps exactly the doc it had before (#96 phase 2).\n ...(state.sections.length ? { sections: moduleSections({ sections: state.sections }) } : {}),\n // Authored mainline path (module-local inches); only when it's a real path.\n ...(state.mainPath.length >= 2 ? { mainPath: state.mainPath } : {}),\n ...(state.main2Path.length >= 2 ? { main2Path: state.main2Path } : {}),\n };\n}\n\n/**\n * Derive editor state from the doc and the module's Track section rows. Tracks\n * are the single source of truth for name/capacity (module_tracks), while the\n * schematic doc adds geometry (lane, positions). We merge: doc tracks first\n * (they carry geometry + their moduleTrackId link), then any module_tracks not\n * yet positioned in the schematic.\n */\nexport function docToState(\n doc: unknown,\n fallbackLength: number,\n moduleTracks: ModuleTrackRow[] = [],\n): EditorState {\n const base = emptyEditorState(fallbackLength);\n const d =\n doc && typeof doc === \"object\" ? (doc as ModuleSchematicDoc) : null;\n const hasDoc = !!d && typeof d.lengthInches === \"number\" && Array.isArray(d.tracks);\n // The module's length is authoritative (the mainline is the module). If the\n // saved doc used a different length, rescale its feature positions to fit so\n // the mainline always reads as the module's true length.\n const len = fallbackLength > 0 ? fallbackLength : hasDoc ? d!.lengthInches! : 24;\n const docLen = hasDoc && d!.lengthInches! > 0 ? d!.lengthInches! : len;\n const scale = docLen > 0 ? len / docLen : 1;\n const sc = (p: number) => Math.round(p * scale);\n\n const nameOf = (id: number | null | undefined): string => {\n const mt = id != null ? moduleTracks.find((m) => m.id === id) : undefined;\n return mt?.track_name ?? \"\";\n };\n\n const extraTracks: EditorTrack[] = [];\n const usedMt = new Set<number>();\n if (hasDoc) {\n for (const t of d!.tracks) {\n if (t.role === \"main\") continue;\n const moduleTrackId = t.moduleTrackId ?? null;\n if (moduleTrackId != null) usedMt.add(moduleTrackId);\n extraTracks.push({\n id: t.id,\n role: (t.role as TrackRole) ?? \"siding\",\n lane: t.lane ?? 1,\n fromPos: sc(t.fromPos ?? 0),\n toPos: t.toPos != null ? sc(t.toPos) : len,\n moduleTrackId,\n trackName: t.trackName ?? nameOf(moduleTrackId),\n ...(t.inLoop ? { inLoop: true } : {}),\n // Authored path kept as-drawn (a physical shape, not rescaled with length).\n ...(trackPath(t.path) ? { path: trackPath(t.path)! } : {}),\n });\n }\n }\n // Link pre-migration doc tracks (no moduleTrackId yet) to unused module_tracks\n // by order — keeping the doc track's id so turnout/signal references stay\n // valid. Only after that do leftover module_tracks become new tracks.\n const unused = moduleTracks.filter((mt) => !usedMt.has(mt.id));\n let ui = 0;\n for (const et of extraTracks) {\n if (et.moduleTrackId == null && ui < unused.length) {\n const mt = unused[ui++];\n et.moduleTrackId = mt.id;\n if (!et.trackName) et.trackName = mt.track_name ?? \"\";\n usedMt.add(mt.id);\n }\n }\n let lane = Math.max(0, ...extraTracks.map((t) => t.lane));\n for (const mt of moduleTracks) {\n if (usedMt.has(mt.id)) continue;\n lane += 1;\n extraTracks.push({\n id: `mt${mt.id}`,\n role: \"siding\",\n lane,\n fromPos: Math.round(len * 0.2),\n toPos: Math.round(len * 0.8),\n moduleTrackId: mt.id,\n trackName: mt.track_name ?? \"\",\n });\n }\n\n if (!hasDoc) return { ...base, lengthInches: len, extraTracks };\n\n const configOf = (id: string): TrackConfig => {\n const ep = (d!.endplates ?? []).find((e) => e.id === id);\n return ep?.tracks?.[0]?.config === \"double\" ? \"double\" : \"single\";\n };\n const loop = isLoopDoc(d!);\n const hasB = (d!.endplates ?? []).some((e) => e.id === \"B\");\n // Branch endplates C, D, … (junction connections, #170).\n const branchEps = (d!.endplates ?? []).filter(\n (e) => e.id !== \"A\" && e.id !== \"B\" && e.at,\n );\n const poseOverrides = poseOverridesFromDoc(d!);\n // Authored endplate face widths by id (unscaled — a cross-track dimension,\n // not a position along the module).\n const endplateWidths: Record<string, number> = {};\n const endplateTrackOffsets: Record<string, number> = {};\n for (const e of d!.endplates ?? []) {\n if (typeof e.widthInches === \"number\" && e.widthInches > 0)\n endplateWidths[e.id] = e.widthInches;\n // Signed, and 0 is meaningful (explicitly centred) — keep any finite value.\n if (typeof e.trackOffsetInches === \"number\" && Number.isFinite(e.trackOffsetInches))\n endplateTrackOffsets[e.id] = e.trackOffsetInches;\n }\n // Benchwork outline — module-local inches, kept as authored (a physical board\n // shape, not rescaled with the mainline length); per-edge bulge preserved.\n const outline = (d!.outline ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n // Benchwork hole (donut inner boundary), kept as authored like the outline.\n const outlineInner = (d!.outlineInner ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n // Authored mainline path — kept as drawn (a physical shape, not rescaled).\n const mainPath = trackPath(d!.mainPath) ?? [];\n // Main 2's authored path may sit on the doc top-level or on its track record.\n const main2Track_ = (d!.tracks ?? []).find((t) => t.id === MAIN2_TRACK_ID);\n const main2Path = trackPath(d!.main2Path ?? main2Track_?.path) ?? [];\n return {\n lengthInches: len,\n loop,\n loopReturn: loop && d!.loopReturn === \"main2\" ? \"main2\" : \"same\",\n mainsSwapped: d!.mainsSwapped === true,\n configA: configOf(\"A\"),\n // On a loop, a missing B means pure turnback; present = interchange loop.\n configB: loop && !hasB ? \"none\" : configOf(\"B\"),\n branches: branchEps.map((ep) => ({\n label: ep.label ?? \"Branch\",\n pos: sc(ep.at!.pos),\n side: ep.at!.side === \"down\" ? \"down\" : \"up\",\n config: ep.tracks?.[0]?.config === \"double\" ? \"double\" : \"single\",\n kind: ep.kind === \"main\" ? \"main\" : \"branch\",\n trackId: ep.trackId ?? null,\n })),\n poseOverrides,\n endplateWidths,\n endplateTrackOffsets,\n outline,\n outlineInner,\n sectionBreaks: (d!.sectionBreaks ?? [])\n .filter((n) => Number.isFinite(n))\n .map((n) => sc(n)),\n sections: moduleSections(d),\n mainPath,\n main2Path,\n crossings: (d!.crossings ?? []).map((x) => ({\n id: x.id,\n name: x.name ?? \"\",\n pos: sc(x.pos),\n trackA: x.tracks?.[0] ?? MAIN_TRACK_ID,\n trackB: x.tracks?.[1] ?? MAIN_TRACK_ID,\n })),\n extraTracks,\n turnouts: (d!.turnouts ?? []).map((t) => {\n // Self-heal a turnout that diverges into the track it sits on — a reversed\n // transition left onTrack === divergeTrack after an on-track edit, so it\n // had no second route and the false \"nothing will draw\" warning fired\n // (#172). Repoint it at the OTHER main so it's a valid transition again.\n let divergeTrack = t.divergeTrack;\n if (divergeTrack === t.onTrack) {\n if (t.onTrack === MAIN_TRACK_ID) divergeTrack = MAIN2_TRACK_ID;\n else if (t.onTrack === MAIN2_TRACK_ID) divergeTrack = MAIN_TRACK_ID;\n }\n return {\n id: t.id,\n name: t.name ?? \"\",\n pos: sc(t.pos),\n onTrack: t.onTrack,\n divergeTrack,\n kind: (t.kind as TurnoutKind) ?? \"right\",\n ...(t.size ? { size: t.size } : {}),\n ...(t.curved ? { curved: true } : {}),\n ...(t.flipped ? { flipped: true } : {}),\n };\n }),\n controlPoints: readControlPoints(d!, sc),\n industries: (d!.industries ?? []).map((ind) => ({\n id: ind.id,\n name: ind.name ?? \"\",\n type: ind.type ?? \"\",\n track: ind.track,\n fromPos: sc(ind.fromPos ?? 0),\n toPos: ind.toPos != null ? sc(ind.toPos) : len,\n spots: (ind.spots ?? []).map((s) => ({\n track: s.track,\n fromPos: sc(s.fromPos ?? 0),\n toPos: s.toPos != null ? sc(s.toPos) : len,\n ...(s.side ? { side: s.side as SignalSide } : {}),\n })),\n side: (ind.side as SignalSide) ?? \"above\",\n labelMode: (ind.labelMode as IndustryLabelMode) ?? \"none\",\n carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],\n moduleIndustryId: ind.moduleIndustryId ?? null,\n })),\n };\n}\n\n/** Control points from a doc, migrating pre-grouping flat signals into groups. */\nfunction readControlPoints(\n d: ModuleSchematicDoc,\n sc: (p: number) => number = (p) => p,\n): EditorControlPoint[] {\n if (Array.isArray(d.controlPoints)) {\n return d.controlPoints.map((c) => ({\n id: c.id,\n name: c.name ?? \"\",\n turnouts: c.turnouts ?? [],\n ...(c.crossings?.length ? { crossings: c.crossings } : {}),\n signals: (c.signals ?? []).map((s) => ({\n id: s.id,\n pos: sc(s.pos),\n track: s.track ?? MAIN_TRACK_ID,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: (s.side as SignalSide) ?? \"above\",\n })),\n }));\n }\n // Back-compat: group old flat signals by their turnout (or standalone).\n const groups = new Map<string, EditorControlPoint>();\n let n = 0;\n for (const s of d.signals ?? []) {\n const key = s.turnout || `blk-${s.id}`;\n let cp = groups.get(key);\n if (!cp) {\n cp = { id: `cp${++n}`, name: s.name ?? \"\", turnouts: s.turnout ? [s.turnout] : [], signals: [] };\n groups.set(key, cp);\n }\n cp.signals.push({\n id: s.id,\n pos: sc(s.pos),\n track: s.track ?? MAIN_TRACK_ID,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: (s.side as SignalSide) ?? \"above\",\n });\n }\n return [...groups.values()];\n}\n\n/** Find an unused `${prefix}${n}` id given the ones already present. */\nexport function nextId(prefix: string, existing: string[]): string {\n let n = 1;\n while (existing.includes(`${prefix}${n}`)) n += 1;\n return `${prefix}${n}`;\n}\n\n/**\n * Build a passing siding as one unit: the siding track, a switch at each end,\n * and control-point signals for both directions at each end (prototype Station\n * Entering Signal). Returns the new items to merge into the editor state.\n */\nexport function buildPassingSiding(state: EditorState): {\n track: EditorTrack;\n turnouts: EditorTurnout[];\n controlPoints: EditorControlPoint[];\n} {\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const inset = Math.max(6, Math.round(len * 0.08));\n const fromPos = inset;\n const toPos = Math.max(fromPos + 1, len - inset);\n // First free lane above the main(s): lane 1 is Main 2 on double modules.\n const baseLane =\n state.configA === \"double\" || state.configB === \"double\" ? 2 : 1;\n const lane = Math.max(baseLane, ...state.extraTracks.map((t) => t.lane + 1));\n\n const trackIds = [MAIN_TRACK_ID, ...state.extraTracks.map((t) => t.id)];\n const sidId = nextId(\"sid\", trackIds);\n const track: EditorTrack = {\n id: sidId,\n role: \"siding\",\n lane,\n fromPos,\n toPos,\n moduleTrackId: null,\n trackName: \"Passing siding\",\n };\n\n const swIds = state.turnouts.map((t) => t.id);\n const swW = nextId(\"sw\", swIds);\n const swE = nextId(\"sw\", [...swIds, swW]);\n // A siding above the main throws LEFT at its west turnout (body runs east) and\n // RIGHT at its east turnout (body runs west) — both resolve to the same side,\n // so `kind` and the drawn lane agree (divergeSideForHand / #bug1).\n const turnouts: EditorTurnout[] = [\n { id: swW, name: \"West Siding\", pos: fromPos, onTrack: MAIN_TRACK_ID, divergeTrack: sidId, kind: \"left\" },\n { id: swE, name: \"East Siding\", pos: toPos, onTrack: MAIN_TRACK_ID, divergeTrack: sidId, kind: \"right\" },\n ];\n\n // One control point at each end, each grouping its switch and both-direction\n // signals on the main (prototype Station Entering Signal).\n const cpIds = state.controlPoints.map((c) => c.id);\n const cpW = nextId(\"cp\", cpIds);\n const cpE = nextId(\"cp\", [...cpIds, cpW]);\n const sig = (cpId: string, pos: number, facing: SignalFacing): EditorCpSignal => ({\n id: `${cpId}-${facing}`,\n pos,\n track: MAIN_TRACK_ID,\n facing,\n // opposite directions on opposite sides so they never overlap\n side: facing === \"AtoB\" ? \"above\" : \"below\",\n });\n const controlPoints: EditorControlPoint[] = [\n { id: cpW, name: \"West Siding\", turnouts: [swW], signals: [sig(cpW, fromPos, \"AtoB\"), sig(cpW, fromPos, \"BtoA\")] },\n { id: cpE, name: \"East Siding\", turnouts: [swE], signals: [sig(cpE, toPos, \"AtoB\"), sig(cpE, toPos, \"BtoA\")] },\n ];\n\n return { track, turnouts, controlPoints };\n}\n\n/**\n * Build a crossover as one unit: a short connector track between Main 1 and\n * Main 2, with a turnout on each main. The two turnouts sit on different lanes,\n * so the feature resolver draws it as a diagonal (not a lane-paralleling siding)\n * — this is what connects the two dots (#bug2). Needs a double-track module.\n */\nexport function buildCrossover(state: EditorState): {\n track: EditorTrack;\n turnouts: EditorTurnout[];\n} | null {\n const hasSecond = state.configA === \"double\" || state.configB === \"double\";\n if (state.loop || !hasSecond) return null;\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const mid = Math.round(len / 2);\n const gap = Math.max(3, Math.round(len * 0.04));\n const w = Math.round(mid - gap / 2);\n const e = Math.round(mid + gap / 2);\n\n const trackIds = [MAIN_TRACK_ID, MAIN2_TRACK_ID, ...state.extraTracks.map((t) => t.id)];\n const xoId = nextId(\"xo\", trackIds);\n const track: EditorTrack = {\n id: xoId,\n role: \"crossover\",\n lane: 1,\n fromPos: w,\n toPos: e,\n moduleTrackId: null,\n trackName: \"Crossover\",\n };\n\n const swIds = state.turnouts.map((t) => t.id);\n const sw1 = nextId(\"sw\", swIds);\n const sw2 = nextId(\"sw\", [...swIds, sw1]);\n const turnouts: EditorTurnout[] = [\n { id: sw1, name: \"Crossover\", pos: w, onTrack: MAIN_TRACK_ID, divergeTrack: xoId, kind: \"left\" },\n { id: sw2, name: \"Crossover\", pos: e, onTrack: MAIN2_TRACK_ID, divergeTrack: xoId, kind: \"right\" },\n ];\n\n return { track, turnouts };\n}\n\n// ---- Pure feature resolver (both renderers draw these) --------------------\n\nexport interface DrawTrack {\n id: string;\n role: TrackRole;\n lane: number;\n fromFrac: number;\n toFrac: number;\n capacityFeet: number | null;\n /** Lane of the main this track diverges from (via its turnout) — the origin\n * of the diverge diagonal. A spur off Main 2 starts at lane 1, not lane 0;\n * without this, renderers draw what looks like a crossover. */\n divergesFromLane: number;\n /** The end that meets the main at its turnout (throat) and the far stub end,\n * as fractions of length. Direction-preserving: unlike fromFrac/toFrac (always\n * sorted West→East), these keep WHICH end joins, so an east-facing spur draws\n * its throat on the east. A siding meets the main at both ends — there\n * throat=fromFrac, stub=toFrac (the fields are only meaningful for spurs). */\n throatFrac: number;\n stubFrac: number;\n /** Inside the balloon of a loop module (#165). */\n inLoop: boolean;\n}\nexport interface DrawTurnout {\n id: string;\n name: string;\n posFrac: number;\n onLane: number;\n divergeLane: number;\n}\nexport interface DrawSignal {\n id: string;\n name: string;\n posFrac: number;\n lane: number;\n facing: SignalFacing;\n side: SignalSide;\n /** Owning control point's id, when the signal came from a CP group — lets a\n * renderer join the drawn signal back to interlocking-level state (aspects). */\n cp?: string;\n /** 0-based rank among signals that would otherwise land on the exact same\n * spot (same lane + side + position). Renderers offset each further from the\n * track by `stack` so a control point's signals never overlap. */\n stack: number;\n}\n/** A grade crossing / diamond — draw an X spanning the two lanes (#170). */\nexport interface DrawCrossing {\n id: string;\n name: string;\n posFrac: number;\n laneA: number;\n laneB: number;\n}\n/** A crossover — a connector track joining two parallel mains through a turnout\n * on each. Draw a straight diagonal between the two turnout points (unlike a\n * siding, which parallels a lane between its turnouts). Detected structurally:\n * a track whose turnouts sit on two different lanes. */\nexport interface DrawCrossover {\n id: string;\n name: string;\n fromPosFrac: number;\n fromLane: number;\n toPosFrac: number;\n toLane: number;\n}\n/** A branch endplate — draw a connector stub + arrow + label off the given\n * side (the CATS/US&S off-band idiom, #170). */\nexport interface BranchConnector {\n id: string;\n label: string;\n posFrac: number;\n side: \"up\" | \"down\";\n}\n/** An industry — draw a car-spot span beside its track's lane, on `side`, with\n * a name label + an optional car/length readout (#industries). */\nexport interface DrawIndustry {\n id: string;\n name: string;\n type: string | null;\n /** Span as fractions of module length (sorted West→East). */\n fromFrac: number;\n toFrac: number;\n /** Lane of the track it spots on, so it draws beside the right track. */\n lane: number;\n side: SignalSide;\n labelMode: IndustryLabelMode;\n /** Cars that spot here, derived from the drawn span length. */\n cars: number;\n carTypes: string[];\n}\nexport interface ModuleFeatures {\n /** Whether either endplate declares a double-track main. */\n doubleMain: boolean;\n /** Balloon loop — draw a terminal bulb at the far end. */\n loop: boolean;\n /** Loop with a standard endplate B on the balloon: an interchange — a\n * second route connects at the loop (draw an endplate branch off the bulb). */\n loopInterchange: boolean;\n /** Where the balloon returns: \"main2\" = directional return on a double-track\n * main — draw a U joining lanes 0 and 1 instead of the bulb (#165). */\n loopReturn: \"same\" | \"main2\";\n /** Rendering override from the doc; renderers may ignore modes they don't\n * implement yet (\"geometric\"). */\n loopRender: \"bulb\" | \"fan\" | \"geometric\" | null;\n /** Non-main tracks (sidings/spurs/yard/crossover). */\n extraTracks: DrawTrack[];\n turnouts: DrawTurnout[];\n signals: DrawSignal[];\n /** Grade crossings / diamonds (#170). */\n crossings: DrawCrossing[];\n /** Crossovers — connector tracks between two mains (drawn as a diagonal). */\n crossovers: DrawCrossover[];\n /** Branch endplates — junction connectors off the module (#170). */\n branchConnectors: BranchConnector[];\n /** Rail-served industries — car-spot spans beside their track (#industries). */\n industries: DrawIndustry[];\n /** Main 2's extent when it doesn't run the full module — a single↔double\n * transition (Main 2 starts/ends at the mainline turnout). Null = full\n * length (or no Main 2). Renderers draw the partial line + its diverge. */\n main2Extent: { fromFrac: number; toFrac: number } | null;\n /** Main 2's drawn lane — +1 above Main 1 by default, −1 below when the mains\n * are swapped (#131/#172). Null when there is no Main 2. Renderers must draw\n * Main 2 (and its diverges) at THIS lane, never a hard-coded +1. */\n main2Lane: number | null;\n /** Single↔double transition, fully described (#FMN-0043). The `through` main\n * runs the whole module; the `branch` main exists only on the double side and\n * merges at `atFrac`. EITHER main can be through/branch — the surviving single\n * track follows the transition turnout's onTrack, so the drawn side isn't\n * hard-wired to Main 1. Null when not a transition. */\n transition: {\n throughLane: number;\n branchLane: number;\n atFrac: number;\n doubleSide: \"west\" | \"east\";\n } | null;\n /** Lane extents across every feature (mains included; negative = outside\n * Main 1). Renderers size their vertical space from these. */\n laneMin: number;\n laneMax: number;\n}\n\n/**\n * Which side of the main a diverging track draws on, given the turnout's HAND\n * and the direction the track body runs along the main from the turnout\n * (`stubDir`: +1 = the body extends east / toward B, −1 = west / toward A).\n * Returns +1 (above the main) or −1 (below); 0 for a wye or unset hand (keep the\n * authored side). A left-hand turnout throws its route to the same side its body\n * runs (facing the frog, left is the inside of a body running that way); a\n * right-hand throws to the opposite side. `kind` is the source of truth for the\n * drawn side (#bug1) — the stored lane's sign is reconciled to match it.\n */\nexport function divergeSideForHand(\n kind: TurnoutKind | undefined,\n stubDir: number,\n /** The turnout is installed the other way round — the points face the far\n * direction, which swaps the side the diverging route leaves on. */\n flipped?: boolean | null,\n): -1 | 0 | 1 {\n if (kind !== \"left\" && kind !== \"right\") return 0; // wye / unset → no change\n const s = (stubDir >= 0 ? 1 : -1) * (flipped ? -1 : 1);\n return kind === \"left\" ? (s as 1 | -1) : ((-s) as 1 | -1);\n}\n\n/**\n * Resolve a schematic doc into positioned drawables. `pos` (inches) becomes a\n * fraction of the module length; endplate A = 0, B = length; turnouts sit at\n * their pos. Tracks may carry explicit fromPos/toPos (overriding node lookup).\n * To-scale: a feature renders at its true position, clamped only to the\n * module's own extent — so signals near an end read at their real spot, not\n * bunched at an inset (#122).\n */\nexport function moduleFeatures(doc: ModuleSchematicDoc): ModuleFeatures {\n const len =\n doc.lengthInches && doc.lengthInches > 0\n ? doc.lengthInches\n : Math.max(\n 1,\n ...doc.tracks.map((t) => Math.max(t.fromPos ?? 0, t.toPos ?? 0)),\n ...(doc.turnouts ?? []).map((t) => t.pos),\n );\n const clampFrac = (p: number) => Math.min(1, Math.max(0, p / len));\n\n const trackLane = new Map<string, number>();\n for (const t of doc.tracks) trackLane.set(t.id, t.lane);\n\n // Endplate positions: first endplate = West (0), the rest = East (len).\n const endplatePos = new Map<string, number>();\n doc.endplates.forEach((e, i) => endplatePos.set(e.id, i === 0 ? 0 : len));\n const turnoutPos = new Map<string, number>();\n for (const t of doc.turnouts ?? []) turnoutPos.set(t.id, t.pos);\n const posOf = (nodeId?: string): number | null => {\n if (nodeId == null) return null;\n if (endplatePos.has(nodeId)) return endplatePos.get(nodeId)!;\n if (turnoutPos.has(nodeId)) return turnoutPos.get(nodeId)!;\n return null;\n };\n\n const doubleMain = doc.endplates.some((e) =>\n e.tracks?.some((t) => t.config === \"double\"),\n );\n\n // The lane a track diverges from = the main its turnout sits on.\n const divergeOrigin = (trackId: string): number => {\n const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === trackId);\n return sw ? (trackLane.get(sw.onTrack) ?? 0) : 0;\n };\n\n // Turnouts grouped by the track they diverge onto (a track's throat/hand).\n const turnoutsByTrack = new Map<string, SchematicTurnout[]>();\n for (const sw of doc.turnouts ?? []) {\n const arr = turnoutsByTrack.get(sw.divergeTrack) ?? [];\n arr.push(sw);\n turnoutsByTrack.set(sw.divergeTrack, arr);\n }\n // A crossover is a connector whose turnouts sit on two different lanes (one on\n // each main) — drawn as a diagonal between them, never as a lane-paralleling\n // siding. A passing siding's two turnouts share one lane, so it isn't one.\n const isCrossover = (trackId: string): boolean => {\n const sws = turnoutsByTrack.get(trackId) ?? [];\n if (sws.length < 2) return false;\n return new Set(sws.map((s) => trackLane.get(s.onTrack) ?? 0)).size >= 2;\n };\n // The in-inches extent of a track (explicit fromPos/toPos or node lookup).\n const extentOf = (t: SchematicTrack): [number, number] | null => {\n const from = t.fromPos ?? posOf(t.from);\n const to = t.toPos ?? posOf(t.to);\n return from == null || to == null ? null : [from, to];\n };\n\n // Reconcile each diverging track's drawn SIDE from its turnout's hand — `kind`\n // is the source of truth (#bug1) — resolved TOPOLOGICALLY. The hand only picks\n // a side for a turnout sitting on the main CENTERLINE (lane 0); a track\n // diverging off any other track (Main 2, or a ladder rung) stays on its\n // PARENT's side and stacks outward — a ladder turnout's hand is relative to\n // its parent, not the main, so it must never flip a rung across the main. The\n // stored lane's magnitude (stacking slot) is always kept.\n const trackById = new Map(doc.tracks.map((t) => [t.id, t]));\n const resolvedLanes = new Map<string, number>();\n const resolving = new Set<string>();\n const resolveLane = (id: string): number => {\n const trk = trackById.get(id);\n if (!trk) return 0;\n if (trk.role === \"main\") return trk.lane; // mains are fixed (0, 1, …)\n if (resolvedLanes.has(id)) return resolvedLanes.get(id)!;\n if (resolving.has(id)) return trk.lane; // cycle guard\n resolving.add(id);\n let lane = trk.lane;\n const sw = turnoutsByTrack.get(id)?.[0];\n const ext = extentOf(trk);\n if (sw && (sw.kind === \"left\" || sw.kind === \"right\") && !isCrossover(id) && ext) {\n const parentLane = resolveLane(sw.onTrack);\n let sign: number;\n if (parentLane === 0) {\n // On the main centerline — the hand chooses above/below.\n const [from, to] = ext;\n const far = Math.abs(to - sw.pos) >= Math.abs(from - sw.pos) ? to : from;\n const s = divergeSideForHand(sw.kind, far - sw.pos);\n sign = s !== 0 ? s : Math.sign(trk.lane) || 1;\n } else {\n // Off Main 2 / a ladder rung — follow the parent's side.\n sign = Math.sign(parentLane) || 1;\n }\n lane = sign * Math.abs(trk.lane);\n }\n resolving.delete(id);\n resolvedLanes.set(id, lane);\n return lane;\n };\n for (const t of doc.tracks) {\n if (t.role === \"main\") continue;\n trackLane.set(t.id, resolveLane(t.id));\n }\n\n const extraTracks: DrawTrack[] = [];\n for (const t of doc.tracks) {\n if (t.role === \"main\") continue; // the spine draws mains\n // A branch route to a placed endplate (#170) leaves the main at 90° — it\n // can't be drawn in this straightened, positional view, and the endplate it\n // reaches already shows as a labelled connector arrow. The physical view\n // draws its real authored path; here it would only smear a degenerate stub.\n if (t.role === \"branch\") continue;\n if (isCrossover(t.id)) continue; // crossovers draw as diagonals, below\n const ext = extentOf(t);\n if (!ext) continue; // can't place it\n const [from, to] = ext;\n // Throat = the end nearest this track's turnout (the join to the main);\n // with no turnout, keep entry order (from = throat) so the author's chosen\n // joining end is honoured. This is what makes an east-facing spur draw its\n // throat on the east instead of always west (#bug3).\n const sw = turnoutsByTrack.get(t.id)?.[0];\n const throatAtTo = sw != null && Math.abs(to - sw.pos) < Math.abs(from - sw.pos);\n const throat = throatAtTo ? to : from;\n const stub = throatAtTo ? from : to;\n extraTracks.push({\n id: t.id,\n role: t.role,\n lane: trackLane.get(t.id) ?? t.lane,\n fromFrac: clampFrac(Math.min(from, to)),\n toFrac: clampFrac(Math.max(from, to)),\n throatFrac: clampFrac(throat),\n stubFrac: clampFrac(stub),\n capacityFeet: t.capacityFeet ?? null,\n divergesFromLane: divergeOrigin(t.id),\n inLoop: t.inLoop === true,\n });\n }\n\n // Crossovers — a diagonal between two parallel mains. Two shapes are drawn:\n const crossovers: DrawCrossover[] = [];\n // (1) a dedicated connector track (buildCrossover) with a turnout on each main.\n for (const t of doc.tracks) {\n if (!isCrossover(t.id)) continue;\n const [s1, s2] = turnoutsByTrack.get(t.id)!;\n crossovers.push({\n id: t.id,\n name: t.trackName ?? \"\",\n fromPosFrac: clampFrac(s1.pos),\n fromLane: trackLane.get(s1.onTrack) ?? 0,\n toPosFrac: clampFrac(s2.pos),\n toLane: trackLane.get(s2.onTrack) ?? 1,\n });\n }\n // (2) modelled as two turnouts each diverging onto the OTHER main (no connector\n // track). Pair a leg with its return leg and connect the two turnout points.\n // A single↔double TRANSITION turnout also connects the two mains but isn't a\n // crossover (Main 2 ends there) — exclude it, and require a matching return\n // leg so a lone main-to-main turnout is never drawn as a crossover.\n const isMainId = (id?: string) => !!id && trackById.get(id)?.role === \"main\";\n const epDouble = (id: string) =>\n (doc.endplates.find((e) => e.id === id)?.tracks ?? []).some(\n (t) => t.config === \"double\",\n );\n const aDbl = epDouble(\"A\");\n const bDbl = epDouble(\"B\");\n const transitionSw =\n aDbl !== bDbl ? (doc.turnouts ?? []).find(isTransitionTurnout) : undefined;\n const m2m = (doc.turnouts ?? []).filter(\n (sw) =>\n sw !== transitionSw &&\n isMainId(sw.onTrack) &&\n isMainId(sw.divergeTrack) &&\n (trackLane.get(sw.onTrack) ?? 0) !== (trackLane.get(sw.divergeTrack) ?? 1),\n );\n const usedLegs = new Set<string>();\n for (const t1 of m2m) {\n if (usedLegs.has(t1.id)) continue;\n const t2 = m2m.find(\n (x) =>\n !usedLegs.has(x.id) &&\n x.id !== t1.id &&\n x.onTrack === t1.divergeTrack &&\n x.divergeTrack === t1.onTrack,\n );\n if (!t2) continue; // lone leg → a transition/junction, not a crossover\n usedLegs.add(t1.id);\n usedLegs.add(t2.id);\n crossovers.push({\n id: `${t1.id}-${t2.id}`,\n name: t1.name ?? t2.name ?? \"\",\n fromPosFrac: clampFrac(t1.pos),\n fromLane: trackLane.get(t1.onTrack) ?? 0,\n toPosFrac: clampFrac(t2.pos),\n toLane: trackLane.get(t2.onTrack) ?? 1,\n });\n }\n\n const turnouts: DrawTurnout[] = (doc.turnouts ?? []).map((t) => ({\n id: t.id,\n name: t.name ?? \"\",\n posFrac: clampFrac(t.pos),\n onLane: trackLane.get(t.onTrack) ?? 0,\n divergeLane: trackLane.get(t.divergeTrack) ?? 1,\n }));\n\n const drawSignal = (\n s: SchematicSignal,\n name: string,\n cp?: string,\n ): DrawSignal => ({\n id: s.id,\n name,\n posFrac: clampFrac(s.pos),\n lane: s.track ? (trackLane.get(s.track) ?? 0) : 0,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: s.side === \"below\" ? \"below\" : \"above\",\n ...(cp ? { cp } : {}),\n stack: 0,\n });\n // Signals come from control-point groups; fall back to pre-grouping flat\n // signals for docs authored before the model changed.\n const signals: DrawSignal[] = Array.isArray(doc.controlPoints)\n ? doc.controlPoints.flatMap((c) =>\n (c.signals ?? []).map((s) => drawSignal(s, c.name ?? \"\", c.id)),\n )\n : (doc.signals ?? []).map((s) => drawSignal(s, s.name ?? \"\"));\n // De-collide: signals landing on the exact same lane+side+position get a\n // rising stack rank so a renderer can fan them out (a control point often\n // carries several signals at one interlocking).\n const stackCount = new Map<string, number>();\n for (const s of signals) {\n const key = `${s.lane}|${s.side}|${Math.round(s.posFrac * 1000)}`;\n const n = stackCount.get(key) ?? 0;\n s.stack = n;\n stackCount.set(key, n + 1);\n }\n\n const crossings: DrawCrossing[] = (doc.crossings ?? []).map((x) => ({\n id: x.id,\n name: x.name ?? \"\",\n posFrac: clampFrac(x.pos),\n laneA: trackLane.get(x.tracks?.[0] ?? \"\") ?? 0,\n laneB: trackLane.get(x.tracks?.[1] ?? \"\") ?? 1,\n }));\n\n // Branch endplates → connector arrows in the operating view — but ONLY once a\n // route actually reaches one. Placing a bare 3rd+ endplate must not conjure a\n // junction arrow; the arrow follows the drawn branch track that links to it\n // (its trackId), so it appears when you connect track, not when you add the\n // endplate (#170).\n const branchConnectors: BranchConnector[] = doc.endplates\n .filter(\n (e) =>\n e.id !== \"A\" &&\n e.id !== \"B\" &&\n e.at &&\n !!e.trackId &&\n (doc.tracks ?? []).some((t) => t.id === e.trackId),\n )\n .map((e) => {\n // The branch leaves the main at its FEEDING turnout, not the endplate's\n // own along-axis spot — draw it there so it meets the main where it really\n // diverges (the endplate can sit well off to one side, #170).\n const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === e.trackId);\n return {\n id: e.id,\n label: e.label ?? e.id,\n posFrac: clampFrac(sw ? sw.pos : e.at!.pos),\n side: e.at!.side === \"down\" ? \"down\" : \"up\",\n };\n });\n\n // Industries — car-spot spans beside the track they serve.\n const industries: DrawIndustry[] = (doc.industries ?? []).flatMap((ind) => {\n // Each spot (the primary track + any house-track spots) draws beside its\n // own track; they share the industry's name, type and car types (#54).\n const spots = [\n { track: ind.track, fromPos: ind.fromPos, toPos: ind.toPos, side: ind.side },\n ...(ind.spots ?? []),\n ];\n return spots.map((sp, i) => {\n const from = sp.fromPos ?? 0;\n const to = sp.toPos ?? len;\n return {\n id: i === 0 ? ind.id : `${ind.id}-s${i}`,\n name: ind.name ?? \"\",\n type: ind.type ?? null,\n fromFrac: clampFrac(Math.min(from, to)),\n toFrac: clampFrac(Math.max(from, to)),\n lane: trackLane.get(sp.track) ?? 0,\n side: (sp.side as SignalSide) ?? \"above\",\n labelMode: (ind.labelMode as IndustryLabelMode) ?? \"none\",\n cars: carCapacity(from, to),\n carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],\n };\n });\n });\n\n // Main 2's actual drawn lane — −1 (below) when the mains are swapped, +1\n // otherwise. Sizing the canvas off a hard-coded +1 clipped a swapped Main 2 at\n // the bottom (#172); the renderer likewise must draw it here, not at +1.\n const main2Lane = trackLane.has(MAIN2_TRACK_ID)\n ? (trackLane.get(MAIN2_TRACK_ID) as number)\n : null;\n const allLanes = [\n 0,\n main2Lane ?? (doubleMain ? 1 : 0),\n ...extraTracks.map((t) => t.lane),\n ...signals.map((s) => s.lane),\n ...crossings.flatMap((x) => [x.laneA, x.laneB]),\n ...crossovers.flatMap((x) => [x.fromLane, x.toLane]),\n ];\n const loop = isLoopDoc(doc);\n // A positioned Main 2 = a transition module (partial second main).\n const main2 = doc.tracks.find((t) => t.id === MAIN2_TRACK_ID);\n const main2Positioned =\n !!main2 && (main2.fromPos != null || main2.toPos != null) && !loop;\n let main2Extent: { fromFrac: number; toFrac: number } | null = null;\n if (main2Positioned) {\n main2Extent = {\n fromFrac: clampFrac(main2!.fromPos ?? 0),\n toFrac: clampFrac(main2!.toPos ?? len),\n };\n } else if (\n main2 &&\n transitionSw &&\n transitionSw.divergeTrack === MAIN2_TRACK_ID &&\n !loop\n ) {\n // Main 2 is the branch but stored full-length — derive its extent from the\n // junction. (When Main 2 is the through main, it stays full: extent null.)\n main2Extent = aDbl\n ? { fromFrac: 0, toFrac: clampFrac(transitionSw.pos) } // double at west\n : { fromFrac: clampFrac(transitionSw.pos), toFrac: 1 }; // double at east\n }\n // Full transition descriptor: the surviving (through) main follows the\n // turnout's onTrack, so either main can be the one that ends (#FMN-0043).\n const transition =\n transitionSw && aDbl !== bDbl && !loop\n ? {\n throughLane: trackLane.get(transitionSw.onTrack) ?? 0,\n branchLane: trackLane.get(transitionSw.divergeTrack) ?? 1,\n atFrac: clampFrac(transitionSw.pos),\n doubleSide: (aDbl ? \"west\" : \"east\") as \"west\" | \"east\",\n }\n : null;\n return {\n doubleMain,\n loop,\n main2Extent,\n main2Lane,\n transition,\n loopInterchange: loop && doc.endplates.filter((e) => !e.at).length >= 2,\n loopReturn: loop && doc.loopReturn === \"main2\" ? \"main2\" : \"same\",\n loopRender: loop ? (doc.loopRender ?? null) : null,\n extraTracks,\n turnouts,\n signals,\n crossings,\n crossovers,\n branchConnectors,\n industries,\n laneMin: Math.min(...allLanes),\n laneMax: Math.max(...allLanes),\n };\n}\n\n// ---- Endplate geometry & poses (#175) --------------------------------------\n//\n// Free-moN endplates are one standard interface; a single (x, y, heading) at\n// the track-crossing point fully determines mating (any endplate ↔ any\n// compatible endplate). Poses are in MODULE-LOCAL inches: endplate A's track\n// point at the origin, its OUTWARD normal pointing west (180°), so the module\n// body runs toward +X. A layout composes modules by walking joins and stacking\n// each pose's rigid transform (rotation + optional reflection for flips).\n//\n// Poses are DERIVED from the simple fields owners already enter — length +\n// geometry type/degrees/offset for the two axial endplates, plus the schematic\n// doc's branch endplates (#170). Complex shapes (wye, loop, other) fall back to\n// hand-entered overrides. Nothing is stored unless overridden.\n\nexport type GeometryType =\n | \"straight\"\n | \"corner_45\"\n | \"corner_90\"\n | \"curve\"\n | \"offset\"\n | \"dead_end\"\n | \"wye\"\n | \"other\";\n\nexport interface EndplatePose {\n /** Endplate id — \"A\"/\"B\" axial, \"C\"/\"D\"… branch. */\n id: string;\n /** Module-local inches; endplate A's track point is the origin. */\n x: number;\n y: number;\n /** Outward normal in degrees (0 = +X east, 90 = +Y north). A neighbour mates\n * facing the opposite heading. */\n heading: number;\n trackConfig: \"single\" | \"double\";\n /** Lateral track offsets from the crossing anchor (0 = centred single). */\n trackOffsets: number[];\n /** True when the pose was hand-entered, not derived (wye/loop/other). */\n manual?: boolean;\n}\n\nexport type ReturnLoopShape = \"circle\" | \"teardrop\" | \"offset-teardrop\" | \"square\";\n\n/** A computed return-loop: a mainline LEAD to the throat, a WYE that splits into\n * two legs, and the LOOP track those legs form, closing back at the throat. Pure\n * geometry, module-local inches, endplate A at the origin, lead heading +x. All\n * shapes are built so the loop CLOSES exactly at the throat and the two wye legs\n * diverge symmetrically about the lead — the piece the earlier eyeballed versions\n * kept getting wrong (#loop). */\nexport interface ReturnLoopGeometry {\n throat: BenchworkPoint;\n /** The loop track, throat → around → throat (starts and ends at the throat). */\n loop: BenchworkPoint[];\n /** The two diverging wye legs at the throat (each throat → its tangent point). */\n wyeLegs: [BenchworkPoint[], BenchworkPoint[]];\n /** Half the angle between the two wye legs, degrees (0 = tangent/no wye). */\n wyeHalfAngleDeg: number;\n /** Benchwork fascia: outer boundary, and an inner boundary for a donut (empty\n * when the board is solid). */\n outlineOuter: BenchworkPoint[];\n outlineInner: BenchworkPoint[];\n}\n\nexport function returnLoop(\n shape: ReturnLoopShape,\n opts: {\n leadInches: number;\n radius: number;\n /** Half-width of the board UNDER the loop track (the donut ring), inches. */\n boardHalfWidth?: number;\n /** Half the endplate face width, inches. The lead/interface board is sized to\n * this so the benchwork is never narrower than the endplate (Free-moN §2.0);\n * the track crosses the endplate centred on a full-width board. */\n endplateHalfWidth?: number;\n },\n): ReturnLoopGeometry {\n const L = Math.max(1, opts.leadInches);\n const R = Math.max(1, opts.radius);\n // Two widths: the ring under the loop track, and the lead/interface board — the\n // latter at least the endplate half-width, so benchwork ≥ endplate at the face.\n const hw = Math.min(opts.boardHalfWidth ?? 6, R - 1); // ring half-width (keeps a hole)\n const leadHalf = Math.max(hw, opts.endplateHalfWidth ?? hw);\n const T: BenchworkPoint = { x: L, y: 0 };\n const r2 = (v: number) => Math.round(v * 100) / 100;\n const rd = (pts: BenchworkPoint[]) => pts.map((p) => ({ x: r2(p.x), y: r2(p.y) }));\n const arc = (cx: number, cy: number, r: number, a0: number, a1: number, steps: number) => {\n const out: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) out.push({ x: cx + r * Math.cos(a0 + ((a1 - a0) * i) / steps), y: cy + r * Math.sin(a0 + ((a1 - a0) * i) / steps) });\n return out;\n };\n\n // circle / teardrop / offset-teardrop / square: the LOOP TRACK is always a\n // proper circle whose centre C sits ahead of the throat — real track can't turn\n // a square corner, so a \"square\" module is a curved loop inside a square board,\n // never a square track. The wye legs are the two tangent lines from the throat\n // to the circle; the loop is the MAJOR (far) arc between the tangent points, so\n // the legs diverge symmetrically (the wye) and the loop closes at the throat.\n const D = shape === \"circle\" || shape === \"square\" ? R * 1.15 : R * 1.6; // throat → centre\n const offY = shape === \"offset-teardrop\" ? R * 0.7 : 0;\n const C = { x: L + D, y: offY };\n const dist = Math.hypot(C.x - T.x, C.y - T.y);\n const ac = Math.acos(Math.min(1, R / dist)); // tangent-point angle at C\n const base = Math.atan2(T.y - C.y, T.x - C.x); // C → T\n const a1 = base + ac; // upper tangent point angle (at C)\n const a2 = base - ac; // lower\n const P1 = { x: C.x + R * Math.cos(a1), y: C.y + R * Math.sin(a1) };\n const P2 = { x: C.x + R * Math.cos(a2), y: C.y + R * Math.sin(a2) };\n // loop: throat → P1 (leg) → major arc → P2 → throat (leg)\n const loop = [T, P1, ...arc(C.x, C.y, R, a1, a2 + 2 * Math.PI, 64).slice(1), T];\n // wye half-angle: angle between the two legs (T→P1, T→P2), halved\n const legDir = (P: BenchworkPoint) => Math.atan2(P.y - T.y, P.x - T.x);\n const half = Math.abs(((legDir(P1) - legDir(P2) + Math.PI) % (2 * Math.PI)) - Math.PI) / 2;\n\n // Donut benchwork: outer ring (R+hw) and inner ring (R-hw) around C, the outer\n // meeting the lead's edges. Inner hole = the open middle of the loop.\n const ringOuter = (rr: number) => {\n // The lead/interface board runs at ±leadHalf (≥ the endplate) until it meets\n // the outer ring; the ring itself is radius rr. Using leadHalf here is what\n // keeps the benchwork at least as wide as the endplate at the face.\n const xTop = C.x - Math.sqrt(Math.max(0, rr * rr - (leadHalf - C.y) ** 2));\n const xBot = C.x - Math.sqrt(Math.max(0, rr * rr - (-leadHalf - C.y) ** 2));\n const tTop = Math.atan2(leadHalf - C.y, xTop - C.x);\n const tBot = Math.atan2(-leadHalf - C.y, xBot - C.x);\n // Sweep CLOCKWISE from tTop down to tBot (the FAR arc, away from the lead\n // notch) as a SINGLE traversal. A fixed `tBot − 2π` double-wraps the circle\n // when tTop/tBot straddle ±π (the symmetric shapes), which a solid fill hides\n // but an even-odd donut fill inverts. Normalise instead so 0 > sweep > −2π.\n let end = tBot;\n while (end >= tTop) end -= 2 * Math.PI;\n return [\n { x: 0, y: leadHalf },\n { x: xTop, y: leadHalf },\n ...arc(C.x, C.y, rr, tTop, end, 48).slice(1, -1),\n { x: xBot, y: -leadHalf },\n { x: 0, y: -leadHalf },\n ];\n };\n const Ri = R - hw;\n\n // A \"square\" module frames that same circular loop in a SQUARE DONUT: a\n // rectangular loop board (a lead strip + a square around the circle) with a\n // square hole in the open middle. The hole's corners are kept inside the track\n // circle (half-diagonal ≤ R − hw) so the board is at least hw wide under the rail.\n if (shape === \"square\") {\n const xL = C.x - R - hw; // square board's left edge\n const xR = C.x + R + hw; // right edge\n const yT = R + hw;\n // Lead/interface strip at ±leadHalf (≥ the endplate) sticking out of the square.\n const outerSquare = [\n { x: 0, y: leadHalf },\n { x: xL, y: leadHalf },\n { x: xL, y: yT },\n { x: xR, y: yT },\n { x: xR, y: -yT },\n { x: xL, y: -yT },\n { x: xL, y: -leadHalf },\n { x: 0, y: -leadHalf },\n ];\n const iHalf = (R - hw) / Math.SQRT2; // inner-square half-side (corners inside R)\n const holeSquare =\n iHalf > 2\n ? [\n { x: C.x - iHalf, y: iHalf },\n { x: C.x + iHalf, y: iHalf },\n { x: C.x + iHalf, y: -iHalf },\n { x: C.x - iHalf, y: -iHalf },\n ]\n : [];\n return {\n throat: T,\n loop: rd(loop),\n wyeLegs: [rd([T, P1]), rd([T, P2])],\n wyeHalfAngleDeg: r2((half * 180) / Math.PI),\n outlineOuter: rd(outerSquare),\n outlineInner: rd(holeSquare),\n };\n }\n\n return {\n throat: T,\n loop: rd(loop),\n wyeLegs: [rd([T, P1]), rd([T, P2])],\n wyeHalfAngleDeg: r2((half * 180) / Math.PI),\n outlineOuter: rd(ringOuter(R + hw)),\n outlineInner: Ri > 2 ? rd(arc(C.x, C.y, Ri, 0, 2 * Math.PI, 40)) : [],\n };\n}\n\nexport interface ModuleGeometryInput {\n lengthInches: number;\n geometryType?: string | null;\n geometryDegrees?: number | null;\n geometryOffsetInches?: number | null;\n /** Axial endplate configs (A first, then B). Missing → single. */\n endplateConfigs?: (\"single\" | \"double\" | null | undefined)[];\n /** Branch endplates (from the schematic doc, #170), positioned along the\n * mainline axis. */\n branches?: {\n id: string;\n atPos: number;\n side: \"up\" | \"down\";\n config?: \"single\" | \"double\" | null;\n }[];\n /** Hand-entered pose overrides by endplate id — win over derivation. */\n poseOverrides?: Record<string, { x: number; y: number; heading: number }>;\n /** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1\",\n * Free-moN ≈ 9/16\"). */\n trackHalfSpacingInches?: number;\n /** The module's sections. When present they define the module's real shape,\n * so endplate B lands at the end of the CHAINED boards rather than where a\n * single module-level geometry would have put it (#108). */\n sections?: SchematicSection[] | null;\n /** A balloon / return loop: the main runs out and turns back on itself, so the\n * module has ONE endplate (A). No far endplate B is derived — the chain closes\n * back near the throat, and a B there would just be a spurious plate on the\n * loop. An interchange endplate on the balloon is placed separately (#loop). */\n loop?: boolean;\n}\n\n/** Signed turn a module applies to the through track (CCW/left positive). */\nexport function geometryTurnDegrees(\n geometryType?: string | null,\n geometryDegrees?: number | null,\n): number {\n switch (geometryType) {\n case \"corner_45\":\n return 45;\n case \"corner_90\":\n return 90;\n case \"curve\":\n return geometryDegrees ?? 0;\n default:\n return 0;\n }\n}\n\nconst DEG = Math.PI / 180;\nconst norm360 = (d: number) => ((d % 360) + 360) % 360;\n\nfunction offsetsFor(\n config: \"single\" | \"double\",\n half: number,\n): number[] {\n return config === \"double\" ? [-half, half] : [0];\n}\n\n/**\n * Derive every endplate's module-local pose. A at the origin facing west; B\n * placed by the module's geometry (straight/offset/corner/curve via a\n * constant-radius arc = arc-length `lengthInches`, turning by the geometry\n * angle); branch endplates positioned along the mainline axis facing out their\n * side. A `dead_end`/loop module has no B. Overrides replace any derived pose.\n */\nexport function deriveEndplatePoses(geo: ModuleGeometryInput): EndplatePose[] {\n const L = geo.lengthInches > 0 ? geo.lengthInches : 24;\n const half = geo.trackHalfSpacingInches ?? 1;\n const cfg = (i: number): \"single\" | \"double\" =>\n geo.endplateConfigs?.[i] === \"double\" ? \"double\" : \"single\";\n const withOverride = (p: EndplatePose): EndplatePose => {\n const o = geo.poseOverrides?.[p.id];\n return o ? { ...p, x: o.x, y: o.y, heading: norm360(o.heading), manual: true } : p;\n };\n\n const poses: EndplatePose[] = [];\n\n // Endplate A — origin, outward normal west.\n poses.push(\n withOverride({\n id: \"A\",\n x: 0,\n y: 0,\n heading: 180,\n trackConfig: cfg(0),\n trackOffsets: offsetsFor(cfg(0), half),\n }),\n );\n\n // Endplate B — unless the module is a dead end / turnback (single endplate).\n // A dead-end has one plate; a balloon/return loop likewise (it turns back on\n // itself, so the chain's end lands near the throat, not a real far endplate).\n const noB = geo.geometryType === \"dead_end\" || geo.loop === true;\n // A sectioned module's real end is where its boards finish, which no single\n // module-level geometry can predict — chain them and read the last point and\n // its closing tangent (#108).\n const end = sectionedEndPose({ sections: geo.sections });\n if (!noB && end) {\n poses.push(\n withOverride({\n id: \"B\",\n x: end.x,\n y: end.y,\n heading: norm360(end.heading),\n trackConfig: cfg(1),\n trackOffsets: offsetsFor(cfg(1), half),\n }),\n );\n } else if (!noB) {\n const turn = geometryTurnDegrees(geo.geometryType, geo.geometryDegrees);\n let bx: number;\n let by: number;\n let bHeading: number;\n if (geo.geometryType === \"offset\") {\n // Parallel endplates, jogged sideways over the run.\n bx = L;\n by = geo.geometryOffsetInches ?? 0;\n bHeading = 0;\n } else if (turn === 0) {\n bx = L;\n by = 0;\n bHeading = 0;\n } else {\n // Constant-radius arc of arc-length L turning `turn` (CCW/left).\n const t = turn * DEG;\n const r = L / t;\n bx = r * Math.sin(t);\n by = r * (1 - Math.cos(t));\n bHeading = turn;\n }\n poses.push(\n withOverride({\n id: \"B\",\n x: bx,\n y: by,\n heading: norm360(bHeading),\n trackConfig: cfg(1),\n trackOffsets: offsetsFor(cfg(1), half),\n }),\n );\n }\n\n // Branch endplates — at their along-axis position, facing out their side.\n // Position along the (possibly curved) mainline is approximated on the A→B\n // chord; the join solver refines with overrides where a module needs it.\n for (const b of geo.branches ?? []) {\n const frac = L > 0 ? Math.min(1, Math.max(0, b.atPos / L)) : 0;\n const px = frac * L;\n const config = b.config === \"double\" ? \"double\" : \"single\";\n poses.push(\n withOverride({\n id: b.id,\n x: px,\n y: 0,\n heading: b.side === \"down\" ? 270 : 90,\n trackConfig: config,\n trackOffsets: offsetsFor(config, half),\n }),\n );\n }\n\n return poses;\n}\n\n/** Free-moN §2.0 — track crossing an endplate must be perpendicular, straight\n * and level for at least this many inches from the outside face. */\nexport const ENDPLATE_LEAD_INCHES = 4;\n/** Free-moN §2.0 — the crossing must stay at least this far from either fascia. */\nexport const ENDPLATE_FASCIA_CLEAR_INCHES = 4;\n\n/** The mandated straight, perpendicular lead a connecting track must follow\n * leaving an endplate (§2.0). Given the endplate's track point + outward-normal\n * heading, returns the face point and the point `leadInches` inboard, plus the\n * inward heading. A track meeting this plate must be collinear with face→inboard\n * for its first `leadInches`. */\nexport function endplateLead(\n pose: { x: number; y: number; heading: number },\n leadInches: number = ENDPLATE_LEAD_INCHES,\n): { face: BenchworkPoint; inboard: BenchworkPoint; inwardHeading: number } {\n const inwardHeading = norm360(pose.heading + 180);\n const r = inwardHeading * DEG;\n return {\n face: { x: pose.x, y: pose.y },\n inboard: { x: pose.x + Math.cos(r) * leadInches, y: pose.y + Math.sin(r) * leadInches },\n inwardHeading,\n };\n}\n\nexport interface EndplateTrackIssue {\n /** \"not-perpendicular\" — the track doesn't cross square to the face;\n * \"short-lead\" — it curves/bends within the required lead;\n * \"fascia-clearance\" — the crossing is <4″ from a fascia. */\n code: \"not-perpendicular\" | \"short-lead\" | \"fascia-clearance\";\n message: string;\n}\n\n/**\n * Validate a drawn path meeting an endplate against Free-moN §2.0: perpendicular\n * crossing, straight + level for ≥4″ from the face, ≥4″ from either fascia.\n * `end` says which end of the authored path touches the plate (\"last\" default).\n * Fascia clearance is checked only when both the face width and the track's\n * offset from the plate centre are supplied. Pure; empty array = compliant.\n */\nexport function trackMeetsEndplateIssues(\n path: BenchworkPoint[],\n pose: { x: number; y: number; heading: number },\n opts?: {\n end?: \"first\" | \"last\";\n faceWidthInches?: number;\n trackOffsetInches?: number;\n leadInches?: number;\n toleranceDeg?: number;\n },\n): EndplateTrackIssue[] {\n const issues: EndplateTrackIssue[] = [];\n const lead = opts?.leadInches ?? ENDPLATE_LEAD_INCHES;\n const tol = opts?.toleranceDeg ?? 5;\n if (path && path.length >= 2) {\n // Order the path plate→inboard so seq[0] is the endplate end.\n const seq = (opts?.end ?? \"last\") === \"last\" ? [...path].reverse() : path.slice();\n const p0 = seq[0];\n const p1 = seq[1];\n const wantIn = norm360(pose.heading + 180); // inboard = opposite the outward normal\n const inHead = norm360(Math.atan2(p1.y - p0.y, p1.x - p0.x) / DEG);\n const diff = Math.abs(((inHead - wantIn + 540) % 360) - 180);\n if (diff > tol)\n issues.push({\n code: \"not-perpendicular\",\n message: `Track must cross the endplate square (within ${tol}°); it is off by ${Math.round(diff)}°.`,\n });\n // Straight + level for the first `lead` inches: no arc, and the near\n // vertices must lie on the lead line (little lateral drift).\n const r = wantIn * DEG;\n const ux = Math.cos(r);\n const uy = Math.sin(r);\n let curved = false;\n let acc = 0;\n for (let i = 1; i < seq.length && acc < lead; i++) {\n const a = seq[i - 1];\n const b = seq[i];\n if (a.bulge) curved = true;\n const rx = b.x - p0.x;\n const ry = b.y - p0.y;\n const along = rx * ux + ry * uy;\n const lat = Math.abs(rx * -uy + ry * ux);\n if (along <= lead + 0.01 && lat > 0.25) curved = true;\n acc += Math.hypot(b.x - a.x, b.y - a.y);\n }\n if (curved)\n issues.push({\n code: \"short-lead\",\n message: `The first ${lead}″ from the endplate must be straight and perpendicular.`,\n });\n }\n const w = opts?.faceWidthInches;\n const off = opts?.trackOffsetInches;\n if (typeof w === \"number\" && w > 0 && typeof off === \"number\") {\n const clear = w / 2 - Math.abs(off);\n if (clear < ENDPLATE_FASCIA_CLEAR_INCHES)\n issues.push({\n code: \"fascia-clearance\",\n message: `Track must stay ≥${ENDPLATE_FASCIA_CLEAR_INCHES}″ from either fascia; it is ${clear.toFixed(1)}″.`,\n });\n }\n return issues;\n}\n\n/** Whether a module shape's poses are fully derivable, or need manual entry\n * (a helpful cue for the authoring UI). */\nexport function poseNeedsManual(geometryType?: string | null): boolean {\n return geometryType === \"wye\" || geometryType === \"other\";\n}\n\n/** Extract manual pose overrides from a schematic doc's endplates (#175 phase\n * 1b) — the map deriveEndplatePoses / a footprint solver feeds as overrides. */\nexport function poseOverridesFromDoc(\n doc: ModuleSchematicDoc,\n): Record<string, { x: number; y: number; heading: number }> {\n const out: Record<string, { x: number; y: number; heading: number }> = {};\n for (const e of doc.endplates ?? []) {\n if (\n e.id &&\n e.pose &&\n typeof e.pose.x === \"number\" &&\n typeof e.pose.y === \"number\" &&\n typeof e.pose.heading === \"number\"\n ) {\n out[e.id] = { x: e.pose.x, y: e.pose.y, heading: e.pose.heading };\n }\n }\n return out;\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["a1"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @willcgage/module-schematic — the shared module operations-schematic (track-graph)\n * that the Module Repository authors and Free-Dispatcher imports.\n *\n * Topological, straightened-first: positions are 1-D inches along the module\n * (from endplate A), lanes are integer track indices (0 = primary main). This is\n * the single source of truth for both apps — the doc types, the lenient parser\n * (docs arrive as jsonb / unknown), the pure feature resolver both renderers\n * draw, the N-scale helpers, and the editor <-> doc state machine an authoring\n * UI binds to. See docs/module-schematic-format.md in the free-dispatcher repo.\n *\n * Framework-agnostic and side-effect-free so it can be unit-tested and consumed\n * from Next.js (server + client) and Electron alike.\n */\n\nexport type TrackConfig = \"single\" | \"double\";\nexport type TrackRole = \"main\" | \"siding\" | \"spur\" | \"yard\" | \"crossover\" | \"branch\";\nexport type TurnoutKind = \"left\" | \"right\" | \"wye\";\nexport type SignalFacing = \"AtoB\" | \"BtoA\";\nexport type SignalSide = \"above\" | \"below\";\n\nexport interface SchematicEndplateTrack {\n trackId: string;\n lane: number;\n config?: TrackConfig | null;\n}\nexport interface SchematicEndplate {\n id: string; // \"A\" (West) | \"B\" (East) | \"C\"… (branch, #170)\n label?: string | null;\n tracks?: SchematicEndplateTrack[];\n /** Branch endplates (#170): where a 3rd+ endplate sits — pos inches from A,\n * on the up (north/above) or down side. Absent = axial (A at 0, B at\n * lengthInches). Renderers draw a named connector arrow (the CATS/US&S\n * off-band idiom) until branch spines land. */\n at?: { pos: number; side: \"up\" | \"down\" };\n /** Manual pose override (#175 phase 1b) — the endplate's module-local track\n * point (x, y inches) + outward-normal heading (°). Hand-entered for shapes\n * the geometry fields can't derive (wye, freeform, loop); wins over\n * deriveEndplatePoses' derivation. */\n pose?: { x: number; y: number; heading: number };\n /** Free-moN endplate FACE width across the track, inches — the physical size\n * of the standard interface at this end. Free-moN spec: 12″ minimum, 24″\n * recommended. Absent = the recommended default (modules may differ end to\n * end, e.g. a transition). */\n widthInches?: number | null;\n /** Where this end's PRIMARY track (Main 1) crosses, as a signed distance from\n * the plate's CENTRE in inches — the standard's own framing (\"each track\n * 0.5625 inches from the center of the endplate\"). §2.0 requires only that\n * every track stay ≥4″ from either fascia; centring is a recommendation the\n * 20220628 revision relaxed, so an offset is legal — a transition SECTION\n * commonly offsets its single-track end so the through main lines up with one\n * of the two tracks at its double end. Absent = the recommended default\n * (single centred; double straddling at ∓ half the track spacing). */\n trackOffsetInches?: number | null;\n /** Branch endplates (#170) only — what the route reaching this endplate IS:\n * a secondary \"branch\" line, or a \"main\" (a diverging / split main). Drives\n * labels + drawn weight, not geometry. Absent = \"branch\". */\n kind?: \"branch\" | \"main\" | null;\n /** Branch endplates only — the id of the drawn diverging track that reaches\n * this endplate (its authored path ends at the plate face). Lets remove/\n * round-trip pair the endplate with its track. Absent = not yet connected. */\n trackId?: string | null;\n}\n\n/** Free-moN endplate face width, inches — the connection interface size. */\nexport const FREEMO_ENDPLATE_WIDTH_MIN_INCHES = 12;\n/** NB: our own default, NOT from the standard — §1.1 states only the 12″ minimum\n * (\"Endplates shall be 6 inches high and a minimum 12 inches wide\"). 24″ is\n * simply a common real-world width. Don't present it as required. */\nexport const FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = 24;\n/** Free-moN §2.0 **standard**: \"Double track endplates must have a track spacing\n * of 1.125 inches (1 1/8 inches). Track spacing shall be measured along the\n * track center line.\" The one definition both apps read. */\nexport const FREEMO_TRACK_SPACING_INCHES = 1.125;\n/** Free-moN §2.0 **standard**: track crossing an endplate must be \"not less than\n * 4 inches from either fascia\" (and perpendicular, straight and level for 4″). */\nexport const FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES = 4;\n\n/**\n * The authored face width for an endplate, or the recommended default when a\n * module hasn't authored one. The single source of truth both apps read so a\n * module's endplate size is drawn the same in the Repository and the layout.\n */\nexport function endplateWidthInches(\n ep: { widthInches?: number | null } | null | undefined,\n): number {\n const w = ep?.widthInches;\n return typeof w === \"number\" && w > 0\n ? w\n : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;\n}\nexport interface SchematicTrack {\n id: string;\n role: TrackRole;\n lane: number;\n from?: string;\n to?: string;\n fromPos?: number | null;\n toPos?: number | null;\n capacityFeet?: number | null;\n industryRef?: number | null;\n /** The module_tracks row this track is (single source of truth); null = new. */\n moduleTrackId?: number | null;\n /** Owner's track name, mirrored to module_tracks.track_name. */\n trackName?: string;\n /** Inside the balloon of a loop module (#165): pos still measures from\n * endplate A (past the throat = in the loop), lane is the ladder/arc index —\n * one record drives both the unrolled fan and a geometric render. */\n inLoop?: boolean;\n /** Authored 2-D path for this track (module-local inches, open path with\n * arcs) — the PHYSICAL shape a bent/rotated spur draws. Absent = derive from\n * the main centre-line + lane, as before. Physical view only; the operations\n * view stays positional (#2d-track). */\n path?: BenchworkPoint[] | null;\n}\nexport interface SchematicTurnout {\n id: string;\n pos: number;\n onTrack: string;\n divergeTrack: string;\n kind?: TurnoutKind;\n name?: string | null;\n address?: string | null;\n /** Frog number (\"size\") — #4, #6, #8, etc. Governs the diverging angle. */\n size?: number | null;\n /** A curved turnout — the diverging route bows into an arc (both routes curve\n * the same way) instead of leaving as a straight diagonal. Physical-render\n * only; the operations view stays topological. */\n curved?: boolean | null;\n /** Rotate the turnout 180° — the points face the other way along the track.\n * HAND is which turnout you own; how it's INSTALLED is a separate choice, and\n * the drawn orientation can't always be inferred from where the diverging\n * track happens to run. A siding at the far end of a module is the case that\n * forces it: the body has nowhere to go but back toward the module, so the\n * derived facing comes out backwards. */\n flipped?: boolean | null;\n}\nexport interface SchematicSignal {\n id: string;\n pos: number;\n /** Track the signal governs; absent = the primary main (lane 0). */\n track?: string;\n facing?: SignalFacing;\n kind?: \"mast\" | \"dwarf\";\n name?: string | null;\n aspects?: string[];\n /** Which side of the track the signal sits on (#122). */\n side?: SignalSide;\n /** Turnout this control point governs; absent = standalone block signal. */\n turnout?: string;\n}\nexport interface SchematicBlock {\n id: string;\n name: string;\n tracks?: string[];\n from: number;\n to: number;\n}\n/** A grade crossing / diamond (#170): two tracks cross with no route choice —\n * a conflict node, not a turnout. A connected diamond adds normal turnouts\n * alongside. Drawn as an X between the two tracks' lanes. */\nexport interface SchematicCrossing {\n id: string;\n pos: number;\n /** The two crossing tracks, by id. */\n tracks: [string, string];\n name?: string | null;\n}\n/**\n * A control point is an interlocking: a named group of one or more signals and\n * zero or more turnouts. A passing siding has two (West/East); a lone block\n * signal is a control point with one signal and no turnouts.\n */\nexport interface SchematicControlPoint {\n id: string;\n name?: string | null;\n turnouts?: string[];\n /** Crossings this interlocking protects (#170). */\n crossings?: string[];\n signals?: SchematicSignal[];\n}\n/** What a rendered industry shows beside its name: a car count, a length in\n * inches, or nothing (name only). Authored per industry. */\nexport type IndustryLabelMode = \"none\" | \"cars\" | \"inches\";\n\n/**\n * An industry — a rail-served customer that spots cars, authored as a SPAN on a\n * track (a spur/siding, or the main). Positional like everything else: it lives\n * in the same module-local inch frame and is rendered into the shared 2-D view,\n * offset to `side`. The span length gives its car capacity; the dispatcher and\n * crews read where cars set out. Mirrors a `freemon_industries` row.\n */\n/** One car-spot span of an industry on a track — an industry may have several\n * (a house track serving one customer across multiple spot tracks, #54). */\nexport interface IndustrySpot {\n track: string;\n fromPos: number;\n toPos: number;\n side?: SignalSide;\n}\n\nexport interface SchematicIndustry {\n id: string;\n name: string;\n /** Industry type value from the lookup (e.g. \"team_track\", \"grain\"). */\n type?: string | null;\n /** The primary track this industry spots cars on (a spur/siding id or main).\n * Additional spots (other tracks) live in `spots`. */\n track: string;\n /** The primary car-spot span along `track`, inches from endplate A. */\n fromPos: number;\n toPos: number;\n /** Extra car-spot spans on other tracks — the industry's house-track spots. */\n spots?: IndustrySpot[];\n /** Which side of the track the building + label sit on. */\n side?: SignalSide;\n /** Secondary readout at the label — a car count, a length, or none. */\n labelMode?: IndustryLabelMode;\n /** Car types this industry receives (car-type value strings). */\n carTypes?: string[];\n /** The `freemon_industries` row this is (single source of truth); null = new. */\n moduleIndustryId?: number | null;\n}\n\nexport interface ModuleSchematicDoc {\n version: number;\n module?: string;\n lengthInches?: number;\n /** Single-endplate turnback (balloon loop): the main enters at A, runs the\n * lead, and turns back — renderers draw a terminal bulb at the far end\n * instead of a second endplate. Also implied by a single-entry endplates\n * array (a category:\"loop\" module like Seaford). */\n loop?: boolean;\n /** Where the balloon returns (#165): \"same\" (default) turns back onto the\n * same main; \"main2\" is a directional return on a double-track main —\n * out on Main 1, back on Main 2 — drawn as a U joining the two lanes\n * (the transit terminal-loop idiom). */\n loopReturn?: \"same\" | \"main2\";\n /** Optional rendering override: \"bulb\" (abstract terminal), \"fan\" (interior\n * tracks unrolled as a ladder past the throat — the default when inLoop\n * tracks exist), \"geometric\" (drawn balloon, AL&E-style). */\n loopRender?: \"bulb\" | \"fan\" | \"geometric\";\n /** The two mains' positions are swapped: Main 1 draws above (lane 1), Main 2\n * on the centre line (lane 0). Absent/false = the default (Main 1 below).\n * Identities are unchanged — only which lane each is drawn in (#FMN-0043). */\n mainsSwapped?: boolean;\n endplates: SchematicEndplate[];\n tracks: SchematicTrack[];\n turnouts?: SchematicTurnout[];\n /** Grade crossings / diamonds (#170). */\n crossings?: SchematicCrossing[];\n controlPoints?: SchematicControlPoint[];\n /** Rail-served industries — car-spot spans on a track (#industries). */\n industries?: SchematicIndustry[];\n /** Benchwork FOOTPRINT outline — the module's physical board shape as a\n * polygon in module-local inches, in the same frame as the endplate poses\n * (endplate A's track point at the origin, the mainline along +x, perpendicular\n * +y up). Stored as an open ring; renderers close it. Absent = derive an\n * approximate band from the endplate widths. */\n outline?: BenchworkPoint[];\n /** Benchwork HOLE — an inner boundary punched out of `outline`, making the\n * board a DONUT (a return loop's open middle). Same frame as `outline`; stored\n * as an open ring, renderers close it. Absent = a solid board. */\n outlineInner?: BenchworkPoint[];\n /** Internal section joints — inches from endplate A where the module's boards\n * split into sections. Operationally one unit; these mark construction/transport\n * seams (exempt from the end-interface standards). Empty/absent = one section.\n * Describes only sections that are full-depth SLICES; a section with a shape\n * of its own lives in `sections` below. */\n sectionBreaks?: number[];\n /** The module's sections as real objects — named, each with a bench-work\n * outline of its own (#96 phase 2). A module is a kit: the same sections can\n * be set up in different combinations, so its footprint is the UNION of the\n * sections present rather than an independently authored shape.\n *\n * Needed because sections are not slices. Real modules hang a deep section\n * off the BACK of a shallow main band — a peninsula carrying an industry —\n * which no single position along the main can describe.\n *\n * Absent = the module keeps using its own `outline` exactly as before; this\n * is purely additive and nothing migrates on read. */\n sections?: SchematicSection[];\n /** @deprecated pre-grouping flat signals; read for back-compat. */\n signals?: SchematicSignal[];\n /** Authored mainline centre-line (module-local inches, open path with arcs).\n * Present = the owner drew the real shape; absent = derive from geometry.\n * Physical view only — the operations view stays derived (#2d-track). */\n mainPath?: BenchworkPoint[] | null;\n /** Authored centre-line for MAIN 2 on a double-track module (module-local\n * inches, open path with arcs). Present = the owner bent Main 2 to its real\n * shape; absent = derive it as a lane offset from Main 1. Physical view only\n * (#131). */\n main2Path?: BenchworkPoint[] | null;\n}\n\n/** A benchwork-outline vertex, module-local inches. The edge from this vertex\n * to the NEXT one is a straight line, unless `bulge` is set — then it's a\n * circular arc whose midpoint is offset `bulge` inches (signed: + bows to the\n * left of the P→next direction) perpendicular from the chord. */\nexport interface BenchworkPoint {\n x: number;\n y: number;\n bulge?: number;\n}\n\n/** NB: a module has NO compass direction of its own, deliberately. It has ends\n * A and B. Direction is a property of the LAYOUT — the same board can be\n * installed running either way round, or on either axis, so a compass label\n * stored here could only ever contradict the layout that placed it. Railroads\n * do the same thing with timetable direction: the railroad declares which way\n * is \"east\", not any one piece of track. Free-Dispatcher owns direction. */\n\n/** One bench-work section of a module (#96 phase 2). */\nexport interface SectionFootprint {\n id: string;\n name?: string;\n outline: { x: number; y: number }[];\n /** True when this shape is DERIVED from the section's span rather than\n * authored — a derived outline follows the board when it's resized, an\n * authored one stays exactly as drawn (#96 phase 2b). */\n derived: boolean;\n}\n\nexport interface SchematicSection {\n id: string;\n /** What the owner calls this board — \"west transition\", \"double #3\". */\n name?: string | null;\n /** This section's own footprint polygon, module-local inches, same frame as\n * the module outline. Absent = the section has no shape of its own yet (it's\n * described only by the joints in `sectionBreaks`). */\n outline?: BenchworkPoint[] | null;\n /** How far this board runs along the main, inches. The module's length is the\n * SUM of these — it isn't authored separately (#108). */\n lengthInches?: number | null;\n /** This board's own shape: straight | curve | corner_45 | corner_90 | offset |\n * dead_end. Geometry belongs to the SECTION, not the module — a module like\n * One Mile is 384″ of mostly-straight boards with two 24″ CURVED sections in\n * the middle, which no single module-level geometry can describe (#108).\n * Absent = straight. */\n geometryType?: string | null;\n /** Degrees turned, for curve/corner sections. */\n geometryDegrees?: number | null;\n /** Lateral jog, for offset sections. */\n geometryOffsetInches?: number | null;\n}\n\n/** The authored benchwork outline, or null when a module hasn't drawn one\n * (renderers then fall back to a band derived from the endplate widths). A\n * valid outline needs at least 3 points. Normalises each vertex to {x, y, bulge?}. */\nexport function benchworkOutline(\n doc: { outline?: BenchworkPoint[] | null } | null | undefined,\n): BenchworkPoint[] | null {\n const pts = (doc?.outline ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n return pts.length >= 3 ? pts : null;\n}\n\n/** The module's sections, normalised — id required, name trimmed away when\n * blank, outline kept only when it's a usable polygon (#96 phase 2). */\nexport function moduleSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): SchematicSection[] {\n return (doc?.sections ?? [])\n .filter((sec) => sec && typeof sec.id === \"string\" && sec.id !== \"\")\n .map((sec) => {\n const outline = benchworkOutline({ outline: sec.outline });\n const name = typeof sec.name === \"string\" ? sec.name.trim() : \"\";\n const len = sec.lengthInches;\n const deg = sec.geometryDegrees;\n const off = sec.geometryOffsetInches;\n return {\n id: sec.id,\n ...(name ? { name } : {}),\n ...(outline ? { outline } : {}),\n ...(typeof len === \"number\" && Number.isFinite(len) && len > 0\n ? { lengthInches: len }\n : {}),\n ...(sec.geometryType ? { geometryType: sec.geometryType } : {}),\n ...(typeof deg === \"number\" && Number.isFinite(deg) ? { geometryDegrees: deg } : {}),\n ...(typeof off === \"number\" && Number.isFinite(off) ? { geometryOffsetInches: off } : {}),\n };\n });\n}\n\n/** Every section outline that's actually a shape, arc-sampled for drawing.\n * Drawing all of them IS the module's footprint — the union of its sections.\n * No polygon boolean is computed: a renderer painting each ring gives the same\n * picture, and an approximate union would be worse than none. If something\n * ever needs a single ring (an export, a collision test), that's the point to\n * bring in real clipping. */\nexport function sectionFootprints(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n /** The module's spine and dimensions. Given these, a section with no\n * authored polygon gets a band derived from its own span, so every section\n * has a shape and a resized board reshapes with it (#96 phase 2b). Omit to\n * get authored outlines only. */\n derive?: {\n centerline: BenchworkPoint[];\n widthA: number;\n widthB: number;\n offsetA: number;\n offsetB: number;\n },\n): SectionFootprint[] {\n const spans = derive ? sectionSpans(doc) : [];\n const spanOf = new Map(spans.map((sp) => [sp.id, sp]));\n return moduleSections(doc)\n .map((sec): SectionFootprint | null => {\n const name = sec.name ? { name: sec.name } : {};\n if (sec.outline)\n return { id: sec.id, ...name, outline: sampleBenchworkOutline(sec.outline), derived: false };\n const sp = spanOf.get(sec.id);\n if (!sp || !derive) return null;\n const band = sectionBand(\n derive.centerline,\n sp.fromPos,\n sp.toPos,\n derive.widthA,\n derive.widthB,\n derive.offsetA,\n derive.offsetB,\n );\n return band.length >= 3 ? { id: sec.id, ...name, outline: band, derived: true } : null;\n })\n .filter((x): x is SectionFootprint => x !== null);\n}\n\n/**\n * Expand a benchwork outline (whose edges may be arcs) into a dense closed\n * polyline for rendering — the SAME sampling both the Repository preview and\n * Free-Dispatcher use, so a curve looks identical in both. Straight edges emit\n * just their start vertex; a bulged edge emits `segsPerArc` points along the\n * circular arc through the two endpoints and the bulged midpoint.\n */\nexport function sampleBenchworkOutline(\n pts: BenchworkPoint[],\n segsPerArc = 20,\n): { x: number; y: number }[] {\n const n = pts.length;\n if (n < 2) return pts.map((p) => ({ x: p.x, y: p.y }));\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i < n; i++) {\n const p0 = pts[i];\n const p1 = pts[(i + 1) % n];\n out.push({ x: p0.x, y: p0.y });\n const bulge = p0.bulge ?? 0;\n if (!bulge) continue; // straight edge\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n const c = Math.hypot(dx, dy);\n if (c < 1e-6) continue;\n // Arc midpoint = chord midpoint + left-normal * sagitta.\n const nx = -dy / c;\n const ny = dx / c;\n const mid = { x: (p0.x + p1.x) / 2 + nx * bulge, y: (p0.y + p1.y) / 2 + ny * bulge };\n const circ = circleThrough(p0, mid, p1);\n if (!circ) continue; // colinear → treat as straight\n const a0 = Math.atan2(p0.y - circ.cy, p0.x - circ.cx);\n const am = Math.atan2(mid.y - circ.cy, mid.x - circ.cx);\n const a1 = Math.atan2(p1.y - circ.cy, p1.x - circ.cx);\n // Sweep from a0 to a1 the way that passes through the midpoint angle.\n const sweep = arcSweep(a0, a1, am);\n for (let s = 1; s < segsPerArc; s++) {\n const a = a0 + (sweep * s) / segsPerArc;\n out.push({ x: circ.cx + circ.r * Math.cos(a), y: circ.cy + circ.r * Math.sin(a) });\n }\n }\n return out;\n}\n\n/**\n * Expand an OPEN track path (whose edges may be arcs) into a dense polyline —\n * the open-ended sibling of sampleBenchworkOutline (which closes the ring).\n * Used for authored track centre-lines (a drawn mainline or spur). The final\n * vertex is always emitted so the path reaches its end.\n */\nexport function samplePath(\n pts: BenchworkPoint[],\n segsPerArc = 20,\n): { x: number; y: number }[] {\n const n = pts.length;\n if (n < 2) return pts.map((p) => ({ x: p.x, y: p.y }));\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i < n - 1; i++) {\n const p0 = pts[i];\n const p1 = pts[i + 1];\n out.push({ x: p0.x, y: p0.y });\n const bulge = p0.bulge ?? 0;\n if (!bulge) continue; // straight edge\n const dx = p1.x - p0.x;\n const dy = p1.y - p0.y;\n const c = Math.hypot(dx, dy);\n if (c < 1e-6) continue;\n const nx = -dy / c;\n const ny = dx / c;\n const mid = { x: (p0.x + p1.x) / 2 + nx * bulge, y: (p0.y + p1.y) / 2 + ny * bulge };\n const circ = circleThrough(p0, mid, p1);\n if (!circ) continue;\n const a0 = Math.atan2(p0.y - circ.cy, p0.x - circ.cx);\n const am = Math.atan2(mid.y - circ.cy, mid.x - circ.cx);\n const a1 = Math.atan2(p1.y - circ.cy, p1.x - circ.cx);\n const sweep = arcSweep(a0, a1, am);\n for (let s = 1; s < segsPerArc; s++) {\n const a = a0 + (sweep * s) / segsPerArc;\n out.push({ x: circ.cx + circ.r * Math.cos(a), y: circ.cy + circ.r * Math.sin(a) });\n }\n }\n out.push({ x: pts[n - 1].x, y: pts[n - 1].y });\n return out;\n}\n\n/** Normalise an authored track path from a doc, or null if it isn't a real path\n * (needs ≥ 2 valid points). Keeps per-vertex bulge. */\nexport function trackPath(\n path: BenchworkPoint[] | null | undefined,\n): BenchworkPoint[] | null {\n const pts = (path ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n return pts.length >= 2 ? pts : null;\n}\n\n/** Circle through three points, or null if (near-)colinear. */\nfunction circleThrough(\n a: { x: number; y: number },\n b: { x: number; y: number },\n c: { x: number; y: number },\n): { cx: number; cy: number; r: number } | null {\n const d = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y));\n if (Math.abs(d) < 1e-9) return null;\n const a2 = a.x * a.x + a.y * a.y;\n const b2 = b.x * b.x + b.y * b.y;\n const c2 = c.x * c.x + c.y * c.y;\n const cx = (a2 * (b.y - c.y) + b2 * (c.y - a.y) + c2 * (a.y - b.y)) / d;\n const cy = (a2 * (c.x - b.x) + b2 * (a.x - c.x) + c2 * (b.x - a.x)) / d;\n return { cx, cy, r: Math.hypot(a.x - cx, a.y - cy) };\n}\n\n/** Signed sweep from a0 to a1 that goes through the midpoint angle am. */\nfunction arcSweep(a0: number, a1: number, am: number): number {\n const norm = (x: number) => {\n let v = (x - a0) % (2 * Math.PI);\n if (v < 0) v += 2 * Math.PI;\n return v; // 0..2π, measured CCW from a0\n };\n const m = norm(am);\n const one = norm(a1);\n // If the midpoint is reached before a1 going CCW, sweep CCW (+); else CW (−).\n return m <= one ? one : one - 2 * Math.PI;\n}\n\n// ── Physical module footprint (shared by the Repository preview + Free-Dispatcher)\n// The single-module geometry both apps draw: the main track centre-line, the\n// derived benchwork band (an endplate-width ribbon, the fallback when no outline\n// is authored), the endplate FACES, and the authored outline (arcs sampled).\n// Module-local inches: endplate A's track point at the origin, mainline +x,\n// perpendicular +y up. Free-Dispatcher's composeFootprint stacks these per module\n// by the join graph; here we expose the per-module primitive so the Repository\n// renders the exact same board.\n\nconst DEG_FP = Math.PI / 180;\n\nexport interface ModuleFootprintInput {\n /** Mainline length (falls back to footprint length), inches. */\n lengthInches: number;\n geometryType?: string | null;\n geometryDegrees?: number | null;\n geometryOffsetInches?: number | null;\n /** Authored endplate face widths by id (\"A\"/\"B\"…), inches; default recommended. */\n endplateWidths?: Record<string, number>;\n /** Where each endplate's CENTRE sits relative to the main centre-line at that\n * end, inches (signed, along the +normal). Free-moN puts a **double**-track\n * plate's two tracks 9/16″ either side of its centre, so with Main 1 on the\n * centre-line the plate centre is half a track spacing up — pass\n * `FREEMO_TRACK_SPACING_INCHES / 2`. Single track crosses at the centre ⇒ 0\n * (the default), and an off-centre track is a signed value. */\n endplateTrackOffsets?: Record<string, number>;\n /** Authored benchwork outline (module-local inches), or absent for the band. */\n outline?: BenchworkPoint[] | null;\n /** Authored benchwork HOLE — the inner boundary punched out of `outline` to\n * make a donut. Absent/short = a solid board. */\n outlineInner?: BenchworkPoint[] | null;\n /** The module's sections (#96 phase 2). When any carries an outline, the\n * module's footprint is the union of those — `outline` is then ignored. */\n sections?: SchematicSection[] | null;\n /** Authored mainline centre-line (module-local inches, open path with arcs).\n * When present it wins over the geometry-derived centre-line — the owner drew\n * the real shape (#2d-track, physical view only). */\n mainPath?: BenchworkPoint[] | null;\n /** A balloon / return loop — the centre-line turns back on itself, so its far\n * end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */\n loop?: boolean;\n}\n\nexport interface OutlineFace {\n /** The endplate face's two corners + midpoint (the track point). */\n p1: BenchworkPoint;\n p2: BenchworkPoint;\n mid: BenchworkPoint;\n}\n\nexport interface ModuleFootprint {\n /** Main track centre-line A→B (arcs sampled). */\n centerline: BenchworkPoint[];\n /** Derived benchwork band (endplate-width ribbon); the outline fallback. */\n band: BenchworkPoint[];\n /** Endplate faces: [A end, B end]. */\n endplateFaces: OutlineFace[];\n /** Authored outline (arc-sampled closed ring) or null → render the band.\n * Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */\n outline: BenchworkPoint[] | null;\n /** Authored HOLE (arc-sampled closed ring) punched out of `outline` → a donut\n * board. Null = solid. Renderers fill `outline` with `outlineInner` cut out. */\n outlineInner: BenchworkPoint[] | null;\n /** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together\n * they are the module's footprint. Empty = this module doesn't use sections,\n * so fall back to `outline ?? band` exactly as before. */\n sectionOutlines: SectionFootprint[];\n}\n\n/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.\n * An authored `mainPath` wins — the owner drew the real shape; otherwise the\n * centre-line is derived from the geometry fields (length + type/degrees/offset). */\nexport function moduleCenterline(input: ModuleFootprintInput): BenchworkPoint[] {\n const drawn = trackPath(input.mainPath);\n if (drawn) return samplePath(drawn);\n // Sections own the shape when there are any (#108) — a multi-section module\n // has no single geometry, so its spine is its boards chained end to end.\n const chained = sectionedCenterline(input);\n if (chained.length >= 2) return chained;\n // No drawn main and no geometry → the owner hasn't established the mainline\n // yet. A fresh module opens as a blank board; the main is drawn as a layer,\n // not auto-derived. (Legacy modules carry a geometry, so they still derive.)\n if (!input.geometryType) return [];\n const L = input.lengthInches > 0 ? input.lengthInches : 24;\n const gt = input.geometryType;\n if (gt === \"dead_end\") return [{ x: 0, y: 0 }];\n if (gt === \"offset\") return [{ x: 0, y: 0 }, { x: L, y: input.geometryOffsetInches ?? 0 }];\n const turn =\n gt === \"corner_45\" ? 45 : gt === \"corner_90\" ? 90 : gt === \"curve\" ? (input.geometryDegrees ?? 0) : 0;\n if (turn === 0) return [{ x: 0, y: 0 }, { x: L, y: 0 }];\n const t = turn * DEG_FP;\n const r = L / t;\n const steps = 12;\n const pts: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) {\n const a = (t * i) / steps;\n pts.push({ x: r * Math.sin(a), y: r * (1 - Math.cos(a)) });\n }\n return pts;\n}\n\n/** One section's centre-line in ITS OWN frame — starting at the origin heading\n * +x — plus where it leaves off. Same geometry vocabulary the module level has\n * always used, just applied per board (#108). */\nfunction sectionCenterlineLocal(sec: SchematicSection): {\n points: BenchworkPoint[];\n endX: number;\n endY: number;\n endHeadingDeg: number;\n} {\n const L = typeof sec.lengthInches === \"number\" && sec.lengthInches > 0 ? sec.lengthInches : 0;\n const gt = sec.geometryType || \"straight\";\n if (L <= 0) return { points: [{ x: 0, y: 0 }], endX: 0, endY: 0, endHeadingDeg: 0 };\n if (gt === \"offset\") {\n const dy = sec.geometryOffsetInches ?? 0;\n // A jog returns to the original heading, so the next board carries on square.\n return { points: [{ x: 0, y: 0 }, { x: L, y: dy }], endX: L, endY: dy, endHeadingDeg: 0 };\n }\n const turn =\n gt === \"corner_45\" ? 45 : gt === \"corner_90\" ? 90 : gt === \"curve\" ? (sec.geometryDegrees ?? 0) : 0;\n if (turn === 0) return { points: [{ x: 0, y: 0 }, { x: L, y: 0 }], endX: L, endY: 0, endHeadingDeg: 0 };\n const t = turn * DEG_FP;\n const r = L / t; // constant-radius arc of arc-length L\n const steps = 12;\n const points: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) {\n const a = (t * i) / steps;\n points.push({ x: r * Math.sin(a), y: r * (1 - Math.cos(a)) });\n }\n const last = points[points.length - 1];\n return { points, endX: last.x, endY: last.y, endHeadingDeg: turn };\n}\n\n/** The module's length as the SUM of its sections, or null when it has none\n * (then the authored module length still speaks). */\nexport function moduleLengthFromSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): number | null {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return null;\n return secs.reduce((a, sec) => a + sec.lengthInches!, 0);\n}\n\n/** Where each section starts and ends along the main, inches from endplate A.\n * This is what `sectionBreaks` used to author by hand — now derived, so a\n * length is just a number you type and nothing steals from its neighbour. */\nexport function sectionSpans(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): { id: string; name?: string; fromPos: number; toPos: number }[] {\n let acc = 0;\n const out: { id: string; name?: string; fromPos: number; toPos: number }[] = [];\n for (const sec of moduleSections(doc)) {\n const L = typeof sec.lengthInches === \"number\" && sec.lengthInches > 0 ? sec.lengthInches : 0;\n if (L <= 0) continue;\n out.push({ id: sec.id, ...(sec.name ? { name: sec.name } : {}), fromPos: acc, toPos: acc + L });\n acc += L;\n }\n return out;\n}\n\n/** A position expressed against the board it sits on, rather than as inches\n * from endplate A (#109). */\nexport interface SectionRelativePos {\n sectionId: string;\n /** Inches from that section's own west end. */\n offsetInches: number;\n}\n\n/**\n * Section spans that ALWAYS cover the whole module. The owner's insight is\n * what makes #109 tractable: every module has at least one section, even if\n * that one section IS the whole module. So a module with no authored sections\n * gets a single implicit span 0→length, every position falls inside exactly\n * one span, and absolute ↔ relative becomes a total, lossless mapping with no\n * un-convertible module and no orphan positions.\n *\n * The last span is also stretched to the module length when the sections come\n * up short, so a position past the end still lands somewhere real.\n */\nexport function sectionSpansOrWhole(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n lengthInches: number,\n): { id: string; name?: string; fromPos: number; toPos: number }[] {\n const L = lengthInches > 0 ? lengthInches : 0;\n const spans = sectionSpans(doc);\n if (!spans.length) return [{ id: WHOLE_MODULE_SECTION_ID, fromPos: 0, toPos: L }];\n const out = spans.map((sp) => ({ ...sp }));\n const last = out[out.length - 1];\n if (L > last.toPos) last.toPos = L;\n return out;\n}\n\n/** The id a module with no authored sections uses for its single implicit one. */\nexport const WHOLE_MODULE_SECTION_ID = \"module\";\n\n/**\n * Absolute inches → the board it sits on plus an offset along it (#109).\n * Total: given spans from `sectionSpansOrWhole`, every position resolves.\n *\n * A position exactly ON a joint is assigned to the section that STARTS there,\n * at offset 0 — a joint is the west end of the next board, and that keeps the\n * mapping single-valued. The module's own east end is the exception: nothing\n * starts there, so it belongs to the last board.\n */\nexport function toSectionRelative(\n pos: number,\n spans: { id: string; fromPos: number; toPos: number }[],\n): SectionRelativePos | null {\n if (!spans.length) return null;\n const p = Math.max(spans[0].fromPos, Math.min(spans[spans.length - 1].toPos, pos));\n for (const sp of spans) {\n if (p >= sp.fromPos && p < sp.toPos)\n return { sectionId: sp.id, offsetInches: round3(p - sp.fromPos) };\n }\n const last = spans[spans.length - 1];\n return { sectionId: last.id, offsetInches: round3(last.toPos - last.fromPos) };\n}\n\n/** …and back. Null when the section is gone — which is the caller's cue that\n * the thing it positioned has lost its board (#96 phase 3). */\nexport function fromSectionRelative(\n rel: SectionRelativePos,\n spans: { id: string; fromPos: number; toPos: number }[],\n): number | null {\n const sp = spans.find((x) => x.id === rel.sectionId);\n if (!sp) return null;\n return round3(sp.fromPos + Math.max(0, Math.min(sp.toPos - sp.fromPos, rel.offsetInches)));\n}\n\n/** Re-derive an absolute position after the sections have moved: read it\n * against the OLD spans, write it against the NEW ones. This is the whole\n * point of #109 — reorder or resize a board and everything on it comes along\n * instead of silently pointing at a different board. */\nexport function remapPos(\n pos: number,\n before: { id: string; fromPos: number; toPos: number }[],\n after: { id: string; fromPos: number; toPos: number }[],\n): number | null {\n const rel = toSectionRelative(pos, before);\n return rel ? fromSectionRelative(rel, after) : null;\n}\n\n/** The joints implied by the sections — the interior boundaries, in inches from\n * endplate A. Replaces the authored `sectionBreaks` for a sectioned module. */\nexport function sectionBreaksFromSections(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): number[] {\n const spans = sectionSpans(doc);\n return spans.slice(0, -1).map((sp) => sp.toPos);\n}\n\n/** The module's centre-line built by CHAINING its sections — each board starts\n * where the previous one ended, at the heading it ended on. This is what makes\n * a module like One Mile expressible: straight boards with two 24″ curved ones\n * in the middle, which no single module-level geometry can describe (#108).\n * Returns [] when the module has no sections with lengths. */\n/** Where the chained boards finish, and on what heading — computed from the\n * section geometry itself rather than read off the sampled polyline. A curve\n * is sampled in steps, so the last chord lags the true tangent by half a step\n * (a 90° board sampled 12 ways reads 86.25°). That error would land straight\n * in endplate B's heading and throw off face-to-face snapping, so the exact\n * value is accumulated here instead. Null when there are no sections. */\nexport function sectionedEndPose(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): { x: number; y: number; heading: number } | null {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return null;\n let ox = 0;\n let oy = 0;\n let heading = 0;\n for (const sec of secs) {\n const local = sectionCenterlineLocal(sec);\n const c = Math.cos(heading * DEG_FP);\n const sn = Math.sin(heading * DEG_FP);\n ox += local.endX * c - local.endY * sn;\n oy += local.endX * sn + local.endY * c;\n heading += local.endHeadingDeg;\n }\n return { x: ox, y: oy, heading };\n}\n\nexport function sectionedCenterline(\n doc: { sections?: SchematicSection[] | null } | null | undefined,\n): BenchworkPoint[] {\n const secs = moduleSections(doc).filter(\n (sec) => typeof sec.lengthInches === \"number\" && sec.lengthInches! > 0,\n );\n if (!secs.length) return [];\n const out: BenchworkPoint[] = [];\n let ox = 0;\n let oy = 0;\n let heading = 0; // degrees, +x at endplate A\n for (const sec of secs) {\n const local = sectionCenterlineLocal(sec);\n const c = Math.cos(heading * DEG_FP);\n const sn = Math.sin(heading * DEG_FP);\n for (let i = 0; i < local.points.length; i++) {\n // The first vertex of every board but the first repeats the previous\n // board's end point — skip it so the spine has no duplicate vertices.\n if (i === 0 && out.length) continue;\n const p = local.points[i];\n out.push({ x: ox + p.x * c - p.y * sn, y: oy + p.x * sn + p.y * c });\n }\n ox += local.endX * c - local.endY * sn;\n oy += local.endX * sn + local.endY * c;\n heading += local.endHeadingDeg;\n }\n return out;\n}\n\n/** Unit left normal of the local direction at each centre-line vertex. */\nfunction centerlineNormals(center: BenchworkPoint[]): BenchworkPoint[] {\n return center.map((_, i) => {\n const a = center[Math.max(0, i - 1)];\n const b = center[Math.min(center.length - 1, i + 1)];\n let dx = b.x - a.x;\n let dy = b.y - a.y;\n const len = Math.hypot(dx, dy) || 1;\n dx /= len;\n dy /= len;\n return { x: -dy, y: dx };\n });\n}\n\n/** Fraction 0→1 along the centre-line by arc length (A end = 0, B end = 1). */\nfunction centerlineFractions(center: BenchworkPoint[]): number[] {\n const cum = [0];\n for (let i = 1; i < center.length; i++)\n cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));\n const total = cum[cum.length - 1] || 1;\n return cum.map((d) => d / total);\n}\n\n/** Benchwork band: the centre-line offset ±half-width, tapering widthA→widthB. */\nexport function benchworkBand(\n center: BenchworkPoint[],\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): BenchworkPoint[] {\n if (center.length < 2) return [];\n const n = centerlineNormals(center);\n const f = centerlineFractions(center);\n const half = (i: number) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;\n // The board is centred on the plate centre, which need not be the main\n // centre-line — a double-track end sits half a track spacing up (#93).\n const off = (i: number) => offsetA * (1 - f[i]) + offsetB * f[i];\n const left = center.map((p, i) => ({\n x: p.x + n[i].x * (off(i) + half(i)),\n y: p.y + n[i].y * (off(i) + half(i)),\n }));\n const right = center.map((p, i) => ({\n x: p.x + n[i].x * (off(i) - half(i)),\n y: p.y + n[i].y * (off(i) - half(i)),\n }));\n return [...left, ...right.reverse()];\n}\n\n/** The sub-polyline of a centre-line between two arc-length positions, with\n * the cut ends interpolated so a slice starts and finishes exactly on them. */\nexport function sliceCenterline(\n center: BenchworkPoint[],\n fromPos: number,\n toPos: number,\n): BenchworkPoint[] {\n if (center.length < 2) return [];\n const cum = [0];\n for (let i = 1; i < center.length; i++)\n cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));\n const total = cum[cum.length - 1];\n const a = Math.max(0, Math.min(total, Math.min(fromPos, toPos)));\n const b = Math.max(0, Math.min(total, Math.max(fromPos, toPos)));\n if (b - a <= 0) return [];\n const at = (d: number): BenchworkPoint => {\n for (let i = 1; i < center.length; i++) {\n if (d <= cum[i] || i === center.length - 1) {\n const seg = cum[i] - cum[i - 1] || 1;\n const t = Math.max(0, Math.min(1, (d - cum[i - 1]) / seg));\n return {\n x: center[i - 1].x + (center[i].x - center[i - 1].x) * t,\n y: center[i - 1].y + (center[i].y - center[i - 1].y) * t,\n };\n }\n }\n return center[center.length - 1];\n };\n const out: BenchworkPoint[] = [at(a)];\n for (let i = 0; i < center.length; i++) {\n if (cum[i] > a && cum[i] < b) out.push({ x: center[i].x, y: center[i].y });\n }\n out.push(at(b));\n return out;\n}\n\n/** One section's bench-work as a band over its own stretch of centre-line —\n * the per-section equivalent of `benchworkBand` (#96 phase 2b). Width and\n * plate offset are interpolated from the module's ends exactly as the whole\n * band does, so a section's derived shape lines up with its neighbours.\n *\n * This is what makes an outline BELONG to the section: a section without an\n * authored polygon gets one derived from its span, so resizing the board\n * reshapes it instead of leaving a hand-drawn outline stranded. */\nexport function sectionBand(\n center: BenchworkPoint[],\n fromPos: number,\n toPos: number,\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): BenchworkPoint[] {\n const slice = sliceCenterline(center, fromPos, toPos);\n if (slice.length < 2) return [];\n // Fractions must be taken along the WHOLE module, not the slice, or every\n // section would taper from widthA to widthB over its own short length.\n let total = 0;\n for (let i = 1; i < center.length; i++)\n total += Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y);\n total = total || 1;\n const lo = Math.min(fromPos, toPos);\n let acc = 0;\n const fr: number[] = [0];\n for (let i = 1; i < slice.length; i++) {\n acc += Math.hypot(slice[i].x - slice[i - 1].x, slice[i].y - slice[i - 1].y);\n fr.push(acc);\n }\n const f = fr.map((d) => Math.max(0, Math.min(1, (lo + d) / total)));\n const n = centerlineNormals(slice);\n const half = (i: number) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;\n const off = (i: number) => offsetA * (1 - f[i]) + offsetB * f[i];\n const left = slice.map((p, i) => ({\n x: p.x + n[i].x * (off(i) + half(i)),\n y: p.y + n[i].y * (off(i) + half(i)),\n }));\n const right = slice.map((p, i) => ({\n x: p.x + n[i].x * (off(i) - half(i)),\n y: p.y + n[i].y * (off(i) - half(i)),\n }));\n return [...left, ...right.reverse()];\n}\n\n/** Two sections that physically meet, and how much edge they share. */\nexport interface SectionAdjacency {\n a: string;\n b: string;\n /** Inches of shared edge — a butt joint across a 24″ board reads ~24. */\n lengthInches: number;\n}\n\n/** Closed-ring edges of a polygon, including the wrap-around. */\nfunction ringEdges(pts: { x: number; y: number }[]): [\n { x: number; y: number },\n { x: number; y: number },\n][] {\n const out: [{ x: number; y: number }, { x: number; y: number }][] = [];\n for (let i = 0; i < pts.length; i++) out.push([pts[i], pts[(i + 1) % pts.length]]);\n return out;\n}\n\n/** How much of two near-collinear segments actually overlap, in inches. 0 when\n * they're skew, too far apart, or merely touching at a point. */\nfunction sharedEdgeLength(\n e1: [{ x: number; y: number }, { x: number; y: number }],\n e2: [{ x: number; y: number }, { x: number; y: number }],\n gap: number,\n angleDeg: number,\n): number {\n const ux = e1[1].x - e1[0].x;\n const uy = e1[1].y - e1[0].y;\n const ul = Math.hypot(ux, uy);\n const vx = e2[1].x - e2[0].x;\n const vy = e2[1].y - e2[0].y;\n const vl = Math.hypot(vx, vy);\n if (ul < 1e-6 || vl < 1e-6) return 0;\n const dx = ux / ul;\n const dy = uy / ul;\n // Parallel either way round — a shared joint has the two boards' edges\n // running in OPPOSITE directions, since each ring winds around its own board.\n const cross = Math.abs((dx * vy - dy * vx) / vl);\n if (cross > Math.sin((angleDeg * Math.PI) / 180)) return 0;\n // Both endpoints of e2 must lie within `gap` of e1's infinite line.\n const perp = (q: { x: number; y: number }) =>\n Math.abs((q.x - e1[0].x) * -dy + (q.y - e1[0].y) * dx);\n if (perp(e2[0]) > gap || perp(e2[1]) > gap) return 0;\n const proj = (q: { x: number; y: number }) => (q.x - e1[0].x) * dx + (q.y - e1[0].y) * dy;\n const t1 = proj(e2[0]);\n const t2 = proj(e2[1]);\n return Math.max(0, Math.min(ul, Math.max(t1, t2)) - Math.max(0, Math.min(t1, t2)));\n}\n\n/**\n * Which sections physically MEET, derived from shared polygon edges rather\n * than list order (#96 phase 2c).\n *\n * Order is the wrong model as soon as a module stops being a row of boards: a\n * peninsula hangs off the BACK of a shallow band over part of its length, so\n * it neighbours a board it isn't next to in any list. Geometry is the only\n * thing that knows.\n */\nexport function sectionAdjacency(\n footprints: SectionFootprint[],\n opts?: { gapInches?: number; angleDegrees?: number; minOverlapInches?: number },\n): SectionAdjacency[] {\n const gap = opts?.gapInches ?? 0.5;\n const angle = opts?.angleDegrees ?? 3;\n const min = opts?.minOverlapInches ?? 1;\n const edges = footprints.map((f) => ringEdges(f.outline));\n const out: SectionAdjacency[] = [];\n for (let i = 0; i < footprints.length; i++) {\n for (let j = i + 1; j < footprints.length; j++) {\n let total = 0;\n for (const e1 of edges[i])\n for (const e2 of edges[j]) total += sharedEdgeLength(e1, e2, gap, angle);\n if (total >= min)\n out.push({\n a: footprints[i].id,\n b: footprints[j].id,\n lengthInches: Math.round(total * 1000) / 1000,\n });\n }\n }\n return out;\n}\n\n/** The sections each one touches. */\nexport function sectionNeighbours(id: string, adj: SectionAdjacency[]): string[] {\n return adj.filter((x) => x.a === id || x.b === id).map((x) => (x.a === id ? x.b : x.a));\n}\n\n/**\n * Groups of sections that hang together, as connected components. One group\n * means the module is a single piece of bench work; more than one means some\n * board is floating free — an authoring mistake now, and the test #96 phase 3\n * needs before it can say whether dropping a section leaves the rest intact.\n */\nexport function sectionComponents(ids: string[], adj: SectionAdjacency[]): string[][] {\n const parent = new Map(ids.map((id) => [id, id]));\n const find = (x: string): string => {\n let r = x;\n while (parent.get(r) !== r) r = parent.get(r)!;\n while (parent.get(x) !== r) {\n const nx = parent.get(x)!;\n parent.set(x, r);\n x = nx;\n }\n return r;\n };\n for (const { a, b } of adj) {\n if (!parent.has(a) || !parent.has(b)) continue;\n const ra = find(a);\n const rb = find(b);\n if (ra !== rb) parent.set(ra, rb);\n }\n const groups = new Map<string, string[]>();\n for (const id of ids) {\n const r = find(id);\n groups.set(r, [...(groups.get(r) ?? []), id]);\n }\n // Keep the caller's ordering so the first group is the one containing the\n // first section — the piece with endplate A on it.\n return [...groups.values()];\n}\n\n/** The two endplate faces (the band's flat ends): [A end at widthA, B end at widthB]. */\nexport function endplateFaceSegments(\n center: BenchworkPoint[],\n widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES,\n offsetA = 0,\n offsetB = 0,\n): OutlineFace[] {\n if (center.length < 2) return [];\n const n = centerlineNormals(center);\n // `mid` stays the TRACK point (what joints and drawn track key off); the face\n // spans ±w/2 about the PLATE centre, which a double-track end offsets (#93).\n const face = (i: number, w: number, o: number): OutlineFace => ({\n p1: { x: center[i].x + n[i].x * (o + w / 2), y: center[i].y + n[i].y * (o + w / 2) },\n p2: { x: center[i].x + n[i].x * (o - w / 2), y: center[i].y + n[i].y * (o - w / 2) },\n mid: { x: center[i].x, y: center[i].y },\n });\n return [face(0, widthA, offsetA), face(center.length - 1, widthB, offsetB)];\n}\n\n/**\n * The full single-module physical footprint: centre-line + derived band +\n * endplate faces + the authored outline (arc-sampled), all in module-local\n * inches. Renderers draw `outline ?? band`.\n */\nexport function moduleFootprint(input: ModuleFootprintInput): ModuleFootprint {\n const centerline = moduleCenterline(input);\n const widthA = endplateWidthFor(input.endplateWidths, \"A\");\n const widthB = endplateWidthFor(input.endplateWidths, \"B\");\n const authored = benchworkOutline(input);\n const offA = input.endplateTrackOffsets?.[\"A\"] ?? 0;\n const offB = input.endplateTrackOffsets?.[\"B\"] ?? 0;\n // A module built from shaped sections IS its sections — the whole-module\n // outline stops speaking for it, so don't hand back both and leave renderers\n // to guess which wins (#96 phase 2).\n //\n // EXCEPT a LONE section with no shape of its own: that section IS the module,\n // so its derived band says nothing the authored outline doesn't already say —\n // and letting it win ORPHANED the owner's corners (drawn as faint context,\n // uneditable, while the Objects list still counted them). That's Steve's\n // \"benchwork points are set but the benchwork is not drawn\" (#173). Two or\n // more sections still own the shape, so a multi-board module keeps its split.\n const secs = input.sections ?? [];\n const sectionsOwnShape =\n secs.length > 1 || secs.some((s) => (s.outline?.length ?? 0) >= 3);\n const sectionOutlines = sectionsOwnShape\n ? sectionFootprints(input, {\n centerline,\n widthA,\n widthB,\n offsetA: offA,\n offsetB: offB,\n })\n : [];\n return {\n centerline,\n band: benchworkBand(centerline, widthA, widthB, offA, offB),\n // A loop's centre-line ends at the throat, not a far endplate — keep only\n // endplate A's face (the far face would be a spurious plate at the throat).\n endplateFaces: input.loop\n ? endplateFaceSegments(centerline, widthA, widthB, offA, offB).slice(0, 1)\n : endplateFaceSegments(centerline, widthA, widthB, offA, offB),\n outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),\n // The donut hole, arc-sampled — only when there's a solid outline to punch it\n // out of (a sectioned module isn't a donut). Renderers cut it from `outline`.\n outlineInner:\n sectionOutlines.length || !authored || !input.outlineInner || input.outlineInner.length < 3\n ? null\n : sampleBenchworkOutline(input.outlineInner),\n sectionOutlines,\n };\n}\n\n/**\n * The offset from the main centre-line to an endplate's CENTRE, inches — the\n * Free-moN geometry. A **double**-track end carries its two tracks 9/16″ either\n * side of the plate centre (§2.0 RP), and Main 1 sits on the centre-line, so the\n * plate centre is half a track spacing up. A single track crosses at the centre.\n */\nexport function endplateTrackOffsetFor(\n config: TrackConfig | \"none\" | undefined,\n authoredTrackOffset?: number | null,\n): number {\n const v = -endplateTrackOffsetInches(authoredTrackOffset, config);\n return v === 0 ? 0 : v; // never hand back -0 (it leaks into JSON and compares oddly)\n}\n\n/**\n * Where an endplate's PRIMARY track (Main 1) crosses, as a signed distance from\n * the plate's CENTRE — the standard's own framing. Authored value wins; absent\n * falls back to the §2.0 recommendations: a single track centred (0), a double\n * straddling so its two tracks land ∓ half the track spacing (Main 1 low).\n */\nexport function endplateTrackOffsetInches(\n authored: number | null | undefined,\n config: TrackConfig | \"none\" | undefined,\n): number {\n if (typeof authored === \"number\" && Number.isFinite(authored)) return authored;\n return config === \"double\" ? -FREEMO_TRACK_SPACING_INCHES / 2 : 0;\n}\n\n/** A Free-moN conformance problem with an endplate's width/track placement. */\nexport interface EndplateWidthIssue {\n /** \"narrow\" = below the 12″ minimum; \"clearance\" = a track too near a fascia. */\n code: \"narrow\" | \"clearance\";\n /** Plain-language problem, for the author. */\n message: string;\n /** The width that would satisfy this rule, inches. */\n requiredInches: number;\n}\n\n/**\n * Check an endplate against the two Free-moN **standards** that bound its width:\n *\n * - §1.1 \"Endplates shall be 6 inches high and a **minimum 12 inches wide**.\"\n * - §2.0 \"At the endplate, track shall cross near center on the width, **not less\n * than 4 inches from either fascia**.\"\n *\n * With the tracks centred (the §2.0 recommendation) a double-track end needs\n * 4 + 1.125 + 4 = 9.125″ for clearance alone, so the 12″ minimum governs — but an\n * **off-centre** track can breach the 4″ rule on a plate that is otherwise wide\n * enough, which is why both are checked. `trackOffsetInches` is the signed\n * distance from the plate's centre to the main's crossing point (0 = centred).\n */\nexport function checkEndplateWidth(input: {\n widthInches?: number | null;\n config?: TrackConfig | \"none\" | null;\n trackOffsetInches?: number | null;\n}): EndplateWidthIssue[] {\n const width = endplateWidthInches(input as { widthInches?: number | null });\n const issues: EndplateWidthIssue[] = [];\n if (width < FREEMO_ENDPLATE_WIDTH_MIN_INCHES) {\n issues.push({\n code: \"narrow\",\n message: `Endplate is ${round2(width)}″ wide — the standard requires at least ${FREEMO_ENDPLATE_WIDTH_MIN_INCHES}″.`,\n requiredInches: FREEMO_ENDPLATE_WIDTH_MIN_INCHES,\n });\n }\n // Track centres relative to the plate centre. `trackOffsetInches` locates\n // MAIN 1 (the same framing the authoring field and the renderer use); a\n // double end carries Main 2 one spacing further out, so check whichever of\n // the two sits nearest a fascia. Unauthored falls back to the §2.0 default,\n // which straddles the centre — so a plain double end still measures ±9/16″.\n const off = endplateTrackOffsetInches(input.trackOffsetInches, input.config ?? undefined);\n const centres =\n input.config === \"double\" ? [off, off + FREEMO_TRACK_SPACING_INCHES] : [off];\n const worst = Math.max(...centres.map((c) => Math.abs(c)));\n const clearance = width / 2 - worst;\n if (clearance < FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES) {\n const required = 2 * (worst + FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES);\n issues.push({\n code: \"clearance\",\n message:\n `Track sits ${round2(clearance)}″ from the fascia — the standard requires at least ` +\n `${FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES}″. Widen this end to ${round2(required)}″` +\n (off !== 0 ? \" or move the track back toward the centre.\" : \".\"),\n requiredInches: required,\n });\n }\n return issues;\n}\n\nconst round2 = (n: number) => Math.round(n * 100) / 100;\nconst round3 = (n: number) => Math.round(n * 1000) / 1000;\n\nfunction endplateWidthFor(widths: Record<string, number> | undefined, id: string): number {\n const w = widths?.[id];\n return typeof w === \"number\" && w > 0 ? w : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;\n}\n\n/** Whether a doc is a single-endplate turnback (explicit flag or one endplate). */\nexport function isLoopDoc(doc: ModuleSchematicDoc): boolean {\n return doc.loop === true || doc.endplates.length === 1;\n}\n\nexport const MAIN_TRACK_ID = \"main\";\n/** The second main on double-track modules — a real track entity so turnouts\n * and signals can attach to it (a spur off Main 2 must diverge from lane 1,\n * not draw a crossover from Main 1). Emitted by stateToDoc when either\n * endplate is double; legacy docs without it still parse. */\nexport const MAIN2_TRACK_ID = \"main2\";\n\n// North American N scale (1:160): 396 real inches → 5280 scale feet = one mile.\nexport const N_SCALE_RATIO = 160;\n/** Real inches on the module → scale feet of prototype track represented. */\nexport function inchesToScaleFeet(inches: number, ratio = N_SCALE_RATIO): number {\n return (inches * ratio) / 12;\n}\n/** Scale feet of prototype track → real inches on the module. */\nexport function scaleFeetToInches(feet: number, ratio = N_SCALE_RATIO): number {\n return (feet * 12) / ratio;\n}\n\n/** Length a spotted car occupies on N-scale track, inches. A 40-ft car body is\n * ~3.0″; ~3.3″ over the couplers — the real spacing a cut of cars takes. The\n * single constant every repo reads so a track's car count matches everywhere. */\nexport const N_CAR_LENGTH_INCHES = 3.3;\n\n/** How many cars fit in a span, from its drawn length — the derived capacity a\n * siding or an industry spot holds (never typed). */\nexport function carCapacity(\n fromPos: number,\n toPos: number,\n carLengthInches = N_CAR_LENGTH_INCHES,\n): number {\n if (!(carLengthInches > 0)) return 0;\n return Math.max(0, Math.floor(Math.abs(toPos - fromPos) / carLengthInches));\n}\n\n/** Parse a jsonb value into a schematic doc, or null if it isn't one. */\nexport function asModuleSchematic(x: unknown): ModuleSchematicDoc | null {\n if (!x || typeof x !== \"object\") return null;\n const d = x as Record<string, unknown>;\n if (typeof d.version !== \"number\") return null;\n if (!Array.isArray(d.endplates) || !Array.isArray(d.tracks)) return null;\n return d as unknown as ModuleSchematicDoc;\n}\n\n// ---- Editor state (a flatter shape an authoring form binds to) -------------\n\nexport interface EditorTrack {\n id: string;\n role: TrackRole;\n lane: number;\n fromPos: number;\n toPos: number;\n /** module_tracks row id (single source of truth), or null for a new track. */\n moduleTrackId: number | null;\n /** Owner's track name → module_tracks.track_name. */\n trackName: string;\n /** Inside the balloon of a loop module (#165). */\n inLoop?: boolean;\n /** Authored 2-D path (module-local inches) — a bent/rotated spur's real\n * shape. Absent = derive from the main + lane (#2d-track). */\n path?: BenchworkPoint[];\n}\n\n/** A module_tracks row as loaded for the editor. */\nexport interface ModuleTrackRow {\n id: number;\n track_name: string | null;\n capacity_scale_feet: number | null;\n}\nexport interface EditorTurnout {\n id: string;\n name: string;\n pos: number;\n onTrack: string;\n divergeTrack: string;\n kind: TurnoutKind;\n /** Frog number (\"size\") — #4, #6, #8, etc. Governs the diverging angle. */\n size?: number;\n /** Rotate the turnout 180° — the points face the other way (#turnout-flip). */\n flipped?: boolean;\n /** A curved turnout — the diverging route bows into an arc rather than a\n * straight diagonal. Physical-render only (the operations view is topological). */\n curved?: boolean;\n}\nexport interface EditorCpSignal {\n id: string;\n pos: number;\n track: string;\n facing: SignalFacing;\n side: SignalSide;\n}\nexport interface EditorControlPoint {\n id: string;\n name: string;\n turnouts: string[]; // turnout ids grouped under this control point\n /** Crossing ids this interlocking protects (#170). */\n crossings?: string[];\n signals: EditorCpSignal[];\n}\nexport interface EditorCrossing {\n id: string;\n name: string;\n pos: number;\n trackA: string;\n trackB: string;\n}\n/** An industry as the authoring form binds it — a car-spot span on a track. */\nexport interface EditorIndustry {\n id: string;\n name: string;\n type: string;\n track: string;\n fromPos: number;\n toPos: number;\n /** Extra car-spot spans on other tracks (house-track spots, #54). */\n spots: IndustrySpot[];\n side: SignalSide;\n labelMode: IndustryLabelMode;\n carTypes: string[];\n /** freemon_industries row (single source of truth), or null for a new one. */\n moduleIndustryId: number | null;\n}\n/** A 3rd+ endplate — a branch/junction connection off the module (#170).\n * A module may have several (e.g. a set carrying a second railroad through:\n * MoPac enters at one branch endplate and leaves at another). */\nexport interface EditorBranch {\n label: string;\n pos: number;\n side: \"up\" | \"down\";\n config: TrackConfig;\n /** What the route to this endplate is — a secondary \"branch\" or a diverging\n * \"main\". Drives labels/weight, not geometry. Default \"branch\". */\n kind?: \"branch\" | \"main\";\n /** The drawn diverging track that reaches this endplate (set when the owner\n * draws track to it; the plate is placed first, connected later). */\n trackId?: string | null;\n}\n/** Endplate B on a loop module: a standard endplate makes the balloon an\n * INTERCHANGE (a second route connects at the loop, e.g. Seaford); \"none\"\n * makes it a pure turnback. Non-loop modules always have a real B. */\nexport type EndplateBConfig = TrackConfig | \"none\";\n\nexport interface EditorState {\n lengthInches: number;\n /** Balloon loop: the main runs the lead and turns back; positions past the\n * throat are inside the balloon. Endplate B stays independently available —\n * present = interchange loop, \"none\" = pure turnback. */\n loop: boolean;\n /** Where the balloon returns: same main, or Main 2 (directional return on a\n * double-track main — drawn as a U joining the two lanes). */\n loopReturn: \"same\" | \"main2\";\n configA: TrackConfig;\n configB: EndplateBConfig;\n /** Swap the two mains' POSITIONS: Main 1 draws above (lane 1) and Main 2 on\n * the centre line (lane 0). The module decides which physical track is which\n * main — on some modules the upper track is the through/primary main\n * (#FMN-0043). Identities and references are unchanged; only the lanes swap. */\n mainsSwapped: boolean;\n extraTracks: EditorTrack[]; // sidings/spurs/…; the main track is implicit\n turnouts: EditorTurnout[];\n /** Grade crossings / diamonds (#170). */\n crossings: EditorCrossing[];\n /** Branch endplates C, D, … — junction connections (#170); empty = through\n * module. Emitted in order as endplates \"C\", \"D\", \"E\"… */\n branches: EditorBranch[];\n /** Manual endplate pose overrides by endplate id (#175 phase 1b). */\n poseOverrides: Record<string, { x: number; y: number; heading: number }>;\n /** Authored endplate face widths by endplate id, inches (Free-moN 12″ min,\n * 24″ recommended). Absent id = the recommended default. */\n endplateWidths: Record<string, number>;\n /** Authored per-endplate TRACK offsets by id — the primary track's signed\n * distance from the plate centre, inches. Absent id = the §2.0 default. */\n endplateTrackOffsets: Record<string, number>;\n /** Benchwork footprint outline — polygon vertices in module-local inches\n * (endplate A's track point at the origin, mainline +x, perpendicular +y up).\n * Empty = no authored outline (fall back to the endplate-width band). */\n outline: BenchworkPoint[];\n /** Benchwork HOLE (donut inner boundary), module-local inches. Empty = a solid\n * board. Set by the return-loop generator; punched out of `outline`. */\n outlineInner: BenchworkPoint[];\n /** Internal section joints — inches from endplate A where the boards split\n * into sections. Empty = a single section (#48). */\n sectionBreaks: number[];\n /** The module's sections as named objects, each optionally carrying its own\n * outline (#96 phase 2). Empty = fall back to `outline` + `sectionBreaks`. */\n sections: SchematicSection[];\n controlPoints: EditorControlPoint[];\n /** Rail-served industries — car-spot spans on a track (#industries). */\n industries: EditorIndustry[];\n /** Authored mainline centre-line (module-local inches) — empty = derive from\n * geometry. The owner-drawn real shape (#2d-track, physical view only). */\n mainPath: BenchworkPoint[];\n /** Authored Main 2 centre-line (double-track only) — empty = lane offset (#131). */\n main2Path: BenchworkPoint[];\n}\n\n/** Build the empty editor state for a module of the given length. */\nexport function emptyEditorState(lengthInches: number): EditorState {\n return {\n lengthInches: lengthInches > 0 ? lengthInches : 24,\n loop: false,\n loopReturn: \"same\",\n configA: \"single\",\n configB: \"single\",\n mainsSwapped: false,\n extraTracks: [],\n turnouts: [],\n crossings: [],\n branches: [],\n poseOverrides: {},\n endplateWidths: {},\n endplateTrackOffsets: {},\n outline: [],\n outlineInner: [],\n sectionBreaks: [],\n sections: [],\n controlPoints: [],\n industries: [],\n mainPath: [],\n main2Path: [],\n };\n}\n\n/** Main 2's doc track for a non-loop double module. Full length when both\n * endplates are double; on a transition module (one single, one double) it\n * runs between the mainline transition turnout (the one diverging to main2)\n * and the double end. */\n/**\n * A single↔double transition turnout connects Main 1 and Main 2 — where the\n * second main begins/ends. It may be authored either way round: on Main 1\n * diverging to Main 2, or on Main 2 diverging to Main 1 (both describe the same\n * junction). Recognise both so editing the direction doesn't drop the transition.\n */\nexport function isTransitionTurnout(t: {\n onTrack?: string;\n divergeTrack?: string;\n}): boolean {\n return (\n (t.onTrack === MAIN_TRACK_ID && t.divergeTrack === MAIN2_TRACK_ID) ||\n (t.onTrack === MAIN2_TRACK_ID && t.divergeTrack === MAIN_TRACK_ID)\n );\n}\n\n/**\n * Main 1's extent. Normally it's the through main, A→B. But on a transition\n * module where MAIN 2 is the surviving through main (the turnout sits ON Main 2\n * and diverges to Main 1, #FMN-0043), Main 1 is the one that ENDS — it must stop\n * at the turnout, or both mains draw endplate-to-endplate and the single-track\n * end shows two tracks reaching it.\n */\nfunction main1Track(state: EditorState): SchematicTrack {\n // Main 1 is the through mainline: always the full module, always on the\n // centre line. The swap moves MAIN 2 to the other side; Main 1 never moves\n // (Steve Branton, #131). A legacy doc where the turnout sits ON Main 2 (Main 2\n // was the through main) still truncates Main 1 so old modules don't break.\n const sw = state.turnouts.find(isTransitionTurnout);\n const legacyThroughMain2 =\n !!sw && sw.onTrack === MAIN2_TRACK_ID && sw.divergeTrack === MAIN_TRACK_ID;\n const isDouble = state.configA === \"double\" || state.configB === \"double\";\n const bothDouble = state.configA === \"double\" && state.configB === \"double\";\n if (!isDouble || bothDouble || !legacyThroughMain2) {\n return { id: MAIN_TRACK_ID, role: \"main\", lane: 0, from: \"A\", to: \"B\" };\n }\n return state.configA === \"double\"\n ? { id: MAIN_TRACK_ID, role: \"main\", lane: 0, fromPos: 0, toPos: sw!.pos }\n : { id: MAIN_TRACK_ID, role: \"main\", lane: 0, fromPos: sw!.pos, toPos: state.lengthInches };\n}\n\nfunction main2Track(state: EditorState): SchematicTrack {\n const bothDouble = state.configA === \"double\" && state.configB === \"double\";\n // EVERY turnout that opens Main 2, west to east — not just the first. A module\n // that's single at both ends with a double stretch in the middle (the ordinary\n // passing-siding module) has TWO, and Main 2 lives between them. Taking only\n // the first ran Main 2 on to the far endplate, so a single-track end drew two\n // tracks reaching it (#118).\n const sws = state.turnouts\n .filter((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID)\n .sort((a, b) => a.pos - b.pos);\n // Main 2 runs partial only when IT is the branch that ends (turnout diverges\n // TO Main 2). If the turnout sits ON Main 2 (Main 2 is the surviving through\n // main, #FMN-0043), Main 2 runs full and Main 1 is the one that ends.\n // Main 2's side: above Main 1 by default, below when swapped (Steve, #131).\n // Main 1 stays on the centre line; only Main 2 changes side.\n const lane = state.mainsSwapped ? -1 : 1;\n // A bent Main 2 draws along its authored path instead of a lane offset (#131).\n const authored = state.main2Path.length >= 2 ? { path: state.main2Path } : {};\n if (bothDouble || !sws.length) {\n return { id: MAIN2_TRACK_ID, role: \"main\", lane, from: \"A\", to: \"B\", ...authored };\n }\n const track = (fromPos: number, toPos: number): SchematicTrack => ({\n id: MAIN2_TRACK_ID,\n role: \"main\",\n lane,\n fromPos,\n toPos,\n ...authored,\n });\n // Double at A: Main 2 runs from A and ends at the turnout that closes it.\n if (state.configA === \"double\") return track(0, sws[0].pos);\n // Double at B: it begins where it FIRST appears and runs through to B.\n if (state.configB === \"double\") return track(sws[0].pos, state.lengthInches);\n // Single at both ends — the ordinary passing-siding module. Main 2 lives\n // between the outermost turnouts.\n if (sws.length >= 2) return track(sws[0].pos, sws[sws.length - 1].pos);\n // One turnout and neither end double: a half-drawn siding. Nothing says\n // where it ends, so let it run out rather than collapsing it to nothing.\n return track(sws[0].pos, state.lengthInches);\n}\n\n/**\n * Build the single↔double transition as one unit (like buildPassingSiding):\n * the mainline turnout where Main 2 begins/ends, grouped in a control point —\n * an \"End of Double Track\" is a classic CTC interlocking — with signals both\n * directions. Returns items to merge into the editor state.\n */\nexport function buildTransition(state: EditorState): {\n turnout: EditorTurnout;\n controlPoint: EditorControlPoint;\n} | null {\n const aDouble = state.configA === \"double\";\n const bDouble = state.configB === \"double\";\n if (state.loop || aDouble === bDouble) return null; // not a transition module\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const inset = Math.max(6, Math.round(len * 0.25));\n // The turnout sits toward the single end so the double track carries most\n // of the module; owner adjusts the position afterwards.\n const pos = aDouble ? len - inset : inset;\n\n const swId = nextId(\"sw\", state.turnouts.map((t) => t.id));\n const turnout: EditorTurnout = {\n id: swId,\n name: \"End of Double Track\",\n pos,\n // The turnout sits ON the through mainline (Main 1) and diverges TO Main 2,\n // the second main being added to start the double track — the modeller's\n // view of the junction, and the direction an owner authors it (Steve\n // Branton, #131). Main 1 runs the full module; Main 2 is the branch.\n onTrack: MAIN_TRACK_ID,\n divergeTrack: MAIN2_TRACK_ID,\n // Hand so the diverging leg lands on Main 2's side. Main 2 extends toward\n // the double end (sign −1 west / +1 east) and sits above (+1) or, when the\n // mains are swapped, below (−1). divergeSideForHand(left)=sign(toward),\n // (right)=−sign(toward), so pick the hand whose side matches Main 2's (#131).\n kind:\n (aDouble ? -1 : 1) === (state.mainsSwapped ? -1 : 1) ? \"left\" : \"right\",\n };\n\n const cpId = nextId(\"cp\", state.controlPoints.map((c) => c.id));\n const sig = (facing: SignalFacing): EditorCpSignal => ({\n id: `${cpId}-${facing}`,\n pos,\n track: MAIN_TRACK_ID,\n facing,\n side: facing === \"AtoB\" ? \"above\" : \"below\",\n });\n const controlPoint: EditorControlPoint = {\n id: cpId,\n name: \"End of Double Track\",\n turnouts: [swId],\n signals: [sig(\"AtoB\"), sig(\"BtoA\")],\n };\n return { turnout, controlPoint };\n}\n\n/** Attach manual pose overrides (#175 phase 1b) to endplates by id. */\nfunction withPoses(\n endplates: SchematicEndplate[],\n overrides: Record<string, { x: number; y: number; heading: number }>,\n): SchematicEndplate[] {\n return endplates.map((e) =>\n overrides[e.id] ? { ...e, pose: overrides[e.id] } : e,\n );\n}\n\n/** Attach authored endplate face widths by id; a non-positive/absent width is\n * left off so it falls back to the recommended default. */\nfunction withWidths(\n endplates: SchematicEndplate[],\n widths: Record<string, number>,\n offsets: Record<string, number> = {},\n): SchematicEndplate[] {\n return endplates.map((e) => {\n const w = widths[e.id];\n const o = offsets[e.id];\n let out = e;\n if (typeof w === \"number\" && w > 0) out = { ...out, widthInches: w };\n if (typeof o === \"number\" && Number.isFinite(o)) out = { ...out, trackOffsetInches: o };\n return out;\n });\n}\n\n/** Assemble a spec-conformant doc from the editor state. */\nexport function stateToDoc(\n state: EditorState,\n recordNumber: string,\n): ModuleSchematicDoc {\n return {\n version: 1,\n module: recordNumber,\n lengthInches: state.lengthInches,\n ...(state.loop ? { loop: true } : {}),\n ...(state.loop && state.loopReturn === \"main2\" ? { loopReturn: \"main2\" as const } : {}),\n ...(state.mainsSwapped ? { mainsSwapped: true } : {}),\n endplates: withWidths(\n withPoses(\n [\n ...(state.loop\n ? // Balloon loop: A is the entry. A standard endplate B on the balloon\n // makes it an INTERCHANGE (second route connects at the loop, e.g.\n // Seaford); configB \"none\" makes it a pure turnback.\n [\n { id: \"A\", label: \"Entry\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },\n ...(state.configB !== \"none\"\n ? [{ id: \"B\", label: \"Interchange\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configB }] }]\n : []),\n ]\n : [\n { id: \"A\", label: \"West\", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },\n // Non-loop modules always have a real B (\"none\" never applies).\n {\n id: \"B\",\n label: \"East\",\n tracks: [\n {\n trackId: MAIN_TRACK_ID,\n lane: 0,\n config: state.configB === \"none\" ? \"single\" : state.configB,\n },\n ],\n },\n ]),\n // Branch endplates C, D, … — junction connections at pos, off one side\n // (#170). A set can carry several (e.g. a second railroad through).\n ...state.branches.map((b, i) => ({\n id: String.fromCharCode(67 + i), // C, D, E…\n label: b.label || `Branch ${i + 1}`,\n tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],\n at: { pos: b.pos, side: b.side },\n kind: b.kind ?? \"branch\",\n ...(b.trackId ? { trackId: b.trackId } : {}),\n })),\n ],\n state.poseOverrides,\n ),\n state.endplateWidths,\n state.endplateTrackOffsets,\n ),\n tracks: [\n state.loop\n ? // The main runs the lead from A and turns back at the balloon.\n { id: MAIN_TRACK_ID, role: \"main\" as const, lane: 0, fromPos: 0, toPos: state.lengthInches }\n : // Normally A→B; partial when MAIN 2 is the through main and Main 1 is\n // the one that ends at the transition turnout (#FMN-0043).\n main1Track(state),\n // Double track: Main 2 is a real entity so turnouts/signals can attach.\n // On a loop it exists only for a Main 2 directional return (the U joins\n // the two lanes at the balloon); a same-main loop's parallel lead legs\n // are ONE main. On a TRANSITION module (one endplate single, the other\n // double) Main 2 only runs from the mainline turnout to the double end —\n // the turnout that diverges to main2 is the single source of truth for\n // where the transition sits (fd#175 / FMN-0038).\n // …and on a module that's SINGLE at both ends but goes double in the\n // middle to form a siding: the turnouts are what make Main 2 exist, so a\n // pair of them is reason enough to emit it (#118). Without this the\n // second main simply wasn't in the doc, and neither the board nor the\n // dispatcher panel could draw it.\n ...(!state.loop &&\n (state.configA === \"double\" ||\n state.configB === \"double\" ||\n state.turnouts.some((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID))\n ? [main2Track(state)]\n : []),\n ...(state.loop && state.loopReturn === \"main2\"\n ? [{ id: MAIN2_TRACK_ID, role: \"main\" as const, lane: 1, fromPos: 0, toPos: state.lengthInches }]\n : []),\n ...state.extraTracks.map((t) => ({\n id: t.id,\n role: t.role,\n lane: t.lane,\n fromPos: t.fromPos,\n toPos: t.toPos,\n moduleTrackId: t.moduleTrackId,\n trackName: t.trackName || undefined,\n capacityFeet: Math.round(inchesToScaleFeet(Math.abs(t.toPos - t.fromPos))),\n ...(state.loop && t.inLoop ? { inLoop: true } : {}),\n ...(t.path && t.path.length >= 2 ? { path: t.path } : {}),\n })),\n ],\n turnouts: state.turnouts.map((t) => ({\n id: t.id,\n pos: t.pos,\n onTrack: t.onTrack,\n divergeTrack: t.divergeTrack,\n kind: t.kind,\n name: t.name || undefined,\n ...(t.size ? { size: t.size } : {}),\n ...(t.curved ? { curved: true } : {}),\n ...(t.flipped ? { flipped: true } : {}),\n })),\n ...(state.crossings.length > 0\n ? {\n crossings: state.crossings.map((x) => ({\n id: x.id,\n pos: x.pos,\n tracks: [x.trackA, x.trackB] as [string, string],\n name: x.name || undefined,\n })),\n }\n : {}),\n controlPoints: state.controlPoints.map((c) => ({\n id: c.id,\n name: c.name,\n turnouts: c.turnouts,\n ...(c.crossings?.length ? { crossings: c.crossings } : {}),\n signals: c.signals.map((s) => ({\n id: s.id,\n pos: s.pos,\n track: s.track,\n facing: s.facing,\n kind: \"mast\" as const,\n side: s.side,\n })),\n })),\n // Industries — car-spot spans on a track; only when any are authored.\n ...(state.industries.length > 0\n ? {\n industries: state.industries.map((ind) => ({\n id: ind.id,\n name: ind.name,\n ...(ind.type ? { type: ind.type } : {}),\n track: ind.track,\n fromPos: ind.fromPos,\n toPos: ind.toPos,\n ...(ind.spots?.length ? { spots: ind.spots } : {}),\n side: ind.side,\n ...(ind.labelMode && ind.labelMode !== \"none\"\n ? { labelMode: ind.labelMode }\n : {}),\n ...(ind.carTypes.length ? { carTypes: ind.carTypes } : {}),\n moduleIndustryId: ind.moduleIndustryId,\n })),\n }\n : {}),\n // Benchwork footprint outline (module-local inches); only when it's a real\n // ring (≥ 3 vertices).\n ...(state.outline.length >= 3 ? { outline: state.outline } : {}),\n // Benchwork hole (donut inner boundary), when it's a real ring.\n ...(state.outlineInner.length >= 3 ? { outlineInner: state.outlineInner } : {}),\n // Internal section joints (inches from A), when the module has more than one.\n ...(state.sectionBreaks.length ? { sectionBreaks: state.sectionBreaks } : {}),\n // Sections as objects — emitted only once the owner has some, so a module\n // that never used them keeps exactly the doc it had before (#96 phase 2).\n ...(state.sections.length ? { sections: moduleSections({ sections: state.sections }) } : {}),\n // Authored mainline path (module-local inches); only when it's a real path.\n ...(state.mainPath.length >= 2 ? { mainPath: state.mainPath } : {}),\n ...(state.main2Path.length >= 2 ? { main2Path: state.main2Path } : {}),\n };\n}\n\n/**\n * Derive editor state from the doc and the module's Track section rows. Tracks\n * are the single source of truth for name/capacity (module_tracks), while the\n * schematic doc adds geometry (lane, positions). We merge: doc tracks first\n * (they carry geometry + their moduleTrackId link), then any module_tracks not\n * yet positioned in the schematic.\n */\nexport function docToState(\n doc: unknown,\n fallbackLength: number,\n moduleTracks: ModuleTrackRow[] = [],\n): EditorState {\n const base = emptyEditorState(fallbackLength);\n const d =\n doc && typeof doc === \"object\" ? (doc as ModuleSchematicDoc) : null;\n const hasDoc = !!d && typeof d.lengthInches === \"number\" && Array.isArray(d.tracks);\n // The module's length is authoritative (the mainline is the module). If the\n // saved doc used a different length, rescale its feature positions to fit so\n // the mainline always reads as the module's true length.\n const len = fallbackLength > 0 ? fallbackLength : hasDoc ? d!.lengthInches! : 24;\n const docLen = hasDoc && d!.lengthInches! > 0 ? d!.lengthInches! : len;\n const scale = docLen > 0 ? len / docLen : 1;\n const sc = (p: number) => Math.round(p * scale);\n\n const nameOf = (id: number | null | undefined): string => {\n const mt = id != null ? moduleTracks.find((m) => m.id === id) : undefined;\n return mt?.track_name ?? \"\";\n };\n\n const extraTracks: EditorTrack[] = [];\n const usedMt = new Set<number>();\n if (hasDoc) {\n for (const t of d!.tracks) {\n if (t.role === \"main\") continue;\n const moduleTrackId = t.moduleTrackId ?? null;\n if (moduleTrackId != null) usedMt.add(moduleTrackId);\n extraTracks.push({\n id: t.id,\n role: (t.role as TrackRole) ?? \"siding\",\n lane: t.lane ?? 1,\n fromPos: sc(t.fromPos ?? 0),\n toPos: t.toPos != null ? sc(t.toPos) : len,\n moduleTrackId,\n trackName: t.trackName ?? nameOf(moduleTrackId),\n ...(t.inLoop ? { inLoop: true } : {}),\n // Authored path kept as-drawn (a physical shape, not rescaled with length).\n ...(trackPath(t.path) ? { path: trackPath(t.path)! } : {}),\n });\n }\n }\n // Link pre-migration doc tracks (no moduleTrackId yet) to unused module_tracks\n // by order — keeping the doc track's id so turnout/signal references stay\n // valid. Only after that do leftover module_tracks become new tracks.\n const unused = moduleTracks.filter((mt) => !usedMt.has(mt.id));\n let ui = 0;\n for (const et of extraTracks) {\n if (et.moduleTrackId == null && ui < unused.length) {\n const mt = unused[ui++];\n et.moduleTrackId = mt.id;\n if (!et.trackName) et.trackName = mt.track_name ?? \"\";\n usedMt.add(mt.id);\n }\n }\n let lane = Math.max(0, ...extraTracks.map((t) => t.lane));\n for (const mt of moduleTracks) {\n if (usedMt.has(mt.id)) continue;\n lane += 1;\n extraTracks.push({\n id: `mt${mt.id}`,\n role: \"siding\",\n lane,\n fromPos: Math.round(len * 0.2),\n toPos: Math.round(len * 0.8),\n moduleTrackId: mt.id,\n trackName: mt.track_name ?? \"\",\n });\n }\n\n if (!hasDoc) return { ...base, lengthInches: len, extraTracks };\n\n const configOf = (id: string): TrackConfig => {\n const ep = (d!.endplates ?? []).find((e) => e.id === id);\n return ep?.tracks?.[0]?.config === \"double\" ? \"double\" : \"single\";\n };\n const loop = isLoopDoc(d!);\n const hasB = (d!.endplates ?? []).some((e) => e.id === \"B\");\n // Branch endplates C, D, … (junction connections, #170).\n const branchEps = (d!.endplates ?? []).filter(\n (e) => e.id !== \"A\" && e.id !== \"B\" && e.at,\n );\n const poseOverrides = poseOverridesFromDoc(d!);\n // Authored endplate face widths by id (unscaled — a cross-track dimension,\n // not a position along the module).\n const endplateWidths: Record<string, number> = {};\n const endplateTrackOffsets: Record<string, number> = {};\n for (const e of d!.endplates ?? []) {\n if (typeof e.widthInches === \"number\" && e.widthInches > 0)\n endplateWidths[e.id] = e.widthInches;\n // Signed, and 0 is meaningful (explicitly centred) — keep any finite value.\n if (typeof e.trackOffsetInches === \"number\" && Number.isFinite(e.trackOffsetInches))\n endplateTrackOffsets[e.id] = e.trackOffsetInches;\n }\n // Benchwork outline — module-local inches, kept as authored (a physical board\n // shape, not rescaled with the mainline length); per-edge bulge preserved.\n const outline = (d!.outline ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n // Benchwork hole (donut inner boundary), kept as authored like the outline.\n const outlineInner = (d!.outlineInner ?? [])\n .filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y))\n .map((p) => ({\n x: p.x,\n y: p.y,\n ...(Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}),\n }));\n // Authored mainline path — kept as drawn (a physical shape, not rescaled).\n const mainPath = trackPath(d!.mainPath) ?? [];\n // Main 2's authored path may sit on the doc top-level or on its track record.\n const main2Track_ = (d!.tracks ?? []).find((t) => t.id === MAIN2_TRACK_ID);\n const main2Path = trackPath(d!.main2Path ?? main2Track_?.path) ?? [];\n return {\n lengthInches: len,\n loop,\n loopReturn: loop && d!.loopReturn === \"main2\" ? \"main2\" : \"same\",\n mainsSwapped: d!.mainsSwapped === true,\n configA: configOf(\"A\"),\n // On a loop, a missing B means pure turnback; present = interchange loop.\n configB: loop && !hasB ? \"none\" : configOf(\"B\"),\n branches: branchEps.map((ep) => ({\n label: ep.label ?? \"Branch\",\n pos: sc(ep.at!.pos),\n side: ep.at!.side === \"down\" ? \"down\" : \"up\",\n config: ep.tracks?.[0]?.config === \"double\" ? \"double\" : \"single\",\n kind: ep.kind === \"main\" ? \"main\" : \"branch\",\n trackId: ep.trackId ?? null,\n })),\n poseOverrides,\n endplateWidths,\n endplateTrackOffsets,\n outline,\n outlineInner,\n sectionBreaks: (d!.sectionBreaks ?? [])\n .filter((n) => Number.isFinite(n))\n .map((n) => sc(n)),\n sections: moduleSections(d),\n mainPath,\n main2Path,\n crossings: (d!.crossings ?? []).map((x) => ({\n id: x.id,\n name: x.name ?? \"\",\n pos: sc(x.pos),\n trackA: x.tracks?.[0] ?? MAIN_TRACK_ID,\n trackB: x.tracks?.[1] ?? MAIN_TRACK_ID,\n })),\n extraTracks,\n turnouts: (d!.turnouts ?? []).map((t) => {\n // Self-heal a turnout that diverges into the track it sits on — a reversed\n // transition left onTrack === divergeTrack after an on-track edit, so it\n // had no second route and the false \"nothing will draw\" warning fired\n // (#172). Repoint it at the OTHER main so it's a valid transition again.\n let divergeTrack = t.divergeTrack;\n if (divergeTrack === t.onTrack) {\n if (t.onTrack === MAIN_TRACK_ID) divergeTrack = MAIN2_TRACK_ID;\n else if (t.onTrack === MAIN2_TRACK_ID) divergeTrack = MAIN_TRACK_ID;\n }\n return {\n id: t.id,\n name: t.name ?? \"\",\n pos: sc(t.pos),\n onTrack: t.onTrack,\n divergeTrack,\n kind: (t.kind as TurnoutKind) ?? \"right\",\n ...(t.size ? { size: t.size } : {}),\n ...(t.curved ? { curved: true } : {}),\n ...(t.flipped ? { flipped: true } : {}),\n };\n }),\n controlPoints: readControlPoints(d!, sc),\n industries: (d!.industries ?? []).map((ind) => ({\n id: ind.id,\n name: ind.name ?? \"\",\n type: ind.type ?? \"\",\n track: ind.track,\n fromPos: sc(ind.fromPos ?? 0),\n toPos: ind.toPos != null ? sc(ind.toPos) : len,\n spots: (ind.spots ?? []).map((s) => ({\n track: s.track,\n fromPos: sc(s.fromPos ?? 0),\n toPos: s.toPos != null ? sc(s.toPos) : len,\n ...(s.side ? { side: s.side as SignalSide } : {}),\n })),\n side: (ind.side as SignalSide) ?? \"above\",\n labelMode: (ind.labelMode as IndustryLabelMode) ?? \"none\",\n carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],\n moduleIndustryId: ind.moduleIndustryId ?? null,\n })),\n };\n}\n\n/** Control points from a doc, migrating pre-grouping flat signals into groups. */\nfunction readControlPoints(\n d: ModuleSchematicDoc,\n sc: (p: number) => number = (p) => p,\n): EditorControlPoint[] {\n if (Array.isArray(d.controlPoints)) {\n return d.controlPoints.map((c) => ({\n id: c.id,\n name: c.name ?? \"\",\n turnouts: c.turnouts ?? [],\n ...(c.crossings?.length ? { crossings: c.crossings } : {}),\n signals: (c.signals ?? []).map((s) => ({\n id: s.id,\n pos: sc(s.pos),\n track: s.track ?? MAIN_TRACK_ID,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: (s.side as SignalSide) ?? \"above\",\n })),\n }));\n }\n // Back-compat: group old flat signals by their turnout (or standalone).\n const groups = new Map<string, EditorControlPoint>();\n let n = 0;\n for (const s of d.signals ?? []) {\n const key = s.turnout || `blk-${s.id}`;\n let cp = groups.get(key);\n if (!cp) {\n cp = { id: `cp${++n}`, name: s.name ?? \"\", turnouts: s.turnout ? [s.turnout] : [], signals: [] };\n groups.set(key, cp);\n }\n cp.signals.push({\n id: s.id,\n pos: sc(s.pos),\n track: s.track ?? MAIN_TRACK_ID,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: (s.side as SignalSide) ?? \"above\",\n });\n }\n return [...groups.values()];\n}\n\n/** Find an unused `${prefix}${n}` id given the ones already present. */\nexport function nextId(prefix: string, existing: string[]): string {\n let n = 1;\n while (existing.includes(`${prefix}${n}`)) n += 1;\n return `${prefix}${n}`;\n}\n\n/**\n * Build a passing siding as one unit: the siding track, a switch at each end,\n * and control-point signals for both directions at each end (prototype Station\n * Entering Signal). Returns the new items to merge into the editor state.\n */\nexport function buildPassingSiding(state: EditorState): {\n track: EditorTrack;\n turnouts: EditorTurnout[];\n controlPoints: EditorControlPoint[];\n} {\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const inset = Math.max(6, Math.round(len * 0.08));\n const fromPos = inset;\n const toPos = Math.max(fromPos + 1, len - inset);\n // First free lane above the main(s): lane 1 is Main 2 on double modules.\n const baseLane =\n state.configA === \"double\" || state.configB === \"double\" ? 2 : 1;\n const lane = Math.max(baseLane, ...state.extraTracks.map((t) => t.lane + 1));\n\n const trackIds = [MAIN_TRACK_ID, ...state.extraTracks.map((t) => t.id)];\n const sidId = nextId(\"sid\", trackIds);\n const track: EditorTrack = {\n id: sidId,\n role: \"siding\",\n lane,\n fromPos,\n toPos,\n moduleTrackId: null,\n trackName: \"Passing siding\",\n };\n\n const swIds = state.turnouts.map((t) => t.id);\n const swW = nextId(\"sw\", swIds);\n const swE = nextId(\"sw\", [...swIds, swW]);\n // A siding above the main throws LEFT at its west turnout (body runs east) and\n // RIGHT at its east turnout (body runs west) — both resolve to the same side,\n // so `kind` and the drawn lane agree (divergeSideForHand / #bug1).\n const turnouts: EditorTurnout[] = [\n { id: swW, name: \"West Siding\", pos: fromPos, onTrack: MAIN_TRACK_ID, divergeTrack: sidId, kind: \"left\" },\n { id: swE, name: \"East Siding\", pos: toPos, onTrack: MAIN_TRACK_ID, divergeTrack: sidId, kind: \"right\" },\n ];\n\n // One control point at each end, each grouping its switch and both-direction\n // signals on the main (prototype Station Entering Signal).\n const cpIds = state.controlPoints.map((c) => c.id);\n const cpW = nextId(\"cp\", cpIds);\n const cpE = nextId(\"cp\", [...cpIds, cpW]);\n const sig = (cpId: string, pos: number, facing: SignalFacing): EditorCpSignal => ({\n id: `${cpId}-${facing}`,\n pos,\n track: MAIN_TRACK_ID,\n facing,\n // opposite directions on opposite sides so they never overlap\n side: facing === \"AtoB\" ? \"above\" : \"below\",\n });\n const controlPoints: EditorControlPoint[] = [\n { id: cpW, name: \"West Siding\", turnouts: [swW], signals: [sig(cpW, fromPos, \"AtoB\"), sig(cpW, fromPos, \"BtoA\")] },\n { id: cpE, name: \"East Siding\", turnouts: [swE], signals: [sig(cpE, toPos, \"AtoB\"), sig(cpE, toPos, \"BtoA\")] },\n ];\n\n return { track, turnouts, controlPoints };\n}\n\n/**\n * Build a crossover as one unit: a short connector track between Main 1 and\n * Main 2, with a turnout on each main. The two turnouts sit on different lanes,\n * so the feature resolver draws it as a diagonal (not a lane-paralleling siding)\n * — this is what connects the two dots (#bug2). Needs a double-track module.\n */\nexport function buildCrossover(state: EditorState): {\n track: EditorTrack;\n turnouts: EditorTurnout[];\n} | null {\n const hasSecond = state.configA === \"double\" || state.configB === \"double\";\n if (state.loop || !hasSecond) return null;\n const len = state.lengthInches > 0 ? state.lengthInches : 24;\n const mid = Math.round(len / 2);\n const gap = Math.max(3, Math.round(len * 0.04));\n const w = Math.round(mid - gap / 2);\n const e = Math.round(mid + gap / 2);\n\n const trackIds = [MAIN_TRACK_ID, MAIN2_TRACK_ID, ...state.extraTracks.map((t) => t.id)];\n const xoId = nextId(\"xo\", trackIds);\n const track: EditorTrack = {\n id: xoId,\n role: \"crossover\",\n lane: 1,\n fromPos: w,\n toPos: e,\n moduleTrackId: null,\n trackName: \"Crossover\",\n };\n\n const swIds = state.turnouts.map((t) => t.id);\n const sw1 = nextId(\"sw\", swIds);\n const sw2 = nextId(\"sw\", [...swIds, sw1]);\n const turnouts: EditorTurnout[] = [\n { id: sw1, name: \"Crossover\", pos: w, onTrack: MAIN_TRACK_ID, divergeTrack: xoId, kind: \"left\" },\n { id: sw2, name: \"Crossover\", pos: e, onTrack: MAIN2_TRACK_ID, divergeTrack: xoId, kind: \"right\" },\n ];\n\n return { track, turnouts };\n}\n\n// ---- Pure feature resolver (both renderers draw these) --------------------\n\nexport interface DrawTrack {\n id: string;\n role: TrackRole;\n lane: number;\n fromFrac: number;\n toFrac: number;\n capacityFeet: number | null;\n /** Lane of the main this track diverges from (via its turnout) — the origin\n * of the diverge diagonal. A spur off Main 2 starts at lane 1, not lane 0;\n * without this, renderers draw what looks like a crossover. */\n divergesFromLane: number;\n /** The end that meets the main at its turnout (throat) and the far stub end,\n * as fractions of length. Direction-preserving: unlike fromFrac/toFrac (always\n * sorted West→East), these keep WHICH end joins, so an east-facing spur draws\n * its throat on the east. A siding meets the main at both ends — there\n * throat=fromFrac, stub=toFrac (the fields are only meaningful for spurs). */\n throatFrac: number;\n stubFrac: number;\n /** Inside the balloon of a loop module (#165). */\n inLoop: boolean;\n}\nexport interface DrawTurnout {\n id: string;\n name: string;\n posFrac: number;\n onLane: number;\n divergeLane: number;\n}\nexport interface DrawSignal {\n id: string;\n name: string;\n posFrac: number;\n lane: number;\n facing: SignalFacing;\n side: SignalSide;\n /** Owning control point's id, when the signal came from a CP group — lets a\n * renderer join the drawn signal back to interlocking-level state (aspects). */\n cp?: string;\n /** 0-based rank among signals that would otherwise land on the exact same\n * spot (same lane + side + position). Renderers offset each further from the\n * track by `stack` so a control point's signals never overlap. */\n stack: number;\n}\n/** A grade crossing / diamond — draw an X spanning the two lanes (#170). */\nexport interface DrawCrossing {\n id: string;\n name: string;\n posFrac: number;\n laneA: number;\n laneB: number;\n}\n/** A crossover — a connector track joining two parallel mains through a turnout\n * on each. Draw a straight diagonal between the two turnout points (unlike a\n * siding, which parallels a lane between its turnouts). Detected structurally:\n * a track whose turnouts sit on two different lanes. */\nexport interface DrawCrossover {\n id: string;\n name: string;\n fromPosFrac: number;\n fromLane: number;\n toPosFrac: number;\n toLane: number;\n}\n/** A branch endplate — draw a connector stub + arrow + label off the given\n * side (the CATS/US&S off-band idiom, #170). */\nexport interface BranchConnector {\n id: string;\n label: string;\n posFrac: number;\n side: \"up\" | \"down\";\n}\n/** An industry — draw a car-spot span beside its track's lane, on `side`, with\n * a name label + an optional car/length readout (#industries). */\nexport interface DrawIndustry {\n id: string;\n name: string;\n type: string | null;\n /** Span as fractions of module length (sorted West→East). */\n fromFrac: number;\n toFrac: number;\n /** Lane of the track it spots on, so it draws beside the right track. */\n lane: number;\n side: SignalSide;\n labelMode: IndustryLabelMode;\n /** Cars that spot here, derived from the drawn span length. */\n cars: number;\n carTypes: string[];\n}\nexport interface ModuleFeatures {\n /** Whether either endplate declares a double-track main. */\n doubleMain: boolean;\n /** Balloon loop — draw a terminal bulb at the far end. */\n loop: boolean;\n /** Loop with a standard endplate B on the balloon: an interchange — a\n * second route connects at the loop (draw an endplate branch off the bulb). */\n loopInterchange: boolean;\n /** Where the balloon returns: \"main2\" = directional return on a double-track\n * main — draw a U joining lanes 0 and 1 instead of the bulb (#165). */\n loopReturn: \"same\" | \"main2\";\n /** Rendering override from the doc; renderers may ignore modes they don't\n * implement yet (\"geometric\"). */\n loopRender: \"bulb\" | \"fan\" | \"geometric\" | null;\n /** Non-main tracks (sidings/spurs/yard/crossover). */\n extraTracks: DrawTrack[];\n turnouts: DrawTurnout[];\n signals: DrawSignal[];\n /** Grade crossings / diamonds (#170). */\n crossings: DrawCrossing[];\n /** Crossovers — connector tracks between two mains (drawn as a diagonal). */\n crossovers: DrawCrossover[];\n /** Branch endplates — junction connectors off the module (#170). */\n branchConnectors: BranchConnector[];\n /** Rail-served industries — car-spot spans beside their track (#industries). */\n industries: DrawIndustry[];\n /** Main 2's extent when it doesn't run the full module — a single↔double\n * transition (Main 2 starts/ends at the mainline turnout). Null = full\n * length (or no Main 2). Renderers draw the partial line + its diverge. */\n main2Extent: { fromFrac: number; toFrac: number } | null;\n /** Main 2's drawn lane — +1 above Main 1 by default, −1 below when the mains\n * are swapped (#131/#172). Null when there is no Main 2. Renderers must draw\n * Main 2 (and its diverges) at THIS lane, never a hard-coded +1. */\n main2Lane: number | null;\n /** Single↔double transition, fully described (#FMN-0043). The `through` main\n * runs the whole module; the `branch` main exists only on the double side and\n * merges at `atFrac`. EITHER main can be through/branch — the surviving single\n * track follows the transition turnout's onTrack, so the drawn side isn't\n * hard-wired to Main 1. Null when not a transition. */\n transition: {\n throughLane: number;\n branchLane: number;\n atFrac: number;\n doubleSide: \"west\" | \"east\";\n } | null;\n /** Lane extents across every feature (mains included; negative = outside\n * Main 1). Renderers size their vertical space from these. */\n laneMin: number;\n laneMax: number;\n}\n\n/**\n * Which side of the main a diverging track draws on, given the turnout's HAND\n * and the direction the track body runs along the main from the turnout\n * (`stubDir`: +1 = the body extends east / toward B, −1 = west / toward A).\n * Returns +1 (above the main) or −1 (below); 0 for a wye or unset hand (keep the\n * authored side). A left-hand turnout throws its route to the same side its body\n * runs (facing the frog, left is the inside of a body running that way); a\n * right-hand throws to the opposite side. `kind` is the source of truth for the\n * drawn side (#bug1) — the stored lane's sign is reconciled to match it.\n */\nexport function divergeSideForHand(\n kind: TurnoutKind | undefined,\n stubDir: number,\n /** The turnout is installed the other way round — the points face the far\n * direction, which swaps the side the diverging route leaves on. */\n flipped?: boolean | null,\n): -1 | 0 | 1 {\n if (kind !== \"left\" && kind !== \"right\") return 0; // wye / unset → no change\n const s = (stubDir >= 0 ? 1 : -1) * (flipped ? -1 : 1);\n return kind === \"left\" ? (s as 1 | -1) : ((-s) as 1 | -1);\n}\n\n/**\n * Resolve a schematic doc into positioned drawables. `pos` (inches) becomes a\n * fraction of the module length; endplate A = 0, B = length; turnouts sit at\n * their pos. Tracks may carry explicit fromPos/toPos (overriding node lookup).\n * To-scale: a feature renders at its true position, clamped only to the\n * module's own extent — so signals near an end read at their real spot, not\n * bunched at an inset (#122).\n */\nexport function moduleFeatures(doc: ModuleSchematicDoc): ModuleFeatures {\n const len =\n doc.lengthInches && doc.lengthInches > 0\n ? doc.lengthInches\n : Math.max(\n 1,\n ...doc.tracks.map((t) => Math.max(t.fromPos ?? 0, t.toPos ?? 0)),\n ...(doc.turnouts ?? []).map((t) => t.pos),\n );\n const clampFrac = (p: number) => Math.min(1, Math.max(0, p / len));\n\n const trackLane = new Map<string, number>();\n for (const t of doc.tracks) trackLane.set(t.id, t.lane);\n\n // Endplate positions: first endplate = West (0), the rest = East (len).\n const endplatePos = new Map<string, number>();\n doc.endplates.forEach((e, i) => endplatePos.set(e.id, i === 0 ? 0 : len));\n const turnoutPos = new Map<string, number>();\n for (const t of doc.turnouts ?? []) turnoutPos.set(t.id, t.pos);\n const posOf = (nodeId?: string): number | null => {\n if (nodeId == null) return null;\n if (endplatePos.has(nodeId)) return endplatePos.get(nodeId)!;\n if (turnoutPos.has(nodeId)) return turnoutPos.get(nodeId)!;\n return null;\n };\n\n const doubleMain = doc.endplates.some((e) =>\n e.tracks?.some((t) => t.config === \"double\"),\n );\n\n // The lane a track diverges from = the main its turnout sits on.\n const divergeOrigin = (trackId: string): number => {\n const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === trackId);\n return sw ? (trackLane.get(sw.onTrack) ?? 0) : 0;\n };\n\n // Turnouts grouped by the track they diverge onto (a track's throat/hand).\n const turnoutsByTrack = new Map<string, SchematicTurnout[]>();\n for (const sw of doc.turnouts ?? []) {\n const arr = turnoutsByTrack.get(sw.divergeTrack) ?? [];\n arr.push(sw);\n turnoutsByTrack.set(sw.divergeTrack, arr);\n }\n // A crossover is a connector whose turnouts sit on two different lanes (one on\n // each main) — drawn as a diagonal between them, never as a lane-paralleling\n // siding. A passing siding's two turnouts share one lane, so it isn't one.\n const isCrossover = (trackId: string): boolean => {\n const sws = turnoutsByTrack.get(trackId) ?? [];\n if (sws.length < 2) return false;\n return new Set(sws.map((s) => trackLane.get(s.onTrack) ?? 0)).size >= 2;\n };\n // The in-inches extent of a track (explicit fromPos/toPos or node lookup).\n const extentOf = (t: SchematicTrack): [number, number] | null => {\n const from = t.fromPos ?? posOf(t.from);\n const to = t.toPos ?? posOf(t.to);\n return from == null || to == null ? null : [from, to];\n };\n\n // Reconcile each diverging track's drawn SIDE from its turnout's hand — `kind`\n // is the source of truth (#bug1) — resolved TOPOLOGICALLY. The hand only picks\n // a side for a turnout sitting on the main CENTERLINE (lane 0); a track\n // diverging off any other track (Main 2, or a ladder rung) stays on its\n // PARENT's side and stacks outward — a ladder turnout's hand is relative to\n // its parent, not the main, so it must never flip a rung across the main. The\n // stored lane's magnitude (stacking slot) is always kept.\n const trackById = new Map(doc.tracks.map((t) => [t.id, t]));\n const resolvedLanes = new Map<string, number>();\n const resolving = new Set<string>();\n const resolveLane = (id: string): number => {\n const trk = trackById.get(id);\n if (!trk) return 0;\n if (trk.role === \"main\") return trk.lane; // mains are fixed (0, 1, …)\n if (resolvedLanes.has(id)) return resolvedLanes.get(id)!;\n if (resolving.has(id)) return trk.lane; // cycle guard\n resolving.add(id);\n let lane = trk.lane;\n const sw = turnoutsByTrack.get(id)?.[0];\n const ext = extentOf(trk);\n if (sw && (sw.kind === \"left\" || sw.kind === \"right\") && !isCrossover(id) && ext) {\n const parentLane = resolveLane(sw.onTrack);\n let sign: number;\n if (parentLane === 0) {\n // On the main centerline — the hand chooses above/below.\n const [from, to] = ext;\n const far = Math.abs(to - sw.pos) >= Math.abs(from - sw.pos) ? to : from;\n const s = divergeSideForHand(sw.kind, far - sw.pos);\n sign = s !== 0 ? s : Math.sign(trk.lane) || 1;\n } else {\n // Off Main 2 / a ladder rung — follow the parent's side.\n sign = Math.sign(parentLane) || 1;\n }\n lane = sign * Math.abs(trk.lane);\n }\n resolving.delete(id);\n resolvedLanes.set(id, lane);\n return lane;\n };\n for (const t of doc.tracks) {\n if (t.role === \"main\") continue;\n trackLane.set(t.id, resolveLane(t.id));\n }\n\n const extraTracks: DrawTrack[] = [];\n for (const t of doc.tracks) {\n if (t.role === \"main\") continue; // the spine draws mains\n // A branch route to a placed endplate (#170) leaves the main at 90° — it\n // can't be drawn in this straightened, positional view, and the endplate it\n // reaches already shows as a labelled connector arrow. The physical view\n // draws its real authored path; here it would only smear a degenerate stub.\n if (t.role === \"branch\") continue;\n if (isCrossover(t.id)) continue; // crossovers draw as diagonals, below\n const ext = extentOf(t);\n if (!ext) continue; // can't place it\n const [from, to] = ext;\n // Throat = the end nearest this track's turnout (the join to the main);\n // with no turnout, keep entry order (from = throat) so the author's chosen\n // joining end is honoured. This is what makes an east-facing spur draw its\n // throat on the east instead of always west (#bug3).\n const sw = turnoutsByTrack.get(t.id)?.[0];\n const throatAtTo = sw != null && Math.abs(to - sw.pos) < Math.abs(from - sw.pos);\n const throat = throatAtTo ? to : from;\n const stub = throatAtTo ? from : to;\n extraTracks.push({\n id: t.id,\n role: t.role,\n lane: trackLane.get(t.id) ?? t.lane,\n fromFrac: clampFrac(Math.min(from, to)),\n toFrac: clampFrac(Math.max(from, to)),\n throatFrac: clampFrac(throat),\n stubFrac: clampFrac(stub),\n capacityFeet: t.capacityFeet ?? null,\n divergesFromLane: divergeOrigin(t.id),\n inLoop: t.inLoop === true,\n });\n }\n\n // Crossovers — a diagonal between two parallel mains. Two shapes are drawn:\n const crossovers: DrawCrossover[] = [];\n // (1) a dedicated connector track (buildCrossover) with a turnout on each main.\n for (const t of doc.tracks) {\n if (!isCrossover(t.id)) continue;\n const [s1, s2] = turnoutsByTrack.get(t.id)!;\n crossovers.push({\n id: t.id,\n name: t.trackName ?? \"\",\n fromPosFrac: clampFrac(s1.pos),\n fromLane: trackLane.get(s1.onTrack) ?? 0,\n toPosFrac: clampFrac(s2.pos),\n toLane: trackLane.get(s2.onTrack) ?? 1,\n });\n }\n // (2) modelled as two turnouts each diverging onto the OTHER main (no connector\n // track). Pair a leg with its return leg and connect the two turnout points.\n // A single↔double TRANSITION turnout also connects the two mains but isn't a\n // crossover (Main 2 ends there) — exclude it, and require a matching return\n // leg so a lone main-to-main turnout is never drawn as a crossover.\n const isMainId = (id?: string) => !!id && trackById.get(id)?.role === \"main\";\n const epDouble = (id: string) =>\n (doc.endplates.find((e) => e.id === id)?.tracks ?? []).some(\n (t) => t.config === \"double\",\n );\n const aDbl = epDouble(\"A\");\n const bDbl = epDouble(\"B\");\n const transitionSw =\n aDbl !== bDbl ? (doc.turnouts ?? []).find(isTransitionTurnout) : undefined;\n const m2m = (doc.turnouts ?? []).filter(\n (sw) =>\n sw !== transitionSw &&\n isMainId(sw.onTrack) &&\n isMainId(sw.divergeTrack) &&\n (trackLane.get(sw.onTrack) ?? 0) !== (trackLane.get(sw.divergeTrack) ?? 1),\n );\n const usedLegs = new Set<string>();\n for (const t1 of m2m) {\n if (usedLegs.has(t1.id)) continue;\n const t2 = m2m.find(\n (x) =>\n !usedLegs.has(x.id) &&\n x.id !== t1.id &&\n x.onTrack === t1.divergeTrack &&\n x.divergeTrack === t1.onTrack,\n );\n if (!t2) continue; // lone leg → a transition/junction, not a crossover\n usedLegs.add(t1.id);\n usedLegs.add(t2.id);\n crossovers.push({\n id: `${t1.id}-${t2.id}`,\n name: t1.name ?? t2.name ?? \"\",\n fromPosFrac: clampFrac(t1.pos),\n fromLane: trackLane.get(t1.onTrack) ?? 0,\n toPosFrac: clampFrac(t2.pos),\n toLane: trackLane.get(t2.onTrack) ?? 1,\n });\n }\n\n const turnouts: DrawTurnout[] = (doc.turnouts ?? []).map((t) => ({\n id: t.id,\n name: t.name ?? \"\",\n posFrac: clampFrac(t.pos),\n onLane: trackLane.get(t.onTrack) ?? 0,\n divergeLane: trackLane.get(t.divergeTrack) ?? 1,\n }));\n\n const drawSignal = (\n s: SchematicSignal,\n name: string,\n cp?: string,\n ): DrawSignal => ({\n id: s.id,\n name,\n posFrac: clampFrac(s.pos),\n lane: s.track ? (trackLane.get(s.track) ?? 0) : 0,\n facing: (s.facing as SignalFacing) ?? \"AtoB\",\n side: s.side === \"below\" ? \"below\" : \"above\",\n ...(cp ? { cp } : {}),\n stack: 0,\n });\n // Signals come from control-point groups; fall back to pre-grouping flat\n // signals for docs authored before the model changed.\n const signals: DrawSignal[] = Array.isArray(doc.controlPoints)\n ? doc.controlPoints.flatMap((c) =>\n (c.signals ?? []).map((s) => drawSignal(s, c.name ?? \"\", c.id)),\n )\n : (doc.signals ?? []).map((s) => drawSignal(s, s.name ?? \"\"));\n // De-collide: signals landing on the exact same lane+side+position get a\n // rising stack rank so a renderer can fan them out (a control point often\n // carries several signals at one interlocking).\n const stackCount = new Map<string, number>();\n for (const s of signals) {\n const key = `${s.lane}|${s.side}|${Math.round(s.posFrac * 1000)}`;\n const n = stackCount.get(key) ?? 0;\n s.stack = n;\n stackCount.set(key, n + 1);\n }\n\n const crossings: DrawCrossing[] = (doc.crossings ?? []).map((x) => ({\n id: x.id,\n name: x.name ?? \"\",\n posFrac: clampFrac(x.pos),\n laneA: trackLane.get(x.tracks?.[0] ?? \"\") ?? 0,\n laneB: trackLane.get(x.tracks?.[1] ?? \"\") ?? 1,\n }));\n\n // Branch endplates → connector arrows in the operating view — but ONLY once a\n // route actually reaches one. Placing a bare 3rd+ endplate must not conjure a\n // junction arrow; the arrow follows the drawn branch track that links to it\n // (its trackId), so it appears when you connect track, not when you add the\n // endplate (#170).\n const branchConnectors: BranchConnector[] = doc.endplates\n .filter(\n (e) =>\n e.id !== \"A\" &&\n e.id !== \"B\" &&\n e.at &&\n !!e.trackId &&\n (doc.tracks ?? []).some((t) => t.id === e.trackId),\n )\n .map((e) => {\n // The branch leaves the main at its FEEDING turnout, not the endplate's\n // own along-axis spot — draw it there so it meets the main where it really\n // diverges (the endplate can sit well off to one side, #170).\n const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === e.trackId);\n return {\n id: e.id,\n label: e.label ?? e.id,\n posFrac: clampFrac(sw ? sw.pos : e.at!.pos),\n side: e.at!.side === \"down\" ? \"down\" : \"up\",\n };\n });\n\n // Industries — car-spot spans beside the track they serve.\n const industries: DrawIndustry[] = (doc.industries ?? []).flatMap((ind) => {\n // Each spot (the primary track + any house-track spots) draws beside its\n // own track; they share the industry's name, type and car types (#54).\n const spots = [\n { track: ind.track, fromPos: ind.fromPos, toPos: ind.toPos, side: ind.side },\n ...(ind.spots ?? []),\n ];\n return spots.map((sp, i) => {\n const from = sp.fromPos ?? 0;\n const to = sp.toPos ?? len;\n return {\n id: i === 0 ? ind.id : `${ind.id}-s${i}`,\n name: ind.name ?? \"\",\n type: ind.type ?? null,\n fromFrac: clampFrac(Math.min(from, to)),\n toFrac: clampFrac(Math.max(from, to)),\n lane: trackLane.get(sp.track) ?? 0,\n side: (sp.side as SignalSide) ?? \"above\",\n labelMode: (ind.labelMode as IndustryLabelMode) ?? \"none\",\n cars: carCapacity(from, to),\n carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],\n };\n });\n });\n\n // Main 2's actual drawn lane — −1 (below) when the mains are swapped, +1\n // otherwise. Sizing the canvas off a hard-coded +1 clipped a swapped Main 2 at\n // the bottom (#172); the renderer likewise must draw it here, not at +1.\n const main2Lane = trackLane.has(MAIN2_TRACK_ID)\n ? (trackLane.get(MAIN2_TRACK_ID) as number)\n : null;\n const allLanes = [\n 0,\n main2Lane ?? (doubleMain ? 1 : 0),\n ...extraTracks.map((t) => t.lane),\n ...signals.map((s) => s.lane),\n ...crossings.flatMap((x) => [x.laneA, x.laneB]),\n ...crossovers.flatMap((x) => [x.fromLane, x.toLane]),\n ];\n const loop = isLoopDoc(doc);\n // A positioned Main 2 = a transition module (partial second main).\n const main2 = doc.tracks.find((t) => t.id === MAIN2_TRACK_ID);\n const main2Positioned =\n !!main2 && (main2.fromPos != null || main2.toPos != null) && !loop;\n let main2Extent: { fromFrac: number; toFrac: number } | null = null;\n if (main2Positioned) {\n main2Extent = {\n fromFrac: clampFrac(main2!.fromPos ?? 0),\n toFrac: clampFrac(main2!.toPos ?? len),\n };\n } else if (\n main2 &&\n transitionSw &&\n transitionSw.divergeTrack === MAIN2_TRACK_ID &&\n !loop\n ) {\n // Main 2 is the branch but stored full-length — derive its extent from the\n // junction. (When Main 2 is the through main, it stays full: extent null.)\n main2Extent = aDbl\n ? { fromFrac: 0, toFrac: clampFrac(transitionSw.pos) } // double at west\n : { fromFrac: clampFrac(transitionSw.pos), toFrac: 1 }; // double at east\n }\n // Full transition descriptor: the surviving (through) main follows the\n // turnout's onTrack, so either main can be the one that ends (#FMN-0043).\n const transition =\n transitionSw && aDbl !== bDbl && !loop\n ? {\n throughLane: trackLane.get(transitionSw.onTrack) ?? 0,\n branchLane: trackLane.get(transitionSw.divergeTrack) ?? 1,\n atFrac: clampFrac(transitionSw.pos),\n doubleSide: (aDbl ? \"west\" : \"east\") as \"west\" | \"east\",\n }\n : null;\n return {\n doubleMain,\n loop,\n main2Extent,\n main2Lane,\n transition,\n loopInterchange: loop && doc.endplates.filter((e) => !e.at).length >= 2,\n loopReturn: loop && doc.loopReturn === \"main2\" ? \"main2\" : \"same\",\n loopRender: loop ? (doc.loopRender ?? null) : null,\n extraTracks,\n turnouts,\n signals,\n crossings,\n crossovers,\n branchConnectors,\n industries,\n laneMin: Math.min(...allLanes),\n laneMax: Math.max(...allLanes),\n };\n}\n\n// ---- Endplate geometry & poses (#175) --------------------------------------\n//\n// Free-moN endplates are one standard interface; a single (x, y, heading) at\n// the track-crossing point fully determines mating (any endplate ↔ any\n// compatible endplate). Poses are in MODULE-LOCAL inches: endplate A's track\n// point at the origin, its OUTWARD normal pointing west (180°), so the module\n// body runs toward +X. A layout composes modules by walking joins and stacking\n// each pose's rigid transform (rotation + optional reflection for flips).\n//\n// Poses are DERIVED from the simple fields owners already enter — length +\n// geometry type/degrees/offset for the two axial endplates, plus the schematic\n// doc's branch endplates (#170). Complex shapes (wye, loop, other) fall back to\n// hand-entered overrides. Nothing is stored unless overridden.\n\nexport type GeometryType =\n | \"straight\"\n | \"corner_45\"\n | \"corner_90\"\n | \"curve\"\n | \"offset\"\n | \"dead_end\"\n | \"wye\"\n | \"other\";\n\nexport interface EndplatePose {\n /** Endplate id — \"A\"/\"B\" axial, \"C\"/\"D\"… branch. */\n id: string;\n /** Module-local inches; endplate A's track point is the origin. */\n x: number;\n y: number;\n /** Outward normal in degrees (0 = +X east, 90 = +Y north). A neighbour mates\n * facing the opposite heading. */\n heading: number;\n trackConfig: \"single\" | \"double\";\n /** Lateral track offsets from the crossing anchor (0 = centred single). */\n trackOffsets: number[];\n /** True when the pose was hand-entered, not derived (wye/loop/other). */\n manual?: boolean;\n}\n\nexport type ReturnLoopShape = \"circle\" | \"teardrop\" | \"offset-teardrop\" | \"square\";\n\n/** A computed return-loop: a mainline LEAD to the throat, a WYE that splits into\n * two legs, and the LOOP track those legs form, closing back at the throat. Pure\n * geometry, module-local inches, endplate A at the origin, lead heading +x. All\n * shapes are built so the loop CLOSES exactly at the throat and the two wye legs\n * diverge symmetrically about the lead — the piece the earlier eyeballed versions\n * kept getting wrong (#loop). */\nexport interface ReturnLoopGeometry {\n throat: BenchworkPoint;\n /** The loop track, throat → around → throat (starts and ends at the throat). */\n loop: BenchworkPoint[];\n /** The two diverging wye legs at the throat (each throat → its tangent point). */\n wyeLegs: [BenchworkPoint[], BenchworkPoint[]];\n /** Half the angle between the two wye legs, degrees (0 = tangent/no wye). */\n wyeHalfAngleDeg: number;\n /** Benchwork fascia: outer boundary, and an inner boundary for a donut (empty\n * when the board is solid). */\n outlineOuter: BenchworkPoint[];\n outlineInner: BenchworkPoint[];\n}\n\nexport function returnLoop(\n shape: ReturnLoopShape,\n opts: {\n leadInches: number;\n radius: number;\n /** Half-width of the board UNDER the loop track (the donut ring), inches. */\n boardHalfWidth?: number;\n /** Half the endplate face width, inches. The lead/interface board is sized to\n * this so the benchwork is never narrower than the endplate (Free-moN §2.0);\n * the track crosses the endplate centred on a full-width board. */\n endplateHalfWidth?: number;\n },\n): ReturnLoopGeometry {\n const L = Math.max(1, opts.leadInches);\n const R = Math.max(1, opts.radius);\n // Two widths: the ring under the loop track, and the lead/interface board — the\n // latter at least the endplate half-width, so benchwork ≥ endplate at the face.\n const hw = Math.min(opts.boardHalfWidth ?? 6, R - 1); // ring half-width (keeps a hole)\n const leadHalf = Math.max(hw, opts.endplateHalfWidth ?? hw);\n const T: BenchworkPoint = { x: L, y: 0 };\n const r2 = (v: number) => Math.round(v * 100) / 100;\n const rd = (pts: BenchworkPoint[]) => pts.map((p) => ({ x: r2(p.x), y: r2(p.y) }));\n const arc = (cx: number, cy: number, r: number, a0: number, a1: number, steps: number) => {\n const out: BenchworkPoint[] = [];\n for (let i = 0; i <= steps; i++) out.push({ x: cx + r * Math.cos(a0 + ((a1 - a0) * i) / steps), y: cy + r * Math.sin(a0 + ((a1 - a0) * i) / steps) });\n return out;\n };\n\n // circle / teardrop / offset-teardrop / square: the LOOP TRACK is always a\n // proper circle whose centre C sits ahead of the throat — real track can't turn\n // a square corner, so a \"square\" module is a curved loop inside a square board,\n // never a square track. The wye legs are the two tangent lines from the throat\n // to the circle; the loop is the MAJOR (far) arc between the tangent points, so\n // the legs diverge symmetrically (the wye) and the loop closes at the throat.\n const D = shape === \"circle\" || shape === \"square\" ? R * 1.15 : R * 1.6; // throat → centre\n const offY = shape === \"offset-teardrop\" ? R * 0.7 : 0;\n const C = { x: L + D, y: offY };\n const dist = Math.hypot(C.x - T.x, C.y - T.y);\n const ac = Math.acos(Math.min(1, R / dist)); // tangent-point angle at C\n const base = Math.atan2(T.y - C.y, T.x - C.x); // C → T\n const a1 = base + ac; // upper tangent point angle (at C)\n const a2 = base - ac; // lower\n const P1 = { x: C.x + R * Math.cos(a1), y: C.y + R * Math.sin(a1) };\n const P2 = { x: C.x + R * Math.cos(a2), y: C.y + R * Math.sin(a2) };\n // loop: throat → P1 (leg) → major arc → P2 → throat (leg)\n const loop = [T, P1, ...arc(C.x, C.y, R, a1, a2 + 2 * Math.PI, 64).slice(1), T];\n // wye half-angle: angle between the two legs (T→P1, T→P2), halved\n const legDir = (P: BenchworkPoint) => Math.atan2(P.y - T.y, P.x - T.x);\n const half = Math.abs(((legDir(P1) - legDir(P2) + Math.PI) % (2 * Math.PI)) - Math.PI) / 2;\n\n // Donut benchwork: outer ring (R+hw) and inner ring (R-hw) around C, the outer\n // meeting the lead's edges. Inner hole = the open middle of the loop.\n const ringOuter = (rr: number) => {\n // The lead/interface board runs at ±leadHalf (≥ the endplate) until it meets\n // the outer ring; the ring itself is radius rr. Using leadHalf here is what\n // keeps the benchwork at least as wide as the endplate at the face.\n const xTop = C.x - Math.sqrt(Math.max(0, rr * rr - (leadHalf - C.y) ** 2));\n const xBot = C.x - Math.sqrt(Math.max(0, rr * rr - (-leadHalf - C.y) ** 2));\n const tTop = Math.atan2(leadHalf - C.y, xTop - C.x);\n const tBot = Math.atan2(-leadHalf - C.y, xBot - C.x);\n // Sweep CLOCKWISE from tTop down to tBot (the FAR arc, away from the lead\n // notch) as a SINGLE traversal. A fixed `tBot − 2π` double-wraps the circle\n // when tTop/tBot straddle ±π (the symmetric shapes), which a solid fill hides\n // but an even-odd donut fill inverts. Normalise instead so 0 > sweep > −2π.\n let end = tBot;\n while (end >= tTop) end -= 2 * Math.PI;\n return [\n { x: 0, y: leadHalf },\n { x: xTop, y: leadHalf },\n ...arc(C.x, C.y, rr, tTop, end, 48).slice(1, -1),\n { x: xBot, y: -leadHalf },\n { x: 0, y: -leadHalf },\n ];\n };\n const Ri = R - hw;\n\n // A \"square\" module frames that same circular loop in a SQUARE DONUT: a\n // rectangular loop board (a lead strip + a square around the circle) with a\n // square hole in the open middle. The hole's corners are kept inside the track\n // circle (half-diagonal ≤ R − hw) so the board is at least hw wide under the rail.\n if (shape === \"square\") {\n const xL = C.x - R - hw; // square board's left edge\n const xR = C.x + R + hw; // right edge\n const yT = R + hw;\n // Lead/interface strip at ±leadHalf (≥ the endplate) sticking out of the square.\n const outerSquare = [\n { x: 0, y: leadHalf },\n { x: xL, y: leadHalf },\n { x: xL, y: yT },\n { x: xR, y: yT },\n { x: xR, y: -yT },\n { x: xL, y: -yT },\n { x: xL, y: -leadHalf },\n { x: 0, y: -leadHalf },\n ];\n const iHalf = (R - hw) / Math.SQRT2; // inner-square half-side (corners inside R)\n const holeSquare =\n iHalf > 2\n ? [\n { x: C.x - iHalf, y: iHalf },\n { x: C.x + iHalf, y: iHalf },\n { x: C.x + iHalf, y: -iHalf },\n { x: C.x - iHalf, y: -iHalf },\n ]\n : [];\n return {\n throat: T,\n loop: rd(loop),\n wyeLegs: [rd([T, P1]), rd([T, P2])],\n wyeHalfAngleDeg: r2((half * 180) / Math.PI),\n outlineOuter: rd(outerSquare),\n outlineInner: rd(holeSquare),\n };\n }\n\n return {\n throat: T,\n loop: rd(loop),\n wyeLegs: [rd([T, P1]), rd([T, P2])],\n wyeHalfAngleDeg: r2((half * 180) / Math.PI),\n outlineOuter: rd(ringOuter(R + hw)),\n outlineInner: Ri > 2 ? rd(arc(C.x, C.y, Ri, 0, 2 * Math.PI, 40)) : [],\n };\n}\n\nexport interface ModuleGeometryInput {\n lengthInches: number;\n geometryType?: string | null;\n geometryDegrees?: number | null;\n geometryOffsetInches?: number | null;\n /** Axial endplate configs (A first, then B). Missing → single. */\n endplateConfigs?: (\"single\" | \"double\" | null | undefined)[];\n /** Branch endplates (from the schematic doc, #170), positioned along the\n * mainline axis. */\n branches?: {\n id: string;\n atPos: number;\n side: \"up\" | \"down\";\n config?: \"single\" | \"double\" | null;\n }[];\n /** Hand-entered pose overrides by endplate id — win over derivation. */\n poseOverrides?: Record<string, { x: number; y: number; heading: number }>;\n /** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1\",\n * Free-moN ≈ 9/16\"). */\n trackHalfSpacingInches?: number;\n /** The module's sections. When present they define the module's real shape,\n * so endplate B lands at the end of the CHAINED boards rather than where a\n * single module-level geometry would have put it (#108). */\n sections?: SchematicSection[] | null;\n /** A balloon / return loop: the main runs out and turns back on itself, so the\n * module has ONE endplate (A). No far endplate B is derived — the chain closes\n * back near the throat, and a B there would just be a spurious plate on the\n * loop. An interchange endplate on the balloon is placed separately (#loop). */\n loop?: boolean;\n}\n\n/** Signed turn a module applies to the through track (CCW/left positive). */\nexport function geometryTurnDegrees(\n geometryType?: string | null,\n geometryDegrees?: number | null,\n): number {\n switch (geometryType) {\n case \"corner_45\":\n return 45;\n case \"corner_90\":\n return 90;\n case \"curve\":\n return geometryDegrees ?? 0;\n default:\n return 0;\n }\n}\n\nconst DEG = Math.PI / 180;\nconst norm360 = (d: number) => ((d % 360) + 360) % 360;\n\nfunction offsetsFor(\n config: \"single\" | \"double\",\n half: number,\n): number[] {\n return config === \"double\" ? [-half, half] : [0];\n}\n\n/**\n * Derive every endplate's module-local pose. A at the origin facing west; B\n * placed by the module's geometry (straight/offset/corner/curve via a\n * constant-radius arc = arc-length `lengthInches`, turning by the geometry\n * angle); branch endplates positioned along the mainline axis facing out their\n * side. A `dead_end`/loop module has no B. Overrides replace any derived pose.\n */\nexport function deriveEndplatePoses(geo: ModuleGeometryInput): EndplatePose[] {\n const L = geo.lengthInches > 0 ? geo.lengthInches : 24;\n const half = geo.trackHalfSpacingInches ?? 1;\n const cfg = (i: number): \"single\" | \"double\" =>\n geo.endplateConfigs?.[i] === \"double\" ? \"double\" : \"single\";\n const withOverride = (p: EndplatePose): EndplatePose => {\n const o = geo.poseOverrides?.[p.id];\n return o ? { ...p, x: o.x, y: o.y, heading: norm360(o.heading), manual: true } : p;\n };\n\n const poses: EndplatePose[] = [];\n\n // Endplate A — origin, outward normal west.\n poses.push(\n withOverride({\n id: \"A\",\n x: 0,\n y: 0,\n heading: 180,\n trackConfig: cfg(0),\n trackOffsets: offsetsFor(cfg(0), half),\n }),\n );\n\n // Endplate B — unless the module is a dead end / turnback (single endplate).\n // A dead-end has one plate; a balloon/return loop likewise (it turns back on\n // itself, so the chain's end lands near the throat, not a real far endplate).\n const noB = geo.geometryType === \"dead_end\" || geo.loop === true;\n // A sectioned module's real end is where its boards finish, which no single\n // module-level geometry can predict — chain them and read the last point and\n // its closing tangent (#108).\n const end = sectionedEndPose({ sections: geo.sections });\n if (!noB && end) {\n poses.push(\n withOverride({\n id: \"B\",\n x: end.x,\n y: end.y,\n heading: norm360(end.heading),\n trackConfig: cfg(1),\n trackOffsets: offsetsFor(cfg(1), half),\n }),\n );\n } else if (!noB) {\n const turn = geometryTurnDegrees(geo.geometryType, geo.geometryDegrees);\n let bx: number;\n let by: number;\n let bHeading: number;\n if (geo.geometryType === \"offset\") {\n // Parallel endplates, jogged sideways over the run.\n bx = L;\n by = geo.geometryOffsetInches ?? 0;\n bHeading = 0;\n } else if (turn === 0) {\n bx = L;\n by = 0;\n bHeading = 0;\n } else {\n // Constant-radius arc of arc-length L turning `turn` (CCW/left).\n const t = turn * DEG;\n const r = L / t;\n bx = r * Math.sin(t);\n by = r * (1 - Math.cos(t));\n bHeading = turn;\n }\n poses.push(\n withOverride({\n id: \"B\",\n x: bx,\n y: by,\n heading: norm360(bHeading),\n trackConfig: cfg(1),\n trackOffsets: offsetsFor(cfg(1), half),\n }),\n );\n }\n\n // Branch endplates — at their along-axis position, facing out their side.\n // Position along the (possibly curved) mainline is approximated on the A→B\n // chord; the join solver refines with overrides where a module needs it.\n for (const b of geo.branches ?? []) {\n const frac = L > 0 ? Math.min(1, Math.max(0, b.atPos / L)) : 0;\n const px = frac * L;\n const config = b.config === \"double\" ? \"double\" : \"single\";\n poses.push(\n withOverride({\n id: b.id,\n x: px,\n y: 0,\n heading: b.side === \"down\" ? 270 : 90,\n trackConfig: config,\n trackOffsets: offsetsFor(config, half),\n }),\n );\n }\n\n return poses;\n}\n\n/** Free-moN §2.0 — track crossing an endplate must be perpendicular, straight\n * and level for at least this many inches from the outside face. */\nexport const ENDPLATE_LEAD_INCHES = 4;\n/** Free-moN §2.0 — the crossing must stay at least this far from either fascia. */\nexport const ENDPLATE_FASCIA_CLEAR_INCHES = 4;\n\n/** The mandated straight, perpendicular lead a connecting track must follow\n * leaving an endplate (§2.0). Given the endplate's track point + outward-normal\n * heading, returns the face point and the point `leadInches` inboard, plus the\n * inward heading. A track meeting this plate must be collinear with face→inboard\n * for its first `leadInches`. */\nexport function endplateLead(\n pose: { x: number; y: number; heading: number },\n leadInches: number = ENDPLATE_LEAD_INCHES,\n): { face: BenchworkPoint; inboard: BenchworkPoint; inwardHeading: number } {\n const inwardHeading = norm360(pose.heading + 180);\n const r = inwardHeading * DEG;\n return {\n face: { x: pose.x, y: pose.y },\n inboard: { x: pose.x + Math.cos(r) * leadInches, y: pose.y + Math.sin(r) * leadInches },\n inwardHeading,\n };\n}\n\nexport interface EndplateTrackIssue {\n /** \"not-perpendicular\" — the track doesn't cross square to the face;\n * \"short-lead\" — it curves/bends within the required lead;\n * \"fascia-clearance\" — the crossing is <4″ from a fascia. */\n code: \"not-perpendicular\" | \"short-lead\" | \"fascia-clearance\";\n message: string;\n}\n\n/**\n * Validate a drawn path meeting an endplate against Free-moN §2.0: perpendicular\n * crossing, straight + level for ≥4″ from the face, ≥4″ from either fascia.\n * `end` says which end of the authored path touches the plate (\"last\" default).\n * Fascia clearance is checked only when both the face width and the track's\n * offset from the plate centre are supplied. Pure; empty array = compliant.\n */\nexport function trackMeetsEndplateIssues(\n path: BenchworkPoint[],\n pose: { x: number; y: number; heading: number },\n opts?: {\n end?: \"first\" | \"last\";\n faceWidthInches?: number;\n trackOffsetInches?: number;\n leadInches?: number;\n toleranceDeg?: number;\n },\n): EndplateTrackIssue[] {\n const issues: EndplateTrackIssue[] = [];\n const lead = opts?.leadInches ?? ENDPLATE_LEAD_INCHES;\n const tol = opts?.toleranceDeg ?? 5;\n if (path && path.length >= 2) {\n // Order the path plate→inboard so seq[0] is the endplate end.\n const seq = (opts?.end ?? \"last\") === \"last\" ? [...path].reverse() : path.slice();\n const p0 = seq[0];\n const p1 = seq[1];\n const wantIn = norm360(pose.heading + 180); // inboard = opposite the outward normal\n const inHead = norm360(Math.atan2(p1.y - p0.y, p1.x - p0.x) / DEG);\n const diff = Math.abs(((inHead - wantIn + 540) % 360) - 180);\n if (diff > tol)\n issues.push({\n code: \"not-perpendicular\",\n message: `Track must cross the endplate square (within ${tol}°); it is off by ${Math.round(diff)}°.`,\n });\n // Straight + level for the first `lead` inches: no arc, and the near\n // vertices must lie on the lead line (little lateral drift).\n const r = wantIn * DEG;\n const ux = Math.cos(r);\n const uy = Math.sin(r);\n let curved = false;\n let acc = 0;\n for (let i = 1; i < seq.length && acc < lead; i++) {\n const a = seq[i - 1];\n const b = seq[i];\n if (a.bulge) curved = true;\n const rx = b.x - p0.x;\n const ry = b.y - p0.y;\n const along = rx * ux + ry * uy;\n const lat = Math.abs(rx * -uy + ry * ux);\n if (along <= lead + 0.01 && lat > 0.25) curved = true;\n acc += Math.hypot(b.x - a.x, b.y - a.y);\n }\n if (curved)\n issues.push({\n code: \"short-lead\",\n message: `The first ${lead}″ from the endplate must be straight and perpendicular.`,\n });\n }\n const w = opts?.faceWidthInches;\n const off = opts?.trackOffsetInches;\n if (typeof w === \"number\" && w > 0 && typeof off === \"number\") {\n const clear = w / 2 - Math.abs(off);\n if (clear < ENDPLATE_FASCIA_CLEAR_INCHES)\n issues.push({\n code: \"fascia-clearance\",\n message: `Track must stay ≥${ENDPLATE_FASCIA_CLEAR_INCHES}″ from either fascia; it is ${clear.toFixed(1)}″.`,\n });\n }\n return issues;\n}\n\n/** Whether a module shape's poses are fully derivable, or need manual entry\n * (a helpful cue for the authoring UI). */\nexport function poseNeedsManual(geometryType?: string | null): boolean {\n return geometryType === \"wye\" || geometryType === \"other\";\n}\n\n/** Extract manual pose overrides from a schematic doc's endplates (#175 phase\n * 1b) — the map deriveEndplatePoses / a footprint solver feeds as overrides. */\nexport function poseOverridesFromDoc(\n doc: ModuleSchematicDoc,\n): Record<string, { x: number; y: number; heading: number }> {\n const out: Record<string, { x: number; y: number; heading: number }> = {};\n for (const e of doc.endplates ?? []) {\n if (\n e.id &&\n e.pose &&\n typeof e.pose.x === \"number\" &&\n typeof e.pose.y === \"number\" &&\n typeof e.pose.heading === \"number\"\n ) {\n out[e.id] = { x: e.pose.x, y: e.pose.y, heading: e.pose.heading };\n }\n }\n return out;\n}\n"]}