{"version":3,"sources":["../src/layout/elk-layouter.ts","../src/layout/size-calculator.ts","../src/layout/post-processing/boundary-event/collector.ts","../src/layout/post-processing/boundary-event/mover.ts","../src/utils/debug.ts","../src/layout/post-processing/boundary-event/edge-recalculator.ts","../src/layout/post-processing/boundary-event/index.ts","../src/layout/edge-routing/geometry-utils.ts","../src/types/bpmn-constants.ts","../src/utils/node-map-builder.ts","../src/layout/post-processing/artifact-positioner.ts","../src/layout/post-processing/group-positioner.ts","../src/layout/post-processing/lane-arranger.ts","../src/layout/constraint/constraint-solver.ts","../src/layout/post-processing/pool-arranger.ts","../src/layout/post-processing/compactor.ts","../src/layout/edge-routing/pathfinding-router.ts","../src/layout/edge-routing/edge-fixer.ts","../src/layout/edge-routing/gateway-endpoint-adjuster.ts","../src/layout/default-options.ts","../src/layout/preparation/elk-graph-preparer.ts","../src/layout/preparation/result-merger.ts","../src/transform/reference-resolver.ts","../src/transform/lane-resolver.ts","../src/transform/diagram-builder.ts","../src/transform/model-builder.ts","../src/generators/bpmn-xml-generator.ts","../src/converter.ts"],"sourcesContent":["/**\n * ELK Layout Engine Wrapper\n * Orchestrates the BPMN layout pipeline using specialized handlers.\n *\n * Lightweight post-processing: Only repositions boundary event targets below main flow.\n * ELK handles all edge routing.\n */\n\nimport ELK from 'elkjs';\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph, ElkLayoutOptions } from '../types';\nimport type { LayoutedGraph } from '../types/elk-output';\nimport { SizeCalculator } from './size-calculator';\nimport { BoundaryEventHandler } from './post-processing/boundary-event';\nimport { ArtifactPositioner } from './post-processing/artifact-positioner';\nimport { GroupPositioner } from './post-processing/group-positioner';\nimport { LaneArranger } from './post-processing/lane-arranger';\nimport { PoolArranger } from './post-processing/pool-arranger';\nimport { Compactor } from './post-processing/compactor';\nimport { EdgeFixer } from './edge-routing';\nimport { ElkGraphPreparer } from './preparation/elk-graph-preparer';\nimport { ResultMerger } from './preparation/result-merger';\nimport { isDebugEnabled } from '../utils/debug';\n\nexport interface ElkLayouterOptions {\n  elkOptions?: ElkLayoutOptions;\n  /** Enable layout compaction to reduce whitespace (default: true) */\n  enableCompaction?: boolean;\n}\n\nexport class ElkLayouter {\n  private elk: InstanceType<typeof ELK>;\n  private userOptions: ElkLayoutOptions;\n  private enableCompaction: boolean;\n  private sizeCalculator: SizeCalculator;\n  private boundaryEventHandler: BoundaryEventHandler;\n  private artifactPositioner: ArtifactPositioner;\n  private groupPositioner: GroupPositioner;\n  private laneArranger: LaneArranger;\n  private poolArranger: PoolArranger;\n  private compactor: Compactor;\n  private edgeFixer: EdgeFixer;\n  private graphPreparer: ElkGraphPreparer;\n  private resultMerger: ResultMerger;\n\n  constructor(options?: ElkLayouterOptions) {\n    this.elk = new ELK();\n    this.userOptions = options?.elkOptions ?? {};\n    this.enableCompaction = options?.enableCompaction ?? true;\n    this.sizeCalculator = new SizeCalculator();\n    this.boundaryEventHandler = new BoundaryEventHandler();\n    this.artifactPositioner = new ArtifactPositioner();\n    this.groupPositioner = new GroupPositioner();\n    this.laneArranger = new LaneArranger();\n    this.poolArranger = new PoolArranger();\n    this.compactor = new Compactor();\n    this.edgeFixer = new EdgeFixer();\n    this.graphPreparer = new ElkGraphPreparer();\n    this.resultMerger = new ResultMerger();\n  }\n\n  /**\n   * Run ELK layout on the graph\n   */\n  async layout(graph: ElkBpmnGraph): Promise<LayoutedGraph> {\n    // Deep clone to avoid mutating the original\n    const graphCopy = JSON.parse(JSON.stringify(graph)) as ElkBpmnGraph;\n\n    // Apply default sizes to all nodes\n    const sizedGraph = this.sizeCalculator.applyDefaultSizes(graphCopy);\n\n    // Collect boundary event info - used to set ELK constraints for target nodes\n    const boundaryEventInfo = this.boundaryEventHandler.collectInfo(sizedGraph);\n\n    // Collect boundary event target IDs for ELK constraint assignment\n    const boundaryEventTargetIds = this.graphPreparer.collectBoundaryEventTargetIds(boundaryEventInfo);\n\n    // Collect artifact association info for post-processing\n    const artifactInfo = this.artifactPositioner.collectInfo(sizedGraph);\n\n    // Collect Group info for post-processing (Groups will be repositioned after layout)\n    const groupInfo = this.groupPositioner.collectInfo(sizedGraph);\n\n    // Prepare graph for ELK (convert to ELK format)\n    // Pass boundaryEventTargetIds so ELK can apply position constraints\n    const elkGraph = this.graphPreparer.prepare(sizedGraph, this.userOptions, boundaryEventTargetIds);\n\n    // Run ELK layout\n    const layoutedElkGraph = await this.elk.layout(elkGraph);\n\n    // Lightweight post-processing: Move boundary event targets below their attached tasks\n    // This is BPMN-specific positioning that ELK cannot handle via constraints\n    const movedNodes = this.boundaryEventHandler.identifyNodesToMove(\n      layoutedElkGraph, boundaryEventInfo, sizedGraph, isDebugEnabled()\n    );\n\n    if (movedNodes.size > 0) {\n      // Move nodes\n      this.boundaryEventHandler.applyNodeMoves(layoutedElkGraph, movedNodes);\n      // Recalculate edges for moved nodes\n      this.boundaryEventHandler.recalculateEdgesForMovedNodes(layoutedElkGraph, movedNodes, boundaryEventInfo);\n    }\n\n    // Reposition artifacts (data objects, data stores, annotations) to be near their associated tasks\n    this.artifactPositioner.reposition(layoutedElkGraph, artifactInfo);\n\n    // Rearrange lanes to stack vertically within pools (ELK's partitioning doesn't do this correctly)\n    this.laneArranger.rearrange(layoutedElkGraph, sizedGraph);\n\n    // Rearrange pools to stack vertically within collaborations\n    this.poolArranger.rearrange(layoutedElkGraph, sizedGraph);\n\n    // Reposition Groups to surround their grouped elements\n    this.groupPositioner.reposition(layoutedElkGraph, groupInfo, sizedGraph);\n\n    // Recalculate artifact edges with obstacle avoidance\n    this.artifactPositioner.recalculateWithObstacleAvoidance(layoutedElkGraph, artifactInfo);\n\n    // Apply layout compaction to reduce whitespace (if enabled)\n    if (this.enableCompaction) {\n      this.compactor.compact(layoutedElkGraph);\n    }\n\n    // Pull content up to the top so canvas doesn't lead with empty space\n    // (ELK sometimes reserves vertical bands that post-processing leaves empty)\n    this.normalizeOrigin(layoutedElkGraph);\n\n    // Update container bounds to include all moved children\n    this.updateContainerBounds(layoutedElkGraph);\n\n    // Final edge correction pass — must run AFTER updateContainerBounds so\n    // edge endpoints snap to the post-shrink container borders. Otherwise\n    // edges anchored to a wider pre-shrink subprocess float past its new edge.\n    this.edgeFixer.fix(layoutedElkGraph);\n\n    // Merge layout results back with BPMN metadata\n    return this.resultMerger.merge(sizedGraph, layoutedElkGraph);\n  }\n\n  // Shift each top-level container so its leftmost/topmost node sits near\n  // the origin: ELK reserves bands for nodes that post-processing later\n  // relocates (e.g. boundary-event targets), and we want the canvas to lead\n  // with content, not empty space.\n  private normalizeOrigin(graph: ElkNode): void {\n    if (!graph.children) return;\n    const margin = 12;\n\n    for (const top of graph.children) {\n      // Find min x/y across direct children of this top-level container.\n      // We only care about positions inside `top`, since `top` itself sits\n      // at (0,0) in the root canvas after ELK.\n      if (!top.children || top.children.length === 0) continue;\n\n      // Boundary events are repositioned onto their parent task by the\n      // diagram builder, so their ELK-assigned y is phantom and must be\n      // ignored when finding the topmost visible content.\n      const isPhantom = (child: ElkNode): boolean => {\n        const bpmn = (child as ElkNode & { bpmn?: { type?: string } }).bpmn;\n        return bpmn?.type === 'boundaryEvent';\n      };\n\n      let minX = Infinity;\n      let minY = Infinity;\n      for (const child of top.children) {\n        if (isPhantom(child)) continue;\n        const x = child.x ?? 0;\n        const y = child.y ?? 0;\n        if (x < minX) minX = x;\n        if (y < minY) minY = y;\n      }\n      if (!isFinite(minX) || !isFinite(minY)) continue;\n\n      const shiftX = margin - minX;\n      const shiftY = margin - minY;\n      if (shiftX === 0 && shiftY === 0) continue;\n\n      for (const child of top.children) {\n        child.x = (child.x ?? 0) + shiftX;\n        child.y = (child.y ?? 0) + shiftY;\n      }\n      // Shift edge waypoints attached at this container level too.\n      if (top.edges) {\n        for (const edge of top.edges) {\n          if (!edge.sections) continue;\n          for (const section of edge.sections) {\n            section.startPoint.x += shiftX;\n            section.startPoint.y += shiftY;\n            section.endPoint.x += shiftX;\n            section.endPoint.y += shiftY;\n            if (section.bendPoints) {\n              for (const bp of section.bendPoints) {\n                bp.x += shiftX;\n                bp.y += shiftY;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  private updateContainerBounds(graph: ElkNode): void {\n    type Bpmned = ElkNode & { bpmn?: { type?: string } };\n\n    const isLane = (n: Bpmned): boolean => n.bpmn?.type === 'lane';\n    const hasLaneChildren = (n: ElkNode): boolean =>\n      !!n.children?.some(c => isLane(c as Bpmned));\n\n    const fit = (node: ElkNode): void => {\n      if (!node.children || node.children.length === 0) return;\n\n      for (const child of node.children) fit(child);\n\n      // Authoritative sizing: don't touch lanes or pools-with-lanes.\n      if (isLane(node as Bpmned)) return;\n      if (hasLaneChildren(node)) return;\n\n      const padding = 12;\n      let requiredWidth = 0;\n      let requiredHeight = 0;\n      for (const child of node.children) {\n        requiredWidth = Math.max(requiredWidth, (child.x ?? 0) + (child.width ?? 0) + padding);\n        requiredHeight = Math.max(requiredHeight, (child.y ?? 0) + (child.height ?? 0) + padding);\n      }\n      node.width = requiredWidth;\n      node.height = requiredHeight;\n    };\n\n    fit(graph);\n  }\n}\n","/**\n * Size Calculator\n * Handles calculating and applying default sizes to BPMN elements.\n * Also estimates label widths based on text content.\n */\n\nimport type { ElkBpmnGraph } from '../types';\nimport type { NodeWithBpmn } from '../types/internal';\n\n/**\n * Default size dimensions for various BPMN element types\n */\nexport interface ElementSize {\n  width: number;\n  height: number;\n}\n\n/**\n * Size Calculator for BPMN elements\n * Applies default sizes based on element type and properties\n */\nexport class SizeCalculator {\n  /**\n   * Apply default sizes to all nodes in the graph\n   */\n  applyDefaultSizes(graph: ElkBpmnGraph): ElkBpmnGraph {\n    if (graph.children) {\n      graph.children = graph.children.map((child) => {\n        return this.applyDefaultSizesRecursive(child);\n      });\n    }\n    return graph;\n  }\n\n  /**\n   * Recursively apply default sizes to a node and its children\n   */\n  private applyDefaultSizesRecursive<T extends object>(node: T): T {\n    const result = { ...node };\n\n    // Apply sizes if this is a node with bpmn type\n    if ('bpmn' in result && 'id' in result) {\n      const bpmn = (result as unknown as NodeWithBpmn).bpmn;\n      const nodeResult = result as { width?: number; height?: number };\n\n      // Get default size based on type\n      const defaultSize = this.getDefaultSizeForType(bpmn.type, bpmn.name, bpmn.isExpanded);\n\n      if (nodeResult.width === undefined) {\n        nodeResult.width = defaultSize.width;\n      }\n      if (nodeResult.height === undefined) {\n        nodeResult.height = defaultSize.height;\n      }\n    }\n\n    // Process children recursively\n    if ('children' in result && Array.isArray((result as { children: unknown[] }).children)) {\n      (result as { children: unknown[] }).children = (result as { children: object[] }).children.map(\n        (child) => this.applyDefaultSizesRecursive(child)\n      );\n    }\n\n    // Process boundary events\n    if ('boundaryEvents' in result && Array.isArray((result as { boundaryEvents: unknown[] }).boundaryEvents)) {\n      const boundaryEvents = (result as { boundaryEvents: object[] }).boundaryEvents;\n      (result as { boundaryEvents: unknown[] }).boundaryEvents = boundaryEvents.map(\n        (be) => this.applyDefaultSizesRecursive(be)\n      );\n\n      // Ensure host node is wide enough to accommodate all boundary events with spacing\n      // Each boundary event is 36px wide, and we need at least 20px spacing between them\n      const beCount = boundaryEvents.length;\n      if (beCount > 1) {\n        const beWidth = 36;\n        const beSpacing = 20;\n        // Need: margin + (beWidth + spacing) * beCount - spacing + margin\n        // Simplified: (beCount * (beWidth + beSpacing)) + margin\n        const minWidth = beCount * (beWidth + beSpacing) + beSpacing;\n        const nodeResult = result as { width?: number };\n        if (nodeResult.width !== undefined && nodeResult.width < minWidth) {\n          nodeResult.width = minWidth;\n        }\n      }\n    }\n\n    // Process artifacts\n    if ('artifacts' in result && Array.isArray((result as { artifacts: unknown[] }).artifacts)) {\n      (result as { artifacts: unknown[] }).artifacts = (result as { artifacts: object[] }).artifacts.map(\n        (artifact) => this.applyDefaultSizesRecursive(artifact)\n      );\n    }\n\n    return result;\n  }\n\n  /**\n   * Estimate label width based on text content\n   * Uses approximate character width of 14px for CJK and 7px for ASCII\n   */\n  estimateLabelWidth(text?: string): number {\n    if (!text) return 50;\n\n    let width = 0;\n    for (const char of text) {\n      // CJK characters are wider\n      if (char.charCodeAt(0) > 255) {\n        width += 14; // ~14px for CJK characters\n      } else {\n        width += 7; // ~7px for ASCII characters\n      }\n    }\n\n    return Math.max(30, Math.min(width, 200)); // Clamp between 30 and 200\n  }\n\n  /**\n   * Get default size for a BPMN element type\n   */\n  getDefaultSizeForType(type: string, name?: string, isExpanded?: boolean): ElementSize {\n    // Expanded subprocesses\n    if (isExpanded === true) {\n      return { width: 300, height: 200 };\n    }\n\n    // Events\n    if (type.includes('Event')) {\n      return { width: 36, height: 36 };\n    }\n\n    // Gateways\n    if (type.includes('Gateway')) {\n      return { width: 50, height: 50 };\n    }\n\n    // Tasks and activities\n    if (type.includes('Task') || type === 'task' || type === 'callActivity') {\n      const nameLen = name?.length ?? 0;\n      if (nameLen > 12) return { width: 150, height: 80 };\n      if (nameLen > 8) return { width: 120, height: 80 };\n      return { width: 100, height: 80 };\n    }\n\n    // Collapsed subprocesses\n    if (type === 'subProcess' || type === 'transaction' || type === 'adHocSubProcess' || type === 'eventSubProcess') {\n      return { width: 100, height: 80 };\n    }\n\n    // Data objects\n    if (type === 'dataObject' || type === 'dataObjectReference' || type === 'dataInput' || type === 'dataOutput') {\n      return { width: 36, height: 50 };\n    }\n\n    // Data store\n    if (type === 'dataStoreReference') {\n      return { width: 50, height: 50 };\n    }\n\n    // Text annotation\n    if (type === 'textAnnotation') {\n      return { width: 100, height: 30 };\n    }\n\n    // Participant/Pool - ELK and the pool/lane arrangers resize non-empty\n    // pools to fit content; this default mostly applies to empty (black box)\n    // pools, which should stay compact.\n    if (type === 'participant') {\n      return { width: 680, height: 80 };\n    }\n\n    // Lane - let ELK calculate\n    if (type === 'lane') {\n      return { width: 680, height: 150 };\n    }\n\n    // Default\n    return { width: 100, height: 80 };\n  }\n}\n\n/**\n * Standalone function to apply default sizes to a graph\n * Convenience wrapper around SizeCalculator\n */\nexport function applyDefaultSizes(graph: ElkBpmnGraph): ElkBpmnGraph {\n  const calculator = new SizeCalculator();\n  return calculator.applyDefaultSizes(graph);\n}\n\n/**\n * Standalone function to estimate label width\n * Convenience wrapper around SizeCalculator\n */\nexport function estimateLabelWidth(text?: string): number {\n  const calculator = new SizeCalculator();\n  return calculator.estimateLabelWidth(text);\n}\n\n/**\n * Standalone function to get default size for a type\n * Convenience wrapper around SizeCalculator\n */\nexport function getDefaultSizeForType(type: string, name?: string, isExpanded?: boolean): ElementSize {\n  const calculator = new SizeCalculator();\n  return calculator.getDefaultSizeForType(type, name, isExpanded);\n}\n","/**\n * Boundary Event Collector\n * Collects boundary event information from the BPMN graph for post-processing.\n */\n\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo } from '../../../types/internal';\n\n/**\n * Collect boundary event information for post-processing.\n * Returns a map of boundary event ID -> { attachedToRef, targets, boundaryIndex, totalBoundaries }\n *\n * @param graph - The ELK-BPMN input graph\n * @returns Map of boundary event ID to BoundaryEventInfo\n */\nexport function collectBoundaryEventInfo(\n  graph: ElkBpmnGraph\n): Map<string, BoundaryEventInfo> {\n  const info = new Map<string, BoundaryEventInfo>();\n  const edgeMap = new Map<string, string[]>(); // source -> targets\n\n  // First pass: collect all edges by source\n  const collectEdges = (node: NodeWithBpmn) => {\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (!source || !target) continue;\n        if (!edgeMap.has(source)) {\n          edgeMap.set(source, []);\n        }\n        edgeMap.get(source)!.push(target);\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectEdges(child as NodeWithBpmn);\n      }\n    }\n  };\n\n  // Second pass: collect boundary events and their targets\n  const collectBoundaryEvents = (node: NodeWithBpmn) => {\n    if (node.boundaryEvents) {\n      const totalBoundaries = node.boundaryEvents.length;\n      node.boundaryEvents.forEach((be, index) => {\n        const targets = edgeMap.get(be.id) || [];\n        info.set(be.id, {\n          attachedToRef: be.attachedToRef,\n          targets,\n          boundaryIndex: index,\n          totalBoundaries,\n        });\n      });\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectBoundaryEvents(child as NodeWithBpmn);\n      }\n    }\n  };\n\n  for (const child of graph.children ?? []) {\n    collectEdges(child as NodeWithBpmn);\n    collectBoundaryEvents(child as NodeWithBpmn);\n  }\n\n  return info;\n}\n","/**\n * Boundary Event Mover\n * Handles identification and movement of boundary event target nodes.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\n\n/**\n * Branch destination type enum for prioritization\n */\nexport enum BranchDestType {\n  MERGE_TO_MAIN = 1, // Branches that merge back to main flow (highest priority - closest to main flow)\n  TO_END_EVENT = 2, // Branches that end at end events (medium priority)\n  DEAD_END = 3, // Branches with no outgoing edges (lowest priority - furthest from main flow)\n}\n\n/**\n * Placed branch info for collision detection\n */\ninterface PlacedBranch {\n  minX: number;\n  maxX: number;\n  minY: number;\n  maxY: number;\n  destType: BranchDestType;\n}\n\n/**\n * Build maps for node lookups and edge relationships\n */\nexport function buildNodeAndEdgeMaps(\n  graph: ElkNode,\n  sizedGraph?: ElkBpmnGraph\n): {\n  nodeMap: Map<string, ElkNode>;\n  nodeTypeMap: Map<string, string>;\n  edgeMap: Map<string, string[]>;\n  reverseEdgeMap: Map<string, string[]>;\n} {\n  const nodeMap = new Map<string, ElkNode>();\n  const nodeTypeMap = new Map<string, string>();\n  const edgeMap = new Map<string, string[]>();\n  const reverseEdgeMap = new Map<string, string[]>();\n\n  // Helper to collect node types from sizedGraph\n  const collectNodeTypes = (node: NodeWithBpmn) => {\n    if (node.bpmn?.type) {\n      nodeTypeMap.set(node.id, node.bpmn.type);\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        collectNodeTypes(child as NodeWithBpmn);\n      }\n    }\n    if (node.boundaryEvents) {\n      for (const be of node.boundaryEvents) {\n        if ((be as NodeWithBpmn).bpmn?.type) {\n          nodeTypeMap.set(be.id, (be as NodeWithBpmn).bpmn!.type!);\n        }\n      }\n    }\n  };\n\n  // Collect node types from sizedGraph if provided\n  if (sizedGraph) {\n    for (const child of sizedGraph.children ?? []) {\n      collectNodeTypes(child as NodeWithBpmn);\n    }\n  }\n\n  const buildMaps = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (source && target) {\n          if (!edgeMap.has(source)) {\n            edgeMap.set(source, []);\n          }\n          edgeMap.get(source)!.push(target);\n\n          if (!reverseEdgeMap.has(target)) {\n            reverseEdgeMap.set(target, []);\n          }\n          reverseEdgeMap.get(target)!.push(source);\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        buildMaps(child);\n      }\n    }\n  };\n  buildMaps(graph);\n\n  return { nodeMap, nodeTypeMap, edgeMap, reverseEdgeMap };\n}\n\n/**\n * Identify nodes that need to be moved below their attached boundary event parent\n * Returns a map of node ID -> new position info\n */\nexport function identifyNodesToMove(\n  graph: ElkNode,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>,\n  sizedGraph: ElkBpmnGraph,\n  debug = false\n): Map<string, NodeMoveInfo> {\n  const movedNodes = new Map<string, NodeMoveInfo>();\n  const { nodeMap, nodeTypeMap, edgeMap, reverseEdgeMap } = buildNodeAndEdgeMaps(\n    graph,\n    sizedGraph\n  );\n\n  // Collect all boundary event target IDs (direct targets of boundary events)\n  const boundaryEventTargetIds = new Set<string>();\n  for (const [_beId, info] of boundaryEventInfo) {\n    for (const targetId of info.targets) {\n      boundaryEventTargetIds.add(targetId);\n    }\n  }\n\n  // Helper to check if a node is a merge point (has incoming edges from non-boundary-event sources)\n  const isMergePoint = (nodeId: string): boolean => {\n    const incomingSources = reverseEdgeMap.get(nodeId) || [];\n    if (incomingSources.length <= 1) return false;\n\n    for (const sourceId of incomingSources) {\n      if (!boundaryEventTargetIds.has(sourceId) && !movedNodes.has(sourceId)) {\n        if (debug) {\n          console.log(\n            `[BPMN] isMergePoint(${nodeId}): true - source ${sourceId} is from main flow`\n          );\n        }\n        return true;\n      }\n    }\n    if (debug) {\n      console.log(\n        `[BPMN] isMergePoint(${nodeId}): false - all ${incomingSources.length} sources are boundary event branches`\n      );\n    }\n    return false;\n  };\n\n  // Helper to trace a branch and determine its destination type\n  const getBranchDestinationType = (startNodeId: string): BranchDestType => {\n    const visited = new Set<string>();\n    const queue = [startNodeId];\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift()!;\n      if (visited.has(nodeId)) continue;\n      visited.add(nodeId);\n\n      const node = nodeMap.get(nodeId);\n      if (!node) continue;\n\n      if (isMergePoint(nodeId)) {\n        return BranchDestType.MERGE_TO_MAIN;\n      }\n\n      const outgoingTargets = edgeMap.get(nodeId) || [];\n\n      if (outgoingTargets.length === 0) {\n        const nodeType = nodeTypeMap.get(nodeId);\n        if (nodeType === 'endEvent') {\n          return BranchDestType.TO_END_EVENT;\n        }\n        return BranchDestType.DEAD_END;\n      }\n\n      for (const targetId of outgoingTargets) {\n        if (!visited.has(targetId)) {\n          if (isMergePoint(targetId)) {\n            return BranchDestType.MERGE_TO_MAIN;\n          }\n          queue.push(targetId);\n        }\n      }\n    }\n\n    return BranchDestType.DEAD_END;\n  };\n\n  // Collect all boundary events with targets\n  const boundaryEventsWithTargets: Array<{\n    beId: string;\n    info: BoundaryEventInfo;\n    attachedNode: ElkNode;\n    beX: number;\n    attachedRight: number;\n    destType: BranchDestType;\n  }> = [];\n\n  for (const [beId, info] of boundaryEventInfo) {\n    if (info.targets.length === 0) continue;\n    const attachedNode = nodeMap.get(info.attachedToRef);\n    if (\n      !attachedNode ||\n      attachedNode.y === undefined ||\n      attachedNode.height === undefined\n    )\n      continue;\n\n    const attachedX = attachedNode.x ?? 0;\n    const attachedWidth = attachedNode.width ?? 100;\n    const attachedRight = attachedX + attachedWidth;\n    const spacing = attachedWidth / (info.totalBoundaries + 1);\n    const beX = attachedX + spacing * (info.boundaryIndex + 1);\n\n    const destType =\n      info.targets.length > 0\n        ? getBranchDestinationType(info.targets[0])\n        : BranchDestType.DEAD_END;\n\n    boundaryEventsWithTargets.push({\n      beId,\n      info,\n      attachedNode,\n      beX,\n      attachedRight,\n      destType,\n    });\n\n    if (debug) {\n      console.log(\n        `[BPMN] Branch ${beId} -> ${info.targets[0]}: destType=${BranchDestType[destType]}`\n      );\n    }\n  }\n\n  // Sort boundary events by destination type, then by X position\n  boundaryEventsWithTargets.sort((a, b) => {\n    if (a.destType !== b.destType) {\n      return a.destType - b.destType;\n    }\n    const xDiff = a.beX - b.beX;\n    if (Math.abs(xDiff) > 1) return xDiff;\n    return a.info.boundaryIndex - b.info.boundaryIndex;\n  });\n\n  // Find the global bottom Y of all attached nodes\n  let mainFlowBottom = 0;\n  for (const be of boundaryEventsWithTargets) {\n    const attachedY = be.attachedNode.y ?? 0;\n    const attachedHeight = be.attachedNode.height ?? 80;\n    const attachedBottom = attachedY + attachedHeight;\n    mainFlowBottom = Math.max(mainFlowBottom, attachedBottom);\n  }\n\n  // Layout constants\n  const minGap = 35;\n  const mergeToMainBaseY = mainFlowBottom + minGap + 50;\n  const toEndEventBaseY = mergeToMainBaseY + 80;\n  const deadEndBaseY = toEndEventBaseY + 100;\n  const horizontalGap = 50;\n\n  // Track placed branches\n  const placedBranches: PlacedBranch[] = [];\n\n  // Helper to calculate branch bounds\n  const calculateBranchBounds = (\n    targetId: string,\n    newX: number\n  ): { minX: number; maxX: number; height: number } => {\n    const targetNode = nodeMap.get(targetId);\n    const targetWidth = targetNode?.width ?? 100;\n    const targetHeight = targetNode?.height ?? 80;\n\n    let maxX = newX + targetWidth;\n    let totalHeight = targetHeight;\n\n    const visited = new Set<string>();\n    const queue = [targetId];\n    let currentMaxX = newX + targetWidth;\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift()!;\n      if (visited.has(nodeId)) continue;\n      visited.add(nodeId);\n\n      const downstreamTargets = edgeMap.get(nodeId) || [];\n      for (const downId of downstreamTargets) {\n        if (isMergePoint(downId)) continue;\n\n        const downNode = nodeMap.get(downId);\n        if (downNode && !visited.has(downId)) {\n          const downWidth = downNode.width ?? 36;\n          currentMaxX += 20 + downWidth;\n          maxX = Math.max(maxX, currentMaxX);\n          totalHeight = Math.max(totalHeight, downNode.height ?? 36);\n          queue.push(downId);\n        }\n      }\n    }\n\n    return { minX: newX, maxX, height: totalHeight };\n  };\n\n  // Helper to check if X ranges overlap\n  const xRangesOverlap = (\n    minX1: number,\n    maxX1: number,\n    minX2: number,\n    maxX2: number\n  ): boolean => {\n    return !(maxX1 + horizontalGap < minX2 || maxX2 + horizontalGap < minX1);\n  };\n\n  // Helper to get base Y for each destination type\n  const getLayerBaseY = (destType: BranchDestType): number => {\n    switch (destType) {\n      case BranchDestType.MERGE_TO_MAIN:\n        return mergeToMainBaseY;\n      case BranchDestType.TO_END_EVENT:\n        return toEndEventBaseY;\n      case BranchDestType.DEAD_END:\n        return deadEndBaseY;\n      default:\n        return deadEndBaseY;\n    }\n  };\n\n  // Helper to find appropriate Y position for a new branch\n  const findYPosition = (\n    branchMinX: number,\n    branchMaxX: number,\n    branchHeight: number,\n    destType: BranchDestType\n  ): number => {\n    const layerBaseY = getLayerBaseY(destType);\n    let candidateY = layerBaseY;\n\n    const overlappingBranches = placedBranches.filter((b) =>\n      xRangesOverlap(branchMinX, branchMaxX, b.minX, b.maxX)\n    );\n\n    if (overlappingBranches.length === 0) {\n      return candidateY;\n    }\n\n    for (const branch of overlappingBranches) {\n      const requiredY = branch.maxY + minGap + 20;\n      candidateY = Math.max(candidateY, requiredY);\n    }\n\n    return candidateY;\n  };\n\n  // Process all boundary events in sorted order\n  for (const beEntry of boundaryEventsWithTargets) {\n    const { info, beX, attachedRight, destType } = beEntry;\n\n    if (debug) {\n      console.log(\n        `[BPMN] Processing boundary event at X=${beX} for ${info.attachedToRef}, destType=${BranchDestType[destType]}`\n      );\n    }\n\n    for (const targetId of info.targets) {\n      const targetNode = nodeMap.get(targetId);\n      if (!targetNode || targetNode.y === undefined) continue;\n\n      const targetWidth = targetNode.width ?? 100;\n      const targetHeight = targetNode.height ?? 80;\n\n      // Calculate new X position based on destination type\n      let newX: number;\n      if (destType === BranchDestType.MERGE_TO_MAIN) {\n        newX = attachedRight + 30;\n      } else if (destType === BranchDestType.TO_END_EVENT) {\n        newX = beX + 20;\n      } else {\n        newX = beX;\n      }\n\n      // Calculate branch bounds\n      const branchBounds = calculateBranchBounds(targetId, newX);\n\n      // Find appropriate Y position\n      const newY = findYPosition(\n        branchBounds.minX,\n        branchBounds.maxX,\n        branchBounds.height,\n        destType\n      );\n      const offset = newY - (targetNode.y ?? 0);\n      movedNodes.set(targetId, { newY, offset, newX });\n\n      if (debug) {\n        console.log(\n          `[BPMN] Moving ${targetId}: (${targetNode.x},${targetNode.y}) -> (${newX},${newY}), destType=${BranchDestType[destType]}`\n        );\n      }\n\n      // Propagate movement to downstream nodes\n      propagateMovement(\n        targetId,\n        newY,\n        nodeMap,\n        edgeMap,\n        movedNodes,\n        newX,\n        isMergePoint,\n        debug\n      );\n\n      // Register this branch\n      placedBranches.push({\n        minX: branchBounds.minX,\n        maxX: branchBounds.maxX,\n        minY: newY,\n        maxY: newY + branchBounds.height,\n        destType,\n      });\n    }\n  }\n\n  // Align merge-point end events with their main-flow predecessor.\n  // ELK can place a convergence end event (one that has both a main-flow\n  // incoming and a boundary branch incoming) far from the main flow band\n  // because it averages incoming-edge Y. Snap it back so the main flow\n  // doesn't curve up/down to reach the end event.\n  for (const [nodeId, node] of nodeMap) {\n    if (movedNodes.has(nodeId)) continue;\n    if (nodeTypeMap.get(nodeId) !== 'endEvent') continue;\n    const sources = reverseEdgeMap.get(nodeId) || [];\n    if (sources.length <= 1) continue;\n\n    let mainFlowSourceY: number | undefined;\n    let mainFlowSourceHeight = 80;\n    for (const sourceId of sources) {\n      if (boundaryEventTargetIds.has(sourceId) || movedNodes.has(sourceId)) continue;\n      if (sourceId.startsWith('boundary_')) continue;\n      const sourceNode = nodeMap.get(sourceId);\n      if (!sourceNode || sourceNode.y === undefined) continue;\n      mainFlowSourceY = sourceNode.y;\n      mainFlowSourceHeight = sourceNode.height ?? 80;\n      break;\n    }\n    if (mainFlowSourceY === undefined) continue;\n\n    const currentY = node.y ?? 0;\n    const currentHeight = node.height ?? 36;\n    const alignedY = mainFlowSourceY + (mainFlowSourceHeight - currentHeight) / 2;\n    if (Math.abs(currentY - alignedY) < 10) continue;\n\n    movedNodes.set(nodeId, {\n      newY: alignedY,\n      offset: alignedY - currentY,\n      newX: undefined,\n    });\n    if (debug) {\n      console.log(\n        `[BPMN] Aligning merge-point end event ${nodeId}: y ${currentY} -> ${alignedY} (main source y=${mainFlowSourceY})`\n      );\n    }\n  }\n\n  return movedNodes;\n}\n\n/**\n * Propagate movement to downstream nodes\n */\nexport function propagateMovement(\n  sourceId: string,\n  sourceNewY: number,\n  nodeMap: Map<string, ElkNode>,\n  edgeMap: Map<string, string[]>,\n  movedNodes: Map<string, NodeMoveInfo>,\n  sourceNewX?: number,\n  isMergePoint?: (nodeId: string) => boolean,\n  debug = false\n): void {\n  const sourceNode = nodeMap.get(sourceId);\n  const sourceWidth = sourceNode?.width ?? 100;\n  const sourceHeight = sourceNode?.height ?? 80;\n\n  const targets = edgeMap.get(sourceId) || [];\n  for (const targetId of targets) {\n    if (movedNodes.has(targetId)) {\n      const existingMove = movedNodes.get(targetId)!;\n      const currentSourceRight = (sourceNewX ?? 0) + sourceWidth + 20;\n\n      if (\n        existingMove.newX !== undefined &&\n        currentSourceRight > existingMove.newX\n      ) {\n        existingMove.newX = currentSourceRight;\n        if (debug) {\n          console.log(\n            `[BPMN] propagateMovement: updating ${targetId} X to ${currentSourceRight} (source is further right)`\n          );\n        }\n      } else if (debug) {\n        console.log(\n          `[BPMN] propagateMovement: skipping ${targetId} - already moved`\n        );\n      }\n      continue;\n    }\n\n    if (isMergePoint && isMergePoint(targetId)) {\n      if (debug) {\n        console.log(\n          `[BPMN] propagateMovement: skipping ${targetId} - is merge point`\n        );\n      }\n      continue;\n    }\n\n    const targetNode = nodeMap.get(targetId);\n    if (!targetNode || targetNode.y === undefined) continue;\n\n    const targetHeight = targetNode.height ?? 36;\n    const newY = sourceNewY + (sourceHeight - targetHeight) / 2;\n    const offset = newY - (targetNode.y ?? 0);\n\n    let newX: number | undefined;\n    if (sourceNewX !== undefined) {\n      newX = sourceNewX + sourceWidth + 20;\n    }\n\n    movedNodes.set(targetId, { newY, offset, newX });\n\n    if (debug) {\n      console.log(\n        `[BPMN] propagateMovement: moving ${targetId} to y=${newY}, newX=${newX}`\n      );\n    }\n\n    propagateMovement(\n      targetId,\n      newY,\n      nodeMap,\n      edgeMap,\n      movedNodes,\n      newX,\n      isMergePoint,\n      debug\n    );\n  }\n}\n\n/**\n * Reposition converging gateways based on their incoming edges.\n */\nexport function repositionConvergingGateways(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>,\n  debug = false\n): Map<string, NodeMoveInfo> {\n  const gatewayMoves = new Map<string, NodeMoveInfo>();\n\n  const nodeMap = new Map<string, ElkNode>();\n  const reverseEdgeMap = new Map<string, string[]>();\n\n  const buildMaps = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const source = edge.sources?.[0];\n        const target = edge.targets?.[0];\n        if (source && target) {\n          if (!reverseEdgeMap.has(target)) {\n            reverseEdgeMap.set(target, []);\n          }\n          reverseEdgeMap.get(target)!.push(source);\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        buildMaps(child);\n      }\n    }\n  };\n  buildMaps(graph);\n\n  // Collect boundary event target IDs\n  const boundaryEventTargetIds = new Set<string>();\n  for (const [_beId, info] of boundaryEventInfo) {\n    for (const targetId of info.targets) {\n      boundaryEventTargetIds.add(targetId);\n    }\n  }\n\n  // Find converging gateways\n  for (const [nodeId, node] of nodeMap) {\n    const incomingSources = reverseEdgeMap.get(nodeId) || [];\n    if (incomingSources.length <= 1) continue;\n\n    let hasMainFlowInput = false;\n    let hasBoundaryBranchInput = false;\n\n    for (const sourceId of incomingSources) {\n      if (boundaryEventTargetIds.has(sourceId) || movedNodes.has(sourceId)) {\n        hasBoundaryBranchInput = true;\n      } else if (!sourceId.startsWith('boundary_')) {\n        hasMainFlowInput = true;\n      }\n    }\n\n    if (!hasMainFlowInput || !hasBoundaryBranchInput) continue;\n\n    let maxSourceRightX = 0;\n    for (const sourceId of incomingSources) {\n      const sourceNode = nodeMap.get(sourceId);\n      if (!sourceNode) continue;\n\n      const moveInfo = movedNodes.get(sourceId);\n      const sourceX = moveInfo?.newX ?? sourceNode.x ?? 0;\n      const sourceWidth = sourceNode.width ?? 100;\n      const sourceRightX = sourceX + sourceWidth;\n\n      maxSourceRightX = Math.max(maxSourceRightX, sourceRightX);\n    }\n\n    const gatewayGap = 50;\n    const newGatewayX = maxSourceRightX + gatewayGap;\n    const currentGatewayX = node.x ?? 0;\n\n    if (newGatewayX > currentGatewayX) {\n      const currentY = node.y ?? 0;\n      gatewayMoves.set(nodeId, {\n        newY: currentY,\n        offset: 0,\n        newX: newGatewayX,\n      });\n\n      if (debug) {\n        console.log(\n          `[BPMN] Repositioning converging gateway ${nodeId}: x ${currentGatewayX} -> ${newGatewayX}`\n        );\n      }\n    }\n  }\n\n  return gatewayMoves;\n}\n\n/**\n * Apply node moves to the layouted graph\n */\nexport function applyNodeMoves(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>\n): void {\n  const applyMoves = (node: ElkNode) => {\n    const moveInfo = movedNodes.get(node.id);\n    if (moveInfo && node.y !== undefined) {\n      node.y = moveInfo.newY;\n      if (moveInfo.newX !== undefined) {\n        node.x = moveInfo.newX;\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        applyMoves(child);\n      }\n    }\n  };\n  applyMoves(graph);\n}\n","/**\n * Shared Debug Utilities\n * Centralized debug flag for consistent debug logging across the codebase.\n */\n\n/**\n * Flag to indicate CLI mode where debug output should be suppressed\n * to ensure clean stdout output.\n */\nlet cliMode = false;\n\n/**\n * Enable CLI mode which suppresses all debug output.\n * This should be called at the very start of the CLI entry point.\n */\nexport function enableCliMode(): void {\n  cliMode = true;\n}\n\n/**\n * Check if CLI mode is enabled.\n */\nexport function isCliMode(): boolean {\n  return cliMode;\n}\n\n/**\n * Check if debug logging is enabled.\n * Returns true only when DEBUG=true environment variable is set AND not in CLI mode.\n *\n * @example\n * ```bash\n * DEBUG=true bun run test -- -t \"21-subprocess\"\n * ```\n */\nexport function isDebugEnabled(): boolean {\n  if (cliMode) return false;\n\n  try {\n    return typeof process !== 'undefined' &&\n           typeof process.env !== 'undefined' &&\n           process.env?.['DEBUG'] === 'true';\n  } catch (e) {\n    // In browser environments, accessing process may throw an error\n    return false;\n  }\n}\n","/**\n * Edge Recalculator for Boundary Events\n * Handles edge waypoint recalculation for moved boundary event nodes.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Point, Bounds, BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\nimport { isDebugEnabled } from '../../../utils/debug';\n\n/**\n * Recalculate edge waypoints for edges connected to moved nodes\n * Implements orthogonal routing with obstacle avoidance\n */\nexport function recalculateEdgesForMovedNodes(\n  graph: ElkNode,\n  movedNodes: Map<string, NodeMoveInfo>,\n  boundaryEventInfo: Map<string, BoundaryEventInfo>\n): void {\n  const debug = isDebugEnabled();\n  // Build node map for position lookups (including boundary events)\n  const nodeMap = new Map<string, ElkNode>();\n  const buildNodeMap = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.children) {\n      for (const child of node.children) {\n        buildNodeMap(child);\n      }\n    }\n    // Also include boundary events\n    const nodeWithBE = node as unknown as { boundaryEvents?: ElkNode[] };\n    if (nodeWithBE.boundaryEvents) {\n      for (const be of nodeWithBE.boundaryEvents) {\n        nodeMap.set(be.id, be);\n      }\n    }\n  };\n  buildNodeMap(graph);\n\n  // Get all obstacle IDs: all flow nodes that could block edge paths\n  const obstacleIds = new Set<string>();\n\n  // Add attached nodes\n  for (const [, info] of boundaryEventInfo) {\n    obstacleIds.add(info.attachedToRef);\n  }\n  // Add all moved nodes as obstacles (they may block edge paths)\n  for (const [nodeId] of movedNodes) {\n    obstacleIds.add(nodeId);\n  }\n\n  // Add all flow nodes as potential obstacles (tasks, gateways, events, etc.)\n  const flowNodePatterns = [\n    /^task_/, /^gateway_/, /^start_/, /^end_/,\n    /^subprocess_/, /^call_/, /^intermediate_/, /^event_/, /^catch_/,\n  ];\n  for (const [nodeId] of nodeMap) {\n    if (flowNodePatterns.some(pattern => pattern.test(nodeId))) {\n      obstacleIds.add(nodeId);\n    }\n  }\n\n  // Calculate correct boundary event positions (they are attached to the bottom of their parent)\n  const boundaryEventPositions = new Map<string, Bounds>();\n  for (const [beId, info] of boundaryEventInfo) {\n    const attachedNode = nodeMap.get(info.attachedToRef);\n    if (attachedNode && attachedNode.x !== undefined && attachedNode.y !== undefined) {\n      const attachedX = attachedNode.x;\n      const attachedY = attachedNode.y;\n      const attachedWidth = attachedNode.width ?? 100;\n      const attachedHeight = attachedNode.height ?? 80;\n      const beWidth = 36;\n      const beHeight = 36;\n\n      // Calculate position on the bottom edge of the attached node\n      const spacing = attachedWidth / (info.totalBoundaries + 1);\n      const beX = attachedX + spacing * (info.boundaryIndex + 1) - beWidth / 2;\n      const beY = attachedY + attachedHeight - beHeight / 2;\n\n      boundaryEventPositions.set(beId, { x: beX, y: beY, width: beWidth, height: beHeight });\n    }\n  }\n\n  // Find and recalculate edges in each node\n  const processEdges = (node: ElkNode) => {\n    if (node.edges) {\n      for (const edge of node.edges) {\n        const sourceId = edge.sources?.[0];\n        const targetId = edge.targets?.[0];\n\n        if (!sourceId || !targetId) continue;\n\n        // Recalculate if source OR target was moved, OR source is a boundary event\n        const sourceMoved = movedNodes.has(sourceId);\n        const targetMoved = movedNodes.has(targetId);\n        const sourceIsBoundaryEvent = boundaryEventInfo.has(sourceId);\n\n        if (sourceMoved || targetMoved || sourceIsBoundaryEvent) {\n          let sourceNode = nodeMap.get(sourceId);\n          const targetNode = nodeMap.get(targetId);\n\n          // For boundary events, use the calculated position\n          if (sourceIsBoundaryEvent && boundaryEventPositions.has(sourceId)) {\n            const bePos = boundaryEventPositions.get(sourceId)!;\n            sourceNode = { ...sourceNode, ...bePos } as ElkNode;\n          }\n\n          if (sourceNode && targetNode) {\n            recalculateEdgeWithObstacleAvoidance(\n              edge,\n              sourceNode,\n              targetNode,\n              obstacleIds,\n              nodeMap\n            );\n          }\n        }\n      }\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        processEdges(child);\n      }\n    }\n  };\n  processEdges(graph);\n}\n\n/**\n * Recalculate edge waypoints with orthogonal routing that avoids obstacles.\n * Key constraints:\n * 1. Edges MUST connect perpendicular to node boundaries\n * 2. Edges MUST NOT pass through any node\n */\nexport function recalculateEdgeWithObstacleAvoidance(\n  edge: ElkExtendedEdge,\n  source: ElkNode,\n  target: ElkNode,\n  obstacleIds: Set<string>,\n  nodeMap: Map<string, ElkNode>\n): void {\n  const debug = isDebugEnabled();\n  const sx = source.x ?? 0;\n  const sy = source.y ?? 0;\n  const sw = source.width ?? 100;\n  const sh = source.height ?? 80;\n\n  const tx = target.x ?? 0;\n  const ty = target.y ?? 0;\n  const tw = target.width ?? 36;\n  const th = target.height ?? 36;\n\n  // Collect all obstacles (excluding source and target)\n  const obstacles: Bounds[] = [];\n  for (const obsId of obstacleIds) {\n    const obs = nodeMap.get(obsId);\n    if (obs && obs.x !== undefined && obs.y !== undefined) {\n      // Skip source and target\n      if (obs.x === sx && obs.y === sy) continue;\n      if (obs.x === tx && obs.y === ty) continue;\n      obstacles.push({\n        x: obs.x,\n        y: obs.y,\n        width: obs.width ?? 100,\n        height: obs.height ?? 80,\n      });\n    }\n  }\n\n  if (debug) {\n    console.log(\n      `[BPMN] Edge ${edge.id}: source(${sx},${sy},${sw},${sh}) -> target(${tx},${ty},${tw},${th}), obstacles: ${obstacles.length}`\n    );\n  }\n\n  // Determine primary direction of travel\n  const dx = tx - sx;\n  const dy = ty - sy;\n  const absDx = Math.abs(dx);\n  const absDy = Math.abs(dy);\n  const isPrimarilyVertical = absDy > absDx;\n\n  const waypoints: Point[] = [];\n\n  if (isPrimarilyVertical && dy > 0) {\n    // Primary direction is DOWN - exit from bottom, enter from top\n    const startX = sx + sw / 2;\n    const startY = sy + sh;\n    const endX = tx + tw / 2;\n    const endY = ty;\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Check for obstacles that would block a direct vertical path\n    const obstaclesToAvoid = findBlockingObstacles(\n      startX,\n      startY,\n      endX,\n      endY,\n      obstacles,\n      'vertical'\n    );\n\n    if (obstaclesToAvoid.length > 0) {\n      // Calculate left routing X\n      let leftAvoidX = Math.min(startX, endX);\n      for (const obs of obstaclesToAvoid) {\n        leftAvoidX = Math.min(leftAvoidX, obs.x - 30);\n      }\n      for (const obs of obstacles) {\n        if (obs.y < endY && obs.y + obs.height > startY) {\n          if (obs.x <= leftAvoidX + 20 && obs.x + obs.width >= leftAvoidX - 20) {\n            leftAvoidX = Math.min(leftAvoidX, obs.x - 30);\n          }\n        }\n      }\n\n      // Calculate right routing X\n      let rightAvoidX = Math.max(startX, endX);\n      for (const obs of obstaclesToAvoid) {\n        rightAvoidX = Math.max(rightAvoidX, obs.x + obs.width + 30);\n      }\n      for (const obs of obstacles) {\n        if (obs.y < endY && obs.y + obs.height > startY) {\n          if (obs.x <= rightAvoidX + 20 && obs.x + obs.width >= rightAvoidX - 20) {\n            rightAvoidX = Math.max(rightAvoidX, obs.x + obs.width + 30);\n          }\n        }\n      }\n\n      // Choose the shorter detour\n      const leftDistance = Math.abs(startX - leftAvoidX) + Math.abs(endX - leftAvoidX);\n      const rightDistance = Math.abs(startX - rightAvoidX) + Math.abs(endX - rightAvoidX);\n      const avoidX = leftDistance <= rightDistance ? leftAvoidX : rightAvoidX;\n\n      const exitY = startY + 20;\n      waypoints.push({ x: startX, y: exitY });\n      waypoints.push({ x: avoidX, y: exitY });\n      waypoints.push({ x: avoidX, y: endY - 20 });\n      waypoints.push({ x: endX, y: endY - 20 });\n    } else {\n      // No obstacles - simple Z-routing\n      const midY = (startY + endY) / 2;\n      waypoints.push({ x: startX, y: midY });\n      waypoints.push({ x: endX, y: midY });\n    }\n\n    waypoints.push({ x: endX, y: endY });\n  } else if (isPrimarilyVertical && dy < 0) {\n    // Primary direction is UP - exit from right, enter from bottom\n    const startX = sx + sw;\n    const startY = sy + sh / 2;\n    const endX = tx + tw / 2;\n    const endY = ty + th;\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Find clearX that avoids all obstacles in the vertical path\n    let clearX = Math.max(sx + sw, tx + tw) + 30;\n    for (const obs of obstacles) {\n      if (obs.y < sy && obs.y + obs.height > ty) {\n        clearX = Math.max(clearX, obs.x + obs.width + 30);\n      }\n    }\n\n    // Check if the horizontal segment at endY would cross any obstacles\n    // The horizontal segment goes from (clearX, endY) to (endX, endY)\n    let horizontalClearY = endY;\n    const horizSegMinX = Math.min(clearX, endX);\n    const horizSegMaxX = Math.max(clearX, endX);\n    const margin = 20; // Minimum distance from obstacles\n\n    for (const obs of obstacles) {\n      // Check if obstacle overlaps with the horizontal segment\n      const obsRight = obs.x + obs.width;\n      const obsBottom = obs.y + obs.height;\n\n      // If obstacle is in the horizontal path (x-range overlaps)\n      if (obs.x < horizSegMaxX && obsRight > horizSegMinX) {\n        // And the horizontal segment is too close to the obstacle\n        if (horizontalClearY >= obs.y - margin && horizontalClearY <= obsBottom + margin) {\n          // Move the horizontal segment below this obstacle\n          horizontalClearY = Math.max(horizontalClearY, obsBottom + margin);\n        }\n      }\n    }\n\n    // Route: right -> down to clearY -> left to endX -> up to target\n    if (horizontalClearY > endY) {\n      // Need to go around obstacles below them\n      waypoints.push({ x: clearX, y: startY });\n      waypoints.push({ x: clearX, y: horizontalClearY });\n      waypoints.push({ x: endX, y: horizontalClearY });\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Original simple routing\n      waypoints.push({ x: clearX, y: startY });\n      waypoints.push({ x: clearX, y: endY });\n      waypoints.push({ x: endX, y: endY });\n    }\n  } else if (!isPrimarilyVertical && dx > 0) {\n    // Primary direction is RIGHT - exit from right, enter from left\n    const startX = sx + sw;\n    const startY = sy + sh / 2;\n    const endX = tx;\n    const endY = ty + th / 2;\n\n    waypoints.push({ x: startX, y: startY });\n\n    const obstaclesToAvoid = findBlockingObstacles(\n      startX,\n      startY,\n      endX,\n      endY,\n      obstacles,\n      'horizontal'\n    );\n\n    if (obstaclesToAvoid.length > 0) {\n      let clearY = Math.max(sy + sh, ty + th) + 30;\n      for (const obs of obstaclesToAvoid) {\n        clearY = Math.max(clearY, obs.y + obs.height + 30);\n      }\n\n      waypoints.push({ x: startX + 20, y: startY });\n      waypoints.push({ x: startX + 20, y: clearY });\n      waypoints.push({ x: endX - 20, y: clearY });\n      waypoints.push({ x: endX - 20, y: endY });\n    } else {\n      // Simple Z-routing\n      const midX = (startX + endX) / 2;\n      waypoints.push({ x: midX, y: startY });\n      waypoints.push({ x: midX, y: endY });\n    }\n\n    waypoints.push({ x: endX, y: endY });\n  } else {\n    // Primary direction is LEFT - exit from left, enter from right\n    const startX = sx;\n    const startY = sy + sh / 2;\n    const endX = tx + tw;\n    const endY = ty + th / 2;\n\n    waypoints.push({ x: startX, y: startY });\n\n    let clearX = Math.min(sx, tx) - 30;\n    for (const obs of obstacles) {\n      clearX = Math.min(clearX, obs.x - 30);\n    }\n\n    waypoints.push({ x: clearX, y: startY });\n    waypoints.push({ x: clearX, y: endY });\n    waypoints.push({ x: endX, y: endY });\n  }\n\n  // Update edge sections\n  const firstWaypoint = waypoints[0];\n  const lastWaypoint = waypoints[waypoints.length - 1];\n  if (waypoints.length >= 2 && firstWaypoint && lastWaypoint) {\n    edge.sections = [\n      {\n        id: `${edge.id}_section_0`,\n        startPoint: firstWaypoint,\n        endPoint: lastWaypoint,\n        bendPoints: waypoints.slice(1, -1),\n      },\n    ];\n\n    if (debug) {\n      console.log(`[BPMN] Waypoints for ${edge.id}: ${JSON.stringify(waypoints)}`);\n    }\n  }\n}\n\n/**\n * Find obstacles that block a path between two points\n */\nexport function findBlockingObstacles(\n  startX: number,\n  startY: number,\n  endX: number,\n  endY: number,\n  obstacles: Bounds[],\n  direction: 'vertical' | 'horizontal'\n): Bounds[] {\n  const blocking: Bounds[] = [];\n  const margin = 5;\n\n  for (const obs of obstacles) {\n    const obsRight = obs.x + obs.width;\n    const obsBottom = obs.y + obs.height;\n\n    if (direction === 'vertical') {\n      const pathMinX = Math.min(startX, endX) - margin;\n      const pathMaxX = Math.max(startX, endX) + margin;\n      const pathMinY = Math.min(startY, endY);\n      const pathMaxY = Math.max(startY, endY);\n\n      if (obs.y < pathMaxY && obsBottom > pathMinY) {\n        if (obs.x < pathMaxX && obsRight > pathMinX) {\n          blocking.push(obs);\n        }\n      }\n    } else {\n      const pathMinX = Math.min(startX, endX);\n      const pathMaxX = Math.max(startX, endX);\n      const pathMinY = Math.min(startY, endY) - margin;\n      const pathMaxY = Math.max(startY, endY) + margin;\n\n      if (obs.x < pathMaxX && obsRight > pathMinX) {\n        if (obs.y < pathMaxY && obsBottom > pathMinY) {\n          blocking.push(obs);\n        }\n      }\n    }\n  }\n\n  return blocking;\n}\n","/**\n * Boundary Event Post-Processing Module\n * Re-exports all boundary event related functionality.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../../types';\nimport type { BoundaryEventInfo, NodeMoveInfo } from '../../../types/internal';\n\n// Export collector function\nexport { collectBoundaryEventInfo } from './collector';\n\n// Export mover functions\nexport {\n  identifyNodesToMove,\n  repositionConvergingGateways,\n  applyNodeMoves,\n  propagateMovement,\n  BranchDestType,\n} from './mover';\n\n// Export edge recalculator functions\nexport {\n  recalculateEdgesForMovedNodes,\n  recalculateEdgeWithObstacleAvoidance,\n  findBlockingObstacles,\n} from './edge-recalculator';\n\n// Import for class implementation\nimport { collectBoundaryEventInfo } from './collector';\nimport {\n  identifyNodesToMove,\n  repositionConvergingGateways,\n  applyNodeMoves,\n} from './mover';\nimport { recalculateEdgesForMovedNodes } from './edge-recalculator';\n\n/**\n * Handler for boundary event post-processing\n * Wraps the extracted functions in a class interface for backward compatibility.\n */\nexport class BoundaryEventHandler {\n  /**\n   * Collect boundary event information for post-processing\n   * Returns a map of boundary event ID -> { attachedToRef, targets, boundaryIndex, totalBoundaries }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, BoundaryEventInfo> {\n    return collectBoundaryEventInfo(graph);\n  }\n\n  /**\n   * Identify nodes that need to be moved below their attached boundary event parent\n   * Returns a map of node ID -> new position info\n   */\n  identifyNodesToMove(\n    graph: ElkNode,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>,\n    sizedGraph: ElkBpmnGraph,\n    debug = false\n  ): Map<string, NodeMoveInfo> {\n    return identifyNodesToMove(graph, boundaryEventInfo, sizedGraph, debug);\n  }\n\n  /**\n   * Reposition converging gateways based on their incoming edges.\n   */\n  repositionConvergingGateways(\n    graph: ElkNode,\n    movedNodes: Map<string, NodeMoveInfo>,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>,\n    debug = false\n  ): Map<string, NodeMoveInfo> {\n    return repositionConvergingGateways(graph, movedNodes, boundaryEventInfo, debug);\n  }\n\n  /**\n   * Apply node moves to the layouted graph\n   */\n  applyNodeMoves(graph: ElkNode, movedNodes: Map<string, NodeMoveInfo>): void {\n    applyNodeMoves(graph, movedNodes);\n  }\n\n  /**\n   * Recalculate edge waypoints for edges connected to moved nodes\n   */\n  recalculateEdgesForMovedNodes(\n    graph: ElkNode,\n    movedNodes: Map<string, NodeMoveInfo>,\n    boundaryEventInfo: Map<string, BoundaryEventInfo>\n  ): void {\n    recalculateEdgesForMovedNodes(graph, movedNodes, boundaryEventInfo);\n  }\n}\n","/**\n * Geometry Utilities for Edge Routing\n * Provides geometric calculation functions for edge routing and obstacle avoidance.\n */\n\nimport type { Point, Bounds } from '../../types/internal';\n\n/**\n * Calculate Euclidean distance between two points\n */\nexport function distance(p1: Point, p2: Point): number {\n  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\n\n/**\n * Calculate total path length of a series of waypoints\n */\nexport function calculatePathLength(waypoints: Point[]): number {\n  let length = 0;\n  for (let i = 0; i < waypoints.length - 1; i++) {\n    const p1 = waypoints[i];\n    const p2 = waypoints[i + 1];\n    if (p1 && p2) {\n      length += distance(p1, p2);\n    }\n  }\n  return length;\n}\n\n/**\n * Check if a line segment intersects a rectangle\n * Used for detecting edge-node collisions\n */\nexport function segmentIntersectsRect(\n  p1: Point,\n  p2: Point,\n  rect: Bounds\n): boolean {\n  const margin = 5;\n  const left = rect.x - margin;\n  const right = rect.x + rect.width + margin;\n  const top = rect.y - margin;\n  const bottom = rect.y + rect.height + margin;\n\n  // Check if both points are on the same side of the rectangle\n  if ((p1.x < left && p2.x < left) || (p1.x > right && p2.x > right)) return false;\n  if ((p1.y < top && p2.y < top) || (p1.y > bottom && p2.y > bottom)) return false;\n\n  // Check if segment is horizontal or vertical\n  if (Math.abs(p1.x - p2.x) < 1) {\n    // Vertical segment\n    const x = p1.x;\n    const minY = Math.min(p1.y, p2.y);\n    const maxY = Math.max(p1.y, p2.y);\n    return x >= left && x <= right && maxY >= top && minY <= bottom;\n  }\n\n  if (Math.abs(p1.y - p2.y) < 1) {\n    // Horizontal segment\n    const y = p1.y;\n    const minX = Math.min(p1.x, p2.x);\n    const maxX = Math.max(p1.x, p2.x);\n    return y >= top && y <= bottom && maxX >= left && minX <= right;\n  }\n\n  // For diagonal segments (shouldn't happen in orthogonal routing)\n  return true; // Assume intersection if not axis-aligned\n}\n\n/**\n * Check if a line segment crosses through a node's interior\n * More strict than segmentIntersectsRect - requires passing through the interior\n */\nexport function segmentCrossesNode(\n  p1: Point,\n  p2: Point,\n  node: Bounds\n): boolean {\n  const margin = 5;\n  const nodeLeft = node.x - margin;\n  const nodeRight = node.x + node.width + margin;\n  const nodeTop = node.y - margin;\n  const nodeBottom = node.y + node.height + margin;\n\n  // Check if segment is horizontal\n  if (Math.abs(p1.y - p2.y) < 1) {\n    const segY = p1.y;\n    const segMinX = Math.min(p1.x, p2.x);\n    const segMaxX = Math.max(p1.x, p2.x);\n\n    // Segment crosses if: y is within node's vertical range AND segment spans node's horizontal range\n    if (segY > nodeTop && segY < nodeBottom) {\n      if (segMinX < nodeRight && segMaxX > nodeLeft) {\n        // Check if segment actually passes through the interior (not just touching edges)\n        const interiorLeft = node.x + margin;\n        const interiorRight = node.x + node.width - margin;\n        if (segMinX < interiorRight && segMaxX > interiorLeft) {\n          return true;\n        }\n      }\n    }\n  }\n\n  // Check if segment is vertical\n  if (Math.abs(p1.x - p2.x) < 1) {\n    const segX = p1.x;\n    const segMinY = Math.min(p1.y, p2.y);\n    const segMaxY = Math.max(p1.y, p2.y);\n\n    // Segment crosses if: x is within node's horizontal range AND segment spans node's vertical range\n    if (segX > nodeLeft && segX < nodeRight) {\n      if (segMinY < nodeBottom && segMaxY > nodeTop) {\n        // Check if segment actually passes through the interior\n        const interiorTop = node.y + margin;\n        const interiorBottom = node.y + node.height - margin;\n        if (segMinY < interiorBottom && segMaxY > interiorTop) {\n          return true;\n        }\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Check if two rectangles overlap\n */\nexport function boundsOverlap(a: Bounds, b: Bounds, margin: number = 0): boolean {\n  return !(\n    a.x + a.width + margin < b.x ||\n    b.x + b.width + margin < a.x ||\n    a.y + a.height + margin < b.y ||\n    b.y + b.height + margin < a.y\n  );\n}\n\n/**\n * Get the center point of a bounds\n */\nexport function getCenter(bounds: Bounds): Point {\n  return {\n    x: bounds.x + bounds.width / 2,\n    y: bounds.y + bounds.height / 2,\n  };\n}\n\n/**\n * Calculate the midpoint between two points\n */\nexport function getMidpoint(p1: Point, p2: Point): Point {\n  return {\n    x: (p1.x + p2.x) / 2,\n    y: (p1.y + p2.y) / 2,\n  };\n}\n\n/**\n * Calculate connection point on a node based on direction\n */\nexport type ConnectionSide = 'left' | 'right' | 'top' | 'bottom';\n\nexport function getConnectionPoint(\n  bounds: Bounds,\n  side: ConnectionSide\n): Point {\n  const center = getCenter(bounds);\n\n  switch (side) {\n    case 'left':\n      return { x: bounds.x, y: center.y };\n    case 'right':\n      return { x: bounds.x + bounds.width, y: center.y };\n    case 'top':\n      return { x: center.x, y: bounds.y };\n    case 'bottom':\n      return { x: center.x, y: bounds.y + bounds.height };\n  }\n}\n\n/**\n * Determine the best connection side based on relative positions\n */\nexport function determineBestConnectionSide(\n  source: Bounds,\n  target: Bounds\n): { sourceSide: ConnectionSide; targetSide: ConnectionSide } {\n  const sourceCenter = getCenter(source);\n  const targetCenter = getCenter(target);\n\n  const dx = targetCenter.x - sourceCenter.x;\n  const dy = targetCenter.y - sourceCenter.y;\n\n  // Determine primary direction\n  if (Math.abs(dx) > Math.abs(dy)) {\n    // Horizontal movement\n    if (dx > 0) {\n      return { sourceSide: 'right', targetSide: 'left' };\n    } else {\n      return { sourceSide: 'left', targetSide: 'right' };\n    }\n  } else {\n    // Vertical movement\n    if (dy > 0) {\n      return { sourceSide: 'bottom', targetSide: 'top' };\n    } else {\n      return { sourceSide: 'top', targetSide: 'bottom' };\n    }\n  }\n}\n\n/**\n * Create an orthogonal path between two points with L-shaped or Z-shaped routing\n */\nexport function createOrthogonalPath(\n  start: Point,\n  end: Point,\n  primaryDirection: 'horizontal' | 'vertical' = 'horizontal'\n): Point[] {\n  const waypoints: Point[] = [start];\n\n  const dx = Math.abs(end.x - start.x);\n  const dy = Math.abs(end.y - start.y);\n\n  // If already aligned, direct connection\n  if (dx < 5 || dy < 5) {\n    waypoints.push(end);\n    return waypoints;\n  }\n\n  // Create L-shaped routing\n  if (primaryDirection === 'horizontal') {\n    const midX = (start.x + end.x) / 2;\n    waypoints.push({ x: midX, y: start.y });\n    waypoints.push({ x: midX, y: end.y });\n  } else {\n    const midY = (start.y + end.y) / 2;\n    waypoints.push({ x: start.x, y: midY });\n    waypoints.push({ x: end.x, y: midY });\n  }\n\n  waypoints.push(end);\n  return waypoints;\n}\n\n/**\n * Score a route based on obstacle crossings and path length\n * Lower score = better route\n */\nexport function scoreRoute(\n  start: Point,\n  bendPoints: Point[],\n  end: Point,\n  obstacles: Bounds[]\n): number {\n  let score = 0;\n  const crossingPenalty = 1000;\n  const lengthWeight = 0.1;\n\n  // Build full path\n  const path = [start, ...bendPoints, end];\n\n  // Check for crossings with each obstacle\n  for (const obs of obstacles) {\n    for (let i = 0; i < path.length - 1; i++) {\n      const p1 = path[i];\n      const p2 = path[i + 1];\n      if (p1 && p2 && segmentIntersectsRect(p1, p2, obs)) {\n        score += crossingPenalty;\n      }\n    }\n  }\n\n  // Add path length to score\n  for (let i = 0; i < path.length - 1; i++) {\n    const p1 = path[i];\n    const p2 = path[i + 1];\n    if (p1 && p2) {\n      score += distance(p1, p2) * lengthWeight;\n    }\n  }\n\n  return score;\n}\n\n/**\n * Find a clear vertical path that avoids obstacles\n * Returns the Y coordinate to route through, or null if direct path is clear\n */\nexport function findClearVerticalPath(\n  x: number,\n  startY: number,\n  endY: number,\n  obstacles: Bounds[]\n): number | null {\n  const minY = Math.min(startY, endY);\n  const maxY = Math.max(startY, endY);\n  const margin = 10;\n\n  // Check if any obstacle blocks the vertical path\n  for (const obs of obstacles) {\n    const obsLeft = obs.x - margin;\n    const obsRight = obs.x + obs.width + margin;\n    const obsTop = obs.y;\n    const obsBottom = obs.y + obs.height;\n\n    // Check if x is within obstacle's horizontal range\n    if (x >= obsLeft && x <= obsRight) {\n      // Check if obstacle is in our vertical path\n      if (obsBottom > minY && obsTop < maxY) {\n        // Found an obstacle - return a Y that goes around it\n        // Prefer going below the obstacle if there's more space\n        const spaceAbove = obsTop - minY;\n        const spaceBelow = maxY - obsBottom;\n\n        if (spaceBelow > spaceAbove && obsBottom + margin < maxY) {\n          return obsBottom + margin;\n        } else if (obsTop - margin > minY) {\n          return obsTop - margin;\n        }\n      }\n    }\n  }\n\n  return null; // No obstacle found, direct path is clear\n}\n\n/**\n * Calculate intersection point of two line segments.\n * Returns null if lines don't intersect within both segments.\n * Used for diamond edge intersection calculations.\n */\nexport function lineIntersection(\n  p1: Point,\n  p2: Point,\n  p3: Point,\n  p4: Point\n): Point | null {\n  const denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);\n  if (Math.abs(denom) < 0.0001) return null; // Lines are parallel\n\n  const ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom;\n  const ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom;\n\n  // Check if intersection is within both line segments\n  if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {\n    return {\n      x: p1.x + ua * (p2.x - p1.x),\n      y: p1.y + ua * (p2.y - p1.y),\n    };\n  }\n\n  return null;\n}\n\n/**\n * Find a clear horizontal path that avoids obstacles\n * Returns the X coordinate to route through, or null if direct path is clear\n */\nexport function findClearHorizontalPath(\n  y: number,\n  startX: number,\n  endX: number,\n  obstacles: Bounds[]\n): number | null {\n  const minX = Math.min(startX, endX);\n  const maxX = Math.max(startX, endX);\n  const margin = 10;\n\n  // Check if any obstacle blocks the horizontal path\n  for (const obs of obstacles) {\n    const obsTop = obs.y - margin;\n    const obsBottom = obs.y + obs.height + margin;\n    const obsLeft = obs.x;\n    const obsRight = obs.x + obs.width;\n\n    // Check if y is within obstacle's vertical range\n    if (y >= obsTop && y <= obsBottom) {\n      // Check if obstacle is in our horizontal path\n      if (obsRight > minX && obsLeft < maxX) {\n        // Found an obstacle - return an X that goes around it\n        // Prefer going right of the obstacle if there's more space\n        const spaceLeft = obsLeft - minX;\n        const spaceRight = maxX - obsRight;\n\n        if (spaceRight > spaceLeft && obsRight + margin < maxX) {\n          return obsRight + margin;\n        } else if (obsLeft - margin > minX) {\n          return obsLeft - margin;\n        }\n      }\n    }\n  }\n\n  return null; // No obstacle found, direct path is clear\n}\n","/**\n * BPMN Constants and Mappings\n */\n\n// ============================================================================\n// Default Element Sizes\n// ============================================================================\n\nexport const DEFAULT_SIZES = {\n  // Events (all types)\n  EVENT: { width: 36, height: 36 },\n\n  // Tasks (all types)\n  TASK: { width: 100, height: 80 },\n  TASK_WIDE: { width: 120, height: 80 },\n  TASK_WIDER: { width: 150, height: 80 },\n\n  // Gateways (all types)\n  GATEWAY: { width: 50, height: 50 },\n\n  // SubProcesses\n  SUBPROCESS_COLLAPSED: { width: 100, height: 80 },\n  SUBPROCESS_EXPANDED_MIN: { width: 300, height: 200 },\n\n  // Data Objects\n  DATA_OBJECT: { width: 36, height: 50 },\n  DATA_STORE: { width: 50, height: 50 },\n\n  // Text Annotation\n  TEXT_ANNOTATION: { width: 100, height: 30 },\n} as const;\n\n// ============================================================================\n// BPMN Element Type to XML Element Mapping\n// ============================================================================\n\nexport const BPMN_ELEMENT_MAP = {\n  // Events (bpmn-moddle uses PascalCase)\n  startEvent: 'bpmn:StartEvent',\n  endEvent: 'bpmn:EndEvent',\n  intermediateCatchEvent: 'bpmn:IntermediateCatchEvent',\n  intermediateThrowEvent: 'bpmn:IntermediateThrowEvent',\n  boundaryEvent: 'bpmn:BoundaryEvent',\n\n  // Tasks\n  task: 'bpmn:Task',\n  userTask: 'bpmn:UserTask',\n  serviceTask: 'bpmn:ServiceTask',\n  scriptTask: 'bpmn:ScriptTask',\n  businessRuleTask: 'bpmn:BusinessRuleTask',\n  sendTask: 'bpmn:SendTask',\n  receiveTask: 'bpmn:ReceiveTask',\n  manualTask: 'bpmn:ManualTask',\n\n  // Gateways\n  exclusiveGateway: 'bpmn:ExclusiveGateway',\n  parallelGateway: 'bpmn:ParallelGateway',\n  inclusiveGateway: 'bpmn:InclusiveGateway',\n  eventBasedGateway: 'bpmn:EventBasedGateway',\n  complexGateway: 'bpmn:ComplexGateway',\n\n  // SubProcesses\n  subProcess: 'bpmn:SubProcess',\n  transaction: 'bpmn:Transaction',\n  adHocSubProcess: 'bpmn:AdHocSubProcess',\n  eventSubProcess: 'bpmn:SubProcess', // Same element, different attribute\n\n  // Call Activity\n  callActivity: 'bpmn:CallActivity',\n\n  // Artifacts\n  dataObject: 'bpmn:DataObject',\n  dataObjectReference: 'bpmn:DataObjectReference',\n  dataInput: 'bpmn:DataInput',\n  dataOutput: 'bpmn:DataOutput',\n  dataStoreReference: 'bpmn:DataStoreReference',\n  textAnnotation: 'bpmn:TextAnnotation',\n  group: 'bpmn:Group',\n\n  // Flows\n  sequenceFlow: 'bpmn:SequenceFlow',\n  messageFlow: 'bpmn:MessageFlow',\n  dataInputAssociation: 'bpmn:DataInputAssociation',\n  dataOutputAssociation: 'bpmn:DataOutputAssociation',\n  association: 'bpmn:Association',\n\n  // Containers\n  collaboration: 'bpmn:Collaboration',\n  participant: 'bpmn:Participant',\n  process: 'bpmn:Process',\n  lane: 'bpmn:Lane',\n  laneSet: 'bpmn:LaneSet',\n} as const;\n\n// ============================================================================\n// Event Definition Type to XML Element Mapping\n// ============================================================================\n\nexport const EVENT_DEFINITION_MAP = {\n  none: null,\n  message: 'bpmn:MessageEventDefinition',\n  timer: 'bpmn:TimerEventDefinition',\n  error: 'bpmn:ErrorEventDefinition',\n  escalation: 'bpmn:EscalationEventDefinition',\n  cancel: 'bpmn:CancelEventDefinition',\n  compensation: 'bpmn:CompensateEventDefinition',\n  conditional: 'bpmn:ConditionalEventDefinition',\n  link: 'bpmn:LinkEventDefinition',\n  signal: 'bpmn:SignalEventDefinition',\n  terminate: 'bpmn:TerminateEventDefinition',\n  multiple: null, // Multiple event definitions\n  parallelMultiple: null, // Multiple parallel event definitions\n} as const;\n\n// ============================================================================\n// BPMN XML Namespaces\n// ============================================================================\n\nexport const BPMN_NAMESPACES = {\n  bpmn: 'http://www.omg.org/spec/BPMN/20100524/MODEL',\n  bpmndi: 'http://www.omg.org/spec/BPMN/20100524/DI',\n  dc: 'http://www.omg.org/spec/DD/20100524/DC',\n  di: 'http://www.omg.org/spec/DD/20100524/DI',\n  xsi: 'http://www.w3.org/2001/XMLSchema-instance',\n  camunda: 'http://camunda.org/schema/1.0/bpmn',\n} as const;\n\n// ============================================================================\n// Default ELK Layout Options\n// ============================================================================\n\nexport const DEFAULT_ELK_OPTIONS = {\n  'elk.algorithm': 'layered',\n  'elk.direction': 'RIGHT',\n  'elk.spacing.nodeNode': 50,\n  'elk.spacing.edgeNode': 30,\n  'elk.spacing.edgeEdge': 20,\n  'elk.layered.spacing.nodeNodeBetweenLayers': 80,\n  'elk.layered.spacing.edgeNodeBetweenLayers': 30,\n  'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n  'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',\n  'elk.edgeRouting': 'ORTHOGONAL',\n} as const;\n\n// ============================================================================\n// Element Categories\n// ============================================================================\n\nexport const EVENT_TYPES = [\n  'startEvent',\n  'endEvent',\n  'intermediateCatchEvent',\n  'intermediateThrowEvent',\n  'boundaryEvent',\n] as const;\n\nexport const TASK_TYPES = [\n  'task',\n  'userTask',\n  'serviceTask',\n  'scriptTask',\n  'businessRuleTask',\n  'sendTask',\n  'receiveTask',\n  'manualTask',\n] as const;\n\nexport const GATEWAY_TYPES = [\n  'exclusiveGateway',\n  'parallelGateway',\n  'inclusiveGateway',\n  'eventBasedGateway',\n  'complexGateway',\n] as const;\n\nexport const SUBPROCESS_TYPES = [\n  'subProcess',\n  'transaction',\n  'adHocSubProcess',\n  'eventSubProcess',\n] as const;\n\nexport const ARTIFACT_TYPES = [\n  'dataObject',\n  'dataObjectReference',\n  'dataStoreReference',\n  'textAnnotation',\n  'group',\n] as const;\n\n/**\n * Group element type constant\n */\nexport const GROUP_TYPE = 'group';\n\n/**\n * Set of artifact types for efficient lookup in layout processing.\n * Note: Excludes 'group' because groups are handled separately by GroupPositioner.\n */\nexport const ARTIFACT_TYPES_SET = new Set([\n  'dataObject',\n  'dataObjectReference',\n  'dataStoreReference',\n  'textAnnotation',\n]);\n\nexport const FLOW_TYPES = [\n  'sequenceFlow',\n  'messageFlow',\n  'dataInputAssociation',\n  'dataOutputAssociation',\n  'association',\n] as const;\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\nexport type EventTypeString = (typeof EVENT_TYPES)[number];\nexport type TaskTypeString = (typeof TASK_TYPES)[number];\nexport type GatewayTypeString = (typeof GATEWAY_TYPES)[number];\nexport type SubProcessTypeString = (typeof SUBPROCESS_TYPES)[number];\nexport type ArtifactTypeString = (typeof ARTIFACT_TYPES)[number];\nexport type FlowTypeString = (typeof FLOW_TYPES)[number];\nexport type BpmnElementType = keyof typeof BPMN_ELEMENT_MAP;\n","/**\n * Node Map Builder Utility\n * Provides shared functions for building node maps from ELK graphs.\n * Used by various post-processors to efficiently look up nodes by ID.\n */\n\nimport type { ElkNode } from 'elkjs';\n\n/**\n * Build a flat map of all nodes in the graph, keyed by ID.\n * Recursively traverses the graph to include all nested nodes.\n *\n * @param graph - The root ELK graph node\n * @returns A Map from node ID to ElkNode\n */\nexport function buildNodeMap(graph: ElkNode): Map<string, ElkNode> {\n  const nodeMap = new Map<string, ElkNode>();\n\n  const traverse = (node: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (node.children) {\n      for (const child of node.children) {\n        traverse(child);\n      }\n    }\n  };\n\n  traverse(graph);\n  return nodeMap;\n}\n\n/**\n * Build a map of nodes with their parent references.\n * Useful when you need to know the parent of each node.\n *\n * @param graph - The root ELK graph node\n * @returns A tuple of [nodeMap, parentMap] where parentMap maps node ID to parent node\n */\nexport function buildNodeMapWithParents(\n  graph: ElkNode\n): [Map<string, ElkNode>, Map<string, ElkNode>] {\n  const nodeMap = new Map<string, ElkNode>();\n  const parentMap = new Map<string, ElkNode>();\n\n  const traverse = (node: ElkNode, parent?: ElkNode) => {\n    nodeMap.set(node.id, node);\n    if (parent) {\n      parentMap.set(node.id, parent);\n    }\n    if (node.children) {\n      for (const child of node.children) {\n        traverse(child, node);\n      }\n    }\n  };\n\n  traverse(graph);\n  return [nodeMap, parentMap];\n}\n\n/**\n * Build a map of nodes with accumulated absolute offsets.\n * Useful when you need absolute coordinates for nodes in nested containers.\n *\n * @param graph - The root ELK graph node\n * @param isContainer - Function to determine if a node is a container (adds offset)\n * @returns A Map from node ID to { node, offsetX, offsetY }\n */\nexport function buildNodeMapWithOffsets(\n  graph: ElkNode,\n  isContainer: (node: ElkNode) => boolean\n): Map<string, { node: ElkNode; offsetX: number; offsetY: number }> {\n  const nodeMap = new Map<string, { node: ElkNode; offsetX: number; offsetY: number }>();\n\n  const traverse = (node: ElkNode, offsetX: number, offsetY: number) => {\n    nodeMap.set(node.id, { node, offsetX, offsetY });\n\n    if (node.children) {\n      // Calculate new offset for children\n      const addOffset = isContainer(node);\n      const newOffsetX = addOffset ? offsetX + (node.x ?? 0) : offsetX;\n      const newOffsetY = addOffset ? offsetY + (node.y ?? 0) : offsetY;\n\n      for (const child of node.children) {\n        traverse(child, newOffsetX, newOffsetY);\n      }\n    }\n  };\n\n  traverse(graph, 0, 0);\n  return nodeMap;\n}\n\n/**\n * Build a map of node absolute positions.\n * Calculates absolute x, y coordinates for each node.\n *\n * @param graph - The root ELK graph node\n * @param isContainer - Function to determine if a node is a container\n * @returns A Map from node ID to { x, y, width, height } in absolute coordinates\n */\nexport function buildAbsolutePositionMap(\n  graph: ElkNode,\n  isContainer: (node: ElkNode) => boolean\n): Map<string, { x: number; y: number; width: number; height: number }> {\n  const positionMap = new Map<string, { x: number; y: number; width: number; height: number }>();\n\n  const traverse = (node: ElkNode, offsetX: number, offsetY: number) => {\n    const absX = offsetX + (node.x ?? 0);\n    const absY = offsetY + (node.y ?? 0);\n\n    positionMap.set(node.id, {\n      x: absX,\n      y: absY,\n      width: node.width ?? 0,\n      height: node.height ?? 0,\n    });\n\n    if (node.children) {\n      // Calculate new offset for children\n      const addOffset = isContainer(node);\n      const newOffsetX = addOffset ? absX : offsetX;\n      const newOffsetY = addOffset ? absY : offsetY;\n\n      for (const child of node.children) {\n        traverse(child, newOffsetX, newOffsetY);\n      }\n    }\n  };\n\n  traverse(graph, 0, 0);\n  return positionMap;\n}\n","/**\n * Artifact Positioner\n * Handles repositioning of BPMN artifacts (data objects, data stores, annotations)\n * to be positioned above/near their associated tasks.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { Point, Bounds, NodeWithBpmn, ArtifactInfo, Obstacle } from '../../types/internal';\nimport {\n  segmentIntersectsRect,\n  scoreRoute,\n  findClearVerticalPath,\n} from '../edge-routing/geometry-utils';\nimport { ARTIFACT_TYPES_SET } from '../../types/bpmn-constants';\nimport { buildNodeMap } from '../../utils/node-map-builder';\n\n/**\n * Artifact types that should be repositioned above their associated tasks\n * @deprecated Use ARTIFACT_TYPES_SET from bpmn-constants instead\n */\nexport const ARTIFACT_TYPES = ARTIFACT_TYPES_SET;\n\n/**\n * Handler for artifact repositioning\n */\nexport class ArtifactPositioner {\n  /**\n   * Collect artifact information for post-processing\n   * Returns a map of artifact ID -> { associatedTaskId, isInput }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, ArtifactInfo> {\n    const info = new Map<string, ArtifactInfo>();\n\n    const collectFromNode = (node: NodeWithBpmn) => {\n      // Build a set of artifact IDs in this node\n      const artifactIds = new Set<string>();\n      if (node.children) {\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          if (childNode.bpmn && ARTIFACT_TYPES.has(childNode.bpmn.type)) {\n            artifactIds.add(childNode.id);\n          }\n        }\n      }\n\n      // Find associations between artifacts and tasks from edges\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n          const edgeType = edge.bpmn?.type;\n\n          if (!sourceId || !targetId) continue;\n\n          // Skip artifact-to-artifact associations (e.g., between two dataStores)\n          // These should not be used for positioning\n          if (artifactIds.has(sourceId) && artifactIds.has(targetId)) {\n            continue;\n          }\n\n          // Data input association: artifact -> task\n          if (edgeType === 'dataInputAssociation' || edgeType === 'association') {\n            if (artifactIds.has(sourceId)) {\n              info.set(sourceId, { associatedTaskId: targetId, isInput: true });\n            }\n          }\n          // Data output association: task -> artifact\n          if (edgeType === 'dataOutputAssociation') {\n            if (artifactIds.has(targetId)) {\n              info.set(targetId, { associatedTaskId: sourceId, isInput: false });\n            }\n          }\n        }\n      }\n\n      // Recurse into children\n      if (node.children) {\n        for (const child of node.children) {\n          collectFromNode(child as NodeWithBpmn);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectFromNode(child as NodeWithBpmn);\n    }\n\n    return info;\n  }\n\n  /**\n   * Reposition artifacts to be above their associated tasks\n   */\n  reposition(graph: ElkNode, artifactInfo: Map<string, ArtifactInfo>): void {\n    // Build node map\n    const nodeMap = buildNodeMap(graph);\n\n    // Track horizontal offset for each task (for multiple artifacts)\n    const taskInputOffsets = new Map<string, number>();\n    const taskOutputOffsets = new Map<string, number>();\n\n    // Reposition each artifact\n    for (const [artifactId, info] of artifactInfo) {\n      const artifactNode = nodeMap.get(artifactId);\n      const taskNode = nodeMap.get(info.associatedTaskId);\n\n      if (!artifactNode || !taskNode) continue;\n      if (taskNode.x === undefined || taskNode.y === undefined) continue;\n\n      const artifactWidth = artifactNode.width ?? 36;\n      const artifactHeight = artifactNode.height ?? 50;\n      const taskWidth = taskNode.width ?? 100;\n\n      // Position artifact above the task\n      // Input artifacts on the left, output artifacts on the right\n      let newX: number;\n      if (info.isInput) {\n        const currentOffset = taskInputOffsets.get(info.associatedTaskId) ?? 0;\n        newX = taskNode.x + currentOffset;\n        taskInputOffsets.set(info.associatedTaskId, currentOffset + artifactWidth + 15);\n      } else {\n        const currentOffset = taskOutputOffsets.get(info.associatedTaskId) ?? 0;\n        newX = taskNode.x + taskWidth + 15 + currentOffset; // Position to the right of task\n        taskOutputOffsets.set(info.associatedTaskId, currentOffset + artifactWidth + 15);\n      }\n      const newY = taskNode.y - artifactHeight - 20; // 20px gap above task\n\n      artifactNode.x = newX;\n      artifactNode.y = newY;\n    }\n\n    // Recalculate edges for repositioned artifacts\n    this.recalculateEdges(graph, artifactInfo, nodeMap);\n  }\n\n  /**\n   * Recalculate edges connected to repositioned artifacts\n   */\n  private recalculateEdges(\n    graph: ElkNode,\n    artifactInfo: Map<string, ArtifactInfo>,\n    nodeMap: Map<string, ElkNode>\n  ): void {\n    const processEdges = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n\n          if (!sourceId || !targetId) continue;\n\n          // Check if this edge involves an artifact\n          const sourceIsArtifact = artifactInfo.has(sourceId);\n          const targetIsArtifact = artifactInfo.has(targetId);\n\n          if (sourceIsArtifact || targetIsArtifact) {\n            const sourceNode = nodeMap.get(sourceId);\n            const targetNode = nodeMap.get(targetId);\n\n            if (sourceNode && targetNode) {\n              this.recalculateArtifactEdge(edge, sourceNode, targetNode, sourceIsArtifact);\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  /**\n   * Recalculate a single artifact edge (simple version)\n   */\n  private recalculateArtifactEdge(\n    edge: ElkExtendedEdge,\n    source: ElkNode,\n    target: ElkNode,\n    sourceIsArtifact: boolean\n  ): void {\n    const sx = source.x ?? 0;\n    const sy = source.y ?? 0;\n    const sw = source.width ?? 36;\n    const sh = source.height ?? 50;\n\n    const tx = target.x ?? 0;\n    const ty = target.y ?? 0;\n    const tw = target.width ?? 100;\n    const th = target.height ?? 80;\n\n    let startPoint: Point;\n    let endPoint: Point;\n\n    if (sourceIsArtifact) {\n      // Artifact -> Task (input): artifact is above/left of task\n      // Start from bottom of artifact, end at top of task\n      startPoint = { x: sx + sw / 2, y: sy + sh };\n      endPoint = { x: Math.min(Math.max(sx + sw / 2, tx), tx + tw), y: ty };\n    } else {\n      // Task -> Artifact (output): artifact is above/right of task\n      // Start from top-right of task, end at bottom of artifact\n      const artifactCenterX = tx + tw / 2;\n      startPoint = { x: Math.min(sx + sw, artifactCenterX), y: sy };\n      endPoint = { x: artifactCenterX, y: ty + th };\n    }\n\n    edge.sections = [{\n      id: `${edge.id}_section_0`,\n      startPoint,\n      endPoint,\n      bendPoints: [],\n    }];\n  }\n\n  /**\n   * Recalculate artifact edges with obstacle avoidance\n   * Implements orthogonal routing that avoids crossing other elements\n   */\n  recalculateWithObstacleAvoidance(\n    graph: ElkNode,\n    artifactInfo: Map<string, ArtifactInfo>\n  ): void {\n    // Build node map for position lookups\n    const nodeMap = buildNodeMap(graph);\n\n    // Collect all obstacles (non-artifact nodes)\n    const obstacles: Obstacle[] = [];\n    const collectObstacles = (node: ElkNode) => {\n      if (node.x !== undefined && node.y !== undefined && !artifactInfo.has(node.id)) {\n        // Skip groups (they're just visual overlays)\n        const isGroup = node.id.includes('group');\n        if (!isGroup) {\n          obstacles.push({\n            id: node.id,\n            x: node.x,\n            y: node.y,\n            width: node.width ?? 100,\n            height: node.height ?? 80,\n          });\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectObstacles(child);\n        }\n      }\n    };\n    collectObstacles(graph);\n\n    // Process edges\n    const processEdges = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const sourceId = edge.sources?.[0];\n          const targetId = edge.targets?.[0];\n\n          if (!sourceId || !targetId) continue;\n\n          // Check if this edge involves an artifact\n          const sourceIsArtifact = artifactInfo.has(sourceId);\n          const targetIsArtifact = artifactInfo.has(targetId);\n\n          if (sourceIsArtifact || targetIsArtifact) {\n            const sourceNode = nodeMap.get(sourceId);\n            const targetNode = nodeMap.get(targetId);\n\n            if (sourceNode && targetNode) {\n              this.recalculateEdgeWithObstacles(\n                edge,\n                sourceNode,\n                targetNode,\n                sourceIsArtifact,\n                obstacles.filter(o => o.id !== sourceId && o.id !== targetId)\n              );\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  /**\n   * Recalculate a single artifact edge with orthogonal routing and obstacle avoidance\n   */\n  private recalculateEdgeWithObstacles(\n    edge: ElkExtendedEdge,\n    source: ElkNode,\n    target: ElkNode,\n    sourceIsArtifact: boolean,\n    obstacles: Obstacle[]\n  ): void {\n    const sx = source.x ?? 0;\n    const sy = source.y ?? 0;\n    const sw = source.width ?? 36;\n    const sh = source.height ?? 50;\n\n    const tx = target.x ?? 0;\n    const ty = target.y ?? 0;\n    const tw = target.width ?? 100;\n    const th = target.height ?? 80;\n\n    // Determine connection points based on relative positions\n    let startPoint: Point;\n    let endPoint: Point;\n    const bendPoints: Point[] = [];\n\n    const sourceCenterX = sx + sw / 2;\n    const sourceCenterY = sy + sh / 2;\n    const targetCenterX = tx + tw / 2;\n    const targetCenterY = ty + th / 2;\n\n    // Determine if we're going up, down, left, or right\n    const goingRight = targetCenterX > sourceCenterX + sw / 2;\n    const goingLeft = targetCenterX < sourceCenterX - sw / 2;\n    const goingDown = targetCenterY > sourceCenterY + sh / 2;\n    const goingUp = targetCenterY < sourceCenterY - sh / 2;\n\n    if (sourceIsArtifact) {\n      // Artifact is source (data input association: artifact -> task)\n      if (goingDown) {\n        // Source above target: exit from bottom, enter from top\n        startPoint = { x: sourceCenterX, y: sy + sh };\n        endPoint = { x: targetCenterX, y: ty };\n\n        // Check for obstacles and route around them\n        const routeY = findClearVerticalPath(startPoint.x, startPoint.y, endPoint.y, obstacles);\n        if (Math.abs(startPoint.x - endPoint.x) > 5 || routeY !== null) {\n          if (routeY !== null && routeY !== startPoint.y && routeY !== endPoint.y) {\n            bendPoints.push({ x: startPoint.x, y: routeY });\n            bendPoints.push({ x: endPoint.x, y: routeY });\n          } else {\n            // Simple L-shaped routing\n            const midY = (startPoint.y + endPoint.y) / 2;\n            bendPoints.push({ x: startPoint.x, y: midY });\n            bendPoints.push({ x: endPoint.x, y: midY });\n          }\n        }\n      } else if (goingUp) {\n        // Source below target: exit from top, enter from bottom\n        startPoint = { x: sourceCenterX, y: sy };\n        endPoint = { x: targetCenterX, y: ty + th };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingRight) {\n        // Source left of target: exit from right, enter from left\n        startPoint = { x: sx + sw, y: sourceCenterY };\n        endPoint = { x: tx, y: targetCenterY };\n\n        // Route with obstacle avoidance\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      } else {\n        // Source right of target: exit from left, enter from right\n        startPoint = { x: sx, y: sourceCenterY };\n        endPoint = { x: tx + tw, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      }\n    } else {\n      // Task is source (data output association: task -> artifact)\n      if (goingUp) {\n        // Target above source: exit from top, enter from bottom\n        startPoint = { x: sourceCenterX, y: sy };\n        endPoint = { x: targetCenterX, y: ty + th };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingDown) {\n        // Target below source: exit from bottom, enter from top\n        startPoint = { x: sourceCenterX, y: sy + sh };\n        endPoint = { x: targetCenterX, y: ty };\n\n        const midY = (startPoint.y + endPoint.y) / 2;\n        if (Math.abs(startPoint.x - endPoint.x) > 5) {\n          bendPoints.push({ x: startPoint.x, y: midY });\n          bendPoints.push({ x: endPoint.x, y: midY });\n        }\n      } else if (goingRight) {\n        // Target right of source: exit from right, enter from left\n        startPoint = { x: sx + sw, y: sourceCenterY };\n        endPoint = { x: tx, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      } else {\n        // Target left of source: exit from left, enter from right\n        startPoint = { x: sx, y: sourceCenterY };\n        endPoint = { x: tx + tw, y: targetCenterY };\n\n        this.addOrthogonalBendPoints(startPoint, endPoint, bendPoints, obstacles);\n      }\n    }\n\n    edge.sections = [{\n      id: `${edge.id}_section_0`,\n      startPoint,\n      endPoint,\n      bendPoints: bendPoints.length > 0 ? bendPoints : undefined,\n    }];\n  }\n\n  /**\n   * Add orthogonal bend points with obstacle avoidance\n   */\n  private addOrthogonalBendPoints(\n    start: Point,\n    end: Point,\n    bendPoints: Point[],\n    obstacles: Bounds[]\n  ): void {\n    const margin = 15;\n\n    // Check if direct path (with one bend) crosses any obstacle\n    const midX = (start.x + end.x) / 2;\n    const midY = (start.y + end.y) / 2;\n\n    // Try different routing strategies\n    const strategies: Array<{ points: Point[]; score: number }> = [];\n\n    // Strategy 1: Horizontal first, then vertical\n    const s1: Point[] = [\n      { x: midX, y: start.y },\n      { x: midX, y: end.y },\n    ];\n    strategies.push({ points: s1, score: scoreRoute(start, s1, end, obstacles) });\n\n    // Strategy 2: Vertical first, then horizontal\n    const s2: Point[] = [\n      { x: start.x, y: midY },\n      { x: end.x, y: midY },\n    ];\n    strategies.push({ points: s2, score: scoreRoute(start, s2, end, obstacles) });\n\n    // Strategy 3: Route above obstacles\n    const maxObstacleTop = Math.min(...obstacles.map(o => o.y), start.y, end.y);\n    const routeAboveY = maxObstacleTop - margin;\n    const s3: Point[] = [\n      { x: start.x, y: routeAboveY },\n      { x: end.x, y: routeAboveY },\n    ];\n    strategies.push({ points: s3, score: scoreRoute(start, s3, end, obstacles) });\n\n    // Strategy 4: Route below obstacles\n    const maxObstacleBottom = Math.max(...obstacles.map(o => o.y + o.height), start.y, end.y);\n    const routeBelowY = maxObstacleBottom + margin;\n    const s4: Point[] = [\n      { x: start.x, y: routeBelowY },\n      { x: end.x, y: routeBelowY },\n    ];\n    strategies.push({ points: s4, score: scoreRoute(start, s4, end, obstacles) });\n\n    // Strategy 5: Route to the right of obstacles\n    const maxObstacleRight = Math.max(...obstacles.map(o => o.x + o.width), start.x, end.x);\n    const routeRightX = maxObstacleRight + margin;\n    const s5: Point[] = [\n      { x: routeRightX, y: start.y },\n      { x: routeRightX, y: end.y },\n    ];\n    strategies.push({ points: s5, score: scoreRoute(start, s5, end, obstacles) });\n\n    // Choose the best strategy (lowest score = fewer crossings + shorter path)\n    strategies.sort((a, b) => a.score - b.score);\n    const best = strategies[0];\n\n    // Only add bend points if they're significantly different from start/end\n    for (const bp of best.points) {\n      if (Math.abs(bp.x - start.x) > 5 || Math.abs(bp.y - start.y) > 5) {\n        if (Math.abs(bp.x - end.x) > 5 || Math.abs(bp.y - end.y) > 5) {\n          bendPoints.push(bp);\n        }\n      }\n    }\n  }\n}\n","/**\n * Group Positioner\n * Handles repositioning of BPMN Group elements to surround their grouped elements.\n * Groups are visual overlays that don't participate in ELK layout.\n */\n\nimport type { ElkNode } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, GroupInfo } from '../../types/internal';\nimport { GROUP_TYPE } from '../../types/bpmn-constants';\nimport { buildNodeMapWithParents } from '../../utils/node-map-builder';\n\n// Re-export GROUP_TYPE for backward compatibility\nexport { GROUP_TYPE };\n\n/**\n * Handler for group repositioning\n */\nexport class GroupPositioner {\n  /**\n   * Collect Group information for post-processing\n   * Returns a map of group ID -> { groupedElements, padding, name, parentId }\n   */\n  collectInfo(graph: ElkBpmnGraph): Map<string, GroupInfo> {\n    const info = new Map<string, GroupInfo>();\n\n    const collectFromNode = (node: NodeWithBpmn, parentId: string) => {\n      if (node.children) {\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          if (childNode.bpmn?.type === GROUP_TYPE) {\n            const bpmn = childNode.bpmn as { groupedElements?: string[]; padding?: number; name?: string };\n            info.set(childNode.id, {\n              groupedElements: bpmn.groupedElements ?? [],\n              padding: bpmn.padding ?? 20,\n              name: bpmn.name,\n              parentId,\n            });\n          }\n          // Recurse into children\n          collectFromNode(childNode, childNode.id);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectFromNode(child as NodeWithBpmn, (child as NodeWithBpmn).id);\n    }\n\n    return info;\n  }\n\n  /**\n   * Remove Groups from the graph before ELK layout\n   * Groups will be repositioned after layout based on their grouped elements\n   */\n  removeFromGraph(graph: ElkBpmnGraph, groupInfo: Map<string, GroupInfo>): void {\n    const groupIds = new Set(groupInfo.keys());\n\n    const removeFromNode = (node: NodeWithBpmn) => {\n      if (node.children) {\n        node.children = node.children.filter((child) => {\n          const childNode = child as NodeWithBpmn;\n          return !groupIds.has(childNode.id);\n        });\n\n        // Recurse into remaining children\n        for (const child of node.children) {\n          removeFromNode(child as NodeWithBpmn);\n        }\n      }\n\n      // Also remove edges that connect to groups\n      if (node.edges) {\n        node.edges = node.edges.filter((edge) => {\n          const sourceId = edge.sources[0];\n          const targetId = edge.targets[0];\n          return !groupIds.has(sourceId) && !groupIds.has(targetId);\n        });\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      removeFromNode(child as NodeWithBpmn);\n    }\n  }\n\n  /**\n   * Reposition Groups to surround their grouped elements\n   * Modifies existing Group nodes in the layouted graph\n   */\n  reposition(\n    graph: ElkNode,\n    groupInfo: Map<string, GroupInfo>,\n    _originalGraph: ElkBpmnGraph\n  ): void {\n    if (groupInfo.size === 0) return;\n\n    // Build node map for position lookups\n    const [nodeMap, parentMap] = buildNodeMapWithParents(graph);\n\n    // Process each group\n    for (const [groupId, info] of groupInfo) {\n      // Find the existing group node in the layouted graph\n      const groupNode = nodeMap.get(groupId);\n      if (!groupNode) continue;\n\n      // If no grouped elements specified, keep the ELK-calculated position\n      if (info.groupedElements.length === 0) continue;\n\n      // Calculate bounding box of grouped elements\n      let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n      for (const elementId of info.groupedElements) {\n        const elementNode = nodeMap.get(elementId);\n        if (!elementNode || elementNode.x === undefined || elementNode.y === undefined) continue;\n\n        // Get position of the element relative to the same parent container as the group\n        // Elements might be nested in lanes, so we need to traverse up to the group's parent\n        let absX = elementNode.x ?? 0;\n        let absY = elementNode.y ?? 0;\n        let currentParent = parentMap.get(elementId);\n        const groupParent = parentMap.get(groupId);\n\n        // Traverse up to find common ancestor or group's parent\n        while (currentParent && currentParent !== groupParent && currentParent.id !== info.parentId) {\n          absX += currentParent.x ?? 0;\n          absY += currentParent.y ?? 0;\n          currentParent = parentMap.get(currentParent.id);\n        }\n\n        const w = elementNode.width ?? 100;\n        const h = elementNode.height ?? 80;\n\n        minX = Math.min(minX, absX);\n        minY = Math.min(minY, absY);\n        maxX = Math.max(maxX, absX + w);\n        maxY = Math.max(maxY, absY + h);\n      }\n\n      // Check if we found any valid elements\n      if (minX === Infinity) continue;\n\n      // Add padding\n      const padding = info.padding;\n      minX -= padding;\n      minY -= padding;\n      maxX += padding;\n      maxY += padding;\n\n      // Update the group node's position and size\n      groupNode.x = minX;\n      groupNode.y = minY;\n      groupNode.width = maxX - minX;\n      groupNode.height = maxY - minY;\n    }\n  }\n}\n","/**\n * Lane Arranger\n * Handles rearranging lanes to stack vertically within pools.\n * Uses simple sequential stacking for lane positioning.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, Point } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\ntype ElkNodeWithBpmn = ElkNode & { bpmn?: NodeWithBpmn['bpmn'] };\n\n/**\n * Handler for lane rearrangement\n */\nexport class LaneArranger {\n  private readonly laneHeaderWidth = 30;\n  private readonly laneMinHorizontalPadding = 32;\n  private readonly laneMaxHorizontalPadding = 96;\n  private readonly laneMinVerticalPadding = 24;\n  private readonly laneMaxVerticalPadding = 80;\n  private readonly emptyLaneContentWidth = 220;\n  // Empty lanes should not claim node-sized vertical real estate.\n  private readonly emptyLaneMinHeight = 60;\n\n  /**\n   * Rearrange lanes within pools to stack vertically\n   */\n  rearrange(layouted: ElkNode, original: ElkBpmnGraph): void {\n    // Find pools in collaborations and process them\n    if (layouted.children) {\n      for (let i = 0; i < layouted.children.length; i++) {\n        const child = layouted.children[i];\n        const origChild = original.children?.[i] as NodeWithBpmn | undefined;\n\n        // Check if this is a collaboration with pools\n        if (origChild?.bpmn?.type === 'collaboration' && child.children) {\n          for (let j = 0; j < child.children.length; j++) {\n            const pool = child.children[j];\n            const origPool = (origChild.children as NodeWithBpmn[] | undefined)?.[j];\n            if (origPool?.bpmn?.type === 'participant') {\n              this.processPool(pool, origPool);\n            }\n          }\n        } else if (origChild?.bpmn?.type === 'participant') {\n          // Direct pool (not in collaboration)\n          this.processPool(child, origChild);\n        }\n      }\n    }\n  }\n\n  /**\n   * Process a single pool to arrange its lanes\n   */\n  private processPool(pool: ElkNode, origPool: NodeWithBpmn | undefined): void {\n    if (!pool.children || !origPool?.children) return;\n\n    // Check if this pool has lanes\n    const hasLanes = (origPool.children as NodeWithBpmn[]).some(c => c.bpmn?.type === 'lane');\n    if (!hasLanes) return;\n\n    // Get layouted nodes (flattened at pool level after ELK)\n    const layoutedNodes = new Map<string, ElkNode>();\n    let maxNodeWidth = 100;\n    for (const child of pool.children) {\n      layoutedNodes.set(child.id, child);\n      maxNodeWidth = Math.max(maxNodeWidth, child.width ?? 100);\n    }\n\n    const horizontalPadding = this.calculateHorizontalPadding(maxNodeWidth);\n\n    // Compute pool-wide global X span so all lanes share the same horizontal\n    // coordinate system. Without this, each lane recenters to its own minX\n    // and ELK's column alignment across lanes is destroyed.\n    let globalMinX = Infinity;\n    let globalMaxX = 0;\n    for (const child of pool.children) {\n      const x = child.x ?? 0;\n      const w = child.width ?? 100;\n      if (x < globalMinX) globalMinX = x;\n      if (x + w > globalMaxX) globalMaxX = x + w;\n    }\n    const contentSpan = isFinite(globalMinX) ? globalMaxX - globalMinX : 0;\n    // Top-level lane content origin equals horizontalPadding (lane-relative).\n    // Each leaf node's final lane-relative x = (origPoolX - globalMinX) + horizontalPadding.\n    const globalXOffset = isFinite(globalMinX) ? (horizontalPadding - globalMinX) : 0;\n\n    // Calculate pool width (content width + dynamic side paddings)\n    const poolContentWidth = Math.max(\n      this.emptyLaneContentWidth + horizontalPadding * 2,\n      contentSpan + horizontalPadding * 2\n    );\n\n    // Build lane structure - lanes fill the full pool width\n    const result = this.buildLaneStructure(\n      origPool.children as NodeWithBpmn[],\n      layoutedNodes,\n      0,\n      poolContentWidth,\n      horizontalPadding,\n      globalXOffset\n    );\n\n    // Update pool - lanes fill the entire pool, no gaps\n    pool.children = result.lanes;\n    pool.width = this.laneHeaderWidth + poolContentWidth;\n    pool.height = result.totalHeight;\n\n    // Recalculate edge waypoints\n    if (pool.edges) {\n      this.recalculatePoolEdges(pool, result.lanes);\n    }\n  }\n\n  /**\n   * Recursively build lane structure with positioned nodes\n   * Uses ConstraintSolver for vertical stacking\n   */\n  private buildLaneStructure(\n    origChildren: NodeWithBpmn[],\n    layoutedNodes: Map<string, ElkNode>,\n    startY: number,\n    maxRight: number,\n    horizontalPadding: number,\n    xOffset: number\n  ): { lanes: ElkNode[]; totalHeight: number } {\n    const lanes: ElkNode[] = [];\n\n    // Filter to get only lanes and sort by partition\n    const origLanes = origChildren.filter(c => c.bpmn?.type === 'lane');\n    origLanes.sort((a, b) => {\n      const partA = a.layoutOptions?.['elk.partitioning.partition'];\n      const partB = b.layoutOptions?.['elk.partitioning.partition'];\n      return (partA !== undefined ? Number(partA) : 0) - (partB !== undefined ? Number(partB) : 0);\n    });\n\n    if (origLanes.length === 0) {\n      return { lanes: [], totalHeight: 0 };\n    }\n\n    // Calculate heights for each lane\n    const laneHeights = new Map<string, number>();\n    const laneNodes = new Map<string, ElkNode[]>();\n\n    for (const origLane of origLanes) {\n      const hasNestedLanes = origLane.children?.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n\n      if (hasNestedLanes) {\n        const nestedWidth = maxRight - this.laneHeaderWidth;\n        // Nested lanes sit at x=laneHeaderWidth within their parent lane, so\n        // their inner X system is shifted by another laneHeaderWidth.\n        const nested = this.buildLaneStructure(\n          origLane.children as NodeWithBpmn[],\n          layoutedNodes,\n          0,\n          nestedWidth,\n          horizontalPadding,\n          xOffset - this.laneHeaderWidth\n        );\n        laneHeights.set(origLane.id, nested.totalHeight);\n        laneNodes.set(origLane.id, nested.lanes);\n      } else {\n        const nodesInLane: ElkNode[] = [];\n        if (origLane.children) {\n          for (const child of origLane.children) {\n            const node = layoutedNodes.get((child as NodeWithBpmn).id);\n            if (node) nodesInLane.push(node);\n          }\n        }\n\n        let minY = Infinity;\n        let maxY = 0;\n        let maxNodeHeight = 80;\n        for (const node of nodesInLane) {\n          minY = Math.min(minY, node.y ?? 0);\n          maxY = Math.max(maxY, (node.y ?? 0) + (node.height ?? 80));\n          maxNodeHeight = Math.max(maxNodeHeight, node.height ?? 80);\n        }\n\n        let laneHeight: number;\n        let yOffset = 0;\n        if (nodesInLane.length > 0) {\n          const contentHeight = maxY - minY;\n          const verticalPadding = this.calculateVerticalPadding(maxNodeHeight);\n          laneHeight = contentHeight + verticalPadding * 2;\n          yOffset = verticalPadding - minY;\n        } else {\n          // Empty lane: collapse to a slim baseline rather than reserving\n          // node-sized vertical space.\n          laneHeight = this.emptyLaneMinHeight;\n        }\n\n        // Per-lane Y offset (each lane has its own vertical baseline) but\n        // shared X offset (preserves ELK's column alignment across lanes).\n        for (const node of nodesInLane) {\n          node.x = (node.x ?? 0) + xOffset;\n          node.y = (node.y ?? 0) + yOffset;\n        }\n\n        laneHeights.set(origLane.id, laneHeight);\n        laneNodes.set(origLane.id, nodesInLane);\n      }\n    }\n\n    // Simple sequential stacking - lanes stack from startY downward\n    let currentY = startY;\n\n    // Build lane nodes with sequential positions\n    for (const origLane of origLanes) {\n      const height = laneHeights.get(origLane.id) ?? 100;\n      const children = laneNodes.get(origLane.id) ?? [];\n      const hasNestedLanes = origLane.children?.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n\n      if (hasNestedLanes) {\n        for (const nestedLane of children) {\n          nestedLane.width = maxRight - this.laneHeaderWidth;\n        }\n      }\n\n      const laneNode: ElkNodeWithBpmn = {\n        id: origLane.id,\n        x: this.laneHeaderWidth,\n        y: currentY,\n        width: maxRight,\n        height: height,\n        children: children,\n        bpmn: origLane.bpmn,\n      };\n      lanes.push(laneNode);\n      currentY += height;\n    }\n\n    const totalHeight = currentY - startY;\n    return { lanes, totalHeight };\n  }\n\n  private calculateHorizontalPadding(maxNodeWidth: number): number {\n    return this.clamp(Math.round(maxNodeWidth * 0.45), this.laneMinHorizontalPadding, this.laneMaxHorizontalPadding);\n  }\n\n  private calculateVerticalPadding(maxNodeHeight: number): number {\n    return this.clamp(Math.round(maxNodeHeight * 0.5), this.laneMinVerticalPadding, this.laneMaxVerticalPadding);\n  }\n\n  private clamp(value: number, min: number, max: number): number {\n    return Math.max(min, Math.min(max, value));\n  }\n\n\n  /**\n   * Recalculate edge waypoints after node positions have shifted (lane stacking).\n   * Produces a simple perpendicular L-shape. Obstacle avoidance is delegated to EdgeFixer.\n   */\n  private recalculatePoolEdges(pool: ElkNode, lanes: ElkNode[]): void {\n    if (!pool.edges) return;\n\n    const nodePositions = this.collectAbsoluteNodePositions(lanes);\n\n    for (const edge of pool.edges) {\n      const sourceId = edge.sources?.[0];\n      const targetId = edge.targets?.[0];\n      const src = sourceId ? nodePositions.get(sourceId) : undefined;\n      const dst = targetId ? nodePositions.get(targetId) : undefined;\n      if (!src || !dst) continue;\n\n      const waypoints = this.buildSimpleLRoute(src, dst);\n      (edge as ElkExtendedEdge & { _poolRelativeCoords?: boolean })._poolRelativeCoords = true;\n      const last = waypoints[waypoints.length - 1];\n      const first = waypoints[0];\n      if (!first || !last) continue;\n      edge.sections = [{\n        id: `${edge.id}_s0`,\n        startPoint: first,\n        endPoint: last,\n        bendPoints: waypoints.length > 2 ? waypoints.slice(1, -1) : undefined,\n      }];\n    }\n  }\n\n  /**\n   * Collect absolute (pool-relative) positions of all flow nodes inside the given lanes,\n   * recursing through nested lanes.\n   */\n  private collectAbsoluteNodePositions(\n    lanes: ElkNode[]\n  ): Map<string, { x: number; y: number; width: number; height: number }> {\n    const positions = new Map<string, { x: number; y: number; width: number; height: number }>();\n    const walk = (container: ElkNode, offsetX: number, offsetY: number) => {\n      if (!container.children) return;\n      for (const child of container.children) {\n        const absX = offsetX + (child.x ?? 0);\n        const absY = offsetY + (child.y ?? 0);\n        positions.set(child.id, {\n          x: absX,\n          y: absY,\n          width: child.width ?? 100,\n          height: child.height ?? 80,\n        });\n        walk(child, absX, absY);\n      }\n    };\n    for (const lane of lanes) {\n      walk(lane, lane.x ?? 0, lane.y ?? 0);\n    }\n    return positions;\n  }\n\n  /**\n   * Build a perpendicular L-shape route between two nodes. The shape prefers\n   * horizontal flow (right→left) when source is left of target, falling back\n   * to vertical (bottom→top) when nodes are nearly column-aligned.\n   * EdgeFixer will replace this with a pathfinding route if it crosses nodes.\n   */\n  private buildSimpleLRoute(\n    src: { x: number; y: number; width: number; height: number },\n    dst: { x: number; y: number; width: number; height: number }\n  ): Point[] {\n    const srcCx = src.x + src.width / 2;\n    const srcCy = src.y + src.height / 2;\n    const dstCx = dst.x + dst.width / 2;\n    const dstCy = dst.y + dst.height / 2;\n    const dx = dstCx - srcCx;\n    const dy = dstCy - srcCy;\n\n    // Choose horizontal-primary unless nodes are clearly stacked vertically.\n    const horizontalPrimary = Math.abs(dx) > 30 || Math.abs(dy) < 50;\n\n    let startX: number, startY: number, endX: number, endY: number;\n    if (horizontalPrimary) {\n      startY = srcCy;\n      endY = dstCy;\n      if (dx >= 0) {\n        startX = src.x + src.width;\n        endX = dst.x;\n      } else {\n        startX = src.x;\n        endX = dst.x + dst.width;\n      }\n    } else {\n      startX = srcCx;\n      endX = dstCx;\n      if (dy >= 0) {\n        startY = src.y + src.height;\n        endY = dst.y;\n      } else {\n        startY = src.y;\n        endY = dst.y + dst.height;\n      }\n    }\n\n    const points: Point[] = [{ x: startX, y: startY }];\n    if (horizontalPrimary && Math.abs(startY - endY) > 1) {\n      // Bend at midpoint of horizontal span\n      const midX = (startX + endX) / 2;\n      points.push({ x: midX, y: startY });\n      points.push({ x: midX, y: endY });\n    } else if (!horizontalPrimary && Math.abs(startX - endX) > 1) {\n      const midY = (startY + endY) / 2;\n      points.push({ x: startX, y: midY });\n      points.push({ x: endX, y: midY });\n    }\n    points.push({ x: endX, y: endY });\n    return points;\n  }\n}\n","/**\n * Constraint-based Layout Solver\n * Uses kiwi.js (Cassowary algorithm) for declarative layout constraints.\n * Replaces imperative post-processing with declarative constraint specifications.\n *\n * Note: Cassowary has specific ordering requirements:\n * - Constraints should be added before edit variables\n * - Use a two-phase approach: collect all constraints, then solve\n */\n\nimport * as kiwi from 'kiwi.js';\nimport type { Bounds } from '../../types/internal';\n\n// ============================================================================\n// Constraint Types\n// ============================================================================\n\n/**\n * Constraint type definitions for BPMN layout\n */\nexport type LayoutConstraint =\n  | AlignXConstraint\n  | AlignYConstraint\n  | LeftOfConstraint\n  | RightOfConstraint\n  | AboveConstraint\n  | BelowConstraint\n  | NoOverlapConstraint\n  | FixedPositionConstraint\n  | InContainerConstraint\n  | MinDistanceConstraint;\n\nexport interface AlignXConstraint {\n  type: 'alignX';\n  nodes: string[];\n  strength?: ConstraintStrength;\n}\n\nexport interface AlignYConstraint {\n  type: 'alignY';\n  nodes: string[];\n  strength?: ConstraintStrength;\n}\n\nexport interface LeftOfConstraint {\n  type: 'leftOf';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface RightOfConstraint {\n  type: 'rightOf';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface AboveConstraint {\n  type: 'above';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface BelowConstraint {\n  type: 'below';\n  node: string;\n  reference: string;\n  minGap: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface NoOverlapConstraint {\n  type: 'noOverlap';\n  nodes: [string, string];\n  margin: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface FixedPositionConstraint {\n  type: 'fixedPosition';\n  node: string;\n  x?: number;\n  y?: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface InContainerConstraint {\n  type: 'inContainer';\n  node: string;\n  container: string;\n  padding: number;\n  strength?: ConstraintStrength;\n}\n\nexport interface MinDistanceConstraint {\n  type: 'minDistance';\n  node1: string;\n  node2: string;\n  axis: 'x' | 'y';\n  minDistance: number;\n  strength?: ConstraintStrength;\n}\n\nexport type ConstraintStrength = 'required' | 'strong' | 'medium' | 'weak';\n\n// ============================================================================\n// Node Variables\n// ============================================================================\n\ninterface NodeVariables {\n  x: kiwi.Variable;\n  y: kiwi.Variable;\n  width: number;\n  height: number;\n  initialX: number;\n  initialY: number;\n}\n\ninterface PendingConstraint {\n  constraint: LayoutConstraint;\n  strength: number;\n}\n\n// ============================================================================\n// Constraint Solver\n// ============================================================================\n\nexport interface ConstraintSolverOptions {\n  /** Default strength for constraints without explicit strength */\n  defaultStrength?: ConstraintStrength;\n  /** Enable debug logging */\n  debug?: boolean;\n}\n\nconst DEFAULT_OPTIONS: ConstraintSolverOptions = {\n  defaultStrength: 'strong',\n  debug: false,\n};\n\n/**\n * Constraint-based layout solver using Cassowary algorithm\n *\n * Usage pattern:\n * 1. Add all nodes with addNode()\n * 2. Add all constraints with addConstraint()\n * 3. Call solve() to get results\n *\n * The solver handles the correct ordering internally.\n */\nexport class ConstraintSolver {\n  private solver: kiwi.Solver | null = null;\n  private variables: Map<string, NodeVariables>;\n  private pendingConstraints: PendingConstraint[];\n  private kiwiConstraints: kiwi.Constraint[];\n  private options: ConstraintSolverOptions;\n  private solved: boolean = false;\n\n  constructor(options?: ConstraintSolverOptions) {\n    this.variables = new Map();\n    this.pendingConstraints = [];\n    this.kiwiConstraints = [];\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n  }\n\n  /**\n   * Add a node to the solver\n   * Note: Nodes are stored but not added to solver until solve() is called\n   */\n  addNode(\n    id: string,\n    initialX: number,\n    initialY: number,\n    width: number,\n    height: number\n  ): void {\n    if (this.variables.has(id)) {\n      if (this.options.debug) {\n        console.log(`[Constraint] Node ${id} already exists, skipping`);\n      }\n      return;\n    }\n\n    const x = new kiwi.Variable(`${id}_x`);\n    const y = new kiwi.Variable(`${id}_y`);\n\n    // Store the node with initial values - will be added to solver in solve()\n    this.variables.set(id, { x, y, width, height, initialX, initialY });\n\n    if (this.options.debug) {\n      console.log(`[Constraint] Added node ${id} at (${initialX}, ${initialY})`);\n    }\n  }\n\n  /**\n   * Add a node from bounds\n   */\n  addNodeFromBounds(id: string, bounds: Bounds): void {\n    this.addNode(id, bounds.x, bounds.y, bounds.width, bounds.height);\n  }\n\n  /**\n   * Add multiple nodes from a map\n   */\n  addNodesFromMap(nodes: Map<string, Bounds>): void {\n    for (const [id, bounds] of nodes) {\n      this.addNodeFromBounds(id, bounds);\n    }\n  }\n\n  /**\n   * Add a constraint\n   * Note: Constraints are stored and applied when solve() is called\n   */\n  addConstraint(constraint: LayoutConstraint): boolean {\n    // Check if all referenced nodes exist\n    const nodeIds = this.getConstraintNodeIds(constraint);\n    for (const id of nodeIds) {\n      if (!this.variables.has(id)) {\n        if (this.options.debug) {\n          console.log(`[Constraint] Node ${id} not found for constraint`);\n        }\n        return false;\n      }\n    }\n\n    if (constraint.type === 'noOverlap') {\n      // NoOverlap is handled specially - it's a disjunctive constraint\n      // Cassowary doesn't directly support disjunctions\n      if (this.options.debug) {\n        console.log(`[Constraint] noOverlap constraint requires special handling`);\n      }\n      return false;\n    }\n\n    const strength = this.getStrength(constraint.strength);\n    this.pendingConstraints.push({ constraint, strength });\n    return true;\n  }\n\n  /**\n   * Get node IDs referenced by a constraint\n   */\n  private getConstraintNodeIds(constraint: LayoutConstraint): string[] {\n    switch (constraint.type) {\n      case 'alignX':\n      case 'alignY':\n        return constraint.nodes;\n      case 'leftOf':\n      case 'rightOf':\n      case 'above':\n      case 'below':\n        return [constraint.node, constraint.reference];\n      case 'fixedPosition':\n        return [constraint.node];\n      case 'inContainer':\n        return [constraint.node, constraint.container];\n      case 'minDistance':\n        return [constraint.node1, constraint.node2];\n      case 'noOverlap':\n        return constraint.nodes;\n      default:\n        return [];\n    }\n  }\n\n  /**\n   * Add multiple constraints\n   */\n  addConstraints(constraints: LayoutConstraint[]): number {\n    let successCount = 0;\n    for (const constraint of constraints) {\n      if (this.addConstraint(constraint)) {\n        successCount++;\n      }\n    }\n    return successCount;\n  }\n\n  /**\n   * Build and solve the constraint system\n   */\n  solve(): Map<string, { x: number; y: number }> {\n    if (this.solved) {\n      // Return cached results\n      const result = new Map<string, { x: number; y: number }>();\n      for (const [id, vars] of this.variables) {\n        result.set(id, {\n          x: vars.x.value(),\n          y: vars.y.value(),\n        });\n      }\n      return result;\n    }\n\n    // Create fresh solver\n    this.solver = new kiwi.Solver();\n    this.kiwiConstraints = [];\n\n    // Step 1: Add all kiwi constraints FIRST (before edit variables)\n    for (const pending of this.pendingConstraints) {\n      this.applyConstraint(pending.constraint, pending.strength);\n    }\n\n    // Step 2: Add edit variables and suggest initial values\n    for (const [_id, vars] of this.variables) {\n      this.solver.addEditVariable(vars.x, kiwi.Strength.weak);\n      this.solver.addEditVariable(vars.y, kiwi.Strength.weak);\n      this.solver.suggestValue(vars.x, vars.initialX);\n      this.solver.suggestValue(vars.y, vars.initialY);\n    }\n\n    // Step 3: Solve\n    try {\n      this.solver.updateVariables();\n      this.solved = true;\n    } catch (error) {\n      if (this.options.debug) {\n        console.error(`[Constraint] Solver failed:`, error);\n      }\n    }\n\n    const result = new Map<string, { x: number; y: number }>();\n    for (const [id, vars] of this.variables) {\n      result.set(id, {\n        x: vars.x.value(),\n        y: vars.y.value(),\n      });\n    }\n    return result;\n  }\n\n  /**\n   * Apply a constraint to the solver\n   */\n  private applyConstraint(constraint: LayoutConstraint, strength: number): boolean {\n    try {\n      switch (constraint.type) {\n        case 'alignX':\n          return this.addAlignXConstraint(constraint, strength);\n        case 'alignY':\n          return this.addAlignYConstraint(constraint, strength);\n        case 'leftOf':\n          return this.addLeftOfConstraint(constraint, strength);\n        case 'rightOf':\n          return this.addRightOfConstraint(constraint, strength);\n        case 'above':\n          return this.addAboveConstraint(constraint, strength);\n        case 'below':\n          return this.addBelowConstraint(constraint, strength);\n        case 'fixedPosition':\n          return this.addFixedPositionConstraint(constraint, strength);\n        case 'inContainer':\n          return this.addInContainerConstraint(constraint, strength);\n        case 'minDistance':\n          return this.addMinDistanceConstraint(constraint, strength);\n        default:\n          return false;\n      }\n    } catch (error) {\n      if (this.options.debug) {\n        console.error(`[Constraint] Failed to apply constraint:`, error);\n      }\n      return false;\n    }\n  }\n\n  /**\n   * Get full bounds including width and height\n   */\n  solveWithBounds(): Map<string, Bounds> {\n    const positions = this.solve();\n    const result = new Map<string, Bounds>();\n\n    for (const [id, pos] of positions) {\n      const vars = this.variables.get(id);\n      if (vars) {\n        result.set(id, {\n          x: pos.x,\n          y: pos.y,\n          width: vars.width,\n          height: vars.height,\n        });\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Clear all nodes and constraints\n   */\n  clear(): void {\n    this.solver = null;\n    this.variables.clear();\n    this.pendingConstraints = [];\n    this.kiwiConstraints = [];\n    this.solved = false;\n  }\n\n  // ============================================================================\n  // Private: Constraint Implementations\n  // ============================================================================\n\n  private addAlignXConstraint(\n    constraint: AlignXConstraint,\n    strength: number\n  ): boolean {\n    const nodes = constraint.nodes\n      .map((id) => this.variables.get(id))\n      .filter((v): v is NodeVariables => v !== undefined);\n\n    if (nodes.length < 2) return false;\n\n    // Align all X coordinates to the first node's X\n    const referenceX = nodes[0].x;\n    for (let i = 1; i < nodes.length; i++) {\n      // x[i] == x[0] => x[i] - x[0] == 0\n      // Expression: x[i] + (-1 * x[0]) + 0 == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodes[i].x, [-1, referenceX]),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addAlignYConstraint(\n    constraint: AlignYConstraint,\n    strength: number\n  ): boolean {\n    const nodes = constraint.nodes\n      .map((id) => this.variables.get(id))\n      .filter((v): v is NodeVariables => v !== undefined);\n\n    if (nodes.length < 2) return false;\n\n    // Align all Y coordinates to the first node's Y\n    const referenceY = nodes[0].y;\n    for (let i = 1; i < nodes.length; i++) {\n      // y[i] == y[0] => y[i] - y[0] == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodes[i].y, [-1, referenceY]),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addLeftOfConstraint(\n    constraint: LeftOfConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.x + node.width + minGap <= reference.x\n    // => reference.x - node.x >= node.width + minGap\n    // => reference.x - node.x - (width + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = nodeVars.width + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(refVars.x, [-1, nodeVars.x], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addRightOfConstraint(\n    constraint: RightOfConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.x >= reference.x + reference.width + minGap\n    // node.x - reference.x - (width + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = refVars.width + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.x, [-1, refVars.x], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addAboveConstraint(\n    constraint: AboveConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.y + node.height + minGap <= reference.y\n    // reference.y - node.y - (height + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = nodeVars.height + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(refVars.y, [-1, nodeVars.y], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addBelowConstraint(\n    constraint: BelowConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const refVars = this.variables.get(constraint.reference);\n    if (!nodeVars || !refVars) return false;\n\n    // node.y >= reference.y + reference.height + minGap\n    // node.y - reference.y - (height + minGap) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const minSeparation = refVars.height + constraint.minGap;\n    const c = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.y, [-1, refVars.y], -minSeparation),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(c);\n    this.kiwiConstraints.push(c);\n\n    return true;\n  }\n\n  private addFixedPositionConstraint(\n    constraint: FixedPositionConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    if (!nodeVars) return false;\n\n    if (constraint.x !== undefined) {\n      // x == fixedX => x - fixedX == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodeVars.x, -constraint.x),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    if (constraint.y !== undefined) {\n      // y == fixedY => y - fixedY == 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(nodeVars.y, -constraint.y),\n        kiwi.Operator.Eq,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  private addInContainerConstraint(\n    constraint: InContainerConstraint,\n    strength: number\n  ): boolean {\n    const nodeVars = this.variables.get(constraint.node);\n    const containerVars = this.variables.get(constraint.container);\n    if (!nodeVars || !containerVars) return false;\n\n    const padding = constraint.padding;\n\n    // node.x >= container.x + padding\n    // node.x - container.x - padding >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const leftC = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.x, [-1, containerVars.x], -padding),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(leftC);\n    this.kiwiConstraints.push(leftC);\n\n    // node.y >= container.y + padding\n    // node.y - container.y - padding >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const topC = new kiwi.Constraint(\n      new kiwi.Expression(nodeVars.y, [-1, containerVars.y], -padding),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(topC);\n    this.kiwiConstraints.push(topC);\n\n    // node.x + node.width <= container.x + container.width - padding\n    // container.x - node.x + (container.width - padding - node.width) >= 0\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const rightC = new kiwi.Constraint(\n      new kiwi.Expression(\n        containerVars.x,\n        [-1, nodeVars.x],\n        containerVars.width - padding - nodeVars.width\n      ),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(rightC);\n    this.kiwiConstraints.push(rightC);\n\n    // node.y + node.height <= container.y + container.height - padding\n    // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n    const bottomC = new kiwi.Constraint(\n      new kiwi.Expression(\n        containerVars.y,\n        [-1, nodeVars.y],\n        containerVars.height - padding - nodeVars.height\n      ),\n      kiwi.Operator.Ge,\n      0,\n      strength\n    );\n    this.solver!.addConstraint(bottomC);\n    this.kiwiConstraints.push(bottomC);\n\n    return true;\n  }\n\n  private addMinDistanceConstraint(\n    constraint: MinDistanceConstraint,\n    strength: number\n  ): boolean {\n    const node1Vars = this.variables.get(constraint.node1);\n    const node2Vars = this.variables.get(constraint.node2);\n    if (!node1Vars || !node2Vars) return false;\n\n    if (constraint.axis === 'x') {\n      // |node1.x - node2.x| >= minDistance\n      // We need to handle this as: node1.x - node2.x >= minDistance OR node2.x - node1.x >= minDistance\n      // Cassowary can't handle OR, so we use a soft constraint that prefers separation\n      // This is a simplification - in practice, we rely on other constraints to maintain order\n\n      // Use a weaker constraint: prefer node2.x > node1.x + width + minDistance\n      // node2.x - node1.x - (width + minDistance) >= 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const size = node1Vars.width;\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(\n          node2Vars.x,\n          [-1, node1Vars.x],\n          -(size + constraint.minDistance)\n        ),\n        kiwi.Operator.Ge,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    } else {\n      // node2.y - node1.y - (height + minDistance) >= 0\n      // kiwi.Constraint(expr, op, rhs?, strength?) - pass 0 as rhs, strength as 4th arg\n      const size = node1Vars.height;\n      const c = new kiwi.Constraint(\n        new kiwi.Expression(\n          node2Vars.y,\n          [-1, node1Vars.y],\n          -(size + constraint.minDistance)\n        ),\n        kiwi.Operator.Ge,\n        0,\n        strength\n      );\n      this.solver!.addConstraint(c);\n      this.kiwiConstraints.push(c);\n    }\n\n    return true;\n  }\n\n  // ============================================================================\n  // Private: Helpers\n  // ============================================================================\n\n  private getStrength(strength?: ConstraintStrength): number {\n    const s = strength ?? this.options.defaultStrength ?? 'strong';\n    switch (s) {\n      case 'required':\n        return kiwi.Strength.required;\n      case 'strong':\n        return kiwi.Strength.strong;\n      case 'medium':\n        return kiwi.Strength.medium;\n      case 'weak':\n        return kiwi.Strength.weak;\n      default:\n        return kiwi.Strength.strong;\n    }\n  }\n}\n\n// ============================================================================\n// BPMN Constraint Generator\n// ============================================================================\n\nexport interface BpmnConstraintGeneratorOptions {\n  /** Minimum horizontal gap between nodes */\n  horizontalGap: number;\n  /** Minimum vertical gap between nodes */\n  verticalGap: number;\n  /** Gap between boundary event targets and their parent */\n  boundaryEventGap: number;\n  /** Padding inside containers */\n  containerPadding: number;\n}\n\nconst DEFAULT_BPMN_OPTIONS: BpmnConstraintGeneratorOptions = {\n  horizontalGap: 50,\n  verticalGap: 40,\n  boundaryEventGap: 50,\n  containerPadding: 20,\n};\n\n/**\n * Generate BPMN-specific layout constraints\n */\nexport function generateBpmnConstraints(\n  nodes: Map<string, Bounds>,\n  edges: Array<{ source: string; target: string; type?: string }>,\n  boundaryEvents: Array<{ id: string; attachedToRef: string; targetId?: string }>,\n  lanes: Array<{ id: string; parentId: string }>,\n  options?: Partial<BpmnConstraintGeneratorOptions>\n): LayoutConstraint[] {\n  const opts = { ...DEFAULT_BPMN_OPTIONS, ...options };\n  const constraints: LayoutConstraint[] = [];\n\n  // 1. Sequence flow direction constraints (source left of target)\n  for (const edge of edges) {\n    if (edge.type === 'sequenceFlow' || !edge.type) {\n      if (nodes.has(edge.source) && nodes.has(edge.target)) {\n        constraints.push({\n          type: 'leftOf',\n          node: edge.source,\n          reference: edge.target,\n          minGap: opts.horizontalGap,\n          strength: 'strong',\n        });\n      }\n    }\n  }\n\n  // 2. Boundary event targets below their attached tasks\n  for (const be of boundaryEvents) {\n    if (be.targetId && nodes.has(be.attachedToRef) && nodes.has(be.targetId)) {\n      constraints.push({\n        type: 'below',\n        node: be.targetId,\n        reference: be.attachedToRef,\n        minGap: opts.boundaryEventGap,\n        strength: 'required',\n      });\n    }\n  }\n\n  // 3. Lanes stacked vertically\n  const lanesByParent = new Map<string, string[]>();\n  for (const lane of lanes) {\n    const parentLanes = lanesByParent.get(lane.parentId) || [];\n    parentLanes.push(lane.id);\n    lanesByParent.set(lane.parentId, parentLanes);\n  }\n\n  for (const [_parentId, laneIds] of lanesByParent) {\n    for (let i = 1; i < laneIds.length; i++) {\n      if (nodes.has(laneIds[i - 1]) && nodes.has(laneIds[i])) {\n        constraints.push({\n          type: 'below',\n          node: laneIds[i],\n          reference: laneIds[i - 1],\n          minGap: 0,\n          strength: 'required',\n        });\n      }\n    }\n  }\n\n  return constraints;\n}\n","/**\n * Pool Arranger\n * Handles rearranging pools (participants) within collaborations.\n * Uses ConstraintSolver for vertical stacking calculations.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, Point, Bounds, ArtifactInfo } from '../../types/internal';\nimport { ARTIFACT_TYPES } from './artifact-positioner';\nimport { ConstraintSolver } from '../constraint';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for pool arrangement\n */\nexport class PoolArranger {\n  private readonly poolHeaderWidth = 55;\n  private readonly poolPaddingX = 25;\n  private readonly poolPaddingY = 40;\n  private readonly minPoolHeight = 100;\n  private readonly maxPoolPaddingX = 120;\n  private readonly maxPoolPaddingY = 90;\n\n  /**\n   * Rearrange pools within collaborations\n   */\n  rearrange(layouted: ElkNode, original: ElkBpmnGraph): void {\n    if (!layouted.children) return;\n\n    for (let i = 0; i < layouted.children.length; i++) {\n      const child = layouted.children[i];\n      const origChild = original.children?.[i] as NodeWithBpmn | undefined;\n\n      // Check if this is a collaboration\n      if (origChild?.bpmn?.type === 'collaboration' && child.children && child.children.length > 0) {\n        // Check if this collaboration had cross-pool edges (nodes were flattened)\n        const hasCrossPoolEdges = origChild.edges && origChild.edges.length > 0;\n        const hasMultiplePools = ((origChild.children as NodeWithBpmn[] | undefined)?.filter(\n          c => c.bpmn?.type === 'participant'\n        ).length ?? 0) > 1;\n\n        // Check if children were flattened\n        const origPools = (origChild.children as NodeWithBpmn[] | undefined)?.filter(\n          c => c.bpmn?.type === 'participant'\n        ) ?? [];\n        const poolIdsInLayouted = new Set(child.children.map(c => c.id));\n        const poolsFoundInLayouted = origPools.filter(p => poolIdsInLayouted.has(p.id)).length;\n        const childrenAreFlattened = poolsFoundInLayouted < origPools.length / 2;\n\n        if (hasCrossPoolEdges && hasMultiplePools && childrenAreFlattened) {\n          this.rearrangeCollaborationWithCrossPoolEdges(child, origChild);\n        } else {\n          this.stackPoolsVertically(child, origChild);\n        }\n      }\n    }\n  }\n\n  /**\n   * Stack pools vertically within a collaboration\n   */\n  private stackPoolsVertically(collab: ElkNode, origCollab: NodeWithBpmn): void {\n    if (!collab.children || collab.children.length === 0) return;\n\n    const pools: ElkNode[] = [];\n    const origPoolMap = new Map<string, NodeWithBpmn>();\n\n    // Collect pools and build original pool map\n    for (const child of collab.children) {\n      const origPool = origCollab.children?.find((c: unknown) => (c as NodeWithBpmn).id === child.id) as NodeWithBpmn | undefined;\n      if (origPool?.bpmn?.type === 'participant') {\n        pools.push(child);\n        origPoolMap.set(child.id, origPool);\n      }\n    }\n\n    if (pools.length === 0) return;\n\n    // Sort pools by original order\n    const poolOrder = new Map<string, number>();\n    origCollab.children?.forEach((c: unknown, idx: number) => {\n      const node = c as NodeWithBpmn;\n      if (node.bpmn?.type === 'participant') {\n        poolOrder.set(node.id, idx);\n      }\n    });\n    pools.sort((a, b) => (poolOrder.get(a.id) ?? 0) - (poolOrder.get(b.id) ?? 0));\n\n    const poolTargetWidths = new Map<string, number>();\n    const poolPaddingById = new Map<string, { x: number; y: number }>();\n\n    // Calculate target widths before normalizing pools to the same width\n    let maxPoolWidth = 0;\n    for (const pool of pools) {\n      const origPool = origPoolMap.get(pool.id);\n      const isBlackBox = origPool?.bpmn?.isBlackBox === true;\n      const hasLanes = (origPool?.children as NodeWithBpmn[] | undefined)?.some(c => c.bpmn?.type === 'lane');\n      const currentWidth = pool.width ?? 680;\n\n      if (hasLanes || isBlackBox) {\n        poolTargetWidths.set(pool.id, currentWidth);\n        maxPoolWidth = Math.max(maxPoolWidth, currentWidth);\n      } else {\n        const padding = this.calculateDynamicPoolPadding(pool);\n        const targetWidth = currentWidth + padding.x * 2;\n        poolPaddingById.set(pool.id, padding);\n        poolTargetWidths.set(pool.id, targetWidth);\n        maxPoolWidth = Math.max(maxPoolWidth, targetWidth);\n      }\n    }\n\n    // Calculate heights and prepare pools\n    const poolHeights = new Map<string, number>();\n    for (const pool of pools) {\n      const origPool = origPoolMap.get(pool.id);\n      // Treat empty pools (no children) as black box so they collapse to a\n      // narrow strip instead of inheriting a node-sized default height.\n      const isBlackBox = origPool?.bpmn?.isBlackBox === true ||\n        !((origPool?.children as NodeWithBpmn[] | undefined)?.length);\n      const hasLanes = (origPool?.children as NodeWithBpmn[] | undefined)?.some(c => c.bpmn?.type === 'lane');\n      const originalTargetWidth = poolTargetWidths.get(pool.id) ?? (pool.width ?? 680);\n\n      pool.width = maxPoolWidth;\n      if (isBlackBox) {\n        pool.height = 60;\n      } else if (!hasLanes) {\n        const padding = poolPaddingById.get(pool.id) ?? this.calculateDynamicPoolPadding(pool);\n        const centeredOffsetX = Math.max(0, Math.round((maxPoolWidth - originalTargetWidth) / 2));\n        const offsetX = padding.x + centeredOffsetX;\n        const offsetY = padding.y;\n\n        pool.height = (pool.height ?? 200) + offsetY * 2;\n        this.offsetPoolChildren(pool, offsetX, offsetY);\n      }\n      poolHeights.set(pool.id, pool.height ?? 200);\n    }\n\n    // Use ConstraintSolver for vertical stacking\n    const solver = new ConstraintSolver();\n    for (const pool of pools) {\n      const height = poolHeights.get(pool.id) ?? 200;\n      solver.addNode(pool.id, 0, 0, maxPoolWidth, height);\n    }\n\n    // Add below constraints for sequential stacking\n    for (let i = 1; i < pools.length; i++) {\n      solver.addConstraint({\n        type: 'below',\n        node: pools[i].id,\n        reference: pools[i - 1].id,\n        minGap: 0,\n        strength: 'required',\n      });\n    }\n\n    const positions = solver.solve();\n    const nodePositions = new Map<string, Bounds>();\n\n    // Apply solved positions\n    let totalHeight = 0;\n    for (const pool of pools) {\n      const pos = positions.get(pool.id);\n      pool.x = 0;\n      pool.y = pos?.y ?? totalHeight;\n\n      nodePositions.set(pool.id, {\n        x: pool.x,\n        y: pool.y,\n        width: pool.width ?? 680,\n        height: pool.height ?? 200,\n      });\n\n      this.collectNodePositionsInPool(pool, pool.x, pool.y, nodePositions);\n      totalHeight = pool.y + (pool.height ?? 200);\n    }\n\n    // Update collaboration dimensions\n    collab.width = maxPoolWidth;\n    collab.height = totalHeight;\n\n    // Recalculate message flows\n    if (collab.edges && origCollab.edges) {\n      this.recalculateMessageFlows(collab.edges, nodePositions, pools, origCollab.edges);\n    }\n  }\n\n  /**\n   * Rearrange collaboration with cross-pool edges\n   */\n  private rearrangeCollaborationWithCrossPoolEdges(\n    collab: ElkNode,\n    origCollab: NodeWithBpmn\n  ): void {\n    if (!collab.children || !origCollab.children) return;\n\n    // Build map of node ID -> pool ID and identify artifacts\n    const nodeToPool = new Map<string, string>();\n    const artifactIds = new Set<string>();\n\n    for (const origPool of origCollab.children as NodeWithBpmn[]) {\n      if (origPool.bpmn?.type === 'participant' && origPool.children) {\n        const hasLanes = origPool.children.some((c: unknown) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n        if (hasLanes) {\n          const mapNodesInLanes = (children: NodeWithBpmn[]) => {\n            for (const child of children) {\n              if (child.bpmn?.type === 'lane') {\n                if (child.children) mapNodesInLanes(child.children as NodeWithBpmn[]);\n              } else {\n                nodeToPool.set(child.id, origPool.id);\n                if (ARTIFACT_TYPES.has(child.bpmn?.type)) {\n                  artifactIds.add(child.id);\n                }\n              }\n            }\n          };\n          mapNodesInLanes(origPool.children as NodeWithBpmn[]);\n        } else {\n          for (const child of origPool.children) {\n            const childNode = child as NodeWithBpmn;\n            nodeToPool.set(childNode.id, origPool.id);\n            if (ARTIFACT_TYPES.has(childNode.bpmn?.type)) {\n              artifactIds.add(childNode.id);\n            }\n          }\n        }\n      }\n    }\n\n    // Get layouted nodes\n    const layoutedNodes = new Map<string, ElkNode>();\n    for (const child of collab.children) {\n      layoutedNodes.set(child.id, child);\n    }\n\n    // Group nodes by pool and calculate X bounds\n    const poolNodesMap = new Map<string, ElkNode[]>();\n    const poolXBounds = new Map<string, { minX: number; maxX: number }>();\n    let globalMinX = Infinity;\n\n    for (const [nodeId, poolId] of nodeToPool) {\n      const node = layoutedNodes.get(nodeId);\n      if (!node) continue;\n\n      if (!poolNodesMap.has(poolId)) {\n        poolNodesMap.set(poolId, []);\n      }\n      poolNodesMap.get(poolId)!.push(node);\n\n      if (!artifactIds.has(nodeId)) {\n        const x = node.x ?? 0;\n        const w = node.width ?? 100;\n        const bounds = poolXBounds.get(poolId) ?? { minX: Infinity, maxX: 0 };\n        bounds.minX = Math.min(bounds.minX, x);\n        bounds.maxX = Math.max(bounds.maxX, x + w);\n        poolXBounds.set(poolId, bounds);\n        globalMinX = Math.min(globalMinX, x);\n      }\n    }\n\n    // Sort pools by original order\n    const origPools = (origCollab.children as NodeWithBpmn[]).filter(c => c.bpmn?.type === 'participant');\n    origPools.sort((a, b) => {\n      const partA = a.layoutOptions?.['elk.partitioning.partition'];\n      const partB = b.layoutOptions?.['elk.partitioning.partition'];\n      if (partA !== undefined && partB !== undefined) {\n        return Number(partA) - Number(partB);\n      }\n      return 0;\n    });\n\n    // Calculate max content width\n    let globalMaxX = 0;\n    for (const bounds of poolXBounds.values()) {\n      globalMaxX = Math.max(globalMaxX, bounds.maxX);\n    }\n    const maxContentWidth = globalMaxX - globalMinX;\n    const poolWidth = this.poolHeaderWidth + maxContentWidth + this.poolPaddingX * 2;\n\n    // Build pool structures\n    const pools: ElkNode[] = [];\n    let currentY = 0;\n\n    for (const origPool of origPools) {\n      const poolNodes = poolNodesMap.get(origPool.id) ?? [];\n      const isBlackBox = origPool.bpmn?.isBlackBox === true || !origPool.children?.length;\n\n      if (isBlackBox) {\n        pools.push({\n          id: origPool.id,\n          x: 0,\n          y: currentY,\n          width: poolWidth,\n          height: 60,\n          children: [],\n        });\n        currentY += 60;\n      } else {\n        const regularNodes = poolNodes.filter(n => !artifactIds.has(n.id));\n        const artifactNodes = poolNodes.filter(n => artifactIds.has(n.id));\n\n        let maxNodeHeight = 0;\n        for (const node of regularNodes) {\n          maxNodeHeight = Math.max(maxNodeHeight, node.height ?? 80);\n        }\n        const poolHeight = Math.max(this.minPoolHeight, maxNodeHeight + this.poolPaddingY * 2);\n\n        const adjustedNodes: ElkNode[] = [];\n        for (const node of regularNodes) {\n          const nodeHeight = node.height ?? 80;\n          const newY = (poolHeight - nodeHeight) / 2;\n          const newX = this.poolHeaderWidth + (node.x ?? 0) - globalMinX + this.poolPaddingX;\n\n          adjustedNodes.push({\n            ...node,\n            x: newX,\n            y: newY,\n          });\n        }\n\n        // Position artifacts\n        for (const artifact of artifactNodes) {\n          const { task: associatedTask, isInput } = this.findArtifactAssociatedTask(\n            artifact.id,\n            origCollab.edges ?? [],\n            adjustedNodes\n          );\n\n          if (associatedTask) {\n            const artifactWidth = artifact.width ?? 36;\n            const artifactHeight = artifact.height ?? 50;\n            const taskX = associatedTask.x ?? 0;\n            const taskY = associatedTask.y ?? 0;\n            const taskWidth = associatedTask.width ?? 100;\n            const taskHeight = associatedTask.height ?? 80;\n\n            const newX = taskX + taskWidth + 15;\n            const newY = taskY + (taskHeight - artifactHeight) / 2;\n\n            adjustedNodes.push({\n              ...artifact,\n              x: newX,\n              y: Math.max(5, newY),\n            });\n          } else {\n            const newX = this.poolHeaderWidth + (artifact.x ?? 0) - globalMinX + this.poolPaddingX;\n            const artifactHeight = artifact.height ?? 50;\n            const newY = (poolHeight - artifactHeight) / 2;\n\n            adjustedNodes.push({\n              ...artifact,\n              x: newX,\n              y: newY,\n            });\n          }\n        }\n\n        pools.push({\n          id: origPool.id,\n          x: 0,\n          y: currentY,\n          width: poolWidth,\n          height: poolHeight,\n          children: adjustedNodes,\n        });\n        currentY += poolHeight;\n      }\n    }\n\n    // Update collaboration\n    collab.children = pools;\n    collab.width = poolWidth;\n    collab.height = currentY;\n\n    // Recalculate edges\n    if (collab.edges) {\n      const nodePositions = new Map<string, Bounds>();\n\n      for (const pool of pools) {\n        const poolX = pool.x ?? 0;\n        const poolY = pool.y ?? 0;\n\n        nodePositions.set(pool.id, {\n          x: poolX,\n          y: poolY,\n          width: pool.width ?? 680,\n          height: pool.height ?? 200,\n        });\n\n        if (pool.children) {\n          for (const child of pool.children) {\n            nodePositions.set(child.id, {\n              x: poolX + (child.x ?? 0),\n              y: poolY + (child.y ?? 0),\n              width: child.width ?? 100,\n              height: child.height ?? 80,\n            });\n          }\n        }\n      }\n\n      this.recalculateMessageFlows(collab.edges, nodePositions, pools, origCollab.edges);\n    }\n  }\n\n  private calculateDynamicPoolPadding(pool: ElkNode): { x: number; y: number } {\n    let maxNodeWidth = 100;\n    let maxNodeHeight = 80;\n\n    if (pool.children) {\n      for (const child of pool.children) {\n        maxNodeWidth = Math.max(maxNodeWidth, child.width ?? 100);\n        maxNodeHeight = Math.max(maxNodeHeight, child.height ?? 80);\n      }\n    }\n\n    const x = this.clamp(Math.round(maxNodeWidth * 0.45), this.poolPaddingX, this.maxPoolPaddingX);\n    const y = this.clamp(Math.round(maxNodeHeight * 0.45), this.poolPaddingY / 2, this.maxPoolPaddingY);\n\n    return { x, y };\n  }\n\n  private clamp(value: number, min: number, max: number): number {\n    return Math.max(min, Math.min(max, value));\n  }\n\n  /**\n   * Offset all children within a pool\n   */\n  private offsetPoolChildren(pool: ElkNode, offsetX: number, offsetY: number): void {\n    if (!pool.children) return;\n\n    for (const child of pool.children) {\n      if (child.x !== undefined) {\n        child.x += offsetX;\n      }\n      if (child.y !== undefined) {\n        child.y += offsetY;\n      }\n      this.offsetPoolChildren(child, 0, 0);\n    }\n\n    if (pool.edges) {\n      for (const edge of pool.edges) {\n        if (edge.sections) {\n          for (const section of edge.sections) {\n            if (section.startPoint) {\n              section.startPoint.x += offsetX;\n              section.startPoint.y += offsetY;\n            }\n            if (section.endPoint) {\n              section.endPoint.x += offsetX;\n              section.endPoint.y += offsetY;\n            }\n            if (section.bendPoints) {\n              for (const bp of section.bendPoints) {\n                bp.x += offsetX;\n                bp.y += offsetY;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Collect node positions within a pool\n   */\n  private collectNodePositionsInPool(\n    container: ElkNode,\n    offsetX: number,\n    offsetY: number,\n    positions: Map<string, Bounds>\n  ): void {\n    if (!container.children) return;\n\n    for (const child of container.children) {\n      const absX = offsetX + (child.x ?? 0);\n      const absY = offsetY + (child.y ?? 0);\n\n      positions.set(child.id, {\n        x: absX,\n        y: absY,\n        width: child.width ?? 100,\n        height: child.height ?? 80,\n      });\n\n      this.collectNodePositionsInPool(child, absX, absY, positions);\n    }\n  }\n\n  /**\n   * Recalculate message flows after pools have been repositioned\n   */\n  private recalculateMessageFlows(\n    edges: ElkExtendedEdge[],\n    nodePositions: Map<string, Bounds>,\n    pools: ElkNode[],\n    originalEdges?: Array<{ id: string; sources: string[]; targets: string[]; bpmn?: { type?: string } }>\n  ): void {\n    const edgeTypeMap = new Map<string, string>();\n    if (originalEdges) {\n      for (const origEdge of originalEdges) {\n        if (origEdge.bpmn?.type) {\n          edgeTypeMap.set(origEdge.id, origEdge.bpmn.type);\n        }\n      }\n    }\n\n    // Identify blackbox pools (pools with no children or very small height)\n    const blackboxPoolIds = new Set<string>();\n    for (const pool of pools) {\n      const isBlackbox = !pool.children || pool.children.length === 0 || (pool.height ?? 0) <= 80;\n      if (isBlackbox) {\n        blackboxPoolIds.add(pool.id);\n      }\n    }\n\n    for (const edge of edges) {\n      const sourceId = edge.sources?.[0];\n      const targetId = edge.targets?.[0];\n      const edgeType = edgeTypeMap.get(edge.id) ?? (edge as { bpmn?: { type?: string } }).bpmn?.type;\n\n      const sourcePos = sourceId ? nodePositions.get(sourceId) : undefined;\n      const targetPos = targetId ? nodePositions.get(targetId) : undefined;\n\n      if (!sourcePos || !targetPos) continue;\n\n      const isSequenceFlow = edgeType === 'sequenceFlow';\n      const isMessageFlow = edgeType === 'messageFlow';\n      const isDataAssociation = edgeType === 'dataInputAssociation' || edgeType === 'dataOutputAssociation';\n\n      const waypoints: Point[] = [];\n\n      if (isSequenceFlow) {\n        this.createSequenceFlowWaypoints(sourcePos, targetPos, waypoints);\n      } else if (isMessageFlow) {\n        this.createMessageFlowWaypoints(sourcePos, targetPos, waypoints, nodePositions, targetId, sourceId, blackboxPoolIds);\n      } else if (isDataAssociation) {\n        (edge as ElkExtendedEdge & { _absoluteCoords?: boolean })._absoluteCoords = true;\n        edge.sections = [];\n        continue;\n      } else {\n        this.createSequenceFlowWaypoints(sourcePos, targetPos, waypoints);\n      }\n\n      (edge as ElkExtendedEdge & { _absoluteCoords?: boolean })._absoluteCoords = true;\n      edge.sections = [{\n        id: `${edge.id}_s0`,\n        startPoint: waypoints[0],\n        endPoint: waypoints[waypoints.length - 1],\n        bendPoints: waypoints.length > 2 ? waypoints.slice(1, -1) : undefined,\n      }];\n\n      // Update label positions\n      if (edge.labels && edge.labels.length > 0) {\n        const midIdx = Math.floor(waypoints.length / 2);\n        const labelPoint = waypoints[midIdx] ?? waypoints[0];\n        for (const label of edge.labels) {\n          const labelWidth = label.width ?? 50;\n          const labelHeight = label.height ?? 14;\n          label.x = labelPoint.x - labelWidth / 2;\n          label.y = labelPoint.y - labelHeight - 5;\n        }\n      }\n    }\n  }\n\n  /**\n   * Create waypoints for sequence flows\n   */\n  private createSequenceFlowWaypoints(\n    sourcePos: Bounds,\n    targetPos: Bounds,\n    waypoints: Point[]\n  ): void {\n    const sourceCenterX = sourcePos.x + sourcePos.width / 2;\n    const sourceCenterY = sourcePos.y + sourcePos.height / 2;\n    const targetCenterX = targetPos.x + targetPos.width / 2;\n    const targetCenterY = targetPos.y + targetPos.height / 2;\n\n    const goingRight = targetCenterX > sourceCenterX;\n    const goingDown = targetCenterY > sourceCenterY + 30;\n    const goingUp = targetCenterY < sourceCenterY - 30;\n    const sameLevel = !goingDown && !goingUp;\n\n    if (goingRight) {\n      if (sameLevel) {\n        const startX = sourcePos.x + sourcePos.width;\n        const startY = sourceCenterY;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        if (Math.abs(startY - endY) > 10) {\n          const midX = (startX + endX) / 2;\n          waypoints.push({ x: midX, y: startY });\n          waypoints.push({ x: midX, y: endY });\n        }\n        waypoints.push({ x: endX, y: endY });\n      } else if (goingDown) {\n        const startX = sourceCenterX;\n        const startY = sourcePos.y + sourcePos.height;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        waypoints.push({ x: startX, y: endY });\n        waypoints.push({ x: endX, y: endY });\n      } else {\n        const startX = sourceCenterX;\n        const startY = sourcePos.y;\n        const endX = targetPos.x;\n        const endY = targetCenterY;\n\n        waypoints.push({ x: startX, y: startY });\n        waypoints.push({ x: startX, y: endY });\n        waypoints.push({ x: endX, y: endY });\n      }\n    } else {\n      const startX = sourcePos.x;\n      const startY = sourceCenterY;\n      const endX = targetPos.x + targetPos.width;\n      const endY = targetCenterY;\n\n      waypoints.push({ x: startX, y: startY });\n\n      const loopY = Math.max(sourcePos.y + sourcePos.height, targetPos.y + targetPos.height) + 30;\n      waypoints.push({ x: startX, y: loopY });\n      waypoints.push({ x: endX, y: loopY });\n\n      waypoints.push({ x: endX, y: endY });\n    }\n  }\n\n  /**\n   * Create waypoints for message flows\n   * Routes message flows to avoid being too close to other nodes in the target pool\n   */\n  private createMessageFlowWaypoints(\n    sourcePos: Bounds,\n    targetPos: Bounds,\n    waypoints: Point[],\n    nodePositions: Map<string, Bounds>,\n    targetId?: string,\n    sourceId?: string,\n    blackboxPoolIds?: Set<string>\n  ): void {\n    let startX: number, startY: number, endX: number, endY: number;\n\n    const goingDown = sourcePos.y + sourcePos.height < targetPos.y;\n\n    // Check if target/source is a blackbox participant using the passed set\n    const isTargetBlackbox = targetId ? blackboxPoolIds?.has(targetId) ?? false : false;\n    const isSourceBlackbox = sourceId ? blackboxPoolIds?.has(sourceId) ?? false : false;\n\n    if (goingDown) {\n      startX = sourcePos.x + sourcePos.width / 2;\n      startY = sourcePos.y + sourcePos.height;\n\n      // For blackbox targets, prefer connecting directly below the source if within target's X range\n      if (isTargetBlackbox) {\n        const targetLeft = targetPos.x;\n        const targetRight = targetPos.x + targetPos.width;\n        // Use source's X if it falls within target's range (with some margin)\n        if (startX >= targetLeft + 20 && startX <= targetRight - 20) {\n          endX = startX;\n        } else {\n          endX = targetPos.x + targetPos.width / 2;\n        }\n      } else {\n        endX = targetPos.x + targetPos.width / 2;\n      }\n      endY = targetPos.y;\n    } else {\n      startX = sourcePos.x + sourcePos.width / 2;\n      startY = sourcePos.y;\n\n      // For blackbox targets, prefer connecting directly above the source if within target's X range\n      if (isTargetBlackbox) {\n        const targetLeft = targetPos.x;\n        const targetRight = targetPos.x + targetPos.width;\n        if (startX >= targetLeft + 20 && startX <= targetRight - 20) {\n          endX = startX;\n        } else {\n          endX = targetPos.x + targetPos.width / 2;\n        }\n      } else {\n        endX = targetPos.x + targetPos.width / 2;\n      }\n      endY = targetPos.y + targetPos.height;\n    }\n\n    // Similarly, for blackbox sources, adjust startX to align with endX if possible\n    if (isSourceBlackbox) {\n      const sourceLeft = sourcePos.x;\n      const sourceRight = sourcePos.x + sourcePos.width;\n      if (endX >= sourceLeft + 20 && endX <= sourceRight - 20) {\n        startX = endX;\n      }\n    }\n\n    // Patterns to identify containers (pools, lanes, etc.) vs flow nodes\n    const containerPatterns = [/^pool_/, /^participant_/, /^lane_/, /^process_/, /^collaboration_/];\n    const minClearance = 25; // Minimum distance to keep from nodes\n\n    // Calculate the Y range of source and target pools (approximate)\n    const sourcePoolYMin = sourcePos.y - 50;\n    const sourcePoolYMax = sourcePos.y + sourcePos.height + 50;\n    const targetPoolYMin = targetPos.y - 50;\n    const targetPoolYMax = targetPos.y + targetPos.height + 50;\n\n    // First, check if a straight vertical line from startX would hit any obstacles\n    // This applies to ALL message flows, not just those with horizontal distance\n    const fullVerticalMinY = Math.min(startY, endY);\n    const fullVerticalMaxY = Math.max(startY, endY);\n\n    // Collect all nodes that would block a straight vertical path at startX\n    const nodesBlockingDirectPath: Array<{ id: string; bounds: Bounds }> = [];\n    for (const [nodeId, bounds] of nodePositions) {\n      if (nodeId === targetId || nodeId === sourceId) continue;\n\n      // Skip container nodes\n      const isContainer = containerPatterns.some(pattern => pattern.test(nodeId));\n      if (isContainer) continue;\n\n      const nodeLeft = bounds.x;\n      const nodeRight = bounds.x + bounds.width;\n      const nodeTop = bounds.y;\n      const nodeBottom = bounds.y + bounds.height;\n\n      // Skip nodes in source/target pool\n      const inSourcePool = nodeTop >= sourcePoolYMin && nodeBottom <= sourcePoolYMax;\n      const inTargetPool = nodeTop >= targetPoolYMin && nodeBottom <= targetPoolYMax;\n      if (inSourcePool || inTargetPool) continue;\n\n      // Check if node blocks the vertical line at startX\n      const overlapsVerticalLine = startX >= nodeLeft - minClearance && startX <= nodeRight + minClearance;\n      const nodeInVerticalRange = nodeBottom > fullVerticalMinY && nodeTop < fullVerticalMaxY;\n\n      if (overlapsVerticalLine && nodeInVerticalRange) {\n        nodesBlockingDirectPath.push({ id: nodeId, bounds });\n      }\n    }\n\n    // If there are obstacles in the direct path, we need to find a clear route\n    let finalRouteX = startX;\n    if (nodesBlockingDirectPath.length > 0) {\n      // Find a clear X position that avoids ALL obstacles in the vertical path\n      // Try both left and right directions and pick the one with smaller shift\n\n      // Collect all obstacle X ranges\n      const allObstacles: Array<{ left: number; right: number }> = [];\n      for (const { bounds } of nodesBlockingDirectPath) {\n        allObstacles.push({\n          left: bounds.x - minClearance,\n          right: bounds.x + bounds.width + minClearance,\n        });\n      }\n\n      // Also check for other nodes that might be in the way at potential route positions\n      // We need to find a gap that's clear all the way down\n      for (const [nodeId, bounds] of nodePositions) {\n        if (nodeId === targetId || nodeId === sourceId) continue;\n        const isContainer = containerPatterns.some(pattern => pattern.test(nodeId));\n        if (isContainer) continue;\n\n        const nodeTop = bounds.y;\n        const nodeBottom = bounds.y + bounds.height;\n        const inSourcePool = nodeTop >= sourcePoolYMin && nodeBottom <= sourcePoolYMax;\n        const inTargetPool = nodeTop >= targetPoolYMin && nodeBottom <= targetPoolYMax;\n        if (inSourcePool || inTargetPool) continue;\n\n        const nodeInVerticalRange = nodeBottom > fullVerticalMinY && nodeTop < fullVerticalMaxY;\n        if (nodeInVerticalRange) {\n          allObstacles.push({\n            left: bounds.x - minClearance,\n            right: bounds.x + bounds.width + minClearance,\n          });\n        }\n      }\n\n      // Sort obstacles by left edge\n      allObstacles.sort((a, b) => a.left - b.left);\n\n      // Merge overlapping obstacles\n      const mergedObstacles: Array<{ left: number; right: number }> = [];\n      for (const obs of allObstacles) {\n        if (mergedObstacles.length === 0) {\n          mergedObstacles.push({ ...obs });\n        } else {\n          const last = mergedObstacles[mergedObstacles.length - 1];\n          if (obs.left <= last.right) {\n            last.right = Math.max(last.right, obs.right);\n          } else {\n            mergedObstacles.push({ ...obs });\n          }\n        }\n      }\n\n      // Find the best route X - either to the left of all obstacles or to the right\n      // or in a gap between obstacles\n      let bestRouteX = startX;\n      let bestShift = Infinity;\n\n      // Option 1: Go to the left of all obstacles\n      if (mergedObstacles.length > 0) {\n        const leftMost = mergedObstacles[0].left;\n        if (leftMost > 20) { // Make sure we don't go off the diagram\n          const shiftNeeded = Math.abs(startX - leftMost);\n          if (shiftNeeded < bestShift) {\n            bestShift = shiftNeeded;\n            bestRouteX = leftMost;\n          }\n        }\n      }\n\n      // Option 2: Go to the right of all obstacles\n      if (mergedObstacles.length > 0) {\n        const rightMost = mergedObstacles[mergedObstacles.length - 1].right;\n        const shiftNeeded = Math.abs(startX - rightMost);\n        if (shiftNeeded < bestShift) {\n          bestShift = shiftNeeded;\n          bestRouteX = rightMost;\n        }\n      }\n\n      // Option 3: Find a gap between obstacles that's close to startX\n      for (let i = 0; i < mergedObstacles.length - 1; i++) {\n        const gapLeft = mergedObstacles[i].right;\n        const gapRight = mergedObstacles[i + 1].left;\n        const gapWidth = gapRight - gapLeft;\n\n        if (gapWidth >= 10) { // Minimum gap width\n          const gapCenter = (gapLeft + gapRight) / 2;\n          const shiftNeeded = Math.abs(startX - gapCenter);\n          if (shiftNeeded < bestShift) {\n            bestShift = shiftNeeded;\n            bestRouteX = gapCenter;\n          }\n        }\n      }\n\n      finalRouteX = bestRouteX;\n    }\n\n    // Now determine if we need horizontal routing\n    const horizontalDist = Math.abs(startX - endX);\n\n    waypoints.push({ x: startX, y: startY });\n\n    // Check if we need to route around obstacles (finalRouteX differs from startX)\n    // This only applies when startX and endX are close (blackbox case)\n    const needsObstacleAvoidance = Math.abs(finalRouteX - startX) > 5 && horizontalDist <= 5;\n\n    if (needsObstacleAvoidance) {\n      // Route around obstacles for blackbox: go horizontally to finalRouteX, then vertically, then horizontally to endX\n      waypoints.push({ x: finalRouteX, y: startY });\n      waypoints.push({ x: finalRouteX, y: endY });\n      if (Math.abs(finalRouteX - endX) > 5) {\n        waypoints.push({ x: endX, y: endY });\n      }\n    } else if (horizontalDist > 5) {\n      // Normal horizontal routing (source and target at different X)\n      let routeY = horizontalDist > 200 ? endY - 20 : (startY + endY) / 2;\n\n      // Adjust routeY to avoid nodes in the horizontal path\n      if (targetId) {\n        const minX = Math.min(startX, endX);\n        const maxX = Math.max(startX, endX);\n\n        for (const [nodeId, bounds] of nodePositions) {\n          if (nodeId === targetId || nodeId === sourceId) continue;\n\n          const nodeLeft = bounds.x;\n          const nodeRight = bounds.x + bounds.width;\n          const nodeTop = bounds.y;\n          const nodeBottom = bounds.y + bounds.height;\n\n          const overlapsHorizontally = nodeRight > minX && nodeLeft < maxX;\n\n          if (overlapsHorizontally) {\n            if (goingDown) {\n              if (routeY >= nodeTop && routeY <= nodeBottom) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              } else if (nodeTop > startY && nodeTop < endY) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              }\n            } else {\n              if (routeY >= nodeTop && routeY <= nodeBottom) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              } else if (nodeTop < startY && nodeBottom > endY) {\n                routeY = Math.min(routeY, nodeTop - minClearance);\n              }\n            }\n          }\n        }\n\n        // Keep routeY in reasonable range\n        if (goingDown) {\n          routeY = Math.max(routeY, startY + 10);\n          routeY = Math.min(routeY, endY - 10);\n        } else {\n          routeY = Math.max(routeY, endY + 10);\n          routeY = Math.min(routeY, startY - 10);\n        }\n      }\n\n      waypoints.push({ x: startX, y: routeY });\n      waypoints.push({ x: endX, y: routeY });\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Direct vertical path - no obstacles and same X position\n      waypoints.push({ x: endX, y: endY });\n    }\n  }\n\n  /**\n   * Find the task associated with an artifact\n   */\n  private findArtifactAssociatedTask(\n    artifactId: string,\n    edges: Array<{ id: string; sources: string[]; targets: string[]; bpmn?: { type?: string } }>,\n    adjustedNodes: ElkNode[]\n  ): { task: ElkNode | undefined; isInput: boolean } {\n    const nodeMap = new Map<string, ElkNode>();\n    for (const node of adjustedNodes) {\n      nodeMap.set(node.id, node);\n    }\n\n    for (const edge of edges) {\n      const edgeType = edge.bpmn?.type;\n\n      if (edgeType === 'dataInputAssociation' || edgeType === 'association') {\n        if (edge.sources.includes(artifactId)) {\n          const targetId = edge.targets[0];\n          const targetNode = nodeMap.get(targetId);\n          if (targetNode) return { task: targetNode, isInput: true };\n        }\n      }\n\n      if (edgeType === 'dataOutputAssociation') {\n        if (edge.targets.includes(artifactId)) {\n          const sourceId = edge.sources[0];\n          const sourceNode = nodeMap.get(sourceId);\n          if (sourceNode) return { task: sourceNode, isInput: false };\n        }\n      }\n    }\n\n    return { task: undefined, isInput: false };\n  }\n}\n","/**\n * Layout Compactor\n * Reduces unnecessary whitespace in layouts while maintaining relative positions and constraints.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Bounds } from '../../types/internal';\n\nexport interface CompactorOptions {\n  /** Minimum horizontal gap between nodes */\n  minHorizontalGap: number;\n  /** Minimum vertical gap between nodes */\n  minVerticalGap: number;\n  /** Whether to compact horizontally */\n  compactHorizontal: boolean;\n  /** Whether to compact vertically */\n  compactVertical: boolean;\n  /** Whether to consider edge dependencies */\n  considerDependencies: boolean;\n}\n\nconst DEFAULT_OPTIONS: CompactorOptions = {\n  minHorizontalGap: 60,\n  minVerticalGap: 40,\n  compactHorizontal: true,\n  compactVertical: true,\n  considerDependencies: true,\n};\n\n/**\n * Compact layout to reduce whitespace while maintaining constraints\n */\nexport class Compactor {\n  private options: CompactorOptions;\n\n  constructor(options?: Partial<CompactorOptions>) {\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n  }\n\n  /**\n   * Compact the graph layout\n   */\n  compact(graph: ElkNode): void {\n    if (!graph.children || graph.children.length === 0) return;\n\n    // Build node bounds map\n    const nodeBounds = this.collectNodeBounds(graph);\n\n    if (nodeBounds.length === 0) return;\n\n    // Collect edges for dependency tracking\n    const edges = this.collectEdges(graph);\n\n    if (this.options.considerDependencies && edges.length > 0) {\n      // Compact with dependency consideration\n      this.compactWithDependencies(graph, nodeBounds, edges);\n    } else {\n      // Simple compaction\n      if (this.options.compactHorizontal) {\n        this.compactHorizontalSimple(nodeBounds);\n      }\n      if (this.options.compactVertical) {\n        this.compactVerticalSimple(nodeBounds);\n      }\n      // Apply bounds back to nodes\n      this.applyBounds(graph, nodeBounds);\n    }\n\n    // Recursively compact children\n    for (const child of graph.children) {\n      if ((child as ElkNode).children && (child as ElkNode).children!.length > 0) {\n        this.compact(child as ElkNode);\n      }\n    }\n  }\n\n  /**\n   * Collect node bounds from graph\n   */\n  private collectNodeBounds(graph: ElkNode): Array<Bounds & { id: string }> {\n    const bounds: Array<Bounds & { id: string }> = [];\n\n    if (!graph.children) return bounds;\n\n    for (const child of graph.children) {\n      const node = child as ElkNode;\n      if (node.x !== undefined && node.y !== undefined) {\n        bounds.push({\n          id: node.id,\n          x: node.x,\n          y: node.y,\n          width: node.width ?? 0,\n          height: node.height ?? 0,\n        });\n      }\n    }\n\n    return bounds;\n  }\n\n  /**\n   * Collect edges from graph.\n   *\n   * Boundary-event sources are excluded because their stored coordinates are\n   * stale: the diagram builder repositions boundary events visually onto the\n   * parent task's border, but their ELK-given x/y remain unchanged. Using\n   * those positions as a compaction anchor pulls the boundary target way to\n   * the left, far from where it should sit visually.\n   */\n  private collectEdges(graph: ElkNode): Array<{ source: string; target: string }> {\n    const edges: Array<{ source: string; target: string }> = [];\n\n    const collectFromNode = (node: ElkNode) => {\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const elkEdge = edge as ElkExtendedEdge;\n          if (elkEdge.sources && elkEdge.targets) {\n            for (const source of elkEdge.sources) {\n              if (source.startsWith('boundary_')) continue;\n              for (const target of elkEdge.targets) {\n                edges.push({ source, target });\n              }\n            }\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectFromNode(child as ElkNode);\n        }\n      }\n    };\n\n    collectFromNode(graph);\n    return edges;\n  }\n\n  /**\n   * Simple horizontal compaction - move nodes left while maintaining minimum gap\n   */\n  private compactHorizontalSimple(nodes: Array<Bounds & { id: string }>): void {\n    if (nodes.length === 0) return;\n\n    // Sort by X coordinate\n    nodes.sort((a, b) => a.x - b.x);\n\n    // Find minimum X (keep first node's position as anchor)\n    const minX = nodes[0].x;\n\n    // Compact from left to right\n    for (let i = 1; i < nodes.length; i++) {\n      const prev = nodes[i - 1];\n      const curr = nodes[i];\n\n      // Check if nodes are on the same horizontal band (Y overlap)\n      if (this.hasVerticalOverlap(prev, curr)) {\n        const minAllowedX = prev.x + prev.width + this.options.minHorizontalGap;\n\n        // Only move left, never right\n        if (curr.x > minAllowedX) {\n          curr.x = minAllowedX;\n        }\n      }\n    }\n\n    // Normalize to start from original min X\n    const newMinX = Math.min(...nodes.map((n) => n.x));\n    const offsetX = minX - newMinX;\n    if (offsetX > 0) {\n      for (const node of nodes) {\n        node.x += offsetX;\n      }\n    }\n  }\n\n  /**\n   * Simple vertical compaction - move nodes up while maintaining minimum gap\n   */\n  private compactVerticalSimple(nodes: Array<Bounds & { id: string }>): void {\n    if (nodes.length === 0) return;\n\n    // Sort by Y coordinate\n    nodes.sort((a, b) => a.y - b.y);\n\n    // Find minimum Y (keep first node's position as anchor)\n    const minY = nodes[0].y;\n\n    // Compact from top to bottom\n    for (let i = 1; i < nodes.length; i++) {\n      const prev = nodes[i - 1];\n      const curr = nodes[i];\n\n      // Check if nodes are on the same vertical band (X overlap)\n      if (this.hasHorizontalOverlap(prev, curr)) {\n        const minAllowedY = prev.y + prev.height + this.options.minVerticalGap;\n\n        // Only move up, never down\n        if (curr.y > minAllowedY) {\n          curr.y = minAllowedY;\n        }\n      }\n    }\n\n    // Normalize to start from original min Y\n    const newMinY = Math.min(...nodes.map((n) => n.y));\n    const offsetY = minY - newMinY;\n    if (offsetY > 0) {\n      for (const node of nodes) {\n        node.y += offsetY;\n      }\n    }\n  }\n\n  /**\n   * Compact with dependency consideration using topological sort\n   */\n  private compactWithDependencies(\n    graph: ElkNode,\n    nodeBounds: Array<Bounds & { id: string }>,\n    edges: Array<{ source: string; target: string }>\n  ): void {\n    // Build node map for quick lookup\n    const boundsMap = new Map<string, Bounds & { id: string }>();\n    for (const node of nodeBounds) {\n      boundsMap.set(node.id, node);\n    }\n\n    // Build dependency graph (target depends on source)\n    const dependencies = new Map<string, Set<string>>();\n    for (const edge of edges) {\n      if (!dependencies.has(edge.target)) {\n        dependencies.set(edge.target, new Set());\n      }\n      dependencies.get(edge.target)!.add(edge.source);\n    }\n\n    // Topological sort\n    const sorted = this.topologicalSort([...boundsMap.keys()], dependencies);\n\n    // Compact horizontally following dependency order\n    if (this.options.compactHorizontal) {\n      for (const nodeId of sorted) {\n        const node = boundsMap.get(nodeId);\n        if (!node) continue;\n\n        const deps = dependencies.get(nodeId);\n        if (!deps || deps.size === 0) continue;\n\n        // Find the rightmost edge of all dependencies\n        let maxRight = 0;\n        for (const depId of deps) {\n          const dep = boundsMap.get(depId);\n          if (dep) {\n            maxRight = Math.max(maxRight, dep.x + dep.width);\n          }\n        }\n\n        // Compact to minimum allowed position\n        const targetX = maxRight + this.options.minHorizontalGap;\n        if (node.x > targetX) {\n          node.x = targetX;\n        }\n      }\n    }\n\n    // Apply bounds back to nodes\n    this.applyBounds(graph, nodeBounds);\n  }\n\n  /**\n   * Apply bounds back to graph nodes\n   */\n  private applyBounds(graph: ElkNode, bounds: Array<Bounds & { id: string }>): void {\n    const boundsMap = new Map<string, Bounds & { id: string }>();\n    for (const b of bounds) {\n      boundsMap.set(b.id, b);\n    }\n\n    if (!graph.children) return;\n\n    for (const child of graph.children) {\n      const node = child as ElkNode;\n      const b = boundsMap.get(node.id);\n      if (b) {\n        node.x = b.x;\n        node.y = b.y;\n      }\n    }\n  }\n\n  /**\n   * Check if two nodes have vertical overlap (same horizontal band)\n   */\n  private hasVerticalOverlap(a: Bounds, b: Bounds): boolean {\n    const aTop = a.y;\n    const aBottom = a.y + a.height;\n    const bTop = b.y;\n    const bBottom = b.y + b.height;\n\n    return aTop < bBottom && bTop < aBottom;\n  }\n\n  /**\n   * Check if two nodes have horizontal overlap (same vertical band)\n   */\n  private hasHorizontalOverlap(a: Bounds, b: Bounds): boolean {\n    const aLeft = a.x;\n    const aRight = a.x + a.width;\n    const bLeft = b.x;\n    const bRight = b.x + b.width;\n\n    return aLeft < bRight && bLeft < aRight;\n  }\n\n  /**\n   * Topological sort using Kahn's algorithm\n   */\n  private topologicalSort(\n    nodes: string[],\n    dependencies: Map<string, Set<string>>\n  ): string[] {\n    const inDegree = new Map<string, number>();\n    const adjacencyList = new Map<string, string[]>();\n\n    // Initialize\n    for (const node of nodes) {\n      inDegree.set(node, 0);\n      adjacencyList.set(node, []);\n    }\n\n    // Build adjacency list and compute in-degrees\n    for (const [target, sources] of dependencies) {\n      for (const source of sources) {\n        if (adjacencyList.has(source)) {\n          adjacencyList.get(source)!.push(target);\n          inDegree.set(target, (inDegree.get(target) ?? 0) + 1);\n        }\n      }\n    }\n\n    // Find nodes with no dependencies\n    const queue: string[] = [];\n    for (const node of nodes) {\n      if ((inDegree.get(node) ?? 0) === 0) {\n        queue.push(node);\n      }\n    }\n\n    const sorted: string[] = [];\n\n    while (queue.length > 0) {\n      const node = queue.shift()!;\n      sorted.push(node);\n\n      for (const dependent of adjacencyList.get(node) ?? []) {\n        const newDegree = (inDegree.get(dependent) ?? 0) - 1;\n        inDegree.set(dependent, newDegree);\n        if (newDegree === 0) {\n          queue.push(dependent);\n        }\n      }\n    }\n\n    // If there are cycles, append remaining nodes\n    for (const node of nodes) {\n      if (!sorted.includes(node)) {\n        sorted.push(node);\n      }\n    }\n\n    return sorted;\n  }\n}\n\n/**\n * Standalone function for horizontal compaction\n */\nexport function compactHorizontal(\n  nodes: Array<{ id: string; x: number; width: number }>,\n  minGap: number\n): void {\n  if (nodes.length === 0) return;\n\n  // Sort by X coordinate\n  nodes.sort((a, b) => a.x - b.x);\n\n  // Compact from left to right\n  for (let i = 1; i < nodes.length; i++) {\n    const prev = nodes[i - 1];\n    const curr = nodes[i];\n\n    const minX = prev.x + prev.width + minGap;\n\n    // Only move left, never right\n    if (curr.x > minX) {\n      curr.x = minX;\n    }\n  }\n}\n\n/**\n * Standalone function for vertical compaction\n */\nexport function compactVertical(\n  nodes: Array<{ id: string; y: number; height: number }>,\n  minGap: number\n): void {\n  if (nodes.length === 0) return;\n\n  // Sort by Y coordinate\n  nodes.sort((a, b) => a.y - b.y);\n\n  // Compact from top to bottom\n  for (let i = 1; i < nodes.length; i++) {\n    const prev = nodes[i - 1];\n    const curr = nodes[i];\n\n    const minY = prev.y + prev.height + minGap;\n\n    // Only move up, never down\n    if (curr.y > minY) {\n      curr.y = minY;\n    }\n  }\n}\n","/**\n * Pathfinding Router\n * Uses pathfinding library (A* algorithm) for obstacle-avoiding edge routing.\n * Provides better edge routing quality compared to simple obstacle detection.\n */\n\nimport PF from 'pathfinding';\nimport type { Bounds, Point } from '../../types/internal';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PathfindingOptions {\n  /** Grid cell size in pixels (smaller = more precise but slower) */\n  cellSize: number;\n  /** Margin around obstacles */\n  obstacleMargin: number;\n  /** Allow diagonal movement (usually false for BPMN orthogonal routing) */\n  allowDiagonal: boolean;\n  /** Padding around the grid bounds */\n  gridPadding: number;\n}\n\nconst DEFAULT_OPTIONS: PathfindingOptions = {\n  cellSize: 10,\n  obstacleMargin: 5,\n  allowDiagonal: false,\n  gridPadding: 50,\n};\n\nexport interface RouteResult {\n  /** Path points in absolute coordinates */\n  path: Point[];\n  /** Whether a valid path was found */\n  success: boolean;\n}\n\n// ============================================================================\n// Pathfinding Router\n// ============================================================================\n\n/**\n * Router that uses A* pathfinding for obstacle-avoiding edge routing\n */\nexport class PathfindingRouter {\n  private options: PathfindingOptions;\n  private obstacles: Bounds[] = [];\n  private gridBounds: Bounds | null = null;\n  private grid: PF.Grid | null = null;\n  private finder: PF.AStarFinder;\n\n  constructor(options?: Partial<PathfindingOptions>) {\n    this.options = { ...DEFAULT_OPTIONS, ...options };\n    this.finder = new PF.AStarFinder({\n      allowDiagonal: this.options.allowDiagonal,\n      dontCrossCorners: true,\n    });\n  }\n\n  /**\n   * Set obstacles (nodes that edges should avoid)\n   */\n  setObstacles(obstacles: Bounds[]): void {\n    this.obstacles = obstacles.map((obs) => ({\n      x: obs.x - this.options.obstacleMargin,\n      y: obs.y - this.options.obstacleMargin,\n      width: obs.width + this.options.obstacleMargin * 2,\n      height: obs.height + this.options.obstacleMargin * 2,\n    }));\n\n    // Calculate grid bounds\n    this.calculateGridBounds();\n\n    // Build the grid\n    this.buildGrid();\n  }\n\n  /**\n   * Find a path between two points avoiding obstacles\n   */\n  findPath(source: Point, target: Point): RouteResult {\n    if (!this.grid || !this.gridBounds) {\n      return { path: [source, target], success: false };\n    }\n\n    // Convert points to grid coordinates\n    const startGrid = this.toGridCoords(source);\n    const endGrid = this.toGridCoords(target);\n\n    // Clamp to grid bounds\n    const gridWidth = this.grid.width;\n    const gridHeight = this.grid.height;\n\n    const clampedStart = {\n      x: Math.max(0, Math.min(gridWidth - 1, startGrid.x)),\n      y: Math.max(0, Math.min(gridHeight - 1, startGrid.y)),\n    };\n    const clampedEnd = {\n      x: Math.max(0, Math.min(gridWidth - 1, endGrid.x)),\n      y: Math.max(0, Math.min(gridHeight - 1, endGrid.y)),\n    };\n\n    // Clone grid for pathfinding (finder modifies the grid)\n    const gridClone = this.grid.clone();\n\n    // Ensure start and end cells are walkable\n    gridClone.setWalkableAt(clampedStart.x, clampedStart.y, true);\n    gridClone.setWalkableAt(clampedEnd.x, clampedEnd.y, true);\n\n    // Find path\n    const gridPath = this.finder.findPath(\n      clampedStart.x,\n      clampedStart.y,\n      clampedEnd.x,\n      clampedEnd.y,\n      gridClone\n    );\n\n    if (gridPath.length === 0) {\n      // No path found, return direct line\n      return { path: [source, target], success: false };\n    }\n\n    // Convert grid path to absolute coordinates\n    const absolutePath = gridPath.map(([gx, gy]) => this.toAbsoluteCoords({ x: gx, y: gy }));\n\n    // Simplify the path (remove redundant points)\n    const simplifiedPath = this.simplifyPath(absolutePath);\n\n    // Ensure start and end points are exact\n    if (simplifiedPath.length > 0) {\n      simplifiedPath[0] = source;\n      simplifiedPath[simplifiedPath.length - 1] = target;\n    }\n\n    return { path: simplifiedPath, success: true };\n  }\n\n  /**\n   * Find an orthogonal path (only horizontal and vertical segments)\n   */\n  findOrthogonalPath(source: Point, target: Point): RouteResult {\n    const result = this.findPath(source, target);\n\n    if (!result.success) {\n      // Create a simple orthogonal path\n      return {\n        path: this.createSimpleOrthogonalPath(source, target),\n        success: false,\n      };\n    }\n\n    // Orthogonalize the path\n    const orthogonalPath = this.orthogonalizePath(result.path);\n\n    return { path: orthogonalPath, success: true };\n  }\n\n  /**\n   * Route an edge from source node to target node\n   */\n  routeEdge(\n    sourceNode: Bounds,\n    targetNode: Bounds,\n    sourcePort?: 'top' | 'bottom' | 'left' | 'right',\n    targetPort?: 'top' | 'bottom' | 'left' | 'right'\n  ): RouteResult {\n    // Determine connection points\n    const source = this.getConnectionPoint(sourceNode, sourcePort ?? this.getBestSourcePort(sourceNode, targetNode));\n    const target = this.getConnectionPoint(targetNode, targetPort ?? this.getBestTargetPort(sourceNode, targetNode));\n\n    return this.findOrthogonalPath(source, target);\n  }\n\n  // ============================================================================\n  // Private: Grid Building\n  // ============================================================================\n\n  private calculateGridBounds(): void {\n    if (this.obstacles.length === 0) {\n      this.gridBounds = { x: 0, y: 0, width: 100, height: 100 };\n      return;\n    }\n\n    let minX = Infinity;\n    let minY = Infinity;\n    let maxX = -Infinity;\n    let maxY = -Infinity;\n\n    for (const obs of this.obstacles) {\n      minX = Math.min(minX, obs.x);\n      minY = Math.min(minY, obs.y);\n      maxX = Math.max(maxX, obs.x + obs.width);\n      maxY = Math.max(maxY, obs.y + obs.height);\n    }\n\n    const padding = this.options.gridPadding;\n    this.gridBounds = {\n      x: minX - padding,\n      y: minY - padding,\n      width: maxX - minX + padding * 2,\n      height: maxY - minY + padding * 2,\n    };\n  }\n\n  private buildGrid(): void {\n    if (!this.gridBounds) return;\n\n    const cellSize = this.options.cellSize;\n    const gridWidth = Math.ceil(this.gridBounds.width / cellSize);\n    const gridHeight = Math.ceil(this.gridBounds.height / cellSize);\n\n    // Create grid with all cells walkable\n    this.grid = new PF.Grid(gridWidth, gridHeight);\n\n    // Mark obstacle cells as unwalkable\n    for (const obs of this.obstacles) {\n      const startX = Math.floor((obs.x - this.gridBounds.x) / cellSize);\n      const startY = Math.floor((obs.y - this.gridBounds.y) / cellSize);\n      const endX = Math.ceil((obs.x + obs.width - this.gridBounds.x) / cellSize);\n      const endY = Math.ceil((obs.y + obs.height - this.gridBounds.y) / cellSize);\n\n      for (let gx = startX; gx < endX; gx++) {\n        for (let gy = startY; gy < endY; gy++) {\n          if (gx >= 0 && gx < gridWidth && gy >= 0 && gy < gridHeight) {\n            this.grid.setWalkableAt(gx, gy, false);\n          }\n        }\n      }\n    }\n  }\n\n  // ============================================================================\n  // Private: Coordinate Conversion\n  // ============================================================================\n\n  private toGridCoords(point: Point): { x: number; y: number } {\n    if (!this.gridBounds) return { x: 0, y: 0 };\n\n    return {\n      x: Math.round((point.x - this.gridBounds.x) / this.options.cellSize),\n      y: Math.round((point.y - this.gridBounds.y) / this.options.cellSize),\n    };\n  }\n\n  private toAbsoluteCoords(gridPoint: { x: number; y: number }): Point {\n    if (!this.gridBounds) return { x: 0, y: 0 };\n\n    return {\n      x: gridPoint.x * this.options.cellSize + this.gridBounds.x,\n      y: gridPoint.y * this.options.cellSize + this.gridBounds.y,\n    };\n  }\n\n  // ============================================================================\n  // Private: Path Processing\n  // ============================================================================\n\n  private simplifyPath(path: Point[]): Point[] {\n    if (path.length <= 2) return path;\n\n    const result: Point[] = [path[0]];\n\n    for (let i = 1; i < path.length - 1; i++) {\n      const prev = path[i - 1];\n      const curr = path[i];\n      const next = path[i + 1];\n\n      // Check if direction changes\n      const dx1 = curr.x - prev.x;\n      const dy1 = curr.y - prev.y;\n      const dx2 = next.x - curr.x;\n      const dy2 = next.y - curr.y;\n\n      // Normalize directions\n      const dir1x = dx1 === 0 ? 0 : dx1 / Math.abs(dx1);\n      const dir1y = dy1 === 0 ? 0 : dy1 / Math.abs(dy1);\n      const dir2x = dx2 === 0 ? 0 : dx2 / Math.abs(dx2);\n      const dir2y = dy2 === 0 ? 0 : dy2 / Math.abs(dy2);\n\n      // Keep point if direction changes\n      if (dir1x !== dir2x || dir1y !== dir2y) {\n        result.push(curr);\n      }\n    }\n\n    result.push(path[path.length - 1]);\n    return result;\n  }\n\n  private orthogonalizePath(path: Point[]): Point[] {\n    if (path.length <= 1) return path;\n\n    const result: Point[] = [path[0]];\n\n    for (let i = 1; i < path.length; i++) {\n      const prev = result[result.length - 1];\n      const curr = path[i];\n\n      // If not already orthogonal, add intermediate point\n      if (prev.x !== curr.x && prev.y !== curr.y) {\n        // Prefer horizontal-then-vertical routing\n        result.push({ x: curr.x, y: prev.y });\n      }\n\n      result.push(curr);\n    }\n\n    return result;\n  }\n\n  private createSimpleOrthogonalPath(source: Point, target: Point): Point[] {\n    // Simple L-shaped or Z-shaped path\n    const midX = (source.x + target.x) / 2;\n\n    if (source.y === target.y) {\n      return [source, target];\n    }\n\n    if (source.x === target.x) {\n      return [source, target];\n    }\n\n    // Create a path with intermediate points\n    return [\n      source,\n      { x: midX, y: source.y },\n      { x: midX, y: target.y },\n      target,\n    ];\n  }\n\n  // ============================================================================\n  // Private: Connection Points\n  // ============================================================================\n\n  private getConnectionPoint(node: Bounds, port: 'top' | 'bottom' | 'left' | 'right'): Point {\n    switch (port) {\n      case 'top':\n        return { x: node.x + node.width / 2, y: node.y };\n      case 'bottom':\n        return { x: node.x + node.width / 2, y: node.y + node.height };\n      case 'left':\n        return { x: node.x, y: node.y + node.height / 2 };\n      case 'right':\n        return { x: node.x + node.width, y: node.y + node.height / 2 };\n    }\n  }\n\n  private getBestSourcePort(source: Bounds, target: Bounds): 'top' | 'bottom' | 'left' | 'right' {\n    const sourceCenterX = source.x + source.width / 2;\n    const sourceCenterY = source.y + source.height / 2;\n    const targetCenterX = target.x + target.width / 2;\n    const targetCenterY = target.y + target.height / 2;\n\n    const dx = targetCenterX - sourceCenterX;\n    const dy = targetCenterY - sourceCenterY;\n\n    if (Math.abs(dx) > Math.abs(dy)) {\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n\n  private getBestTargetPort(source: Bounds, target: Bounds): 'top' | 'bottom' | 'left' | 'right' {\n    const sourceCenterX = source.x + source.width / 2;\n    const sourceCenterY = source.y + source.height / 2;\n    const targetCenterX = target.x + target.width / 2;\n    const targetCenterY = target.y + target.height / 2;\n\n    const dx = sourceCenterX - targetCenterX;\n    const dy = sourceCenterY - targetCenterY;\n\n    if (Math.abs(dx) > Math.abs(dy)) {\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Route multiple edges with obstacle avoidance\n */\nexport function routeEdges(\n  edges: Array<{\n    id: string;\n    source: Bounds;\n    target: Bounds;\n    sourcePort?: 'top' | 'bottom' | 'left' | 'right';\n    targetPort?: 'top' | 'bottom' | 'left' | 'right';\n  }>,\n  obstacles: Bounds[],\n  options?: Partial<PathfindingOptions>\n): Map<string, Point[]> {\n  const router = new PathfindingRouter(options);\n  router.setObstacles(obstacles);\n\n  const results = new Map<string, Point[]>();\n\n  for (const edge of edges) {\n    const result = router.routeEdge(edge.source, edge.target, edge.sourcePort, edge.targetPort);\n    results.set(edge.id, result.path);\n  }\n\n  return results;\n}\n\n/**\n * Find a path between two points avoiding obstacles\n */\nexport function findPathAvoidingObstacles(\n  source: Point,\n  target: Point,\n  obstacles: Bounds[],\n  options?: Partial<PathfindingOptions>\n): Point[] {\n  const router = new PathfindingRouter(options);\n  router.setObstacles(obstacles);\n  const result = router.findOrthogonalPath(source, target);\n  return result.path;\n}\n","/**\n * Edge Fixer\n * Detects and fixes edges that cross through nodes.\n * Uses PathfindingRouter for obstacle-avoiding pathfinding.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { Point, Bounds, NodeWithBpmn } from '../../types/internal';\nimport { EVENT_TYPES, GATEWAY_TYPES, SUBPROCESS_TYPES, TASK_TYPES } from '../../types/bpmn-constants';\nimport { segmentCrossesNode, createOrthogonalPath } from './geometry-utils';\nimport { PathfindingRouter } from './pathfinding-router';\nimport { isDebugEnabled } from '../../utils/debug';\n\nconst SUBPROCESS_TYPE_SET = new Set<string>(SUBPROCESS_TYPES);\n// Nodes that act as obstacles for edge routing. Detected by bpmn.type rather\n// than ID prefix because IDs like `tx_end` (a transaction's internal end event)\n// share a prefix with their parent and would slip past a regex-based filter.\nconst OBSTACLE_TYPE_SET = new Set<string>([\n  ...EVENT_TYPES.filter((t) => t !== 'boundaryEvent'),\n  ...TASK_TYPES,\n  ...GATEWAY_TYPES,\n  'callActivity',\n  // Collapsed subprocesses are obstacles; expanded ones are containers and\n  // handled by the isContainer branch below.\n  ...SUBPROCESS_TYPES,\n]);\n\n// A node whose x/y is a coordinate system for its descendants and edges.\n// Expanded subprocesses, pools, lanes, and processes all share this property:\n// child positions and edge waypoints are stored relative to them.\nfunction isContainer(bpmn: NodeWithBpmn['bpmn']): boolean {\n  if (!bpmn) return false;\n  const type = bpmn.type;\n  if (!type) return false;\n  if (type === 'participant' || type === 'lane' || type === 'process') return true;\n  return bpmn.isExpanded === true && SUBPROCESS_TYPE_SET.has(type);\n}\n\nfunction isFlowObstacle(bpmn: NodeWithBpmn['bpmn']): boolean {\n  if (!bpmn?.type) return false;\n  if (bpmn.type === 'boundaryEvent') return false;\n  // Skip expanded subprocesses — they're containers, not obstacles.\n  if (bpmn.isExpanded === true && SUBPROCESS_TYPE_SET.has(bpmn.type)) return false;\n  return OBSTACLE_TYPE_SET.has(bpmn.type);\n}\n\n/**\n * Handler for edge crossing detection and fixing\n */\nexport class EdgeFixer {\n  private readonly margin = 15;\n  private router: PathfindingRouter;\n\n  constructor() {\n    this.router = new PathfindingRouter({\n      cellSize: 10,\n      obstacleMargin: this.margin,\n      allowDiagonal: false,\n      gridPadding: 50,\n    });\n  }\n\n  /**\n   * Fix edges that cross through nodes\n   */\n  fix(graph: ElkNode): void {\n    // Obstacles for crossing-detection. Excludes containers (expanded\n    // subprocesses, pools/lanes) because edges crossing their borders is\n    // expected behavior, not a routing failure.\n    const obstaclesByContainer = new Map<string, Map<string, Bounds>>();\n    // All anchorable nodes (obstacles + container nodes that can act as\n    // edge source/target). Snap consults this so it can re-anchor edges\n    // that start/end on a subprocess after post-processing resized it.\n    const anchorsByContainer = new Map<string, Map<string, Bounds>>();\n    const boundaryEventIds = new Set<string>();\n\n    const isPoolType = (bpmn: NodeWithBpmn['bpmn']): boolean =>\n      bpmn?.type === 'participant' || bpmn?.type === 'process';\n\n    const recordNode = (\n      bucket: Map<string, Map<string, Bounds>>,\n      containerId: string,\n      id: string,\n      bounds: Bounds\n    ) => {\n      if (!bucket.has(containerId)) bucket.set(containerId, new Map());\n      bucket.get(containerId)!.set(id, bounds);\n    };\n\n    const collectNodePositions = (\n      node: ElkNode,\n      offsetX: number = 0,\n      offsetY: number = 0,\n      containerId: string = 'root'\n    ) => {\n      const bpmn = (node as unknown as NodeWithBpmn).bpmn;\n      const currentContainerId = isPoolType(bpmn) ? node.id : containerId;\n      if (bpmn?.type === 'boundaryEvent') boundaryEventIds.add(node.id);\n\n      if (node.x !== undefined && node.y !== undefined) {\n        // Use visual dimensions for edge anchoring/crossing. ELK inflates\n        // event heights (label band) and gateway widths (long-label band),\n        // but edges should attach to the visible shape, not the layout box.\n        const visualWidth = bpmn?._visualWidth ?? node.width ?? 100;\n        const visualHeight = bpmn?._visualHeight ?? node.height ?? 80;\n        const bounds: Bounds = {\n          x: offsetX + node.x,\n          y: offsetY + node.y,\n          width: visualWidth,\n          height: visualHeight,\n        };\n        const obstacle = isFlowObstacle(bpmn);\n        // Subprocesses (and any container that can host edge endpoints) are\n        // anchorable even though they aren't obstacles.\n        const anchorable = obstacle || (bpmn?.isExpanded === true && SUBPROCESS_TYPE_SET.has(bpmn.type));\n        if (obstacle) recordNode(obstaclesByContainer, currentContainerId, node.id, bounds);\n        if (anchorable) recordNode(anchorsByContainer, currentContainerId, node.id, bounds);\n      }\n\n      if (node.children) {\n        const descend = isContainer(bpmn);\n        const newOffsetX = descend ? offsetX + (node.x ?? 0) : offsetX;\n        const newOffsetY = descend ? offsetY + (node.y ?? 0) : offsetY;\n        for (const child of node.children) {\n          collectNodePositions(child, newOffsetX, newOffsetY, currentContainerId);\n        }\n      }\n    };\n    collectNodePositions(graph);\n\n    const processEdges = (\n      node: ElkNode,\n      containerOffsetX: number = 0,\n      containerOffsetY: number = 0,\n      containerId: string = 'root'\n    ) => {\n      const bpmn = (node as unknown as NodeWithBpmn).bpmn;\n      const currentContainerId = isPoolType(bpmn) ? node.id : containerId;\n\n      // Edge waypoints on a container node are stored relative to that\n      // container, so accumulate the container's own x/y before walking into\n      // its edges (which are processed before recursing into children).\n      const descend = isContainer(bpmn);\n      const selfOffsetX = descend ? containerOffsetX + (node.x ?? 0) : containerOffsetX;\n      const selfOffsetY = descend ? containerOffsetY + (node.y ?? 0) : containerOffsetY;\n\n      if (node.edges) {\n        const anchors = anchorsByContainer.get(currentContainerId) ?? new Map();\n        const obstacles = obstaclesByContainer.get(currentContainerId) ?? new Map();\n\n        for (const edge of node.edges) {\n          if (!edge.sections || edge.sections.length === 0) continue;\n          // Boundary-event edges have bespoke routing in diagram-builder;\n          // re-snapping them here would discard that work.\n          const sourceId = edge.sources?.[0];\n          if (sourceId && boundaryEventIds.has(sourceId)) continue;\n          this.snapEdgeEndpointsToNodeBorders(edge, anchors, selfOffsetX, selfOffsetY);\n          this.fixEdgeIfCrossing(edge, anchors, obstacles, selfOffsetX, selfOffsetY);\n        }\n      }\n\n      if (node.children) {\n        for (const child of node.children) {\n          processEdges(child, selfOffsetX, selfOffsetY, currentContainerId);\n        }\n      }\n    };\n    processEdges(graph);\n  }\n\n  private fixEdgeIfCrossing(\n    edge: ElkExtendedEdge,\n    anchors: Map<string, Bounds>,\n    obstacleMap: Map<string, Bounds>,\n    containerOffsetX: number,\n    containerOffsetY: number\n  ): void {\n    const section = edge.sections?.[0];\n    if (!section) return;\n\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n\n    const waypoints: Point[] = [\n      { x: containerOffsetX + section.startPoint.x, y: containerOffsetY + section.startPoint.y },\n    ];\n    if (section.bendPoints) {\n      for (const bp of section.bendPoints) {\n        waypoints.push({ x: containerOffsetX + bp.x, y: containerOffsetY + bp.y });\n      }\n    }\n    waypoints.push({ x: containerOffsetX + section.endPoint.x, y: containerOffsetY + section.endPoint.y });\n\n    const crossedNodes: string[] = [];\n    for (let i = 0; i < waypoints.length - 1; i++) {\n      const p1 = waypoints[i];\n      const p2 = waypoints[i + 1];\n      if (!p1 || !p2) continue;\n\n      for (const [nodeId, pos] of obstacleMap) {\n        if (nodeId === sourceId || nodeId === targetId) continue;\n        if (segmentCrossesNode(p1, p2, pos)) {\n          crossedNodes.push(nodeId);\n        }\n      }\n    }\n\n    const targetPos = targetId ? anchors.get(targetId) : undefined;\n    const sourcePos = sourceId ? anchors.get(sourceId) : undefined;\n\n    if (targetPos && sourcePos && waypoints.length >= 2) {\n      const lastWaypoint = waypoints[waypoints.length - 1];\n      const secondLastWaypoint = waypoints[waypoints.length - 2];\n      const isReturnEdge = targetPos.y + targetPos.height < sourcePos.y;\n\n      if (isReturnEdge && lastWaypoint && secondLastWaypoint) {\n        if (Math.abs(secondLastWaypoint.y - lastWaypoint.y) < 5) {\n          const segY = secondLastWaypoint.y;\n          const segMinX = Math.min(secondLastWaypoint.x, lastWaypoint.x);\n          const segMaxX = Math.max(secondLastWaypoint.x, lastWaypoint.x);\n\n          if (segY > targetPos.y && segY < targetPos.y + targetPos.height) {\n            if (segMinX < targetPos.x + targetPos.width && segMaxX > targetPos.x) {\n              crossedNodes.push(targetId + ' (target)');\n            }\n          }\n        }\n      }\n    }\n\n    if (crossedNodes.length === 0) return;\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Edge ${edge.id} crosses nodes: ${crossedNodes.join(', ')}`);\n    }\n\n    if (!sourcePos || !targetPos) return;\n\n    // Exclude source and target from obstacles. Otherwise the inflated\n    // obstacle margin engulfs the start/end cells, the pathfinder can't\n    // step out, and we fall back to a midpoint Z-shape that still cuts\n    // straight through other nodes.\n    const obstacles: Bounds[] = [];\n    for (const [nodeId, pos] of obstacleMap) {\n      if (nodeId === sourceId || nodeId === targetId) continue;\n      obstacles.push(pos);\n    }\n\n    this.router.setObstacles(obstacles);\n\n    const dx = (targetPos.x + targetPos.width / 2) - (sourcePos.x + sourcePos.width / 2);\n    const dy = (targetPos.y + targetPos.height / 2) - (sourcePos.y + sourcePos.height / 2);\n\n    // Pick the primary axis. When only one axis is cleanly separated, the\n    // route HAS to leave/enter along it. When both are separated (i.e.,\n    // source and target diagonal to each other with an obstacle band between),\n    // pick the axis with the larger separation so the longer leg comes first\n    // and the final segment is short and perpendicular to the target.\n    const horizontallySeparated =\n      targetPos.x >= sourcePos.x + sourcePos.width ||\n      sourcePos.x >= targetPos.x + targetPos.width;\n    const verticallySeparated =\n      targetPos.y >= sourcePos.y + sourcePos.height ||\n      sourcePos.y >= targetPos.y + targetPos.height;\n    let horizontalPrimary: boolean;\n    if (horizontallySeparated && !verticallySeparated) horizontalPrimary = true;\n    else if (verticallySeparated && !horizontallySeparated) horizontalPrimary = false;\n    else horizontalPrimary = Math.abs(dx) >= Math.abs(dy);\n\n    let sourcePort: 'top' | 'bottom' | 'left' | 'right';\n    let targetPort: 'top' | 'bottom' | 'left' | 'right';\n    if (horizontalPrimary) {\n      sourcePort = dx >= 0 ? 'right' : 'left';\n      targetPort = dx >= 0 ? 'left' : 'right';\n    } else {\n      sourcePort = dy >= 0 ? 'bottom' : 'top';\n      targetPort = dy >= 0 ? 'top' : 'bottom';\n    }\n\n    const result = this.router.routeEdge(sourcePos, targetPos, sourcePort, targetPort);\n    // A* on a 10px grid emits a step-by-step path; collapse runs of stairs\n    // into the longest L-shape that still clears every obstacle, otherwise\n    // the diagram fills up with jagged staircases.\n    const path = this.shortcutOrthogonal(result.path, obstacles);\n\n    if (path.length < 2) return;\n\n    // Re-anchor the target endpoint if the final segment's direction doesn't\n    // match the requested side. When the route had to wrap around obstacles,\n    // pathfinder's final L-leg can come in perpendicular to a DIFFERENT side\n    // (e.g., vertical-into-left). Snapping to the matching side avoids\n    // ensurePerpendicularEndpoints later inserting a tiny stub that bpmn.io\n    // renders as an arrow tip pointing the wrong direction.\n    this.alignFinalSegmentToTargetSide(path, targetPos);\n    this.alignFinalSegmentToSourceSide(path, sourcePos);\n\n    const startPoint = path[0];\n    const endPoint = path[path.length - 1];\n    const bendPoints = path.slice(1, -1);\n\n    section.startPoint = {\n      x: startPoint.x - containerOffsetX,\n      y: startPoint.y - containerOffsetY,\n    };\n    section.endPoint = {\n      x: endPoint.x - containerOffsetX,\n      y: endPoint.y - containerOffsetY,\n    };\n    section.bendPoints = bendPoints.length > 0\n      ? bendPoints.map(bp => ({\n          x: bp.x - containerOffsetX,\n          y: bp.y - containerOffsetY,\n        }))\n      : undefined;\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Fixed edge ${edge.id} with ${bendPoints.length} bend points using PathfindingRouter`);\n    }\n  }\n\n  /**\n   * Re-anchor edge start/end points to their source/target node borders.\n   * Post-processing (compactor, lane stacking, etc.) often moves nodes after\n   * ELK ran, leaving edge endpoints pointing at stale positions. Without this\n   * pass, an edge can appear to continue past its target into empty space.\n   *\n   * The strategy is deliberately simple: snap endpoints to the natural border\n   * for the source→target direction (horizontal-primary unless the nodes are\n   * nearly column-aligned), and keep any bend points along the way intact.\n   */\n  private snapEdgeEndpointsToNodeBorders(\n    edge: ElkExtendedEdge,\n    nodePositions: Map<string, Bounds>,\n    containerOffsetX: number,\n    containerOffsetY: number\n  ): void {\n    const section = edge.sections?.[0];\n    if (!section) return;\n\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n    if (!sourceId || !targetId) return;\n\n    const sourcePos = nodePositions.get(sourceId);\n    const targetPos = nodePositions.get(targetId);\n    if (!sourcePos || !targetPos) return;\n\n    const srcCx = sourcePos.x + sourcePos.width / 2;\n    const srcCy = sourcePos.y + sourcePos.height / 2;\n    const dstCx = targetPos.x + targetPos.width / 2;\n    const dstCy = targetPos.y + targetPos.height / 2;\n    const dx = dstCx - srcCx;\n    const dy = dstCy - srcCy;\n    // If source and target are completely separated on one axis (one's far edge ≤\n    // the other's near edge), the edge HAS to leave/enter via that axis — picking\n    // the other axis sends the connector along the side of the source/target\n    // bounding box and the perpendicular bend then often slices through whatever\n    // node sits between them on the same layer. So whenever an axis is cleanly\n    // separated, force that as the primary; only fall back to magnitude when both\n    // axes overlap.\n    const horizontallySeparated =\n      targetPos.x >= sourcePos.x + sourcePos.width ||\n      sourcePos.x >= targetPos.x + targetPos.width;\n    const verticallySeparated =\n      targetPos.y >= sourcePos.y + sourcePos.height ||\n      sourcePos.y >= targetPos.y + targetPos.height;\n    let horizontalPrimary: boolean;\n    if (horizontallySeparated) horizontalPrimary = true;\n    else if (verticallySeparated) horizontalPrimary = false;\n    else horizontalPrimary = Math.abs(dx) >= Math.abs(dy);\n\n    let startAbsX: number, startAbsY: number, endAbsX: number, endAbsY: number;\n    if (horizontalPrimary) {\n      startAbsY = srcCy;\n      endAbsY = dstCy;\n      if (dx >= 0) {\n        startAbsX = sourcePos.x + sourcePos.width;\n        endAbsX = targetPos.x;\n      } else {\n        startAbsX = sourcePos.x;\n        endAbsX = targetPos.x + targetPos.width;\n      }\n    } else {\n      startAbsX = srcCx;\n      endAbsX = dstCx;\n      if (dy >= 0) {\n        startAbsY = sourcePos.y + sourcePos.height;\n        endAbsY = targetPos.y;\n      } else {\n        startAbsY = sourcePos.y;\n        endAbsY = targetPos.y + targetPos.height;\n      }\n    }\n\n    // Emit a Z-shape so the downstream crossing check (which only inspects\n    // axis-aligned segments) can see the actual route. A bare diagonal would\n    // be invisible to the check, and diagram-builder would later orthogonalize\n    // it straight through whatever node sits between source and target.\n    const path = createOrthogonalPath(\n      { x: startAbsX, y: startAbsY },\n      { x: endAbsX, y: endAbsY },\n      horizontalPrimary ? 'horizontal' : 'vertical'\n    );\n    const first = path[0];\n    const last = path[path.length - 1];\n    section.startPoint = {\n      x: first.x - containerOffsetX,\n      y: first.y - containerOffsetY,\n    };\n    section.endPoint = {\n      x: last.x - containerOffsetX,\n      y: last.y - containerOffsetY,\n    };\n    section.bendPoints = path.length > 2\n      ? path.slice(1, -1).map((p) => ({\n          x: p.x - containerOffsetX,\n          y: p.y - containerOffsetY,\n        }))\n      : undefined;\n  }\n\n  // When the final segment is vertical but the endpoint sits on the target's\n  // left/right edge (or horizontal but on top/bottom), swap the endpoint to\n  // the side that matches the segment's direction. Keeps the route a clean L\n  // instead of producing a stubby corner.\n  private alignFinalSegmentToTargetSide(path: Point[], targetPos: Bounds): void {\n    if (path.length < 2) return;\n    const end = path[path.length - 1];\n    const prev = path[path.length - 2];\n    const segHorizontal = Math.abs(end.y - prev.y) < 1;\n    const segVertical = Math.abs(end.x - prev.x) < 1;\n    if (!segHorizontal && !segVertical) return;\n\n    const left = targetPos.x;\n    const right = targetPos.x + targetPos.width;\n    const top = targetPos.y;\n    const bottom = targetPos.y + targetPos.height;\n    const cx = targetPos.x + targetPos.width / 2;\n    const cy = targetPos.y + targetPos.height / 2;\n    const onLeft = Math.abs(end.x - left) < 3;\n    const onRight = Math.abs(end.x - right) < 3;\n    const onTop = Math.abs(end.y - top) < 3;\n    const onBottom = Math.abs(end.y - bottom) < 3;\n\n    if (segVertical && (onLeft || onRight)) {\n      const approachFromBelow = prev.y > end.y;\n      end.x = cx;\n      end.y = approachFromBelow ? bottom : top;\n      prev.x = cx;\n    } else if (segHorizontal && (onTop || onBottom)) {\n      const approachFromRight = prev.x > end.x;\n      end.y = cy;\n      end.x = approachFromRight ? right : left;\n      prev.y = cy;\n    }\n  }\n\n  private alignFinalSegmentToSourceSide(path: Point[], sourcePos: Bounds): void {\n    if (path.length < 2) return;\n    const start = path[0];\n    const next = path[1];\n    const segHorizontal = Math.abs(start.y - next.y) < 1;\n    const segVertical = Math.abs(start.x - next.x) < 1;\n    if (!segHorizontal && !segVertical) return;\n\n    const left = sourcePos.x;\n    const right = sourcePos.x + sourcePos.width;\n    const top = sourcePos.y;\n    const bottom = sourcePos.y + sourcePos.height;\n    const cx = sourcePos.x + sourcePos.width / 2;\n    const cy = sourcePos.y + sourcePos.height / 2;\n    const onLeft = Math.abs(start.x - left) < 3;\n    const onRight = Math.abs(start.x - right) < 3;\n    const onTop = Math.abs(start.y - top) < 3;\n    const onBottom = Math.abs(start.y - bottom) < 3;\n\n    if (segVertical && (onLeft || onRight)) {\n      const departsUp = next.y < start.y;\n      start.x = cx;\n      start.y = departsUp ? top : bottom;\n      next.x = cx;\n    } else if (segHorizontal && (onTop || onBottom)) {\n      const departsLeft = next.x < start.x;\n      start.y = cy;\n      start.x = departsLeft ? left : right;\n      next.y = cy;\n    }\n  }\n\n  // Greedy orthogonal \"string pulling\" — A* on a 10px grid emits step-by-step\n  // staircases; for each anchor, jump to the farthest path point still reachable\n  // via a single L-shape (or straight segment) that clears every obstacle.\n  private shortcutOrthogonal(path: Point[], obstacles: Bounds[]): Point[] {\n    if (path.length <= 2) return path;\n\n    const segmentClear = (p1: Point, p2: Point): boolean => {\n      for (const obs of obstacles) {\n        if (segmentCrossesNode(p1, p2, obs)) return false;\n      }\n      return true;\n    };\n\n    // Try to connect a→b via a single L (or straight). Push the bend (if any)\n    // and the endpoint to `out`; return false when no clearance is possible.\n    const pushLShape = (a: Point, b: Point, out: Point[]): boolean => {\n      if (Math.abs(a.x - b.x) < 1 || Math.abs(a.y - b.y) < 1) {\n        if (!segmentClear(a, b)) return false;\n        out.push(b);\n        return true;\n      }\n      const hThenV = { x: b.x, y: a.y };\n      if (segmentClear(a, hThenV) && segmentClear(hThenV, b)) {\n        out.push(hThenV, b);\n        return true;\n      }\n      const vThenH = { x: a.x, y: b.y };\n      if (segmentClear(a, vThenH) && segmentClear(vThenH, b)) {\n        out.push(vThenH, b);\n        return true;\n      }\n      return false;\n    };\n\n    const result: Point[] = [path[0]];\n    let i = 0;\n    while (i < path.length - 1) {\n      // Try the farthest jump first; A* only emits walkable steps so the\n      // i→i+1 fallback is always reachable.\n      for (let j = path.length - 1; j > i; j--) {\n        if (j === i + 1 || pushLShape(path[i], path[j], result)) {\n          if (j === i + 1) result.push(path[j]);\n          i = j;\n          break;\n        }\n      }\n    }\n    return result;\n  }\n}\n","/**\n * Gateway Endpoint Adjuster\n * Handles the calculation of edge endpoint positions for gateway diamond shapes.\n * Gateways in BPMN are rendered as diamonds, so edge endpoints need to be adjusted\n * to connect to the diamond edges rather than the rectangular bounding box.\n */\n\nimport type { Point, Bounds } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Adjust an edge endpoint to connect to a gateway's diamond shape.\n * Gateway diamonds have 4 corners: left, top, right, bottom (at midpoints of bounding box edges).\n *\n * @param endpoint - The current endpoint position\n * @param adjacentPoint - The adjacent point on the edge (used to determine approach direction)\n * @param gatewayBounds - The bounding box of the gateway\n * @param isSource - Whether this endpoint is the source (true) or target (false) of the edge\n * @returns The adjusted endpoint position on the diamond edge\n */\nexport function adjustGatewayEndpoint(\n  endpoint: Point,\n  adjacentPoint: Point,\n  gatewayBounds: Bounds,\n  isSource: boolean\n): Point {\n  const gatewayCenterX = gatewayBounds.x + gatewayBounds.width / 2;\n  const gatewayCenterY = gatewayBounds.y + gatewayBounds.height / 2;\n  const tolerance = 1; // Tolerance for corner detection\n\n  if (isDebugEnabled()) {\n    console.log(`[BPMN] adjustGatewayEndpoint: isSource=${isSource}`);\n    console.log(`  endpoint: (${endpoint.x}, ${endpoint.y})`);\n    console.log(`  gatewayBounds: x=${gatewayBounds.x}, y=${gatewayBounds.y}, w=${gatewayBounds.width}, h=${gatewayBounds.height}`);\n    console.log(`  gatewayCenter: (${gatewayCenterX}, ${gatewayCenterY})`);\n    console.log(`  right edge x: ${gatewayBounds.x + gatewayBounds.width}`);\n  }\n\n  // Diamond corners (at midpoints of bounding box edges)\n  const leftCorner = { x: gatewayBounds.x, y: gatewayCenterY };\n  const rightCorner = { x: gatewayBounds.x + gatewayBounds.width, y: gatewayCenterY };\n  const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };\n  const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };\n\n  // Check if endpoint is already at a diamond corner (no adjustment needed)\n  // Left corner: x at left edge AND y at center\n  if (Math.abs(endpoint.x - gatewayBounds.x) < tolerance &&\n      Math.abs(endpoint.y - gatewayCenterY) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at LEFT corner, no adjustment`);\n    return endpoint;\n  }\n  // Right corner: x at right edge AND y at center\n  if (Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance &&\n      Math.abs(endpoint.y - gatewayCenterY) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at RIGHT corner, no adjustment`);\n    return endpoint;\n  }\n  // Top corner: y at top edge AND x at center\n  if (Math.abs(endpoint.y - gatewayBounds.y) < tolerance &&\n      Math.abs(endpoint.x - gatewayCenterX) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at TOP corner, no adjustment`);\n    return endpoint;\n  }\n  // Bottom corner: y at bottom edge AND x at center\n  if (Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance &&\n      Math.abs(endpoint.x - gatewayCenterX) < tolerance) {\n    if (isDebugEnabled()) console.log(`  -> Already at BOTTOM corner, no adjustment`);\n    return endpoint;\n  }\n\n  if (isDebugEnabled()) {\n    console.log(`  -> NOT at corner, will adjust`);\n  }\n\n  // Endpoint is NOT at a corner - calculate intersection with diamond edge\n  const result = calculateDiamondIntersection(\n    endpoint,\n    gatewayBounds,\n    gatewayCenterX,\n    gatewayCenterY,\n    isSource,\n    adjacentPoint\n  );\n  if (isDebugEnabled()) {\n    console.log(`  -> Adjusted to: (${result.x}, ${result.y})`);\n  }\n  return result;\n}\n\n/**\n * Calculate the intersection point with the diamond edge.\n * The diamond is defined by connecting the midpoints of the bounding box edges.\n *\n * @param endpoint - The current endpoint position\n * @param gatewayBounds - The bounding box of the gateway\n * @param gatewayCenterX - X coordinate of gateway center\n * @param gatewayCenterY - Y coordinate of gateway center\n * @param isSource - Whether this endpoint is the source of the edge\n * @param adjacentPoint - The adjacent point on the edge\n * @returns The intersection point on the diamond edge\n */\nexport function calculateDiamondIntersection(\n  endpoint: Point,\n  gatewayBounds: Bounds,\n  gatewayCenterX: number,\n  gatewayCenterY: number,\n  isSource: boolean,\n  adjacentPoint: Point\n): Point {\n  const tolerance = 1;\n\n  const leftCorner = { x: gatewayBounds.x, y: gatewayCenterY };\n  const rightCorner = { x: gatewayBounds.x + gatewayBounds.width, y: gatewayCenterY };\n  const topCorner = { x: gatewayCenterX, y: gatewayBounds.y };\n  const bottomCorner = { x: gatewayCenterX, y: gatewayBounds.y + gatewayBounds.height };\n\n  // Determine which side based on endpoint position relative to gateway\n  const isOnLeftEdge = Math.abs(endpoint.x - gatewayBounds.x) < tolerance;\n  const isOnRightEdge = Math.abs(endpoint.x - (gatewayBounds.x + gatewayBounds.width)) < tolerance;\n  const isOnTopEdge = Math.abs(endpoint.y - gatewayBounds.y) < tolerance;\n  const isOnBottomEdge = Math.abs(endpoint.y - (gatewayBounds.y + gatewayBounds.height)) < tolerance;\n\n  const halfWidth = gatewayBounds.width / 2;\n  const halfHeight = gatewayBounds.height / 2;\n\n  if (isOnLeftEdge || isOnRightEdge) {\n    // Endpoint is on left or right edge of bounding box but not at corner\n    // Calculate diamond edge intersection at this Y position\n    const yDistFromCenter = Math.abs(endpoint.y - gatewayCenterY);\n\n    if (yDistFromCenter >= halfHeight) {\n      // Outside diamond vertically - snap to corner\n      return isOnLeftEdge ? leftCorner : rightCorner;\n    }\n\n    // Diamond edge equation: |x - centerX| / halfWidth + |y - centerY| / halfHeight = 1\n    const xOffsetFromCenter = halfWidth * (1 - yDistFromCenter / halfHeight);\n    const intersectX = isOnLeftEdge\n      ? gatewayCenterX - xOffsetFromCenter\n      : gatewayCenterX + xOffsetFromCenter;\n\n    return { x: intersectX, y: endpoint.y };\n  }\n\n  if (isOnTopEdge || isOnBottomEdge) {\n    // Endpoint is on top or bottom edge of bounding box but not at corner\n    // Calculate diamond edge intersection at this X position\n    const xDistFromCenter = Math.abs(endpoint.x - gatewayCenterX);\n\n    if (xDistFromCenter >= halfWidth) {\n      // Outside diamond horizontally - snap to corner\n      return isOnTopEdge ? topCorner : bottomCorner;\n    }\n\n    const yOffsetFromCenter = halfHeight * (1 - xDistFromCenter / halfWidth);\n    const intersectY = isOnTopEdge\n      ? gatewayCenterY - yOffsetFromCenter\n      : gatewayCenterY + yOffsetFromCenter;\n\n    return { x: endpoint.x, y: intersectY };\n  }\n\n  // Endpoint is not on any edge - use approach direction to determine corner\n  const dx = isSource ? adjacentPoint.x - endpoint.x : endpoint.x - adjacentPoint.x;\n  const dy = isSource ? adjacentPoint.y - endpoint.y : endpoint.y - adjacentPoint.y;\n\n  if (Math.abs(dx) > Math.abs(dy)) {\n    // Horizontal approach\n    if (isSource) {\n      return dx > 0 ? rightCorner : leftCorner;\n    } else {\n      return dx > 0 ? leftCorner : rightCorner;\n    }\n  } else {\n    // Vertical approach\n    if (isSource) {\n      return dy > 0 ? bottomCorner : topCorner;\n    } else {\n      return dy > 0 ? topCorner : bottomCorner;\n    }\n  }\n}\n\n/**\n * Get the four corner points of a gateway diamond.\n *\n * @param gatewayBounds - The bounding box of the gateway\n * @returns Object containing all four corner points\n */\nexport function getDiamondCorners(gatewayBounds: Bounds): {\n  left: Point;\n  right: Point;\n  top: Point;\n  bottom: Point;\n} {\n  const centerX = gatewayBounds.x + gatewayBounds.width / 2;\n  const centerY = gatewayBounds.y + gatewayBounds.height / 2;\n\n  return {\n    left: { x: gatewayBounds.x, y: centerY },\n    right: { x: gatewayBounds.x + gatewayBounds.width, y: centerY },\n    top: { x: centerX, y: gatewayBounds.y },\n    bottom: { x: centerX, y: gatewayBounds.y + gatewayBounds.height },\n  };\n}\n\n/**\n * Check if a point is on the diamond edge (within tolerance).\n *\n * @param point - The point to check\n * @param gatewayBounds - The bounding box of the gateway\n * @param tolerance - Distance tolerance for edge detection\n * @returns True if the point is on the diamond edge\n */\nexport function isPointOnDiamondEdge(\n  point: Point,\n  gatewayBounds: Bounds,\n  tolerance: number = 2\n): boolean {\n  const centerX = gatewayBounds.x + gatewayBounds.width / 2;\n  const centerY = gatewayBounds.y + gatewayBounds.height / 2;\n  const halfWidth = gatewayBounds.width / 2;\n  const halfHeight = gatewayBounds.height / 2;\n\n  // Diamond edge equation: |x - centerX| / halfWidth + |y - centerY| / halfHeight = 1\n  // Check if point satisfies this equation within tolerance\n  const normalizedX = Math.abs(point.x - centerX) / halfWidth;\n  const normalizedY = Math.abs(point.y - centerY) / halfHeight;\n  const edgeValue = normalizedX + normalizedY;\n\n  return Math.abs(edgeValue - 1) < tolerance / Math.min(halfWidth, halfHeight);\n}\n","/**\n * Default ELK Layout Options\n * Optimized for BPMN diagram layout\n */\n\nimport type { ElkLayoutOptions } from '../types';\n\nexport const DEFAULT_ELK_OPTIONS: ElkLayoutOptions = {\n  // === Basic Configuration ===\n  'elk.algorithm': 'layered',\n  'elk.direction': 'RIGHT',\n\n  // === Layer Assignment ===\n  // NETWORK_SIMPLEX provides better layer distribution than LONGEST_PATH\n  'elk.layered.layering.strategy': 'NETWORK_SIMPLEX',\n\n  // === Crossing Minimization ===\n  'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',\n  // TWO_SIDED greedy switch improves crossing reduction\n  'elk.layered.crossingMinimization.greedySwitch.type': 'TWO_SIDED',\n\n  // === Node Placement ===\n  // BRANDES_KOEPF provides better vertical alignment than NETWORK_SIMPLEX\n  'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF',\n  // Use BALANCED alignment for symmetric layouts\n  'elk.layered.nodePlacement.bk.fixedAlignment': 'BALANCED',\n\n  // === Edge Routing ===\n  'elk.edgeRouting': 'ORTHOGONAL',\n  // Distribute self-loops evenly\n  'elk.layered.edgeRouting.selfLoopDistribution': 'EQUALLY',\n\n  // === Edge Labels ===\n  // Place edge labels at the center of the edge\n  'elk.edgeLabels.placement': 'CENTER',\n  // Ensure labels don't overlap with nodes or other labels\n  'elk.spacing.labelLabel': 5,\n  'elk.spacing.labelNode': 10,\n  'elk.spacing.edgeLabel': 10,\n\n  // === Spacing (increased for better readability) ===\n  'elk.spacing.nodeNode': 60,\n  'elk.spacing.edgeNode': 40,\n  'elk.spacing.edgeEdge': 25,\n  'elk.layered.spacing.nodeNodeBetweenLayers': 100,\n  'elk.layered.spacing.edgeNodeBetweenLayers': 40,\n  'elk.layered.spacing.edgeEdgeBetweenLayers': 25,\n  // Disconnected components (e.g. event-only test fixtures, ad-hoc islands)\n  // need their own breathing room or they collapse on top of one another.\n  'elk.spacing.componentComponent': 50,\n\n  // === Hierarchy Handling ===\n  'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n\n  // === Model Order ===\n  // Consider both node and edge order from the input model\n  'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES',\n\n  // === Compaction ===\n  // Compact connected components together\n  'elk.layered.compaction.connectedComponents': true,\n\n  // === Alignment ===\n  // Center alignment for cleaner appearance\n  'elk.alignment': 'CENTER',\n};\n\n/**\n * Merge user options with default options\n */\nexport function mergeElkOptions(\n  userOptions?: ElkLayoutOptions,\n  graphOptions?: ElkLayoutOptions\n): ElkLayoutOptions {\n  return {\n    ...DEFAULT_ELK_OPTIONS,\n    ...graphOptions,\n    ...userOptions,\n  };\n}\n","/**\n * ELK Graph Preparer\n * Prepares BPMN graphs for ELK layout by:\n * - Merging layout options\n * - Converting to ELK-compatible format\n * - Flattening pool/lane structures when needed for cross-pool edges\n * - Handling boundary events as siblings for proper edge routing\n * - Identifying main flow nodes for layout priority\n */\n\nimport type { ElkNode, ElkExtendedEdge, LayoutOptions } from 'elkjs';\nimport type { ElkBpmnGraph } from '../../types';\nimport type { NodeWithBpmn, BoundaryEventInfo } from '../../types/internal';\nimport { mergeElkOptions } from '../default-options';\nimport { SizeCalculator } from '../size-calculator';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for preparing graphs for ELK layout\n */\nexport class ElkGraphPreparer {\n  private sizeCalculator: SizeCalculator;\n\n  constructor() {\n    this.sizeCalculator = new SizeCalculator();\n  }\n\n  /**\n   * Prepare the graph for ELK layout\n   */\n  prepare(\n    graph: ElkBpmnGraph,\n    userOptions: Record<string, unknown> = {},\n    boundaryEventTargetIds: Set<string> = new Set()\n  ): ElkNode {\n    let layoutOptions = mergeElkOptions(userOptions as Record<string, string | number | boolean | undefined>, graph.layoutOptions);\n\n    // Check if this graph contains a cross-pool collaboration\n    // If so, force RIGHT direction for better horizontal layout\n    if (this.hasCrossPoolCollaboration(graph)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.direction': 'RIGHT',\n      };\n    }\n\n    // Identify main flow nodes to give them layout priority\n    const mainFlowNodes = this.identifyMainFlowNodes(graph, boundaryEventTargetIds);\n\n    const root: ElkNode = {\n      id: graph.id ?? 'root',\n      layoutOptions: layoutOptions as LayoutOptions,\n      children: this.prepareChildrenForElk(graph.children, boundaryEventTargetIds, mainFlowNodes),\n    };\n\n    // BPMN link events are paired by `linkEventDefinition.name` and act like\n    // gotos: a throw exits the visible flow and a catch with the same name\n    // resumes it elsewhere. ELK has no way to know about this relationship,\n    // so without help it scatters the disconnected events. Add invisible\n    // edges between paired throw/catch events to bring them close together.\n    // The edges are stripped from the BPMN output by the result merger.\n    this.addLinkEventPairingEdges(root);\n\n    return root;\n  }\n\n  /**\n   * Walk all processes / containers and add invisible ELK edges between\n   * link-throw and link-catch events that share the same linkEventDefinition\n   * name. Each edge is marked with `_isLinkPair: true` so the BPMN merger\n   * can drop it before serialization.\n   */\n  private addLinkEventPairingEdges(root: ElkNode): void {\n    const throwsByLinkName = new Map<string, string[]>();\n    const catchesByLinkName = new Map<string, string[]>();\n    let containerWithLinks: ElkNode | undefined;\n\n    const walk = (node: ElkNode, parent: ElkNode | undefined) => {\n      const bpmn = (node as ElkNode & { bpmn?: { type?: string; eventDefinitionType?: string; linkEventDefinition?: { name?: string } } }).bpmn;\n      if (bpmn?.eventDefinitionType === 'link') {\n        const linkName = bpmn.linkEventDefinition?.name;\n        if (linkName && parent) {\n          containerWithLinks ??= parent;\n          if (bpmn.type === 'intermediateThrowEvent') {\n            (throwsByLinkName.get(linkName) ?? throwsByLinkName.set(linkName, []).get(linkName)!).push(node.id);\n          } else if (bpmn.type === 'intermediateCatchEvent') {\n            (catchesByLinkName.get(linkName) ?? catchesByLinkName.set(linkName, []).get(linkName)!).push(node.id);\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) walk(child, node);\n      }\n    };\n    walk(root, undefined);\n\n    if (!containerWithLinks || throwsByLinkName.size === 0) return;\n\n    containerWithLinks.edges ??= [];\n    let pairCounter = 0;\n    for (const [linkName, throws] of throwsByLinkName) {\n      const catches = catchesByLinkName.get(linkName) ?? [];\n      for (const throwId of throws) {\n        for (const catchId of catches) {\n          const edge: ElkExtendedEdge & { _isLinkPair?: boolean } = {\n            id: `_link_pair_${pairCounter++}_${throwId}_${catchId}`,\n            sources: [throwId],\n            targets: [catchId],\n            _isLinkPair: true,\n          };\n          containerWithLinks.edges.push(edge);\n        }\n      }\n    }\n  }\n\n  /**\n   * Check if the graph contains a collaboration with cross-pool sequence flows\n   */\n  hasCrossPoolCollaboration(graph: ElkBpmnGraph): boolean {\n    if (!graph.children) return false;\n\n    for (const child of graph.children) {\n      const node = child as unknown as NodeWithBpmn;\n      if (node.bpmn?.type !== 'collaboration') continue;\n\n      // Check if collaboration has multiple pools\n      const pools = (node.children as NodeWithBpmn[] | undefined)?.filter(\n        c => c.bpmn?.type === 'participant'\n      ) ?? [];\n      if (pools.length <= 1) continue;\n\n      // Check if collaboration has cross-pool sequence flows\n      const hasCrossPoolFlows = node.edges?.some(\n        edge => edge.bpmn?.type === 'sequenceFlow' ||\n                edge.bpmn?.type === 'dataInputAssociation' ||\n                edge.bpmn?.type === 'dataOutputAssociation'\n      );\n\n      if (hasCrossPoolFlows) return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Collect all boundary event target IDs from boundary event info\n   */\n  collectBoundaryEventTargetIds(boundaryEventInfo: Map<string, BoundaryEventInfo>): Set<string> {\n    const targetIds = new Set<string>();\n    for (const [_beId, info] of boundaryEventInfo) {\n      for (const targetId of info.targets) {\n        targetIds.add(targetId);\n      }\n    }\n    return targetIds;\n  }\n\n  /**\n   * Collect all boundary event IDs and their target nodes from edges\n   */\n  collectBoundaryEventTargets(node: NodeWithBpmn): Set<string> {\n    const boundaryEventIds = new Set<string>();\n    const targetNodeIds = new Set<string>();\n\n    // Collect boundary event IDs from this node and children\n    const collectBoundaryEventIds = (n: NodeWithBpmn) => {\n      if (n.boundaryEvents) {\n        for (const be of n.boundaryEvents) {\n          boundaryEventIds.add(be.id);\n        }\n      }\n      if (n.children) {\n        for (const child of n.children) {\n          collectBoundaryEventIds(child as NodeWithBpmn);\n        }\n      }\n    };\n    collectBoundaryEventIds(node);\n\n    // Find edges where source is a boundary event\n    const findTargets = (n: NodeWithBpmn) => {\n      if (n.edges) {\n        for (const edge of n.edges) {\n          const sourceId = edge.sources[0];\n          if (boundaryEventIds.has(sourceId)) {\n            targetNodeIds.add(edge.targets[0]);\n          }\n        }\n      }\n      if (n.children) {\n        for (const child of n.children) {\n          findTargets(child as NodeWithBpmn);\n        }\n      }\n    };\n    findTargets(node);\n\n    return targetNodeIds;\n  }\n\n  /**\n   * Identify main flow nodes - nodes that are in the primary path from start to end,\n   * not including boundary event branches.\n   * Main flow nodes should be prioritized in layout to stay at the top.\n   */\n  identifyMainFlowNodes(graph: ElkBpmnGraph, boundaryEventTargetIds: Set<string>): Set<string> {\n    const mainFlowNodes = new Set<string>();\n    const edgeMap = new Map<string, string[]>(); // source -> targets\n    const boundaryEventIds = new Set<string>();\n\n    // Collect all boundary event IDs and edges\n    const collectInfo = (node: NodeWithBpmn) => {\n      if (node.boundaryEvents) {\n        for (const be of node.boundaryEvents) {\n          boundaryEventIds.add(be.id);\n        }\n      }\n      if (node.edges) {\n        for (const edge of node.edges) {\n          const source = edge.sources?.[0];\n          const target = edge.targets?.[0];\n          if (source && target) {\n            if (!edgeMap.has(source)) {\n              edgeMap.set(source, []);\n            }\n            edgeMap.get(source)!.push(target);\n          }\n        }\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          collectInfo(child as NodeWithBpmn);\n        }\n      }\n    };\n\n    // Find start events\n    const findStartEvents = (node: NodeWithBpmn): string[] => {\n      const starts: string[] = [];\n      if (node.bpmn?.type === 'startEvent') {\n        starts.push(node.id);\n      }\n      if (node.children) {\n        for (const child of node.children) {\n          starts.push(...findStartEvents(child as NodeWithBpmn));\n        }\n      }\n      return starts;\n    };\n\n    // Traverse from start events, following only non-boundary-event edges\n    const traverseMainFlow = (nodeId: string) => {\n      if (mainFlowNodes.has(nodeId)) return;\n      // Don't include boundary event targets as main flow\n      if (boundaryEventTargetIds.has(nodeId)) return;\n      // Don't include boundary events themselves\n      if (boundaryEventIds.has(nodeId)) return;\n\n      mainFlowNodes.add(nodeId);\n\n      const targets = edgeMap.get(nodeId) || [];\n      for (const targetId of targets) {\n        // Skip if this edge originates from a boundary event\n        if (!boundaryEventIds.has(nodeId)) {\n          traverseMainFlow(targetId);\n        }\n      }\n    };\n\n    for (const child of graph.children ?? []) {\n      collectInfo(child as NodeWithBpmn);\n    }\n\n    const startEvents = findStartEvents({ children: graph.children } as NodeWithBpmn);\n    for (const startId of startEvents) {\n      traverseMainFlow(startId);\n    }\n\n    if (isDebugEnabled()) {\n      console.log(`[BPMN] Main flow nodes: ${Array.from(mainFlowNodes).join(', ')}`);\n    }\n\n    return mainFlowNodes;\n  }\n\n  /**\n   * Prepare children for ELK layout\n   */\n  private prepareChildrenForElk(\n    nodes: ElkBpmnGraph['children'],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): ElkNode[] {\n    if (!nodes) return [];\n\n    const result: ElkNode[] = [];\n\n    for (const child of nodes) {\n      const node = child as unknown as NodeWithBpmn;\n      result.push(this.prepareNodeForElk(node, boundaryEventTargetIds, mainFlowNodes));\n\n      // Add boundary events as sibling nodes (not children of the task)\n      // This allows ELK to route edges from boundary events correctly\n      if (node.boundaryEvents && node.boundaryEvents.length > 0) {\n        for (const be of node.boundaryEvents) {\n          result.push({\n            id: be.id,\n            width: be.width ?? 36,\n            height: be.height ?? 36,\n          });\n        }\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Prepare a single node for ELK layout\n   */\n  private prepareNodeForElk(\n    node: NodeWithBpmn,\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): ElkNode {\n    let layoutOptions = node.layoutOptions as LayoutOptions | undefined;\n\n    // Add ELK layer constraints for start/end events to ensure proper flow direction\n    // startEvent should be in the first layer (leftmost in RIGHT direction)\n    // endEvent should be in the last layer (rightmost in RIGHT direction)\n    const nodeType = node.bpmn?.type;\n    if (nodeType === 'startEvent') {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.layered.layering.layerConstraint': 'FIRST',\n      } as LayoutOptions;\n    } else if (nodeType === 'endEvent') {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.layered.layering.layerConstraint': 'LAST',\n      } as LayoutOptions;\n    }\n\n    // Calculate extra height for nodes with ioSpecification to reserve space for data objects\n    // These constants must match the values in diagram-builder.ts buildIoSpecificationShapes()\n    const ioSpec = node.bpmn?.ioSpecification;\n    let ioSpecExtraHeight = 0;\n    if (ioSpec) {\n      const dataInputs = ioSpec.dataInputs ?? [];\n      const dataOutputs = ioSpec.dataOutputs ?? [];\n      const maxCount = Math.max(dataInputs.length, dataOutputs.length);\n\n      if (maxCount > 0) {\n        // Constants matching diagram-builder.ts\n        const dataHeight = 50;\n        const gapBelow = 20;\n        const verticalSpacing = 24;\n        const labelHeight = 14;\n\n        // Calculate required extra height for ELK layout:\n        // gapBelow + maxCount * (dataHeight + verticalSpacing) + labelHeight\n        ioSpecExtraHeight = gapBelow + maxCount * (dataHeight + verticalSpacing) + labelHeight;\n\n        if (isDebugEnabled()) {\n          console.log(`[BPMN] Adding extra height ${ioSpecExtraHeight} for node ${node.id} with ioSpecification`);\n        }\n      }\n    }\n\n    // Give main flow nodes higher priority so ELK keeps them aligned\n    if (mainFlowNodes.has(node.id) && !boundaryEventTargetIds.has(node.id)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.priority': '10',\n      } as LayoutOptions;\n    }\n\n    // Give boundary event targets lower priority\n    // Actual positioning below main flow is done in post-processing\n    if (boundaryEventTargetIds.has(node.id)) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.priority': '1',\n      } as LayoutOptions;\n    }\n\n\n\n    // For expanded subprocesses, add top padding for the label header\n    const isExpandedSubprocess = node.bpmn?.isExpanded === true &&\n      (node.bpmn?.type === 'subProcess' || node.bpmn?.type === 'transaction' ||\n       node.bpmn?.type === 'adHocSubProcess' || node.bpmn?.type === 'eventSubProcess');\n\n    // Save user-specified padding to preserve it\n    const userPadding = layoutOptions?.['elk.padding'];\n\n    if (isExpandedSubprocess) {\n      layoutOptions = {\n        'elk.padding': '[top=30,left=12,bottom=30,right=12]',\n        ...layoutOptions,\n      } as LayoutOptions;\n      // Restore user padding if specified (it takes precedence)\n      if (userPadding) {\n        layoutOptions['elk.padding'] = userPadding;\n      }\n    }\n\n    // Ad-hoc subprocess: its children are tasks that may execute in any\n    // order (BPMN semantic). They typically have no sequence flows between\n    // them, so the default `layered` algorithm stacks them in a single\n    // column, which looks wrong. Pack them in a grid instead.\n    if (node.bpmn?.type === 'adHocSubProcess' && node.bpmn?.isExpanded) {\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'rectpacking',\n        'elk.padding': '[top=30,left=12,bottom=12,right=12]',\n        'elk.spacing.nodeNode': 30,\n        'elk.aspectRatio': '2.0',\n      } as LayoutOptions;\n    }\n\n    // Check if this is a collaboration with multiple pools and cross-pool sequence flow edges\n    // Only flatten nodes when there are actual sequenceFlow edges crossing pools\n    // (messageFlow edges are normal for collaborations and don't require flattening)\n    const isCollaboration = node.bpmn?.type === 'collaboration';\n    const hasMultiplePools = isCollaboration &&\n      ((node.children as NodeWithBpmn[] | undefined)?.filter((c) => c.bpmn?.type === 'participant').length ?? 0) > 1;\n\n    // Check if any collaboration-level edges are sequenceFlow (cross-pool flow)\n    const hasCrossPoolSequenceFlows = isCollaboration && node.edges?.some(\n      (edge) => edge.bpmn?.type === 'sequenceFlow' ||\n                edge.bpmn?.type === 'dataInputAssociation' ||\n                edge.bpmn?.type === 'dataOutputAssociation'\n    );\n\n    if (isCollaboration && hasCrossPoolSequenceFlows && hasMultiplePools) {\n      // For collaborations with cross-pool edges, flatten all pool contents\n      // to collaboration level for unified layout\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n        'elk.padding': '[top=12,left=12,bottom=12,right=12]',\n      } as LayoutOptions;\n\n      const elkNode: ElkNode & { bpmn?: NodeWithBpmn['bpmn'] } = {\n        id: node.id,\n        width: node.width,\n        height: node.height,\n        layoutOptions,\n        bpmn: node.bpmn,\n      };\n\n      // Flatten all pool contents to collaboration level\n      const childNodes: ElkNode[] = [];\n      this.extractNodesFromPools(node.children as NodeWithBpmn[], childNodes, boundaryEventTargetIds, mainFlowNodes);\n      elkNode.children = childNodes;\n\n      // Copy edges to ELK format\n      if (node.edges && node.edges.length > 0) {\n        elkNode.edges = this.prepareEdges(node.edges);\n      }\n\n      return elkNode;\n    }\n\n    // Check if this is a pool (participant)\n    const isPool = node.bpmn?.type === 'participant';\n    const hasLanes = isPool &&\n      (node.children as NodeWithBpmn[] | undefined)?.some((c) => c.bpmn?.type === 'lane');\n\n    if (hasLanes) {\n      // For pools with lanes, use a different layout strategy:\n      // - Use partitioning to create horizontal swim lanes (rows, not columns)\n      // - Set direction to RIGHT for flow within lanes\n      // - Use 'elk.partitioning.activate' with vertical partitions\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        // Remove partitioning - we'll handle lane stacking differently\n        'elk.partitioning.activate': 'false',\n        // Add padding for lane header (left side)\n        'elk.padding': '[top=12,left=30,bottom=12,right=12]',\n        'elk.hierarchyHandling': 'INCLUDE_CHILDREN',\n      } as LayoutOptions;\n    } else if (isPool) {\n      // For pools without lanes, still add left padding for pool label\n      layoutOptions = {\n        ...layoutOptions,\n        'elk.algorithm': 'layered',\n        'elk.direction': 'RIGHT',\n        // Add padding for pool header (left side) - 55px to accommodate vertical label\n        'elk.padding': '[top=12,left=55,bottom=12,right=12]',\n      } as LayoutOptions;\n    }\n\n    // Check if this is a lane\n    const isLane = node.bpmn?.type === 'lane';\n    if (isLane) {\n      // For lanes, don't set separate layout algorithm - let parent pool handle layout\n      // Just set padding for content spacing\n      layoutOptions = {\n        'elk.padding': '[top=12,left=12,bottom=12,right=12]',\n      } as LayoutOptions;\n    }\n\n    // For nodes with ioSpecification, increase height for ELK layout to reserve space\n    // Store original height in bpmn metadata for rendering\n    const originalHeight = node.height ?? 80;\n\n    // Events render their label BELOW the icon. ELK doesn't know that, so\n    // two stacked event-only columns get cramped — each event's label\n    // nearly touches the next event's icon. Inflate the ELK-seen height to\n    // reserve the label area; diagram-builder still draws a 36×36 shape via\n    // _visualHeight.\n    let eventLabelExtra = 0;\n    const isEventType = nodeType === 'startEvent' || nodeType === 'endEvent' ||\n      nodeType === 'intermediateThrowEvent' || nodeType === 'intermediateCatchEvent' ||\n      nodeType === 'boundaryEvent';\n    const hasEventLabel = !!(node.bpmn?.name || node.labels?.[0]?.text);\n    if (isEventType && hasEventLabel) {\n      eventLabelExtra = 18; // 4 px gap + ~14 px label line\n    }\n\n    const elkHeight = originalHeight + ioSpecExtraHeight + eventLabelExtra;\n\n    // For gateways with a long label, inflate the ELK-seen width so ELK\n    // spaces neighbors far enough apart that labels don't collide. The\n    // diamond keeps its true visual width; diagram-builder centers it\n    // within the inflated bounds using _visualWidth.\n    const originalWidth = node.width ?? 100;\n    let elkWidth = originalWidth;\n    let visualWidth: number | undefined;\n    if (nodeType?.includes('Gateway')) {\n      const labelText = node.bpmn?.name ?? node.labels?.[0]?.text ?? '';\n      if (labelText) {\n        const labelWidth = this.sizeCalculator.estimateLabelWidth(labelText);\n        const required = labelWidth + 16; // small breathing room\n        if (required > originalWidth) {\n          elkWidth = required;\n          visualWidth = originalWidth;\n        }\n      }\n    }\n\n    const needsVisualHeight = ioSpecExtraHeight > 0 || eventLabelExtra > 0;\n    const bpmnWithVisualHeight = (needsVisualHeight || visualWidth !== undefined)\n      ? {\n          ...node.bpmn,\n          ...(needsVisualHeight ? { _visualHeight: originalHeight } : {}),\n          ...(visualWidth !== undefined ? { _visualWidth: visualWidth } : {}),\n        }\n      : node.bpmn;\n\n    const elkNode: ElkNode & { bpmn?: NodeWithBpmn['bpmn'] } = {\n      id: node.id,\n      width: elkWidth,\n      height: elkHeight,\n      layoutOptions,\n      bpmn: bpmnWithVisualHeight,\n    };\n\n    // Process children (including boundary events as siblings)\n    if (node.children && node.children.length > 0) {\n      const childNodes: ElkNode[] = [];\n\n      // For pools with lanes, flatten all lane contents to pool level for unified layout\n      // This allows ELK to consider cross-lane edges when positioning nodes\n      if (hasLanes) {\n        // Recursively extract all flow nodes from lanes (including nested lanes)\n        this.extractNodesFromLanes(node.children as NodeWithBpmn[], childNodes, boundaryEventTargetIds, mainFlowNodes);\n      } else {\n        // Normal processing for non-lane containers\n        for (const child of node.children) {\n          const childNode = child as NodeWithBpmn;\n          childNodes.push(this.prepareNodeForElk(childNode, boundaryEventTargetIds, mainFlowNodes));\n\n          // Add boundary events as siblings\n          if (childNode.boundaryEvents && childNode.boundaryEvents.length > 0) {\n            for (const be of childNode.boundaryEvents) {\n              childNodes.push({\n                id: be.id,\n                width: be.width ?? 36,\n                height: be.height ?? 36,\n                bpmn: be.bpmn,\n              } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n            }\n          }\n        }\n      }\n      elkNode.children = childNodes;\n    }\n\n    // Process edges\n    if (node.edges && node.edges.length > 0) {\n      elkNode.edges = this.prepareEdges(node.edges);\n    }\n\n    // Process labels - ensure all labels have dimensions (ELK requires this)\n    if (node.labels && node.labels.length > 0) {\n      elkNode.labels = node.labels.map((l) => ({\n        text: l.text,\n        width: l.width ?? this.sizeCalculator.estimateLabelWidth(l.text),\n        height: l.height ?? 14,\n      }));\n    }\n\n    // Process ports\n    if (node.ports && node.ports.length > 0) {\n      elkNode.ports = node.ports.map((p) => ({\n        id: p.id,\n        width: p.width ?? 10,\n        height: p.height ?? 10,\n      }));\n    }\n\n    return elkNode;\n  }\n\n  /**\n   * Prepare edges for ELK format\n   */\n  private prepareEdges(edges: NodeWithBpmn['edges']): ElkExtendedEdge[] {\n    if (!edges) return [];\n\n    return edges.map((edge) => ({\n      id: edge.id,\n      sources: edge.sources,\n      targets: edge.targets,\n      layoutOptions: edge.layoutOptions as LayoutOptions | undefined,\n      labels: edge.labels?.map((l) => ({\n        text: l.text,\n        width: l.width ?? 50,\n        height: l.height ?? 14,\n      })),\n    })) as ElkExtendedEdge[];\n  }\n\n  /**\n   * Extract all flow nodes from pools to flatten them for unified layout\n   * This is used for collaborations with cross-pool edges\n   */\n  private extractNodesFromPools(\n    children: NodeWithBpmn[],\n    result: ElkNode[],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): void {\n    for (const child of children) {\n      if (child.bpmn?.type === 'participant') {\n        // Check if this is an empty/black box pool\n        const isEmpty = !child.children || child.children.length === 0;\n\n        if (isEmpty) {\n          // Add the pool itself as a node (for message flows targeting the pool)\n          result.push({\n            id: child.id,\n            width: child.width ?? 680,\n            height: child.height ?? 60,\n            bpmn: child.bpmn,\n          } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n        } else {\n          // Extract nodes from this pool\n          // Check if pool has lanes\n          const hasLanes = child.children!.some((c) => (c as NodeWithBpmn).bpmn?.type === 'lane');\n          if (hasLanes) {\n            this.extractNodesFromLanes(child.children! as NodeWithBpmn[], result, boundaryEventTargetIds, mainFlowNodes);\n          } else {\n            // Direct children of pool (no lanes)\n            for (const poolChild of child.children!) {\n              const node = poolChild as NodeWithBpmn;\n              result.push(this.prepareNodeForElk(node, boundaryEventTargetIds, mainFlowNodes));\n\n              // Add boundary events as siblings\n              if (node.boundaryEvents && node.boundaryEvents.length > 0) {\n                for (const be of node.boundaryEvents) {\n                  result.push({\n                    id: be.id,\n                    width: be.width ?? 36,\n                    height: be.height ?? 36,\n                    bpmn: be.bpmn,\n                  } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Recursively extract all flow nodes from lanes (including nested lanes)\n   * and add them to the result array for unified ELK layout\n   */\n  private extractNodesFromLanes(\n    children: NodeWithBpmn[],\n    result: ElkNode[],\n    boundaryEventTargetIds: Set<string> = new Set(),\n    mainFlowNodes: Set<string> = new Set()\n  ): void {\n    for (const child of children) {\n      if (child.bpmn?.type === 'lane') {\n        // Recursively extract from nested lanes\n        if (child.children) {\n          this.extractNodesFromLanes(child.children as NodeWithBpmn[], result, boundaryEventTargetIds, mainFlowNodes);\n        }\n      } else {\n        // Non-lane node - add to result\n        result.push(this.prepareNodeForElk(child, boundaryEventTargetIds, mainFlowNodes));\n\n        // Add boundary events as siblings\n        if (child.boundaryEvents && child.boundaryEvents.length > 0) {\n          for (const be of child.boundaryEvents) {\n            result.push({\n              id: be.id,\n              width: be.width ?? 36,\n              height: be.height ?? 36,\n              bpmn: be.bpmn,\n            } as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] });\n          }\n        }\n      }\n    }\n  }\n}\n","/**\n * Result Merger\n * Merges ELK layout results back with original BPMN metadata.\n * Preserves BPMN-specific properties while applying layout coordinates.\n */\n\nimport type { ElkNode, ElkExtendedEdge } from 'elkjs';\nimport type { ElkBpmnGraph, LayoutedGraph } from '../../types';\nimport type { NodeWithBpmn } from '../../types/internal';\nimport { isDebugEnabled } from '../../utils/debug';\n\n/**\n * Handler for merging layout results with original BPMN data\n */\nexport class ResultMerger {\n  /**\n   * Merge ELK layout results back with original BPMN metadata\n   */\n  merge(original: ElkBpmnGraph, layouted: ElkNode): LayoutedGraph {\n    const result: LayoutedGraph = {\n      ...original,\n      x: layouted.x,\n      y: layouted.y,\n      width: layouted.width,\n      height: layouted.height,\n      children: [],\n    };\n\n    // Merge children by ID\n    if (original.children && layouted.children) {\n      const layoutedChildMap = new Map(layouted.children.map((c) => [c.id, c]));\n\n      result.children = original.children.map((origChild) => {\n        const layoutedChild = layoutedChildMap.get(origChild.id);\n        if (layoutedChild) {\n          return this.mergeNodeResults(\n            origChild as unknown as NodeWithBpmn,\n            layoutedChild\n          );\n        }\n        return origChild as unknown as LayoutedGraph['children'][number];\n      }) as LayoutedGraph['children'];\n    }\n\n    return result;\n  }\n\n  /**\n   * Merge a single node's layout results with original BPMN data\n   */\n  private mergeNodeResults(original: NodeWithBpmn, layouted: ElkNode): NodeWithBpmn {\n    // Propagate visual-size hints (set by elk-graph-preparer when ELK is\n    // given an inflated width/height to reserve label/data-object space).\n    // Without these, diagram-builder renders the inflated bounds and shapes\n    // like gateway diamonds stretch into wide flat rectangles.\n    const layoutedBpmn = (layouted as ElkNode & { bpmn?: NodeWithBpmn['bpmn'] }).bpmn;\n    const visualHeight = layoutedBpmn?._visualHeight;\n    const visualWidth = layoutedBpmn?._visualWidth;\n    let mergedBpmn = original.bpmn;\n    if (visualHeight !== undefined || visualWidth !== undefined) {\n      mergedBpmn = { ...original.bpmn };\n      if (visualHeight !== undefined) mergedBpmn._visualHeight = visualHeight;\n      if (visualWidth !== undefined) mergedBpmn._visualWidth = visualWidth;\n    }\n\n    const result: NodeWithBpmn = {\n      ...original,\n      x: layouted.x ?? 0,\n      y: layouted.y ?? 0,\n      width: layouted.width ?? original.width,\n      height: layouted.height ?? original.height,\n      bpmn: mergedBpmn,\n    };\n\n    // Merge children\n    if (original.children && layouted.children) {\n      const layoutedChildMap = new Map(layouted.children.map((c) => [c.id, c]));\n\n      result.children = original.children.map((origChild) => {\n        const layoutedChild = layoutedChildMap.get((origChild as NodeWithBpmn).id);\n        if (layoutedChild) {\n          return this.mergeNodeResults(origChild as NodeWithBpmn, layoutedChild);\n        }\n        return origChild;\n      });\n    }\n\n    // Keep boundary events as-is (their positions are calculated in model-builder.ts)\n    if (original.boundaryEvents) {\n      result.boundaryEvents = original.boundaryEvents;\n    }\n\n    // Merge edges\n    if (original.edges && layouted.edges) {\n      result.edges = this.mergeEdges(original.edges, layouted.edges);\n    }\n\n    // Merge labels\n    if (original.labels && layouted.labels) {\n      result.labels = original.labels.map((label, idx) => {\n        const layoutedLabel = layouted.labels?.[idx];\n        if (layoutedLabel) {\n          return {\n            ...label,\n            x: layoutedLabel.x ?? 0,\n            y: layoutedLabel.y ?? 0,\n            width: layoutedLabel.width ?? label.width,\n            height: layoutedLabel.height ?? label.height,\n          };\n        }\n        return label;\n      });\n    }\n\n    return result;\n  }\n\n  /**\n   * Merge edge layout results\n   */\n  private mergeEdges(\n    originalEdges: NodeWithBpmn['edges'],\n    layoutedEdges: ElkExtendedEdge[]\n  ): NodeWithBpmn['edges'] {\n    if (!originalEdges) return undefined;\n\n    const layoutedEdgeMap = new Map(layoutedEdges.map((e) => [e.id, e]));\n\n    return originalEdges.map((origEdge) => {\n      const layoutedEdge = layoutedEdgeMap.get(origEdge.id);\n      if (layoutedEdge) {\n        if (isDebugEnabled() && layoutedEdge.sections?.[0]?.bendPoints?.length) {\n          console.log(`[BPMN] Merge ${origEdge.id}: bendPoints=${JSON.stringify(layoutedEdge.sections[0].bendPoints)}`);\n        }\n\n        const mergedEdge: typeof origEdge & { _absoluteCoords?: boolean; _poolRelativeCoords?: boolean } = {\n          ...origEdge,\n          sections: layoutedEdge.sections ?? [],\n          labels: origEdge.labels?.map((label, idx) => {\n            const layoutedLabel = layoutedEdge.labels?.[idx];\n            if (layoutedLabel) {\n              return {\n                ...label,\n                x: layoutedLabel.x ?? 0,\n                y: layoutedLabel.y ?? 0,\n                width: layoutedLabel.width ?? label.width ?? 50,\n                height: layoutedLabel.height ?? label.height ?? 14,\n              };\n            }\n            return label;\n          }),\n        };\n\n        // Preserve the _absoluteCoords flag for message flows\n        if ((layoutedEdge as { _absoluteCoords?: boolean })._absoluteCoords) {\n          mergedEdge._absoluteCoords = true;\n        }\n\n        // Preserve the _poolRelativeCoords flag for pool edges\n        if ((layoutedEdge as { _poolRelativeCoords?: boolean })._poolRelativeCoords) {\n          mergedEdge._poolRelativeCoords = true;\n        }\n\n        return mergedEdge;\n      }\n      return origEdge;\n    });\n  }\n}\n","/**\n * Reference Resolver\n * Builds incoming/outgoing references for BPMN flow nodes\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\n\ninterface EdgeInfo {\n  id: string;\n  sourceRef: string;\n  targetRef: string;\n  type: 'sequenceFlow' | 'messageFlow' | 'dataInputAssociation' | 'dataOutputAssociation' | 'association';\n}\n\ninterface NodeInfo {\n  id: string;\n  type: string;\n  parentId?: string;\n}\n\nexport class ReferenceResolver {\n  private nodeMap: Map<string, NodeInfo> = new Map();\n  private edgesBySource: Map<string, EdgeInfo[]> = new Map();\n  private edgesByTarget: Map<string, EdgeInfo[]> = new Map();\n  private allEdges: EdgeInfo[] = [];\n\n  /**\n   * Resolve all references in the graph\n   */\n  resolve(graph: LayoutedGraph): void {\n    this.clear();\n    this.indexGraph(graph);\n  }\n\n  /**\n   * Clear all cached data\n   */\n  clear(): void {\n    this.nodeMap.clear();\n    this.edgesBySource.clear();\n    this.edgesByTarget.clear();\n    this.allEdges = [];\n  }\n\n  /**\n   * Get incoming edge IDs for a node\n   */\n  getIncoming(nodeId: string): string[] {\n    const edges = this.edgesByTarget.get(nodeId);\n    return edges?.map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get outgoing edge IDs for a node\n   */\n  getOutgoing(nodeId: string): string[] {\n    const edges = this.edgesBySource.get(nodeId);\n    return edges?.map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get incoming sequence flows for a node\n   */\n  getIncomingSequenceFlows(nodeId: string): string[] {\n    const edges = this.edgesByTarget.get(nodeId);\n    return edges?.filter((e) => e.type === 'sequenceFlow').map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get outgoing sequence flows for a node\n   */\n  getOutgoingSequenceFlows(nodeId: string): string[] {\n    const edges = this.edgesBySource.get(nodeId);\n    return edges?.filter((e) => e.type === 'sequenceFlow').map((e) => e.id) ?? [];\n  }\n\n  /**\n   * Get all edges\n   */\n  getAllEdges(): EdgeInfo[] {\n    return this.allEdges;\n  }\n\n  /**\n   * Get node by ID\n   */\n  getNode(nodeId: string): NodeInfo | undefined {\n    return this.nodeMap.get(nodeId);\n  }\n\n  /**\n   * Get all nodes\n   */\n  getAllNodes(): Map<string, NodeInfo> {\n    return this.nodeMap;\n  }\n\n  /**\n   * Check if a node exists\n   */\n  hasNode(nodeId: string): boolean {\n    return this.nodeMap.has(nodeId);\n  }\n\n  /**\n   * Index the entire graph\n   */\n  private indexGraph(graph: LayoutedGraph): void {\n    for (const child of graph.children) {\n      this.indexNode(child as unknown as GraphNode);\n    }\n  }\n\n  /**\n   * Recursively index a node and its children\n   */\n  private indexNode(node: GraphNode, parentId?: string): void {\n    // Index the node itself (skip containers like collaboration)\n    if (node.bpmn && node.bpmn.type !== 'collaboration') {\n      this.nodeMap.set(node.id, {\n        id: node.id,\n        type: node.bpmn.type,\n        parentId,\n      });\n    }\n\n    // Index children\n    if (node.children) {\n      for (const child of node.children) {\n        this.indexNode(child as GraphNode, node.id);\n      }\n    }\n\n    // Index boundary events\n    if (node.boundaryEvents) {\n      for (const be of node.boundaryEvents) {\n        this.nodeMap.set(be.id, {\n          id: be.id,\n          type: 'boundaryEvent',\n          parentId: node.id,\n        });\n      }\n    }\n\n    // Index edges\n    if (node.edges) {\n      for (const edge of node.edges) {\n        this.indexEdge(edge);\n      }\n    }\n  }\n\n  /**\n   * Index an edge\n   */\n  private indexEdge(edge: GraphEdge): void {\n    const sourceRef = edge.sources[0];\n    const targetRef = edge.targets[0];\n\n    if (!sourceRef || !targetRef) return;\n\n    const edgeType = edge.bpmn?.type;\n    const validTypes = ['sequenceFlow', 'messageFlow', 'dataInputAssociation', 'dataOutputAssociation', 'association'] as const;\n    const edgeInfo: EdgeInfo = {\n      id: edge.id,\n      sourceRef,\n      targetRef,\n      type: (validTypes.includes(edgeType as typeof validTypes[number]) ? edgeType : 'sequenceFlow') as EdgeInfo['type'],\n    };\n\n    this.allEdges.push(edgeInfo);\n\n    // Index by source\n    if (!this.edgesBySource.has(sourceRef)) {\n      this.edgesBySource.set(sourceRef, []);\n    }\n    this.edgesBySource.get(sourceRef)!.push(edgeInfo);\n\n    // Index by target\n    if (!this.edgesByTarget.has(targetRef)) {\n      this.edgesByTarget.set(targetRef, []);\n    }\n    this.edgesByTarget.get(targetRef)!.push(edgeInfo);\n  }\n}\n\n// Internal types\ninterface GraphNode {\n  id: string;\n  bpmn?: { type: string };\n  children?: GraphNode[];\n  edges?: GraphEdge[];\n  boundaryEvents?: Array<{ id: string; bpmn: { type: string } }>;\n}\n\ninterface GraphEdge {\n  id: string;\n  sources: string[];\n  targets: string[];\n  bpmn?: { type: string };\n}\n","/**\n * Lane Resolver\n * Builds flowNodeRef arrays for BPMN lanes\n */\n\nexport interface LaneInfo {\n  id: string;\n  name?: string;\n  flowNodeRefs: string[];\n  childLaneSet?: LaneSetInfo;\n}\n\nexport interface LaneSetInfo {\n  id: string;\n  lanes: LaneInfo[];\n}\n\nexport class LaneResolver {\n  private laneIdCounter = 0;\n\n  /**\n   * Resolve lanes from a participant or process\n   */\n  resolve(container: ContainerNode): LaneSetInfo | undefined {\n    const lanes = this.findLanes(container.children);\n\n    if (lanes.length === 0) {\n      return undefined;\n    }\n\n    return {\n      id: this.generateLaneSetId(),\n      lanes: lanes.map((lane) => this.processLane(lane)),\n    };\n  }\n\n  /**\n   * Find all lanes in children\n   */\n  private findLanes(children?: ChildNode[]): LaneNode[] {\n    if (!children) return [];\n    return children.filter((c): c is LaneNode => c.bpmn?.type === 'lane');\n  }\n\n  /**\n   * Process a lane and collect all flow node refs\n   */\n  private processLane(lane: LaneNode): LaneInfo {\n    const flowNodeRefs = this.collectFlowNodeRefs(lane.children);\n    const nestedLanes = this.findLanes(lane.children);\n\n    const result: LaneInfo = {\n      id: lane.id,\n      name: lane.bpmn?.name,\n      flowNodeRefs,\n    };\n\n    // Handle nested lanes\n    if (nestedLanes.length > 0) {\n      result.childLaneSet = {\n        id: this.generateLaneSetId(),\n        lanes: nestedLanes.map((l) => this.processLane(l)),\n      };\n    }\n\n    return result;\n  }\n\n  /**\n   * Collect all flow node IDs within a lane (excluding nested lanes)\n   */\n  private collectFlowNodeRefs(children?: ChildNode[]): string[] {\n    if (!children) return [];\n\n    const refs: string[] = [];\n\n    for (const child of children) {\n      // Skip lanes - their content belongs to them\n      if (child.bpmn?.type === 'lane') {\n        continue;\n      }\n\n      // Add this node's ID\n      refs.push(child.id);\n\n      // For subprocesses, don't traverse children - they're internal\n      // Boundary events are still part of the lane though\n      if (child.boundaryEvents) {\n        for (const be of child.boundaryEvents) {\n          refs.push(be.id);\n        }\n      }\n    }\n\n    return refs;\n  }\n\n  /**\n   * Generate a unique lane set ID\n   */\n  private generateLaneSetId(): string {\n    return `LaneSet_${++this.laneIdCounter}`;\n  }\n\n  /**\n   * Reset the ID counter\n   */\n  reset(): void {\n    this.laneIdCounter = 0;\n  }\n}\n\n// Internal types\ninterface ChildNode {\n  id: string;\n  bpmn?: { type: string; name?: string };\n  children?: ChildNode[];\n  boundaryEvents?: Array<{ id: string }>;\n}\n\ninterface LaneNode extends ChildNode {\n  bpmn: { type: 'lane'; name?: string };\n}\n\ninterface ContainerNode {\n  id: string;\n  children?: ChildNode[];\n}\n","/**\n * Diagram Builder\n * Handles building the visual diagram (shapes and edges) from a layouted graph.\n * This module is responsible for converting layouted node positions into\n * BPMN DI (Diagram Interchange) format.\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\nimport type { IoSpecification } from '../types/elk-bpmn';\nimport { SUBPROCESS_TYPES } from '../types/bpmn-constants';\nimport type {\n  DiagramModel,\n  ShapeModel,\n  EdgeModel,\n  PointModel,\n  DefinitionsModel,\n  LayoutedNode,\n  LayoutedEdge,\n  NodePosition,\n  NodeOffset,\n  NodeBpmnInfo,\n} from './model-types';\nimport { isDebugEnabled } from '../utils/debug';\nimport {\n  adjustGatewayEndpoint,\n  distance,\n  calculatePathLength,\n} from '../layout/edge-routing';\n\n// ============================================================================\n// Diagram Builder\n// ============================================================================\n\nexport class DiagramBuilder {\n  // Map to track boundary event positions: id -> { x, y, width, height }\n  private boundaryEventPositions: Map<string, NodePosition> = new Map();\n  // Map to track all node positions for edge routing: id -> { x, y, width, height }\n  private nodePositions: Map<string, NodePosition> = new Map();\n  // Map to track the offset used for each node (for edge coordinate transformation)\n  private nodeOffsets: Map<string, NodeOffset> = new Map();\n  // Map to track node BPMN metadata for gateway detection\n  private nodeBpmn: Map<string, NodeBpmnInfo> = new Map();\n  // ioSpecification data objects: dataObjectId -> owner task id. Used so we\n  // know which data shapes belong to which task when routing edges, since data\n  // objects synthesized for a task should NOT be treated as obstacles for\n  // edges whose source/target is that same task.\n  private dataObjectOwners: Map<string, string> = new Map();\n  // List of already placed edge labels for collision detection\n  private placedEdgeLabels: Array<{ x: number; y: number; width: number; height: number }> = [];\n\n  /**\n   * Build the diagram model from a layouted graph\n   */\n  build(graph: LayoutedGraph, definitions: DefinitionsModel): DiagramModel {\n    // Reset placed edge labels for each build\n    this.placedEdgeLabels = [];\n    // Reset all maps\n    this.boundaryEventPositions.clear();\n    this.nodePositions.clear();\n    this.nodeOffsets.clear();\n    this.dataObjectOwners.clear();\n    this.nodeBpmn.clear();\n\n    const shapes: ShapeModel[] = [];\n    const edges: EdgeModel[] = [];\n\n    // Find the main bpmn element for the plane\n    const mainElement = definitions.rootElements[0];\n    if (!mainElement) {\n      throw new Error('Cannot create BPMN diagram: definitions.rootElements is empty. The graph must contain at least one process or collaboration.');\n    }\n    const planeElement = mainElement.type === 'collaboration' ? mainElement.id : mainElement.id;\n\n    // Build shapes and edges\n    for (const child of graph.children) {\n      this.collectShapesAndEdges(child as LayoutedNode, shapes, edges);\n    }\n\n    return {\n      id: `BPMNDiagram_${graph.id}`,\n      name: 'BPMNDiagram',\n      plane: {\n        id: `BPMNPlane_${graph.id}`,\n        bpmnElement: planeElement,\n        shapes,\n        edges,\n      },\n    };\n  }\n\n  /**\n   * Get stored node positions (for external access if needed)\n   */\n  getNodePositions(): Map<string, NodePosition> {\n    return this.nodePositions;\n  }\n\n  /**\n   * Collect shapes and edges recursively\n   * @param offsetX - Parent container's absolute X offset\n   * @param offsetY - Parent container's absolute Y offset\n   * @param insideParticipant - Whether we are inside a participant container\n   */\n  private collectShapesAndEdges(\n    node: LayoutedNode,\n    shapes: ShapeModel[],\n    edges: EdgeModel[],\n    offsetX: number = 0,\n    offsetY: number = 0,\n    insideParticipant: boolean = false\n  ): void {\n    // Add shape for this node (if it has coordinates)\n    if (node.x !== undefined && node.y !== undefined) {\n      const absoluteX = offsetX + node.x;\n      const absoluteY = offsetY + node.y;\n      const elkWidth = node.width ?? 100;\n      // Use visual dimensions when ELK was given an inflated size to reserve\n      // label or data-object space (ioSpecification, long gateway label).\n      const bpmnAny = node.bpmn as { _visualHeight?: number; _visualWidth?: number } | undefined;\n      const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 80;\n      const visualWidth = bpmnAny?._visualWidth ?? elkWidth;\n      // The visual shape is centered horizontally inside the inflated ELK bounds.\n      const visualX = absoluteX + (elkWidth - visualWidth) / 2;\n\n      // Store node position for edge routing\n      // For events, include the label area below the node in the bounds\n      // to help edge labels avoid overlapping with node labels\n      let effectiveHeight = nodeHeight;\n      if (this.isEventType(node.bpmn?.type) && node.labels && node.labels.length > 0) {\n        // Events have labels below them - extend the effective height\n        const labelHeight = node.labels[0]?.height ?? 14;\n        effectiveHeight = nodeHeight + 4 + labelHeight; // 4px gap + label height\n      }\n\n      // Store visualHeight when node has ioSpecification (ELK layout uses larger height for spacing)\n      // This is used by buildEdge to adjust edge endpoints to connect to the visual node border\n      const nodePosition: NodePosition = {\n        x: visualX,\n        y: absoluteY,\n        width: visualWidth,\n        height: effectiveHeight,\n      };\n      if (bpmnAny?._visualHeight !== undefined) {\n        nodePosition.visualHeight = bpmnAny._visualHeight;\n      }\n      this.nodePositions.set(node.id, nodePosition);\n\n      // Store node BPMN metadata for gateway detection\n      if (node.bpmn) {\n        this.storeNodeBpmn(node.id, { type: node.bpmn.type, isExpanded: node.bpmn.isExpanded });\n      }\n\n      // Store the offset used for this node (needed for edge coordinate transformation)\n      this.nodeOffsets.set(node.id, { x: offsetX, y: offsetY });\n\n      shapes.push(this.buildShape(node, offsetX, offsetY));\n\n      // Process ioSpecification dataInput/dataOutput shapes for tasks/activities only\n      // These are visual representations of task inputs/outputs positioned around the task\n      // Skip for process-level ioSpecification (process type should not have visual data shapes)\n      const nodeType = node.bpmn?.type;\n      const isTaskOrActivity = nodeType && (\n        nodeType.includes('Task') ||\n        nodeType === 'task' ||\n        nodeType === 'callActivity' ||\n        nodeType === 'subProcess' ||\n        nodeType === 'transaction' ||\n        nodeType === 'adHocSubProcess'\n      );\n\n      if (isTaskOrActivity) {\n        const ioSpec = (node.bpmn as { ioSpecification?: IoSpecification } | undefined)?.ioSpecification;\n        if (ioSpec) {\n          this.buildIoSpecificationShapes(node, ioSpec, shapes, edges, absoluteX, absoluteY, elkWidth, nodeHeight);\n        }\n      }\n    }\n\n    // Calculate offset for children\n    // Containers that offset their children: pools (participants), lanes, and expanded subprocesses\n    const isExpandedSubprocess = node.bpmn?.isExpanded === true &&\n      (node.bpmn?.type === 'subProcess' || node.bpmn?.type === 'transaction' ||\n       node.bpmn?.type === 'adHocSubProcess' || node.bpmn?.type === 'eventSubProcess' ||\n       (node.bpmn as { triggeredByEvent?: boolean })?.triggeredByEvent === true);\n\n    const isPoolOrLane = node.bpmn?.type === 'participant' || node.bpmn?.type === 'lane';\n\n    // Process nested inside participant also acts as a container for coordinate offsets\n    const isNestedProcess = node.bpmn?.type === 'process' && insideParticipant;\n\n    const isContainer = isExpandedSubprocess || isPoolOrLane || isNestedProcess;\n\n    const childOffsetX = isContainer ? offsetX + (node.x ?? 0) : offsetX;\n    const childOffsetY = isContainer ? offsetY + (node.y ?? 0) : offsetY;\n\n    // Track if we're entering a participant\n    const childInsideParticipant = insideParticipant || node.bpmn?.type === 'participant';\n\n    // Process children\n    if (node.children) {\n      for (const child of node.children) {\n        this.collectShapesAndEdges(child as LayoutedNode, shapes, edges, childOffsetX, childOffsetY, childInsideParticipant);\n      }\n    }\n\n    // Process boundary events - position them on the bottom edge of the task\n    if (node.boundaryEvents) {\n      const nodeX = offsetX + (node.x ?? 0);\n      const nodeY = offsetY + (node.y ?? 0);\n      const nodeWidth = node.width ?? 100;\n      const nodeHeight = node.height ?? 80;\n      const beCount = node.boundaryEvents.length;\n\n      node.boundaryEvents.forEach((be, index) => {\n        const beWidth = be.width ?? 36;\n        const beHeight = be.height ?? 36;\n\n        // Calculate position on the bottom edge of the task\n        // Distribute multiple boundary events evenly along the bottom\n        const spacing = nodeWidth / (beCount + 1);\n        const beX = nodeX + spacing * (index + 1) - beWidth / 2;\n        const beY = nodeY + nodeHeight - beHeight / 2; // Half inside, half outside\n\n        // Store boundary event position for edge routing\n        this.boundaryEventPositions.set(be.id, {\n          x: beX,\n          y: beY,\n          width: beWidth,\n          height: beHeight,\n        });\n\n        // When several boundary events share the same parent task, bpmn.io's\n        // default label position (centered below the event) leaves all their\n        // labels piled on top of each other because the events themselves are\n        // packed tighter than the label widths. Stagger label Y by index so the\n        // labels stack vertically instead of overlapping side-by-side.\n        const labelText = be.bpmn?.name ?? '';\n        const labelHeight = 14;\n        // ~12px per CJK char, 7px per ASCII char; padding 6.\n        let estimatedTextWidth = 6;\n        for (const ch of labelText) {\n          estimatedTextWidth += /[一-鿿]/.test(ch) ? 12 : 7;\n        }\n        if (estimatedTextWidth < 24) estimatedTextWidth = 24;\n        const labelX = beX + beWidth / 2 - estimatedTextWidth / 2;\n        const labelY = beY + beHeight + 4 + (beCount > 1 ? index * (labelHeight + 2) : 0);\n\n        shapes.push({\n          id: `${be.id}_di`,\n          bpmnElement: be.id,\n          bounds: {\n            x: beX,\n            y: beY,\n            width: beWidth,\n            height: beHeight,\n          },\n          label: labelText\n            ? {\n                bounds: {\n                  x: labelX,\n                  y: labelY,\n                  width: estimatedTextWidth,\n                  height: labelHeight,\n                },\n              }\n            : undefined,\n        });\n      });\n    }\n\n    // Process edges\n    // Edge waypoints from ELK are relative to the source node's parent container,\n    // not necessarily the edge's container. We use the source node's stored offset.\n    if (node.edges) {\n      for (const edge of node.edges) {\n        if (edge.sections && edge.sections.length > 0) {\n          // Check if edge has absolute coordinates (set by rearrangePools for message flows)\n          const hasAbsoluteCoords = (edge as { _absoluteCoords?: boolean })._absoluteCoords === true;\n          // Check if edge has pool-relative coordinates (set by recalculatePoolEdges for pool edges with lanes)\n          const hasPoolRelativeCoords = (edge as { _poolRelativeCoords?: boolean })._poolRelativeCoords === true;\n\n          if (hasAbsoluteCoords) {\n            // Edge already has absolute coordinates - don't add offset\n            edges.push(this.buildEdge(edge, 0, 0));\n          } else if (hasPoolRelativeCoords) {\n            // Edge waypoints are relative to pool (already include lane offsets within pool)\n            // Use container's offset (pool's offset), not source node's offset\n            edges.push(this.buildEdge(edge, offsetX + (node.x ?? 0), offsetY + (node.y ?? 0)));\n          } else {\n            const sourceId = edge.sources?.[0];\n            // Use the source node's offset if available, otherwise fall back to childOffset\n            const sourceOffset = sourceId ? this.nodeOffsets.get(sourceId) : undefined;\n            const edgeOffsetX = sourceOffset?.x ?? childOffsetX;\n            const edgeOffsetY = sourceOffset?.y ?? childOffsetY;\n            edges.push(this.buildEdge(edge, edgeOffsetX, edgeOffsetY));\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Check if a node type is an event type\n   */\n  private isEventType(type?: string): boolean {\n    if (!type) return false;\n    return type.includes('Event') || type === 'startEvent' || type === 'endEvent' ||\n           type === 'intermediateThrowEvent' || type === 'intermediateCatchEvent';\n  }\n\n  /**\n   * Check if a node type is a gateway type\n   */\n  private isGatewayType(type?: string): boolean {\n    if (!type) return false;\n    return type.includes('Gateway');\n  }\n\n  /**\n   * Store node BPMN metadata for later gateway detection\n   */\n  private storeNodeBpmn(nodeId: string, bpmn: NodeBpmnInfo): void {\n    this.nodeBpmn.set(nodeId, bpmn);\n  }\n\n  /**\n   * Build shapes for ioSpecification dataInputs and dataOutputs\n   * Positions: dataInputs below-left of the task (stacked vertically),\n   *            dataOutputs below-right of the task (stacked vertically)\n   * Only the topmost item in each stack has a dashed association edge to the task\n   */\n  private buildIoSpecificationShapes(\n    node: LayoutedNode,\n    ioSpec: IoSpecification,\n    shapes: ShapeModel[],\n    edges: EdgeModel[],\n    taskX: number,\n    taskY: number,\n    taskWidth: number,\n    taskHeight: number\n  ): void {\n    // Data object dimensions (same as dataObjectReference)\n    const dataWidth = 36;\n    const dataHeight = 50;\n    const gapBelow = 20; // Gap between task and first data object (vertical)\n    const verticalSpacing = 24; // Spacing between stacked data objects (includes label space)\n    const labelHeight = 14;\n\n    // Position dataInputs below the task, aligned to the left side, stacked vertically\n    const dataInputs = ioSpec.dataInputs ?? [];\n    const inputStartX = taskX; // Start from task's left edge\n\n    dataInputs.forEach((dataInput, index) => {\n      const inputId = dataInput.id ?? `${node.id}_input_${index}`;\n      const inputX = inputStartX;\n      const inputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);\n\n      this.dataObjectOwners.set(inputId, node.id);\n\n      // Store position for edge routing\n      this.nodePositions.set(inputId, {\n        x: inputX,\n        y: inputY,\n        width: dataWidth,\n        height: dataHeight,\n      });\n\n      const shape: ShapeModel = {\n        id: `${inputId}_di`,\n        bpmnElement: inputId,\n        bounds: {\n          x: inputX,\n          y: inputY,\n          width: dataWidth,\n          height: dataHeight,\n        },\n      };\n\n      // Add label below the data object\n      if (dataInput.name) {\n        const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataInput.name));\n        shape.label = {\n          bounds: {\n            x: inputX + (dataWidth - labelWidth) / 2,\n            y: inputY + dataHeight + 4,\n            width: labelWidth,\n            height: labelHeight,\n          },\n        };\n      }\n\n      shapes.push(shape);\n\n      // Only the first (topmost) dataInput gets an edge to the task\n      if (index === 0) {\n        // Create dashed edge from dataInput to task (arrow pointing to task)\n        // bpmnElement references the auto-generated dataInputAssociation\n        const assocId = `${inputId}_assoc`;\n        const inputCenterX = inputX + dataWidth / 2;\n        const inputTopY = inputY;\n        const taskBottomY = taskY + taskHeight;\n\n        // Simple vertical connection from data object top to task bottom\n        edges.push({\n          id: `${assocId}_di`,\n          bpmnElement: assocId,\n          waypoints: [\n            { x: inputCenterX, y: inputTopY },\n            { x: inputCenterX, y: taskBottomY },\n          ],\n        });\n      }\n    });\n\n    // Position dataOutputs below the task, aligned to the right side, stacked vertically\n    const dataOutputs = ioSpec.dataOutputs ?? [];\n    const outputStartX = taskX + taskWidth - dataWidth; // Align to right edge\n\n    dataOutputs.forEach((dataOutput, index) => {\n      const outputId = dataOutput.id ?? `${node.id}_output_${index}`;\n      const outputX = outputStartX;\n      const outputY = taskY + taskHeight + gapBelow + index * (dataHeight + verticalSpacing);\n\n      this.dataObjectOwners.set(outputId, node.id);\n\n      // Store position for edge routing\n      this.nodePositions.set(outputId, {\n        x: outputX,\n        y: outputY,\n        width: dataWidth,\n        height: dataHeight,\n      });\n\n      const shape: ShapeModel = {\n        id: `${outputId}_di`,\n        bpmnElement: outputId,\n        bounds: {\n          x: outputX,\n          y: outputY,\n          width: dataWidth,\n          height: dataHeight,\n        },\n      };\n\n      // Add label below the data object\n      if (dataOutput.name) {\n        const labelWidth = Math.max(dataWidth, this.estimateTextWidth(dataOutput.name));\n        shape.label = {\n          bounds: {\n            x: outputX + (dataWidth - labelWidth) / 2,\n            y: outputY + dataHeight + 4,\n            width: labelWidth,\n            height: labelHeight,\n          },\n        };\n      }\n\n      shapes.push(shape);\n\n      // Only the first (topmost) dataOutput gets an edge from the task\n      if (index === 0) {\n        // Create dashed edge from task to dataOutput (arrow pointing to dataOutput)\n        // bpmnElement references the auto-generated dataOutputAssociation\n        const assocId = `${outputId}_assoc`;\n        const outputCenterX = outputX + dataWidth / 2;\n        const outputTopY = outputY;\n        const taskBottomY = taskY + taskHeight;\n\n        // Simple vertical connection from task bottom to data object top\n        edges.push({\n          id: `${assocId}_di`,\n          bpmnElement: assocId,\n          waypoints: [\n            { x: outputCenterX, y: taskBottomY },\n            { x: outputCenterX, y: outputTopY },\n          ],\n        });\n      }\n    });\n  }\n\n  /**\n   * Estimate text width for label sizing (simplified)\n   */\n  private estimateTextWidth(text: string): number {\n    let width = 0;\n    for (const char of text) {\n      // CJK characters are wider\n      if (char.charCodeAt(0) > 255) {\n        width += 14;\n      } else {\n        width += 7;\n      }\n    }\n    return Math.max(36, Math.min(width, 150));\n  }\n\n  /**\n   * Find node BPMN metadata by id\n   */\n  private findNodeBpmn(nodeId: string): NodeBpmnInfo | undefined {\n    return this.nodeBpmn.get(nodeId);\n  }\n\n  /**\n   * Estimate number of lines needed for a label based on text and width\n   * Uses approximate character width of 14px for CJK and 7px for ASCII\n   */\n  private estimateLabelLines(text: string, maxWidth: number): number {\n    if (!text || maxWidth <= 0) return 1;\n\n    let currentLineWidth = 0;\n    let lines = 1;\n\n    for (const char of text) {\n      // CJK characters are wider\n      const charWidth = char.charCodeAt(0) > 255 ? 14 : 7;\n\n      if (currentLineWidth + charWidth > maxWidth) {\n        lines++;\n        currentLineWidth = charWidth;\n      } else {\n        currentLineWidth += charWidth;\n      }\n    }\n\n    return lines;\n  }\n\n  /**\n   * Build a shape model\n   */\n  private buildShape(node: LayoutedNode, offsetX: number = 0, offsetY: number = 0): ShapeModel {\n    const absoluteX = offsetX + (node.x ?? 0);\n    const absoluteY = offsetY + (node.y ?? 0);\n    // Use visual dimensions when ELK was given an inflated size to reserve\n    // label or data-object space (ioSpecification, long gateway label).\n    const bpmnAny = node.bpmn as { _visualHeight?: number; _visualWidth?: number } | undefined;\n    const elkWidth = node.width ?? 100;\n    const visualHeight = bpmnAny?._visualHeight ?? node.height ?? 80;\n    const visualWidth = bpmnAny?._visualWidth ?? elkWidth;\n    // Center the shape horizontally inside the inflated ELK width.\n    const xCentered = absoluteX + (elkWidth - visualWidth) / 2;\n\n    const shape: ShapeModel = {\n      id: `${node.id}_di`,\n      bpmnElement: node.id,\n      bounds: {\n        x: xCentered,\n        y: absoluteY,\n        width: visualWidth,\n        height: visualHeight,\n      },\n    };\n\n    // Add isExpanded for subprocesses\n    if (node.bpmn?.isExpanded !== undefined) {\n      shape.isExpanded = node.bpmn.isExpanded;\n    }\n\n    // Add isHorizontal for pools/lanes\n    if (node.bpmn?.type === 'participant' || node.bpmn?.type === 'lane') {\n      shape.isHorizontal = true;\n    }\n\n    // Add label positioning for elements that need external labels\n    // Priority: use explicit labels data if present, otherwise generate from bpmn.name\n    const nodeWidth = node.width ?? 36;\n    const nodeHeight = bpmnAny?._visualHeight ?? node.height ?? 36;\n    const label = node.labels?.[0];\n    const labelText = node.bpmn?.name ?? label?.text ?? '';\n\n    if (this.isEventType(node.bpmn?.type) && labelText) {\n      // For events (circles), position the label below the shape (bpmn-js default behavior)\n      const labelWidth = label?.width ?? 100;\n      const labelHeight = label?.height ?? 14;\n\n      // Position label below the event circle, horizontally centered (using absolute coords)\n      shape.label = {\n        bounds: {\n          x: absoluteX + (nodeWidth - labelWidth) / 2,\n          y: absoluteY + nodeHeight + 4, // 4px gap below the circle\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    } else if (this.isGatewayType(node.bpmn?.type) && labelText) {\n      // For gateways (diamonds), position the label above the shape to avoid overlap with nodes below\n      const labelWidth = label?.width ?? 100;\n      // Calculate label height based on text content (may need multiple lines)\n      const estimatedLines = this.estimateLabelLines(labelText, labelWidth);\n      const labelHeight = estimatedLines * 14; // 14px per line\n\n      // Position label above the gateway diamond, horizontally centered\n      // Adjust Y position upward based on label height\n      shape.label = {\n        bounds: {\n          x: absoluteX + (nodeWidth - labelWidth) / 2,\n          y: absoluteY - labelHeight - 4, // 4px gap above the diamond\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    } else if (label?.x !== undefined && label?.y !== undefined) {\n      // For other elements with explicit label positioning, use ELK-calculated position\n      shape.label = {\n        bounds: {\n          x: absoluteX + label.x,\n          y: absoluteY + label.y,\n          width: label?.width ?? 100,\n          height: label?.height ?? 20,\n        },\n      };\n    }\n\n    return shape;\n  }\n\n  /**\n   * Build an edge model\n   */\n  private buildEdge(edge: LayoutedEdge, offsetX: number = 0, offsetY: number = 0): EdgeModel {\n    const sourceId = edge.sources?.[0];\n    const targetId = edge.targets?.[0];\n\n    // Check if source is a boundary event\n    const bePosition = sourceId ? this.boundaryEventPositions.get(sourceId) : undefined;\n    const targetPosition = targetId ? this.nodePositions.get(targetId) : undefined;\n\n    // Check if source or target is a gateway (for diamond shape adjustment)\n    const sourceNode = sourceId ? this.findNodeBpmn(sourceId) : undefined;\n    const targetNode = targetId ? this.findNodeBpmn(targetId) : undefined;\n    const sourceIsGateway = this.isGatewayType(sourceNode?.type);\n    const targetIsGateway = this.isGatewayType(targetNode?.type);\n\n    let waypoints: PointModel[] = [];\n\n    // Check if edge has pre-calculated sections with bendPoints (from obstacle avoidance)\n    const hasPreCalculatedSections = edge.sections &&\n      edge.sections.length > 0 &&\n      edge.sections[0]?.bendPoints &&\n      edge.sections[0].bendPoints.length > 0;\n\n    if (isDebugEnabled() && bePosition) {\n      console.log(`[BPMN] buildEdge ${edge.id}: preCalculated=${hasPreCalculatedSections}`);\n    }\n\n    // Boundary-event edges: always reroute from the diagram-builder's recomputed\n    // boundary position. ELK's sections are based on positions before\n    // boundary/mover post-processing, so reusing them leaves the endpoint\n    // floating outside the actual target (e.g. 17-subprocess-transaction's\n    // cancel edge landing past task_cancel_handler).\n    if (bePosition && targetPosition) {\n      // Source is a boundary event without pre-calculated routing - calculate simple waypoints\n      // Start from bottom center of boundary event\n      const startX = bePosition.x + bePosition.width / 2;\n      const startY = bePosition.y + bePosition.height;\n\n      // End at left center of target (or top center if target is below)\n      let endX: number;\n      let endY: number;\n\n      // Determine connection point based on relative position\n      if (targetPosition.y > bePosition.y + bePosition.height) {\n        // Target is below - connect to top center\n        endX = targetPosition.x + targetPosition.width / 2;\n        endY = targetPosition.y;\n      } else if (targetPosition.x > bePosition.x + bePosition.width) {\n        // Target is to the right - connect to left center\n        endX = targetPosition.x;\n        endY = targetPosition.y + targetPosition.height / 2;\n      } else if (targetPosition.x + targetPosition.width < bePosition.x) {\n        // Target is to the left - connect to right center\n        endX = targetPosition.x + targetPosition.width;\n        endY = targetPosition.y + targetPosition.height / 2;\n      } else {\n        // Target is above - connect to bottom center\n        endX = targetPosition.x + targetPosition.width / 2;\n        endY = targetPosition.y + targetPosition.height;\n      }\n\n      waypoints.push({ x: startX, y: startY });\n\n      // Add bend point if needed for orthogonal routing\n      if (Math.abs(startX - endX) > 10 && Math.abs(startY - endY) > 10) {\n        // Go down first, then turn\n        const midY = startY + 20;\n        waypoints.push({ x: startX, y: midY });\n        waypoints.push({ x: endX, y: midY });\n      }\n\n      waypoints.push({ x: endX, y: endY });\n    } else {\n      // Normal edge - use ELK calculated waypoints\n      for (const section of edge.sections) {\n        // Start point\n        waypoints.push({ x: offsetX + section.startPoint.x, y: offsetY + section.startPoint.y });\n\n        // Bend points\n        if (section.bendPoints) {\n          for (const bp of section.bendPoints) {\n            waypoints.push({ x: offsetX + bp.x, y: offsetY + bp.y });\n          }\n        }\n\n        // End point\n        waypoints.push({ x: offsetX + section.endPoint.x, y: offsetY + section.endPoint.y });\n      }\n\n      // Adjust endpoints for gateway diamond shapes\n      // This calculates the actual intersection with the diamond edge to maintain\n      // visual separation when multiple edges connect to the same gateway side\n      if (waypoints.length >= 2) {\n        // Adjust start point if source is a gateway\n        if (sourceIsGateway && sourceId) {\n          const sourcePos = this.nodePositions.get(sourceId);\n          if (sourcePos) {\n            const wp0 = waypoints[0];\n            const wp1 = waypoints[1];\n            if (wp0 && wp1) {\n              waypoints[0] = adjustGatewayEndpoint(\n                wp0,\n                wp1,\n                sourcePos,\n                true // isSource\n              );\n              // No adjacent point adjustment needed - the intersection calculation\n              // preserves the original Y (or X) coordinate, maintaining orthogonality\n            }\n          }\n        }\n\n        // Adjust end point if target is a gateway\n        if (targetIsGateway && targetId) {\n          const targetPos = this.nodePositions.get(targetId);\n          if (targetPos) {\n            const lastIdx = waypoints.length - 1;\n            const prevIdx = lastIdx - 1;\n            const wpLast = waypoints[lastIdx];\n            const wpPrev = waypoints[prevIdx];\n            if (wpLast && wpPrev) {\n              waypoints[lastIdx] = adjustGatewayEndpoint(\n                wpLast,\n                wpPrev,\n                targetPos,\n                false // isSource\n              );\n              // No adjacent point adjustment needed - the intersection calculation\n              // preserves the original Y (or X) coordinate, maintaining orthogonality\n            }\n          }\n        }\n      }\n\n      // Adjust endpoints for nodes with ioSpecification (visualHeight)\n      // ELK calculates waypoints based on the enlarged layout height (which includes space for data objects),\n      // but we need to connect to the visual node border, not the layout center\n      this.adjustEndpointsForVisualHeight(waypoints, sourceId, targetId);\n    }\n\n    // Ensure all waypoint segments are orthogonal (no diagonal lines)\n    // Insert bend points where needed to convert diagonals to L-shaped routes\n    this.ensureOrthogonalWaypoints(waypoints);\n\n    // Ensure endpoints connect perpendicular to node borders\n    // This adds bend points if the last/first segment isn't perpendicular\n    this.ensurePerpendicularEndpoints(\n      waypoints,\n      sourceId,\n      targetId,\n      sourceIsGateway,\n      targetIsGateway\n    );\n\n    // Re-route around obstacles ELK's edge-fixer can't see — data shapes\n    // and foreign flow nodes that a boundary L-shape or post-alignment\n    // shift may have routed through.\n    const detoured = this.routeAroundLocalObstacles(waypoints, sourceId, targetId);\n\n    // Detours can leave the last/first segment running parallel to the\n    // node border instead of perpendicular to it. Re-apply perpendicular\n    // enforcement so the connector still meets the node at a clean angle.\n    if (detoured) {\n      this.ensurePerpendicularEndpoints(\n        waypoints,\n        sourceId,\n        targetId,\n        sourceIsGateway,\n        targetIsGateway\n      );\n    }\n\n    const edgeModel: EdgeModel = {\n      id: `${edge.id}_di`,\n      bpmnElement: edge.id,\n      waypoints,\n    };\n\n    // Add label if present - use smart positioning on longest segment\n    if (edge.labels && edge.labels.length > 0) {\n      const label = edge.labels[0];\n      const labelWidth = label?.width ?? 50;\n      const labelHeight = label?.height ?? 14;\n\n      // Always use our smart label positioning (ELK's positions are often poor)\n      const labelPos = this.calculateSmartLabelPosition(\n        waypoints,\n        labelWidth,\n        labelHeight,\n        sourceId,\n        targetId\n      );\n\n      // Register this label position for collision detection with other edge labels\n      this.placedEdgeLabels.push({\n        x: labelPos.x,\n        y: labelPos.y,\n        width: labelWidth,\n        height: labelHeight,\n      });\n\n      edgeModel.label = {\n        bounds: {\n          x: labelPos.x,\n          y: labelPos.y,\n          width: labelWidth,\n          height: labelHeight,\n        },\n      };\n    }\n\n    return edgeModel;\n  }\n\n  /**\n   * Adjust edge endpoints for nodes with ioSpecification (visualHeight)\n   *\n   * When a node has ioSpecification, ELK uses an enlarged height for layout (to make space for data objects).\n   * However, the edge endpoints should connect to the visual node border, not based on the layout height.\n   *\n   * This method adjusts endpoint Y coordinates and also adjusts adjacent waypoints if they were\n   * on the same horizontal line, to maintain horizontal segments without introducing extra bends.\n   */\n  private adjustEndpointsForVisualHeight(\n    waypoints: PointModel[],\n    sourceId?: string,\n    targetId?: string\n  ): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 5;\n\n    // Adjust source endpoint if source has visualHeight\n    if (sourceId) {\n      const sourcePos = this.nodePositions.get(sourceId);\n      if (sourcePos?.visualHeight !== undefined) {\n        const firstWp = waypoints[0];\n        const secondWp = waypoints[1];\n        if (firstWp && secondWp) {\n          const nodeRight = sourcePos.x + sourcePos.width;\n          const nodeLeft = sourcePos.x;\n          const visualBottom = sourcePos.y + sourcePos.visualHeight;\n          const visualCenterY = sourcePos.y + sourcePos.visualHeight / 2;\n\n          // Check if leaving from left or right side (horizontal connection)\n          if (Math.abs(firstWp.x - nodeRight) < tolerance || Math.abs(firstWp.x - nodeLeft) < tolerance) {\n            const oldY = firstWp.y;\n            const newY = visualCenterY;\n            // Horizontal exit - adjust Y to visual center\n            firstWp.y = newY;\n            // If second waypoint was on the same horizontal line, adjust it too to maintain horizontal segment\n            // BUT only if second waypoint is NOT the last waypoint (i.e., not connecting directly to target)\n            if (Math.abs(secondWp.y - oldY) < tolerance && waypoints.length > 2) {\n              secondWp.y = newY;\n            }\n          } else if (firstWp.y > visualBottom) {\n            // Leaving from below visual bottom - clamp to visual bottom\n            firstWp.y = visualBottom;\n          }\n        }\n      }\n    }\n\n    // Adjust target endpoint if target has visualHeight\n    if (targetId) {\n      const targetPos = this.nodePositions.get(targetId);\n      if (targetPos?.visualHeight !== undefined) {\n        const lastIdx = waypoints.length - 1;\n        const lastWp = waypoints[lastIdx];\n        const prevWp = waypoints[lastIdx - 1];\n        if (lastWp && prevWp) {\n          const nodeLeft = targetPos.x;\n          const nodeRight = targetPos.x + targetPos.width;\n          const visualBottom = targetPos.y + targetPos.visualHeight;\n          const visualCenterY = targetPos.y + targetPos.visualHeight / 2;\n\n          // Check if entering from left or right side (horizontal connection)\n          if (Math.abs(lastWp.x - nodeLeft) < tolerance || Math.abs(lastWp.x - nodeRight) < tolerance) {\n            const oldY = lastWp.y;\n            const newY = visualCenterY;\n            // Horizontal entry - adjust Y to visual center\n            lastWp.y = newY;\n            // If previous waypoint was on the same horizontal line, adjust it too to maintain horizontal segment\n            // BUT only if previous waypoint is NOT the first waypoint (i.e., not connecting directly from source)\n            if (Math.abs(prevWp.y - oldY) < tolerance && waypoints.length > 2) {\n              prevWp.y = newY;\n            }\n          } else if (lastWp.y > visualBottom) {\n            // Entering from below visual bottom - clamp to visual bottom\n            lastWp.y = visualBottom;\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Calculate smart label position on the edge\n   * Strategy:\n   * 1. Find the longest segment of the edge (best visibility)\n   * 2. Place label at the midpoint of that segment\n   * 3. Offset based on segment direction, avoiding overlap with source/target nodes\n   */\n  private calculateSmartLabelPosition(\n    waypoints: PointModel[],\n    labelWidth: number,\n    labelHeight: number,\n    sourceId?: string,\n    targetId?: string\n  ): { x: number; y: number } {\n    if (waypoints.length < 2) {\n      return { x: 0, y: 0 };\n    }\n\n    // Get source and target node positions for collision avoidance\n    const sourcePos = sourceId ? this.nodePositions.get(sourceId) : undefined;\n    const targetPos = targetId ? this.nodePositions.get(targetId) : undefined;\n\n    // Find the longest segment that is not too close to source/target\n    let bestSegmentIndex = -1;\n    let bestSegmentLength = 0;\n\n    for (let i = 0; i < waypoints.length - 1; i++) {\n      const wpCurrent = waypoints[i];\n      const wpNext = waypoints[i + 1];\n      if (!wpCurrent || !wpNext) continue;\n\n      const segmentLength = distance(wpCurrent, wpNext);\n\n      // Skip very short segments\n      if (segmentLength < 30) continue;\n\n      // Calculate segment midpoint\n      const midX = (wpCurrent.x + wpNext.x) / 2;\n      const midY = (wpCurrent.y + wpNext.y) / 2;\n\n      // Check if midpoint is too close to source or target node\n      const tooCloseToSource = sourcePos && this.isPointNearNode(midX, midY, sourcePos, 20);\n      const tooCloseToTarget = targetPos && this.isPointNearNode(midX, midY, targetPos, 20);\n\n      if (!tooCloseToSource && !tooCloseToTarget && segmentLength > bestSegmentLength) {\n        bestSegmentLength = segmentLength;\n        bestSegmentIndex = i;\n      }\n    }\n\n    // If no good segment found, fall back to longest segment\n    if (bestSegmentIndex < 0) {\n      for (let i = 0; i < waypoints.length - 1; i++) {\n        const wpCurrent = waypoints[i];\n        const wpNext = waypoints[i + 1];\n        if (!wpCurrent || !wpNext) continue;\n\n        const segmentLength = distance(wpCurrent, wpNext);\n        if (segmentLength > bestSegmentLength) {\n          bestSegmentLength = segmentLength;\n          bestSegmentIndex = i;\n        }\n      }\n    }\n\n    if (bestSegmentIndex < 0) {\n      bestSegmentIndex = 0;\n    }\n\n    const wpStart = waypoints[bestSegmentIndex];\n    const wpEnd = waypoints[bestSegmentIndex + 1];\n\n    if (!wpStart || !wpEnd) {\n      return { x: 0, y: 0 };\n    }\n\n    // Calculate midpoint of the chosen segment\n    const midX = (wpStart.x + wpEnd.x) / 2;\n    const midY = (wpStart.y + wpEnd.y) / 2;\n\n    // Determine segment direction\n    const dx = wpEnd.x - wpStart.x;\n    const dy = wpEnd.y - wpStart.y;\n    const isHorizontal = Math.abs(dx) > Math.abs(dy);\n    const segmentLength = Math.sqrt(dx * dx + dy * dy);\n\n    // Label offset from the edge line\n    const offset = 5;\n\n    if (isHorizontal) {\n      // Horizontal segment - place label above the line by default. When several\n      // edges share the same horizontal stub (typical gateway-fan with multiple\n      // outgoing flows), the natural midpoint collides — so try increasing\n      // vertical offsets and both sides before giving up.\n      const labelX = midX - labelWidth / 2;\n      const baseAbove = midY - labelHeight - offset;\n      const baseBelow = midY + offset;\n\n      const tryPositions: { x: number; y: number }[] = [];\n      for (let step = 0; step <= 5; step++) {\n        const delta = step * (labelHeight + 4);\n        tryPositions.push({ x: labelX, y: baseAbove - delta });\n        tryPositions.push({ x: labelX, y: baseBelow + delta });\n      }\n\n      let fallback = tryPositions[0]!;\n      for (const pos of tryPositions) {\n        const bounds = { x: pos.x, y: pos.y, width: labelWidth, height: labelHeight };\n        const overlapsNode = this.labelOverlapsAnyNode(bounds);\n        const overlapsLabel = this.labelOverlapsAnyEdgeLabel(bounds);\n        if (!overlapsNode && !overlapsLabel) {\n          return pos;\n        }\n        // Prefer at least non-node-overlap as the fallback choice.\n        if (!overlapsNode) {\n          fallback = pos;\n        }\n      }\n      return fallback;\n    } else {\n      // Vertical segment - for long vertical segments (like message flows),\n      // place label at various positions to avoid overlap with nodes AND other edge labels\n\n      // For long segments (like message flows), try multiple positions\n      // to find one that doesn't overlap with nodes or other labels\n      const positions = segmentLength > 80\n        ? [0.35, 0.5, 0.65, 0.2, 0.8, 0.15, 0.85]\n        : [0.5];\n\n      // Try each position with both right and left placement\n      for (const ratio of positions) {\n        const testY = wpStart.y + (wpEnd.y - wpStart.y) * ratio - labelHeight / 2;\n\n        // Try right side\n        const boundsRight = { x: midX + offset, y: testY, width: labelWidth, height: labelHeight };\n        if (!this.labelOverlapsAnyNode(boundsRight) && !this.labelOverlapsAnyEdgeLabel(boundsRight)) {\n          return { x: midX + offset, y: testY };\n        }\n\n        // Try left side\n        const boundsLeft = { x: midX - labelWidth - offset, y: testY, width: labelWidth, height: labelHeight };\n        if (!this.labelOverlapsAnyNode(boundsLeft) && !this.labelOverlapsAnyEdgeLabel(boundsLeft)) {\n          return { x: midX - labelWidth - offset, y: testY };\n        }\n      }\n\n      // Fallback: use midpoint, but offset Y if overlapping with other labels\n      let labelX = midX + offset;\n      let labelY = midY - labelHeight / 2;\n\n      // If overlapping with existing label, try different Y offsets\n      for (let yOffset = 0; yOffset <= 100; yOffset += 20) {\n        for (const side of [1, -1]) { // right side, then left side\n          for (const yDir of [0, 1, -1]) { // no offset, down, up\n            const testX = side === 1 ? midX + offset : midX - labelWidth - offset;\n            const testY = labelY + yDir * yOffset;\n            const testBounds = { x: testX, y: testY, width: labelWidth, height: labelHeight };\n\n            if (!this.labelOverlapsAnyEdgeLabel(testBounds)) {\n              // Found a position that doesn't overlap with other labels\n              // Check node overlap is secondary - we prefer no label overlap\n              if (!this.labelOverlapsAnyNode(testBounds)) {\n                return { x: testX, y: testY };\n              }\n              // Even if overlapping node, use this if no label overlap\n              labelX = testX;\n              labelY = testY;\n            }\n          }\n        }\n      }\n\n      return { x: labelX, y: labelY };\n    }\n  }\n\n  /**\n   * Check if a point is near a node (within padding distance)\n   */\n  private isPointNearNode(\n    x: number,\n    y: number,\n    nodePos: NodePosition,\n    padding: number\n  ): boolean {\n    return (\n      x >= nodePos.x - padding &&\n      x <= nodePos.x + nodePos.width + padding &&\n      y >= nodePos.y - padding &&\n      y <= nodePos.y + nodePos.height + padding\n    );\n  }\n\n  /**\n   * Check if a label bounds overlaps with any node\n   */\n  private labelOverlapsAnyNode(labelBounds: { x: number; y: number; width: number; height: number }): boolean {\n    for (const nodePos of this.nodePositions.values()) {\n      if (this.boundsOverlap(labelBounds, nodePos)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Check if a label bounds overlaps with any already placed edge label\n   */\n  private labelOverlapsAnyEdgeLabel(labelBounds: { x: number; y: number; width: number; height: number }): boolean {\n    for (const placedLabel of this.placedEdgeLabels) {\n      if (this.boundsOverlap(labelBounds, placedLabel)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Check if two rectangles overlap\n   */\n  private boundsOverlap(\n    a: { x: number; y: number; width: number; height: number },\n    b: { x: number; y: number; width: number; height: number }\n  ): boolean {\n    return !(\n      a.x + a.width < b.x ||\n      b.x + b.width < a.x ||\n      a.y + a.height < b.y ||\n      b.y + b.height < a.y\n    );\n  }\n\n  /**\n   * Ensure all waypoint segments are orthogonal (horizontal or vertical)\n   * If a diagonal segment is found, insert intermediate bend points to create\n   * an L-shaped orthogonal path.\n   *\n   * Strategy: For diagonal segments, we use \"horizontal first\" - go horizontally\n   * to the target X, then vertically to the target Y.\n   */\n  private ensureOrthogonalWaypoints(waypoints: PointModel[]): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 1; // Allow 1px tolerance for floating point errors\n    let i = 0;\n\n    while (i < waypoints.length - 1) {\n      const current = waypoints[i];\n      const next = waypoints[i + 1];\n      if (!current || !next) {\n        i++;\n        continue;\n      }\n\n      const dx = Math.abs(next.x - current.x);\n      const dy = Math.abs(next.y - current.y);\n\n      // Check if this segment is diagonal (both dx and dy are significant)\n      if (dx > tolerance && dy > tolerance) {\n        // Insert a bend point to make it orthogonal\n        // Use \"horizontal first\" strategy: go to next.x first, then to next.y\n        const bendPoint: PointModel = { x: next.x, y: current.y };\n        waypoints.splice(i + 1, 0, bendPoint);\n        // Don't increment i - we need to check the newly created segment\n        // But the next iteration will check (current -> bendPoint) which is horizontal\n        // So we can safely increment to check the next pair\n        i++;\n      } else {\n        i++;\n      }\n    }\n  }\n\n  /**\n   * Detect which side of a node a point is connected to.\n   * Returns 'top', 'bottom', 'left', 'right', or 'unknown'.\n   *\n   * First tries exact match with tolerance, then falls back to closest edge detection.\n   */\n  private detectConnectionSide(\n    point: PointModel,\n    nodeBounds: NodePosition,\n    _isGateway: boolean = false\n  ): 'top' | 'bottom' | 'left' | 'right' | 'unknown' {\n    const exactTolerance = 3;\n    const maxTolerance = 15; // Maximum distance to consider for closest edge\n\n    const nodeTop = nodeBounds.y;\n    const nodeBottom = nodeBounds.y + nodeBounds.height;\n    const nodeLeft = nodeBounds.x;\n    const nodeRight = nodeBounds.x + nodeBounds.width;\n\n    // For regular nodes, check rectangular edges\n    // First, try exact match with small tolerance\n    if (Math.abs(point.y - nodeTop) <= exactTolerance) return 'top';\n    if (Math.abs(point.y - nodeBottom) <= exactTolerance) return 'bottom';\n    if (Math.abs(point.x - nodeLeft) <= exactTolerance) return 'left';\n    if (Math.abs(point.x - nodeRight) <= exactTolerance) return 'right';\n\n    // If no exact match, find the closest edge\n    const distToTop = Math.abs(point.y - nodeTop);\n    const distToBottom = Math.abs(point.y - nodeBottom);\n    const distToLeft = Math.abs(point.x - nodeLeft);\n    const distToRight = Math.abs(point.x - nodeRight);\n\n    const minDist = Math.min(distToTop, distToBottom, distToLeft, distToRight);\n\n    // Only use closest edge if it's within reasonable distance\n    if (minDist > maxTolerance) return 'unknown';\n\n    // Return the closest edge\n    if (minDist === distToTop) return 'top';\n    if (minDist === distToBottom) return 'bottom';\n    if (minDist === distToLeft) return 'left';\n    return 'right';\n  }\n\n  /**\n   * Detect connection side for gateway based on edge direction.\n   * When point is on a diagonal edge of the diamond, use the adjacent point to determine direction.\n   */\n  private detectGatewayConnectionSide(\n    point: PointModel,\n    adjacentPoint: PointModel,\n    nodeBounds: NodePosition,\n    isSource: boolean\n  ): 'top' | 'bottom' | 'left' | 'right' {\n    const centerX = nodeBounds.x + nodeBounds.width / 2;\n    const centerY = nodeBounds.y + nodeBounds.height / 2;\n    const nodeTop = nodeBounds.y;\n    const nodeBottom = nodeBounds.y + nodeBounds.height;\n    const nodeLeft = nodeBounds.x;\n    const nodeRight = nodeBounds.x + nodeBounds.width;\n\n    // Calculate distances to each diamond corner\n    const distToTopCorner = Math.abs(point.x - centerX) + Math.abs(point.y - nodeTop);\n    const distToBottomCorner = Math.abs(point.x - centerX) + Math.abs(point.y - nodeBottom);\n    const distToLeftCorner = Math.abs(point.x - nodeLeft) + Math.abs(point.y - centerY);\n    const distToRightCorner = Math.abs(point.x - nodeRight) + Math.abs(point.y - centerY);\n\n    const minDist = Math.min(distToTopCorner, distToBottomCorner, distToLeftCorner, distToRightCorner);\n\n    // If clearly closest to one corner, use that\n    const tolerance = 5;\n    if (distToTopCorner <= minDist + tolerance && distToTopCorner < distToBottomCorner - tolerance &&\n        distToTopCorner < distToLeftCorner - tolerance && distToTopCorner < distToRightCorner - tolerance) {\n      return 'top';\n    }\n    if (distToBottomCorner <= minDist + tolerance && distToBottomCorner < distToTopCorner - tolerance &&\n        distToBottomCorner < distToLeftCorner - tolerance && distToBottomCorner < distToRightCorner - tolerance) {\n      return 'bottom';\n    }\n    if (distToLeftCorner <= minDist + tolerance && distToLeftCorner < distToTopCorner - tolerance &&\n        distToLeftCorner < distToBottomCorner - tolerance && distToLeftCorner < distToRightCorner - tolerance) {\n      return 'left';\n    }\n    if (distToRightCorner <= minDist + tolerance && distToRightCorner < distToTopCorner - tolerance &&\n        distToRightCorner < distToBottomCorner - tolerance && distToRightCorner < distToLeftCorner - tolerance) {\n      return 'right';\n    }\n\n    // Ambiguous case: use edge direction to decide\n    // For source: look at direction TO adjacentPoint\n    // For target: look at direction FROM adjacentPoint\n    const dx = isSource ? (adjacentPoint.x - point.x) : (point.x - adjacentPoint.x);\n    const dy = isSource ? (adjacentPoint.y - point.y) : (point.y - adjacentPoint.y);\n\n    // If edge is more horizontal, prefer left/right connection\n    // If edge is more vertical, prefer top/bottom connection\n    if (Math.abs(dx) > Math.abs(dy)) {\n      // Horizontal direction - use left or right\n      return dx > 0 ? 'right' : 'left';\n    } else {\n      // Vertical direction - use top or bottom\n      return dy > 0 ? 'bottom' : 'top';\n    }\n  }\n\n  /**\n   * Ensure edge endpoints connect perpendicular to node borders.\n   * - Connection to top/bottom: last segment must be vertical (same x)\n   * - Connection to left/right: last segment must be horizontal (same y)\n   *\n   * When inserting bend points, we also update the previous waypoint to maintain\n   * orthogonality (no diagonal lines).\n   */\n  private ensurePerpendicularEndpoints(\n    waypoints: PointModel[],\n    sourceId: string | undefined,\n    targetId: string | undefined,\n    sourceIsGateway: boolean = false,\n    targetIsGateway: boolean = false\n  ): void {\n    if (waypoints.length < 2) return;\n\n    const tolerance = 2;\n    const minBendOffset = 15; // Minimum distance for bend point from endpoint\n\n    // Process target endpoint (end of edge)\n    if (targetId) {\n      const targetPos = this.nodePositions.get(targetId);\n      if (targetPos) {\n        const lastIdx = waypoints.length - 1;\n        const endPoint = waypoints[lastIdx];\n        const prevPoint = waypoints[lastIdx - 1];\n\n        if (endPoint && prevPoint) {\n          const side = targetIsGateway\n            ? this.detectGatewayConnectionSide(endPoint, prevPoint, targetPos, false)\n            : this.detectConnectionSide(endPoint, targetPos, false);\n\n          if (side === 'top' || side === 'bottom') {\n            // Vertical edge - last segment must be vertical (x should be same)\n            if (Math.abs(endPoint.x - prevPoint.x) > tolerance) {\n              // Need to insert a bend point to make it vertical\n              // Calculate bend point Y position\n              const bendY = side === 'top'\n                ? endPoint.y - minBendOffset\n                : endPoint.y + minBendOffset;\n\n              // Insert bend point and update previous point to maintain orthogonality\n              // Path: ... -> prevPoint -> bendPoint -> endPoint\n              // bendPoint.x = endPoint.x (vertical final segment)\n              // bendPoint.y = bendY\n              // prevPoint needs to have y = bendY to make prevPoint->bendPoint horizontal\n              const bendPoint: PointModel = { x: endPoint.x, y: bendY };\n              waypoints.splice(lastIdx, 0, bendPoint);\n\n              // Update prevPoint's y to match bendY for orthogonality\n              prevPoint.y = bendY;\n            }\n          } else if (side === 'left' || side === 'right') {\n            // Horizontal edge - last segment must be horizontal (y should be same)\n            if (Math.abs(endPoint.y - prevPoint.y) > tolerance) {\n              // Need to insert a bend point to make it horizontal\n              const bendX = side === 'left'\n                ? endPoint.x - minBendOffset\n                : endPoint.x + minBendOffset;\n\n              const bendPoint: PointModel = { x: bendX, y: endPoint.y };\n              waypoints.splice(lastIdx, 0, bendPoint);\n\n              // Update prevPoint's x to match bendX for orthogonality\n              prevPoint.x = bendX;\n            }\n          }\n        }\n      }\n    }\n\n    // Process source endpoint (start of edge)\n    if (sourceId) {\n      // Check both nodePositions and boundaryEventPositions for source\n      const sourcePos = this.nodePositions.get(sourceId) ?? this.boundaryEventPositions.get(sourceId);\n      if (sourcePos) {\n        const startPoint = waypoints[0];\n        const nextPoint = waypoints[1];\n\n        if (startPoint && nextPoint) {\n          const side = sourceIsGateway\n            ? this.detectGatewayConnectionSide(startPoint, nextPoint, sourcePos, true)\n            : this.detectConnectionSide(startPoint, sourcePos, false);\n\n          if (side === 'top' || side === 'bottom') {\n            // Vertical edge - first segment must be vertical (x should be same)\n            if (Math.abs(startPoint.x - nextPoint.x) > tolerance) {\n              // Need to insert a bend point to make it vertical\n              const bendY = side === 'top'\n                ? startPoint.y - minBendOffset\n                : startPoint.y + minBendOffset;\n\n              const bendPoint: PointModel = { x: startPoint.x, y: bendY };\n              waypoints.splice(1, 0, bendPoint);\n\n              // Update nextPoint's y to match bendY for orthogonality\n              nextPoint.y = bendY;\n            }\n          } else if (side === 'left' || side === 'right') {\n            // Horizontal edge - first segment must be horizontal (y should be same)\n            if (Math.abs(startPoint.y - nextPoint.y) > tolerance) {\n              // Need to insert a bend point to make it horizontal\n              const bendX = side === 'left'\n                ? startPoint.x - minBendOffset\n                : startPoint.x + minBendOffset;\n\n              const bendPoint: PointModel = { x: bendX, y: startPoint.y };\n              waypoints.splice(1, 0, bendPoint);\n\n              // Update nextPoint's x to match bendX for orthogonality\n              nextPoint.x = bendX;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Re-route any axis-aligned segment that crosses a non-endpoint node.\n   *\n   * For each blocked segment we slide it perpendicular until it clears ALL\n   * obstacles in its band — picking just past the directly crossed one can\n   * land the segment inside a different node sitting at the new coordinate.\n   * The scan repeats until no segment moves, since a slide can introduce a\n   * new crossing on a neighboring segment.\n   */\n  private routeAroundLocalObstacles(\n    waypoints: PointModel[],\n    sourceId?: string,\n    targetId?: string\n  ): boolean {\n    if (waypoints.length < 2) return false;\n    const margin = 10;\n\n    const obstacles = this.collectEdgeObstacles(sourceId, targetId);\n    if (obstacles.length === 0) return false;\n\n    // Slide `preferred` along one axis past every interval in `intervals`\n    // that contains it. Intervals are sorted and merged so a single sweep\n    // jumps to the first gap in the chosen direction.\n    const findClearance = (\n      preferred: number,\n      direction: 1 | -1,\n      intervals: Array<{ lo: number; hi: number }>\n    ): number => {\n      const merged = mergeIntervals(intervals, margin);\n      if (direction === 1) {\n        for (const iv of merged) {\n          if (preferred >= iv.hi) continue;\n          if (preferred <= iv.lo) return preferred;\n          preferred = iv.hi;\n        }\n        return preferred;\n      }\n      for (let i = merged.length - 1; i >= 0; i--) {\n        const iv = merged[i];\n        if (preferred <= iv.lo) continue;\n        if (preferred >= iv.hi) return preferred;\n        preferred = iv.lo;\n      }\n      return preferred;\n    };\n\n    const trySlide = (i: number, axis: 'x' | 'y'): boolean => {\n      const a = waypoints[i];\n      const b = waypoints[i + 1];\n      if (!a || !b) return false;\n      // The slide axis is the one the segment is *constant* on. For a\n      // horizontal segment (constant y) we slide y; perpendicular span is x.\n      const slide = axis;\n      const span = axis === 'y' ? 'x' : 'y';\n      const dim = axis === 'y' ? 'height' : 'width';\n      const perpDim = span === 'y' ? 'height' : 'width';\n\n      const segSlide = a[slide];\n      const segMin = Math.min(a[span], b[span]);\n      const segMax = Math.max(a[span], b[span]);\n\n      const band: Array<{ lo: number; hi: number }> = [];\n      let crosses = false;\n      for (const obs of obstacles) {\n        const oSpan = obs[span];\n        const oSpanHi = oSpan + obs[perpDim];\n        if (segMax <= oSpan + 1 || segMin >= oSpanHi - 1) continue;\n        const oSlide = obs[slide];\n        const oSlideHi = oSlide + obs[dim];\n        band.push({ lo: oSlide, hi: oSlideHi });\n        if (segSlide > oSlide + 1 && segSlide < oSlideHi - 1) crosses = true;\n      }\n      if (!crosses) return false;\n\n      const lower = findClearance(segSlide, -1, band);\n      const upper = findClearance(segSlide, 1, band);\n      const distLower = lower > 0 ? segSlide - lower : Infinity;\n      const distUpper = upper - segSlide;\n      const newVal = distLower <= distUpper ? lower : upper;\n\n      const isFirst = i === 0;\n      const isLast = i === waypoints.length - 2;\n      if (isFirst && isLast) return false;\n      if (isFirst) {\n        const bend = { x: a.x, y: a.y, [slide]: newVal } as PointModel;\n        bend[span] = a[span];\n        waypoints.splice(i + 1, 0, bend);\n        b[slide] = newVal;\n      } else if (isLast) {\n        a[slide] = newVal;\n        const bend = { x: b.x, y: b.y, [slide]: newVal } as PointModel;\n        bend[span] = b[span];\n        waypoints.splice(i + 1, 0, bend);\n      } else {\n        a[slide] = newVal;\n        b[slide] = newVal;\n      }\n      return true;\n    };\n\n    let changed = false;\n    // Bounded outer loop: a slide on one segment can push a neighbor into a\n    // new obstacle. 8 iterations is well above the diameter of any path we\n    // produce; hitting the cap means the route can't be cleared and the\n    // hard \"no crossings\" constraint is violated — surface in tests.\n    const MAX_ITERS = 8;\n    for (let iter = 0; iter < MAX_ITERS; iter++) {\n      let changedThisIter = false;\n      for (let i = waypoints.length - 2; i >= 0; i--) {\n        const a = waypoints[i];\n        const b = waypoints[i + 1];\n        if (!a || !b) continue;\n        const dxAbs = Math.abs(a.x - b.x);\n        const dyAbs = Math.abs(a.y - b.y);\n        const moved =\n          (dyAbs <= 1 && dxAbs > 1 && trySlide(i, 'y')) ||\n          (dxAbs <= 1 && dyAbs > 1 && trySlide(i, 'x'));\n        if (moved) {\n          changed = true;\n          changedThisIter = true;\n        }\n      }\n      if (!changedThisIter) break;\n      if (iter === MAX_ITERS - 1 && isDebugEnabled()) {\n        console.log('[BPMN] routeAroundLocalObstacles: hit MAX_ITERS, some crossings may remain');\n      }\n    }\n\n    return changed;\n  }\n\n  private collectEdgeObstacles(\n    sourceId: string | undefined,\n    targetId: string | undefined\n  ): NodePosition[] {\n    const out: NodePosition[] = [];\n    for (const [id, pos] of this.nodePositions) {\n      if (id === sourceId || id === targetId) continue;\n      const dataOwner = this.dataObjectOwners.get(id);\n      if (dataOwner !== undefined) {\n        if (dataOwner !== sourceId && dataOwner !== targetId) out.push(pos);\n        continue;\n      }\n      if (this.isObstacleNode(id)) out.push(pos);\n    }\n    return out;\n  }\n\n  private isObstacleNode(id: string): boolean {\n    const info = this.nodeBpmn.get(id);\n    if (!info?.type) return false;\n    const t = info.type;\n    if (t === 'dataObject' || t === 'dataObjectReference' ||\n        t === 'dataInput' || t === 'dataOutput' ||\n        t === 'dataStoreReference' || t === 'textAnnotation' ||\n        t === 'group' || t === 'lane' || t === 'participant' ||\n        t === 'process' || t === 'collaboration') {\n      return false;\n    }\n    // Expanded subprocesses host the edge's coordinate space — sliding around\n    // them would push the route out of its own container.\n    if (info.isExpanded === true && (SUBPROCESS_TYPES as readonly string[]).includes(t)) {\n      return false;\n    }\n    return true;\n  }\n}\n\nfunction mergeIntervals(\n  intervals: Array<{ lo: number; hi: number }>,\n  margin: number\n): Array<{ lo: number; hi: number }> {\n  if (intervals.length === 0) return intervals;\n  const sorted = intervals\n    .map((iv) => ({ lo: iv.lo - margin, hi: iv.hi + margin }))\n    .sort((a, b) => a.lo - b.lo);\n  const merged: Array<{ lo: number; hi: number }> = [sorted[0]];\n  for (let i = 1; i < sorted.length; i++) {\n    const last = merged[merged.length - 1];\n    const cur = sorted[i];\n    if (cur.lo <= last.hi) {\n      if (cur.hi > last.hi) last.hi = cur.hi;\n    } else {\n      merged.push(cur);\n    }\n  }\n  return merged;\n}\n","/**\n * Model Builder\n * Builds the intermediate BPMN model from layouted ELK-BPMN graph.\n * This module focuses on building the BPMN process/collaboration structure,\n * while DiagramBuilder handles the visual diagram (shapes and edges).\n */\n\nimport type { LayoutedGraph } from '../types/elk-output';\nimport type {\n  MessageDefinition,\n  SignalDefinition,\n  ErrorDefinition,\n  EscalationDefinition,\n} from '../types';\nimport { ReferenceResolver } from './reference-resolver';\nimport { LaneResolver, type LaneSetInfo } from './lane-resolver';\nimport { DiagramBuilder } from './diagram-builder';\nimport type {\n  BpmnModel,\n  DefinitionsModel,\n  CollaborationModel,\n  ProcessModel,\n  FlowElementModel,\n  ArtifactModel,\n  DiagramModel,\n  CollaborationNode,\n  ParticipantNode,\n  ProcessNode,\n  ChildNode,\n  BoundaryEventNode,\n  EdgeNode,\n  ArtifactNode,\n  IoSpecificationModel,\n} from './model-types';\nimport type { IoSpecification } from '../types/elk-bpmn';\n\n// Re-export types for external consumers\nexport type {\n  BpmnModel,\n  DefinitionsModel,\n  CollaborationModel,\n  ProcessModel,\n  FlowElementModel,\n  ArtifactModel,\n  DiagramModel,\n  ShapeModel,\n  EdgeModel,\n  BoundsModel,\n  PointModel,\n  LabelModel,\n  PlaneModel,\n  ParticipantModel,\n  MessageFlowModel,\n  SequenceFlowModel,\n  DataAssociationModel,\n  RootElement,\n  IoSpecificationModel,\n  DataInputModel,\n  DataOutputModel,\n  InputSetModel,\n  OutputSetModel,\n} from './model-types';\n\n// ============================================================================\n// Model Builder\n// ============================================================================\n\nexport class ModelBuilder {\n  private refResolver: ReferenceResolver;\n  private laneResolver: LaneResolver;\n  private diagramBuilder: DiagramBuilder;\n\n  constructor() {\n    this.refResolver = new ReferenceResolver();\n    this.laneResolver = new LaneResolver();\n    this.diagramBuilder = new DiagramBuilder();\n  }\n\n  /**\n   * Build the complete BPMN model from a layouted graph\n   */\n  build(graph: LayoutedGraph): BpmnModel {\n    // Reset resolvers\n    this.laneResolver.reset();\n\n    // Resolve references first\n    this.refResolver.resolve(graph);\n\n    // Build definitions model\n    const definitions = this.buildDefinitions(graph);\n\n    // Build diagram model using DiagramBuilder\n    const diagram = this.diagramBuilder.build(graph, definitions);\n\n    return { definitions, diagram };\n  }\n\n  /**\n   * Get the reference resolver\n   */\n  getRefResolver(): ReferenceResolver {\n    return this.refResolver;\n  }\n\n  /**\n   * Build definitions model\n   */\n  private buildDefinitions(graph: LayoutedGraph): DefinitionsModel {\n    const definitions: DefinitionsModel = {\n      id: graph.id,\n      targetNamespace: graph.bpmn?.targetNamespace ?? 'http://bpmn.io/schema/bpmn',\n      exporter: graph.bpmn?.exporter ?? 'bpmn-elk-layout',\n      exporterVersion: graph.bpmn?.exporterVersion ?? '1.0.0',\n      messages: graph.messages ?? [],\n      signals: graph.signals ?? [],\n      errors: graph.errors ?? [],\n      escalations: graph.escalations ?? [],\n      rootElements: [],\n    };\n\n    // Process top-level children\n    for (const child of graph.children) {\n      const bpmnType = (child as { bpmn: { type: string } }).bpmn?.type;\n\n      if (!bpmnType) {\n        throw new Error(`Invalid graph child: missing bpmn.type property for node ${(child as any).id}`);\n      }\n\n      if (bpmnType === 'collaboration') {\n        definitions.rootElements.push(this.buildCollaboration(child as CollaborationNode));\n\n        // Also add processes for each non-black-box participant\n        const collab = child as CollaborationNode;\n        for (const participant of collab.children ?? []) {\n          if (!participant.bpmn?.isBlackBox) {\n            const processId = participant.bpmn?.processRef ?? `Process_${participant.id}`;\n            definitions.rootElements.push(\n              this.buildProcessFromParticipant(participant, processId)\n            );\n          }\n        }\n      } else if (bpmnType === 'process') {\n        definitions.rootElements.push(this.buildProcess(child as ProcessNode));\n      } else {\n        throw new Error(`Invalid top-level element type: \"${bpmnType}\". Only \"process\" or \"collaboration\" are allowed at the top level.`);\n      }\n    }\n\n    if (definitions.rootElements.length === 0) {\n      throw new Error('Cannot create BPMN definitions: no valid process or collaboration found in the graph.');\n    }\n\n    return definitions;\n  }\n\n  /**\n   * Build collaboration model\n   */\n  private buildCollaboration(collab: CollaborationNode): CollaborationModel {\n    return {\n      type: 'collaboration',\n      id: collab.id,\n      name: collab.bpmn?.name,\n      isClosed: collab.bpmn?.isClosed,\n      participants: (collab.children ?? []).map((p) => ({\n        id: p.id,\n        name: p.bpmn?.name,\n        processRef: p.bpmn?.processRef ?? `Process_${p.id}`,\n        isBlackBox: p.bpmn?.isBlackBox,\n        participantMultiplicity: p.bpmn?.participantMultiplicity,\n      })),\n      messageFlows: (collab.edges ?? [])\n        .filter((e): e is typeof e & { sources: [string, ...string[]]; targets: [string, ...string[]] } =>\n          e.sources[0] !== undefined && e.targets[0] !== undefined)\n        .map((e) => ({\n          id: e.id,\n          name: e.bpmn?.name,\n          sourceRef: e.sources[0],\n          targetRef: e.targets[0],\n          messageRef: e.bpmn?.messageRef,\n        })),\n    };\n  }\n\n  /**\n   * Build process model from participant\n   */\n  private buildProcessFromParticipant(\n    participant: ParticipantNode,\n    processId: string\n  ): ProcessModel {\n    const process: ProcessModel = {\n      type: 'process',\n      id: processId,\n      name: participant.bpmn?.name,\n      isExecutable: true,\n      laneSet: this.laneResolver.resolve(participant),\n      flowElements: [],\n      artifacts: [],\n    };\n\n    // Collect all flow elements\n    this.collectFlowElements(participant.children ?? [], process.flowElements);\n\n    // Collect sequence flows\n    this.collectSequenceFlows(participant.edges ?? [], process.flowElements);\n\n    // Collect data associations and attach to flow elements (BPMN spec compliance)\n    this.collectDataAssociations(participant.edges ?? [], process.flowElements);\n\n    return process;\n  }\n\n  /**\n   * Build process model\n   */\n  private buildProcess(processNode: ProcessNode): ProcessModel {\n    const process: ProcessModel = {\n      type: 'process',\n      id: processNode.id,\n      name: processNode.bpmn?.name,\n      isExecutable: processNode.bpmn?.isExecutable ?? true,\n      processType: processNode.bpmn?.processType,\n      isClosed: processNode.bpmn?.isClosed,\n      laneSet: this.laneResolver.resolve(processNode),\n      flowElements: [],\n      artifacts: [],\n    };\n\n    // Collect all flow elements\n    this.collectFlowElements(processNode.children ?? [], process.flowElements);\n\n    // Collect sequence flows\n    this.collectSequenceFlows(processNode.edges ?? [], process.flowElements);\n\n    // Collect artifacts\n    if (processNode.artifacts) {\n      for (const artifact of processNode.artifacts) {\n        process.artifacts.push(this.buildArtifact(artifact));\n      }\n    }\n\n    // Collect associations from edges\n    this.collectAssociations(processNode.edges ?? [], process.artifacts);\n\n    // Collect data associations and attach to flow elements (BPMN spec compliance)\n    this.collectDataAssociations(processNode.edges ?? [], process.flowElements);\n\n    return process;\n  }\n\n  /**\n   * Collect flow elements recursively\n   */\n  private collectFlowElements(children: ChildNode[], elements: FlowElementModel[]): void {\n    for (const child of children) {\n      // Skip lanes - just traverse their children\n      if (child.bpmn?.type === 'lane') {\n        this.collectFlowElements(child.children ?? [], elements);\n        continue;\n      }\n\n      // Skip nested process - traverse its children and edges\n      // This handles the case where participant > children > [process > children: [flowNodes]]\n      if (child.bpmn?.type === 'process') {\n        this.collectFlowElements(child.children ?? [], elements);\n        this.collectSequenceFlows(child.edges ?? [], elements);\n        continue;\n      }\n\n      // Build flow element\n      const flowElement = this.buildFlowElement(child);\n      elements.push(flowElement);\n\n      // For expanded subprocesses, collect nested elements into the subprocess itself\n      if (child.bpmn?.isExpanded && child.children) {\n        flowElement.flowElements = [];\n        flowElement.artifacts = [];\n        this.collectFlowElements(child.children, flowElement.flowElements);\n        // Collect nested sequence flows into subprocess\n        if (child.edges) {\n          this.collectSequenceFlows(child.edges, flowElement.flowElements);\n        }\n      } else if (child.edges) {\n        // Collect nested sequence flows for non-expanded containers\n        this.collectSequenceFlows(child.edges, elements);\n      }\n\n      // Add boundary events (after subprocess content processing)\n      if (child.boundaryEvents) {\n        for (const be of child.boundaryEvents) {\n          elements.push(this.buildBoundaryEvent(be));\n        }\n      }\n    }\n  }\n\n  /**\n   * Build a flow element model\n   */\n  private buildFlowElement(node: ChildNode): FlowElementModel {\n    const incoming = this.refResolver.getIncomingSequenceFlows(node.id);\n    const outgoing = this.refResolver.getOutgoingSequenceFlows(node.id);\n\n    const flowElement: FlowElementModel = {\n      type: node.bpmn?.type ?? 'task',\n      id: node.id,\n      name: node.bpmn?.name,\n      incoming,\n      outgoing,\n      properties: this.extractProperties(node.bpmn ?? {}),\n    };\n\n    // Extract ioSpecification if present (for tasks)\n    const ioSpec = (node.bpmn as { ioSpecification?: IoSpecification } | undefined)?.ioSpecification;\n    if (ioSpec) {\n      flowElement.ioSpecification = this.buildIoSpecification(ioSpec, node.id);\n\n      // Auto-generate dataInputAssociation for only the first dataInput\n      // Only the topmost input in the vertical stack gets a dashed line to the task\n      const dataInputs = ioSpec.dataInputs ?? [];\n      if (dataInputs.length > 0) {\n        const firstInput = dataInputs[0];\n        flowElement.dataInputAssociations = [{\n          id: `${firstInput.id ?? `${node.id}_input_0`}_assoc`,\n          sourceRef: firstInput.id ?? `${node.id}_input_0`,\n          targetRef: node.id,\n        }];\n      }\n\n      // Auto-generate dataOutputAssociation for only the first dataOutput\n      // Only the topmost output in the vertical stack gets a dashed line from the task\n      const dataOutputs = ioSpec.dataOutputs ?? [];\n      if (dataOutputs.length > 0) {\n        const firstOutput = dataOutputs[0];\n        flowElement.dataOutputAssociations = [{\n          id: `${firstOutput.id ?? `${node.id}_output_0`}_assoc`,\n          sourceRef: node.id,\n          targetRef: firstOutput.id ?? `${node.id}_output_0`,\n        }];\n      }\n    }\n\n    return flowElement;\n  }\n\n  /**\n   * Build ioSpecification model from input\n   */\n  private buildIoSpecification(ioSpec: IoSpecification, taskId: string): IoSpecificationModel {\n    const dataInputs = (ioSpec.dataInputs ?? []).map((di, index) => ({\n      id: di.id ?? `${taskId}_input_${index}`,\n      name: di.name,\n      itemSubjectRef: di.itemSubjectRef,\n      isCollection: di.isCollection,\n    }));\n\n    const dataOutputs = (ioSpec.dataOutputs ?? []).map((dout, index) => ({\n      id: dout.id ?? `${taskId}_output_${index}`,\n      name: dout.name,\n      itemSubjectRef: dout.itemSubjectRef,\n      isCollection: dout.isCollection,\n    }));\n\n    // Build inputSets - if not provided, create default one with all inputs\n    const inputSets = (ioSpec.inputSets ?? []).map((is, index) => ({\n      id: is.id ?? `${taskId}_inputSet_${index}`,\n      name: is.name,\n      dataInputRefs: is.dataInputRefs ?? [],\n    }));\n    if (inputSets.length === 0 && dataInputs.length > 0) {\n      inputSets.push({\n        id: `${taskId}_inputSet_0`,\n        name: undefined,\n        dataInputRefs: dataInputs.map(di => di.id),\n      });\n    }\n\n    // Build outputSets - if not provided, create default one with all outputs\n    const outputSets = (ioSpec.outputSets ?? []).map((os, index) => ({\n      id: os.id ?? `${taskId}_outputSet_${index}`,\n      name: os.name,\n      dataOutputRefs: os.dataOutputRefs ?? [],\n    }));\n    if (outputSets.length === 0 && dataOutputs.length > 0) {\n      outputSets.push({\n        id: `${taskId}_outputSet_0`,\n        name: undefined,\n        dataOutputRefs: dataOutputs.map(dout => dout.id),\n      });\n    }\n\n    return {\n      dataInputs,\n      dataOutputs,\n      inputSets,\n      outputSets,\n    };\n  }\n\n  /**\n   * Build a boundary event model\n   */\n  private buildBoundaryEvent(be: BoundaryEventNode): FlowElementModel {\n    const incoming = this.refResolver.getIncomingSequenceFlows(be.id);\n    const outgoing = this.refResolver.getOutgoingSequenceFlows(be.id);\n\n    return {\n      type: 'boundaryEvent',\n      id: be.id,\n      name: be.bpmn?.name,\n      incoming,\n      outgoing,\n      attachedToRef: be.attachedToRef,\n      cancelActivity: be.bpmn?.isInterrupting ?? be.bpmn?.cancelActivity ?? true,\n      properties: this.extractProperties(be.bpmn ?? {}),\n    };\n  }\n\n  /**\n   * Collect sequence flows\n   */\n  private collectSequenceFlows(edges: EdgeNode[], elements: FlowElementModel[]): void {\n    for (const edge of edges) {\n      if (edge.bpmn?.type === 'sequenceFlow') {\n        elements.push({\n          type: 'sequenceFlow',\n          id: edge.id,\n          name: edge.bpmn?.name,\n          incoming: [],\n          outgoing: [],\n          properties: {\n            sourceRef: edge.sources[0],\n            targetRef: edge.targets[0],\n            conditionExpression: edge.bpmn?.conditionExpression,\n            isDefault: edge.bpmn?.isDefault,\n          },\n        });\n      }\n    }\n  }\n\n  /**\n   * Collect associations from edges\n   */\n  private collectAssociations(edges: EdgeNode[], artifacts: ArtifactModel[]): void {\n    for (const edge of edges) {\n      if (edge.bpmn?.type === 'association') {\n        artifacts.push({\n          type: 'association',\n          id: edge.id,\n          name: edge.bpmn?.name,\n          properties: {\n            sourceRef: edge.sources[0],\n            targetRef: edge.targets[0],\n            associationDirection: (edge.bpmn as { associationDirection?: string })?.associationDirection ?? 'None',\n          },\n        });\n      }\n    }\n  }\n\n  /**\n   * Collect data associations from edges and attach them to flow elements\n   * Per BPMN 2.0 spec: dataInputAssociation/dataOutputAssociation are child elements of Activity\n   */\n  private collectDataAssociations(edges: EdgeNode[], elements: FlowElementModel[]): void {\n    // Build a map of element IDs to their models for quick lookup\n    const elementMap = new Map<string, FlowElementModel>();\n    for (const element of elements) {\n      elementMap.set(element.id, element);\n    }\n\n    for (const edge of edges) {\n      const edgeType = edge.bpmn?.type;\n\n      if (edgeType === 'dataInputAssociation') {\n        // dataInputAssociation: data object (source) -> task (target)\n        // The association is a child of the TARGET task\n        const targetId = edge.targets[0];\n        const sourceId = edge.sources[0];\n        if (!targetId || !sourceId) continue;\n        const targetElement = elementMap.get(targetId);\n\n        if (targetElement) {\n          if (!targetElement.dataInputAssociations) {\n            targetElement.dataInputAssociations = [];\n          }\n          targetElement.dataInputAssociations.push({\n            id: edge.id,\n            sourceRef: sourceId,\n          });\n        }\n      } else if (edgeType === 'dataOutputAssociation') {\n        // dataOutputAssociation: task (source) -> data object (target)\n        // The association is a child of the SOURCE task\n        const sourceId = edge.sources[0];\n        const targetId = edge.targets[0];\n        if (!sourceId || !targetId) continue;\n        const sourceElement = elementMap.get(sourceId);\n\n        if (sourceElement) {\n          if (!sourceElement.dataOutputAssociations) {\n            sourceElement.dataOutputAssociations = [];\n          }\n          sourceElement.dataOutputAssociations.push({\n            id: edge.id,\n            sourceRef: sourceId,\n            targetRef: targetId,\n          });\n        }\n      }\n    }\n  }\n\n  /**\n   * Build an artifact model\n   */\n  private buildArtifact(artifact: ArtifactNode): ArtifactModel {\n    return {\n      type: artifact.bpmn?.type ?? 'textAnnotation',\n      id: artifact.id,\n      name: artifact.bpmn?.name,\n      properties: this.extractProperties(artifact.bpmn ?? {}),\n    };\n  }\n\n  /**\n   * Extract properties from bpmn object (excluding type and name)\n   */\n  private extractProperties(bpmn: Record<string, unknown>): Record<string, unknown> {\n    const { type, name, ...rest } = bpmn;\n    return rest;\n  }\n}\n","/**\n * BPMN XML Generator\n * Generates BPMN 2.0 XML from the intermediate model using bpmn-moddle\n */\n\nimport BpmnModdle from 'bpmn-moddle';\nimport type {\n  BpmnModel,\n  DefinitionsModel,\n  DiagramModel,\n  ProcessModel,\n  CollaborationModel,\n  FlowElementModel,\n  ArtifactModel,\n  ShapeModel,\n  EdgeModel,\n  IoSpecificationModel,\n} from '../transform/model-builder';\nimport type { LaneSetInfo, LaneInfo } from '../transform/lane-resolver';\nimport { BPMN_ELEMENT_MAP, EVENT_DEFINITION_MAP } from '../types/bpmn-constants';\n\n// Type definitions for bpmn-moddle elements\ninterface ModdleElement {\n  $type: string;\n  id?: string;\n  [key: string]: unknown;\n}\n\nexport class BpmnXmlGenerator {\n  private moddle: BpmnModdle;\n\n  constructor() {\n    this.moddle = new BpmnModdle();\n  }\n\n  /**\n   * Generate BPMN 2.0 XML from the model\n   */\n  async generate(model: BpmnModel): Promise<string> {\n    // Build the definitions element\n    const definitions = this.buildDefinitions(model.definitions, model.diagram);\n\n    // Serialize to XML\n    const { xml } = await this.moddle.toXML(definitions, {\n      format: true,\n      preamble: true,\n    });\n\n    return xml;\n  }\n\n  /**\n   * Build the root definitions element\n   */\n  private buildDefinitions(def: DefinitionsModel, diagram: DiagramModel): ModdleElement {\n    const definitions = this.moddle.create('bpmn:Definitions', {\n      id: def.id,\n      targetNamespace: def.targetNamespace,\n      exporter: def.exporter,\n      exporterVersion: def.exporterVersion,\n    });\n\n    const rootElements: ModdleElement[] = [];\n\n    // Add global definitions (messages, signals, errors, escalations)\n    for (const msg of def.messages) {\n      rootElements.push(\n        this.moddle.create('bpmn:Message', {\n          id: msg.id,\n          name: msg.name,\n        })\n      );\n    }\n\n    for (const sig of def.signals) {\n      rootElements.push(\n        this.moddle.create('bpmn:Signal', {\n          id: sig.id,\n          name: sig.name,\n        })\n      );\n    }\n\n    for (const err of def.errors) {\n      rootElements.push(\n        this.moddle.create('bpmn:Error', {\n          id: err.id,\n          name: err.name,\n          errorCode: err.errorCode,\n        })\n      );\n    }\n\n    for (const esc of def.escalations) {\n      rootElements.push(\n        this.moddle.create('bpmn:Escalation', {\n          id: esc.id,\n          name: esc.name,\n          escalationCode: esc.escalationCode,\n        })\n      );\n    }\n\n    // Add root elements (collaborations and processes)\n    for (const element of def.rootElements) {\n      if (element.type === 'collaboration') {\n        rootElements.push(this.buildCollaboration(element, def.messages));\n      } else if (element.type === 'process') {\n        rootElements.push(this.buildProcess(element));\n      }\n    }\n\n    definitions.rootElements = rootElements;\n\n    // Add diagram\n    definitions.diagrams = [this.buildDiagram(diagram)];\n\n    return definitions;\n  }\n\n  /**\n   * Build a collaboration element\n   */\n  private buildCollaboration(\n    collab: CollaborationModel,\n    messages: { id: string; name?: string }[] = []\n  ): ModdleElement {\n    const collaboration = this.moddle.create('bpmn:Collaboration', {\n      id: collab.id,\n      name: collab.name,\n      isClosed: collab.isClosed,\n    });\n\n    // Add participants\n    collaboration.participants = collab.participants.map((p) => {\n      const participant = this.moddle.create('bpmn:Participant', {\n        id: p.id,\n        name: p.name,\n        processRef: p.processRef ? { id: p.processRef } : undefined,\n      });\n\n      if (p.participantMultiplicity) {\n        participant.participantMultiplicity = this.moddle.create(\n          'bpmn:ParticipantMultiplicity',\n          {\n            minimum: p.participantMultiplicity.minimum,\n            maximum: p.participantMultiplicity.maximum,\n          }\n        );\n      }\n\n      return participant;\n    });\n\n    // Add message flows.\n    // bpmn.io renders the BPMNLabel (driven by messageFlow.name) AND auto-draws\n    // messageRef.name at the edge midpoint — so when both exist the same label\n    // appears twice (the \"请求/请求消息\" pile-up). Suppress messageFlow.name\n    // whenever a messageRef carries the canonical label; otherwise keep it.\n    const messagesById = new Map(messages.map((m) => [m.id, m]));\n    collaboration.messageFlows = collab.messageFlows.map((mf) => {\n      const refMsg = mf.messageRef ? messagesById.get(mf.messageRef) : undefined;\n      const hideName = refMsg?.name !== undefined && refMsg.name !== '';\n      return this.moddle.create('bpmn:MessageFlow', {\n        id: mf.id,\n        name: hideName ? undefined : mf.name,\n        sourceRef: { id: mf.sourceRef },\n        targetRef: { id: mf.targetRef },\n        messageRef: mf.messageRef ? { id: mf.messageRef } : undefined,\n      });\n    });\n\n    return collaboration;\n  }\n\n  /**\n   * Build a process element\n   */\n  private buildProcess(process: ProcessModel): ModdleElement {\n    const bpmnProcess = this.moddle.create('bpmn:Process', {\n      id: process.id,\n      name: process.name,\n      isExecutable: process.isExecutable ?? true,\n      processType: process.processType,\n      isClosed: process.isClosed,\n    });\n\n    const flowElements: ModdleElement[] = [];\n\n    // Add lane set if present\n    if (process.laneSet) {\n      bpmnProcess.laneSets = [this.buildLaneSet(process.laneSet)];\n    }\n\n    // Add flow elements\n    for (const element of process.flowElements) {\n      flowElements.push(this.buildFlowElement(element));\n    }\n\n    bpmnProcess.flowElements = flowElements;\n\n    // Add artifacts\n    if (process.artifacts.length > 0) {\n      bpmnProcess.artifacts = process.artifacts.map((a) => this.buildArtifact(a));\n    }\n\n    return bpmnProcess;\n  }\n\n  /**\n   * Build a lane set\n   */\n  private buildLaneSet(laneSet: LaneSetInfo): ModdleElement {\n    const bpmnLaneSet = this.moddle.create('bpmn:LaneSet', {\n      id: laneSet.id,\n    });\n\n    bpmnLaneSet.lanes = laneSet.lanes.map((lane) => this.buildLane(lane));\n\n    return bpmnLaneSet;\n  }\n\n  /**\n   * Build a lane\n   */\n  private buildLane(lane: LaneInfo): ModdleElement {\n    const bpmnLane = this.moddle.create('bpmn:Lane', {\n      id: lane.id,\n      name: lane.name,\n    });\n\n    // Add flow node references\n    bpmnLane.flowNodeRef = lane.flowNodeRefs.map((ref) => ({ id: ref }));\n\n    // Add child lane set if present\n    if (lane.childLaneSet) {\n      bpmnLane.childLaneSet = this.buildLaneSet(lane.childLaneSet);\n    }\n\n    return bpmnLane;\n  }\n\n  /**\n   * Build a flow element (event, task, gateway, subprocess, sequence flow)\n   */\n  private buildFlowElement(element: FlowElementModel): ModdleElement {\n    const elementType = BPMN_ELEMENT_MAP[element.type as keyof typeof BPMN_ELEMENT_MAP];\n    if (!elementType) {\n      throw new Error(`Unknown element type: ${element.type}`);\n    }\n\n    // TextAnnotation's text body must be set at creation time so the moddle\n    // serializer emits `<bpmn:text>…</bpmn:text>` correctly. Assigning it\n    // post-creation is silently ignored by the serializer.\n    const createAttrs: Record<string, unknown> = {\n      id: element.id,\n    };\n    if (element.name) {\n      createAttrs.name = element.name;\n    }\n    if (element.type === 'textAnnotation') {\n      const text = element.properties['text'];\n      if (typeof text === 'string' && text.length > 0) {\n        createAttrs.text = text;\n      }\n    }\n    const bpmnElement = this.moddle.create(elementType, createAttrs);\n\n    // Add incoming/outgoing references\n    if (element.incoming.length > 0) {\n      bpmnElement.incoming = element.incoming.map((id) => ({ id }));\n    }\n    if (element.outgoing.length > 0) {\n      bpmnElement.outgoing = element.outgoing.map((id) => ({ id }));\n    }\n\n    // Handle specific element types\n    this.applyElementProperties(bpmnElement, element);\n\n    // Add data associations (BPMN 2.0 spec: child elements of Activity)\n    this.applyDataAssociations(bpmnElement, element);\n\n    return bpmnElement;\n  }\n\n  /**\n   * Apply element-specific properties\n   */\n  private applyElementProperties(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    const props = element.properties;\n\n    // Events\n    if (element.type.includes('Event')) {\n      this.applyEventProperties(bpmnElement, element);\n    }\n\n    // Tasks\n    if (element.type.includes('Task') || element.type === 'task') {\n      this.applyTaskProperties(bpmnElement, props);\n      // Add ioSpecification if present\n      if (element.ioSpecification) {\n        bpmnElement.ioSpecification = this.buildIoSpecification(element.ioSpecification);\n      }\n    }\n\n    // Gateways\n    if (element.type.includes('Gateway')) {\n      this.applyGatewayProperties(bpmnElement, props);\n    }\n\n    // SubProcesses\n    if (element.type === 'subProcess' || element.type === 'transaction' ||\n        element.type === 'adHocSubProcess' || element.type === 'eventSubProcess') {\n      this.applySubProcessProperties(bpmnElement, props);\n\n      // Add nested flow elements for expanded subprocesses\n      if (element.flowElements && element.flowElements.length > 0) {\n        bpmnElement.flowElements = element.flowElements.map((fe) => this.buildFlowElement(fe));\n      }\n      if (element.artifacts && element.artifacts.length > 0) {\n        bpmnElement.artifacts = element.artifacts.map((a) => this.buildArtifact(a));\n      }\n    }\n\n    // Call Activity\n    if (element.type === 'callActivity') {\n      this.applyCallActivityProperties(bpmnElement, props);\n    }\n\n    // Boundary Event\n    if (element.type === 'boundaryEvent') {\n      bpmnElement.attachedToRef = { id: element.attachedToRef };\n      bpmnElement.cancelActivity = element.cancelActivity ?? true;\n    }\n\n    // Sequence Flow\n    if (element.type === 'sequenceFlow') {\n      this.applySequenceFlowProperties(bpmnElement, props);\n    }\n\n    // Loop characteristics\n    if (props.loopCharacteristics) {\n      bpmnElement.loopCharacteristics = this.buildLoopCharacteristics(\n        props.loopCharacteristics as LoopCharacteristicsProps\n      );\n    }\n  }\n\n  /**\n   * Apply event-specific properties\n   */\n  private applyEventProperties(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    const props = element.properties;\n    const eventDefType = props.eventDefinitionType as string | undefined;\n\n    if (!eventDefType || eventDefType === 'none') {\n      return;\n    }\n\n    const eventDefElementType = EVENT_DEFINITION_MAP[eventDefType as keyof typeof EVENT_DEFINITION_MAP];\n    if (!eventDefElementType) {\n      return;\n    }\n\n    const eventDef = this.moddle.create(eventDefElementType, {});\n\n    // Apply event definition specific properties\n    switch (eventDefType) {\n      case 'message':\n        if (props.messageRef) {\n          eventDef.messageRef = { id: props.messageRef as string };\n        }\n        break;\n      case 'signal':\n        if (props.signalRef) {\n          eventDef.signalRef = { id: props.signalRef as string };\n        }\n        break;\n      case 'error':\n        if (props.errorRef) {\n          eventDef.errorRef = { id: props.errorRef as string };\n        }\n        break;\n      case 'escalation':\n        if (props.escalationRef) {\n          eventDef.escalationRef = { id: props.escalationRef as string };\n        }\n        break;\n      case 'timer':\n        if (props.timerEventDefinition) {\n          const timerDef = props.timerEventDefinition as TimerEventDefinitionProps;\n          if (timerDef.timeDate) {\n            eventDef.timeDate = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeDate,\n            });\n          }\n          if (timerDef.timeDuration) {\n            eventDef.timeDuration = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeDuration,\n            });\n          }\n          if (timerDef.timeCycle) {\n            eventDef.timeCycle = this.moddle.create('bpmn:FormalExpression', {\n              body: timerDef.timeCycle,\n            });\n          }\n        }\n        break;\n      case 'conditional':\n        if (props.conditionalEventDefinition) {\n          const condDef = props.conditionalEventDefinition as ConditionalEventDefinitionProps;\n          if (condDef.condition) {\n            eventDef.condition = this.moddle.create('bpmn:FormalExpression', {\n              language: condDef.condition.language,\n              body: condDef.condition.body,\n            });\n          }\n        }\n        break;\n      case 'link':\n        if (props.linkEventDefinition) {\n          const linkDef = props.linkEventDefinition as LinkEventDefinitionProps;\n          eventDef.name = linkDef.name;\n          if (linkDef.target) {\n            eventDef.target = { id: linkDef.target };\n          }\n        }\n        break;\n    }\n\n    bpmnElement.eventDefinitions = [eventDef];\n  }\n\n  /**\n   * Apply task-specific properties\n   */\n  private applyTaskProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    // User Task properties (Camunda extensions would go here)\n    // For standard BPMN, we just set the basic properties\n    if (props.implementation) {\n      bpmnElement.implementation = props.implementation;\n    }\n\n    // Script Task\n    if (props.script) {\n      const script = props.script as ScriptProps;\n      bpmnElement.scriptFormat = script.scriptFormat;\n      bpmnElement.script = script.script;\n    }\n\n    // Send/Receive Task\n    if (props.messageRef) {\n      bpmnElement.messageRef = { id: props.messageRef as string };\n    }\n    if (props.instantiate !== undefined) {\n      bpmnElement.instantiate = props.instantiate;\n    }\n  }\n\n  /**\n   * Apply gateway-specific properties\n   */\n  private applyGatewayProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props.gatewayDirection) {\n      bpmnElement.gatewayDirection = props.gatewayDirection;\n    }\n    if (props.default) {\n      bpmnElement.default = { id: props.default as string };\n    }\n    if (props.instantiate !== undefined) {\n      bpmnElement.instantiate = props.instantiate;\n    }\n    if (props.eventGatewayType) {\n      bpmnElement.eventGatewayType = props.eventGatewayType;\n    }\n    if (props.activationCondition) {\n      bpmnElement.activationCondition = this.moddle.create('bpmn:FormalExpression', {\n        body: props.activationCondition as string,\n      });\n    }\n  }\n\n  /**\n   * Apply subprocess-specific properties\n   */\n  private applySubProcessProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props['triggeredByEvent'] !== undefined) {\n      bpmnElement['triggeredByEvent'] = props['triggeredByEvent'];\n    }\n\n    // AdHoc SubProcess\n    if (props['adHocOrdering']) {\n      bpmnElement['ordering'] = props['adHocOrdering'];\n    }\n    if (props['adHocCompletionCondition']) {\n      bpmnElement['completionCondition'] = this.moddle.create('bpmn:FormalExpression', {\n        body: props['adHocCompletionCondition'] as string,\n      });\n    }\n    if (props['cancelRemainingInstances'] !== undefined) {\n      bpmnElement['cancelRemainingInstances'] = props['cancelRemainingInstances'];\n    }\n\n    // Transaction\n    if (props['transactionProtocol']) {\n      bpmnElement['protocol'] = props['transactionProtocol'];\n    }\n  }\n\n  /**\n   * Apply call activity properties\n   */\n  private applyCallActivityProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    if (props['calledElement']) {\n      bpmnElement['calledElement'] = props['calledElement'];\n    }\n  }\n\n  /**\n   * Apply sequence flow properties\n   */\n  private applySequenceFlowProperties(bpmnElement: ModdleElement, props: Record<string, unknown>): void {\n    bpmnElement['sourceRef'] = { id: props['sourceRef'] as string };\n    bpmnElement['targetRef'] = { id: props['targetRef'] as string };\n\n    if (props['conditionExpression']) {\n      const condExpr = props['conditionExpression'] as ConditionExpressionProps;\n      bpmnElement['conditionExpression'] = this.moddle.create('bpmn:FormalExpression', {\n        language: condExpr.language,\n        body: condExpr.body,\n      });\n    }\n  }\n\n  /**\n   * Build ioSpecification element\n   */\n  private buildIoSpecification(ioSpec: IoSpecificationModel): ModdleElement {\n    const ioSpecElement = this.moddle.create('bpmn:InputOutputSpecification', {});\n\n    // Build dataInputs\n    if (ioSpec.dataInputs.length > 0) {\n      ioSpecElement.dataInputs = ioSpec.dataInputs.map((di) => {\n        return this.moddle.create('bpmn:DataInput', {\n          id: di.id,\n          name: di.name,\n          isCollection: di.isCollection,\n        });\n      });\n    }\n\n    // Build dataOutputs\n    if (ioSpec.dataOutputs.length > 0) {\n      ioSpecElement.dataOutputs = ioSpec.dataOutputs.map((dout) => {\n        return this.moddle.create('bpmn:DataOutput', {\n          id: dout.id,\n          name: dout.name,\n          isCollection: dout.isCollection,\n        });\n      });\n    }\n\n    // Build inputSets\n    if (ioSpec.inputSets.length > 0) {\n      ioSpecElement.inputSets = ioSpec.inputSets.map((is) => {\n        const inputSet = this.moddle.create('bpmn:InputSet', {\n          id: is.id,\n          name: is.name,\n        });\n        if (is.dataInputRefs.length > 0) {\n          inputSet.dataInputRefs = is.dataInputRefs.map((ref) => ({ id: ref }));\n        }\n        return inputSet;\n      });\n    }\n\n    // Build outputSets\n    if (ioSpec.outputSets.length > 0) {\n      ioSpecElement.outputSets = ioSpec.outputSets.map((os) => {\n        const outputSet = this.moddle.create('bpmn:OutputSet', {\n          id: os.id,\n          name: os.name,\n        });\n        if (os.dataOutputRefs.length > 0) {\n          outputSet.dataOutputRefs = os.dataOutputRefs.map((ref) => ({ id: ref }));\n        }\n        return outputSet;\n      });\n    }\n\n    return ioSpecElement;\n  }\n\n  /**\n   * Apply data associations (BPMN 2.0 spec: dataInputAssociation/dataOutputAssociation are child elements of Activity)\n   */\n  private applyDataAssociations(bpmnElement: ModdleElement, element: FlowElementModel): void {\n    // Add dataInputAssociations\n    if (element.dataInputAssociations && element.dataInputAssociations.length > 0) {\n      bpmnElement['dataInputAssociations'] = element.dataInputAssociations.map((assoc) => {\n        const dataInputAssoc = this.moddle.create('bpmn:DataInputAssociation', {\n          id: assoc.id,\n        });\n        // sourceRef is an array of references\n        dataInputAssoc.sourceRef = [{ id: assoc.sourceRef }];\n        return dataInputAssoc;\n      });\n    }\n\n    // Add dataOutputAssociations\n    if (element.dataOutputAssociations && element.dataOutputAssociations.length > 0) {\n      bpmnElement['dataOutputAssociations'] = element.dataOutputAssociations.map((assoc) => {\n        const dataOutputAssoc = this.moddle.create('bpmn:DataOutputAssociation', {\n          id: assoc.id,\n        });\n        // targetRef is a single reference\n        if (assoc.targetRef) {\n          dataOutputAssoc.targetRef = { id: assoc.targetRef };\n        }\n        return dataOutputAssoc;\n      });\n    }\n  }\n\n  /**\n   * Build loop characteristics\n   */\n  private buildLoopCharacteristics(props: LoopCharacteristicsProps): ModdleElement {\n    if (props.loopType === 'standard') {\n      const loop = this.moddle.create('bpmn:StandardLoopCharacteristics', {\n        testBefore: props.testBefore,\n        loopMaximum: props.loopMaximum,\n      });\n      if (props.loopCondition) {\n        loop.loopCondition = this.moddle.create('bpmn:FormalExpression', {\n          body: props.loopCondition,\n        });\n      }\n      return loop;\n    }\n\n    // Multi-instance (default)\n    const multiInstance = this.moddle.create('bpmn:MultiInstanceLoopCharacteristics', {\n      isSequential: props.isSequential ?? false,\n    });\n\n    if (props.loopCardinality) {\n      multiInstance.loopCardinality = this.moddle.create('bpmn:FormalExpression', {\n        body: props.loopCardinality,\n      });\n    }\n    if (props.loopDataInputRef) {\n      multiInstance.loopDataInputRef = { id: props.loopDataInputRef };\n    }\n    if (props.loopDataOutputRef) {\n      multiInstance.loopDataOutputRef = { id: props.loopDataOutputRef };\n    }\n    if (props.completionCondition) {\n      multiInstance.completionCondition = this.moddle.create('bpmn:FormalExpression', {\n        body: props.completionCondition,\n      });\n    }\n\n    return multiInstance;\n  }\n\n  /**\n   * Build an artifact element\n   */\n  private buildArtifact(artifact: ArtifactModel): ModdleElement {\n    const elementType = BPMN_ELEMENT_MAP[artifact.type as keyof typeof BPMN_ELEMENT_MAP];\n    if (!elementType) {\n      throw new Error(`Unknown artifact type: ${artifact.type}`);\n    }\n\n    const props = artifact.properties;\n\n    // For textAnnotation, the text body is a moddle body property — we have\n    // to pass it at create time. Setting `bpmnArtifact['text']` after the\n    // fact does not get picked up by the BPMN moddle serializer.\n    const createAttrs: Record<string, unknown> = {\n      id: artifact.id,\n    };\n    if (artifact.name) {\n      createAttrs.name = artifact.name;\n    }\n    if (artifact.type === 'textAnnotation' && props['text'] !== undefined) {\n      createAttrs.text = props['text'];\n      if (props['textFormat'] !== undefined) {\n        createAttrs.textFormat = props['textFormat'];\n      }\n    }\n    const bpmnArtifact = this.moddle.create(elementType, createAttrs);\n\n    if (artifact.type === 'dataObjectReference' || artifact.type === 'dataObject') {\n      if (props['isCollection'] !== undefined) {\n        bpmnArtifact['isCollection'] = props['isCollection'];\n      }\n      if (props['dataState']) {\n        const state = props['dataState'] as { name?: string };\n        bpmnArtifact['dataState'] = this.moddle.create('bpmn:DataState', {\n          name: state.name,\n        });\n      }\n    }\n\n    if (artifact.type === 'dataStoreReference') {\n      if (props['capacity'] !== undefined) {\n        bpmnArtifact['capacity'] = props['capacity'];\n      }\n      if (props['isUnlimited'] !== undefined) {\n        bpmnArtifact['isUnlimited'] = props['isUnlimited'];\n      }\n    }\n\n    if (artifact.type === 'group') {\n      if (props['categoryValueRef']) {\n        bpmnArtifact['categoryValueRef'] = { id: props['categoryValueRef'] as string };\n      }\n    }\n\n    if (artifact.type === 'association') {\n      if (props['sourceRef']) {\n        bpmnArtifact['sourceRef'] = { id: props['sourceRef'] as string };\n      }\n      if (props['targetRef']) {\n        bpmnArtifact['targetRef'] = { id: props['targetRef'] as string };\n      }\n      if (props['associationDirection']) {\n        bpmnArtifact['associationDirection'] = props['associationDirection'] as string;\n      }\n    }\n\n    return bpmnArtifact;\n  }\n\n  /**\n   * Build the diagram element\n   */\n  private buildDiagram(diagram: DiagramModel): ModdleElement {\n    const bpmnDiagram = this.moddle.create('bpmndi:BPMNDiagram', {\n      id: diagram.id,\n      name: diagram.name,\n    });\n\n    const plane = this.moddle.create('bpmndi:BPMNPlane', {\n      id: diagram.plane.id,\n      bpmnElement: { id: diagram.plane.bpmnElement },\n    });\n\n    const planeElements: ModdleElement[] = [];\n\n    // Add shapes\n    for (const shape of diagram.plane.shapes) {\n      planeElements.push(this.buildShape(shape));\n    }\n\n    // Add edges\n    for (const edge of diagram.plane.edges) {\n      planeElements.push(this.buildEdge(edge));\n    }\n\n    plane.planeElement = planeElements;\n    bpmnDiagram.plane = plane;\n\n    return bpmnDiagram;\n  }\n\n  /**\n   * Build a shape element\n   */\n  private buildShape(shape: ShapeModel): ModdleElement {\n    const bpmnShape = this.moddle.create('bpmndi:BPMNShape', {\n      id: shape.id,\n      bpmnElement: { id: shape.bpmnElement },\n    });\n\n    bpmnShape.bounds = this.moddle.create('dc:Bounds', {\n      x: shape.bounds.x,\n      y: shape.bounds.y,\n      width: shape.bounds.width,\n      height: shape.bounds.height,\n    });\n\n    if (shape.isExpanded !== undefined) {\n      bpmnShape.isExpanded = shape.isExpanded;\n    }\n\n    if (shape.isHorizontal !== undefined) {\n      bpmnShape.isHorizontal = shape.isHorizontal;\n    }\n\n    if (shape.label?.bounds) {\n      bpmnShape.label = this.moddle.create('bpmndi:BPMNLabel', {\n        bounds: this.moddle.create('dc:Bounds', {\n          x: shape.label.bounds.x,\n          y: shape.label.bounds.y,\n          width: shape.label.bounds.width,\n          height: shape.label.bounds.height,\n        }),\n      });\n    }\n\n    return bpmnShape;\n  }\n\n  /**\n   * Build an edge element\n   */\n  private buildEdge(edge: EdgeModel): ModdleElement {\n    const bpmnEdge = this.moddle.create('bpmndi:BPMNEdge', {\n      id: edge.id,\n      bpmnElement: { id: edge.bpmnElement },\n    });\n\n    bpmnEdge.waypoint = edge.waypoints.map((wp) =>\n      this.moddle.create('dc:Point', {\n        x: wp.x,\n        y: wp.y,\n      })\n    );\n\n    if (edge.label?.bounds) {\n      bpmnEdge.label = this.moddle.create('bpmndi:BPMNLabel', {\n        bounds: this.moddle.create('dc:Bounds', {\n          x: edge.label.bounds.x,\n          y: edge.label.bounds.y,\n          width: edge.label.bounds.width,\n          height: edge.label.bounds.height,\n        }),\n      });\n    }\n\n    return bpmnEdge;\n  }\n}\n\n// Property type definitions\ninterface TimerEventDefinitionProps {\n  timeDate?: string;\n  timeDuration?: string;\n  timeCycle?: string;\n}\n\ninterface ConditionalEventDefinitionProps {\n  condition?: {\n    type?: string;\n    language?: string;\n    body?: string;\n  };\n}\n\ninterface LinkEventDefinitionProps {\n  name?: string;\n  source?: string[];\n  target?: string;\n}\n\ninterface ScriptProps {\n  scriptFormat?: string;\n  script?: string;\n  resultVariable?: string;\n}\n\ninterface ConditionExpressionProps {\n  type?: string;\n  language?: string;\n  body?: string;\n}\n\ninterface LoopCharacteristicsProps {\n  loopType?: 'standard' | 'multiInstance';\n  isSequential?: boolean;\n  loopCardinality?: string;\n  loopDataInputRef?: string;\n  loopDataOutputRef?: string;\n  inputDataItem?: string;\n  outputDataItem?: string;\n  completionCondition?: string;\n  loopCondition?: string;\n  loopMaximum?: number;\n  testBefore?: boolean;\n}\n","/**\n * BpmnElkLayout - Main Converter Class\n *\n * Converts ELK-BPMN JSON to:\n * - BPMN 2.0 XML (with diagram interchange)\n * - Layouted ELK-BPMN JSON (with coordinates)\n */\n\nimport type { ElkBpmnGraph, ElkLayoutOptions } from './types';\nimport type { LayoutedGraph } from './types/elk-output';\nimport { ElkLayouter } from './layout';\nimport { ModelBuilder } from './transform';\nimport { BpmnXmlGenerator } from './generators';\n\nexport interface BpmnElkLayoutOptions {\n  /**\n   * ELK layout options to override defaults\n   */\n  elkOptions?: ElkLayoutOptions;\n  /**\n   * Enable layout compaction to reduce unnecessary whitespace\n   * @default true\n   */\n  enableCompaction?: boolean;\n}\n\nexport class BpmnElkLayout {\n  private layouter: ElkLayouter;\n  private modelBuilder: ModelBuilder;\n  private xmlGenerator: BpmnXmlGenerator;\n\n  constructor(options?: BpmnElkLayoutOptions) {\n    this.layouter = new ElkLayouter({\n      elkOptions: options?.elkOptions,\n      enableCompaction: options?.enableCompaction ?? true,\n    });\n    this.modelBuilder = new ModelBuilder();\n    this.xmlGenerator = new BpmnXmlGenerator();\n  }\n\n  /**\n   * Convert ELK-BPMN JSON to BPMN 2.0 XML\n   *\n   * @param input - ELK-BPMN JSON (without coordinates)\n   * @returns BPMN 2.0 XML string with diagram interchange\n   *\n   * @example\n   * ```typescript\n   * const converter = new BpmnElkLayout();\n   * const xml = await converter.to_bpmn(elkBpmnJson);\n   * console.log(xml);\n   * ```\n   */\n  async to_bpmn(input: ElkBpmnGraph): Promise<string> {\n    // Step 1: Run ELK layout to get coordinates\n    const layouted = await this.layouter.layout(input);\n\n    // Step 2: Build intermediate model\n    const model = this.modelBuilder.build(layouted);\n\n    // Step 3: Generate BPMN XML\n    const xml = await this.xmlGenerator.generate(model);\n\n    return xml;\n  }\n\n  /**\n   * Convert ELK-BPMN JSON to layouted JSON with coordinates\n   *\n   * @param input - ELK-BPMN JSON (without coordinates)\n   * @returns ELK-BPMN JSON with x, y coordinates for all nodes and edges\n   *\n   * @example\n   * ```typescript\n   * const converter = new BpmnElkLayout();\n   * const layouted = await converter.to_json(elkBpmnJson);\n   * console.log(layouted.children[0].x, layouted.children[0].y);\n   * ```\n   */\n  async to_json(input: ElkBpmnGraph): Promise<LayoutedGraph> {\n    return this.layouter.layout(input);\n  }\n\n  /**\n   * Create a new instance with different options\n   */\n  static create(options?: BpmnElkLayoutOptions): BpmnElkLayout {\n    return new BpmnElkLayout(options);\n  }\n}\n\n// Re-export types for convenience\nexport type { ElkBpmnGraph, ElkLayoutOptions } from './types';\nexport type { LayoutedGraph } from './types/elk-output';\n"],"mappings":"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","names":["BranchDestType","buildNodeMap","ARTIFACT_TYPES","result","ARTIFACT_TYPES","isContainer","DEFAULT_OPTIONS","DEFAULT_OPTIONS","DEFAULT_ELK_OPTIONS","elkNode","isContainer","segmentLength","midX","midY","process","process"]}