@willcgage/module-schematic 0.107.0 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +9 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["at","pts","c","r","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 /** ⭐ THE ENDPLATE'S EDGE OF THE BENCHWORK (ADR 0001). When present it WINS\n * over `pose` and over derivation, and position, heading and width are all\n * read off the polygon — so they cannot drift apart from the board.\n *\n * `pose` remains for modules authored before this and for shapes with no\n * benchwork polygon to bind to. Nothing is auto-converted: guessing which\n * edge an owner's freehand pose meant would be inventing an intent. */\n edge?: EndplateEdge | null;\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 /** Whether that pose was AUTHORED — placed or typed by the owner — rather\n * than a derived one that found its way into the doc (#182).\n *\n * Authorship used to be inferred from `pose` merely existing, so a derived\n * pose written back silently PINNED the plate: it stopped following the\n * module and went stale the moment the length changed (FMN-0068 ended up with\n * endplate B at x=48 on a 47.9″ board). A pose is only an override when the\n * owner meant it.\n *\n * Absent on A/B = derived residue, ignored. Absent on a placed branch\n * endplate (one with `at`) = still authored — placing it IS the gesture, and\n * docs predate this flag. */\n poseAuthored?: boolean;\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 * Free-moN **standard**: minimum MAIN-LINE radius, 22″.\n *\n * ⚠️ The main line only. A spur, a yard lead or an industrial track may be\n * tighter, and telling an owner their yard is out of spec because it is not a\n * main would be worse than saying nothing.\n */\nexport const FREEMO_MAIN_MIN_RADIUS_INCHES = 22;\n/** Free-moN **standard**: at least 6″ of straight track between REVERSE curves,\n * so a train is never asked to change hands instantly. */\nexport const FREEMO_REVERSE_CURVE_STRAIGHT_INCHES = 6;\n\n/**\n * A stretch where a pair of parallel tracks runs at something other than the\n * standard spacing, because a rigid assembly built to another spacing sits in\n * it (#180).\n *\n * The case this exists for: a crossover fixture is machined for ONE track\n * spacing and cannot be built to another. The Fast Tracks N crossovers are\n * 1.09″ where Free-moN §2.0 requires 1.125″, so a module with one genuinely has\n * its two mains 0.035″ closer together across the crossover, opening back to\n * 1.125″ at the endplates — which the standard fixes. That pinch is real, and\n * drawing it is more honest than drawing a straight pair.\n */\nexport interface LanePinch {\n /** The lane pulled in. Lane 0 is the reference and never moves. */\n lane: number;\n /** Inches from endplate A where the rigid section begins and ends. */\n fromPos: number;\n toPos: number;\n /** Centre-to-centre spacing INSIDE that span, inches. */\n spacingInches: number;\n}\n\n/**\n * How far either side of a rigid section the pair takes to reach it.\n *\n * ⚠️ A DRAWING CONVENTION, NOT A MEASUREMENT. Nobody publishes this and it is\n * not a property of any part — in the real world the builder eases the flex over\n * whatever room they have. It exists so the pinch renders as a smooth deviation\n * rather than a kink, and it is deliberately a round number so it never reads as\n * something that was measured.\n */\nexport const PINCH_EASE_INCHES = 3;\n\n/**\n * The lane offset at a point, honouring any {@link LanePinch} covering it.\n *\n * Eases with a smoothstep, whose slope is zero at both ends, so the deviation\n * leaves and rejoins the straight run tangentially — the way bent flex actually\n * behaves. A linear ramp would put a visible corner at each end.\n *\n * ⚠️ ONLY THE PINCH'S OWN LANE MOVES. The main is the reference every Free-moN\n * measurement is taken from, so it stays put and the parallel track deviates,\n * which is also what a builder does.\n */\nexport function laneOffsetAt(\n lane: number,\n pos: number,\n pinches?: LanePinch[] | null,\n spacingInches = FREEMO_TRACK_SPACING_INCHES,\n): number {\n const base = (lane ?? 0) * spacingInches;\n if (!lane || !pinches?.length) return base;\n const sign = Math.sign(lane);\n const smooth = (t: number) => t * t * (3 - 2 * t);\n let off = base;\n for (const p of pinches) {\n if (p.lane !== lane) continue;\n const a = Math.min(p.fromPos, p.toPos);\n const b = Math.max(p.fromPos, p.toPos);\n // The pinch names ONE lane step's spacing. A pinched lane 2 would need to\n // say which of its two gaps closed, and nothing records that: not modelled.\n const target = base - sign * (spacingInches * Math.abs(lane) - p.spacingInches);\n const e = PINCH_EASE_INCHES;\n let t: number | null = null;\n if (pos >= a && pos <= b) t = 1;\n else if (pos > a - e && pos < a) t = smooth((pos - (a - e)) / e);\n else if (pos > b && pos < b + e) t = smooth(1 - (pos - b) / e);\n if (t == null) continue;\n // Where two overlap the DEEPEST wins rather than summing: two crossovers in\n // the same place is a data error, not a doubly-tight pair.\n const candidate = base + (target - base) * t;\n if (Math.abs(candidate - base) > Math.abs(off - base)) off = candidate;\n }\n return off;\n}\n\n/**\n * The pinches a document's crossovers impose — one per crossover connector that\n * names a part whose {@link TrackPart.trackSpacing} differs from the standard.\n *\n * A crossover with no part named, or one built to the standard spacing, imposes\n * nothing: an owner who hasn't said what they built gets the straight pair they\n * had before, which is the only honest default.\n */\nexport function crossoverPinches(\n tracks: Array<{\n role?: string;\n lane?: number;\n fromPos?: number | null;\n toPos?: number | null;\n crossoverPartId?: string | null;\n }>,\n library = BUILT_IN_TRACK_PARTS,\n spacingInches = FREEMO_TRACK_SPACING_INCHES,\n): LanePinch[] {\n const out: LanePinch[] = [];\n for (const t of tracks) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = library.find((p) => p.id === t.crossoverPartId);\n const s = part?.trackSpacing?.inches;\n if (typeof s !== \"number\" || !Number.isFinite(s) || s <= 0) continue;\n if (Math.abs(s - spacingInches) < 1e-9) continue;\n const lane = t.lane ?? 1;\n if (!lane) continue;\n const a = t.fromPos ?? 0;\n const b = t.toPos ?? 0;\n if (!Number.isFinite(a) || !Number.isFinite(b) || Math.abs(b - a) < 1e-9) continue;\n const pinch = {\n lane,\n fromPos: Math.min(a, b),\n toPos: Math.max(a, b),\n spacingInches: s,\n };\n // ⚠️ A DOUBLE CROSSOVER IS TWO CONNECTORS AND ONE PINCH. It is built as two\n // diagonals, so the document holds two records over the same\n // span at the same spacing — but the pair of tracks only closes up once.\n // Left un-deduped the geometry is still right (identical pinches agree), so\n // this shows up as a doubled CALLOUT rather than a wrong drawing: the label\n // renders twice, exactly superimposed.\n const same = out.some(\n (p) =>\n p.lane === pinch.lane &&\n Math.abs(p.fromPos - pinch.fromPos) < 1e-9 &&\n Math.abs(p.toPos - pinch.toPos) < 1e-9 &&\n Math.abs(p.spacingInches - pinch.spacingInches) < 1e-9,\n );\n if (!same) out.push(pinch);\n }\n return out;\n}\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 /** The flex product this run is laid with — a slug from the parts library\n * (#193). Absent = the default. Per TRACK, so a module can have its mains in\n * one product and a siding in another. */\n flexPartId?: string | null;\n /** Authored rail joints, inches along this run. Absent = derived from the\n * product's maximum piece length. Present = these are the ONLY joints, so an\n * owner's deliberate cut survives a change elsewhere on the module. */\n flexCuts?: number[] | null;\n /** `role: \"crossover\"` only — the crossover product this connector was built\n * from, a slug from the parts library.\n *\n * It sits on the CONNECTOR rather than on the turnouts at its ends because a\n * crossover is one assembly: the fixture that set its angle also set its\n * {@link TrackPart.trackSpacing}, and that spacing belongs to the pair of\n * tracks, not to either turnout. Naming it is what lets the physical view draw\n * the crossover at the spacing it was actually built to — the Fast Tracks N\n * fixtures are 1.09″ against Free-moN's 1.125″, and the difference is real. */\n crossoverPartId?: string | null;\n /**\n * Which end of this track is CLOSED BY A BUMPER — deliberately the end of the\n * line, rather than track that merely stops.\n *\n * ⭐ The difference is operational, not decorative: a bumpered end is where a\n * cut of cars can be shoved to, and it is where usable length runs out. An\n * end that just stops might only be unfinished.\n */\n bumperAt?: \"from\" | \"to\" | null;\n /** The owner's MEASURED usable length, real inches (#20) — for what the\n * drawing can't know: a bumper post short of the drawn end, a structure\n * fouling the track. Absent = derive it from the clearance points (#19). */\n measuredUsableInches?: number | null;\n}\n/**\n * A turnout.\n *\n * ⭐ **THE WORD IS \"TURNOUT\", NOT \"SWITCH\".** They were used interchangeably\n * across both apps; this is the one name. The Free-moN standard says turnout\n * (\"main-line turnouts at least #6\") and so does the NMRA, every user-facing\n * string already said it, and \"switch\" is ambiguous three ways for us — the\n * points assembly, an electrical switch, and *switching*, the operation of\n * moving cars, which we need as its own word.\n *\n * ⚠️ TWO DELIBERATE EXCEPTIONS, both still correct usage:\n * 1. **A manufacturer's own product name, quoted as they sell it.** Atlas sells\n * a \"#7 LH Switch\" (2052). Renaming their product makes it un-findable in a\n * catalogue, which is the opposite of what a parts library is for.\n * 2. **The points assembly and its geometry** — \"switch points\", and the\n * \"switch angle\" that {@link TurnoutClosure.switchSlope} carries. That is a\n * part OF a turnout, not another word FOR one.\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 /** The library part this turnout IS — e.g. \"atlas-c55-n-7\". Binds a drawn\n * turnout to real geometry: with it the renderer can draw the part's own\n * outline instead of a shape derived from `size`. Absent means \"just a #N\",\n * which is what every turnout authored before the parts library was. */\n partId?: string | null;\n}\nexport interface SchematicSignal {\n id: string;\n pos: number;\n /** Hold this signal by the piece it stands beside (ADR 0001). See\n * {@link GraphAnchor} — a mast is planted next to a particular bit of rail. */\n anchor?: GraphAnchor | null;\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). */\n/**\n * ⭐ A PLACE ON THE TRACK, HELD BY THE PIECE THAT IS THERE (ADR 0001).\n *\n * `pos` — inches from endplate A — is a fine way to *read* where something is\n * and a poor way to *hold* it: it is a number about the whole module, so every\n * edit anywhere upstream silently changes what it means. A car spot belongs to\n * the rail it is beside. Anchored to the piece, moving that piece takes the\n * industry with it and moving anything else leaves it alone, which is what an\n * owner dragging track expects to happen.\n *\n * Present = `pos` / `fromPos` / `toPos` are DERIVED from this by\n * {@link graphToDoc}. Absent = the authored numbers stand, exactly as before —\n * nothing migrates (ADR 0001).\n */\nexport interface GraphAnchor {\n /** The {@link TrackPiece} it sits on. */\n piece: string;\n /**\n * Inches along that piece from its OWN origin end — joint `a` on flex, the\n * throat on a turnout, and in every case the part's x=0.\n *\n * ⚠️ Deliberately NOT \"from the end the walk came in by\". Which end that is\n * depends on where the module's endplate A happens to be, so the same spot\n * beside the same rail would mean two different numbers on two modules.\n */\n atInches: number;\n}\n\nexport interface IndustrySpot {\n track: string;\n fromPos: number;\n toPos: number;\n side?: SignalSide;\n /** Hold this spot by the piece it is beside (ADR 0001). See {@link GraphAnchor}. */\n anchor?: GraphAnchor | null;\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 /** Hold this span by the piece it is beside (ADR 0001). See {@link GraphAnchor}.\n * The span's LENGTH stays authored — a dock face is as long as it is built;\n * only where it begins is read off the track. */\n anchor?: GraphAnchor | null;\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 * ⭐⭐ THE AUTHORED TRACK, when this module was drawn as PIECES (ADR 0001).\n *\n * Present = this is the source, and `tracks`, `turnouts` and every anchored\n * feature's position are DERIVED from it by {@link deriveGraphDoc} — they are\n * still written into the document so that everything downstream, Free-\n * Dispatcher included, reads an ordinary document and is never told which way\n * the module was authored.\n *\n * Absent = the module is authored the way it always was, and nothing about it\n * changes. No document is converted (ADR 0001): converting one would mean\n * inventing the leads, frogs and radii nobody measured.\n */\n graph?: {\n pieces: TrackPiece[];\n /** Where the main starts: the joint endplate A's track arrives at. */\n startAt: { piece: string; joint: string };\n /** Where MAIN 2 starts, on a double-track module — the joint the endplate's\n * SECOND track arrives at. Absent = single track.\n *\n * Two starts rather than a list because a document has exactly two mains,\n * `main` and `main2`. This mirrors the thing downstream instead of inventing\n * a generality nothing can read. */\n start2?: { piece: string; joint: string } | null;\n } | 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 /** This board's WEST end (the A side) — see {@link SectionEnd}. */\n endA?: SectionEnd | null;\n /** This board's EAST end (the B side). */\n endB?: SectionEnd | null;\n}\n\n/**\n * One end of a board (#130).\n *\n * Owner's question was *\"how would I update my section joints to be endplates\n * from within MR?\"* — and until now nothing could say it: a section had a\n * length, a shape and an outline, but nothing about its ends.\n *\n * ⚠️ **There is deliberately no \"this is an endplate\" flag.** An owner could\n * tick it wrongly and the registry would then tell Free-Dispatcher that two\n * boards will physically mate when they won't. The geometry decides — describe\n * the end and {@link assessSectionEnd} works out whether it conforms.\n *\n * Absent means **not described**, which is an ordinary internal joint, not a\n * failing endplate: the standard exempts internal boundaries from the\n * end-interface rules (#96).\n */\nexport interface SectionEnd {\n /** What this end presents. `\"none\"` = a closed end (a bumper). */\n config?: TrackConfig | \"none\" | null;\n /** Face width, inches. Absent = the recommended default. */\n widthInches?: number | null;\n /** Main 1's signed distance from the face centre — the standard's own\n * framing, same as an endplate's (see {@link endplateTrackOffsetInches}). */\n trackOffsetInches?: 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 // The board's two ends (#130). Written only when actually described —\n // an absent end is an ordinary internal joint, and an empty object\n // would claim the owner had said something about it.\n ...(sectionEnd(sec.endA) ? { endA: sectionEnd(sec.endA)! } : {}),\n ...(sectionEnd(sec.endB) ? { endB: sectionEnd(sec.endB)! } : {}),\n };\n });\n}\n\n/** Normalise one board end, or null when nothing was actually said about it\n * (#130). Keeps `{}` and `{ config: null }` from round-tripping as a described\n * end — see {@link SectionEnd}. */\nfunction sectionEnd(end: SectionEnd | null | undefined): SectionEnd | null {\n if (!end) return null;\n const config =\n end.config === \"single\" || end.config === \"double\" || end.config === \"none\"\n ? end.config\n : null;\n const w = end.widthInches;\n const o = end.trackOffsetInches;\n const out: SectionEnd = {\n ...(config ? { config } : {}),\n ...(typeof w === \"number\" && Number.isFinite(w) && w > 0 ? { widthInches: w } : {}),\n // Signed, and 0 is meaningful (\"explicitly centred\", #93) — keep any finite.\n ...(typeof o === \"number\" && Number.isFinite(o) ? { trackOffsetInches: o } : {}),\n };\n return Object.keys(out).length ? out : null;\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/**\n * Arc length of an authored path, inches — the path's OWN length, independent of\n * where it sits or which way it runs. A branch route to a third endplate (#181)\n * has no meaningful extent along the module axis (a square 90° exit projects to\n * zero), so its own length is the only honest measure of it.\n */\nexport function pathLengthInches(\n path: BenchworkPoint[] | null | undefined,\n): number {\n const pts = trackPath(path);\n if (!pts) return 0;\n const poly = samplePath(pts);\n let total = 0;\n for (let i = 1; i < poly.length; i++)\n total += Math.hypot(poly[i].x - poly[i - 1].x, poly[i].y - poly[i - 1].y);\n return total;\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 toward Main 2. Single\n * track crosses at the centre ⇒ 0, and an off-centre track is a signed value.\n * {@link endplateCentreOffsetInches} computes it from what the owner authored.\n *\n * ⚠️ OMITTING an end no longer means 0 — it means \"use §2.0\", which is a\n * straddle on a double end. Centring a double plate on Main 1 drew its pair\n * wholly to one side, which is what the read-only and catalog views did by\n * passing nothing at all (#190). Pass an explicit number to place a plate. */\n endplateTrackOffsets?: Record<string, number>;\n /** Whether Main 2 runs BELOW Main 1 (`mainsSwapped`, #131). Only affects which\n * way an unauthored double plate straddles. */\n mainsSwapped?: boolean;\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 * The document already places track along a main (see {@link\n * moduleCenterline}). Set from the doc's own `tracks`; without it a module\n * whose track was authored before it had a geometry draws as a bare board.\n */\n hasPlacedTrack?: boolean;\n /** Axial endplate configs (A first, then B), same as\n * {@link ModuleGeometryInput.endplateConfigs}. `\"none\"` at B means the module\n * presents no far endplate, so no face is emitted there (#184/#191). */\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | null | undefined)[];\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 //\n // ⚠️ UNLESS THE DOCUMENT ALREADY PLACES TRACK. `pos` means inches from\n // endplate A ALONG THE MAIN, so a document with tracks on it is asserting\n // that a main exists — refusing one then draws the board and silently none of\n // its track, which is what a card for such a module did. The blank-module\n // rule is about a module with NOTHING on it, and a module with track is not\n // that. Callers pass `hasPlacedTrack` from the document they already hold.\n if (!input.geometryType && !input.hasPlacedTrack) 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 // Where each plate's CENTRE sits relative to Main 1. The DEFAULT is §2.0's\n // geometry, not zero — a caller that says nothing about a double end still\n // gets a plate its two tracks straddle (#190).\n const offOf = (i: number, id: string) =>\n input.endplateTrackOffsets?.[id] ??\n endplateCentreOffsetInches({\n config: input.endplateConfigs?.[i],\n main2Below: input.mainsSwapped === true,\n });\n const offA = offOf(0, \"A\");\n const offB = offOf(1, \"B\");\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 // Only emit a face where the module actually presents one. A loop's\n // centre-line ends at the THROAT, and an end of the line / pocket simply\n // stops — a far face there is a plate the module hasn't got (#191).\n endplateFaces: hasNoFarEndplate(input)\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 * Where an endplate's CENTRE sits relative to MAIN 1 — the renderer's framing,\n * and the one number a drawing needs to place the plate.\n *\n * ⭐ THE single definition. Two callers had their own: the builder computed it\n * inline (swap-aware), and the read-only/catalog footprint **passed nothing at\n * all**, so every plate there was centred on Main 1 — a double end drew its pair\n * entirely to one side of the plate instead of straddling it (#190).\n *\n * §2.0 puts a double end's two tracks 0.5625″ either side of the plate centre,\n * so the plate centre is half a track spacing away from Main 1 — **toward Main\n * 2**, which is why the swap matters: with Main 2 below, the plate centre is\n * below too. An authored offset always wins (an off-centre end is legal since\n * the 20220628 revision), and is given in the standard's own framing — Main 1's\n * distance from the plate centre — so it comes back negated here.\n */\nexport function endplateCentreOffsetInches(input: {\n config?: TrackConfig | \"none\" | null;\n /** Main 1's signed distance from the plate centre, as authored. */\n authoredTrackOffsetInches?: number | null;\n /** Whether Main 2 runs below Main 1 (the mains are swapped). */\n main2Below?: boolean;\n}): number {\n // Simply the other framing of the same fact, so there is ONE default to get\n // right rather than two that can disagree.\n const v = -endplateTrackOffsetInches(\n input.authoredTrackOffsetInches,\n input.config ?? undefined,\n input.main2Below,\n );\n return v === 0 ? 0 : v; // never hand back -0\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 /** Whether Main 2 runs BELOW Main 1 (the mains are swapped). The pair\n * straddles the plate centre either way, so Main 1 sits on the side AWAY from\n * Main 2 — low when Main 2 is high, high when it's low. Omitting this\n * hard-coded \"Main 2 is above\", which is the assumption behind #190. */\n main2Below = false,\n): number {\n if (typeof authored === \"number\" && Number.isFinite(authored)) return authored;\n if (config !== \"double\") return 0;\n const half = FREEMO_TRACK_SPACING_INCHES / 2;\n return main2Below ? half : -half;\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 * \"offcentre\" = a double end whose pair doesn't straddle the plate centre. */\n code: \"narrow\" | \"clearance\" | \"offcentre\";\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 /** Whether Main 2 runs BELOW Main 1 (the mains are swapped). Without it a\n * double end's second track was assumed to be one spacing ABOVE Main 1, so a\n * swapped pair was measured on the wrong side of the plate (#190). */\n main2Below?: boolean;\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(\n input.trackOffsetInches,\n input.config ?? undefined,\n input.main2Below,\n );\n // Main 2 sits one spacing from Main 1, on Main 2's OWN side — below when the\n // mains are swapped. Assuming \"above\" put a swapped pair on the wrong side of\n // the plate and demanded a wider end than the geometry needs (#190).\n const second = off + (input.main2Below ? -1 : 1) * FREEMO_TRACK_SPACING_INCHES;\n const centres = input.config === \"double\" ? [off, second] : [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 // §2.0 puts a double end's two tracks 0.5625″ EITHER SIDE of the plate centre.\n // Off-centre is legal — the 20220628 revision relaxed centring to a\n // recommendation — but a pair sitting wholly to one side is worth saying out\n // loud, because it's almost always an accident: an authored 0 reads as \"centre\n // Main 1\", which pushes the whole pair off the plate's middle (#190).\n if (input.config === \"double\") {\n const mid = (off + second) / 2;\n if (Math.abs(mid) > 0.01) {\n issues.push({\n code: \"offcentre\",\n message:\n `The two tracks sit ${round2(Math.abs(mid))}″ off the centre of this endplate. ` +\n `The standard recommends they straddle it — Main 1 at ` +\n `${round2((input.main2Below ? 1 : -1) * (FREEMO_TRACK_SPACING_INCHES / 2))}″. ` +\n `Clear the offset to use that.`,\n // Not a width problem — no wider plate fixes it — so hand back the\n // width unchanged rather than imply one would.\n requiredInches: width,\n });\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/**\n * Whether a module presents NO far endplate — one conforming face only.\n *\n * ⭐ THE single definition. Three places had grown their own answer to this and\n * drifted: `deriveEndplatePoses` (which knew about `dead_end` and `\"none\"`), the\n * operations preview's end label, and `moduleFootprint`'s endplate faces — the\n * last two using \"is it a loop?\" as a stand-in for \"has it got two ends?\", which\n * was true until #184 and silently wrong after. Anything asking this must call\n * THIS.\n *\n * Three ways to have one end, and they are genuinely different things: the\n * geometry is a dead end; it's a balloon loop, whose far end is the throat and\n * not a plate at all; or the owner said this end has no plate, which is how an\n * *end of the line* or a *pocket* is authored — ordinary straight boards that\n * simply stop, so no geometry type would ever say it for them.\n */\nexport function hasNoFarEndplate(input: {\n geometryType?: string | null;\n loop?: boolean;\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | null | undefined)[];\n}): boolean {\n return (\n input.geometryType === \"dead_end\" ||\n input.loop === true ||\n input.endplateConfigs?.[1] === \"none\"\n );\n}\n\n/**\n * Whether a doc is a balloon loop — **the authored flag, and only that**.\n *\n * ⚠️ This used to ALSO infer a loop from `endplates.length === 1`, which was\n * safe only while the sole way to have one endplate was to be a turnback. #184\n * ended that: an *end of the line* or a *pocket* presents one conforming face\n * too, so every single-ended module was silently classified as a loop — drawn\n * with a bulb, its endplate A relabelled \"Entry\", and positions past the throat\n * read as being inside a balloon that doesn't exist (#191).\n *\n * A loop is now only ever a loop because someone said so: the Loop checkbox and\n * the return-loop generator both set `loop: true`. Checked before removing the\n * inference — no stored doc relied on it (no module in the catalogue has one\n * endplate without the flag, and none is `category:\"loop\"` or `dead_end`).\n */\nexport function isLoopDoc(doc: ModuleSchematicDoc): boolean {\n return doc.loop === true;\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/**\n * How far the two routes must separate before a car on one clears equipment on\n * the other — the CLEARANCE POINT's defining distance (#19).\n *\n * ⭐ Deliberately the **Free-moN track spacing**, not a second number. §2.0 uses\n * 1.125″ as the distance at which two parallel tracks coexist, so \"a car here\n * clears a car there\" is the same statement the standard already makes. It's\n * 15 scale feet centre to centre, inside the prototype's usual 13–15 ft range.\n *\n * The alternative — a separate prototype constant — would leave the app holding\n * two spacings that disagree about what \"clear\" means.\n */\nexport const CLEARANCE_SPACING_INCHES = FREEMO_TRACK_SPACING_INCHES;\n\n/**\n * How far past the FROG a turnout's diverging route reaches the clearance point\n * (#19) — the point from which usable capacity is measured.\n *\n * Not a measurement and not a guess: it's solved from the closure the drawing\n * already uses, by asking where `offsetAt` first reaches\n * {@link CLEARANCE_SPACING_INCHES}. So it follows the part's real lead, and a\n * better-measured part moves it automatically.\n *\n * Returns the distance PAST THE FROG because `pos` means the frog (#132) — add\n * it to the turnout's position, in the direction the turnout faces.\n */\nexport function clearancePointPastFrogInches(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n clearanceInches = CLEARANCE_SPACING_INCHES,\n): number {\n const N = size > 0 ? size : 6;\n const lead = leadInchesForSize(N, library);\n const cl = turnoutClosure(N, { leadInches: lead });\n // The profile rises monotonically, so bisect — cheap, and it doesn't care\n // which branch of the closure (switch curve, frog angle, ease) the answer\n // lands in.\n let lo = 0;\n let hi = Math.max(4 * lead, 4 * clearanceInches * N);\n if (cl.offsetAt(hi) < clearanceInches) return hi - lead;\n for (let i = 0; i < 60; i++) {\n const mid = (lo + hi) / 2;\n if (cl.offsetAt(mid) < clearanceInches) lo = mid;\n else hi = mid;\n }\n return Math.max(0, hi - lead);\n}\n\n/** A track's usable capacity, measured to the clearance-point standard (#19). */\nexport interface UsableCapacity {\n /** The stretch a car can actually stand on, inches along the run. */\n fromPos: number;\n toPos: number;\n /** Its length — what capacity is computed from. */\n usableInches: number;\n /** The run's full drawn length, for comparison. */\n drawnInches: number;\n /** How much each end gives up to its governing turnout's clearance point. */\n givenUpInches: number;\n /** Cars that fit in the usable length. */\n cars: number;\n /** Usable length as scale feet. */\n scaleFeet: number;\n}\n\n/**\n * A track's USABLE capacity — measured from the governing turnout's clearance\n * point, not from the rail ends (#19/#20).\n *\n * A spur runs clearance point → end of track; a siding, clearance point →\n * clearance point. The difference is not small: FMN-0040's 70″ passing siding\n * has two #7s on it, and loses 5.4″ at each end — 21 cars drawn, 17 usable.\n *\n * `measuredUsableInches` is the owner's override for what the drawing can't\n * know — a bumper post short of the drawn end, a structure fouling the track.\n * Given, it wins outright and the clearance points aren't applied to it: they\n * measured the usable length itself.\n */\nexport function usableCapacity(input: {\n fromPos: number;\n toPos: number;\n /** Turnouts that DIVERGE ONTO this track — the ones that govern its ends. */\n governing?: { pos: number; size?: number | null }[] | null;\n /** The owner's measured usable length, inches. Wins when present. */\n measuredUsableInches?: number | null;\n library?: TrackPart[];\n carLengthInches?: number;\n}): UsableCapacity {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n const drawn = hi - lo;\n const carLen = input.carLengthInches ?? N_CAR_LENGTH_INCHES;\n\n if (typeof input.measuredUsableInches === \"number\" && input.measuredUsableInches >= 0) {\n const m = input.measuredUsableInches;\n return {\n fromPos: lo,\n toPos: lo + m,\n usableInches: m,\n drawnInches: drawn,\n givenUpInches: Math.max(0, drawn - m),\n cars: carCapacity(0, m, carLen),\n scaleFeet: Math.round(inchesToScaleFeet(m)),\n };\n }\n\n // Each governing turnout pushes the END NEAREST IT inward to its clearance\n // point. Nearest, not \"the low one\": a siding's two turnouts sit at its two\n // ends, and a spur's single turnout may govern either.\n let a = lo;\n let b = hi;\n for (const sw of input.governing ?? []) {\n const c = clearancePointPastFrogInches(sw.size ?? 6, input.library);\n if (Math.abs(sw.pos - lo) <= Math.abs(sw.pos - hi)) a = Math.max(a, lo + c);\n else b = Math.min(b, hi - c);\n }\n const usable = Math.max(0, b - a);\n return {\n fromPos: a,\n toPos: Math.max(a, b),\n usableInches: usable,\n drawnInches: drawn,\n givenUpInches: Math.max(0, drawn - usable),\n cars: carCapacity(0, usable, carLen),\n scaleFeet: Math.round(inchesToScaleFeet(usable)),\n };\n}\n\n/** What a board's end is, once the geometry has been asked (#130). */\nexport interface SectionEndAssessment {\n /** Has the owner described this end at all? Undescribed is an ordinary\n * internal joint — exempt from the end-interface rules (#96) — not a failure. */\n described: boolean;\n /** Does it meet the standard's end-interface rules? Only a described end can. */\n conforming: boolean;\n /** Why it doesn't, when it doesn't. Empty for a conforming or undescribed end. */\n issues: EndplateWidthIssue[];\n /** The resolved values the assessment was made against. */\n config: TrackConfig | \"none\";\n widthInches: number;\n trackOffsetInches: number;\n}\n\n/**\n * Is this end of a board a standard endplate? (#130)\n *\n * ⭐ **Derived, never declared.** The issue is emphatic and the reason is good:\n * a checkbox could be ticked wrongly, and the registry would then promise\n * Free-Dispatcher a mating surface that doesn't exist. So the answer comes from\n * the same rules {@link checkEndplateWidth} already applies to a module's own\n * plates — §1.1's 12″ minimum, and §2.0's 4″ fascia clearance and 1.125″ pair.\n *\n * Two of the standard's conditions aren't checked because they can't be false\n * here: track crosses the face **perpendicular** and a double end's two tracks\n * sit **1.125″ apart** are both true by construction in this model. Inventing\n * fields for them would be inventing ways to be wrong.\n *\n * An end with no config is **undescribed**, which is the ordinary case — most\n * joints inside a module are just joints.\n */\nexport function assessSectionEnd(\n end: SectionEnd | null | undefined,\n opts: { main2Below?: boolean } = {},\n): SectionEndAssessment {\n const config = (end?.config ?? \"none\") as TrackConfig | \"none\";\n const widthInches = endplateWidthInches({ widthInches: end?.widthInches });\n const trackOffsetInches = endplateTrackOffsetInches(\n end?.trackOffsetInches,\n config,\n opts.main2Below,\n );\n // \"Described\" means the owner said what this end PRESENTS. A width alone\n // doesn't make a joint an interface; a track configuration does.\n const described = config === \"single\" || config === \"double\";\n if (!described) {\n return { described: false, conforming: false, issues: [], config, widthInches, trackOffsetInches };\n }\n const issues = checkEndplateWidth({\n widthInches: end?.widthInches,\n config,\n trackOffsetInches: end?.trackOffsetInches,\n main2Below: opts.main2Below,\n });\n return { described: true, conforming: issues.length === 0, issues, config, widthInches, trackOffsetInches };\n}\n\n/** Two board ends meeting at a joint, and whether that joint is a standard\n * interface (#130). */\nexport interface SectionJointAssessment {\n west: SectionEndAssessment;\n east: SectionEndAssessment;\n /** Both ends conform AND present the same number of tracks — so these two\n * boards could be separated and each used against any other module. */\n standardInterface: boolean;\n /** Plain-language reason it isn't one, or null when it is. */\n reason: string | null;\n}\n\n/**\n * Assess a joint — the two board ends that meet there (#130).\n *\n * ⚠️ Track COUNT is the only compatibility rule. Two conforming ends of\n * differing face WIDTH still mate: the standard lets plates differ in width and\n * be offset, so long as the track lines up. That's a deliberate non-check — see\n * the note on endplate width authoring.\n */\nexport function assessSectionJoint(\n west: SectionEnd | null | undefined,\n east: SectionEnd | null | undefined,\n opts: { main2Below?: boolean } = {},\n): SectionJointAssessment {\n const w = assessSectionEnd(west, opts);\n const e = assessSectionEnd(east, opts);\n let reason: string | null = null;\n if (!w.described || !e.described) {\n reason = \"an internal joint — neither end has been described as an interface\";\n if (w.described !== e.described)\n reason = `only the ${w.described ? \"west\" : \"east\"} side is described as an endplate`;\n } else if (!w.conforming || !e.conforming) {\n const bad = !w.conforming ? w : e;\n reason = bad.issues[0]?.message ?? \"an end doesn't meet the standard\";\n } else if (w.config !== e.config) {\n // Single↔double is the one real mismatch: the track counts don't line up.\n reason = `${w.config} meets ${e.config} — the track counts differ`;\n }\n return { west: w, east: e, standardInterface: reason === null, reason };\n}\n\n/** How much of a car-spot span has no rail under it (#194). */\nexport interface SpanOverhang {\n /** Inches the span runs past the track's near end (0 = it starts on track). */\n beforeInches: number;\n /** Inches it runs past the far end. */\n afterInches: number;\n /** The part of the span that IS on the track. */\n onTrackInches: number;\n /** Total overhang — `beforeInches + afterInches`. 0 = the span fits. */\n overhangInches: number;\n}\n\n/**\n * How far a car-spot span runs past the ends of the track it spots on (#194).\n *\n * An industry is a span with a start and an end, and its capacity is computed\n * from those — but nothing checked that the span fits on the siding it's\n * spotting. FMN-0013's \"Team track\" claims 29.8″ → 41″ on a track running\n * 30″ → 39″: about a car and a half of capacity with no rail under it.\n *\n * Both spans are given in the same coordinate (inches along the module) and\n * either may run \"backwards\" — a siding authored east-to-west is ordinary — so\n * both are normalised first.\n */\nexport function spanOverhang(input: {\n fromPos: number;\n toPos: number;\n trackFromPos: number;\n trackToPos: number;\n}): SpanOverhang {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n const tLo = Math.min(input.trackFromPos, input.trackToPos);\n const tHi = Math.max(input.trackFromPos, input.trackToPos);\n const before = Math.max(0, tLo - lo);\n const after = Math.max(0, hi - tHi);\n return {\n beforeInches: before,\n afterInches: after,\n onTrackInches: Math.max(0, Math.min(hi, tHi) - Math.max(lo, tLo)),\n overhangInches: before + after,\n };\n}\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/** Repoint a turnout that diverges into the track it sits on at the OTHER main.\n * A reversed transition whose on-track was later set to the same main stored\n * `onTrack === divergeTrack` (#172): it then had no second route, so\n * `isTransitionTurnout` went false and the module derived as if it had no\n * transition at all — both mains running endplate to endplate. Applied on READ\n * so a doc saved in that state renders correctly everywhere without waiting for\n * its owner to open and re-save it. Returns the same array when nothing needs\n * healing, so untouched docs keep referential identity. */\nfunction healSelfDivergingTurnouts(\n turnouts: SchematicTurnout[] | undefined,\n): SchematicTurnout[] | undefined {\n if (!turnouts?.some((t) => t.onTrack === t.divergeTrack)) return turnouts;\n return turnouts.map((t) => {\n if (t.onTrack !== t.divergeTrack) return t;\n if (t.onTrack === MAIN_TRACK_ID) return { ...t, divergeTrack: MAIN2_TRACK_ID };\n if (t.onTrack === MAIN2_TRACK_ID) return { ...t, divergeTrack: MAIN_TRACK_ID };\n return t; // not a main — nothing sensible to repoint it at\n });\n}\n\n/** Parse a jsonb value into a schematic doc, or null if it isn't one.\n * EVERY read path goes through here (catalog, module page, my-modules, FD), so\n * it's also where a stored doc gets healed — see healSelfDivergingTurnouts. */\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 const doc = d as unknown as ModuleSchematicDoc;\n const healed = healSelfDivergingTurnouts(doc.turnouts);\n return healed === doc.turnouts ? doc : { ...doc, turnouts: healed };\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 /** Measured usable length, real inches (#20). Absent = derived (#19). */\n measuredUsableInches?: number;\n /** `role: \"crossover\"` only — the crossover product this connector was built\n * from. Drives the spacing the pair is DRAWN at (see\n * {@link SchematicTrack.crossoverPartId}). */\n crossoverPartId?: string;\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 /** The library part this turnout IS — see SchematicTurnout.partId. */\n partId?: string;\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 /** The piece this span is held by (ADR 0001). See {@link GraphAnchor}. */\n anchor?: GraphAnchor | 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's configuration — or `\"none\"`, meaning **the module has no far\n * endplate**: an end of the line, a pocket, or a loop's pure turnback. On a\n * loop, a standard endplate B instead makes the balloon an INTERCHANGE (a second\n * route connects there, e.g. Seaford). A module presents one conforming face,\n * or two, or more; the standard governs the faces it offers, not how many (#184). */\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 /**\n * Flex track settings by TRACK id (#193) — which product a run is laid with,\n * and where the owner has decided its rail joints fall.\n *\n * One map rather than fields, because the MAINS aren't `extraTracks` (the main\n * IS the centre-line), so per-track settings would otherwise need a separate\n * pair of fields for Main 1 and Main 2 — four ways to say one thing. Round-trips\n * onto each track in the doc, where it's self-describing for Free-Dispatcher.\n */\n flexByTrack: Record<string, { partId?: string; cuts?: 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 /** Endplate EDGE bindings by id (ADR 0001) — an endplate that is part of the\n * benchwork. Wins over a pose; nothing is auto-converted from one. */\n endplateEdges?: Record<string, EndplateEdge>;\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 /** ⭐ The track as PLACED PIECES (ADR 0001), when the owner drew it that way.\n * Absent = authored the way it always was, and nothing changes. See\n * {@link ModuleSchematicDoc.graph} and {@link deriveGraphDoc}. */\n graph?: ModuleSchematicDoc[\"graph\"];\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 flexByTrack: {},\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 // Everything in the map is an override the owner placed or typed — a derived\n // pose never enters it (poseOverridesFromDoc filters those out on the way in),\n // so it's safe to mark every one authored. That's what stops a derived pose\n // round-tripping into a silent pin, and it cleans an already-affected doc the\n // next time its owner saves (#182).\n return endplates.map((e) =>\n overrides[e.id] ? { ...e, pose: overrides[e.id], poseAuthored: true } : e,\n );\n}\n\n/** Attach endplate EDGE bindings by id (ADR 0001).\n *\n * A binding is not an override — it says the endplate IS this edge of the\n * benchwork, so position, heading and width are read off the board and cannot\n * go stale. Written back verbatim; there is deliberately no conversion from a\n * `pose`, because guessing which edge someone's freehand placement meant would\n * be inventing their intent. */\nfunction withEdges(\n endplates: SchematicEndplate[],\n edges: Record<string, EndplateEdge> | undefined,\n): SchematicEndplate[] {\n if (!edges) return endplates;\n return endplates.map((e) => (edges[e.id] ? { ...e, edge: edges[e.id] } : e));\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/**\n * Attach each track's flex settings (#193). Only what the owner has actually\n * chosen is written: an absent product means the default, and absent cuts mean\n * \"derive them\", which is a different thing from an empty list (that would mean\n * \"one uncut piece, however long the run is\").\n */\nfunction withFlex(state: EditorState, tracks: SchematicTrack[]): SchematicTrack[] {\n return tracks.map((t) => {\n const f = state.flexByTrack?.[t.id];\n if (!f) return t;\n const cuts = f.cuts?.filter((c) => Number.isFinite(c)).sort((a, b) => a - b);\n return {\n ...t,\n ...(f.partId ? { flexPartId: f.partId } : {}),\n ...(cuts ? { flexCuts: cuts } : {}),\n };\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 withEdges(\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 // ⚠️ `configB: \"none\"` means the module HAS NO FAR ENDPLATE, and\n // that is not loop-only (#184). An *end of the line* or a *pocket*\n // presents one conforming face and the track simply stops. The\n // standard governs the ends a module offers for joining; it never\n // required a module to offer two. This used to coerce \"none\" to\n // \"single\" and emit a B regardless, so a single-ended module was\n // impossible to author.\n ...(state.configB !== \"none\"\n ? [\n {\n id: \"B\",\n label: \"East\",\n tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: 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 ), state.endplateEdges),\n state.endplateWidths,\n state.endplateTrackOffsets,\n ),\n // Flex settings are attached to every track at once, at the end — the array\n // below has half a dozen branches and adding two fields to each of them is\n // how they'd end up disagreeing (#193).\n tracks: withFlex(state, [\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 // ⚠️ USABLE capacity, measured from the governing turnouts' CLEARANCE\n // POINTS (#19) — not the drawn rail-to-rail length, which counts track\n // a car can't stand on without fouling the route it diverged from.\n // FMN-0040's 70″ siding is 21 cars drawn and 17 usable.\n capacityFeet: usableCapacity({\n fromPos: t.fromPos,\n toPos: t.toPos,\n governing: state.turnouts.filter((sw) => sw.divergeTrack === t.id),\n measuredUsableInches: t.measuredUsableInches,\n }).scaleFeet,\n ...(typeof t.measuredUsableInches === \"number\" && t.measuredUsableInches >= 0\n ? { measuredUsableInches: t.measuredUsableInches }\n : {}),\n ...(state.loop && t.inLoop ? { inLoop: true } : {}),\n ...(t.crossoverPartId ? { crossoverPartId: t.crossoverPartId } : {}),\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 ...(t.partId ? { partId: t.partId } : {}),\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 // Carried, not interpreted. An anchor is what HOLDS the span (ADR\n // 0001); dropping it here would quietly convert an anchored\n // industry back into a typed number the next time anyone saved.\n ...(ind.anchor ? { anchor: ind.anchor } : {}),\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 // The pieces the owner drew, carried verbatim (ADR 0001). This function\n // stays dumb about them on purpose: deriving here would put the derivation\n // in every save path in both apps. `deriveGraphDoc` is the one place.\n ...(state.graph?.pieces?.length ? { graph: state.graph } : {}),\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 // Keep HUNDREDTHS, not whole inches. Rounding to 1″ silently flattened every\n // authored position on load — Steve's 17.4″ frog read as 17″, Oxnard's 68.4″\n // spur as 68″ — and since the editor autosaves, the rounded value was written\n // back over the owner's measurement. #132 asks owners to type positions taken\n // off XTrkCAD to the tenth, so this was destroying exactly the precision we\n // requested (and left the editor disagreeing with every raw-doc renderer by up\n // to half an inch). Hundredths still absorb float noise from a real rescale.\n const sc = (p: number) => Math.round(p * scale * 100) / 100;\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 // The crossover product this connector was built from — what makes the\n // physical view draw the pair at the spacing it was really built to.\n ...(typeof t.crossoverPartId === \"string\" && t.crossoverPartId\n ? { crossoverPartId: t.crossoverPartId }\n : {}),\n // Authored path kept as-drawn (a physical shape, not rescaled with length).\n ...(trackPath(t.path) ? { path: trackPath(t.path)! } : {}),\n // A MEASURED length is a real-world fact about the physical track, so it\n // rescales with the module exactly as its positions do (#20).\n ...(typeof t.measuredUsableInches === \"number\" && Number.isFinite(t.measuredUsableInches)\n ? { measuredUsableInches: sc(t.measuredUsableInches) }\n : {}),\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 // ⭐ Edge bindings (ADR 0001) — an endplate that IS part of the benchwork.\n // Carried through unscaled: an edge index is a reference, not a dimension.\n const endplateEdges: Record<string, EndplateEdge> = {};\n for (const e of d!.endplates ?? []) {\n if (e.edge && Number.isFinite(e.edge.index) && e.edge.index >= 0)\n endplateEdges[e.id] = {\n index: Math.trunc(e.edge.index),\n ...(e.edge.section ? { section: e.edge.section } : {}),\n ...(Number.isFinite(e.edge.fromT as number) ? { fromT: e.edge.fromT } : {}),\n ...(Number.isFinite(e.edge.toT as number) ? { toT: e.edge.toT } : {}),\n };\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 // Flex settings by track id (#193). Cuts are positions ALONG the run, so they\n // rescale with the module exactly as fromPos/toPos do — a rescaled module\n // whose joints stayed put would have them landing in different places.\n const flexByTrack: Record<string, { partId?: string; cuts?: number[] }> = {};\n for (const t of d!.tracks ?? []) {\n const partId = typeof t.flexPartId === \"string\" && t.flexPartId ? t.flexPartId : undefined;\n // An EMPTY authored list is meaningful — \"no joints, one uncut piece\" — and\n // is a different statement from absent, which means \"derive them\".\n const cuts = Array.isArray(t.flexCuts)\n ? t.flexCuts.filter((c) => Number.isFinite(c)).map(sc).sort((a, b) => a - b)\n : undefined;\n if (partId || cuts) flexByTrack[t.id] = { ...(partId ? { partId } : {}), ...(cuts ? { cuts } : {}) };\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 // NO ENDPLATE B ⇒ \"none\", whatever kind of module this is. On a loop that\n // reads as a pure turnback (a present B makes it an interchange); on an end\n // of the line or a pocket it simply means the module has one face (#184).\n // ⚠️ This used to be `loop && !hasB`, so \"none\" only survived a round trip on\n // a loop — which passed its test yesterday ONLY because a single-endplate\n // module was still being misclassified as one (#191). The absence of the\n // plate is the fact; why it's absent doesn't change what to read.\n configB: hasB ? configOf(\"B\") : \"none\",\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 flexByTrack,\n endplateWidths,\n endplateTrackOffsets,\n endplateEdges,\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 // ⚠️ NOT scaled by `sc()` like every position above it. A piece is placed in\n // real inches on the board; stretching the module's length does not move it,\n // and the length is DERIVED from the pieces anyway when a graph is present.\n ...(d!.graph?.pieces?.length ? { graph: d!.graph } : {}),\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 // Heal a turnout that diverges into the track it sits on (#172) with the\n // same helper the read path uses, so the editor and every renderer agree.\n turnouts: (healSelfDivergingTurnouts(d!.turnouts) ?? []).map((t) => ({\n id: t.id,\n name: t.name ?? \"\",\n pos: sc(t.pos),\n onTrack: t.onTrack,\n divergeTrack: t.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 ...(t.partId ? { partId: t.partId } : {}),\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 ...(s.anchor ? { anchor: s.anchor } : {}),\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 ...(ind.anchor ? { anchor: ind.anchor } : {}),\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 turnout 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 turnout 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/**\n * A route leaving the module at a third endplate — and an endplate is an\n * endplate, whatever letter it carries (#183).\n *\n * There is no split in the standard between \"the two ends\" and \"the others\": an\n * endplate is the standardised face where a module joins another module, and a\n * module may present two, three, or one. So a route to C is drawn the way a\n * route to A or B is drawn — **it runs to the edge of the module and terminates\n * in an endplate face carrying its letter**, rather than stopping partway along\n * the strip as a stub.\n *\n * ⚠️ Because it runs the full width it would otherwise read as just another\n * parallel main, which is exactly the confusion a dispatcher must not have. Its\n * lane is therefore placed with a clear GAP beyond every other lane (see\n * `laneGapFromOthers`), and it ends at a plate rather than running off the edge.\n * The two requirements — full width, and not-a-parallel-main — are in tension by\n * design, and the separation is what resolves it.\n *\n * The LETTER is the module's own fact and is fine to draw. The DESTINATION\n * (\"to Fillmore\") depends on which module is physically attached at that\n * junction, so it stays Free-Dispatcher's to derive at runtime.\n */\nexport interface BranchConnector {\n /** Endplate id — \"C\", \"D\", … */\n id: string;\n /** The owner's local name for the plate. NOT the destination — that depends\n * on what's physically attached, so FD derives it at runtime. */\n label: string;\n /** The route's own name, from the track. */\n name: string;\n /** The branch track's id. */\n trackId: string;\n /** Whether the route IS a main (a diverging/split main) or a secondary\n * branch line. Drives drawn weight, not geometry. */\n kind: \"branch\" | \"main\";\n /** Where it leaves its host main. */\n posFrac: number;\n /** The host track's lane — a branch need not leave Main 1. Renderers must\n * start the diverge HERE, not at a hard-coded lane 0. */\n fromLane: number;\n /** Which side of the module it exits. */\n side: \"up\" | \"down\";\n /** The branch's own lane, signed by `side`, placed a clear GAP beyond every\n * other lane so it can't be mistaken for a parallel main — already folded\n * into laneMin/laneMax. */\n lane: number;\n /** Where the run ends and the endplate face is drawn: the module EDGE, 0 or\n * 1, because this is an end of the module like any other (#183). */\n endFrac: number;\n /** The route's own arc length on this module, inches — for the tooltip. The\n * drawn run is the strip's width, not this. */\n lengthInches: number;\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 /** Whether the module presents a far endplate at all. False for an *end of\n * the line* or a *pocket*, which offer one conforming face and simply stop\n * (#184) — a renderer must not label that end, or it announces a plate the\n * module hasn't got and invites something to be coupled to it (#191). A loop\n * is separate: see {@link loop} and {@link loopInterchange}. */\n hasEndplateB: boolean;\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 */\n/** N-scale track gauge, inches (9 mm). */\nexport const RAIL_GAUGE_INCHES = 0.354;\n/**\n * ⚠️⚠️ **DEAD — REFUTED *AND* BASELESS. NOTHING SHOULD REACH THIS.** Kept only\n * so a library with no measured leads at all still returns a number, and as a\n * record of how the mistake was made.\n *\n * It was points→frog for a #1 frog: a turnout's LEAD if lead were proportional\n * to frog number, from an Atlas #7 measuring 3⅜″ (Steve Branton, #173) ⇒\n * 3.375 / 7.\n *\n * TWO independent things are wrong with it:\n * 1. **Lead is not proportional to N.** Measured lead ÷ N: #5 = 0.600,\n * #7 = 0.513, #10 = 0.494. It reads ~20% SHORT at N=5.\n * 2. **Its founding measurement was superseded.** Will Gage re-measured the same\n * part at 3¹⁹⁄₃₂″, ⁷⁄₃₂″ longer, confirmed against his own points and frog\n * positions. So 0.482 is not even the right constant for the wrong model.\n *\n * {@link leadInchesForSize} now INTERPOLATES across the measured parts instead.\n * A single measurement can only ever be scaled — which is this rule — so the\n * lesson is that one data point cannot support a shape, only a value.\n *\n * A constant-switch-angle model was also proposed here and is likewise REFUTED:\n * inverting {@link turnoutClosure} gives α = 0.036 (#5), 0.067 (#7), 0.043\n * (#10). Kept as a warning — it was floated when the #7 and #10 agreed to 3%,\n * on a #10 figure that later turned out to be measured to the wrong landmark.\n * TWO AGREEING PARTS ARE NOT A LAW, and neither is a coincidence you haven't\n * checked the provenance of.\n *\n * The pattern that currently fits is on {@link ATLAS_CODE55_N}: the moulding\n * runs past the frog far enough to gain a constant 0.25″ of separation. Note it\n * predicts the FROG POSITION, not the lead — this constant has no successor.\n */\nexport const TURNOUT_LEAD_INCHES_PER_FROG = 0.482;\n\n// ---- Track parts library (#179 stage 3) ------------------------------------\n//\n// Real commercial track parts, so a turnout drawn in MR is dimensionally the\n// part the owner will actually lay. Two sources, deliberately kept apart:\n//\n// 1. BUILT-IN parts below — our own data, from manufacturer specs and owner\n// measurements. Dimensions are facts, so this is safe to publish.\n// 2. IMPORTED parts — `parseXtpLibrary()` reads an owner's OWN XTrkCAD .xtp.\n// We deliberately DON'T redistribute those files: they ship with a GPL\n// program, carry individual attribution (\"Design by …\") and no license of\n// their own. Owners who have XTrkCAD already have the data.\n//\n// ⚠️ Every dimension records WHERE IT CAME FROM. Published specs for N-scale\n// turnout leads are scarce — most of what's out there is derived or measured —\n// and a derived number that looks like a spec is how bad geometry becomes\n// permanent. If you improve a value, update its `source` with it.\n\n/** Where a dimension came from. `derived` = we computed it from another part or\n * a rule of thumb; `unverified` = plausible but unconfirmed — treat with care. */\nexport type DimensionSource = \"manufacturer\" | \"measured\" | \"derived\" | \"unverified\";\n\nexport interface PartDimension {\n inches: number;\n source: DimensionSource;\n /** Who measured it / which spec, so it can be re-checked. */\n note?: string;\n}\n\n/** Same provenance discipline as {@link PartDimension}, for angles. */\nexport interface PartAngle {\n deg: number;\n source: DimensionSource;\n note?: string;\n}\n\nexport interface TrackPart {\n /** Stable slug, e.g. \"atlas-c55-n-7\". */\n id: string;\n manufacturer: string;\n /** Product line — \"Code 55\", \"Code 80\". */\n line: string;\n scale: \"N\";\n name: string;\n /** `flex` is track sold by the length rather than as a fixed geometry — its\n * {@link overallLength} is the LONGEST piece you can lay from it, not a shape\n * (#193). */\n /** ⚠️ `crossover` is an ASSEMBLY, not a single turnout. A Fast Tracks\n * crossover fixture builds ONE SYMMETRICAL HALF; you build a second, rotate it\n * 180° and butt the two together at the through routes and the scissors to get\n * a complete DOUBLE CROSSOVER — four turnouts, two diagonals, and the SCISSORS\n * where they cross. ⚠️ Will Gage, 2026-07-26: *\"A double crossover contains\n * the scissors.\"* The scissors is that X, not the whole assembly — do not use\n * it as another name for the part. So it carries {@link trackSpacing} and\n * {@link secondaryFrogAngle}, which no single turnout has, and\n * {@link piecesPerAssembly} — because its lengths describe the HALF, not the\n * finished crossover. */\n kind:\n | \"turnout\"\n | \"wye\"\n | \"curved-turnout\"\n | \"crossover\"\n | \"crossing\"\n | \"flex\"\n /** ⚠️ A SECTIONAL PIECE IS NOT FLEX CUT TO LENGTH, even though the rail ends\n * up in the same place. Its length belongs to the PART and cannot be\n * changed, because an owner has a box of them and cannot cut one — which is\n * the whole reason to model it separately from flex. */\n | \"straight\"\n | \"curve\"\n | \"bumper\";\n /** Manufacturer part numbers by hand, where the part has a hand. */\n partNumbers?: { left?: string; right?: string; single?: string };\n /** Frog number N (the 1:N ratio). Definitional, so no provenance needed. */\n frogNumber?: number;\n /** The angle the part ACTUALLY diverges at, where that's known to differ from\n * the theoretical `atan(1/N)`. Atlas appear to build to SECTIONAL angles\n * (multiples of 11.25° = 1/32 turn) rather than true frog ratios, so a \"#5\" is\n * 11.25° not 11.31°. ⚠️ Currently below our drawing resolution — 0.06° over a\n * 6″ turnout is 0.006″ — so nothing uses this yet. Recorded because it's a\n * real property of the product and will matter if we ever check whether a part\n * mates with sectional track. */\n actualAngle?: PartAngle;\n /** Points → frog. The number that decides where a turnout's throat lands. */\n lead?: PartDimension;\n /** End of the tie strip → the point tips. Where the working turnout starts\n * inside its moulding; the rest of that end is plain approach track. Needed to\n * fit a part into a space, and by any renderer drawing the real outline. */\n pointsOffset?: PartDimension;\n /** End of the tie strip → the APEX OF THE FROG V, measured from the same end\n * as {@link pointsOffset}. ⚠️ The apex, NOT the end of the frog casting — on a\n * shallow #10 those are ¾″ apart, which is how this library recorded a wrong\n * #10 lead through two releases. `lead` is the difference of the two, so\n * prefer these when both are known: they're what someone can actually put a\n * rule against. */\n frogOffset?: PartDimension;\n /** End-to-end length of the part.\n *\n * ⚠️ On a {@link buildable} part this is the manufacturer's DEFAULT length,\n * not a property of the part — the modeller cuts the rail, so their turnout\n * is whatever they built between {@link minimumLength} and as long as they\n * like. */\n overallLength?: PartDimension;\n /** True when the product is a FIXTURE or template rather than a finished\n * turnout — Fast Tracks sell jigs, not parts. The distinction is not cosmetic:\n * a buildable part has no single length, so `overallLength` becomes a default\n * and `minimumLength` a floor, and nothing may infer where an owner's actual\n * turnout ends from either of them. */\n buildable?: boolean;\n /**\n * This part stands in for one nobody has identified — its shape is\n * interpolated, not read off anything.\n *\n * ⛔ A provisional part must never be adopted automatically, offered beside\n * real products as an equal, or allowed to look measured. It exists so an\n * owner who cannot answer \"which turnout is this?\" is not blocked, and so that\n * what they could not answer stays visible afterwards.\n */\n provisional?: boolean;\n /** The shortest the part can be built. Buildable parts only. */\n minimumLength?: PartDimension;\n /** How many identical pieces built on this fixture make ONE finished part.\n *\n * ⚠️ WHEN THIS IS SET, `overallLength` AND `minimumLength` DESCRIBE ONE PIECE,\n * NOT THE FINISHED ITEM. A Fast Tracks crossover fixture builds one half of a\n * double crossover: you build it twice, rotate the second 180°, and butt them\n * together. Its 10.07″ is the half. Absent or 1 means the fixture builds the\n * whole part in one go, which is the case for every turnout and wye here. */\n piecesPerAssembly?: number;\n /** The radius of plain curve this turnout can stand in for, as a\n * layout-planning figure. Fast Tracks publish it; Atlas do not. Nothing draws\n * with it — it is here because it is a real published dimension and dropping\n * it would mean the library could not represent what a manufacturer actually\n * says about their own product. */\n substitutionRadius?: PartDimension;\n /** Frog apex → the end of the diverging rail, measured ALONG that rail. The\n * independent cross-check on {@link frogOffset}: it must be slightly LONGER\n * than the axial `overallLength − frogOffset`, because the rail is the\n * hypotenuse of the angle it leaves at. A reading that makes that difference\n * negative means a mis-read frog — which is exactly how the 2057 wye's frog\n * was caught (see its note). Too insensitive to recover the angle from — at\n * these angles ¹⁄₃₂″ of slop swings the implied half-angle by 6° — so use it\n * to falsify a frog position, never to derive one. */\n divergingLength?: PartDimension;\n /** Diverging route radius (straight turnouts). */\n divergingRadius?: PartDimension;\n /**\n * SECTIONAL CURVE only: the radius it is built to.\n *\n * ⚠️ Distinct from {@link outerRadius}/{@link innerRadius}, which are the two\n * routes of a CURVED TURNOUT. A plain curve has one radius, and giving it the\n * \"outer\" one would say there is another.\n */\n radius?: PartDimension;\n /**\n * SECTIONAL CURVE only: how much of a circle the piece covers, degrees.\n *\n * ⭐ Radius and arc are how curves are SOLD (\"19″ radius, 10°\"), so they are\n * what an owner can read off the box. The piece's length is the arc between\n * them and is never stored — a chord recorded as a length would quietly\n * shorten every curve on the module.\n */\n arcDegrees?: number;\n /** Curved turnouts: the two concentric radii. */\n outerRadius?: PartDimension;\n innerRadius?: PartDimension;\n /** Crossing angle, degrees. */\n crossingAngleDeg?: number;\n /** Centre-to-centre distance of the two parallel tracks a {@link kind}\n * `crossover` joins. A crossover fixture is BUILT for one spacing — it is not\n * adjustable — so this decides whether the part suits a given standard at all.\n *\n * ⚠️ READ {@link FREEMO_TRACK_SPACING_INCHES} ALONGSIDE THIS. Free-moN §2.0\n * fixes double-track spacing at exactly 1.125″; the Fast Tracks N crossovers\n * are built to 1.09″. That 0.035″ is small but it is REAL and it is not a\n * tolerance — the fixture cannot be built to another spacing. Recorded rather\n * than reconciled: it is a fact about the product, and an owner deciding what\n * to buy is better served by the true number than by a convenient one. */\n trackSpacing?: PartDimension;\n /** The SECOND frog angle on a part that has two — the SCISSORS of a double\n * crossover, the X where its two opposite diverging routes meet and cross.\n * Published in degrees. */\n secondaryFrogAngle?: PartAngle;\n /** The part's drawn geometry in its own frame, when it came from a library\n * file. This is the payload worth importing — real outlines we can draw\n * instead of deriving a turnout's shape from a frog number. */\n segments?: PartSegment[];\n /** Connection points, each carrying position AND tangent. The seam a piece\n * graph would snap on (#179 stage 1-2). */\n ends?: PartEnd[];\n /** Set when the part came from an imported library file rather than our own\n * data — names the source so a user can tell where a dimension came from. */\n importedFrom?: string;\n}\n\n/** N-scale code 55 rail height, inches — Atlas publish .055″. */\nexport const CODE55_RAIL_HEIGHT_INCHES = 0.055;\n\n/**\n * Atlas N-scale Code 55 — the Free-moN mainstay.\n *\n * ⚠️ Atlas do not publish leads or overall lengths for the straight turnouts.\n * Everything here traces to physical measurements: Steve Branton's #7 lead\n * (3⅜″ points→frog, #173) and Will Gage's #5/#7/#10 overall lengths plus the\n * #10's lead and points offset. The #5's lead and the wye's are still derived.\n *\n * MEASURED GEOMETRY (all Will Gage's, off physical parts, frog taken at the V):\n *\n * part points frog V overall lead past frog ÷N\n * #5 1¾″ 4.75″ 6.00″ 3.00000″ 1.25″ 0.2500\n * #7 ⁵⁄₈″ 4⁷⁄₃₂″ 6.00″ 3.59375″ 1.78125″ 0.2545\n * #10 ⁹⁄₁₆″ 5.50″ 8.00″ 4.93750″ 2.50″ 0.2500\n * wye points frog V overall lead past frog diverging rail\n * #2.5 1⁵⁄₈″ 4⅛″ 6.50″ 2.50000″ 2.375″ 2.4375″\n * #3.5 ¾″ 3⁵⁄₃₂″ 5.00″ 2.40625″ 1.84375″ 1.9375″\n *\n * ⚠️ THE WYES ARE NOT ON THE ÷N TREND AND MUST NOT BE INTERPOLATED WITH THE\n * TURNOUTS. lead ÷ N is 1.00 and 0.69 against the turnouts' flat 0.25, and the\n * #2.5 is the LONGER part despite the sharper frog. Every size lookup here\n * filters `kind === \"turnout\"`, which is what keeps them out — do not \"fix\"\n * that filter to include wyes.\n *\n * Every one of these is Will Gage's, off a physical part, frog taken at the V.\n * ⚠️ The #7 lead SUPERSEDES Steve Branton's 3⅜″ (#173) — the library's founding\n * measurement, ⁷⁄₃₂″ short. Will's single-span reading and his two positions\n * agree exactly, which is why it wins. Steve's number was also the sole basis of\n * {@link TURNOUT_LEAD_INCHES_PER_FROG}; that constant is now baseless as well as\n * refuted, and {@link leadInchesForSize} interpolates across this table instead.\n *\n * ⭐ **THE PART RUNS PAST THE FROG FAR ENOUGH TO GAIN 0.25″ OF SEPARATION.**\n * Past-frog run ÷ N is 0.2500 / 0.2545 / 0.2500 — the #5 and #10 EXACT, the #7\n * within ¹⁄₃₂″ of the tie end (a 4¼″ frog would make it exact too, one tape\n * division away). Provenance note: the measurer was told that prediction BEFORE\n * re-reading and did not return 4¼″, so this is not a confirmation artefact. At the frog\n * the routes are one gauge apart; at the end of the moulding they are\n * 0.354 + 0.25 ≈ 0.6″ apart. So Atlas size the moulding for a constant\n * CLEARANCE, not a constant length — which is what a manufacturer would\n * sensibly do, and why overall length looks arbitrary until you divide by N.\n * ⚠️ It predicts the FROG POSITION from the overall length. It does NOT predict\n * the lead — the points offset is independent and must still be measured.\n * ⚠️ HYPOTHESIS. It is the FOURTH rule fitted to this data; the first three all\n * died. Two exact hits and a near miss is not a law.\n *\n * NOTHING HERE IS PROPORTIONAL TO FROG NUMBER. Three rules assumed otherwise;\n * all three were tested against a physical part and FAILED:\n * - ❌ **Lead ∝ N.** Measured lead ÷ N: #5 = 0.600, #7 = 0.513, #10 = 0.494.\n * {@link TURNOUT_LEAD_INCHES_PER_FROG} reads ~20% SHORT at N=5 — and its\n * founding measurement has since been superseded, so it is baseless too.\n * - ❌ **Constant switch angle.** Inverting {@link turnoutClosure} gives α =\n * 0.036 (#5), 0.055 (#7), 0.043 (#10). Not constant.\n * - ❌ **Overall length ∝ N.** #5 = 6.00″ and #7 = 6.00″ — same moulding, two\n * frog numbers.\n * - ❌ **Frog fixed at 4.75″** (shipped in 0.54.0, retracted in 0.55.0). It\n * rested on the #5 and #10 both reading 4.75″, but the #10's was the END OF\n * THE FROG CASTING, not the V. Measured consistently the frogs are at 4.75″,\n * 4³⁄₁₆″ and 5.5″ — all different.\n *\n * The definition is the reason: #N fixes the DIVERGENCE RATE AT THE FROG (1\n * across per N along) and says NOTHING about how much tie strip the manufacturer\n * wraps around it, or where inside it the frog goes. Angle is geometry;\n * everything else is a tooling decision. **Measure the part. Do not model it.**\n */\nexport const ATLAS_CODE55_N: TrackPart[] = [\n {\n id: \"atlas-c55-n-5\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#5 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2050\", right: \"2051\" },\n frogNumber: 5,\n lead: {\n inches: 3.0,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2050 (#5 LH): points at 1¾″, frog at 4.75″ ⇒ 3″ \" +\n \"exactly. REFUTED BOTH standing models — the per-frog rule predicted 2.41″, \" +\n \"the constant-switch-angle model 2.64″; both read short. It also retired my \" +\n \"earlier ~2.4″ photo estimate, which was 20% under.\",\n },\n pointsOffset: {\n inches: 1.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH) — end of tie strip to point tips\",\n },\n frogOffset: {\n inches: 4.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH) — tie end to the apex of the V\",\n },\n overallLength: {\n inches: 6.0,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH), end tie to end tie\",\n },\n actualAngle: {\n deg: 11.25,\n source: \"unverified\",\n note:\n \"CORROBORATED: XTrkCAD N-atlasn55.xtp gives 11.250152°, and AnyRail-forum \" +\n \"trial-and-error (glakedylan, 2012) gives 11.25°. Theory atan(1/5) = 11.310°. \" +\n \"11.25° is exactly 1/32 turn — Atlas appear to build to sectional angles.\",\n },\n },\n {\n id: \"atlas-c55-n-7\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#7 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2052\", right: \"2053\" },\n frogNumber: 7,\n lead: {\n inches: 3.59375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7), 3¹⁹⁄₃₂″ points→frog as a single \" +\n \"span — and it matches his two positions exactly (4⁷⁄₃₂ − ⁵⁄₈), so the \" +\n \"reading is internally consistent. SUPERSEDES Steve Branton's 3⅜″ (#173), \" +\n \"which was ⁷⁄₃₂″ short and was the library's founding measurement. \" +\n \"⚠️ Steve's number was also the SOLE basis of \" +\n \"TURNOUT_LEAD_INCHES_PER_FROG (3.375/7 = 0.482) — that constant is now \" +\n \"baseless as well as refuted.\",\n },\n pointsOffset: {\n inches: 0.625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2052 (#7) — ¹⁰⁄₁₆″ tie end to point tips\",\n },\n frogOffset: {\n inches: 4.21875,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7) — 4⁷⁄₃₂″, tie end to the apex of the V. \" +\n \"Supersedes an initial 4³⁄₁₆″. Worth noting for provenance: he was told \" +\n \"beforehand that the clearance hypothesis predicted 4¼″ and did NOT read \" +\n \"4¼″ — so this number is not a confirmation artefact, and it sits ¹⁄₃₂″ \" +\n \"(one tape division) from the predicted value.\",\n },\n overallLength: {\n inches: 6.0,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7), end tie to end tie — the SAME 6″ \" +\n \"as the #5, which is what proves length is not a function of frog number\",\n },\n actualAngle: {\n deg: 8.13,\n source: \"unverified\",\n note:\n \"DISPUTED: XTrkCAD .xtp says 8.1818°, AnyRail forum says 8.125°, theory \" +\n \"atan(1/7) = 8.130°. The sources disagree, so theory is used here.\",\n },\n },\n {\n id: \"atlas-c55-n-10\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#10 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2054\", right: \"2055\" },\n frogNumber: 10,\n lead: {\n inches: 4.9375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2054 (#10): 5.5″ frog − 9/16″ points = 4¹⁵⁄₁₆″. \" +\n \"⚠️ CORRECTED from 4³⁄₁₆″ (0.53.0–0.54.0), which used a 4.75″ frog reading \" +\n \"taken before we'd agreed the landmark. That earlier figure was the END OF \" +\n \"THE FROG CASTING; a #10's V is shallow, so the apex is ¾″ back from it.\",\n },\n pointsOffset: {\n inches: 0.5625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10) — end of tie strip to point tips\",\n },\n frogOffset: {\n inches: 5.5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10) — tie end to the apex of the V\",\n },\n overallLength: {\n inches: 8.0,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10), end tie to end tie\",\n },\n actualAngle: {\n deg: 5.74,\n source: \"unverified\",\n note:\n \"CORROBORATED: XTrkCAD .xtp gives 5.739°, AnyRail forum 5.75° — they agree \" +\n \"with each other and not with theory atan(1/10) = 5.711°.\",\n },\n },\n {\n id: \"atlas-c55-n-wye\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#2.5 Wye\",\n kind: \"wye\",\n partNumbers: { single: \"2056\" },\n frogNumber: 2.5,\n lead: {\n inches: 2.5,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2056, 2026-07-26: points at 1⁵⁄₈″, frog at 4⅛″ ⇒ \" +\n \"2.5″ — the difference of the two offsets, per the rule above. \" +\n \"⚠️ RETIRES a `derived` 1.205″ (2.5 × TURNOUT_LEAD_INCHES_PER_FROG) — the \" +\n \"real lead is more than DOUBLE it. Third independent refutation of the \" +\n \"per-frog rule, and the largest: at low N it is not merely mis-sloped, \" +\n \"it is nowhere near.\",\n },\n pointsOffset: {\n inches: 1.625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — end of tie strip to point tips (1¹⁰⁄₁₆″)\",\n },\n frogOffset: {\n inches: 4.125,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — tie end to the apex of the V (4²⁄₁₆″)\",\n },\n overallLength: {\n inches: 6.5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — end to end\",\n },\n divergingLength: {\n inches: 2.4375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2056 — frog to the end of each diverging rail \" +\n \"(2⁷⁄₁₆″, both legs equal). ✔ CROSS-CHECKS the frog: axial past-frog is \" +\n \"6.5 − 4.125 = 2.375″, and the rail is ¹⁄₁₆″ longer than its own \" +\n \"projection, which is the right sign and the right order of magnitude.\",\n },\n },\n {\n // Will Gage, 2026-07-26: \"2057 is 3.5, 2056 is 2.5\" — the two Atlas Code 55\n // wyes are different FROG NUMBERS, not a left/right pair of one part. The\n // 2056 half of that confirms the entry above; this is the one we didn't have.\n //\n // Fully measured 2026-07-26, after one reading was caught and re-read.\n //\n // ⚠️ WORKED EXAMPLE OF WHY THIS LIBRARY CROSS-CHECKS. The frog first came in\n // at 5⁵⁄₃₂″, which is PAST the part's own 5″ overall length — the apex would\n // have sat beyond the end of the moulding. Two independent lines said ~3⅛″:\n // · points ¾″ + points→frog 2⅜″ = 3.125″\n // · overall 5″ − diverging rail 1³⁰⁄₃₂″ ≈ 3.06″ axial\n // Queried, and Will re-read it as 3⁵⁄₃₂″ — a leading-digit slip, exactly what\n // the arithmetic implied. That re-read is the number recorded here; it was\n // NOT inferred. Had it been taken at face value the wye would have drawn its\n // frog off the end of itself.\n id: \"atlas-c55-n-wye-35\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#3.5 Wye\",\n kind: \"wye\",\n partNumbers: { single: \"2057\" },\n frogNumber: 3.5,\n lead: {\n inches: 2.40625,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057, 2026-07-26: points at ¾″, frog at 3⁵⁄₃₂″ ⇒ \" +\n \"2.40625″ — the difference of the two offsets, per the rule above. His \" +\n \"direct points→frog reading was 2⅜″, ¹⁄₃₂″ short; the offsets win. \" +\n \"⚠️ RETIRES the reasoning in this entry's original note, which left the \" +\n \"lead unset so `leadInchesForSize` would interpolate at the wye's \" +\n \"effective frog (3.5 × 2 = 7) and land on the measured #7's 3.59375″. \" +\n \"That substitution was 49% over.\",\n },\n pointsOffset: {\n inches: 0.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2057 — end of tie strip to point tips (¾″)\",\n },\n frogOffset: {\n inches: 3.15625,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057 — tie end to the apex of the V (3⁵⁄₃₂″). \" +\n \"This is his RE-READ after the first reading (5⁵⁄₃₂″) was queried for \" +\n \"landing past the part's 5″ end; see the comment above this entry.\",\n },\n overallLength: {\n inches: 5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2057 — end to end\",\n },\n divergingLength: {\n inches: 1.9375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057 — frog to the end of each diverging rail \" +\n \"(1³⁰⁄₃₂″, both legs equal). ✔ THE READING THAT CAUGHT THE BAD FROG: \" +\n \"against the first 5⁵⁄₃₂″ the axial past-frog is NEGATIVE, which a 1.9375″ \" +\n \"rail flatly contradicts. Against the re-read 3⁵⁄₃₂″ it is 5 − 3.15625 = \" +\n \"1.84375″, so the rail runs ³⁄₃₂″ longer than its own projection — right \" +\n \"sign, same order as the 2056's ¹⁄₁₆″. (The two differ because this is a \" +\n \"cos() residual on a small angle, which is why the field doc says not to \" +\n \"read an angle back out of it.)\",\n },\n },\n {\n id: \"atlas-c55-n-curved-21-15\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: 'Curved Turnout 21¼\" / 15\"',\n kind: \"curved-turnout\",\n partNumbers: { left: \"2058\", right: \"2059\" },\n outerRadius: { inches: 21.25, source: \"manufacturer\", note: \"Atlas product listing\" },\n innerRadius: { inches: 15, source: \"manufacturer\", note: \"Atlas product listing\" },\n },\n];\n\n/**\n * Flex track — the stuff every run that isn't a turnout or a crossing is made\n * of (#193). A length of flex has no fixed geometry, so the only dimension it\n * carries is **how long a piece you can lay from one**: past that you have\n * another length, with a rail joint between them.\n *\n * ⚠️ These lengths are the NOMINAL PRODUCT LENGTHS as reported by Will Gage\n * (2026-07-26), not values read off a spec sheet or measured. They are what the\n * product is sold as — \"30 inch flex track\" — which is exactly the number a\n * builder plans cuts against, so they're recorded as `manufacturer` with the\n * source named. Correct them if a listing says otherwise.\n *\n * No part numbers here: I don't have them confirmed, and a wrong part number is\n * worse than none — someone would order against it.\n */\nexport const FLEX_TRACK_PARTS: TrackPart[] = [\n {\n id: \"atlas-c55-n-flex\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"Code 55 Flex Track\",\n kind: \"flex\",\n overallLength: {\n inches: 30,\n source: \"manufacturer\",\n note: \"nominal product length, reported by Will Gage 2026-07-26\",\n },\n },\n {\n id: \"me-c55-n-flex\",\n manufacturer: \"Micro Engineering\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"Code 55 Flex Track\",\n kind: \"flex\",\n overallLength: {\n inches: 36,\n source: \"manufacturer\",\n note: \"nominal product length, reported by Will Gage 2026-07-26\",\n },\n },\n];\n\n/**\n * Fast Tracks N-scale assembly fixtures, Micro Engineering Code 55 rail.\n *\n * ⚠️ A DIFFERENT MANUFACTURER PUBLISHES DIFFERENT NUMBERS, and the library has\n * to hold what each one actually says rather than a lowest common denominator.\n * Fast Tracks publish none of Atlas's three landmarks — no points offset, no\n * frog offset, no lead — and four things Atlas never state:\n *\n * straight angle div R default minimum substitution R\n * #4 14.04° 8″ 4.57″ 3.43″ 11″\n * #4.5 12.53° 11″ 5.00″ 3.90″ 14″\n * #5 11.31° 14″ 5.39″ 3.92″ 17″\n * #6 9.46° 23″ 6.26″ 4.30″ 24″\n * #7 8.13° 27″ 7.40″ 5.44″ 34″\n * #8 7.13° 36″ 8.00″ 5.93″ 42″\n * #9 6.34° 50″ 8.38″ 6.42″ 57″\n * #10 5.71° 64″ 9.15″ 6.80″ 70″\n * #12 4.76° 82″ 10.34″ 7.95″ 90″\n *\n * wye angle div R default minimum substitution R\n * #4 14.04° 23″ 4.63″ 3.48″ 27″\n * #5 11.31° 25″ 5.23″ 3.81″ 30″\n * #6 9.46° 35″ 5.99″ 4.30″ 47″\n * #8 7.13° 70″ 8.22″ 5.93″ 94″\n * #10 5.71° 89″ 9.47″ 6.97″ 130″\n *\n * ⭐ **FAST TRACKS BUILD TO TRUE FROG RATIOS.** Every angle above is `atan(1/N)`\n * to the digits published — 14.04, 11.31, 9.46, 8.13, 7.13, 6.34, 5.71, 4.76.\n * Atlas do NOT: they build to SECTIONAL angles (a \"#5\" is 11.25°, a 1/32 turn,\n * against theory's 11.310°). Two manufacturers, two different meanings for the\n * same number on the box, and the difference is real if you ever check whether\n * a part mates with sectional track.\n *\n * ⚠️ THESE ARE FIXTURES, SO THEY HAVE NO LENGTH. The modeller cuts the rail:\n * `overallLength` here is the manufacturer's DEFAULT and `minimumLength` the\n * floor. Because Fast Tracks publish no points offset, {@link partExtent}\n * returns null for every one of them, so none claims a body and flex still runs\n * through it (#193). That is the honest answer — we do not know where an\n * owner's hand-built turnout stops, and guessing from a default length would be\n * inventing a measurement. An owner who measures their own build can enter it,\n * and the admin form's cross-checks will catch a bad reading.\n *\n * Source: handlaidtrack.com product pages, \"Detailed Specifications\" tables,\n * read 2026-07-26. ⚠️ The PDF templates in Will's local reference folder are\n * ENCRYPTED (`/Encrypt /Standard`), so they are deliberately not the source\n * here — the public product pages say the same thing and can be cited.\n */\nexport const FAST_TRACKS_N_ME55: TrackPart[] = (\n [\n // [kind, N, angle°, divergingR, defaultLength, minLength, substitutionR]\n [\"turnout\", 4, 14.04, 8, 4.57, 3.43, 11],\n [\"turnout\", 4.5, 12.53, 11, 5, 3.9, 14],\n [\"turnout\", 5, 11.31, 14, 5.39, 3.92, 17],\n [\"turnout\", 6, 9.46, 23, 6.26, 4.3, 24],\n [\"turnout\", 7, 8.13, 27, 7.4, 5.44, 34],\n [\"turnout\", 8, 7.13, 36, 8, 5.93, 42],\n [\"turnout\", 9, 6.34, 50, 8.38, 6.42, 57],\n [\"turnout\", 10, 5.71, 64, 9.15, 6.8, 70],\n [\"turnout\", 12, 4.76, 82, 10.34, 7.95, 90],\n [\"wye\", 4, 14.04, 23, 4.63, 3.48, 27],\n [\"wye\", 5, 11.31, 25, 5.23, 3.81, 30],\n [\"wye\", 6, 9.46, 35, 5.99, 4.3, 47],\n [\"wye\", 8, 7.13, 70, 8.22, 5.93, 94],\n [\"wye\", 10, 5.71, 89, 9.47, 6.97, 130],\n ] as Array<[\"turnout\" | \"wye\", number, number, number, number, number, number]>\n).map(([kind, n, deg, divR, dflt, min, subR]) => {\n const code = kind === \"wye\" ? \"y\" : \"t\";\n const spec = \"handlaidtrack.com Detailed Specifications, read 2026-07-26\";\n const manufacturer: DimensionSource = \"manufacturer\";\n return {\n id: `fast-tracks-n-me55-${code}-${n}`,\n manufacturer: \"Fast Tracks\",\n line: \"Code 55\",\n scale: \"N\" as const,\n // Named for what the OWNER has, not what Fast Tracks sell. They sell a jig;\n // the person picking this in the editor is holding the turnout they built\n // on it. `buildable` and the AF-… part number carry the fixture fact.\n name: `#${n} ${kind === \"wye\" ? \"Wye\" : \"Turnout\"}`,\n kind,\n partNumbers: { single: `AF-N-${code.toUpperCase()}-${n}-ME55` },\n frogNumber: n,\n buildable: true,\n actualAngle: {\n deg,\n source: manufacturer,\n note: `${spec}. Matches atan(1/${n}) to the published digits — Fast Tracks build to TRUE frog ratios, unlike Atlas's sectional angles.`,\n },\n divergingRadius: { inches: divR, source: manufacturer, note: spec },\n overallLength: {\n inches: dflt,\n source: manufacturer,\n note: `${spec}. The DEFAULT length — this is a fixture, so the builder chooses.`,\n },\n minimumLength: { inches: min, source: manufacturer, note: spec },\n substitutionRadius: { inches: subR, source: manufacturer, note: spec },\n } satisfies TrackPart;\n});\n\n/**\n * Fast Tracks N-scale CROSSOVER fixtures, ME Code 55.\n *\n * crossover angle 2nd frog HALF: default minimum track spacing\n * #6 9.46° 19° 10.07″ 9.31″ 1.09″\n * #8 7.13° 14.3° 13.61″ 13.07″ 1.09″\n *\n * ⚠️⚠️ **THE LENGTHS ABOVE ARE ONE HALF, NOT THE FINISHED CROSSOVER.** Will\n * Gage, 2026-07-26: *\"crossovers are two pieces. the pdf shows half, then you\n * would duplicate this same piece and flip it 180 and butt it up to the through\n * and X.\"* Fast Tracks say the same — *\"Crossovers are constructed by building\n * two symmetrical halves of a crossover in the Assembly Fixture and then joining\n * them to form a complete double crossover\"* — and their own gloss on the\n * length is \"the length of the turnout on the QuickSticks\", i.e. the piece the\n * fixture holds. `piecesPerAssembly: 2` records this so the number cannot be\n * read as the assembly's.\n *\n * ⚠️ THE FINISHED LENGTH IS NOT PUBLISHED, and is deliberately not stored. The\n * two halves are related by a 180° rotation about the scissors, so they cover the\n * same longitudinal span and the finished crossover is plausibly also ~10.07″ —\n * but that is an inference from the symmetry, not a reading, and this library\n * has been burned four times by exactly that kind of plausible reconstruction.\n * If it matters, measure a built one.\n *\n * ⚠️ THESE MAKE A DOUBLE CROSSOVER — four turnouts, two diagonals, and the\n * SCISSORS where the two opposite diverging routes meet and cross in an X.\n * A half carries one full 9.46° frog and HALF of the 19° scissors, which is why\n * the scissors only exists once the second piece is butted up. Not a single\n * crossover: half a scissors is not usable on its own.\n *\n * ⚠️ TERMINOLOGY, from Will Gage 2026-07-26: *\"A double crossover contains the\n * scissors. The location where both opposite diverging routes meet and cross\n * like an 'X'.\"* The scissors is that crossing, NOT another name for the whole\n * part — the assembly is a double crossover. Nor is it this library's\n * `crossing`/diamond kind, which is two tracks crossing with no route choice\n * (#170); the scissors is internal to the crossover.\n *\n * ⚠️⚠️ **THE TRACK SPACING IS 1.09″, AND FREE-moN §2.0 REQUIRES 1.125″.**\n * A crossover fixture is machined for ONE spacing; it is not adjustable. So a\n * crossover hand-built on either of these puts the parallel track 0.035″ closer\n * than the standard, and that difference has to go somewhere — the tracks pinch\n * through the crossover and open back out to meet the endplates, which is fixed\n * at both ends by {@link FREEMO_TRACK_SPACING_INCHES}.\n *\n * Recorded, NOT reconciled. It is 0.9 mm and most builders will absorb it, but\n * it is a property of the product rather than a tolerance, and someone choosing\n * what to buy for a double-track Free-moN module is better served by the true\n * number than a convenient one. Nothing here warns or blocks — that would be a\n * decision for the app, not for a data table.\n *\n * ⭐ THE SECOND FROG IS EXACTLY TWICE THE FIRST — 19° against 2 × 9.46 = 18.92,\n * and 14.3° against 2 × 7.13 = 14.26, both inside the published rounding. That\n * is the diamond, where the two halves' diagonals — each leaving its main at the\n * frog angle, and pointing opposite ways because the second piece is turned\n * 180° — cross each other. It is a free cross-check on the pair, it passes, and\n * it independently corroborates the two-piece build: a part with one frog would\n * have no second angle to publish.\n *\n * ⚠️ A CROSSOVER IS AN ASSEMBLY, so `partExtent` means nothing for it and the\n * turnout size lookups must never see it: `kind` is `\"crossover\"`, and every\n * one of them filters `kind === \"turnout\"`.\n *\n * Atlas make crossover parts too — Will has no figures for them as of\n * 2026-07-26, so there are deliberately no Atlas entries here rather than\n * guessed ones.\n *\n * Source: handlaidtrack.com product pages, read 2026-07-26. Their tables also\n * carry tie size and tie spacing; those describe the QuickSticks tie strip's\n * appearance rather than the track's geometry, so they are not carried here.\n */\nexport const FAST_TRACKS_N_ME55_CROSSOVERS: TrackPart[] = (\n [\n // [N, angle°, secondFrog°, defaultLength, minLength, trackSpacing]\n [6, 9.46, 19, 10.07, 9.31, 1.09],\n [8, 7.13, 14.3, 13.61, 13.07, 1.09],\n ] as Array<[number, number, number, number, number, number]>\n).map(([n, deg, second, dflt, min, spacing]) => {\n const spec = \"handlaidtrack.com Detailed Specifications, read 2026-07-26\";\n const manufacturer: DimensionSource = \"manufacturer\";\n return {\n id: `fast-tracks-n-me55-c-${n}`,\n manufacturer: \"Fast Tracks\",\n line: \"Code 55\",\n scale: \"N\" as const,\n name: `#${n} Double Crossover`,\n kind: \"crossover\" as const,\n partNumbers: { single: `AF-N-C-${n}-ME55` },\n frogNumber: n,\n buildable: true,\n piecesPerAssembly: 2,\n actualAngle: { deg, source: manufacturer, note: `${spec}. atan(1/${n}) exactly.` },\n secondaryFrogAngle: {\n deg: second,\n source: manufacturer,\n note: `${spec}. The SCISSORS of a double crossover — the X where its two opposite diverging routes cross — at 2 × ${deg}° within the published rounding.`,\n },\n overallLength: {\n inches: dflt,\n source: manufacturer,\n note:\n `${spec}. ⚠️ ONE HALF, NOT THE FINISHED CROSSOVER — the fixture builds a ` +\n \"symmetrical half, which you build twice and butt together after turning \" +\n \"the second 180°. Fast Tracks gloss it as \\\"the length of the turnout on \" +\n \"the QuickSticks\\\", i.e. the piece in the jig. The DEFAULT for that \" +\n \"piece; it is a fixture, so the builder chooses.\",\n },\n minimumLength: {\n inches: min,\n source: manufacturer,\n note: `${spec}. The shortest ONE HALF can be built — see the overall length's note.`,\n },\n trackSpacing: {\n inches: spacing,\n source: manufacturer,\n note:\n `${spec}. ${spacing}″, and the fixture cannot be built to another spacing. ` +\n `⚠️ THIS IS NOT A DEPARTURE FROM THE STANDARD. Free-moN §2.0 fixes ` +\n `${FREEMO_TRACK_SPACING_INCHES}″ at the ENDPLATE — \"double track endplates must ` +\n `have a track spacing of 1.125 inches\", with track perpendicular, straight and ` +\n `level for 4″ from the outside face. What the two mains do in between is the ` +\n `module builder's business, and every real double crossover pinches them ` +\n `closer. Earlier wording here called the fixture \"tighter than the standard\", ` +\n `which reads as non-conformance and is wrong.`,\n },\n } satisfies TrackPart;\n});\n\n/** What a track is laid with when nobody has said — the commonest N-scale flex. */\nexport const DEFAULT_FLEX_PART_ID = \"atlas-c55-n-flex\";\n\n/** Every built-in part, across manufacturers. */\n/**\n * A bumper that is not a product.\n *\n * ⭐ DELIBERATELY GENERIC, AND CARRYING NO DIMENSIONS AT ALL. Owners build these\n * out of a tie and a scrap of rail as often as they buy them, and what a bumper\n * MEANS — this end of the track is closed on purpose — does not depend on which\n * one it is. Recording an invented length here would be exactly the mistake the\n * rest of this library exists to avoid; a named product can be added with its\n * own measurement, and will draw at it.\n */\n/** Frog numbers a placeholder is offered for. #6 is the standard's floor for a\n * main line; #4 and #5 are ordinary in yards. Outside the measured 5–10 range\n * the interpolators extrapolate, which is acceptable in a part that already\n * says it is a stand-in. */\nexport const GENERIC_TURNOUT_FROG_NUMBERS = [4, 5, 6, 7, 8, 10] as const;\n\n/**\n * A turnout nobody has identified — \"it's a #6, I don't know whose\".\n *\n * ⭐⭐ **IT IS THE TURNOUT'S WORKING GEOMETRY AND NOTHING ELSE**: points → frog\n * → end, with **no moulded approach track in front of the points**. That is not\n * a shortcut, it is the only honest shape available. `pointsOffset` is the one\n * dimension a frog number cannot yield — the measured Atlas parts read 1.75″,\n * 0.625″ and 0.5625″ for #5, #7 and #10, which is a moulding decision and not\n * geometry, so there is nothing to interpolate along. Zero is therefore not a\n * guess about the owner's part; it says we are modelling the turnout and not\n * some product's tie strip. It is also what a hand-laid turnout actually is.\n *\n * ⭐ **The lead and the length past the frog ARE derivable**, by interpolating\n * the measured parts ({@link leadInchesForSize}, {@link pastFrogInchesForSize})\n * — the same interpolation the 1-D model has always drawn an unidentified `#N`\n * with. Nothing new is invented here; what changes is that it is now labelled.\n *\n * ⚠️ **EVERY DIMENSION IS `derived`.** Two things follow, both wanted:\n * {@link partGeometry} reports `source: \"derived\"`, so any surface can say the\n * shape is provisional; and {@link partExtent} returns **null**, so the drawing\n * declines to claim where this turnout's body ends rather than laundering an\n * interpolation into a boundary an owner would read as measured.\n *\n * ⛔ **NEVER ADOPTED AUTOMATICALLY.** A placeholder is something an owner\n * chooses when they cannot answer; resolving a bare `#6` to one behind their\n * back would be exactly the invention ADR 0001 forbids. See\n * {@link moduleConversionReport}, which excludes provisional parts from both\n * automatic resolution and its candidate list.\n */\nexport function genericTurnoutPart(\n frogNumber: number,\n library = ATLAS_CODE55_N,\n): TrackPart {\n const derived: DimensionSource = \"derived\";\n const lead = leadInchesForSize(frogNumber, library);\n const past = pastFrogInchesForSize(frogNumber, library);\n const why =\n `Interpolated across the measured parts by frog number — a stand-in, not a reading. ` +\n `No points offset: it is not a function of the frog number (the measured #5, #7 and #10 ` +\n `read 1.75″, 0.625″ and 0.5625″), so this part begins AT the points, as a hand-laid ` +\n `turnout does.`;\n return {\n id: `generic-turnout-${frogNumber}`,\n manufacturer: \"Generic\",\n line: \"N scale\",\n scale: \"N\",\n name: `#${frogNumber} Turnout (make unknown)`,\n kind: \"turnout\",\n frogNumber,\n provisional: true,\n pointsOffset: { inches: 0, source: derived, note: why },\n lead: { inches: lead, source: derived, note: why },\n frogOffset: { inches: lead, source: derived, note: why },\n overallLength: { inches: lead + past, source: derived, note: why },\n };\n}\n\n/** The placeholders, one per {@link GENERIC_TURNOUT_FROG_NUMBERS}. */\nexport const GENERIC_TURNOUTS: TrackPart[] = GENERIC_TURNOUT_FROG_NUMBERS.map((n) =>\n genericTurnoutPart(n),\n);\n\n/** Parts that stand in for one nobody has identified — offered only where an\n * owner is being asked what something is, and never mixed in with real products\n * as though they were equivalent. */\nexport function provisionalParts(library = BUILT_IN_TRACK_PARTS): TrackPart[] {\n return library.filter((p) => p.provisional);\n}\n\nexport const GENERIC_END_OF_TRACK: TrackPart[] = [\n {\n id: \"generic-bumper\",\n manufacturer: \"Generic\",\n line: \"N scale\",\n scale: \"N\",\n name: \"Bumper\",\n kind: \"bumper\",\n },\n];\n\nexport const BUILT_IN_TRACK_PARTS: TrackPart[] = [\n ...ATLAS_CODE55_N,\n ...FAST_TRACKS_N_ME55,\n ...FAST_TRACKS_N_ME55_CROSSOVERS,\n ...FLEX_TRACK_PARTS,\n ...GENERIC_END_OF_TRACK,\n // ⚠️ LAST, AND PROVISIONAL. These are stand-ins, not products; every path that\n // resolves a turnout automatically filters them out, and every picker that\n // offers them must say what they are.\n ...GENERIC_TURNOUTS,\n];\n\n/** Every flex product a track can be laid with. */\nexport function flexParts(library = BUILT_IN_TRACK_PARTS): TrackPart[] {\n return library.filter((p) => p.kind === \"flex\");\n}\n\n/**\n * The flex product a track is laid with, falling back to the default rather\n * than to nothing: every non-turnout inch of track IS some product, and a run\n * whose owner hasn't chosen still gets cut into buyable lengths.\n */\nexport function flexPartFor(\n id: string | null | undefined,\n library = BUILT_IN_TRACK_PARTS,\n): TrackPart | null {\n const chosen = id ? library.find((p) => p.id === id && p.kind === \"flex\") : null;\n return chosen ?? library.find((p) => p.id === DEFAULT_FLEX_PART_ID) ?? flexParts(library)[0] ?? null;\n}\n\n/** How long a single piece of this product can be, inches. */\nexport function maxFlexPieceInches(\n id: string | null | undefined,\n library = BUILT_IN_TRACK_PARTS,\n): number {\n return flexPartFor(id, library)?.overallLength?.inches ?? 30;\n}\n\n/** Look a part up by its slug. */\nexport function trackPart(id: string, library = BUILT_IN_TRACK_PARTS): TrackPart | null {\n return library.find((p) => p.id === id) ?? null;\n}\n\n/** One length of flex track in a run — a real object you could pick up (#193). */\nexport interface FlexPiece {\n /** Position in the run, west to east. Stable enough to select and label by. */\n index: number;\n /** Inches along the RUN, not the module — the same coordinate turnouts,\n * industries and signals use, so a piece can be placed without a second\n * geometry to keep in step. */\n fromPos: number;\n toPos: number;\n lengthInches: number;\n /** Longer than the product allows. Only reachable from AUTHORED cuts, or from\n * a run that grew after they were authored — which is precisely when someone\n * needs telling. */\n overlong: boolean;\n /** What this piece butts against at each end: another piece, a part (turnout\n * or crossing), or the end of the run. */\n fromEnd: FlexPieceEnd;\n toEnd: FlexPieceEnd;\n}\n\n/** What a flex piece meets at one of its ends. */\nexport type FlexPieceEnd = \"piece\" | \"part\" | \"runEnd\";\n\n/**\n * A stretch of a run that is NOT flex — a turnout's or a crossing's own body.\n *\n * A **zero-length** span is meaningful: it's a break in the run at a point whose\n * own length we don't know. That's a crossing today — the run stops and starts\n * there, giving a rail joint, but we've measured no crossing part so claiming an\n * extent for it would be inventing one.\n */\nexport interface OccupiedSpan {\n fromPos: number;\n toPos: number;\n}\n\n/** Positions closer than this are the same position — a cut can't be a hair\n * from a turnout's end and mean anything different from being on it. */\nconst FLEX_EPS = 1e-6;\n\n/**\n * Shorter than this and it isn't a piece of track, it's an offcut — nobody\n * joints a tenth of an inch on. Full lengths from the start of a gap can leave\n * one (72.1″ of 36″ flex leaves 0.1″), so the last two get balanced instead.\n * A 6″ tail off a 30″ length is a real piece and is left alone.\n */\nconst FLEX_MIN_PIECE_INCHES = 1;\n\n/**\n * Cut a run into lengths of flex track.\n *\n * The model (#193): everything that isn't a turnout or a crossing is flex, flex\n * comes in pieces of a maximum length, and where two pieces meet is a rail\n * joint — the same joint a turnout makes with the track past it (#189). A 96″\n * main isn't one piece of track; it's four lengths of Atlas flex with three\n * joints in it, which is what someone actually buys and lays.\n *\n * Pieces are **spans of the run**, not free-floating geometry. That's deliberate:\n * `pos` — inches along the run — is what every turnout, industry and signal is\n * placed in, so a piece that carried its own shape would be a second geometry to\n * keep in step with the first. As spans they get identity, a length you can\n * change, and ends that meet their neighbours by construction.\n *\n * `cuts` is the owner's authoring and is **complete when present**: those are\n * the only joints, and a piece that ends up too long is flagged rather than\n * silently re-cut. Absent, the cuts are derived — full lengths from the start of\n * each gap, remainder at the end, which is how you lay it. That's what lets\n * every existing module arrive already cut up without anyone touching it.\n */\nexport function flexPieces(input: {\n fromPos: number;\n toPos: number;\n /** Longest single piece of the product this run is laid with. */\n maxPieceInches: number;\n /** Stretches the run gives up to parts — turnout bodies, crossings. */\n occupied?: OccupiedSpan[] | null;\n /** Authored joint positions, inches along the run. Absent = derive. */\n cuts?: number[] | null;\n}): FlexPiece[] {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n if (!(hi - lo > FLEX_EPS)) return [];\n const max = input.maxPieceInches > FLEX_EPS ? input.maxPieceInches : Infinity;\n\n // The run minus the parts sitting in it. Overlapping bodies are merged first\n // so a crossover's two turnouts don't carve the same inch twice.\n const blocks = (input.occupied ?? [])\n .map((s) => ({\n from: Math.max(lo, Math.min(s.fromPos, s.toPos)),\n to: Math.min(hi, Math.max(s.fromPos, s.toPos)),\n }))\n // Zero-length spans are KEPT — they're breaks at a point of unknown extent\n // (a crossing), and they still end one piece and start the next.\n .filter((s) => s.to - s.from >= -FLEX_EPS && s.from < hi + FLEX_EPS && s.to > lo - FLEX_EPS)\n .sort((a, b) => a.from - b.from);\n const merged: { from: number; to: number }[] = [];\n for (const b of blocks) {\n const last = merged[merged.length - 1];\n if (last && b.from <= last.to + FLEX_EPS) last.to = Math.max(last.to, b.to);\n else merged.push({ ...b });\n }\n const gaps: { from: number; to: number }[] = [];\n let cursor = lo;\n for (const b of merged) {\n if (b.from - cursor > FLEX_EPS) gaps.push({ from: cursor, to: b.from });\n cursor = Math.max(cursor, b.to);\n }\n if (hi - cursor > FLEX_EPS) gaps.push({ from: cursor, to: hi });\n\n const authored = input.cuts != null;\n const out: FlexPiece[] = [];\n for (const g of gaps) {\n // Where this gap gets cut. Authored cuts inside it win outright; otherwise\n // full lengths from its start, remainder at the end.\n let inner: number[];\n if (authored) {\n inner = [...new Set(input.cuts!)]\n .filter((c) => c > g.from + FLEX_EPS && c < g.to - FLEX_EPS)\n .sort((a, b) => a - b);\n } else {\n inner = [];\n for (let at = g.from + max; at < g.to - FLEX_EPS; at += max) inner.push(at);\n // A sliver at the end isn't a piece. Split the last two evenly instead —\n // both stay under the maximum, because together they're at most one full\n // length plus a sliver.\n const tail = g.to - (inner[inner.length - 1] ?? g.from);\n if (inner.length && tail < FLEX_MIN_PIECE_INCHES) {\n const start = inner.length >= 2 ? inner[inner.length - 2] : g.from;\n inner[inner.length - 1] = start + (g.to - start) / 2;\n }\n }\n const bounds = [g.from, ...inner, g.to];\n for (let i = 0; i < bounds.length - 1; i++) {\n const from = bounds[i];\n const to = bounds[i + 1];\n out.push({\n index: out.length,\n fromPos: from,\n toPos: to,\n lengthInches: to - from,\n overlong: to - from > max + FLEX_EPS,\n // The run's own ends are runEnd; anything else is a part body, except\n // where a cut put a neighbouring piece there.\n fromEnd: i > 0 ? \"piece\" : from <= lo + FLEX_EPS ? \"runEnd\" : \"part\",\n toEnd:\n i < bounds.length - 2 ? \"piece\" : to >= hi - FLEX_EPS ? \"runEnd\" : \"part\",\n });\n }\n }\n return out;\n}\n\n/**\n * Which way a turnout faces along its host track: `+1` = its points look toward\n * increasing pos, `-1` = the other way.\n *\n * ⭐ ONE definition. The canvas had this inline for drawing the leg, and the\n * flex solver needs the same answer to know which side of `pos` the moulding\n * extends — a turnout's body is NOT symmetric about its points (an Atlas #7 is\n * about 0.9″ behind them and 5.1″ ahead), so getting the facing wrong moves a\n * rail joint four inches (#193).\n *\n * The rule: the turnout faces the way its diverging track LEAVES, because that's\n * where the frog is. `flipped` is the owner's override — rotating the part 180°\n * faces the points the other way, which is the only thing that can be right for\n * a siding pinned at a module end where the geometry reads ambiguously.\n *\n * `divergeFarPos` is whatever the caller can measure best: the canvas projects\n * the diverging track's real far end back onto the main, the editor uses its\n * authored extent. Same rule either way; only the precision of the input differs.\n */\nexport function turnoutFacing(input: {\n pos: number;\n /** Where the diverging track ends up, in the same coordinate as `pos`. */\n divergeFarPos?: number | null;\n flipped?: boolean;\n}): 1 | -1 {\n const far = input.divergeFarPos;\n const geometric =\n typeof far === \"number\" && Number.isFinite(far)\n ? (Math.sign(far - input.pos) as 1 | -1 | 0) || 1\n : 1;\n return (input.flipped ? -geometric : geometric) as 1 | -1;\n}\n\n/**\n * The stretch of its host run a turnout's moulding occupies (#193) — what flex\n * track has to stop short of on each side.\n *\n * Null when the part hasn't been measured, exactly as {@link partExtent} is:\n * without a real length we don't know where the moulding stops, and a guessed\n * body would put a rail joint on track nobody has checked.\n */\nexport function turnoutOccupiedSpan(input: {\n pos: number;\n extent: PartExtent | null | undefined;\n facing: 1 | -1;\n}): OccupiedSpan | null {\n const e = input.extent;\n if (!e) return null;\n // ⭐⭐ ANCHORED ON THE FROG, because that is what a document's `pos` is (Will,\n // 2026-07-27). This read `behindPoints`/`aheadOfPoints`, which put the whole\n // moulding `lead` too far along the run — 3.59″ on an Atlas #7 — so the flex\n // was cut to stop where the turnout was not.\n const a = input.pos - input.facing * e.behindFrog;\n const b = input.pos + input.facing * e.pastFrog;\n return { fromPos: Math.min(a, b), toPos: Math.max(a, b) };\n}\n\n/**\n * Retype one piece's length: move the rail joint at its far end, and let its\n * NEIGHBOUR take up the difference (#193).\n *\n * That's what cutting one piece longer actually does — the run doesn't grow, so\n * the next piece gets shorter by the same amount. The pair's total is fixed,\n * which is why the value is clamped to it: without that, asking for a length\n * past the next joint silently reorders the cuts and you get back something you\n * didn't ask for.\n *\n * Returns the run's COMPLETE new cut list (`flexCuts`), or null when the piece\n * has no neighbour to trade with — the last piece in a gap butts a turnout or\n * the endplate, and its length is set by what it meets, not by preference.\n */\nexport function resizeFlexPiece(\n pieces: FlexPiece[],\n index: number,\n nextLengthInches: number,\n): number[] | null {\n const piece = pieces[index];\n const next = pieces[index + 1];\n if (!piece || !next) return null;\n if (piece.toEnd !== \"piece\") return null; // butts a part or the run's end\n if (!Number.isFinite(nextLengthInches)) return null;\n const pair = piece.lengthInches + next.lengthInches;\n if (pair < 2 * FLEX_MIN_PIECE_INCHES) return null;\n const want = Math.max(\n FLEX_MIN_PIECE_INCHES,\n Math.min(pair - FLEX_MIN_PIECE_INCHES, nextLengthInches),\n );\n const moved = piece.fromPos + want;\n return pieces\n .filter((p) => p.toEnd === \"piece\")\n .map((p) => (p.index === index ? moved : p.toPos))\n .map((v) => Math.round(v * 1000) / 1000)\n .sort((a, b) => a - b);\n}\n\n/** What a run costs in flex, for someone about to order it (#193). */\nexport function flexUsage(pieces: FlexPiece[]): {\n /** How many separate lengths have to be cut. */\n pieces: number;\n /** Total flex laid, inches — the run minus whatever the parts occupy. */\n totalInches: number;\n /** Pieces the product can't actually supply in one length. */\n overlong: number;\n} {\n return {\n pieces: pieces.length,\n totalInches: pieces.reduce((a, p) => a + p.lengthInches, 0),\n overlong: pieces.filter((p) => p.overlong).length,\n };\n}\n\n/** Half an N-scale tie, inches — a 8′6″ tie is 102″ prototype, /160 ≈ 0.638″.\n * The half-width a tie strip extends either side of the rail it carries, which\n * is what gives a drawn turnout body its width. */\nexport const TIE_HALF_LENGTH_INCHES = 0.319;\n\n/** Where a turnout part physically starts and stops, relative to its POINTS.\n * All inches; `aheadOfPoints` is the end of the tie strip, which is essentially\n * where the diverging rail stops and the owner's flex track begins. */\nexport interface PartExtent {\n /** Points → the near end of the tie strip. Positive = the strip starts this\n * far BEHIND the points (it always does — that end is plain approach track). */\n behindPoints: number;\n /** Points → the far end of the tie strip. */\n aheadOfPoints: number;\n /** Frog → the far end. How much turnout there still is past the frog. */\n pastFrog: number;\n /**\n * Frog → the NEAR end of the tie strip.\n *\n * ⭐⭐ **THIS IS THE ONE A BODY IS MEASURED BACK FROM.** A document's `pos` is\n * the FROG (Will, 2026-07-27), so a turnout occupies\n * `[pos − behindFrog, pos + pastFrog]`. Anchoring on the points instead put\n * every turnout body `lead` too far along — 3.59″ on an Atlas #7.\n *\n * ⚠️ Falls back to `behindPoints` when the frog was never measured: without a\n * frog reading there is nowhere to anchor, and the points is the only landmark\n * left. `pastFrog` degrades the same way, so the pair stays consistent.\n */\n behindFrog: number;\n}\n\n/**\n * A part's real extent, or **null when it hasn't been measured**.\n *\n * ⚠️ This deliberately does NOT fall back to a frog-number rule, unlike\n * {@link leadInchesForSize}. Overall length is not a function of N — the #5 and\n * the #7 are BOTH 6.00″, same tie strip, different frog. Angle is geometry;\n * length is packaging, and packaging can only be looked up. A renderer that\n * gets null should draw no part boundary rather than invent one: the absence is\n * a truthful signal that the library has a gap, and inventing a length here is\n * how hand-built geometry once reached owners as if it were part data.\n *\n * Requires `pointsOffset` and `overallLength`; `pastFrog` additionally needs\n * `frogOffset`. Every dimension must be `measured` — a derived one would launder\n * a guess into a drawing that says \"this is where your turnout ends\".\n */\nexport function partExtent(part: TrackPart | null | undefined): PartExtent | null {\n const pts = part?.pointsOffset;\n const overall = part?.overallLength;\n if (!pts || !overall) return null;\n if (pts.source !== \"measured\" || overall.source !== \"measured\") return null;\n const frog = part?.frogOffset;\n const aheadOfPoints = overall.inches - pts.inches;\n const frogMeasured = frog && frog.source === \"measured\";\n return {\n behindPoints: pts.inches,\n aheadOfPoints,\n pastFrog: frogMeasured ? overall.inches - frog.inches : aheadOfPoints,\n behindFrog: frogMeasured ? frog.inches : pts.inches,\n };\n}\n\n/** The extent of the part a turnout of this frog number IS, or null when no\n * measured part matches EXACTLY. A #6 is not a #5 or a #7 — the nearest part's\n * length says nothing about it (see {@link partExtent}). */\nexport function partExtentForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): PartExtent | null {\n const part = turnoutPartForSize(size, library);\n return part && part.frogNumber === size ? partExtent(part) : null;\n}\n\n/**\n * The closest built-in turnout for a frog number — what a bare `size` maps to\n * when a turnout names no part. Exact match wins; otherwise the nearest frog.\n *\n * ⚠️ TIES ARE BROKEN TOWARD A PART WE CAN ACTUALLY DRAW. Two parts can share a\n * frog number — Atlas sell a #5 and Fast Tracks make a #5 fixture — and only one\n * of them may carry the measured offsets {@link partExtent} needs. Picking by\n * frog number alone would let a part with no geometry win on array order and\n * take the other's body away with it, which is the #193 failure (a turnout that\n * claims no extent has flex drawn straight through it). So: nearest frog first,\n * and among equals, one with a real extent.\n */\nexport function turnoutPartForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): TrackPart | null {\n // ⛔ A PROVISIONAL PART IS NEVER WHAT A BARE `#N` MEANS. It is a stand-in an\n // owner chooses; adopting one here would answer a question nobody asked.\n const turnouts = library.filter(\n (p) => p.kind === \"turnout\" && p.frogNumber != null && !p.provisional,\n );\n if (!turnouts.length) return null;\n const dist = (p: TrackPart) => Math.abs((p.frogNumber as number) - size);\n return turnouts.reduce((best, p) => {\n const d = dist(p);\n const bd = dist(best);\n if (d !== bd) return d < bd ? p : best;\n // Same frog number: prefer the one that can be drawn at its real size.\n if (!partExtent(best) && partExtent(p)) return p;\n return best;\n });\n}\n\n/** Measured leads, ascending by frog number — the interpolation basis. Only\n * `measured` counts: interpolating through a derived value would launder a guess\n * into the sizes either side of it. */\nfunction measuredLeadPoints(library: TrackPart[]): Array<{ n: number; lead: number }> {\n return library\n .filter(\n (p) =>\n p.kind === \"turnout\" &&\n p.frogNumber != null &&\n p.lead?.source === \"measured\" &&\n !p.provisional,\n )\n .map((p) => ({ n: p.frogNumber as number, lead: p.lead!.inches }))\n .sort((a, b) => a.n - b.n);\n}\n\n/**\n * The lead to draw a turnout of this size with. Keeps `frogLegOf` honest without\n * it needing to know the library exists.\n *\n * 1. An exact part match wins — a #7's measurement says nothing about a #4.\n * 2. Otherwise INTERPOLATE piecewise-linearly across the measured parts. This\n * replaced `size × TURNOUT_LEAD_INCHES_PER_FROG`, which was refuted (its\n * error changes sign across the measured range) and is now baseless besides,\n * its founding #7 measurement having been superseded.\n * 3. ⚠️ Outside the measured range the end segments EXTRAPOLATE. Measured leads\n * span N = 5…10, so a #4 or #12 is a projection, not a reading, and the #2.5\n * wye is a long way out. Treat those as placeholders until a part is measured.\n */\nexport function leadInchesForSize(size: number, library = BUILT_IN_TRACK_PARTS): number {\n // An exact part match wins — but it has to be an exact part that HAS a lead.\n // Several makers can sell the same frog number and only some publish a lead:\n // Fast Tracks state an angle and a radius and no landmarks at all, so asking\n // `turnoutPartForSize` for \"the #6\" and reading its (absent) lead would skip\n // straight past an Atlas #6 that had one. Search for the dimension, not the\n // part.\n const exact = library.find(\n (p) => p.kind === \"turnout\" && p.frogNumber === size && p.lead != null && !p.provisional,\n );\n if (exact) return exact.lead!.inches;\n\n const pts = measuredLeadPoints(library);\n if (!pts.length) return size * TURNOUT_LEAD_INCHES_PER_FROG;\n // One measurement can only be scaled; that IS the refuted rule, so say so.\n if (pts.length === 1) return (size / pts[0].n) * pts[0].lead;\n\n let i: number;\n if (size >= pts[pts.length - 1].n) i = pts.length - 2;\n else i = Math.max(0, pts.findIndex((p) => p.n >= size) - 1);\n const lo = pts[i];\n const hi = pts[i + 1];\n const t = (size - lo.n) / (hi.n - lo.n);\n return lo.lead + t * (hi.lead - lo.lead);\n}\n\n/**\n * How far a turnout of this size keeps going PAST its frog — the rest of the\n * moulding, after which the owner's flex track begins.\n *\n * The companion to {@link leadInchesForSize}, and it follows the same rule: an\n * exact measured part wins, otherwise interpolate across the measured ones. Both\n * numbers describe *how long to draw a turnout*, which is a question that always\n * has to be answered — you cannot draw nothing — so a reasoned interpolation is\n * the honest floor, and it is a far better answer than the alternative it\n * replaced (running the diverging route until it arrived parallel with the track\n * it fed, which was 10.79″ on a 6.00″ part).\n *\n * ⚠️ Do NOT confuse this with {@link partExtent}, which returns null rather than\n * guess. The difference is what is being claimed. `partExtent` says \"THIS part\n * stops HERE\" — a statement about a specific product, which may only be made\n * from a measurement. This says \"a turnout of about this frog number runs about\n * this far past its frog\", which is a drawing approximation and is labelled as\n * one: renderers draw the part's boundary only where {@link partExtent} answers.\n */\nexport function pastFrogInchesForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): number {\n const measured = library\n .filter((p) => p.kind === \"turnout\" && p.frogNumber != null)\n .map((p) => ({ n: p.frogNumber as number, ext: partExtent(p) }))\n .filter((p): p is { n: number; ext: PartExtent } => p.ext != null)\n .map((p) => ({ n: p.n, past: p.ext.pastFrog }))\n .sort((a, b) => a.n - b.n);\n\n // Nothing measured at all: fall back to the frog angle itself. A turnout\n // whose rails have separated by about a gauge past the frog is short, but it\n // is bounded and it never claims a length nobody has checked.\n if (!measured.length) return RAIL_GAUGE_INCHES * size;\n if (measured.length === 1) return measured[0].past;\n\n let i: number;\n if (size >= measured[measured.length - 1].n) i = measured.length - 2;\n else i = Math.max(0, measured.findIndex((p) => p.n >= size) - 1);\n const lo = measured[i];\n const hi = measured[i + 1];\n const t = (size - lo.n) / (hi.n - lo.n);\n return Math.max(0, lo.past + t * (hi.past - lo.past));\n}\n\n/** One drawn piece of a part's geometry, in the part's own local frame. */\nexport type PartSegment =\n | { kind: \"straight\"; x0: number; y0: number; x1: number; y1: number }\n | {\n kind: \"curve\";\n radius: number;\n cx: number;\n cy: number;\n startDeg: number;\n extentDeg: number;\n };\n\n/** A connection point on an imported part: position plus the tangent it faces. */\nexport interface PartEnd {\n x: number;\n y: number;\n angleDeg: number;\n}\n\nexport interface ImportedPart {\n /** Raw title, tab-separated in the file: manufacturer, name, part number. */\n title: string;\n manufacturer?: string;\n name?: string;\n partNumber?: string;\n scale?: string;\n ends: PartEnd[];\n segments: PartSegment[];\n}\n\n/**\n * Parse an XTrkCAD `.xtp` parameter file into parts.\n *\n * The format is plain text, record-per-line inside `TURNOUT … END` blocks:\n * `E x y angle` an endpoint\n * `S layer width x0 y0 x1 y1` a straight segment\n * `C layer width radius cx cy a0 ext` a curved segment (radius signed by hand)\n *\n * We parse an owner's OWN file — nothing from XTrkCAD is redistributed. Their\n * geometry is taken as authoritative for part OUTLINES; ⚠️ don't infer frog\n * positions from it, the shipped Atlas file is internally inconsistent (it puts\n * the #5's frog further out than the #7's, which is physically impossible).\n */\nexport function parseXtpLibrary(text: string): ImportedPart[] {\n const parts: ImportedPart[] = [];\n let cur: ImportedPart | null = null;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n if (line.startsWith(\"TURNOUT\")) {\n // TURNOUT <scale> \"<manufacturer>\\t<name>\\t<part no.>\"\n const quoted = line.match(/\"([^\"]*)\"/);\n const scale = line.split(/\\s+/)[1];\n const title = quoted?.[1] ?? \"\";\n const bits = title.split(\"\\t\").map((s) => s.trim()).filter(Boolean);\n cur = {\n title,\n scale,\n manufacturer: bits[0],\n name: bits[1],\n partNumber: bits[2],\n ends: [],\n segments: [],\n };\n continue;\n }\n if (!cur) continue;\n if (line === \"END\") {\n if (cur.ends.length || cur.segments.length) parts.push(cur);\n cur = null;\n continue;\n }\n const n = line.split(/\\s+/);\n const num = (i: number) => Number(n[i]);\n if (n[0] === \"E\" && n.length >= 4) {\n cur.ends.push({ x: num(1), y: num(2), angleDeg: num(3) });\n } else if (n[0] === \"S\" && n.length >= 7) {\n cur.segments.push({ kind: \"straight\", x0: num(3), y0: num(4), x1: num(5), y1: num(6) });\n } else if (n[0] === \"C\" && n.length >= 8) {\n cur.segments.push({\n kind: \"curve\",\n radius: num(3),\n cx: num(4),\n cy: num(5),\n startDeg: num(6),\n extentDeg: num(7),\n });\n }\n }\n return parts;\n}\n\n/** Sample an imported part's segments into polylines, in the part's own frame —\n * XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is\n * `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */\nexport function samplePartSegments(\n segments: PartSegment[],\n stepsPerCurve = 16,\n): BenchworkPoint[][] {\n return segments.map((s) => {\n if (s.kind === \"straight\") {\n return [\n { x: s.x0, y: s.y0 },\n { x: s.x1, y: s.y1 },\n ];\n }\n const r = Math.abs(s.radius);\n const out: BenchworkPoint[] = [];\n for (let i = 0; i <= stepsPerCurve; i++) {\n const a = ((s.startDeg + (s.extentDeg * i) / stepsPerCurve) * Math.PI) / 180;\n out.push({ x: s.cx + r * Math.sin(a), y: s.cy + r * Math.cos(a) });\n }\n return out;\n });\n}\n\n/** Signed difference between two XTrkCAD headings, normalised to (-180, 180]. */\nfunction angleDeltaDeg(a: number, b: number): number {\n let d = ((a - b) % 360 + 540) % 360 - 180;\n if (d === -180) d = 180;\n return d;\n}\n\n/** Pull a frog number out of a part name — \"#5\", \"No. 5\", \"Number 7 Left\".\n * Identification, not measurement: it reads the label the maker printed. */\nexport function frogNumberFromName(name: string | undefined): number | undefined {\n if (!name) return undefined;\n const m = name.match(/(?:#|no\\.?\\s*|number\\s+)(\\d+(?:\\.\\d+)?)/i);\n if (!m) return undefined;\n const n = Number(m[1]);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction importedKind(name: string | undefined): TrackPart[\"kind\"] {\n const s = (name ?? \"\").toLowerCase();\n if (s.includes(\"wye\")) return \"wye\";\n if (s.includes(\"crossing\")) return \"crossing\";\n if (s.includes(\"curved\")) return \"curved-turnout\";\n return \"turnout\";\n}\n\nconst slug = (s: string) =>\n s.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\");\n\n/**\n * Convert a parsed `.xtp` part into a library {@link TrackPart}.\n *\n * ⚠️⚠️ **DELIBERATELY DERIVES NO `lead` AND NO `frogOffset`.** The shipped Atlas\n * file's frog positions are internally inconsistent — it puts the #5's frog\n * FURTHER OUT than the #7's, which cannot be true of physical parts. Every lead\n * in this library is a physical measurement and must stay that way; an imported\n * lead would silently outrank {@link leadInchesForSize}'s interpolation across\n * those measurements, which is exactly the wrong trade.\n *\n * What IS taken: identity (manufacturer, name, part number, frog number), the\n * drawn `segments` and `ends`, and two dimensions the geometry states directly —\n * overall length along the through axis, and the actual divergence angle. Both\n * land as `unverified`, because a community CAD file is not a measurement.\n */\nexport function importedPartToTrackPart(\n part: ImportedPart,\n sourceName = \"imported .xtp\",\n): TrackPart {\n const name = part.name ?? part.title ?? \"Imported part\";\n const manufacturer = part.manufacturer ?? \"Unknown\";\n const note = `from ${sourceName} — community CAD data, not a measurement`;\n const out: TrackPart = {\n id: `xtp-${slug(manufacturer)}-${slug(part.partNumber || name)}`,\n manufacturer,\n name,\n line: \"\",\n scale: \"N\",\n kind: importedKind(name),\n frogNumber: frogNumberFromName(name),\n segments: part.segments,\n ends: part.ends,\n importedFrom: sourceName,\n };\n if (part.partNumber) out.partNumbers = { single: part.partNumber };\n\n const ends = part.ends;\n if (ends.length >= 2) {\n // Span along the axis the part faces at its first end. XTrkCAD headings run\n // CLOCKWISE FROM NORTH, so the unit vector is (sin, cos).\n const a = (ends[0].angleDeg * Math.PI) / 180;\n const ux = Math.sin(a);\n const uy = Math.cos(a);\n const proj = ends.map((e) => (e.x - ends[0].x) * ux + (e.y - ends[0].y) * uy);\n const span = Math.max(...proj) - Math.min(...proj);\n if (span > 0) out.overallLength = { inches: span, source: \"unverified\", note };\n }\n if (ends.length >= 3) {\n // The through end faces opposite the points end; the other one diverges, and\n // the gap between their headings IS the frog angle.\n const rest = ends.slice(1);\n const opposite = rest\n .map((e) => ({ e, off: Math.abs(angleDeltaDeg(e.angleDeg, ends[0].angleDeg + 180)) }))\n .sort((p, q) => p.off - q.off);\n const through = opposite[0].e;\n const diverging = opposite[opposite.length - 1].e;\n const deg = Math.abs(angleDeltaDeg(diverging.angleDeg, through.angleDeg));\n if (deg > 0.01) out.actualAngle = { deg, source: \"unverified\", note };\n }\n return out;\n}\n\n/**\n * A part as an application stores it — one flat row, so the package needs to\n * know nothing about any particular database. Dimensions are plain numbers with\n * a `source` beside each, mirroring {@link PartDimension}.\n */\nexport interface StoredTrackPart {\n slug: string;\n manufacturer: string;\n line: string;\n scale?: string | null;\n name: string;\n kind?: string | null;\n partNumberLeft?: string | null;\n partNumberRight?: string | null;\n partNumberSingle?: string | null;\n frogNumber?: number | null;\n pointsOffsetInches?: number | null;\n pointsOffsetSource?: string | null;\n frogOffsetInches?: number | null;\n frogOffsetSource?: string | null;\n overallLengthInches?: number | null;\n overallLengthSource?: string | null;\n divergingLengthInches?: number | null;\n divergingLengthSource?: string | null;\n minimumLengthInches?: number | null;\n minimumLengthSource?: string | null;\n substitutionRadiusInches?: number | null;\n substitutionRadiusSource?: string | null;\n trackSpacingInches?: number | null;\n trackSpacingSource?: string | null;\n secondaryFrogAngleDeg?: number | null;\n secondaryFrogAngleSource?: string | null;\n buildable?: boolean | null;\n piecesPerAssembly?: number | null;\n leadInches?: number | null;\n leadSource?: string | null;\n outerRadiusInches?: number | null;\n innerRadiusInches?: number | null;\n radiusSource?: string | null;\n /** Sectional curve: its single radius, and how far it turns. */\n radiusInches?: number | null;\n arcDegrees?: number | null;\n actualAngleDeg?: number | null;\n actualAngleSource?: string | null;\n measurementNote?: string | null;\n}\n\nconst asSource = (s: string | null | undefined): DimensionSource =>\n s === \"manufacturer\" || s === \"measured\" || s === \"derived\" ? s : \"unverified\";\n\n/**\n * Convert a stored row into a {@link TrackPart}.\n *\n * The LEAD is derived from the two offsets whenever both are present, rather\n * than read from its own column: they're measured from the same tie end, so\n * their difference is the lead by construction, and a separately-entered lead\n * could silently disagree with the positions it's supposed to summarise. A\n * stored `leadInches` is used only for a part whose offsets aren't known.\n */\nexport function storedPartToTrackPart(row: StoredTrackPart): TrackPart {\n const note = row.measurementNote ?? undefined;\n const dim = (\n inches: number | null | undefined,\n source: string | null | undefined,\n ): PartDimension | undefined =>\n typeof inches === \"number\" && Number.isFinite(inches)\n ? { inches, source: asSource(source), ...(note ? { note } : {}) }\n : undefined;\n\n const points = dim(row.pointsOffsetInches, row.pointsOffsetSource);\n const frog = dim(row.frogOffsetInches, row.frogOffsetSource);\n // Both offsets ⇒ the lead is their difference, and it is only as good as the\n // weaker of the two readings.\n const lead: PartDimension | undefined =\n points && frog\n ? {\n inches: frog.inches - points.inches,\n source:\n points.source === \"measured\" && frog.source === \"measured\"\n ? \"measured\"\n : \"derived\",\n ...(note ? { note } : {}),\n }\n : dim(row.leadInches, row.leadSource);\n\n // ⚠️ EVERY KIND, not a hand-picked few. This allow-list had three entries and\n // silently turned everything else into a TURNOUT — so a stored crossover,\n // flex, bumper or sectional piece came back claiming to be a turnout and was\n // then blocked for having no points offset, blaming a measurement that was\n // never going to exist. Kinds are added to the type often enough that the\n // list has to live next to it.\n const kind = TRACK_PART_KINDS.includes(row.kind as TrackPart[\"kind\"])\n ? (row.kind as TrackPart[\"kind\"])\n : \"turnout\";\n const part: TrackPart = {\n id: row.slug,\n manufacturer: row.manufacturer,\n line: row.line,\n scale: \"N\",\n name: row.name,\n kind,\n };\n const numbers = {\n ...(row.partNumberLeft ? { left: row.partNumberLeft } : {}),\n ...(row.partNumberRight ? { right: row.partNumberRight } : {}),\n ...(row.partNumberSingle ? { single: row.partNumberSingle } : {}),\n };\n if (Object.keys(numbers).length) part.partNumbers = numbers;\n if (typeof row.frogNumber === \"number\") part.frogNumber = row.frogNumber;\n if (points) part.pointsOffset = points;\n if (frog) part.frogOffset = frog;\n const overall = dim(row.overallLengthInches, row.overallLengthSource);\n if (overall) part.overallLength = overall;\n const diverging = dim(row.divergingLengthInches, row.divergingLengthSource);\n if (diverging) part.divergingLength = diverging;\n const minimum = dim(row.minimumLengthInches, row.minimumLengthSource);\n if (minimum) part.minimumLength = minimum;\n const substitution = dim(row.substitutionRadiusInches, row.substitutionRadiusSource);\n if (substitution) part.substitutionRadius = substitution;\n const spacing = dim(row.trackSpacingInches, row.trackSpacingSource);\n if (spacing) part.trackSpacing = spacing;\n if (typeof row.secondaryFrogAngleDeg === \"number\")\n part.secondaryFrogAngle = {\n deg: row.secondaryFrogAngleDeg,\n source: asSource(row.secondaryFrogAngleSource),\n ...(note ? { note } : {}),\n };\n if (row.buildable) part.buildable = true;\n if (typeof row.piecesPerAssembly === \"number\" && row.piecesPerAssembly > 1)\n part.piecesPerAssembly = row.piecesPerAssembly;\n if (lead) part.lead = lead;\n const outer = dim(row.outerRadiusInches, row.radiusSource);\n const inner = dim(row.innerRadiusInches, row.radiusSource);\n if (outer) part.outerRadius = outer;\n if (inner) part.innerRadius = inner;\n // ⚠️ A SECTIONAL CURVE'S OWN RADIUS, not one of a curved turnout's pair.\n // Without this an admin could enter a curve's radius and arc and the part\n // would still come back unplaceable, with the palette blaming a missing\n // radius that had just been typed in.\n const radius = dim(row.radiusInches, row.radiusSource);\n if (radius) part.radius = radius;\n if (typeof row.arcDegrees === \"number\") part.arcDegrees = row.arcDegrees;\n if (typeof row.actualAngleDeg === \"number\")\n part.actualAngle = {\n deg: row.actualAngleDeg,\n source: asSource(row.actualAngleSource),\n ...(note ? { note } : {}),\n };\n return part;\n}\n\n/**\n * Fold an application's STORED library over the built-in one, by slug.\n *\n * ⚠️ Unlike {@link mergeImportedParts}, a stored part **replaces** a built-in\n * outright. That difference is deliberate, and the reason is who is speaking: an\n * import is a third-party file that may have been fitted in someone else's CAD\n * program, so it may only fill gaps. The stored library is seeded FROM these\n * built-ins and edited by an admin with the part in their hand — it is the same\n * library, later. Refusing their correction would mean a wrong dimension could\n * only be fixed by shipping a release, which is exactly the limitation the\n * stored library exists to remove.\n *\n * The built-ins remain the floor: a part nobody has stored still resolves, so\n * geometry keeps working with no database at all.\n *\n * ⛔ THE TRAP THIS CREATES, and it has already been sprung once. Replacement is\n * WHOLESALE, so a stored row that is merely INCOMPLETE deletes every dimension\n * the built-in had. When both Atlas wyes were measured in 0.78.0 their stored\n * rows still held null offsets from the original seed — so in production the\n * new measurements were invisible and the 2056 still carried a `derived` lead\n * the release had just retired. Nothing failed; the parts simply had no\n * dimensions, which is indistinguishable from never having measured them.\n *\n * **Measuring a built-in is therefore not finished until the stored row is\n * updated too.** Adding a dimension here and stopping ships nothing.\n */\nexport function mergeStoredParts(\n stored: StoredTrackPart[],\n library: TrackPart[] = BUILT_IN_TRACK_PARTS,\n): TrackPart[] {\n const bySlug = new Map(library.map((p) => [p.id, p]));\n for (const row of stored) bySlug.set(row.slug, storedPartToTrackPart(row));\n return [...bySlug.values()];\n}\n\n/**\n * Fold imported parts into a library.\n *\n * **Imports never overwrite. Ever.** They may only fill a gap — attach geometry\n * a built-in lacks, or add a part we have no entry for. A dimension already\n * present wins regardless of its source, because our worst built-in value is at\n * least one we can trace, and this library has already been burned once by a\n * plausible number from a CAD file (the constant-switch-angle model was fitted\n * to an `.xtp` figure that turned out to be measured to the wrong landmark).\n *\n * Matching is by manufacturer part number first, then manufacturer + frog number.\n */\nexport function mergeImportedParts(\n imported: ImportedPart[],\n library: TrackPart[] = BUILT_IN_TRACK_PARTS,\n sourceName = \"imported .xtp\",\n): TrackPart[] {\n const out = library.map((p) => ({ ...p }));\n const numbersOf = (p: TrackPart) =>\n [p.partNumbers?.left, p.partNumbers?.right, p.partNumbers?.single]\n .filter(Boolean)\n .map((s) => (s as string).trim().toLowerCase());\n\n for (const raw of imported) {\n const conv = importedPartToTrackPart(raw, sourceName);\n const pn = raw.partNumber?.trim().toLowerCase();\n const match =\n (pn ? out.find((p) => numbersOf(p).includes(pn)) : undefined) ??\n (conv.frogNumber != null\n ? out.find(\n (p) =>\n p.frogNumber === conv.frogNumber &&\n p.kind === conv.kind &&\n p.manufacturer.toLowerCase() === conv.manufacturer.toLowerCase(),\n )\n : undefined);\n\n if (!match) {\n out.push(conv);\n continue;\n }\n // Geometry is the point of importing — take it when we have none.\n if (!match.segments?.length && conv.segments?.length) match.segments = conv.segments;\n if (!match.ends?.length && conv.ends?.length) match.ends = conv.ends;\n if (!match.importedFrom && (conv.segments?.length || conv.ends?.length)) {\n match.importedFrom = sourceName;\n }\n if (!match.overallLength && conv.overallLength) match.overallLength = conv.overallLength;\n if (!match.actualAngle && conv.actualAngle) match.actualAngle = conv.actualAngle;\n }\n return out;\n}\n\n/**\n * A part's drawn outline in TURNOUT-LOCAL coordinates, ready for MR to map onto\n * a lane: `x` = inches along the through route measured **from the frog**\n * (negative back toward the points), `y` = lateral offset with the DIVERGING\n * side positive. That is the same frame {@link turnoutClosure} works in, so a\n * renderer can swap one for the other.\n *\n * ⚠️ **Anchored on OUR measured lead, not the file's frog.** The part is placed\n * so its points sit `leadInches` back from the frog, because `pos` means the\n * frog (#132) and our leads are physical measurements while the shipped Atlas\n * `.xtp`'s frog positions are internally inconsistent. A consequence worth\n * knowing: if the file's own geometry disagrees, its drawn V will not land on\n * the frog marker — and that visible gap IS the validation. Don't \"fix\" it by\n * anchoring on the file.\n *\n * Returns null when the part carries no geometry to draw.\n */\nexport function partOutlineAtFrog(\n part: TrackPart,\n leadInches: number,\n stepsPerCurve = 16,\n): BenchworkPoint[][] | null {\n const ends = part.ends ?? [];\n const segs = part.segments ?? [];\n if (!segs.length || ends.length < 2) return null;\n\n // The two EXIT ends sit close together at the far end; the points end is the\n // odd one out. More robust than assuming the file lists points first.\n let points = ends[0];\n if (ends.length >= 3) {\n let bestPair = Infinity;\n let pairIdx: [number, number] = [1, 2];\n for (let i = 0; i < ends.length; i++) {\n for (let j = i + 1; j < ends.length; j++) {\n const d = Math.hypot(ends[i].x - ends[j].x, ends[i].y - ends[j].y);\n if (d < bestPair) {\n bestPair = d;\n pairIdx = [i, j];\n }\n }\n }\n const odd = ends.findIndex((_, k) => k !== pairIdx[0] && k !== pairIdx[1]);\n if (odd >= 0) points = ends[odd];\n }\n\n // Ends face OUTWARD, so the through direction is the inward normal. XTrkCAD\n // headings run clockwise from north ⇒ the heading vector is (sin, cos).\n const a = (points.angleDeg * Math.PI) / 180;\n const ux = -Math.sin(a);\n const uy = -Math.cos(a);\n // Left-perpendicular, so `y` is a consistent lateral before we fix its sign.\n const toLocal = (p: BenchworkPoint): BenchworkPoint => {\n const dx = p.x - points.x;\n const dy = p.y - points.y;\n return { x: dx * ux + dy * uy, y: dx * -uy + dy * ux };\n };\n\n // Whichever exit end is off-axis is the diverging one; flip so it reads +y.\n let sign = 1;\n const offAxis = ends\n .filter((e) => e !== points)\n .map(toLocal)\n .sort((p, q) => Math.abs(q.y) - Math.abs(p.y))[0];\n if (offAxis && offAxis.y < 0) sign = -1;\n\n return samplePartSegments(segs, stepsPerCurve).map((poly) =>\n poly.map((p) => {\n const l = toLocal(p);\n return { x: l.x - leadInches, y: l.y * sign };\n }),\n );\n}\n\n/** A turnout's CLOSURE — the diverging route's lateral offset from the through\n * route, from the points (s = 0) to the frog (s = lead) and beyond.\n *\n * Anchored on one geometric fact: the FROG is where the two routes' inner rails\n * cross, which happens where the centre-lines are exactly ONE GAUGE apart. So\n * `pos` (which means the frog, #132) must be where d = gauge — otherwise the\n * drawn crossing and the frog marker disagree.\n *\n * The curve is `d(s) = α·s + k·s²`, fixed by three conditions:\n * d(0) = 0 — the points start ON the stock rail\n * d(lead) = gauge — the frog lands exactly on `pos`\n * d'(lead) = 1/N — it leaves at the frog angle\n *\n * ⚠️ `α` is the SWITCH ANGLE and is deliberately non-zero. A curve leaving\n * TANGENT to the stock rail only reaches `lead/2N` of lateral by the frog\n * (0.24″ on a #7) — it could never reach a gauge within a commercial lead; you'd\n * need `lead = 2·gauge·N` ≈ the prototype figure. Real points leave the stock\n * rail at a finite angle, which is exactly why a commercial turnout can be\n * shorter than prototype. Valid while `lead < 2·gauge·N`; α is clamped at 0\n * otherwise so an absurd lead degrades to a tangent start instead of bending\n * backwards. */\nexport interface TurnoutClosure {\n /** Lateral offset from the through route at arc length `s` past the points. */\n offsetAt: (s: number) => number;\n /** Points→frog, inches. */\n lead: number;\n /** Slope at the points (the switch angle), rise over run. */\n switchSlope: number;\n /** Slope at and beyond the frog — the frog angle, 1/N. */\n frogSlope: number;\n /** Total run from the points to where the route arrives PARALLEL at\n * `arriveAtInches`. Infinity when no target was given (the legacy\n * straight-forever behaviour). Use this rather than solving for the offset:\n * solving finds where the route REACHES the lane, not where it arrives\n * parallel, and the difference is a visible kink. */\n span: number;\n /** Length of the easing curve, 0 when not easing. */\n easeInches: number;\n}\n\nexport function turnoutClosure(\n size: number,\n opts: {\n leadInches?: number;\n gaugeInches?: number;\n /**\n * Lateral offset the diverging route must ARRIVE AT, PARALLEL — normally\n * one lane spacing, i.e. the track it feeds.\n *\n * ⚠️ Without this the route runs straight at the frog angle forever, and a\n * caller can only solve for where it first REACHES the offset. Reaching is\n * not arriving: it gets there still climbing at 1/N while the track it\n * joins runs parallel, so the two meet with an instantaneous change of\n * direction. That KINK is what reads as \"the rails don't line up\" — each\n * rail is offset perpendicular to its own heading, so at a kink the two\n * rails meet at different points.\n */\n arriveAtInches?: number;\n /** Length of the easing curve. Defaults to one lead, which puts the radius\n * around 25″ on a #7 — clear of the Free-moN 22″ minimum. */\n easeInches?: number;\n } = {},\n): TurnoutClosure {\n const N = size > 0 ? size : 6;\n const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;\n const lead = Math.max(0.01, opts.leadInches ?? N * TURNOUT_LEAD_INCHES_PER_FROG);\n const frogSlope = 1 / N;\n const k = (lead / N - g) / (lead * lead);\n const switchSlope = Math.max(0, frogSlope - 2 * k * lead);\n\n // Post-frog profile. Straight at the frog angle for `a`, then ease the slope\n // from 1/N to ZERO over `b`, arriving parallel at the target.\n // straight gains m·a ease gains m·b/2 (parabolic, slope m → 0)\n const target = opts.arriveAtInches;\n let a = Infinity;\n let b = 0;\n if (target != null && target > g) {\n b = Math.max(0.01, opts.easeInches ?? lead);\n a = (target - g) / frogSlope - b / 2;\n if (a < 0) {\n // Too close to ease over a full lead — shorten the ease instead of\n // starting it before the frog, which would move the crossing.\n a = 0;\n b = (2 * (target - g)) / frogSlope;\n }\n }\n const span = target != null && target > g ? lead + a + b : Infinity;\n\n return {\n lead,\n switchSlope,\n frogSlope,\n span,\n easeInches: b,\n offsetAt: (s: number) => {\n if (s <= lead) return switchSlope * s + k * s * s;\n const past = s - lead;\n if (past <= a) return g + frogSlope * past;\n if (target == null) return g + frogSlope * past;\n const u = Math.min(past - a, b);\n // slope m at u=0 falling linearly to 0 at u=b\n const eased = g + frogSlope * a + frogSlope * u - (frogSlope * u * u) / (2 * b);\n return past - a >= b ? target : eased;\n },\n };\n}\n\n// ─── PIECE GEOMETRY (ADR 0001) ───────────────────────────────────────────────\n// A part's ENDS, in the part's own frame, so a piece graph has something to\n// snap. `PartEnd` already carried position and tangent for imported .xtp files;\n// what a graph also needs is WHICH end is which, and which ends a train can run\n// between. That is what this section derives, from measurements we already have.\n\n/** Which end of a part this is. A graph connects joints; a walk uses `routes`. */\nexport type PartJointRole =\n | \"throat\"\n | \"through\"\n | \"diverge\"\n | \"divergeB\"\n /** An end of one of the two parallel tracks THROUGH a crossover assembly.\n * A double crossover has four, and none of them is a throat: every end is\n * both a straight route and a crossing route, which is exactly why it is one\n * moulding and not four turnouts. */\n | \"crossoverEnd\";\n\n/** One end of a part, in part-local inches: `x` along the through route from\n * the tie end, `y` lateral toward the diverging side, `angleDeg` the OUTWARD\n * tangent (0 = +x). Named, unlike {@link PartEnd}, because a graph has to know\n * a throat from a frog. */\nexport interface PartJoint extends PartEnd {\n id: string;\n role: PartJointRole;\n}\n\nexport interface PartGeometry {\n joints: PartJoint[];\n /** Joint id pairs a train can run between. A turnout has two routes sharing\n * its throat; flex has one; a double crossover has four. */\n routes: [string, string][];\n /** The weakest provenance among the dimensions used — so a caller can tell a\n * placed-from-measurement part from a placed-from-a-catalogue-figure one. */\n source: DimensionSource;\n /** True when the diverging end came from a measured {@link\n * TrackPart.divergingLength} rather than from assuming the diverging rail\n * leaves the moulding at the same place the through route does. */\n divergingEndMeasured: boolean;\n}\n\n/**\n * A double crossover's geometry, every number of it PUBLISHED rather than\n * guessed — or null when the part does not carry them.\n *\n * ⭐⭐ **A DOUBLE CROSSOVER IS ONE ASSEMBLY, NOT FOUR TURNOUTS** (Will,\n * 2026-07-28). Modelling it as four independent turnout mouldings is what made a\n * rebuild of FMN-0078 collapse: two Atlas #7s 2.5″ apart overlap by 3.5″, so the\n * pieces intersected and the walk emitted a module nobody has. The real thing is\n * a single moulding whose four point-sets sit closer together than four separate\n * turnouts ever could — which is precisely why it is sold as one fixture.\n *\n * ⚠️ **ITS SPACING IS NOT A DEPARTURE FROM THE STANDARD.** Free-moN §2.0 fixes\n * {@link FREEMO_TRACK_SPACING_INCHES} **at the endplate** — \"double track\n * endplates must have a track spacing of 1.125 inches\", perpendicular, straight\n * and level for 4″ from the outside face. What the mains do in between is the\n * builder's business, and every real double crossover pinches them closer.\n *\n * The derivation:\n * - **Length** is `overallLength × piecesPerAssembly`. Fast Tracks' figure is\n * ONE HALF — the fixture builds a symmetrical half you make twice and butt\n * together after turning the second 180°.\n * - **The crossing run** `W = spacing / tan θ` is how far along the track a route\n * takes to cross to the other one. The two point-sets on the SAME track are\n * therefore `W` apart — 6.54″ for a #6 at 1.09″, not the 2.5″ my own FMN-0078\n * fixture claimed.\n * - Both crossing routes are centred on the assembly, so they meet in the middle\n * at `2θ` — which is exactly the {@link TrackPart.secondaryFrogAngle} Fast\n * Tracks publish, an independent check that this reading is right.\n */\nexport function crossoverAssembly(part: TrackPart): {\n /** End to end along the track, both halves. */\n lengthInches: number;\n spacingInches: number;\n /** Along-track distance a crossing route takes to reach the other track. */\n crossingRunInches: number;\n /** Where the four point-sets sit along the assembly. */\n pointsAtInches: [number, number];\n /** The X where the two crossing routes meet — a real diamond in the middle. */\n scissorsAtInches: number;\n} | null {\n const overall = part.overallLength?.inches;\n const spacing = part.trackSpacing?.inches;\n const n = part.frogNumber;\n if (!overall || !spacing || !n) return null;\n const lengthInches = overall * (part.piecesPerAssembly ?? 1);\n // tan θ = 1/N for a frog of number N. Use the part's own measured angle where\n // it has one — Atlas build to sectional angles rather than true frog ratios.\n const tan = part.actualAngle ? Math.tan((part.actualAngle.deg * Math.PI) / 180) : 1 / n;\n if (!(tan > 0)) return null;\n const crossingRunInches = spacing / tan;\n const mid = lengthInches / 2;\n const half = crossingRunInches / 2;\n return {\n lengthInches,\n spacingInches: spacing,\n crossingRunInches,\n pointsAtInches: [mid - half, mid + half],\n scissorsAtInches: mid,\n };\n}\n\n/** The weakest provenance among some dimensions — a placed part is only as\n * trustworthy as the softest number under it. */\nfunction weakestOf(...ds: (PartDimension | undefined)[]): DimensionSource {\n const rank: DimensionSource[] = [\"measured\", \"manufacturer\", \"derived\", \"unverified\"];\n let worst = 0;\n for (const d of ds) if (d) worst = Math.max(worst, rank.indexOf(d.source));\n return rank[worst];\n}\n\n/**\n * Why a part has no derivable geometry — null when it has.\n *\n * Worth its own function because \"we cannot place this yet\" is a fact an owner\n * should see in the picker, not a silent absence. It is also the parts-library\n * backlog in machine-readable form: every string this returns is a measurement\n * someone could take.\n */\nexport function partGeometryGap(part: TrackPart): string | null {\n if (part.kind === \"flex\") return null;\n // ⭐ A BUMPER NEEDS NO MEASUREMENT TO BE PLACEABLE. Its job is to say that an\n // end of track is closed deliberately, and that is true of a hand-built tie\n // bumper as much as of a product. Blocking it for want of a dimension would\n // withhold the one piece whose whole meaning is independent of its size.\n if (part.kind === \"bumper\") return null;\n if (part.kind === \"straight\")\n return part.overallLength ? null : \"no overall length — a sectional straight IS its length\";\n if (part.kind === \"curve\") {\n if (!part.radius) return \"no radius — a sectional curve is a radius and an arc\";\n if (part.arcDegrees == null) return \"no arc — the radius alone does not say how far it turns\";\n return null;\n }\n if (part.kind === \"crossover\") {\n // ⭐ IT IS DERIVABLE AFTER ALL. The published half-length, the fixture's\n // track spacing and its frog angle fix the whole assembly between them —\n // see {@link crossoverAssembly}. What was missing was reading the half as a\n // half, not the geometry.\n if (!part.overallLength) return \"no overall length — nothing says how long the assembly is\";\n if (!part.trackSpacing)\n return \"no track spacing — a crossover is defined by how far apart the two tracks it joins are\";\n if (part.frogNumber == null) return \"no frog number — the crossing angle is unknown\";\n return null;\n }\n if (part.kind === \"crossing\") return \"crossing geometry is not modelled yet\";\n if (part.kind === \"curved-turnout\")\n return \"a curved turnout needs both radii AND its points/frog landmarks; only the radii are published\";\n if (!part.pointsOffset)\n // ⚠️ CONSIDERED AND REJECTED for buildable parts: a fixture's frame could be\n // anchored at the POINTS instead of the tie end, which would make its\n // geometry derivable from the published radius and angle alone. Rejected\n // because it would give one library two different meanings for x=0 — and\n // because a hand-built turnout's tie end is wherever the builder cut, so an\n // owner measuring their own build is the honest source. One reading per\n // size unblocks all fourteen Fast Tracks parts.\n return \"no points offset — without it there is nowhere for the diverging route to begin\";\n if (!part.overallLength) return \"no overall length — the part has no end to put a joint on\";\n if (part.frogNumber == null) return \"no frog number — the diverging angle is unknown\";\n return null;\n}\n\n/**\n * A part's joints and routes, in its own frame.\n *\n * The through route runs along +x from the tie end; the diverging side is +y.\n * A placed piece is this, transformed — which is the whole point: the geometry\n * belongs to the PART, and placement is a rotation and a translation.\n *\n * ⚠️ THE DIVERGING END IS MEASURED WHERE WE HAVE A MEASUREMENT. `divergingLength`\n * (frog → end of the diverging rail, along the rail) says exactly where that end\n * is. Without it we fall back to assuming the diverging rail leaves the moulding\n * at the same x as the through route — which is what `partExtent` has always\n * assumed, and is an assumption, not a reading. `divergingEndMeasured` says\n * which you got.\n */\nexport function partGeometry(\n part: TrackPart,\n library = BUILT_IN_TRACK_PARTS,\n): PartGeometry | null {\n if (partGeometryGap(part)) return null;\n\n if (part.kind === \"straight\" || part.kind === \"curve\") {\n // ⭐ THE SAME ARC DEFINITION BENT FLEX USES (`flexRunEnd`), so a sectional\n // curve and a bent run of flex of the same radius land in exactly the same\n // place. Two definitions of an arc in one library would be a bug waiting\n // for someone to lay one against the other.\n const end =\n part.kind === \"curve\"\n ? flexRunEnd(sectionalArcInches(part), part.radius!.inches)\n : { x: part.overallLength!.inches, y: 0, headingDeg: 0 };\n return {\n joints: [\n { id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b\", role: \"through\", x: end.x, y: end.y, angleDeg: end.headingDeg },\n ],\n routes: [[\"a\", \"b\"]],\n source: (part.kind === \"curve\" ? part.radius : part.overallLength)?.source ?? \"unverified\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"bumper\") {\n // ⭐ ONE JOINT, AND NO ROUTE THROUGH IT — which is the entire point. A\n // bumper is where track STOPS, so the graph closes that end by\n // construction: the joint it takes is no longer open, and the walk that\n // reaches it has nowhere further to go. Nothing has to be flagged.\n return {\n joints: [{ id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 }],\n routes: [],\n source: part.overallLength?.source ?? \"unverified\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"flex\") {\n // Flex has no fixed geometry — it is the one piece a builder cuts. Its ends\n // are a and b; where b sits is the placed piece's business, not the part's.\n return {\n joints: [\n { id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b\", role: \"through\", x: 0, y: 0, angleDeg: 0 },\n ],\n routes: [[\"a\", \"b\"]],\n source: \"derived\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"crossover\") {\n const g = crossoverAssembly(part);\n if (!g) return null;\n return {\n joints: [\n { id: \"a1\", role: \"crossoverEnd\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b1\", role: \"crossoverEnd\", x: g.lengthInches, y: 0, angleDeg: 0 },\n { id: \"a2\", role: \"crossoverEnd\", x: 0, y: g.spacingInches, angleDeg: 180 },\n { id: \"b2\", role: \"crossoverEnd\", x: g.lengthInches, y: g.spacingInches, angleDeg: 0 },\n ],\n // ⭐ FOUR ROUTES, and that is the whole point. From either end of either\n // track a train can run straight on or cross to the other — which is what\n // makes this ONE assembly rather than four turnouts that happen to be near\n // each other.\n routes: [\n [\"a1\", \"b1\"],\n [\"a2\", \"b2\"],\n [\"a1\", \"b2\"],\n [\"a2\", \"b1\"],\n ],\n source: weakestOf(part.overallLength, part.trackSpacing),\n divergingEndMeasured: false,\n };\n }\n\n const N = part.frogNumber as number;\n const points = part.pointsOffset!;\n const overall = part.overallLength!;\n const frog = part.frogOffset;\n const lead = part.lead?.inches ?? (frog ? frog.inches - points.inches : undefined);\n if (lead == null || !(lead > 0)) return null;\n\n // A wye splits SYMMETRICALLY: each leg takes HALF the divergence, so each\n // behaves as a #2N. Same rule `frogLegOf` uses — one definition, two callers.\n const isWye = part.kind === \"wye\";\n const effN = isWye ? N * 2 : N;\n const closure = turnoutClosure(effN, { leadInches: lead });\n\n /** The diverging route's end: measured along the rail when we have it. */\n const divergingEnd = (): { x: number; y: number; measured: boolean } => {\n const frogX = frog ? frog.inches : points.inches + lead;\n const slope = closure.frogSlope;\n const dir = 1 / Math.hypot(1, slope); // unit x-component along the rail\n if (part.divergingLength) {\n // Frog → end of the diverging rail, ALONG the rail.\n const L = part.divergingLength.inches;\n return {\n x: frogX + L * dir,\n y: closure.offsetAt(frogX - points.inches) + L * slope * dir,\n measured: true,\n };\n }\n return {\n x: overall.inches,\n y: closure.offsetAt(overall.inches - points.inches),\n measured: false,\n };\n };\n\n const weakest = (...ds: (PartDimension | undefined)[]): DimensionSource => {\n const rank: DimensionSource[] = [\"measured\", \"manufacturer\", \"derived\", \"unverified\"];\n let worst = 0;\n for (const d of ds) if (d) worst = Math.max(worst, rank.indexOf(d.source));\n return rank[worst];\n };\n\n const de = divergingEnd();\n const legAngle = (Math.atan(closure.frogSlope) * 180) / Math.PI;\n\n if (isWye) {\n // Both legs diverge, mirrored. There is no straight through route — which is\n // exactly why a wye has no hand.\n return {\n joints: [\n { id: \"throat\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"legA\", role: \"diverge\", x: de.x, y: de.y, angleDeg: legAngle },\n { id: \"legB\", role: \"divergeB\", x: de.x, y: -de.y, angleDeg: -legAngle },\n ],\n routes: [\n [\"throat\", \"legA\"],\n [\"throat\", \"legB\"],\n ],\n source: weakest(points, overall, frog, part.divergingLength),\n divergingEndMeasured: de.measured,\n };\n }\n\n return {\n joints: [\n { id: \"throat\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"through\", role: \"through\", x: overall.inches, y: 0, angleDeg: 0 },\n { id: \"diverge\", role: \"diverge\", x: de.x, y: de.y, angleDeg: legAngle },\n ],\n routes: [\n [\"throat\", \"through\"],\n [\"throat\", \"diverge\"],\n ],\n source: weakest(points, overall, frog, part.divergingLength),\n divergingEndMeasured: de.measured,\n };\n}\n\n/**\n * The SHAPE of every route through a placed piece, in MODULE inches — the\n * polyline a renderer draws.\n *\n * ⭐ The shape belongs to the PART, so it lives here rather than in either app's\n * canvas. A diverging route drawn as a straight chord from throat to diverging\n * end cuts the corner the closure actually turns; every renderer would have to\n * rebuild that curve, and they would drift.\n *\n * ⚠️ Each polyline ENDS EXACTLY ON ITS JOINTS, by construction — the samples in\n * between follow the closure, but the ends are the joint positions themselves.\n * Track that stops short of its own joint would draw a gap at a connection that\n * the graph considers made.\n */\nexport function pieceRoutePaths(\n piece: TrackPiece,\n library = BUILT_IN_TRACK_PARTS,\n): { route: [string, string]; points: { x: number; y: number }[] }[] {\n const part = library.find((p) => p.id === piece.partId);\n if (!part) return [];\n const geo = partGeometry(part, library);\n if (!geo) return [];\n const joints = placedJoints([piece], library);\n const at = (id: string) => joints.find((j) => j.joint === id);\n\n // Sample the closure between the points and the diverging end, in the part's\n // own frame, then put it through the same transform the joints went through.\n const RAD = Math.PI / 180;\n const c = Math.cos(piece.rotationDeg * RAD);\n const s = Math.sin(piece.rotationDeg * RAD);\n const place = (x: number, y: number) => {\n const ly = piece.flipped ? -y : y;\n return { x: piece.x + x * c - ly * s, y: piece.y + x * s + ly * c };\n };\n\n const out: { route: [string, string]; points: { x: number; y: number }[] }[] = [];\n\n // ⚠️ A BUMPER HAS NO ROUTE, so the loop below would draw nothing at all and\n // the piece would be invisible and un-clickable. This polyline is its BODY,\n // not a path through it — the repeated joint id says there is nowhere to go.\n if (part.kind === \"bumper\") {\n const at = joints[0];\n if (!at) return out;\n const len = part.overallLength?.inches ?? BUMPER_DRAWN_INCHES;\n return [{ route: [\"a\", \"a\"], points: [{ x: at.x, y: at.y }, place(len, 0)] }];\n }\n\n // ⚠️ A SECTIONAL CURVE IS AN ARC AND MUST BE DRAWN AS ONE. Its joints land in\n // the right place either way, so this looks correct until you notice the rail\n // cutting the corner between them — the same mistake as drawing a turnout's\n // diverging route as a chord, arriving by a different door.\n if (part.kind === \"curve\") {\n const a = joints.find((j) => j.joint === \"a\");\n const b = joints.find((j) => j.joint === \"b\");\n if (!a || !b) return out;\n // `place` already mirrors a flipped piece, so the radius stays positive here\n // — negating it too would flip it back.\n const pts = flexRunPoints(sectionalArcInches(part), part.radius!.inches).map((q) =>\n place(q.x, q.y),\n );\n pts[pts.length - 1] = { x: b.x, y: b.y };\n return [{ route: [\"a\", \"b\"], points: pts }];\n }\n\n // ⚠️ A CROSSING ROUTE IS NOT A DIAGONAL FROM END TO END. It runs straight\n // along its own track to the point-set, crosses at the frog angle, and runs\n // straight again — so drawn as a chord the rail would leave the railhead for\n // most of the assembly and the scissors X would land nowhere near the middle.\n // Same mistake as drawing a sectional curve as its chord, arriving by another\n // door (that one shipped, because the JOINTS are right either way).\n if (part.kind === \"crossover\") {\n const g = crossoverAssembly(part);\n if (g) {\n const [p1, p2] = g.pointsAtInches;\n const S = g.spacingInches;\n const L = g.lengthInches;\n const yOf = (id: string) => (id.endsWith(\"2\") ? S : 0);\n return geo.routes.map((route) => {\n const [from, to] = route;\n const y0 = yOf(from);\n const y1 = yOf(to);\n // Which end each joint is at: \"a\" west (x=0), \"b\" east (x=L).\n const x0 = from.startsWith(\"a\") ? 0 : L;\n const x1 = to.startsWith(\"a\") ? 0 : L;\n if (y0 === y1)\n return { route, points: [place(x0, y0), place(x1, y1)] }; // straight through\n // Crossing: straight to the near point-set, over, then straight on.\n const west = Math.min(x0, x1) === 0;\n const [xa, xb] = west ? [p1, p2] : [p2, p1];\n return {\n route,\n points: [place(x0, y0), place(xa, y0), place(xb, y1), place(x1, y1)],\n };\n });\n }\n }\n\n for (const route of geo.routes) {\n const a = at(route[0]);\n const b = at(route[1]);\n if (!a || !b) continue;\n const ends = [{ x: a.x, y: a.y }, { x: b.x, y: b.y }];\n if (part.kind === \"flex\") {\n // Bent flex is an arc; straight flex comes back as its two ends.\n const pts = flexRunPoints(piece.lengthInches ?? 0, piece.radiusInches).map((q) =>\n place(q.x, q.y),\n );\n pts[pts.length - 1] = { x: b.x, y: b.y };\n out.push({ route, points: pts });\n continue;\n }\n const diverging = route.some((r) => r === \"diverge\" || r === \"legA\" || r === \"legB\");\n if (!diverging) {\n out.push({ route, points: ends });\n continue;\n }\n const lead = part.lead?.inches ?? 0;\n const pts0 = part.pointsOffset?.inches ?? 0;\n const far = geo.joints.find((j) => j.id === route[1]) ?? geo.joints.find((j) => j.id === route[0]);\n if (!far || !(lead > 0)) {\n out.push({ route, points: ends });\n continue;\n }\n const isWye = part.kind === \"wye\";\n const closure = turnoutClosure(isWye ? (part.frogNumber as number) * 2 : (part.frogNumber as number), {\n leadInches: lead,\n });\n // The route runs straight to the points, then follows the closure. `legB` is\n // the mirror of `legA` — a wye splits symmetrically, which is the same rule\n // its joints were placed by.\n const mirror = route.includes(\"legB\") ? -1 : 1;\n const pts: { x: number; y: number }[] = [place(0, 0), place(pts0, 0)];\n const steps = 12;\n for (let i = 1; i <= steps; i++) {\n const x = pts0 + ((far.x - pts0) * i) / steps;\n pts.push(place(x, mirror * closure.offsetAt(x - pts0)));\n }\n // End ON the joint: the sampled curve and the joint are worked out the same\n // way, but only this makes them the same number.\n pts[pts.length - 1] = { x: b.x, y: b.y };\n out.push({ route, points: route[0] === \"throat\" ? pts : pts.slice().reverse() });\n }\n return out;\n}\n\n/**\n * The HAND of a placed piece — the product an owner would actually buy.\n *\n * ⭐ THE MODEL HAS NO HAND, AND THIS IS NOT A CONTRADICTION. Nothing derived\n * from the graph asks which way a turnout is handed: the side a route leaves on\n * is simply where the piece is (ADR 0001). But a turnout on a shelf IS a\n * left-hand or a right-hand product, with its own part number, and an owner\n * picking one out of a palette is choosing between two things they could own.\n * So the hand belongs at the point of PURCHASE and PLACEMENT, and nowhere after.\n *\n * ⚠️ UNFLIPPED IS THE LEFT-HAND PART. A part's own frame diverges toward +y, and\n * +y is to the left of the through route looking from the throat — which agrees\n * with the library: the Atlas #7's `partNumbers.left` (2052) is the one whose\n * published geometry these dimensions were read from.\n *\n * Null for a part with no hand to have — a wye splits symmetrically, which is\n * exactly why it is sold as one product.\n */\nexport function pieceHand(part: TrackPart, flipped?: boolean | null): \"left\" | \"right\" | null {\n const n = part.partNumbers;\n if (!n?.left || !n?.right) return null;\n return flipped ? \"right\" : \"left\";\n}\n\n/** The part number a placed piece corresponds to — what to order. */\nexport function piecePartNumber(part: TrackPart, flipped?: boolean | null): string | undefined {\n const hand = pieceHand(part, flipped);\n if (!hand) return part.partNumbers?.single;\n return part.partNumbers?.[hand];\n}\n\n/** Every part that can be PLACED on a board today, and every one that can only\n * be named — with the reason. The gap list is the parts backlog. */\nexport function partsPlaceable(library = BUILT_IN_TRACK_PARTS): {\n placeable: TrackPart[];\n blocked: { part: TrackPart; why: string }[];\n} {\n const placeable: TrackPart[] = [];\n const blocked: { part: TrackPart; why: string }[] = [];\n for (const p of library) {\n const why = partGeometryGap(p);\n if (why) blocked.push({ part: p, why });\n else if (partGeometry(p, library)) placeable.push(p);\n else blocked.push({ part: p, why: \"dimensions present but inconsistent\" });\n }\n return { placeable, blocked };\n}\n\n// ─── THE TRACK GRAPH (ADR 0001) ──────────────────────────────────────────────\n// Pieces placed on the board; joints that coincide are connected. Everything\n// positional — `pos`, a siding's extent, which track hosts a turnout — is READ\n// OFF this by walking it, rather than authored separately and reconciled.\n\n/** A part placed on the benchwork. */\nexport interface TrackPiece {\n id: string;\n /** A slug from the parts library. */\n partId: string;\n /** Where the part's own origin sits, in module-local inches. */\n x: number;\n y: number;\n /** Rotation about that origin, degrees. */\n rotationDeg: number;\n /** Mirrored across its own through route — a left-hand turnout from a right. */\n flipped?: boolean;\n /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001).\n * ⚠️ ARC length when the run is bent — the rail, not the chord across it. */\n lengthInches?: number;\n /**\n * FLEX ONLY: the radius this run is bent to, inches. Absent = straight.\n *\n * ⭐ It lives on the PIECE, not the part, because bending flex is what a\n * builder does to it — the product is the same product either way. That is\n * the same reason `lengthInches` is here.\n *\n * ⭐ SIGNED, and the sign IS the side: positive curves toward +y in the\n * piece's own frame, negative the other way. One number, no separate\n * \"direction\" field to disagree with it — the same reasoning that keeps a\n * hand off turnouts, where the side is simply where the piece is.\n *\n * ⚠️ {@link lengthInches} stays the ARC length. `pos` is arc length\n * everywhere in this model, a curve's rail is genuinely longer than the chord\n * it spans (a 90° corner at R30 runs 47.1″ across a 42.4″ chord), and it is\n * the rail a train travels.\n */\n radiusInches?: number;\n /** Owner's label, carried onto whatever route this piece ends up in. */\n name?: string;\n}\n\n/** A piece's joint, in MODULE coordinates. */\nexport interface PlacedJoint {\n /** `\"<pieceId>.<jointId>\"` — stable, and what connections refer to. */\n key: string;\n piece: string;\n joint: string;\n role: PartJointRole;\n x: number;\n y: number;\n headingDeg: number;\n}\n\n/** Two joints in the same place. That is the entire connection rule. */\nexport interface GraphConnection {\n a: string;\n b: string;\n}\n\n/**\n * More than two joints in one place — REFUSED, not resolved.\n *\n * ⚠️ THIS IS THE GAP THE SPIKE FOUND, and the one that would bite owners. With\n * three ends stacked on a point, picking a pair silently drops a piece out of\n * the layout: the walk never reaches it, and nothing says so. So none of them\n * connect and the ambiguity is reported. Refusing is the only honest answer —\n * the model cannot know which two the owner meant.\n */\nexport interface GraphConflict {\n x: number;\n y: number;\n joints: string[];\n reason: string;\n}\n\nexport interface TrackGraph {\n joints: PlacedJoint[];\n connections: GraphConnection[];\n /** Joints connected to nothing — an unfinished layout, which is a real thing\n * to show an owner rather than quietly draw as if it were joined. */\n open: string[];\n conflicts: GraphConflict[];\n /** Pieces whose part has no derivable geometry (see {@link partGeometryGap}). */\n unplaceable: { piece: string; partId: string; why: string }[];\n}\n\n/** How close two joints must be to count as connected. A hundredth of an inch:\n * tight enough that nothing joins by accident, loose enough to absorb the\n * rounding of a drag. */\nexport const JOINT_SNAP_INCHES = 0.01;\n\n/**\n * How long a bumper draws when it is not a named product.\n *\n * ⚠️ A DRAWING DEFAULT, NOT A MEASUREMENT, and deliberately not recorded as one\n * on any part. What a bumper is FOR — saying this end of the track is closed on\n * purpose — does not depend on its length, and plenty are a tie and a bit of\n * scrap. A named product supplies its own `overallLength` and this stops\n * applying.\n */\n/** Every kind of part the library can hold. Beside the type it mirrors, so a\n * new kind is one edit and not two. */\nexport const TRACK_PART_KINDS: TrackPart[\"kind\"][] = [\n \"turnout\",\n \"wye\",\n \"curved-turnout\",\n \"crossover\",\n \"crossing\",\n \"flex\",\n \"straight\",\n \"curve\",\n \"bumper\",\n];\n\nexport const BUMPER_DRAWN_INCHES = 0.75;\n\n/**\n * How long a sectional curve's RAIL is — the arc, not the chord across it.\n *\n * ⚠️ Curves are sold as a radius and an arc, never as a length, and the chord is\n * always shorter. Recording one as the piece's length would put everything past\n * that curve closer to endplate A than it is — the same mistake the walk exists\n * to avoid, arriving through the parts library instead.\n */\nexport function sectionalArcInches(part: TrackPart): number {\n if (part.kind !== \"curve\" || !part.radius || part.arcDegrees == null) return 0;\n return (part.radius.inches * Math.abs(part.arcDegrees) * Math.PI) / 180;\n}\n\n/**\n * Where a bent run's far end lands, and which way it points — in the piece's own\n * frame, starting at its origin heading +x.\n *\n * ONE definition, called by both {@link placedJoints} and\n * {@link pieceRoutePaths}, so the drawn rail cannot arrive anywhere other than\n * the joint at the end of it.\n */\nexport function flexRunEnd(\n lengthInches: number,\n radiusInches?: number,\n): { x: number; y: number; headingDeg: number } {\n const L = lengthInches;\n const R = radiusInches;\n if (!R || !Number.isFinite(R) || Math.abs(R) < 1e-6)\n return { x: L, y: 0, headingDeg: 0 };\n // Sweep follows from the two of them: a length of rail bent to a radius has\n // no freedom left. Positive R turns toward +y.\n const theta = L / R;\n return {\n x: Math.abs(R) * Math.sin(Math.abs(theta)) * Math.sign(L || 1),\n y: R * (1 - Math.cos(theta)),\n headingDeg: (theta * 180) / Math.PI,\n };\n}\n\n/** Points along a bent run, in the piece's own frame. */\nfunction flexRunPoints(lengthInches: number, radiusInches: number | undefined, steps = 16) {\n if (!radiusInches || !Number.isFinite(radiusInches) || Math.abs(radiusInches) < 1e-6)\n return [{ x: 0, y: 0 }, { x: lengthInches, y: 0 }];\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i <= steps; i++) out.push(flexRunEnd((lengthInches * i) / steps, radiusInches));\n return out.map((p) => ({ x: p.x, y: p.y }));\n}\n\n/** Every piece's joints, transformed onto the board. */\nexport function placedJoints(\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n): PlacedJoint[] {\n const out: PlacedJoint[] = [];\n const RAD = Math.PI / 180;\n for (const p of pieces) {\n const part = library.find((x) => x.id === p.partId);\n if (!part) continue;\n const geo = partGeometry(part, library);\n if (!geo) continue;\n const c = Math.cos(p.rotationDeg * RAD);\n const s = Math.sin(p.rotationDeg * RAD);\n // Flex is the ONE piece whose geometry the builder sets: its far end is\n // wherever they cut it, and — bent — wherever the curve puts it. Everything\n // else is rigid.\n const run =\n part.kind === \"flex\" ? flexRunEnd(p.lengthInches ?? 0, p.radiusInches) : null;\n for (const j of geo.joints) {\n const far = run && j.id === \"b\";\n const lx = far ? run.x : j.x;\n const ly = p.flipped ? -(far ? run.y : j.y) : far ? run.y : j.y;\n // ⚠️ A bent run's far end POINTS somewhere else. Leaving the angle at 0\n // would make a curve's end claim to face along +x, so the next piece\n // snapped to it would come in across the rail instead of along it.\n const local = far ? run.headingDeg : j.angleDeg;\n const h = (p.flipped ? -local : local) + p.rotationDeg;\n out.push({\n key: `${p.id}.${j.id}`,\n piece: p.id,\n joint: j.id,\n role: j.role,\n x: p.x + lx * c - ly * s,\n y: p.y + lx * s + ly * c,\n headingDeg: norm360(h),\n });\n }\n }\n return out;\n}\n\n/**\n * Build the graph: which joints are connected, which are open, and where the\n * layout is ambiguous.\n *\n * ⭐ A JOINT HOLDS AT MOST ONE CONNECTION. Rail has two ends; a place where\n * three meet is a mistake, not a junction — a junction is a TURNOUT, which is a\n * part carrying three joints of its own.\n */\nexport function buildTrackGraph(\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n snapInches = JOINT_SNAP_INCHES,\n): TrackGraph {\n const joints = placedJoints(pieces, library);\n const unplaceable: TrackGraph[\"unplaceable\"] = [];\n for (const p of pieces) {\n const part = library.find((x) => x.id === p.partId);\n if (!part) {\n unplaceable.push({ piece: p.id, partId: p.partId, why: \"no such part in the library\" });\n continue;\n }\n const why = partGeometryGap(part);\n if (why) unplaceable.push({ piece: p.id, partId: p.partId, why });\n }\n\n // Group coincident joints FIRST. Pairing greedily would connect two of three\n // and hide the third, which is exactly the failure this rule exists to stop.\n const groups: PlacedJoint[][] = [];\n const taken = new Set<string>();\n for (const j of joints) {\n if (taken.has(j.key)) continue;\n const g = [j];\n taken.add(j.key);\n for (const k of joints) {\n if (taken.has(k.key) || k.piece === j.piece) continue;\n if (Math.hypot(k.x - j.x, k.y - j.y) <= snapInches) {\n g.push(k);\n taken.add(k.key);\n }\n }\n groups.push(g);\n }\n\n const connections: GraphConnection[] = [];\n const open: string[] = [];\n const conflicts: GraphConflict[] = [];\n for (const g of groups) {\n if (g.length === 1) open.push(g[0].key);\n else if (g.length === 2) connections.push({ a: g[0].key, b: g[1].key });\n else {\n conflicts.push({\n x: g[0].x,\n y: g[0].y,\n joints: g.map((j) => j.key),\n reason:\n `${g.length} track ends are stacked in one place. Rail has two ends, ` +\n \"so a junction of three is a turnout, not a joint — none of these are \" +\n \"joined until one is moved.\",\n });\n for (const j of g) open.push(j.key);\n }\n }\n return { joints, connections, open, conflicts, unplaceable };\n}\n\n/** A piece as the route crosses it — what an anchored feature resolves against. */\nexport interface RouteSpan {\n piece: string;\n /** The joints the route entered and left this piece by. Tell you which way\n * round the piece's own measurements run against the route's. */\n entryJoint: string;\n exitJoint: string;\n /** Inches from endplate A at the entry joint, and at the one it left by. */\n fromPos: number;\n toPos: number;\n}\n\n/** A piece moved into place against an open joint. */\nexport interface PieceSnap {\n /** The piece, rotated and translated so the two joints coincide. */\n piece: TrackPiece;\n /** The moving joint's key, and the open joint it was brought onto. */\n from: string;\n to: string;\n}\n\n/**\n * Bring a piece being dragged onto the nearest OPEN joint of the others.\n *\n * ⛔ **ONLY OPEN JOINTS ARE CANDIDATES, and that is the ADR's standing rule\n * enforced where it can still be obeyed.** A joint already holding a connection\n * is not offered, so an owner cannot stack a third rail end on a joint at all —\n * rather than stacking it and having {@link buildTrackGraph} refuse all three\n * afterwards, with a piece silently outside the layout until they notice.\n *\n * The piece is ROTATED as well as moved: two ends meet when they are in the same\n * place and facing opposite ways, so the rotation falls out of the joint it is\n * brought to. That is what makes laying a curve out of straight pieces possible\n * without typing an angle.\n *\n * `withinInches` is a GRAB radius — how near counts as \"meant it\" — and is a\n * different thing from {@link JOINT_SNAP_INCHES}, which is how close two joints\n * must be to BE connected. This one is generous; that one is a hundredth of an\n * inch.\n */\nexport function snapPiece(\n moving: TrackPiece,\n others: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 0.5,\n): PieceSnap | null {\n const mine = placedJoints([moving], library);\n if (!mine.length) return null;\n const graph = buildTrackGraph(others, library);\n const taken = new Set(graph.connections.flatMap((c) => [c.a, c.b]));\n const open = graph.joints.filter((j) => !taken.has(j.key));\n\n let best: { m: PlacedJoint; t: PlacedJoint; d: number } | null = null;\n for (const m of mine)\n for (const t of open) {\n const d = Math.hypot(t.x - m.x, t.y - m.y);\n if (d <= withinInches && (!best || d < best.d)) best = { m, t, d };\n }\n if (!best) return null;\n\n // Turn the piece about the joint that is being brought in — so that joint\n // stays where the owner's pointer left it — then slide it onto the target.\n const RAD = Math.PI / 180;\n const dRot = norm360(best.t.headingDeg + 180 - best.m.headingDeg);\n const c = Math.cos(dRot * RAD);\n const s = Math.sin(dRot * RAD);\n const ox = moving.x - best.m.x;\n const oy = moving.y - best.m.y;\n return {\n piece: {\n ...moving,\n rotationDeg: norm360(moving.rotationDeg + dRot),\n x: best.t.x + ox * c - oy * s,\n y: best.t.y + ox * s + oy * c,\n },\n from: best.m.key,\n to: best.t.key,\n };\n}\n\n/**\n * Cut a run of flex to fit BETWEEN two joints — the piece's near end already\n * where it belongs, its far end brought onto another open joint.\n *\n * ⭐ WITHOUT THIS A CROSSOVER CANNOT BE BUILT BY HAND. A piece snaps by ONE end,\n * and a flex run's length handle drags along its own axis, so the far end can\n * never be steered onto the turnout opposite: an owner would have to type an\n * angle and a length to a hundredth of an inch. Cutting a piece to fit between\n * two fixed points is exactly what a builder does with flex, and it is the last\n * thing standing between \"two mains\" and \"two mains joined\".\n *\n * ⚠️ STRAIGHT RUNS ONLY. A bend is already fixed by its radius; asking an arc to\n * meet a second point as well over-constrains it, and quietly re-bending an\n * owner's curve to reach something is not a fit, it is a guess.\n */\nexport function fitFlexBetween(\n piece: TrackPiece,\n others: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 0.5,\n): TrackPiece | null {\n const part = library.find((p) => p.id === piece.partId);\n if (part?.kind !== \"flex\" || piece.radiusInches) return null;\n const mine = placedJoints([piece], library);\n const far = mine.find((j) => j.joint === \"b\");\n const near = mine.find((j) => j.joint === \"a\");\n if (!far || !near) return null;\n const graph = buildTrackGraph(others, library);\n const taken = new Set(graph.connections.flatMap((c) => [c.a, c.b]));\n let best: { j: PlacedJoint; d: number } | null = null;\n for (const j of graph.joints) {\n if (taken.has(j.key)) continue; // an occupied joint is not on offer\n // ⚠️ NOR THE ONE THIS PIECE ALREADY STARTS ON. A short connector's far end\n // is often nearer its own near-end joint than the joint opposite — a\n // crossover's diverging ends are a tenth of an inch apart — so the nearest\n // open joint is the piece's own, and fitting to it asks for a run of zero\n // length. That is what \"the crossover cannot be built\" looked like.\n if (Math.hypot(j.x - near.x, j.y - near.y) <= JOINT_SNAP_INCHES) continue;\n const d = Math.hypot(j.x - far.x, j.y - far.y);\n if (d <= withinInches && (!best || d < best.d)) best = { j, d };\n }\n if (!best) return null;\n const dx = best.j.x - piece.x;\n const dy = best.j.y - piece.y;\n const len = Math.hypot(dx, dy);\n if (!(len > 0)) return null;\n return {\n ...piece,\n rotationDeg: norm360((Math.atan2(dy, dx) * 180) / Math.PI),\n lengthInches: Math.round(len * 1000) / 1000,\n };\n}\n\n/** A run cut in two to let a piece in. */\nexport interface RunInsertion {\n /** The whole set: the host shortened, the new piece, and the remainder. */\n pieces: TrackPiece[];\n /** The run that was cut, and the piece that went into it. */\n hostId: string;\n insertedId: string;\n}\n\n/**\n * Drop a piece ONTO a run and cut the run to take it.\n *\n * ⭐ Will, 2026-07-27: *\"When I drop a turnout on the track, it should cut the\n * track there and automatically snap to the new joints.\"* Snapping alone cannot\n * do this: the middle of a run has no open joint, so there is nothing to snap\n * TO — the joints have to be made by cutting, which is exactly what a builder\n * does with a razor saw.\n *\n * ⚠️ ONLY FLEX CAN BE CUT. A turnout or a sectional piece is a moulding: you\n * cannot saw one in half and have two of anything. Dropping onto one is refused\n * rather than fudged.\n *\n * ⚠️ AND THE PIECE HAS TO FIT. It consumes length along the run — a #7 is six\n * inches of it — so an insertion that would run off the end is refused instead\n * of silently producing a remainder of negative length.\n */\nexport function insertIntoRun(\n pieces: TrackPiece[],\n fresh: TrackPiece,\n at: { x: number; y: number },\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 1,\n): RunInsertion | null {\n // The nearest run, measured against the rail rather than the piece's origin.\n let host: TrackPiece | null = null;\n let bestD = Infinity;\n for (const piece of pieces) {\n const part = library.find((x) => x.id === piece.partId);\n if (part?.kind !== \"flex\") continue;\n for (const { points } of pieceRoutePaths(piece, library))\n for (let i = 1; i < points.length; i++) {\n const d = distanceToSegment(at, points[i - 1], points[i]);\n if (d < bestD) {\n bestD = d;\n host = piece;\n }\n }\n }\n if (!host || bestD > withinInches) return null;\n\n const L = host.lengthInches ?? 0;\n const R = host.radiusInches;\n // How far along the host the drop lands, by walking its own arc.\n const steps = 200;\n let s = 0;\n let closest = Infinity;\n for (let i = 0; i <= steps; i++) {\n const t = (L * i) / steps;\n const local = flexRunEnd(t, R);\n const world = placeLocal(host, local.x, local.y);\n const d = Math.hypot(world.x - at.x, world.y - at.y);\n if (d < closest) {\n closest = d;\n s = t;\n }\n }\n\n // Sit the new piece on the run, pointing the way the run points there.\n const cutLocal = flexRunEnd(s, R);\n const cut = placeLocal(host, cutLocal.x, cutLocal.y);\n const heading = norm360(host.rotationDeg + (host.flipped ? -cutLocal.headingDeg : cutLocal.headingDeg));\n const placed: TrackPiece = { ...fresh, x: cut.x, y: cut.y, rotationDeg: heading };\n\n // What it consumes along the run: entry joint to the one the run leaves by.\n const js = placedJoints([placed], library);\n const entry = js.find((j) => j.joint === \"throat\" || j.joint === \"a\");\n const exit = js.find((j) => j.joint === \"through\" || j.joint === \"b\");\n if (!entry || !exit) return null;\n const body = Math.hypot(exit.x - entry.x, exit.y - entry.y);\n const rest = L - s - body;\n if (s < 0 || rest < 0) return null;\n\n const ids = new Set(pieces.map((p) => p.id));\n let n = 1;\n while (ids.has(`${host.id}b${n}`)) n += 1;\n const tail: TrackPiece = {\n ...host,\n id: `${host.id}b${n}`,\n x: exit.x,\n y: exit.y,\n rotationDeg: exit.headingDeg,\n lengthInches: rest,\n };\n\n const out = pieces.map((p) => (p.id === host!.id ? { ...p, lengthInches: s } : p));\n // A cut at the very start or end leaves a stub of nothing — drop it rather\n // than leaving a zero-length run for the graph to puzzle over.\n const kept = out.filter((p) => p.id !== host!.id || s > 0);\n return {\n pieces: [...kept, placed, ...(rest > 0 ? [tail] : [])],\n hostId: host.id,\n insertedId: placed.id,\n };\n}\n\n/** A point in a piece's own frame, put on the board. */\nfunction placeLocal(piece: TrackPiece, x: number, y: number): { x: number; y: number } {\n const rad = (piece.rotationDeg * Math.PI) / 180;\n const ly = piece.flipped ? -y : y;\n return {\n x: piece.x + x * Math.cos(rad) - ly * Math.sin(rad),\n y: piece.y + x * Math.sin(rad) + ly * Math.cos(rad),\n };\n}\n\nfunction distanceToSegment(\n p: { x: number; y: number },\n a: { x: number; y: number },\n b: { x: number; y: number },\n): number {\n const vx = b.x - a.x;\n const vy = b.y - a.y;\n const len2 = vx * vx + vy * vy;\n if (len2 === 0) return Math.hypot(p.x - a.x, p.y - a.y);\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * vx + (p.y - a.y) * vy) / len2));\n return Math.hypot(p.x - (a.x + t * vx), p.y - (a.y + t * vy));\n}\n\n/** A route the walk found: a continuous run of pieces a train can travel. */\nexport interface GraphRoute {\n id: string;\n /** Inches from endplate A, ALONG THE RAIL, to where this route begins. */\n fromPos: number;\n toPos: number;\n /** The turnout this route branched from; null for the main. */\n bornAt: string | null;\n /** The turnout it runs back into. Set = a SIDING; null = it dead-ends. */\n endsAt: string | null;\n /** The piece that CLOSES this route — a bumper. Set = the track ends here on\n * purpose; null = it simply stops, which may just mean unfinished. */\n closedBy: string | null;\n pieces: string[];\n /** The same pieces, each with where it starts and ends along the route. */\n spans: RouteSpan[];\n /** Furthest lateral offset reached — what gives a lane its side. */\n lateral: number;\n}\n\nexport interface GraphTurnout {\n id: string;\n /** ⚠️ The FROG's distance from endplate A (#132), measured along the rail. */\n pos: number;\n onRoute: string;\n divergeRoute: string | null;\n}\n\nexport interface GraphWalk {\n routes: GraphRoute[];\n turnouts: GraphTurnout[];\n /** Every reason this walk is not the whole layout. */\n warnings: string[];\n /** Turnouts whose diverging route reaches nothing — the ids, not just the\n * sentence, so a caller can act on it (and say it ONCE) instead of matching\n * on prose. */\n danglingDiverges: string[];\n /** Pieces this walk never got to. ⚠️ \"Unreached BY THIS WALK\" is not the same\n * as \"unreachable\": a double-track module's second main is unreached by the\n * first walk and perfectly well connected. Ids, so a caller running more than\n * one walk can tell the difference. */\n unreached: string[];\n}\n\n/** The one wording for a turnout whose diverging route reaches nothing, so a\n * caller can recognise it exactly rather than by substring. */\nconst danglingDivergeWarning = (id: string) =>\n `the route diverging at ${id} is not connected to anything`;\n\n/** Likewise for a piece the walk never got to. */\nconst unreachedWarning = (id: string) =>\n `${id} is not reachable from the endplate — nothing connects it`;\n\n/**\n * Walk the graph from an endplate and read the topology off it.\n *\n * ⚠️ POSITIONS ARE ARC LENGTH ALONG THE RAIL, never x. On a curved module the\n * two differ by inches — a 90°/R30 corner runs 47.1″ of rail across a 42.4″\n * chord — and it is the rail a train travels.\n *\n * Nesting falls out for free: a turnout found on a branch queues the branch IT\n * opens, so a yard ladder resolves to whatever depth it actually has. That is\n * the case the 1-D model can only approximate.\n */\nexport function walkTrackGraph(\n graph: TrackGraph,\n pieces: TrackPiece[],\n startAt: { piece: string; joint: string },\n library = BUILT_IN_TRACK_PARTS,\n): GraphWalk {\n const byKey = new Map(graph.joints.map((j) => [j.key, j]));\n const pieceById = new Map(pieces.map((p) => [p.id, p]));\n const link = new Map<string, string>();\n for (const c of graph.connections) {\n link.set(c.a, c.b);\n link.set(c.b, c.a);\n }\n const partOf = (pid: string) => {\n const p = pieceById.get(pid);\n return p ? library.find((x) => x.id === p.partId) : undefined;\n };\n const geoOf = (pid: string) => {\n const part = partOf(pid);\n return part ? partGeometry(part, library) : null;\n };\n /**\n * How far it is THROUGH a piece, from one of its joints to another.\n *\n * ⚠️⚠️ NOT THE DISTANCE BETWEEN THE TWO JOINTS. On a bent run those differ by\n * inches — a 90° corner at R30 is 47.1″ of rail across a 42.4″ chord — and\n * `pos` is arc length along the rail, because that is what a train travels\n * and what every position in the document means. A flex run's arc length is\n * the length it was cut to, which is exactly `lengthInches`.\n */\n const gap = (a?: PlacedJoint, b?: PlacedJoint) => {\n if (!a || !b) return 0;\n if (a.piece === b.piece) {\n const piece = pieceById.get(a.piece);\n const part = piece ? partOf(a.piece) : undefined;\n if (piece && part?.kind === \"flex\") return piece.lengthInches ?? 0;\n // ⚠️ AND A SECTIONAL CURVE BY ITS ARC. Missing this measured one 19″ 30°\n // section as its 9.83″ chord instead of 9.95″ of rail — an eighth of an\n // inch per section, compounding all the way along a curved module. The\n // invariant is not \"flex is special\"; it is that a curve's rail is longer\n // than the straight line across it, whoever made the curve.\n if (part?.kind === \"curve\") return sectionalArcInches(part);\n }\n return Math.hypot(a.x - b.x, a.y - b.y);\n };\n\n const routes: GraphRoute[] = [];\n const turnouts: GraphTurnout[] = [];\n const warnings: string[] = [];\n const danglingDiverges: string[] = [];\n const queued = new Set<string>();\n const pending: { from: string; at: number; joint: string; skew: number }[] = [];\n\n const walk = (\n startKey: string,\n startPos: number,\n id: string,\n bornAt: string | null,\n ): GraphRoute => {\n const route: GraphRoute = {\n id, fromPos: startPos, toPos: startPos, bornAt, endsAt: null, closedBy: null,\n pieces: [], spans: [], lateral: 0,\n };\n let cur: string | undefined = startKey;\n let pos = startPos;\n const guard = new Set<string>();\n while (cur && !guard.has(cur)) {\n guard.add(cur);\n const here = byKey.get(cur);\n if (!here) break;\n const geo = geoOf(here.piece);\n if (!geo) break;\n // Where this route leaves the piece: whichever of its routes uses the\n // joint we came in by. At a turnout prefer the THROUGH route, so the walk\n // stays on the line it is on and the diverging leg becomes a branch.\n const opts = geo.routes.filter((r) => r.includes(here.joint));\n if (!opts.length) {\n // ⭐ NOWHERE TO GO — a bumper. The route ends here DELIBERATELY, which\n // is a different thing from running out of track, and the difference is\n // the whole reason bumpers exist in the model.\n //\n // ⚠️ It must be recorded as REACHED. Breaking out without it left the\n // bumper looking like stray track that nothing connects, which is the\n // opposite of what it says.\n route.pieces.push(here.piece);\n route.closedBy = here.piece;\n break;\n }\n // ⭐ THROUGH A CROSSOVER, STAY ON THE TRACK YOU ARE ON. Its four routes\n // are two straights and two crossings, and none of them is called\n // \"through\" — so the old rule fell through to `opts[0]` and a main could\n // walk out on the other main. The straight route is the one whose far end\n // is on the same track, which the joint ids say: a1/b1 are one track,\n // a2/b2 the other. A crossing is a route a train CHOOSES, exactly like a\n // turnout's diverging leg, so it is left for the branch pass.\n const sameTrack = (r: [string, string]) => {\n const other = r[0] === here.joint ? r[1] : r[0];\n return other.slice(-1) === here.joint.slice(-1);\n };\n const pick =\n (partOf(here.piece)?.kind === \"crossover\" ? opts.find(sameTrack) : undefined) ??\n opts.find((r) => r.includes(\"through\")) ??\n opts[0];\n const exitJoint = pick[0] === here.joint ? pick[1] : pick[0];\n const exit = byKey.get(`${here.piece}.${exitJoint}`);\n const part = partOf(here.piece);\n\n if (part && (part.kind === \"turnout\" || part.kind === \"wye\")) {\n const throat = byKey.get(`${here.piece}.throat`);\n const through =\n byKey.get(`${here.piece}.through`) ?? byKey.get(`${here.piece}.legA`);\n const body = gap(throat, through);\n const lead = part.lead?.inches ?? body / 2;\n // ⚠️⚠️ THE FROG SITS AT `frogOffset` FROM THE TIE END, NOT AT `lead`.\n // `lead` is measured POINTS → frog (see {@link TrackPart.lead}, and the\n // measured table on {@link ATLAS_CODE55_N}: the #7's ⅝″ points and\n // 4⁷⁄₃₂″ frog give exactly its 3.59375″ lead). Adding it to the THROAT\n // landed 0.625″ short of the frog on a #7 — on no landmark at all.\n const frogAxial = part.frogOffset?.inches ?? (part.pointsOffset?.inches ?? 0) + lead;\n // ⚠️ ENTERED FROM EITHER END. A turnout facing the other way is entered\n // at its `through` joint, so the frog is `body − frogAxial` along.\n // The frog, in the piece's own frame — where the diverging rail has\n // climbed one gauge and the two routes truly cross.\n const dvj = byKey.get(`${here.piece}.diverge`) ?? byKey.get(`${here.piece}.legB`);\n const frogPt =\n throat && body > 0 && dvj\n ? {\n x: throat.x + ((dvj.x - throat.x) * frogAxial) / body,\n y: throat.y + ((dvj.y - throat.y) * frogAxial) / body,\n }\n : null;\n // ⚠️ HOW FAR THE FROG IS DEPENDS ON WHICH END YOU CAME IN BY, and there\n // are THREE answers, not two. From the throat it is the lead. From the\n // through end it is `body − lead`. From a DIVERGING end it is neither:\n // that rail runs at an angle, so it is longer than the axial distance —\n // measure it. Using `body − lead` there put a siding's far end 0.01\"\n // out, which is small only because the angle is.\n const toFrog =\n here.joint === \"throat\"\n ? frogAxial\n : here.joint === \"diverge\" || here.joint === \"legB\"\n ? frogPt && dvj\n ? Math.hypot(dvj.x - frogPt.x, dvj.y - frogPt.y)\n : Math.max(0, body - frogAxial)\n : Math.max(0, body - frogAxial);\n const frogPos = pos + toFrog;\n if (here.joint === \"diverge\" || here.joint === \"legB\") {\n // Arrived by a diverging end: this route has run into the far turnout\n // of a siding, which is what makes it a siding rather than a spur.\n //\n // ⚠️ ITS EXTENT IS THE FAR TURNOUT'S POSITION, not this branch's\n // accumulated arc. A siding climbs away from the main and back, so\n // its own rail is genuinely longer than the span it covers — reading\n // the arc here put a 13→73 siding's far end at 73.02. `fromPos`/\n // `toPos` mean where a track sits ALONG THE MODULE, so use the\n // position the main walk already established for that turnout.\n route.endsAt = here.piece;\n const known = turnouts.find((t) => t.id === here.piece);\n route.toPos = known ? known.pos : frogPos;\n break;\n }\n turnouts.push({ id: here.piece, pos: frogPos, onRoute: id, divergeRoute: null });\n for (const dj of [\"diverge\", \"legB\"]) {\n const dk = `${here.piece}.${dj}`;\n const d = byKey.get(dk);\n if (!d || queued.has(dk)) continue;\n queued.add(dk);\n // A branch BEGINS at the frog, but its joint is further along the\n // diverging rail. Losing that stretch makes every position downstream\n // creep, and on a ladder the error compounds.\n const fp =\n throat && body > 0\n ? {\n x: throat.x + ((d.x - throat.x) * frogAxial) / body,\n y: throat.y + ((d.y - throat.y) * frogAxial) / body,\n }\n : null;\n pending.push({\n from: here.piece,\n at: frogPos,\n joint: dk,\n skew: fp ? Math.hypot(d.x - fp.x, d.y - fp.y) : 0,\n });\n }\n }\n\n route.pieces.push(here.piece);\n for (const j of graph.joints)\n if (j.piece === here.piece && Math.abs(j.y) > Math.abs(route.lateral))\n route.lateral = j.y;\n const entered = pos;\n pos += gap(here, exit);\n route.spans.push({\n piece: here.piece, entryJoint: here.joint, exitJoint, fromPos: entered, toPos: pos,\n });\n route.toPos = pos;\n const next = exit ? link.get(exit.key) : undefined;\n if (!next) break;\n cur = next;\n }\n return route;\n };\n\n routes.push(walk(`${startAt.piece}.${startAt.joint}`, 0, \"main\", null));\n\n let n = 0;\n while (pending.length) {\n const b = pending.shift()!;\n const start = link.get(b.joint);\n if (!start) {\n warnings.push(danglingDivergeWarning(b.from));\n danglingDiverges.push(b.from);\n continue;\n }\n // ⚠️ A SIDING IS FOUND TWICE — once from each of its turnouts. Both queue a\n // diverging branch, and the second walks the same rail back the other way.\n // Walking it again would put the same track in the layout twice, on two\n // lanes, with the far turnout diverging onto the copy. A piece belongs to\n // exactly ONE route, so if this branch starts on a piece a route already\n // holds, the answer is that route: the far turnout diverges onto the siding\n // that is already there.\n const already = routes.find((r) => r.pieces.includes(byKey.get(start)!.piece));\n if (already) {\n const swFar = turnouts.find((t) => t.id === b.from);\n if (swFar && !swFar.divergeRoute) swFar.divergeRoute = already.id;\n continue;\n }\n n += 1;\n const r = walk(start, b.at + b.skew, `route${n}`, b.from);\n r.fromPos = b.at; // it begins at the frog, whatever its first joint is\n routes.push(r);\n const sw = turnouts.find((t) => t.id === b.from);\n if (sw && !sw.divergeRoute) sw.divergeRoute = r.id;\n }\n\n const reached = new Set(routes.flatMap((r) => r.pieces));\n const unreached: string[] = [];\n for (const p of pieces)\n if (!reached.has(p.id) && !graph.unplaceable.some((u) => u.piece === p.id)) {\n warnings.push(unreachedWarning(p.id));\n unreached.push(p.id);\n }\n for (const c of graph.conflicts) warnings.push(c.reason);\n\n return { routes, turnouts, warnings, danglingDiverges, unreached };\n}\n\n// ─── GRAPH → DOCUMENT (ADR 0001) ─────────────────────────────────────────────\n// The claim the whole decision rests on: the 1-D document becomes a DERIVED\n// artifact, so `moduleFeatures`, the dispatcher view and Free-Dispatcher are\n// unaffected. This is where that claim is demonstrated IN THE PACKAGE — the\n// graph emits an ordinary `ModuleSchematicDoc` and the same pure function reads\n// it. Nothing downstream is told which way a module was authored.\n\n/** Where an anchored feature turned out to be. */\nexport interface ResolvedAnchor {\n /** Inches from endplate A — the number the document and the dispatcher read. */\n pos: number;\n /** The route the anchored piece is part of. */\n routeId: string;\n /** The piece's own measuring direction runs BACKWARD along the route, so\n * increasing {@link GraphAnchor.atInches} moves toward endplate A. */\n reversed: boolean;\n}\n\n/**\n * Turn a {@link GraphAnchor} into a position along the module.\n *\n * The piece is measured from its own origin end, and the walk knows both ends\n * of it, so whichever end the route arrived by, the sum comes out the same.\n * Returns null when the anchored piece is not on any route — a spur nobody has\n * connected yet — which is a thing to report, not to guess at.\n */\nexport function resolveGraphAnchor(\n anchor: GraphAnchor,\n walk: GraphWalk,\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n): ResolvedAnchor | null {\n const piece = pieces.find((p) => p.id === anchor.piece);\n const part = piece ? library.find((x) => x.id === piece.partId) : undefined;\n // Every part's own frame starts at x=0 at one joint: `a` on flex, the throat\n // on everything with points.\n const origin = part?.kind === \"flex\" ? \"a\" : \"throat\";\n for (const r of walk.routes) {\n const span = r.spans.find((s) => s.piece === anchor.piece);\n if (!span) continue;\n if (span.entryJoint === origin)\n return { pos: span.fromPos + anchor.atInches, routeId: r.id, reversed: false };\n if (span.exitJoint === origin)\n return { pos: span.toPos - anchor.atInches, routeId: r.id, reversed: true };\n // A wye crossed leg-to-leg never touches its throat, so there is no\n // measuring from it. Better to say so than to pick an end.\n return null;\n }\n return null;\n}\n\n/** What the graph cannot know, and therefore never invents. */\nexport interface GraphDocInput {\n /** Where the main begins: the joint endplate A's track arrives at. */\n startAt: { piece: string; joint: string };\n /** Where MAIN 2 begins, on a double-track module. Absent = single track. */\n start2?: { piece: string; joint: string } | null;\n /**\n * The rest of the document — module id, endplate identities, the benchwork,\n * industries and signals. Merged UNDERNEATH the derived keys, so the graph\n * wins on length, tracks and turnouts and on nothing else.\n *\n * ⏸️ Industries, signals and control points are PASSED THROUGH untouched.\n * Where they live in a graph is deliberately still open (ADR 0001 defers it\n * to persistence); carrying them is honest, re-deriving them would be a guess.\n */\n base?: Partial<ModuleSchematicDoc>;\n /**\n * Owner metadata for a run, keyed by the piece the run STARTS at — the piece\n * they select and name. Held here rather than on {@link TrackPiece} because\n * it describes the whole run, not the one piece.\n */\n meta?: Record<\n string,\n { trackName?: string; capacityFeet?: number | null; moduleTrackId?: number | null }\n >;\n library?: TrackPart[];\n}\n\nexport interface GraphDocResult {\n doc: ModuleSchematicDoc;\n graph: TrackGraph;\n walk: GraphWalk;\n /** The walk's warnings, plus anything the emission itself had to leave out. */\n warnings: string[];\n}\n\n/**\n * Derive a `ModuleSchematicDoc` from placed pieces.\n *\n * ⭐ **NO HAND IS EMITTED.** A turnout's `kind` is left unset on purpose. The\n * graph knows which side the diverging route is on — it is where the piece IS —\n * so the lane carries the side and `moduleFeatures` keeps the lane it is given\n * (`resolveLane` only overrides the sign for a stated left/right). Emitting a\n * hand as well would be a second source for one fact, which is the ~120 lines\n * of reconciliation this model exists to remove.\n *\n * ⚠️ ONE MAIN. The walk starts at one endplate, so a double-track module's\n * second main is not reached — it surfaces in `warnings` as unreachable pieces\n * rather than vanishing quietly. Emitting Main 2 needs a second start point and\n * is not built yet.\n */\nexport function graphToDoc(pieces: TrackPiece[], input: GraphDocInput): GraphDocResult {\n const library = input.library ?? BUILT_IN_TRACK_PARTS;\n const graph = buildTrackGraph(pieces, library);\n const walk = walkTrackGraph(graph, pieces, input.startAt, library);\n // ⚠️ ONE PROBLEM, ONE SENTENCE. The walk reports a diverging route that\n // reaches nothing, and the emission has its own thing to say about the same\n // turnout — printed together they read as two faults. Drop the walk's wording\n // in favour of the one below, which names the consequence as well as the fact.\n const dangling = new Set(walk.danglingDiverges.map(danglingDivergeWarning));\n const warnings = walk.warnings.filter((w) => !dangling.has(w));\n const round = (n: number) => Math.round(n * 100) / 100;\n\n const base = input.base ?? {};\n const endplates: SchematicEndplate[] =\n base.endplates && base.endplates.length\n ? base.endplates\n : [{ id: \"A\", label: \"West\" }, { id: \"B\", label: \"East\" }];\n const epA = endplates[0];\n const epB = endplates[1];\n\n const main = walk.routes.find((r) => r.id === \"main\")!;\n\n /**\n * MAIN 2 is its own walk, from its own end of the endplate.\n *\n * ⚠️ It is a SEPARATE RUN, not a branch: the two mains of a double-track\n * module never touch along their length. So it is walked independently and its\n * routes are kept apart by a prefix, because both walks name their own route\n * \"main\".\n */\n const walk2 = input.start2\n ? walkTrackGraph(graph, pieces, input.start2, library)\n : null;\n const main2 = walk2?.routes.find((r) => r.id === \"main\") ?? null;\n /**\n * ⚠️⚠️ **A CROSSOVER IS THE ONE PIECE TWO ROUTES MAY BOTH HOLD.** Everywhere\n * else \"this piece is already in a route\" means the two starts landed on the\n * same run and emitting it twice would put one piece of track in the document\n * as two. A double crossover is the exception BY CONSTRUCTION: both mains run\n * straight through the same assembly, which is what it is for. Counting it as\n * a collision made an ordinary double-track module with a crossover report its\n * two mains as one run and emit neither.\n */\n const sharedByDesign = (id: string) => {\n const piece = pieces.find((p) => p.id === id);\n return library.find((p) => p.id === piece?.partId)?.kind === \"crossover\";\n };\n const claimed = new Set(walk.routes.flatMap((r) => r.pieces).filter((p) => !sharedByDesign(p)));\n if (main2 && main2.pieces.some((p) => claimed.has(p))) {\n // Both starts landed on the same run. Emitting it twice would put one piece\n // of track in the document as two, on two lanes.\n warnings.push(\n \"Main 2 starts on track that Main 1 already runs along — they are one run, not two\",\n );\n }\n const twoMains = !!main2 && !main2.pieces.some((p) => claimed.has(p));\n\n // ⭐ WHICH SIDE MAIN 2 IS ON IS READ, NOT AUTHORED. The 1-D model needs a\n // `mainsSwapped` flag to say Main 2 draws below; here it is simply where the\n // track is. Module-local +y is above, and endplate A's track point is the\n // origin, so the sign of its first joint's offset is the answer.\n const main2Lane = twoMains\n ? (graph.joints.find((j) => j.key === `${input.start2!.piece}.${input.start2!.joint}`)?.y ?? 1) >= 0\n ? 1\n : -1\n : 0;\n\n const lengthInches = round(Math.max(main.toPos, twoMains ? main2!.toPos : 0));\n\n // A branch takes the id of the piece it STARTS at — the run's own first piece.\n // It is the piece an owner selects, so it is the thing their name belongs to.\n // ⚠️ Not stable against inserting a piece at the throat: that changes the id.\n // Persisting the graph will need a run identity of its own; nothing yet reads\n // these ids back.\n const branches = [\n ...walk.routes.filter((r) => r.id !== \"main\" && r.pieces.length),\n ...(twoMains\n ? walk2!.routes\n .filter((r) => r.id !== \"main\" && r.pieces.length)\n .map((r) => ({ ...r, id: `main2:${r.id}`, bornAt: r.bornAt }))\n : []),\n ];\n const trackIdOf = new Map<string, string>([[\"main\", MAIN_TRACK_ID]]);\n if (twoMains) trackIdOf.set(\"main2:main\", MAIN2_TRACK_ID);\n for (const r of branches) trackIdOf.set(r.id, r.pieces[0]);\n // ⚠️ A CROSSOVER IS FOUND BY BOTH WALKS — once from each main, exactly as a\n // siding is found from each of its turnouts, but now across two walks. The\n // two finds name the same first piece, so they resolve to the same track id\n // and the second is dropped rather than emitted as a phantom second\n // connector. Both turnouts still point at the one that remains.\n const emitted = new Set<string>();\n const uniqueBranches = branches.filter((r) => {\n const id = trackIdOf.get(r.id)!;\n if (emitted.has(id)) return false;\n emitted.add(id);\n return true;\n });\n\n // LANE is an ordinal: which side, and how many tracks out. The side is the\n // sign of how far the run reaches laterally; the magnitude is its rank among\n // the runs on that side, so a spur off a spur stacks OUTSIDE its parent.\n //\n // ⚠️ MAIN 2 ALREADY OCCUPIES A LANE on its own side, so branches there start\n // at 2. Ranking branches alone put the first siding above the main on lane 1\n // — the same lane as Main 2 — and the two drew on top of each other.\n const laneOf = (r: GraphRoute, among: GraphRoute[]): number => {\n const side = Math.sign(r.lateral) || 1;\n const sameSide = among\n .filter((x) => (Math.sign(x.lateral) || 1) === side)\n .sort((a, b) => Math.abs(a.lateral) - Math.abs(b.lateral));\n const taken = side === main2Lane ? 1 : 0;\n return side * (sameSide.indexOf(r) + 1 + taken);\n };\n\n const tracks: SchematicTrack[] = [\n {\n id: MAIN_TRACK_ID,\n role: \"main\",\n lane: 0,\n from: epA?.id ?? \"A\",\n ...(epB ? { to: epB.id } : {}),\n // A main can be closed too — that is a pocket module, where the track\n // runs in and stops rather than crossing to a second endplate.\n ...(main.closedBy ? { bumperAt: \"to\" as const } : {}),\n },\n ...(twoMains\n ? [\n {\n id: MAIN2_TRACK_ID,\n role: \"main\" as const,\n lane: main2Lane,\n from: epA?.id ?? \"A\",\n ...(epB ? { to: epB.id } : {}),\n // ⚠️ Its own extent, because a second main need not run the whole\n // module: on a transition module it starts or stops partway.\n fromPos: round(Math.min(main2!.fromPos, main2!.toPos)),\n toPos: round(Math.max(main2!.fromPos, main2!.toPos)),\n },\n ]\n : []),\n ];\n for (const r of uniqueBranches) {\n const id = trackIdOf.get(r.id)!;\n const meta = input.meta?.[id] ?? {};\n tracks.push({\n id,\n // It runs back into a second turnout, or it doesn't. That is the whole\n // difference between a siding and a spur, and it is read, not declared.\n role: r.endsAt ? \"siding\" : \"spur\",\n lane: laneOf(r, uniqueBranches),\n fromPos: round(Math.min(r.fromPos, r.toPos)),\n toPos: round(Math.max(r.fromPos, r.toPos)),\n // ⚠️ ALWAYS THE `to` END, and not because of an assumption: a branch's\n // positions are ARC LENGTH FROM ITS THROAT, so they only ever grow — a\n // spur running physically back toward endplate A still ends at the larger\n // number. The closed end is the far one from the turnout, by definition.\n ...(r.closedBy ? { bumperAt: \"to\" as const } : {}),\n ...(meta.trackName ? { trackName: meta.trackName } : {}),\n ...(meta.capacityFeet != null ? { capacityFeet: meta.capacityFeet } : {}),\n ...(meta.moduleTrackId != null ? { moduleTrackId: meta.moduleTrackId } : {}),\n });\n }\n\n if (walk2) {\n // ⚠️ EACH WALK CALLS THE OTHER MAIN UNREACHABLE, and neither is right. A\n // walk only knows what IT got to; with two starts, a piece reached by\n // either one is connected. Told as it stood, a perfectly ordinary\n // double-track module reported both of its mains as stray track.\n const seen = new Set([\n ...walk.routes.flatMap((r) => r.pieces),\n ...walk2.routes.flatMap((r) => r.pieces),\n ]);\n const covered = new Set([...walk.unreached, ...walk2.unreached].filter((id) => seen.has(id)));\n const drop = new Set([...covered].map(unreachedWarning));\n const d2 = new Set(walk2.danglingDiverges.map(danglingDivergeWarning));\n for (let i = warnings.length - 1; i >= 0; i--) if (drop.has(warnings[i])) warnings.splice(i, 1);\n for (const w of walk2.warnings)\n if (!d2.has(w) && !drop.has(w) && !warnings.includes(w)) warnings.push(w);\n }\n\n const pieceById = new Map(pieces.map((p) => [p.id, p]));\n const turnouts: SchematicTurnout[] = [];\n const allTurnouts = [\n ...walk.turnouts,\n ...(twoMains\n ? walk2!.turnouts.map((t) => ({\n ...t,\n onRoute: t.onRoute === \"main\" ? \"main2:main\" : `main2:${t.onRoute}`,\n divergeRoute: t.divergeRoute ? `main2:${t.divergeRoute}` : null,\n }))\n : []),\n ];\n for (const t of allTurnouts) {\n const diverge = t.divergeRoute ? trackIdOf.get(t.divergeRoute) : undefined;\n if (!diverge) {\n // A turnout whose diverging route reaches nothing is an unfinished layout,\n // not an operating turnout. Said out loud rather than emitted with a\n // dangling reference for the dispatcher view to trip over.\n warnings.push(\n `${t.id} is placed but its diverging route goes nowhere, so it is not in the operations view`,\n );\n continue;\n }\n const piece = pieceById.get(t.id);\n const part = piece ? library.find((p) => p.id === piece.partId) : undefined;\n turnouts.push({\n id: t.id,\n pos: round(t.pos),\n onTrack: trackIdOf.get(t.onRoute) ?? MAIN_TRACK_ID,\n divergeTrack: diverge,\n ...(piece?.name ? { name: piece.name } : {}),\n ...(part?.frogNumber != null ? { size: part.frogNumber } : {}),\n ...(part ? { partId: part.id } : {}),\n });\n }\n /**\n * ⭐⭐ A DOUBLE CROSSOVER IS ONE PIECE, AND THE DOCUMENT NEEDS FOUR TURNOUTS\n * AND TWO CONNECTORS OUT OF IT.\n *\n * Emitted here rather than through the walk's turnout machinery, because the\n * walk records one turnout per PIECE and this piece carries four point-sets.\n * Everything needed is already known: {@link crossoverAssembly} says where the\n * point-sets sit inside the assembly, and the walk's own\n * {@link RouteSpan.fromPos} says where the assembly sits on each main. So the\n * operations view gets the four turnouts and both crossing moves it needs,\n * while the physical view keeps drawing the single moulding that is really\n * there.\n *\n * ⚠️ It only emits when BOTH mains actually run through the assembly. Half a\n * double crossover is not a thing, and a piece reached from one main only\n * means the other main is not connected to it — which the open-end and\n * unreachable reporting already says, without inventing a turnout here.\n */\n const crossoverSpans = (() => {\n const found: {\n piece: string;\n part: TrackPart;\n /** By track index (1 = joints a1/b1, 2 = a2/b2): route id + the two\n * point-set positions along that route. */\n byTrack: Map<number, { routeId: string; at: [number, number] }>;\n }[] = [];\n const routesAll = [\n ...walk.routes.map((r) => ({ r, prefix: \"\" })),\n ...(twoMains ? walk2!.routes.map((r) => ({ r, prefix: \"main2:\" })) : []),\n ];\n const seen = new Map<string, (typeof found)[number]>();\n for (const { r, prefix } of routesAll) {\n for (const sp of r.spans) {\n const piece = pieceById.get(sp.piece);\n const part = piece ? library.find((p) => p.id === piece.partId) : undefined;\n if (!part || part.kind !== \"crossover\") continue;\n const g = crossoverAssembly(part);\n if (!g) continue;\n const [p1, p2] = g.pointsAtInches;\n // Entered from the west end the point-sets are p1 then p2 along; from\n // the east end the assembly is walked backwards.\n const west = sp.entryJoint.startsWith(\"a\");\n const at: [number, number] = west\n ? [sp.fromPos + p1, sp.fromPos + p2]\n : [sp.fromPos + (g.lengthInches - p2), sp.fromPos + (g.lengthInches - p1)];\n const track = sp.entryJoint.endsWith(\"2\") ? 2 : 1;\n const routeId = r.id === \"main\" && prefix ? \"main2:main\" : `${prefix}${r.id}`;\n const rec =\n seen.get(sp.piece) ?? { piece: sp.piece, part, byTrack: new Map() };\n rec.byTrack.set(track, { routeId, at });\n seen.set(sp.piece, rec);\n }\n }\n for (const rec of seen.values()) if (rec.byTrack.size === 2) found.push(rec);\n return found;\n })();\n\n for (const xo of crossoverSpans) {\n const one = xo.byTrack.get(1)!;\n const two = xo.byTrack.get(2)!;\n const onA = trackIdOf.get(one.routeId) ?? MAIN_TRACK_ID;\n const onB = trackIdOf.get(two.routeId) ?? MAIN2_TRACK_ID;\n // The two crossing moves. A goes track 1 → track 2, B the other way; each\n // spans the same stretch of the module, which is what a scissors looks like.\n const legs: { id: string; from: [string, number]; to: [string, number] }[] = [\n { id: `${xo.piece}-a`, from: [onA, one.at[0]], to: [onB, two.at[1]] },\n { id: `${xo.piece}-b`, from: [onB, two.at[0]], to: [onA, one.at[1]] },\n ];\n for (const leg of legs) {\n tracks.push({\n id: leg.id,\n role: \"crossover\",\n // The connector lives between the mains, so it takes Main 2's lane —\n // the same lane the 1-D model has always drawn a crossover in.\n lane: main2Lane ?? 1,\n fromPos: round(Math.min(leg.from[1], leg.to[1])),\n toPos: round(Math.max(leg.from[1], leg.to[1])),\n trackName: xo.part.name ?? \"Crossover\",\n crossoverPartId: xo.part.id,\n });\n turnouts.push(\n {\n id: `${leg.id}-1`,\n pos: round(leg.from[1]),\n onTrack: leg.from[0],\n divergeTrack: leg.id,\n name: xo.part.name ?? \"Crossover\",\n ...(xo.part.frogNumber != null ? { size: xo.part.frogNumber } : {}),\n },\n {\n id: `${leg.id}-2`,\n pos: round(leg.to[1]),\n onTrack: leg.to[0],\n divergeTrack: leg.id,\n name: xo.part.name ?? \"Crossover\",\n ...(xo.part.frogNumber != null ? { size: xo.part.frogNumber } : {}),\n },\n );\n }\n }\n\n turnouts.sort((a, b) => a.pos - b.pos);\n\n /**\n * ⭐ A CONNECTOR BETWEEN TWO DIFFERENT MAINS IS A CROSSOVER, not a siding.\n *\n * Both are \"a track with a turnout at each end\"; what separates them is\n * whether those turnouts sit on the SAME track. A siding leaves the main and\n * comes back to it; a crossover goes somewhere else. That is the same test\n * `moduleFeatures` applies to decide whether to draw a diagonal or a\n * lane-paralleling band, so deciding it here means the document says what the\n * drawing will do instead of leaving both to work it out separately.\n *\n * Read, not authored — like everything else in this model.\n */\n for (const t of tracks) {\n if (t.role === \"main\") continue;\n const ends = turnouts.filter((sw) => sw.divergeTrack === t.id);\n if (ends.length >= 2 && new Set(ends.map((sw) => sw.onTrack)).size >= 2)\n t.role = \"crossover\";\n }\n\n // ⭐ ANCHORED FEATURES ARE PLACED BY THE PIECE THEY ARE BESIDE, not by a\n // number about the module. Unanchored ones keep exactly the positions their\n // owner typed — nothing migrates (ADR 0001).\n const place = (a: GraphAnchor | null | undefined, what: string) => {\n if (!a) return null;\n const hit = resolveGraphAnchor(a, walk, pieces, library);\n if (!hit) {\n warnings.push(\n `${what} is anchored to ${a.piece}, which is not on any route — its authored position stands`,\n );\n return null;\n }\n return hit;\n };\n /** A span keeps its authored LENGTH and takes its start from the anchor. */\n const spanAt = (hit: ResolvedAnchor, from: number, to: number): [number, number] => {\n const len = Math.abs(to - from);\n return hit.reversed\n ? [round(hit.pos - len), round(hit.pos)]\n : [round(hit.pos), round(hit.pos + len)];\n };\n\n const industries = base.industries?.map((ind) => {\n const hit = place(ind.anchor, `industry \"${ind.name}\"`);\n const spots = ind.spots?.map((s) => {\n const sh = place(s.anchor, `a spot of industry \"${ind.name}\"`);\n if (!sh) return s;\n const [from, to] = spanAt(sh, s.fromPos, s.toPos);\n return { ...s, track: trackIdOf.get(sh.routeId) ?? s.track, fromPos: from, toPos: to };\n });\n if (!hit) return spots ? { ...ind, spots } : ind;\n const [fromPos, toPos] = spanAt(hit, ind.fromPos, ind.toPos);\n return {\n ...ind,\n track: trackIdOf.get(hit.routeId) ?? ind.track,\n fromPos,\n toPos,\n ...(spots ? { spots } : {}),\n };\n });\n\n const signals = base.signals?.map((sig) => {\n const hit = place(sig.anchor, `signal \"${sig.name ?? sig.id}\"`);\n return hit\n ? { ...sig, pos: round(hit.pos), track: trackIdOf.get(hit.routeId) ?? sig.track }\n : sig;\n });\n\n const doc: ModuleSchematicDoc = {\n version: 1,\n ...base,\n lengthInches,\n endplates,\n tracks,\n turnouts,\n ...(industries ? { industries } : {}),\n ...(signals ? { signals } : {}),\n };\n return { doc, graph, walk, warnings };\n}\n\n/**\n * Bring a document up to date with the track its owner drew.\n *\n * A document with no `graph` is returned UNTOUCHED — that is the ADR's\n * no-migration rule in one line, and it is why every module authored before this\n * keeps behaving exactly as it did. With a graph, the tracks and turnouts are\n * re-read off the pieces and written back into the ordinary document keys, so\n * the module is stored in a form every existing reader already understands.\n *\n * ⭐ Owners' names, capacities and `module_tracks` links are carried across from\n * the tracks already in the document, keyed by id. Re-deriving must never cost\n * an owner the name they gave a siding.\n */\nexport function deriveGraphDoc(\n doc: ModuleSchematicDoc,\n library = BUILT_IN_TRACK_PARTS,\n): { doc: ModuleSchematicDoc; warnings: string[] } {\n const g = doc.graph;\n if (!g || !g.pieces?.length || !g.startAt) return { doc, warnings: [] };\n const meta: NonNullable<GraphDocInput[\"meta\"]> = {};\n for (const t of doc.tracks ?? []) {\n if (t.role === \"main\") continue;\n meta[t.id] = {\n ...(t.trackName ? { trackName: t.trackName } : {}),\n ...(t.capacityFeet != null ? { capacityFeet: t.capacityFeet } : {}),\n ...(t.moduleTrackId != null ? { moduleTrackId: t.moduleTrackId } : {}),\n };\n }\n const out = graphToDoc(g.pieces, {\n startAt: g.startAt,\n start2: g.start2 ?? null,\n base: doc,\n meta,\n library,\n });\n return { doc: out.doc, warnings: out.warnings };\n}\n\n/**\n * What a turnout in a 1-D document would become as a piece — or what it is\n * missing before it can become anything.\n *\n * ⭐⭐ **IDENTITY IS THE GATE, NOT GEOMETRY.** This is the thing that surprised\n * us and it is worth stating plainly: converting a drawn module to pieces is\n * blocked far more often by not knowing WHICH TURNOUT IT IS than by any missing\n * measurement. Across the production database not one turnout names a part, and\n * most state no frog number either — so for those there is nothing to look up.\n * No amount of measuring fixes that; only the owner knows what they laid, which\n * is exactly why conversion asks instead of guessing.\n */\nexport interface TurnoutIdentity {\n /** The turnout's id in the document. */\n id: string;\n name?: string | null;\n pos: number;\n /** The frog number the document states, if any. */\n size?: number | null;\n /** A part the document already names — the strongest possible answer. */\n statedPartId?: string | null;\n /** The part this turnout converts to; null = the owner has to say. */\n partId: string | null;\n /** How `partId` was arrived at. `assembly` = this is a crossover's own\n * point-set, and the crossover product answers for it. */\n from: \"named\" | \"frog-number\" | \"unresolved\" | \"assembly\";\n /**\n * The weakest provenance behind the chosen part's geometry, so a caller can\n * tell a turnout placed from real readings from one placed off a catalogue\n * figure. Null when unresolved.\n */\n source: DimensionSource | null;\n /** Why it cannot be resolved — null when it can. */\n why: string | null;\n /**\n * Parts the owner could reasonably pick, best first: an exact frog match\n * ahead of the rest. Only PLACEABLE parts are offered — listing one that\n * cannot be drawn would be an answer that does not answer.\n */\n candidates: string[];\n}\n\n/** Something that stops a whole document converting, whatever the owner says. */\nexport interface ConversionBlocker {\n /** `crossing` · `curved-turnout` · `loop` — the shapes with no piece to be. */\n kind: string;\n /** The document object it came from, where there is one. */\n ref?: string;\n why: string;\n}\n\n/**\n * A track the document draws but nothing in it connects — no turnout diverges\n * onto it.\n *\n * ⚠️⚠️ **THE 1-D MODEL TOLERATES THIS AND THE GRAPH CANNOT.** A siding is drawn\n * from its `lane` and its `fromPos`/`toPos` alone, so a document can carry a\n * named, capacity-bearing yard track that joins nothing at all and still look\n * completely normal. Real ones do: Idaho Falls Grain Yard has five yard tracks\n * and not one turnout. A piece, by contrast, has to be joined to something.\n *\n * So these are surfaced rather than converted. Dropping them would lose an\n * owner's named track and its capacity silently, and inventing a turnout to\n * reach it would be exactly the fabrication ADR 0001 forbids — the owner is the\n * only one who knows where it actually joins.\n */\nexport interface OrphanTrack {\n id: string;\n trackName?: string;\n role: TrackRole;\n why: string;\n}\n\nexport interface ModuleConversionReport {\n /** Already authored as pieces — there is nothing to convert. */\n alreadyGraph: boolean;\n /**\n * The rebuild can be offered. False when {@link blockers} is non-empty: those\n * are shapes no answer can supply, so offering would promise something that\n * cannot finish.\n */\n offerable: boolean;\n /**\n * True when the rebuild could run right now with nothing asked.\n *\n * ⚠️ Requires BOTH that every turnout resolves and that no track is orphaned.\n * Checking only the turnouts claimed four production modules were ready when\n * converting them would have quietly dropped nine named tracks.\n */\n readyWithoutAsking: boolean;\n turnouts: TurnoutIdentity[];\n /** Ids of the turnouts the owner must identify first. */\n unanswered: string[];\n orphanTracks: OrphanTrack[];\n blockers: ConversionBlocker[];\n}\n\n/** A part that IS this frog number and can actually be drawn — never a nearby\n * one. A #6 is not a #5 (see {@link partExtentForSize}); silently converting a\n * #6 into the #7 we happen to have measured would put a real turnout's frog in\n * a place the owner never built it. */\nfunction placeableTurnoutParts(library: TrackPart[], kind: TrackPart[\"kind\"][]): TrackPart[] {\n // ⛔ NO STAND-INS. This answers \"which real part is this?\", both for automatic\n // resolution and for the candidates offered beside it. A placeholder is a\n // separate, explicitly-chosen fallback — see `provisionalParts`.\n return library.filter(\n (p) => kind.includes(p.kind) && !p.provisional && partGeometryGap(p) == null,\n );\n}\n\n/**\n * What would happen if this document were rebuilt as pieces — WITHOUT rebuilding\n * anything.\n *\n * This exists so an owner can be shown the offer and its cost before they accept\n * it (ADR 0001 amendment, 2026-07-27: conversion is opt-in PER MODULE, never\n * silent). It is pure, cheap, reads no geometry, and is safe to run on every\n * module in a list.\n *\n * ⚠️ **A document with a graph is NOT re-reported.** It is already the thing\n * conversion produces.\n */\nexport function moduleConversionReport(\n doc: ModuleSchematicDoc,\n library = BUILT_IN_TRACK_PARTS,\n): ModuleConversionReport {\n if (doc.graph?.pieces?.length) {\n return {\n alreadyGraph: true,\n offerable: false,\n readyWithoutAsking: false,\n turnouts: [],\n unanswered: [],\n orphanTracks: [],\n blockers: [],\n };\n }\n\n const straight = placeableTurnoutParts(library, [\"turnout\"]);\n const curved = placeableTurnoutParts(library, [\"curved-turnout\"]);\n const blockers: ConversionBlocker[] = [];\n\n /**\n * ⭐ A CROSSOVER'S OWN POINT-SETS ARE ALREADY ANSWERED.\n *\n * The document names the crossover product on its connectors, and a double\n * crossover is ONE assembly whose four point-sets come with it. Asking \"which\n * turnout is this?\" about them asks an owner to identify parts of a product\n * they have already named — and on a #6 crossover it asked for a measured #6\n * TURNOUT, which has nothing to do with it.\n */\n const assemblyPart = new Map<string, TrackPart>();\n for (const t of doc.tracks ?? []) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = library.find((p) => p.id === t.crossoverPartId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n for (const sw of doc.turnouts ?? [])\n if (sw.divergeTrack === t.id) assemblyPart.set(sw.id, part);\n }\n\n const turnouts: TurnoutIdentity[] = (doc.turnouts ?? []).map((t) => {\n const asm = assemblyPart.get(t.id);\n if (asm)\n return {\n id: t.id,\n name: t.name,\n pos: t.pos,\n size: t.size,\n statedPartId: t.partId,\n partId: asm.id,\n from: \"assembly\" as const,\n source: partGeometry(asm, library)?.source ?? null,\n why: null,\n candidates: [],\n };\n const wantCurved = t.curved === true;\n const pool = wantCurved ? curved : straight;\n const base = {\n id: t.id,\n name: t.name,\n pos: t.pos,\n size: t.size,\n statedPartId: t.partId,\n };\n // An exact frog match first, then everything placeable — the owner may know\n // the part even where the document's frog number is wrong or absent.\n const exact = t.size == null ? [] : pool.filter((p) => p.frogNumber === t.size);\n const candidates = [...exact, ...pool.filter((p) => !exact.includes(p))].map((p) => p.id);\n const resolve = (part: TrackPart, from: TurnoutIdentity[\"from\"]): TurnoutIdentity => ({\n ...base,\n partId: part.id,\n from,\n source: partGeometry(part, library)?.source ?? null,\n why: null,\n candidates,\n });\n\n // 1. The document names a part. Strongest answer there is — provided we can\n // draw it. A named part we cannot place is still unanswered, but the\n // reason names the measurement rather than the owner.\n if (t.partId) {\n const named = library.find((p) => p.id === t.partId);\n if (named && partGeometryGap(named) == null) return resolve(named, \"named\");\n return {\n ...base,\n partId: null,\n from: \"unresolved\",\n source: null,\n why: named\n ? `this turnout names ${named.id}, which cannot be placed yet — ${partGeometryGap(named)}`\n : `this turnout names a part the library does not have (${t.partId})`,\n candidates,\n };\n }\n\n // 2. A frog number, and a placeable part that IS that frog number.\n if (t.size != null && exact.length) return resolve(exact[0], \"frog-number\");\n\n // 3. Everything else is a question for the owner. The two reasons are\n // genuinely different and an owner can act on the difference: one is a\n // measurement nobody has taken, the other is a fact only they hold.\n return {\n ...base,\n partId: null,\n from: \"unresolved\",\n source: null,\n why:\n t.size == null\n ? \"the document never says what this turnout is — no part, no frog number\"\n : wantCurved\n ? `no curved turnout is placeable yet, so a curved #${t.size} cannot be converted`\n : `no measured #${t.size} in the parts library yet`,\n candidates,\n };\n });\n\n // ⚠️ BLOCKERS ARE NOT QUESTIONS. A question has an answer the owner can give;\n // these are shapes the piece model cannot express at all yet, so the offer is\n // withheld rather than made and then abandoned half way.\n for (const c of doc.crossings ?? [])\n blockers.push({\n kind: \"crossing\",\n ref: c.id,\n why: \"crossing geometry is not modelled yet, so a diamond has no piece to become\",\n });\n if (doc.loop)\n blockers.push({\n kind: \"loop\",\n why:\n \"a balloon's curve radii were never recorded, and laying the loop would mean \" +\n \"inventing them — the one thing ADR 0001 forbids\",\n });\n\n // A track is reached by a turnout DIVERGING onto it. Appearing as a turnout's\n // `onTrack` does not count: that says something branches OFF this track, which\n // still leaves it needing a way in of its own.\n const reached = new Set((doc.turnouts ?? []).map((t) => t.divergeTrack));\n const orphanTracks: OrphanTrack[] = (doc.tracks ?? [])\n // A main is reached by definition — it starts at the endplate.\n .filter((t) => t.role !== \"main\" && !reached.has(t.id))\n .map((t) => ({\n id: t.id,\n ...(t.trackName ? { trackName: t.trackName } : {}),\n role: t.role,\n why: \"no turnout in the document diverges onto this track, so there is nothing to join it to\",\n }));\n\n const unanswered = turnouts.filter((t) => !t.partId).map((t) => t.id);\n return {\n alreadyGraph: false,\n offerable: blockers.length === 0,\n readyWithoutAsking:\n blockers.length === 0 && unanswered.length === 0 && orphanTracks.length === 0,\n turnouts,\n unanswered,\n orphanTracks,\n blockers,\n };\n}\n\n/**\n * What the owner said when offered the rebuild.\n *\n * ⭐ **ONE ANSWER FOR THE WHOLE MODULE.** Owners lay one kind of turnout\n * throughout, or at most two, so asking per turnout asks the same question eight\n * times on a yard. The module-wide answer IS the question; `overrides` is for the\n * odd one out. (Will's call, 2026-07-27 — it turns 41 questions across the\n * production database into 14.)\n */\nexport interface ConversionAnswers {\n /** \"The turnouts on this module are…\" — a part id from the library. */\n turnoutPartId?: string | null;\n /** The exceptions, by turnout id. Beats {@link turnoutPartId}. */\n overrides?: Record<string, string>;\n}\n\nexport interface DocToGraphResult {\n /** The graph to store, or null when the document could not be converted. */\n graph: NonNullable<ModuleSchematicDoc[\"graph\"]> | null;\n /** Why the whole conversion was refused — null when it ran. */\n refused: string | null;\n /**\n * Track the conversion could not lay, each with a reason.\n *\n * ⚠️ **A REAL LOSS, AND THE OWNER MUST SEE IT.** Unshown, a \"successful\"\n * rebuild would quietly be missing a named siding.\n */\n notLaid: { id: string; why: string }[];\n warnings: string[];\n}\n\n/** Below this a transition curve is not something anyone laid by hand. Flagged,\n * never corrected — the house rule (see {@link FREEMO_MAIN_MIN_RADIUS_INCHES}). */\nconst CONVERSION_TIGHT_RADIUS_INCHES = 12;\n\n/**\n * Rebuild a 1-D document as a graph of placed pieces.\n *\n * ⭐ **THE OWNER ASKED FOR THIS ONE MODULE** (ADR 0001 amendment, 2026-07-27).\n * Nothing calls it on a schedule, on load, or in bulk. Conversion supplies\n * geometry the 1-D document never recorded, which is what the original\n * constraint forbade doing behind an owner's back; done in front of them, having\n * shown them {@link moduleConversionReport} and taken their answer, it is an\n * edit they made.\n *\n * ⚠️ **STRAIGHT HOSTS ONLY.** A run is laid along its host's axis, so a module\n * whose main is DRAWN with bends is refused rather than quietly straightened.\n * Every module in production today has a straight main; the refusal is there so\n * the first curved one is a message and not a flattened drawing.\n *\n * ⭐ **PIECES CHAIN FROM MEASURED JOINTS, NOT FROM ABSOLUTE ARITHMETIC.** Each\n * piece is placed, its real joints are read back with {@link placedJoints}, and\n * the next starts from one of those. Connection then holds BY CONSTRUCTION\n * rather than by two independent calculations agreeing to within\n * {@link JOINT_SNAP_INCHES} — a hundredth of an inch is far too tight to hit by\n * coincidence.\n *\n\n * ⭐ A TURNOUT'S THROAT GOES AT `pos − frogOffset`: a document's `pos` is the\n * That is the inverse of what {@link walkTrackGraph} reports, which is the only\n * thing that makes convert-then-derive an identity. It is deliberately NOT\n * {@link turnoutOccupiedSpan}'s anchor, and the two disagree by\n * `lead − pointsOffset` — 2.97″ on an Atlas #7. That disagreement is real and\n * unresolved: see the note on {@link moduleConversionReport}. Because of it the\n * flex gaps here are measured off the placed pieces' OWN joints rather than\n * through the 1-D helper, so whichever anchor turns out to be right, the track\n * still meets the turnout it was cut for.\n */\nexport function docToGraph(\n doc: ModuleSchematicDoc,\n answers: ConversionAnswers = {},\n library = BUILT_IN_TRACK_PARTS,\n): DocToGraphResult {\n const refuse = (why: string): DocToGraphResult => ({\n graph: null,\n refused: why,\n notLaid: [],\n warnings: [],\n });\n\n const report = moduleConversionReport(doc, library);\n if (report.alreadyGraph) return refuse(\"this module is already authored as pieces\");\n if (!report.offerable) return refuse(report.blockers.map((b) => b.why).join(\"; \"));\n if ((doc.mainPath?.length ?? 0) > 2)\n return refuse(\n \"this module's mainline is drawn with bends, and laying it as pieces would need each bend's radius — convert it once curved runs are supported\",\n );\n\n const partById = new Map(library.map((p) => [p.id, p]));\n\n /**\n * ⭐ Turnouts that are a CROSSOVER ASSEMBLY'S OWN POINT-SETS.\n *\n * The assembly answers for them, so they are neither asked about nor laid\n * individually. Without this an owner is asked \"which turnout is this?\" about\n * four point-sets of a product they have already named — and on FMN-0078,\n * whose crossovers are #6, the whole conversion refused for want of a measured\n * #6 turnout that has nothing to do with it.\n */\n const inAssembly = new Set<string>();\n for (const t of doc.tracks ?? []) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = partById.get(t.crossoverPartId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n for (const sw of doc.turnouts ?? []) if (sw.divergeTrack === t.id) inAssembly.add(sw.id);\n }\n\n const chosen = new Map<string, TrackPart>();\n const unknown: string[] = [];\n for (const t of report.turnouts) {\n if (inAssembly.has(t.id)) continue;\n const id = answers.overrides?.[t.id] ?? (t.partId ? t.partId : answers.turnoutPartId) ?? null;\n const part = id ? partById.get(id) : undefined;\n if (!part || partGeometryGap(part)) unknown.push(t.id);\n else chosen.set(t.id, part);\n }\n if (unknown.length)\n return refuse(\n `${unknown.length} turnout${unknown.length === 1 ? \"\" : \"s\"} still need identifying: ${unknown.join(\", \")}`,\n );\n\n const flexId = DEFAULT_FLEX_PART_ID;\n if (!partById.get(flexId)) return refuse(\"the parts library has no flex track to lay plain track with\");\n const maxPiece = maxFlexPieceInches(flexId, library);\n\n const tracks = doc.tracks ?? [];\n const trackById = new Map(tracks.map((t) => [t.id, t]));\n const turnouts = doc.turnouts ?? [];\n const mainLen =\n doc.lengthInches ??\n Math.max(0, ...tracks.map((t) => t.toPos ?? 0), ...turnouts.map((t) => t.pos));\n if (!(mainLen > 0)) return refuse(\"this module has no length to lay track along\");\n\n const pieces: TrackPiece[] = [];\n const notLaid: { id: string; why: string }[] = [];\n const warnings: string[] = [];\n const rad = (d: number) => (d * Math.PI) / 180;\n /** Signed turn, −180…180 — a heading difference has a SIDE, and `norm360`\n * would report a small left turn as 359°. */\n const norm180 = (d: number) => ((((d + 180) % 360) + 360) % 360) - 180;\n const r3 = (n: number) => Math.round(n * 1000) / 1000;\n const jointsOf = (p: TrackPiece) => placedJoints([p], library);\n const jointAt = (p: TrackPiece, id: string) => jointsOf(p).find((j) => j.joint === id) ?? null;\n type Cursor = { x: number; y: number; headingDeg: number };\n\n /**\n * A transition curve: leave `from` on its current heading, arrive parallel to\n * the module axis at `toY`.\n *\n * ⭐ **THE RADIUS IS DERIVED, NOT INVENTED.** Turning through θ moves a run\n * R(1 − cos θ) sideways, so the document's own lane offset and the part's own\n * frog angle fix R between them. Nothing here is a preference. It is also what\n * track physically does: the turnout throws the rail out at the frog angle and\n * a curve brings it back parallel. The 1-D model's instant jump to a lane\n * offset is the thing that was never real.\n */\n const transition = (\n id: string,\n from: Cursor,\n toY: number,\n /** +1 running east, −1 running west. ⚠️ A SIDING'S CLOSING CURVE RUNS THE\n * OTHER WAY, and measuring its heading against +x called an 8° turn a 172°\n * one — which came out as a 0.3″ radius instead of 51″. Everything here is\n * relative to the direction of travel. */\n dirSign: 1 | -1 = 1,\n ): TrackPiece | null => {\n const theta = rad(norm180(from.headingDeg - (dirSign > 0 ? 0 : 180)));\n // The piece's own +y is the module's +y only when it runs east.\n const dy = (toY - from.y) * dirSign;\n if (Math.abs(theta) < 1e-9 || Math.abs(dy) < 1e-9) return null;\n const R = dy / (1 - Math.cos(theta));\n if (!Number.isFinite(R) || R === 0) return null;\n const mag = Math.abs(R);\n if (mag < CONVERSION_TIGHT_RADIUS_INCHES)\n warnings.push(\n `the curve bringing ${id} back parallel works out at ${mag.toFixed(1)}″ radius — tighter than anyone lays by hand, which usually means the document's lane and its turnout disagree`,\n );\n return {\n id,\n partId: flexId,\n x: from.x,\n y: from.y,\n rotationDeg: from.headingDeg,\n // Curving BACK toward the host: opposite the way we are already heading.\n // `radiusInches` is signed and the sign IS the side.\n radiusInches: r3(-Math.sign(theta) * mag),\n lengthInches: r3(mag * Math.abs(theta)),\n };\n };\n\n /** Place a turnout so {@link walkTrackGraph} will report it at `t.pos`. */\n const layTurnout = (t: SchematicTurnout, hostY: number) => {\n const part = chosen.get(t.id)!;\n const geom = partGeometry(part, library)!;\n const branch = trackById.get(t.divergeTrack);\n // ⚠️ WHICH WAY DOES THE BRANCH LEAVE? The far end is whichever of the\n // branch's ends is further from this turnout — NOT always `toPos`. On a\n // siding's east turnout `toPos` IS its own position, so passing it left\n // `turnoutFacing` with a zero to sign and it fell through to \"east\",\n // pointing the diverging rail away from the siding it opens.\n const ends = [branch?.fromPos, branch?.toPos].filter(\n (n): n is number => typeof n === \"number\" && Number.isFinite(n),\n );\n const divergeFarPos = ends.length\n ? ends.reduce((a, b) => (Math.abs(b - t.pos) > Math.abs(a - t.pos) ? b : a))\n : undefined;\n const facing = turnoutFacing({\n pos: t.pos,\n divergeFarPos,\n flipped: t.flipped ?? false,\n });\n const body = part.overallLength!.inches;\n const lead = part.lead?.inches ?? body / 2;\n // ⭐ A DOCUMENT'S `pos` IS THE FROG (Will, 2026-07-27), and the frog sits\n // `frogOffset` from the tie end. Entered at the throat the walk reports\n // `throat + frogOffset`; entered at the through end, `through + (body −\n // frogOffset)`. Invert whichever applies so the turnout comes back out where\n // the document put it.\n const frogAxial = part.frogOffset?.inches ?? (part.pointsOffset?.inches ?? 0) + lead;\n const throatPos = facing > 0 ? t.pos - frogAxial : t.pos + frogAxial;\n const hostLane = trackById.get(t.onTrack)?.lane ?? 0;\n // Which way must the diverging route go? The part diverges to its own +y;\n // turning it end-for-end sends that to module −y. ⭐ No hand is stored\n // anywhere — this reads the side off the document's lanes.\n const want = Math.sign((branch?.lane ?? hostLane) - hostLane) || 1;\n const unflipped = facing > 0 ? 1 : -1;\n const piece: TrackPiece = {\n id: `t-${t.id}`,\n partId: part.id,\n x: throatPos,\n y: hostY,\n rotationDeg: facing > 0 ? 0 : 180,\n ...(unflipped !== want ? { flipped: true } : {}),\n ...(t.name ? { name: t.name } : {}),\n };\n // ⚠️ THE BODY IS MEASURED OFF THE PIECE, not off `partExtent` — see the\n // anchor warning on this function. Whatever the 1-D helper believes, flex\n // has to stop where this piece's rail actually starts.\n const bodyEnds = [throatPos, facing > 0 ? throatPos + body : throatPos - body];\n const span: OccupiedSpan = { fromPos: Math.min(...bodyEnds), toPos: Math.max(...bodyEnds) };\n const divergeId = geom.joints.find((j) => j.role === \"diverge\")?.id ?? \"diverge\";\n return { t, piece, span, divergeId };\n };\n\n /**\n * Re-aim a straight flex piece so its far end lands exactly on a point.\n *\n * A run that has to meet something slightly off its lane — a crossover pinches\n * the mains together — is eased over by the builder, and the angle is far\n * below anything drawable (0.035″ over a 30″ piece is 0.07°). Doing it by\n * re-aiming the piece keeps the joint EXACT, which is what the graph needs.\n */\n const aimEndAt = (piece: TrackPiece, to: { x: number; y: number }) => {\n const dx = to.x - piece.x;\n const dy = to.y - piece.y;\n const len = Math.hypot(dx, dy);\n if (!(len > 0)) return;\n // ⚠️ THE ANGLE IS NOT ROUNDED. Rounding it to three places moved the far end\n // by ~1.5e-5″ — harmless against JOINT_SNAP_INCHES, but this joint is meant\n // to be exact BY CONSTRUCTION, and \"close enough to snap\" is the habit that\n // lets real drift in.\n piece.rotationDeg = (Math.atan2(dy, dx) * 180) / Math.PI;\n piece.lengthInches = len;\n };\n\n /** Lay the plain track of one straight run at `hostY`, between two positions,\n * around the bodies already sitting in it. */\n const layFlex = (\n label: string,\n hostY: number,\n fromPos: number,\n toPos: number,\n occupied: OccupiedSpan[],\n cuts?: number[] | null,\n ) => {\n const out = flexPieces({ fromPos, toPos, maxPieceInches: maxPiece, occupied, cuts: cuts ?? null });\n const placed: TrackPiece[] = out.map((f, i) => ({\n id: `f-${label}-${i}`,\n partId: flexId,\n x: f.fromPos,\n y: hostY,\n rotationDeg: 0,\n lengthInches: r3(f.lengthInches),\n }));\n pieces.push(...placed);\n return placed;\n };\n\n /**\n * Every turnout sitting ON a track, laid, with its body span — minus any whose\n * mouldings would occupy the same rail.\n *\n * ⚠️⚠️ **TWO TURNOUTS CANNOT SHARE AN INCH OF TRACK, AND NOTHING ELSE NOTICES.**\n * {@link flexPieces} deliberately MERGES overlapping occupied spans, so the\n * flex is cut around the union and the two pieces are simply left intersecting;\n * the walk then threads a path through geometry that cannot exist and emits a\n * module nobody has. FMN-0078 is the case: its scissors crossover puts two\n * turnouts 2.5″ apart, and an Atlas #7 is 6″ long — the rebuild produced two\n * turnouts at 91.9″ and called the crossovers sidings.\n *\n * A real scissors is ONE assembly for exactly this reason. Dropping the pair\n * and saying so leaves a module that is honestly missing its crossover, rather\n * than one that is quietly wrong.\n */\n const turnoutsOn = (trackId: string, hostY: number) => {\n const laid = turnouts\n .filter((t) => t.onTrack === trackId && chosen.has(t.id))\n .map((t) => layTurnout(t, hostY))\n .sort((a, b) => a.span.fromPos - b.span.fromPos);\n const clashed = new Set<string>();\n for (let i = 1; i < laid.length; i += 1) {\n const prev = laid[i - 1];\n const cur = laid[i];\n if (cur.span.fromPos < prev.span.toPos - 1e-6) {\n clashed.add(prev.t.id);\n clashed.add(cur.t.id);\n const gap = Math.abs(cur.t.pos - prev.t.pos);\n const body = prev.span.toPos - prev.span.fromPos;\n // ⭐⭐ IS THIS A CROSSOVER ASSEMBLY? Then the overlap is OUR modelling\n // error, not the owner's track. A double crossover is ONE moulding whose\n // four point-sets sit closer together than four separate turnouts ever\n // could — that is the entire reason it is sold as a single fixture.\n // Telling an owner their turnouts collide would blame them for a real\n // and perfectly ordinary piece of trackwork.\n const asm = trackById.get(cur.t.divergeTrack)?.role === \"crossover\";\n notLaid.push({\n id: cur.t.divergeTrack,\n why: asm\n ? `this is a crossover — one assembly, not ${gap.toFixed(1)}″ between two separate turnouts. Laying it needs the crossover product itself; pick one on the track and it can be placed as the single piece it is`\n : `${prev.t.name || prev.t.id} and ${cur.t.name || cur.t.id} are ${gap.toFixed(1)}″ apart on the same track, but the turnout chosen is ${body.toFixed(1)}″ long — their mouldings would overlap, so they cannot both be where the document puts them`,\n });\n }\n }\n return laid.filter((l) => !clashed.has(l.t.id));\n };\n\n /**\n * ⭐⭐ A DOUBLE CROSSOVER IS LAID AS **ONE PIECE** (Will, 2026-07-28).\n *\n * Found by its connectors: crossover-role tracks naming a placeable crossover\n * product. The four turnouts the document lists are the assembly's own\n * point-sets, so they are NOT laid individually — doing that is what made the\n * FMN-0078 rebuild collapse.\n *\n * ⚠️ **THE PRODUCT'S GEOMETRY WINS, AND ITS POSITION IS THE OWNER'S.** A real\n * #6 assembly is 20.14″ with its point-sets 6.54″ apart; a document may record\n * them anywhere. So it is centred on the mean of the recorded positions — the\n * crossover stays where the owner put it — and any discrepancy is reported\n * rather than silently absorbed.\n */\n const assemblies = (() => {\n const out: {\n part: TrackPart;\n geom: NonNullable<ReturnType<typeof crossoverAssembly>>;\n x0: number;\n trackIds: Set<string>;\n turnoutIds: Set<string>;\n }[] = [];\n const byPart = new Map<string, SchematicTrack[]>();\n for (const t of tracks) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const list = byPart.get(t.crossoverPartId) ?? [];\n list.push(t);\n byPart.set(t.crossoverPartId, list);\n }\n for (const [partId, connectors] of byPart) {\n const part = partById.get(partId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n const geom = crossoverAssembly(part);\n if (!geom) continue;\n const trackIds = new Set(connectors.map((c) => c.id));\n const mine = turnouts.filter((t) => trackIds.has(t.divergeTrack));\n if (!mine.length) continue;\n const centre = mine.reduce((a, t) => a + t.pos, 0) / mine.length;\n const x0 = centre - geom.lengthInches / 2;\n const spread = Math.max(...mine.map((t) => t.pos)) - Math.min(...mine.map((t) => t.pos));\n if (Math.abs(spread - geom.crossingRunInches) > 0.05)\n warnings.push(\n `this document puts the crossover's point-sets ${spread.toFixed(2)}″ apart, but a ${part.name ?? partId} is ${geom.crossingRunInches.toFixed(2)}″ — the assembly is laid to its own dimensions, centred where the document has it`,\n );\n out.push({ part, geom, x0, trackIds, turnoutIds: new Set(mine.map((t) => t.id)) });\n }\n return out;\n })();\n /** Connectors that belong to an assembly are ITS business, not branches. */\n const assemblyTracks = new Set(assemblies.flatMap((a) => [...a.trackIds]));\n\n // ── THE MAINS. Both run along the module's axis; Main 2 sits a lane over.\n const main = trackById.get(MAIN_TRACK_ID) ?? tracks.find((t) => t.role === \"main\");\n if (!main) return refuse(\"this module's document has no mainline to convert\");\n const mains = [main, ...tracks.filter((t) => t.role === \"main\" && t.id !== main.id)];\n const laidTurnouts = new Map<string, ReturnType<typeof layTurnout>>();\n const done = new Set<string>();\n\n // The assemblies go down first: they sit ON the mains, so the flex has to be\n // cut around them, and Main 2 has to be brought in to meet them.\n const mainY = laneOffsetAt(mains[0]?.lane ?? 0, 0);\n for (const [i, a] of assemblies.entries()) {\n pieces.push({\n id: `xo-${i}`,\n partId: a.part.id,\n x: r3(a.x0),\n y: mainY,\n rotationDeg: 0,\n ...(a.part.name ? { name: a.part.name } : {}),\n });\n }\n const assemblySpans: OccupiedSpan[] = assemblies.map((a) => ({\n fromPos: a.x0,\n toPos: a.x0 + a.geom.lengthInches,\n }));\n\n for (const m of mains) {\n const y = laneOffsetAt(m.lane ?? 0, 0);\n const on = turnoutsOn(m.id, y);\n for (const l of on) {\n pieces.push(l.piece);\n laidTurnouts.set(l.t.id, l);\n }\n const laidFlex = layFlex(\n m.id,\n y,\n m.fromPos ?? 0,\n m.toPos ?? mainLen,\n [...on.map((l) => l.span), ...assemblySpans],\n m.flexCuts,\n );\n /**\n * ⚠️⚠️ **THE PINCH.** A #6 assembly is 1.09″ wide while the mains run\n * {@link FREEMO_TRACK_SPACING_INCHES} apart, so Main 2's rail has to come in\n * 0.035″ to meet it and go back out the other side. In the graph this is not\n * a special case at all — the piece IS 1.09″ wide and the flex bends to\n * reach it, which is exactly what retires `LanePinch`, `laneOffsetAt`'s\n * pinch handling and `PINCH_EASE_INCHES` from the 1-D model.\n *\n * ⚠️ NOT a departure from the standard: §2.0 fixes the spacing AT THE\n * ENDPLATE, and every real double crossover pinches the mains closer.\n */\n if (m !== mains[0]) {\n for (const a of assemblies) {\n const west = a.x0;\n const east = a.x0 + a.geom.lengthInches;\n const target = mainY + a.geom.spacingInches;\n for (const f of laidFlex) {\n const end = f.x + (f.lengthInches ?? 0);\n if (Math.abs(end - west) < 1e-6) aimEndAt(f, { x: west, y: target });\n else if (Math.abs(f.x - east) < 1e-6) {\n f.y = target;\n aimEndAt(f, { x: end, y: y });\n }\n }\n }\n }\n done.add(m.id);\n }\n\n // An assembly's connectors are already on the board — they are routes THROUGH\n // the piece, not branches hanging off a turnout. Marking them done keeps the\n // final sweep from reporting a crossover that was laid perfectly well.\n for (const id of assemblyTracks) done.add(id);\n\n // ── EVERY OTHER TRACK HANGS OFF A TURNOUT. Laid outward from the mains,\n // repeating until nothing new is reachable — which is how a ladder three\n // turnouts deep resolves without the conversion knowing it is one.\n let progressed = true;\n while (progressed) {\n progressed = false;\n for (const t of turnouts) {\n if (!done.has(t.onTrack)) continue; // its host is not laid yet\n const branch = trackById.get(t.divergeTrack);\n if (!branch || done.has(branch.id)) continue;\n const near = laidTurnouts.get(t.id);\n if (!near) continue;\n done.add(branch.id);\n progressed = true;\n\n const dj = jointAt(near.piece, near.divergeId);\n if (!dj) {\n notLaid.push({ id: branch.id, why: `turnout ${t.id} has no diverging end to leave from` });\n continue;\n }\n // A SIDING is the same track reached by a SECOND turnout — and a CROSSOVER\n // is that too, but between the two mains.\n const farSw0 = turnouts.find(\n (o) => o.id !== t.id && o.divergeTrack === branch.id && laidTurnouts.has(o.id),\n );\n const farJoint0 = farSw0\n ? (() => {\n const f = laidTurnouts.get(farSw0.id)!;\n return jointAt(f.piece, f.divergeId);\n })()\n : null;\n\n // ⭐⭐ A CROSSOVER CONNECTOR NEVER COMES PARALLEL TO A LANE. It runs\n // diagonally from one main to the other, so the transition curve that\n // straightens a siding onto its lane is exactly the wrong shape here — it\n // asked for a 0.3″ radius and then reported the crossover as unbuildable.\n // Straight between the two diverging joints is what a crossover IS, and\n // landing on both by construction is what makes it join at all.\n if (branch.role === \"crossover\" && farJoint0) {\n const dx = farJoint0.x - dj.x;\n const dy = farJoint0.y - dj.y;\n const len = Math.hypot(dx, dy);\n if (len > 1e-6) {\n pieces.push({\n id: `x-${branch.id}`,\n partId: flexId,\n x: dj.x,\n y: dj.y,\n rotationDeg: (Math.atan2(dy, dx) * 180) / Math.PI,\n lengthInches: r3(len),\n ...(branch.trackName ? { name: branch.trackName } : {}),\n });\n } else {\n notLaid.push({\n id: branch.id,\n why: \"this crossover's two turnouts meet at the same point, so there is no connector between them to lay\",\n });\n }\n continue;\n }\n\n const branchY = laneOffsetAt(branch.lane ?? 0, 0);\n const curve = transition(branch.id, { x: dj.x, y: dj.y, headingDeg: dj.headingDeg }, branchY);\n let start: Cursor = { x: dj.x, y: dj.y, headingDeg: dj.headingDeg };\n if (curve) {\n pieces.push(curve);\n const e = jointAt(curve, \"b\");\n if (e) start = { x: e.x, y: e.y, headingDeg: e.headingDeg };\n }\n\n // A SIDING is the same track reached by a SECOND turnout. Its far end is\n // that turnout's diverging joint, not a position — so the run is closed\n // onto it, the way a builder cuts the last piece to fit.\n const farJoint = farJoint0;\n let endX =\n farJoint != null\n ? farJoint.x\n : Math.max(branch.fromPos ?? t.pos, branch.toPos ?? t.pos);\n let farCurve: TrackPiece | null = null;\n if (farJoint) {\n // ⚠️ The joint's heading ALREADY points the way this rail runs — west,\n // out of the far turnout and back down the siding. Reversing it as well\n // as passing `dirSign: -1` flipped it twice and turned an 8° transition\n // into a 172° one.\n farCurve = transition(\n `${branch.id}-far`,\n { x: farJoint.x, y: farJoint.y, headingDeg: farJoint.headingDeg },\n branchY,\n -1,\n );\n if (farCurve) {\n pieces.push(farCurve);\n const e = jointAt(farCurve, \"b\");\n if (e) endX = e.x;\n }\n }\n\n // ⚠️ THE MODULE MAY NOT HAVE ROOM FOR WHAT THE OWNER CHOSE. A turnout has\n // a real body and a real transition; a ladder pitched tighter than they\n // need cannot be built from those parts at all. The 1-D model never had to\n // notice — it draws a spur at its lane the instant the turnout appears.\n // Say so rather than lay a run of negative length.\n if (endX - start.x <= 1e-6) {\n notLaid.push({\n id: branch.id,\n why: `the turnout and the curve bringing this track parallel already reach ${start.x.toFixed(1)}″, past where it has to end at ${endX.toFixed(1)}″ — with the turnout chosen there is no room for this track where the document places it`,\n });\n continue;\n }\n\n const on = turnoutsOn(branch.id, branchY).filter((l) => {\n if (l.span.fromPos >= start.x - 1e-6) return true;\n notLaid.push({\n id: l.t.divergeTrack,\n why: `turnout ${l.t.id} sits at ${l.t.pos}″ but this track has only reached ${start.x.toFixed(1)}″ by then — the ladder is pitched tighter than the chosen turnout allows`,\n });\n return false;\n });\n for (const l of on) {\n pieces.push(l.piece);\n laidTurnouts.set(l.t.id, l);\n }\n layFlex(branch.id, branchY, start.x, endX, on.map((l) => l.span), branch.flexCuts);\n }\n }\n\n // ⚠️ Anything still unlaid has to be named. A track whose parent could not be\n // laid never gets its turn in the loop above, so without this sweep a ladder\n // that failed at its second turnout would report the second track and stay\n // silent about the third — the owner would be told about part of the loss.\n const orphanWhy = new Map(report.orphanTracks.map((o) => [o.id, o.why]));\n const alreadySaid = new Set(notLaid.map((n) => n.id));\n for (const t of tracks) {\n if (t.role === \"main\" || done.has(t.id) || alreadySaid.has(t.id)) continue;\n notLaid.push({\n id: t.id,\n why:\n orphanWhy.get(t.id) ??\n \"the track it branches from could not be laid, so there is nothing to join it to\",\n });\n }\n\n // ── Where each main begins: the westmost joint sitting in its lane.\n const startOf = (t: SchematicTrack) => {\n const y = laneOffsetAt(t.lane ?? 0, 0);\n let best: { piece: string; joint: string; x: number } | null = null;\n for (const p of pieces)\n for (const j of jointsOf(p)) {\n if (Math.abs(j.y - y) > 0.05) continue;\n if (!best || j.x < best.x) best = { piece: p.id, joint: j.joint, x: j.x };\n }\n return best ? { piece: best.piece, joint: best.joint } : null;\n };\n const startAt = startOf(main);\n if (!startAt) return refuse(\"nothing was laid on the mainline, so the module has no starting point\");\n const second = mains[1] ? startOf(mains[1]) : null;\n\n return {\n graph: { pieces, startAt, ...(second ? { start2: second } : {}) },\n refused: null,\n notLaid,\n warnings,\n };\n}\n\n/** A frog casting's parts, in TURNOUT-LOCAL inches: `x` = distance past the\n * points, `y` = lateral offset from the through route. */\nexport interface FrogCasting {\n /** The point rail — the acute V, apex at the crossing, opening toward the\n * diverging end. Three points: through leg, apex, diverging leg. */\n point: Array<{ x: number; y: number }>;\n /** The two wing rails flanking the point, each a short polyline. */\n wings: Array<Array<{ x: number; y: number }>>;\n /** The apex — where the two inner rails actually cross. */\n apex: { x: number; y: number };\n}\n\n/**\n * The frog casting at a turnout's crossing.\n *\n * The apex is where the two INNER rails cross, which is HALF a gauge off the\n * through centre-line (the through inner rail sits at +g/2, the diverging inner\n * rail at d−g/2, and d = g at the frog). Not one full gauge — that is the\n * diverging CENTRE-line, and putting the casting there floats it clear of the\n * rails it is made of.\n *\n * ⚠️ **The flangeway is EXAGGERATED and that is deliberate.** True scale in N is\n * about 0.011″ (prototype 1¾″ ÷ 160) — one pixel in a close-up render and\n * invisible at module zoom. Drawn to scale the wing rails would sit exactly on\n * the running rails and add nothing. `flangewayInches` defaults to a readable\n * fraction of the gauge instead; pass the true figure if you ever need it.\n */\nexport function frogCasting(\n cl: TurnoutClosure,\n opts: {\n gaugeInches?: number;\n /** How far the casting runs either side of the apex. */\n reachInches?: number;\n /** See the warning above — exaggerated for legibility by default. */\n flangewayInches?: number;\n } = {},\n): FrogCasting {\n const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;\n const w = opts.reachInches ?? g * 1.5;\n const fw = opts.flangewayInches ?? g * 0.12;\n const m = cl.frogSlope;\n const lead = cl.lead;\n const apex = { x: lead, y: g / 2 };\n\n // Past the apex the two inner rails separate: the through one stays at +g/2,\n // the diverging one climbs at the frog angle. That divergence IS the V.\n const point = [\n { x: lead + w, y: g / 2 },\n apex,\n { x: lead + w, y: g / 2 + m * w },\n ];\n\n // Approaching the frog those same two rails converge. The wing rails are that\n // incoming pair, bent out by a flangeway so a wheel is carried across the gap\n // rather than dropping into it — so each runs past the apex, not up to it.\n const wings = [\n [\n { x: lead - w, y: g / 2 - fw },\n { x: lead - w * 0.35, y: g / 2 - fw },\n { x: lead + w * 0.35, y: g / 2 - fw * 0.5 },\n ],\n [\n { x: lead - w, y: g / 2 + m * -w + fw },\n { x: lead - w * 0.35, y: g / 2 + m * -w * 0.35 + fw },\n { x: lead + w * 0.35, y: g / 2 + m * w * 0.35 + fw * 0.5 },\n ],\n ];\n return { point, wings, apex };\n}\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 // ⚠️ `flipped` MUST be passed. Rotating a turnout 180° swaps the side\n // its route leaves on — that is what divergeSideForHand's third\n // argument is for. Omitting it made the operations view honour the\n // author's HAND but silently ignore their FLIP, so a flipped turnout\n // drew on opposite sides in the 2-D and the dispatcher views. The\n // three authored facts — host track, hand, flip — must all reach the\n // drawing, and both views must read them through THIS function.\n const s = divergeSideForHand(sw.kind, far - sw.pos, sw.flipped);\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 // 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 // Every lane in use BEFORE the branches — the branch routes are then placed\n // clear of all of them, so a branch can never land on top of a siding.\n const baseLanes = [\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\n // Branch endplates → a route leaving the module in the operating view — but\n // ONLY once track actually reaches one. Placing a bare 3rd+ endplate must not\n // conjure a junction; the route follows the drawn branch track that links to\n // it (its trackId), so it appears when you connect track, not when you add the\n // endplate (#170).\n //\n // This is where a branch stops being decoration and becomes Main 3 (#181): it\n // gets a lane of its own and a run of its own length, which together are the\n // axis anything positioned along the branch needs. NB the return-loop\n // generator also emits role:\"branch\" tracks — they're excluded here (and only\n // here) because no endplate's trackId points at them, so loops keep their bulb.\n // Branch lanes start a clear GAP beyond the outermost drawn lane. One empty\n // lane is what stops a route that runs the full width of the strip reading as\n // just another main alongside (#183) — it is an END of the module, and it has\n // to look like one.\n const LANE_GAP_FROM_OTHERS = 2;\n let upLane = Math.max(...baseLanes, 0) + (LANE_GAP_FROM_OTHERS - 1);\n let downLane = Math.min(...baseLanes, 0) - (LANE_GAP_FROM_OTHERS - 1);\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 const trk = (doc.tracks ?? []).find((t) => t.id === e.trackId)!;\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 const startPos = sw ? sw.pos : e.at!.pos;\n const side = e.at!.side === \"down\" ? \"down\" : \"up\";\n const lane = side === \"down\" ? --downLane : ++upLane;\n // The run is the route's OWN length, straightened onto the strip. Its\n // projection on the module axis would be the \"natural\" span, but a square\n // 90° exit projects to zero — the very case that made branches invisible.\n // A path is always shorter along the axis than along itself, so the length\n // is also the larger, safer number.\n const runInches =\n pathLengthInches(trk.path) ||\n Math.abs(e.at!.pos - startPos) ||\n FREEMO_ENDPLATE_WIDTH_MIN_INCHES;\n // ⚠️ The route runs to the EDGE of the module, not for its own length.\n // This is an endplate: a train leaves the module here, exactly as it does\n // at A or B, and the straightened view says so by taking the route to the\n // end of the strip and terminating it at a plate (#183). Its real\n // on-module length is still reported, for the tooltip.\n //\n // Which edge is the one the plate actually sits toward — a junction near\n // the west end exits west.\n const toB = e.at!.pos >= startPos;\n return {\n id: e.id,\n label: e.label ?? e.id,\n name: trk.trackName ?? \"\",\n trackId: trk.id,\n kind: (e.kind === \"main\" ? \"main\" : \"branch\") as \"branch\" | \"main\",\n posFrac: clampFrac(startPos),\n fromLane: (sw ? (trackLane.get(sw.onTrack) ?? 0) : 0) as number,\n side: side as \"up\" | \"down\",\n lane,\n endFrac: toB ? 1 : 0,\n lengthInches: runInches,\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 // Branch lanes are part of the drawn extent, so renderers size their canvas\n // from laneMin/laneMax alone — no \"leave a lane spare if there's a branch\"\n // headroom hack at either end (#181).\n const allLanes = [...baseLanes, ...branchConnectors.map((b) => b.lane)];\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 hasEndplateB: doc.endplates.some((e) => e.id === \"B\"),\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\n/**\n * An endplate bound to a BENCHWORK EDGE (ADR 0001).\n *\n * Will Gage, 2026-07-26: *\"Endplates are a part of the benchwork. We have\n * separated them causing some challenges.\"* A {@link SchematicEndplate.pose} is\n * a point floating in module space, so it can disagree with the board — and has:\n * a junction plate landed on the module CENTRE LINE rather than the fascia, a\n * derived pose written back silently PINNED a plate so it went stale when the\n * length changed (which is the only reason `poseAuthored` exists), and a face\n * drawn flat across a tapered edge is flush only at its midpoint.\n *\n * Bind it to an edge and none of those are expressible. Position, heading and\n * WIDTH all come from the edge, so they cannot drift apart.\n */\nexport interface EndplateEdge {\n /** The section whose outline owns this edge; absent = the module outline. */\n section?: string | null;\n /** Which edge: the segment from vertex `index` to vertex `index + 1`. */\n index: number;\n /** Optional span along that edge, 0…1. Absent = the whole edge — which is the\n * common case, because a board's end IS the endplate. */\n fromT?: number | null;\n toT?: number | null;\n}\n\n/** What an {@link EndplateEdge} resolves to. Everything here is READ OFF the\n * polygon; nothing is stored, so nothing can go stale. */\nexport interface EndplateEdgePose {\n x: number;\n y: number;\n /** The edge's OUTWARD normal, degrees. */\n heading: number;\n /** The span's length — the face's real width, not a separate number that\n * might disagree with the board. */\n widthInches: number;\n /** The face's two ends. On a tapered board this follows the slope, which a\n * stored pose + width could never do. */\n face: [{ x: number; y: number }, { x: number; y: number }];\n}\n\n/**\n * Resolve an endplate's edge binding against a benchwork polygon.\n *\n * ⚠️ REFUSES A CURVED EDGE. Free-moN §2.0 requires the track crossing an\n * endplate to be perpendicular, straight and level for 4″ — so an endplate face\n * is flat by the standard, and a bulged edge is not somewhere one can go. That\n * is a rule, not a missing feature.\n *\n * Returns null when the edge doesn't exist or isn't usable, so a caller can say\n * why rather than drawing something wrong.\n */\nexport function endplateEdgePose(\n outline: BenchworkPoint[] | null | undefined,\n edge: EndplateEdge,\n): EndplateEdgePose | null {\n if (!outline || outline.length < 3) return null;\n const n = outline.length;\n const i = Math.trunc(edge.index);\n if (!Number.isFinite(i) || i < 0 || i >= n) return null;\n const p0 = outline[i];\n const p1 = outline[(i + 1) % n];\n if (p0.bulge) return null; // a curved fascia is not an endplate face\n\n const t0 = Math.max(0, Math.min(1, edge.fromT ?? 0));\n const t1 = Math.max(0, Math.min(1, edge.toT ?? 1));\n const a = { x: p0.x + (p1.x - p0.x) * Math.min(t0, t1), y: p0.y + (p1.y - p0.y) * Math.min(t0, t1) };\n const b = { x: p0.x + (p1.x - p0.x) * Math.max(t0, t1), y: p0.y + (p1.y - p0.y) * Math.max(t0, t1) };\n const w = Math.hypot(b.x - a.x, b.y - a.y);\n if (!(w > 0)) return null;\n\n // Outward = away from the polygon's centroid. Same rule `snapPoseToOutline`\n // uses, so a dragged plate and a bound one agree on which way is out.\n let cx = 0;\n let cy = 0;\n for (const v of outline) {\n cx += v.x;\n cy += v.y;\n }\n cx /= n;\n cy /= n;\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const ex = (b.x - a.x) / w;\n const ey = (b.y - a.y) / w;\n let nx = ey;\n let ny = -ex;\n if ((mid.x - cx) * nx + (mid.y - cy) * ny < 0) {\n nx = -nx;\n ny = -ny;\n }\n return {\n x: mid.x,\n y: mid.y,\n heading: norm360((Math.atan2(ny, nx) * 180) / Math.PI),\n widthInches: w,\n face: [a, b],\n };\n}\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 /** Set when this pose came from an {@link EndplateEdge} — read off the\n * benchwork rather than stored. Its width and face are the board's own. */\n boundToEdge?: boolean;\n /** The face's real width, when bound to an edge. */\n widthInches?: number;\n /** The face's two ends, when bound to an edge — follows a tapered board. */\n face?: [{ x: number; y: number }, { x: number; y: 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. `\"none\"` at B\n * means the module has no far endplate at all — an end of the line, a pocket,\n * or a turnback (#184). */\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | 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 /** ⭐ Endplate EDGE bindings by id (ADR 0001) — an endplate that is part of\n * the benchwork rather than a point floating beside it. Wins over\n * `poseOverrides` and over derivation. */\n endplateEdges?: Record<string, EndplateEdge>;\n /** The module's benchwork polygon, needed to resolve `endplateEdges`. */\n outline?: BenchworkPoint[] | null;\n /** Hand-entered pose overrides by endplate id — win over derivation. */\n poseOverrides?: Record<string, { x: number; y: number; heading: number }>;\n /** Authored endplate FACE widths by id (\"A\"/\"B\"), inches — the board's depth.\n * Needed to place a branch endplate on the benchwork edge rather than on the\n * centre line; absent ends use the recommended default. */\n endplateWidths?: Record<string, 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 // ⭐ AN EDGE BINDING WINS OVER EVERYTHING (ADR 0001). It is not an override\n // in the sense a pose is — it is where the endplate IS, read off the board,\n // so it can never go stale and can never sit somewhere the benchwork isn't.\n // `manual` stays FALSE: nothing was hand-placed, and treating it as manual\n // is what pinned plates and made them stop following the module (#182).\n const bound = geo.endplateEdges?.[p.id];\n if (bound) {\n const outline =\n (bound.section\n ? geo.sections?.find((s) => s.id === bound.section)?.outline\n : geo.outline) ?? geo.outline;\n const e = endplateEdgePose(outline, bound);\n if (e)\n return {\n ...p,\n x: e.x,\n y: e.y,\n heading: e.heading,\n widthInches: e.widthInches,\n face: e.face,\n boundToEdge: true,\n };\n // The edge named nothing usable — a curved fascia, or an outline that has\n // since changed shape. Fall through rather than draw a lie; the caller can\n // see `boundToEdge` is absent and say so.\n }\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 presents only ONE face. See\n // hasNoFarEndplate for the three ways to say so and why they differ (#184).\n const noB = hasNoFarEndplate(geo);\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 — ON THE BENCHWORK EDGE of their side, facing out.\n //\n // ⚠️ This used to derive `y: 0`, putting the plate on the module's CENTRE\n // LINE. An endplate is where a train leaves the module, so a side-facing one\n // belongs on the board's border — at y = 0 it sat buried mid-board and any\n // track drawn to it stopped in the middle of nowhere. It only ever looked\n // right on modules whose branch pose had been hand-authored to the edge.\n //\n // The depth is the endplate-width band's half-width at that point, which is\n // exactly what the derived board is drawn as. A module with an AUTHORED\n // outline may have its real edge elsewhere; that's the case the note below\n // covers — drag the plate and the override wins.\n //\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 const widthAt = (frac: number) => {\n const wa = endplateWidthFor(geo.endplateWidths, \"A\");\n const wb = endplateWidthFor(geo.endplateWidths, \"B\");\n return (wa * (1 - frac) + wb * frac) / 2;\n };\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 const depth = widthAt(frac);\n poses.push(\n withOverride({\n id: b.id,\n x: px,\n y: b.side === \"down\" ? -depth : depth,\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/** Whether a pose sits on the module's own axis — on the centre line, facing\n * straight out either end. That's the shape plain derivation produces for A and\n * B, so an unflagged axial pose can't be told apart from derived residue (#182).\n * Anything off-axis had to be put there by hand. */\nfunction isAxialPose(p: { y: number; heading: number }): boolean {\n const h = norm360(p.heading);\n return Math.abs(p.y) < 1e-6 && (Math.abs(h) < 1e-6 || Math.abs(h - 180) < 1e-6);\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 // Only an AUTHORED pose overrides derivation (#182) — but docs written\n // before the flag existed have to keep working, so authorship is inferred\n // for the two cases that can only BE authored:\n // · a placed branch endplate (`at`) — dropping it on the board is the\n // gesture, and it has no derivable position at all;\n // · an OFF-AXIS pose on A/B — a hand-placed plate is off-axis by\n // definition (that's why it needed hand placing, e.g. a wye's B).\n // What's left is an axial A/B pose, which is exactly the shape plain\n // derivation produces — residue. Honouring it silently pins the plate so\n // it stops following the module and goes stale (FMN-0068's B sat at 48 on\n // a 47.9″ board). Anything saved from now on carries the flag, so this\n // guesswork only ever applies to old docs.\n (e.poseAuthored === true || !!e.at || !isAxialPose(e.pose))\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":["at","pts","c","r","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 /** ⭐ THE ENDPLATE'S EDGE OF THE BENCHWORK (ADR 0001). When present it WINS\n * over `pose` and over derivation, and position, heading and width are all\n * read off the polygon — so they cannot drift apart from the board.\n *\n * `pose` remains for modules authored before this and for shapes with no\n * benchwork polygon to bind to. Nothing is auto-converted: guessing which\n * edge an owner's freehand pose meant would be inventing an intent. */\n edge?: EndplateEdge | null;\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 /** Whether that pose was AUTHORED — placed or typed by the owner — rather\n * than a derived one that found its way into the doc (#182).\n *\n * Authorship used to be inferred from `pose` merely existing, so a derived\n * pose written back silently PINNED the plate: it stopped following the\n * module and went stale the moment the length changed (FMN-0068 ended up with\n * endplate B at x=48 on a 47.9″ board). A pose is only an override when the\n * owner meant it.\n *\n * Absent on A/B = derived residue, ignored. Absent on a placed branch\n * endplate (one with `at`) = still authored — placing it IS the gesture, and\n * docs predate this flag. */\n poseAuthored?: boolean;\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 * Free-moN **standard**: minimum MAIN-LINE radius, 22″.\n *\n * ⚠️ The main line only. A spur, a yard lead or an industrial track may be\n * tighter, and telling an owner their yard is out of spec because it is not a\n * main would be worse than saying nothing.\n */\nexport const FREEMO_MAIN_MIN_RADIUS_INCHES = 22;\n/** Free-moN **standard**: at least 6″ of straight track between REVERSE curves,\n * so a train is never asked to change hands instantly. */\nexport const FREEMO_REVERSE_CURVE_STRAIGHT_INCHES = 6;\n\n/**\n * A stretch where a pair of parallel tracks runs at something other than the\n * standard spacing, because a rigid assembly built to another spacing sits in\n * it (#180).\n *\n * The case this exists for: a crossover fixture is machined for ONE track\n * spacing and cannot be built to another. The Fast Tracks N crossovers are\n * 1.09″ where Free-moN §2.0 requires 1.125″, so a module with one genuinely has\n * its two mains 0.035″ closer together across the crossover, opening back to\n * 1.125″ at the endplates — which the standard fixes. That pinch is real, and\n * drawing it is more honest than drawing a straight pair.\n */\nexport interface LanePinch {\n /** The lane pulled in. Lane 0 is the reference and never moves. */\n lane: number;\n /** Inches from endplate A where the rigid section begins and ends. */\n fromPos: number;\n toPos: number;\n /** Centre-to-centre spacing INSIDE that span, inches. */\n spacingInches: number;\n}\n\n/**\n * How far either side of a rigid section the pair takes to reach it.\n *\n * ⚠️ A DRAWING CONVENTION, NOT A MEASUREMENT. Nobody publishes this and it is\n * not a property of any part — in the real world the builder eases the flex over\n * whatever room they have. It exists so the pinch renders as a smooth deviation\n * rather than a kink, and it is deliberately a round number so it never reads as\n * something that was measured.\n */\nexport const PINCH_EASE_INCHES = 3;\n\n/**\n * The lane offset at a point, honouring any {@link LanePinch} covering it.\n *\n * Eases with a smoothstep, whose slope is zero at both ends, so the deviation\n * leaves and rejoins the straight run tangentially — the way bent flex actually\n * behaves. A linear ramp would put a visible corner at each end.\n *\n * ⚠️ ONLY THE PINCH'S OWN LANE MOVES. The main is the reference every Free-moN\n * measurement is taken from, so it stays put and the parallel track deviates,\n * which is also what a builder does.\n */\nexport function laneOffsetAt(\n lane: number,\n pos: number,\n pinches?: LanePinch[] | null,\n spacingInches = FREEMO_TRACK_SPACING_INCHES,\n): number {\n const base = (lane ?? 0) * spacingInches;\n if (!lane || !pinches?.length) return base;\n const sign = Math.sign(lane);\n const smooth = (t: number) => t * t * (3 - 2 * t);\n let off = base;\n for (const p of pinches) {\n if (p.lane !== lane) continue;\n const a = Math.min(p.fromPos, p.toPos);\n const b = Math.max(p.fromPos, p.toPos);\n // The pinch names ONE lane step's spacing. A pinched lane 2 would need to\n // say which of its two gaps closed, and nothing records that: not modelled.\n const target = base - sign * (spacingInches * Math.abs(lane) - p.spacingInches);\n const e = PINCH_EASE_INCHES;\n let t: number | null = null;\n if (pos >= a && pos <= b) t = 1;\n else if (pos > a - e && pos < a) t = smooth((pos - (a - e)) / e);\n else if (pos > b && pos < b + e) t = smooth(1 - (pos - b) / e);\n if (t == null) continue;\n // Where two overlap the DEEPEST wins rather than summing: two crossovers in\n // the same place is a data error, not a doubly-tight pair.\n const candidate = base + (target - base) * t;\n if (Math.abs(candidate - base) > Math.abs(off - base)) off = candidate;\n }\n return off;\n}\n\n/**\n * The pinches a document's crossovers impose — one per crossover connector that\n * names a part whose {@link TrackPart.trackSpacing} differs from the standard.\n *\n * A crossover with no part named, or one built to the standard spacing, imposes\n * nothing: an owner who hasn't said what they built gets the straight pair they\n * had before, which is the only honest default.\n */\nexport function crossoverPinches(\n tracks: Array<{\n role?: string;\n lane?: number;\n fromPos?: number | null;\n toPos?: number | null;\n crossoverPartId?: string | null;\n }>,\n library = BUILT_IN_TRACK_PARTS,\n spacingInches = FREEMO_TRACK_SPACING_INCHES,\n): LanePinch[] {\n const out: LanePinch[] = [];\n for (const t of tracks) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = library.find((p) => p.id === t.crossoverPartId);\n const s = part?.trackSpacing?.inches;\n if (typeof s !== \"number\" || !Number.isFinite(s) || s <= 0) continue;\n if (Math.abs(s - spacingInches) < 1e-9) continue;\n const lane = t.lane ?? 1;\n if (!lane) continue;\n const a = t.fromPos ?? 0;\n const b = t.toPos ?? 0;\n if (!Number.isFinite(a) || !Number.isFinite(b) || Math.abs(b - a) < 1e-9) continue;\n const pinch = {\n lane,\n fromPos: Math.min(a, b),\n toPos: Math.max(a, b),\n spacingInches: s,\n };\n // ⚠️ A DOUBLE CROSSOVER IS TWO CONNECTORS AND ONE PINCH. It is built as two\n // diagonals, so the document holds two records over the same\n // span at the same spacing — but the pair of tracks only closes up once.\n // Left un-deduped the geometry is still right (identical pinches agree), so\n // this shows up as a doubled CALLOUT rather than a wrong drawing: the label\n // renders twice, exactly superimposed.\n const same = out.some(\n (p) =>\n p.lane === pinch.lane &&\n Math.abs(p.fromPos - pinch.fromPos) < 1e-9 &&\n Math.abs(p.toPos - pinch.toPos) < 1e-9 &&\n Math.abs(p.spacingInches - pinch.spacingInches) < 1e-9,\n );\n if (!same) out.push(pinch);\n }\n return out;\n}\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 /** The flex product this run is laid with — a slug from the parts library\n * (#193). Absent = the default. Per TRACK, so a module can have its mains in\n * one product and a siding in another. */\n flexPartId?: string | null;\n /** Authored rail joints, inches along this run. Absent = derived from the\n * product's maximum piece length. Present = these are the ONLY joints, so an\n * owner's deliberate cut survives a change elsewhere on the module. */\n flexCuts?: number[] | null;\n /** `role: \"crossover\"` only — the crossover product this connector was built\n * from, a slug from the parts library.\n *\n * It sits on the CONNECTOR rather than on the turnouts at its ends because a\n * crossover is one assembly: the fixture that set its angle also set its\n * {@link TrackPart.trackSpacing}, and that spacing belongs to the pair of\n * tracks, not to either turnout. Naming it is what lets the physical view draw\n * the crossover at the spacing it was actually built to — the Fast Tracks N\n * fixtures are 1.09″ against Free-moN's 1.125″, and the difference is real. */\n crossoverPartId?: string | null;\n /**\n * Which end of this track is CLOSED BY A BUMPER — deliberately the end of the\n * line, rather than track that merely stops.\n *\n * ⭐ The difference is operational, not decorative: a bumpered end is where a\n * cut of cars can be shoved to, and it is where usable length runs out. An\n * end that just stops might only be unfinished.\n */\n bumperAt?: \"from\" | \"to\" | null;\n /** The owner's MEASURED usable length, real inches (#20) — for what the\n * drawing can't know: a bumper post short of the drawn end, a structure\n * fouling the track. Absent = derive it from the clearance points (#19). */\n measuredUsableInches?: number | null;\n}\n/**\n * A turnout.\n *\n * ⭐ **THE WORD IS \"TURNOUT\", NOT \"SWITCH\".** They were used interchangeably\n * across both apps; this is the one name. The Free-moN standard says turnout\n * (\"main-line turnouts at least #6\") and so does the NMRA, every user-facing\n * string already said it, and \"switch\" is ambiguous three ways for us — the\n * points assembly, an electrical switch, and *switching*, the operation of\n * moving cars, which we need as its own word.\n *\n * ⚠️ TWO DELIBERATE EXCEPTIONS, both still correct usage:\n * 1. **A manufacturer's own product name, quoted as they sell it.** Atlas sells\n * a \"#7 LH Switch\" (2052). Renaming their product makes it un-findable in a\n * catalogue, which is the opposite of what a parts library is for.\n * 2. **The points assembly and its geometry** — \"switch points\", and the\n * \"switch angle\" that {@link TurnoutClosure.switchSlope} carries. That is a\n * part OF a turnout, not another word FOR one.\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 /** The library part this turnout IS — e.g. \"atlas-c55-n-7\". Binds a drawn\n * turnout to real geometry: with it the renderer can draw the part's own\n * outline instead of a shape derived from `size`. Absent means \"just a #N\",\n * which is what every turnout authored before the parts library was. */\n partId?: string | null;\n}\nexport interface SchematicSignal {\n id: string;\n pos: number;\n /** Hold this signal by the piece it stands beside (ADR 0001). See\n * {@link GraphAnchor} — a mast is planted next to a particular bit of rail. */\n anchor?: GraphAnchor | null;\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). */\n/**\n * ⭐ A PLACE ON THE TRACK, HELD BY THE PIECE THAT IS THERE (ADR 0001).\n *\n * `pos` — inches from endplate A — is a fine way to *read* where something is\n * and a poor way to *hold* it: it is a number about the whole module, so every\n * edit anywhere upstream silently changes what it means. A car spot belongs to\n * the rail it is beside. Anchored to the piece, moving that piece takes the\n * industry with it and moving anything else leaves it alone, which is what an\n * owner dragging track expects to happen.\n *\n * Present = `pos` / `fromPos` / `toPos` are DERIVED from this by\n * {@link graphToDoc}. Absent = the authored numbers stand, exactly as before —\n * nothing migrates (ADR 0001).\n */\nexport interface GraphAnchor {\n /** The {@link TrackPiece} it sits on. */\n piece: string;\n /**\n * Inches along that piece from its OWN origin end — joint `a` on flex, the\n * throat on a turnout, and in every case the part's x=0.\n *\n * ⚠️ Deliberately NOT \"from the end the walk came in by\". Which end that is\n * depends on where the module's endplate A happens to be, so the same spot\n * beside the same rail would mean two different numbers on two modules.\n */\n atInches: number;\n}\n\nexport interface IndustrySpot {\n track: string;\n fromPos: number;\n toPos: number;\n side?: SignalSide;\n /** Hold this spot by the piece it is beside (ADR 0001). See {@link GraphAnchor}. */\n anchor?: GraphAnchor | null;\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 /** Hold this span by the piece it is beside (ADR 0001). See {@link GraphAnchor}.\n * The span's LENGTH stays authored — a dock face is as long as it is built;\n * only where it begins is read off the track. */\n anchor?: GraphAnchor | null;\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 * ⭐⭐ THE AUTHORED TRACK, when this module was drawn as PIECES (ADR 0001).\n *\n * Present = this is the source, and `tracks`, `turnouts` and every anchored\n * feature's position are DERIVED from it by {@link deriveGraphDoc} — they are\n * still written into the document so that everything downstream, Free-\n * Dispatcher included, reads an ordinary document and is never told which way\n * the module was authored.\n *\n * Absent = the module is authored the way it always was, and nothing about it\n * changes. No document is converted (ADR 0001): converting one would mean\n * inventing the leads, frogs and radii nobody measured.\n */\n graph?: {\n pieces: TrackPiece[];\n /** Where the main starts: the joint endplate A's track arrives at. */\n startAt: { piece: string; joint: string };\n /** Where MAIN 2 starts, on a double-track module — the joint the endplate's\n * SECOND track arrives at. Absent = single track.\n *\n * Two starts rather than a list because a document has exactly two mains,\n * `main` and `main2`. This mirrors the thing downstream instead of inventing\n * a generality nothing can read. */\n start2?: { piece: string; joint: string } | null;\n } | 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 /** This board's WEST end (the A side) — see {@link SectionEnd}. */\n endA?: SectionEnd | null;\n /** This board's EAST end (the B side). */\n endB?: SectionEnd | null;\n}\n\n/**\n * One end of a board (#130).\n *\n * Owner's question was *\"how would I update my section joints to be endplates\n * from within MR?\"* — and until now nothing could say it: a section had a\n * length, a shape and an outline, but nothing about its ends.\n *\n * ⚠️ **There is deliberately no \"this is an endplate\" flag.** An owner could\n * tick it wrongly and the registry would then tell Free-Dispatcher that two\n * boards will physically mate when they won't. The geometry decides — describe\n * the end and {@link assessSectionEnd} works out whether it conforms.\n *\n * Absent means **not described**, which is an ordinary internal joint, not a\n * failing endplate: the standard exempts internal boundaries from the\n * end-interface rules (#96).\n */\nexport interface SectionEnd {\n /** What this end presents. `\"none\"` = a closed end (a bumper). */\n config?: TrackConfig | \"none\" | null;\n /** Face width, inches. Absent = the recommended default. */\n widthInches?: number | null;\n /** Main 1's signed distance from the face centre — the standard's own\n * framing, same as an endplate's (see {@link endplateTrackOffsetInches}). */\n trackOffsetInches?: 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 // The board's two ends (#130). Written only when actually described —\n // an absent end is an ordinary internal joint, and an empty object\n // would claim the owner had said something about it.\n ...(sectionEnd(sec.endA) ? { endA: sectionEnd(sec.endA)! } : {}),\n ...(sectionEnd(sec.endB) ? { endB: sectionEnd(sec.endB)! } : {}),\n };\n });\n}\n\n/** Normalise one board end, or null when nothing was actually said about it\n * (#130). Keeps `{}` and `{ config: null }` from round-tripping as a described\n * end — see {@link SectionEnd}. */\nfunction sectionEnd(end: SectionEnd | null | undefined): SectionEnd | null {\n if (!end) return null;\n const config =\n end.config === \"single\" || end.config === \"double\" || end.config === \"none\"\n ? end.config\n : null;\n const w = end.widthInches;\n const o = end.trackOffsetInches;\n const out: SectionEnd = {\n ...(config ? { config } : {}),\n ...(typeof w === \"number\" && Number.isFinite(w) && w > 0 ? { widthInches: w } : {}),\n // Signed, and 0 is meaningful (\"explicitly centred\", #93) — keep any finite.\n ...(typeof o === \"number\" && Number.isFinite(o) ? { trackOffsetInches: o } : {}),\n };\n return Object.keys(out).length ? out : null;\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/**\n * Arc length of an authored path, inches — the path's OWN length, independent of\n * where it sits or which way it runs. A branch route to a third endplate (#181)\n * has no meaningful extent along the module axis (a square 90° exit projects to\n * zero), so its own length is the only honest measure of it.\n */\nexport function pathLengthInches(\n path: BenchworkPoint[] | null | undefined,\n): number {\n const pts = trackPath(path);\n if (!pts) return 0;\n const poly = samplePath(pts);\n let total = 0;\n for (let i = 1; i < poly.length; i++)\n total += Math.hypot(poly[i].x - poly[i - 1].x, poly[i].y - poly[i - 1].y);\n return total;\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 toward Main 2. Single\n * track crosses at the centre ⇒ 0, and an off-centre track is a signed value.\n * {@link endplateCentreOffsetInches} computes it from what the owner authored.\n *\n * ⚠️ OMITTING an end no longer means 0 — it means \"use §2.0\", which is a\n * straddle on a double end. Centring a double plate on Main 1 drew its pair\n * wholly to one side, which is what the read-only and catalog views did by\n * passing nothing at all (#190). Pass an explicit number to place a plate. */\n endplateTrackOffsets?: Record<string, number>;\n /** Whether Main 2 runs BELOW Main 1 (`mainsSwapped`, #131). Only affects which\n * way an unauthored double plate straddles. */\n mainsSwapped?: boolean;\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 * The document already places track along a main (see {@link\n * moduleCenterline}). Set from the doc's own `tracks`; without it a module\n * whose track was authored before it had a geometry draws as a bare board.\n */\n hasPlacedTrack?: boolean;\n /** Axial endplate configs (A first, then B), same as\n * {@link ModuleGeometryInput.endplateConfigs}. `\"none\"` at B means the module\n * presents no far endplate, so no face is emitted there (#184/#191). */\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | null | undefined)[];\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 //\n // ⚠️ UNLESS THE DOCUMENT ALREADY PLACES TRACK. `pos` means inches from\n // endplate A ALONG THE MAIN, so a document with tracks on it is asserting\n // that a main exists — refusing one then draws the board and silently none of\n // its track, which is what a card for such a module did. The blank-module\n // rule is about a module with NOTHING on it, and a module with track is not\n // that. Callers pass `hasPlacedTrack` from the document they already hold.\n if (!input.geometryType && !input.hasPlacedTrack) 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 // Where each plate's CENTRE sits relative to Main 1. The DEFAULT is §2.0's\n // geometry, not zero — a caller that says nothing about a double end still\n // gets a plate its two tracks straddle (#190).\n const offOf = (i: number, id: string) =>\n input.endplateTrackOffsets?.[id] ??\n endplateCentreOffsetInches({\n config: input.endplateConfigs?.[i],\n main2Below: input.mainsSwapped === true,\n });\n const offA = offOf(0, \"A\");\n const offB = offOf(1, \"B\");\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 // Only emit a face where the module actually presents one. A loop's\n // centre-line ends at the THROAT, and an end of the line / pocket simply\n // stops — a far face there is a plate the module hasn't got (#191).\n endplateFaces: hasNoFarEndplate(input)\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 * Where an endplate's CENTRE sits relative to MAIN 1 — the renderer's framing,\n * and the one number a drawing needs to place the plate.\n *\n * ⭐ THE single definition. Two callers had their own: the builder computed it\n * inline (swap-aware), and the read-only/catalog footprint **passed nothing at\n * all**, so every plate there was centred on Main 1 — a double end drew its pair\n * entirely to one side of the plate instead of straddling it (#190).\n *\n * §2.0 puts a double end's two tracks 0.5625″ either side of the plate centre,\n * so the plate centre is half a track spacing away from Main 1 — **toward Main\n * 2**, which is why the swap matters: with Main 2 below, the plate centre is\n * below too. An authored offset always wins (an off-centre end is legal since\n * the 20220628 revision), and is given in the standard's own framing — Main 1's\n * distance from the plate centre — so it comes back negated here.\n */\nexport function endplateCentreOffsetInches(input: {\n config?: TrackConfig | \"none\" | null;\n /** Main 1's signed distance from the plate centre, as authored. */\n authoredTrackOffsetInches?: number | null;\n /** Whether Main 2 runs below Main 1 (the mains are swapped). */\n main2Below?: boolean;\n}): number {\n // Simply the other framing of the same fact, so there is ONE default to get\n // right rather than two that can disagree.\n const v = -endplateTrackOffsetInches(\n input.authoredTrackOffsetInches,\n input.config ?? undefined,\n input.main2Below,\n );\n return v === 0 ? 0 : v; // never hand back -0\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 /** Whether Main 2 runs BELOW Main 1 (the mains are swapped). The pair\n * straddles the plate centre either way, so Main 1 sits on the side AWAY from\n * Main 2 — low when Main 2 is high, high when it's low. Omitting this\n * hard-coded \"Main 2 is above\", which is the assumption behind #190. */\n main2Below = false,\n): number {\n if (typeof authored === \"number\" && Number.isFinite(authored)) return authored;\n if (config !== \"double\") return 0;\n const half = FREEMO_TRACK_SPACING_INCHES / 2;\n return main2Below ? half : -half;\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 * \"offcentre\" = a double end whose pair doesn't straddle the plate centre. */\n code: \"narrow\" | \"clearance\" | \"offcentre\";\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 /** Whether Main 2 runs BELOW Main 1 (the mains are swapped). Without it a\n * double end's second track was assumed to be one spacing ABOVE Main 1, so a\n * swapped pair was measured on the wrong side of the plate (#190). */\n main2Below?: boolean;\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(\n input.trackOffsetInches,\n input.config ?? undefined,\n input.main2Below,\n );\n // Main 2 sits one spacing from Main 1, on Main 2's OWN side — below when the\n // mains are swapped. Assuming \"above\" put a swapped pair on the wrong side of\n // the plate and demanded a wider end than the geometry needs (#190).\n const second = off + (input.main2Below ? -1 : 1) * FREEMO_TRACK_SPACING_INCHES;\n const centres = input.config === \"double\" ? [off, second] : [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 // §2.0 puts a double end's two tracks 0.5625″ EITHER SIDE of the plate centre.\n // Off-centre is legal — the 20220628 revision relaxed centring to a\n // recommendation — but a pair sitting wholly to one side is worth saying out\n // loud, because it's almost always an accident: an authored 0 reads as \"centre\n // Main 1\", which pushes the whole pair off the plate's middle (#190).\n if (input.config === \"double\") {\n const mid = (off + second) / 2;\n if (Math.abs(mid) > 0.01) {\n issues.push({\n code: \"offcentre\",\n message:\n `The two tracks sit ${round2(Math.abs(mid))}″ off the centre of this endplate. ` +\n `The standard recommends they straddle it — Main 1 at ` +\n `${round2((input.main2Below ? 1 : -1) * (FREEMO_TRACK_SPACING_INCHES / 2))}″. ` +\n `Clear the offset to use that.`,\n // Not a width problem — no wider plate fixes it — so hand back the\n // width unchanged rather than imply one would.\n requiredInches: width,\n });\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/**\n * Whether a module presents NO far endplate — one conforming face only.\n *\n * ⭐ THE single definition. Three places had grown their own answer to this and\n * drifted: `deriveEndplatePoses` (which knew about `dead_end` and `\"none\"`), the\n * operations preview's end label, and `moduleFootprint`'s endplate faces — the\n * last two using \"is it a loop?\" as a stand-in for \"has it got two ends?\", which\n * was true until #184 and silently wrong after. Anything asking this must call\n * THIS.\n *\n * Three ways to have one end, and they are genuinely different things: the\n * geometry is a dead end; it's a balloon loop, whose far end is the throat and\n * not a plate at all; or the owner said this end has no plate, which is how an\n * *end of the line* or a *pocket* is authored — ordinary straight boards that\n * simply stop, so no geometry type would ever say it for them.\n */\nexport function hasNoFarEndplate(input: {\n geometryType?: string | null;\n loop?: boolean;\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | null | undefined)[];\n}): boolean {\n return (\n input.geometryType === \"dead_end\" ||\n input.loop === true ||\n input.endplateConfigs?.[1] === \"none\"\n );\n}\n\n/**\n * Whether a doc is a balloon loop — **the authored flag, and only that**.\n *\n * ⚠️ This used to ALSO infer a loop from `endplates.length === 1`, which was\n * safe only while the sole way to have one endplate was to be a turnback. #184\n * ended that: an *end of the line* or a *pocket* presents one conforming face\n * too, so every single-ended module was silently classified as a loop — drawn\n * with a bulb, its endplate A relabelled \"Entry\", and positions past the throat\n * read as being inside a balloon that doesn't exist (#191).\n *\n * A loop is now only ever a loop because someone said so: the Loop checkbox and\n * the return-loop generator both set `loop: true`. Checked before removing the\n * inference — no stored doc relied on it (no module in the catalogue has one\n * endplate without the flag, and none is `category:\"loop\"` or `dead_end`).\n */\nexport function isLoopDoc(doc: ModuleSchematicDoc): boolean {\n return doc.loop === true;\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/**\n * How far the two routes must separate before a car on one clears equipment on\n * the other — the CLEARANCE POINT's defining distance (#19).\n *\n * ⭐ Deliberately the **Free-moN track spacing**, not a second number. §2.0 uses\n * 1.125″ as the distance at which two parallel tracks coexist, so \"a car here\n * clears a car there\" is the same statement the standard already makes. It's\n * 15 scale feet centre to centre, inside the prototype's usual 13–15 ft range.\n *\n * The alternative — a separate prototype constant — would leave the app holding\n * two spacings that disagree about what \"clear\" means.\n */\nexport const CLEARANCE_SPACING_INCHES = FREEMO_TRACK_SPACING_INCHES;\n\n/**\n * How far past the FROG a turnout's diverging route reaches the clearance point\n * (#19) — the point from which usable capacity is measured.\n *\n * Not a measurement and not a guess: it's solved from the closure the drawing\n * already uses, by asking where `offsetAt` first reaches\n * {@link CLEARANCE_SPACING_INCHES}. So it follows the part's real lead, and a\n * better-measured part moves it automatically.\n *\n * Returns the distance PAST THE FROG because `pos` means the frog (#132) — add\n * it to the turnout's position, in the direction the turnout faces.\n */\nexport function clearancePointPastFrogInches(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n clearanceInches = CLEARANCE_SPACING_INCHES,\n): number {\n const N = size > 0 ? size : 6;\n const lead = leadInchesForSize(N, library);\n const cl = turnoutClosure(N, { leadInches: lead });\n // The profile rises monotonically, so bisect — cheap, and it doesn't care\n // which branch of the closure (switch curve, frog angle, ease) the answer\n // lands in.\n let lo = 0;\n let hi = Math.max(4 * lead, 4 * clearanceInches * N);\n if (cl.offsetAt(hi) < clearanceInches) return hi - lead;\n for (let i = 0; i < 60; i++) {\n const mid = (lo + hi) / 2;\n if (cl.offsetAt(mid) < clearanceInches) lo = mid;\n else hi = mid;\n }\n return Math.max(0, hi - lead);\n}\n\n/** A track's usable capacity, measured to the clearance-point standard (#19). */\nexport interface UsableCapacity {\n /** The stretch a car can actually stand on, inches along the run. */\n fromPos: number;\n toPos: number;\n /** Its length — what capacity is computed from. */\n usableInches: number;\n /** The run's full drawn length, for comparison. */\n drawnInches: number;\n /** How much each end gives up to its governing turnout's clearance point. */\n givenUpInches: number;\n /** Cars that fit in the usable length. */\n cars: number;\n /** Usable length as scale feet. */\n scaleFeet: number;\n}\n\n/**\n * A track's USABLE capacity — measured from the governing turnout's clearance\n * point, not from the rail ends (#19/#20).\n *\n * A spur runs clearance point → end of track; a siding, clearance point →\n * clearance point. The difference is not small: FMN-0040's 70″ passing siding\n * has two #7s on it, and loses 5.4″ at each end — 21 cars drawn, 17 usable.\n *\n * `measuredUsableInches` is the owner's override for what the drawing can't\n * know — a bumper post short of the drawn end, a structure fouling the track.\n * Given, it wins outright and the clearance points aren't applied to it: they\n * measured the usable length itself.\n */\nexport function usableCapacity(input: {\n fromPos: number;\n toPos: number;\n /** Turnouts that DIVERGE ONTO this track — the ones that govern its ends. */\n governing?: { pos: number; size?: number | null }[] | null;\n /** The owner's measured usable length, inches. Wins when present. */\n measuredUsableInches?: number | null;\n library?: TrackPart[];\n carLengthInches?: number;\n}): UsableCapacity {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n const drawn = hi - lo;\n const carLen = input.carLengthInches ?? N_CAR_LENGTH_INCHES;\n\n if (typeof input.measuredUsableInches === \"number\" && input.measuredUsableInches >= 0) {\n const m = input.measuredUsableInches;\n return {\n fromPos: lo,\n toPos: lo + m,\n usableInches: m,\n drawnInches: drawn,\n givenUpInches: Math.max(0, drawn - m),\n cars: carCapacity(0, m, carLen),\n scaleFeet: Math.round(inchesToScaleFeet(m)),\n };\n }\n\n // Each governing turnout pushes the END NEAREST IT inward to its clearance\n // point. Nearest, not \"the low one\": a siding's two turnouts sit at its two\n // ends, and a spur's single turnout may govern either.\n let a = lo;\n let b = hi;\n for (const sw of input.governing ?? []) {\n const c = clearancePointPastFrogInches(sw.size ?? 6, input.library);\n if (Math.abs(sw.pos - lo) <= Math.abs(sw.pos - hi)) a = Math.max(a, lo + c);\n else b = Math.min(b, hi - c);\n }\n const usable = Math.max(0, b - a);\n return {\n fromPos: a,\n toPos: Math.max(a, b),\n usableInches: usable,\n drawnInches: drawn,\n givenUpInches: Math.max(0, drawn - usable),\n cars: carCapacity(0, usable, carLen),\n scaleFeet: Math.round(inchesToScaleFeet(usable)),\n };\n}\n\n/** What a board's end is, once the geometry has been asked (#130). */\nexport interface SectionEndAssessment {\n /** Has the owner described this end at all? Undescribed is an ordinary\n * internal joint — exempt from the end-interface rules (#96) — not a failure. */\n described: boolean;\n /** Does it meet the standard's end-interface rules? Only a described end can. */\n conforming: boolean;\n /** Why it doesn't, when it doesn't. Empty for a conforming or undescribed end. */\n issues: EndplateWidthIssue[];\n /** The resolved values the assessment was made against. */\n config: TrackConfig | \"none\";\n widthInches: number;\n trackOffsetInches: number;\n}\n\n/**\n * Is this end of a board a standard endplate? (#130)\n *\n * ⭐ **Derived, never declared.** The issue is emphatic and the reason is good:\n * a checkbox could be ticked wrongly, and the registry would then promise\n * Free-Dispatcher a mating surface that doesn't exist. So the answer comes from\n * the same rules {@link checkEndplateWidth} already applies to a module's own\n * plates — §1.1's 12″ minimum, and §2.0's 4″ fascia clearance and 1.125″ pair.\n *\n * Two of the standard's conditions aren't checked because they can't be false\n * here: track crosses the face **perpendicular** and a double end's two tracks\n * sit **1.125″ apart** are both true by construction in this model. Inventing\n * fields for them would be inventing ways to be wrong.\n *\n * An end with no config is **undescribed**, which is the ordinary case — most\n * joints inside a module are just joints.\n */\nexport function assessSectionEnd(\n end: SectionEnd | null | undefined,\n opts: { main2Below?: boolean } = {},\n): SectionEndAssessment {\n const config = (end?.config ?? \"none\") as TrackConfig | \"none\";\n const widthInches = endplateWidthInches({ widthInches: end?.widthInches });\n const trackOffsetInches = endplateTrackOffsetInches(\n end?.trackOffsetInches,\n config,\n opts.main2Below,\n );\n // \"Described\" means the owner said what this end PRESENTS. A width alone\n // doesn't make a joint an interface; a track configuration does.\n const described = config === \"single\" || config === \"double\";\n if (!described) {\n return { described: false, conforming: false, issues: [], config, widthInches, trackOffsetInches };\n }\n const issues = checkEndplateWidth({\n widthInches: end?.widthInches,\n config,\n trackOffsetInches: end?.trackOffsetInches,\n main2Below: opts.main2Below,\n });\n return { described: true, conforming: issues.length === 0, issues, config, widthInches, trackOffsetInches };\n}\n\n/** Two board ends meeting at a joint, and whether that joint is a standard\n * interface (#130). */\nexport interface SectionJointAssessment {\n west: SectionEndAssessment;\n east: SectionEndAssessment;\n /** Both ends conform AND present the same number of tracks — so these two\n * boards could be separated and each used against any other module. */\n standardInterface: boolean;\n /** Plain-language reason it isn't one, or null when it is. */\n reason: string | null;\n}\n\n/**\n * Assess a joint — the two board ends that meet there (#130).\n *\n * ⚠️ Track COUNT is the only compatibility rule. Two conforming ends of\n * differing face WIDTH still mate: the standard lets plates differ in width and\n * be offset, so long as the track lines up. That's a deliberate non-check — see\n * the note on endplate width authoring.\n */\nexport function assessSectionJoint(\n west: SectionEnd | null | undefined,\n east: SectionEnd | null | undefined,\n opts: { main2Below?: boolean } = {},\n): SectionJointAssessment {\n const w = assessSectionEnd(west, opts);\n const e = assessSectionEnd(east, opts);\n let reason: string | null = null;\n if (!w.described || !e.described) {\n reason = \"an internal joint — neither end has been described as an interface\";\n if (w.described !== e.described)\n reason = `only the ${w.described ? \"west\" : \"east\"} side is described as an endplate`;\n } else if (!w.conforming || !e.conforming) {\n const bad = !w.conforming ? w : e;\n reason = bad.issues[0]?.message ?? \"an end doesn't meet the standard\";\n } else if (w.config !== e.config) {\n // Single↔double is the one real mismatch: the track counts don't line up.\n reason = `${w.config} meets ${e.config} — the track counts differ`;\n }\n return { west: w, east: e, standardInterface: reason === null, reason };\n}\n\n/** How much of a car-spot span has no rail under it (#194). */\nexport interface SpanOverhang {\n /** Inches the span runs past the track's near end (0 = it starts on track). */\n beforeInches: number;\n /** Inches it runs past the far end. */\n afterInches: number;\n /** The part of the span that IS on the track. */\n onTrackInches: number;\n /** Total overhang — `beforeInches + afterInches`. 0 = the span fits. */\n overhangInches: number;\n}\n\n/**\n * How far a car-spot span runs past the ends of the track it spots on (#194).\n *\n * An industry is a span with a start and an end, and its capacity is computed\n * from those — but nothing checked that the span fits on the siding it's\n * spotting. FMN-0013's \"Team track\" claims 29.8″ → 41″ on a track running\n * 30″ → 39″: about a car and a half of capacity with no rail under it.\n *\n * Both spans are given in the same coordinate (inches along the module) and\n * either may run \"backwards\" — a siding authored east-to-west is ordinary — so\n * both are normalised first.\n */\nexport function spanOverhang(input: {\n fromPos: number;\n toPos: number;\n trackFromPos: number;\n trackToPos: number;\n}): SpanOverhang {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n const tLo = Math.min(input.trackFromPos, input.trackToPos);\n const tHi = Math.max(input.trackFromPos, input.trackToPos);\n const before = Math.max(0, tLo - lo);\n const after = Math.max(0, hi - tHi);\n return {\n beforeInches: before,\n afterInches: after,\n onTrackInches: Math.max(0, Math.min(hi, tHi) - Math.max(lo, tLo)),\n overhangInches: before + after,\n };\n}\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/** Repoint a turnout that diverges into the track it sits on at the OTHER main.\n * A reversed transition whose on-track was later set to the same main stored\n * `onTrack === divergeTrack` (#172): it then had no second route, so\n * `isTransitionTurnout` went false and the module derived as if it had no\n * transition at all — both mains running endplate to endplate. Applied on READ\n * so a doc saved in that state renders correctly everywhere without waiting for\n * its owner to open and re-save it. Returns the same array when nothing needs\n * healing, so untouched docs keep referential identity. */\nfunction healSelfDivergingTurnouts(\n turnouts: SchematicTurnout[] | undefined,\n): SchematicTurnout[] | undefined {\n if (!turnouts?.some((t) => t.onTrack === t.divergeTrack)) return turnouts;\n return turnouts.map((t) => {\n if (t.onTrack !== t.divergeTrack) return t;\n if (t.onTrack === MAIN_TRACK_ID) return { ...t, divergeTrack: MAIN2_TRACK_ID };\n if (t.onTrack === MAIN2_TRACK_ID) return { ...t, divergeTrack: MAIN_TRACK_ID };\n return t; // not a main — nothing sensible to repoint it at\n });\n}\n\n/** Parse a jsonb value into a schematic doc, or null if it isn't one.\n * EVERY read path goes through here (catalog, module page, my-modules, FD), so\n * it's also where a stored doc gets healed — see healSelfDivergingTurnouts. */\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 const doc = d as unknown as ModuleSchematicDoc;\n const healed = healSelfDivergingTurnouts(doc.turnouts);\n return healed === doc.turnouts ? doc : { ...doc, turnouts: healed };\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 /** Measured usable length, real inches (#20). Absent = derived (#19). */\n measuredUsableInches?: number;\n /** `role: \"crossover\"` only — the crossover product this connector was built\n * from. Drives the spacing the pair is DRAWN at (see\n * {@link SchematicTrack.crossoverPartId}). */\n crossoverPartId?: string;\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 /** The library part this turnout IS — see SchematicTurnout.partId. */\n partId?: string;\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 /** The piece this span is held by (ADR 0001). See {@link GraphAnchor}. */\n anchor?: GraphAnchor | 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's configuration — or `\"none\"`, meaning **the module has no far\n * endplate**: an end of the line, a pocket, or a loop's pure turnback. On a\n * loop, a standard endplate B instead makes the balloon an INTERCHANGE (a second\n * route connects there, e.g. Seaford). A module presents one conforming face,\n * or two, or more; the standard governs the faces it offers, not how many (#184). */\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 /**\n * Flex track settings by TRACK id (#193) — which product a run is laid with,\n * and where the owner has decided its rail joints fall.\n *\n * One map rather than fields, because the MAINS aren't `extraTracks` (the main\n * IS the centre-line), so per-track settings would otherwise need a separate\n * pair of fields for Main 1 and Main 2 — four ways to say one thing. Round-trips\n * onto each track in the doc, where it's self-describing for Free-Dispatcher.\n */\n flexByTrack: Record<string, { partId?: string; cuts?: 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 /** Endplate EDGE bindings by id (ADR 0001) — an endplate that is part of the\n * benchwork. Wins over a pose; nothing is auto-converted from one. */\n endplateEdges?: Record<string, EndplateEdge>;\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 /** ⭐ The track as PLACED PIECES (ADR 0001), when the owner drew it that way.\n * Absent = authored the way it always was, and nothing changes. See\n * {@link ModuleSchematicDoc.graph} and {@link deriveGraphDoc}. */\n graph?: ModuleSchematicDoc[\"graph\"];\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 flexByTrack: {},\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 // Everything in the map is an override the owner placed or typed — a derived\n // pose never enters it (poseOverridesFromDoc filters those out on the way in),\n // so it's safe to mark every one authored. That's what stops a derived pose\n // round-tripping into a silent pin, and it cleans an already-affected doc the\n // next time its owner saves (#182).\n return endplates.map((e) =>\n overrides[e.id] ? { ...e, pose: overrides[e.id], poseAuthored: true } : e,\n );\n}\n\n/** Attach endplate EDGE bindings by id (ADR 0001).\n *\n * A binding is not an override — it says the endplate IS this edge of the\n * benchwork, so position, heading and width are read off the board and cannot\n * go stale. Written back verbatim; there is deliberately no conversion from a\n * `pose`, because guessing which edge someone's freehand placement meant would\n * be inventing their intent. */\nfunction withEdges(\n endplates: SchematicEndplate[],\n edges: Record<string, EndplateEdge> | undefined,\n): SchematicEndplate[] {\n if (!edges) return endplates;\n return endplates.map((e) => (edges[e.id] ? { ...e, edge: edges[e.id] } : e));\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/**\n * Attach each track's flex settings (#193). Only what the owner has actually\n * chosen is written: an absent product means the default, and absent cuts mean\n * \"derive them\", which is a different thing from an empty list (that would mean\n * \"one uncut piece, however long the run is\").\n */\nfunction withFlex(state: EditorState, tracks: SchematicTrack[]): SchematicTrack[] {\n return tracks.map((t) => {\n const f = state.flexByTrack?.[t.id];\n if (!f) return t;\n const cuts = f.cuts?.filter((c) => Number.isFinite(c)).sort((a, b) => a - b);\n return {\n ...t,\n ...(f.partId ? { flexPartId: f.partId } : {}),\n ...(cuts ? { flexCuts: cuts } : {}),\n };\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 withEdges(\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 // ⚠️ `configB: \"none\"` means the module HAS NO FAR ENDPLATE, and\n // that is not loop-only (#184). An *end of the line* or a *pocket*\n // presents one conforming face and the track simply stops. The\n // standard governs the ends a module offers for joining; it never\n // required a module to offer two. This used to coerce \"none\" to\n // \"single\" and emit a B regardless, so a single-ended module was\n // impossible to author.\n ...(state.configB !== \"none\"\n ? [\n {\n id: \"B\",\n label: \"East\",\n tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: 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 ), state.endplateEdges),\n state.endplateWidths,\n state.endplateTrackOffsets,\n ),\n // Flex settings are attached to every track at once, at the end — the array\n // below has half a dozen branches and adding two fields to each of them is\n // how they'd end up disagreeing (#193).\n tracks: withFlex(state, [\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 // ⚠️ USABLE capacity, measured from the governing turnouts' CLEARANCE\n // POINTS (#19) — not the drawn rail-to-rail length, which counts track\n // a car can't stand on without fouling the route it diverged from.\n // FMN-0040's 70″ siding is 21 cars drawn and 17 usable.\n capacityFeet: usableCapacity({\n fromPos: t.fromPos,\n toPos: t.toPos,\n governing: state.turnouts.filter((sw) => sw.divergeTrack === t.id),\n measuredUsableInches: t.measuredUsableInches,\n }).scaleFeet,\n ...(typeof t.measuredUsableInches === \"number\" && t.measuredUsableInches >= 0\n ? { measuredUsableInches: t.measuredUsableInches }\n : {}),\n ...(state.loop && t.inLoop ? { inLoop: true } : {}),\n ...(t.crossoverPartId ? { crossoverPartId: t.crossoverPartId } : {}),\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 ...(t.partId ? { partId: t.partId } : {}),\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 // Carried, not interpreted. An anchor is what HOLDS the span (ADR\n // 0001); dropping it here would quietly convert an anchored\n // industry back into a typed number the next time anyone saved.\n ...(ind.anchor ? { anchor: ind.anchor } : {}),\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 // The pieces the owner drew, carried verbatim (ADR 0001). This function\n // stays dumb about them on purpose: deriving here would put the derivation\n // in every save path in both apps. `deriveGraphDoc` is the one place.\n ...(state.graph?.pieces?.length ? { graph: state.graph } : {}),\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 // Keep HUNDREDTHS, not whole inches. Rounding to 1″ silently flattened every\n // authored position on load — Steve's 17.4″ frog read as 17″, Oxnard's 68.4″\n // spur as 68″ — and since the editor autosaves, the rounded value was written\n // back over the owner's measurement. #132 asks owners to type positions taken\n // off XTrkCAD to the tenth, so this was destroying exactly the precision we\n // requested (and left the editor disagreeing with every raw-doc renderer by up\n // to half an inch). Hundredths still absorb float noise from a real rescale.\n const sc = (p: number) => Math.round(p * scale * 100) / 100;\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 // The crossover product this connector was built from — what makes the\n // physical view draw the pair at the spacing it was really built to.\n ...(typeof t.crossoverPartId === \"string\" && t.crossoverPartId\n ? { crossoverPartId: t.crossoverPartId }\n : {}),\n // Authored path kept as-drawn (a physical shape, not rescaled with length).\n ...(trackPath(t.path) ? { path: trackPath(t.path)! } : {}),\n // A MEASURED length is a real-world fact about the physical track, so it\n // rescales with the module exactly as its positions do (#20).\n ...(typeof t.measuredUsableInches === \"number\" && Number.isFinite(t.measuredUsableInches)\n ? { measuredUsableInches: sc(t.measuredUsableInches) }\n : {}),\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 // ⭐ Edge bindings (ADR 0001) — an endplate that IS part of the benchwork.\n // Carried through unscaled: an edge index is a reference, not a dimension.\n const endplateEdges: Record<string, EndplateEdge> = {};\n for (const e of d!.endplates ?? []) {\n if (e.edge && Number.isFinite(e.edge.index) && e.edge.index >= 0)\n endplateEdges[e.id] = {\n index: Math.trunc(e.edge.index),\n ...(e.edge.section ? { section: e.edge.section } : {}),\n ...(Number.isFinite(e.edge.fromT as number) ? { fromT: e.edge.fromT } : {}),\n ...(Number.isFinite(e.edge.toT as number) ? { toT: e.edge.toT } : {}),\n };\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 // Flex settings by track id (#193). Cuts are positions ALONG the run, so they\n // rescale with the module exactly as fromPos/toPos do — a rescaled module\n // whose joints stayed put would have them landing in different places.\n const flexByTrack: Record<string, { partId?: string; cuts?: number[] }> = {};\n for (const t of d!.tracks ?? []) {\n const partId = typeof t.flexPartId === \"string\" && t.flexPartId ? t.flexPartId : undefined;\n // An EMPTY authored list is meaningful — \"no joints, one uncut piece\" — and\n // is a different statement from absent, which means \"derive them\".\n const cuts = Array.isArray(t.flexCuts)\n ? t.flexCuts.filter((c) => Number.isFinite(c)).map(sc).sort((a, b) => a - b)\n : undefined;\n if (partId || cuts) flexByTrack[t.id] = { ...(partId ? { partId } : {}), ...(cuts ? { cuts } : {}) };\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 // NO ENDPLATE B ⇒ \"none\", whatever kind of module this is. On a loop that\n // reads as a pure turnback (a present B makes it an interchange); on an end\n // of the line or a pocket it simply means the module has one face (#184).\n // ⚠️ This used to be `loop && !hasB`, so \"none\" only survived a round trip on\n // a loop — which passed its test yesterday ONLY because a single-endplate\n // module was still being misclassified as one (#191). The absence of the\n // plate is the fact; why it's absent doesn't change what to read.\n configB: hasB ? configOf(\"B\") : \"none\",\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 flexByTrack,\n endplateWidths,\n endplateTrackOffsets,\n endplateEdges,\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 // ⚠️ NOT scaled by `sc()` like every position above it. A piece is placed in\n // real inches on the board; stretching the module's length does not move it,\n // and the length is DERIVED from the pieces anyway when a graph is present.\n ...(d!.graph?.pieces?.length ? { graph: d!.graph } : {}),\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 // Heal a turnout that diverges into the track it sits on (#172) with the\n // same helper the read path uses, so the editor and every renderer agree.\n turnouts: (healSelfDivergingTurnouts(d!.turnouts) ?? []).map((t) => ({\n id: t.id,\n name: t.name ?? \"\",\n pos: sc(t.pos),\n onTrack: t.onTrack,\n divergeTrack: t.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 ...(t.partId ? { partId: t.partId } : {}),\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 ...(s.anchor ? { anchor: s.anchor } : {}),\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 ...(ind.anchor ? { anchor: ind.anchor } : {}),\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 turnout 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 turnout 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/**\n * A route leaving the module at a third endplate — and an endplate is an\n * endplate, whatever letter it carries (#183).\n *\n * There is no split in the standard between \"the two ends\" and \"the others\": an\n * endplate is the standardised face where a module joins another module, and a\n * module may present two, three, or one. So a route to C is drawn the way a\n * route to A or B is drawn — **it runs to the edge of the module and terminates\n * in an endplate face carrying its letter**, rather than stopping partway along\n * the strip as a stub.\n *\n * ⚠️ Because it runs the full width it would otherwise read as just another\n * parallel main, which is exactly the confusion a dispatcher must not have. Its\n * lane is therefore placed with a clear GAP beyond every other lane (see\n * `laneGapFromOthers`), and it ends at a plate rather than running off the edge.\n * The two requirements — full width, and not-a-parallel-main — are in tension by\n * design, and the separation is what resolves it.\n *\n * The LETTER is the module's own fact and is fine to draw. The DESTINATION\n * (\"to Fillmore\") depends on which module is physically attached at that\n * junction, so it stays Free-Dispatcher's to derive at runtime.\n */\nexport interface BranchConnector {\n /** Endplate id — \"C\", \"D\", … */\n id: string;\n /** The owner's local name for the plate. NOT the destination — that depends\n * on what's physically attached, so FD derives it at runtime. */\n label: string;\n /** The route's own name, from the track. */\n name: string;\n /** The branch track's id. */\n trackId: string;\n /** Whether the route IS a main (a diverging/split main) or a secondary\n * branch line. Drives drawn weight, not geometry. */\n kind: \"branch\" | \"main\";\n /** Where it leaves its host main. */\n posFrac: number;\n /** The host track's lane — a branch need not leave Main 1. Renderers must\n * start the diverge HERE, not at a hard-coded lane 0. */\n fromLane: number;\n /** Which side of the module it exits. */\n side: \"up\" | \"down\";\n /** The branch's own lane, signed by `side`, placed a clear GAP beyond every\n * other lane so it can't be mistaken for a parallel main — already folded\n * into laneMin/laneMax. */\n lane: number;\n /** Where the run ends and the endplate face is drawn: the module EDGE, 0 or\n * 1, because this is an end of the module like any other (#183). */\n endFrac: number;\n /** The route's own arc length on this module, inches — for the tooltip. The\n * drawn run is the strip's width, not this. */\n lengthInches: number;\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 /** Whether the module presents a far endplate at all. False for an *end of\n * the line* or a *pocket*, which offer one conforming face and simply stop\n * (#184) — a renderer must not label that end, or it announces a plate the\n * module hasn't got and invites something to be coupled to it (#191). A loop\n * is separate: see {@link loop} and {@link loopInterchange}. */\n hasEndplateB: boolean;\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 */\n/** N-scale track gauge, inches (9 mm). */\nexport const RAIL_GAUGE_INCHES = 0.354;\n/**\n * ⚠️⚠️ **DEAD — REFUTED *AND* BASELESS. NOTHING SHOULD REACH THIS.** Kept only\n * so a library with no measured leads at all still returns a number, and as a\n * record of how the mistake was made.\n *\n * It was points→frog for a #1 frog: a turnout's LEAD if lead were proportional\n * to frog number, from an Atlas #7 measuring 3⅜″ (Steve Branton, #173) ⇒\n * 3.375 / 7.\n *\n * TWO independent things are wrong with it:\n * 1. **Lead is not proportional to N.** Measured lead ÷ N: #5 = 0.600,\n * #7 = 0.513, #10 = 0.494. It reads ~20% SHORT at N=5.\n * 2. **Its founding measurement was superseded.** Will Gage re-measured the same\n * part at 3¹⁹⁄₃₂″, ⁷⁄₃₂″ longer, confirmed against his own points and frog\n * positions. So 0.482 is not even the right constant for the wrong model.\n *\n * {@link leadInchesForSize} now INTERPOLATES across the measured parts instead.\n * A single measurement can only ever be scaled — which is this rule — so the\n * lesson is that one data point cannot support a shape, only a value.\n *\n * A constant-switch-angle model was also proposed here and is likewise REFUTED:\n * inverting {@link turnoutClosure} gives α = 0.036 (#5), 0.067 (#7), 0.043\n * (#10). Kept as a warning — it was floated when the #7 and #10 agreed to 3%,\n * on a #10 figure that later turned out to be measured to the wrong landmark.\n * TWO AGREEING PARTS ARE NOT A LAW, and neither is a coincidence you haven't\n * checked the provenance of.\n *\n * The pattern that currently fits is on {@link ATLAS_CODE55_N}: the moulding\n * runs past the frog far enough to gain a constant 0.25″ of separation. Note it\n * predicts the FROG POSITION, not the lead — this constant has no successor.\n */\nexport const TURNOUT_LEAD_INCHES_PER_FROG = 0.482;\n\n// ---- Track parts library (#179 stage 3) ------------------------------------\n//\n// Real commercial track parts, so a turnout drawn in MR is dimensionally the\n// part the owner will actually lay. Two sources, deliberately kept apart:\n//\n// 1. BUILT-IN parts below — our own data, from manufacturer specs and owner\n// measurements. Dimensions are facts, so this is safe to publish.\n// 2. IMPORTED parts — `parseXtpLibrary()` reads an owner's OWN XTrkCAD .xtp.\n// We deliberately DON'T redistribute those files: they ship with a GPL\n// program, carry individual attribution (\"Design by …\") and no license of\n// their own. Owners who have XTrkCAD already have the data.\n//\n// ⚠️ Every dimension records WHERE IT CAME FROM. Published specs for N-scale\n// turnout leads are scarce — most of what's out there is derived or measured —\n// and a derived number that looks like a spec is how bad geometry becomes\n// permanent. If you improve a value, update its `source` with it.\n\n/** Where a dimension came from. `derived` = we computed it from another part or\n * a rule of thumb; `unverified` = plausible but unconfirmed — treat with care. */\nexport type DimensionSource = \"manufacturer\" | \"measured\" | \"derived\" | \"unverified\";\n\nexport interface PartDimension {\n inches: number;\n source: DimensionSource;\n /** Who measured it / which spec, so it can be re-checked. */\n note?: string;\n}\n\n/** Same provenance discipline as {@link PartDimension}, for angles. */\nexport interface PartAngle {\n deg: number;\n source: DimensionSource;\n note?: string;\n}\n\nexport interface TrackPart {\n /** Stable slug, e.g. \"atlas-c55-n-7\". */\n id: string;\n manufacturer: string;\n /** Product line — \"Code 55\", \"Code 80\". */\n line: string;\n scale: \"N\";\n name: string;\n /** `flex` is track sold by the length rather than as a fixed geometry — its\n * {@link overallLength} is the LONGEST piece you can lay from it, not a shape\n * (#193). */\n /** ⚠️ `crossover` is an ASSEMBLY, not a single turnout. A Fast Tracks\n * crossover fixture builds ONE SYMMETRICAL HALF; you build a second, rotate it\n * 180° and butt the two together at the through routes and the scissors to get\n * a complete DOUBLE CROSSOVER — four turnouts, two diagonals, and the SCISSORS\n * where they cross. ⚠️ Will Gage, 2026-07-26: *\"A double crossover contains\n * the scissors.\"* The scissors is that X, not the whole assembly — do not use\n * it as another name for the part. So it carries {@link trackSpacing} and\n * {@link secondaryFrogAngle}, which no single turnout has, and\n * {@link piecesPerAssembly} — because its lengths describe the HALF, not the\n * finished crossover. */\n kind:\n | \"turnout\"\n | \"wye\"\n | \"curved-turnout\"\n | \"crossover\"\n | \"crossing\"\n | \"flex\"\n /** ⚠️ A SECTIONAL PIECE IS NOT FLEX CUT TO LENGTH, even though the rail ends\n * up in the same place. Its length belongs to the PART and cannot be\n * changed, because an owner has a box of them and cannot cut one — which is\n * the whole reason to model it separately from flex. */\n | \"straight\"\n | \"curve\"\n | \"bumper\";\n /** Manufacturer part numbers by hand, where the part has a hand. */\n partNumbers?: { left?: string; right?: string; single?: string };\n /** Frog number N (the 1:N ratio). Definitional, so no provenance needed. */\n frogNumber?: number;\n /** The angle the part ACTUALLY diverges at, where that's known to differ from\n * the theoretical `atan(1/N)`. Atlas appear to build to SECTIONAL angles\n * (multiples of 11.25° = 1/32 turn) rather than true frog ratios, so a \"#5\" is\n * 11.25° not 11.31°. ⚠️ Currently below our drawing resolution — 0.06° over a\n * 6″ turnout is 0.006″ — so nothing uses this yet. Recorded because it's a\n * real property of the product and will matter if we ever check whether a part\n * mates with sectional track. */\n actualAngle?: PartAngle;\n /** Points → frog. The number that decides where a turnout's throat lands. */\n lead?: PartDimension;\n /** End of the tie strip → the point tips. Where the working turnout starts\n * inside its moulding; the rest of that end is plain approach track. Needed to\n * fit a part into a space, and by any renderer drawing the real outline. */\n pointsOffset?: PartDimension;\n /** End of the tie strip → the APEX OF THE FROG V, measured from the same end\n * as {@link pointsOffset}. ⚠️ The apex, NOT the end of the frog casting — on a\n * shallow #10 those are ¾″ apart, which is how this library recorded a wrong\n * #10 lead through two releases. `lead` is the difference of the two, so\n * prefer these when both are known: they're what someone can actually put a\n * rule against. */\n frogOffset?: PartDimension;\n /** End-to-end length of the part.\n *\n * ⚠️ On a {@link buildable} part this is the manufacturer's DEFAULT length,\n * not a property of the part — the modeller cuts the rail, so their turnout\n * is whatever they built between {@link minimumLength} and as long as they\n * like. */\n overallLength?: PartDimension;\n /** True when the product is a FIXTURE or template rather than a finished\n * turnout — Fast Tracks sell jigs, not parts. The distinction is not cosmetic:\n * a buildable part has no single length, so `overallLength` becomes a default\n * and `minimumLength` a floor, and nothing may infer where an owner's actual\n * turnout ends from either of them. */\n buildable?: boolean;\n /**\n * This part stands in for one nobody has identified — its shape is\n * interpolated, not read off anything.\n *\n * ⛔ A provisional part must never be adopted automatically, offered beside\n * real products as an equal, or allowed to look measured. It exists so an\n * owner who cannot answer \"which turnout is this?\" is not blocked, and so that\n * what they could not answer stays visible afterwards.\n */\n provisional?: boolean;\n /** The shortest the part can be built. Buildable parts only. */\n minimumLength?: PartDimension;\n /** How many identical pieces built on this fixture make ONE finished part.\n *\n * ⚠️ WHEN THIS IS SET, `overallLength` AND `minimumLength` DESCRIBE ONE PIECE,\n * NOT THE FINISHED ITEM. A Fast Tracks crossover fixture builds one half of a\n * double crossover: you build it twice, rotate the second 180°, and butt them\n * together. Its 10.07″ is the half. Absent or 1 means the fixture builds the\n * whole part in one go, which is the case for every turnout and wye here. */\n piecesPerAssembly?: number;\n /** The radius of plain curve this turnout can stand in for, as a\n * layout-planning figure. Fast Tracks publish it; Atlas do not. Nothing draws\n * with it — it is here because it is a real published dimension and dropping\n * it would mean the library could not represent what a manufacturer actually\n * says about their own product. */\n substitutionRadius?: PartDimension;\n /** Frog apex → the end of the diverging rail, measured ALONG that rail. The\n * independent cross-check on {@link frogOffset}: it must be slightly LONGER\n * than the axial `overallLength − frogOffset`, because the rail is the\n * hypotenuse of the angle it leaves at. A reading that makes that difference\n * negative means a mis-read frog — which is exactly how the 2057 wye's frog\n * was caught (see its note). Too insensitive to recover the angle from — at\n * these angles ¹⁄₃₂″ of slop swings the implied half-angle by 6° — so use it\n * to falsify a frog position, never to derive one. */\n divergingLength?: PartDimension;\n /** Diverging route radius (straight turnouts). */\n divergingRadius?: PartDimension;\n /**\n * SECTIONAL CURVE only: the radius it is built to.\n *\n * ⚠️ Distinct from {@link outerRadius}/{@link innerRadius}, which are the two\n * routes of a CURVED TURNOUT. A plain curve has one radius, and giving it the\n * \"outer\" one would say there is another.\n */\n radius?: PartDimension;\n /**\n * SECTIONAL CURVE only: how much of a circle the piece covers, degrees.\n *\n * ⭐ Radius and arc are how curves are SOLD (\"19″ radius, 10°\"), so they are\n * what an owner can read off the box. The piece's length is the arc between\n * them and is never stored — a chord recorded as a length would quietly\n * shorten every curve on the module.\n */\n arcDegrees?: number;\n /** Curved turnouts: the two concentric radii. */\n outerRadius?: PartDimension;\n innerRadius?: PartDimension;\n /** Crossing angle, degrees. */\n crossingAngleDeg?: number;\n /** Centre-to-centre distance of the two parallel tracks a {@link kind}\n * `crossover` joins. A crossover fixture is BUILT for one spacing — it is not\n * adjustable — so this decides whether the part suits a given standard at all.\n *\n * ⚠️ READ {@link FREEMO_TRACK_SPACING_INCHES} ALONGSIDE THIS. Free-moN §2.0\n * fixes double-track spacing at exactly 1.125″; the Fast Tracks N crossovers\n * are built to 1.09″. That 0.035″ is small but it is REAL and it is not a\n * tolerance — the fixture cannot be built to another spacing. Recorded rather\n * than reconciled: it is a fact about the product, and an owner deciding what\n * to buy is better served by the true number than by a convenient one. */\n trackSpacing?: PartDimension;\n /** The SECOND frog angle on a part that has two — the SCISSORS of a double\n * crossover, the X where its two opposite diverging routes meet and cross.\n * Published in degrees. */\n secondaryFrogAngle?: PartAngle;\n /** The part's drawn geometry in its own frame, when it came from a library\n * file. This is the payload worth importing — real outlines we can draw\n * instead of deriving a turnout's shape from a frog number. */\n segments?: PartSegment[];\n /** Connection points, each carrying position AND tangent. The seam a piece\n * graph would snap on (#179 stage 1-2). */\n ends?: PartEnd[];\n /** Set when the part came from an imported library file rather than our own\n * data — names the source so a user can tell where a dimension came from. */\n importedFrom?: string;\n}\n\n/** N-scale code 55 rail height, inches — Atlas publish .055″. */\nexport const CODE55_RAIL_HEIGHT_INCHES = 0.055;\n\n/**\n * Atlas N-scale Code 55 — the Free-moN mainstay.\n *\n * ⚠️ Atlas do not publish leads or overall lengths for the straight turnouts.\n * Everything here traces to physical measurements: Steve Branton's #7 lead\n * (3⅜″ points→frog, #173) and Will Gage's #5/#7/#10 overall lengths plus the\n * #10's lead and points offset. The #5's lead and the wye's are still derived.\n *\n * MEASURED GEOMETRY (all Will Gage's, off physical parts, frog taken at the V):\n *\n * part points frog V overall lead past frog ÷N\n * #5 1¾″ 4.75″ 6.00″ 3.00000″ 1.25″ 0.2500\n * #7 ⁵⁄₈″ 4⁷⁄₃₂″ 6.00″ 3.59375″ 1.78125″ 0.2545\n * #10 ⁹⁄₁₆″ 5.50″ 8.00″ 4.93750″ 2.50″ 0.2500\n * wye points frog V overall lead past frog diverging rail\n * #2.5 1⁵⁄₈″ 4⅛″ 6.50″ 2.50000″ 2.375″ 2.4375″\n * #3.5 ¾″ 3⁵⁄₃₂″ 5.00″ 2.40625″ 1.84375″ 1.9375″\n *\n * ⚠️ THE WYES ARE NOT ON THE ÷N TREND AND MUST NOT BE INTERPOLATED WITH THE\n * TURNOUTS. lead ÷ N is 1.00 and 0.69 against the turnouts' flat 0.25, and the\n * #2.5 is the LONGER part despite the sharper frog. Every size lookup here\n * filters `kind === \"turnout\"`, which is what keeps them out — do not \"fix\"\n * that filter to include wyes.\n *\n * Every one of these is Will Gage's, off a physical part, frog taken at the V.\n * ⚠️ The #7 lead SUPERSEDES Steve Branton's 3⅜″ (#173) — the library's founding\n * measurement, ⁷⁄₃₂″ short. Will's single-span reading and his two positions\n * agree exactly, which is why it wins. Steve's number was also the sole basis of\n * {@link TURNOUT_LEAD_INCHES_PER_FROG}; that constant is now baseless as well as\n * refuted, and {@link leadInchesForSize} interpolates across this table instead.\n *\n * ⭐ **THE PART RUNS PAST THE FROG FAR ENOUGH TO GAIN 0.25″ OF SEPARATION.**\n * Past-frog run ÷ N is 0.2500 / 0.2545 / 0.2500 — the #5 and #10 EXACT, the #7\n * within ¹⁄₃₂″ of the tie end (a 4¼″ frog would make it exact too, one tape\n * division away). Provenance note: the measurer was told that prediction BEFORE\n * re-reading and did not return 4¼″, so this is not a confirmation artefact. At the frog\n * the routes are one gauge apart; at the end of the moulding they are\n * 0.354 + 0.25 ≈ 0.6″ apart. So Atlas size the moulding for a constant\n * CLEARANCE, not a constant length — which is what a manufacturer would\n * sensibly do, and why overall length looks arbitrary until you divide by N.\n * ⚠️ It predicts the FROG POSITION from the overall length. It does NOT predict\n * the lead — the points offset is independent and must still be measured.\n * ⚠️ HYPOTHESIS. It is the FOURTH rule fitted to this data; the first three all\n * died. Two exact hits and a near miss is not a law.\n *\n * NOTHING HERE IS PROPORTIONAL TO FROG NUMBER. Three rules assumed otherwise;\n * all three were tested against a physical part and FAILED:\n * - ❌ **Lead ∝ N.** Measured lead ÷ N: #5 = 0.600, #7 = 0.513, #10 = 0.494.\n * {@link TURNOUT_LEAD_INCHES_PER_FROG} reads ~20% SHORT at N=5 — and its\n * founding measurement has since been superseded, so it is baseless too.\n * - ❌ **Constant switch angle.** Inverting {@link turnoutClosure} gives α =\n * 0.036 (#5), 0.055 (#7), 0.043 (#10). Not constant.\n * - ❌ **Overall length ∝ N.** #5 = 6.00″ and #7 = 6.00″ — same moulding, two\n * frog numbers.\n * - ❌ **Frog fixed at 4.75″** (shipped in 0.54.0, retracted in 0.55.0). It\n * rested on the #5 and #10 both reading 4.75″, but the #10's was the END OF\n * THE FROG CASTING, not the V. Measured consistently the frogs are at 4.75″,\n * 4³⁄₁₆″ and 5.5″ — all different.\n *\n * The definition is the reason: #N fixes the DIVERGENCE RATE AT THE FROG (1\n * across per N along) and says NOTHING about how much tie strip the manufacturer\n * wraps around it, or where inside it the frog goes. Angle is geometry;\n * everything else is a tooling decision. **Measure the part. Do not model it.**\n */\nexport const ATLAS_CODE55_N: TrackPart[] = [\n {\n id: \"atlas-c55-n-5\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#5 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2050\", right: \"2051\" },\n frogNumber: 5,\n lead: {\n inches: 3.0,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2050 (#5 LH): points at 1¾″, frog at 4.75″ ⇒ 3″ \" +\n \"exactly. REFUTED BOTH standing models — the per-frog rule predicted 2.41″, \" +\n \"the constant-switch-angle model 2.64″; both read short. It also retired my \" +\n \"earlier ~2.4″ photo estimate, which was 20% under.\",\n },\n pointsOffset: {\n inches: 1.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH) — end of tie strip to point tips\",\n },\n frogOffset: {\n inches: 4.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH) — tie end to the apex of the V\",\n },\n overallLength: {\n inches: 6.0,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2050 (#5 LH), end tie to end tie\",\n },\n actualAngle: {\n deg: 11.25,\n source: \"unverified\",\n note:\n \"CORROBORATED: XTrkCAD N-atlasn55.xtp gives 11.250152°, and AnyRail-forum \" +\n \"trial-and-error (glakedylan, 2012) gives 11.25°. Theory atan(1/5) = 11.310°. \" +\n \"11.25° is exactly 1/32 turn — Atlas appear to build to sectional angles.\",\n },\n },\n {\n id: \"atlas-c55-n-7\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#7 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2052\", right: \"2053\" },\n frogNumber: 7,\n lead: {\n inches: 3.59375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7), 3¹⁹⁄₃₂″ points→frog as a single \" +\n \"span — and it matches his two positions exactly (4⁷⁄₃₂ − ⁵⁄₈), so the \" +\n \"reading is internally consistent. SUPERSEDES Steve Branton's 3⅜″ (#173), \" +\n \"which was ⁷⁄₃₂″ short and was the library's founding measurement. \" +\n \"⚠️ Steve's number was also the SOLE basis of \" +\n \"TURNOUT_LEAD_INCHES_PER_FROG (3.375/7 = 0.482) — that constant is now \" +\n \"baseless as well as refuted.\",\n },\n pointsOffset: {\n inches: 0.625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2052 (#7) — ¹⁰⁄₁₆″ tie end to point tips\",\n },\n frogOffset: {\n inches: 4.21875,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7) — 4⁷⁄₃₂″, tie end to the apex of the V. \" +\n \"Supersedes an initial 4³⁄₁₆″. Worth noting for provenance: he was told \" +\n \"beforehand that the clearance hypothesis predicted 4¼″ and did NOT read \" +\n \"4¼″ — so this number is not a confirmation artefact, and it sits ¹⁄₃₂″ \" +\n \"(one tape division) from the predicted value.\",\n },\n overallLength: {\n inches: 6.0,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2052 (#7), end tie to end tie — the SAME 6″ \" +\n \"as the #5, which is what proves length is not a function of frog number\",\n },\n actualAngle: {\n deg: 8.13,\n source: \"unverified\",\n note:\n \"DISPUTED: XTrkCAD .xtp says 8.1818°, AnyRail forum says 8.125°, theory \" +\n \"atan(1/7) = 8.130°. The sources disagree, so theory is used here.\",\n },\n },\n {\n id: \"atlas-c55-n-10\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#10 Turnout\",\n kind: \"turnout\",\n partNumbers: { left: \"2054\", right: \"2055\" },\n frogNumber: 10,\n lead: {\n inches: 4.9375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2054 (#10): 5.5″ frog − 9/16″ points = 4¹⁵⁄₁₆″. \" +\n \"⚠️ CORRECTED from 4³⁄₁₆″ (0.53.0–0.54.0), which used a 4.75″ frog reading \" +\n \"taken before we'd agreed the landmark. That earlier figure was the END OF \" +\n \"THE FROG CASTING; a #10's V is shallow, so the apex is ¾″ back from it.\",\n },\n pointsOffset: {\n inches: 0.5625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10) — end of tie strip to point tips\",\n },\n frogOffset: {\n inches: 5.5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10) — tie end to the apex of the V\",\n },\n overallLength: {\n inches: 8.0,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2054 (#10), end tie to end tie\",\n },\n actualAngle: {\n deg: 5.74,\n source: \"unverified\",\n note:\n \"CORROBORATED: XTrkCAD .xtp gives 5.739°, AnyRail forum 5.75° — they agree \" +\n \"with each other and not with theory atan(1/10) = 5.711°.\",\n },\n },\n {\n id: \"atlas-c55-n-wye\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#2.5 Wye\",\n kind: \"wye\",\n partNumbers: { single: \"2056\" },\n frogNumber: 2.5,\n lead: {\n inches: 2.5,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2056, 2026-07-26: points at 1⁵⁄₈″, frog at 4⅛″ ⇒ \" +\n \"2.5″ — the difference of the two offsets, per the rule above. \" +\n \"⚠️ RETIRES a `derived` 1.205″ (2.5 × TURNOUT_LEAD_INCHES_PER_FROG) — the \" +\n \"real lead is more than DOUBLE it. Third independent refutation of the \" +\n \"per-frog rule, and the largest: at low N it is not merely mis-sloped, \" +\n \"it is nowhere near.\",\n },\n pointsOffset: {\n inches: 1.625,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — end of tie strip to point tips (1¹⁰⁄₁₆″)\",\n },\n frogOffset: {\n inches: 4.125,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — tie end to the apex of the V (4²⁄₁₆″)\",\n },\n overallLength: {\n inches: 6.5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2056 — end to end\",\n },\n divergingLength: {\n inches: 2.4375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2056 — frog to the end of each diverging rail \" +\n \"(2⁷⁄₁₆″, both legs equal). ✔ CROSS-CHECKS the frog: axial past-frog is \" +\n \"6.5 − 4.125 = 2.375″, and the rail is ¹⁄₁₆″ longer than its own \" +\n \"projection, which is the right sign and the right order of magnitude.\",\n },\n },\n {\n // Will Gage, 2026-07-26: \"2057 is 3.5, 2056 is 2.5\" — the two Atlas Code 55\n // wyes are different FROG NUMBERS, not a left/right pair of one part. The\n // 2056 half of that confirms the entry above; this is the one we didn't have.\n //\n // Fully measured 2026-07-26, after one reading was caught and re-read.\n //\n // ⚠️ WORKED EXAMPLE OF WHY THIS LIBRARY CROSS-CHECKS. The frog first came in\n // at 5⁵⁄₃₂″, which is PAST the part's own 5″ overall length — the apex would\n // have sat beyond the end of the moulding. Two independent lines said ~3⅛″:\n // · points ¾″ + points→frog 2⅜″ = 3.125″\n // · overall 5″ − diverging rail 1³⁰⁄₃₂″ ≈ 3.06″ axial\n // Queried, and Will re-read it as 3⁵⁄₃₂″ — a leading-digit slip, exactly what\n // the arithmetic implied. That re-read is the number recorded here; it was\n // NOT inferred. Had it been taken at face value the wye would have drawn its\n // frog off the end of itself.\n id: \"atlas-c55-n-wye-35\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"#3.5 Wye\",\n kind: \"wye\",\n partNumbers: { single: \"2057\" },\n frogNumber: 3.5,\n lead: {\n inches: 2.40625,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057, 2026-07-26: points at ¾″, frog at 3⁵⁄₃₂″ ⇒ \" +\n \"2.40625″ — the difference of the two offsets, per the rule above. His \" +\n \"direct points→frog reading was 2⅜″, ¹⁄₃₂″ short; the offsets win. \" +\n \"⚠️ RETIRES the reasoning in this entry's original note, which left the \" +\n \"lead unset so `leadInchesForSize` would interpolate at the wye's \" +\n \"effective frog (3.5 × 2 = 7) and land on the measured #7's 3.59375″. \" +\n \"That substitution was 49% over.\",\n },\n pointsOffset: {\n inches: 0.75,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2057 — end of tie strip to point tips (¾″)\",\n },\n frogOffset: {\n inches: 3.15625,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057 — tie end to the apex of the V (3⁵⁄₃₂″). \" +\n \"This is his RE-READ after the first reading (5⁵⁄₃₂″) was queried for \" +\n \"landing past the part's 5″ end; see the comment above this entry.\",\n },\n overallLength: {\n inches: 5,\n source: \"measured\",\n note: \"Will Gage, physical Atlas 2057 — end to end\",\n },\n divergingLength: {\n inches: 1.9375,\n source: \"measured\",\n note:\n \"Will Gage, physical Atlas 2057 — frog to the end of each diverging rail \" +\n \"(1³⁰⁄₃₂″, both legs equal). ✔ THE READING THAT CAUGHT THE BAD FROG: \" +\n \"against the first 5⁵⁄₃₂″ the axial past-frog is NEGATIVE, which a 1.9375″ \" +\n \"rail flatly contradicts. Against the re-read 3⁵⁄₃₂″ it is 5 − 3.15625 = \" +\n \"1.84375″, so the rail runs ³⁄₃₂″ longer than its own projection — right \" +\n \"sign, same order as the 2056's ¹⁄₁₆″. (The two differ because this is a \" +\n \"cos() residual on a small angle, which is why the field doc says not to \" +\n \"read an angle back out of it.)\",\n },\n },\n {\n id: \"atlas-c55-n-curved-21-15\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: 'Curved Turnout 21¼\" / 15\"',\n kind: \"curved-turnout\",\n partNumbers: { left: \"2058\", right: \"2059\" },\n outerRadius: { inches: 21.25, source: \"manufacturer\", note: \"Atlas product listing\" },\n innerRadius: { inches: 15, source: \"manufacturer\", note: \"Atlas product listing\" },\n },\n];\n\n/**\n * Flex track — the stuff every run that isn't a turnout or a crossing is made\n * of (#193). A length of flex has no fixed geometry, so the only dimension it\n * carries is **how long a piece you can lay from one**: past that you have\n * another length, with a rail joint between them.\n *\n * ⚠️ These lengths are the NOMINAL PRODUCT LENGTHS as reported by Will Gage\n * (2026-07-26), not values read off a spec sheet or measured. They are what the\n * product is sold as — \"30 inch flex track\" — which is exactly the number a\n * builder plans cuts against, so they're recorded as `manufacturer` with the\n * source named. Correct them if a listing says otherwise.\n *\n * No part numbers here: I don't have them confirmed, and a wrong part number is\n * worse than none — someone would order against it.\n */\nexport const FLEX_TRACK_PARTS: TrackPart[] = [\n {\n id: \"atlas-c55-n-flex\",\n manufacturer: \"Atlas\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"Code 55 Flex Track\",\n kind: \"flex\",\n overallLength: {\n inches: 30,\n source: \"manufacturer\",\n note: \"nominal product length, reported by Will Gage 2026-07-26\",\n },\n },\n {\n id: \"me-c55-n-flex\",\n manufacturer: \"Micro Engineering\",\n line: \"Code 55\",\n scale: \"N\",\n name: \"Code 55 Flex Track\",\n kind: \"flex\",\n overallLength: {\n inches: 36,\n source: \"manufacturer\",\n note: \"nominal product length, reported by Will Gage 2026-07-26\",\n },\n },\n];\n\n/**\n * Fast Tracks N-scale assembly fixtures, Micro Engineering Code 55 rail.\n *\n * ⚠️ A DIFFERENT MANUFACTURER PUBLISHES DIFFERENT NUMBERS, and the library has\n * to hold what each one actually says rather than a lowest common denominator.\n * Fast Tracks publish none of Atlas's three landmarks — no points offset, no\n * frog offset, no lead — and four things Atlas never state:\n *\n * straight angle div R default minimum substitution R\n * #4 14.04° 8″ 4.57″ 3.43″ 11″\n * #4.5 12.53° 11″ 5.00″ 3.90″ 14″\n * #5 11.31° 14″ 5.39″ 3.92″ 17″\n * #6 9.46° 23″ 6.26″ 4.30″ 24″\n * #7 8.13° 27″ 7.40″ 5.44″ 34″\n * #8 7.13° 36″ 8.00″ 5.93″ 42″\n * #9 6.34° 50″ 8.38″ 6.42″ 57″\n * #10 5.71° 64″ 9.15″ 6.80″ 70″\n * #12 4.76° 82″ 10.34″ 7.95″ 90″\n *\n * wye angle div R default minimum substitution R\n * #4 14.04° 23″ 4.63″ 3.48″ 27″\n * #5 11.31° 25″ 5.23″ 3.81″ 30″\n * #6 9.46° 35″ 5.99″ 4.30″ 47″\n * #8 7.13° 70″ 8.22″ 5.93″ 94″\n * #10 5.71° 89″ 9.47″ 6.97″ 130″\n *\n * ⭐ **FAST TRACKS BUILD TO TRUE FROG RATIOS.** Every angle above is `atan(1/N)`\n * to the digits published — 14.04, 11.31, 9.46, 8.13, 7.13, 6.34, 5.71, 4.76.\n * Atlas do NOT: they build to SECTIONAL angles (a \"#5\" is 11.25°, a 1/32 turn,\n * against theory's 11.310°). Two manufacturers, two different meanings for the\n * same number on the box, and the difference is real if you ever check whether\n * a part mates with sectional track.\n *\n * ⚠️ THESE ARE FIXTURES, SO THEY HAVE NO LENGTH. The modeller cuts the rail:\n * `overallLength` here is the manufacturer's DEFAULT and `minimumLength` the\n * floor. Because Fast Tracks publish no points offset, {@link partExtent}\n * returns null for every one of them, so none claims a body and flex still runs\n * through it (#193). That is the honest answer — we do not know where an\n * owner's hand-built turnout stops, and guessing from a default length would be\n * inventing a measurement. An owner who measures their own build can enter it,\n * and the admin form's cross-checks will catch a bad reading.\n *\n * Source: handlaidtrack.com product pages, \"Detailed Specifications\" tables,\n * read 2026-07-26. ⚠️ The PDF templates in Will's local reference folder are\n * ENCRYPTED (`/Encrypt /Standard`), so they are deliberately not the source\n * here — the public product pages say the same thing and can be cited.\n */\nexport const FAST_TRACKS_N_ME55: TrackPart[] = (\n [\n // [kind, N, angle°, divergingR, defaultLength, minLength, substitutionR]\n [\"turnout\", 4, 14.04, 8, 4.57, 3.43, 11],\n [\"turnout\", 4.5, 12.53, 11, 5, 3.9, 14],\n [\"turnout\", 5, 11.31, 14, 5.39, 3.92, 17],\n [\"turnout\", 6, 9.46, 23, 6.26, 4.3, 24],\n [\"turnout\", 7, 8.13, 27, 7.4, 5.44, 34],\n [\"turnout\", 8, 7.13, 36, 8, 5.93, 42],\n [\"turnout\", 9, 6.34, 50, 8.38, 6.42, 57],\n [\"turnout\", 10, 5.71, 64, 9.15, 6.8, 70],\n [\"turnout\", 12, 4.76, 82, 10.34, 7.95, 90],\n [\"wye\", 4, 14.04, 23, 4.63, 3.48, 27],\n [\"wye\", 5, 11.31, 25, 5.23, 3.81, 30],\n [\"wye\", 6, 9.46, 35, 5.99, 4.3, 47],\n [\"wye\", 8, 7.13, 70, 8.22, 5.93, 94],\n [\"wye\", 10, 5.71, 89, 9.47, 6.97, 130],\n ] as Array<[\"turnout\" | \"wye\", number, number, number, number, number, number]>\n).map(([kind, n, deg, divR, dflt, min, subR]) => {\n const code = kind === \"wye\" ? \"y\" : \"t\";\n const spec = \"handlaidtrack.com Detailed Specifications, read 2026-07-26\";\n const manufacturer: DimensionSource = \"manufacturer\";\n return {\n id: `fast-tracks-n-me55-${code}-${n}`,\n manufacturer: \"Fast Tracks\",\n line: \"Code 55\",\n scale: \"N\" as const,\n // Named for what the OWNER has, not what Fast Tracks sell. They sell a jig;\n // the person picking this in the editor is holding the turnout they built\n // on it. `buildable` and the AF-… part number carry the fixture fact.\n name: `#${n} ${kind === \"wye\" ? \"Wye\" : \"Turnout\"}`,\n kind,\n partNumbers: { single: `AF-N-${code.toUpperCase()}-${n}-ME55` },\n frogNumber: n,\n buildable: true,\n actualAngle: {\n deg,\n source: manufacturer,\n note: `${spec}. Matches atan(1/${n}) to the published digits — Fast Tracks build to TRUE frog ratios, unlike Atlas's sectional angles.`,\n },\n divergingRadius: { inches: divR, source: manufacturer, note: spec },\n overallLength: {\n inches: dflt,\n source: manufacturer,\n note: `${spec}. The DEFAULT length — this is a fixture, so the builder chooses.`,\n },\n minimumLength: { inches: min, source: manufacturer, note: spec },\n substitutionRadius: { inches: subR, source: manufacturer, note: spec },\n } satisfies TrackPart;\n});\n\n/**\n * Fast Tracks N-scale CROSSOVER fixtures, ME Code 55.\n *\n * crossover angle 2nd frog HALF: default minimum track spacing\n * #6 9.46° 19° 10.07″ 9.31″ 1.09″\n * #8 7.13° 14.3° 13.61″ 13.07″ 1.09″\n *\n * ⚠️⚠️ **THE LENGTHS ABOVE ARE ONE HALF, NOT THE FINISHED CROSSOVER.** Will\n * Gage, 2026-07-26: *\"crossovers are two pieces. the pdf shows half, then you\n * would duplicate this same piece and flip it 180 and butt it up to the through\n * and X.\"* Fast Tracks say the same — *\"Crossovers are constructed by building\n * two symmetrical halves of a crossover in the Assembly Fixture and then joining\n * them to form a complete double crossover\"* — and their own gloss on the\n * length is \"the length of the turnout on the QuickSticks\", i.e. the piece the\n * fixture holds. `piecesPerAssembly: 2` records this so the number cannot be\n * read as the assembly's.\n *\n * ⚠️ THE FINISHED LENGTH IS NOT PUBLISHED, and is deliberately not stored. The\n * two halves are related by a 180° rotation about the scissors, so they cover the\n * same longitudinal span and the finished crossover is plausibly also ~10.07″ —\n * but that is an inference from the symmetry, not a reading, and this library\n * has been burned four times by exactly that kind of plausible reconstruction.\n * If it matters, measure a built one.\n *\n * ⚠️ THESE MAKE A DOUBLE CROSSOVER — four turnouts, two diagonals, and the\n * SCISSORS where the two opposite diverging routes meet and cross in an X.\n * A half carries one full 9.46° frog and HALF of the 19° scissors, which is why\n * the scissors only exists once the second piece is butted up. Not a single\n * crossover: half a scissors is not usable on its own.\n *\n * ⚠️ TERMINOLOGY, from Will Gage 2026-07-26: *\"A double crossover contains the\n * scissors. The location where both opposite diverging routes meet and cross\n * like an 'X'.\"* The scissors is that crossing, NOT another name for the whole\n * part — the assembly is a double crossover. Nor is it this library's\n * `crossing`/diamond kind, which is two tracks crossing with no route choice\n * (#170); the scissors is internal to the crossover.\n *\n * ⚠️⚠️ **THE TRACK SPACING IS 1.09″, AND FREE-moN §2.0 REQUIRES 1.125″.**\n * A crossover fixture is machined for ONE spacing; it is not adjustable. So a\n * crossover hand-built on either of these puts the parallel track 0.035″ closer\n * than the standard, and that difference has to go somewhere — the tracks pinch\n * through the crossover and open back out to meet the endplates, which is fixed\n * at both ends by {@link FREEMO_TRACK_SPACING_INCHES}.\n *\n * Recorded, NOT reconciled. It is 0.9 mm and most builders will absorb it, but\n * it is a property of the product rather than a tolerance, and someone choosing\n * what to buy for a double-track Free-moN module is better served by the true\n * number than a convenient one. Nothing here warns or blocks — that would be a\n * decision for the app, not for a data table.\n *\n * ⭐ THE SECOND FROG IS EXACTLY TWICE THE FIRST — 19° against 2 × 9.46 = 18.92,\n * and 14.3° against 2 × 7.13 = 14.26, both inside the published rounding. That\n * is the diamond, where the two halves' diagonals — each leaving its main at the\n * frog angle, and pointing opposite ways because the second piece is turned\n * 180° — cross each other. It is a free cross-check on the pair, it passes, and\n * it independently corroborates the two-piece build: a part with one frog would\n * have no second angle to publish.\n *\n * ⚠️ A CROSSOVER IS AN ASSEMBLY, so `partExtent` means nothing for it and the\n * turnout size lookups must never see it: `kind` is `\"crossover\"`, and every\n * one of them filters `kind === \"turnout\"`.\n *\n * Atlas make crossover parts too — Will has no figures for them as of\n * 2026-07-26, so there are deliberately no Atlas entries here rather than\n * guessed ones.\n *\n * Source: handlaidtrack.com product pages, read 2026-07-26. Their tables also\n * carry tie size and tie spacing; those describe the QuickSticks tie strip's\n * appearance rather than the track's geometry, so they are not carried here.\n */\nexport const FAST_TRACKS_N_ME55_CROSSOVERS: TrackPart[] = (\n [\n // [N, angle°, secondFrog°, defaultLength, minLength, trackSpacing]\n [6, 9.46, 19, 10.07, 9.31, 1.09],\n [8, 7.13, 14.3, 13.61, 13.07, 1.09],\n ] as Array<[number, number, number, number, number, number]>\n).map(([n, deg, second, dflt, min, spacing]) => {\n const spec = \"handlaidtrack.com Detailed Specifications, read 2026-07-26\";\n const manufacturer: DimensionSource = \"manufacturer\";\n return {\n id: `fast-tracks-n-me55-c-${n}`,\n manufacturer: \"Fast Tracks\",\n line: \"Code 55\",\n scale: \"N\" as const,\n name: `#${n} Double Crossover`,\n kind: \"crossover\" as const,\n partNumbers: { single: `AF-N-C-${n}-ME55` },\n frogNumber: n,\n buildable: true,\n piecesPerAssembly: 2,\n actualAngle: { deg, source: manufacturer, note: `${spec}. atan(1/${n}) exactly.` },\n secondaryFrogAngle: {\n deg: second,\n source: manufacturer,\n note: `${spec}. The SCISSORS of a double crossover — the X where its two opposite diverging routes cross — at 2 × ${deg}° within the published rounding.`,\n },\n overallLength: {\n inches: dflt,\n source: manufacturer,\n note:\n `${spec}. ⚠️ ONE HALF, NOT THE FINISHED CROSSOVER — the fixture builds a ` +\n \"symmetrical half, which you build twice and butt together after turning \" +\n \"the second 180°. Fast Tracks gloss it as \\\"the length of the turnout on \" +\n \"the QuickSticks\\\", i.e. the piece in the jig. The DEFAULT for that \" +\n \"piece; it is a fixture, so the builder chooses.\",\n },\n minimumLength: {\n inches: min,\n source: manufacturer,\n note: `${spec}. The shortest ONE HALF can be built — see the overall length's note.`,\n },\n trackSpacing: {\n inches: spacing,\n source: manufacturer,\n note:\n `${spec}. ${spacing}″, and the fixture cannot be built to another spacing. ` +\n `⚠️ THIS IS NOT A DEPARTURE FROM THE STANDARD. Free-moN §2.0 fixes ` +\n `${FREEMO_TRACK_SPACING_INCHES}″ at the ENDPLATE — \"double track endplates must ` +\n `have a track spacing of 1.125 inches\", with track perpendicular, straight and ` +\n `level for 4″ from the outside face. What the two mains do in between is the ` +\n `module builder's business, and every real double crossover pinches them ` +\n `closer. Earlier wording here called the fixture \"tighter than the standard\", ` +\n `which reads as non-conformance and is wrong.`,\n },\n } satisfies TrackPart;\n});\n\n/** What a track is laid with when nobody has said — the commonest N-scale flex. */\nexport const DEFAULT_FLEX_PART_ID = \"atlas-c55-n-flex\";\n\n/** Every built-in part, across manufacturers. */\n/**\n * A bumper that is not a product.\n *\n * ⭐ DELIBERATELY GENERIC, AND CARRYING NO DIMENSIONS AT ALL. Owners build these\n * out of a tie and a scrap of rail as often as they buy them, and what a bumper\n * MEANS — this end of the track is closed on purpose — does not depend on which\n * one it is. Recording an invented length here would be exactly the mistake the\n * rest of this library exists to avoid; a named product can be added with its\n * own measurement, and will draw at it.\n */\n/** Frog numbers a placeholder is offered for. #6 is the standard's floor for a\n * main line; #4 and #5 are ordinary in yards. Outside the measured 5–10 range\n * the interpolators extrapolate, which is acceptable in a part that already\n * says it is a stand-in. */\nexport const GENERIC_TURNOUT_FROG_NUMBERS = [4, 5, 6, 7, 8, 10] as const;\n\n/**\n * A turnout nobody has identified — \"it's a #6, I don't know whose\".\n *\n * ⭐⭐ **IT IS THE TURNOUT'S WORKING GEOMETRY AND NOTHING ELSE**: points → frog\n * → end, with **no moulded approach track in front of the points**. That is not\n * a shortcut, it is the only honest shape available. `pointsOffset` is the one\n * dimension a frog number cannot yield — the measured Atlas parts read 1.75″,\n * 0.625″ and 0.5625″ for #5, #7 and #10, which is a moulding decision and not\n * geometry, so there is nothing to interpolate along. Zero is therefore not a\n * guess about the owner's part; it says we are modelling the turnout and not\n * some product's tie strip. It is also what a hand-laid turnout actually is.\n *\n * ⭐ **The lead and the length past the frog ARE derivable**, by interpolating\n * the measured parts ({@link leadInchesForSize}, {@link pastFrogInchesForSize})\n * — the same interpolation the 1-D model has always drawn an unidentified `#N`\n * with. Nothing new is invented here; what changes is that it is now labelled.\n *\n * ⚠️ **EVERY DIMENSION IS `derived`.** Two things follow, both wanted:\n * {@link partGeometry} reports `source: \"derived\"`, so any surface can say the\n * shape is provisional; and {@link partExtent} returns **null**, so the drawing\n * declines to claim where this turnout's body ends rather than laundering an\n * interpolation into a boundary an owner would read as measured.\n *\n * ⛔ **NEVER ADOPTED AUTOMATICALLY.** A placeholder is something an owner\n * chooses when they cannot answer; resolving a bare `#6` to one behind their\n * back would be exactly the invention ADR 0001 forbids. See\n * {@link moduleConversionReport}, which excludes provisional parts from both\n * automatic resolution and its candidate list.\n */\nexport function genericTurnoutPart(\n frogNumber: number,\n library = ATLAS_CODE55_N,\n): TrackPart {\n const derived: DimensionSource = \"derived\";\n const lead = leadInchesForSize(frogNumber, library);\n const past = pastFrogInchesForSize(frogNumber, library);\n const why =\n `Interpolated across the measured parts by frog number — a stand-in, not a reading. ` +\n `No points offset: it is not a function of the frog number (the measured #5, #7 and #10 ` +\n `read 1.75″, 0.625″ and 0.5625″), so this part begins AT the points, as a hand-laid ` +\n `turnout does.`;\n return {\n id: `generic-turnout-${frogNumber}`,\n manufacturer: \"Generic\",\n line: \"N scale\",\n scale: \"N\",\n name: `#${frogNumber} Turnout (make unknown)`,\n kind: \"turnout\",\n frogNumber,\n provisional: true,\n pointsOffset: { inches: 0, source: derived, note: why },\n lead: { inches: lead, source: derived, note: why },\n frogOffset: { inches: lead, source: derived, note: why },\n overallLength: { inches: lead + past, source: derived, note: why },\n };\n}\n\n/** The placeholders, one per {@link GENERIC_TURNOUT_FROG_NUMBERS}. */\nexport const GENERIC_TURNOUTS: TrackPart[] = GENERIC_TURNOUT_FROG_NUMBERS.map((n) =>\n genericTurnoutPart(n),\n);\n\n/** Parts that stand in for one nobody has identified — offered only where an\n * owner is being asked what something is, and never mixed in with real products\n * as though they were equivalent. */\nexport function provisionalParts(library = BUILT_IN_TRACK_PARTS): TrackPart[] {\n return library.filter((p) => p.provisional);\n}\n\nexport const GENERIC_END_OF_TRACK: TrackPart[] = [\n {\n id: \"generic-bumper\",\n manufacturer: \"Generic\",\n line: \"N scale\",\n scale: \"N\",\n name: \"Bumper\",\n kind: \"bumper\",\n },\n];\n\nexport const BUILT_IN_TRACK_PARTS: TrackPart[] = [\n ...ATLAS_CODE55_N,\n ...FAST_TRACKS_N_ME55,\n ...FAST_TRACKS_N_ME55_CROSSOVERS,\n ...FLEX_TRACK_PARTS,\n ...GENERIC_END_OF_TRACK,\n // ⚠️ LAST, AND PROVISIONAL. These are stand-ins, not products; every path that\n // resolves a turnout automatically filters them out, and every picker that\n // offers them must say what they are.\n ...GENERIC_TURNOUTS,\n];\n\n/** Every flex product a track can be laid with. */\nexport function flexParts(library = BUILT_IN_TRACK_PARTS): TrackPart[] {\n return library.filter((p) => p.kind === \"flex\");\n}\n\n/**\n * The flex product a track is laid with, falling back to the default rather\n * than to nothing: every non-turnout inch of track IS some product, and a run\n * whose owner hasn't chosen still gets cut into buyable lengths.\n */\nexport function flexPartFor(\n id: string | null | undefined,\n library = BUILT_IN_TRACK_PARTS,\n): TrackPart | null {\n const chosen = id ? library.find((p) => p.id === id && p.kind === \"flex\") : null;\n return chosen ?? library.find((p) => p.id === DEFAULT_FLEX_PART_ID) ?? flexParts(library)[0] ?? null;\n}\n\n/** How long a single piece of this product can be, inches. */\nexport function maxFlexPieceInches(\n id: string | null | undefined,\n library = BUILT_IN_TRACK_PARTS,\n): number {\n return flexPartFor(id, library)?.overallLength?.inches ?? 30;\n}\n\n/** Look a part up by its slug. */\nexport function trackPart(id: string, library = BUILT_IN_TRACK_PARTS): TrackPart | null {\n return library.find((p) => p.id === id) ?? null;\n}\n\n/** One length of flex track in a run — a real object you could pick up (#193). */\nexport interface FlexPiece {\n /** Position in the run, west to east. Stable enough to select and label by. */\n index: number;\n /** Inches along the RUN, not the module — the same coordinate turnouts,\n * industries and signals use, so a piece can be placed without a second\n * geometry to keep in step. */\n fromPos: number;\n toPos: number;\n lengthInches: number;\n /** Longer than the product allows. Only reachable from AUTHORED cuts, or from\n * a run that grew after they were authored — which is precisely when someone\n * needs telling. */\n overlong: boolean;\n /** What this piece butts against at each end: another piece, a part (turnout\n * or crossing), or the end of the run. */\n fromEnd: FlexPieceEnd;\n toEnd: FlexPieceEnd;\n}\n\n/** What a flex piece meets at one of its ends. */\nexport type FlexPieceEnd = \"piece\" | \"part\" | \"runEnd\";\n\n/**\n * A stretch of a run that is NOT flex — a turnout's or a crossing's own body.\n *\n * A **zero-length** span is meaningful: it's a break in the run at a point whose\n * own length we don't know. That's a crossing today — the run stops and starts\n * there, giving a rail joint, but we've measured no crossing part so claiming an\n * extent for it would be inventing one.\n */\nexport interface OccupiedSpan {\n fromPos: number;\n toPos: number;\n}\n\n/** Positions closer than this are the same position — a cut can't be a hair\n * from a turnout's end and mean anything different from being on it. */\nconst FLEX_EPS = 1e-6;\n\n/**\n * Shorter than this and it isn't a piece of track, it's an offcut — nobody\n * joints a tenth of an inch on. Full lengths from the start of a gap can leave\n * one (72.1″ of 36″ flex leaves 0.1″), so the last two get balanced instead.\n * A 6″ tail off a 30″ length is a real piece and is left alone.\n */\nconst FLEX_MIN_PIECE_INCHES = 1;\n\n/**\n * Cut a run into lengths of flex track.\n *\n * The model (#193): everything that isn't a turnout or a crossing is flex, flex\n * comes in pieces of a maximum length, and where two pieces meet is a rail\n * joint — the same joint a turnout makes with the track past it (#189). A 96″\n * main isn't one piece of track; it's four lengths of Atlas flex with three\n * joints in it, which is what someone actually buys and lays.\n *\n * Pieces are **spans of the run**, not free-floating geometry. That's deliberate:\n * `pos` — inches along the run — is what every turnout, industry and signal is\n * placed in, so a piece that carried its own shape would be a second geometry to\n * keep in step with the first. As spans they get identity, a length you can\n * change, and ends that meet their neighbours by construction.\n *\n * `cuts` is the owner's authoring and is **complete when present**: those are\n * the only joints, and a piece that ends up too long is flagged rather than\n * silently re-cut. Absent, the cuts are derived — full lengths from the start of\n * each gap, remainder at the end, which is how you lay it. That's what lets\n * every existing module arrive already cut up without anyone touching it.\n */\nexport function flexPieces(input: {\n fromPos: number;\n toPos: number;\n /** Longest single piece of the product this run is laid with. */\n maxPieceInches: number;\n /** Stretches the run gives up to parts — turnout bodies, crossings. */\n occupied?: OccupiedSpan[] | null;\n /** Authored joint positions, inches along the run. Absent = derive. */\n cuts?: number[] | null;\n}): FlexPiece[] {\n const lo = Math.min(input.fromPos, input.toPos);\n const hi = Math.max(input.fromPos, input.toPos);\n if (!(hi - lo > FLEX_EPS)) return [];\n const max = input.maxPieceInches > FLEX_EPS ? input.maxPieceInches : Infinity;\n\n // The run minus the parts sitting in it. Overlapping bodies are merged first\n // so a crossover's two turnouts don't carve the same inch twice.\n const blocks = (input.occupied ?? [])\n .map((s) => ({\n from: Math.max(lo, Math.min(s.fromPos, s.toPos)),\n to: Math.min(hi, Math.max(s.fromPos, s.toPos)),\n }))\n // Zero-length spans are KEPT — they're breaks at a point of unknown extent\n // (a crossing), and they still end one piece and start the next.\n .filter((s) => s.to - s.from >= -FLEX_EPS && s.from < hi + FLEX_EPS && s.to > lo - FLEX_EPS)\n .sort((a, b) => a.from - b.from);\n const merged: { from: number; to: number }[] = [];\n for (const b of blocks) {\n const last = merged[merged.length - 1];\n if (last && b.from <= last.to + FLEX_EPS) last.to = Math.max(last.to, b.to);\n else merged.push({ ...b });\n }\n const gaps: { from: number; to: number }[] = [];\n let cursor = lo;\n for (const b of merged) {\n if (b.from - cursor > FLEX_EPS) gaps.push({ from: cursor, to: b.from });\n cursor = Math.max(cursor, b.to);\n }\n if (hi - cursor > FLEX_EPS) gaps.push({ from: cursor, to: hi });\n\n const authored = input.cuts != null;\n const out: FlexPiece[] = [];\n for (const g of gaps) {\n // Where this gap gets cut. Authored cuts inside it win outright; otherwise\n // full lengths from its start, remainder at the end.\n let inner: number[];\n if (authored) {\n inner = [...new Set(input.cuts!)]\n .filter((c) => c > g.from + FLEX_EPS && c < g.to - FLEX_EPS)\n .sort((a, b) => a - b);\n } else {\n inner = [];\n for (let at = g.from + max; at < g.to - FLEX_EPS; at += max) inner.push(at);\n // A sliver at the end isn't a piece. Split the last two evenly instead —\n // both stay under the maximum, because together they're at most one full\n // length plus a sliver.\n const tail = g.to - (inner[inner.length - 1] ?? g.from);\n if (inner.length && tail < FLEX_MIN_PIECE_INCHES) {\n const start = inner.length >= 2 ? inner[inner.length - 2] : g.from;\n inner[inner.length - 1] = start + (g.to - start) / 2;\n }\n }\n const bounds = [g.from, ...inner, g.to];\n for (let i = 0; i < bounds.length - 1; i++) {\n const from = bounds[i];\n const to = bounds[i + 1];\n out.push({\n index: out.length,\n fromPos: from,\n toPos: to,\n lengthInches: to - from,\n overlong: to - from > max + FLEX_EPS,\n // The run's own ends are runEnd; anything else is a part body, except\n // where a cut put a neighbouring piece there.\n fromEnd: i > 0 ? \"piece\" : from <= lo + FLEX_EPS ? \"runEnd\" : \"part\",\n toEnd:\n i < bounds.length - 2 ? \"piece\" : to >= hi - FLEX_EPS ? \"runEnd\" : \"part\",\n });\n }\n }\n return out;\n}\n\n/**\n * Which way a turnout faces along its host track: `+1` = its points look toward\n * increasing pos, `-1` = the other way.\n *\n * ⭐ ONE definition. The canvas had this inline for drawing the leg, and the\n * flex solver needs the same answer to know which side of `pos` the moulding\n * extends — a turnout's body is NOT symmetric about its points (an Atlas #7 is\n * about 0.9″ behind them and 5.1″ ahead), so getting the facing wrong moves a\n * rail joint four inches (#193).\n *\n * The rule: the turnout faces the way its diverging track LEAVES, because that's\n * where the frog is. `flipped` is the owner's override — rotating the part 180°\n * faces the points the other way, which is the only thing that can be right for\n * a siding pinned at a module end where the geometry reads ambiguously.\n *\n * `divergeFarPos` is whatever the caller can measure best: the canvas projects\n * the diverging track's real far end back onto the main, the editor uses its\n * authored extent. Same rule either way; only the precision of the input differs.\n */\nexport function turnoutFacing(input: {\n pos: number;\n /** Where the diverging track ends up, in the same coordinate as `pos`. */\n divergeFarPos?: number | null;\n flipped?: boolean;\n}): 1 | -1 {\n const far = input.divergeFarPos;\n const geometric =\n typeof far === \"number\" && Number.isFinite(far)\n ? (Math.sign(far - input.pos) as 1 | -1 | 0) || 1\n : 1;\n return (input.flipped ? -geometric : geometric) as 1 | -1;\n}\n\n/**\n * The stretch of its host run a turnout's moulding occupies (#193) — what flex\n * track has to stop short of on each side.\n *\n * Null when the part hasn't been measured, exactly as {@link partExtent} is:\n * without a real length we don't know where the moulding stops, and a guessed\n * body would put a rail joint on track nobody has checked.\n */\nexport function turnoutOccupiedSpan(input: {\n pos: number;\n extent: PartExtent | null | undefined;\n facing: 1 | -1;\n}): OccupiedSpan | null {\n const e = input.extent;\n if (!e) return null;\n // ⭐⭐ ANCHORED ON THE FROG, because that is what a document's `pos` is (Will,\n // 2026-07-27). This read `behindPoints`/`aheadOfPoints`, which put the whole\n // moulding `lead` too far along the run — 3.59″ on an Atlas #7 — so the flex\n // was cut to stop where the turnout was not.\n const a = input.pos - input.facing * e.behindFrog;\n const b = input.pos + input.facing * e.pastFrog;\n return { fromPos: Math.min(a, b), toPos: Math.max(a, b) };\n}\n\n/**\n * Retype one piece's length: move the rail joint at its far end, and let its\n * NEIGHBOUR take up the difference (#193).\n *\n * That's what cutting one piece longer actually does — the run doesn't grow, so\n * the next piece gets shorter by the same amount. The pair's total is fixed,\n * which is why the value is clamped to it: without that, asking for a length\n * past the next joint silently reorders the cuts and you get back something you\n * didn't ask for.\n *\n * Returns the run's COMPLETE new cut list (`flexCuts`), or null when the piece\n * has no neighbour to trade with — the last piece in a gap butts a turnout or\n * the endplate, and its length is set by what it meets, not by preference.\n */\nexport function resizeFlexPiece(\n pieces: FlexPiece[],\n index: number,\n nextLengthInches: number,\n): number[] | null {\n const piece = pieces[index];\n const next = pieces[index + 1];\n if (!piece || !next) return null;\n if (piece.toEnd !== \"piece\") return null; // butts a part or the run's end\n if (!Number.isFinite(nextLengthInches)) return null;\n const pair = piece.lengthInches + next.lengthInches;\n if (pair < 2 * FLEX_MIN_PIECE_INCHES) return null;\n const want = Math.max(\n FLEX_MIN_PIECE_INCHES,\n Math.min(pair - FLEX_MIN_PIECE_INCHES, nextLengthInches),\n );\n const moved = piece.fromPos + want;\n return pieces\n .filter((p) => p.toEnd === \"piece\")\n .map((p) => (p.index === index ? moved : p.toPos))\n .map((v) => Math.round(v * 1000) / 1000)\n .sort((a, b) => a - b);\n}\n\n/** What a run costs in flex, for someone about to order it (#193). */\nexport function flexUsage(pieces: FlexPiece[]): {\n /** How many separate lengths have to be cut. */\n pieces: number;\n /** Total flex laid, inches — the run minus whatever the parts occupy. */\n totalInches: number;\n /** Pieces the product can't actually supply in one length. */\n overlong: number;\n} {\n return {\n pieces: pieces.length,\n totalInches: pieces.reduce((a, p) => a + p.lengthInches, 0),\n overlong: pieces.filter((p) => p.overlong).length,\n };\n}\n\n/** Half an N-scale tie, inches — a 8′6″ tie is 102″ prototype, /160 ≈ 0.638″.\n * The half-width a tie strip extends either side of the rail it carries, which\n * is what gives a drawn turnout body its width. */\nexport const TIE_HALF_LENGTH_INCHES = 0.319;\n\n/** Where a turnout part physically starts and stops, relative to its POINTS.\n * All inches; `aheadOfPoints` is the end of the tie strip, which is essentially\n * where the diverging rail stops and the owner's flex track begins. */\nexport interface PartExtent {\n /** Points → the near end of the tie strip. Positive = the strip starts this\n * far BEHIND the points (it always does — that end is plain approach track). */\n behindPoints: number;\n /** Points → the far end of the tie strip. */\n aheadOfPoints: number;\n /** Frog → the far end. How much turnout there still is past the frog. */\n pastFrog: number;\n /**\n * Frog → the NEAR end of the tie strip.\n *\n * ⭐⭐ **THIS IS THE ONE A BODY IS MEASURED BACK FROM.** A document's `pos` is\n * the FROG (Will, 2026-07-27), so a turnout occupies\n * `[pos − behindFrog, pos + pastFrog]`. Anchoring on the points instead put\n * every turnout body `lead` too far along — 3.59″ on an Atlas #7.\n *\n * ⚠️ Falls back to `behindPoints` when the frog was never measured: without a\n * frog reading there is nowhere to anchor, and the points is the only landmark\n * left. `pastFrog` degrades the same way, so the pair stays consistent.\n */\n behindFrog: number;\n}\n\n/**\n * A part's real extent, or **null when it hasn't been measured**.\n *\n * ⚠️ This deliberately does NOT fall back to a frog-number rule, unlike\n * {@link leadInchesForSize}. Overall length is not a function of N — the #5 and\n * the #7 are BOTH 6.00″, same tie strip, different frog. Angle is geometry;\n * length is packaging, and packaging can only be looked up. A renderer that\n * gets null should draw no part boundary rather than invent one: the absence is\n * a truthful signal that the library has a gap, and inventing a length here is\n * how hand-built geometry once reached owners as if it were part data.\n *\n * Requires `pointsOffset` and `overallLength`; `pastFrog` additionally needs\n * `frogOffset`. Every dimension must be `measured` — a derived one would launder\n * a guess into a drawing that says \"this is where your turnout ends\".\n */\nexport function partExtent(part: TrackPart | null | undefined): PartExtent | null {\n const pts = part?.pointsOffset;\n const overall = part?.overallLength;\n if (!pts || !overall) return null;\n if (pts.source !== \"measured\" || overall.source !== \"measured\") return null;\n const frog = part?.frogOffset;\n const aheadOfPoints = overall.inches - pts.inches;\n const frogMeasured = frog && frog.source === \"measured\";\n return {\n behindPoints: pts.inches,\n aheadOfPoints,\n pastFrog: frogMeasured ? overall.inches - frog.inches : aheadOfPoints,\n behindFrog: frogMeasured ? frog.inches : pts.inches,\n };\n}\n\n/** The extent of the part a turnout of this frog number IS, or null when no\n * measured part matches EXACTLY. A #6 is not a #5 or a #7 — the nearest part's\n * length says nothing about it (see {@link partExtent}). */\nexport function partExtentForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): PartExtent | null {\n const part = turnoutPartForSize(size, library);\n return part && part.frogNumber === size ? partExtent(part) : null;\n}\n\n/**\n * The closest built-in turnout for a frog number — what a bare `size` maps to\n * when a turnout names no part. Exact match wins; otherwise the nearest frog.\n *\n * ⚠️ TIES ARE BROKEN TOWARD A PART WE CAN ACTUALLY DRAW. Two parts can share a\n * frog number — Atlas sell a #5 and Fast Tracks make a #5 fixture — and only one\n * of them may carry the measured offsets {@link partExtent} needs. Picking by\n * frog number alone would let a part with no geometry win on array order and\n * take the other's body away with it, which is the #193 failure (a turnout that\n * claims no extent has flex drawn straight through it). So: nearest frog first,\n * and among equals, one with a real extent.\n */\nexport function turnoutPartForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): TrackPart | null {\n // ⛔ A PROVISIONAL PART IS NEVER WHAT A BARE `#N` MEANS. It is a stand-in an\n // owner chooses; adopting one here would answer a question nobody asked.\n const turnouts = library.filter(\n (p) => p.kind === \"turnout\" && p.frogNumber != null && !p.provisional,\n );\n if (!turnouts.length) return null;\n const dist = (p: TrackPart) => Math.abs((p.frogNumber as number) - size);\n return turnouts.reduce((best, p) => {\n const d = dist(p);\n const bd = dist(best);\n if (d !== bd) return d < bd ? p : best;\n // Same frog number: prefer the one that can be drawn at its real size.\n if (!partExtent(best) && partExtent(p)) return p;\n return best;\n });\n}\n\n/** Measured leads, ascending by frog number — the interpolation basis. Only\n * `measured` counts: interpolating through a derived value would launder a guess\n * into the sizes either side of it. */\nfunction measuredLeadPoints(library: TrackPart[]): Array<{ n: number; lead: number }> {\n return library\n .filter(\n (p) =>\n p.kind === \"turnout\" &&\n p.frogNumber != null &&\n p.lead?.source === \"measured\" &&\n !p.provisional,\n )\n .map((p) => ({ n: p.frogNumber as number, lead: p.lead!.inches }))\n .sort((a, b) => a.n - b.n);\n}\n\n/**\n * The lead to draw a turnout of this size with. Keeps `frogLegOf` honest without\n * it needing to know the library exists.\n *\n * 1. An exact part match wins — a #7's measurement says nothing about a #4.\n * 2. Otherwise INTERPOLATE piecewise-linearly across the measured parts. This\n * replaced `size × TURNOUT_LEAD_INCHES_PER_FROG`, which was refuted (its\n * error changes sign across the measured range) and is now baseless besides,\n * its founding #7 measurement having been superseded.\n * 3. ⚠️ Outside the measured range the end segments EXTRAPOLATE. Measured leads\n * span N = 5…10, so a #4 or #12 is a projection, not a reading, and the #2.5\n * wye is a long way out. Treat those as placeholders until a part is measured.\n */\nexport function leadInchesForSize(size: number, library = BUILT_IN_TRACK_PARTS): number {\n // An exact part match wins — but it has to be an exact part that HAS a lead.\n // Several makers can sell the same frog number and only some publish a lead:\n // Fast Tracks state an angle and a radius and no landmarks at all, so asking\n // `turnoutPartForSize` for \"the #6\" and reading its (absent) lead would skip\n // straight past an Atlas #6 that had one. Search for the dimension, not the\n // part.\n const exact = library.find(\n (p) => p.kind === \"turnout\" && p.frogNumber === size && p.lead != null && !p.provisional,\n );\n if (exact) return exact.lead!.inches;\n\n const pts = measuredLeadPoints(library);\n if (!pts.length) return size * TURNOUT_LEAD_INCHES_PER_FROG;\n // One measurement can only be scaled; that IS the refuted rule, so say so.\n if (pts.length === 1) return (size / pts[0].n) * pts[0].lead;\n\n let i: number;\n if (size >= pts[pts.length - 1].n) i = pts.length - 2;\n else i = Math.max(0, pts.findIndex((p) => p.n >= size) - 1);\n const lo = pts[i];\n const hi = pts[i + 1];\n const t = (size - lo.n) / (hi.n - lo.n);\n return lo.lead + t * (hi.lead - lo.lead);\n}\n\n/**\n * How far a turnout of this size keeps going PAST its frog — the rest of the\n * moulding, after which the owner's flex track begins.\n *\n * The companion to {@link leadInchesForSize}, and it follows the same rule: an\n * exact measured part wins, otherwise interpolate across the measured ones. Both\n * numbers describe *how long to draw a turnout*, which is a question that always\n * has to be answered — you cannot draw nothing — so a reasoned interpolation is\n * the honest floor, and it is a far better answer than the alternative it\n * replaced (running the diverging route until it arrived parallel with the track\n * it fed, which was 10.79″ on a 6.00″ part).\n *\n * ⚠️ Do NOT confuse this with {@link partExtent}, which returns null rather than\n * guess. The difference is what is being claimed. `partExtent` says \"THIS part\n * stops HERE\" — a statement about a specific product, which may only be made\n * from a measurement. This says \"a turnout of about this frog number runs about\n * this far past its frog\", which is a drawing approximation and is labelled as\n * one: renderers draw the part's boundary only where {@link partExtent} answers.\n */\nexport function pastFrogInchesForSize(\n size: number,\n library = BUILT_IN_TRACK_PARTS,\n): number {\n const measured = library\n .filter((p) => p.kind === \"turnout\" && p.frogNumber != null)\n .map((p) => ({ n: p.frogNumber as number, ext: partExtent(p) }))\n .filter((p): p is { n: number; ext: PartExtent } => p.ext != null)\n .map((p) => ({ n: p.n, past: p.ext.pastFrog }))\n .sort((a, b) => a.n - b.n);\n\n // Nothing measured at all: fall back to the frog angle itself. A turnout\n // whose rails have separated by about a gauge past the frog is short, but it\n // is bounded and it never claims a length nobody has checked.\n if (!measured.length) return RAIL_GAUGE_INCHES * size;\n if (measured.length === 1) return measured[0].past;\n\n let i: number;\n if (size >= measured[measured.length - 1].n) i = measured.length - 2;\n else i = Math.max(0, measured.findIndex((p) => p.n >= size) - 1);\n const lo = measured[i];\n const hi = measured[i + 1];\n const t = (size - lo.n) / (hi.n - lo.n);\n return Math.max(0, lo.past + t * (hi.past - lo.past));\n}\n\n/** One drawn piece of a part's geometry, in the part's own local frame. */\nexport type PartSegment =\n | { kind: \"straight\"; x0: number; y0: number; x1: number; y1: number }\n | {\n kind: \"curve\";\n radius: number;\n cx: number;\n cy: number;\n startDeg: number;\n extentDeg: number;\n };\n\n/** A connection point on an imported part: position plus the tangent it faces. */\nexport interface PartEnd {\n x: number;\n y: number;\n angleDeg: number;\n}\n\nexport interface ImportedPart {\n /** Raw title, tab-separated in the file: manufacturer, name, part number. */\n title: string;\n manufacturer?: string;\n name?: string;\n partNumber?: string;\n scale?: string;\n ends: PartEnd[];\n segments: PartSegment[];\n}\n\n/**\n * Parse an XTrkCAD `.xtp` parameter file into parts.\n *\n * The format is plain text, record-per-line inside `TURNOUT … END` blocks:\n * `E x y angle` an endpoint\n * `S layer width x0 y0 x1 y1` a straight segment\n * `C layer width radius cx cy a0 ext` a curved segment (radius signed by hand)\n *\n * We parse an owner's OWN file — nothing from XTrkCAD is redistributed. Their\n * geometry is taken as authoritative for part OUTLINES; ⚠️ don't infer frog\n * positions from it, the shipped Atlas file is internally inconsistent (it puts\n * the #5's frog further out than the #7's, which is physically impossible).\n */\nexport function parseXtpLibrary(text: string): ImportedPart[] {\n const parts: ImportedPart[] = [];\n let cur: ImportedPart | null = null;\n for (const raw of text.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n if (line.startsWith(\"TURNOUT\")) {\n // TURNOUT <scale> \"<manufacturer>\\t<name>\\t<part no.>\"\n const quoted = line.match(/\"([^\"]*)\"/);\n const scale = line.split(/\\s+/)[1];\n const title = quoted?.[1] ?? \"\";\n const bits = title.split(\"\\t\").map((s) => s.trim()).filter(Boolean);\n cur = {\n title,\n scale,\n manufacturer: bits[0],\n name: bits[1],\n partNumber: bits[2],\n ends: [],\n segments: [],\n };\n continue;\n }\n if (!cur) continue;\n if (line === \"END\") {\n if (cur.ends.length || cur.segments.length) parts.push(cur);\n cur = null;\n continue;\n }\n const n = line.split(/\\s+/);\n const num = (i: number) => Number(n[i]);\n if (n[0] === \"E\" && n.length >= 4) {\n cur.ends.push({ x: num(1), y: num(2), angleDeg: num(3) });\n } else if (n[0] === \"S\" && n.length >= 7) {\n cur.segments.push({ kind: \"straight\", x0: num(3), y0: num(4), x1: num(5), y1: num(6) });\n } else if (n[0] === \"C\" && n.length >= 8) {\n cur.segments.push({\n kind: \"curve\",\n radius: num(3),\n cx: num(4),\n cy: num(5),\n startDeg: num(6),\n extentDeg: num(7),\n });\n }\n }\n return parts;\n}\n\n/** Sample an imported part's segments into polylines, in the part's own frame —\n * XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is\n * `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */\nexport function samplePartSegments(\n segments: PartSegment[],\n stepsPerCurve = 16,\n): BenchworkPoint[][] {\n return segments.map((s) => {\n if (s.kind === \"straight\") {\n return [\n { x: s.x0, y: s.y0 },\n { x: s.x1, y: s.y1 },\n ];\n }\n const r = Math.abs(s.radius);\n const out: BenchworkPoint[] = [];\n for (let i = 0; i <= stepsPerCurve; i++) {\n const a = ((s.startDeg + (s.extentDeg * i) / stepsPerCurve) * Math.PI) / 180;\n out.push({ x: s.cx + r * Math.sin(a), y: s.cy + r * Math.cos(a) });\n }\n return out;\n });\n}\n\n/** Signed difference between two XTrkCAD headings, normalised to (-180, 180]. */\nfunction angleDeltaDeg(a: number, b: number): number {\n let d = ((a - b) % 360 + 540) % 360 - 180;\n if (d === -180) d = 180;\n return d;\n}\n\n/** Pull a frog number out of a part name — \"#5\", \"No. 5\", \"Number 7 Left\".\n * Identification, not measurement: it reads the label the maker printed. */\nexport function frogNumberFromName(name: string | undefined): number | undefined {\n if (!name) return undefined;\n const m = name.match(/(?:#|no\\.?\\s*|number\\s+)(\\d+(?:\\.\\d+)?)/i);\n if (!m) return undefined;\n const n = Number(m[1]);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nfunction importedKind(name: string | undefined): TrackPart[\"kind\"] {\n const s = (name ?? \"\").toLowerCase();\n if (s.includes(\"wye\")) return \"wye\";\n if (s.includes(\"crossing\")) return \"crossing\";\n if (s.includes(\"curved\")) return \"curved-turnout\";\n return \"turnout\";\n}\n\nconst slug = (s: string) =>\n s.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\");\n\n/**\n * Convert a parsed `.xtp` part into a library {@link TrackPart}.\n *\n * ⚠️⚠️ **DELIBERATELY DERIVES NO `lead` AND NO `frogOffset`.** The shipped Atlas\n * file's frog positions are internally inconsistent — it puts the #5's frog\n * FURTHER OUT than the #7's, which cannot be true of physical parts. Every lead\n * in this library is a physical measurement and must stay that way; an imported\n * lead would silently outrank {@link leadInchesForSize}'s interpolation across\n * those measurements, which is exactly the wrong trade.\n *\n * What IS taken: identity (manufacturer, name, part number, frog number), the\n * drawn `segments` and `ends`, and two dimensions the geometry states directly —\n * overall length along the through axis, and the actual divergence angle. Both\n * land as `unverified`, because a community CAD file is not a measurement.\n */\nexport function importedPartToTrackPart(\n part: ImportedPart,\n sourceName = \"imported .xtp\",\n): TrackPart {\n const name = part.name ?? part.title ?? \"Imported part\";\n const manufacturer = part.manufacturer ?? \"Unknown\";\n const note = `from ${sourceName} — community CAD data, not a measurement`;\n const out: TrackPart = {\n id: `xtp-${slug(manufacturer)}-${slug(part.partNumber || name)}`,\n manufacturer,\n name,\n line: \"\",\n scale: \"N\",\n kind: importedKind(name),\n frogNumber: frogNumberFromName(name),\n segments: part.segments,\n ends: part.ends,\n importedFrom: sourceName,\n };\n if (part.partNumber) out.partNumbers = { single: part.partNumber };\n\n const ends = part.ends;\n if (ends.length >= 2) {\n // Span along the axis the part faces at its first end. XTrkCAD headings run\n // CLOCKWISE FROM NORTH, so the unit vector is (sin, cos).\n const a = (ends[0].angleDeg * Math.PI) / 180;\n const ux = Math.sin(a);\n const uy = Math.cos(a);\n const proj = ends.map((e) => (e.x - ends[0].x) * ux + (e.y - ends[0].y) * uy);\n const span = Math.max(...proj) - Math.min(...proj);\n if (span > 0) out.overallLength = { inches: span, source: \"unverified\", note };\n }\n if (ends.length >= 3) {\n // The through end faces opposite the points end; the other one diverges, and\n // the gap between their headings IS the frog angle.\n const rest = ends.slice(1);\n const opposite = rest\n .map((e) => ({ e, off: Math.abs(angleDeltaDeg(e.angleDeg, ends[0].angleDeg + 180)) }))\n .sort((p, q) => p.off - q.off);\n const through = opposite[0].e;\n const diverging = opposite[opposite.length - 1].e;\n const deg = Math.abs(angleDeltaDeg(diverging.angleDeg, through.angleDeg));\n if (deg > 0.01) out.actualAngle = { deg, source: \"unverified\", note };\n }\n return out;\n}\n\n/**\n * A part as an application stores it — one flat row, so the package needs to\n * know nothing about any particular database. Dimensions are plain numbers with\n * a `source` beside each, mirroring {@link PartDimension}.\n */\nexport interface StoredTrackPart {\n slug: string;\n manufacturer: string;\n line: string;\n scale?: string | null;\n name: string;\n kind?: string | null;\n partNumberLeft?: string | null;\n partNumberRight?: string | null;\n partNumberSingle?: string | null;\n frogNumber?: number | null;\n pointsOffsetInches?: number | null;\n pointsOffsetSource?: string | null;\n frogOffsetInches?: number | null;\n frogOffsetSource?: string | null;\n overallLengthInches?: number | null;\n overallLengthSource?: string | null;\n divergingLengthInches?: number | null;\n divergingLengthSource?: string | null;\n minimumLengthInches?: number | null;\n minimumLengthSource?: string | null;\n substitutionRadiusInches?: number | null;\n substitutionRadiusSource?: string | null;\n trackSpacingInches?: number | null;\n trackSpacingSource?: string | null;\n secondaryFrogAngleDeg?: number | null;\n secondaryFrogAngleSource?: string | null;\n buildable?: boolean | null;\n piecesPerAssembly?: number | null;\n leadInches?: number | null;\n leadSource?: string | null;\n outerRadiusInches?: number | null;\n innerRadiusInches?: number | null;\n radiusSource?: string | null;\n /** Sectional curve: its single radius, and how far it turns. */\n radiusInches?: number | null;\n arcDegrees?: number | null;\n actualAngleDeg?: number | null;\n actualAngleSource?: string | null;\n measurementNote?: string | null;\n}\n\nconst asSource = (s: string | null | undefined): DimensionSource =>\n s === \"manufacturer\" || s === \"measured\" || s === \"derived\" ? s : \"unverified\";\n\n/**\n * Convert a stored row into a {@link TrackPart}.\n *\n * The LEAD is derived from the two offsets whenever both are present, rather\n * than read from its own column: they're measured from the same tie end, so\n * their difference is the lead by construction, and a separately-entered lead\n * could silently disagree with the positions it's supposed to summarise. A\n * stored `leadInches` is used only for a part whose offsets aren't known.\n */\nexport function storedPartToTrackPart(row: StoredTrackPart): TrackPart {\n const note = row.measurementNote ?? undefined;\n const dim = (\n inches: number | null | undefined,\n source: string | null | undefined,\n ): PartDimension | undefined =>\n typeof inches === \"number\" && Number.isFinite(inches)\n ? { inches, source: asSource(source), ...(note ? { note } : {}) }\n : undefined;\n\n const points = dim(row.pointsOffsetInches, row.pointsOffsetSource);\n const frog = dim(row.frogOffsetInches, row.frogOffsetSource);\n // Both offsets ⇒ the lead is their difference, and it is only as good as the\n // weaker of the two readings.\n const lead: PartDimension | undefined =\n points && frog\n ? {\n inches: frog.inches - points.inches,\n source:\n points.source === \"measured\" && frog.source === \"measured\"\n ? \"measured\"\n : \"derived\",\n ...(note ? { note } : {}),\n }\n : dim(row.leadInches, row.leadSource);\n\n // ⚠️ EVERY KIND, not a hand-picked few. This allow-list had three entries and\n // silently turned everything else into a TURNOUT — so a stored crossover,\n // flex, bumper or sectional piece came back claiming to be a turnout and was\n // then blocked for having no points offset, blaming a measurement that was\n // never going to exist. Kinds are added to the type often enough that the\n // list has to live next to it.\n const kind = TRACK_PART_KINDS.includes(row.kind as TrackPart[\"kind\"])\n ? (row.kind as TrackPart[\"kind\"])\n : \"turnout\";\n const part: TrackPart = {\n id: row.slug,\n manufacturer: row.manufacturer,\n line: row.line,\n scale: \"N\",\n name: row.name,\n kind,\n };\n const numbers = {\n ...(row.partNumberLeft ? { left: row.partNumberLeft } : {}),\n ...(row.partNumberRight ? { right: row.partNumberRight } : {}),\n ...(row.partNumberSingle ? { single: row.partNumberSingle } : {}),\n };\n if (Object.keys(numbers).length) part.partNumbers = numbers;\n if (typeof row.frogNumber === \"number\") part.frogNumber = row.frogNumber;\n if (points) part.pointsOffset = points;\n if (frog) part.frogOffset = frog;\n const overall = dim(row.overallLengthInches, row.overallLengthSource);\n if (overall) part.overallLength = overall;\n const diverging = dim(row.divergingLengthInches, row.divergingLengthSource);\n if (diverging) part.divergingLength = diverging;\n const minimum = dim(row.minimumLengthInches, row.minimumLengthSource);\n if (minimum) part.minimumLength = minimum;\n const substitution = dim(row.substitutionRadiusInches, row.substitutionRadiusSource);\n if (substitution) part.substitutionRadius = substitution;\n const spacing = dim(row.trackSpacingInches, row.trackSpacingSource);\n if (spacing) part.trackSpacing = spacing;\n if (typeof row.secondaryFrogAngleDeg === \"number\")\n part.secondaryFrogAngle = {\n deg: row.secondaryFrogAngleDeg,\n source: asSource(row.secondaryFrogAngleSource),\n ...(note ? { note } : {}),\n };\n if (row.buildable) part.buildable = true;\n if (typeof row.piecesPerAssembly === \"number\" && row.piecesPerAssembly > 1)\n part.piecesPerAssembly = row.piecesPerAssembly;\n if (lead) part.lead = lead;\n const outer = dim(row.outerRadiusInches, row.radiusSource);\n const inner = dim(row.innerRadiusInches, row.radiusSource);\n if (outer) part.outerRadius = outer;\n if (inner) part.innerRadius = inner;\n // ⚠️ A SECTIONAL CURVE'S OWN RADIUS, not one of a curved turnout's pair.\n // Without this an admin could enter a curve's radius and arc and the part\n // would still come back unplaceable, with the palette blaming a missing\n // radius that had just been typed in.\n const radius = dim(row.radiusInches, row.radiusSource);\n if (radius) part.radius = radius;\n if (typeof row.arcDegrees === \"number\") part.arcDegrees = row.arcDegrees;\n if (typeof row.actualAngleDeg === \"number\")\n part.actualAngle = {\n deg: row.actualAngleDeg,\n source: asSource(row.actualAngleSource),\n ...(note ? { note } : {}),\n };\n return part;\n}\n\n/**\n * Fold an application's STORED library over the built-in one, by slug.\n *\n * ⚠️ Unlike {@link mergeImportedParts}, a stored part **replaces** a built-in\n * outright. That difference is deliberate, and the reason is who is speaking: an\n * import is a third-party file that may have been fitted in someone else's CAD\n * program, so it may only fill gaps. The stored library is seeded FROM these\n * built-ins and edited by an admin with the part in their hand — it is the same\n * library, later. Refusing their correction would mean a wrong dimension could\n * only be fixed by shipping a release, which is exactly the limitation the\n * stored library exists to remove.\n *\n * The built-ins remain the floor: a part nobody has stored still resolves, so\n * geometry keeps working with no database at all.\n *\n * ⛔ THE TRAP THIS CREATES, and it has already been sprung once. Replacement is\n * WHOLESALE, so a stored row that is merely INCOMPLETE deletes every dimension\n * the built-in had. When both Atlas wyes were measured in 0.78.0 their stored\n * rows still held null offsets from the original seed — so in production the\n * new measurements were invisible and the 2056 still carried a `derived` lead\n * the release had just retired. Nothing failed; the parts simply had no\n * dimensions, which is indistinguishable from never having measured them.\n *\n * **Measuring a built-in is therefore not finished until the stored row is\n * updated too.** Adding a dimension here and stopping ships nothing.\n */\nexport function mergeStoredParts(\n stored: StoredTrackPart[],\n library: TrackPart[] = BUILT_IN_TRACK_PARTS,\n): TrackPart[] {\n const bySlug = new Map(library.map((p) => [p.id, p]));\n for (const row of stored) bySlug.set(row.slug, storedPartToTrackPart(row));\n return [...bySlug.values()];\n}\n\n/**\n * Fold imported parts into a library.\n *\n * **Imports never overwrite. Ever.** They may only fill a gap — attach geometry\n * a built-in lacks, or add a part we have no entry for. A dimension already\n * present wins regardless of its source, because our worst built-in value is at\n * least one we can trace, and this library has already been burned once by a\n * plausible number from a CAD file (the constant-switch-angle model was fitted\n * to an `.xtp` figure that turned out to be measured to the wrong landmark).\n *\n * Matching is by manufacturer part number first, then manufacturer + frog number.\n */\nexport function mergeImportedParts(\n imported: ImportedPart[],\n library: TrackPart[] = BUILT_IN_TRACK_PARTS,\n sourceName = \"imported .xtp\",\n): TrackPart[] {\n const out = library.map((p) => ({ ...p }));\n const numbersOf = (p: TrackPart) =>\n [p.partNumbers?.left, p.partNumbers?.right, p.partNumbers?.single]\n .filter(Boolean)\n .map((s) => (s as string).trim().toLowerCase());\n\n for (const raw of imported) {\n const conv = importedPartToTrackPart(raw, sourceName);\n const pn = raw.partNumber?.trim().toLowerCase();\n const match =\n (pn ? out.find((p) => numbersOf(p).includes(pn)) : undefined) ??\n (conv.frogNumber != null\n ? out.find(\n (p) =>\n p.frogNumber === conv.frogNumber &&\n p.kind === conv.kind &&\n p.manufacturer.toLowerCase() === conv.manufacturer.toLowerCase(),\n )\n : undefined);\n\n if (!match) {\n out.push(conv);\n continue;\n }\n // Geometry is the point of importing — take it when we have none.\n if (!match.segments?.length && conv.segments?.length) match.segments = conv.segments;\n if (!match.ends?.length && conv.ends?.length) match.ends = conv.ends;\n if (!match.importedFrom && (conv.segments?.length || conv.ends?.length)) {\n match.importedFrom = sourceName;\n }\n if (!match.overallLength && conv.overallLength) match.overallLength = conv.overallLength;\n if (!match.actualAngle && conv.actualAngle) match.actualAngle = conv.actualAngle;\n }\n return out;\n}\n\n/**\n * A part's drawn outline in TURNOUT-LOCAL coordinates, ready for MR to map onto\n * a lane: `x` = inches along the through route measured **from the frog**\n * (negative back toward the points), `y` = lateral offset with the DIVERGING\n * side positive. That is the same frame {@link turnoutClosure} works in, so a\n * renderer can swap one for the other.\n *\n * ⚠️ **Anchored on OUR measured lead, not the file's frog.** The part is placed\n * so its points sit `leadInches` back from the frog, because `pos` means the\n * frog (#132) and our leads are physical measurements while the shipped Atlas\n * `.xtp`'s frog positions are internally inconsistent. A consequence worth\n * knowing: if the file's own geometry disagrees, its drawn V will not land on\n * the frog marker — and that visible gap IS the validation. Don't \"fix\" it by\n * anchoring on the file.\n *\n * Returns null when the part carries no geometry to draw.\n */\nexport function partOutlineAtFrog(\n part: TrackPart,\n leadInches: number,\n stepsPerCurve = 16,\n): BenchworkPoint[][] | null {\n const ends = part.ends ?? [];\n const segs = part.segments ?? [];\n if (!segs.length || ends.length < 2) return null;\n\n // The two EXIT ends sit close together at the far end; the points end is the\n // odd one out. More robust than assuming the file lists points first.\n let points = ends[0];\n if (ends.length >= 3) {\n let bestPair = Infinity;\n let pairIdx: [number, number] = [1, 2];\n for (let i = 0; i < ends.length; i++) {\n for (let j = i + 1; j < ends.length; j++) {\n const d = Math.hypot(ends[i].x - ends[j].x, ends[i].y - ends[j].y);\n if (d < bestPair) {\n bestPair = d;\n pairIdx = [i, j];\n }\n }\n }\n const odd = ends.findIndex((_, k) => k !== pairIdx[0] && k !== pairIdx[1]);\n if (odd >= 0) points = ends[odd];\n }\n\n // Ends face OUTWARD, so the through direction is the inward normal. XTrkCAD\n // headings run clockwise from north ⇒ the heading vector is (sin, cos).\n const a = (points.angleDeg * Math.PI) / 180;\n const ux = -Math.sin(a);\n const uy = -Math.cos(a);\n // Left-perpendicular, so `y` is a consistent lateral before we fix its sign.\n const toLocal = (p: BenchworkPoint): BenchworkPoint => {\n const dx = p.x - points.x;\n const dy = p.y - points.y;\n return { x: dx * ux + dy * uy, y: dx * -uy + dy * ux };\n };\n\n // Whichever exit end is off-axis is the diverging one; flip so it reads +y.\n let sign = 1;\n const offAxis = ends\n .filter((e) => e !== points)\n .map(toLocal)\n .sort((p, q) => Math.abs(q.y) - Math.abs(p.y))[0];\n if (offAxis && offAxis.y < 0) sign = -1;\n\n return samplePartSegments(segs, stepsPerCurve).map((poly) =>\n poly.map((p) => {\n const l = toLocal(p);\n return { x: l.x - leadInches, y: l.y * sign };\n }),\n );\n}\n\n/** A turnout's CLOSURE — the diverging route's lateral offset from the through\n * route, from the points (s = 0) to the frog (s = lead) and beyond.\n *\n * Anchored on one geometric fact: the FROG is where the two routes' inner rails\n * cross, which happens where the centre-lines are exactly ONE GAUGE apart. So\n * `pos` (which means the frog, #132) must be where d = gauge — otherwise the\n * drawn crossing and the frog marker disagree.\n *\n * The curve is `d(s) = α·s + k·s²`, fixed by three conditions:\n * d(0) = 0 — the points start ON the stock rail\n * d(lead) = gauge — the frog lands exactly on `pos`\n * d'(lead) = 1/N — it leaves at the frog angle\n *\n * ⚠️ `α` is the SWITCH ANGLE and is deliberately non-zero. A curve leaving\n * TANGENT to the stock rail only reaches `lead/2N` of lateral by the frog\n * (0.24″ on a #7) — it could never reach a gauge within a commercial lead; you'd\n * need `lead = 2·gauge·N` ≈ the prototype figure. Real points leave the stock\n * rail at a finite angle, which is exactly why a commercial turnout can be\n * shorter than prototype. Valid while `lead < 2·gauge·N`; α is clamped at 0\n * otherwise so an absurd lead degrades to a tangent start instead of bending\n * backwards. */\nexport interface TurnoutClosure {\n /** Lateral offset from the through route at arc length `s` past the points. */\n offsetAt: (s: number) => number;\n /** Points→frog, inches. */\n lead: number;\n /** Slope at the points (the switch angle), rise over run. */\n switchSlope: number;\n /** Slope at and beyond the frog — the frog angle, 1/N. */\n frogSlope: number;\n /** Total run from the points to where the route arrives PARALLEL at\n * `arriveAtInches`. Infinity when no target was given (the legacy\n * straight-forever behaviour). Use this rather than solving for the offset:\n * solving finds where the route REACHES the lane, not where it arrives\n * parallel, and the difference is a visible kink. */\n span: number;\n /** Length of the easing curve, 0 when not easing. */\n easeInches: number;\n}\n\nexport function turnoutClosure(\n size: number,\n opts: {\n leadInches?: number;\n gaugeInches?: number;\n /**\n * Lateral offset the diverging route must ARRIVE AT, PARALLEL — normally\n * one lane spacing, i.e. the track it feeds.\n *\n * ⚠️ Without this the route runs straight at the frog angle forever, and a\n * caller can only solve for where it first REACHES the offset. Reaching is\n * not arriving: it gets there still climbing at 1/N while the track it\n * joins runs parallel, so the two meet with an instantaneous change of\n * direction. That KINK is what reads as \"the rails don't line up\" — each\n * rail is offset perpendicular to its own heading, so at a kink the two\n * rails meet at different points.\n */\n arriveAtInches?: number;\n /** Length of the easing curve. Defaults to one lead, which puts the radius\n * around 25″ on a #7 — clear of the Free-moN 22″ minimum. */\n easeInches?: number;\n } = {},\n): TurnoutClosure {\n const N = size > 0 ? size : 6;\n const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;\n const lead = Math.max(0.01, opts.leadInches ?? N * TURNOUT_LEAD_INCHES_PER_FROG);\n const frogSlope = 1 / N;\n const k = (lead / N - g) / (lead * lead);\n const switchSlope = Math.max(0, frogSlope - 2 * k * lead);\n\n // Post-frog profile. Straight at the frog angle for `a`, then ease the slope\n // from 1/N to ZERO over `b`, arriving parallel at the target.\n // straight gains m·a ease gains m·b/2 (parabolic, slope m → 0)\n const target = opts.arriveAtInches;\n let a = Infinity;\n let b = 0;\n if (target != null && target > g) {\n b = Math.max(0.01, opts.easeInches ?? lead);\n a = (target - g) / frogSlope - b / 2;\n if (a < 0) {\n // Too close to ease over a full lead — shorten the ease instead of\n // starting it before the frog, which would move the crossing.\n a = 0;\n b = (2 * (target - g)) / frogSlope;\n }\n }\n const span = target != null && target > g ? lead + a + b : Infinity;\n\n return {\n lead,\n switchSlope,\n frogSlope,\n span,\n easeInches: b,\n offsetAt: (s: number) => {\n if (s <= lead) return switchSlope * s + k * s * s;\n const past = s - lead;\n if (past <= a) return g + frogSlope * past;\n if (target == null) return g + frogSlope * past;\n const u = Math.min(past - a, b);\n // slope m at u=0 falling linearly to 0 at u=b\n const eased = g + frogSlope * a + frogSlope * u - (frogSlope * u * u) / (2 * b);\n return past - a >= b ? target : eased;\n },\n };\n}\n\n// ─── PIECE GEOMETRY (ADR 0001) ───────────────────────────────────────────────\n// A part's ENDS, in the part's own frame, so a piece graph has something to\n// snap. `PartEnd` already carried position and tangent for imported .xtp files;\n// what a graph also needs is WHICH end is which, and which ends a train can run\n// between. That is what this section derives, from measurements we already have.\n\n/** Which end of a part this is. A graph connects joints; a walk uses `routes`. */\nexport type PartJointRole =\n | \"throat\"\n | \"through\"\n | \"diverge\"\n | \"divergeB\"\n /** An end of one of the two parallel tracks THROUGH a crossover assembly.\n * A double crossover has four, and none of them is a throat: every end is\n * both a straight route and a crossing route, which is exactly why it is one\n * moulding and not four turnouts. */\n | \"crossoverEnd\";\n\n/** One end of a part, in part-local inches: `x` along the through route from\n * the tie end, `y` lateral toward the diverging side, `angleDeg` the OUTWARD\n * tangent (0 = +x). Named, unlike {@link PartEnd}, because a graph has to know\n * a throat from a frog. */\nexport interface PartJoint extends PartEnd {\n id: string;\n role: PartJointRole;\n}\n\nexport interface PartGeometry {\n joints: PartJoint[];\n /** Joint id pairs a train can run between. A turnout has two routes sharing\n * its throat; flex has one; a double crossover has four. */\n routes: [string, string][];\n /** The weakest provenance among the dimensions used — so a caller can tell a\n * placed-from-measurement part from a placed-from-a-catalogue-figure one. */\n source: DimensionSource;\n /** True when the diverging end came from a measured {@link\n * TrackPart.divergingLength} rather than from assuming the diverging rail\n * leaves the moulding at the same place the through route does. */\n divergingEndMeasured: boolean;\n}\n\n/**\n * A double crossover's geometry, every number of it PUBLISHED rather than\n * guessed — or null when the part does not carry them.\n *\n * ⭐⭐ **A DOUBLE CROSSOVER IS ONE ASSEMBLY, NOT FOUR TURNOUTS** (Will,\n * 2026-07-28). Modelling it as four independent turnout mouldings is what made a\n * rebuild of FMN-0078 collapse: two Atlas #7s 2.5″ apart overlap by 3.5″, so the\n * pieces intersected and the walk emitted a module nobody has. The real thing is\n * a single moulding whose four point-sets sit closer together than four separate\n * turnouts ever could — which is precisely why it is sold as one fixture.\n *\n * ⚠️ **ITS SPACING IS NOT A DEPARTURE FROM THE STANDARD.** Free-moN §2.0 fixes\n * {@link FREEMO_TRACK_SPACING_INCHES} **at the endplate** — \"double track\n * endplates must have a track spacing of 1.125 inches\", perpendicular, straight\n * and level for 4″ from the outside face. What the mains do in between is the\n * builder's business, and every real double crossover pinches them closer.\n *\n * The derivation:\n * - **Length** is `overallLength × piecesPerAssembly`. Fast Tracks' figure is\n * ONE HALF — the fixture builds a symmetrical half you make twice and butt\n * together after turning the second 180°.\n * - **The crossing run** `W = spacing / tan θ` is how far along the track a route\n * takes to cross to the other one. The two point-sets on the SAME track are\n * therefore `W` apart — 6.54″ for a #6 at 1.09″, not the 2.5″ my own FMN-0078\n * fixture claimed.\n * - Both crossing routes are centred on the assembly, so they meet in the middle\n * at `2θ` — which is exactly the {@link TrackPart.secondaryFrogAngle} Fast\n * Tracks publish, an independent check that this reading is right.\n */\nexport function crossoverAssembly(part: TrackPart): {\n /** End to end along the track, both halves. */\n lengthInches: number;\n spacingInches: number;\n /** Along-track distance a crossing route takes to reach the other track. */\n crossingRunInches: number;\n /** Where the four point-sets sit along the assembly. */\n pointsAtInches: [number, number];\n /** The X where the two crossing routes meet — a real diamond in the middle. */\n scissorsAtInches: number;\n} | null {\n const overall = part.overallLength?.inches;\n const spacing = part.trackSpacing?.inches;\n const n = part.frogNumber;\n if (!overall || !spacing || !n) return null;\n const lengthInches = overall * (part.piecesPerAssembly ?? 1);\n // tan θ = 1/N for a frog of number N. Use the part's own measured angle where\n // it has one — Atlas build to sectional angles rather than true frog ratios.\n const tan = part.actualAngle ? Math.tan((part.actualAngle.deg * Math.PI) / 180) : 1 / n;\n if (!(tan > 0)) return null;\n const crossingRunInches = spacing / tan;\n const mid = lengthInches / 2;\n const half = crossingRunInches / 2;\n return {\n lengthInches,\n spacingInches: spacing,\n crossingRunInches,\n pointsAtInches: [mid - half, mid + half],\n scissorsAtInches: mid,\n };\n}\n\n/** The weakest provenance among some dimensions — a placed part is only as\n * trustworthy as the softest number under it. */\nfunction weakestOf(...ds: (PartDimension | undefined)[]): DimensionSource {\n const rank: DimensionSource[] = [\"measured\", \"manufacturer\", \"derived\", \"unverified\"];\n let worst = 0;\n for (const d of ds) if (d) worst = Math.max(worst, rank.indexOf(d.source));\n return rank[worst];\n}\n\n/**\n * Why a part has no derivable geometry — null when it has.\n *\n * Worth its own function because \"we cannot place this yet\" is a fact an owner\n * should see in the picker, not a silent absence. It is also the parts-library\n * backlog in machine-readable form: every string this returns is a measurement\n * someone could take.\n */\nexport function partGeometryGap(part: TrackPart): string | null {\n if (part.kind === \"flex\") return null;\n // ⭐ A BUMPER NEEDS NO MEASUREMENT TO BE PLACEABLE. Its job is to say that an\n // end of track is closed deliberately, and that is true of a hand-built tie\n // bumper as much as of a product. Blocking it for want of a dimension would\n // withhold the one piece whose whole meaning is independent of its size.\n if (part.kind === \"bumper\") return null;\n if (part.kind === \"straight\")\n return part.overallLength ? null : \"no overall length — a sectional straight IS its length\";\n if (part.kind === \"curve\") {\n if (!part.radius) return \"no radius — a sectional curve is a radius and an arc\";\n if (part.arcDegrees == null) return \"no arc — the radius alone does not say how far it turns\";\n return null;\n }\n if (part.kind === \"crossover\") {\n // ⭐ IT IS DERIVABLE AFTER ALL. The published half-length, the fixture's\n // track spacing and its frog angle fix the whole assembly between them —\n // see {@link crossoverAssembly}. What was missing was reading the half as a\n // half, not the geometry.\n if (!part.overallLength) return \"no overall length — nothing says how long the assembly is\";\n if (!part.trackSpacing)\n return \"no track spacing — a crossover is defined by how far apart the two tracks it joins are\";\n if (part.frogNumber == null) return \"no frog number — the crossing angle is unknown\";\n return null;\n }\n if (part.kind === \"crossing\") return \"crossing geometry is not modelled yet\";\n if (part.kind === \"curved-turnout\")\n return \"a curved turnout needs both radii AND its points/frog landmarks; only the radii are published\";\n if (!part.pointsOffset)\n // ⚠️ CONSIDERED AND REJECTED for buildable parts: a fixture's frame could be\n // anchored at the POINTS instead of the tie end, which would make its\n // geometry derivable from the published radius and angle alone. Rejected\n // because it would give one library two different meanings for x=0 — and\n // because a hand-built turnout's tie end is wherever the builder cut, so an\n // owner measuring their own build is the honest source. One reading per\n // size unblocks all fourteen Fast Tracks parts.\n return \"no points offset — without it there is nowhere for the diverging route to begin\";\n if (!part.overallLength) return \"no overall length — the part has no end to put a joint on\";\n if (part.frogNumber == null) return \"no frog number — the diverging angle is unknown\";\n return null;\n}\n\n/**\n * A part's joints and routes, in its own frame.\n *\n * The through route runs along +x from the tie end; the diverging side is +y.\n * A placed piece is this, transformed — which is the whole point: the geometry\n * belongs to the PART, and placement is a rotation and a translation.\n *\n * ⚠️ THE DIVERGING END IS MEASURED WHERE WE HAVE A MEASUREMENT. `divergingLength`\n * (frog → end of the diverging rail, along the rail) says exactly where that end\n * is. Without it we fall back to assuming the diverging rail leaves the moulding\n * at the same x as the through route — which is what `partExtent` has always\n * assumed, and is an assumption, not a reading. `divergingEndMeasured` says\n * which you got.\n */\nexport function partGeometry(\n part: TrackPart,\n library = BUILT_IN_TRACK_PARTS,\n): PartGeometry | null {\n if (partGeometryGap(part)) return null;\n\n if (part.kind === \"straight\" || part.kind === \"curve\") {\n // ⭐ THE SAME ARC DEFINITION BENT FLEX USES (`flexRunEnd`), so a sectional\n // curve and a bent run of flex of the same radius land in exactly the same\n // place. Two definitions of an arc in one library would be a bug waiting\n // for someone to lay one against the other.\n const end =\n part.kind === \"curve\"\n ? flexRunEnd(sectionalArcInches(part), part.radius!.inches)\n : { x: part.overallLength!.inches, y: 0, headingDeg: 0 };\n return {\n joints: [\n { id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b\", role: \"through\", x: end.x, y: end.y, angleDeg: end.headingDeg },\n ],\n routes: [[\"a\", \"b\"]],\n source: (part.kind === \"curve\" ? part.radius : part.overallLength)?.source ?? \"unverified\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"bumper\") {\n // ⭐ ONE JOINT, AND NO ROUTE THROUGH IT — which is the entire point. A\n // bumper is where track STOPS, so the graph closes that end by\n // construction: the joint it takes is no longer open, and the walk that\n // reaches it has nowhere further to go. Nothing has to be flagged.\n return {\n joints: [{ id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 }],\n routes: [],\n source: part.overallLength?.source ?? \"unverified\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"flex\") {\n // Flex has no fixed geometry — it is the one piece a builder cuts. Its ends\n // are a and b; where b sits is the placed piece's business, not the part's.\n return {\n joints: [\n { id: \"a\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b\", role: \"through\", x: 0, y: 0, angleDeg: 0 },\n ],\n routes: [[\"a\", \"b\"]],\n source: \"derived\",\n divergingEndMeasured: false,\n };\n }\n\n if (part.kind === \"crossover\") {\n const g = crossoverAssembly(part);\n if (!g) return null;\n return {\n joints: [\n { id: \"a1\", role: \"crossoverEnd\", x: 0, y: 0, angleDeg: 180 },\n { id: \"b1\", role: \"crossoverEnd\", x: g.lengthInches, y: 0, angleDeg: 0 },\n { id: \"a2\", role: \"crossoverEnd\", x: 0, y: g.spacingInches, angleDeg: 180 },\n { id: \"b2\", role: \"crossoverEnd\", x: g.lengthInches, y: g.spacingInches, angleDeg: 0 },\n ],\n // ⭐ FOUR ROUTES, and that is the whole point. From either end of either\n // track a train can run straight on or cross to the other — which is what\n // makes this ONE assembly rather than four turnouts that happen to be near\n // each other.\n routes: [\n [\"a1\", \"b1\"],\n [\"a2\", \"b2\"],\n [\"a1\", \"b2\"],\n [\"a2\", \"b1\"],\n ],\n source: weakestOf(part.overallLength, part.trackSpacing),\n divergingEndMeasured: false,\n };\n }\n\n const N = part.frogNumber as number;\n const points = part.pointsOffset!;\n const overall = part.overallLength!;\n const frog = part.frogOffset;\n const lead = part.lead?.inches ?? (frog ? frog.inches - points.inches : undefined);\n if (lead == null || !(lead > 0)) return null;\n\n // A wye splits SYMMETRICALLY: each leg takes HALF the divergence, so each\n // behaves as a #2N. Same rule `frogLegOf` uses — one definition, two callers.\n const isWye = part.kind === \"wye\";\n const effN = isWye ? N * 2 : N;\n const closure = turnoutClosure(effN, { leadInches: lead });\n\n /** The diverging route's end: measured along the rail when we have it. */\n const divergingEnd = (): { x: number; y: number; measured: boolean } => {\n const frogX = frog ? frog.inches : points.inches + lead;\n const slope = closure.frogSlope;\n const dir = 1 / Math.hypot(1, slope); // unit x-component along the rail\n if (part.divergingLength) {\n // Frog → end of the diverging rail, ALONG the rail.\n const L = part.divergingLength.inches;\n return {\n x: frogX + L * dir,\n y: closure.offsetAt(frogX - points.inches) + L * slope * dir,\n measured: true,\n };\n }\n return {\n x: overall.inches,\n y: closure.offsetAt(overall.inches - points.inches),\n measured: false,\n };\n };\n\n const weakest = (...ds: (PartDimension | undefined)[]): DimensionSource => {\n const rank: DimensionSource[] = [\"measured\", \"manufacturer\", \"derived\", \"unverified\"];\n let worst = 0;\n for (const d of ds) if (d) worst = Math.max(worst, rank.indexOf(d.source));\n return rank[worst];\n };\n\n const de = divergingEnd();\n const legAngle = (Math.atan(closure.frogSlope) * 180) / Math.PI;\n\n if (isWye) {\n // Both legs diverge, mirrored. There is no straight through route — which is\n // exactly why a wye has no hand.\n return {\n joints: [\n { id: \"throat\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"legA\", role: \"diverge\", x: de.x, y: de.y, angleDeg: legAngle },\n { id: \"legB\", role: \"divergeB\", x: de.x, y: -de.y, angleDeg: -legAngle },\n ],\n routes: [\n [\"throat\", \"legA\"],\n [\"throat\", \"legB\"],\n ],\n source: weakest(points, overall, frog, part.divergingLength),\n divergingEndMeasured: de.measured,\n };\n }\n\n return {\n joints: [\n { id: \"throat\", role: \"throat\", x: 0, y: 0, angleDeg: 180 },\n { id: \"through\", role: \"through\", x: overall.inches, y: 0, angleDeg: 0 },\n { id: \"diverge\", role: \"diverge\", x: de.x, y: de.y, angleDeg: legAngle },\n ],\n routes: [\n [\"throat\", \"through\"],\n [\"throat\", \"diverge\"],\n ],\n source: weakest(points, overall, frog, part.divergingLength),\n divergingEndMeasured: de.measured,\n };\n}\n\n/**\n * The SHAPE of every route through a placed piece, in MODULE inches — the\n * polyline a renderer draws.\n *\n * ⭐ The shape belongs to the PART, so it lives here rather than in either app's\n * canvas. A diverging route drawn as a straight chord from throat to diverging\n * end cuts the corner the closure actually turns; every renderer would have to\n * rebuild that curve, and they would drift.\n *\n * ⚠️ Each polyline ENDS EXACTLY ON ITS JOINTS, by construction — the samples in\n * between follow the closure, but the ends are the joint positions themselves.\n * Track that stops short of its own joint would draw a gap at a connection that\n * the graph considers made.\n */\nexport function pieceRoutePaths(\n piece: TrackPiece,\n library = BUILT_IN_TRACK_PARTS,\n): { route: [string, string]; points: { x: number; y: number }[] }[] {\n const part = library.find((p) => p.id === piece.partId);\n if (!part) return [];\n const geo = partGeometry(part, library);\n if (!geo) return [];\n const joints = placedJoints([piece], library);\n const at = (id: string) => joints.find((j) => j.joint === id);\n\n // Sample the closure between the points and the diverging end, in the part's\n // own frame, then put it through the same transform the joints went through.\n const RAD = Math.PI / 180;\n const c = Math.cos(piece.rotationDeg * RAD);\n const s = Math.sin(piece.rotationDeg * RAD);\n const place = (x: number, y: number) => {\n const ly = piece.flipped ? -y : y;\n return { x: piece.x + x * c - ly * s, y: piece.y + x * s + ly * c };\n };\n\n const out: { route: [string, string]; points: { x: number; y: number }[] }[] = [];\n\n // ⚠️ A BUMPER HAS NO ROUTE, so the loop below would draw nothing at all and\n // the piece would be invisible and un-clickable. This polyline is its BODY,\n // not a path through it — the repeated joint id says there is nowhere to go.\n if (part.kind === \"bumper\") {\n const at = joints[0];\n if (!at) return out;\n const len = part.overallLength?.inches ?? BUMPER_DRAWN_INCHES;\n return [{ route: [\"a\", \"a\"], points: [{ x: at.x, y: at.y }, place(len, 0)] }];\n }\n\n // ⚠️ A SECTIONAL CURVE IS AN ARC AND MUST BE DRAWN AS ONE. Its joints land in\n // the right place either way, so this looks correct until you notice the rail\n // cutting the corner between them — the same mistake as drawing a turnout's\n // diverging route as a chord, arriving by a different door.\n if (part.kind === \"curve\") {\n const a = joints.find((j) => j.joint === \"a\");\n const b = joints.find((j) => j.joint === \"b\");\n if (!a || !b) return out;\n // `place` already mirrors a flipped piece, so the radius stays positive here\n // — negating it too would flip it back.\n const pts = flexRunPoints(sectionalArcInches(part), part.radius!.inches).map((q) =>\n place(q.x, q.y),\n );\n pts[pts.length - 1] = { x: b.x, y: b.y };\n return [{ route: [\"a\", \"b\"], points: pts }];\n }\n\n // ⚠️ A CROSSING ROUTE IS NOT A DIAGONAL FROM END TO END. It runs straight\n // along its own track to the point-set, crosses at the frog angle, and runs\n // straight again — so drawn as a chord the rail would leave the railhead for\n // most of the assembly and the scissors X would land nowhere near the middle.\n // Same mistake as drawing a sectional curve as its chord, arriving by another\n // door (that one shipped, because the JOINTS are right either way).\n if (part.kind === \"crossover\") {\n const g = crossoverAssembly(part);\n if (g) {\n const [p1, p2] = g.pointsAtInches;\n const S = g.spacingInches;\n const L = g.lengthInches;\n const yOf = (id: string) => (id.endsWith(\"2\") ? S : 0);\n return geo.routes.map((route) => {\n const [from, to] = route;\n const y0 = yOf(from);\n const y1 = yOf(to);\n // Which end each joint is at: \"a\" west (x=0), \"b\" east (x=L).\n const x0 = from.startsWith(\"a\") ? 0 : L;\n const x1 = to.startsWith(\"a\") ? 0 : L;\n if (y0 === y1)\n return { route, points: [place(x0, y0), place(x1, y1)] }; // straight through\n // Crossing: straight to the near point-set, over, then straight on.\n const west = Math.min(x0, x1) === 0;\n const [xa, xb] = west ? [p1, p2] : [p2, p1];\n return {\n route,\n points: [place(x0, y0), place(xa, y0), place(xb, y1), place(x1, y1)],\n };\n });\n }\n }\n\n for (const route of geo.routes) {\n const a = at(route[0]);\n const b = at(route[1]);\n if (!a || !b) continue;\n const ends = [{ x: a.x, y: a.y }, { x: b.x, y: b.y }];\n if (part.kind === \"flex\") {\n // Bent flex is an arc; straight flex comes back as its two ends.\n const pts = flexRunPoints(piece.lengthInches ?? 0, piece.radiusInches).map((q) =>\n place(q.x, q.y),\n );\n pts[pts.length - 1] = { x: b.x, y: b.y };\n out.push({ route, points: pts });\n continue;\n }\n const diverging = route.some((r) => r === \"diverge\" || r === \"legA\" || r === \"legB\");\n if (!diverging) {\n out.push({ route, points: ends });\n continue;\n }\n const lead = part.lead?.inches ?? 0;\n const pts0 = part.pointsOffset?.inches ?? 0;\n const far = geo.joints.find((j) => j.id === route[1]) ?? geo.joints.find((j) => j.id === route[0]);\n if (!far || !(lead > 0)) {\n out.push({ route, points: ends });\n continue;\n }\n const isWye = part.kind === \"wye\";\n const closure = turnoutClosure(isWye ? (part.frogNumber as number) * 2 : (part.frogNumber as number), {\n leadInches: lead,\n });\n // The route runs straight to the points, then follows the closure. `legB` is\n // the mirror of `legA` — a wye splits symmetrically, which is the same rule\n // its joints were placed by.\n const mirror = route.includes(\"legB\") ? -1 : 1;\n const pts: { x: number; y: number }[] = [place(0, 0), place(pts0, 0)];\n const steps = 12;\n for (let i = 1; i <= steps; i++) {\n const x = pts0 + ((far.x - pts0) * i) / steps;\n pts.push(place(x, mirror * closure.offsetAt(x - pts0)));\n }\n // End ON the joint: the sampled curve and the joint are worked out the same\n // way, but only this makes them the same number.\n pts[pts.length - 1] = { x: b.x, y: b.y };\n out.push({ route, points: route[0] === \"throat\" ? pts : pts.slice().reverse() });\n }\n return out;\n}\n\n/**\n * The HAND of a placed piece — the product an owner would actually buy.\n *\n * ⭐ THE MODEL HAS NO HAND, AND THIS IS NOT A CONTRADICTION. Nothing derived\n * from the graph asks which way a turnout is handed: the side a route leaves on\n * is simply where the piece is (ADR 0001). But a turnout on a shelf IS a\n * left-hand or a right-hand product, with its own part number, and an owner\n * picking one out of a palette is choosing between two things they could own.\n * So the hand belongs at the point of PURCHASE and PLACEMENT, and nowhere after.\n *\n * ⚠️ UNFLIPPED IS THE LEFT-HAND PART. A part's own frame diverges toward +y, and\n * +y is to the left of the through route looking from the throat — which agrees\n * with the library: the Atlas #7's `partNumbers.left` (2052) is the one whose\n * published geometry these dimensions were read from.\n *\n * Null for a part with no hand to have — a wye splits symmetrically, which is\n * exactly why it is sold as one product.\n */\nexport function pieceHand(part: TrackPart, flipped?: boolean | null): \"left\" | \"right\" | null {\n const n = part.partNumbers;\n if (!n?.left || !n?.right) return null;\n return flipped ? \"right\" : \"left\";\n}\n\n/** The part number a placed piece corresponds to — what to order. */\nexport function piecePartNumber(part: TrackPart, flipped?: boolean | null): string | undefined {\n const hand = pieceHand(part, flipped);\n if (!hand) return part.partNumbers?.single;\n return part.partNumbers?.[hand];\n}\n\n/** Every part that can be PLACED on a board today, and every one that can only\n * be named — with the reason. The gap list is the parts backlog. */\nexport function partsPlaceable(library = BUILT_IN_TRACK_PARTS): {\n placeable: TrackPart[];\n blocked: { part: TrackPart; why: string }[];\n} {\n const placeable: TrackPart[] = [];\n const blocked: { part: TrackPart; why: string }[] = [];\n for (const p of library) {\n const why = partGeometryGap(p);\n if (why) blocked.push({ part: p, why });\n else if (partGeometry(p, library)) placeable.push(p);\n else blocked.push({ part: p, why: \"dimensions present but inconsistent\" });\n }\n return { placeable, blocked };\n}\n\n// ─── THE TRACK GRAPH (ADR 0001) ──────────────────────────────────────────────\n// Pieces placed on the board; joints that coincide are connected. Everything\n// positional — `pos`, a siding's extent, which track hosts a turnout — is READ\n// OFF this by walking it, rather than authored separately and reconciled.\n\n/** A part placed on the benchwork. */\nexport interface TrackPiece {\n id: string;\n /** A slug from the parts library. */\n partId: string;\n /** Where the part's own origin sits, in module-local inches. */\n x: number;\n y: number;\n /** Rotation about that origin, degrees. */\n rotationDeg: number;\n /** Mirrored across its own through route — a left-hand turnout from a right. */\n flipped?: boolean;\n /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001).\n * ⚠️ ARC length when the run is bent — the rail, not the chord across it. */\n lengthInches?: number;\n /**\n * FLEX ONLY: the radius this run is bent to, inches. Absent = straight.\n *\n * ⭐ It lives on the PIECE, not the part, because bending flex is what a\n * builder does to it — the product is the same product either way. That is\n * the same reason `lengthInches` is here.\n *\n * ⭐ SIGNED, and the sign IS the side: positive curves toward +y in the\n * piece's own frame, negative the other way. One number, no separate\n * \"direction\" field to disagree with it — the same reasoning that keeps a\n * hand off turnouts, where the side is simply where the piece is.\n *\n * ⚠️ {@link lengthInches} stays the ARC length. `pos` is arc length\n * everywhere in this model, a curve's rail is genuinely longer than the chord\n * it spans (a 90° corner at R30 runs 47.1″ across a 42.4″ chord), and it is\n * the rail a train travels.\n */\n radiusInches?: number;\n /** Owner's label, carried onto whatever route this piece ends up in. */\n name?: string;\n}\n\n/** A piece's joint, in MODULE coordinates. */\nexport interface PlacedJoint {\n /** `\"<pieceId>.<jointId>\"` — stable, and what connections refer to. */\n key: string;\n piece: string;\n joint: string;\n role: PartJointRole;\n x: number;\n y: number;\n headingDeg: number;\n}\n\n/** Two joints in the same place. That is the entire connection rule. */\nexport interface GraphConnection {\n a: string;\n b: string;\n}\n\n/**\n * More than two joints in one place — REFUSED, not resolved.\n *\n * ⚠️ THIS IS THE GAP THE SPIKE FOUND, and the one that would bite owners. With\n * three ends stacked on a point, picking a pair silently drops a piece out of\n * the layout: the walk never reaches it, and nothing says so. So none of them\n * connect and the ambiguity is reported. Refusing is the only honest answer —\n * the model cannot know which two the owner meant.\n */\nexport interface GraphConflict {\n x: number;\n y: number;\n joints: string[];\n reason: string;\n}\n\nexport interface TrackGraph {\n joints: PlacedJoint[];\n connections: GraphConnection[];\n /** Joints connected to nothing — an unfinished layout, which is a real thing\n * to show an owner rather than quietly draw as if it were joined. */\n open: string[];\n conflicts: GraphConflict[];\n /** Pieces whose part has no derivable geometry (see {@link partGeometryGap}). */\n unplaceable: { piece: string; partId: string; why: string }[];\n}\n\n/** How close two joints must be to count as connected. A hundredth of an inch:\n * tight enough that nothing joins by accident, loose enough to absorb the\n * rounding of a drag. */\nexport const JOINT_SNAP_INCHES = 0.01;\n\n/**\n * How long a bumper draws when it is not a named product.\n *\n * ⚠️ A DRAWING DEFAULT, NOT A MEASUREMENT, and deliberately not recorded as one\n * on any part. What a bumper is FOR — saying this end of the track is closed on\n * purpose — does not depend on its length, and plenty are a tie and a bit of\n * scrap. A named product supplies its own `overallLength` and this stops\n * applying.\n */\n/** Every kind of part the library can hold. Beside the type it mirrors, so a\n * new kind is one edit and not two. */\nexport const TRACK_PART_KINDS: TrackPart[\"kind\"][] = [\n \"turnout\",\n \"wye\",\n \"curved-turnout\",\n \"crossover\",\n \"crossing\",\n \"flex\",\n \"straight\",\n \"curve\",\n \"bumper\",\n];\n\nexport const BUMPER_DRAWN_INCHES = 0.75;\n\n/**\n * How long a sectional curve's RAIL is — the arc, not the chord across it.\n *\n * ⚠️ Curves are sold as a radius and an arc, never as a length, and the chord is\n * always shorter. Recording one as the piece's length would put everything past\n * that curve closer to endplate A than it is — the same mistake the walk exists\n * to avoid, arriving through the parts library instead.\n */\nexport function sectionalArcInches(part: TrackPart): number {\n if (part.kind !== \"curve\" || !part.radius || part.arcDegrees == null) return 0;\n return (part.radius.inches * Math.abs(part.arcDegrees) * Math.PI) / 180;\n}\n\n/**\n * Where a bent run's far end lands, and which way it points — in the piece's own\n * frame, starting at its origin heading +x.\n *\n * ONE definition, called by both {@link placedJoints} and\n * {@link pieceRoutePaths}, so the drawn rail cannot arrive anywhere other than\n * the joint at the end of it.\n */\nexport function flexRunEnd(\n lengthInches: number,\n radiusInches?: number,\n): { x: number; y: number; headingDeg: number } {\n const L = lengthInches;\n const R = radiusInches;\n if (!R || !Number.isFinite(R) || Math.abs(R) < 1e-6)\n return { x: L, y: 0, headingDeg: 0 };\n // Sweep follows from the two of them: a length of rail bent to a radius has\n // no freedom left. Positive R turns toward +y.\n const theta = L / R;\n return {\n x: Math.abs(R) * Math.sin(Math.abs(theta)) * Math.sign(L || 1),\n y: R * (1 - Math.cos(theta)),\n headingDeg: (theta * 180) / Math.PI,\n };\n}\n\n/** Points along a bent run, in the piece's own frame. */\nfunction flexRunPoints(lengthInches: number, radiusInches: number | undefined, steps = 16) {\n if (!radiusInches || !Number.isFinite(radiusInches) || Math.abs(radiusInches) < 1e-6)\n return [{ x: 0, y: 0 }, { x: lengthInches, y: 0 }];\n const out: { x: number; y: number }[] = [];\n for (let i = 0; i <= steps; i++) out.push(flexRunEnd((lengthInches * i) / steps, radiusInches));\n return out.map((p) => ({ x: p.x, y: p.y }));\n}\n\n/** Every piece's joints, transformed onto the board. */\nexport function placedJoints(\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n): PlacedJoint[] {\n const out: PlacedJoint[] = [];\n const RAD = Math.PI / 180;\n for (const p of pieces) {\n const part = library.find((x) => x.id === p.partId);\n if (!part) continue;\n const geo = partGeometry(part, library);\n if (!geo) continue;\n const c = Math.cos(p.rotationDeg * RAD);\n const s = Math.sin(p.rotationDeg * RAD);\n // Flex is the ONE piece whose geometry the builder sets: its far end is\n // wherever they cut it, and — bent — wherever the curve puts it. Everything\n // else is rigid.\n const run =\n part.kind === \"flex\" ? flexRunEnd(p.lengthInches ?? 0, p.radiusInches) : null;\n for (const j of geo.joints) {\n const far = run && j.id === \"b\";\n const lx = far ? run.x : j.x;\n const ly = p.flipped ? -(far ? run.y : j.y) : far ? run.y : j.y;\n // ⚠️ A bent run's far end POINTS somewhere else. Leaving the angle at 0\n // would make a curve's end claim to face along +x, so the next piece\n // snapped to it would come in across the rail instead of along it.\n const local = far ? run.headingDeg : j.angleDeg;\n const h = (p.flipped ? -local : local) + p.rotationDeg;\n out.push({\n key: `${p.id}.${j.id}`,\n piece: p.id,\n joint: j.id,\n role: j.role,\n x: p.x + lx * c - ly * s,\n y: p.y + lx * s + ly * c,\n headingDeg: norm360(h),\n });\n }\n }\n return out;\n}\n\n/**\n * Build the graph: which joints are connected, which are open, and where the\n * layout is ambiguous.\n *\n * ⭐ A JOINT HOLDS AT MOST ONE CONNECTION. Rail has two ends; a place where\n * three meet is a mistake, not a junction — a junction is a TURNOUT, which is a\n * part carrying three joints of its own.\n */\nexport function buildTrackGraph(\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n snapInches = JOINT_SNAP_INCHES,\n): TrackGraph {\n const joints = placedJoints(pieces, library);\n const unplaceable: TrackGraph[\"unplaceable\"] = [];\n for (const p of pieces) {\n const part = library.find((x) => x.id === p.partId);\n if (!part) {\n unplaceable.push({ piece: p.id, partId: p.partId, why: \"no such part in the library\" });\n continue;\n }\n const why = partGeometryGap(part);\n if (why) unplaceable.push({ piece: p.id, partId: p.partId, why });\n }\n\n // Group coincident joints FIRST. Pairing greedily would connect two of three\n // and hide the third, which is exactly the failure this rule exists to stop.\n const groups: PlacedJoint[][] = [];\n const taken = new Set<string>();\n for (const j of joints) {\n if (taken.has(j.key)) continue;\n const g = [j];\n taken.add(j.key);\n for (const k of joints) {\n if (taken.has(k.key) || k.piece === j.piece) continue;\n if (Math.hypot(k.x - j.x, k.y - j.y) <= snapInches) {\n g.push(k);\n taken.add(k.key);\n }\n }\n groups.push(g);\n }\n\n const connections: GraphConnection[] = [];\n const open: string[] = [];\n const conflicts: GraphConflict[] = [];\n for (const g of groups) {\n if (g.length === 1) open.push(g[0].key);\n else if (g.length === 2) connections.push({ a: g[0].key, b: g[1].key });\n else {\n conflicts.push({\n x: g[0].x,\n y: g[0].y,\n joints: g.map((j) => j.key),\n reason:\n `${g.length} track ends are stacked in one place. Rail has two ends, ` +\n \"so a junction of three is a turnout, not a joint — none of these are \" +\n \"joined until one is moved.\",\n });\n for (const j of g) open.push(j.key);\n }\n }\n return { joints, connections, open, conflicts, unplaceable };\n}\n\n/** A piece as the route crosses it — what an anchored feature resolves against. */\nexport interface RouteSpan {\n piece: string;\n /** The joints the route entered and left this piece by. Tell you which way\n * round the piece's own measurements run against the route's. */\n entryJoint: string;\n exitJoint: string;\n /** Inches from endplate A at the entry joint, and at the one it left by. */\n fromPos: number;\n toPos: number;\n}\n\n/** A piece moved into place against an open joint. */\nexport interface PieceSnap {\n /** The piece, rotated and translated so the two joints coincide. */\n piece: TrackPiece;\n /** The moving joint's key, and the open joint it was brought onto. */\n from: string;\n to: string;\n}\n\n/**\n * Bring a piece being dragged onto the nearest OPEN joint of the others.\n *\n * ⛔ **ONLY OPEN JOINTS ARE CANDIDATES, and that is the ADR's standing rule\n * enforced where it can still be obeyed.** A joint already holding a connection\n * is not offered, so an owner cannot stack a third rail end on a joint at all —\n * rather than stacking it and having {@link buildTrackGraph} refuse all three\n * afterwards, with a piece silently outside the layout until they notice.\n *\n * The piece is ROTATED as well as moved: two ends meet when they are in the same\n * place and facing opposite ways, so the rotation falls out of the joint it is\n * brought to. That is what makes laying a curve out of straight pieces possible\n * without typing an angle.\n *\n * `withinInches` is a GRAB radius — how near counts as \"meant it\" — and is a\n * different thing from {@link JOINT_SNAP_INCHES}, which is how close two joints\n * must be to BE connected. This one is generous; that one is a hundredth of an\n * inch.\n */\nexport function snapPiece(\n moving: TrackPiece,\n others: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 0.5,\n): PieceSnap | null {\n const mine = placedJoints([moving], library);\n if (!mine.length) return null;\n const graph = buildTrackGraph(others, library);\n const taken = new Set(graph.connections.flatMap((c) => [c.a, c.b]));\n const open = graph.joints.filter((j) => !taken.has(j.key));\n\n let best: { m: PlacedJoint; t: PlacedJoint; d: number } | null = null;\n for (const m of mine)\n for (const t of open) {\n const d = Math.hypot(t.x - m.x, t.y - m.y);\n if (d <= withinInches && (!best || d < best.d)) best = { m, t, d };\n }\n if (!best) return null;\n\n // Turn the piece about the joint that is being brought in — so that joint\n // stays where the owner's pointer left it — then slide it onto the target.\n const RAD = Math.PI / 180;\n const dRot = norm360(best.t.headingDeg + 180 - best.m.headingDeg);\n const c = Math.cos(dRot * RAD);\n const s = Math.sin(dRot * RAD);\n const ox = moving.x - best.m.x;\n const oy = moving.y - best.m.y;\n return {\n piece: {\n ...moving,\n rotationDeg: norm360(moving.rotationDeg + dRot),\n x: best.t.x + ox * c - oy * s,\n y: best.t.y + ox * s + oy * c,\n },\n from: best.m.key,\n to: best.t.key,\n };\n}\n\n/**\n * Cut a run of flex to fit BETWEEN two joints — the piece's near end already\n * where it belongs, its far end brought onto another open joint.\n *\n * ⭐ WITHOUT THIS A CROSSOVER CANNOT BE BUILT BY HAND. A piece snaps by ONE end,\n * and a flex run's length handle drags along its own axis, so the far end can\n * never be steered onto the turnout opposite: an owner would have to type an\n * angle and a length to a hundredth of an inch. Cutting a piece to fit between\n * two fixed points is exactly what a builder does with flex, and it is the last\n * thing standing between \"two mains\" and \"two mains joined\".\n *\n * ⚠️ STRAIGHT RUNS ONLY. A bend is already fixed by its radius; asking an arc to\n * meet a second point as well over-constrains it, and quietly re-bending an\n * owner's curve to reach something is not a fit, it is a guess.\n */\nexport function fitFlexBetween(\n piece: TrackPiece,\n others: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 0.5,\n): TrackPiece | null {\n const part = library.find((p) => p.id === piece.partId);\n if (part?.kind !== \"flex\" || piece.radiusInches) return null;\n const mine = placedJoints([piece], library);\n const far = mine.find((j) => j.joint === \"b\");\n const near = mine.find((j) => j.joint === \"a\");\n if (!far || !near) return null;\n const graph = buildTrackGraph(others, library);\n const taken = new Set(graph.connections.flatMap((c) => [c.a, c.b]));\n let best: { j: PlacedJoint; d: number } | null = null;\n for (const j of graph.joints) {\n if (taken.has(j.key)) continue; // an occupied joint is not on offer\n // ⚠️ NOR THE ONE THIS PIECE ALREADY STARTS ON. A short connector's far end\n // is often nearer its own near-end joint than the joint opposite — a\n // crossover's diverging ends are a tenth of an inch apart — so the nearest\n // open joint is the piece's own, and fitting to it asks for a run of zero\n // length. That is what \"the crossover cannot be built\" looked like.\n if (Math.hypot(j.x - near.x, j.y - near.y) <= JOINT_SNAP_INCHES) continue;\n const d = Math.hypot(j.x - far.x, j.y - far.y);\n if (d <= withinInches && (!best || d < best.d)) best = { j, d };\n }\n if (!best) return null;\n const dx = best.j.x - piece.x;\n const dy = best.j.y - piece.y;\n const len = Math.hypot(dx, dy);\n if (!(len > 0)) return null;\n return {\n ...piece,\n rotationDeg: norm360((Math.atan2(dy, dx) * 180) / Math.PI),\n lengthInches: Math.round(len * 1000) / 1000,\n };\n}\n\n/** A run cut in two to let a piece in. */\nexport interface RunInsertion {\n /** The whole set: the host shortened, the new piece, and the remainder. */\n pieces: TrackPiece[];\n /** The run that was cut, and the piece that went into it. */\n hostId: string;\n insertedId: string;\n}\n\n/**\n * Drop a piece ONTO a run and cut the run to take it.\n *\n * ⭐ Will, 2026-07-27: *\"When I drop a turnout on the track, it should cut the\n * track there and automatically snap to the new joints.\"* Snapping alone cannot\n * do this: the middle of a run has no open joint, so there is nothing to snap\n * TO — the joints have to be made by cutting, which is exactly what a builder\n * does with a razor saw.\n *\n * ⚠️ ONLY FLEX CAN BE CUT. A turnout or a sectional piece is a moulding: you\n * cannot saw one in half and have two of anything. Dropping onto one is refused\n * rather than fudged.\n *\n * ⚠️ AND THE PIECE HAS TO FIT. It consumes length along the run — a #7 is six\n * inches of it — so an insertion that would run off the end is refused instead\n * of silently producing a remainder of negative length.\n */\nexport function insertIntoRun(\n pieces: TrackPiece[],\n fresh: TrackPiece,\n at: { x: number; y: number },\n library = BUILT_IN_TRACK_PARTS,\n withinInches = 1,\n): RunInsertion | null {\n // The nearest run, measured against the rail rather than the piece's origin.\n let host: TrackPiece | null = null;\n let bestD = Infinity;\n for (const piece of pieces) {\n const part = library.find((x) => x.id === piece.partId);\n if (part?.kind !== \"flex\") continue;\n for (const { points } of pieceRoutePaths(piece, library))\n for (let i = 1; i < points.length; i++) {\n const d = distanceToSegment(at, points[i - 1], points[i]);\n if (d < bestD) {\n bestD = d;\n host = piece;\n }\n }\n }\n if (!host || bestD > withinInches) return null;\n\n const L = host.lengthInches ?? 0;\n const R = host.radiusInches;\n // How far along the host the drop lands, by walking its own arc.\n const steps = 200;\n let s = 0;\n let closest = Infinity;\n for (let i = 0; i <= steps; i++) {\n const t = (L * i) / steps;\n const local = flexRunEnd(t, R);\n const world = placeLocal(host, local.x, local.y);\n const d = Math.hypot(world.x - at.x, world.y - at.y);\n if (d < closest) {\n closest = d;\n s = t;\n }\n }\n\n // Sit the new piece on the run, pointing the way the run points there.\n const cutLocal = flexRunEnd(s, R);\n const cut = placeLocal(host, cutLocal.x, cutLocal.y);\n const heading = norm360(host.rotationDeg + (host.flipped ? -cutLocal.headingDeg : cutLocal.headingDeg));\n const placed: TrackPiece = { ...fresh, x: cut.x, y: cut.y, rotationDeg: heading };\n\n // What it consumes along the run: entry joint to the one the run leaves by.\n const js = placedJoints([placed], library);\n const entry = js.find((j) => j.joint === \"throat\" || j.joint === \"a\");\n const exit = js.find((j) => j.joint === \"through\" || j.joint === \"b\");\n if (!entry || !exit) return null;\n const body = Math.hypot(exit.x - entry.x, exit.y - entry.y);\n const rest = L - s - body;\n if (s < 0 || rest < 0) return null;\n\n const ids = new Set(pieces.map((p) => p.id));\n let n = 1;\n while (ids.has(`${host.id}b${n}`)) n += 1;\n const tail: TrackPiece = {\n ...host,\n id: `${host.id}b${n}`,\n x: exit.x,\n y: exit.y,\n rotationDeg: exit.headingDeg,\n lengthInches: rest,\n };\n\n const out = pieces.map((p) => (p.id === host!.id ? { ...p, lengthInches: s } : p));\n // A cut at the very start or end leaves a stub of nothing — drop it rather\n // than leaving a zero-length run for the graph to puzzle over.\n const kept = out.filter((p) => p.id !== host!.id || s > 0);\n return {\n pieces: [...kept, placed, ...(rest > 0 ? [tail] : [])],\n hostId: host.id,\n insertedId: placed.id,\n };\n}\n\n/** A point in a piece's own frame, put on the board. */\nfunction placeLocal(piece: TrackPiece, x: number, y: number): { x: number; y: number } {\n const rad = (piece.rotationDeg * Math.PI) / 180;\n const ly = piece.flipped ? -y : y;\n return {\n x: piece.x + x * Math.cos(rad) - ly * Math.sin(rad),\n y: piece.y + x * Math.sin(rad) + ly * Math.cos(rad),\n };\n}\n\nfunction distanceToSegment(\n p: { x: number; y: number },\n a: { x: number; y: number },\n b: { x: number; y: number },\n): number {\n const vx = b.x - a.x;\n const vy = b.y - a.y;\n const len2 = vx * vx + vy * vy;\n if (len2 === 0) return Math.hypot(p.x - a.x, p.y - a.y);\n const t = Math.max(0, Math.min(1, ((p.x - a.x) * vx + (p.y - a.y) * vy) / len2));\n return Math.hypot(p.x - (a.x + t * vx), p.y - (a.y + t * vy));\n}\n\n/** A route the walk found: a continuous run of pieces a train can travel. */\nexport interface GraphRoute {\n id: string;\n /** Inches from endplate A, ALONG THE RAIL, to where this route begins. */\n fromPos: number;\n toPos: number;\n /** The turnout this route branched from; null for the main. */\n bornAt: string | null;\n /** The turnout it runs back into. Set = a SIDING; null = it dead-ends. */\n endsAt: string | null;\n /** The piece that CLOSES this route — a bumper. Set = the track ends here on\n * purpose; null = it simply stops, which may just mean unfinished. */\n closedBy: string | null;\n pieces: string[];\n /** The same pieces, each with where it starts and ends along the route. */\n spans: RouteSpan[];\n /** Furthest lateral offset reached — what gives a lane its side. */\n lateral: number;\n}\n\nexport interface GraphTurnout {\n id: string;\n /** ⚠️ The FROG's distance from endplate A (#132), measured along the rail. */\n pos: number;\n onRoute: string;\n divergeRoute: string | null;\n}\n\nexport interface GraphWalk {\n routes: GraphRoute[];\n turnouts: GraphTurnout[];\n /** Every reason this walk is not the whole layout. */\n warnings: string[];\n /** Turnouts whose diverging route reaches nothing — the ids, not just the\n * sentence, so a caller can act on it (and say it ONCE) instead of matching\n * on prose. */\n danglingDiverges: string[];\n /** Pieces this walk never got to. ⚠️ \"Unreached BY THIS WALK\" is not the same\n * as \"unreachable\": a double-track module's second main is unreached by the\n * first walk and perfectly well connected. Ids, so a caller running more than\n * one walk can tell the difference. */\n unreached: string[];\n}\n\n/** The one wording for a turnout whose diverging route reaches nothing, so a\n * caller can recognise it exactly rather than by substring. */\nconst danglingDivergeWarning = (id: string) =>\n `the route diverging at ${id} is not connected to anything`;\n\n/** Likewise for a piece the walk never got to. */\nconst unreachedWarning = (id: string) =>\n `${id} is not reachable from the endplate — nothing connects it`;\n\n/**\n * Walk the graph from an endplate and read the topology off it.\n *\n * ⚠️ POSITIONS ARE ARC LENGTH ALONG THE RAIL, never x. On a curved module the\n * two differ by inches — a 90°/R30 corner runs 47.1″ of rail across a 42.4″\n * chord — and it is the rail a train travels.\n *\n * Nesting falls out for free: a turnout found on a branch queues the branch IT\n * opens, so a yard ladder resolves to whatever depth it actually has. That is\n * the case the 1-D model can only approximate.\n */\nexport function walkTrackGraph(\n graph: TrackGraph,\n pieces: TrackPiece[],\n startAt: { piece: string; joint: string },\n library = BUILT_IN_TRACK_PARTS,\n): GraphWalk {\n const byKey = new Map(graph.joints.map((j) => [j.key, j]));\n const pieceById = new Map(pieces.map((p) => [p.id, p]));\n const link = new Map<string, string>();\n for (const c of graph.connections) {\n link.set(c.a, c.b);\n link.set(c.b, c.a);\n }\n const partOf = (pid: string) => {\n const p = pieceById.get(pid);\n return p ? library.find((x) => x.id === p.partId) : undefined;\n };\n const geoOf = (pid: string) => {\n const part = partOf(pid);\n return part ? partGeometry(part, library) : null;\n };\n /**\n * How far it is THROUGH a piece, from one of its joints to another.\n *\n * ⚠️⚠️ NOT THE DISTANCE BETWEEN THE TWO JOINTS. On a bent run those differ by\n * inches — a 90° corner at R30 is 47.1″ of rail across a 42.4″ chord — and\n * `pos` is arc length along the rail, because that is what a train travels\n * and what every position in the document means. A flex run's arc length is\n * the length it was cut to, which is exactly `lengthInches`.\n */\n const gap = (a?: PlacedJoint, b?: PlacedJoint) => {\n if (!a || !b) return 0;\n if (a.piece === b.piece) {\n const piece = pieceById.get(a.piece);\n const part = piece ? partOf(a.piece) : undefined;\n if (piece && part?.kind === \"flex\") return piece.lengthInches ?? 0;\n // ⚠️ AND A SECTIONAL CURVE BY ITS ARC. Missing this measured one 19″ 30°\n // section as its 9.83″ chord instead of 9.95″ of rail — an eighth of an\n // inch per section, compounding all the way along a curved module. The\n // invariant is not \"flex is special\"; it is that a curve's rail is longer\n // than the straight line across it, whoever made the curve.\n if (part?.kind === \"curve\") return sectionalArcInches(part);\n }\n return Math.hypot(a.x - b.x, a.y - b.y);\n };\n\n const routes: GraphRoute[] = [];\n const turnouts: GraphTurnout[] = [];\n const warnings: string[] = [];\n const danglingDiverges: string[] = [];\n const queued = new Set<string>();\n const pending: { from: string; at: number; joint: string; skew: number }[] = [];\n\n const walk = (\n startKey: string,\n startPos: number,\n id: string,\n bornAt: string | null,\n ): GraphRoute => {\n const route: GraphRoute = {\n id, fromPos: startPos, toPos: startPos, bornAt, endsAt: null, closedBy: null,\n pieces: [], spans: [], lateral: 0,\n };\n let cur: string | undefined = startKey;\n let pos = startPos;\n const guard = new Set<string>();\n while (cur && !guard.has(cur)) {\n guard.add(cur);\n const here = byKey.get(cur);\n if (!here) break;\n const geo = geoOf(here.piece);\n if (!geo) break;\n // Where this route leaves the piece: whichever of its routes uses the\n // joint we came in by. At a turnout prefer the THROUGH route, so the walk\n // stays on the line it is on and the diverging leg becomes a branch.\n const opts = geo.routes.filter((r) => r.includes(here.joint));\n if (!opts.length) {\n // ⭐ NOWHERE TO GO — a bumper. The route ends here DELIBERATELY, which\n // is a different thing from running out of track, and the difference is\n // the whole reason bumpers exist in the model.\n //\n // ⚠️ It must be recorded as REACHED. Breaking out without it left the\n // bumper looking like stray track that nothing connects, which is the\n // opposite of what it says.\n route.pieces.push(here.piece);\n route.closedBy = here.piece;\n break;\n }\n // ⭐ THROUGH A CROSSOVER, STAY ON THE TRACK YOU ARE ON. Its four routes\n // are two straights and two crossings, and none of them is called\n // \"through\" — so the old rule fell through to `opts[0]` and a main could\n // walk out on the other main. The straight route is the one whose far end\n // is on the same track, which the joint ids say: a1/b1 are one track,\n // a2/b2 the other. A crossing is a route a train CHOOSES, exactly like a\n // turnout's diverging leg, so it is left for the branch pass.\n const sameTrack = (r: [string, string]) => {\n const other = r[0] === here.joint ? r[1] : r[0];\n return other.slice(-1) === here.joint.slice(-1);\n };\n const pick =\n (partOf(here.piece)?.kind === \"crossover\" ? opts.find(sameTrack) : undefined) ??\n opts.find((r) => r.includes(\"through\")) ??\n opts[0];\n const exitJoint = pick[0] === here.joint ? pick[1] : pick[0];\n const exit = byKey.get(`${here.piece}.${exitJoint}`);\n const part = partOf(here.piece);\n\n if (part && (part.kind === \"turnout\" || part.kind === \"wye\")) {\n const throat = byKey.get(`${here.piece}.throat`);\n const through =\n byKey.get(`${here.piece}.through`) ?? byKey.get(`${here.piece}.legA`);\n const body = gap(throat, through);\n const lead = part.lead?.inches ?? body / 2;\n // ⚠️⚠️ THE FROG SITS AT `frogOffset` FROM THE TIE END, NOT AT `lead`.\n // `lead` is measured POINTS → frog (see {@link TrackPart.lead}, and the\n // measured table on {@link ATLAS_CODE55_N}: the #7's ⅝″ points and\n // 4⁷⁄₃₂″ frog give exactly its 3.59375″ lead). Adding it to the THROAT\n // landed 0.625″ short of the frog on a #7 — on no landmark at all.\n const frogAxial = part.frogOffset?.inches ?? (part.pointsOffset?.inches ?? 0) + lead;\n // ⚠️ ENTERED FROM EITHER END. A turnout facing the other way is entered\n // at its `through` joint, so the frog is `body − frogAxial` along.\n // The frog, in the piece's own frame — where the diverging rail has\n // climbed one gauge and the two routes truly cross.\n const dvj = byKey.get(`${here.piece}.diverge`) ?? byKey.get(`${here.piece}.legB`);\n const frogPt =\n throat && body > 0 && dvj\n ? {\n x: throat.x + ((dvj.x - throat.x) * frogAxial) / body,\n y: throat.y + ((dvj.y - throat.y) * frogAxial) / body,\n }\n : null;\n // ⚠️ HOW FAR THE FROG IS DEPENDS ON WHICH END YOU CAME IN BY, and there\n // are THREE answers, not two. From the throat it is the lead. From the\n // through end it is `body − lead`. From a DIVERGING end it is neither:\n // that rail runs at an angle, so it is longer than the axial distance —\n // measure it. Using `body − lead` there put a siding's far end 0.01\"\n // out, which is small only because the angle is.\n const toFrog =\n here.joint === \"throat\"\n ? frogAxial\n : here.joint === \"diverge\" || here.joint === \"legB\"\n ? frogPt && dvj\n ? Math.hypot(dvj.x - frogPt.x, dvj.y - frogPt.y)\n : Math.max(0, body - frogAxial)\n : Math.max(0, body - frogAxial);\n const frogPos = pos + toFrog;\n if (here.joint === \"diverge\" || here.joint === \"legB\") {\n // Arrived by a diverging end: this route has run into the far turnout\n // of a siding, which is what makes it a siding rather than a spur.\n //\n // ⚠️ ITS EXTENT IS THE FAR TURNOUT'S POSITION, not this branch's\n // accumulated arc. A siding climbs away from the main and back, so\n // its own rail is genuinely longer than the span it covers — reading\n // the arc here put a 13→73 siding's far end at 73.02. `fromPos`/\n // `toPos` mean where a track sits ALONG THE MODULE, so use the\n // position the main walk already established for that turnout.\n route.endsAt = here.piece;\n const known = turnouts.find((t) => t.id === here.piece);\n route.toPos = known ? known.pos : frogPos;\n break;\n }\n turnouts.push({ id: here.piece, pos: frogPos, onRoute: id, divergeRoute: null });\n for (const dj of [\"diverge\", \"legB\"]) {\n const dk = `${here.piece}.${dj}`;\n const d = byKey.get(dk);\n if (!d || queued.has(dk)) continue;\n queued.add(dk);\n // A branch BEGINS at the frog, but its joint is further along the\n // diverging rail. Losing that stretch makes every position downstream\n // creep, and on a ladder the error compounds.\n const fp =\n throat && body > 0\n ? {\n x: throat.x + ((d.x - throat.x) * frogAxial) / body,\n y: throat.y + ((d.y - throat.y) * frogAxial) / body,\n }\n : null;\n pending.push({\n from: here.piece,\n at: frogPos,\n joint: dk,\n skew: fp ? Math.hypot(d.x - fp.x, d.y - fp.y) : 0,\n });\n }\n }\n\n route.pieces.push(here.piece);\n for (const j of graph.joints)\n if (j.piece === here.piece && Math.abs(j.y) > Math.abs(route.lateral))\n route.lateral = j.y;\n const entered = pos;\n pos += gap(here, exit);\n route.spans.push({\n piece: here.piece, entryJoint: here.joint, exitJoint, fromPos: entered, toPos: pos,\n });\n route.toPos = pos;\n const next = exit ? link.get(exit.key) : undefined;\n if (!next) break;\n cur = next;\n }\n return route;\n };\n\n routes.push(walk(`${startAt.piece}.${startAt.joint}`, 0, \"main\", null));\n\n let n = 0;\n while (pending.length) {\n const b = pending.shift()!;\n const start = link.get(b.joint);\n if (!start) {\n warnings.push(danglingDivergeWarning(b.from));\n danglingDiverges.push(b.from);\n continue;\n }\n // ⚠️ A SIDING IS FOUND TWICE — once from each of its turnouts. Both queue a\n // diverging branch, and the second walks the same rail back the other way.\n // Walking it again would put the same track in the layout twice, on two\n // lanes, with the far turnout diverging onto the copy. A piece belongs to\n // exactly ONE route, so if this branch starts on a piece a route already\n // holds, the answer is that route: the far turnout diverges onto the siding\n // that is already there.\n const already = routes.find((r) => r.pieces.includes(byKey.get(start)!.piece));\n if (already) {\n const swFar = turnouts.find((t) => t.id === b.from);\n if (swFar && !swFar.divergeRoute) swFar.divergeRoute = already.id;\n continue;\n }\n n += 1;\n const r = walk(start, b.at + b.skew, `route${n}`, b.from);\n r.fromPos = b.at; // it begins at the frog, whatever its first joint is\n routes.push(r);\n const sw = turnouts.find((t) => t.id === b.from);\n if (sw && !sw.divergeRoute) sw.divergeRoute = r.id;\n }\n\n const reached = new Set(routes.flatMap((r) => r.pieces));\n const unreached: string[] = [];\n for (const p of pieces)\n if (!reached.has(p.id) && !graph.unplaceable.some((u) => u.piece === p.id)) {\n warnings.push(unreachedWarning(p.id));\n unreached.push(p.id);\n }\n for (const c of graph.conflicts) warnings.push(c.reason);\n\n return { routes, turnouts, warnings, danglingDiverges, unreached };\n}\n\n// ─── GRAPH → DOCUMENT (ADR 0001) ─────────────────────────────────────────────\n// The claim the whole decision rests on: the 1-D document becomes a DERIVED\n// artifact, so `moduleFeatures`, the dispatcher view and Free-Dispatcher are\n// unaffected. This is where that claim is demonstrated IN THE PACKAGE — the\n// graph emits an ordinary `ModuleSchematicDoc` and the same pure function reads\n// it. Nothing downstream is told which way a module was authored.\n\n/** Where an anchored feature turned out to be. */\nexport interface ResolvedAnchor {\n /** Inches from endplate A — the number the document and the dispatcher read. */\n pos: number;\n /** The route the anchored piece is part of. */\n routeId: string;\n /** The piece's own measuring direction runs BACKWARD along the route, so\n * increasing {@link GraphAnchor.atInches} moves toward endplate A. */\n reversed: boolean;\n}\n\n/**\n * Turn a {@link GraphAnchor} into a position along the module.\n *\n * The piece is measured from its own origin end, and the walk knows both ends\n * of it, so whichever end the route arrived by, the sum comes out the same.\n * Returns null when the anchored piece is not on any route — a spur nobody has\n * connected yet — which is a thing to report, not to guess at.\n */\nexport function resolveGraphAnchor(\n anchor: GraphAnchor,\n walk: GraphWalk,\n pieces: TrackPiece[],\n library = BUILT_IN_TRACK_PARTS,\n): ResolvedAnchor | null {\n const piece = pieces.find((p) => p.id === anchor.piece);\n const part = piece ? library.find((x) => x.id === piece.partId) : undefined;\n // Every part's own frame starts at x=0 at one joint: `a` on flex, the throat\n // on everything with points.\n const origin = part?.kind === \"flex\" ? \"a\" : \"throat\";\n for (const r of walk.routes) {\n const span = r.spans.find((s) => s.piece === anchor.piece);\n if (!span) continue;\n if (span.entryJoint === origin)\n return { pos: span.fromPos + anchor.atInches, routeId: r.id, reversed: false };\n if (span.exitJoint === origin)\n return { pos: span.toPos - anchor.atInches, routeId: r.id, reversed: true };\n // A wye crossed leg-to-leg never touches its throat, so there is no\n // measuring from it. Better to say so than to pick an end.\n return null;\n }\n return null;\n}\n\n/** What the graph cannot know, and therefore never invents. */\nexport interface GraphDocInput {\n /** Where the main begins: the joint endplate A's track arrives at. */\n startAt: { piece: string; joint: string };\n /** Where MAIN 2 begins, on a double-track module. Absent = single track. */\n start2?: { piece: string; joint: string } | null;\n /**\n * The rest of the document — module id, endplate identities, the benchwork,\n * industries and signals. Merged UNDERNEATH the derived keys, so the graph\n * wins on length, tracks and turnouts and on nothing else.\n *\n * ⏸️ Industries, signals and control points are PASSED THROUGH untouched.\n * Where they live in a graph is deliberately still open (ADR 0001 defers it\n * to persistence); carrying them is honest, re-deriving them would be a guess.\n */\n base?: Partial<ModuleSchematicDoc>;\n /**\n * Owner metadata for a run, keyed by the piece the run STARTS at — the piece\n * they select and name. Held here rather than on {@link TrackPiece} because\n * it describes the whole run, not the one piece.\n */\n meta?: Record<\n string,\n { trackName?: string; capacityFeet?: number | null; moduleTrackId?: number | null }\n >;\n library?: TrackPart[];\n}\n\nexport interface GraphDocResult {\n doc: ModuleSchematicDoc;\n graph: TrackGraph;\n walk: GraphWalk;\n /** The walk's warnings, plus anything the emission itself had to leave out. */\n warnings: string[];\n}\n\n/**\n * Derive a `ModuleSchematicDoc` from placed pieces.\n *\n * ⭐ **NO HAND IS EMITTED.** A turnout's `kind` is left unset on purpose. The\n * graph knows which side the diverging route is on — it is where the piece IS —\n * so the lane carries the side and `moduleFeatures` keeps the lane it is given\n * (`resolveLane` only overrides the sign for a stated left/right). Emitting a\n * hand as well would be a second source for one fact, which is the ~120 lines\n * of reconciliation this model exists to remove.\n *\n * ⚠️ ONE MAIN. The walk starts at one endplate, so a double-track module's\n * second main is not reached — it surfaces in `warnings` as unreachable pieces\n * rather than vanishing quietly. Emitting Main 2 needs a second start point and\n * is not built yet.\n */\nexport function graphToDoc(pieces: TrackPiece[], input: GraphDocInput): GraphDocResult {\n const library = input.library ?? BUILT_IN_TRACK_PARTS;\n const graph = buildTrackGraph(pieces, library);\n const walk = walkTrackGraph(graph, pieces, input.startAt, library);\n // ⚠️ ONE PROBLEM, ONE SENTENCE. The walk reports a diverging route that\n // reaches nothing, and the emission has its own thing to say about the same\n // turnout — printed together they read as two faults. Drop the walk's wording\n // in favour of the one below, which names the consequence as well as the fact.\n const dangling = new Set(walk.danglingDiverges.map(danglingDivergeWarning));\n const warnings = walk.warnings.filter((w) => !dangling.has(w));\n const round = (n: number) => Math.round(n * 100) / 100;\n\n const base = input.base ?? {};\n const endplates: SchematicEndplate[] =\n base.endplates && base.endplates.length\n ? base.endplates\n : [{ id: \"A\", label: \"West\" }, { id: \"B\", label: \"East\" }];\n const epA = endplates[0];\n const epB = endplates[1];\n\n const main = walk.routes.find((r) => r.id === \"main\")!;\n\n /**\n * MAIN 2 is its own walk, from its own end of the endplate.\n *\n * ⚠️ It is a SEPARATE RUN, not a branch: the two mains of a double-track\n * module never touch along their length. So it is walked independently and its\n * routes are kept apart by a prefix, because both walks name their own route\n * \"main\".\n */\n const walk2 = input.start2\n ? walkTrackGraph(graph, pieces, input.start2, library)\n : null;\n const main2 = walk2?.routes.find((r) => r.id === \"main\") ?? null;\n /**\n * ⚠️⚠️ **A CROSSOVER IS THE ONE PIECE TWO ROUTES MAY BOTH HOLD.** Everywhere\n * else \"this piece is already in a route\" means the two starts landed on the\n * same run and emitting it twice would put one piece of track in the document\n * as two. A double crossover is the exception BY CONSTRUCTION: both mains run\n * straight through the same assembly, which is what it is for. Counting it as\n * a collision made an ordinary double-track module with a crossover report its\n * two mains as one run and emit neither.\n */\n const sharedByDesign = (id: string) => {\n const piece = pieces.find((p) => p.id === id);\n return library.find((p) => p.id === piece?.partId)?.kind === \"crossover\";\n };\n const claimed = new Set(walk.routes.flatMap((r) => r.pieces).filter((p) => !sharedByDesign(p)));\n if (main2 && main2.pieces.some((p) => claimed.has(p))) {\n // Both starts landed on the same run. Emitting it twice would put one piece\n // of track in the document as two, on two lanes.\n warnings.push(\n \"Main 2 starts on track that Main 1 already runs along — they are one run, not two\",\n );\n }\n const twoMains = !!main2 && !main2.pieces.some((p) => claimed.has(p));\n\n // ⭐ WHICH SIDE MAIN 2 IS ON IS READ, NOT AUTHORED. The 1-D model needs a\n // `mainsSwapped` flag to say Main 2 draws below; here it is simply where the\n // track is. Module-local +y is above, and endplate A's track point is the\n // origin, so the sign of its first joint's offset is the answer.\n const main2Lane = twoMains\n ? (graph.joints.find((j) => j.key === `${input.start2!.piece}.${input.start2!.joint}`)?.y ?? 1) >= 0\n ? 1\n : -1\n : 0;\n\n const lengthInches = round(Math.max(main.toPos, twoMains ? main2!.toPos : 0));\n\n // A branch takes the id of the piece it STARTS at — the run's own first piece.\n // It is the piece an owner selects, so it is the thing their name belongs to.\n // ⚠️ Not stable against inserting a piece at the throat: that changes the id.\n // Persisting the graph will need a run identity of its own; nothing yet reads\n // these ids back.\n const branches = [\n ...walk.routes.filter((r) => r.id !== \"main\" && r.pieces.length),\n ...(twoMains\n ? walk2!.routes\n .filter((r) => r.id !== \"main\" && r.pieces.length)\n .map((r) => ({ ...r, id: `main2:${r.id}`, bornAt: r.bornAt }))\n : []),\n ];\n const trackIdOf = new Map<string, string>([[\"main\", MAIN_TRACK_ID]]);\n if (twoMains) trackIdOf.set(\"main2:main\", MAIN2_TRACK_ID);\n for (const r of branches) trackIdOf.set(r.id, r.pieces[0]);\n // ⚠️ A CROSSOVER IS FOUND BY BOTH WALKS — once from each main, exactly as a\n // siding is found from each of its turnouts, but now across two walks. The\n // two finds name the same first piece, so they resolve to the same track id\n // and the second is dropped rather than emitted as a phantom second\n // connector. Both turnouts still point at the one that remains.\n const emitted = new Set<string>();\n const uniqueBranches = branches.filter((r) => {\n const id = trackIdOf.get(r.id)!;\n if (emitted.has(id)) return false;\n emitted.add(id);\n return true;\n });\n\n // LANE is an ordinal: which side, and how many tracks out. The side is the\n // sign of how far the run reaches laterally; the magnitude is its rank among\n // the runs on that side, so a spur off a spur stacks OUTSIDE its parent.\n //\n // ⚠️ MAIN 2 ALREADY OCCUPIES A LANE on its own side, so branches there start\n // at 2. Ranking branches alone put the first siding above the main on lane 1\n // — the same lane as Main 2 — and the two drew on top of each other.\n const laneOf = (r: GraphRoute, among: GraphRoute[]): number => {\n const side = Math.sign(r.lateral) || 1;\n const sameSide = among\n .filter((x) => (Math.sign(x.lateral) || 1) === side)\n .sort((a, b) => Math.abs(a.lateral) - Math.abs(b.lateral));\n const taken = side === main2Lane ? 1 : 0;\n return side * (sameSide.indexOf(r) + 1 + taken);\n };\n\n const tracks: SchematicTrack[] = [\n {\n id: MAIN_TRACK_ID,\n role: \"main\",\n lane: 0,\n from: epA?.id ?? \"A\",\n ...(epB ? { to: epB.id } : {}),\n // A main can be closed too — that is a pocket module, where the track\n // runs in and stops rather than crossing to a second endplate.\n ...(main.closedBy ? { bumperAt: \"to\" as const } : {}),\n },\n ...(twoMains\n ? [\n {\n id: MAIN2_TRACK_ID,\n role: \"main\" as const,\n lane: main2Lane,\n from: epA?.id ?? \"A\",\n ...(epB ? { to: epB.id } : {}),\n // ⚠️ Its own extent, because a second main need not run the whole\n // module: on a transition module it starts or stops partway.\n fromPos: round(Math.min(main2!.fromPos, main2!.toPos)),\n toPos: round(Math.max(main2!.fromPos, main2!.toPos)),\n },\n ]\n : []),\n ];\n for (const r of uniqueBranches) {\n const id = trackIdOf.get(r.id)!;\n const meta = input.meta?.[id] ?? {};\n tracks.push({\n id,\n // It runs back into a second turnout, or it doesn't. That is the whole\n // difference between a siding and a spur, and it is read, not declared.\n role: r.endsAt ? \"siding\" : \"spur\",\n lane: laneOf(r, uniqueBranches),\n fromPos: round(Math.min(r.fromPos, r.toPos)),\n toPos: round(Math.max(r.fromPos, r.toPos)),\n // ⚠️ ALWAYS THE `to` END, and not because of an assumption: a branch's\n // positions are ARC LENGTH FROM ITS THROAT, so they only ever grow — a\n // spur running physically back toward endplate A still ends at the larger\n // number. The closed end is the far one from the turnout, by definition.\n ...(r.closedBy ? { bumperAt: \"to\" as const } : {}),\n ...(meta.trackName ? { trackName: meta.trackName } : {}),\n ...(meta.capacityFeet != null ? { capacityFeet: meta.capacityFeet } : {}),\n ...(meta.moduleTrackId != null ? { moduleTrackId: meta.moduleTrackId } : {}),\n });\n }\n\n if (walk2) {\n // ⚠️ EACH WALK CALLS THE OTHER MAIN UNREACHABLE, and neither is right. A\n // walk only knows what IT got to; with two starts, a piece reached by\n // either one is connected. Told as it stood, a perfectly ordinary\n // double-track module reported both of its mains as stray track.\n const seen = new Set([\n ...walk.routes.flatMap((r) => r.pieces),\n ...walk2.routes.flatMap((r) => r.pieces),\n ]);\n const covered = new Set([...walk.unreached, ...walk2.unreached].filter((id) => seen.has(id)));\n const drop = new Set([...covered].map(unreachedWarning));\n const d2 = new Set(walk2.danglingDiverges.map(danglingDivergeWarning));\n for (let i = warnings.length - 1; i >= 0; i--) if (drop.has(warnings[i])) warnings.splice(i, 1);\n for (const w of walk2.warnings)\n if (!d2.has(w) && !drop.has(w) && !warnings.includes(w)) warnings.push(w);\n }\n\n const pieceById = new Map(pieces.map((p) => [p.id, p]));\n const turnouts: SchematicTurnout[] = [];\n const allTurnouts = [\n ...walk.turnouts,\n ...(twoMains\n ? walk2!.turnouts.map((t) => ({\n ...t,\n onRoute: t.onRoute === \"main\" ? \"main2:main\" : `main2:${t.onRoute}`,\n divergeRoute: t.divergeRoute ? `main2:${t.divergeRoute}` : null,\n }))\n : []),\n ];\n for (const t of allTurnouts) {\n const diverge = t.divergeRoute ? trackIdOf.get(t.divergeRoute) : undefined;\n if (!diverge) {\n // A turnout whose diverging route reaches nothing is an unfinished layout,\n // not an operating turnout. Said out loud rather than emitted with a\n // dangling reference for the dispatcher view to trip over.\n warnings.push(\n `${t.id} is placed but its diverging route goes nowhere, so it is not in the operations view`,\n );\n continue;\n }\n const piece = pieceById.get(t.id);\n const part = piece ? library.find((p) => p.id === piece.partId) : undefined;\n turnouts.push({\n id: t.id,\n pos: round(t.pos),\n onTrack: trackIdOf.get(t.onRoute) ?? MAIN_TRACK_ID,\n divergeTrack: diverge,\n ...(piece?.name ? { name: piece.name } : {}),\n ...(part?.frogNumber != null ? { size: part.frogNumber } : {}),\n ...(part ? { partId: part.id } : {}),\n });\n }\n /**\n * ⭐⭐ A DOUBLE CROSSOVER IS ONE PIECE, AND THE DOCUMENT NEEDS FOUR TURNOUTS\n * AND TWO CONNECTORS OUT OF IT.\n *\n * Emitted here rather than through the walk's turnout machinery, because the\n * walk records one turnout per PIECE and this piece carries four point-sets.\n * Everything needed is already known: {@link crossoverAssembly} says where the\n * point-sets sit inside the assembly, and the walk's own\n * {@link RouteSpan.fromPos} says where the assembly sits on each main. So the\n * operations view gets the four turnouts and both crossing moves it needs,\n * while the physical view keeps drawing the single moulding that is really\n * there.\n *\n * ⚠️ It only emits when BOTH mains actually run through the assembly. Half a\n * double crossover is not a thing, and a piece reached from one main only\n * means the other main is not connected to it — which the open-end and\n * unreachable reporting already says, without inventing a turnout here.\n */\n const crossoverSpans = (() => {\n const found: {\n piece: string;\n part: TrackPart;\n /** By track index (1 = joints a1/b1, 2 = a2/b2): route id + the two\n * point-set positions along that route. */\n byTrack: Map<number, { routeId: string; at: [number, number] }>;\n }[] = [];\n const routesAll = [\n ...walk.routes.map((r) => ({ r, prefix: \"\" })),\n ...(twoMains ? walk2!.routes.map((r) => ({ r, prefix: \"main2:\" })) : []),\n ];\n const seen = new Map<string, (typeof found)[number]>();\n for (const { r, prefix } of routesAll) {\n for (const sp of r.spans) {\n const piece = pieceById.get(sp.piece);\n const part = piece ? library.find((p) => p.id === piece.partId) : undefined;\n if (!part || part.kind !== \"crossover\") continue;\n const g = crossoverAssembly(part);\n if (!g) continue;\n const [p1, p2] = g.pointsAtInches;\n // Entered from the west end the point-sets are p1 then p2 along; from\n // the east end the assembly is walked backwards.\n const west = sp.entryJoint.startsWith(\"a\");\n const at: [number, number] = west\n ? [sp.fromPos + p1, sp.fromPos + p2]\n : [sp.fromPos + (g.lengthInches - p2), sp.fromPos + (g.lengthInches - p1)];\n const track = sp.entryJoint.endsWith(\"2\") ? 2 : 1;\n const routeId = r.id === \"main\" && prefix ? \"main2:main\" : `${prefix}${r.id}`;\n const rec =\n seen.get(sp.piece) ?? { piece: sp.piece, part, byTrack: new Map() };\n rec.byTrack.set(track, { routeId, at });\n seen.set(sp.piece, rec);\n }\n }\n for (const rec of seen.values()) if (rec.byTrack.size === 2) found.push(rec);\n return found;\n })();\n\n for (const xo of crossoverSpans) {\n const one = xo.byTrack.get(1)!;\n const two = xo.byTrack.get(2)!;\n const onA = trackIdOf.get(one.routeId) ?? MAIN_TRACK_ID;\n const onB = trackIdOf.get(two.routeId) ?? MAIN2_TRACK_ID;\n // The two crossing moves. A goes track 1 → track 2, B the other way; each\n // spans the same stretch of the module, which is what a scissors looks like.\n const legs: { id: string; from: [string, number]; to: [string, number] }[] = [\n { id: `${xo.piece}-a`, from: [onA, one.at[0]], to: [onB, two.at[1]] },\n { id: `${xo.piece}-b`, from: [onB, two.at[0]], to: [onA, one.at[1]] },\n ];\n for (const leg of legs) {\n tracks.push({\n id: leg.id,\n role: \"crossover\",\n // The connector lives between the mains, so it takes Main 2's lane —\n // the same lane the 1-D model has always drawn a crossover in.\n lane: main2Lane ?? 1,\n fromPos: round(Math.min(leg.from[1], leg.to[1])),\n toPos: round(Math.max(leg.from[1], leg.to[1])),\n trackName: xo.part.name ?? \"Crossover\",\n crossoverPartId: xo.part.id,\n });\n turnouts.push(\n {\n id: `${leg.id}-1`,\n pos: round(leg.from[1]),\n onTrack: leg.from[0],\n divergeTrack: leg.id,\n name: xo.part.name ?? \"Crossover\",\n ...(xo.part.frogNumber != null ? { size: xo.part.frogNumber } : {}),\n },\n {\n id: `${leg.id}-2`,\n pos: round(leg.to[1]),\n onTrack: leg.to[0],\n divergeTrack: leg.id,\n name: xo.part.name ?? \"Crossover\",\n ...(xo.part.frogNumber != null ? { size: xo.part.frogNumber } : {}),\n },\n );\n }\n }\n\n turnouts.sort((a, b) => a.pos - b.pos);\n\n /**\n * ⭐ A CONNECTOR BETWEEN TWO DIFFERENT MAINS IS A CROSSOVER, not a siding.\n *\n * Both are \"a track with a turnout at each end\"; what separates them is\n * whether those turnouts sit on the SAME track. A siding leaves the main and\n * comes back to it; a crossover goes somewhere else. That is the same test\n * `moduleFeatures` applies to decide whether to draw a diagonal or a\n * lane-paralleling band, so deciding it here means the document says what the\n * drawing will do instead of leaving both to work it out separately.\n *\n * Read, not authored — like everything else in this model.\n */\n for (const t of tracks) {\n if (t.role === \"main\") continue;\n const ends = turnouts.filter((sw) => sw.divergeTrack === t.id);\n if (ends.length >= 2 && new Set(ends.map((sw) => sw.onTrack)).size >= 2)\n t.role = \"crossover\";\n }\n\n // ⭐ ANCHORED FEATURES ARE PLACED BY THE PIECE THEY ARE BESIDE, not by a\n // number about the module. Unanchored ones keep exactly the positions their\n // owner typed — nothing migrates (ADR 0001).\n const place = (a: GraphAnchor | null | undefined, what: string) => {\n if (!a) return null;\n const hit = resolveGraphAnchor(a, walk, pieces, library);\n if (!hit) {\n warnings.push(\n `${what} is anchored to ${a.piece}, which is not on any route — its authored position stands`,\n );\n return null;\n }\n return hit;\n };\n /** A span keeps its authored LENGTH and takes its start from the anchor. */\n const spanAt = (hit: ResolvedAnchor, from: number, to: number): [number, number] => {\n const len = Math.abs(to - from);\n return hit.reversed\n ? [round(hit.pos - len), round(hit.pos)]\n : [round(hit.pos), round(hit.pos + len)];\n };\n\n const industries = base.industries?.map((ind) => {\n const hit = place(ind.anchor, `industry \"${ind.name}\"`);\n const spots = ind.spots?.map((s) => {\n const sh = place(s.anchor, `a spot of industry \"${ind.name}\"`);\n if (!sh) return s;\n const [from, to] = spanAt(sh, s.fromPos, s.toPos);\n return { ...s, track: trackIdOf.get(sh.routeId) ?? s.track, fromPos: from, toPos: to };\n });\n if (!hit) return spots ? { ...ind, spots } : ind;\n const [fromPos, toPos] = spanAt(hit, ind.fromPos, ind.toPos);\n return {\n ...ind,\n track: trackIdOf.get(hit.routeId) ?? ind.track,\n fromPos,\n toPos,\n ...(spots ? { spots } : {}),\n };\n });\n\n const signals = base.signals?.map((sig) => {\n const hit = place(sig.anchor, `signal \"${sig.name ?? sig.id}\"`);\n return hit\n ? { ...sig, pos: round(hit.pos), track: trackIdOf.get(hit.routeId) ?? sig.track }\n : sig;\n });\n\n const doc: ModuleSchematicDoc = {\n version: 1,\n ...base,\n lengthInches,\n endplates,\n tracks,\n turnouts,\n ...(industries ? { industries } : {}),\n ...(signals ? { signals } : {}),\n };\n return { doc, graph, walk, warnings };\n}\n\n/**\n * Bring a document up to date with the track its owner drew.\n *\n * A document with no `graph` is returned UNTOUCHED — that is the ADR's\n * no-migration rule in one line, and it is why every module authored before this\n * keeps behaving exactly as it did. With a graph, the tracks and turnouts are\n * re-read off the pieces and written back into the ordinary document keys, so\n * the module is stored in a form every existing reader already understands.\n *\n * ⭐ Owners' names, capacities and `module_tracks` links are carried across from\n * the tracks already in the document, keyed by id. Re-deriving must never cost\n * an owner the name they gave a siding.\n */\nexport function deriveGraphDoc(\n doc: ModuleSchematicDoc,\n library = BUILT_IN_TRACK_PARTS,\n): { doc: ModuleSchematicDoc; warnings: string[] } {\n const g = doc.graph;\n if (!g || !g.pieces?.length || !g.startAt) return { doc, warnings: [] };\n const meta: NonNullable<GraphDocInput[\"meta\"]> = {};\n for (const t of doc.tracks ?? []) {\n if (t.role === \"main\") continue;\n meta[t.id] = {\n ...(t.trackName ? { trackName: t.trackName } : {}),\n ...(t.capacityFeet != null ? { capacityFeet: t.capacityFeet } : {}),\n ...(t.moduleTrackId != null ? { moduleTrackId: t.moduleTrackId } : {}),\n };\n }\n const out = graphToDoc(g.pieces, {\n startAt: g.startAt,\n start2: g.start2 ?? null,\n base: doc,\n meta,\n library,\n });\n return { doc: out.doc, warnings: out.warnings };\n}\n\n/**\n * What a turnout in a 1-D document would become as a piece — or what it is\n * missing before it can become anything.\n *\n * ⭐⭐ **IDENTITY IS THE GATE, NOT GEOMETRY.** This is the thing that surprised\n * us and it is worth stating plainly: converting a drawn module to pieces is\n * blocked far more often by not knowing WHICH TURNOUT IT IS than by any missing\n * measurement. Across the production database not one turnout names a part, and\n * most state no frog number either — so for those there is nothing to look up.\n * No amount of measuring fixes that; only the owner knows what they laid, which\n * is exactly why conversion asks instead of guessing.\n */\nexport interface TurnoutIdentity {\n /** The turnout's id in the document. */\n id: string;\n name?: string | null;\n pos: number;\n /** The frog number the document states, if any. */\n size?: number | null;\n /** A part the document already names — the strongest possible answer. */\n statedPartId?: string | null;\n /** The part this turnout converts to; null = the owner has to say. */\n partId: string | null;\n /** How `partId` was arrived at. `assembly` = this is a crossover's own\n * point-set, and the crossover product answers for it. */\n from: \"named\" | \"frog-number\" | \"unresolved\" | \"assembly\";\n /**\n * The weakest provenance behind the chosen part's geometry, so a caller can\n * tell a turnout placed from real readings from one placed off a catalogue\n * figure. Null when unresolved.\n */\n source: DimensionSource | null;\n /** Why it cannot be resolved — null when it can. */\n why: string | null;\n /**\n * Parts the owner could reasonably pick, best first: an exact frog match\n * ahead of the rest. Only PLACEABLE parts are offered — listing one that\n * cannot be drawn would be an answer that does not answer.\n */\n candidates: string[];\n}\n\n/** Something that stops a whole document converting, whatever the owner says. */\nexport interface ConversionBlocker {\n /** `crossing` · `curved-turnout` · `loop` — the shapes with no piece to be. */\n kind: string;\n /** The document object it came from, where there is one. */\n ref?: string;\n why: string;\n}\n\n/**\n * A track the document draws but nothing in it connects — no turnout diverges\n * onto it.\n *\n * ⚠️⚠️ **THE 1-D MODEL TOLERATES THIS AND THE GRAPH CANNOT.** A siding is drawn\n * from its `lane` and its `fromPos`/`toPos` alone, so a document can carry a\n * named, capacity-bearing yard track that joins nothing at all and still look\n * completely normal. Real ones do: Idaho Falls Grain Yard has five yard tracks\n * and not one turnout. A piece, by contrast, has to be joined to something.\n *\n * So these are surfaced rather than converted. Dropping them would lose an\n * owner's named track and its capacity silently, and inventing a turnout to\n * reach it would be exactly the fabrication ADR 0001 forbids — the owner is the\n * only one who knows where it actually joins.\n */\nexport interface OrphanTrack {\n id: string;\n trackName?: string;\n role: TrackRole;\n why: string;\n}\n\nexport interface ModuleConversionReport {\n /** Already authored as pieces — there is nothing to convert. */\n alreadyGraph: boolean;\n /**\n * The rebuild can be offered. False when {@link blockers} is non-empty: those\n * are shapes no answer can supply, so offering would promise something that\n * cannot finish.\n */\n offerable: boolean;\n /**\n * True when the rebuild could run right now with nothing asked.\n *\n * ⚠️ Requires BOTH that every turnout resolves and that no track is orphaned.\n * Checking only the turnouts claimed four production modules were ready when\n * converting them would have quietly dropped nine named tracks.\n */\n readyWithoutAsking: boolean;\n turnouts: TurnoutIdentity[];\n /** Ids of the turnouts the owner must identify first. */\n unanswered: string[];\n orphanTracks: OrphanTrack[];\n blockers: ConversionBlocker[];\n}\n\n/** A part that IS this frog number and can actually be drawn — never a nearby\n * one. A #6 is not a #5 (see {@link partExtentForSize}); silently converting a\n * #6 into the #7 we happen to have measured would put a real turnout's frog in\n * a place the owner never built it. */\nfunction placeableTurnoutParts(library: TrackPart[], kind: TrackPart[\"kind\"][]): TrackPart[] {\n // ⛔ NO STAND-INS. This answers \"which real part is this?\", both for automatic\n // resolution and for the candidates offered beside it. A placeholder is a\n // separate, explicitly-chosen fallback — see `provisionalParts`.\n return library.filter(\n (p) => kind.includes(p.kind) && !p.provisional && partGeometryGap(p) == null,\n );\n}\n\n/**\n * What would happen if this document were rebuilt as pieces — WITHOUT rebuilding\n * anything.\n *\n * This exists so an owner can be shown the offer and its cost before they accept\n * it (ADR 0001 amendment, 2026-07-27: conversion is opt-in PER MODULE, never\n * silent). It is pure, cheap, reads no geometry, and is safe to run on every\n * module in a list.\n *\n * ⚠️ **A document with a graph is NOT re-reported.** It is already the thing\n * conversion produces.\n */\nexport function moduleConversionReport(\n doc: ModuleSchematicDoc,\n library = BUILT_IN_TRACK_PARTS,\n): ModuleConversionReport {\n if (doc.graph?.pieces?.length) {\n return {\n alreadyGraph: true,\n offerable: false,\n readyWithoutAsking: false,\n turnouts: [],\n unanswered: [],\n orphanTracks: [],\n blockers: [],\n };\n }\n\n const straight = placeableTurnoutParts(library, [\"turnout\"]);\n const curved = placeableTurnoutParts(library, [\"curved-turnout\"]);\n const blockers: ConversionBlocker[] = [];\n\n /**\n * ⭐ A CROSSOVER'S OWN POINT-SETS ARE ALREADY ANSWERED.\n *\n * The document names the crossover product on its connectors, and a double\n * crossover is ONE assembly whose four point-sets come with it. Asking \"which\n * turnout is this?\" about them asks an owner to identify parts of a product\n * they have already named — and on a #6 crossover it asked for a measured #6\n * TURNOUT, which has nothing to do with it.\n */\n const assemblyPart = new Map<string, TrackPart>();\n for (const t of doc.tracks ?? []) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = library.find((p) => p.id === t.crossoverPartId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n for (const sw of doc.turnouts ?? [])\n if (sw.divergeTrack === t.id) assemblyPart.set(sw.id, part);\n }\n\n const turnouts: TurnoutIdentity[] = (doc.turnouts ?? []).map((t) => {\n const asm = assemblyPart.get(t.id);\n if (asm)\n return {\n id: t.id,\n name: t.name,\n pos: t.pos,\n size: t.size,\n statedPartId: t.partId,\n partId: asm.id,\n from: \"assembly\" as const,\n source: partGeometry(asm, library)?.source ?? null,\n why: null,\n candidates: [],\n };\n const wantCurved = t.curved === true;\n const pool = wantCurved ? curved : straight;\n const base = {\n id: t.id,\n name: t.name,\n pos: t.pos,\n size: t.size,\n statedPartId: t.partId,\n };\n // An exact frog match first, then everything placeable — the owner may know\n // the part even where the document's frog number is wrong or absent.\n const exact = t.size == null ? [] : pool.filter((p) => p.frogNumber === t.size);\n const candidates = [...exact, ...pool.filter((p) => !exact.includes(p))].map((p) => p.id);\n const resolve = (part: TrackPart, from: TurnoutIdentity[\"from\"]): TurnoutIdentity => ({\n ...base,\n partId: part.id,\n from,\n source: partGeometry(part, library)?.source ?? null,\n why: null,\n candidates,\n });\n\n // 1. The document names a part. Strongest answer there is — provided we can\n // draw it. A named part we cannot place is still unanswered, but the\n // reason names the measurement rather than the owner.\n if (t.partId) {\n const named = library.find((p) => p.id === t.partId);\n if (named && partGeometryGap(named) == null) return resolve(named, \"named\");\n return {\n ...base,\n partId: null,\n from: \"unresolved\",\n source: null,\n why: named\n ? `this turnout names ${named.id}, which cannot be placed yet — ${partGeometryGap(named)}`\n : `this turnout names a part the library does not have (${t.partId})`,\n candidates,\n };\n }\n\n // 2. A frog number, and a placeable part that IS that frog number.\n if (t.size != null && exact.length) return resolve(exact[0], \"frog-number\");\n\n // 3. Everything else is a question for the owner. The two reasons are\n // genuinely different and an owner can act on the difference: one is a\n // measurement nobody has taken, the other is a fact only they hold.\n return {\n ...base,\n partId: null,\n from: \"unresolved\",\n source: null,\n why:\n t.size == null\n ? \"the document never says what this turnout is — no part, no frog number\"\n : wantCurved\n ? `no curved turnout is placeable yet, so a curved #${t.size} cannot be converted`\n : `no measured #${t.size} in the parts library yet`,\n candidates,\n };\n });\n\n // ⚠️ BLOCKERS ARE NOT QUESTIONS. A question has an answer the owner can give;\n // these are shapes the piece model cannot express at all yet, so the offer is\n // withheld rather than made and then abandoned half way.\n /**\n * ⚠️⚠️ A TURNOUT THAT OPENS A MAIN — a single-to-double transition, or a\n * crossover written as two bare turnouts with no connector between them.\n *\n * Both mains are laid as their own runs from endplate A, so a main that\n * actually BEGINS at a turnout is laid somewhere that turnout does not reach:\n * its diverging route then goes nowhere, `graphToDoc` drops the turnout, and\n * the module comes out with one fewer main and no turnout at all. It did that\n * silently on FMN-0075, whose preview promised \"1 turnout\" and produced none —\n * the branch pass never even looked, because a main is laid before it runs.\n *\n * Withheld rather than half-converted: losing a main is losing half the\n * module, and no answer an owner can give supplies it. The standard actively\n * recommends building transition modules, so this shape is common and will\n * need proper support — laying the second main off the turnout the way a\n * branch is laid, while keeping its `main` role in the emitted document.\n */\n const mainIds = new Set((doc.tracks ?? []).filter((t) => t.role === \"main\").map((t) => t.id));\n for (const t of doc.turnouts ?? []) {\n if (!mainIds.has(t.divergeTrack)) continue;\n blockers.push({\n kind: \"turnout-opens-a-main\",\n ref: t.id,\n why: `${t.name || t.id} opens ${t.divergeTrack}, which is a main — a main that begins at a turnout cannot be laid as pieces yet, and converting anyway would drop both it and the turnout`,\n });\n }\n\n for (const c of doc.crossings ?? [])\n blockers.push({\n kind: \"crossing\",\n ref: c.id,\n why: \"crossing geometry is not modelled yet, so a diamond has no piece to become\",\n });\n if (doc.loop)\n blockers.push({\n kind: \"loop\",\n why:\n \"a balloon's curve radii were never recorded, and laying the loop would mean \" +\n \"inventing them — the one thing ADR 0001 forbids\",\n });\n\n // A track is reached by a turnout DIVERGING onto it. Appearing as a turnout's\n // `onTrack` does not count: that says something branches OFF this track, which\n // still leaves it needing a way in of its own.\n const reached = new Set((doc.turnouts ?? []).map((t) => t.divergeTrack));\n const orphanTracks: OrphanTrack[] = (doc.tracks ?? [])\n // A main is reached by definition — it starts at the endplate.\n .filter((t) => t.role !== \"main\" && !reached.has(t.id))\n .map((t) => ({\n id: t.id,\n ...(t.trackName ? { trackName: t.trackName } : {}),\n role: t.role,\n why: \"no turnout in the document diverges onto this track, so there is nothing to join it to\",\n }));\n\n const unanswered = turnouts.filter((t) => !t.partId).map((t) => t.id);\n return {\n alreadyGraph: false,\n offerable: blockers.length === 0,\n readyWithoutAsking:\n blockers.length === 0 && unanswered.length === 0 && orphanTracks.length === 0,\n turnouts,\n unanswered,\n orphanTracks,\n blockers,\n };\n}\n\n/**\n * What the owner said when offered the rebuild.\n *\n * ⭐ **ONE ANSWER FOR THE WHOLE MODULE.** Owners lay one kind of turnout\n * throughout, or at most two, so asking per turnout asks the same question eight\n * times on a yard. The module-wide answer IS the question; `overrides` is for the\n * odd one out. (Will's call, 2026-07-27 — it turns 41 questions across the\n * production database into 14.)\n */\nexport interface ConversionAnswers {\n /** \"The turnouts on this module are…\" — a part id from the library. */\n turnoutPartId?: string | null;\n /** The exceptions, by turnout id. Beats {@link turnoutPartId}. */\n overrides?: Record<string, string>;\n}\n\nexport interface DocToGraphResult {\n /** The graph to store, or null when the document could not be converted. */\n graph: NonNullable<ModuleSchematicDoc[\"graph\"]> | null;\n /** Why the whole conversion was refused — null when it ran. */\n refused: string | null;\n /**\n * Track the conversion could not lay, each with a reason.\n *\n * ⚠️ **A REAL LOSS, AND THE OWNER MUST SEE IT.** Unshown, a \"successful\"\n * rebuild would quietly be missing a named siding.\n */\n notLaid: { id: string; why: string }[];\n warnings: string[];\n}\n\n/** Below this a transition curve is not something anyone laid by hand. Flagged,\n * never corrected — the house rule (see {@link FREEMO_MAIN_MIN_RADIUS_INCHES}). */\nconst CONVERSION_TIGHT_RADIUS_INCHES = 12;\n\n/**\n * Rebuild a 1-D document as a graph of placed pieces.\n *\n * ⭐ **THE OWNER ASKED FOR THIS ONE MODULE** (ADR 0001 amendment, 2026-07-27).\n * Nothing calls it on a schedule, on load, or in bulk. Conversion supplies\n * geometry the 1-D document never recorded, which is what the original\n * constraint forbade doing behind an owner's back; done in front of them, having\n * shown them {@link moduleConversionReport} and taken their answer, it is an\n * edit they made.\n *\n * ⚠️ **STRAIGHT HOSTS ONLY.** A run is laid along its host's axis, so a module\n * whose main is DRAWN with bends is refused rather than quietly straightened.\n * Every module in production today has a straight main; the refusal is there so\n * the first curved one is a message and not a flattened drawing.\n *\n * ⭐ **PIECES CHAIN FROM MEASURED JOINTS, NOT FROM ABSOLUTE ARITHMETIC.** Each\n * piece is placed, its real joints are read back with {@link placedJoints}, and\n * the next starts from one of those. Connection then holds BY CONSTRUCTION\n * rather than by two independent calculations agreeing to within\n * {@link JOINT_SNAP_INCHES} — a hundredth of an inch is far too tight to hit by\n * coincidence.\n *\n\n * ⭐ A TURNOUT'S THROAT GOES AT `pos − frogOffset`: a document's `pos` is the\n * That is the inverse of what {@link walkTrackGraph} reports, which is the only\n * thing that makes convert-then-derive an identity. It is deliberately NOT\n * {@link turnoutOccupiedSpan}'s anchor, and the two disagree by\n * `lead − pointsOffset` — 2.97″ on an Atlas #7. That disagreement is real and\n * unresolved: see the note on {@link moduleConversionReport}. Because of it the\n * flex gaps here are measured off the placed pieces' OWN joints rather than\n * through the 1-D helper, so whichever anchor turns out to be right, the track\n * still meets the turnout it was cut for.\n */\nexport function docToGraph(\n doc: ModuleSchematicDoc,\n answers: ConversionAnswers = {},\n library = BUILT_IN_TRACK_PARTS,\n): DocToGraphResult {\n const refuse = (why: string): DocToGraphResult => ({\n graph: null,\n refused: why,\n notLaid: [],\n warnings: [],\n });\n\n const report = moduleConversionReport(doc, library);\n if (report.alreadyGraph) return refuse(\"this module is already authored as pieces\");\n if (!report.offerable) return refuse(report.blockers.map((b) => b.why).join(\"; \"));\n if ((doc.mainPath?.length ?? 0) > 2)\n return refuse(\n \"this module's mainline is drawn with bends, and laying it as pieces would need each bend's radius — convert it once curved runs are supported\",\n );\n\n const partById = new Map(library.map((p) => [p.id, p]));\n\n /**\n * ⭐ Turnouts that are a CROSSOVER ASSEMBLY'S OWN POINT-SETS.\n *\n * The assembly answers for them, so they are neither asked about nor laid\n * individually. Without this an owner is asked \"which turnout is this?\" about\n * four point-sets of a product they have already named — and on FMN-0078,\n * whose crossovers are #6, the whole conversion refused for want of a measured\n * #6 turnout that has nothing to do with it.\n */\n const inAssembly = new Set<string>();\n for (const t of doc.tracks ?? []) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const part = partById.get(t.crossoverPartId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n for (const sw of doc.turnouts ?? []) if (sw.divergeTrack === t.id) inAssembly.add(sw.id);\n }\n\n const chosen = new Map<string, TrackPart>();\n const unknown: string[] = [];\n for (const t of report.turnouts) {\n if (inAssembly.has(t.id)) continue;\n const id = answers.overrides?.[t.id] ?? (t.partId ? t.partId : answers.turnoutPartId) ?? null;\n const part = id ? partById.get(id) : undefined;\n if (!part || partGeometryGap(part)) unknown.push(t.id);\n else chosen.set(t.id, part);\n }\n if (unknown.length)\n return refuse(\n `${unknown.length} turnout${unknown.length === 1 ? \"\" : \"s\"} still need identifying: ${unknown.join(\", \")}`,\n );\n\n const flexId = DEFAULT_FLEX_PART_ID;\n if (!partById.get(flexId)) return refuse(\"the parts library has no flex track to lay plain track with\");\n const maxPiece = maxFlexPieceInches(flexId, library);\n\n const tracks = doc.tracks ?? [];\n const trackById = new Map(tracks.map((t) => [t.id, t]));\n const turnouts = doc.turnouts ?? [];\n const mainLen =\n doc.lengthInches ??\n Math.max(0, ...tracks.map((t) => t.toPos ?? 0), ...turnouts.map((t) => t.pos));\n if (!(mainLen > 0)) return refuse(\"this module has no length to lay track along\");\n\n const pieces: TrackPiece[] = [];\n const notLaid: { id: string; why: string }[] = [];\n const warnings: string[] = [];\n const rad = (d: number) => (d * Math.PI) / 180;\n /** Signed turn, −180…180 — a heading difference has a SIDE, and `norm360`\n * would report a small left turn as 359°. */\n const norm180 = (d: number) => ((((d + 180) % 360) + 360) % 360) - 180;\n const r3 = (n: number) => Math.round(n * 1000) / 1000;\n const jointsOf = (p: TrackPiece) => placedJoints([p], library);\n const jointAt = (p: TrackPiece, id: string) => jointsOf(p).find((j) => j.joint === id) ?? null;\n type Cursor = { x: number; y: number; headingDeg: number };\n\n /**\n * A transition curve: leave `from` on its current heading, arrive parallel to\n * the module axis at `toY`.\n *\n * ⭐ **THE RADIUS IS DERIVED, NOT INVENTED.** Turning through θ moves a run\n * R(1 − cos θ) sideways, so the document's own lane offset and the part's own\n * frog angle fix R between them. Nothing here is a preference. It is also what\n * track physically does: the turnout throws the rail out at the frog angle and\n * a curve brings it back parallel. The 1-D model's instant jump to a lane\n * offset is the thing that was never real.\n */\n const transition = (\n id: string,\n from: Cursor,\n toY: number,\n /** +1 running east, −1 running west. ⚠️ A SIDING'S CLOSING CURVE RUNS THE\n * OTHER WAY, and measuring its heading against +x called an 8° turn a 172°\n * one — which came out as a 0.3″ radius instead of 51″. Everything here is\n * relative to the direction of travel. */\n dirSign: 1 | -1 = 1,\n ): TrackPiece | null => {\n const theta = rad(norm180(from.headingDeg - (dirSign > 0 ? 0 : 180)));\n // The piece's own +y is the module's +y only when it runs east.\n const dy = (toY - from.y) * dirSign;\n if (Math.abs(theta) < 1e-9 || Math.abs(dy) < 1e-9) return null;\n const R = dy / (1 - Math.cos(theta));\n if (!Number.isFinite(R) || R === 0) return null;\n const mag = Math.abs(R);\n if (mag < CONVERSION_TIGHT_RADIUS_INCHES)\n warnings.push(\n `the curve bringing ${id} back parallel works out at ${mag.toFixed(1)}″ radius — tighter than anyone lays by hand, which usually means the document's lane and its turnout disagree`,\n );\n return {\n id,\n partId: flexId,\n x: from.x,\n y: from.y,\n rotationDeg: from.headingDeg,\n // Curving BACK toward the host: opposite the way we are already heading.\n // `radiusInches` is signed and the sign IS the side.\n radiusInches: r3(-Math.sign(theta) * mag),\n lengthInches: r3(mag * Math.abs(theta)),\n };\n };\n\n /** Place a turnout so {@link walkTrackGraph} will report it at `t.pos`. */\n const layTurnout = (t: SchematicTurnout, hostY: number) => {\n const part = chosen.get(t.id)!;\n const geom = partGeometry(part, library)!;\n const branch = trackById.get(t.divergeTrack);\n // ⚠️ WHICH WAY DOES THE BRANCH LEAVE? The far end is whichever of the\n // branch's ends is further from this turnout — NOT always `toPos`. On a\n // siding's east turnout `toPos` IS its own position, so passing it left\n // `turnoutFacing` with a zero to sign and it fell through to \"east\",\n // pointing the diverging rail away from the siding it opens.\n const ends = [branch?.fromPos, branch?.toPos].filter(\n (n): n is number => typeof n === \"number\" && Number.isFinite(n),\n );\n const divergeFarPos = ends.length\n ? ends.reduce((a, b) => (Math.abs(b - t.pos) > Math.abs(a - t.pos) ? b : a))\n : undefined;\n const facing = turnoutFacing({\n pos: t.pos,\n divergeFarPos,\n flipped: t.flipped ?? false,\n });\n const body = part.overallLength!.inches;\n const lead = part.lead?.inches ?? body / 2;\n // ⭐ A DOCUMENT'S `pos` IS THE FROG (Will, 2026-07-27), and the frog sits\n // `frogOffset` from the tie end. Entered at the throat the walk reports\n // `throat + frogOffset`; entered at the through end, `through + (body −\n // frogOffset)`. Invert whichever applies so the turnout comes back out where\n // the document put it.\n const frogAxial = part.frogOffset?.inches ?? (part.pointsOffset?.inches ?? 0) + lead;\n const throatPos = facing > 0 ? t.pos - frogAxial : t.pos + frogAxial;\n const hostLane = trackById.get(t.onTrack)?.lane ?? 0;\n // Which way must the diverging route go? The part diverges to its own +y;\n // turning it end-for-end sends that to module −y. ⭐ No hand is stored\n // anywhere — this reads the side off the document's lanes.\n const want = Math.sign((branch?.lane ?? hostLane) - hostLane) || 1;\n const unflipped = facing > 0 ? 1 : -1;\n const piece: TrackPiece = {\n id: `t-${t.id}`,\n partId: part.id,\n x: throatPos,\n y: hostY,\n rotationDeg: facing > 0 ? 0 : 180,\n ...(unflipped !== want ? { flipped: true } : {}),\n ...(t.name ? { name: t.name } : {}),\n };\n // ⚠️ THE BODY IS MEASURED OFF THE PIECE, not off `partExtent` — see the\n // anchor warning on this function. Whatever the 1-D helper believes, flex\n // has to stop where this piece's rail actually starts.\n const bodyEnds = [throatPos, facing > 0 ? throatPos + body : throatPos - body];\n const span: OccupiedSpan = { fromPos: Math.min(...bodyEnds), toPos: Math.max(...bodyEnds) };\n const divergeId = geom.joints.find((j) => j.role === \"diverge\")?.id ?? \"diverge\";\n return { t, piece, span, divergeId };\n };\n\n /**\n * Re-aim a straight flex piece so its far end lands exactly on a point.\n *\n * A run that has to meet something slightly off its lane — a crossover pinches\n * the mains together — is eased over by the builder, and the angle is far\n * below anything drawable (0.035″ over a 30″ piece is 0.07°). Doing it by\n * re-aiming the piece keeps the joint EXACT, which is what the graph needs.\n */\n const aimEndAt = (piece: TrackPiece, to: { x: number; y: number }) => {\n const dx = to.x - piece.x;\n const dy = to.y - piece.y;\n const len = Math.hypot(dx, dy);\n if (!(len > 0)) return;\n // ⚠️ THE ANGLE IS NOT ROUNDED. Rounding it to three places moved the far end\n // by ~1.5e-5″ — harmless against JOINT_SNAP_INCHES, but this joint is meant\n // to be exact BY CONSTRUCTION, and \"close enough to snap\" is the habit that\n // lets real drift in.\n piece.rotationDeg = (Math.atan2(dy, dx) * 180) / Math.PI;\n piece.lengthInches = len;\n };\n\n /** Lay the plain track of one straight run at `hostY`, between two positions,\n * around the bodies already sitting in it. */\n const layFlex = (\n label: string,\n hostY: number,\n fromPos: number,\n toPos: number,\n occupied: OccupiedSpan[],\n cuts?: number[] | null,\n ) => {\n const out = flexPieces({ fromPos, toPos, maxPieceInches: maxPiece, occupied, cuts: cuts ?? null });\n const placed: TrackPiece[] = out.map((f, i) => ({\n id: `f-${label}-${i}`,\n partId: flexId,\n x: f.fromPos,\n y: hostY,\n rotationDeg: 0,\n lengthInches: r3(f.lengthInches),\n }));\n pieces.push(...placed);\n return placed;\n };\n\n /**\n * Every turnout sitting ON a track, laid, with its body span — minus any whose\n * mouldings would occupy the same rail.\n *\n * ⚠️⚠️ **TWO TURNOUTS CANNOT SHARE AN INCH OF TRACK, AND NOTHING ELSE NOTICES.**\n * {@link flexPieces} deliberately MERGES overlapping occupied spans, so the\n * flex is cut around the union and the two pieces are simply left intersecting;\n * the walk then threads a path through geometry that cannot exist and emits a\n * module nobody has. FMN-0078 is the case: its scissors crossover puts two\n * turnouts 2.5″ apart, and an Atlas #7 is 6″ long — the rebuild produced two\n * turnouts at 91.9″ and called the crossovers sidings.\n *\n * A real scissors is ONE assembly for exactly this reason. Dropping the pair\n * and saying so leaves a module that is honestly missing its crossover, rather\n * than one that is quietly wrong.\n */\n const turnoutsOn = (trackId: string, hostY: number) => {\n const laid = turnouts\n .filter((t) => t.onTrack === trackId && chosen.has(t.id))\n .map((t) => layTurnout(t, hostY))\n .sort((a, b) => a.span.fromPos - b.span.fromPos);\n const clashed = new Set<string>();\n for (let i = 1; i < laid.length; i += 1) {\n const prev = laid[i - 1];\n const cur = laid[i];\n if (cur.span.fromPos < prev.span.toPos - 1e-6) {\n clashed.add(prev.t.id);\n clashed.add(cur.t.id);\n const gap = Math.abs(cur.t.pos - prev.t.pos);\n const body = prev.span.toPos - prev.span.fromPos;\n // ⭐⭐ IS THIS A CROSSOVER ASSEMBLY? Then the overlap is OUR modelling\n // error, not the owner's track. A double crossover is ONE moulding whose\n // four point-sets sit closer together than four separate turnouts ever\n // could — that is the entire reason it is sold as a single fixture.\n // Telling an owner their turnouts collide would blame them for a real\n // and perfectly ordinary piece of trackwork.\n const asm = trackById.get(cur.t.divergeTrack)?.role === \"crossover\";\n notLaid.push({\n id: cur.t.divergeTrack,\n why: asm\n ? `this is a crossover — one assembly, not ${gap.toFixed(1)}″ between two separate turnouts. Laying it needs the crossover product itself; pick one on the track and it can be placed as the single piece it is`\n : `${prev.t.name || prev.t.id} and ${cur.t.name || cur.t.id} are ${gap.toFixed(1)}″ apart on the same track, but the turnout chosen is ${body.toFixed(1)}″ long — their mouldings would overlap, so they cannot both be where the document puts them`,\n });\n }\n }\n return laid.filter((l) => !clashed.has(l.t.id));\n };\n\n /**\n * ⭐⭐ A DOUBLE CROSSOVER IS LAID AS **ONE PIECE** (Will, 2026-07-28).\n *\n * Found by its connectors: crossover-role tracks naming a placeable crossover\n * product. The four turnouts the document lists are the assembly's own\n * point-sets, so they are NOT laid individually — doing that is what made the\n * FMN-0078 rebuild collapse.\n *\n * ⚠️ **THE PRODUCT'S GEOMETRY WINS, AND ITS POSITION IS THE OWNER'S.** A real\n * #6 assembly is 20.14″ with its point-sets 6.54″ apart; a document may record\n * them anywhere. So it is centred on the mean of the recorded positions — the\n * crossover stays where the owner put it — and any discrepancy is reported\n * rather than silently absorbed.\n */\n const assemblies = (() => {\n const out: {\n part: TrackPart;\n geom: NonNullable<ReturnType<typeof crossoverAssembly>>;\n x0: number;\n trackIds: Set<string>;\n turnoutIds: Set<string>;\n }[] = [];\n const byPart = new Map<string, SchematicTrack[]>();\n for (const t of tracks) {\n if (t.role !== \"crossover\" || !t.crossoverPartId) continue;\n const list = byPart.get(t.crossoverPartId) ?? [];\n list.push(t);\n byPart.set(t.crossoverPartId, list);\n }\n for (const [partId, connectors] of byPart) {\n const part = partById.get(partId);\n if (!part || part.kind !== \"crossover\" || partGeometryGap(part)) continue;\n const geom = crossoverAssembly(part);\n if (!geom) continue;\n const trackIds = new Set(connectors.map((c) => c.id));\n const mine = turnouts.filter((t) => trackIds.has(t.divergeTrack));\n if (!mine.length) continue;\n const centre = mine.reduce((a, t) => a + t.pos, 0) / mine.length;\n const x0 = centre - geom.lengthInches / 2;\n const spread = Math.max(...mine.map((t) => t.pos)) - Math.min(...mine.map((t) => t.pos));\n if (Math.abs(spread - geom.crossingRunInches) > 0.05)\n warnings.push(\n `this document puts the crossover's point-sets ${spread.toFixed(2)}″ apart, but a ${part.name ?? partId} is ${geom.crossingRunInches.toFixed(2)}″ — the assembly is laid to its own dimensions, centred where the document has it`,\n );\n out.push({ part, geom, x0, trackIds, turnoutIds: new Set(mine.map((t) => t.id)) });\n }\n return out;\n })();\n /** Connectors that belong to an assembly are ITS business, not branches. */\n const assemblyTracks = new Set(assemblies.flatMap((a) => [...a.trackIds]));\n\n // ── THE MAINS. Both run along the module's axis; Main 2 sits a lane over.\n const main = trackById.get(MAIN_TRACK_ID) ?? tracks.find((t) => t.role === \"main\");\n if (!main) return refuse(\"this module's document has no mainline to convert\");\n const mains = [main, ...tracks.filter((t) => t.role === \"main\" && t.id !== main.id)];\n const laidTurnouts = new Map<string, ReturnType<typeof layTurnout>>();\n const done = new Set<string>();\n\n // The assemblies go down first: they sit ON the mains, so the flex has to be\n // cut around them, and Main 2 has to be brought in to meet them.\n const mainY = laneOffsetAt(mains[0]?.lane ?? 0, 0);\n for (const [i, a] of assemblies.entries()) {\n pieces.push({\n id: `xo-${i}`,\n partId: a.part.id,\n x: r3(a.x0),\n y: mainY,\n rotationDeg: 0,\n ...(a.part.name ? { name: a.part.name } : {}),\n });\n }\n const assemblySpans: OccupiedSpan[] = assemblies.map((a) => ({\n fromPos: a.x0,\n toPos: a.x0 + a.geom.lengthInches,\n }));\n\n for (const m of mains) {\n const y = laneOffsetAt(m.lane ?? 0, 0);\n const on = turnoutsOn(m.id, y);\n for (const l of on) {\n pieces.push(l.piece);\n laidTurnouts.set(l.t.id, l);\n }\n const laidFlex = layFlex(\n m.id,\n y,\n m.fromPos ?? 0,\n m.toPos ?? mainLen,\n [...on.map((l) => l.span), ...assemblySpans],\n m.flexCuts,\n );\n /**\n * ⚠️⚠️ **THE PINCH.** A #6 assembly is 1.09″ wide while the mains run\n * {@link FREEMO_TRACK_SPACING_INCHES} apart, so Main 2's rail has to come in\n * 0.035″ to meet it and go back out the other side. In the graph this is not\n * a special case at all — the piece IS 1.09″ wide and the flex bends to\n * reach it, which is exactly what retires `LanePinch`, `laneOffsetAt`'s\n * pinch handling and `PINCH_EASE_INCHES` from the 1-D model.\n *\n * ⚠️ NOT a departure from the standard: §2.0 fixes the spacing AT THE\n * ENDPLATE, and every real double crossover pinches the mains closer.\n */\n if (m !== mains[0]) {\n for (const a of assemblies) {\n const west = a.x0;\n const east = a.x0 + a.geom.lengthInches;\n const target = mainY + a.geom.spacingInches;\n for (const f of laidFlex) {\n const end = f.x + (f.lengthInches ?? 0);\n if (Math.abs(end - west) < 1e-6) aimEndAt(f, { x: west, y: target });\n else if (Math.abs(f.x - east) < 1e-6) {\n f.y = target;\n aimEndAt(f, { x: end, y: y });\n }\n }\n }\n }\n done.add(m.id);\n }\n\n // An assembly's connectors are already on the board — they are routes THROUGH\n // the piece, not branches hanging off a turnout. Marking them done keeps the\n // final sweep from reporting a crossover that was laid perfectly well.\n for (const id of assemblyTracks) done.add(id);\n\n // ── EVERY OTHER TRACK HANGS OFF A TURNOUT. Laid outward from the mains,\n // repeating until nothing new is reachable — which is how a ladder three\n // turnouts deep resolves without the conversion knowing it is one.\n let progressed = true;\n while (progressed) {\n progressed = false;\n for (const t of turnouts) {\n if (!done.has(t.onTrack)) continue; // its host is not laid yet\n const branch = trackById.get(t.divergeTrack);\n if (!branch || done.has(branch.id)) continue;\n const near = laidTurnouts.get(t.id);\n if (!near) continue;\n done.add(branch.id);\n progressed = true;\n\n const dj = jointAt(near.piece, near.divergeId);\n if (!dj) {\n notLaid.push({ id: branch.id, why: `turnout ${t.id} has no diverging end to leave from` });\n continue;\n }\n // A SIDING is the same track reached by a SECOND turnout — and a CROSSOVER\n // is that too, but between the two mains.\n const farSw0 = turnouts.find(\n (o) => o.id !== t.id && o.divergeTrack === branch.id && laidTurnouts.has(o.id),\n );\n const farJoint0 = farSw0\n ? (() => {\n const f = laidTurnouts.get(farSw0.id)!;\n return jointAt(f.piece, f.divergeId);\n })()\n : null;\n\n // ⭐⭐ A CROSSOVER CONNECTOR NEVER COMES PARALLEL TO A LANE. It runs\n // diagonally from one main to the other, so the transition curve that\n // straightens a siding onto its lane is exactly the wrong shape here — it\n // asked for a 0.3″ radius and then reported the crossover as unbuildable.\n // Straight between the two diverging joints is what a crossover IS, and\n // landing on both by construction is what makes it join at all.\n if (branch.role === \"crossover\" && farJoint0) {\n const dx = farJoint0.x - dj.x;\n const dy = farJoint0.y - dj.y;\n const len = Math.hypot(dx, dy);\n if (len > 1e-6) {\n pieces.push({\n id: `x-${branch.id}`,\n partId: flexId,\n x: dj.x,\n y: dj.y,\n rotationDeg: (Math.atan2(dy, dx) * 180) / Math.PI,\n lengthInches: r3(len),\n ...(branch.trackName ? { name: branch.trackName } : {}),\n });\n } else {\n notLaid.push({\n id: branch.id,\n why: \"this crossover's two turnouts meet at the same point, so there is no connector between them to lay\",\n });\n }\n continue;\n }\n\n const branchY = laneOffsetAt(branch.lane ?? 0, 0);\n const curve = transition(branch.id, { x: dj.x, y: dj.y, headingDeg: dj.headingDeg }, branchY);\n let start: Cursor = { x: dj.x, y: dj.y, headingDeg: dj.headingDeg };\n if (curve) {\n pieces.push(curve);\n const e = jointAt(curve, \"b\");\n if (e) start = { x: e.x, y: e.y, headingDeg: e.headingDeg };\n }\n\n // A SIDING is the same track reached by a SECOND turnout. Its far end is\n // that turnout's diverging joint, not a position — so the run is closed\n // onto it, the way a builder cuts the last piece to fit.\n const farJoint = farJoint0;\n let endX =\n farJoint != null\n ? farJoint.x\n : Math.max(branch.fromPos ?? t.pos, branch.toPos ?? t.pos);\n let farCurve: TrackPiece | null = null;\n if (farJoint) {\n // ⚠️ The joint's heading ALREADY points the way this rail runs — west,\n // out of the far turnout and back down the siding. Reversing it as well\n // as passing `dirSign: -1` flipped it twice and turned an 8° transition\n // into a 172° one.\n farCurve = transition(\n `${branch.id}-far`,\n { x: farJoint.x, y: farJoint.y, headingDeg: farJoint.headingDeg },\n branchY,\n -1,\n );\n if (farCurve) {\n pieces.push(farCurve);\n const e = jointAt(farCurve, \"b\");\n if (e) endX = e.x;\n }\n }\n\n // ⚠️ THE MODULE MAY NOT HAVE ROOM FOR WHAT THE OWNER CHOSE. A turnout has\n // a real body and a real transition; a ladder pitched tighter than they\n // need cannot be built from those parts at all. The 1-D model never had to\n // notice — it draws a spur at its lane the instant the turnout appears.\n // Say so rather than lay a run of negative length.\n if (endX - start.x <= 1e-6) {\n notLaid.push({\n id: branch.id,\n why: `the turnout and the curve bringing this track parallel already reach ${start.x.toFixed(1)}″, past where it has to end at ${endX.toFixed(1)}″ — with the turnout chosen there is no room for this track where the document places it`,\n });\n continue;\n }\n\n const on = turnoutsOn(branch.id, branchY).filter((l) => {\n if (l.span.fromPos >= start.x - 1e-6) return true;\n notLaid.push({\n id: l.t.divergeTrack,\n why: `turnout ${l.t.id} sits at ${l.t.pos}″ but this track has only reached ${start.x.toFixed(1)}″ by then — the ladder is pitched tighter than the chosen turnout allows`,\n });\n return false;\n });\n for (const l of on) {\n pieces.push(l.piece);\n laidTurnouts.set(l.t.id, l);\n }\n layFlex(branch.id, branchY, start.x, endX, on.map((l) => l.span), branch.flexCuts);\n }\n }\n\n // ⚠️ Anything still unlaid has to be named. A track whose parent could not be\n // laid never gets its turn in the loop above, so without this sweep a ladder\n // that failed at its second turnout would report the second track and stay\n // silent about the third — the owner would be told about part of the loss.\n const orphanWhy = new Map(report.orphanTracks.map((o) => [o.id, o.why]));\n const alreadySaid = new Set(notLaid.map((n) => n.id));\n for (const t of tracks) {\n if (t.role === \"main\" || done.has(t.id) || alreadySaid.has(t.id)) continue;\n notLaid.push({\n id: t.id,\n why:\n orphanWhy.get(t.id) ??\n \"the track it branches from could not be laid, so there is nothing to join it to\",\n });\n }\n\n // ── Where each main begins: the westmost joint sitting in its lane.\n const startOf = (t: SchematicTrack) => {\n const y = laneOffsetAt(t.lane ?? 0, 0);\n let best: { piece: string; joint: string; x: number } | null = null;\n for (const p of pieces)\n for (const j of jointsOf(p)) {\n if (Math.abs(j.y - y) > 0.05) continue;\n if (!best || j.x < best.x) best = { piece: p.id, joint: j.joint, x: j.x };\n }\n return best ? { piece: best.piece, joint: best.joint } : null;\n };\n const startAt = startOf(main);\n if (!startAt) return refuse(\"nothing was laid on the mainline, so the module has no starting point\");\n const second = mains[1] ? startOf(mains[1]) : null;\n\n return {\n graph: { pieces, startAt, ...(second ? { start2: second } : {}) },\n refused: null,\n notLaid,\n warnings,\n };\n}\n\n/** A frog casting's parts, in TURNOUT-LOCAL inches: `x` = distance past the\n * points, `y` = lateral offset from the through route. */\nexport interface FrogCasting {\n /** The point rail — the acute V, apex at the crossing, opening toward the\n * diverging end. Three points: through leg, apex, diverging leg. */\n point: Array<{ x: number; y: number }>;\n /** The two wing rails flanking the point, each a short polyline. */\n wings: Array<Array<{ x: number; y: number }>>;\n /** The apex — where the two inner rails actually cross. */\n apex: { x: number; y: number };\n}\n\n/**\n * The frog casting at a turnout's crossing.\n *\n * The apex is where the two INNER rails cross, which is HALF a gauge off the\n * through centre-line (the through inner rail sits at +g/2, the diverging inner\n * rail at d−g/2, and d = g at the frog). Not one full gauge — that is the\n * diverging CENTRE-line, and putting the casting there floats it clear of the\n * rails it is made of.\n *\n * ⚠️ **The flangeway is EXAGGERATED and that is deliberate.** True scale in N is\n * about 0.011″ (prototype 1¾″ ÷ 160) — one pixel in a close-up render and\n * invisible at module zoom. Drawn to scale the wing rails would sit exactly on\n * the running rails and add nothing. `flangewayInches` defaults to a readable\n * fraction of the gauge instead; pass the true figure if you ever need it.\n */\nexport function frogCasting(\n cl: TurnoutClosure,\n opts: {\n gaugeInches?: number;\n /** How far the casting runs either side of the apex. */\n reachInches?: number;\n /** See the warning above — exaggerated for legibility by default. */\n flangewayInches?: number;\n } = {},\n): FrogCasting {\n const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;\n const w = opts.reachInches ?? g * 1.5;\n const fw = opts.flangewayInches ?? g * 0.12;\n const m = cl.frogSlope;\n const lead = cl.lead;\n const apex = { x: lead, y: g / 2 };\n\n // Past the apex the two inner rails separate: the through one stays at +g/2,\n // the diverging one climbs at the frog angle. That divergence IS the V.\n const point = [\n { x: lead + w, y: g / 2 },\n apex,\n { x: lead + w, y: g / 2 + m * w },\n ];\n\n // Approaching the frog those same two rails converge. The wing rails are that\n // incoming pair, bent out by a flangeway so a wheel is carried across the gap\n // rather than dropping into it — so each runs past the apex, not up to it.\n const wings = [\n [\n { x: lead - w, y: g / 2 - fw },\n { x: lead - w * 0.35, y: g / 2 - fw },\n { x: lead + w * 0.35, y: g / 2 - fw * 0.5 },\n ],\n [\n { x: lead - w, y: g / 2 + m * -w + fw },\n { x: lead - w * 0.35, y: g / 2 + m * -w * 0.35 + fw },\n { x: lead + w * 0.35, y: g / 2 + m * w * 0.35 + fw * 0.5 },\n ],\n ];\n return { point, wings, apex };\n}\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 // ⚠️ `flipped` MUST be passed. Rotating a turnout 180° swaps the side\n // its route leaves on — that is what divergeSideForHand's third\n // argument is for. Omitting it made the operations view honour the\n // author's HAND but silently ignore their FLIP, so a flipped turnout\n // drew on opposite sides in the 2-D and the dispatcher views. The\n // three authored facts — host track, hand, flip — must all reach the\n // drawing, and both views must read them through THIS function.\n const s = divergeSideForHand(sw.kind, far - sw.pos, sw.flipped);\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 // 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 // Every lane in use BEFORE the branches — the branch routes are then placed\n // clear of all of them, so a branch can never land on top of a siding.\n const baseLanes = [\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\n // Branch endplates → a route leaving the module in the operating view — but\n // ONLY once track actually reaches one. Placing a bare 3rd+ endplate must not\n // conjure a junction; the route follows the drawn branch track that links to\n // it (its trackId), so it appears when you connect track, not when you add the\n // endplate (#170).\n //\n // This is where a branch stops being decoration and becomes Main 3 (#181): it\n // gets a lane of its own and a run of its own length, which together are the\n // axis anything positioned along the branch needs. NB the return-loop\n // generator also emits role:\"branch\" tracks — they're excluded here (and only\n // here) because no endplate's trackId points at them, so loops keep their bulb.\n // Branch lanes start a clear GAP beyond the outermost drawn lane. One empty\n // lane is what stops a route that runs the full width of the strip reading as\n // just another main alongside (#183) — it is an END of the module, and it has\n // to look like one.\n const LANE_GAP_FROM_OTHERS = 2;\n let upLane = Math.max(...baseLanes, 0) + (LANE_GAP_FROM_OTHERS - 1);\n let downLane = Math.min(...baseLanes, 0) - (LANE_GAP_FROM_OTHERS - 1);\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 const trk = (doc.tracks ?? []).find((t) => t.id === e.trackId)!;\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 const startPos = sw ? sw.pos : e.at!.pos;\n const side = e.at!.side === \"down\" ? \"down\" : \"up\";\n const lane = side === \"down\" ? --downLane : ++upLane;\n // The run is the route's OWN length, straightened onto the strip. Its\n // projection on the module axis would be the \"natural\" span, but a square\n // 90° exit projects to zero — the very case that made branches invisible.\n // A path is always shorter along the axis than along itself, so the length\n // is also the larger, safer number.\n const runInches =\n pathLengthInches(trk.path) ||\n Math.abs(e.at!.pos - startPos) ||\n FREEMO_ENDPLATE_WIDTH_MIN_INCHES;\n // ⚠️ The route runs to the EDGE of the module, not for its own length.\n // This is an endplate: a train leaves the module here, exactly as it does\n // at A or B, and the straightened view says so by taking the route to the\n // end of the strip and terminating it at a plate (#183). Its real\n // on-module length is still reported, for the tooltip.\n //\n // Which edge is the one the plate actually sits toward — a junction near\n // the west end exits west.\n const toB = e.at!.pos >= startPos;\n return {\n id: e.id,\n label: e.label ?? e.id,\n name: trk.trackName ?? \"\",\n trackId: trk.id,\n kind: (e.kind === \"main\" ? \"main\" : \"branch\") as \"branch\" | \"main\",\n posFrac: clampFrac(startPos),\n fromLane: (sw ? (trackLane.get(sw.onTrack) ?? 0) : 0) as number,\n side: side as \"up\" | \"down\",\n lane,\n endFrac: toB ? 1 : 0,\n lengthInches: runInches,\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 // Branch lanes are part of the drawn extent, so renderers size their canvas\n // from laneMin/laneMax alone — no \"leave a lane spare if there's a branch\"\n // headroom hack at either end (#181).\n const allLanes = [...baseLanes, ...branchConnectors.map((b) => b.lane)];\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 hasEndplateB: doc.endplates.some((e) => e.id === \"B\"),\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\n/**\n * An endplate bound to a BENCHWORK EDGE (ADR 0001).\n *\n * Will Gage, 2026-07-26: *\"Endplates are a part of the benchwork. We have\n * separated them causing some challenges.\"* A {@link SchematicEndplate.pose} is\n * a point floating in module space, so it can disagree with the board — and has:\n * a junction plate landed on the module CENTRE LINE rather than the fascia, a\n * derived pose written back silently PINNED a plate so it went stale when the\n * length changed (which is the only reason `poseAuthored` exists), and a face\n * drawn flat across a tapered edge is flush only at its midpoint.\n *\n * Bind it to an edge and none of those are expressible. Position, heading and\n * WIDTH all come from the edge, so they cannot drift apart.\n */\nexport interface EndplateEdge {\n /** The section whose outline owns this edge; absent = the module outline. */\n section?: string | null;\n /** Which edge: the segment from vertex `index` to vertex `index + 1`. */\n index: number;\n /** Optional span along that edge, 0…1. Absent = the whole edge — which is the\n * common case, because a board's end IS the endplate. */\n fromT?: number | null;\n toT?: number | null;\n}\n\n/** What an {@link EndplateEdge} resolves to. Everything here is READ OFF the\n * polygon; nothing is stored, so nothing can go stale. */\nexport interface EndplateEdgePose {\n x: number;\n y: number;\n /** The edge's OUTWARD normal, degrees. */\n heading: number;\n /** The span's length — the face's real width, not a separate number that\n * might disagree with the board. */\n widthInches: number;\n /** The face's two ends. On a tapered board this follows the slope, which a\n * stored pose + width could never do. */\n face: [{ x: number; y: number }, { x: number; y: number }];\n}\n\n/**\n * Resolve an endplate's edge binding against a benchwork polygon.\n *\n * ⚠️ REFUSES A CURVED EDGE. Free-moN §2.0 requires the track crossing an\n * endplate to be perpendicular, straight and level for 4″ — so an endplate face\n * is flat by the standard, and a bulged edge is not somewhere one can go. That\n * is a rule, not a missing feature.\n *\n * Returns null when the edge doesn't exist or isn't usable, so a caller can say\n * why rather than drawing something wrong.\n */\nexport function endplateEdgePose(\n outline: BenchworkPoint[] | null | undefined,\n edge: EndplateEdge,\n): EndplateEdgePose | null {\n if (!outline || outline.length < 3) return null;\n const n = outline.length;\n const i = Math.trunc(edge.index);\n if (!Number.isFinite(i) || i < 0 || i >= n) return null;\n const p0 = outline[i];\n const p1 = outline[(i + 1) % n];\n if (p0.bulge) return null; // a curved fascia is not an endplate face\n\n const t0 = Math.max(0, Math.min(1, edge.fromT ?? 0));\n const t1 = Math.max(0, Math.min(1, edge.toT ?? 1));\n const a = { x: p0.x + (p1.x - p0.x) * Math.min(t0, t1), y: p0.y + (p1.y - p0.y) * Math.min(t0, t1) };\n const b = { x: p0.x + (p1.x - p0.x) * Math.max(t0, t1), y: p0.y + (p1.y - p0.y) * Math.max(t0, t1) };\n const w = Math.hypot(b.x - a.x, b.y - a.y);\n if (!(w > 0)) return null;\n\n // Outward = away from the polygon's centroid. Same rule `snapPoseToOutline`\n // uses, so a dragged plate and a bound one agree on which way is out.\n let cx = 0;\n let cy = 0;\n for (const v of outline) {\n cx += v.x;\n cy += v.y;\n }\n cx /= n;\n cy /= n;\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const ex = (b.x - a.x) / w;\n const ey = (b.y - a.y) / w;\n let nx = ey;\n let ny = -ex;\n if ((mid.x - cx) * nx + (mid.y - cy) * ny < 0) {\n nx = -nx;\n ny = -ny;\n }\n return {\n x: mid.x,\n y: mid.y,\n heading: norm360((Math.atan2(ny, nx) * 180) / Math.PI),\n widthInches: w,\n face: [a, b],\n };\n}\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 /** Set when this pose came from an {@link EndplateEdge} — read off the\n * benchwork rather than stored. Its width and face are the board's own. */\n boundToEdge?: boolean;\n /** The face's real width, when bound to an edge. */\n widthInches?: number;\n /** The face's two ends, when bound to an edge — follows a tapered board. */\n face?: [{ x: number; y: number }, { x: number; y: 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. `\"none\"` at B\n * means the module has no far endplate at all — an end of the line, a pocket,\n * or a turnback (#184). */\n endplateConfigs?: (\"single\" | \"double\" | \"none\" | 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 /** ⭐ Endplate EDGE bindings by id (ADR 0001) — an endplate that is part of\n * the benchwork rather than a point floating beside it. Wins over\n * `poseOverrides` and over derivation. */\n endplateEdges?: Record<string, EndplateEdge>;\n /** The module's benchwork polygon, needed to resolve `endplateEdges`. */\n outline?: BenchworkPoint[] | null;\n /** Hand-entered pose overrides by endplate id — win over derivation. */\n poseOverrides?: Record<string, { x: number; y: number; heading: number }>;\n /** Authored endplate FACE widths by id (\"A\"/\"B\"), inches — the board's depth.\n * Needed to place a branch endplate on the benchwork edge rather than on the\n * centre line; absent ends use the recommended default. */\n endplateWidths?: Record<string, 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 // ⭐ AN EDGE BINDING WINS OVER EVERYTHING (ADR 0001). It is not an override\n // in the sense a pose is — it is where the endplate IS, read off the board,\n // so it can never go stale and can never sit somewhere the benchwork isn't.\n // `manual` stays FALSE: nothing was hand-placed, and treating it as manual\n // is what pinned plates and made them stop following the module (#182).\n const bound = geo.endplateEdges?.[p.id];\n if (bound) {\n const outline =\n (bound.section\n ? geo.sections?.find((s) => s.id === bound.section)?.outline\n : geo.outline) ?? geo.outline;\n const e = endplateEdgePose(outline, bound);\n if (e)\n return {\n ...p,\n x: e.x,\n y: e.y,\n heading: e.heading,\n widthInches: e.widthInches,\n face: e.face,\n boundToEdge: true,\n };\n // The edge named nothing usable — a curved fascia, or an outline that has\n // since changed shape. Fall through rather than draw a lie; the caller can\n // see `boundToEdge` is absent and say so.\n }\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 presents only ONE face. See\n // hasNoFarEndplate for the three ways to say so and why they differ (#184).\n const noB = hasNoFarEndplate(geo);\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 — ON THE BENCHWORK EDGE of their side, facing out.\n //\n // ⚠️ This used to derive `y: 0`, putting the plate on the module's CENTRE\n // LINE. An endplate is where a train leaves the module, so a side-facing one\n // belongs on the board's border — at y = 0 it sat buried mid-board and any\n // track drawn to it stopped in the middle of nowhere. It only ever looked\n // right on modules whose branch pose had been hand-authored to the edge.\n //\n // The depth is the endplate-width band's half-width at that point, which is\n // exactly what the derived board is drawn as. A module with an AUTHORED\n // outline may have its real edge elsewhere; that's the case the note below\n // covers — drag the plate and the override wins.\n //\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 const widthAt = (frac: number) => {\n const wa = endplateWidthFor(geo.endplateWidths, \"A\");\n const wb = endplateWidthFor(geo.endplateWidths, \"B\");\n return (wa * (1 - frac) + wb * frac) / 2;\n };\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 const depth = widthAt(frac);\n poses.push(\n withOverride({\n id: b.id,\n x: px,\n y: b.side === \"down\" ? -depth : depth,\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/** Whether a pose sits on the module's own axis — on the centre line, facing\n * straight out either end. That's the shape plain derivation produces for A and\n * B, so an unflagged axial pose can't be told apart from derived residue (#182).\n * Anything off-axis had to be put there by hand. */\nfunction isAxialPose(p: { y: number; heading: number }): boolean {\n const h = norm360(p.heading);\n return Math.abs(p.y) < 1e-6 && (Math.abs(h) < 1e-6 || Math.abs(h - 180) < 1e-6);\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 // Only an AUTHORED pose overrides derivation (#182) — but docs written\n // before the flag existed have to keep working, so authorship is inferred\n // for the two cases that can only BE authored:\n // · a placed branch endplate (`at`) — dropping it on the board is the\n // gesture, and it has no derivable position at all;\n // · an OFF-AXIS pose on A/B — a hand-placed plate is off-axis by\n // definition (that's why it needed hand placing, e.g. a wye's B).\n // What's left is an axial A/B pose, which is exactly the shape plain\n // derivation produces — residue. Honouring it silently pins the plate so\n // it stops following the module and goes stale (FMN-0068's B sat at 48 on\n // a 47.9″ board). Anything saved from now on carries the flag, so this\n // guesswork only ever applies to old docs.\n (e.poseAuthored === true || !!e.at || !isAxialPose(e.pose))\n ) {\n out[e.id] = { x: e.pose.x, y: e.pose.y, heading: e.pose.heading };\n }\n }\n return out;\n}\n"]}
|