{"version":3,"sources":["../src/core/flow-engine.ts","../src/core/state-manager.ts","../src/core/cel-evaluator.ts","../src/utils/evaluator-factory.ts","../src/utils/error-handler.ts","../src/utils/state-executor.ts","../src/utils/schema-validator.ts","../src/utils/content-interpolator.ts","../src/utils/infer-node-types.ts","../src/utils/performance-cache.ts","../src/utils/graph-utils.ts","../src/analysis/flow-validator.ts","../src/analysis/path-tester.ts","../src/analysis/flow-analyzer.ts","../src/analysis/test-runner.ts"],"sourcesContent":["import { EventEmitter } from 'eventemitter3';\nimport { StateManager } from './state-manager';\nimport { ContentInterpolator } from '../utils/content-interpolator';\nimport {\n  AnnotatedNode,\n  Choice,\n  EngineEventData,\n  EngineOptions,\n  ExecutionResult,\n  ExecutionStep,\n  IStateManager,\n} from '../types/execution-types';\nimport {\n  NodeType,\n  StateRule,\n  ZFFlow,\n  ZFNode,\n  XFOutlet,\n} from '../types/flow-types';\nimport { inferNodeTypes } from '../utils/infer-node-types';\n\nexport class FlowEngine<\n  TState extends object = Record<string, unknown>,\n> extends EventEmitter<EngineEventData<TState>> {\n  private flow: ZFFlow;\n  private nodeTypes: Record<string, NodeType>;\n  private stateManager: IStateManager<TState>;\n  private currentNode: ZFNode | null = null;\n  private history: ExecutionStep<TState>[] = [];\n  private options: EngineOptions<TState>;\n  private contentInterpolator: ContentInterpolator;\n\n  constructor(flow: ZFFlow, options: EngineOptions<TState> = {}) {\n    super();\n    this.flow = flow;\n    this.nodeTypes = inferNodeTypes(flow.nodes);\n    this.options = {\n      enableHistory: true,\n      maxHistorySize: 100,\n      autoSave: false,\n      ...options,\n    };\n\n    // Initialize state manager with deep cloned state to avoid reference sharing\n    const initialState = {\n      ...JSON.parse(JSON.stringify(flow.globalState || {})),\n      ...JSON.parse(JSON.stringify(options.initialState || {})),\n    };\n\n    // Use provided StateManager or create default one\n    if (options.stateManager) {\n      this.stateManager = options.stateManager;\n    } else {\n      this.stateManager = new StateManager<TState>(\n        initialState as TState,\n        flow.stateRules || [],\n        {\n          expressionLanguage: flow.expressionLanguage ?? 'cel',\n          stateSchema: flow.stateSchema,\n          validateOnChange: true,\n        }\n      );\n    }\n\n    // Initialize content interpolator\n    this.contentInterpolator = new ContentInterpolator({\n      expressionLanguage: flow.expressionLanguage ?? 'cel',\n      enableLogging: options.enableLogging ?? false,\n    });\n\n    // Forward state manager events\n    this.stateManager.on(\n      'stateChange',\n      (data: { oldState: TState; newState: TState }) =>\n        this.emit('stateChange', data)\n    );\n    this.stateManager.on(\n      'error',\n      (data: {\n        error: Error;\n        context?: { type: string; rule?: StateRule };\n      }) => {\n        if (\n          data.context?.type === 'forceTransition' &&\n          data.context.rule?.target\n        ) {\n          // Handle forced transitions from state rules\n          this.handleForcedTransition(data.context.rule.target);\n        } else {\n          this.emit('error', data);\n        }\n      }\n    );\n  }\n\n  async start(): Promise<ExecutionResult<TState>> {\n    const startNode = this.findNodeById(this.flow.startNodeId);\n    if (!startNode) {\n      throw new Error(\n        `Start node with id \"${this.flow.startNodeId}\" not found`\n      );\n    }\n\n    return this.transitionToNode(startNode);\n  }\n\n  async next(choiceId?: string): Promise<ExecutionResult<TState>> {\n    if (!this.currentNode) {\n      throw new Error('No current node. Call start() first.');\n    }\n\n    let targetNode: ZFNode | null = null;\n    const currentNodeType = this.nodeTypes[this.currentNode.id];\n\n    if (choiceId) {\n      // Handle user choice (for any node type that has choices)\n      const outletResult = this.findOutletById(choiceId);\n      if (!outletResult || outletResult.fromNodeId !== this.currentNode.id) {\n        throw new Error(`Invalid choice: ${choiceId}`);\n      }\n      targetNode = this.findNodeById(outletResult.outlet.to);\n    } else {\n      if (currentNodeType === 'decision') {\n        // Handle automatic decision evaluation if no choice provided\n        targetNode = this.evaluateAutomaticDecision(this.currentNode);\n      } else {\n        // Handle automatic progression for action nodes only\n        // Decision nodes should not auto-progress - they wait for user choice\n        if (currentNodeType === 'action') {\n          const outlets = this.getOutlets(this.currentNode.id);\n          if (outlets.length === 1 && outlets[0]) {\n            targetNode = this.findNodeById(outlets[0].to);\n          }\n        }\n      }\n    }\n\n    if (!targetNode && currentNodeType !== 'decision') {\n      throw new Error('No valid transition found');\n    }\n\n    // If this is a decision node and no choice was made, don't transition\n    if (currentNodeType === 'decision' && !choiceId) {\n      return this.createExecutionResult();\n    }\n\n    if (!targetNode) {\n      throw new Error('No valid transition found');\n    }\n\n    return this.transitionToNode(targetNode, choiceId);\n  }\n\n  getCurrentNode(): AnnotatedNode | null {\n    if (!this.currentNode) {\n      return null;\n    }\n    const nodeType = this.nodeTypes[this.currentNode.id];\n    if (!nodeType) {\n      throw new Error(`Node type not found for node: ${this.currentNode.id}`);\n    }\n    return {\n      node: this.getInterpolatedNode(this.currentNode),\n      type: nodeType,\n    };\n  }\n\n  getHistory(): ExecutionStep<TState>[] {\n    return [...this.history];\n  }\n\n  getAvailableChoices(): Choice[] {\n    if (!this.currentNode) {\n      return [];\n    }\n    const currentNodeType = this.nodeTypes[this.currentNode.id];\n    if (currentNodeType === 'end') {\n      return [];\n    }\n\n    const allOutlets = this.getOutlets(this.currentNode.id);\n    const showDisabled = this.options.showDisabledChoices || false;\n    const currentState = this.stateManager.getState();\n\n    let outletsToShow: XFOutlet[];\n    let choices: Choice[];\n    const isSingleChoice = allOutlets.length === 1;\n\n    const singleChoiceDefaultLabel = 'Continue';\n\n    if (showDisabled) {\n      // Show all outlets, mark disabled ones\n      outletsToShow = allOutlets;\n      choices = outletsToShow.map((outlet, index): Choice => {\n        const isEnabled = this.evaluateOutletCondition(outlet);\n        const description =\n          outlet.metadata &&\n          'description' in outlet.metadata &&\n          typeof outlet.metadata.description === 'string'\n            ? outlet.metadata.description\n            : undefined;\n\n        // Get the label with interpolation support\n        let label = this.contentInterpolator.interpolate(\n          outlet.label\n            ? outlet.label\n            : isSingleChoice\n              ? singleChoiceDefaultLabel\n              : 'Choice ' + (index + 1), // Ensure outlets have labels\n          currentState as Record<string, unknown>\n        ).content;\n\n        return {\n          id: outlet.id,\n          label,\n          description,\n          outletId: outlet.id,\n          disabled: !isEnabled,\n          disabledReason:\n            !isEnabled && outlet.condition\n              ? 'Condition not met' // `Condition not met: ${outlet.condition}`\n              : undefined,\n        };\n      });\n    } else {\n      // Only show enabled outlets (current behavior)\n      outletsToShow = allOutlets.filter((outlet) =>\n        this.evaluateOutletCondition(outlet)\n      );\n      choices = outletsToShow.map((outlet, index): Choice => {\n        // Get the label with interpolation support\n        let label = this.contentInterpolator.interpolate(\n          outlet.label\n            ? outlet.label\n            : isSingleChoice\n              ? singleChoiceDefaultLabel\n              : 'Choice ' + (index + 1), // Ensure outlets have labels\n          currentState as Record<string, unknown>\n        ).content;\n\n        return {\n          id: outlet.id,\n          label,\n          description:\n            outlet.metadata &&\n            'description' in outlet.metadata &&\n            typeof outlet.metadata.description === 'string'\n              ? outlet.metadata.description\n              : undefined,\n          outletId: outlet.id,\n        };\n      });\n    }\n\n    // If there's only one enabled outlet forward, create a \"Continue\" choice\n    const enabledChoices = showDisabled\n      ? choices.filter((choice) => !choice.disabled)\n      : choices;\n\n    if (\n      enabledChoices.length === 1 &&\n      enabledChoices[0] &&\n      !enabledChoices[0].label?.trim()\n    ) {\n      const continueChoice = enabledChoices[0];\n      if (!continueChoice.id || !continueChoice.outletId) {\n        throw new Error('Invalid choice structure: missing required fields');\n      }\n      const targetOutlet = outletsToShow.find(\n        (p) => p.id === continueChoice.id\n      );\n      const targetNode = targetOutlet\n        ? this.findNodeById(targetOutlet.to)\n        : null;\n      return [\n        {\n          ...continueChoice,\n          id: continueChoice.id,\n          outletId: continueChoice.outletId,\n          label: singleChoiceDefaultLabel,\n          description: `Continue to ${targetNode?.title || 'next step'}`,\n        },\n        ...choices.filter((choice) => choice.disabled), // Add any disabled choices if showing them\n      ];\n    }\n\n    return choices;\n  }\n\n  isComplete(): boolean {\n    if (!this.currentNode) {\n      return false;\n    }\n    const currentNodeType = this.nodeTypes[this.currentNode.id];\n    return currentNodeType === 'end';\n  }\n\n  canGoBack(): boolean {\n    return Boolean(this.options.enableHistory) && this.history.length > 1;\n  }\n\n  goBack(): Promise<ExecutionResult<TState>> {\n    if (!this.canGoBack()) {\n      throw new Error('Cannot go back');\n    }\n\n    // Remove current step and go to previous\n    this.history.pop();\n    const previousStep = this.history[this.history.length - 1];\n    if (!previousStep) {\n      throw new Error('No previous step available');\n    }\n\n    // Restore previous state\n    this.stateManager.reset(previousStep.state);\n    this.currentNode = previousStep.node.node;\n\n    return Promise.resolve(this.createExecutionResult());\n  }\n\n  reset(): void {\n    this.currentNode = null;\n    this.history = [];\n    // Deep clone globalState to avoid reference sharing on reset\n    this.stateManager.reset(\n      JSON.parse(JSON.stringify(this.flow.globalState || {}))\n    );\n  }\n\n  getState(): TState {\n    return this.stateManager.getState();\n  }\n\n  getStateManager(): IStateManager<TState> {\n    return this.stateManager;\n  }\n\n  private async transitionToNode(\n    node: ZFNode,\n    choiceId?: string\n  ): Promise<ExecutionResult<TState>> {\n    // Exit current node\n    if (this.currentNode) {\n      this.emit('nodeExit', {\n        node: this.currentNode,\n        choice: choiceId,\n        state: this.stateManager.getState(),\n      });\n    }\n\n    // Execute outlet actions if transitioning via a specific outlet\n    if (choiceId && this.currentNode) {\n      const outletResult = this.findOutletById(choiceId);\n      if (outletResult?.outlet.actions) {\n        this.stateManager.executeActions(outletResult.outlet.actions);\n      }\n    }\n\n    // Update current node\n    this.currentNode = node;\n\n    // Execute node actions\n    if (node.actions) {\n      this.stateManager.executeActions(node.actions);\n    }\n\n    // Add to history\n    if (this.options.enableHistory) {\n      const nodeType = this.nodeTypes[node.id];\n      if (!nodeType) {\n        throw new Error(`Node type not found for node: ${node.id}`);\n      }\n      const step: ExecutionStep<TState> = {\n        node: { node, type: nodeType },\n        choice: choiceId,\n        timestamp: new Date(),\n        state: this.stateManager.getState(),\n      };\n      this.history.push(step);\n\n      // Limit history size\n      const maxSize = this.options.maxHistorySize || 100;\n      if (this.history.length > maxSize) {\n        this.history.shift();\n      }\n    }\n\n    // Emit node enter event\n    this.emit('nodeEnter', {\n      node,\n      state: this.stateManager.getState(),\n    });\n\n    // Check for auto-advance conditions\n    const availableOutlets = this.getOutlets(node.id);\n    if (this.shouldAutoAdvance(node, availableOutlets)) {\n      const selectedOutlet = this.selectAutoAdvanceOutlet(\n        node,\n        availableOutlets\n      );\n      if (!selectedOutlet) {\n        this.emit('error', {\n          error: new Error(\n            `No valid outlet found for auto-advance from node \"${node.id}\"`\n          ),\n          context: {\n            node,\n            availableOutlets,\n          },\n        });\n        return this.createExecutionResult();\n      }\n\n      const nodeTo = this.flow.nodes.find((n) => n.id === selectedOutlet.to);\n      if (!nodeTo) {\n        this.emit('error', {\n          error: new Error(`Node with id \"${selectedOutlet.to}\" not found`),\n          context: {\n            node,\n            outlet: selectedOutlet,\n          },\n        });\n        return this.createExecutionResult();\n      }\n\n      this.emit('autoAdvance', {\n        from: node,\n        to: nodeTo,\n        condition: selectedOutlet.condition,\n      });\n\n      return this.transitionToNode(nodeTo, selectedOutlet.id);\n    }\n\n    return this.createExecutionResult();\n  }\n\n  private evaluateAutomaticDecision(node: ZFNode): ZFNode | null {\n    // Get available outlets and sort by priority\n    const availableOutlets = this.getOutlets(node.id);\n    const sortedOutlets = [...availableOutlets];\n\n    // Find first outlet with satisfied condition\n    for (const outlet of sortedOutlets) {\n      if (this.evaluateOutletCondition(outlet)) {\n        return this.findNodeById(outlet.to);\n      }\n    }\n\n    return null;\n  }\n\n  private evaluateOutletCondition(outlet: XFOutlet): boolean {\n    if (!outlet.condition) return true;\n\n    try {\n      return this.stateManager.evaluateCondition(outlet.condition);\n    } catch (error) {\n      console.warn(\n        `Failed to evaluate outlet condition: ${outlet.condition}`,\n        error\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Selects the appropriate outlet for auto-advance using if-else style logic.\n   * Evaluates outlets in order, returning the first outlet whose condition is true.\n   * If no conditional outlets match, returns the default outlet (one without condition).\n   */\n  private selectAutoAdvanceOutlet(\n    _node: ZFNode,\n    availableOutlets: XFOutlet[]\n  ): XFOutlet | null {\n    // Separate conditional and default outlets\n    const conditionalOutlets = availableOutlets.filter(\n      (outlet) => outlet.condition\n    );\n    const defaultOutlets = availableOutlets.filter(\n      (outlet) => !outlet.condition\n    );\n\n    // Evaluate conditional outlets in order (if-else if logic)\n    for (const outlet of conditionalOutlets) {\n      if (this.evaluateOutletCondition(outlet)) {\n        return outlet;\n      }\n    }\n\n    // If no conditional outlet matches, use the default outlet (else clause)\n    if (defaultOutlets.length > 0 && defaultOutlets[0]) {\n      return defaultOutlets[0];\n    }\n\n    // No valid outlet found\n    return null;\n  }\n\n  /**\n   * Get a node with interpolated content and title\n   */\n  private getInterpolatedNode(node: ZFNode): ZFNode {\n    const currentState = this.stateManager.getState();\n    let interpolatedNode = { ...node };\n    let hasAnyInterpolations = false;\n    const allErrors: string[] = [];\n\n    // Interpolate node title if it has interpolations\n    if (node.title && this.contentInterpolator.hasInterpolations(node.title)) {\n      const titleResult = this.contentInterpolator.interpolate(\n        node.title,\n        currentState as Record<string, unknown>\n      );\n      interpolatedNode.title = titleResult.content;\n      hasAnyInterpolations = true;\n      allErrors.push(...titleResult.errors);\n    }\n\n    // Interpolate node content if it has interpolations\n    if (\n      node.content &&\n      this.contentInterpolator.hasInterpolations(node.content)\n    ) {\n      const contentResult = this.contentInterpolator.interpolate(\n        node.content,\n        currentState as Record<string, unknown>\n      );\n      interpolatedNode.content = contentResult.content;\n      hasAnyInterpolations = true;\n      allErrors.push(...contentResult.errors);\n    }\n\n    // Log any interpolation errors if logging is enabled\n    if (allErrors.length > 0 && this.options.enableLogging) {\n      console.warn(`Interpolation errors for node \"${node.id}\":`, allErrors);\n    }\n\n    // Return original node if no interpolations were found\n    if (!hasAnyInterpolations) {\n      return node;\n    }\n\n    return interpolatedNode;\n  }\n\n  private createExecutionResult(): ExecutionResult<TState> {\n    if (!this.currentNode) {\n      throw new Error('No current node. Call start() first.');\n    }\n    const nodeType = this.nodeTypes[this.currentNode.id];\n    if (!nodeType) {\n      throw new Error(`Node type not found for node: ${this.currentNode.id}`);\n    }\n    return {\n      node: {\n        node: this.getInterpolatedNode(this.currentNode),\n        type: nodeType,\n      },\n      choices: this.getAvailableChoices(),\n      isComplete: this.isComplete(),\n      canGoBack: this.canGoBack(),\n      state: this.stateManager.getState(),\n    };\n  }\n\n  private handleForcedTransition(targetNodeId: string): void {\n    const targetNode = this.findNodeById(targetNodeId);\n    if (!targetNode) {\n      this.emit('error', {\n        error: new Error(\n          `Target node \"${targetNodeId}\" not found for forced transition`\n        ),\n        context: { type: 'forcedTransition', targetNodeId },\n      });\n      return;\n    }\n\n    this.transitionToNode(targetNode).catch((error) => {\n      this.emit('error', {\n        error,\n        context: { type: 'forcedTransition', targetNodeId },\n      });\n    });\n  }\n\n  private shouldAutoAdvance(\n    node: ZFNode,\n    availableOutlets: XFOutlet[]\n  ): boolean {\n    if (\n      this.flow.autoAdvance === 'never' ||\n      this.options.autoAdvance === 'never'\n    ) {\n      return false;\n    }\n    if (node.isAutoAdvance) {\n      return this.selectAutoAdvanceOutlet(node, availableOutlets) !== null;\n    } else if (\n      this.flow.autoAdvance === 'always' ||\n      this.options.autoAdvance === 'always'\n    ) {\n      return this.selectAutoAdvanceOutlet(node, availableOutlets) !== null;\n    } else {\n      return false;\n    }\n  }\n\n  private findNodeById(id: string): ZFNode | null {\n    return this.flow.nodes.find((node) => node.id === id) || null;\n  }\n\n  private getOutlets(nodeId: string): XFOutlet[] {\n    const node = this.findNodeById(nodeId);\n    return node?.outlets || [];\n  }\n\n  private findOutletById(\n    outletId: string\n  ): { outlet: XFOutlet; fromNodeId: string } | null {\n    for (const node of this.flow.nodes) {\n      if (node.outlets) {\n        const outlet = node.outlets.find((p) => p.id === outletId);\n        if (outlet) {\n          return { outlet, fromNodeId: node.id };\n        }\n      }\n    }\n    return null;\n  }\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type { JSONSchema7 } from 'json-schema';\nimport { ExpressionEvaluator } from './expression-evaluator';\nimport { StateAction, StateRule } from '../types/flow-types';\nimport { ExpressionLanguage } from '../types/expression-types';\nimport { IStateManager, StateManagerOptions } from '../types/execution-types';\nimport { StateActionExecutor } from '../utils/state-executor';\nimport {\n  globalSchemaValidator,\n  SchemaValidator,\n} from '../utils/schema-validator';\nimport { EvaluatorFactory } from '../utils/evaluator-factory';\n\nexport class StateManager<TState extends object = Record<string, unknown>>\n  extends EventEmitter\n  implements IStateManager<TState>\n{\n  private state: TState;\n  private rules: StateRule[];\n  private expressionLanguage: ExpressionLanguage;\n  private evaluators: Record<string, ExpressionEvaluator>;\n  private stateSchema: JSONSchema7 | undefined;\n  private schemaValidator: SchemaValidator;\n  private validateOnChange: boolean;\n  private actionExecutor: StateActionExecutor<TState>;\n\n  constructor(\n    initialState: TState = {} as TState,\n    rules: StateRule[] = [],\n    options: StateManagerOptions = {}\n  ) {\n    super();\n    this.rules = rules;\n    this.expressionLanguage = options.expressionLanguage ?? 'cel';\n    this.evaluators = EvaluatorFactory.getDefaultEvaluators();\n    this.stateSchema = options.stateSchema;\n    this.schemaValidator = globalSchemaValidator;\n    this.validateOnChange = options.validateOnChange ?? true;\n\n    // Validate and set initial state\n    this.validateState(initialState, 'Initial state validation failed');\n    this.state = { ...initialState };\n\n    // Initialize shared action executor\n    this.actionExecutor = new StateActionExecutor<TState>({\n      expressionLanguage: this.expressionLanguage,\n      evaluators: this.evaluators,\n      enableLogging: true,\n    });\n  }\n\n  getState(): TState {\n    // Deep clone the state to avoid reference sharing for arrays/objects\n    return JSON.parse(JSON.stringify(this.state)) as TState;\n  }\n\n  setState(newState: Partial<TState>): void {\n    // Deep clone the state to avoid reference sharing for arrays/objects\n    const oldState = JSON.parse(JSON.stringify(this.state)) as TState;\n    const updatedState = { ...this.state, ...newState } as TState;\n\n    // Validate new state if schema is provided\n    this.validateState(updatedState, 'State update validation failed');\n\n    this.state = updatedState;\n    this.emit('stateChange', { oldState, newState: this.getState() });\n    this.evaluateRules();\n  }\n\n  executeActions(actions: StateAction[]): void {\n    // Deep clone the state to avoid reference sharing for arrays/objects\n    const oldState = JSON.parse(JSON.stringify(this.state)) as TState;\n\n    const result = this.actionExecutor.executeActions(actions, this.state);\n    const newState = result.newState;\n\n    // Validate new state if schema is provided\n    this.validateState(newState, 'Action execution validation failed');\n\n    this.state = newState;\n\n    this.emit('stateChange', { oldState, newState: this.getState() });\n    this.evaluateRules();\n  }\n\n  evaluateCondition(expression: string): boolean {\n    return this.actionExecutor.evaluateCondition(expression, this.state);\n  }\n\n  private evaluateRules(): void {\n    for (const rule of this.rules) {\n      if (this.evaluateCondition(rule.condition)) {\n        this.executeRule(rule);\n      }\n    }\n  }\n\n  private executeRule(rule: StateRule): void {\n    switch (rule.action) {\n      case 'forceTransition':\n        this.emit('error', {\n          error: new Error(`Force transition to ${rule.target}`),\n          context: { rule, type: 'forceTransition' },\n        });\n        break;\n\n      case 'setState':\n        if (rule.target && rule.value !== undefined) {\n          // Use the shared executor for state setting\n          const result = this.actionExecutor.executeAction(\n            { type: 'set', target: rule.target, value: rule.value },\n            this.state\n          );\n          if (result.success) {\n            this.state = result.newState;\n          }\n        }\n        break;\n\n      case 'triggerEvent':\n        // Custom event handling can be implemented here\n        break;\n    }\n  }\n\n  reset(newState: Partial<TState> = {} as Partial<TState>): void {\n    // Deep clone the old state to avoid reference sharing for arrays/objects\n    const oldState = JSON.parse(JSON.stringify(this.state)) as TState;\n    // Deep clone the new state to avoid reference sharing for arrays/objects\n    const resetState = JSON.parse(JSON.stringify(newState)) as TState;\n\n    // Validate new state if schema is provided\n    this.validateState(resetState, 'State reset validation failed');\n\n    this.state = resetState;\n    this.emit('stateChange', { oldState, newState: this.getState() });\n    this.evaluateRules();\n  }\n\n  /**\n   * Validate state against the JSON schema if one is provided\n   */\n  private validateState(state: unknown, errorPrefix: string): void {\n    if (!this.stateSchema || !this.validateOnChange) {\n      return;\n    }\n\n    try {\n      const result = this.schemaValidator.validate(state, this.stateSchema);\n\n      if (!result.isValid) {\n        const error = new Error(`${errorPrefix}: ${result.errors.join(', ')}`);\n        this.emit('error', {\n          error,\n          context: { type: 'schemaValidation', errors: result.errors },\n        });\n        throw error;\n      }\n    } catch (error) {\n      if (error instanceof Error) {\n        // Re-throw validation errors\n        throw error;\n      }\n\n      // Handle unexpected errors\n      const validationError = new Error(\n        `${errorPrefix}: Unexpected validation error`\n      );\n      this.emit('error', {\n        error: validationError,\n        context: { type: 'schemaValidation', originalError: error },\n      });\n      throw validationError;\n    }\n  }\n}\n","import { parse, evaluate, Failure, Success } from 'cel-js';\nimport type {\n  ExpressionEvaluator,\n  ExpressionEvaluationOptions,\n  ExpressionCompilationOptions,\n  ExpressionCompilationResult,\n} from './expression-evaluator';\n\ntype CstType = Success['cst'];\n\n/**\n * CelEvaluator compiles and evaluates CEL expressions against a state context.\n * It caches compiled runtimes per expression for performance.\n */\nexport class CelEvaluator implements ExpressionEvaluator {\n  private cache: Map<string, CstType> = new Map();\n\n  compile(\n    expression: string,\n    options?: ExpressionCompilationOptions\n  ): ExpressionCompilationResult {\n    const parsed = parse(expression);\n    if (parsed.isSuccess && options?.cache) {\n      this.cache.set(expression, parsed.cst);\n    }\n    return {\n      success: parsed.isSuccess,\n      error: !parsed.isSuccess\n        ? (parsed as Failure).errors.join(', ')\n        : undefined,\n    };\n  }\n\n  evaluate(\n    expression: string,\n    context: unknown,\n    { onError }: ExpressionEvaluationOptions = { onError: undefined }\n  ): unknown {\n    if (!expression || typeof expression !== 'string') return undefined;\n\n    try {\n      let cst = this.cache.get(expression);\n      if (!cst) {\n        const parsed = parse(expression);\n        if (parsed.isSuccess) {\n          cst = parsed.cst;\n          this.cache.set(expression, cst);\n        } else {\n          onError?.(new Error((parsed as Failure).errors.join(', ')));\n          return undefined;\n        }\n      }\n\n      const result = evaluate(\n        cst,\n        context && typeof context === 'object'\n          ? { ...(context as Record<string, unknown>) }\n          : {}\n      );\n\n      return result;\n    } catch (err) {\n      // Any evaluation failure is a false condition.\n      // Callers can decide how to log/report.\n      onError?.(err instanceof Error ? err : new Error(err as string));\n      return undefined;\n    }\n  }\n\n  clearCache(): void {\n    this.cache.clear();\n  }\n}\n","//\n\nimport { ExpressionLanguage } from '../types/expression-types';\nimport { CelEvaluator } from '../core/cel-evaluator';\nimport { ExpressionEvaluator } from '../core/expression-evaluator';\n\n/**\n * Factory for creating expression evaluators\n */\nexport class EvaluatorFactory {\n  private static defaultEvaluators: Record<string, ExpressionEvaluator> | null =\n    null;\n\n  /**\n   * Get the default set of evaluators (singleton pattern for performance)\n   */\n  static getDefaultEvaluators(): Record<string, ExpressionEvaluator> {\n    if (!this.defaultEvaluators) {\n      this.defaultEvaluators = {\n        cel: new CelEvaluator(),\n      };\n    }\n    return this.defaultEvaluators;\n  }\n\n  /**\n   * Create evaluators with optional custom ones\n   */\n  static createEvaluators(\n    customEvaluators?: Record<string, ExpressionEvaluator>\n  ): Record<string, ExpressionEvaluator> {\n    if (customEvaluators) {\n      return { ...this.getDefaultEvaluators(), ...customEvaluators };\n    }\n    return this.getDefaultEvaluators();\n  }\n\n  /**\n   * Get a specific evaluator by language\n   */\n  static getEvaluator(\n    language: ExpressionLanguage,\n    evaluators?: Record<string, ExpressionEvaluator>\n  ): ExpressionEvaluator {\n    const allEvaluators = evaluators ?? this.getDefaultEvaluators();\n    const evaluator = allEvaluators[language];\n\n    if (!evaluator) {\n      throw new Error(`No evaluator found for language: ${language}`);\n    }\n\n    return evaluator;\n  }\n}\n","/**\n * Comprehensive error handling utilities for ZFlo\n */\n\nexport interface ZFloError {\n  code: string;\n  message: string;\n  context?: Record<string, unknown>;\n  cause?: Error;\n}\n\nexport class ZFloErrorHandler {\n  private enableLogging: boolean;\n\n  constructor(enableLogging = false) {\n    this.enableLogging = enableLogging;\n  }\n\n  /**\n   * Create a standardized ZFlo error\n   */\n  createError(\n    code: string,\n    message: string,\n    context?: Record<string, unknown>,\n    cause?: Error\n  ): ZFloError {\n    return {\n      code,\n      message,\n      context,\n      cause,\n    };\n  }\n\n  /**\n   * Handle and log errors consistently\n   */\n  handleError(error: unknown, context?: Record<string, unknown>): ZFloError {\n    let ZFloError: ZFloError;\n\n    if (this.isZFloError(error)) {\n      ZFloError = error;\n    } else if (error instanceof Error) {\n      ZFloError = this.createError(\n        'UNKNOWN_ERROR',\n        error.message,\n        context,\n        error\n      );\n    } else {\n      ZFloError = this.createError('UNKNOWN_ERROR', String(error), context);\n    }\n\n    if (this.enableLogging) {\n      console.error('ZFlo Error:', ZFloError);\n    }\n\n    return ZFloError;\n  }\n\n  /**\n   * Safe execution wrapper with error handling\n   */\n  async safeExecute<T>(\n    operation: () => Promise<T>,\n    fallback: T,\n    context?: Record<string, unknown>\n  ): Promise<{ success: boolean; result: T; error?: ZFloError }> {\n    try {\n      const result = await operation();\n      return { success: true, result };\n    } catch (error) {\n      const ZFloError = this.handleError(error, context);\n      return { success: false, result: fallback, error: ZFloError };\n    }\n  }\n\n  /**\n   * Safe synchronous execution wrapper\n   */\n  safeExecuteSync<T>(\n    operation: () => T,\n    fallback: T,\n    context?: Record<string, unknown>\n  ): { success: boolean; result: T; error?: ZFloError } {\n    try {\n      const result = operation();\n      return { success: true, result };\n    } catch (error) {\n      const ZFloError = this.handleError(error, context);\n      return { success: false, result: fallback, error: ZFloError };\n    }\n  }\n\n  /**\n   * Validate if an object is an ZFlo error\n   */\n  private isZFloError(obj: unknown): obj is ZFloError {\n    return (\n      typeof obj === 'object' &&\n      obj !== null &&\n      'code' in obj &&\n      'message' in obj\n    );\n  }\n}\n\n/**\n * Common error codes used throughout ZFlo\n */\nexport const ErrorCodes = {\n  // Flow execution errors\n  NODE_NOT_FOUND: 'NODE_NOT_FOUND',\n  PATH_NOT_FOUND: 'PATH_NOT_FOUND',\n  INVALID_TRANSITION: 'INVALID_TRANSITION',\n  CONDITION_EVALUATION_FAILED: 'CONDITION_EVALUATION_FAILED',\n\n  // State management errors\n  STATE_ACTION_FAILED: 'STATE_ACTION_FAILED',\n  INVALID_STATE_VALUE: 'INVALID_STATE_VALUE',\n\n  // Validation errors\n  VALIDATION_FAILED: 'VALIDATION_FAILED',\n  INVALID_FLOW: 'INVALID_FLOW',\n\n  // Expression evaluation errors\n  EXPRESSION_COMPILATION_FAILED: 'EXPRESSION_COMPILATION_FAILED',\n  EXPRESSION_EVALUATION_FAILED: 'EXPRESSION_EVALUATION_FAILED',\n  UNSUPPORTED_EXPRESSION_LANGUAGE: 'UNSUPPORTED_EXPRESSION_LANGUAGE',\n\n  // General errors\n  UNKNOWN_ERROR: 'UNKNOWN_ERROR',\n  OPERATION_TIMEOUT: 'OPERATION_TIMEOUT',\n} as const;\n\n/**\n * Global error handler instance\n */\nexport const globalErrorHandler = new ZFloErrorHandler();\n\n/**\n * Utility functions for common error scenarios\n */\nexport function createNodeNotFoundError(nodeId: string): ZFloError {\n  return globalErrorHandler.createError(\n    ErrorCodes.NODE_NOT_FOUND,\n    `Node not found: ${nodeId}`,\n    { nodeId }\n  );\n}\n\nexport function createConditionEvaluationError(\n  condition: string,\n  cause?: Error\n): ZFloError {\n  return globalErrorHandler.createError(\n    ErrorCodes.CONDITION_EVALUATION_FAILED,\n    `Failed to evaluate condition: ${condition}`,\n    { condition },\n    cause\n  );\n}\n\nexport function createStateActionError(\n  action: string,\n  cause?: Error\n): ZFloError {\n  return globalErrorHandler.createError(\n    ErrorCodes.STATE_ACTION_FAILED,\n    `Failed to execute state action: ${action}`,\n    { action },\n    cause\n  );\n}\n","//\n\nimport { ExpressionEvaluator } from '../core/expression-evaluator';\nimport { EvaluatorFactory } from './evaluator-factory';\nimport {\n  createStateActionError,\n  createConditionEvaluationError,\n} from './error-handler';\nimport { ExpressionLanguage } from '../types/expression-types';\nimport { StateAction } from '../types/flow-types';\n\nexport interface StateExecutorOptions {\n  expressionLanguage?: ExpressionLanguage;\n  evaluators?: Record<string, ExpressionEvaluator>;\n  enableLogging?: boolean;\n}\n\nexport interface StateExecutionResult<\n  TState extends object = Record<string, unknown>,\n> {\n  success: boolean;\n  newState: TState;\n  errors: string[];\n}\n\n/**\n * Shared state action executor that eliminates duplication between\n * StateManager and PathTester action execution logic.\n */\nexport class StateActionExecutor<\n  TState extends object = Record<string, unknown>,\n> {\n  private evaluators: Record<string, ExpressionEvaluator>;\n  private expressionLanguage: ExpressionLanguage;\n  private enableLogging: boolean;\n\n  constructor(options: StateExecutorOptions = {}) {\n    this.expressionLanguage = options.expressionLanguage ?? 'cel';\n    this.enableLogging = options.enableLogging ?? false;\n    this.evaluators =\n      options.evaluators ?? EvaluatorFactory.getDefaultEvaluators();\n  }\n\n  /**\n   * Execute a single state action on the provided state\n   */\n  executeAction(\n    action: StateAction,\n    state: TState\n  ): StateExecutionResult<TState> {\n    const newState = { ...state };\n    const errors: string[] = [];\n\n    try {\n      const { type, target, value, expression } = action;\n\n      switch (type) {\n        case 'set':\n          if (expression) {\n            const evaluatedValue = this.evaluateExpression(\n              expression,\n              newState\n            );\n            this.setNestedValue(newState, target, evaluatedValue);\n            if (this.enableLogging) {\n              console.log(`Setting ${target} to ${evaluatedValue}.`);\n            }\n          } else {\n            this.setNestedValue(newState, target, value);\n          }\n          break;\n\n        default:\n          throw new Error(`Unknown action type: ${type}`);\n      }\n\n      return {\n        success: true,\n        newState,\n        errors,\n      };\n    } catch (error) {\n      const ZFloError = createStateActionError(\n        `${action.type}:${action.target}`,\n        error instanceof Error ? error : undefined\n      );\n      errors.push(ZFloError.message);\n\n      return {\n        success: false,\n        newState: state, // Return original state on error\n        errors,\n      };\n    }\n  }\n\n  /**\n   * Execute multiple state actions in sequence\n   */\n  executeActions(\n    actions: StateAction[],\n    initialState: TState\n  ): StateExecutionResult<TState> {\n    let currentState = { ...initialState };\n    const allErrors: string[] = [];\n\n    for (const action of actions) {\n      const result = this.executeAction(action, currentState);\n\n      if (result.success) {\n        currentState = result.newState;\n      } else {\n        allErrors.push(...result.errors);\n        // Continue with other actions even if one fails\n      }\n    }\n\n    return {\n      success: allErrors.length === 0,\n      newState: currentState,\n      errors: allErrors,\n    };\n  }\n\n  /**\n   * Evaluate a condition expression\n   */\n  evaluateCondition(expression: string, state: TState): boolean {\n    try {\n      const expr = (expression || '').trim();\n      if (!expr) return true;\n\n      const evaluator = this.evaluators[this.expressionLanguage];\n      if (!evaluator) {\n        throw new Error(\n          `Unsupported expression language: ${this.expressionLanguage}`\n        );\n      }\n\n      const result = evaluator.evaluate(expr, state);\n\n      if (typeof result === 'boolean') {\n        return result;\n      }\n\n      if (this.enableLogging) {\n        console.warn(\n          `Condition ${expr} evaluated to ${result}`,\n          'Expected boolean result'\n        );\n      }\n\n      return false;\n    } catch (error) {\n      const ZFloError = createConditionEvaluationError(\n        expression,\n        error instanceof Error ? error : undefined\n      );\n\n      if (this.enableLogging) {\n        console.warn('ZFlo Condition Evaluation Error:', ZFloError);\n      }\n      return false;\n    }\n  }\n\n  /**\n   * Evaluate an expression and return the result\n   */\n  private evaluateExpression(expression: string, state: TState): unknown {\n    let evalError: Error | undefined;\n\n    const evaluator = this.evaluators[this.expressionLanguage];\n    if (!evaluator) {\n      throw new Error(\n        `Unsupported expression language: ${this.expressionLanguage}`\n      );\n    }\n\n    const value = evaluator.evaluate(expression, state, {\n      onError: (err) => {\n        evalError = err;\n      },\n    });\n\n    if (evalError) {\n      throw evalError;\n    }\n\n    return value;\n  }\n\n  /**\n   * Set nested value in state using dot notation\n   */\n  private setNestedValue(state: TState, path: string, value: unknown): void {\n    if (!(typeof state === 'object' && state !== null)) {\n      throw new Error('State must be an object');\n    }\n\n    const keys = path.split('.');\n    const lastKey = keys.pop();\n\n    if (!lastKey) {\n      throw new Error(`Invalid path: ${path}`);\n    }\n\n    const target = keys.reduce(\n      (obj: Record<string, unknown>, key: string) => {\n        if (!(key in obj)) obj[key] = {};\n        const prop = obj[key];\n\n        if (!prop) {\n          throw new Error(`Invalid path: ${path}`);\n        }\n\n        if (typeof prop !== 'object') {\n          throw new Error(`Invalid path: ${path}`);\n        }\n\n        return prop as Record<string, unknown>;\n      },\n      state as Record<string, unknown>\n    );\n\n    target[lastKey] = value;\n  }\n}\n\n/**\n * Create a default state action executor\n */\nexport function createStateExecutor(\n  options: StateExecutorOptions = {}\n): StateActionExecutor {\n  return new StateActionExecutor(options);\n}\n\n/**\n * Utility function to execute actions on state\n */\nexport function executeStateActions<\n  TState extends object = Record<string, unknown>,\n>(\n  actions: StateAction[],\n  state: TState,\n  options: StateExecutorOptions = {}\n): StateExecutionResult<TState> {\n  const executor = new StateActionExecutor<TState>(options);\n  return executor.executeActions(actions, state);\n}\n\n/**\n * Utility function to evaluate a condition\n */\nexport function evaluateCondition<\n  TState extends object = Record<string, unknown>,\n>(\n  expression: string,\n  state: TState,\n  options: StateExecutorOptions = {}\n): boolean {\n  const executor = new StateActionExecutor<TState>(options);\n  return executor.evaluateCondition(expression, state);\n}\n","import Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport type { JSONSchema7 } from 'json-schema';\n\nexport interface SchemaValidationResult {\n  isValid: boolean;\n  errors: string[];\n  data?: unknown;\n}\n\nexport interface SchemaValidationError extends Error {\n  validationErrors: string[];\n  data: unknown;\n}\n\n/**\n * Utility class for JSON Schema validation using Ajv\n */\nexport class SchemaValidator {\n  private ajv: Ajv;\n  private compiledSchemas = new Map<string, ValidateFunction>();\n\n  constructor() {\n    this.ajv = new Ajv({\n      allErrors: true, // Collect all validation errors\n      removeAdditional: false, // Don't remove additional properties\n      useDefaults: true, // Apply default values from schema\n      coerceTypes: false, // Don't coerce types automatically\n    });\n\n    // Add format validators (email, date, uri, etc.)\n    addFormats(this.ajv);\n  }\n\n  /**\n   * Compile and cache a JSON schema for validation\n   */\n  compileSchema(schema: JSONSchema7, schemaId?: string): ValidateFunction {\n    const id = schemaId || JSON.stringify(schema);\n\n    let validator = this.compiledSchemas.get(id);\n    if (!validator) {\n      try {\n        validator = this.ajv.compile(schema);\n        this.compiledSchemas.set(id, validator);\n      } catch (error) {\n        throw new Error(\n          `Failed to compile schema: ${error instanceof Error ? error.message : String(error)}`\n        );\n      }\n    }\n\n    return validator;\n  }\n\n  /**\n   * Validate data against a JSON schema\n   */\n  validate(\n    data: unknown,\n    schema: JSONSchema7,\n    schemaId?: string\n  ): SchemaValidationResult {\n    try {\n      const validator = this.compileSchema(schema, schemaId);\n      const isValid = validator(data);\n\n      if (isValid) {\n        return {\n          isValid: true,\n          errors: [],\n          data,\n        };\n      }\n\n      const errors = this.formatValidationErrors(validator.errors || []);\n      return {\n        isValid: false,\n        errors,\n        data,\n      };\n    } catch (error) {\n      return {\n        isValid: false,\n        errors: [\n          `Schema validation failed: ${error instanceof Error ? error.message : String(error)}`,\n        ],\n        data,\n      };\n    }\n  }\n\n  /**\n   * Validate data and throw an error if validation fails\n   */\n  validateOrThrow(data: unknown, schema: JSONSchema7, schemaId?: string): void {\n    const result = this.validate(data, schema, schemaId);\n\n    if (!result.isValid) {\n      const error = new Error(\n        `Schema validation failed: ${result.errors.join(', ')}`\n      ) as SchemaValidationError;\n      error.validationErrors = result.errors;\n      error.data = data;\n      throw error;\n    }\n  }\n\n  /**\n   * Format Ajv validation errors into human-readable messages\n   */\n  private formatValidationErrors(errors: ErrorObject[]): string[] {\n    return errors.map((error) => {\n      const path = error.instancePath || 'root';\n      const message = error.message || 'validation failed';\n\n      switch (error.keyword) {\n        case 'required':\n          return `Missing required property: ${error.params?.missingProperty} at ${path}`;\n        case 'type':\n          return `Invalid type at ${path}: expected ${error.params?.type}, got ${typeof error.data}`;\n        case 'minimum':\n          return `Value at ${path} (${error.data}) is below minimum ${error.params?.limit}`;\n        case 'maximum':\n          return `Value at ${path} (${error.data}) is above maximum ${error.params?.limit}`;\n        case 'minLength':\n          return `String at ${path} is too short (minimum length: ${error.params?.limit})`;\n        case 'maxLength':\n          return `String at ${path} is too long (maximum length: ${error.params?.limit})`;\n        case 'pattern':\n          return `String at ${path} does not match required pattern`;\n        case 'format':\n          return `Invalid format at ${path}: expected ${error.params?.format}`;\n        case 'additionalProperties':\n          return `Unexpected property '${error.params?.additionalProperty}' at ${path}`;\n        default:\n          return `Validation error at ${path}: ${message}`;\n      }\n    });\n  }\n\n  /**\n   * Clear compiled schema cache\n   */\n  clearCache(): void {\n    this.compiledSchemas.clear();\n  }\n\n  /**\n   * Get cache statistics\n   */\n  getCacheStats(): { size: number; schemas: string[] } {\n    return {\n      size: this.compiledSchemas.size,\n      schemas: Array.from(this.compiledSchemas.keys()),\n    };\n  }\n}\n\n// Global instance for reuse across the application\nexport const globalSchemaValidator = new SchemaValidator();\n","/**\n * Content interpolation utilities for ZFlo\n * Supports ${expression} syntax for dynamic content\n */\n\nimport { EvaluatorFactory } from './evaluator-factory';\nimport { ExpressionLanguage } from '../types/expression-types';\n\nexport interface ContentInterpolationOptions {\n  expressionLanguage?: ExpressionLanguage;\n  enableLogging?: boolean;\n}\n\nexport interface InterpolationResult {\n  content: string;\n  hasInterpolations: boolean;\n  errors: string[];\n}\n\n/**\n * Content interpolator that processes ${expression} placeholders\n */\nexport class ContentInterpolator {\n  private expressionLanguage: ExpressionLanguage;\n  private enableLogging: boolean;\n  private evaluators: ReturnType<typeof EvaluatorFactory.getDefaultEvaluators>;\n\n  constructor(options: ContentInterpolationOptions = {}) {\n    this.expressionLanguage = options.expressionLanguage ?? 'cel';\n    this.enableLogging = options.enableLogging ?? false;\n    this.evaluators = EvaluatorFactory.getDefaultEvaluators();\n  }\n\n  /**\n   * Interpolate expressions in content string\n   */\n  interpolate(\n    content: string,\n    state: Record<string, unknown>\n  ): InterpolationResult {\n    if (!content || typeof content !== 'string') {\n      return {\n        content: content || '',\n        hasInterpolations: false,\n        errors: [],\n      };\n    }\n\n    const errors: string[] = [];\n    let hasInterpolations = false;\n\n    // First, handle escaped interpolations by temporarily replacing them\n    const escapedPlaceholder = '___ZFLO_ESCAPED_INTERPOLATION___';\n    let escapedInterpolations: string[] = [];\n\n    // Replace escaped ${...} with placeholders\n    let processedContent = content.replace(\n      /\\\\\\$\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/g,\n      (_match, expression) => {\n        escapedInterpolations.push(`\\${${expression}}`);\n        return `${escapedPlaceholder}${escapedInterpolations.length - 1}`;\n      }\n    );\n\n    // Match ${...} patterns, supporting nested braces\n    const interpolationRegex = /\\$\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/g;\n\n    const interpolatedContent = processedContent.replace(\n      interpolationRegex,\n      (_match, expression) => {\n        hasInterpolations = true;\n\n        try {\n          const result = this.evaluateExpression(expression.trim(), state);\n\n          // Handle undefined/null results\n          if (result === undefined || result === null) {\n            const errorMsg = `Variable \"${expression}\" is undefined`;\n            errors.push(errorMsg);\n\n            if (this.enableLogging) {\n              console.warn('ZFlo Content Interpolation Warning:', errorMsg);\n            }\n\n            return '';\n          }\n\n          return this.formatValue(result);\n        } catch (error) {\n          const errorMsg = `Failed to interpolate \"${expression}\": ${\n            error instanceof Error ? error.message : String(error)\n          }`;\n\n          errors.push(errorMsg);\n\n          if (this.enableLogging) {\n            console.warn('ZFlo Content Interpolation Error:', errorMsg);\n          }\n\n          // Return empty string for missing variables, original placeholder for syntax errors\n          return '';\n        }\n      }\n    );\n\n    // Restore escaped interpolations\n    const finalContent = interpolatedContent.replace(\n      new RegExp(`${escapedPlaceholder}(\\\\d+)`, 'g'),\n      (match, ...args) => {\n        return escapedInterpolations[parseInt(args[0])] || match;\n      }\n    );\n\n    return {\n      content: finalContent,\n      hasInterpolations,\n      errors,\n    };\n  }\n\n  /**\n   * Check if content contains interpolation expressions\n   */\n  hasInterpolations(content: string): boolean {\n    if (!content || typeof content !== 'string') return false;\n    return /\\$\\{[^}]+\\}/.test(content);\n  }\n\n  /**\n   * Extract all interpolation expressions from content\n   */\n  extractExpressions(content: string): string[] {\n    if (!content || typeof content !== 'string') return [];\n\n    const expressions: string[] = [];\n    const interpolationRegex = /\\$\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}/g;\n    let match;\n\n    while ((match = interpolationRegex.exec(content)) !== null) {\n      if (!match || !match[1]) {\n        continue;\n      }\n      expressions.push(match[1].trim());\n    }\n\n    return expressions;\n  }\n\n  /**\n   * Validate all expressions in content\n   */\n  validateExpressions(content: string): { valid: boolean; errors: string[] } {\n    const expressions = this.extractExpressions(content);\n    const errors: string[] = [];\n\n    for (const expression of expressions) {\n      try {\n        const evaluator = this.evaluators[this.expressionLanguage];\n        if (!evaluator) {\n          errors.push(\n            `Unsupported expression language: ${this.expressionLanguage}`\n          );\n          continue;\n        }\n\n        // Try to compile the expression to check syntax\n        if (evaluator.compile) {\n          const result = evaluator.compile(expression, { cache: false });\n          if (!result.success && result.error) {\n            errors.push(`Invalid expression \"${expression}\": ${result.error}`);\n          }\n        }\n      } catch (error) {\n        errors.push(\n          `Expression validation failed for \"${expression}\": ${\n            error instanceof Error ? error.message : String(error)\n          }`\n        );\n      }\n    }\n\n    return {\n      valid: errors.length === 0,\n      errors,\n    };\n  }\n\n  /**\n   * Evaluate a single expression\n   */\n  private evaluateExpression(\n    expression: string,\n    state: Record<string, unknown>\n  ): unknown {\n    const evaluator = this.evaluators[this.expressionLanguage];\n    if (!evaluator) {\n      throw new Error(\n        `Unsupported expression language: ${this.expressionLanguage}`\n      );\n    }\n\n    let evaluationError: Error | undefined;\n\n    const result = evaluator.evaluate(expression, state, {\n      onError: (err) => {\n        evaluationError = err;\n      },\n    });\n\n    if (evaluationError) {\n      throw evaluationError;\n    }\n\n    return result;\n  }\n\n  /**\n   * Format a value for display in content\n   */\n  private formatValue(value: unknown): string {\n    if (value === null || value === undefined) {\n      return '';\n    }\n\n    if (typeof value === 'string') {\n      return value;\n    }\n\n    if (typeof value === 'number') {\n      // Format numbers nicely\n      return Number.isInteger(value) ? value.toString() : value.toFixed(2);\n    }\n\n    if (typeof value === 'boolean') {\n      return value ? 'true' : 'false';\n    }\n\n    if (Array.isArray(value)) {\n      return value.map((v) => this.formatValue(v)).join(', ');\n    }\n\n    if (typeof value === 'object') {\n      try {\n        return JSON.stringify(value);\n      } catch {\n        return '[Object]';\n      }\n    }\n\n    return String(value);\n  }\n}\n\n/**\n * Global content interpolator instance for convenience\n */\nlet globalInterpolator: ContentInterpolator | null = null;\n\n/**\n * Get or create the global content interpolator\n */\nexport function getContentInterpolator(\n  options?: ContentInterpolationOptions\n): ContentInterpolator {\n  if (!globalInterpolator || options) {\n    globalInterpolator = new ContentInterpolator(options);\n  }\n  return globalInterpolator;\n}\n\n/**\n * Convenience function to interpolate content\n */\nexport function interpolateContent(\n  content: string,\n  state: Record<string, unknown>,\n  options?: ContentInterpolationOptions\n): string {\n  const interpolator = getContentInterpolator(options);\n  const result = interpolator.interpolate(content, state);\n  return result.content;\n}\n\n/**\n * Convenience function to check if content has interpolations\n */\nexport function hasContentInterpolations(content: string): boolean {\n  const interpolator = getContentInterpolator();\n  return interpolator.hasInterpolations(content);\n}\n","import { ZFNode, NodeType } from '../types/flow-types';\n\nexport function inferNodeTypes(nodes: ZFNode[]): Record<string, NodeType> {\n  const incoming = new Map<string, number>();\n  const outgoing = new Map<string, number>();\n\n  for (const n of nodes) {\n    outgoing.set(n.id, n.outlets?.length ?? 0);\n    for (const p of n.outlets ?? []) {\n      incoming.set(p.to, (incoming.get(p.to) ?? 0) + 1);\n    }\n  }\n\n  const typeMap: Record<string, NodeType> = {};\n\n  for (const n of nodes) {\n    const out = outgoing.get(n.id) ?? 0;\n    const inc = incoming.get(n.id) ?? 0;\n    if (out === 0 && inc === 0) {\n      typeMap[n.id] = 'isolated';\n    } else if (!inc && out > 0) {\n      typeMap[n.id] = 'start';\n    } else if (out === 0 && inc > 0) {\n      typeMap[n.id] = 'end';\n    } else if (out > 1) {\n      typeMap[n.id] = 'decision';\n    } else {\n      typeMap[n.id] = 'action';\n    }\n  }\n\n  return typeMap;\n}\n","/**\n * Performance optimization utilities for ZFlo\n */\n\nexport interface CacheOptions {\n  maxSize?: number;\n  ttl?: number; // Time to live in milliseconds\n}\n\n/**\n * Simple LRU cache for expensive operations\n */\nexport class LRUCache<K, V> {\n  private cache = new Map<K, { value: V; timestamp: number }>();\n  private maxSize: number;\n  private ttl: number;\n\n  constructor(options: CacheOptions = {}) {\n    this.maxSize = options.maxSize ?? 100;\n    this.ttl = options.ttl ?? 300000; // 5 minutes default\n  }\n\n  get(key: K): V | undefined {\n    const entry = this.cache.get(key);\n    if (!entry) return undefined;\n\n    // Check TTL\n    if (Date.now() - entry.timestamp > this.ttl) {\n      this.cache.delete(key);\n      return undefined;\n    }\n\n    // Move to end (most recently used)\n    this.cache.delete(key);\n    this.cache.set(key, entry);\n    return entry.value;\n  }\n\n  set(key: K, value: V): void {\n    // Remove if exists\n    this.cache.delete(key);\n\n    // Check size limit\n    if (this.cache.size >= this.maxSize) {\n      // Remove oldest entry\n      const firstKey = this.cache.keys().next().value;\n      if (firstKey !== undefined) {\n        this.cache.delete(firstKey);\n      }\n    }\n\n    this.cache.set(key, { value, timestamp: Date.now() });\n  }\n\n  clear(): void {\n    this.cache.clear();\n  }\n\n  size(): number {\n    return this.cache.size;\n  }\n}\n\n/**\n * Memoization decorator for expensive functions\n */\nexport function memoize<T extends (...args: unknown[]) => unknown>(\n  fn: T,\n  options: CacheOptions = {}\n): T {\n  const cache = new LRUCache<string, ReturnType<T>>(options);\n\n  return ((...args: Parameters<T>): ReturnType<T> => {\n    const key = JSON.stringify(args);\n    const cached = cache.get(key);\n\n    if (cached !== undefined) {\n      return cached;\n    }\n\n    const result = fn(...args);\n    const typedResult = result as ReturnType<T>;\n    cache.set(key, typedResult);\n    return typedResult;\n  }) as T;\n}\n\n/**\n * Batch processing utility for large arrays\n */\nexport async function processBatch<T, R>(\n  items: T[],\n  processor: (item: T) => Promise<R> | R,\n  batchSize = 50\n): Promise<R[]> {\n  const results: R[] = [];\n\n  for (let i = 0; i < items.length; i += batchSize) {\n    const batch = items.slice(i, i + batchSize);\n    const batchResults = await Promise.all(\n      batch.map((item) => Promise.resolve(processor(item)))\n    );\n    results.push(...batchResults);\n  }\n\n  return results;\n}\n\n/**\n * Debounce utility for frequent operations\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n  fn: T,\n  delay: number\n): T {\n  let timeoutId: NodeJS.Timeout | undefined;\n\n  return ((...args: Parameters<T>) => {\n    clearTimeout(timeoutId);\n    timeoutId = setTimeout(() => fn(...args), delay);\n  }) as T;\n}\n","//\n\nimport { ZFFlow, ZFNode, XFOutlet } from '../types/flow-types';\nimport { LRUCache } from './performance-cache';\n\n/**\n * Shared graph traversal and analysis utilities for ZFlo flows.\n * Eliminates duplicated functionality across FlowValidator, FlowAnalyzer, and PathTester.\n */\n\nexport interface GraphTraversalResult {\n  reachableNodes: Set<string>;\n  visitedPaths: Set<string>;\n  nodeDepths: Map<string, number>;\n  pathsFromNode: Map<string, XFOutlet[]>;\n}\n\nexport interface PathExplorationOptions {\n  maxDepth?: number;\n  maxPaths?: number;\n  includeState?: boolean;\n  conditionEvaluator?: (condition: string, state: unknown) => boolean;\n}\n\nexport interface PathExplorationResult {\n  allPaths: Array<{\n    nodeIds: string[];\n    pathIds: string[];\n    depth: number;\n    state?: unknown;\n  }>;\n  reachableNodes: Set<string>;\n  unreachableNodes: Set<string>;\n  maxDepth: number;\n  hasCycles: boolean;\n}\n\n/**\n * Comprehensive graph utilities for ZFlo flow analysis\n */\nexport class FlowGraphUtils {\n  private flow: ZFFlow;\n  private nodeMap: Map<string, ZFNode>;\n  private pathMap: Map<string, { path: XFOutlet; fromNodeId: string }>;\n  private reachabilityCache: LRUCache<string, Set<string>>;\n  private depthCache: LRUCache<string, Map<string, number>>;\n\n  constructor(flow: ZFFlow) {\n    this.flow = flow;\n    this.nodeMap = new Map();\n    this.pathMap = new Map();\n    this.reachabilityCache = new LRUCache({ maxSize: 50, ttl: 300000 });\n    this.depthCache = new LRUCache({ maxSize: 50, ttl: 300000 });\n\n    // Build node lookup map\n    for (const node of flow.nodes) {\n      this.nodeMap.set(node.id, node);\n    }\n\n    // Build path lookup map\n    for (const node of flow.nodes) {\n      if (node.outlets) {\n        for (const path of node.outlets) {\n          this.pathMap.set(path.id, { path, fromNodeId: node.id });\n        }\n      }\n    }\n  }\n\n  /**\n   * Find a node by ID\n   */\n  findNode(nodeId: string): ZFNode | null {\n    return this.nodeMap.get(nodeId) || null;\n  }\n\n  /**\n   * Find a path by ID with its source node\n   */\n  findPath(pathId: string): { path: XFOutlet; fromNodeId: string } | null {\n    return this.pathMap.get(pathId) || null;\n  }\n\n  /**\n   * Get all outgoing paths from a node\n   */\n  getOutgoingPaths(nodeId: string): XFOutlet[] {\n    const node = this.nodeMap.get(nodeId);\n    return node?.outlets || [];\n  }\n\n  /**\n   * Get all incoming paths to a node\n   */\n  getIncomingPaths(\n    nodeId: string\n  ): Array<{ path: XFOutlet; fromNodeId: string }> {\n    const incoming: Array<{ path: XFOutlet; fromNodeId: string }> = [];\n\n    for (const node of this.flow.nodes) {\n      if (node.outlets) {\n        for (const path of node.outlets) {\n          if (path.to === nodeId) {\n            incoming.push({ path, fromNodeId: node.id });\n          }\n        }\n      }\n    }\n\n    return incoming;\n  }\n\n  /**\n   * Find all nodes reachable from a given start node (cached)\n   */\n  findReachableNodes(startNodeId?: string): Set<string> {\n    const start = startNodeId || this.flow.startNodeId;\n    const cacheKey = `reachable:${start}`;\n\n    // Check cache first\n    const cached = this.reachabilityCache.get(cacheKey);\n    if (cached) {\n      return new Set(cached); // Return copy to prevent mutation\n    }\n\n    const reachable = new Set<string>();\n    const queue = [start];\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift();\n      if (!nodeId || reachable.has(nodeId)) continue;\n\n      reachable.add(nodeId);\n\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n      for (const path of outgoingPaths) {\n        if (!reachable.has(path.to)) {\n          queue.push(path.to);\n        }\n      }\n    }\n\n    // Cache the result\n    this.reachabilityCache.set(cacheKey, reachable);\n    return reachable;\n  }\n\n  /**\n   * Find unreachable nodes\n   */\n  findUnreachableNodes(startNodeId?: string): Set<string> {\n    const reachable = this.findReachableNodes(startNodeId);\n    const unreachable = new Set<string>();\n\n    for (const node of this.flow.nodes) {\n      if (!reachable.has(node.id)) {\n        unreachable.add(node.id);\n      }\n    }\n\n    return unreachable;\n  }\n\n  /**\n   * Check if a specific node is reachable from start\n   */\n  isNodeReachable(targetNodeId: string, startNodeId?: string): boolean {\n    const start = startNodeId || this.flow.startNodeId;\n    const visited = new Set<string>();\n    const queue = [start];\n\n    while (queue.length > 0) {\n      const nodeId = queue.shift();\n      if (!nodeId || visited.has(nodeId)) continue;\n      visited.add(nodeId);\n\n      if (nodeId === targetNodeId) return true;\n\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n      for (const path of outgoingPaths) {\n        if (!visited.has(path.to)) {\n          queue.push(path.to);\n        }\n      }\n    }\n\n    return false;\n  }\n\n  /**\n   * Calculate the maximum depth from start node\n   */\n  calculateMaxDepth(startNodeId?: string): number {\n    const start = startNodeId || this.flow.startNodeId;\n    const visited = new Set<string>();\n\n    const dfs = (nodeId: string, depth: number): number => {\n      if (visited.has(nodeId)) return depth;\n      visited.add(nodeId);\n\n      const node = this.findNode(nodeId);\n      if (!node) return depth;\n\n      let maxDepth = depth;\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n\n      for (const path of outgoingPaths) {\n        maxDepth = Math.max(maxDepth, dfs(path.to, depth + 1));\n      }\n\n      return maxDepth;\n    };\n\n    return dfs(start, 1);\n  }\n\n  /**\n   * Calculate node depths from start (cached)\n   */\n  calculateNodeDepths(startNodeId?: string): Map<string, number> {\n    const start = startNodeId || this.flow.startNodeId;\n    const cacheKey = `depths:${start}`;\n\n    // Check cache first\n    const cached = this.depthCache.get(cacheKey);\n    if (cached) {\n      return new Map(cached); // Return copy to prevent mutation\n    }\n\n    const depths = new Map<string, number>();\n    const queue = [{ nodeId: start, depth: 0 }];\n\n    while (queue.length > 0) {\n      const current = queue.shift();\n      if (!current) break;\n      const { nodeId, depth } = current;\n\n      if (depths.has(nodeId)) continue;\n      depths.set(nodeId, depth);\n\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n      for (const path of outgoingPaths) {\n        if (!depths.has(path.to)) {\n          queue.push({ nodeId: path.to, depth: depth + 1 });\n        }\n      }\n    }\n\n    // Cache the result\n    this.depthCache.set(cacheKey, depths);\n    return depths;\n  }\n\n  /**\n   * Detect cycles in the flow graph\n   */\n  hasCycles(startNodeId?: string): boolean {\n    const start = startNodeId || this.flow.startNodeId;\n    const visiting = new Set<string>();\n    const visited = new Set<string>();\n\n    const dfs = (nodeId: string): boolean => {\n      if (visiting.has(nodeId)) return true; // Back edge found - cycle detected\n      if (visited.has(nodeId)) return false;\n\n      visiting.add(nodeId);\n\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n      for (const path of outgoingPaths) {\n        if (dfs(path.to)) return true;\n      }\n\n      visiting.delete(nodeId);\n      visited.add(nodeId);\n      return false;\n    };\n\n    return dfs(start);\n  }\n\n  /**\n   * Comprehensive graph traversal with detailed results\n   */\n  performTraversal(startNodeId?: string): GraphTraversalResult {\n    const start = startNodeId || this.flow.startNodeId;\n    const reachableNodes = this.findReachableNodes(start);\n    const nodeDepths = this.calculateNodeDepths(start);\n    const visitedPaths = new Set<string>();\n    const pathsFromNode = new Map<string, XFOutlet[]>();\n\n    // Collect all visited paths and organize by source node\n    for (const nodeId of reachableNodes) {\n      const outgoingPaths = this.getOutgoingPaths(nodeId);\n      pathsFromNode.set(nodeId, outgoingPaths);\n\n      for (const path of outgoingPaths) {\n        if (reachableNodes.has(path.to)) {\n          visitedPaths.add(path.id);\n        }\n      }\n    }\n\n    return {\n      reachableNodes,\n      visitedPaths,\n      nodeDepths,\n      pathsFromNode,\n    };\n  }\n\n  /**\n   * Explore all possible paths through the flow with optional state tracking\n   */\n  exploreAllPaths(options: PathExplorationOptions = {}): PathExplorationResult {\n    const {\n      maxDepth = 100,\n      maxPaths = 1000,\n      includeState = false,\n      conditionEvaluator,\n    } = options;\n\n    const allPaths: Array<{\n      nodeIds: string[];\n      pathIds: string[];\n      depth: number;\n      state?: unknown;\n    }> = [];\n\n    const queue = [\n      {\n        nodeId: this.flow.startNodeId,\n        path: [this.flow.startNodeId],\n        pathIds: [] as string[],\n        depth: 1,\n        state: includeState ? { ...this.flow.globalState } : undefined,\n      },\n    ];\n\n    const reachableNodes = new Set<string>();\n    let currentMaxDepth = 0;\n    let hasCycles = false;\n\n    while (queue.length > 0 && allPaths.length < maxPaths) {\n      const current = queue.shift();\n      if (!current) break;\n\n      reachableNodes.add(current.nodeId);\n      currentMaxDepth = Math.max(currentMaxDepth, current.depth);\n\n      // Check for cycles\n      const nodeCount = current.path.filter(\n        (id) => id === current.nodeId\n      ).length;\n      if (nodeCount > 1) {\n        hasCycles = true;\n      }\n\n      const node = this.findNode(current.nodeId);\n      if (!node) continue;\n\n      const outgoingPaths = this.getOutgoingPaths(current.nodeId);\n\n      // If no outgoing paths or max depth reached, this is a complete path\n      if (outgoingPaths.length === 0 || current.depth >= maxDepth) {\n        allPaths.push({\n          nodeIds: current.path,\n          pathIds: current.pathIds,\n          depth: current.depth,\n          state: current.state,\n        });\n        continue;\n      }\n\n      // Explore each outgoing path\n      for (const path of outgoingPaths) {\n        // Evaluate path condition if evaluator provided\n        if (conditionEvaluator && path.condition && current.state) {\n          try {\n            if (!conditionEvaluator(path.condition, current.state)) {\n              continue; // Skip this path\n            }\n          } catch {\n            continue; // Skip on evaluation error\n          }\n        }\n\n        const newPath = [...current.path, path.to];\n        const newPathIds = [...current.pathIds, path.id];\n\n        queue.push({\n          nodeId: path.to,\n          path: newPath,\n          pathIds: newPathIds,\n          depth: current.depth + 1,\n          state: current.state ? { ...current.state } : undefined,\n        });\n      }\n    }\n\n    const allNodeIds = new Set(this.flow.nodes.map((n) => n.id));\n    const unreachableNodes = new Set<string>();\n\n    for (const nodeId of allNodeIds) {\n      if (!reachableNodes.has(nodeId)) {\n        unreachableNodes.add(nodeId);\n      }\n    }\n\n    return {\n      allPaths,\n      reachableNodes,\n      unreachableNodes,\n      maxDepth: currentMaxDepth,\n      hasCycles,\n    };\n  }\n\n  /**\n   * Get flow statistics\n   */\n  getFlowStats() {\n    const traversal = this.performTraversal();\n    const pathExploration = this.exploreAllPaths({ maxPaths: 100 });\n\n    return {\n      totalNodes: this.flow.nodes.length,\n      reachableNodes: traversal.reachableNodes.size,\n      unreachableNodes: this.flow.nodes.length - traversal.reachableNodes.size,\n      totalPaths: traversal.visitedPaths.size,\n      maxDepth: this.calculateMaxDepth(),\n      hasCycles: this.hasCycles(),\n      possiblePaths: pathExploration.allPaths.length,\n    };\n  }\n}\n\n/**\n * Utility functions for common graph operations\n */\n\n/**\n * Create a FlowGraphUtils instance for a flow\n */\nexport function createFlowGraph(flow: ZFFlow): FlowGraphUtils {\n  return new FlowGraphUtils(flow);\n}\n\n/**\n * Quick check if a node is reachable\n */\nexport function isNodeReachable(\n  flow: ZFFlow,\n  targetNodeId: string,\n  startNodeId?: string\n): boolean {\n  const graph = new FlowGraphUtils(flow);\n  return graph.isNodeReachable(targetNodeId, startNodeId);\n}\n\n/**\n * Quick find of all reachable nodes\n */\nexport function findReachableNodes(\n  flow: ZFFlow,\n  startNodeId?: string\n): Set<string> {\n  const graph = new FlowGraphUtils(flow);\n  return graph.findReachableNodes(startNodeId);\n}\n\n/**\n * Quick find of unreachable nodes\n */\nexport function findUnreachableNodes(\n  flow: ZFFlow,\n  startNodeId?: string\n): Set<string> {\n  const graph = new FlowGraphUtils(flow);\n  return graph.findUnreachableNodes(startNodeId);\n}\n\n/**\n * Quick cycle detection\n */\nexport function hasCycles(flow: ZFFlow, startNodeId?: string): boolean {\n  const graph = new FlowGraphUtils(flow);\n  return graph.hasCycles(startNodeId);\n}\n","//\n\nimport { ExpressionEvaluator } from '../core/expression-evaluator';\nimport {\n  ValidationError,\n  ValidationResult,\n  ValidationWarning,\n} from '../types/analysis-types';\nimport { NodeType, ZFFlow, ZFNode, XFOutlet } from '../types/flow-types';\nimport { EvaluatorFactory } from '../utils/evaluator-factory';\nimport { FlowGraphUtils } from '../utils/graph-utils';\nimport { inferNodeTypes } from '../utils/infer-node-types';\n\ninterface ValidationContext {\n  flow: ZFFlow;\n  nodeTypes: Record<string, NodeType>;\n  graphUtils: FlowGraphUtils;\n}\n\nexport class FlowValidator {\n  private evaluators: Record<string, ExpressionEvaluator>;\n\n  constructor(evaluators?: Record<string, ExpressionEvaluator>) {\n    this.evaluators = evaluators ?? EvaluatorFactory.getDefaultEvaluators();\n  }\n\n  validate(flow: ZFFlow): ValidationResult {\n    const errors: ValidationError[] = [];\n    const warnings: ValidationWarning[] = [];\n    const nodeTypes = inferNodeTypes(flow.nodes);\n    const graphUtils = new FlowGraphUtils(flow);\n    const context: ValidationContext = {\n      flow: flow,\n      nodeTypes,\n      graphUtils,\n    };\n\n    // Check for start node\n    const startNode = flow.nodes.find((node) => node.id === flow.startNodeId);\n    if (!startNode) {\n      errors.push({\n        type: 'missing_node',\n        message: `Start node with id \"${flow.startNodeId}\" not found`,\n        nodeId: flow.startNodeId,\n      });\n    }\n\n    // Check for at least one end node\n    const endNodes = flow.nodes.filter((node) => nodeTypes[node.id] === 'end');\n    if (endNodes.length === 0) {\n      warnings.push({\n        type: 'missing_end_node',\n        message: 'No end nodes found in flow',\n      });\n    }\n\n    // Validate paths within nodes\n    for (const node of flow.nodes) {\n      if (node.outlets) {\n        for (const path of node.outlets) {\n          const toNode = flow.nodes.find((n) => n.id === path.to);\n\n          if (!toNode) {\n            errors.push({\n              type: 'missing_node',\n              message: `Path references non-existent \"to\" node: ${path.to}`,\n              edgeId: path.id,\n              nodeId: path.to,\n            });\n          }\n        }\n      }\n    }\n\n    // Check for unreachable nodes using shared graph utilities\n    const reachableNodes = context.graphUtils.findReachableNodes();\n    const unreachableNodes = flow.nodes.filter(\n      (node) => !reachableNodes.has(node.id)\n    );\n    for (const node of unreachableNodes) {\n      warnings.push({\n        type: 'unreachable_node',\n        message: `Node \"${node.id}\" is unreachable from start node`,\n        nodeId: node.id,\n      });\n    }\n\n    // Check for circular dependencies using shared graph utilities\n    if (context.graphUtils.hasCycles()) {\n      warnings.push({\n        type: 'circular_dependency',\n        message: 'Potential circular dependencies detected',\n      });\n    }\n\n    // Validate path condition expressions (syntax-level)\n    for (const node of flow.nodes) {\n      if (node.outlets) {\n        for (const path of node.outlets) {\n          if (\n            path.condition !== undefined &&\n            !this.isValidExpression(\n              path.condition,\n              flow.expressionLanguage ?? 'cel'\n            )\n          ) {\n            errors.push({\n              type: 'syntax_error',\n              message: `Invalid path condition expression: ${path.condition}`,\n              nodeId: node.id,\n              edgeId: path.id,\n            });\n          }\n        }\n      }\n    }\n\n    // Validate auto-advance nodes follow if-else logic\n    this.validateAutoAdvanceNodes(context, errors, warnings);\n\n    return {\n      isValid: errors.length === 0,\n      errors,\n      warnings,\n    };\n  }\n\n  /**\n   * Validates that auto-advance nodes follow proper if-else logic patterns.\n   * Auto-advance nodes should have their outlets structured like if-else statements:\n   * - Conditional outlets (if/else-if clauses) should be evaluated in order\n   * - At most one default outlet (else clause) without conditions\n   * - No unreachable outlets after a default outlet\n   */\n  private validateAutoAdvanceNodes(\n    context: ValidationContext,\n    errors: ValidationError[],\n    warnings: ValidationWarning[]\n  ): void {\n    for (const node of context.flow.nodes) {\n      // Check if node uses auto-advance\n      if (!node.isAutoAdvance) continue;\n\n      const autoAdvanceMode = context.flow.autoAdvance || 'default';\n\n      if (autoAdvanceMode === 'never') continue;\n\n      // Only validate nodes that can auto-advance\n      const canAutoAdvance = true;\n\n      if (!canAutoAdvance || !node.outlets || node.outlets.length === 0)\n        continue;\n\n      this.validateIfElsePathStructure(node, errors, warnings);\n    }\n  }\n\n  /**\n   * Validates that a node's outlets follow proper if-else structure:\n   * - Conditional outlets come first (if/else-if)\n   * - At most one default outlet (else)\n   * - Default outlet should be last\n   */\n  private validateIfElsePathStructure(\n    node: ZFNode,\n    errors: ValidationError[],\n    warnings: ValidationWarning[]\n  ): void {\n    const paths = node.outlets || [];\n    const conditionalPaths = paths.filter((path: XFOutlet) => path.condition);\n    const defaultPaths = paths.filter((path: XFOutlet) => !path.condition);\n    const autoAdvanceFrom = node.isAutoAdvance ? 'node' : 'flow';\n\n    // Check for multiple default outlets (multiple else clauses)\n    if (defaultPaths.length > 1) {\n      errors.push({\n        type: 'invalid_path_structure',\n        message: `Auto-advance node \"${node.id}\" (${autoAdvanceFrom}) has multiple default outlets (else clauses). Only one default outlet is allowed.`,\n        nodeId: node.id,\n      });\n    }\n\n    // Check if default outlet is not at the end\n    if (defaultPaths.length === 1 && defaultPaths[0]) {\n      const defaultPathIndex = paths.indexOf(defaultPaths[0]);\n      const lastConditionalPath = conditionalPaths[conditionalPaths.length - 1];\n      const lastConditionalIndex = lastConditionalPath\n        ? paths.indexOf(lastConditionalPath)\n        : -1;\n\n      if (\n        lastConditionalIndex >= 0 &&\n        defaultPathIndex < lastConditionalIndex\n      ) {\n        warnings.push({\n          type: 'suboptimal_path_order',\n          message: `Auto-advance node \"${node.id}\" (${autoAdvanceFrom}) has default outlet before conditional outlets. Consider moving default outlet to the end for clarity.`,\n          nodeId: node.id,\n        });\n      }\n    }\n\n    // Check for unreachable outlets (outlets after an always-true condition)\n    for (let i = 0; i < conditionalPaths.length - 1; i++) {\n      const currentPath = conditionalPaths[i];\n      if (\n        currentPath &&\n        currentPath.condition &&\n        this.isAlwaysTrueCondition(currentPath.condition)\n      ) {\n        warnings.push({\n          type: 'unreachable_path',\n          message: `Auto-advance node \"${node.id}\" (${autoAdvanceFrom}) has paths after an always-true condition \"${currentPath.condition}\". These paths will never be reached.`,\n          nodeId: node.id,\n          edgeId: currentPath.id,\n        });\n        break;\n      }\n    }\n\n    // Warn if no default outlet and all conditions might be false\n    if (defaultPaths.length === 0 && conditionalPaths.length > 0) {\n      warnings.push({\n        type: 'missing_default_path',\n        message: `Auto-advance node \"${node.id}\" (${autoAdvanceFrom}) has only conditional outlets without a default outlet. Consider adding a default outlet (else clause) to handle cases where no conditions are met.`,\n        nodeId: node.id,\n      });\n    }\n  }\n\n  /**\n   * Checks if a condition expression is always true (basic heuristics)\n   */\n  private isAlwaysTrueCondition(condition: string): boolean {\n    if (!condition) return false;\n\n    const trimmed = condition.trim().toLowerCase();\n    return (\n      trimmed === 'true' ||\n      trimmed === '1' ||\n      trimmed === '1 == 1' ||\n      trimmed === 'true == true'\n    );\n  }\n\n  private isValidExpression(expression: string, language: 'cel'): boolean {\n    try {\n      // Normalize and support per-expression language override via prefix\n      let expr = (expression || '').trim();\n      let lang: 'cel' = language;\n\n      // Check for basic syntax issues\n      if (expr === '') return false;\n\n      // Check for balanced parentheses\n      let parenCount = 0;\n      for (const char of expr) {\n        if (char === '(') parenCount++;\n        if (char === ')') parenCount--;\n        if (parenCount < 0) return false;\n      }\n      if (parenCount !== 0) return false;\n\n      const evaluator = this.evaluators[lang];\n      if (!evaluator) {\n        return false;\n      }\n      // Try to compile the expression with CEL Runtime; errors mean invalid syntax\n      try {\n        const result = evaluator.compile(expr);\n        return result.success;\n      } catch {\n        return false;\n      }\n    } catch {\n      return false;\n    }\n  }\n}\n","//\n\nimport { ExpressionEvaluator } from '../core/expression-evaluator';\nimport { FlowEngine } from '../core/flow-engine';\nimport { ExpressionLanguage } from '../types/expression-types';\nimport { NodeType, ZFFlow, ZFNode, XFOutlet } from '../types/flow-types';\nimport { EvaluatorFactory } from '../utils/evaluator-factory';\nimport { inferNodeTypes } from '../utils/infer-node-types';\nimport { StateActionExecutor } from '../utils/state-executor';\n\nexport interface PathTestResult {\n  isValid: boolean;\n  totalPaths: number;\n  completedPaths: number;\n  errors: PathTestPointOfInterest[];\n  warnings: PathTestPointOfInterest[];\n  pathSummary: PathSummary[];\n  coverage: CoverageReport;\n}\n\nexport interface PathTestPointOfInterest {\n  type:\n    | 'missing_node'\n    | 'unreachable_node'\n    | 'infinite_loop'\n    | 'missing_end'\n    | 'invalid_transition'\n    | 'state_error'\n    | 'long_path'\n    | 'unused_node'\n    | 'complex_condition'\n    | 'state_inconsistency';\n  message: string;\n  path?: string[];\n  nodeId?: string;\n  pathId?: string;\n}\n\nexport interface PathSummary {\n  id: string;\n  path: string[];\n  endType: 'completed' | 'error' | 'infinite_loop';\n  steps: number;\n  finalState: Record<string, unknown>;\n  choices: string[];\n}\n\nexport interface CoverageReport {\n  nodesCovered: number;\n  totalNodes: number;\n  pathsCovered: number;\n  totalPaths: number;\n  uncoveredNodes: string[];\n  uncoveredPaths: string[];\n}\n\nexport class PathTester {\n  private flow: ZFFlow;\n  private nodeTypes: Record<string, NodeType>;\n  private maxPaths: number;\n  private maxSteps: number;\n  private evaluators: Record<string, ExpressionEvaluator>;\n  private defaultLanguage: ExpressionLanguage;\n  private actionExecutor: StateActionExecutor;\n\n  constructor(flow: ZFFlow, maxPaths: number = 1000, maxSteps: number = 100) {\n    this.flow = flow;\n    this.nodeTypes = inferNodeTypes(flow.nodes);\n    this.maxPaths = maxPaths;\n    this.maxSteps = maxSteps;\n    this.defaultLanguage = flow.expressionLanguage ?? 'cel';\n    this.evaluators = EvaluatorFactory.getDefaultEvaluators();\n\n    // Initialize shared action executor\n    this.actionExecutor = new StateActionExecutor({\n      expressionLanguage: this.defaultLanguage,\n      evaluators: this.evaluators,\n      enableLogging: false,\n    });\n  }\n\n  /**\n   * Test all possible paths through the flow\n   */\n  async testAllPaths(): Promise<PathTestResult> {\n    const errors: PathTestPointOfInterest[] = [];\n    const warnings: PathTestPointOfInterest[] = [];\n    const pathSummaries: PathSummary[] = [];\n    const visitedNodes = new Set<string>();\n    const visitedPaths = new Set<string>();\n\n    // Start path exploration from the start node\n    const pathQueue: {\n      nodeId: string;\n      path: string[];\n      state: Record<string, unknown>;\n      choices: string[];\n    }[] = [\n      {\n        nodeId: this.flow.startNodeId,\n        path: [this.flow.startNodeId],\n        state: { ...this.flow.globalState },\n        choices: [],\n      },\n    ];\n\n    let pathCount = 0;\n    let completedPaths = 0;\n\n    while (pathQueue.length > 0 && pathCount < this.maxPaths) {\n      const current = pathQueue.shift();\n      if (!current) {\n        errors.push({\n          type: 'state_error',\n          message: 'Path queue is empty',\n        });\n        continue;\n      }\n      pathCount++;\n\n      // Check for infinite loops\n      if (current.path.length > this.maxSteps) {\n        errors.push({\n          type: 'infinite_loop',\n          message: `Path exceeded maximum steps (${this.maxSteps})`,\n          path: current.path,\n          nodeId: current.nodeId,\n        });\n        continue;\n      }\n\n      // Track visited nodes and paths\n      visitedNodes.add(current.nodeId);\n      const pathKey = current.path.join('->');\n      visitedPaths.add(pathKey);\n\n      const node = this.findNodeById(current.nodeId);\n      if (!node) {\n        errors.push({\n          type: 'unreachable_node',\n          message: `Node not found: ${current.nodeId}`,\n          path: current.path,\n          nodeId: current.nodeId,\n        });\n        continue;\n      }\n\n      // Check if this is an end node\n      if (this.nodeTypes[node.id] === 'end') {\n        completedPaths++;\n        pathSummaries.push({\n          id: `path-${pathCount}`,\n          path: current.path,\n          endType: 'completed',\n          steps: current.path.length,\n          finalState: current.state,\n          choices: current.choices,\n        });\n        continue;\n      }\n\n      // Get available paths from this node\n      const availablePaths = this.getAvailablePaths(node, current.state);\n\n      if (availablePaths.length === 0) {\n        errors.push({\n          type: 'missing_end',\n          message: `Node has no available paths and is not an end node: ${node.id}`,\n          path: current.path,\n          nodeId: node.id,\n        });\n        continue;\n      }\n\n      // Explore each available path\n      for (const path of availablePaths) {\n        const targetNode = this.findNodeById(path.to);\n        if (!targetNode) {\n          errors.push({\n            type: 'invalid_transition',\n            message: `Path references non-existent node: ${path.to}`,\n            path: current.path,\n            pathId: path.id,\n          });\n          continue;\n        }\n\n        // Apply node actions to state using shared executor\n        const actionResult = node.actions\n          ? this.actionExecutor.executeActions(node.actions, current.state)\n          : { success: true, newState: current.state, errors: [] };\n        const newState = actionResult.newState;\n\n        // Check for cycles (but allow some repetition for complex flows)\n        const newPath = [...current.path, path.to];\n        const cycleCount = newPath.filter(\n          (nodeId) => nodeId === path.to\n        ).length;\n\n        if (cycleCount > 3) {\n          warnings.push({\n            type: 'long_path',\n            message: `Potential infinite loop detected: node ${path.to} visited ${cycleCount} times`,\n            path: newPath,\n            nodeId: path.to,\n          });\n          continue;\n        }\n\n        pathQueue.push({\n          nodeId: path.to,\n          path: newPath,\n          state: newState,\n          choices: [...current.choices, path.label || path.id],\n        });\n      }\n    }\n\n    // Generate coverage report\n    const coverage = this.generateCoverageReport(visitedNodes, visitedPaths);\n\n    // Add warnings for uncovered nodes\n    for (const nodeId of coverage.uncoveredNodes) {\n      warnings.push({\n        type: 'unused_node',\n        message: `Node is never reached: ${nodeId}`,\n        nodeId,\n      });\n    }\n\n    return {\n      isValid: errors.length === 0,\n      totalPaths: pathCount,\n      completedPaths,\n      errors,\n      warnings,\n      pathSummary: pathSummaries,\n      coverage,\n    };\n  }\n\n  /**\n   * Test a specific path through the flow\n   */\n  async testPath(choices: string[]): Promise<PathSummary> {\n    const engine = new FlowEngine(this.flow, { enableHistory: true });\n\n    try {\n      await engine.start();\n      const path = [this.flow.startNodeId];\n\n      for (const choice of choices) {\n        const result = await engine.next(choice);\n        path.push(result.node.node.id);\n\n        if (result.isComplete) {\n          break;\n        }\n      }\n\n      return {\n        id: 'manual-test',\n        path,\n        endType: engine.isComplete() ? 'completed' : 'error',\n        steps: path.length,\n        finalState: engine.getState(),\n        choices,\n      };\n    } catch {\n      return {\n        id: 'manual-test',\n        path: [this.flow.startNodeId],\n        endType: 'error',\n        steps: 1,\n        finalState: {},\n        choices,\n      };\n    }\n  }\n\n  /**\n   * Generate a simple test report\n   */\n  generateReport(result: PathTestResult): string {\n    const lines = [\n      '# ZFlo Path Test Report',\n      `**Flow:** ${this.flow.title}`,\n      `**Status:** ${result.isValid ? '✅ PASS' : '❌ FAIL'}`,\n      '',\n      '## Summary',\n      `- Total paths explored: ${result.totalPaths}`,\n      `- Completed paths: ${result.completedPaths}`,\n      `- Errors: ${result.errors.length}`,\n      `- Warnings: ${result.warnings.length}`,\n      '',\n      '## Coverage',\n      `- Nodes covered: ${result.coverage.nodesCovered}/${result.coverage.totalNodes} (${Math.round((result.coverage.nodesCovered / result.coverage.totalNodes) * 100)}%)`,\n      `- Paths covered: ${result.coverage.pathsCovered}/${result.coverage.totalPaths} (${Math.round((result.coverage.pathsCovered / result.coverage.totalPaths) * 100)}%)`,\n      '',\n    ];\n\n    if (result.errors.length > 0) {\n      lines.push('## Errors');\n      for (const error of result.errors) {\n        lines.push(`- **${error.type}**: ${error.message}`);\n        if (error.path) {\n          lines.push(`  Path: ${error.path.join(' → ')}`);\n        }\n      }\n      lines.push('');\n    }\n\n    if (result.warnings.length > 0) {\n      lines.push('## Warnings');\n      for (const warning of result.warnings) {\n        lines.push(`- **${warning.type}**: ${warning.message}`);\n        if (warning.path) {\n          lines.push(`  Path: ${warning.path.join(' → ')}`);\n        }\n      }\n      lines.push('');\n    }\n\n    if (result.coverage.uncoveredNodes.length > 0) {\n      lines.push('## Uncovered Nodes');\n      for (const nodeId of result.coverage.uncoveredNodes) {\n        lines.push(`- ${nodeId}`);\n      }\n      lines.push('');\n    }\n\n    return lines.join('\\n');\n  }\n\n  private findNodeById(id: string): ZFNode | null {\n    return this.flow.nodes.find((node) => node.id === id) || null;\n  }\n\n  private getAvailablePaths(\n    node: ZFNode,\n    state: Record<string, unknown>\n  ): XFOutlet[] {\n    if (!node.outlets) return [];\n\n    return node.outlets.filter((path) => {\n      if (!path.condition) return true;\n\n      try {\n        // Simple condition evaluation (can be enhanced)\n        return this.evaluateCondition(path.condition, state);\n      } catch {\n        return false;\n      }\n    });\n  }\n\n  private evaluateCondition(\n    condition: string,\n    state: Record<string, unknown>\n  ): boolean {\n    return this.actionExecutor.evaluateCondition(condition, state);\n  }\n\n  private generateCoverageReport(\n    visitedNodes: Set<string>,\n    visitedPaths: Set<string>\n  ): CoverageReport {\n    const totalNodes = this.flow.nodes.length;\n    const uncoveredNodes = this.flow.nodes\n      .filter((node) => !visitedNodes.has(node.id))\n      .map((node) => node.id);\n\n    // Count total paths\n    let totalPaths = 0;\n    const uncoveredPaths: string[] = [];\n\n    for (const node of this.flow.nodes) {\n      if (node.outlets) {\n        for (const path of node.outlets) {\n          totalPaths++;\n          const pathKey = `${node.id}->${path.to}`;\n          if (!visitedPaths.has(pathKey)) {\n            uncoveredPaths.push(pathKey);\n          }\n        }\n      }\n    }\n\n    return {\n      nodesCovered: visitedNodes.size,\n      totalNodes,\n      pathsCovered: totalPaths - uncoveredPaths.length,\n      totalPaths,\n      uncoveredNodes,\n      uncoveredPaths,\n    };\n  }\n}\n","//\n\nimport {\n  ValidationError,\n  ValidationResult,\n  ValidationWarning,\n} from '../types/analysis-types';\nimport { NodeType, ZFFlow } from '../types/flow-types';\nimport { FlowGraphUtils } from '../utils/graph-utils';\nimport { inferNodeTypes } from '../utils/infer-node-types';\nimport { FlowValidator } from './flow-validator';\nimport {\n  PathSummary,\n  PathTester,\n  PathTestPointOfInterest,\n  PathTestResult,\n} from './path-tester';\n\nexport interface AnalysisInsight {\n  type: 'info' | 'warning' | 'error' | 'suggestion';\n  category: 'structure' | 'paths' | 'content' | 'performance' | 'usability';\n  title: string;\n  description: string;\n  nodeId?: string;\n  pathExample?: string[];\n  actionable?: boolean;\n  suggestion?: string;\n}\n\nexport interface FlowAnalysis {\n  isValid: boolean;\n  score: number; // 0-100 quality score\n  insights: AnalysisInsight[];\n\n  // Structure metrics\n  structure: {\n    totalNodes: number;\n    decisionNodes: number;\n    endNodes: number;\n    startNodes: number;\n    averageChoicesPerDecision: number;\n    maxDepth: number;\n    branchingFactor: number;\n  };\n\n  // Path metrics\n  paths: {\n    totalPaths: number;\n    completedPaths: number;\n    averagePathLength: number;\n    shortestPath: number;\n    longestPath: number;\n    unreachableNodes: number;\n    loops: number;\n  };\n\n  // Content quality\n  content: {\n    averageNodeTextLength: number;\n    emptyNodes: number;\n    duplicateContent: number;\n    clarityScore: number; // 0-100\n  };\n\n  // User experience\n  userExperience: {\n    replayability: number; // 0-100\n    engagement: number; // 0-100\n    complexity: 'simple' | 'moderate' | 'complex';\n    estimatedPlayTime: string;\n  };\n}\n\ninterface AnalysisContext {\n  flow: ZFFlow;\n  nodeTypes: Record<string, NodeType>;\n  insights: AnalysisInsight[];\n  graphUtils: FlowGraphUtils;\n}\n\nexport class FlowAnalyzer {\n  private validator: FlowValidator;\n  private pathTester?: PathTester;\n\n  constructor() {\n    this.validator = new FlowValidator();\n  }\n\n  async analyze(flow: ZFFlow): Promise<FlowAnalysis> {\n    const insights: AnalysisInsight[] = [];\n    const nodeTypes = inferNodeTypes(flow.nodes);\n    const graphUtils = new FlowGraphUtils(flow);\n    const context: AnalysisContext = {\n      flow,\n      nodeTypes,\n      insights,\n      graphUtils,\n    };\n\n    // Basic validation\n    const validationResult = this.validator.validate(flow);\n\n    // Path testing\n    this.pathTester = new PathTester(flow, 1000, 100);\n    const pathResult = await this.pathTester.testAllPaths();\n\n    // Detailed node analysis first\n    this.analyzeNodesInDetail(context);\n\n    // Structure analysis\n    const structure = this.analyzeStructure(context);\n\n    // Path analysis\n    const paths = this.analyzePaths(pathResult, context.insights);\n\n    // Content analysis\n    const content = this.analyzeContent(context.flow, context.insights);\n\n    // User experience analysis\n    const userExperience = this.analyzeUserExperience(\n      structure,\n      paths,\n      context.insights\n    );\n\n    // Add validation insights\n    this.addValidationInsights(validationResult, context.insights);\n\n    // Calculate overall score\n    const score = this.calculateScore(\n      structure,\n      paths,\n      content,\n      userExperience,\n      context.insights\n    );\n\n    return {\n      isValid: validationResult.isValid,\n      score,\n      insights: context.insights.sort(\n        (a, b) => this.getInsightPriority(a) - this.getInsightPriority(b)\n      ),\n      structure,\n      paths,\n      content,\n      userExperience,\n    };\n  }\n\n  private analyzeNodesInDetail(context: AnalysisContext) {\n    const nodes = context.flow.nodes;\n\n    nodes.forEach((node) => {\n      // Check for empty or very short content\n      const content = node.content || node.title || '';\n      if (content.trim().length === 0) {\n        context.insights.push({\n          type: 'error',\n          category: 'content',\n          title: 'Empty Node Content',\n          description: `Node \"${node.id}\" has no content. Users won't know what this step represents.`,\n          nodeId: node.id,\n          actionable: true,\n          suggestion: `Add descriptive text like: \"${this.generateSampleContent(context.nodeTypes[node.id] || 'activity')}\"`,\n        });\n      } else if (content.trim().length < 10) {\n        context.insights.push({\n          type: 'warning',\n          category: 'content',\n          title: 'Very Brief Content',\n          description: `Node \"${node.id}\" has only ${content.trim().length} characters: \"${content.trim()}\"`,\n          nodeId: node.id,\n          actionable: true,\n          suggestion: `Expand to something like: \"${this.expandContent(content.trim(), context.nodeTypes[node.id] || 'activity')}\"`,\n        });\n      }\n\n      // Check decision nodes without proper choices\n      if (context.nodeTypes[node.id] === 'decision') {\n        if (!node.outlets || node.outlets.length < 2) {\n          context.insights.push({\n            type: 'error',\n            category: 'structure',\n            title: 'Decision Node Needs Choices',\n            description: `Decision node \"${node.id}\" should have at least 2 choice paths.`,\n            nodeId: node.id,\n            actionable: true,\n            suggestion:\n              'Add more paths with labels like \"Yes\" and \"No\" or \"Option A\" and \"Option B\"',\n          });\n        } else if (\n          node.outlets.some(\n            (path) => !path.label || path.label.trim().length === 0\n          )\n        ) {\n          const unlabeledPaths = node.outlets.filter(\n            (path) => !path.label || path.label.trim().length === 0\n          );\n          context.insights.push({\n            type: 'warning',\n            category: 'usability',\n            title: 'Unlabeled Choice Paths',\n            description: `Decision node \"${node.id}\" has ${unlabeledPaths.length} paths without clear labels.`,\n            nodeId: node.id,\n            actionable: true,\n            suggestion:\n              'Add descriptive labels like \"Accept the offer\", \"Decline politely\", \"Ask for more time\"',\n          });\n        }\n      }\n\n      // Check for nodes that might be unreachable using shared graph utilities\n      const isReachable = context.graphUtils.isNodeReachable(node.id);\n      if (!isReachable && node.id !== context.flow.startNodeId) {\n        context.insights.push({\n          type: 'error',\n          category: 'structure',\n          title: 'Unreachable Node',\n          description: `Node \"${node.id}\" cannot be reached from the start node.`,\n          nodeId: node.id,\n          actionable: true,\n          suggestion:\n            'Connect this node to the flow by adding a path from another node, or remove it if not needed.',\n        });\n      }\n\n      // Check for dead-end nodes (except end nodes)\n      if (\n        context.nodeTypes[node.id] !== 'end' &&\n        (!node.outlets || node.outlets.length === 0)\n      ) {\n        context.insights.push({\n          type: 'warning',\n          category: 'structure',\n          title: 'Dead-End Node',\n          description: `Node \"${node.id}\" doesn't lead anywhere. Users will get stuck here.`,\n          nodeId: node.id,\n          actionable: true,\n          suggestion:\n            'Add a path to continue the story, or change this to an end node if it should conclude the flow.',\n        });\n      }\n    });\n\n    // Check for duplicate content across nodes\n    const contentMap = new Map<string, string[]>();\n    nodes.forEach((node) => {\n      const content = (node.content || node.title || '').trim().toLowerCase();\n      if (content && content.length > 5) {\n        if (!contentMap.has(content)) {\n          contentMap.set(content, []);\n        }\n        contentMap.get(content)?.push(node.id);\n      }\n    });\n\n    contentMap.forEach((nodeIds, content) => {\n      if (nodeIds.length > 1) {\n        context.insights.push({\n          type: 'info',\n          category: 'content',\n          title: 'Duplicate Content Found',\n          description: `Nodes ${nodeIds.join(', ')} have identical content: \"${content.substring(0, 50)}...\"`,\n          actionable: true,\n          suggestion:\n            'Make each node unique by adding different details, context, or outcomes.',\n        });\n      }\n    });\n  }\n\n  private generateSampleContent(nodeType: string): string {\n    switch (nodeType) {\n      case 'start':\n        return 'Welcome! Your adventure begins here...';\n      case 'decision':\n        return 'You face a choice. What do you decide?';\n      case 'action':\n        return 'Something important happens in your story...';\n      case 'end':\n        return 'Your journey concludes. Well done!';\n      default:\n        return 'Describe what happens at this point in your story...';\n    }\n  }\n\n  private expandContent(content: string, nodeType: string): string {\n    const expanded = {\n      start: `${content} - Begin your journey and discover what awaits you.`,\n      decision: `${content} - Consider your options carefully. Each choice leads to a different outcome.`,\n      action: `${content} - This moment shapes your path forward. What happens next depends on your previous choices.`,\n      end: `${content} - Your adventure concludes here. Reflect on the journey you've taken.`,\n    };\n    return (\n      expanded[nodeType as keyof typeof expanded] ||\n      `${content} - Add more detail about what happens, how it feels, or what the user should consider.`\n    );\n  }\n\n  private analyzeStructure(context: AnalysisContext): StructureAnalysis {\n    const nodes = context.flow.nodes;\n    const nodeTypes = context.nodeTypes;\n    const decisionNodes = nodes.filter((n) => nodeTypes[n.id] === 'decision');\n    const endNodes = nodes.filter((n) => nodeTypes[n.id] === 'end');\n    const startNodes = nodes.filter((n) => n.id === context.flow.startNodeId);\n\n    const totalChoices = decisionNodes.reduce(\n      (sum, node) => sum + (node.outlets?.length || 0),\n      0\n    );\n    const averageChoicesPerDecision =\n      decisionNodes.length > 0 ? totalChoices / decisionNodes.length : 0;\n\n    const maxDepth = context.graphUtils.calculateMaxDepth();\n    const branchingFactor = this.calculateBranchingFactor(context);\n\n    // Add structure insights with specific examples\n    if (decisionNodes.length === 0) {\n      context.insights.push({\n        type: 'suggestion',\n        category: 'structure',\n        title: 'Add Interactive Choices',\n        description:\n          'Your flow is currently linear. Adding decision points makes it interactive.',\n        actionable: true,\n        suggestion:\n          'Convert some action nodes to decision nodes. Example: Change \"You find a door\" to \"You find a door {Open it|Walk away|Look for a key}\"',\n      });\n    }\n\n    if (endNodes.length === 1 && nodes.length > 3) {\n      context.insights.push({\n        type: 'suggestion',\n        category: 'structure',\n        title: 'Create Multiple Endings',\n        description: `You have ${nodes.length} nodes but only 1 ending. Multiple endings encourage replay.`,\n        actionable: true,\n        suggestion:\n          'Add 2-3 different ending nodes like \"Victory!\", \"Defeat...\", \"Mysterious ending...\" based on different paths.',\n      });\n    }\n\n    if (decisionNodes.length > 0 && averageChoicesPerDecision < 2.5) {\n      const poorDecisions = decisionNodes.filter(\n        (n) => (n.outlets?.length || 0) < 3\n      );\n      if (poorDecisions.length > 0) {\n        context.insights.push({\n          type: 'suggestion',\n          category: 'structure',\n          title: 'Expand Decision Options',\n          description: `${poorDecisions.length} decision nodes have limited choices. More options create richer experiences.`,\n          actionable: true,\n          suggestion: `Add a third option to decisions. Example: Instead of just \"Yes|No\", try \"Yes|No|Ask for more information\"`,\n        });\n      }\n    }\n\n    if (maxDepth > 12) {\n      context.insights.push({\n        type: 'info',\n        category: 'usability',\n        title: 'Long Story Paths',\n        description: `Your longest path has ${maxDepth} steps. Consider if this feels too long for users.`,\n        actionable: true,\n        suggestion:\n          'Add shortcuts or early endings for users who want quicker resolution, or break into chapters.',\n      });\n    }\n\n    return {\n      totalNodes: nodes.length,\n      decisionNodes: decisionNodes.length,\n      endNodes: endNodes.length,\n      startNodes: startNodes.length,\n      averageChoicesPerDecision:\n        Math.round(averageChoicesPerDecision * 10) / 10,\n      maxDepth,\n      branchingFactor: Math.round(branchingFactor * 10) / 10,\n    };\n  }\n\n  private analyzePaths(\n    pathResult: PathTestResult,\n    insights: AnalysisInsight[]\n  ): PathAnalysis {\n    const pathLengths = pathResult.pathSummary.map((p: PathSummary) => p.steps);\n    const averagePathLength =\n      pathLengths.length > 0\n        ? pathLengths.reduce((sum: number, len: number) => sum + len, 0) /\n          pathLengths.length\n        : 0;\n\n    const shortestPath = pathLengths.length > 0 ? Math.min(...pathLengths) : 0;\n    const longestPath = pathLengths.length > 0 ? Math.max(...pathLengths) : 0;\n\n    // Add specific path insights with examples\n    pathResult.errors.forEach((error: PathTestPointOfInterest) => {\n      if (error.path && error.path.length > 0) {\n        insights.push({\n          type: 'error',\n          category: 'paths',\n          title: `Broken Path: ${error.type}`,\n          description: `Path breaks at: ${error.path.join(' → ')}`,\n          pathExample: error.path,\n          actionable: true,\n          suggestion:\n            error.type === 'missing_node'\n              ? 'Add the missing node or fix the connection.'\n              : 'Check that this path leads to a valid destination.',\n        });\n      }\n    });\n\n    if (pathResult.totalPaths < 3 && pathResult.totalPaths > 0) {\n      insights.push({\n        type: 'suggestion',\n        category: 'paths',\n        title: 'Add More Story Branches',\n        description: `Only ${pathResult.totalPaths} possible paths through your story.`,\n        actionable: true,\n        suggestion:\n          'Add decision nodes with 3+ choices each. Example: \"What do you do? {Fight|Flee|Hide|Negotiate}\"',\n      });\n    }\n\n    if (shortestPath > 0 && longestPath > 0) {\n      if (shortestPath < 3) {\n        insights.push({\n          type: 'warning',\n          category: 'paths',\n          title: 'Very Short Path Found',\n          description: `Shortest path is only ${shortestPath} steps. Users might feel unsatisfied.`,\n          actionable: true,\n          suggestion:\n            'Add more content or merge this with another path to create a richer experience.',\n        });\n      }\n\n      if (longestPath - shortestPath > 8) {\n        insights.push({\n          type: 'info',\n          category: 'paths',\n          title: 'Unbalanced Path Lengths',\n          description: `Path lengths vary from ${shortestPath} to ${longestPath} steps.`,\n          actionable: true,\n          suggestion:\n            'Consider balancing by adding content to shorter paths or providing early exits for longer ones.',\n        });\n      }\n    }\n\n    return {\n      totalPaths: pathResult.totalPaths,\n      completedPaths: pathResult.completedPaths,\n      averagePathLength: Math.round(averagePathLength * 10) / 10,\n      shortestPath,\n      longestPath,\n      unreachableNodes: pathResult.errors.filter(\n        (e: PathTestPointOfInterest) => e.type === 'unreachable_node'\n      ).length,\n      loops: pathResult.warnings.filter(\n        (w: PathTestPointOfInterest) => w.type === 'infinite_loop'\n      ).length,\n    };\n  }\n\n  private analyzeContent(\n    flow: ZFFlow,\n    insights: AnalysisInsight[]\n  ): ContentAnalysis {\n    const nodes = flow.nodes;\n    const textLengths = nodes.map((n) => (n.content || n.title || '').length);\n    const averageNodeTextLength =\n      textLengths.reduce((sum, len) => sum + len, 0) / textLengths.length;\n\n    const emptyNodes = nodes.filter(\n      (n) => !(n.content || n.title || '').trim()\n    ).length;\n\n    // Check for duplicate content\n    const contentMap = new Map<string, number>();\n    nodes.forEach((node) => {\n      const content = (node.content || node.title || '').trim().toLowerCase();\n      if (content) {\n        contentMap.set(content, (contentMap.get(content) || 0) + 1);\n      }\n    });\n    const duplicateContent = Array.from(contentMap.values()).filter(\n      (count) => count > 1\n    ).length;\n\n    // Calculate clarity score based on text length and readability\n    const clarityScore = this.calculateClarityScore(textLengths);\n\n    // Add content insights\n    if (emptyNodes > 0) {\n      insights.push({\n        type: 'warning',\n        category: 'content',\n        title: 'Empty Nodes',\n        description: `${emptyNodes} nodes have no content text.`,\n        actionable: true,\n        suggestion:\n          'Add descriptive text to all nodes to improve user experience.',\n      });\n    }\n\n    if (averageNodeTextLength < 10) {\n      insights.push({\n        type: 'suggestion',\n        category: 'content',\n        title: 'Brief Content',\n        description: 'Consider adding more descriptive text to engage users.',\n        actionable: true,\n        suggestion: 'Expand node content with more detail and context.',\n      });\n    }\n\n    if (duplicateContent > 0) {\n      insights.push({\n        type: 'info',\n        category: 'content',\n        title: 'Duplicate Content',\n        description: `${duplicateContent} pieces of content are repeated.`,\n        actionable: true,\n        suggestion: 'Consider varying the text to avoid repetition.',\n      });\n    }\n\n    return {\n      averageNodeTextLength: Math.round(averageNodeTextLength * 10) / 10,\n      emptyNodes,\n      duplicateContent,\n      clarityScore,\n    };\n  }\n\n  private analyzeUserExperience(\n    structure: StructureAnalysis,\n    paths: PathAnalysis,\n    insights: AnalysisInsight[]\n  ): UserExperienceAnalysis {\n    // Calculate replayability based on paths and endings\n    const replayability = Math.min(\n      100,\n      structure.endNodes * 20 +\n        paths.totalPaths * 5 +\n        structure.decisionNodes * 10\n    );\n\n    // Calculate engagement based on choices and content\n    const engagement = Math.min(\n      100,\n      structure.averageChoicesPerDecision * 25 +\n        Math.min(paths.averagePathLength, 10) * 5 +\n        structure.decisionNodes * 8\n    );\n\n    // Determine complexity\n    let complexity: 'simple' | 'moderate' | 'complex' = 'simple';\n    if (structure.totalNodes > 15 || paths.totalPaths > 8) {\n      complexity = 'complex';\n    } else if (structure.totalNodes > 8 || paths.totalPaths > 4) {\n      complexity = 'moderate';\n    }\n\n    // Estimate play time\n    const estimatedMinutes = Math.ceil(paths.averagePathLength * 0.5); // ~30 seconds per node\n    const estimatedPlayTime =\n      estimatedMinutes < 2\n        ? '1-2 minutes'\n        : estimatedMinutes < 5\n          ? '2-5 minutes'\n          : estimatedMinutes < 10\n            ? '5-10 minutes'\n            : '10+ minutes';\n\n    // Add UX insights\n    if (replayability < 30) {\n      insights.push({\n        type: 'suggestion',\n        category: 'usability',\n        title: 'Low Replayability',\n        description: 'Users might not want to replay this flow multiple times.',\n        actionable: true,\n        suggestion:\n          'Add more decision points and multiple endings to encourage replay.',\n      });\n    }\n\n    if (engagement < 40) {\n      insights.push({\n        type: 'suggestion',\n        category: 'usability',\n        title: 'Could Be More Engaging',\n        description:\n          'Consider adding more interactive elements and meaningful choices.',\n        actionable: true,\n        suggestion:\n          'Increase the number of decision points and choice variety.',\n      });\n    }\n\n    return {\n      replayability: Math.round(replayability),\n      engagement: Math.round(engagement),\n      complexity,\n      estimatedPlayTime,\n    };\n  }\n\n  private addValidationInsights(\n    validationResult: ValidationResult,\n    insights: AnalysisInsight[]\n  ) {\n    validationResult.errors.forEach((error: ValidationError) => {\n      insights.push({\n        type: 'error',\n        category: 'structure',\n        title: error.type,\n        description: error.message,\n        nodeId: error.nodeId,\n        actionable: true,\n        suggestion:\n          'Fix this structural issue to ensure proper flow operation.',\n      });\n    });\n\n    validationResult.warnings.forEach((warning: ValidationWarning) => {\n      insights.push({\n        type: 'warning',\n        category: 'structure',\n        title: warning.type,\n        description: warning.message,\n        nodeId: warning.nodeId,\n        actionable: true,\n      });\n    });\n  }\n\n  private calculateScore(\n    structure: StructureAnalysis,\n    paths: PathAnalysis,\n    content: ContentAnalysis,\n    ux: UserExperienceAnalysis,\n    insights: AnalysisInsight[]\n  ): number {\n    let score = 100;\n\n    // Deduct for errors and warnings\n    const errors = insights.filter((i) => i.type === 'error').length;\n    const warnings = insights.filter((i) => i.type === 'warning').length;\n\n    score -= errors * 20;\n    score -= warnings * 10;\n\n    // Bonus for good structure\n    if (structure.decisionNodes > 0) score += 10;\n    if (structure.endNodes > 1) score += 10;\n    if (structure.averageChoicesPerDecision >= 2) score += 5;\n\n    // Bonus for good paths\n    if (paths.totalPaths > 3) score += 10;\n    if (paths.completedPaths === paths.totalPaths) score += 15;\n\n    // Bonus for good content\n    if (content.emptyNodes === 0) score += 10;\n    if (content.clarityScore > 70) score += 5;\n\n    // Bonus for good UX\n    if (ux.replayability > 60) score += 10;\n    if (ux.engagement > 60) score += 10;\n\n    return Math.max(0, Math.min(100, Math.round(score)));\n  }\n\n  private calculateBranchingFactor(context: AnalysisContext): number {\n    const nodeTypes = context.nodeTypes;\n    const decisionNodes = context.flow.nodes.filter(\n      (n) => nodeTypes[n.id] === 'decision'\n    );\n    if (decisionNodes.length === 0) return 1;\n\n    const totalBranches = decisionNodes.reduce(\n      (sum, node) => sum + (node.outlets?.length || 0),\n      0\n    );\n    return totalBranches / decisionNodes.length;\n  }\n\n  private calculateClarityScore(textLengths: number[]): number {\n    const avgLength =\n      textLengths.reduce((sum, len) => sum + len, 0) / textLengths.length;\n\n    // Ideal length is around 50-150 characters\n    if (avgLength >= 50 && avgLength <= 150) return 100;\n    if (avgLength >= 20 && avgLength <= 200) return 80;\n    if (avgLength >= 10 && avgLength <= 300) return 60;\n    return 40;\n  }\n\n  private getInsightPriority(insight: AnalysisInsight): number {\n    const typePriority = { error: 1, warning: 2, suggestion: 3, info: 4 };\n    const categoryPriority = {\n      structure: 1,\n      paths: 2,\n      content: 3,\n      usability: 4,\n      performance: 5,\n    };\n\n    return typePriority[insight.type] * 10 + categoryPriority[insight.category];\n  }\n}\n\ninterface StructureAnalysis {\n  totalNodes: number;\n  decisionNodes: number;\n  endNodes: number;\n  startNodes: number;\n  averageChoicesPerDecision: number;\n  maxDepth: number;\n  branchingFactor: number;\n}\n\ninterface PathAnalysis {\n  totalPaths: number;\n  completedPaths: number;\n  averagePathLength: number;\n  shortestPath: number;\n  longestPath: number;\n  unreachableNodes: number;\n  loops: number;\n}\n\ninterface ContentAnalysis {\n  averageNodeTextLength: number;\n  emptyNodes: number;\n  duplicateContent: number;\n  clarityScore: number;\n}\n\ninterface UserExperienceAnalysis {\n  replayability: number;\n  engagement: number;\n  complexity: 'simple' | 'moderate' | 'complex';\n  estimatedPlayTime: string;\n}\n","#!/usr/bin/env node\n\nimport { PathTester, PathTestResult } from './path-tester';\nimport { FlowValidator } from './flow-validator';\nimport { ZFFlow } from '../types/flow-types';\nimport { ValidationResult } from '../types/analysis-types';\n\n/**\n * Simple test runner utility for ZFlo flows\n */\nexport async function runPathTests(\n  flow: ZFFlow,\n  options: {\n    maxSteps?: number;\n    maxPaths?: number;\n    verbose?: boolean;\n  } = {}\n): Promise<PathTestResult> {\n  const pathTester = new PathTester(\n    flow,\n    options.maxPaths || 1000,\n    options.maxSteps || 100\n  );\n\n  console.log(`🧪 Testing flow: ${flow.title}`);\n  console.log('━'.repeat(50));\n\n  const startTime = Date.now();\n  const result = await pathTester.testAllPaths();\n  const duration = Date.now() - startTime;\n\n  // Print summary\n  console.log(`\\n📊 Test Results (${duration}ms)`);\n  console.log(`Status: ${result.isValid ? '✅ PASS' : '❌ FAIL'}`);\n  console.log(`Total paths: ${result.totalPaths}`);\n  console.log(`Completed paths: ${result.completedPaths}`);\n  console.log(`Errors: ${result.errors.length}`);\n  console.log(`Warnings: ${result.warnings.length}`);\n\n  // Coverage\n  const nodesCoverage = Math.round(\n    (result.coverage.nodesCovered / result.coverage.totalNodes) * 100\n  );\n  const pathsCoverage = Math.round(\n    (result.coverage.pathsCovered / result.coverage.totalPaths) * 100\n  );\n  console.log(`\\n📈 Coverage`);\n  console.log(\n    `Nodes: ${result.coverage.nodesCovered}/${result.coverage.totalNodes} (${nodesCoverage}%)`\n  );\n  console.log(\n    `Paths: ${result.coverage.pathsCovered}/${result.coverage.totalPaths} (${pathsCoverage}%)`\n  );\n\n  // Show errors\n  if (result.errors.length > 0) {\n    console.log(`\\n❌ Errors:`);\n    for (const error of result.errors) {\n      console.log(`  • ${error.type}: ${error.message}`);\n      if (error.path && options.verbose) {\n        console.log(`    Path: ${error.path.join(' → ')}`);\n      }\n    }\n  }\n\n  // Show warnings\n  if (result.warnings.length > 0) {\n    console.log(`\\n⚠️  Warnings:`);\n    for (const warning of result.warnings) {\n      console.log(`  • ${warning.type}: ${warning.message}`);\n      if (warning.path && options.verbose) {\n        console.log(`    Path: ${warning.path.join(' → ')}`);\n      }\n    }\n  }\n\n  // Show uncovered nodes\n  if (result.coverage.uncoveredNodes.length > 0) {\n    console.log(`\\n🔍 Uncovered Nodes:`);\n    for (const nodeId of result.coverage.uncoveredNodes) {\n      console.log(`  • ${nodeId}`);\n    }\n  }\n\n  // Show sample paths if verbose\n  if (options.verbose && result.pathSummary.length > 0) {\n    console.log(`\\n🛤️  Sample Paths:`);\n    const samplePaths = result.pathSummary.slice(0, 5);\n    for (const path of samplePaths) {\n      console.log(\n        `  • ${path.path.join(' → ')} (${path.steps} steps, ${path.endType})`\n      );\n    }\n    if (result.pathSummary.length > 5) {\n      console.log(`  ... and ${result.pathSummary.length - 5} more paths`);\n    }\n  }\n\n  console.log('\\n' + '━'.repeat(50));\n\n  return result;\n}\n\n/**\n * Quick validation function for a single flow\n */\nexport function validateFlow(flow: ZFFlow): ValidationResult {\n  const validator = new FlowValidator();\n  return validator.validate(flow);\n}\n"],"mappings":";AAAA,SAAS,gBAAAA,qBAAoB;;;ACA7B,SAAS,oBAAoB;;;ACA7B,SAAS,OAAO,gBAAkC;AAc3C,IAAM,eAAN,MAAkD;AAAA,EAAlD;AACL,SAAQ,QAA8B,oBAAI,IAAI;AAAA;AAAA,EAE9C,QACE,YACA,SAC6B;AAC7B,UAAM,SAAS,MAAM,UAAU;AAC/B,QAAI,OAAO,aAAa,SAAS,OAAO;AACtC,WAAK,MAAM,IAAI,YAAY,OAAO,GAAG;AAAA,IACvC;AACA,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,OAAO,CAAC,OAAO,YACV,OAAmB,OAAO,KAAK,IAAI,IACpC;AAAA,IACN;AAAA,EACF;AAAA,EAEA,SACE,YACA,SACA,EAAE,QAAQ,IAAiC,EAAE,SAAS,OAAU,GACvD;AACT,QAAI,CAAC,cAAc,OAAO,eAAe,SAAU,QAAO;AAE1D,QAAI;AACF,UAAI,MAAM,KAAK,MAAM,IAAI,UAAU;AACnC,UAAI,CAAC,KAAK;AACR,cAAM,SAAS,MAAM,UAAU;AAC/B,YAAI,OAAO,WAAW;AACpB,gBAAM,OAAO;AACb,eAAK,MAAM,IAAI,YAAY,GAAG;AAAA,QAChC,OAAO;AACL,oBAAU,IAAI,MAAO,OAAmB,OAAO,KAAK,IAAI,CAAC,CAAC;AAC1D,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,SAAS;AAAA,QACb;AAAA,QACA,WAAW,OAAO,YAAY,WAC1B,EAAE,GAAI,QAAoC,IAC1C,CAAC;AAAA,MACP;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AAGZ,gBAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,GAAa,CAAC;AAC/D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;;;AC/DO,IAAM,mBAAN,MAAuB;AAAA;AAAA;AAAA;AAAA,EAO5B,OAAO,uBAA4D;AACjE,QAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,oBAAoB;AAAA,QACvB,KAAK,IAAI,aAAa;AAAA,MACxB;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,iBACL,kBACqC;AACrC,QAAI,kBAAkB;AACpB,aAAO,EAAE,GAAG,KAAK,qBAAqB,GAAG,GAAG,iBAAiB;AAAA,IAC/D;AACA,WAAO,KAAK,qBAAqB;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,aACL,UACA,YACqB;AACrB,UAAM,gBAAgB,cAAc,KAAK,qBAAqB;AAC9D,UAAM,YAAY,cAAc,QAAQ;AAExC,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,oCAAoC,QAAQ,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,EACT;AACF;AA5Ca,iBACI,oBACb;;;ACAG,IAAM,mBAAN,MAAuB;AAAA,EAG5B,YAAY,gBAAgB,OAAO;AACjC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,YACE,MACA,SACA,SACA,OACW;AACX,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,OAAgB,SAA8C;AACxE,QAAI;AAEJ,QAAI,KAAK,YAAY,KAAK,GAAG;AAC3B,kBAAY;AAAA,IACd,WAAW,iBAAiB,OAAO;AACjC,kBAAY,KAAK;AAAA,QACf;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,kBAAY,KAAK,YAAY,iBAAiB,OAAO,KAAK,GAAG,OAAO;AAAA,IACtE;AAEA,QAAI,KAAK,eAAe;AACtB,cAAQ,MAAM,eAAe,SAAS;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,WACA,UACA,SAC6D;AAC7D,QAAI;AACF,YAAM,SAAS,MAAM,UAAU;AAC/B,aAAO,EAAE,SAAS,MAAM,OAAO;AAAA,IACjC,SAAS,OAAO;AACd,YAAM,YAAY,KAAK,YAAY,OAAO,OAAO;AACjD,aAAO,EAAE,SAAS,OAAO,QAAQ,UAAU,OAAO,UAAU;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBACE,WACA,UACA,SACoD;AACpD,QAAI;AACF,YAAM,SAAS,UAAU;AACzB,aAAO,EAAE,SAAS,MAAM,OAAO;AAAA,IACjC,SAAS,OAAO;AACd,YAAM,YAAY,KAAK,YAAY,OAAO,OAAO;AACjD,aAAO,EAAE,SAAS,OAAO,QAAQ,UAAU,OAAO,UAAU;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,KAAgC;AAClD,WACE,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,aAAa;AAAA,EAEjB;AACF;AAKO,IAAM,aAAa;AAAA;AAAA,EAExB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,6BAA6B;AAAA;AAAA,EAG7B,qBAAqB;AAAA,EACrB,qBAAqB;AAAA;AAAA,EAGrB,mBAAmB;AAAA,EACnB,cAAc;AAAA;AAAA,EAGd,+BAA+B;AAAA,EAC/B,8BAA8B;AAAA,EAC9B,iCAAiC;AAAA;AAAA,EAGjC,eAAe;AAAA,EACf,mBAAmB;AACrB;AAKO,IAAM,qBAAqB,IAAI,iBAAiB;AAahD,SAAS,+BACd,WACA,OACW;AACX,SAAO,mBAAmB;AAAA,IACxB,WAAW;AAAA,IACX,iCAAiC,SAAS;AAAA,IAC1C,EAAE,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEO,SAAS,uBACd,QACA,OACW;AACX,SAAO,mBAAmB;AAAA,IACxB,WAAW;AAAA,IACX,mCAAmC,MAAM;AAAA,IACzC,EAAE,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACjJO,IAAM,sBAAN,MAEL;AAAA,EAKA,YAAY,UAAgC,CAAC,GAAG;AAC9C,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,aACH,QAAQ,cAAc,iBAAiB,qBAAqB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,cACE,QACA,OAC8B;AAC9B,UAAM,WAAW,EAAE,GAAG,MAAM;AAC5B,UAAM,SAAmB,CAAC;AAE1B,QAAI;AACF,YAAM,EAAE,MAAM,QAAQ,OAAO,WAAW,IAAI;AAE5C,cAAQ,MAAM;AAAA,QACZ,KAAK;AACH,cAAI,YAAY;AACd,kBAAM,iBAAiB,KAAK;AAAA,cAC1B;AAAA,cACA;AAAA,YACF;AACA,iBAAK,eAAe,UAAU,QAAQ,cAAc;AACpD,gBAAI,KAAK,eAAe;AACtB,sBAAQ,IAAI,WAAW,MAAM,OAAO,cAAc,GAAG;AAAA,YACvD;AAAA,UACF,OAAO;AACL,iBAAK,eAAe,UAAU,QAAQ,KAAK;AAAA,UAC7C;AACA;AAAA,QAEF;AACE,gBAAM,IAAI,MAAM,wBAAwB,IAAI,EAAE;AAAA,MAClD;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,YAAY;AAAA,QAChB,GAAG,OAAO,IAAI,IAAI,OAAO,MAAM;AAAA,QAC/B,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AACA,aAAO,KAAK,UAAU,OAAO;AAE7B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eACE,SACA,cAC8B;AAC9B,QAAI,eAAe,EAAE,GAAG,aAAa;AACrC,UAAM,YAAsB,CAAC;AAE7B,eAAW,UAAU,SAAS;AAC5B,YAAM,SAAS,KAAK,cAAc,QAAQ,YAAY;AAEtD,UAAI,OAAO,SAAS;AAClB,uBAAe,OAAO;AAAA,MACxB,OAAO;AACL,kBAAU,KAAK,GAAG,OAAO,MAAM;AAAA,MAEjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,UAAU,WAAW;AAAA,MAC9B,UAAU;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,YAAoB,OAAwB;AAC5D,QAAI;AACF,YAAM,QAAQ,cAAc,IAAI,KAAK;AACrC,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,YAAY,KAAK,WAAW,KAAK,kBAAkB;AACzD,UAAI,CAAC,WAAW;AACd,cAAM,IAAI;AAAA,UACR,oCAAoC,KAAK,kBAAkB;AAAA,QAC7D;AAAA,MACF;AAEA,YAAM,SAAS,UAAU,SAAS,MAAM,KAAK;AAE7C,UAAI,OAAO,WAAW,WAAW;AAC/B,eAAO;AAAA,MACT;AAEA,UAAI,KAAK,eAAe;AACtB,gBAAQ;AAAA,UACN,aAAa,IAAI,iBAAiB,MAAM;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,YAAY;AAAA,QAChB;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAEA,UAAI,KAAK,eAAe;AACtB,gBAAQ,KAAK,oCAAoC,SAAS;AAAA,MAC5D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,YAAoB,OAAwB;AACrE,QAAI;AAEJ,UAAM,YAAY,KAAK,WAAW,KAAK,kBAAkB;AACzD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,oCAAoC,KAAK,kBAAkB;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,QAAQ,UAAU,SAAS,YAAY,OAAO;AAAA,MAClD,SAAS,CAAC,QAAQ;AAChB,oBAAY;AAAA,MACd;AAAA,IACF,CAAC;AAED,QAAI,WAAW;AACb,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,OAAe,MAAc,OAAsB;AACxE,QAAI,EAAE,OAAO,UAAU,YAAY,UAAU,OAAO;AAClD,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAM,UAAU,KAAK,IAAI;AAEzB,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,IACzC;AAEA,UAAM,SAAS,KAAK;AAAA,MAClB,CAAC,KAA8B,QAAgB;AAC7C,YAAI,EAAE,OAAO,KAAM,KAAI,GAAG,IAAI,CAAC;AAC/B,cAAM,OAAO,IAAI,GAAG;AAEpB,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,QACzC;AAEA,YAAI,OAAO,SAAS,UAAU;AAC5B,gBAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,QACzC;AAEA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAEA,WAAO,OAAO,IAAI;AAAA,EACpB;AACF;;;ACnOA,OAAO,SAAsD;AAC7D,OAAO,gBAAgB;AAiBhB,IAAM,kBAAN,MAAsB;AAAA,EAI3B,cAAc;AAFd,SAAQ,kBAAkB,oBAAI,IAA8B;AAG1D,SAAK,MAAM,IAAI,IAAI;AAAA,MACjB,WAAW;AAAA;AAAA,MACX,kBAAkB;AAAA;AAAA,MAClB,aAAa;AAAA;AAAA,MACb,aAAa;AAAA;AAAA,IACf,CAAC;AAGD,eAAW,KAAK,GAAG;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAAqB,UAAqC;AACtE,UAAM,KAAK,YAAY,KAAK,UAAU,MAAM;AAE5C,QAAI,YAAY,KAAK,gBAAgB,IAAI,EAAE;AAC3C,QAAI,CAAC,WAAW;AACd,UAAI;AACF,oBAAY,KAAK,IAAI,QAAQ,MAAM;AACnC,aAAK,gBAAgB,IAAI,IAAI,SAAS;AAAA,MACxC,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SACE,MACA,QACA,UACwB;AACxB,QAAI;AACF,YAAM,YAAY,KAAK,cAAc,QAAQ,QAAQ;AACrD,YAAM,UAAU,UAAU,IAAI;AAE9B,UAAI,SAAS;AACX,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ,CAAC;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,uBAAuB,UAAU,UAAU,CAAC,CAAC;AACjE,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACrF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,MAAe,QAAqB,UAAyB;AAC3E,UAAM,SAAS,KAAK,SAAS,MAAM,QAAQ,QAAQ;AAEnD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,QAAQ,IAAI;AAAA,QAChB,6BAA6B,OAAO,OAAO,KAAK,IAAI,CAAC;AAAA,MACvD;AACA,YAAM,mBAAmB,OAAO;AAChC,YAAM,OAAO;AACb,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,QAAiC;AAC9D,WAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,YAAM,OAAO,MAAM,gBAAgB;AACnC,YAAM,UAAU,MAAM,WAAW;AAEjC,cAAQ,MAAM,SAAS;AAAA,QACrB,KAAK;AACH,iBAAO,8BAA8B,MAAM,QAAQ,eAAe,OAAO,IAAI;AAAA,QAC/E,KAAK;AACH,iBAAO,mBAAmB,IAAI,cAAc,MAAM,QAAQ,IAAI,SAAS,OAAO,MAAM,IAAI;AAAA,QAC1F,KAAK;AACH,iBAAO,YAAY,IAAI,KAAK,MAAM,IAAI,sBAAsB,MAAM,QAAQ,KAAK;AAAA,QACjF,KAAK;AACH,iBAAO,YAAY,IAAI,KAAK,MAAM,IAAI,sBAAsB,MAAM,QAAQ,KAAK;AAAA,QACjF,KAAK;AACH,iBAAO,aAAa,IAAI,kCAAkC,MAAM,QAAQ,KAAK;AAAA,QAC/E,KAAK;AACH,iBAAO,aAAa,IAAI,iCAAiC,MAAM,QAAQ,KAAK;AAAA,QAC9E,KAAK;AACH,iBAAO,aAAa,IAAI;AAAA,QAC1B,KAAK;AACH,iBAAO,qBAAqB,IAAI,cAAc,MAAM,QAAQ,MAAM;AAAA,QACpE,KAAK;AACH,iBAAO,wBAAwB,MAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAAA,QAC7E;AACE,iBAAO,uBAAuB,IAAI,KAAK,OAAO;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,gBAAgB,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAqD;AACnD,WAAO;AAAA,MACL,MAAM,KAAK,gBAAgB;AAAA,MAC3B,SAAS,MAAM,KAAK,KAAK,gBAAgB,KAAK,CAAC;AAAA,IACjD;AAAA,EACF;AACF;AAGO,IAAM,wBAAwB,IAAI,gBAAgB;;;ALnJlD,IAAM,eAAN,cACG,aAEV;AAAA,EAUE,YACE,eAAuB,CAAC,GACxB,QAAqB,CAAC,GACtB,UAA+B,CAAC,GAChC;AACA,UAAM;AACN,SAAK,QAAQ;AACb,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,aAAa,iBAAiB,qBAAqB;AACxD,SAAK,cAAc,QAAQ;AAC3B,SAAK,kBAAkB;AACvB,SAAK,mBAAmB,QAAQ,oBAAoB;AAGpD,SAAK,cAAc,cAAc,iCAAiC;AAClE,SAAK,QAAQ,EAAE,GAAG,aAAa;AAG/B,SAAK,iBAAiB,IAAI,oBAA4B;AAAA,MACpD,oBAAoB,KAAK;AAAA,MACzB,YAAY,KAAK;AAAA,MACjB,eAAe;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,WAAmB;AAEjB,WAAO,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,CAAC;AAAA,EAC9C;AAAA,EAEA,SAAS,UAAiC;AAExC,UAAM,WAAW,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,CAAC;AACtD,UAAM,eAAe,EAAE,GAAG,KAAK,OAAO,GAAG,SAAS;AAGlD,SAAK,cAAc,cAAc,gCAAgC;AAEjE,SAAK,QAAQ;AACb,SAAK,KAAK,eAAe,EAAE,UAAU,UAAU,KAAK,SAAS,EAAE,CAAC;AAChE,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,eAAe,SAA8B;AAE3C,UAAM,WAAW,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,CAAC;AAEtD,UAAM,SAAS,KAAK,eAAe,eAAe,SAAS,KAAK,KAAK;AACrE,UAAM,WAAW,OAAO;AAGxB,SAAK,cAAc,UAAU,oCAAoC;AAEjE,SAAK,QAAQ;AAEb,SAAK,KAAK,eAAe,EAAE,UAAU,UAAU,KAAK,SAAS,EAAE,CAAC;AAChE,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,kBAAkB,YAA6B;AAC7C,WAAO,KAAK,eAAe,kBAAkB,YAAY,KAAK,KAAK;AAAA,EACrE;AAAA,EAEQ,gBAAsB;AAC5B,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,kBAAkB,KAAK,SAAS,GAAG;AAC1C,aAAK,YAAY,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,MAAuB;AACzC,YAAQ,KAAK,QAAQ;AAAA,MACnB,KAAK;AACH,aAAK,KAAK,SAAS;AAAA,UACjB,OAAO,IAAI,MAAM,uBAAuB,KAAK,MAAM,EAAE;AAAA,UACrD,SAAS,EAAE,MAAM,MAAM,kBAAkB;AAAA,QAC3C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,YAAI,KAAK,UAAU,KAAK,UAAU,QAAW;AAE3C,gBAAM,SAAS,KAAK,eAAe;AAAA,YACjC,EAAE,MAAM,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,MAAM;AAAA,YACtD,KAAK;AAAA,UACP;AACA,cAAI,OAAO,SAAS;AAClB,iBAAK,QAAQ,OAAO;AAAA,UACtB;AAAA,QACF;AACA;AAAA,MAEF,KAAK;AAEH;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,WAA4B,CAAC,GAA4B;AAE7D,UAAM,WAAW,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,CAAC;AAEtD,UAAM,aAAa,KAAK,MAAM,KAAK,UAAU,QAAQ,CAAC;AAGtD,SAAK,cAAc,YAAY,+BAA+B;AAE9D,SAAK,QAAQ;AACb,SAAK,KAAK,eAAe,EAAE,UAAU,UAAU,KAAK,SAAS,EAAE,CAAC;AAChE,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAgB,aAA2B;AAC/D,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,kBAAkB;AAC/C;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,KAAK,gBAAgB,SAAS,OAAO,KAAK,WAAW;AAEpE,UAAI,CAAC,OAAO,SAAS;AACnB,cAAM,QAAQ,IAAI,MAAM,GAAG,WAAW,KAAK,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AACrE,aAAK,KAAK,SAAS;AAAA,UACjB;AAAA,UACA,SAAS,EAAE,MAAM,oBAAoB,QAAQ,OAAO,OAAO;AAAA,QAC7D,CAAC;AACD,cAAM;AAAA,MACR;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,OAAO;AAE1B,cAAM;AAAA,MACR;AAGA,YAAM,kBAAkB,IAAI;AAAA,QAC1B,GAAG,WAAW;AAAA,MAChB;AACA,WAAK,KAAK,SAAS;AAAA,QACjB,OAAO;AAAA,QACP,SAAS,EAAE,MAAM,oBAAoB,eAAe,MAAM;AAAA,MAC5D,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AMzJO,IAAM,sBAAN,MAA0B;AAAA,EAK/B,YAAY,UAAuC,CAAC,GAAG;AACrD,SAAK,qBAAqB,QAAQ,sBAAsB;AACxD,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,aAAa,iBAAiB,qBAAqB;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,YACE,SACA,OACqB;AACrB,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,aAAO;AAAA,QACL,SAAS,WAAW;AAAA,QACpB,mBAAmB;AAAA,QACnB,QAAQ,CAAC;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAmB,CAAC;AAC1B,QAAI,oBAAoB;AAGxB,UAAM,qBAAqB;AAC3B,QAAI,wBAAkC,CAAC;AAGvC,QAAI,mBAAmB,QAAQ;AAAA,MAC7B;AAAA,MACA,CAAC,QAAQ,eAAe;AACtB,8BAAsB,KAAK,MAAM,UAAU,GAAG;AAC9C,eAAO,GAAG,kBAAkB,GAAG,sBAAsB,SAAS,CAAC;AAAA,MACjE;AAAA,IACF;AAGA,UAAM,qBAAqB;AAE3B,UAAM,sBAAsB,iBAAiB;AAAA,MAC3C;AAAA,MACA,CAAC,QAAQ,eAAe;AACtB,4BAAoB;AAEpB,YAAI;AACF,gBAAM,SAAS,KAAK,mBAAmB,WAAW,KAAK,GAAG,KAAK;AAG/D,cAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,kBAAM,WAAW,aAAa,UAAU;AACxC,mBAAO,KAAK,QAAQ;AAEpB,gBAAI,KAAK,eAAe;AACtB,sBAAQ,KAAK,uCAAuC,QAAQ;AAAA,YAC9D;AAEA,mBAAO;AAAA,UACT;AAEA,iBAAO,KAAK,YAAY,MAAM;AAAA,QAChC,SAAS,OAAO;AACd,gBAAM,WAAW,0BAA0B,UAAU,MACnD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAEA,iBAAO,KAAK,QAAQ;AAEpB,cAAI,KAAK,eAAe;AACtB,oBAAQ,KAAK,qCAAqC,QAAQ;AAAA,UAC5D;AAGA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,UAAM,eAAe,oBAAoB;AAAA,MACvC,IAAI,OAAO,GAAG,kBAAkB,UAAU,GAAG;AAAA,MAC7C,CAAC,UAAU,SAAS;AAClB,eAAO,sBAAsB,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK;AAAA,MACrD;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAA0B;AAC1C,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,WAAO,cAAc,KAAK,OAAO;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,SAA2B;AAC5C,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO,CAAC;AAErD,UAAM,cAAwB,CAAC;AAC/B,UAAM,qBAAqB;AAC3B,QAAI;AAEJ,YAAQ,QAAQ,mBAAmB,KAAK,OAAO,OAAO,MAAM;AAC1D,UAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AACvB;AAAA,MACF;AACA,kBAAY,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,SAAuD;AACzE,UAAM,cAAc,KAAK,mBAAmB,OAAO;AACnD,UAAM,SAAmB,CAAC;AAE1B,eAAW,cAAc,aAAa;AACpC,UAAI;AACF,cAAM,YAAY,KAAK,WAAW,KAAK,kBAAkB;AACzD,YAAI,CAAC,WAAW;AACd,iBAAO;AAAA,YACL,oCAAoC,KAAK,kBAAkB;AAAA,UAC7D;AACA;AAAA,QACF;AAGA,YAAI,UAAU,SAAS;AACrB,gBAAM,SAAS,UAAU,QAAQ,YAAY,EAAE,OAAO,MAAM,CAAC;AAC7D,cAAI,CAAC,OAAO,WAAW,OAAO,OAAO;AACnC,mBAAO,KAAK,uBAAuB,UAAU,MAAM,OAAO,KAAK,EAAE;AAAA,UACnE;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,eAAO;AAAA,UACL,qCAAqC,UAAU,MAC7C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,OAAO,WAAW;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBACN,YACA,OACS;AACT,UAAM,YAAY,KAAK,WAAW,KAAK,kBAAkB;AACzD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,oCAAoC,KAAK,kBAAkB;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI;AAEJ,UAAM,SAAS,UAAU,SAAS,YAAY,OAAO;AAAA,MACnD,SAAS,CAAC,QAAQ;AAChB,0BAAkB;AAAA,MACpB;AAAA,IACF,CAAC;AAED,QAAI,iBAAiB;AACnB,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,OAAwB;AAC1C,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,UAAU,UAAU;AAE7B,aAAO,OAAO,UAAU,KAAK,IAAI,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC;AAAA,IACrE;AAEA,QAAI,OAAO,UAAU,WAAW;AAC9B,aAAO,QAAQ,SAAS;AAAA,IAC1B;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO,MAAM,IAAI,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,EAAE,KAAK,IAAI;AAAA,IACxD;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,UAAI;AACF,eAAO,KAAK,UAAU,KAAK;AAAA,MAC7B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;;ACzPO,SAAS,eAAe,OAA2C;AACxE,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,WAAW,oBAAI,IAAoB;AAEzC,aAAW,KAAK,OAAO;AACrB,aAAS,IAAI,EAAE,IAAI,EAAE,SAAS,UAAU,CAAC;AACzC,eAAW,KAAK,EAAE,WAAW,CAAC,GAAG;AAC/B,eAAS,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,EAAE,KAAK,KAAK,CAAC;AAAA,IAClD;AAAA,EACF;AAEA,QAAM,UAAoC,CAAC;AAE3C,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,SAAS,IAAI,EAAE,EAAE,KAAK;AAClC,UAAM,MAAM,SAAS,IAAI,EAAE,EAAE,KAAK;AAClC,QAAI,QAAQ,KAAK,QAAQ,GAAG;AAC1B,cAAQ,EAAE,EAAE,IAAI;AAAA,IAClB,WAAW,CAAC,OAAO,MAAM,GAAG;AAC1B,cAAQ,EAAE,EAAE,IAAI;AAAA,IAClB,WAAW,QAAQ,KAAK,MAAM,GAAG;AAC/B,cAAQ,EAAE,EAAE,IAAI;AAAA,IAClB,WAAW,MAAM,GAAG;AAClB,cAAQ,EAAE,EAAE,IAAI;AAAA,IAClB,OAAO;AACL,cAAQ,EAAE,EAAE,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AACT;;;ARXO,IAAM,aAAN,cAEGC,cAAsC;AAAA,EAS9C,YAAY,MAAc,UAAiC,CAAC,GAAG;AAC7D,UAAM;AANR,SAAQ,cAA6B;AACrC,SAAQ,UAAmC,CAAC;AAM1C,SAAK,OAAO;AACZ,SAAK,YAAY,eAAe,KAAK,KAAK;AAC1C,SAAK,UAAU;AAAA,MACb,eAAe;AAAA,MACf,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,GAAG;AAAA,IACL;AAGA,UAAM,eAAe;AAAA,MACnB,GAAG,KAAK,MAAM,KAAK,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC;AAAA,MACpD,GAAG,KAAK,MAAM,KAAK,UAAU,QAAQ,gBAAgB,CAAC,CAAC,CAAC;AAAA,IAC1D;AAGA,QAAI,QAAQ,cAAc;AACxB,WAAK,eAAe,QAAQ;AAAA,IAC9B,OAAO;AACL,WAAK,eAAe,IAAI;AAAA,QACtB;AAAA,QACA,KAAK,cAAc,CAAC;AAAA,QACpB;AAAA,UACE,oBAAoB,KAAK,sBAAsB;AAAA,UAC/C,aAAa,KAAK;AAAA,UAClB,kBAAkB;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAGA,SAAK,sBAAsB,IAAI,oBAAoB;AAAA,MACjD,oBAAoB,KAAK,sBAAsB;AAAA,MAC/C,eAAe,QAAQ,iBAAiB;AAAA,IAC1C,CAAC;AAGD,SAAK,aAAa;AAAA,MAChB;AAAA,MACA,CAAC,SACC,KAAK,KAAK,eAAe,IAAI;AAAA,IACjC;AACA,SAAK,aAAa;AAAA,MAChB;AAAA,MACA,CAAC,SAGK;AACJ,YACE,KAAK,SAAS,SAAS,qBACvB,KAAK,QAAQ,MAAM,QACnB;AAEA,eAAK,uBAAuB,KAAK,QAAQ,KAAK,MAAM;AAAA,QACtD,OAAO;AACL,eAAK,KAAK,SAAS,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAA0C;AAC9C,UAAM,YAAY,KAAK,aAAa,KAAK,KAAK,WAAW;AACzD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,uBAAuB,KAAK,KAAK,WAAW;AAAA,MAC9C;AAAA,IACF;AAEA,WAAO,KAAK,iBAAiB,SAAS;AAAA,EACxC;AAAA,EAEA,MAAM,KAAK,UAAqD;AAC9D,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAEA,QAAI,aAA4B;AAChC,UAAM,kBAAkB,KAAK,UAAU,KAAK,YAAY,EAAE;AAE1D,QAAI,UAAU;AAEZ,YAAM,eAAe,KAAK,eAAe,QAAQ;AACjD,UAAI,CAAC,gBAAgB,aAAa,eAAe,KAAK,YAAY,IAAI;AACpE,cAAM,IAAI,MAAM,mBAAmB,QAAQ,EAAE;AAAA,MAC/C;AACA,mBAAa,KAAK,aAAa,aAAa,OAAO,EAAE;AAAA,IACvD,OAAO;AACL,UAAI,oBAAoB,YAAY;AAElC,qBAAa,KAAK,0BAA0B,KAAK,WAAW;AAAA,MAC9D,OAAO;AAGL,YAAI,oBAAoB,UAAU;AAChC,gBAAM,UAAU,KAAK,WAAW,KAAK,YAAY,EAAE;AACnD,cAAI,QAAQ,WAAW,KAAK,QAAQ,CAAC,GAAG;AACtC,yBAAa,KAAK,aAAa,QAAQ,CAAC,EAAE,EAAE;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,cAAc,oBAAoB,YAAY;AACjD,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAGA,QAAI,oBAAoB,cAAc,CAAC,UAAU;AAC/C,aAAO,KAAK,sBAAsB;AAAA,IACpC;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAEA,WAAO,KAAK,iBAAiB,YAAY,QAAQ;AAAA,EACnD;AAAA,EAEA,iBAAuC;AACrC,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO;AAAA,IACT;AACA,UAAM,WAAW,KAAK,UAAU,KAAK,YAAY,EAAE;AACnD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,iCAAiC,KAAK,YAAY,EAAE,EAAE;AAAA,IACxE;AACA,WAAO;AAAA,MACL,MAAM,KAAK,oBAAoB,KAAK,WAAW;AAAA,MAC/C,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,aAAsC;AACpC,WAAO,CAAC,GAAG,KAAK,OAAO;AAAA,EACzB;AAAA,EAEA,sBAAgC;AAC9B,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,kBAAkB,KAAK,UAAU,KAAK,YAAY,EAAE;AAC1D,QAAI,oBAAoB,OAAO;AAC7B,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,aAAa,KAAK,WAAW,KAAK,YAAY,EAAE;AACtD,UAAM,eAAe,KAAK,QAAQ,uBAAuB;AACzD,UAAM,eAAe,KAAK,aAAa,SAAS;AAEhD,QAAI;AACJ,QAAI;AACJ,UAAM,iBAAiB,WAAW,WAAW;AAE7C,UAAM,2BAA2B;AAEjC,QAAI,cAAc;AAEhB,sBAAgB;AAChB,gBAAU,cAAc,IAAI,CAAC,QAAQ,UAAkB;AACrD,cAAM,YAAY,KAAK,wBAAwB,MAAM;AACrD,cAAM,cACJ,OAAO,YACP,iBAAiB,OAAO,YACxB,OAAO,OAAO,SAAS,gBAAgB,WACnC,OAAO,SAAS,cAChB;AAGN,YAAI,QAAQ,KAAK,oBAAoB;AAAA,UACnC,OAAO,QACH,OAAO,QACP,iBACE,2BACA,aAAa,QAAQ;AAAA;AAAA,UAC3B;AAAA,QACF,EAAE;AAEF,eAAO;AAAA,UACL,IAAI,OAAO;AAAA,UACX;AAAA,UACA;AAAA,UACA,UAAU,OAAO;AAAA,UACjB,UAAU,CAAC;AAAA,UACX,gBACE,CAAC,aAAa,OAAO,YACjB,sBACA;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AAEL,sBAAgB,WAAW;AAAA,QAAO,CAAC,WACjC,KAAK,wBAAwB,MAAM;AAAA,MACrC;AACA,gBAAU,cAAc,IAAI,CAAC,QAAQ,UAAkB;AAErD,YAAI,QAAQ,KAAK,oBAAoB;AAAA,UACnC,OAAO,QACH,OAAO,QACP,iBACE,2BACA,aAAa,QAAQ;AAAA;AAAA,UAC3B;AAAA,QACF,EAAE;AAEF,eAAO;AAAA,UACL,IAAI,OAAO;AAAA,UACX;AAAA,UACA,aACE,OAAO,YACP,iBAAiB,OAAO,YACxB,OAAO,OAAO,SAAS,gBAAgB,WACnC,OAAO,SAAS,cAChB;AAAA,UACN,UAAU,OAAO;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,iBAAiB,eACnB,QAAQ,OAAO,CAAC,WAAW,CAAC,OAAO,QAAQ,IAC3C;AAEJ,QACE,eAAe,WAAW,KAC1B,eAAe,CAAC,KAChB,CAAC,eAAe,CAAC,EAAE,OAAO,KAAK,GAC/B;AACA,YAAM,iBAAiB,eAAe,CAAC;AACvC,UAAI,CAAC,eAAe,MAAM,CAAC,eAAe,UAAU;AAClD,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AACA,YAAM,eAAe,cAAc;AAAA,QACjC,CAAC,MAAM,EAAE,OAAO,eAAe;AAAA,MACjC;AACA,YAAM,aAAa,eACf,KAAK,aAAa,aAAa,EAAE,IACjC;AACJ,aAAO;AAAA,QACL;AAAA,UACE,GAAG;AAAA,UACH,IAAI,eAAe;AAAA,UACnB,UAAU,eAAe;AAAA,UACzB,OAAO;AAAA,UACP,aAAa,eAAe,YAAY,SAAS,WAAW;AAAA,QAC9D;AAAA,QACA,GAAG,QAAQ,OAAO,CAAC,WAAW,OAAO,QAAQ;AAAA;AAAA,MAC/C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,aAAsB;AACpB,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO;AAAA,IACT;AACA,UAAM,kBAAkB,KAAK,UAAU,KAAK,YAAY,EAAE;AAC1D,WAAO,oBAAoB;AAAA,EAC7B;AAAA,EAEA,YAAqB;AACnB,WAAO,QAAQ,KAAK,QAAQ,aAAa,KAAK,KAAK,QAAQ,SAAS;AAAA,EACtE;AAAA,EAEA,SAA2C;AACzC,QAAI,CAAC,KAAK,UAAU,GAAG;AACrB,YAAM,IAAI,MAAM,gBAAgB;AAAA,IAClC;AAGA,SAAK,QAAQ,IAAI;AACjB,UAAM,eAAe,KAAK,QAAQ,KAAK,QAAQ,SAAS,CAAC;AACzD,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAGA,SAAK,aAAa,MAAM,aAAa,KAAK;AAC1C,SAAK,cAAc,aAAa,KAAK;AAErC,WAAO,QAAQ,QAAQ,KAAK,sBAAsB,CAAC;AAAA,EACrD;AAAA,EAEA,QAAc;AACZ,SAAK,cAAc;AACnB,SAAK,UAAU,CAAC;AAEhB,SAAK,aAAa;AAAA,MAChB,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,eAAe,CAAC,CAAC,CAAC;AAAA,IACxD;AAAA,EACF;AAAA,EAEA,WAAmB;AACjB,WAAO,KAAK,aAAa,SAAS;AAAA,EACpC;AAAA,EAEA,kBAAyC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,iBACZ,MACA,UACkC;AAElC,QAAI,KAAK,aAAa;AACpB,WAAK,KAAK,YAAY;AAAA,QACpB,MAAM,KAAK;AAAA,QACX,QAAQ;AAAA,QACR,OAAO,KAAK,aAAa,SAAS;AAAA,MACpC,CAAC;AAAA,IACH;AAGA,QAAI,YAAY,KAAK,aAAa;AAChC,YAAM,eAAe,KAAK,eAAe,QAAQ;AACjD,UAAI,cAAc,OAAO,SAAS;AAChC,aAAK,aAAa,eAAe,aAAa,OAAO,OAAO;AAAA,MAC9D;AAAA,IACF;AAGA,SAAK,cAAc;AAGnB,QAAI,KAAK,SAAS;AAChB,WAAK,aAAa,eAAe,KAAK,OAAO;AAAA,IAC/C;AAGA,QAAI,KAAK,QAAQ,eAAe;AAC9B,YAAM,WAAW,KAAK,UAAU,KAAK,EAAE;AACvC,UAAI,CAAC,UAAU;AACb,cAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE,EAAE;AAAA,MAC5D;AACA,YAAM,OAA8B;AAAA,QAClC,MAAM,EAAE,MAAM,MAAM,SAAS;AAAA,QAC7B,QAAQ;AAAA,QACR,WAAW,oBAAI,KAAK;AAAA,QACpB,OAAO,KAAK,aAAa,SAAS;AAAA,MACpC;AACA,WAAK,QAAQ,KAAK,IAAI;AAGtB,YAAM,UAAU,KAAK,QAAQ,kBAAkB;AAC/C,UAAI,KAAK,QAAQ,SAAS,SAAS;AACjC,aAAK,QAAQ,MAAM;AAAA,MACrB;AAAA,IACF;AAGA,SAAK,KAAK,aAAa;AAAA,MACrB;AAAA,MACA,OAAO,KAAK,aAAa,SAAS;AAAA,IACpC,CAAC;AAGD,UAAM,mBAAmB,KAAK,WAAW,KAAK,EAAE;AAChD,QAAI,KAAK,kBAAkB,MAAM,gBAAgB,GAAG;AAClD,YAAM,iBAAiB,KAAK;AAAA,QAC1B;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,gBAAgB;AACnB,aAAK,KAAK,SAAS;AAAA,UACjB,OAAO,IAAI;AAAA,YACT,qDAAqD,KAAK,EAAE;AAAA,UAC9D;AAAA,UACA,SAAS;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AACD,eAAO,KAAK,sBAAsB;AAAA,MACpC;AAEA,YAAM,SAAS,KAAK,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,eAAe,EAAE;AACrE,UAAI,CAAC,QAAQ;AACX,aAAK,KAAK,SAAS;AAAA,UACjB,OAAO,IAAI,MAAM,iBAAiB,eAAe,EAAE,aAAa;AAAA,UAChE,SAAS;AAAA,YACP;AAAA,YACA,QAAQ;AAAA,UACV;AAAA,QACF,CAAC;AACD,eAAO,KAAK,sBAAsB;AAAA,MACpC;AAEA,WAAK,KAAK,eAAe;AAAA,QACvB,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,WAAW,eAAe;AAAA,MAC5B,CAAC;AAED,aAAO,KAAK,iBAAiB,QAAQ,eAAe,EAAE;AAAA,IACxD;AAEA,WAAO,KAAK,sBAAsB;AAAA,EACpC;AAAA,EAEQ,0BAA0B,MAA6B;AAE7D,UAAM,mBAAmB,KAAK,WAAW,KAAK,EAAE;AAChD,UAAM,gBAAgB,CAAC,GAAG,gBAAgB;AAG1C,eAAW,UAAU,eAAe;AAClC,UAAI,KAAK,wBAAwB,MAAM,GAAG;AACxC,eAAO,KAAK,aAAa,OAAO,EAAE;AAAA,MACpC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,wBAAwB,QAA2B;AACzD,QAAI,CAAC,OAAO,UAAW,QAAO;AAE9B,QAAI;AACF,aAAO,KAAK,aAAa,kBAAkB,OAAO,SAAS;AAAA,IAC7D,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,wCAAwC,OAAO,SAAS;AAAA,QACxD;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,wBACN,OACA,kBACiB;AAEjB,UAAM,qBAAqB,iBAAiB;AAAA,MAC1C,CAAC,WAAW,OAAO;AAAA,IACrB;AACA,UAAM,iBAAiB,iBAAiB;AAAA,MACtC,CAAC,WAAW,CAAC,OAAO;AAAA,IACtB;AAGA,eAAW,UAAU,oBAAoB;AACvC,UAAI,KAAK,wBAAwB,MAAM,GAAG;AACxC,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,eAAe,SAAS,KAAK,eAAe,CAAC,GAAG;AAClD,aAAO,eAAe,CAAC;AAAA,IACzB;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,MAAsB;AAChD,UAAM,eAAe,KAAK,aAAa,SAAS;AAChD,QAAI,mBAAmB,EAAE,GAAG,KAAK;AACjC,QAAI,uBAAuB;AAC3B,UAAM,YAAsB,CAAC;AAG7B,QAAI,KAAK,SAAS,KAAK,oBAAoB,kBAAkB,KAAK,KAAK,GAAG;AACxE,YAAM,cAAc,KAAK,oBAAoB;AAAA,QAC3C,KAAK;AAAA,QACL;AAAA,MACF;AACA,uBAAiB,QAAQ,YAAY;AACrC,6BAAuB;AACvB,gBAAU,KAAK,GAAG,YAAY,MAAM;AAAA,IACtC;AAGA,QACE,KAAK,WACL,KAAK,oBAAoB,kBAAkB,KAAK,OAAO,GACvD;AACA,YAAM,gBAAgB,KAAK,oBAAoB;AAAA,QAC7C,KAAK;AAAA,QACL;AAAA,MACF;AACA,uBAAiB,UAAU,cAAc;AACzC,6BAAuB;AACvB,gBAAU,KAAK,GAAG,cAAc,MAAM;AAAA,IACxC;AAGA,QAAI,UAAU,SAAS,KAAK,KAAK,QAAQ,eAAe;AACtD,cAAQ,KAAK,kCAAkC,KAAK,EAAE,MAAM,SAAS;AAAA,IACvE;AAGA,QAAI,CAAC,sBAAsB;AACzB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,wBAAiD;AACvD,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,UAAM,WAAW,KAAK,UAAU,KAAK,YAAY,EAAE;AACnD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,iCAAiC,KAAK,YAAY,EAAE,EAAE;AAAA,IACxE;AACA,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,MAAM,KAAK,oBAAoB,KAAK,WAAW;AAAA,QAC/C,MAAM;AAAA,MACR;AAAA,MACA,SAAS,KAAK,oBAAoB;AAAA,MAClC,YAAY,KAAK,WAAW;AAAA,MAC5B,WAAW,KAAK,UAAU;AAAA,MAC1B,OAAO,KAAK,aAAa,SAAS;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,uBAAuB,cAA4B;AACzD,UAAM,aAAa,KAAK,aAAa,YAAY;AACjD,QAAI,CAAC,YAAY;AACf,WAAK,KAAK,SAAS;AAAA,QACjB,OAAO,IAAI;AAAA,UACT,gBAAgB,YAAY;AAAA,QAC9B;AAAA,QACA,SAAS,EAAE,MAAM,oBAAoB,aAAa;AAAA,MACpD,CAAC;AACD;AAAA,IACF;AAEA,SAAK,iBAAiB,UAAU,EAAE,MAAM,CAAC,UAAU;AACjD,WAAK,KAAK,SAAS;AAAA,QACjB;AAAA,QACA,SAAS,EAAE,MAAM,oBAAoB,aAAa;AAAA,MACpD,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,kBACN,MACA,kBACS;AACT,QACE,KAAK,KAAK,gBAAgB,WAC1B,KAAK,QAAQ,gBAAgB,SAC7B;AACA,aAAO;AAAA,IACT;AACA,QAAI,KAAK,eAAe;AACtB,aAAO,KAAK,wBAAwB,MAAM,gBAAgB,MAAM;AAAA,IAClE,WACE,KAAK,KAAK,gBAAgB,YAC1B,KAAK,QAAQ,gBAAgB,UAC7B;AACA,aAAO,KAAK,wBAAwB,MAAM,gBAAgB,MAAM;AAAA,IAClE,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,aAAa,IAA2B;AAC9C,WAAO,KAAK,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE,KAAK;AAAA,EAC3D;AAAA,EAEQ,WAAW,QAA4B;AAC7C,UAAM,OAAO,KAAK,aAAa,MAAM;AACrC,WAAO,MAAM,WAAW,CAAC;AAAA,EAC3B;AAAA,EAEQ,eACN,UACiD;AACjD,eAAW,QAAQ,KAAK,KAAK,OAAO;AAClC,UAAI,KAAK,SAAS;AAChB,cAAM,SAAS,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzD,YAAI,QAAQ;AACV,iBAAO,EAAE,QAAQ,YAAY,KAAK,GAAG;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AS1mBO,IAAM,WAAN,MAAqB;AAAA,EAK1B,YAAY,UAAwB,CAAC,GAAG;AAJxC,SAAQ,QAAQ,oBAAI,IAAwC;AAK1D,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,MAAM,QAAQ,OAAO;AAAA,EAC5B;AAAA,EAEA,IAAI,KAAuB;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AAGnB,QAAI,KAAK,IAAI,IAAI,MAAM,YAAY,KAAK,KAAK;AAC3C,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAGA,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,IAAI,KAAQ,OAAgB;AAE1B,SAAK,MAAM,OAAO,GAAG;AAGrB,QAAI,KAAK,MAAM,QAAQ,KAAK,SAAS;AAEnC,YAAM,WAAW,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC1C,UAAI,aAAa,QAAW;AAC1B,aAAK,MAAM,OAAO,QAAQ;AAAA,MAC5B;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,KAAK,EAAE,OAAO,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EACtD;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,OAAe;AACb,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;;;ACrBO,IAAM,iBAAN,MAAqB;AAAA,EAO1B,YAAY,MAAc;AACxB,SAAK,OAAO;AACZ,SAAK,UAAU,oBAAI,IAAI;AACvB,SAAK,UAAU,oBAAI,IAAI;AACvB,SAAK,oBAAoB,IAAI,SAAS,EAAE,SAAS,IAAI,KAAK,IAAO,CAAC;AAClE,SAAK,aAAa,IAAI,SAAS,EAAE,SAAS,IAAI,KAAK,IAAO,CAAC;AAG3D,eAAW,QAAQ,KAAK,OAAO;AAC7B,WAAK,QAAQ,IAAI,KAAK,IAAI,IAAI;AAAA,IAChC;AAGA,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,SAAS;AAChB,mBAAW,QAAQ,KAAK,SAAS;AAC/B,eAAK,QAAQ,IAAI,KAAK,IAAI,EAAE,MAAM,YAAY,KAAK,GAAG,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAA+B;AACtC,WAAO,KAAK,QAAQ,IAAI,MAAM,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAA+D;AACtE,WAAO,KAAK,QAAQ,IAAI,MAAM,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,QAA4B;AAC3C,UAAM,OAAO,KAAK,QAAQ,IAAI,MAAM;AACpC,WAAO,MAAM,WAAW,CAAC;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,iBACE,QAC+C;AAC/C,UAAM,WAA0D,CAAC;AAEjE,eAAW,QAAQ,KAAK,KAAK,OAAO;AAClC,UAAI,KAAK,SAAS;AAChB,mBAAW,QAAQ,KAAK,SAAS;AAC/B,cAAI,KAAK,OAAO,QAAQ;AACtB,qBAAS,KAAK,EAAE,MAAM,YAAY,KAAK,GAAG,CAAC;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,aAAmC;AACpD,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,WAAW,aAAa,KAAK;AAGnC,UAAM,SAAS,KAAK,kBAAkB,IAAI,QAAQ;AAClD,QAAI,QAAQ;AACV,aAAO,IAAI,IAAI,MAAM;AAAA,IACvB;AAEA,UAAM,YAAY,oBAAI,IAAY;AAClC,UAAM,QAAQ,CAAC,KAAK;AAEpB,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,SAAS,MAAM,MAAM;AAC3B,UAAI,CAAC,UAAU,UAAU,IAAI,MAAM,EAAG;AAEtC,gBAAU,IAAI,MAAM;AAEpB,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAClD,iBAAW,QAAQ,eAAe;AAChC,YAAI,CAAC,UAAU,IAAI,KAAK,EAAE,GAAG;AAC3B,gBAAM,KAAK,KAAK,EAAE;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAGA,SAAK,kBAAkB,IAAI,UAAU,SAAS;AAC9C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,aAAmC;AACtD,UAAM,YAAY,KAAK,mBAAmB,WAAW;AACrD,UAAM,cAAc,oBAAI,IAAY;AAEpC,eAAW,QAAQ,KAAK,KAAK,OAAO;AAClC,UAAI,CAAC,UAAU,IAAI,KAAK,EAAE,GAAG;AAC3B,oBAAY,IAAI,KAAK,EAAE;AAAA,MACzB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,cAAsB,aAA+B;AACnE,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,QAAQ,CAAC,KAAK;AAEpB,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,SAAS,MAAM,MAAM;AAC3B,UAAI,CAAC,UAAU,QAAQ,IAAI,MAAM,EAAG;AACpC,cAAQ,IAAI,MAAM;AAElB,UAAI,WAAW,aAAc,QAAO;AAEpC,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAClD,iBAAW,QAAQ,eAAe;AAChC,YAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,GAAG;AACzB,gBAAM,KAAK,KAAK,EAAE;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,aAA8B;AAC9C,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,UAAU,oBAAI,IAAY;AAEhC,UAAM,MAAM,CAAC,QAAgB,UAA0B;AACrD,UAAI,QAAQ,IAAI,MAAM,EAAG,QAAO;AAChC,cAAQ,IAAI,MAAM;AAElB,YAAM,OAAO,KAAK,SAAS,MAAM;AACjC,UAAI,CAAC,KAAM,QAAO;AAElB,UAAI,WAAW;AACf,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAElD,iBAAW,QAAQ,eAAe;AAChC,mBAAW,KAAK,IAAI,UAAU,IAAI,KAAK,IAAI,QAAQ,CAAC,CAAC;AAAA,MACvD;AAEA,aAAO;AAAA,IACT;AAEA,WAAO,IAAI,OAAO,CAAC;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,aAA2C;AAC7D,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,WAAW,UAAU,KAAK;AAGhC,UAAM,SAAS,KAAK,WAAW,IAAI,QAAQ;AAC3C,QAAI,QAAQ;AACV,aAAO,IAAI,IAAI,MAAM;AAAA,IACvB;AAEA,UAAM,SAAS,oBAAI,IAAoB;AACvC,UAAM,QAAQ,CAAC,EAAE,QAAQ,OAAO,OAAO,EAAE,CAAC;AAE1C,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,MAAM;AAC5B,UAAI,CAAC,QAAS;AACd,YAAM,EAAE,QAAQ,MAAM,IAAI;AAE1B,UAAI,OAAO,IAAI,MAAM,EAAG;AACxB,aAAO,IAAI,QAAQ,KAAK;AAExB,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAClD,iBAAW,QAAQ,eAAe;AAChC,YAAI,CAAC,OAAO,IAAI,KAAK,EAAE,GAAG;AACxB,gBAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,OAAO,QAAQ,EAAE,CAAC;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAGA,SAAK,WAAW,IAAI,UAAU,MAAM;AACpC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,aAA+B;AACvC,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,WAAW,oBAAI,IAAY;AACjC,UAAM,UAAU,oBAAI,IAAY;AAEhC,UAAM,MAAM,CAAC,WAA4B;AACvC,UAAI,SAAS,IAAI,MAAM,EAAG,QAAO;AACjC,UAAI,QAAQ,IAAI,MAAM,EAAG,QAAO;AAEhC,eAAS,IAAI,MAAM;AAEnB,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAClD,iBAAW,QAAQ,eAAe;AAChC,YAAI,IAAI,KAAK,EAAE,EAAG,QAAO;AAAA,MAC3B;AAEA,eAAS,OAAO,MAAM;AACtB,cAAQ,IAAI,MAAM;AAClB,aAAO;AAAA,IACT;AAEA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,aAA4C;AAC3D,UAAM,QAAQ,eAAe,KAAK,KAAK;AACvC,UAAM,iBAAiB,KAAK,mBAAmB,KAAK;AACpD,UAAM,aAAa,KAAK,oBAAoB,KAAK;AACjD,UAAM,eAAe,oBAAI,IAAY;AACrC,UAAM,gBAAgB,oBAAI,IAAwB;AAGlD,eAAW,UAAU,gBAAgB;AACnC,YAAM,gBAAgB,KAAK,iBAAiB,MAAM;AAClD,oBAAc,IAAI,QAAQ,aAAa;AAEvC,iBAAW,QAAQ,eAAe;AAChC,YAAI,eAAe,IAAI,KAAK,EAAE,GAAG;AAC/B,uBAAa,IAAI,KAAK,EAAE;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,UAAkC,CAAC,GAA0B;AAC3E,UAAM;AAAA,MACJ,WAAW;AAAA,MACX,WAAW;AAAA,MACX,eAAe;AAAA,MACf;AAAA,IACF,IAAI;AAEJ,UAAM,WAKD,CAAC;AAEN,UAAM,QAAQ;AAAA,MACZ;AAAA,QACE,QAAQ,KAAK,KAAK;AAAA,QAClB,MAAM,CAAC,KAAK,KAAK,WAAW;AAAA,QAC5B,SAAS,CAAC;AAAA,QACV,OAAO;AAAA,QACP,OAAO,eAAe,EAAE,GAAG,KAAK,KAAK,YAAY,IAAI;AAAA,MACvD;AAAA,IACF;AAEA,UAAM,iBAAiB,oBAAI,IAAY;AACvC,QAAI,kBAAkB;AACtB,QAAI,YAAY;AAEhB,WAAO,MAAM,SAAS,KAAK,SAAS,SAAS,UAAU;AACrD,YAAM,UAAU,MAAM,MAAM;AAC5B,UAAI,CAAC,QAAS;AAEd,qBAAe,IAAI,QAAQ,MAAM;AACjC,wBAAkB,KAAK,IAAI,iBAAiB,QAAQ,KAAK;AAGzD,YAAM,YAAY,QAAQ,KAAK;AAAA,QAC7B,CAAC,OAAO,OAAO,QAAQ;AAAA,MACzB,EAAE;AACF,UAAI,YAAY,GAAG;AACjB,oBAAY;AAAA,MACd;AAEA,YAAM,OAAO,KAAK,SAAS,QAAQ,MAAM;AACzC,UAAI,CAAC,KAAM;AAEX,YAAM,gBAAgB,KAAK,iBAAiB,QAAQ,MAAM;AAG1D,UAAI,cAAc,WAAW,KAAK,QAAQ,SAAS,UAAU;AAC3D,iBAAS,KAAK;AAAA,UACZ,SAAS,QAAQ;AAAA,UACjB,SAAS,QAAQ;AAAA,UACjB,OAAO,QAAQ;AAAA,UACf,OAAO,QAAQ;AAAA,QACjB,CAAC;AACD;AAAA,MACF;AAGA,iBAAW,QAAQ,eAAe;AAEhC,YAAI,sBAAsB,KAAK,aAAa,QAAQ,OAAO;AACzD,cAAI;AACF,gBAAI,CAAC,mBAAmB,KAAK,WAAW,QAAQ,KAAK,GAAG;AACtD;AAAA,YACF;AAAA,UACF,QAAQ;AACN;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAU,CAAC,GAAG,QAAQ,MAAM,KAAK,EAAE;AACzC,cAAM,aAAa,CAAC,GAAG,QAAQ,SAAS,KAAK,EAAE;AAE/C,cAAM,KAAK;AAAA,UACT,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,SAAS;AAAA,UACT,OAAO,QAAQ,QAAQ;AAAA,UACvB,OAAO,QAAQ,QAAQ,EAAE,GAAG,QAAQ,MAAM,IAAI;AAAA,QAChD,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,aAAa,IAAI,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC3D,UAAM,mBAAmB,oBAAI,IAAY;AAEzC,eAAW,UAAU,YAAY;AAC/B,UAAI,CAAC,eAAe,IAAI,MAAM,GAAG;AAC/B,yBAAiB,IAAI,MAAM;AAAA,MAC7B;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe;AACb,UAAM,YAAY,KAAK,iBAAiB;AACxC,UAAM,kBAAkB,KAAK,gBAAgB,EAAE,UAAU,IAAI,CAAC;AAE9D,WAAO;AAAA,MACL,YAAY,KAAK,KAAK,MAAM;AAAA,MAC5B,gBAAgB,UAAU,eAAe;AAAA,MACzC,kBAAkB,KAAK,KAAK,MAAM,SAAS,UAAU,eAAe;AAAA,MACpE,YAAY,UAAU,aAAa;AAAA,MACnC,UAAU,KAAK,kBAAkB;AAAA,MACjC,WAAW,KAAK,UAAU;AAAA,MAC1B,eAAe,gBAAgB,SAAS;AAAA,IAC1C;AAAA,EACF;AACF;;;AC/ZO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YAAY,YAAkD;AAC5D,SAAK,aAAa,cAAc,iBAAiB,qBAAqB;AAAA,EACxE;AAAA,EAEA,SAAS,MAAgC;AACvC,UAAM,SAA4B,CAAC;AACnC,UAAM,WAAgC,CAAC;AACvC,UAAM,YAAY,eAAe,KAAK,KAAK;AAC3C,UAAM,aAAa,IAAI,eAAe,IAAI;AAC1C,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,KAAK,WAAW;AACxE,QAAI,CAAC,WAAW;AACd,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,uBAAuB,KAAK,WAAW;AAAA,QAChD,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAGA,UAAM,WAAW,KAAK,MAAM,OAAO,CAAC,SAAS,UAAU,KAAK,EAAE,MAAM,KAAK;AACzE,QAAI,SAAS,WAAW,GAAG;AACzB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,SAAS;AAChB,mBAAW,QAAQ,KAAK,SAAS;AAC/B,gBAAM,SAAS,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE;AAEtD,cAAI,CAAC,QAAQ;AACX,mBAAO,KAAK;AAAA,cACV,MAAM;AAAA,cACN,SAAS,2CAA2C,KAAK,EAAE;AAAA,cAC3D,QAAQ,KAAK;AAAA,cACb,QAAQ,KAAK;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAiB,QAAQ,WAAW,mBAAmB;AAC7D,UAAM,mBAAmB,KAAK,MAAM;AAAA,MAClC,CAAC,SAAS,CAAC,eAAe,IAAI,KAAK,EAAE;AAAA,IACvC;AACA,eAAW,QAAQ,kBAAkB;AACnC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,SAAS,KAAK,EAAE;AAAA,QACzB,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAGA,QAAI,QAAQ,WAAW,UAAU,GAAG;AAClC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,SAAS;AAChB,mBAAW,QAAQ,KAAK,SAAS;AAC/B,cACE,KAAK,cAAc,UACnB,CAAC,KAAK;AAAA,YACJ,KAAK;AAAA,YACL,KAAK,sBAAsB;AAAA,UAC7B,GACA;AACA,mBAAO,KAAK;AAAA,cACV,MAAM;AAAA,cACN,SAAS,sCAAsC,KAAK,SAAS;AAAA,cAC7D,QAAQ,KAAK;AAAA,cACb,QAAQ,KAAK;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,SAAK,yBAAyB,SAAS,QAAQ,QAAQ;AAEvD,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,yBACN,SACA,QACA,UACM;AACN,eAAW,QAAQ,QAAQ,KAAK,OAAO;AAErC,UAAI,CAAC,KAAK,cAAe;AAEzB,YAAM,kBAAkB,QAAQ,KAAK,eAAe;AAEpD,UAAI,oBAAoB,QAAS;AAGjC,YAAM,iBAAiB;AAEvB,UAAI,CAAC,kBAAkB,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW;AAC9D;AAEF,WAAK,4BAA4B,MAAM,QAAQ,QAAQ;AAAA,IACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,4BACN,MACA,QACA,UACM;AACN,UAAM,QAAQ,KAAK,WAAW,CAAC;AAC/B,UAAM,mBAAmB,MAAM,OAAO,CAAC,SAAmB,KAAK,SAAS;AACxE,UAAM,eAAe,MAAM,OAAO,CAAC,SAAmB,CAAC,KAAK,SAAS;AACrE,UAAM,kBAAkB,KAAK,gBAAgB,SAAS;AAGtD,QAAI,aAAa,SAAS,GAAG;AAC3B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,sBAAsB,KAAK,EAAE,MAAM,eAAe;AAAA,QAC3D,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAGA,QAAI,aAAa,WAAW,KAAK,aAAa,CAAC,GAAG;AAChD,YAAM,mBAAmB,MAAM,QAAQ,aAAa,CAAC,CAAC;AACtD,YAAM,sBAAsB,iBAAiB,iBAAiB,SAAS,CAAC;AACxE,YAAM,uBAAuB,sBACzB,MAAM,QAAQ,mBAAmB,IACjC;AAEJ,UACE,wBAAwB,KACxB,mBAAmB,sBACnB;AACA,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,sBAAsB,KAAK,EAAE,MAAM,eAAe;AAAA,UAC3D,QAAQ,KAAK;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAGA,aAAS,IAAI,GAAG,IAAI,iBAAiB,SAAS,GAAG,KAAK;AACpD,YAAM,cAAc,iBAAiB,CAAC;AACtC,UACE,eACA,YAAY,aACZ,KAAK,sBAAsB,YAAY,SAAS,GAChD;AACA,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,sBAAsB,KAAK,EAAE,MAAM,eAAe,+CAA+C,YAAY,SAAS;AAAA,UAC/H,QAAQ,KAAK;AAAA,UACb,QAAQ,YAAY;AAAA,QACtB,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAGA,QAAI,aAAa,WAAW,KAAK,iBAAiB,SAAS,GAAG;AAC5D,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,sBAAsB,KAAK,EAAE,MAAM,eAAe;AAAA,QAC3D,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,WAA4B;AACxD,QAAI,CAAC,UAAW,QAAO;AAEvB,UAAM,UAAU,UAAU,KAAK,EAAE,YAAY;AAC7C,WACE,YAAY,UACZ,YAAY,OACZ,YAAY,YACZ,YAAY;AAAA,EAEhB;AAAA,EAEQ,kBAAkB,YAAoB,UAA0B;AACtE,QAAI;AAEF,UAAI,QAAQ,cAAc,IAAI,KAAK;AACnC,UAAI,OAAc;AAGlB,UAAI,SAAS,GAAI,QAAO;AAGxB,UAAI,aAAa;AACjB,iBAAW,QAAQ,MAAM;AACvB,YAAI,SAAS,IAAK;AAClB,YAAI,SAAS,IAAK;AAClB,YAAI,aAAa,EAAG,QAAO;AAAA,MAC7B;AACA,UAAI,eAAe,EAAG,QAAO;AAE7B,YAAM,YAAY,KAAK,WAAW,IAAI;AACtC,UAAI,CAAC,WAAW;AACd,eAAO;AAAA,MACT;AAEA,UAAI;AACF,cAAM,SAAS,UAAU,QAAQ,IAAI;AACrC,eAAO,OAAO;AAAA,MAChB,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC9NO,IAAM,aAAN,MAAiB;AAAA,EAStB,YAAY,MAAc,WAAmB,KAAM,WAAmB,KAAK;AACzE,SAAK,OAAO;AACZ,SAAK,YAAY,eAAe,KAAK,KAAK;AAC1C,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,kBAAkB,KAAK,sBAAsB;AAClD,SAAK,aAAa,iBAAiB,qBAAqB;AAGxD,SAAK,iBAAiB,IAAI,oBAAoB;AAAA,MAC5C,oBAAoB,KAAK;AAAA,MACzB,YAAY,KAAK;AAAA,MACjB,eAAe;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAwC;AAC5C,UAAM,SAAoC,CAAC;AAC3C,UAAM,WAAsC,CAAC;AAC7C,UAAM,gBAA+B,CAAC;AACtC,UAAM,eAAe,oBAAI,IAAY;AACrC,UAAM,eAAe,oBAAI,IAAY;AAGrC,UAAM,YAKA;AAAA,MACJ;AAAA,QACE,QAAQ,KAAK,KAAK;AAAA,QAClB,MAAM,CAAC,KAAK,KAAK,WAAW;AAAA,QAC5B,OAAO,EAAE,GAAG,KAAK,KAAK,YAAY;AAAA,QAClC,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI,iBAAiB;AAErB,WAAO,UAAU,SAAS,KAAK,YAAY,KAAK,UAAU;AACxD,YAAM,UAAU,UAAU,MAAM;AAChC,UAAI,CAAC,SAAS;AACZ,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AACA;AAGA,UAAI,QAAQ,KAAK,SAAS,KAAK,UAAU;AACvC,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,gCAAgC,KAAK,QAAQ;AAAA,UACtD,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AAGA,mBAAa,IAAI,QAAQ,MAAM;AAC/B,YAAM,UAAU,QAAQ,KAAK,KAAK,IAAI;AACtC,mBAAa,IAAI,OAAO;AAExB,YAAM,OAAO,KAAK,aAAa,QAAQ,MAAM;AAC7C,UAAI,CAAC,MAAM;AACT,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,mBAAmB,QAAQ,MAAM;AAAA,UAC1C,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD;AAAA,MACF;AAGA,UAAI,KAAK,UAAU,KAAK,EAAE,MAAM,OAAO;AACrC;AACA,sBAAc,KAAK;AAAA,UACjB,IAAI,QAAQ,SAAS;AAAA,UACrB,MAAM,QAAQ;AAAA,UACd,SAAS;AAAA,UACT,OAAO,QAAQ,KAAK;AAAA,UACpB,YAAY,QAAQ;AAAA,UACpB,SAAS,QAAQ;AAAA,QACnB,CAAC;AACD;AAAA,MACF;AAGA,YAAM,iBAAiB,KAAK,kBAAkB,MAAM,QAAQ,KAAK;AAEjE,UAAI,eAAe,WAAW,GAAG;AAC/B,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,uDAAuD,KAAK,EAAE;AAAA,UACvE,MAAM,QAAQ;AAAA,UACd,QAAQ,KAAK;AAAA,QACf,CAAC;AACD;AAAA,MACF;AAGA,iBAAW,QAAQ,gBAAgB;AACjC,cAAM,aAAa,KAAK,aAAa,KAAK,EAAE;AAC5C,YAAI,CAAC,YAAY;AACf,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,SAAS,sCAAsC,KAAK,EAAE;AAAA,YACtD,MAAM,QAAQ;AAAA,YACd,QAAQ,KAAK;AAAA,UACf,CAAC;AACD;AAAA,QACF;AAGA,cAAM,eAAe,KAAK,UACtB,KAAK,eAAe,eAAe,KAAK,SAAS,QAAQ,KAAK,IAC9D,EAAE,SAAS,MAAM,UAAU,QAAQ,OAAO,QAAQ,CAAC,EAAE;AACzD,cAAM,WAAW,aAAa;AAG9B,cAAM,UAAU,CAAC,GAAG,QAAQ,MAAM,KAAK,EAAE;AACzC,cAAM,aAAa,QAAQ;AAAA,UACzB,CAAC,WAAW,WAAW,KAAK;AAAA,QAC9B,EAAE;AAEF,YAAI,aAAa,GAAG;AAClB,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SAAS,0CAA0C,KAAK,EAAE,YAAY,UAAU;AAAA,YAChF,MAAM;AAAA,YACN,QAAQ,KAAK;AAAA,UACf,CAAC;AACD;AAAA,QACF;AAEA,kBAAU,KAAK;AAAA,UACb,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,OAAO;AAAA,UACP,SAAS,CAAC,GAAG,QAAQ,SAAS,KAAK,SAAS,KAAK,EAAE;AAAA,QACrD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,uBAAuB,cAAc,YAAY;AAGvE,eAAW,UAAU,SAAS,gBAAgB;AAC5C,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,0BAA0B,MAAM;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,SAAyC;AACtD,UAAM,SAAS,IAAI,WAAW,KAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAEhE,QAAI;AACF,YAAM,OAAO,MAAM;AACnB,YAAM,OAAO,CAAC,KAAK,KAAK,WAAW;AAEnC,iBAAW,UAAU,SAAS;AAC5B,cAAM,SAAS,MAAM,OAAO,KAAK,MAAM;AACvC,aAAK,KAAK,OAAO,KAAK,KAAK,EAAE;AAE7B,YAAI,OAAO,YAAY;AACrB;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA,SAAS,OAAO,WAAW,IAAI,cAAc;AAAA,QAC7C,OAAO,KAAK;AAAA,QACZ,YAAY,OAAO,SAAS;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM,CAAC,KAAK,KAAK,WAAW;AAAA,QAC5B,SAAS;AAAA,QACT,OAAO;AAAA,QACP,YAAY,CAAC;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,QAAgC;AAC7C,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA,aAAa,KAAK,KAAK,KAAK;AAAA,MAC5B,eAAe,OAAO,UAAU,gBAAW,aAAQ;AAAA,MACnD;AAAA,MACA;AAAA,MACA,2BAA2B,OAAO,UAAU;AAAA,MAC5C,sBAAsB,OAAO,cAAc;AAAA,MAC3C,aAAa,OAAO,OAAO,MAAM;AAAA,MACjC,eAAe,OAAO,SAAS,MAAM;AAAA,MACrC;AAAA,MACA;AAAA,MACA,oBAAoB,OAAO,SAAS,YAAY,IAAI,OAAO,SAAS,UAAU,KAAK,KAAK,MAAO,OAAO,SAAS,eAAe,OAAO,SAAS,aAAc,GAAG,CAAC;AAAA,MAChK,oBAAoB,OAAO,SAAS,YAAY,IAAI,OAAO,SAAS,UAAU,KAAK,KAAK,MAAO,OAAO,SAAS,eAAe,OAAO,SAAS,aAAc,GAAG,CAAC;AAAA,MAChK;AAAA,IACF;AAEA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,YAAM,KAAK,WAAW;AACtB,iBAAW,SAAS,OAAO,QAAQ;AACjC,cAAM,KAAK,OAAO,MAAM,IAAI,OAAO,MAAM,OAAO,EAAE;AAClD,YAAI,MAAM,MAAM;AACd,gBAAM,KAAK,WAAW,MAAM,KAAK,KAAK,UAAK,CAAC,EAAE;AAAA,QAChD;AAAA,MACF;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,QAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,YAAM,KAAK,aAAa;AACxB,iBAAW,WAAW,OAAO,UAAU;AACrC,cAAM,KAAK,OAAO,QAAQ,IAAI,OAAO,QAAQ,OAAO,EAAE;AACtD,YAAI,QAAQ,MAAM;AAChB,gBAAM,KAAK,WAAW,QAAQ,KAAK,KAAK,UAAK,CAAC,EAAE;AAAA,QAClD;AAAA,MACF;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,QAAI,OAAO,SAAS,eAAe,SAAS,GAAG;AAC7C,YAAM,KAAK,oBAAoB;AAC/B,iBAAW,UAAU,OAAO,SAAS,gBAAgB;AACnD,cAAM,KAAK,KAAK,MAAM,EAAE;AAAA,MAC1B;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA,EAEQ,aAAa,IAA2B;AAC9C,WAAO,KAAK,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE,KAAK;AAAA,EAC3D;AAAA,EAEQ,kBACN,MACA,OACY;AACZ,QAAI,CAAC,KAAK,QAAS,QAAO,CAAC;AAE3B,WAAO,KAAK,QAAQ,OAAO,CAAC,SAAS;AACnC,UAAI,CAAC,KAAK,UAAW,QAAO;AAE5B,UAAI;AAEF,eAAO,KAAK,kBAAkB,KAAK,WAAW,KAAK;AAAA,MACrD,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,kBACN,WACA,OACS;AACT,WAAO,KAAK,eAAe,kBAAkB,WAAW,KAAK;AAAA,EAC/D;AAAA,EAEQ,uBACN,cACA,cACgB;AAChB,UAAM,aAAa,KAAK,KAAK,MAAM;AACnC,UAAM,iBAAiB,KAAK,KAAK,MAC9B,OAAO,CAAC,SAAS,CAAC,aAAa,IAAI,KAAK,EAAE,CAAC,EAC3C,IAAI,CAAC,SAAS,KAAK,EAAE;AAGxB,QAAI,aAAa;AACjB,UAAM,iBAA2B,CAAC;AAElC,eAAW,QAAQ,KAAK,KAAK,OAAO;AAClC,UAAI,KAAK,SAAS;AAChB,mBAAW,QAAQ,KAAK,SAAS;AAC/B;AACA,gBAAM,UAAU,GAAG,KAAK,EAAE,KAAK,KAAK,EAAE;AACtC,cAAI,CAAC,aAAa,IAAI,OAAO,GAAG;AAC9B,2BAAe,KAAK,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,cAAc,aAAa;AAAA,MAC3B;AAAA,MACA,cAAc,aAAa,eAAe;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC7TO,IAAM,eAAN,MAAmB;AAAA,EAIxB,cAAc;AACZ,SAAK,YAAY,IAAI,cAAc;AAAA,EACrC;AAAA,EAEA,MAAM,QAAQ,MAAqC;AACjD,UAAM,WAA8B,CAAC;AACrC,UAAM,YAAY,eAAe,KAAK,KAAK;AAC3C,UAAM,aAAa,IAAI,eAAe,IAAI;AAC1C,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,mBAAmB,KAAK,UAAU,SAAS,IAAI;AAGrD,SAAK,aAAa,IAAI,WAAW,MAAM,KAAM,GAAG;AAChD,UAAM,aAAa,MAAM,KAAK,WAAW,aAAa;AAGtD,SAAK,qBAAqB,OAAO;AAGjC,UAAM,YAAY,KAAK,iBAAiB,OAAO;AAG/C,UAAM,QAAQ,KAAK,aAAa,YAAY,QAAQ,QAAQ;AAG5D,UAAM,UAAU,KAAK,eAAe,QAAQ,MAAM,QAAQ,QAAQ;AAGlE,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAGA,SAAK,sBAAsB,kBAAkB,QAAQ,QAAQ;AAG7D,UAAM,QAAQ,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,WAAO;AAAA,MACL,SAAS,iBAAiB;AAAA,MAC1B;AAAA,MACA,UAAU,QAAQ,SAAS;AAAA,QACzB,CAAC,GAAG,MAAM,KAAK,mBAAmB,CAAC,IAAI,KAAK,mBAAmB,CAAC;AAAA,MAClE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAAqB,SAA0B;AACrD,UAAM,QAAQ,QAAQ,KAAK;AAE3B,UAAM,QAAQ,CAAC,SAAS;AAEtB,YAAM,UAAU,KAAK,WAAW,KAAK,SAAS;AAC9C,UAAI,QAAQ,KAAK,EAAE,WAAW,GAAG;AAC/B,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,SAAS,KAAK,EAAE;AAAA,UAC7B,QAAQ,KAAK;AAAA,UACb,YAAY;AAAA,UACZ,YAAY,+BAA+B,KAAK,sBAAsB,QAAQ,UAAU,KAAK,EAAE,KAAK,UAAU,CAAC;AAAA,QACjH,CAAC;AAAA,MACH,WAAW,QAAQ,KAAK,EAAE,SAAS,IAAI;AACrC,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,SAAS,KAAK,EAAE,cAAc,QAAQ,KAAK,EAAE,MAAM,iBAAiB,QAAQ,KAAK,CAAC;AAAA,UAC/F,QAAQ,KAAK;AAAA,UACb,YAAY;AAAA,UACZ,YAAY,8BAA8B,KAAK,cAAc,QAAQ,KAAK,GAAG,QAAQ,UAAU,KAAK,EAAE,KAAK,UAAU,CAAC;AAAA,QACxH,CAAC;AAAA,MACH;AAGA,UAAI,QAAQ,UAAU,KAAK,EAAE,MAAM,YAAY;AAC7C,YAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC5C,kBAAQ,SAAS,KAAK;AAAA,YACpB,MAAM;AAAA,YACN,UAAU;AAAA,YACV,OAAO;AAAA,YACP,aAAa,kBAAkB,KAAK,EAAE;AAAA,YACtC,QAAQ,KAAK;AAAA,YACb,YAAY;AAAA,YACZ,YACE;AAAA,UACJ,CAAC;AAAA,QACH,WACE,KAAK,QAAQ;AAAA,UACX,CAAC,SAAS,CAAC,KAAK,SAAS,KAAK,MAAM,KAAK,EAAE,WAAW;AAAA,QACxD,GACA;AACA,gBAAM,iBAAiB,KAAK,QAAQ;AAAA,YAClC,CAAC,SAAS,CAAC,KAAK,SAAS,KAAK,MAAM,KAAK,EAAE,WAAW;AAAA,UACxD;AACA,kBAAQ,SAAS,KAAK;AAAA,YACpB,MAAM;AAAA,YACN,UAAU;AAAA,YACV,OAAO;AAAA,YACP,aAAa,kBAAkB,KAAK,EAAE,SAAS,eAAe,MAAM;AAAA,YACpE,QAAQ,KAAK;AAAA,YACb,YAAY;AAAA,YACZ,YACE;AAAA,UACJ,CAAC;AAAA,QACH;AAAA,MACF;AAGA,YAAM,cAAc,QAAQ,WAAW,gBAAgB,KAAK,EAAE;AAC9D,UAAI,CAAC,eAAe,KAAK,OAAO,QAAQ,KAAK,aAAa;AACxD,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,SAAS,KAAK,EAAE;AAAA,UAC7B,QAAQ,KAAK;AAAA,UACb,YAAY;AAAA,UACZ,YACE;AAAA,QACJ,CAAC;AAAA,MACH;AAGA,UACE,QAAQ,UAAU,KAAK,EAAE,MAAM,UAC9B,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW,IAC1C;AACA,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,SAAS,KAAK,EAAE;AAAA,UAC7B,QAAQ,KAAK;AAAA,UACb,YAAY;AAAA,UACZ,YACE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAGD,UAAM,aAAa,oBAAI,IAAsB;AAC7C,UAAM,QAAQ,CAAC,SAAS;AACtB,YAAM,WAAW,KAAK,WAAW,KAAK,SAAS,IAAI,KAAK,EAAE,YAAY;AACtE,UAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,YAAI,CAAC,WAAW,IAAI,OAAO,GAAG;AAC5B,qBAAW,IAAI,SAAS,CAAC,CAAC;AAAA,QAC5B;AACA,mBAAW,IAAI,OAAO,GAAG,KAAK,KAAK,EAAE;AAAA,MACvC;AAAA,IACF,CAAC;AAED,eAAW,QAAQ,CAAC,SAAS,YAAY;AACvC,UAAI,QAAQ,SAAS,GAAG;AACtB,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,SAAS,QAAQ,KAAK,IAAI,CAAC,6BAA6B,QAAQ,UAAU,GAAG,EAAE,CAAC;AAAA,UAC7F,YAAY;AAAA,UACZ,YACE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,sBAAsB,UAA0B;AACtD,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,cAAc,SAAiB,UAA0B;AAC/D,UAAM,WAAW;AAAA,MACf,OAAO,GAAG,OAAO;AAAA,MACjB,UAAU,GAAG,OAAO;AAAA,MACpB,QAAQ,GAAG,OAAO;AAAA,MAClB,KAAK,GAAG,OAAO;AAAA,IACjB;AACA,WACE,SAAS,QAAiC,KAC1C,GAAG,OAAO;AAAA,EAEd;AAAA,EAEQ,iBAAiB,SAA6C;AACpE,UAAM,QAAQ,QAAQ,KAAK;AAC3B,UAAM,YAAY,QAAQ;AAC1B,UAAM,gBAAgB,MAAM,OAAO,CAAC,MAAM,UAAU,EAAE,EAAE,MAAM,UAAU;AACxE,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM,UAAU,EAAE,EAAE,MAAM,KAAK;AAC9D,UAAM,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ,KAAK,WAAW;AAExE,UAAM,eAAe,cAAc;AAAA,MACjC,CAAC,KAAK,SAAS,OAAO,KAAK,SAAS,UAAU;AAAA,MAC9C;AAAA,IACF;AACA,UAAM,4BACJ,cAAc,SAAS,IAAI,eAAe,cAAc,SAAS;AAEnE,UAAM,WAAW,QAAQ,WAAW,kBAAkB;AACtD,UAAM,kBAAkB,KAAK,yBAAyB,OAAO;AAG7D,QAAI,cAAc,WAAW,GAAG;AAC9B,cAAQ,SAAS,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aACE;AAAA,QACF,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,QAAI,SAAS,WAAW,KAAK,MAAM,SAAS,GAAG;AAC7C,cAAQ,SAAS,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,YAAY,MAAM,MAAM;AAAA,QACrC,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,QAAI,cAAc,SAAS,KAAK,4BAA4B,KAAK;AAC/D,YAAM,gBAAgB,cAAc;AAAA,QAClC,CAAC,OAAO,EAAE,SAAS,UAAU,KAAK;AAAA,MACpC;AACA,UAAI,cAAc,SAAS,GAAG;AAC5B,gBAAQ,SAAS,KAAK;AAAA,UACpB,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,GAAG,cAAc,MAAM;AAAA,UACpC,YAAY;AAAA,UACZ,YAAY;AAAA,QACd,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,WAAW,IAAI;AACjB,cAAQ,SAAS,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,yBAAyB,QAAQ;AAAA,QAC9C,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,YAAY,MAAM;AAAA,MAClB,eAAe,cAAc;AAAA,MAC7B,UAAU,SAAS;AAAA,MACnB,YAAY,WAAW;AAAA,MACvB,2BACE,KAAK,MAAM,4BAA4B,EAAE,IAAI;AAAA,MAC/C;AAAA,MACA,iBAAiB,KAAK,MAAM,kBAAkB,EAAE,IAAI;AAAA,IACtD;AAAA,EACF;AAAA,EAEQ,aACN,YACA,UACc;AACd,UAAM,cAAc,WAAW,YAAY,IAAI,CAAC,MAAmB,EAAE,KAAK;AAC1E,UAAM,oBACJ,YAAY,SAAS,IACjB,YAAY,OAAO,CAAC,KAAa,QAAgB,MAAM,KAAK,CAAC,IAC7D,YAAY,SACZ;AAEN,UAAM,eAAe,YAAY,SAAS,IAAI,KAAK,IAAI,GAAG,WAAW,IAAI;AACzE,UAAM,cAAc,YAAY,SAAS,IAAI,KAAK,IAAI,GAAG,WAAW,IAAI;AAGxE,eAAW,OAAO,QAAQ,CAAC,UAAmC;AAC5D,UAAI,MAAM,QAAQ,MAAM,KAAK,SAAS,GAAG;AACvC,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO,gBAAgB,MAAM,IAAI;AAAA,UACjC,aAAa,mBAAmB,MAAM,KAAK,KAAK,UAAK,CAAC;AAAA,UACtD,aAAa,MAAM;AAAA,UACnB,YAAY;AAAA,UACZ,YACE,MAAM,SAAS,iBACX,gDACA;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,QAAI,WAAW,aAAa,KAAK,WAAW,aAAa,GAAG;AAC1D,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,QAAQ,WAAW,UAAU;AAAA,QAC1C,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,QAAI,eAAe,KAAK,cAAc,GAAG;AACvC,UAAI,eAAe,GAAG;AACpB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,yBAAyB,YAAY;AAAA,UAClD,YAAY;AAAA,UACZ,YACE;AAAA,QACJ,CAAC;AAAA,MACH;AAEA,UAAI,cAAc,eAAe,GAAG;AAClC,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,0BAA0B,YAAY,OAAO,WAAW;AAAA,UACrE,YAAY;AAAA,UACZ,YACE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,YAAY,WAAW;AAAA,MACvB,gBAAgB,WAAW;AAAA,MAC3B,mBAAmB,KAAK,MAAM,oBAAoB,EAAE,IAAI;AAAA,MACxD;AAAA,MACA;AAAA,MACA,kBAAkB,WAAW,OAAO;AAAA,QAClC,CAAC,MAA+B,EAAE,SAAS;AAAA,MAC7C,EAAE;AAAA,MACF,OAAO,WAAW,SAAS;AAAA,QACzB,CAAC,MAA+B,EAAE,SAAS;AAAA,MAC7C,EAAE;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,eACN,MACA,UACiB;AACjB,UAAM,QAAQ,KAAK;AACnB,UAAM,cAAc,MAAM,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,IAAI,MAAM;AACxE,UAAM,wBACJ,YAAY,OAAO,CAAC,KAAK,QAAQ,MAAM,KAAK,CAAC,IAAI,YAAY;AAE/D,UAAM,aAAa,MAAM;AAAA,MACvB,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,IAAI,KAAK;AAAA,IAC5C,EAAE;AAGF,UAAM,aAAa,oBAAI,IAAoB;AAC3C,UAAM,QAAQ,CAAC,SAAS;AACtB,YAAM,WAAW,KAAK,WAAW,KAAK,SAAS,IAAI,KAAK,EAAE,YAAY;AACtE,UAAI,SAAS;AACX,mBAAW,IAAI,UAAU,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AACD,UAAM,mBAAmB,MAAM,KAAK,WAAW,OAAO,CAAC,EAAE;AAAA,MACvD,CAAC,UAAU,QAAQ;AAAA,IACrB,EAAE;AAGF,UAAM,eAAe,KAAK,sBAAsB,WAAW;AAG3D,QAAI,aAAa,GAAG;AAClB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,GAAG,UAAU;AAAA,QAC1B,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,QAAI,wBAAwB,IAAI;AAC9B,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,QAAI,mBAAmB,GAAG;AACxB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,GAAG,gBAAgB;AAAA,QAChC,YAAY;AAAA,QACZ,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,uBAAuB,KAAK,MAAM,wBAAwB,EAAE,IAAI;AAAA,MAChE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,sBACN,WACA,OACA,UACwB;AAExB,UAAM,gBAAgB,KAAK;AAAA,MACzB;AAAA,MACA,UAAU,WAAW,KACnB,MAAM,aAAa,IACnB,UAAU,gBAAgB;AAAA,IAC9B;AAGA,UAAM,aAAa,KAAK;AAAA,MACtB;AAAA,MACA,UAAU,4BAA4B,KACpC,KAAK,IAAI,MAAM,mBAAmB,EAAE,IAAI,IACxC,UAAU,gBAAgB;AAAA,IAC9B;AAGA,QAAI,aAAgD;AACpD,QAAI,UAAU,aAAa,MAAM,MAAM,aAAa,GAAG;AACrD,mBAAa;AAAA,IACf,WAAW,UAAU,aAAa,KAAK,MAAM,aAAa,GAAG;AAC3D,mBAAa;AAAA,IACf;AAGA,UAAM,mBAAmB,KAAK,KAAK,MAAM,oBAAoB,GAAG;AAChE,UAAM,oBACJ,mBAAmB,IACf,gBACA,mBAAmB,IACjB,gBACA,mBAAmB,KACjB,iBACA;AAGV,QAAI,gBAAgB,IAAI;AACtB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,QAAI,aAAa,IAAI;AACnB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aACE;AAAA,QACF,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,eAAe,KAAK,MAAM,aAAa;AAAA,MACvC,YAAY,KAAK,MAAM,UAAU;AAAA,MACjC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,sBACN,kBACA,UACA;AACA,qBAAiB,OAAO,QAAQ,CAAC,UAA2B;AAC1D,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO,MAAM;AAAA,QACb,aAAa,MAAM;AAAA,QACnB,QAAQ,MAAM;AAAA,QACd,YAAY;AAAA,QACZ,YACE;AAAA,MACJ,CAAC;AAAA,IACH,CAAC;AAED,qBAAiB,SAAS,QAAQ,CAAC,YAA+B;AAChE,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO,QAAQ;AAAA,QACf,aAAa,QAAQ;AAAA,QACrB,QAAQ,QAAQ;AAAA,QAChB,YAAY;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,eACN,WACA,OACA,SACA,IACA,UACQ;AACR,QAAI,QAAQ;AAGZ,UAAM,SAAS,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE;AAC1D,UAAM,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE;AAE9D,aAAS,SAAS;AAClB,aAAS,WAAW;AAGpB,QAAI,UAAU,gBAAgB,EAAG,UAAS;AAC1C,QAAI,UAAU,WAAW,EAAG,UAAS;AACrC,QAAI,UAAU,6BAA6B,EAAG,UAAS;AAGvD,QAAI,MAAM,aAAa,EAAG,UAAS;AACnC,QAAI,MAAM,mBAAmB,MAAM,WAAY,UAAS;AAGxD,QAAI,QAAQ,eAAe,EAAG,UAAS;AACvC,QAAI,QAAQ,eAAe,GAAI,UAAS;AAGxC,QAAI,GAAG,gBAAgB,GAAI,UAAS;AACpC,QAAI,GAAG,aAAa,GAAI,UAAS;AAEjC,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,EACrD;AAAA,EAEQ,yBAAyB,SAAkC;AACjE,UAAM,YAAY,QAAQ;AAC1B,UAAM,gBAAgB,QAAQ,KAAK,MAAM;AAAA,MACvC,CAAC,MAAM,UAAU,EAAE,EAAE,MAAM;AAAA,IAC7B;AACA,QAAI,cAAc,WAAW,EAAG,QAAO;AAEvC,UAAM,gBAAgB,cAAc;AAAA,MAClC,CAAC,KAAK,SAAS,OAAO,KAAK,SAAS,UAAU;AAAA,MAC9C;AAAA,IACF;AACA,WAAO,gBAAgB,cAAc;AAAA,EACvC;AAAA,EAEQ,sBAAsB,aAA+B;AAC3D,UAAM,YACJ,YAAY,OAAO,CAAC,KAAK,QAAQ,MAAM,KAAK,CAAC,IAAI,YAAY;AAG/D,QAAI,aAAa,MAAM,aAAa,IAAK,QAAO;AAChD,QAAI,aAAa,MAAM,aAAa,IAAK,QAAO;AAChD,QAAI,aAAa,MAAM,aAAa,IAAK,QAAO;AAChD,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,SAAkC;AAC3D,UAAM,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,EAAE;AACpE,UAAM,mBAAmB;AAAA,MACvB,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,aAAa;AAAA,IACf;AAEA,WAAO,aAAa,QAAQ,IAAI,IAAI,KAAK,iBAAiB,QAAQ,QAAQ;AAAA,EAC5E;AACF;;;ACjsBA,eAAsB,aACpB,MACA,UAII,CAAC,GACoB;AACzB,QAAM,aAAa,IAAI;AAAA,IACrB;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,QAAQ,YAAY;AAAA,EACtB;AAEA,UAAQ,IAAI,2BAAoB,KAAK,KAAK,EAAE;AAC5C,UAAQ,IAAI,SAAI,OAAO,EAAE,CAAC;AAE1B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,SAAS,MAAM,WAAW,aAAa;AAC7C,QAAM,WAAW,KAAK,IAAI,IAAI;AAG9B,UAAQ,IAAI;AAAA,0BAAsB,QAAQ,KAAK;AAC/C,UAAQ,IAAI,WAAW,OAAO,UAAU,gBAAW,aAAQ,EAAE;AAC7D,UAAQ,IAAI,gBAAgB,OAAO,UAAU,EAAE;AAC/C,UAAQ,IAAI,oBAAoB,OAAO,cAAc,EAAE;AACvD,UAAQ,IAAI,WAAW,OAAO,OAAO,MAAM,EAAE;AAC7C,UAAQ,IAAI,aAAa,OAAO,SAAS,MAAM,EAAE;AAGjD,QAAM,gBAAgB,KAAK;AAAA,IACxB,OAAO,SAAS,eAAe,OAAO,SAAS,aAAc;AAAA,EAChE;AACA,QAAM,gBAAgB,KAAK;AAAA,IACxB,OAAO,SAAS,eAAe,OAAO,SAAS,aAAc;AAAA,EAChE;AACA,UAAQ,IAAI;AAAA,mBAAe;AAC3B,UAAQ;AAAA,IACN,UAAU,OAAO,SAAS,YAAY,IAAI,OAAO,SAAS,UAAU,KAAK,aAAa;AAAA,EACxF;AACA,UAAQ;AAAA,IACN,UAAU,OAAO,SAAS,YAAY,IAAI,OAAO,SAAS,UAAU,KAAK,aAAa;AAAA,EACxF;AAGA,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,YAAQ,IAAI;AAAA,eAAa;AACzB,eAAW,SAAS,OAAO,QAAQ;AACjC,cAAQ,IAAI,YAAO,MAAM,IAAI,KAAK,MAAM,OAAO,EAAE;AACjD,UAAI,MAAM,QAAQ,QAAQ,SAAS;AACjC,gBAAQ,IAAI,aAAa,MAAM,KAAK,KAAK,UAAK,CAAC,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,YAAQ,IAAI;AAAA,wBAAiB;AAC7B,eAAW,WAAW,OAAO,UAAU;AACrC,cAAQ,IAAI,YAAO,QAAQ,IAAI,KAAK,QAAQ,OAAO,EAAE;AACrD,UAAI,QAAQ,QAAQ,QAAQ,SAAS;AACnC,gBAAQ,IAAI,aAAa,QAAQ,KAAK,KAAK,UAAK,CAAC,EAAE;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,SAAS,eAAe,SAAS,GAAG;AAC7C,YAAQ,IAAI;AAAA,2BAAuB;AACnC,eAAW,UAAU,OAAO,SAAS,gBAAgB;AACnD,cAAQ,IAAI,YAAO,MAAM,EAAE;AAAA,IAC7B;AAAA,EACF;AAGA,MAAI,QAAQ,WAAW,OAAO,YAAY,SAAS,GAAG;AACpD,YAAQ,IAAI;AAAA,+BAAsB;AAClC,UAAM,cAAc,OAAO,YAAY,MAAM,GAAG,CAAC;AACjD,eAAW,QAAQ,aAAa;AAC9B,cAAQ;AAAA,QACN,YAAO,KAAK,KAAK,KAAK,UAAK,CAAC,KAAK,KAAK,KAAK,WAAW,KAAK,OAAO;AAAA,MACpE;AAAA,IACF;AACA,QAAI,OAAO,YAAY,SAAS,GAAG;AACjC,cAAQ,IAAI,aAAa,OAAO,YAAY,SAAS,CAAC,aAAa;AAAA,IACrE;AAAA,EACF;AAEA,UAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AAEjC,SAAO;AACT;AAKO,SAAS,aAAa,MAAgC;AAC3D,QAAM,YAAY,IAAI,cAAc;AACpC,SAAO,UAAU,SAAS,IAAI;AAChC;","names":["EventEmitter","EventEmitter"]}