{"version":3,"file":"vitals.mjs","sources":["../../../src/lib/performance/vitals.ts"],"sourcesContent":["/**\n * @file Web Vitals Collection and Reporting System\n * @description Enterprise-grade Core Web Vitals collection with analytics integration,\n * performance budgets, and real-time monitoring capabilities.\n *\n * Targets:\n * - LCP: < 2500ms (good), < 4000ms (needs improvement)\n * - INP: < 200ms (good), < 500ms (needs improvement)\n * - CLS: < 0.1 (good), < 0.25 (needs improvement)\n * - FCP: < 1800ms (good), < 3000ms (needs improvement)\n * - TTFB: < 800ms (good), < 1800ms (needs improvement)\n */\n\nimport {\n  onCLS,\n  onFCP,\n  onINP,\n  onLCP,\n  onTTFB,\n  type Metric,\n} from 'web-vitals';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Core Web Vitals metric names\n */\nexport type VitalMetricName = 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB';\n\n/**\n * Performance rating based on Core Web Vitals thresholds\n */\nexport type PerformanceRating = 'good' | 'needs-improvement' | 'poor';\n\n/**\n * Extended metric with rating and context\n */\nexport interface VitalMetricEntry {\n  name: VitalMetricName;\n  value: number;\n  rating: PerformanceRating;\n  delta: number;\n  id: string;\n  navigationType: string;\n  timestamp: number;\n  attribution?: unknown;\n}\n\n/**\n * Aggregated vitals snapshot\n */\nexport interface VitalsSnapshot {\n  CLS?: VitalMetricEntry;\n  FCP?: VitalMetricEntry;\n  INP?: VitalMetricEntry;\n  LCP?: VitalMetricEntry;\n  TTFB?: VitalMetricEntry;\n  timestamp: number;\n  url: string;\n  path: string;\n  score: number;\n  rating: PerformanceRating;\n}\n\n/**\n * Performance budget configuration\n */\nexport interface PerformanceBudget {\n  CLS: { good: number; poor: number };\n  FCP: { good: number; poor: number };\n  INP: { good: number; poor: number };\n  LCP: { good: number; poor: number };\n  TTFB: { good: number; poor: number };\n}\n\n/**\n * Budget violation event\n */\nexport interface BudgetViolation {\n  metric: VitalMetricName;\n  value: number;\n  budget: number;\n  severity: 'warning' | 'critical';\n  timestamp: number;\n  url: string;\n}\n\n/**\n * Vitals reporter callback\n */\nexport type VitalsReporter = (\n  metric: VitalMetricEntry,\n  snapshot: VitalsSnapshot\n) => void;\n\n/**\n * Budget violation callback\n */\nexport type BudgetViolationHandler = (violation: BudgetViolation) => void;\n\n/**\n * Configuration for vitals collection\n */\nexport interface VitalsCollectorConfig {\n  /** Enable reporting to analytics endpoint */\n  reportToAnalytics?: boolean;\n  /** Analytics endpoint URL */\n  analyticsEndpoint?: string;\n  /** Custom performance budgets */\n  budgets?: Partial<PerformanceBudget>;\n  /** Callback for each metric update */\n  onMetric?: VitalsReporter;\n  /** Callback for budget violations */\n  onBudgetViolation?: BudgetViolationHandler;\n  /** Sample rate for reporting (0-1) */\n  sampleRate?: number;\n  /** Enable debug logging */\n  debug?: boolean;\n  /** Batch reports before sending */\n  batchReports?: boolean;\n  /** Batch flush interval in ms */\n  batchInterval?: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default Core Web Vitals thresholds (Google recommended)\n */\nexport const DEFAULT_BUDGETS: PerformanceBudget = {\n  CLS: { good: 0.1, poor: 0.25 },\n  FCP: { good: 1800, poor: 3000 },\n  INP: { good: 200, poor: 500 },\n  LCP: { good: 2500, poor: 4000 },\n  TTFB: { good: 800, poor: 1800 },\n};\n\n/**\n * Metric weights for overall score calculation\n */\nconst METRIC_WEIGHTS: Record<VitalMetricName, number> = {\n  LCP: 0.25,\n  INP: 0.30, // INP replaced FID with higher weight\n  CLS: 0.25,\n  FCP: 0.10,\n  TTFB: 0.10,\n};\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Calculate rating based on value and thresholds\n */\nfunction calculateRating(\n  value: number,\n  thresholds: { good: number; poor: number }\n): PerformanceRating {\n  if (value <= thresholds.good) return 'good';\n  if (value <= thresholds.poor) return 'needs-improvement';\n  return 'poor';\n}\n\n/**\n * Convert rating to numeric score (0-100)\n */\nfunction ratingToScore(rating: PerformanceRating): number {\n  switch (rating) {\n    case 'good':\n      return 100;\n    case 'needs-improvement':\n      return 50;\n    case 'poor':\n      return 0;\n  }\n}\n\n/**\n * Calculate overall performance score from vitals\n */\nfunction calculateOverallScore(metrics: Partial<Record<VitalMetricName, VitalMetricEntry>>): number {\n  let totalWeight = 0;\n  let weightedScore = 0;\n\n  for (const [name, entry] of Object.entries(metrics)) {\n    if (entry !== undefined && entry !== null) {\n      const weight = METRIC_WEIGHTS[name as VitalMetricName];\n      weightedScore += ratingToScore(entry.rating) * weight;\n      totalWeight += weight;\n    }\n  }\n\n  return totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0;\n}\n\n/**\n * Get overall rating from score\n */\nfunction scoreToRating(score: number): PerformanceRating {\n  if (score >= 90) return 'good';\n  if (score >= 50) return 'needs-improvement';\n  return 'poor';\n}\n\n// ============================================================================\n// Vitals Collector Class\n// ============================================================================\n\n/**\n * Core Web Vitals collector with real-time monitoring\n */\nexport class VitalsCollector {\n  private config: Required<VitalsCollectorConfig>;\n  private metrics: Partial<Record<VitalMetricName, VitalMetricEntry>> = {};\n  private subscribers: Set<VitalsReporter> = new Set();\n  private budgetHandlers: Set<BudgetViolationHandler> = new Set();\n  private reportBuffer: VitalMetricEntry[] = [];\n  private flushTimer: ReturnType<typeof setTimeout> | null = null;\n  private isInitialized = false;\n\n  // Performance optimization: Cache calculated score to avoid recalculation on every getSnapshot()\n  private cachedScore: number | null = null;\n  private cachedScoreMetricsVersion = 0;\n  private metricsVersion = 0;\n\n  constructor(config: VitalsCollectorConfig = {}) {\n    this.config = {\n      reportToAnalytics: config.reportToAnalytics ?? false,\n      analyticsEndpoint: config.analyticsEndpoint ?? '/api/analytics/vitals',\n      budgets: { ...DEFAULT_BUDGETS, ...config.budgets },\n      onMetric: config.onMetric ?? (() => {}),\n      onBudgetViolation: config.onBudgetViolation ?? (() => {}),\n      sampleRate: config.sampleRate ?? 1,\n      debug: config.debug ?? false,\n      batchReports: config.batchReports ?? true,\n      batchInterval: config.batchInterval ?? 5000,\n    };\n  }\n\n  /**\n   * Initialize vitals collection\n   */\n  init(): () => void {\n    if (this.isInitialized) {\n      this.log('VitalsCollector already initialized');\n      return () => {};\n    }\n\n    // Check sample rate\n    if (Math.random() > this.config.sampleRate) {\n      this.log('Skipping vitals collection (sample rate)');\n      return () => {};\n    }\n\n    this.log('Initializing VitalsCollector');\n    this.isInitialized = true;\n\n    // Register metric handlers\n    onCLS(this.handleMetric.bind(this));\n    onFCP(this.handleMetric.bind(this));\n    onINP(this.handleMetric.bind(this));\n    onLCP(this.handleMetric.bind(this));\n    onTTFB(this.handleMetric.bind(this));\n\n    // Setup batch flush\n    if (this.config.batchReports) {\n      this.scheduleBatchFlush();\n    }\n\n    // Setup unload handlers with stored references for proper cleanup\n    const handlePagehide = (): void => this.flush();\n    const handleVisibilityChange = (): void => {\n      if (document.visibilityState === 'hidden') {\n        this.flush();\n      }\n    };\n\n    window.addEventListener('visibilitychange', handleVisibilityChange);\n    window.addEventListener('pagehide', handlePagehide);\n\n    // Return cleanup function\n    return () => {\n      this.isInitialized = false;\n      this.flush();\n      if (this.flushTimer) {\n        clearTimeout(this.flushTimer);\n      }\n      window.removeEventListener('visibilitychange', handleVisibilityChange);\n      window.removeEventListener('pagehide', handlePagehide);\n    };\n  }\n\n  /**\n   * Flush buffered reports to analytics\n   */\n  flush(): void {\n    if (this.reportBuffer.length === 0) return;\n\n    const reports = [...this.reportBuffer];\n    this.reportBuffer = [];\n\n    if (this.config.reportToAnalytics && this.config.analyticsEndpoint) {\n      void this.sendToAnalytics(reports);\n    }\n  }\n\n  /**\n   * Get current vitals snapshot\n   * Performance optimized: Uses cached score to avoid recalculation on every call\n   */\n  getSnapshot(): VitalsSnapshot {\n    // Use cached score if metrics haven't changed\n    if (this.cachedScore === null || this.cachedScoreMetricsVersion !== this.metricsVersion) {\n      this.cachedScore = calculateOverallScore(this.metrics);\n      this.cachedScoreMetricsVersion = this.metricsVersion;\n    }\n\n    return {\n      ...this.metrics,\n      timestamp: Date.now(),\n      url: window.location.href,\n      path: window.location.pathname,\n      score: this.cachedScore,\n      rating: scoreToRating(this.cachedScore),\n    };\n  }\n\n  /**\n   * Get specific metric\n   */\n  getMetric(name: VitalMetricName): VitalMetricEntry | undefined {\n    return this.metrics[name];\n  }\n\n  /**\n   * Subscribe to metric updates\n   */\n  subscribe(callback: VitalsReporter): () => void {\n    this.subscribers.add(callback);\n    return () => this.subscribers.delete(callback);\n  }\n\n  /**\n   * Subscribe to budget violations\n   */\n  onViolation(callback: BudgetViolationHandler): () => void {\n    this.budgetHandlers.add(callback);\n    return () => this.budgetHandlers.delete(callback);\n  }\n\n  /**\n   * Handle incoming metric\n   */\n  private handleMetric(metric: Metric): void {\n    const name = metric.name as VitalMetricName;\n    const budget = this.config.budgets[name];\n\n    if (!budget) return;\n\n    const entry: VitalMetricEntry = {\n      name,\n      value: metric.value,\n      rating: calculateRating(metric.value, budget),\n      delta: metric.delta,\n      id: metric.id,\n      navigationType: metric.navigationType,\n      timestamp: Date.now(),\n      attribution: this.extractAttribution(metric),\n    };\n\n    this.metrics[name] = entry;\n    // Invalidate cached score when metrics change\n    this.metricsVersion++;\n    this.log(`Metric ${name}: ${metric.value} (${entry.rating})`);\n\n    // Check budget violation\n    this.checkBudgetViolation(entry);\n\n    // Get current snapshot\n    const snapshot = this.getSnapshot();\n\n    // Notify subscribers\n    this.config.onMetric(entry, snapshot);\n    this.subscribers.forEach((subscriber) => subscriber(entry, snapshot));\n\n    // Buffer for batch reporting\n    if (this.config.reportToAnalytics) {\n      this.reportBuffer.push(entry);\n    }\n  }\n\n  /**\n   * Extract attribution data from metric\n   */\n  private extractAttribution(metric: Metric): unknown {\n    // Type-specific attribution using optional chaining\n    const metricWithAttribution = metric as Metric & { attribution?: unknown };\n    return metricWithAttribution.attribution;\n  }\n\n  /**\n   * Check and report budget violations\n   */\n  private checkBudgetViolation(entry: VitalMetricEntry): void {\n    const budget = this.config.budgets[entry.name];\n    if (!budget) return;\n\n    let violation: BudgetViolation | null = null;\n\n    if (entry.value > budget.poor) {\n      violation = {\n        metric: entry.name,\n        value: entry.value,\n        budget: budget.poor,\n        severity: 'critical',\n        timestamp: Date.now(),\n        url: window.location.href,\n      };\n    } else if (entry.value > budget.good) {\n      violation = {\n        metric: entry.name,\n        value: entry.value,\n        budget: budget.good,\n        severity: 'warning',\n        timestamp: Date.now(),\n        url: window.location.href,\n      };\n    }\n\n    if (violation) {\n      this.config.onBudgetViolation(violation);\n      this.budgetHandlers.forEach((handler) => handler(violation));\n    }\n  }\n\n  /**\n   * Schedule batch flush\n   */\n  private scheduleBatchFlush(): void {\n    if (this.flushTimer) {\n      clearTimeout(this.flushTimer);\n    }\n\n    this.flushTimer = setTimeout(() => {\n      this.flush();\n      this.scheduleBatchFlush();\n    }, this.config.batchInterval);\n  }\n\n  /**\n   * Send metrics to analytics endpoint\n   */\n  private async sendToAnalytics(metrics: VitalMetricEntry[]): Promise<void> {\n    try {\n      const payload = {\n        metrics,\n        snapshot: this.getSnapshot(),\n        userAgent: navigator.userAgent,\n        connection: this.getConnectionInfo(),\n        timestamp: Date.now(),\n      };\n\n      // Use sendBeacon for reliability during page unload\n      if (typeof navigator.sendBeacon !== 'undefined') {\n        navigator.sendBeacon(\n          this.config.analyticsEndpoint,\n          JSON.stringify(payload)\n        );\n      } else {\n        await fetch(this.config.analyticsEndpoint, {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify(payload),\n          keepalive: true,\n        });\n      }\n\n      this.log(`Sent ${metrics.length} metrics to analytics`);\n    } catch (error) {\n      console.error('[VitalsCollector] Failed to send analytics:', error);\n    }\n  }\n\n  /**\n   * Get connection information\n   */\n  private getConnectionInfo(): Record<string, unknown> {\n    const nav = navigator as Navigator & {\n      connection?: {\n        effectiveType?: string;\n        downlink?: number;\n        rtt?: number;\n        saveData?: boolean;\n      };\n    };\n\n    return {\n      effectiveType: nav.connection?.effectiveType,\n      downlink: nav.connection?.downlink,\n      rtt: nav.connection?.rtt,\n      saveData: nav.connection?.saveData,\n    };\n  }\n\n  /**\n   * Debug logging\n   */\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[VitalsCollector] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet collectorInstance: VitalsCollector | null = null;\n\n/**\n * Get or create the global VitalsCollector instance\n */\nexport function getVitalsCollector(config?: VitalsCollectorConfig): VitalsCollector {\n  collectorInstance ??= new VitalsCollector(config);\n  return collectorInstance;\n}\n\n/**\n * Initialize vitals collection with config\n */\nexport function initVitals(config?: VitalsCollectorConfig): () => void {\n  const collector = getVitalsCollector(config);\n  return collector.init();\n}\n\n// ============================================================================\n// React Integration Helpers\n// ============================================================================\n\n/**\n * Format metric value for display\n */\nexport function formatMetricValue(name: VitalMetricName, value: number): string {\n  if (name === 'CLS') {\n    return value.toFixed(3);\n  }\n  return `${Math.round(value)}ms`;\n}\n\n/**\n * Get color for rating\n */\nexport function getRatingColor(rating: PerformanceRating): string {\n  switch (rating) {\n    case 'good':\n      return '#22c55e'; // green-500\n    case 'needs-improvement':\n      return '#f59e0b'; // amber-500\n    case 'poor':\n      return '#ef4444'; // red-500\n  }\n}\n\n/**\n * Get metric description\n */\nexport function getMetricDescription(name: VitalMetricName): string {\n  switch (name) {\n    case 'LCP':\n      return 'Largest Contentful Paint - Time to render the largest visible element';\n    case 'INP':\n      return 'Interaction to Next Paint - Responsiveness to user interactions';\n    case 'CLS':\n      return 'Cumulative Layout Shift - Visual stability of the page';\n    case 'FCP':\n      return 'First Contentful Paint - Time to first content render';\n    case 'TTFB':\n      return 'Time to First Byte - Server response time';\n  }\n}\n\n/**\n * Get metric target value\n */\nexport function getMetricTarget(name: VitalMetricName): string {\n  const budget = DEFAULT_BUDGETS[name];\n  if (name === 'CLS') {\n    return `< ${budget.good}`;\n  }\n  return `< ${budget.good}ms`;\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n  calculateRating,\n  calculateOverallScore,\n  ratingToScore,\n  scoreToRating,\n};\n"],"names":["DEFAULT_BUDGETS","METRIC_WEIGHTS","calculateRating","value","thresholds","ratingToScore","rating","calculateOverallScore","metrics","totalWeight","weightedScore","name","entry","weight","scoreToRating","score","VitalsCollector","config","onCLS","onFCP","onINP","onLCP","onTTFB","handlePagehide","handleVisibilityChange","reports","callback","metric","budget","snapshot","subscriber","violation","handler","payload","error","nav","message","args","collectorInstance","getVitalsCollector","initVitals","formatMetricValue","getRatingColor","getMetricDescription","getMetricTarget"],"mappings":";AAqIO,MAAMA,IAAqC;AAAA,EAChD,KAAK,EAAE,MAAM,KAAK,MAAM,KAAA;AAAA,EACxB,KAAK,EAAE,MAAM,MAAM,MAAM,IAAA;AAAA,EACzB,KAAK,EAAE,MAAM,KAAK,MAAM,IAAA;AAAA,EACxB,KAAK,EAAE,MAAM,MAAM,MAAM,IAAA;AAAA,EACzB,MAAM,EAAE,MAAM,KAAK,MAAM,KAAA;AAC3B,GAKMC,IAAkD;AAAA,EACtD,KAAK;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AACR;AASA,SAASC,EACPC,GACAC,GACmB;AACnB,SAAID,KAASC,EAAW,OAAa,SACjCD,KAASC,EAAW,OAAa,sBAC9B;AACT;AAKA,SAASC,EAAcC,GAAmC;AACxD,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EAAA;AAEb;AAKA,SAASC,EAAsBC,GAAqE;AAClG,MAAIC,IAAc,GACdC,IAAgB;AAEpB,aAAW,CAACC,GAAMC,CAAK,KAAK,OAAO,QAAQJ,CAAO;AAChD,QAA2BI,KAAU,MAAM;AACzC,YAAMC,IAASZ,EAAeU,CAAuB;AACrD,MAAAD,KAAiBL,EAAcO,EAAM,MAAM,IAAIC,GAC/CJ,KAAeI;AAAA,IACjB;AAGF,SAAOJ,IAAc,IAAI,KAAK,MAAMC,IAAgBD,CAAW,IAAI;AACrE;AAKA,SAASK,EAAcC,GAAkC;AACvD,SAAIA,KAAS,KAAW,SACpBA,KAAS,KAAW,sBACjB;AACT;AASO,MAAMC,EAAgB;AAAA,EACnB;AAAA,EACA,UAA8D,CAAA;AAAA,EAC9D,kCAAuC,IAAA;AAAA,EACvC,qCAAkD,IAAA;AAAA,EAClD,eAAmC,CAAA;AAAA,EACnC,aAAmD;AAAA,EACnD,gBAAgB;AAAA;AAAA,EAGhB,cAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,iBAAiB;AAAA,EAEzB,YAAYC,IAAgC,IAAI;AAC9C,SAAK,SAAS;AAAA,MACZ,mBAAmBA,EAAO,qBAAqB;AAAA,MAC/C,mBAAmBA,EAAO,qBAAqB;AAAA,MAC/C,SAAS,EAAE,GAAGjB,GAAiB,GAAGiB,EAAO,QAAA;AAAA,MACzC,UAAUA,EAAO,aAAa,MAAM;AAAA,MAAC;AAAA,MACrC,mBAAmBA,EAAO,sBAAsB,MAAM;AAAA,MAAC;AAAA,MACvD,YAAYA,EAAO,cAAc;AAAA,MACjC,OAAOA,EAAO,SAAS;AAAA,MACvB,cAAcA,EAAO,gBAAgB;AAAA,MACrC,eAAeA,EAAO,iBAAiB;AAAA,IAAA;AAAA,EAE3C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAmB;AACjB,QAAI,KAAK;AACP,kBAAK,IAAI,qCAAqC,GACvC,MAAM;AAAA,MAAC;AAIhB,QAAI,KAAK,OAAA,IAAW,KAAK,OAAO;AAC9B,kBAAK,IAAI,0CAA0C,GAC5C,MAAM;AAAA,MAAC;AAGhB,SAAK,IAAI,8BAA8B,GACvC,KAAK,gBAAgB,IAGrBC,EAAM,KAAK,aAAa,KAAK,IAAI,CAAC,GAClCC,EAAM,KAAK,aAAa,KAAK,IAAI,CAAC,GAClCC,EAAM,KAAK,aAAa,KAAK,IAAI,CAAC,GAClCC,EAAM,KAAK,aAAa,KAAK,IAAI,CAAC,GAClCC,EAAO,KAAK,aAAa,KAAK,IAAI,CAAC,GAG/B,KAAK,OAAO,gBACd,KAAK,mBAAA;AAIP,UAAMC,IAAiB,MAAY,KAAK,MAAA,GAClCC,IAAyB,MAAY;AACzC,MAAI,SAAS,oBAAoB,YAC/B,KAAK,MAAA;AAAA,IAET;AAEA,kBAAO,iBAAiB,oBAAoBA,CAAsB,GAClE,OAAO,iBAAiB,YAAYD,CAAc,GAG3C,MAAM;AACX,WAAK,gBAAgB,IACrB,KAAK,MAAA,GACD,KAAK,cACP,aAAa,KAAK,UAAU,GAE9B,OAAO,oBAAoB,oBAAoBC,CAAsB,GACrE,OAAO,oBAAoB,YAAYD,CAAc;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,QAAI,KAAK,aAAa,WAAW,EAAG;AAEpC,UAAME,IAAU,CAAC,GAAG,KAAK,YAAY;AACrC,SAAK,eAAe,CAAA,GAEhB,KAAK,OAAO,qBAAqB,KAAK,OAAO,qBAC1C,KAAK,gBAAgBA,CAAO;AAAA,EAErC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAA8B;AAE5B,YAAI,KAAK,gBAAgB,QAAQ,KAAK,8BAA8B,KAAK,oBACvE,KAAK,cAAclB,EAAsB,KAAK,OAAO,GACrD,KAAK,4BAA4B,KAAK,iBAGjC;AAAA,MACL,GAAG,KAAK;AAAA,MACR,WAAW,KAAK,IAAA;AAAA,MAChB,KAAK,OAAO,SAAS;AAAA,MACrB,MAAM,OAAO,SAAS;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQO,EAAc,KAAK,WAAW;AAAA,IAAA;AAAA,EAE1C;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUH,GAAqD;AAC7D,WAAO,KAAK,QAAQA,CAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAUe,GAAsC;AAC9C,gBAAK,YAAY,IAAIA,CAAQ,GACtB,MAAM,KAAK,YAAY,OAAOA,CAAQ;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAYA,GAA8C;AACxD,gBAAK,eAAe,IAAIA,CAAQ,GACzB,MAAM,KAAK,eAAe,OAAOA,CAAQ;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAaC,GAAsB;AACzC,UAAMhB,IAAOgB,EAAO,MACdC,IAAS,KAAK,OAAO,QAAQjB,CAAI;AAEvC,QAAI,CAACiB,EAAQ;AAEb,UAAMhB,IAA0B;AAAA,MAC9B,MAAAD;AAAA,MACA,OAAOgB,EAAO;AAAA,MACd,QAAQzB,EAAgByB,EAAO,OAAOC,CAAM;AAAA,MAC5C,OAAOD,EAAO;AAAA,MACd,IAAIA,EAAO;AAAA,MACX,gBAAgBA,EAAO;AAAA,MACvB,WAAW,KAAK,IAAA;AAAA,MAChB,aAAa,KAAK,mBAAmBA,CAAM;AAAA,IAAA;AAG7C,SAAK,QAAQhB,CAAI,IAAIC,GAErB,KAAK,kBACL,KAAK,IAAI,UAAUD,CAAI,KAAKgB,EAAO,KAAK,KAAKf,EAAM,MAAM,GAAG,GAG5D,KAAK,qBAAqBA,CAAK;AAG/B,UAAMiB,IAAW,KAAK,YAAA;AAGtB,SAAK,OAAO,SAASjB,GAAOiB,CAAQ,GACpC,KAAK,YAAY,QAAQ,CAACC,MAAeA,EAAWlB,GAAOiB,CAAQ,CAAC,GAGhE,KAAK,OAAO,qBACd,KAAK,aAAa,KAAKjB,CAAK;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmBe,GAAyB;AAGlD,WAD8BA,EACD;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqBf,GAA+B;AAC1D,UAAMgB,IAAS,KAAK,OAAO,QAAQhB,EAAM,IAAI;AAC7C,QAAI,CAACgB,EAAQ;AAEb,QAAIG,IAAoC;AAExC,IAAInB,EAAM,QAAQgB,EAAO,OACvBG,IAAY;AAAA,MACV,QAAQnB,EAAM;AAAA,MACd,OAAOA,EAAM;AAAA,MACb,QAAQgB,EAAO;AAAA,MACf,UAAU;AAAA,MACV,WAAW,KAAK,IAAA;AAAA,MAChB,KAAK,OAAO,SAAS;AAAA,IAAA,IAEdhB,EAAM,QAAQgB,EAAO,SAC9BG,IAAY;AAAA,MACV,QAAQnB,EAAM;AAAA,MACd,OAAOA,EAAM;AAAA,MACb,QAAQgB,EAAO;AAAA,MACf,UAAU;AAAA,MACV,WAAW,KAAK,IAAA;AAAA,MAChB,KAAK,OAAO,SAAS;AAAA,IAAA,IAIrBG,MACF,KAAK,OAAO,kBAAkBA,CAAS,GACvC,KAAK,eAAe,QAAQ,CAACC,MAAYA,EAAQD,CAAS,CAAC;AAAA,EAE/D;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AACjC,IAAI,KAAK,cACP,aAAa,KAAK,UAAU,GAG9B,KAAK,aAAa,WAAW,MAAM;AACjC,WAAK,MAAA,GACL,KAAK,mBAAA;AAAA,IACP,GAAG,KAAK,OAAO,aAAa;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgBvB,GAA4C;AACxE,QAAI;AACF,YAAMyB,IAAU;AAAA,QACd,SAAAzB;AAAA,QACA,UAAU,KAAK,YAAA;AAAA,QACf,WAAW,UAAU;AAAA,QACrB,YAAY,KAAK,kBAAA;AAAA,QACjB,WAAW,KAAK,IAAA;AAAA,MAAI;AAItB,MAAI,OAAO,UAAU,aAAe,MAClC,UAAU;AAAA,QACR,KAAK,OAAO;AAAA,QACZ,KAAK,UAAUyB,CAAO;AAAA,MAAA,IAGxB,MAAM,MAAM,KAAK,OAAO,mBAAmB;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,QAC3B,MAAM,KAAK,UAAUA,CAAO;AAAA,QAC5B,WAAW;AAAA,MAAA,CACZ,GAGH,KAAK,IAAI,QAAQzB,EAAQ,MAAM,uBAAuB;AAAA,IACxD,SAAS0B,GAAO;AACd,cAAQ,MAAM,+CAA+CA,CAAK;AAAA,IACpE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA6C;AACnD,UAAMC,IAAM;AASZ,WAAO;AAAA,MACL,eAAeA,EAAI,YAAY;AAAA,MAC/B,UAAUA,EAAI,YAAY;AAAA,MAC1B,KAAKA,EAAI,YAAY;AAAA,MACrB,UAAUA,EAAI,YAAY;AAAA,IAAA;AAAA,EAE9B;AAAA;AAAA;AAAA;AAAA,EAKQ,IAAIC,MAAoBC,GAAuB;AACrD,IAAI,KAAK,OAAO,SACd,QAAQ,KAAK,qBAAqBD,CAAO,IAAI,GAAGC,CAAI;AAAA,EAExD;AACF;AAMA,IAAIC,IAA4C;AAKzC,SAASC,EAAmBtB,GAAiD;AAClF,SAAAqB,MAAsB,IAAItB,EAAgBC,CAAM,GACzCqB;AACT;AAKO,SAASE,EAAWvB,GAA4C;AAErE,SADkBsB,EAAmBtB,CAAM,EAC1B,KAAA;AACnB;AASO,SAASwB,EAAkB9B,GAAuBR,GAAuB;AAC9E,SAAIQ,MAAS,QACJR,EAAM,QAAQ,CAAC,IAEjB,GAAG,KAAK,MAAMA,CAAK,CAAC;AAC7B;AAKO,SAASuC,EAAepC,GAAmC;AAChE,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EAAA;AAEb;AAKO,SAASqC,EAAqBhC,GAA+B;AAClE,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EAAA;AAEb;AAKO,SAASiC,EAAgBjC,GAA+B;AAC7D,QAAMiB,IAAS5B,EAAgBW,CAAI;AACnC,SAAIA,MAAS,QACJ,KAAKiB,EAAO,IAAI,KAElB,KAAKA,EAAO,IAAI;AACzB;"}