{"version":3,"file":"scroll-tracker.mjs","sources":["../../../../src/lib/layouts/context-aware/scroll-tracker.ts"],"sourcesContent":["/**\n * @fileoverview Scroll Container Tracking System\n *\n * This module provides comprehensive scroll container detection and tracking:\n * - Automatic scroll container detection\n * - Scroll position and velocity tracking\n * - Scroll direction detection\n * - Sticky element coordination\n * - Scroll event batching for performance\n *\n * @module layouts/context-aware/scroll-tracker\n * @author Agent 4 - PhD Context Systems Expert\n * @version 1.0.0\n */\n\nimport type {\n  ScrollContainer,\n  ScrollDirection,\n  StickyState,\n  OverflowType,\n  ContextTrackingConfig,\n} from './types';\nimport { DEFAULT_TRACKING_CONFIG, isScrollContainer } from './types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Callback for scroll events.\n */\nexport type ScrollCallback = (container: ScrollContainer) => void;\n\n/**\n * Callback for scroll edge events.\n */\nexport type ScrollEdgeCallback = (edge: 'top' | 'right' | 'bottom' | 'left') => void;\n\n/**\n * Callback for sticky state changes.\n */\nexport type StickyCallback = (state: StickyState) => void;\n\n/**\n * Options for scroll tracking.\n */\nexport interface ScrollTrackingOptions {\n  /** Throttle interval for scroll events (ms) */\n  throttleMs?: number;\n  /** Whether to track velocity */\n  trackVelocity?: boolean;\n  /** Whether to track direction */\n  trackDirection?: boolean;\n  /** Edge detection threshold (px) */\n  edgeThreshold?: number;\n}\n\n/**\n * Internal state for velocity calculation.\n */\ninterface VelocityState {\n  lastX: number;\n  lastY: number;\n  lastTime: number;\n  velocityX: number;\n  velocityY: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_EDGE_THRESHOLD = 5;\nconst VELOCITY_SAMPLE_INTERVAL = 50; // ms\n\n// ============================================================================\n// ScrollTracker Class\n// ============================================================================\n\n/**\n * Tracks scroll containers and their state.\n *\n * @remarks\n * Manages scroll tracking for individual containers, providing\n * scroll position, velocity, direction, and edge detection.\n *\n * @example\n * ```typescript\n * const tracker = new ScrollTracker(scrollElement);\n *\n * tracker.onScroll((container) => {\n *   console.log('Scroll position:', container.scrollPosition);\n * });\n *\n * tracker.onEdge((edge) => {\n *   console.log('Reached edge:', edge);\n * });\n * ```\n */\nexport class ScrollTracker {\n  /** ID counter for trackers */\n  private static idCounter = 0;\n  /** The scroll container element */\n  private readonly element: Element;\n  /** Unique identifier for this tracker */\n  private readonly id: string;\n  /** Configuration */\n  private readonly config: ContextTrackingConfig;\n  /** Options */\n  private readonly options: Required<ScrollTrackingOptions>;\n  /** Current scroll container state */\n  private state: ScrollContainer;\n  /** Velocity tracking state */\n  private velocityState: VelocityState;\n  /** Last known scroll direction */\n  private lastDirection: ScrollDirection = 'none';\n  /** Scroll event callbacks */\n  private readonly scrollCallbacks: Set<ScrollCallback> = new Set();\n  /** Edge event callbacks */\n  private readonly edgeCallbacks: Set<ScrollEdgeCallback> = new Set();\n  /** Sticky element callbacks */\n  private readonly stickyCallbacks: Map<Element, StickyCallback> = new Map();\n  /** Sticky element states */\n  private readonly stickyStates: Map<Element, StickyState> = new Map();\n  /** Throttle timer */\n  private throttleTimer: number | null = null;\n  /** Last throttle time */\n  private lastThrottleTime = 0;\n  /** Animation frame handle */\n  private rafHandle: number | null = null;\n  /** Whether scrolling is in progress */\n  private isScrolling = false;\n  /** Scroll end detection timer */\n  private scrollEndTimer: number | null = null;\n  /** Whether we're in SSR mode */\n  private readonly isSSR: boolean;\n\n  /**\n   * Creates a new ScrollTracker.\n   *\n   * @param element - Scroll container element\n   * @param config - Tracking configuration\n   * @param options - Scroll tracking options\n   */\n  constructor(\n    element: Element,\n    config: Partial<ContextTrackingConfig> = {},\n    options: ScrollTrackingOptions = {}\n  ) {\n    this.element = element;\n    this.id = `scroll-${++ScrollTracker.idCounter}`;\n    this.config = { ...DEFAULT_TRACKING_CONFIG, ...config };\n    this.options = {\n      throttleMs: options.throttleMs ?? 16,\n      trackVelocity: options.trackVelocity ?? true,\n      trackDirection: options.trackDirection ?? true,\n      edgeThreshold: options.edgeThreshold ?? DEFAULT_EDGE_THRESHOLD,\n    };\n\n    this.isSSR = typeof window === 'undefined';\n\n    this.velocityState = {\n      lastX: 0,\n      lastY: 0,\n      lastTime: 0,\n      velocityX: 0,\n      velocityY: 0,\n    };\n\n    this.state = this.computeState();\n\n    if (!this.isSSR) {\n      this.attachListeners();\n    }\n  }\n\n  // ==========================================================================\n  // Public API\n  // ==========================================================================\n\n  /**\n   * Gets the current scroll container state.\n   *\n   * @returns Current ScrollContainer state\n   */\n  public getState(): ScrollContainer {\n    return this.state;\n  }\n\n  /**\n   * Gets the tracker ID.\n   *\n   * @returns Unique identifier\n   */\n  public getId(): string {\n    return this.id;\n  }\n\n  /**\n   * Gets the scroll container element.\n   *\n   * @returns The scroll container element\n   */\n  public getElement(): Element {\n    return this.element;\n  }\n\n  /**\n   * Subscribes to scroll events.\n   *\n   * @param callback - Callback function\n   * @returns Unsubscribe function\n   */\n  public onScroll(callback: ScrollCallback): () => void {\n    this.scrollCallbacks.add(callback);\n    return () => {\n      this.scrollCallbacks.delete(callback);\n    };\n  }\n\n  /**\n   * Subscribes to edge events.\n   *\n   * @param callback - Callback function\n   * @returns Unsubscribe function\n   */\n  public onEdge(callback: ScrollEdgeCallback): () => void {\n    this.edgeCallbacks.add(callback);\n    return () => {\n      this.edgeCallbacks.delete(callback);\n    };\n  }\n\n  /**\n   * Registers a sticky element for tracking.\n   *\n   * @param element - Sticky element\n   * @param callback - Callback for state changes\n   * @returns Unregister function\n   */\n  public trackSticky(element: Element, callback: StickyCallback): () => void {\n    this.stickyCallbacks.set(element, callback);\n    this.updateStickyState(element);\n    return () => {\n      this.stickyCallbacks.delete(element);\n      this.stickyStates.delete(element);\n    };\n  }\n\n  /**\n   * Scrolls to a specific position.\n   *\n   * @param options - Scroll options\n   */\n  public scrollTo(options: { x?: number; y?: number; behavior?: 'auto' | 'smooth' }): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    const { x, y, behavior = 'auto' } = options;\n    this.element.scrollTo({\n      left: x,\n      top: y,\n      behavior,\n    });\n  }\n\n  /**\n   * Scrolls by a relative offset.\n   *\n   * @param options - Scroll options\n   */\n  public scrollBy(options: { x?: number; y?: number; behavior?: 'auto' | 'smooth' }): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    const { x = 0, y = 0, behavior = 'auto' } = options;\n    this.element.scrollBy({\n      left: x,\n      top: y,\n      behavior,\n    });\n  }\n\n  /**\n   * Scrolls to top.\n   *\n   * @param behavior - Scroll behavior\n   */\n  public scrollToTop(behavior: 'auto' | 'smooth' = 'smooth'): void {\n    this.scrollTo({ y: 0, behavior });\n  }\n\n  /**\n   * Scrolls to bottom.\n   *\n   * @param behavior - Scroll behavior\n   */\n  public scrollToBottom(behavior: 'auto' | 'smooth' = 'smooth'): void {\n    this.scrollTo({ y: this.state.scrollDimensions.height, behavior });\n  }\n\n  /**\n   * Scrolls an element into view within this container.\n   *\n   * @param element - Element to scroll to\n   * @param options - Scroll into view options\n   */\n  public scrollIntoView(\n    element: Element,\n    options: ScrollIntoViewOptions = { behavior: 'smooth', block: 'center' }\n  ): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    element.scrollIntoView(options);\n  }\n\n  /**\n   * Forces a state refresh.\n   */\n  public refresh(): void {\n    if (!this.isSSR) {\n      this.updateState();\n    }\n  }\n\n  /**\n   * Destroys the tracker and cleans up resources.\n   */\n  public destroy(): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    // Clear timers\n    if (this.throttleTimer !== null) {\n      window.clearTimeout(this.throttleTimer);\n    }\n    if (this.scrollEndTimer !== null) {\n      window.clearTimeout(this.scrollEndTimer);\n    }\n    if (this.rafHandle !== null) {\n      cancelAnimationFrame(this.rafHandle);\n    }\n\n    // Remove listener\n    this.element.removeEventListener('scroll', this.handleScroll);\n\n    // Clear callbacks\n    this.scrollCallbacks.clear();\n    this.edgeCallbacks.clear();\n    this.stickyCallbacks.clear();\n    this.stickyStates.clear();\n  }\n\n  // ==========================================================================\n  // Private Methods - Event Handling\n  // ==========================================================================\n\n  /**\n   * Attaches scroll event listener.\n   */\n  private attachListeners(): void {\n    this.element.addEventListener('scroll', this.handleScroll, { passive: true });\n  }\n\n  /**\n   * Handles scroll events with throttling.\n   */\n  private handleScroll = (): void => {\n    this.isScrolling = true;\n\n    // Clear existing scroll end timer\n    if (this.scrollEndTimer !== null) {\n      window.clearTimeout(this.scrollEndTimer);\n    }\n\n    // Set scroll end detection\n    this.scrollEndTimer = window.setTimeout(() => {\n      this.isScrolling = false;\n      this.velocityState.velocityX = 0;\n      this.velocityState.velocityY = 0;\n      this.updateState();\n    }, 150);\n\n    // Throttle the update\n    const now = Date.now();\n    const elapsed = now - this.lastThrottleTime;\n\n    if (elapsed >= this.options.throttleMs) {\n      this.lastThrottleTime = now;\n      this.updateState();\n    } else {\n      this.throttleTimer ??= window.setTimeout(() => {\n        this.throttleTimer = null;\n        this.lastThrottleTime = Date.now();\n        this.updateState();\n      }, this.options.throttleMs - elapsed);\n    }\n  };\n\n  // ==========================================================================\n  // Private Methods - State Computation\n  // ==========================================================================\n\n  /**\n   * Computes the current scroll container state.\n   */\n  private computeState(): ScrollContainer {\n    if (this.isSSR) {\n      return this.createDefaultState();\n    }\n\n    const {scrollLeft} = this.element;\n    const {scrollTop} = this.element;\n    const {scrollWidth} = this.element;\n    const {scrollHeight} = this.element;\n    const {clientWidth} = this.element;\n    const {clientHeight} = this.element;\n\n    // Calculate scroll progress\n    const maxScrollX = Math.max(0, scrollWidth - clientWidth);\n    const maxScrollY = Math.max(0, scrollHeight - clientHeight);\n    const progressX = maxScrollX > 0 ? scrollLeft / maxScrollX : 0;\n    const progressY = maxScrollY > 0 ? scrollTop / maxScrollY : 0;\n\n    // Detect edges\n    const threshold = this.options.edgeThreshold;\n    const atEdge = {\n      top: scrollTop <= threshold,\n      right: scrollLeft >= maxScrollX - threshold,\n      bottom: scrollTop >= maxScrollY - threshold,\n      left: scrollLeft <= threshold,\n    };\n\n    // Get overflow values\n    const style = getComputedStyle(this.element);\n    const overflow = {\n      x: style.overflowX as OverflowType,\n      y: style.overflowY as OverflowType,\n    };\n\n    return {\n      element: this.element,\n      id: this.id,\n      scrollPosition: { x: scrollLeft, y: scrollTop },\n      scrollDimensions: { width: scrollWidth, height: scrollHeight },\n      visibleDimensions: { width: clientWidth, height: clientHeight },\n      overflow,\n      isScrolling: this.isScrolling,\n      scrollDirection: this.lastDirection,\n      scrollVelocity: {\n        x: this.velocityState.velocityX,\n        y: this.velocityState.velocityY,\n      },\n      scrollProgress: { x: progressX, y: progressY },\n      atEdge,\n    };\n  }\n\n  /**\n   * Creates default state for SSR.\n   */\n  private createDefaultState(): ScrollContainer {\n    return {\n      element: this.element,\n      id: this.id,\n      scrollPosition: { x: 0, y: 0 },\n      scrollDimensions: { width: 0, height: 0 },\n      visibleDimensions: { width: 0, height: 0 },\n      overflow: { x: 'auto', y: 'auto' },\n      isScrolling: false,\n      scrollDirection: 'none',\n      scrollVelocity: { x: 0, y: 0 },\n      scrollProgress: { x: 0, y: 0 },\n      atEdge: { top: true, right: true, bottom: true, left: true },\n    };\n  }\n\n  /**\n   * Updates state and notifies listeners.\n   */\n  private updateState(): void {\n    const prevState = this.state;\n    const newState = this.computeState();\n\n    // Calculate velocity if tracking\n    if (this.options.trackVelocity) {\n      this.updateVelocity(newState);\n    }\n\n    // Calculate direction if tracking\n    if (this.options.trackDirection) {\n      this.updateDirection(prevState, newState);\n    }\n\n    // Update state\n    this.state = {\n      ...newState,\n      scrollDirection: this.lastDirection,\n      scrollVelocity: {\n        x: this.velocityState.velocityX,\n        y: this.velocityState.velocityY,\n      },\n    };\n\n    // Notify scroll callbacks\n    this.notifyScrollCallbacks();\n\n    // Check for edge events\n    this.checkEdgeEvents(prevState, this.state);\n\n    // Update sticky elements\n    this.updateAllStickyStates();\n  }\n\n  /**\n   * Updates velocity tracking.\n   */\n  private updateVelocity(state: ScrollContainer): void {\n    const now = Date.now();\n    const deltaTime = now - this.velocityState.lastTime;\n\n    if (deltaTime >= VELOCITY_SAMPLE_INTERVAL) {\n      const deltaX = state.scrollPosition.x - this.velocityState.lastX;\n      const deltaY = state.scrollPosition.y - this.velocityState.lastY;\n\n      this.velocityState.velocityX = deltaX / deltaTime * 1000; // px/s\n      this.velocityState.velocityY = deltaY / deltaTime * 1000; // px/s\n\n      this.velocityState.lastX = state.scrollPosition.x;\n      this.velocityState.lastY = state.scrollPosition.y;\n      this.velocityState.lastTime = now;\n    }\n  }\n\n  /**\n   * Updates scroll direction.\n   */\n  private updateDirection(prevState: ScrollContainer, newState: ScrollContainer): void {\n    const deltaX = newState.scrollPosition.x - prevState.scrollPosition.x;\n    const deltaY = newState.scrollPosition.y - prevState.scrollPosition.y;\n\n    // Prioritize vertical scrolling detection\n    if (Math.abs(deltaY) > Math.abs(deltaX)) {\n      if (deltaY > 0) {\n        this.lastDirection = 'down';\n      } else if (deltaY < 0) {\n        this.lastDirection = 'up';\n      } else {\n        this.lastDirection = 'none';\n      }\n    } else if (deltaX !== 0) {\n      this.lastDirection = deltaX > 0 ? 'right' : 'left';\n    }\n    // If no movement, keep last direction\n  }\n\n  /**\n   * Notifies all scroll callbacks.\n   */\n  private notifyScrollCallbacks(): void {\n    this.scrollCallbacks.forEach((callback) => {\n      try {\n        callback(this.state);\n      } catch (error) {\n        if (this.config.debug) {\n          console.error('[ScrollTracker] Callback error:', error);\n        }\n      }\n    });\n  }\n\n  /**\n   * Checks and emits edge events.\n   */\n  private checkEdgeEvents(prevState: ScrollContainer, newState: ScrollContainer): void {\n    if (this.edgeCallbacks.size === 0) {\n      return;\n    }\n\n    // Check each edge for transition to at-edge state\n    const edges: Array<'top' | 'right' | 'bottom' | 'left'> = ['top', 'right', 'bottom', 'left'];\n\n    for (const edge of edges) {\n      if (!prevState.atEdge[edge] && newState.atEdge[edge]) {\n        this.edgeCallbacks.forEach((callback) => {\n          try {\n            callback(edge);\n          } catch (error) {\n            if (this.config.debug) {\n              console.error('[ScrollTracker] Edge callback error:', error);\n            }\n          }\n        });\n      }\n    }\n  }\n\n  /**\n   * Updates all sticky element states.\n   */\n  private updateAllStickyStates(): void {\n    this.stickyCallbacks.forEach((_, element) => {\n      this.updateStickyState(element);\n    });\n  }\n\n  /**\n   * Updates sticky state for an element.\n   */\n  private updateStickyState(element: Element): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    const callback = this.stickyCallbacks.get(element);\n    if (!callback) {\n      return;\n    }\n\n    const prevState = this.stickyStates.get(element);\n    const newState = this.computeStickyState(element);\n\n    this.stickyStates.set(element, newState);\n\n    // Only notify if state changed\n    if ((prevState === undefined) || (prevState.isStuck !== newState.isStuck)) {\n      callback(newState);\n    }\n  }\n\n  /**\n   * Computes sticky state for an element.\n   */\n  private computeStickyState(element: Element): StickyState {\n    const style = getComputedStyle(element);\n    const rect = element.getBoundingClientRect();\n    const containerRect = this.element.getBoundingClientRect();\n\n    const stickyTop = parseFloat(style.top) ?? 0;\n    const stickyBottom = parseFloat(style.bottom) ?? 0;\n\n    // Determine if stuck\n    let isStuck = false;\n    let stuckTo: StickyState['stuckTo'] = null;\n\n    if (style.position === 'sticky') {\n      // Check if stuck to top\n      if (rect.top <= containerRect.top + stickyTop + 1) {\n        isStuck = true;\n        stuckTo = 'top';\n      }\n      // Check if stuck to bottom\n      else if (rect.bottom >= containerRect.bottom - stickyBottom - 1) {\n        isStuck = true;\n        stuckTo = 'bottom';\n      }\n    }\n\n    // Get sibling stickies\n    const siblingStickies: Array<{ id: string; isStuck: boolean; offset: number }> = [];\n    this.stickyStates.forEach((state, el) => {\n      if (el !== element) {\n        siblingStickies.push({\n          id: el.id ?? 'unknown',\n          isStuck: state.isStuck,\n          offset: state.offset,\n        });\n      }\n    });\n\n    let offset = 0;\n    if (isStuck) {\n      offset = stuckTo === 'top' ? stickyTop : stickyBottom;\n    }\n\n    return {\n      isStuck,\n      stuckTo,\n      originalPosition: {\n        top: rect.top - containerRect.top + this.state.scrollPosition.y,\n        left: rect.left - containerRect.left + this.state.scrollPosition.x,\n      },\n      offset,\n      siblingStickies,\n    };\n  }\n}\n\n// ============================================================================\n// ScrollContainerRegistry\n// ============================================================================\n\n/**\n * Registry for managing multiple scroll trackers.\n */\nexport class ScrollContainerRegistry {\n  private static instance: ScrollContainerRegistry | null = null;\n\n  /** Map of elements to their trackers */\n  private readonly trackers: WeakMap<Element, ScrollTracker> = new WeakMap();\n\n  /** Set of all active trackers */\n  private readonly activeTrackers: Set<ScrollTracker> = new Set();\n\n  private constructor() {}\n\n  /**\n   * Gets the singleton instance.\n   */\n  public static getInstance(): ScrollContainerRegistry {\n    ScrollContainerRegistry.instance ??= new ScrollContainerRegistry();\n    return ScrollContainerRegistry.instance;\n  }\n\n  /**\n   * Gets or creates a tracker for an element.\n   *\n   * @param element - Scroll container element\n   * @param options - Tracking options\n   * @returns ScrollTracker instance\n   */\n  public getTracker(element: Element, options?: ScrollTrackingOptions): ScrollTracker {\n    let tracker = this.trackers.get(element);\n\n    if (!tracker) {\n      tracker = new ScrollTracker(element, {}, options);\n      this.trackers.set(element, tracker);\n      this.activeTrackers.add(tracker);\n    }\n\n    return tracker;\n  }\n\n  /**\n   * Removes a tracker.\n   *\n   * @param element - Scroll container element\n   */\n  public removeTracker(element: Element): void {\n    const tracker = this.trackers.get(element);\n    if (tracker) {\n      tracker.destroy();\n      this.trackers.delete(element);\n      this.activeTrackers.delete(tracker);\n    }\n  }\n\n  /**\n   * Finds the nearest scroll container for an element.\n   *\n   * @param element - Element to check\n   * @returns Scroll container tracker or null\n   */\n  public findScrollContainer(element: Element): ScrollTracker | null {\n    let current: Element | null = element.parentElement;\n\n    while (current) {\n      if (isScrollContainer(current)) {\n        return this.getTracker(current);\n      }\n      current = current.parentElement;\n    }\n\n    // Check if document is scrollable\n    if (isScrollContainer(document.documentElement)) {\n      return this.getTracker(document.documentElement);\n    }\n\n    return null;\n  }\n\n  /**\n   * Gets all active trackers.\n   */\n  public getAllTrackers(): ScrollTracker[] {\n    return Array.from(this.activeTrackers);\n  }\n\n  /**\n   * Destroys all trackers.\n   */\n  public destroyAll(): void {\n    this.activeTrackers.forEach((tracker) => {\n      tracker.destroy();\n    });\n    this.activeTrackers.clear();\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Gets the scroll container registry instance.\n */\nexport function getScrollContainerRegistry(): ScrollContainerRegistry {\n  return ScrollContainerRegistry.getInstance();\n}\n\n/**\n * Finds the nearest scroll container for an element.\n *\n * @param element - Element to check\n * @returns ScrollTracker or null\n */\nexport function findScrollContainer(element: Element): ScrollTracker | null {\n  return getScrollContainerRegistry().findScrollContainer(element);\n}\n\n/**\n * Creates a scroll tracker for an element.\n *\n * @param element - Scroll container element\n * @param options - Tracking options\n * @returns ScrollTracker instance\n */\nexport function createScrollTracker(\n  element: Element,\n  options?: ScrollTrackingOptions\n): ScrollTracker {\n  return getScrollContainerRegistry().getTracker(element, options);\n}\n"],"names":["DEFAULT_EDGE_THRESHOLD","VELOCITY_SAMPLE_INTERVAL","ScrollTracker","element","config","options","DEFAULT_TRACKING_CONFIG","callback","x","y","behavior","now","elapsed","scrollLeft","scrollTop","scrollWidth","scrollHeight","clientWidth","clientHeight","maxScrollX","maxScrollY","progressX","progressY","threshold","atEdge","style","overflow","prevState","newState","state","deltaTime","deltaX","deltaY","error","edges","edge","_","rect","containerRect","stickyTop","stickyBottom","isStuck","stuckTo","siblingStickies","el","offset","ScrollContainerRegistry","tracker","current","isScrollContainer","getScrollContainerRegistry","findScrollContainer","createScrollTracker"],"mappings":";AAwEA,MAAMA,IAAyB,GACzBC,IAA2B;AA0B1B,MAAMC,EAAc;AAAA;AAAA,EAEzB,OAAe,YAAY;AAAA;AAAA,EAEV;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAET;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA,gBAAiC;AAAA;AAAA,EAExB,sCAA2C,IAAA;AAAA;AAAA,EAE3C,oCAA6C,IAAA;AAAA;AAAA,EAE7C,sCAAoD,IAAA;AAAA;AAAA,EAEpD,mCAA8C,IAAA;AAAA;AAAA,EAEvD,gBAA+B;AAAA;AAAA,EAE/B,mBAAmB;AAAA;AAAA,EAEnB,YAA2B;AAAA;AAAA,EAE3B,cAAc;AAAA;AAAA,EAEd,iBAAgC;AAAA;AAAA,EAEvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjB,YACEC,GACAC,IAAyC,CAAA,GACzCC,IAAiC,CAAA,GACjC;AACA,SAAK,UAAUF,GACf,KAAK,KAAK,UAAU,EAAED,EAAc,SAAS,IAC7C,KAAK,SAAS,EAAE,GAAGI,GAAyB,GAAGF,EAAA,GAC/C,KAAK,UAAU;AAAA,MACb,YAAYC,EAAQ,cAAc;AAAA,MAClC,eAAeA,EAAQ,iBAAiB;AAAA,MACxC,gBAAgBA,EAAQ,kBAAkB;AAAA,MAC1C,eAAeA,EAAQ,iBAAiBL;AAAA,IAAA,GAG1C,KAAK,QAAQ,OAAO,SAAW,KAE/B,KAAK,gBAAgB;AAAA,MACnB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IAAA,GAGb,KAAK,QAAQ,KAAK,aAAA,GAEb,KAAK,SACR,KAAK,gBAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWO,WAA4B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,QAAgB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,aAAsB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,SAASO,GAAsC;AACpD,gBAAK,gBAAgB,IAAIA,CAAQ,GAC1B,MAAM;AACX,WAAK,gBAAgB,OAAOA,CAAQ;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,OAAOA,GAA0C;AACtD,gBAAK,cAAc,IAAIA,CAAQ,GACxB,MAAM;AACX,WAAK,cAAc,OAAOA,CAAQ;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,YAAYJ,GAAkBI,GAAsC;AACzE,gBAAK,gBAAgB,IAAIJ,GAASI,CAAQ,GAC1C,KAAK,kBAAkBJ,CAAO,GACvB,MAAM;AACX,WAAK,gBAAgB,OAAOA,CAAO,GACnC,KAAK,aAAa,OAAOA,CAAO;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,SAASE,GAAyE;AACvF,QAAI,KAAK;AACP;AAGF,UAAM,EAAE,GAAAG,GAAG,GAAAC,GAAG,UAAAC,IAAW,WAAWL;AACpC,SAAK,QAAQ,SAAS;AAAA,MACpB,MAAMG;AAAA,MACN,KAAKC;AAAA,MACL,UAAAC;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,SAASL,GAAyE;AACvF,QAAI,KAAK;AACP;AAGF,UAAM,EAAE,GAAAG,IAAI,GAAG,GAAAC,IAAI,GAAG,UAAAC,IAAW,WAAWL;AAC5C,SAAK,QAAQ,SAAS;AAAA,MACpB,MAAMG;AAAA,MACN,KAAKC;AAAA,MACL,UAAAC;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YAAYA,IAA8B,UAAgB;AAC/D,SAAK,SAAS,EAAE,GAAG,GAAG,UAAAA,GAAU;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,eAAeA,IAA8B,UAAgB;AAClE,SAAK,SAAS,EAAE,GAAG,KAAK,MAAM,iBAAiB,QAAQ,UAAAA,GAAU;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,eACLP,GACAE,IAAiC,EAAE,UAAU,UAAU,OAAO,YACxD;AACN,IAAI,KAAK,SAITF,EAAQ,eAAeE,CAAO;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,IAAK,KAAK,SACR,KAAK,YAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,IAAI,KAAK,UAKL,KAAK,kBAAkB,QACzB,OAAO,aAAa,KAAK,aAAa,GAEpC,KAAK,mBAAmB,QAC1B,OAAO,aAAa,KAAK,cAAc,GAErC,KAAK,cAAc,QACrB,qBAAqB,KAAK,SAAS,GAIrC,KAAK,QAAQ,oBAAoB,UAAU,KAAK,YAAY,GAG5D,KAAK,gBAAgB,MAAA,GACrB,KAAK,cAAc,MAAA,GACnB,KAAK,gBAAgB,MAAA,GACrB,KAAK,aAAa,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,kBAAwB;AAC9B,SAAK,QAAQ,iBAAiB,UAAU,KAAK,cAAc,EAAE,SAAS,IAAM;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,MAAY;AACjC,SAAK,cAAc,IAGf,KAAK,mBAAmB,QAC1B,OAAO,aAAa,KAAK,cAAc,GAIzC,KAAK,iBAAiB,OAAO,WAAW,MAAM;AAC5C,WAAK,cAAc,IACnB,KAAK,cAAc,YAAY,GAC/B,KAAK,cAAc,YAAY,GAC/B,KAAK,YAAA;AAAA,IACP,GAAG,GAAG;AAGN,UAAMM,IAAM,KAAK,IAAA,GACXC,IAAUD,IAAM,KAAK;AAE3B,IAAIC,KAAW,KAAK,QAAQ,cAC1B,KAAK,mBAAmBD,GACxB,KAAK,YAAA,KAEL,KAAK,kBAAkB,OAAO,WAAW,MAAM;AAC7C,WAAK,gBAAgB,MACrB,KAAK,mBAAmB,KAAK,IAAA,GAC7B,KAAK,YAAA;AAAA,IACP,GAAG,KAAK,QAAQ,aAAaC,CAAO;AAAA,EAExC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,eAAgC;AACtC,QAAI,KAAK;AACP,aAAO,KAAK,mBAAA;AAGd,UAAM,EAAC,YAAAC,MAAc,KAAK,SACpB,EAAC,WAAAC,MAAa,KAAK,SACnB,EAAC,aAAAC,MAAe,KAAK,SACrB,EAAC,cAAAC,MAAgB,KAAK,SACtB,EAAC,aAAAC,MAAe,KAAK,SACrB,EAAC,cAAAC,MAAgB,KAAK,SAGtBC,IAAa,KAAK,IAAI,GAAGJ,IAAcE,CAAW,GAClDG,IAAa,KAAK,IAAI,GAAGJ,IAAeE,CAAY,GACpDG,IAAYF,IAAa,IAAIN,IAAaM,IAAa,GACvDG,IAAYF,IAAa,IAAIN,IAAYM,IAAa,GAGtDG,IAAY,KAAK,QAAQ,eACzBC,IAAS;AAAA,MACb,KAAKV,KAAaS;AAAA,MAClB,OAAOV,KAAcM,IAAaI;AAAA,MAClC,QAAQT,KAAaM,IAAaG;AAAA,MAClC,MAAMV,KAAcU;AAAA,IAAA,GAIhBE,IAAQ,iBAAiB,KAAK,OAAO,GACrCC,IAAW;AAAA,MACf,GAAGD,EAAM;AAAA,MACT,GAAGA,EAAM;AAAA,IAAA;AAGX,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,IAAI,KAAK;AAAA,MACT,gBAAgB,EAAE,GAAGZ,GAAY,GAAGC,EAAA;AAAA,MACpC,kBAAkB,EAAE,OAAOC,GAAa,QAAQC,EAAA;AAAA,MAChD,mBAAmB,EAAE,OAAOC,GAAa,QAAQC,EAAA;AAAA,MACjD,UAAAQ;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,gBAAgB;AAAA,QACd,GAAG,KAAK,cAAc;AAAA,QACtB,GAAG,KAAK,cAAc;AAAA,MAAA;AAAA,MAExB,gBAAgB,EAAE,GAAGL,GAAW,GAAGC,EAAA;AAAA,MACnC,QAAAE;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAsC;AAC5C,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,IAAI,KAAK;AAAA,MACT,gBAAgB,EAAE,GAAG,GAAG,GAAG,EAAA;AAAA,MAC3B,kBAAkB,EAAE,OAAO,GAAG,QAAQ,EAAA;AAAA,MACtC,mBAAmB,EAAE,OAAO,GAAG,QAAQ,EAAA;AAAA,MACvC,UAAU,EAAE,GAAG,QAAQ,GAAG,OAAA;AAAA,MAC1B,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,gBAAgB,EAAE,GAAG,GAAG,GAAG,EAAA;AAAA,MAC3B,gBAAgB,EAAE,GAAG,GAAG,GAAG,EAAA;AAAA,MAC3B,QAAQ,EAAE,KAAK,IAAM,OAAO,IAAM,QAAQ,IAAM,MAAM,GAAA;AAAA,IAAK;AAAA,EAE/D;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAoB;AAC1B,UAAMG,IAAY,KAAK,OACjBC,IAAW,KAAK,aAAA;AAGtB,IAAI,KAAK,QAAQ,iBACf,KAAK,eAAeA,CAAQ,GAI1B,KAAK,QAAQ,kBACf,KAAK,gBAAgBD,GAAWC,CAAQ,GAI1C,KAAK,QAAQ;AAAA,MACX,GAAGA;AAAA,MACH,iBAAiB,KAAK;AAAA,MACtB,gBAAgB;AAAA,QACd,GAAG,KAAK,cAAc;AAAA,QACtB,GAAG,KAAK,cAAc;AAAA,MAAA;AAAA,IACxB,GAIF,KAAK,sBAAA,GAGL,KAAK,gBAAgBD,GAAW,KAAK,KAAK,GAG1C,KAAK,sBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAeE,GAA8B;AACnD,UAAMlB,IAAM,KAAK,IAAA,GACXmB,IAAYnB,IAAM,KAAK,cAAc;AAE3C,QAAImB,KAAa7B,GAA0B;AACzC,YAAM8B,IAASF,EAAM,eAAe,IAAI,KAAK,cAAc,OACrDG,IAASH,EAAM,eAAe,IAAI,KAAK,cAAc;AAE3D,WAAK,cAAc,YAAYE,IAASD,IAAY,KACpD,KAAK,cAAc,YAAYE,IAASF,IAAY,KAEpD,KAAK,cAAc,QAAQD,EAAM,eAAe,GAChD,KAAK,cAAc,QAAQA,EAAM,eAAe,GAChD,KAAK,cAAc,WAAWlB;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgBgB,GAA4BC,GAAiC;AACnF,UAAMG,IAASH,EAAS,eAAe,IAAID,EAAU,eAAe,GAC9DK,IAASJ,EAAS,eAAe,IAAID,EAAU,eAAe;AAGpE,IAAI,KAAK,IAAIK,CAAM,IAAI,KAAK,IAAID,CAAM,IAChCC,IAAS,IACX,KAAK,gBAAgB,SACZA,IAAS,IAClB,KAAK,gBAAgB,OAErB,KAAK,gBAAgB,SAEdD,MAAW,MACpB,KAAK,gBAAgBA,IAAS,IAAI,UAAU;AAAA,EAGhD;AAAA;AAAA;AAAA;AAAA,EAKQ,wBAA8B;AACpC,SAAK,gBAAgB,QAAQ,CAACxB,MAAa;AACzC,UAAI;AACF,QAAAA,EAAS,KAAK,KAAK;AAAA,MACrB,SAAS0B,GAAO;AACd,QAAI,KAAK,OAAO,SACd,QAAQ,MAAM,mCAAmCA,CAAK;AAAA,MAE1D;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgBN,GAA4BC,GAAiC;AACnF,QAAI,KAAK,cAAc,SAAS;AAC9B;AAIF,UAAMM,IAAoD,CAAC,OAAO,SAAS,UAAU,MAAM;AAE3F,eAAWC,KAAQD;AACjB,MAAI,CAACP,EAAU,OAAOQ,CAAI,KAAKP,EAAS,OAAOO,CAAI,KACjD,KAAK,cAAc,QAAQ,CAAC5B,MAAa;AACvC,YAAI;AACF,UAAAA,EAAS4B,CAAI;AAAA,QACf,SAASF,GAAO;AACd,UAAI,KAAK,OAAO,SACd,QAAQ,MAAM,wCAAwCA,CAAK;AAAA,QAE/D;AAAA,MACF,CAAC;AAAA,EAGP;AAAA;AAAA;AAAA;AAAA,EAKQ,wBAA8B;AACpC,SAAK,gBAAgB,QAAQ,CAACG,GAAGjC,MAAY;AAC3C,WAAK,kBAAkBA,CAAO;AAAA,IAChC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkBA,GAAwB;AAChD,QAAI,KAAK;AACP;AAGF,UAAMI,IAAW,KAAK,gBAAgB,IAAIJ,CAAO;AACjD,QAAI,CAACI;AACH;AAGF,UAAMoB,IAAY,KAAK,aAAa,IAAIxB,CAAO,GACzCyB,IAAW,KAAK,mBAAmBzB,CAAO;AAEhD,SAAK,aAAa,IAAIA,GAASyB,CAAQ,IAGlCD,MAAc,UAAeA,EAAU,YAAYC,EAAS,YAC/DrB,EAASqB,CAAQ;AAAA,EAErB;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmBzB,GAA+B;AACxD,UAAMsB,IAAQ,iBAAiBtB,CAAO,GAChCkC,IAAOlC,EAAQ,sBAAA,GACfmC,IAAgB,KAAK,QAAQ,sBAAA,GAE7BC,IAAY,WAAWd,EAAM,GAAG,KAAK,GACrCe,IAAe,WAAWf,EAAM,MAAM,KAAK;AAGjD,QAAIgB,IAAU,IACVC,IAAkC;AAEtC,IAAIjB,EAAM,aAAa,aAEjBY,EAAK,OAAOC,EAAc,MAAMC,IAAY,KAC9CE,IAAU,IACVC,IAAU,SAGHL,EAAK,UAAUC,EAAc,SAASE,IAAe,MAC5DC,IAAU,IACVC,IAAU;AAKd,UAAMC,IAA2E,CAAA;AACjF,SAAK,aAAa,QAAQ,CAACd,GAAOe,MAAO;AACvC,MAAIA,MAAOzC,KACTwC,EAAgB,KAAK;AAAA,QACnB,IAAIC,EAAG,MAAM;AAAA,QACb,SAASf,EAAM;AAAA,QACf,QAAQA,EAAM;AAAA,MAAA,CACf;AAAA,IAEL,CAAC;AAED,QAAIgB,IAAS;AACb,WAAIJ,MACFI,IAASH,MAAY,QAAQH,IAAYC,IAGpC;AAAA,MACL,SAAAC;AAAA,MACA,SAAAC;AAAA,MACA,kBAAkB;AAAA,QAChB,KAAKL,EAAK,MAAMC,EAAc,MAAM,KAAK,MAAM,eAAe;AAAA,QAC9D,MAAMD,EAAK,OAAOC,EAAc,OAAO,KAAK,MAAM,eAAe;AAAA,MAAA;AAAA,MAEnE,QAAAO;AAAA,MACA,iBAAAF;AAAA,IAAA;AAAA,EAEJ;AACF;AASO,MAAMG,EAAwB;AAAA,EACnC,OAAe,WAA2C;AAAA;AAAA,EAGzC,+BAAgD,QAAA;AAAA;AAAA,EAGhD,qCAAyC,IAAA;AAAA,EAElD,cAAc;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA,EAKvB,OAAc,cAAuC;AACnD,WAAAA,EAAwB,aAAa,IAAIA,EAAA,GAClCA,EAAwB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,WAAW3C,GAAkBE,GAAgD;AAClF,QAAI0C,IAAU,KAAK,SAAS,IAAI5C,CAAO;AAEvC,WAAK4C,MACHA,IAAU,IAAI7C,EAAcC,GAAS,CAAA,GAAIE,CAAO,GAChD,KAAK,SAAS,IAAIF,GAAS4C,CAAO,GAClC,KAAK,eAAe,IAAIA,CAAO,IAG1BA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,cAAc5C,GAAwB;AAC3C,UAAM4C,IAAU,KAAK,SAAS,IAAI5C,CAAO;AACzC,IAAI4C,MACFA,EAAQ,QAAA,GACR,KAAK,SAAS,OAAO5C,CAAO,GAC5B,KAAK,eAAe,OAAO4C,CAAO;AAAA,EAEtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,oBAAoB5C,GAAwC;AACjE,QAAI6C,IAA0B7C,EAAQ;AAEtC,WAAO6C,KAAS;AACd,UAAIC,EAAkBD,CAAO;AAC3B,eAAO,KAAK,WAAWA,CAAO;AAEhC,MAAAA,IAAUA,EAAQ;AAAA,IACpB;AAGA,WAAIC,EAAkB,SAAS,eAAe,IACrC,KAAK,WAAW,SAAS,eAAe,IAG1C;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAkC;AACvC,WAAO,MAAM,KAAK,KAAK,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKO,aAAmB;AACxB,SAAK,eAAe,QAAQ,CAACF,MAAY;AACvC,MAAAA,EAAQ,QAAA;AAAA,IACV,CAAC,GACD,KAAK,eAAe,MAAA;AAAA,EACtB;AACF;AASO,SAASG,IAAsD;AACpE,SAAOJ,EAAwB,YAAA;AACjC;AAQO,SAASK,EAAoBhD,GAAwC;AAC1E,SAAO+C,EAAA,EAA6B,oBAAoB/C,CAAO;AACjE;AASO,SAASiD,EACdjD,GACAE,GACe;AACf,SAAO6C,EAAA,EAA6B,WAAW/C,GAASE,CAAO;AACjE;"}