{"version":3,"sources":["../src/types/index.ts","../src/triggers/index.ts","../src/config/env.ts","../src/ui/surveyHtml.ts","../src/platform/react-native-renderer.ts","../src/platform/renderer.ts","../src/analytics/analytics-manager.ts","../src/analytics/feedback-payload.ts","../src/tracking/navigation-observer.ts","../src/analytics/device-info.ts","../src/analytics/engagement-tracker.ts","../src/contact/contact-manager.ts","../src/core/deepdots-popups.ts","../src/react-native/setup.ts"],"sourcesContent":["/**\n * Configuration options for initializing the DeepdotsPopups SDK\n */\nimport type { KeyValueStorage } from '../tracking/tracking-manager';\nimport type { DeviceInfo } from '../analytics/device-info';\nimport type { AnalyticsKeys } from '../analytics/feedback-payload';\n\nexport interface DeepdotsInitParams {\n    /** API key for authentication */\n    apiKey?: string;\n    /** Node environment: 'development' or 'production' */\n    nodeEnv?: 'development' | 'production';\n    /** Enable debug logging */\n    debug?: boolean;\n    /** Optional user id to send with popup events */\n    userId?: string;\n    /** Starts tracking enabled (default) or disabled (e.g. until consent is granted). Equivalent to calling `setTrackingEnabled` after init. */\n    trackingEnabled?: boolean;\n    /** Host app version (for analytics device info / Technology #11). */\n    appVersion?: string;\n    /** Injectable persistent storage (RN: adapter over AsyncStorage). If missing, uses localStorage/in-memory. */\n    storage?: KeyValueStorage;\n    /** Platform used in the analytics envelope. Default is 'web'; in RN pass 'android'/'ios'. */\n    platform?: 'web' | 'android' | 'ios';\n    /** Injectable device info (RN: from react-native-device-info). If missing, it is derived from the browser. */\n    device?: DeviceInfo;\n    /**\n     * Analytics channel keys (`POST /sdk/feedback`). If provided, analytics is SENT\n     * to the configured integration; if missing, it stays in dry-run mode (console.log only).\n     */\n    analytics?: AnalyticsKeys;\n    /**\n     * Internal user attributes known only by the host (language, age, plan, ...), sent\n     * to the backend Contact for segmentation/targeting. Requires `userId`. Equivalent to calling\n     * `setContactAttributes` after init (sends only when values changed from the last sync).\n     */\n    contactAttributes?: Record<string, string | number | boolean>;\n\n}\nexport interface DeepdotsConfig {\n    /** API key for authentication */\n    apiKey?: string;\n    /** Enable debug logging */\n    debug?: boolean;\n    /** Optional user id to send with popup events */\n    userId?: string;\n}\n\n/**\n * Options for configuring survey triggers\n */\nexport interface TriggerConfig {\n    /** Trigger type: 'time' (delay), 'scroll' (scroll percentage), 'exit' (route exit), 'click' (element id), 'event' (host event) */\n    type: 'time' | 'scroll' | 'exit' | 'click' | 'event';\n    /** Value for the trigger (milliseconds for time, percentage for scroll, seconds for exit, element id for click, event name for event) */\n    value?: number | string;\n    /** Survey ID to show when triggered */\n    surveyId: string;\n    /** Optional popup definition id (used to disambiguate repeated survey ids) */\n    popupId?: string;\n}\n\n/**\n * Event types emitted by the SDK\n */\nexport type DeepdotsEventType =\n    | 'popup_shown'\n    | 'popup_clicked'\n    | 'survey_completed';\n\n/**\n * Event payload structure\n */\nexport interface DeepdotsEvent {\n    type: DeepdotsEventType;\n    surveyId: string;\n    timestamp: number;\n    data?: Record<string, unknown>;\n}\n\n/**\n * Event listener callback\n */\nexport type EventListener = (event: DeepdotsEvent) => void;\n\n/** Trigger type used by remote popup definitions */\nexport type PopupTriggerType = 'time_on_page' | 'scroll' | 'exit' | 'click' | 'event';\n\nexport type PopupTriggerConditionStatus = 'SHOWED' | 'PARTIAL' | 'COMPLETED';\n\nexport const POPUP_TRIGGER_CONDITION_STATUSES: PopupTriggerConditionStatus[] = [\n    'SHOWED',\n    'PARTIAL',\n    'COMPLETED',\n];\n\n/** Extra condition used to activate the popup */\nexport interface PopupTriggerCondition {\n    answered: PopupTriggerConditionStatus; // user progress status in the survey\n    cooldownDays: number; // cooldown days before showing again\n}\n\n/** Trigger attached to the popup definition */\nexport interface PopupTrigger {\n    type: PopupTriggerType;\n    value: number | string; // seconds on page, scroll percentage, click id, or event name\n}\n\n/** Accept action (open survey) */\nexport interface PopupActionAccept {\n    label: string;\n    surveyId: string; // survey id to launch\n}\n\n/** Decline action */\nexport interface PopupActionDecline {\n    label: string;\n    cooldownDays?: number; // optional: do not show again until X days pass\n}\n\n/** Start Surveys Action */\nexport interface PopupActionStart {\n    label: string;\n}\n\n/** Complete action (accept and auto-complete survey) */\n// Requires the survey to support auto-completion via parameters.\nexport interface PopupActionComplete {\n    label: string;\n    surveyId: string; // survey id to launch\n    autoCompleteParams: Record<string, unknown>; // parameters used for auto-completion\n    cooldownDays?: number;\n}\n\n/** Set of actions available in the popup */\nexport interface PopupActions {\n    accept?: PopupActionAccept;\n    decline?: PopupActionDecline;\n    complete?: PopupActionComplete;\n    start?: PopupActionStart;\n    back?: PopupActionDecline;\n}\n\n/** Configurable popup styles */\nexport interface PopupStyle {\n    theme: 'light' | 'dark';\n    position: 'bottom' | 'bottom-right' | 'bottom-left' | 'top' | 'top-right' | 'top-left' | 'center';\n    /** @deprecated Not used by the SDK; kept only for API compatibility */\n    imageUrl?: string | null;\n}\n\n/** Segments/targeting rules for showing the popup */\nexport interface PopupSegments {\n    lang?: string[]; // allowed languages\n    path?: string[]; // app routes where it can be shown\n    [key: string]: unknown; // possible future extension\n}\n\n/** Full popup definition */\nexport interface PopupDefinition {\n    id: string;\n    title: string;\n    message: string; // rendered safe HTML (recommended to sanitize upstream)\n    triggers: PopupTrigger[];\n    cooldown?: PopupTriggerCondition[];\n    actions?: PopupActions;\n    surveyId: string;\n    productId: string;\n    style?: PopupStyle;\n    segments?: PopupSegments;\n}\n\nexport interface FormStyle\n{\n    id: string;\n    logo: string;\n    title: string;\n    companyName: string;\n    backgroundColor: string;\n    boxBackgroundColor: string;\n    buttonOnTopColor: string;\n    buttonPrimaryColor: string\n    buttonSecondaryColor: string;\n    loadingBarColor: string;\n    favIcon: string;\n    startMessage: string;\n    successMessage: string;\n    addLogoInMsg: boolean;\n    privacyPolicyUrl: string;\n    helpUrl: string;\n    integrationId: string;\n    redirectLink: string;\n    redirectError: string;\n    redirectTime: number;\n    integrationThemeId: string;\n    contentAlign: 'top' | 'center';\n    logoSize: 'small' | 'medium' | 'large';\n    logoPosition: 'left' | 'right' | 'center';\n    showProgressBar: boolean;\n    showProgressUnit: boolean;\n    progressUnit: 'percentage' | 'fraction';\n}\n\n\nexport interface FormData {\n    id: string;\n    name: string;\n    description: string;\n    type: string;\n    identity: string;\n    status: string;\n    createdAt: Date;\n    updatedAt: Date;\n    externalId?: string | null;\n    companyId: string;\n    productId: string;\n    userId: string;\n    style: FormStyle\n}\n\nexport enum POPUPSESSIONSTATUS {\n    NONE = \"NONE\",\n    SHOWED = \"SHOWED\",\n    PARTIAL = \"PARTIAL\",\n    COMPLETED = \"COMPLETED\",\n    DEPRECATED = \"DEPRECATED\",\n}\n","import type { TriggerConfig } from '../types';\nimport type { DeepdotsPopups } from '../core/deepdots-popups';\n\nexport function setupTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  switch (trigger.type) {\n    case 'time':\n      setupTimeTrigger(popups, trigger);\n      break;\n    case 'scroll':\n      setupScrollTrigger(popups, trigger);\n      break;\n    case 'exit':\n      setupExitTrigger(popups, trigger);\n      break;\n    case 'event':\n      setupEventTrigger(popups, trigger);\n      break;\n    case 'click':\n      setupClickTrigger(popups, trigger);\n      break;\n  }\n}\n\nfunction setupTimeTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  const delay = trigger.value || 5000;\n  setTimeout(() => {\n    popups.triggerSurvey(trigger.surveyId, trigger.popupId);\n  }, delay);\n  popups.debug(`Time trigger set for ${delay}ms`);\n}\n\nfunction setupScrollTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  const threshold = trigger.value || 50;\n  const handler = () => {\n    const scrollPercentage = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100;\n    if (scrollPercentage >= threshold) {\n      popups.triggerSurvey(trigger.surveyId, trigger.popupId);\n      window.removeEventListener('scroll', handler);\n    }\n  };\n  window.addEventListener('scroll', handler);\n  popups.debug(`Scroll trigger set for ${threshold}%`);\n}\n\nfunction setupExitTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  if (typeof window === 'undefined') return;\n\n  const delaySeconds = parseExitDelaySeconds(trigger.value);\n  const historyRef = window.history;\n  const originalPushState = historyRef.pushState.bind(historyRef);\n  const originalReplaceState = historyRef.replaceState.bind(historyRef);\n\n  let lastUrl = normalizeUrl(window.location.href);\n  let lastQueuedKey = '';\n  let lastQueuedAt = 0;\n\n  const queueLeave = (fromRaw: string, toRaw: string) => {\n    const from = normalizeUrl(fromRaw);\n    const to = normalizeUrl(toRaw);\n    if (!from || !to || from === to) return;\n\n    const key = `${from}=>${to}`;\n    const now = Date.now();\n    if (key === lastQueuedKey && now - lastQueuedAt < 150) return;\n    lastQueuedKey = key;\n    lastQueuedAt = now;\n    popups.queueExitPopup(trigger.surveyId, delaySeconds, from, trigger.popupId);\n  };\n\n  const handleNavigation = (to: string) => {\n    const from = lastUrl;\n    queueLeave(from, to);\n    lastUrl = normalizeUrl(to);\n  };\n\n  const handleDocumentClick = (event: MouseEvent) => {\n    if (event.defaultPrevented) return;\n    if (event.button !== 0) return;\n    if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;\n\n    const anchor = (event.target as Element | null)?.closest?.('a');\n    if (!(anchor instanceof HTMLAnchorElement)) return;\n\n    const href = anchor.getAttribute('href');\n    if (!href || href.startsWith('javascript:') || href.startsWith('mailto:') || href.startsWith('tel:')) {\n      return;\n    }\n    const target = anchor.getAttribute('target');\n    if (target && target !== '_self') return;\n\n    let destination: URL;\n    try {\n      destination = new URL(href, window.location.href);\n    } catch {\n      return;\n    }\n\n    if (destination.origin !== window.location.origin) return;\n    queueLeave(window.location.href, destination.href);\n  };\n\n  const handleHashChange = (event: HashChangeEvent) => {\n    const to = event.newURL || window.location.href;\n    const from = event.oldURL || lastUrl;\n    queueLeave(from, to);\n    lastUrl = normalizeUrl(to);\n  };\n\n  const handlePopState = () => {\n    handleNavigation(window.location.href);\n  };\n\n  historyRef.pushState = function (data: any, unused: string, url?: string | URL | null) {\n    const from = window.location.href;\n    const result = originalPushState(data, unused, url as any);\n    queueLeave(from, window.location.href);\n    lastUrl = normalizeUrl(window.location.href);\n    return result;\n  };\n\n  historyRef.replaceState = function (data: any, unused: string, url?: string | URL | null) {\n    const from = window.location.href;\n    const result = originalReplaceState(data, unused, url as any);\n    queueLeave(from, window.location.href);\n    lastUrl = normalizeUrl(window.location.href);\n    return result;\n  };\n\n  document.addEventListener('click', handleDocumentClick, true);\n  window.addEventListener('hashchange', handleHashChange);\n  window.addEventListener('popstate', handlePopState);\n  popups.debug('Exit trigger set (deferred to next route)', {\n    surveyId: trigger.surveyId,\n    delaySeconds,\n  });\n}\n\nfunction setupEventTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  // Event triggers are manually fired by host application using popups.triggerEvent(name).\n  popups.debug('Event trigger registered', {\n    popupId: trigger.popupId,\n    surveyId: trigger.surveyId,\n    eventName: String(trigger.value || ''),\n  });\n}\n\nfunction parseExitDelaySeconds(value?: number | string): number {\n  if (typeof value === 'number' && Number.isFinite(value)) {\n    return Math.max(0, value);\n  }\n  if (typeof value === 'string' && value.trim()) {\n    const parsed = Number(value);\n    if (Number.isFinite(parsed)) return Math.max(0, parsed);\n  }\n  return 0;\n}\n\nfunction normalizeUrl(value: string): string {\n  if (!value) return '';\n  const withoutIndex = value.replace(/\\/index\\.html(?=($|[?#]))/i, '');\n  return withoutIndex.length > 1 && withoutIndex.endsWith('/') ? withoutIndex.slice(0, -1) : withoutIndex;\n}\n\nfunction setupClickTrigger(popups: DeepdotsPopups, trigger: TriggerConfig): void {\n  const targetId = typeof trigger.value === 'string' ? trigger.value : '';\n  if (!targetId) {\n    popups.debug('Click trigger missing element id', trigger);\n    return;\n  }\n\n  const attach = () => {\n    const el = document.getElementById(targetId);\n    if (!el) {\n      popups.debug('Click trigger target not found', targetId);\n      return false;\n    }\n    const handler = (e: MouseEvent) => {\n      if (e.defaultPrevented) return;\n      popups.triggerSurvey(trigger.surveyId, trigger.popupId);\n      el.removeEventListener('click', handler);\n    };\n    el.addEventListener('click', handler);\n    popups.debug(`Click trigger set for #${targetId}`);\n    return true;\n  };\n\n  if (typeof document === 'undefined') return;\n  if (attach()) return;\n  window.addEventListener('DOMContentLoaded', () => attach(), { once: true });\n}\n","import {DeepdotsConfig, DeepdotsInitParams} from '../types';\n\n/** Variables específicas por entorno derivadas de nodeEnv */\nexport interface EnvironmentVariables {\n  apiBaseUrl: string;\n}\n\nconst ENVIRONMENT_MAP: Record<\"development\" | \"production\", EnvironmentVariables> = {\n  development: {\n    apiBaseUrl: 'https://api-dev.deepdots.com',\n  },\n  production: {\n    apiBaseUrl: 'https://api.deepdots.com',\n  },\n};\n\n/** Resuelve las variables para el entorno indicado */\nexport function resolveEnvironment(nodeEnv: DeepdotsInitParams['nodeEnv']): EnvironmentVariables {\n  return ENVIRONMENT_MAP[nodeEnv || 'production'];\n}\n\n","import type { IdentityAnswer } from '../tracking/tracking-manager';\n\n/**\n * Construye un HTML autocontenido que renderiza el survey de `@magicfeedback/native`\n * dentro de un WebView (React Native). Carga el bundle desde CDN, crea el form con la\n * identidad inyectada (`profile`/`metadata`) y reenvía los eventos del survey al host\n * vía el puente de react-native-webview: `window.ReactNativeWebView.postMessage`.\n *\n * Mensajes emitidos (JSON `{name, payload}`): `loaded`, `before_submit`, `after_submit`,\n * `survey_completed`, `back`, `popup_close`.\n */\nexport interface BuildSurveyHtmlOptions {\n  surveyId: string;\n  productId: string;\n  env?: string; // 'production' | 'development'\n  profile?: IdentityAnswer[];\n  metadata?: IdentityAnswer[];\n  version?: string; // versión de @magicfeedback/native\n}\n\nexport function buildSurveyHtml(opts: BuildSurveyHtmlOptions): string {\n  const env = opts.env === 'development' ? 'dev' : 'prod';\n  const version = opts.version ?? '2.2.4';\n  const cdn = `https://cdn.jsdelivr.net/npm/@magicfeedback/native@${version}/dist/magicfeedback-sdk.browser.js`;\n  const sid = JSON.stringify(opts.surveyId);\n  const pid = JSON.stringify(opts.productId);\n  const profileJson = JSON.stringify(opts.profile ?? []);\n  const metaJson = JSON.stringify(opts.metadata ?? []);\n\n  return `<!DOCTYPE html><html><head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n<meta name=\"color-scheme\" content=\"light\"/>\n<style>html,body{margin:0;padding:0;background:transparent;font-family:-apple-system,system-ui,sans-serif}#mf{width:100%;box-sizing:border-box}#mf *{max-width:100%;box-sizing:border-box}</style>\n</head><body>\n<div id=\"mf\"></div>\n<script>\n(function(){\n  function emit(s){ try{ if(window.ReactNativeWebView){ window.ReactNativeWebView.postMessage(s); } }catch(e){} }\n  function emitJSON(n,p){ try{ emit(JSON.stringify({name:n,payload:p||{}})); }catch(e){} }\n  window.DeepdotsClose = function(){ emitJSON('popup_close'); };\n  var initialized=false;\n  function initMF(){\n    if(initialized || !window.magicfeedback) return initialized;\n    initialized=true;\n    try{\n      window.magicfeedback.init({ debug:false, env:'${env}' });\n      var form = window.magicfeedback.form(${sid}, ${pid}, ${profileJson}, ${metaJson});\n      window.DeepdotsForm = form;\n      form.generate('mf', {\n        addButton:false,\n        getMetaData:true,\n        onLoadedEvent:function(){ emitJSON('loaded'); },\n        beforeSubmitEvent:function(){ emitJSON('before_submit'); },\n        afterSubmitEvent:function(p){\n          try{ if(p && p.completed){ emitJSON('survey_completed', p); } else { emitJSON('after_submit', p); } }\n          catch(e){ emitJSON('after_submit'); }\n        },\n        onBackEvent:function(p){ emitJSON('back', p); }\n      }).catch(function(e){ emit('error:init'); });\n    }catch(e){ emit('error:exception'); }\n    return true;\n  }\n  var s=document.createElement('script'); s.src=${JSON.stringify(cdn)}; s.async=true;\n  s.onload=function(){ initMF(); };\n  s.onerror=function(){ emit('error:load'); };\n  document.head.appendChild(s);\n  var tries=0, t=setInterval(function(){ if(initMF()||++tries>40){ clearInterval(t); } },150);\n})();\n</script>\n</body></html>`;\n}\n","import type { DeepdotsEventType, PopupActions, PopupStyle } from '../types';\nimport type { PopupRenderer } from './renderer';\nimport { buildSurveyIdentity } from '../tracking/tracking-manager';\nimport { buildSurveyHtml } from '../ui/surveyHtml';\n\ntype EmitFn = (type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>) => void;\n\n/** Payload que recibe el host para montar el WebView del survey. */\nexport interface ReactNativeSurveyPayload {\n  surveyId: string;\n  productId: string;\n  /** HTML autocontenido para `<WebView source={{ html }}>`. */\n  html: string;\n}\n\nexport interface ReactNativeRendererOptions {\n  /** Se llama al mostrar un popup: monta el WebView con `payload.html`. */\n  onShow?: (payload: ReactNativeSurveyPayload) => void;\n  /** Se llama al cerrar el popup: desmonta el WebView. */\n  onHide?: () => void;\n}\n\n/**\n * Renderer de React Native: el SDK no puede pintar componentes RN, así que entrega el\n * HTML del survey al host (que lo monta en `react-native-webview`) y traduce los\n * mensajes del WebView a eventos de popup del SDK (→ `POST /sdk/popups`, Messaging #18–22).\n *\n * Uso:\n * ```tsx\n * const renderer = new ReactNativePopupRenderer({\n *   onShow: (p) => setSurvey({ ...p, visible: true }),\n *   onHide: () => setSurvey((s) => ({ ...s, visible: false })),\n * });\n * sdk.setRenderer(renderer);\n * // …\n * <WebView source={{ html: survey.html }}\n *          onMessage={(e) => renderer.handleMessage(e.nativeEvent.data)} />\n * ```\n */\nexport class ReactNativePopupRenderer implements PopupRenderer {\n  private emitFn: EmitFn | null = null;\n  private onCloseFn: (() => void) | null = null;\n  private currentSurveyId: string | null = null;\n  private partialEmitted = false;\n\n  constructor(private options: ReactNativeRendererOptions = {}) {}\n\n  init(): void {\n    /* nada que preparar */\n  }\n\n  show(\n    surveyId: string,\n    productId: string,\n    _actions: PopupActions | undefined,\n    emit: EmitFn,\n    onClose: () => void,\n    env: string = 'production',\n    userId?: string,\n    _style?: PopupStyle,\n    sessionId?: string,\n    miniService?: string,\n  ): void {\n    this.emitFn = emit;\n    this.onCloseFn = onClose;\n    this.currentSurveyId = surveyId;\n    this.partialEmitted = false;\n\n    const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null);\n    const html = buildSurveyHtml({ surveyId, productId, env, profile, metadata });\n    if (this.options.onShow) {\n      this.options.onShow({ surveyId, productId, html });\n    } else {\n      console.warn(\n        '[Deepdots] ReactNativePopupRenderer sin onShow: pasa { onShow } a new ReactNativePopupRenderer({...}) para montar el WebView del survey.',\n      );\n    }\n  }\n\n  hide(): void {\n    this.options.onHide?.();\n    this.currentSurveyId = null;\n  }\n\n  /**\n   * El host la conecta al `onMessage` del WebView. Traduce los mensajes del survey a\n   * eventos del SDK: primera interacción → `popup_clicked` (PARTIAL), completado →\n   * `survey_completed` (COMPLETED) y cierra el popup.\n   */\n  handleMessage(raw: string): void {\n    const surveyId = this.currentSurveyId;\n    if (!surveyId || !this.emitFn) return;\n\n    let name: string | undefined;\n    try {\n      name = (JSON.parse(raw) as { name?: string }).name;\n    } catch {\n      name = raw; // mensajes simples (\"error:load\")\n    }\n\n    switch (name) {\n      case 'loaded':\n      case 'before_submit':\n      case 'after_submit':\n      case 'back':\n        if (!this.partialEmitted) {\n          this.partialEmitted = true;\n          this.emitFn('popup_clicked', surveyId, { action: 'partial' });\n        }\n        break;\n      case 'survey_completed':\n        this.emitFn('survey_completed', surveyId);\n        this.onCloseFn?.(); // el core enruta a hidePopup() → renderer.hide() → onHide\n        break;\n      case 'popup_close':\n        this.onCloseFn?.();\n        break;\n      default:\n        break;\n    }\n  }\n}\n\n/** Detección simple de entorno React Native. */\nexport function isReactNativeEnv(): boolean {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  return typeof navigator !== 'undefined' && (navigator as any).product === 'ReactNative';\n}\n\n/** Factoría usada por `createDefaultRenderer` cuando se detecta RN (el host debería pasar onShow). */\nexport function createReactNativeRenderer(): PopupRenderer {\n  return new ReactNativePopupRenderer();\n}\n","import {DeepdotsEventType, PopupActions, PopupStyle} from '../types';\nimport { isReactNativeEnv, createReactNativeRenderer } from './react-native-renderer';\n// renderPopup (DOM + @magicfeedback/native) se carga PEREZOSAMENTE solo al mostrar\n// un popup en navegador, para que importar el SDK sea seguro en React Native/SSR.\n\nexport interface PopupRenderer {\n  /** Preparar recursos si aplica */\n  init?(): void;\n  /** Mostrar popup */\n  show(\n    surveyId: string,\n    productId: string,\n    actions: PopupActions | undefined,\n    emit: (type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>) => void,\n    onClose: () => void,\n    env?: string,\n    userId?: string,\n    style?: PopupStyle,\n    sessionId?: string,\n    miniService?: string,\n  ): void;\n  /** Ocultar popup */\n  hide(): void;\n}\n\n/** Renderer que no hace nada (SSR / entornos sin DOM) */\nexport class NoopPopupRenderer implements PopupRenderer {\n  show(): void { /* no-op */ }\n  hide(): void { /* no-op */ }\n}\n\n/** Renderer para navegadores usando la implementación actual basada en renderPopup */\nexport class BrowserPopupRenderer implements PopupRenderer {\n  private container: HTMLElement | null = null;\n  private visible = false;\n\n  init(): void {\n    if (typeof document === 'undefined') return;\n    if (!this.container) {\n      this.container = document.createElement('div');\n      this.container.id = 'deepdots-popup-container';\n      this.container.style.cssText = `\n          position: fixed;\n          top: 0;\n          left: 0;\n          width: 100%;\n          height: 100%;\n          display: none;\n          z-index: 999999;\n          background: rgba(0, 0, 0, 0.5);\n          justify-content: center;\n          align-items: center;\n        `;\n    }\n    if (!document.body.contains(this.container)) {\n      document.body.appendChild(this.container);\n    }\n  }\n\n  show(\n    surveyId: string,\n    productId: string,\n    actions: PopupActions | undefined,\n    emit: (type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>) => void,\n    onClose: () => void,\n    env: string = 'production',\n    userId?: string,\n    style?: PopupStyle,\n    sessionId?: string,\n    miniService?: string,\n  ): void {\n    if (this.visible) return;\n    if (!this.container || !document.body.contains(this.container)) this.init();\n    if (!this.container) return; // aún sin DOM\n    this.visible = true;\n    const container = this.container;\n    void import('../ui/renderPopup').then(({ renderPopup }) => {\n      renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService);\n    });\n  }\n\n  hide(): void {\n    this.visible = false;\n    if (this.container) {\n      this.container.style.display = 'none';\n      this.container.innerHTML = '';\n    }\n  }\n}\n\n/** Factoría para obtener renderer por defecto */\nexport function createDefaultRenderer(): PopupRenderer {\n  if (typeof document === 'undefined') {\n    // Entorno sin DOM: probar RN primero\n    if (isReactNativeEnv()) return createReactNativeRenderer();\n    return new NoopPopupRenderer();\n  }\n  // Si estamos en React Native y hay WebView con document emulado, aún queremos RN renderer\n  if (isReactNativeEnv()) return createReactNativeRenderer();\n  return new BrowserPopupRenderer();\n}\n","/**\n * Capa de Analytics (eventos GA-style) — canal SEPARADO del feedback de survey.\n *\n * El feedback de survey se envía con `magicfeedback.send()`. La analítica de\n * navegación/comportamiento (page views, mini-services, tasks/funnels, meaningful\n * interactions, findability…) va por un ENDPOINT PROPIO, vinculada por `user_id`.\n *\n * De momento NO se hace la llamada: el `sink` por defecto hace `console.log` del\n * payload exacto que se enviaría (dry-run), para poder verificarlo. Cuando el\n * endpoint exista, se sustituye el sink por un POST.\n */\n\nimport type { DeviceInfo } from './device-info';\n\nexport interface AnalyticsEvent {\n  name: string;\n  timestamp: number;\n  params?: Record<string, unknown>;\n}\n\nexport interface AnalyticsEnvelope {\n  /** Clave pública del cliente (auth). */\n  publicKey?: string;\n  /** Id que vincula la analítica al usuario (el backend cose por aquí). */\n  userId: string | null;\n  /** Session id del backend si ya se conoce (puede ir null). */\n  sessionId: string | null;\n  context: {\n    platform: string; // 'web' | 'android' | 'ios' (RN inyecta la suya)\n    language?: string;\n    /** Info de dispositivo (Technology #11–13). */\n    device?: DeviceInfo;\n    /** User attributes del cliente, usados para breakdowns (registration_status, pass_type, …). */\n    attributes: Record<string, string>;\n  };\n  events: AnalyticsEvent[];\n}\n\nexport type AnalyticsSink = (payload: AnalyticsEnvelope) => void;\n\n/** Identidad resuelta por el tracking, inyectada al construir el payload. */\nexport interface AnalyticsIdentity {\n  userId: string | null;\n  sessionId: string | null;\n}\n\n/** Sink por defecto: NO envía nada, solo pinta por consola lo que se enviaría. */\nexport const dryRunSink: AnalyticsSink = (payload) => {\n  // eslint-disable-next-line no-console\n  console.log(\n    '[DeepdotsAnalytics] (dry-run · NO enviado · sin init.analytics) POST /sdk/feedback →',\n    JSON.stringify(payload, null, 2),\n  );\n};\n\nexport interface AnalyticsManagerOptions {\n  sink?: AnalyticsSink;\n  now?: () => number;\n  publicKey?: string;\n  language?: string;\n  device?: DeviceInfo;\n  /** Plataforma del envelope (default 'web'; RN inyecta 'android'/'ios'). */\n  platform?: string;\n}\n\nexport class AnalyticsManager {\n  private sink: AnalyticsSink;\n  private now: () => number;\n  private publicKey?: string;\n  private language?: string;\n  private device?: DeviceInfo;\n  private platform: string;\n\n  private events: AnalyticsEvent[] = [];\n  private attributes: Record<string, string> = {};\n  private miniService: string | null = null;\n  private miniServiceEnteredAt = 0;\n\n  constructor(options: AnalyticsManagerOptions = {}) {\n    this.sink = options.sink ?? dryRunSink;\n    this.now = options.now ?? (() => Date.now());\n    this.publicKey = options.publicKey;\n    this.language = options.language;\n    this.device = options.device;\n    this.platform = options.platform ?? 'web';\n  }\n\n  /** Mezcla user attributes (se coercionan a string). Mutable en runtime. */\n  setUserAttributes(attrs: Record<string, string | number | boolean>): void {\n    for (const [k, v] of Object.entries(attrs)) {\n      if (!k) continue;\n      this.attributes[k] = String(v);\n    }\n  }\n\n  /** Marca el inicio de un mini-service; etiqueta los eventos siguientes con `mini_service`. */\n  enterMiniService(name: string, entryPointType?: string): void {\n    this.miniService = name;\n    this.miniServiceEnteredAt = this.now();\n    this.track('mini_service_enter', { entry_point_type: entryPointType ?? null });\n  }\n\n  /** Cierra el mini-service activo emitiendo `mini_service_exit` con su duración (#27). No-op si no hay ninguno. */\n  exitMiniService(): void {\n    const name = this.miniService;\n    if (name == null) return;\n    const durationSeconds = Math.max(0, Math.round((this.now() - this.miniServiceEnteredAt) / 1000));\n    this.miniService = null; // dejar de etiquetar antes de emitir el evento de salida\n    this.track('mini_service_exit', { mini_service: name, duration_seconds: durationSeconds });\n  }\n\n  /** Registra un evento de analítica (modelo GA: nombre + params). */\n  track(name: string, params?: Record<string, unknown>): void {\n    const merged: Record<string, unknown> = {\n      ...(this.miniService ? { mini_service: this.miniService } : {}),\n      ...(params ?? {}),\n    };\n    this.events.push({\n      name,\n      timestamp: this.now(),\n      params: Object.keys(merged).length ? merged : undefined,\n    });\n  }\n\n  /** Mini-service activo (para inyectarlo en la metadata del survey, #33). */\n  getMiniService(): string | null {\n    return this.miniService;\n  }\n\n  /** Nº de eventos pendientes de flush. */\n  pending(): number {\n    return this.events.length;\n  }\n\n  /** Construye el envelope que se enviaría al endpoint de analytics. */\n  buildPayload(identity: AnalyticsIdentity): AnalyticsEnvelope {\n    return {\n      publicKey: this.publicKey,\n      userId: identity.userId,\n      sessionId: identity.sessionId,\n      context: {\n        platform: this.platform,\n        language: this.language,\n        device: this.device,\n        attributes: { ...this.attributes },\n      },\n      events: [...this.events],\n    };\n  }\n\n  /** Envía (vía sink) el lote acumulado y vacía el buffer. No-op si no hay eventos. */\n  flush(identity: AnalyticsIdentity): AnalyticsEnvelope | null {\n    if (this.events.length === 0) return null;\n    const payload = this.buildPayload(identity);\n    this.sink(payload);\n    this.events = [];\n    return payload;\n  }\n}\n","/**\n * Mapeo del envelope de analytics → body de `POST /sdk/feedback`.\n *\n * La analítica se envía como un Feedback del modelo del Surveys SDK, agrupado por una\n * INTEGRACIÓN creada en la plataforma. Se manda en streaming con `completed:false` y\n * `finished:false` (nunca se \"cierra\"); el backend cose por `sessionId` + `user_id`.\n *\n * Encoding (decisión 2026-06-22):\n *  - cada evento (dato recabado) → una `metric` {key: nombre_evento, value: JSON(timestamp + params)}\n *  - identidad (user_id) → `profile` como `external-user-id`\n *  - contexto (user_id, session_id, platform, language, device, attributes) → `metadata`\n *  - `answers` vacío\n *  - `text` vacío\n */\n\nimport type { AnalyticsEnvelope, AnalyticsSink } from './analytics-manager';\n\nexport interface AnalyticsKeys {\n  publicKey: string;\n  integration: string;\n}\n\nexport interface FeedbackKV {\n  key: string;\n  value: string;\n}\n\nexport interface AnalyticsFeedbackBody {\n  feedback: {\n    text: string;\n    answers?: FeedbackKV[];\n    metadata: FeedbackKV[];\n    metrics: FeedbackKV[];\n    profile?: FeedbackKV[];\n    finished: boolean;\n  };\n  publicKey: string;\n  integration: string;\n  completed: boolean;\n  finished?: boolean;\n  /** sessionId devuelto por el primer POST; permite que el backend agrupe todos los eventos en un solo registro. */\n  sessionId?: string;\n}\n\n/** Inserta un par key/value en la lista solo si el valor está definido y no es vacío. */\nfunction pushKV(list: FeedbackKV[], key: string, value: unknown): void {\n  if (value === undefined || value === null || value === '') return;\n  list.push({ key, value: String(value) });\n}\n\nexport function buildAnalyticsFeedbackBody(\n  envelope: AnalyticsEnvelope,\n  keys: AnalyticsKeys,\n  feedbackSessionId?: string,\n): AnalyticsFeedbackBody {\n  const { context } = envelope;\n\n  const metrics: FeedbackKV[] = envelope.events.map((e) => ({\n    key: e.name,\n    value: JSON.stringify({ timestamp: e.timestamp, ...(e.params ?? {}) }),\n  }));\n\n  const profile: FeedbackKV[] = [];\n  pushKV(profile, 'external-user-id', envelope.userId);\n\n  const metadata: FeedbackKV[] = [];\n  pushKV(metadata, 'user_id', envelope.userId);\n  pushKV(metadata, 'session_id', envelope.sessionId);\n  pushKV(metadata, 'platform', context.platform);\n  pushKV(metadata, 'language', context.language);\n  if (context.device) {\n    pushKV(metadata, 'device_type', context.device.device_type);\n    pushKV(metadata, 'os_version', context.device.os_version);\n    pushKV(metadata, 'device_model', context.device.device_model);\n    pushKV(metadata, 'app_version', context.device.app_version);\n    pushKV(metadata, 'user_agent', context.device.user_agent);\n  }\n  for (const [k, v] of Object.entries(context.attributes ?? {})) {\n    pushKV(metadata, k, v);\n  }\n\n  return {\n    feedback: {\n      text: '',\n      answers: [],\n      metadata,\n      metrics,\n      profile,\n      finished: false,\n    },\n    publicKey: keys.publicKey,\n    integration: keys.integration,\n    completed: false,\n    // finished: false,\n    ...(feedbackSessionId ? { sessionId: feedbackSessionId } : {}),\n  };\n}\n\nexport interface FeedbackSinkOptions {\n  /** Base URL del backend (api(.|-dev.)deepdots.com) ya resuelta por el entorno. */\n  baseUrl: string;\n  keys: AnalyticsKeys;\n  /** Logger opcional (gated por debug). */\n  log?: (...args: unknown[]) => void;\n  /** fetch inyectable (tests / RN). */\n  fetchImpl?: typeof fetch;\n}\n\n/**\n * Sink real: transforma el envelope y hace `POST {baseUrl}/sdk/feedback`.\n * Fire-and-forget (no bloquea el flush); errores solo se loguean.\n * Stateful: cachea el `sessionId` que devuelve el backend en la primera respuesta\n * y lo envía en los siguientes POSTs para que el backend agrupe todos los eventos\n * en un único registro de feedback.\n */\nexport function createFeedbackSink(options: FeedbackSinkOptions): AnalyticsSink {\n  let feedbackSessionId: string | undefined;\n\n  return (envelope: AnalyticsEnvelope) => {\n    const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId);\n    const f = options.fetchImpl ?? (typeof fetch !== 'undefined' ? fetch : undefined);\n    if (!f) {\n      options.log?.('[DeepdotsAnalytics] no fetch disponible; payload no enviado', body);\n      return;\n    }\n    options.log?.('[DeepdotsAnalytics] POST /sdk/feedback →', body);\n    f(`${options.baseUrl}/sdk/feedback`, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(body),\n    })\n      .then(async (res) => {\n        if (res.ok) {\n          try {\n            const data = (await res.json()) as { sessionId?: string };\n            if (data?.sessionId && data.sessionId !== feedbackSessionId) {\n              feedbackSessionId = data.sessionId;\n              options.log?.('[DeepdotsAnalytics] feedbackSessionId cacheado:', feedbackSessionId);\n            }\n          } catch {\n            /* respuesta sin JSON — ignorar */\n          }\n        }\n      })\n      .catch((err) => options.log?.('[DeepdotsAnalytics] error enviando feedback', err));\n  };\n}\n","/**\n * Observador de navegación (Fase 2). Detecta cambios de pantalla y emite \"visitas\"\n * completadas (screen + entrada/salida/duración) cuando se abandona una pantalla.\n *\n * En Web se engancha a la History API (pushState/replaceState/popstate/hashchange).\n * La lógica de timing y normalización es pura y testeable sin DOM (vía `begin`/`visit`/`stop`\n * y un reloj inyectable).\n *\n * El consumidor (DeepdotsPopups) reenvía cada visita como un evento `page_view` por el\n * canal de analytics; el grafo se reconstruye en backend por orden + timestamp.\n */\n\nexport interface ScreenVisit {\n  screen: string;\n  entry: number;\n  exit: number;\n  durationSeconds: number;\n}\n\nexport type VisitListener = (visit: ScreenVisit) => void;\n\nconst UUID_PREFIX = /^[0-9a-f]{8}-[0-9a-f]{4}-/i;\n\n/** Normaliza una URL a un nombre de pantalla: path (+hash route), sin query, IDs → :id. */\nexport function normalizeScreen(href: string): string {\n  let pathAndHash: string;\n  try {\n    const u = new URL(href, 'http://deepdots.local');\n    pathAndHash = u.pathname + (u.hash || '');\n  } catch {\n    pathAndHash = href;\n  }\n  // quitar query (incluida la que pueda venir dentro del hash route)\n  pathAndHash = pathAndHash.replace(/\\?[^#]*/g, '');\n  const collapsed = pathAndHash\n    .split('/')\n    .map((seg) => (/^[0-9]+$/.test(seg) || UUID_PREFIX.test(seg) ? ':id' : seg))\n    .join('/');\n  return collapsed || '/';\n}\n\nexport interface NavigationObserverOptions {\n  now?: () => number;\n}\n\nexport class NavigationObserver {\n  private now: () => number;\n  private listeners = new Set<VisitListener>();\n  private currentScreen: string | null = null;\n  private entryAt = 0;\n  private installed = false;\n  private domHandlers: Array<() => void> = [];\n\n  constructor(options: NavigationObserverOptions = {}) {\n    this.now = options.now ?? (() => Date.now());\n  }\n\n  onVisit(listener: VisitListener): void {\n    this.listeners.add(listener);\n  }\n\n  /** Fija la pantalla inicial (sin emitir visita; su duración se cierra al salir). */\n  begin(href: string): void {\n    this.currentScreen = normalizeScreen(href);\n    this.entryAt = this.now();\n  }\n\n  /** Navega a una pantalla nueva: cierra la anterior (emite visita) y abre la nueva. */\n  visit(href: string): void {\n    const next = normalizeScreen(href);\n    if (next === this.currentScreen) return; // misma pantalla → no es una visita nueva\n    this.closeCurrent();\n    this.currentScreen = next;\n    this.entryAt = this.now();\n  }\n\n  /** Cierra la pantalla actual emitiendo su visita (p. ej. al cerrar la app/pestaña). */\n  stop(): void {\n    this.closeCurrent();\n    this.currentScreen = null;\n  }\n\n  private closeCurrent(): void {\n    if (this.currentScreen == null) return;\n    const exit = this.now();\n    const visit: ScreenVisit = {\n      screen: this.currentScreen,\n      entry: this.entryAt,\n      exit,\n      durationSeconds: Math.max(0, Math.round((exit - this.entryAt) / 1000)),\n    };\n    this.listeners.forEach((l) => {\n      try {\n        l(visit);\n      } catch {\n        /* listener no debe romper la navegación */\n      }\n    });\n  }\n\n  /** Instala los hooks de History en el navegador y registra la pantalla actual. */\n  install(): void {\n    if (this.installed || typeof window === 'undefined' || typeof history === 'undefined') return;\n    this.installed = true;\n\n    const handle = () => this.visit(window.location.href);\n\n    const originalPush = history.pushState.bind(history);\n    const originalReplace = history.replaceState.bind(history);\n    history.pushState = (data: unknown, unused: string, url?: string | URL | null) => {\n      const r = originalPush(data as never, unused, url as never);\n      handle();\n      return r;\n    };\n    history.replaceState = (data: unknown, unused: string, url?: string | URL | null) => {\n      const r = originalReplace(data as never, unused, url as never);\n      handle();\n      return r;\n    };\n    window.addEventListener('popstate', handle);\n    window.addEventListener('hashchange', handle);\n\n    this.domHandlers.push(() => {\n      history.pushState = originalPush;\n      history.replaceState = originalReplace;\n      window.removeEventListener('popstate', handle);\n      window.removeEventListener('hashchange', handle);\n    });\n\n    this.begin(window.location.href);\n  }\n\n  uninstall(): void {\n    this.domHandlers.forEach((off) => off());\n    this.domHandlers = [];\n    this.installed = false;\n  }\n}\n","/**\n * Device info para el context de analytics (Technology #11–13).\n *\n * En Web enviamos `device_type` (heurística fiable) + `user_agent` crudo, y dejamos\n * que el backend derive OS/modelo/navegador del UA (como hace GA) — el parseo de UA en\n * cliente es frágil. `app_version` lo provee el cliente (una web no tiene versión de app\n * nativa). En KMP las APIs nativas dan os_version/device_model reales.\n */\n\nexport interface DeviceInfo {\n  device_type: 'mobile' | 'tablet' | 'desktop';\n  os_version?: string;\n  device_model?: string;\n  app_version?: string;\n  user_agent?: string;\n}\n\nexport function parseDeviceType(ua: string): 'mobile' | 'tablet' | 'desktop' {\n  const s = (ua || '').toLowerCase();\n  if (/ipad|tablet|playbook|silk/.test(s) || (/android/.test(s) && !/mobile/.test(s))) {\n    return 'tablet';\n  }\n  if (/mobi|iphone|ipod|windows phone/.test(s) || (/android/.test(s) && /mobile/.test(s))) {\n    return 'mobile';\n  }\n  return 'desktop';\n}\n\nexport function collectDeviceInfo(appVersion?: string): DeviceInfo {\n  const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';\n  return {\n    device_type: parseDeviceType(ua),\n    user_agent: ua || undefined,\n    app_version: appVersion,\n  };\n}\n","/**\n * Mide el tiempo ACTIVO (en primer plano), estilo GA4 (engagement time).\n * Acumula mientras está \"resumed\" (pestaña visible / app en foreground) y pausa en\n * background. `consume()` devuelve los ms activos desde la última lectura y reinicia,\n * dejando el timer corriendo. El consumidor emite un evento `user_engagement` con\n * `engagement_time_msec`; el backend lo suma por sesión → \"Average Time Spent per Session\" (#8).\n */\nexport class EngagementTracker {\n  private now: () => number;\n  private activeMs = 0;\n  private lastResumeAt: number | null = null;\n\n  constructor(now: () => number = () => Date.now()) {\n    this.now = now;\n  }\n\n  /** Reanuda el conteo (pestaña visible / app en foreground). Idempotente. */\n  resume(): void {\n    if (this.lastResumeAt === null) this.lastResumeAt = this.now();\n  }\n\n  /** Pausa el conteo (pestaña oculta / app en background), acumulando el tramo activo. */\n  pause(): void {\n    if (this.lastResumeAt !== null) {\n      this.activeMs += this.now() - this.lastResumeAt;\n      this.lastResumeAt = null;\n    }\n  }\n\n  /** Devuelve los ms activos acumulados desde la última lectura y reinicia (sin parar el timer). */\n  consume(): number {\n    if (this.lastResumeAt !== null) {\n      const t = this.now();\n      this.activeMs += t - this.lastResumeAt;\n      this.lastResumeAt = t;\n    }\n    const ms = this.activeMs;\n    this.activeMs = 0;\n    return ms;\n  }\n\n  isActive(): boolean {\n    return this.lastResumeAt !== null;\n  }\n}\n","import type { KeyValueStorage } from '../tracking/tracking-manager';\nimport { STORAGE_KEYS } from '../tracking/tracking-manager';\n\n/** Valor de un atributo de contact (info interna del usuario que solo conoce el host). */\nexport type ContactAttributeValue = string | number | boolean;\nexport type ContactAttributes = Record<string, ContactAttributeValue>;\n\n/** Body de `POST /sdk/popups/contact`. */\nexport interface ContactBody {\n  publicKey: string;\n  userId: string;\n  userAttributes: ContactAttributes;\n}\n\nexport interface ContactManagerOptions {\n  storage: KeyValueStorage;\n  publicKey: string;\n  userId: string;\n  /** Envío real (inyectable para tests): hace el `POST /sdk/popups/contact`. */\n  post: (body: ContactBody) => Promise<void>;\n}\n\n/** Serialización estable (claves ordenadas) para el diff contra lo último enviado. */\nfunction stableSerialize(attrs: ContactAttributes): string {\n  const sorted: ContactAttributes = {};\n  for (const key of Object.keys(attrs).sort()) {\n    sorted[key] = attrs[key];\n  }\n  return JSON.stringify(sorted);\n}\n\n/**\n * Gestiona los atributos de contact del usuario identificado (`userId` del init).\n * Solo envía cuando cambian respecto a lo último persistido en storage, para ahorrar\n * peticiones (el host puede llamar `setAttributes` en cada identificación sin miedo).\n */\nexport class ContactManager {\n  private readonly storage: KeyValueStorage;\n  private readonly publicKey: string;\n  private readonly userId: string;\n  private readonly post: (body: ContactBody) => Promise<void>;\n\n  constructor(options: ContactManagerOptions) {\n    this.storage = options.storage;\n    this.publicKey = options.publicKey;\n    this.userId = options.userId;\n    this.post = options.post;\n  }\n\n  /**\n   * Envía los atributos si cambiaron respecto a lo último enviado.\n   * @returns `true` si se envió, `false` si no hubo cambios.\n   */\n  async setAttributes(attributes: ContactAttributes): Promise<boolean> {\n    const serialized = stableSerialize(attributes);\n    const last = this.storage.getItem(STORAGE_KEYS.contactAttributes);\n    if (last === serialized) return false;\n\n    await this.post({\n      publicKey: this.publicKey,\n      userId: this.userId,\n      userAttributes: attributes,\n    });\n    this.storage.setItem(STORAGE_KEYS.contactAttributes, serialized);\n    return true;\n  }\n}\n","import {\n    DeepdotsConfig,\n    TriggerConfig,\n    DeepdotsEvent,\n    DeepdotsEventType,\n    EventListener,\n    DeepdotsInitParams,\n    PopupDefinition,\n    PopupTriggerCondition,\n    PopupActions,\n    PopupTrigger,\n    PopupTriggerConditionStatus,\n    POPUP_TRIGGER_CONDITION_STATUSES, POPUPSESSIONSTATUS,\n    PopupStyle,\n} from '../types';\n// renderPopup se carga de forma PEREZOSA (dynamic import) para no arrastrar\n// `@magicfeedback/native` (browser) ni el CSS al importar el SDK en entornos sin DOM (React Native).\nimport { setupTrigger } from '../triggers';\nimport { resolveEnvironment } from '../config/env';\nimport { PopupRenderer, createDefaultRenderer } from '../platform/renderer';\nimport { TrackingManager, createDefaultStorage } from '../tracking/tracking-manager';\nimport { AnalyticsManager, type AnalyticsEnvelope } from '../analytics/analytics-manager';\nimport { createFeedbackSink } from '../analytics/feedback-payload';\nimport { NavigationObserver } from '../tracking/navigation-observer';\nimport { collectDeviceInfo } from '../analytics/device-info';\nimport { EngagementTracker } from '../analytics/engagement-tracker';\nimport { ContactManager, type ContactAttributes } from '../contact/contact-manager';\n\nconst EXIT_QUEUE_STORAGE_KEY = '__deepdots_exit_popup_queue__';\nconst DAY_IN_MS = 24 * 60 * 60 * 1000;\n\ninterface DeferredExitPopup {\n    id: string;\n    surveyId: string;\n    dueAt: number;\n    sourceUrl: string;\n}\n\ninterface LegacyPopupTriggerCondition {\n    answered?: boolean;\n    cooldownDays?: number;\n}\n\ninterface PopupProgressState {\n    status: PopupTriggerConditionStatus;\n    timestamp: number;\n}\n\ntype NormalizedPopupDefinition = PopupDefinition & {\n    legacyConditions?: LegacyPopupTriggerCondition[];\n};\n\n/**\n * Main class for managing survey popups\n */\nexport class DeepdotsPopups {\n    private config: DeepdotsConfig | null = null;\n    private listeners: Map<DeepdotsEventType, Set<EventListener>> = new Map();\n    private triggers: TriggerConfig[] = [];\n    private initialized = false;\n    private renderer: PopupRenderer = createDefaultRenderer();\n    private popupContainer: HTMLElement | null = null; // deprecated: mantenido para compatibilidad interna\n    private popupDefinitions: NormalizedPopupDefinition[] = [];\n    private popupsLoaded = false;\n    private pendingAutoLaunch = false;\n\n    private answeredSurveys: Set<string> = new Set();\n    private surveyProgress: Map<string, PopupProgressState> = new Map();\n    private lastShown: Map<string, number> = new Map(); // popupId -> timestamp mostrado\n    private surveyToPopupId: Map<string, string> = new Map(); // surveyId -> popupId\n    private deferredExitTimers: number[] = [];\n\n    private baseUrl: string = '';\n    private env: 'production' | 'development' = 'production';\n\n    /** Identidad + sesión (Fase 1 tracking). Null hasta init(). */\n    private tracking: TrackingManager | null = null;\n    /** Capa de analytics (canal separado del feedback). Null hasta init(). */\n    private analytics: AnalyticsManager | null = null;\n    /** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */\n    private navObserver: NavigationObserver | null = null;\n    /** Tiempo activo (engagement time, #8). */\n    private engagement: EngagementTracker | null = null;\n    /** Atributos internos del usuario identificado → POST /sdk/popups/contact. Null si no hay userId. */\n    private contact: ContactManager | null = null;\n    /** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */\n    private navStarted = false;\n\n    /** Initialize the SDK with configuration */\n    init(config: DeepdotsInitParams): void {\n        if (this.initialized) {\n            this.log('SDK already initialized');\n            return;\n        }\n\n        const env = resolveEnvironment(config.nodeEnv);\n\n        this.baseUrl = env.apiBaseUrl;\n        this.env = config.nodeEnv || 'production';\n\n        this.config = {\n            apiKey: config.apiKey || undefined,\n            debug: config.debug || false,\n            userId: config.userId || undefined,\n        } as DeepdotsConfig;\n\n        // user_id lo gestiona el SDK (persistente); el session_id lo provee el backend\n        // (respuesta de POST /sdk/popups) y se cachea — el SDK no genera ni expira sesiones.\n        const storage = config.storage ?? createDefaultStorage();\n        this.tracking = new TrackingManager({\n            storage,\n            clientUserId: this.config.userId,\n            enabled: config.trackingEnabled ?? true,\n        });\n\n        // Contact: info interna del usuario que solo conoce el host (segmentación/targeting).\n        // Solo trackeamos usuarios IDENTIFICADOS → se crea únicamente si hay userId del init.\n        if (this.config.userId) {\n            const userId = this.config.userId;\n            const publicKey = this.config.apiKey ?? '';\n            this.contact = new ContactManager({\n                storage,\n                publicKey,\n                userId,\n                post: (body) => this.postContact(body),\n            });\n            // Atributos de contact pasados en init: envío fire-and-forget (solo si cambiaron).\n            if (config.contactAttributes) {\n                void this.setContactAttributes(config.contactAttributes);\n            }\n        }\n        this.log('tracking · user_id:', this.tracking.getUserId(), '· new_user:', this.tracking.isNewUser(), '· enabled:', this.tracking.isTrackingEnabled());\n\n        // Analytics: se envía como Feedback a la integración (`POST /sdk/feedback`) si se\n        // pasan claves en init.analytics; si no, queda en dry-run (solo console.log).\n        const analyticsSink = config.analytics\n            ? createFeedbackSink({\n                  baseUrl: this.baseUrl,\n                  keys: config.analytics,\n                  log: (...a) => this.log(...a),\n              })\n            : undefined;\n        this.analytics = new AnalyticsManager({\n            sink: analyticsSink,\n            publicKey: config.analytics?.publicKey ?? this.config.apiKey,\n            language: typeof navigator !== 'undefined' ? navigator.language : undefined,\n            platform: config.platform ?? 'web',\n            device: config.device ?? collectDeviceInfo(config.appVersion),\n        });\n        // Fase 2: navegación → eventos page_view por el canal de analytics.\n        this.navObserver = new NavigationObserver();\n        this.navObserver.onVisit((v) => this.track('page_view', { screen: v.screen, duration_seconds: v.durationSeconds }));\n        this.navObserver.install();\n        // Engagement time (#8): cuenta tiempo activo en primer plano.\n        this.engagement = new EngagementTracker();\n        this.engagement.resume();\n        this.setupAnalyticsFlush();\n\n        this.initialized = true;\n        this.log('SDK initialized', this.config);\n        if (this.renderer.init) this.renderer.init();\n        this.setupPopupContainer();\n\n        // Los popups SIEMPRE se reciben de la API (no se definen en init).\n        this.fetchPopupsFromServer().then((defs) => {\n            this.popupDefinitions = this.validatePopupDefinitions(defs);\n            this.popupsLoaded = true;\n            this.log('Popups loaded from API', this.popupDefinitions);\n            this.configureTriggersFromDefinitions();\n            this.processDeferredExitQueue();\n            if (this.pendingAutoLaunch) {\n                this.startTriggers();\n            }\n        });\n    }\n\n    /** User id actual (generado por el SDK o provisto por el cliente). Null si tracking off. */\n    getUserId(): string | null {\n        return this.tracking?.getUserId() ?? null;\n    }\n\n    /** Session id de navegación actual. Null si tracking off. */\n    getSessionId(): string | null {\n        return this.tracking?.getSessionId() ?? null;\n    }\n\n    /** Activa/desactiva el tracking (identidad + sesión + analytics). Kill-switch del contrato §7bis. */\n    setTrackingEnabled(enabled: boolean): void {\n        this.tracking?.setTrackingEnabled(enabled);\n        this.log('tracking · setTrackingEnabled:', enabled, '· session_id:', this.tracking?.getSessionId() ?? null);\n    }\n\n    // ───────── Analytics (canal separado del feedback, vinculado por user_id) ─────────\n\n    /** Registra un evento de analítica (modelo GA: nombre + params). No-op si tracking off. */\n    track(name: string, params?: Record<string, unknown>): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        this.analytics?.track(name, params);\n        this.log('analytics · track:', name, params ?? {});\n    }\n\n    /** User attributes para breakdowns (registration_status, pass_type, sector, pass_status…). */\n    setUserAttributes(attributes: Record<string, string | number | boolean>): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        this.analytics?.setUserAttributes(attributes);\n    }\n\n    /**\n     * Info interna del usuario que solo conoce el host (idioma, edad, plan…), persistida en el\n     * Contact del backend para segmentación/targeting de popups. Identificada por el `userId` del\n     * init. Solo envía si los atributos cambiaron (diff en storage). No-op si tracking off o sin userId.\n     * @returns `true` si se envió al backend, `false` si no hubo cambios o está deshabilitado.\n     */\n    async setContactAttributes(attributes: ContactAttributes): Promise<boolean> {\n        if (!this.tracking?.isTrackingEnabled()) return false;\n        if (!this.contact) return false;\n        return this.contact.setAttributes(attributes);\n    }\n\n    /** Marca el inicio de un mini-service; etiqueta los eventos siguientes. No-op si tracking off. */\n    enterMiniService(name: string, entryPointType?: string): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        this.analytics?.enterMiniService(name, entryPointType);\n        this.log('analytics · enterMiniService:', name, entryPointType ?? '');\n    }\n\n    /** Cierra el mini-service activo (emite `mini_service_exit` con duración, #27). No-op si tracking off. */\n    exitMiniService(): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        this.analytics?.exitMiniService();\n        this.log('analytics · exitMiniService');\n    }\n\n    /** Findability (#31/#35): registra una búsqueda. `has_results` se deriva de `resultsCount`. */\n    trackSearch(query: string, resultsCount: number, params?: Record<string, unknown>): void {\n        this.track('search', { query, results_count: resultsCount, has_results: resultsCount > 0, ...(params ?? {}) });\n    }\n\n    /** Findability friction (#34/#35): señal de fricción con su `friction_topic`. */\n    trackFindabilityFriction(frictionTopic: string, params?: Record<string, unknown>): void {\n        this.track('findability_friction', { friction_topic: frictionTopic, ...(params ?? {}) });\n    }\n\n    /** Funnel: un paso del embudo, correlacionado por `taskId`. El backend reconstruye conversión/drop-off/tiempo. */\n    trackFunnelStep(funnel: string, step: string, taskId: string, params?: Record<string, unknown>): void {\n        this.track('funnel_step', { funnel, step, task_id: taskId, ...(params ?? {}) });\n    }\n\n    /**\n     * Navegación MANUAL (entornos sin History API, p. ej. React Native con React Navigation).\n     * El host la llama en cada cambio de pantalla; emite `page_view` al salir de la anterior.\n     */\n    setScreen(name: string): void {\n        if (!this.navObserver) return;\n        if (!this.navStarted) {\n            this.navObserver.begin(name);\n            this.navStarted = true;\n        } else {\n            this.navObserver.visit(name);\n        }\n    }\n\n    /** App a foreground (RN: AppState 'active'): reanuda el engagement time. */\n    onForeground(): void {\n        this.engagement?.resume();\n    }\n\n    /**\n     * App a background (RN: AppState 'background'): cierra pantalla actual (page_view),\n     * mini-service (mini_service_exit), emite engagement y hace flush del lote.\n     */\n    onBackground(): void {\n        this.navObserver?.stop();\n        this.navStarted = false;\n        this.exitMiniService();\n        this.flushEngagement();\n        this.engagement?.pause();\n        this.flushAnalytics();\n    }\n\n    /** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */\n    previewAnalytics(): AnalyticsEnvelope {\n        return (\n            this.analytics?.buildPayload(this.analyticsIdentity()) ?? {\n                userId: null,\n                sessionId: null,\n                context: { platform: 'web', attributes: {} },\n                events: [],\n            }\n        );\n    }\n\n    /** Envía (hoy dry-run → console.log) el lote acumulado de analytics y vacía el buffer. */\n    flushAnalytics(): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        this.analytics?.flush(this.analyticsIdentity());\n    }\n\n    /** Emite un evento `user_engagement` con el tiempo activo acumulado (#8). */\n    private flushEngagement(): void {\n        if (!this.tracking?.isTrackingEnabled()) return;\n        const ms = this.engagement?.consume() ?? 0;\n        if (ms > 0) this.track('user_engagement', { engagement_time_msec: ms });\n    }\n\n    private analyticsIdentity() {\n        return {\n            userId: this.tracking?.getUserId() ?? null,\n            sessionId: this.tracking?.getSessionId() ?? null,\n        };\n    }\n\n    /** Flush automático al ocultar/cerrar la página (no perder el lote pendiente). */\n    private setupAnalyticsFlush(): void {\n        if (typeof document === 'undefined' || typeof window === 'undefined') return;\n        // al cerrar la página: cerrar pantalla (page_view) + mini-service + engagement, y enviar el lote\n        window.addEventListener('pagehide', () => {\n            this.navObserver?.stop();\n            this.exitMiniService();\n            this.flushEngagement();\n            this.flushAnalytics();\n        });\n        // al ocultar/mostrar la pestaña: pausar/reanudar engagement y enviar lo acumulado\n        document.addEventListener('visibilitychange', () => {\n            if (document.visibilityState === 'hidden') {\n                this.flushEngagement();\n                this.engagement?.pause();\n                this.flushAnalytics();\n            } else if (document.visibilityState === 'visible') {\n                this.engagement?.resume();\n            }\n        });\n    }\n\n    /** Enable auto-launch functionality with configured triggers */\n    autoLaunch(): void {\n        if (!this.initialized) {\n            throw new Error('SDK not initialized. Call init() first.');\n        }\n        if (!this.popupsLoaded) {\n            this.pendingAutoLaunch = true;\n            this.log('Auto-launch deferred until popups are loaded');\n            return;\n        }\n        this.startTriggers();\n    }\n\n    /** Inicia los triggers configurados */\n    private startTriggers(): void {\n        this.log('Auto-launch enabled');\n        this.triggers.forEach((trigger) => setupTrigger(this, trigger));\n    }\n\n    /** Configure triggers for auto-launching popups (manual) */\n    configureTriggers(triggers: TriggerConfig[]): void {\n        if (!this.initialized) {\n            throw new Error('SDK not initialized. Call init() first.');\n        }\n        this.triggers = triggers;\n        this.log('Triggers configured', triggers);\n    }\n\n    /** Deriva triggers desde las definiciones de popup */\n    private configureTriggersFromDefinitions(): void {\n        const derived: TriggerConfig[] = [];\n        this.debug('Validated popup definitions', this.popupDefinitions);\n\n        this.popupDefinitions.forEach((def) => {\n            def.triggers.forEach((trigger) => {\n                const type = this.mapPopupTriggerType(trigger.type);\n                if (!type) {\n                    this.debug('Unsupported trigger type', trigger.type);\n                    return;\n                }\n                const value = type === 'time' && typeof trigger.value === 'number'\n                    ? trigger.value * 1000\n                    : trigger.value;\n                derived.push({ type, value, surveyId: def.surveyId, popupId: def.id });\n            });\n        });\n\n        if (derived.length) {\n            this.configureTriggers(derived);\n        }\n    }\n\n    /** Lógica para evaluar condiciones antes de mostrar una encuesta */\n    triggerSurvey(surveyId: string, popupId?: string): void {\n        const def = this.findPopupDefinition(surveyId, popupId);\n        if (!def) {\n            this.debug('No popup definition for trigger', { surveyId, popupId });\n            return;\n        }\n        if (!this.shouldShow(def)) {\n            this.debug('Conditions prevented showing popup', def.id);\n            return;\n        }\n        this.showDefinition(def);\n    }\n\n    /** Trigger popups configured with trigger.type = 'event' and matching trigger.value */\n    public triggerEvent(eventName: string): void {\n        if (!this.initialized) {\n            throw new Error('SDK not initialized. Call init() first.');\n        }\n        const normalized = String(eventName || '').trim();\n        if (!normalized) {\n            this.debug('Ignoring empty event trigger name');\n            return;\n        }\n\n        const candidates = this.popupDefinitions.filter((def) => {\n            return def.triggers.some((trigger) => {\n                const triggerValue = String(trigger.value ?? '').trim();\n                return trigger.type === 'event' && triggerValue === normalized;\n            });\n        });\n\n        if (!candidates.length) {\n            this.debug('No event popup definitions found', { eventName: normalized });\n            return;\n        }\n\n        const matched = candidates.find((def) => this.shouldShow(def));\n        if (!matched) {\n            this.debug('Event popup blocked by conditions/segments', { eventName: normalized });\n            return;\n        }\n\n        this.showDefinition(matched);\n    }\n\n    private showDefinition(def: PopupDefinition): void {\n        this.log('Showing popup (definition)', def);\n        this.surveyToPopupId.set(def.surveyId, def.id);\n        this.lastShown.set(def.id, Date.now());\n        this.renderPopup(def.surveyId, def.productId, def.actions, def.style);\n        this.emitEvent('popup_shown', def.surveyId, { popupId: def.id });\n    }\n\n    private shouldShow(def: NormalizedPopupDefinition, pathUrl?: string, skipPathCheck = false): boolean {\n        if (!skipPathCheck && !this.matchesSegmentsPath(def, pathUrl)) {\n            return false;\n        }\n        if (!this.matchesSegmentsLang(def)) {\n            return false;\n        }\n\n        const cooldowns = def.cooldown || [];\n        if (cooldowns.length && !cooldowns.every((cooldown) => this.evaluateCooldown(def, cooldown))) {\n            return false;\n        }\n\n        const legacyConditions = def.legacyConditions || [];\n        if (!legacyConditions.length) return true;\n        return legacyConditions.every((condition) => this.evaluateLegacyCondition(def, condition));\n    }\n\n    private matchesSegmentsLang(def: PopupDefinition): boolean {\n        const langs = def.segments?.lang;\n        if (!langs || langs.length === 0) return true;\n\n        // navigator.language puede ser \"en\", \"en-US\", \"da\", \"da-DK\", etc.\n        const browserLang = (\n            typeof navigator !== 'undefined' ? navigator.language : ''\n        ).toLowerCase();\n\n        if (!browserLang) {\n            this.debug('No navigator.language available for lang comparison', { popupId: def.id, langs });\n            return true;\n        }\n\n        // Acepta si el idioma del browser empieza con alguno de los configurados\n        // ej: browser \"en-US\" coincide con segment \"en\"\n        const matches = langs.some((lang) => browserLang.startsWith(lang.toLowerCase()));\n        if (!matches) {\n            this.debug('Lang mismatch for popup', { popupId: def.id, langs, browserLang });\n        }\n        return matches;\n    }\n\n    private matchesSegmentsPath(def: PopupDefinition, pathUrl?: string): boolean {\n        const paths = def.segments?.path;\n        if (!paths || paths.length === 0) return true;\n        if (typeof window === 'undefined' || !window.location) {\n            this.debug('No window.location available for path comparison', { popupId: def.id, paths });\n            return true;\n        }\n\n        const normalizedHref = this.normalizeUrl(pathUrl || window.location.href || '');\n        const currentUrl = this.safeParseUrl(normalizedHref);\n        const normalizedPath = this.normalizeUrl(currentUrl?.pathname || window.location.pathname || '');\n\n        const matches = paths.some((rawCandidate) => {\n            const candidate = this.normalizeUrl(rawCandidate);\n            let match = false;\n            if (candidate.startsWith('http://') || candidate.startsWith('https://')) {\n                match = normalizedHref === candidate;\n            } else if (candidate.startsWith('/')) {\n                match = normalizedHref.includes(candidate);\n            } else {\n                match = normalizedPath === candidate;\n            }\n            this.debug('Path comparison', {\n                popupId: def.id,\n                candidate,\n                currentPath: normalizedPath,\n                currentHref: normalizedHref,\n                match,\n            });\n            return match;\n        });\n\n        if (!matches) {\n            this.debug('No path match for popup', { popupId: def.id, paths, currentPath: normalizedPath });\n        }\n\n        return matches;\n    }\n\n    private evaluateCooldown(def: PopupDefinition, condition: PopupTriggerCondition): boolean {\n        switch (condition.answered) {\n            case 'SHOWED':\n                return this.hasCooldownElapsed(this.lastShown.get(def.id), condition.cooldownDays);\n            case 'PARTIAL':\n            case 'COMPLETED': {\n                const progress = this.surveyProgress.get(def.surveyId);\n                if (!progress || progress.status !== condition.answered) {\n                    return true;\n                }\n                return this.hasCooldownElapsed(progress.timestamp, condition.cooldownDays);\n            }\n            default:\n                return true;\n        }\n    }\n\n    private evaluateLegacyCondition(def: PopupDefinition, condition: LegacyPopupTriggerCondition): boolean {\n        if (!condition.answered && this.answeredSurveys.has(def.surveyId)) {\n            return false;\n        }\n        return this.hasCooldownElapsed(this.lastShown.get(def.id), condition.cooldownDays);\n    }\n\n    private hasCooldownElapsed(timestamp: number | undefined, cooldownDays?: number): boolean {\n        if (!timestamp || !cooldownDays) {\n            return true;\n        }\n        return Date.now() - timestamp >= cooldownDays * DAY_IN_MS;\n    }\n\n    /** Marcar encuesta como contestada externamente */\n    public markSurveyAnswered(surveyId: string): void {\n        this.answeredSurveys.add(surveyId);\n        this.markSurveyProgress(surveyId, 'COMPLETED');\n    }\n\n    /** Queue an exit popup so it can render after navigation */\n    public queueExitPopup(surveyId: string, delaySeconds: number, sourceUrl?: string, popupId?: string): void {\n        const def = this.findPopupDefinition(surveyId, popupId);\n        if (!def) {\n            this.debug('No popup definition for exit trigger', { surveyId, popupId });\n            return;\n        }\n\n        const originUrl = sourceUrl || (typeof window !== 'undefined' ? window.location.href : '');\n        if (!originUrl) {\n            this.debug('Exit popup skipped: missing source URL', { surveyId });\n            return;\n        }\n\n        if (!this.shouldShow(def, originUrl)) {\n            this.debug('Exit popup skipped by conditions/path', { popupId: def.id, sourceUrl: originUrl });\n            return;\n        }\n\n        const safeDelayMs = Number.isFinite(delaySeconds) ? Math.max(0, delaySeconds * 1000) : 0;\n        const deferred: DeferredExitPopup = {\n            id: def.id,\n            surveyId: def.surveyId,\n            sourceUrl: this.normalizeUrl(originUrl),\n            dueAt: Date.now() + safeDelayMs,\n        };\n\n        const queue = this.getDeferredExitQueue().filter((item) => !(item.id === deferred.id && item.sourceUrl === deferred.sourceUrl));\n        queue.push(deferred);\n        this.setDeferredExitQueue(queue);\n        this.scheduleDeferredExitPopup(deferred);\n        this.debug('Exit popup queued', deferred);\n    }\n\n    private processDeferredExitQueue(): void {\n        const queue = this.getDeferredExitQueue();\n        if (!queue.length) return;\n\n        const pending: DeferredExitPopup[] = [];\n        const now = Date.now();\n        queue.forEach((item) => {\n            const def = this.popupDefinitions.find((popup) => popup.id === item.id && popup.surveyId === item.surveyId);\n            if (!def) {\n                return;\n            }\n            if (item.dueAt <= now) {\n                this.tryShowDeferredExitPopup(item);\n                return;\n            }\n            pending.push(item);\n            this.scheduleDeferredExitPopup(item);\n        });\n        this.setDeferredExitQueue(pending);\n    }\n\n    private scheduleDeferredExitPopup(item: DeferredExitPopup): void {\n        if (typeof window === 'undefined') return;\n        const delay = Math.max(0, item.dueAt - Date.now());\n        const timer = window.setTimeout(() => this.tryShowDeferredExitPopup(item), delay);\n        this.deferredExitTimers.push(timer);\n    }\n\n    private tryShowDeferredExitPopup(item: DeferredExitPopup): void {\n        const def = this.popupDefinitions.find((popup) => popup.id === item.id && popup.surveyId === item.surveyId);\n        if (!def) {\n            this.removeDeferredExitPopup(item);\n            return;\n        }\n\n        const currentUrl = typeof window !== 'undefined' ? this.normalizeUrl(window.location.href || '') : '';\n        if (!currentUrl || currentUrl === this.normalizeUrl(item.sourceUrl)) {\n            this.removeDeferredExitPopup(item);\n            this.debug('Exit popup dropped because route did not change', item);\n            return;\n        }\n\n        if (!this.shouldShow(def, undefined, true)) {\n            this.removeDeferredExitPopup(item);\n            this.debug('Exit popup skipped at render-time conditions', item);\n            return;\n        }\n\n        this.showDefinition(def);\n        this.removeDeferredExitPopup(item);\n    }\n\n    private findPopupDefinition(surveyId: string, popupId?: string): NormalizedPopupDefinition | undefined {\n        if (popupId) {\n            const byId = this.popupDefinitions.find((popup) => popup.id === popupId);\n            if (byId) return byId;\n        }\n        return this.popupDefinitions.find((popup) => popup.surveyId === surveyId);\n    }\n\n    private removeDeferredExitPopup(item: DeferredExitPopup): void {\n        const queue = this.getDeferredExitQueue().filter((entry) => !(entry.id === item.id && entry.sourceUrl === item.sourceUrl));\n        this.setDeferredExitQueue(queue);\n    }\n\n    private getDeferredExitQueue(): DeferredExitPopup[] {\n        if (typeof window === 'undefined') return [];\n        try {\n            const raw = window.sessionStorage.getItem(EXIT_QUEUE_STORAGE_KEY);\n            if (!raw) return [];\n            const parsed = JSON.parse(raw);\n            if (!Array.isArray(parsed)) return [];\n            return parsed\n                .filter((entry: unknown): entry is DeferredExitPopup => {\n                    if (typeof entry !== 'object' || entry === null) return false;\n                    const item = entry as Partial<DeferredExitPopup>;\n                    return typeof item.id === 'string'\n                        && typeof item.surveyId === 'string'\n                        && typeof item.sourceUrl === 'string'\n                        && typeof item.dueAt === 'number'\n                        && Number.isFinite(item.dueAt);\n                })\n                .map((item) => ({\n                    ...item,\n                    sourceUrl: this.normalizeUrl(item.sourceUrl),\n                }));\n        } catch {\n            return [];\n        }\n    }\n\n    private setDeferredExitQueue(queue: DeferredExitPopup[]): void {\n        if (typeof window === 'undefined') return;\n        try {\n            if (!queue.length) {\n                window.sessionStorage.removeItem(EXIT_QUEUE_STORAGE_KEY);\n                return;\n            }\n            window.sessionStorage.setItem(EXIT_QUEUE_STORAGE_KEY, JSON.stringify(queue));\n        } catch {\n            // Ignore storage errors in host environments that block storage access.\n        }\n    }\n\n    /** Fetch al servidor para obtener popups */\n    private async fetchPopupsFromServer(): Promise<unknown[]> {\n        const apiKey = this.config?.apiKey;\n        const baseUrl = this.baseUrl;\n        const userId = this.config?.userId;\n        if (!apiKey || !baseUrl) {\n            this.log('Missing apiKey or baseUrl. Skipping popups fetch.');\n            return [];\n        }\n        const filter = userId ? { where: { userId } } : null;\n        const query = filter ? `?filter=${encodeURIComponent(JSON.stringify(filter))}` : '';\n        const endpoint = `${baseUrl}/sdk/${encodeURIComponent(apiKey)}/popups${query}`;\n        try {\n            const response = await fetch(endpoint);\n            if (!response.ok) {\n                this.log('Failed to fetch popups', response.status, response.statusText);\n                return [];\n            }\n            const raw = await response.text();\n            const parsed = JSON.parse(raw);\n            if (!Array.isArray(parsed)) {\n                this.log('Unexpected popups payload', parsed);\n                return [];\n            }\n            this.debug('Fetched popups payload', parsed);\n            return parsed;\n        } catch (error) {\n            this.log('Error fetching popups', error);\n            return [];\n        }\n    }\n\n    /** Envía los atributos de contact a la API (`POST /sdk/popups/contact`). */\n    private async postContact(body: { publicKey: string; userId: string; userAttributes: ContactAttributes }): Promise<void> {\n        const baseUrl = this.baseUrl;\n        if (!baseUrl) return;\n        const endpoint = `${baseUrl}/sdk/popups/contact`;\n        try {\n            const response = await fetch(endpoint, {\n                method: 'POST',\n                headers: { 'Content-Type': 'application/json' },\n                body: JSON.stringify(body),\n            });\n            if (!response.ok) {\n                this.log('Failed to post contact', response.status, response.statusText);\n                return;\n            }\n            this.log('contact · sent attributes for user:', body.userId);\n        } catch (error) {\n            this.log('Error posting contact', error);\n        }\n    }\n\n    /** Notifica eventos de popup a la API */\n    private async postPopupEvent(status: POPUPSESSIONSTATUS, popupId: string, userId?: string): Promise<void> {\n        const apiKey = this.config?.apiKey;\n        const baseUrl = this.baseUrl;\n        if (!apiKey || !baseUrl) {\n            return;\n        }\n        const endpoint = `${baseUrl}/sdk/popups`;\n        try {\n            const response = await fetch(endpoint, {\n                method: 'POST',\n                headers: { 'Content-Type': 'application/json' },\n                body: JSON.stringify({\n                    publicKey: apiKey,\n                    status,\n                    popupId,\n                    userId: userId || undefined,\n                }),\n            });\n            if (!response.ok) {\n                this.log('Failed to post popup event', response.status, response.statusText);\n                return;\n            }\n            // Contrato Fase 1 §6: el backend devuelve el sessionId; lo cacheamos para\n            // inyectarlo en las respuestas de survey (lo cose por user_id).\n            try {\n                const data = await response.json();\n                if (data && typeof data.sessionId === 'string') {\n                    this.tracking?.setSessionId(data.sessionId);\n                    this.log('tracking · session_id from backend:', data.sessionId);\n                }\n            } catch {\n                // respuesta sin cuerpo JSON: nada que cachear\n            }\n        } catch (error) {\n            this.log('Error posting popup event', error);\n        }\n    }\n\n    /** Add an event listener */\n    on(eventType: DeepdotsEventType, listener: EventListener): void {\n        if (!this.listeners.has(eventType)) {\n            this.listeners.set(eventType, new Set());\n        }\n        this.listeners.get(eventType)!.add(listener);\n    }\n\n    /** Remove an event listener */\n    off(eventType: DeepdotsEventType, listener: EventListener): void {\n        const listeners = this.listeners.get(eventType);\n        if (listeners) {\n            listeners.delete(listener);\n        }\n    }\n\n    /** Setup popup container element */\n    private setupPopupContainer(): void {\n        if (typeof document === 'undefined') {\n            return;\n        }\n        this.popupContainer = document.createElement('div');\n        this.popupContainer.id = 'deepdots-popup-container';\n        this.popupContainer.style.cssText = `\n          position: fixed;\n          top: 0;\n          left: 0;\n          width: 100%;\n          height: 100%;\n          display: none;\n          z-index: 999999;\n          background: rgba(0, 0, 0, 0.5);\n          justify-content: center;\n          align-items: center;\n        `;\n        document.body.appendChild(this.popupContainer);\n    }\n\n    /** Render the popup UI */\n    private renderPopup(surveyId: string, productId: string, actions?: PopupActions, style?: PopupStyle): void {\n        const userId = this.tracking?.getUserId() ?? this.config?.userId;\n        const sessionId = this.tracking?.getSessionId() ?? undefined;\n        const miniService = this.analytics?.getMiniService() ?? undefined;\n        this.log('tracking · survey identity →', { userId: userId ?? null, sessionId: sessionId ?? null, miniService: miniService ?? null });\n        if (this.renderer) {\n            this.renderer.show(\n                surveyId,\n                productId,\n                actions,\n                (type, id, payload) => this.emitEvent(type, id, payload),\n                () => this.hidePopup(),\n                this.env,\n                userId,\n                style,\n                sessionId,\n                miniService,\n            );\n            return;\n        }\n\n        if (!this.popupContainer) return;\n        const container = this.popupContainer;\n        void import('../ui/renderPopup').then(({ renderPopup }) => {\n            renderPopup(\n                container,\n                surveyId,\n                productId,\n                actions,\n                (type, id, payload) => this.emitEvent(type, id, payload),\n                () => this.hidePopup(),\n                this.env,\n                userId,\n                style,\n                sessionId,\n                miniService,\n            );\n        });\n    }\n\n    /** Hide the popup */\n    private hidePopup(): void {\n        if (this.renderer) {\n            this.renderer.hide();\n            return;\n        }\n        if (this.popupContainer) {\n            this.popupContainer.style.display = 'none';\n            this.popupContainer.innerHTML = '';\n        }\n    }\n\n    /** Emit an event */\n    private emitEvent(type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>): void {\n        const event: DeepdotsEvent = { type, surveyId, timestamp: Date.now(), data };\n        this.log('Event emitted', event);\n\n        const isPartialClick = type === 'popup_clicked' && data?.action === 'partial';\n        if (isPartialClick) {\n            this.markSurveyProgress(surveyId, 'PARTIAL');\n        }\n        if (type === 'survey_completed') {\n            this.markSurveyAnswered(surveyId);\n        }\n        if (type === 'popup_shown' || type === 'survey_completed' || isPartialClick) {\n            const popupIdFromData = data?.popupId as string | undefined;\n            const popupId = popupIdFromData || this.surveyToPopupId.get(surveyId);\n            if (popupId) {\n                const userIdFromData = data?.userId as string | undefined;\n                const status = type === 'popup_shown'\n                    ? POPUPSESSIONSTATUS.SHOWED\n                    : type === 'survey_completed'\n                        ? POPUPSESSIONSTATUS.COMPLETED\n                        : POPUPSESSIONSTATUS.PARTIAL;\n                void this.postPopupEvent(status, popupId, userIdFromData || this.tracking?.getUserId() || this.config?.userId);\n            } else {\n                this.debug('No popupId available to post event', { type, surveyId });\n            }\n        }\n\n        const listeners = this.listeners.get(type);\n        if (listeners) {\n            listeners.forEach((listener) => {\n                try {\n                    listener(event);\n                } catch (error) {\n                    console.error('Error in event listener:', error);\n                }\n            });\n        }\n    }\n\n    /** Log debug messages */\n    private log(...args: unknown[]): void {\n        if (this.config?.debug) {\n            console.log('[DeepdotsPopups]', ...args);\n        }\n    }\n\n    /** External debug method for triggers */\n    public debug(...args: unknown[]): void {\n        this.log(...args);\n    }\n\n    /** Set a custom renderer */\n    public setRenderer(renderer: PopupRenderer): void {\n        this.renderer = renderer;\n        if (this.initialized && this.renderer.init) {\n            this.renderer.init();\n        }\n    }\n\n    private normalizeUrl(value: string): string {\n        if (!value) return '';\n        const withoutIndex = value.replace(/\\/index\\.html(?=($|[?#]))/i, '');\n        return withoutIndex.length > 1 && withoutIndex.endsWith('/') ? withoutIndex.slice(0, -1) : withoutIndex;\n    }\n\n    private safeParseUrl(url: string): URL | null {\n        if (!url) return null;\n        try {\n            return new URL(url, typeof window !== 'undefined' ? window.location.href : undefined);\n        } catch {\n            return null;\n        }\n    }\n\n    private mapPopupTriggerType(type: PopupTrigger['type']): TriggerConfig['type'] | null {\n        switch (type) {\n            case 'time_on_page':\n                return 'time';\n            case 'scroll':\n                return 'scroll';\n            case 'exit':\n                return 'exit';\n            case 'click':\n                return 'click';\n            case 'event':\n                return 'event';\n            default:\n                return null;\n        }\n    }\n\n    private markSurveyProgress(surveyId: string, status: PopupTriggerConditionStatus): void {\n        const current = this.surveyProgress.get(surveyId);\n        if (current?.status === 'COMPLETED' && status !== 'COMPLETED') {\n            return;\n        }\n        this.surveyProgress.set(surveyId, { status, timestamp: Date.now() });\n    }\n\n    private isPopupDefinition(value: unknown): value is NormalizedPopupDefinition {\n        if (typeof value !== 'object' || value === null) return false;\n        const popup = value as Partial<NormalizedPopupDefinition>;\n\n        return typeof popup.id === 'string'\n            && typeof popup.title === 'string'\n            && typeof popup.message === 'string'\n            && typeof popup.surveyId === 'string'\n            && typeof popup.productId === 'string'\n            && Array.isArray(popup.triggers)\n            && popup.triggers.length > 0\n            && popup.triggers.every((trigger) => this.isPopupTrigger(trigger))\n            && (!popup.cooldown || popup.cooldown.every((condition) => this.isPopupTriggerCondition(condition)));\n    }\n\n    private isPopupTrigger(value: unknown): value is PopupTrigger {\n        if (typeof value !== 'object' || value === null) return false;\n        const trigger = value as Partial<PopupTrigger>;\n        return this.isPopupTriggerType(trigger.type)\n            && (typeof trigger.value === 'number' || typeof trigger.value === 'string');\n    }\n\n    private isPopupTriggerType(value: unknown): value is PopupTrigger['type'] {\n        return value === 'time_on_page'\n            || value === 'scroll'\n            || value === 'exit'\n            || value === 'click'\n            || value === 'event';\n    }\n\n    private isPopupTriggerCondition(value: unknown): value is PopupTriggerCondition {\n        if (typeof value !== 'object' || value === null) return false;\n        const condition = value as Partial<PopupTriggerCondition>;\n        return POPUP_TRIGGER_CONDITION_STATUSES.includes(condition.answered as PopupTriggerConditionStatus)\n            && typeof condition.cooldownDays === 'number'\n            && Number.isFinite(condition.cooldownDays)\n            && condition.cooldownDays >= 0;\n    }\n\n    private isLegacyPopupTriggerCondition(value: unknown): value is LegacyPopupTriggerCondition {\n        if (typeof value !== 'object' || value === null) return false;\n        const condition = value as Partial<LegacyPopupTriggerCondition>;\n        if (condition.answered !== undefined && typeof condition.answered !== 'boolean') {\n            return false;\n        }\n        if (condition.cooldownDays !== undefined) {\n            return typeof condition.cooldownDays === 'number'\n                && Number.isFinite(condition.cooldownDays)\n                && condition.cooldownDays >= 0;\n        }\n        return true;\n    }\n\n    private normalizeTriggers(value: unknown): PopupTrigger[] {\n        const items = Array.isArray(value) ? value : value ? [value] : [];\n        return items\n            .filter((trigger): trigger is PopupTrigger => this.isPopupTrigger(trigger))\n            .map((trigger) => ({\n                type: trigger.type,\n                value: trigger.value,\n            }));\n    }\n\n    private normalizeCooldown(value: unknown): PopupTriggerCondition[] {\n        if (!Array.isArray(value)) return [];\n        return value.filter((condition): condition is PopupTriggerCondition => this.isPopupTriggerCondition(condition));\n    }\n\n    private normalizeLegacyConditions(value: unknown): LegacyPopupTriggerCondition[] {\n        if (!Array.isArray(value)) return [];\n        return value.filter((condition): condition is LegacyPopupTriggerCondition => this.isLegacyPopupTriggerCondition(condition));\n    }\n\n    private normalizePopupDefinition(def: unknown): NormalizedPopupDefinition | null {\n        if (typeof def !== 'object' || def === null) return null;\n        const raw = def as Partial<PopupDefinition> & {\n            trigger?: PopupTrigger | PopupTrigger[];\n            triggers?: PopupTrigger | PopupTrigger[];\n            conditions?: LegacyPopupTriggerCondition[];\n            cooldown?: PopupTriggerCondition[];\n        };\n\n        const rawTriggers = raw.triggers ?? raw.trigger;\n        const triggers = this.normalizeTriggers(rawTriggers);\n        if (!triggers.length) return null;\n\n        const rawTriggerList = Array.isArray(rawTriggers) ? rawTriggers : rawTriggers ? [rawTriggers] : [];\n        const legacyConditions = [\n            ...this.normalizeLegacyConditions(raw.conditions),\n            ...rawTriggerList.flatMap((trigger) => this.normalizeLegacyConditions((trigger as { condition?: unknown }).condition)),\n        ];\n        const cooldown = this.normalizeCooldown(raw.cooldown);\n\n        return {\n            ...(raw as PopupDefinition),\n            triggers,\n            cooldown,\n            legacyConditions,\n        };\n    }\n\n    private validatePopupDefinitions(defs: unknown[]): NormalizedPopupDefinition[] {\n        return defs\n            .map((def) => this.normalizePopupDefinition(def))\n            .filter((def): def is NormalizedPopupDefinition => !!def && this.isPopupDefinition(def));\n    }\n}\n","/**\n * Auto-wiring de React Native: concentra TODA la configuración en el SDK para que el\n * host solo tenga que envolver su app en un `<DeepdotsProvider config={...}>`.\n *\n * No importa React ni librerías nativas: el host (o el Provider) le pasa los módulos\n * nativos que tenga instalados (MMKV, device-info, AppState). Todo es opcional y degrada\n * con elegancia (sin MMKV → in-memory; sin device-info → sin device info).\n */\nimport type { DeepdotsPopups } from '../core/deepdots-popups';\nimport type { DeepdotsInitParams } from '../types';\nimport type { KeyValueStorage } from '../tracking/tracking-manager';\nimport type { DeviceInfo } from '../analytics/device-info';\nimport type { PopupRenderer } from '../platform/renderer';\n\n/** Forma mínima de `react-native-mmkv` (instancia MMKV). */\nexport interface MmkvLike {\n  getString(key: string): string | undefined | null;\n  set(key: string, value: string): void;\n  delete(key: string): void;\n}\n\n/** Forma mínima de `react-native-device-info`. */\nexport interface DeviceInfoLike {\n  isTablet?: () => boolean;\n  getSystemVersion?: () => string;\n  getDeviceId?: () => string;\n  getVersion?: () => string;\n}\n\n/** Forma mínima de `AppState` de react-native. */\nexport interface AppStateLike {\n  addEventListener(type: 'change', listener: (state: string) => void): { remove: () => void } | void;\n}\n\nexport interface ReactNativeSetupDeps {\n  mmkv?: MmkvLike | null;\n  deviceInfo?: DeviceInfoLike | null;\n  appState?: AppStateLike | null;\n  platform?: 'web' | 'android' | 'ios';\n  renderer?: PopupRenderer;\n}\n\n/** Adaptador KeyValueStorage (síncrono) sobre una instancia de MMKV. */\nexport function mmkvStorage(mmkv: MmkvLike): KeyValueStorage {\n  return {\n    getItem: (k) => mmkv.getString(k) ?? null,\n    setItem: (k, v) => mmkv.set(k, v),\n    removeItem: (k) => mmkv.delete(k),\n  };\n}\n\n/** Recoge device info desde react-native-device-info (Technology #11–13). */\nexport function collectRnDevice(d: DeviceInfoLike): DeviceInfo {\n  return {\n    device_type: d.isTablet?.() ? 'tablet' : 'mobile',\n    os_version: d.getSystemVersion?.(),\n    device_model: d.getDeviceId?.(),\n    app_version: d.getVersion?.(),\n  };\n}\n\n/**\n * Configura el SDK para React Native en una sola llamada: storage persistente (MMKV),\n * device info, platform, init y lifecycle (AppState → onForeground/onBackground).\n * Devuelve una función de limpieza (quita el listener de AppState).\n */\nexport function setupReactNative(\n  sdk: DeepdotsPopups,\n  config: DeepdotsInitParams,\n  deps: ReactNativeSetupDeps = {},\n): () => void {\n  if (deps.renderer) sdk.setRenderer(deps.renderer);\n\n  const storage = deps.mmkv ? mmkvStorage(deps.mmkv) : config.storage;\n  const device = deps.deviceInfo ? collectRnDevice(deps.deviceInfo) : config.device;\n  const platform = deps.platform ?? config.platform;\n\n  sdk.init({ ...config, storage, device, platform });\n\n  let subscription: { remove: () => void } | void;\n  if (deps.appState?.addEventListener) {\n    subscription = deps.appState.addEventListener('change', (state) => {\n      if (state === 'active') sdk.onForeground();\n      else sdk.onBackground(); // 'background' | 'inactive'\n    });\n  }\n\n  return () => {\n    if (subscription && typeof subscription.remove === 'function') subscription.remove();\n  };\n}\n"],"mappings":";;;;;;;;;AA0FO,IAAM,mCAAkE;AAAA,EAC3E;AAAA,EACA;AAAA,EACA;AACJ;;;AC3FO,SAAS,aAAa,QAAwB,SAA8B;AACjF,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,uBAAiB,QAAQ,OAAO;AAChC;AAAA,IACF,KAAK;AACH,yBAAmB,QAAQ,OAAO;AAClC;AAAA,IACF,KAAK;AACH,uBAAiB,QAAQ,OAAO;AAChC;AAAA,IACF,KAAK;AACH,wBAAkB,QAAQ,OAAO;AACjC;AAAA,IACF,KAAK;AACH,wBAAkB,QAAQ,OAAO;AACjC;AAAA,EACJ;AACF;AAEA,SAAS,iBAAiB,QAAwB,SAA8B;AAC9E,QAAM,QAAQ,QAAQ,SAAS;AAC/B,aAAW,MAAM;AACf,WAAO,cAAc,QAAQ,UAAU,QAAQ,OAAO;AAAA,EACxD,GAAG,KAAK;AACR,SAAO,MAAM,wBAAwB,KAAK,IAAI;AAChD;AAEA,SAAS,mBAAmB,QAAwB,SAA8B;AAChF,QAAM,YAAY,QAAQ,SAAS;AACnC,QAAM,UAAU,MAAM;AACpB,UAAM,mBAAoB,OAAO,WAAW,SAAS,gBAAgB,eAAe,OAAO,eAAgB;AAC3G,QAAI,oBAAoB,WAAW;AACjC,aAAO,cAAc,QAAQ,UAAU,QAAQ,OAAO;AACtD,aAAO,oBAAoB,UAAU,OAAO;AAAA,IAC9C;AAAA,EACF;AACA,SAAO,iBAAiB,UAAU,OAAO;AACzC,SAAO,MAAM,0BAA0B,SAAS,GAAG;AACrD;AAEA,SAAS,iBAAiB,QAAwB,SAA8B;AAC9E,MAAI,OAAO,WAAW,YAAa;AAEnC,QAAM,eAAe,sBAAsB,QAAQ,KAAK;AACxD,QAAM,aAAa,OAAO;AAC1B,QAAM,oBAAoB,WAAW,UAAU,KAAK,UAAU;AAC9D,QAAM,uBAAuB,WAAW,aAAa,KAAK,UAAU;AAEpE,MAAI,UAAU,aAAa,OAAO,SAAS,IAAI;AAC/C,MAAI,gBAAgB;AACpB,MAAI,eAAe;AAEnB,QAAM,aAAa,CAAC,SAAiB,UAAkB;AACrD,UAAM,OAAO,aAAa,OAAO;AACjC,UAAM,KAAK,aAAa,KAAK;AAC7B,QAAI,CAAC,QAAQ,CAAC,MAAM,SAAS,GAAI;AAEjC,UAAM,MAAM,GAAG,IAAI,KAAK,EAAE;AAC1B,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,QAAQ,iBAAiB,MAAM,eAAe,IAAK;AACvD,oBAAgB;AAChB,mBAAe;AACf,WAAO,eAAe,QAAQ,UAAU,cAAc,MAAM,QAAQ,OAAO;AAAA,EAC7E;AAEA,QAAM,mBAAmB,CAAC,OAAe;AACvC,UAAM,OAAO;AACb,eAAW,MAAM,EAAE;AACnB,cAAU,aAAa,EAAE;AAAA,EAC3B;AAEA,QAAM,sBAAsB,CAAC,UAAsB;AACjD,QAAI,MAAM,iBAAkB;AAC5B,QAAI,MAAM,WAAW,EAAG;AACxB,QAAI,MAAM,WAAW,MAAM,WAAW,MAAM,YAAY,MAAM,OAAQ;AAEtE,UAAM,SAAU,MAAM,QAA2B,UAAU,GAAG;AAC9D,QAAI,EAAE,kBAAkB,mBAAoB;AAE5C,UAAM,OAAO,OAAO,aAAa,MAAM;AACvC,QAAI,CAAC,QAAQ,KAAK,WAAW,aAAa,KAAK,KAAK,WAAW,SAAS,KAAK,KAAK,WAAW,MAAM,GAAG;AACpG;AAAA,IACF;AACA,UAAM,SAAS,OAAO,aAAa,QAAQ;AAC3C,QAAI,UAAU,WAAW,QAAS;AAElC,QAAI;AACJ,QAAI;AACF,oBAAc,IAAI,IAAI,MAAM,OAAO,SAAS,IAAI;AAAA,IAClD,QAAQ;AACN;AAAA,IACF;AAEA,QAAI,YAAY,WAAW,OAAO,SAAS,OAAQ;AACnD,eAAW,OAAO,SAAS,MAAM,YAAY,IAAI;AAAA,EACnD;AAEA,QAAM,mBAAmB,CAAC,UAA2B;AACnD,UAAM,KAAK,MAAM,UAAU,OAAO,SAAS;AAC3C,UAAM,OAAO,MAAM,UAAU;AAC7B,eAAW,MAAM,EAAE;AACnB,cAAU,aAAa,EAAE;AAAA,EAC3B;AAEA,QAAM,iBAAiB,MAAM;AAC3B,qBAAiB,OAAO,SAAS,IAAI;AAAA,EACvC;AAEA,aAAW,YAAY,SAAU,MAAW,QAAgB,KAA2B;AACrF,UAAM,OAAO,OAAO,SAAS;AAC7B,UAAM,SAAS,kBAAkB,MAAM,QAAQ,GAAU;AACzD,eAAW,MAAM,OAAO,SAAS,IAAI;AACrC,cAAU,aAAa,OAAO,SAAS,IAAI;AAC3C,WAAO;AAAA,EACT;AAEA,aAAW,eAAe,SAAU,MAAW,QAAgB,KAA2B;AACxF,UAAM,OAAO,OAAO,SAAS;AAC7B,UAAM,SAAS,qBAAqB,MAAM,QAAQ,GAAU;AAC5D,eAAW,MAAM,OAAO,SAAS,IAAI;AACrC,cAAU,aAAa,OAAO,SAAS,IAAI;AAC3C,WAAO;AAAA,EACT;AAEA,WAAS,iBAAiB,SAAS,qBAAqB,IAAI;AAC5D,SAAO,iBAAiB,cAAc,gBAAgB;AACtD,SAAO,iBAAiB,YAAY,cAAc;AAClD,SAAO,MAAM,6CAA6C;AAAA,IACxD,UAAU,QAAQ;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,kBAAkB,QAAwB,SAA8B;AAE/E,SAAO,MAAM,4BAA4B;AAAA,IACvC,SAAS,QAAQ;AAAA,IACjB,UAAU,QAAQ;AAAA,IAClB,WAAW,OAAO,QAAQ,SAAS,EAAE;AAAA,EACvC,CAAC;AACH;AAEA,SAAS,sBAAsB,OAAiC;AAC9D,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO,KAAK,IAAI,GAAG,KAAK;AAAA,EAC1B;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AAC7C,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,OAAO,SAAS,MAAM,EAAG,QAAO,KAAK,IAAI,GAAG,MAAM;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAuB;AAC3C,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,eAAe,MAAM,QAAQ,8BAA8B,EAAE;AACnE,SAAO,aAAa,SAAS,KAAK,aAAa,SAAS,GAAG,IAAI,aAAa,MAAM,GAAG,EAAE,IAAI;AAC7F;AAEA,SAAS,kBAAkB,QAAwB,SAA8B;AAC/E,QAAM,WAAW,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AACrE,MAAI,CAAC,UAAU;AACb,WAAO,MAAM,oCAAoC,OAAO;AACxD;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AACnB,UAAM,KAAK,SAAS,eAAe,QAAQ;AAC3C,QAAI,CAAC,IAAI;AACP,aAAO,MAAM,kCAAkC,QAAQ;AACvD,aAAO;AAAA,IACT;AACA,UAAM,UAAU,CAAC,MAAkB;AACjC,UAAI,EAAE,iBAAkB;AACxB,aAAO,cAAc,QAAQ,UAAU,QAAQ,OAAO;AACtD,SAAG,oBAAoB,SAAS,OAAO;AAAA,IACzC;AACA,OAAG,iBAAiB,SAAS,OAAO;AACpC,WAAO,MAAM,0BAA0B,QAAQ,EAAE;AACjD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,aAAa,YAAa;AACrC,MAAI,OAAO,EAAG;AACd,SAAO,iBAAiB,oBAAoB,MAAM,OAAO,GAAG,EAAE,MAAM,KAAK,CAAC;AAC5E;;;ACtLA,IAAM,kBAA8E;AAAA,EAClF,aAAa;AAAA,IACX,YAAY;AAAA,EACd;AAAA,EACA,YAAY;AAAA,IACV,YAAY;AAAA,EACd;AACF;AAGO,SAAS,mBAAmB,SAA8D;AAC/F,SAAO,gBAAgB,WAAW,YAAY;AAChD;;;ACCO,SAAS,gBAAgB,MAAsC;AACpE,QAAM,MAAM,KAAK,QAAQ,gBAAgB,QAAQ;AACjD,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,MAAM,sDAAsD,OAAO;AACzE,QAAM,MAAM,KAAK,UAAU,KAAK,QAAQ;AACxC,QAAM,MAAM,KAAK,UAAU,KAAK,SAAS;AACzC,QAAM,cAAc,KAAK,UAAU,KAAK,WAAW,CAAC,CAAC;AACrD,QAAM,WAAW,KAAK,UAAU,KAAK,YAAY,CAAC,CAAC;AAEnD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sDAgB6C,GAAG;AAAA,6CACZ,GAAG,KAAK,GAAG,KAAK,WAAW,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kDAgBnC,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQrE;;;AC/BO,IAAM,2BAAN,MAAwD;AAAA,EAM7D,YAAoB,UAAsC,CAAC,GAAG;AAA1C;AALpB,SAAQ,SAAwB;AAChC,SAAQ,YAAiC;AACzC,SAAQ,kBAAiC;AACzC,SAAQ,iBAAiB;AAAA,EAEsC;AAAA,EAE/D,OAAa;AAAA,EAEb;AAAA,EAEA,KACE,UACA,WACA,UACA,MACA,SACA,MAAc,cACd,QACA,QACA,WACA,aACM;AACN,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,SAAK,kBAAkB;AACvB,SAAK,iBAAiB;AAEtB,UAAM,EAAE,SAAS,SAAS,IAAI,oBAAoB,UAAU,MAAM,aAAa,MAAM,eAAe,IAAI;AACxG,UAAM,OAAO,gBAAgB,EAAE,UAAU,WAAW,KAAK,SAAS,SAAS,CAAC;AAC5E,QAAI,KAAK,QAAQ,QAAQ;AACvB,WAAK,QAAQ,OAAO,EAAE,UAAU,WAAW,KAAK,CAAC;AAAA,IACnD,OAAO;AACL,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAa;AACX,SAAK,QAAQ,SAAS;AACtB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,KAAmB;AAC/B,UAAM,WAAW,KAAK;AACtB,QAAI,CAAC,YAAY,CAAC,KAAK,OAAQ;AAE/B,QAAI;AACJ,QAAI;AACF,aAAQ,KAAK,MAAM,GAAG,EAAwB;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAEA,YAAQ,MAAM;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,YAAI,CAAC,KAAK,gBAAgB;AACxB,eAAK,iBAAiB;AACtB,eAAK,OAAO,iBAAiB,UAAU,EAAE,QAAQ,UAAU,CAAC;AAAA,QAC9D;AACA;AAAA,MACF,KAAK;AACH,aAAK,OAAO,oBAAoB,QAAQ;AACxC,aAAK,YAAY;AACjB;AAAA,MACF,KAAK;AACH,aAAK,YAAY;AACjB;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF;AACF;AAGO,SAAS,mBAA4B;AAE1C,SAAO,OAAO,cAAc,eAAgB,UAAkB,YAAY;AAC5E;AAGO,SAAS,4BAA2C;AACzD,SAAO,IAAI,yBAAyB;AACtC;;;AC1GO,IAAM,oBAAN,MAAiD;AAAA,EACtD,OAAa;AAAA,EAAc;AAAA,EAC3B,OAAa;AAAA,EAAc;AAC7B;AAGO,IAAM,uBAAN,MAAoD;AAAA,EAApD;AACL,SAAQ,YAAgC;AACxC,SAAQ,UAAU;AAAA;AAAA,EAElB,OAAa;AACX,QAAI,OAAO,aAAa,YAAa;AACrC,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,WAAK,UAAU,KAAK;AACpB,WAAK,UAAU,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYjC;AACA,QAAI,CAAC,SAAS,KAAK,SAAS,KAAK,SAAS,GAAG;AAC3C,eAAS,KAAK,YAAY,KAAK,SAAS;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,KACE,UACA,WACA,SACA,MACA,SACA,MAAc,cACd,QACA,OACA,WACA,aACM;AACN,QAAI,KAAK,QAAS;AAClB,QAAI,CAAC,KAAK,aAAa,CAAC,SAAS,KAAK,SAAS,KAAK,SAAS,EAAG,MAAK,KAAK;AAC1E,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,UAAU;AACf,UAAM,YAAY,KAAK;AACvB,SAAK,OAAO,4BAAmB,EAAE,KAAK,CAAC,EAAE,YAAY,MAAM;AACzD,kBAAY,WAAW,UAAU,WAAW,SAAS,MAAM,SAAS,KAAK,QAAQ,OAAO,WAAW,WAAW;AAAA,IAChH,CAAC;AAAA,EACH;AAAA,EAEA,OAAa;AACX,SAAK,UAAU;AACf,QAAI,KAAK,WAAW;AAClB,WAAK,UAAU,MAAM,UAAU;AAC/B,WAAK,UAAU,YAAY;AAAA,IAC7B;AAAA,EACF;AACF;AAGO,SAAS,wBAAuC;AACrD,MAAI,OAAO,aAAa,aAAa;AAEnC,QAAI,iBAAiB,EAAG,QAAO,0BAA0B;AACzD,WAAO,IAAI,kBAAkB;AAAA,EAC/B;AAEA,MAAI,iBAAiB,EAAG,QAAO,0BAA0B;AACzD,SAAO,IAAI,qBAAqB;AAClC;;;ACrDO,IAAM,aAA4B,CAAC,YAAY;AAEpD,UAAQ;AAAA,IACN;AAAA,IACA,KAAK,UAAU,SAAS,MAAM,CAAC;AAAA,EACjC;AACF;AAYO,IAAM,mBAAN,MAAuB;AAAA,EAa5B,YAAY,UAAmC,CAAC,GAAG;AALnD,SAAQ,SAA2B,CAAC;AACpC,SAAQ,aAAqC,CAAC;AAC9C,SAAQ,cAA6B;AACrC,SAAQ,uBAAuB;AAG7B,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,IAAI;AAC1C,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AACxB,SAAK,SAAS,QAAQ;AACtB,SAAK,WAAW,QAAQ,YAAY;AAAA,EACtC;AAAA;AAAA,EAGA,kBAAkB,OAAwD;AACxE,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC1C,UAAI,CAAC,EAAG;AACR,WAAK,WAAW,CAAC,IAAI,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,MAAc,gBAA+B;AAC5D,SAAK,cAAc;AACnB,SAAK,uBAAuB,KAAK,IAAI;AACrC,SAAK,MAAM,sBAAsB,EAAE,kBAAkB,kBAAkB,KAAK,CAAC;AAAA,EAC/E;AAAA;AAAA,EAGA,kBAAwB;AACtB,UAAM,OAAO,KAAK;AAClB,QAAI,QAAQ,KAAM;AAClB,UAAM,kBAAkB,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,wBAAwB,GAAI,CAAC;AAC/F,SAAK,cAAc;AACnB,SAAK,MAAM,qBAAqB,EAAE,cAAc,MAAM,kBAAkB,gBAAgB,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,MAAM,MAAc,QAAwC;AAC1D,UAAM,SAAkC;AAAA,MACtC,GAAI,KAAK,cAAc,EAAE,cAAc,KAAK,YAAY,IAAI,CAAC;AAAA,MAC7D,GAAI,UAAU,CAAC;AAAA,IACjB;AACA,SAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ,OAAO,KAAK,MAAM,EAAE,SAAS,SAAS;AAAA,IAChD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,iBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,UAAkB;AAChB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA,EAGA,aAAa,UAAgD;AAC3D,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,QAAQ,SAAS;AAAA,MACjB,WAAW,SAAS;AAAA,MACpB,SAAS;AAAA,QACP,UAAU,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,YAAY,EAAE,GAAG,KAAK,WAAW;AAAA,MACnC;AAAA,MACA,QAAQ,CAAC,GAAG,KAAK,MAAM;AAAA,IACzB;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAuD;AAC3D,QAAI,KAAK,OAAO,WAAW,EAAG,QAAO;AACrC,UAAM,UAAU,KAAK,aAAa,QAAQ;AAC1C,SAAK,KAAK,OAAO;AACjB,SAAK,SAAS,CAAC;AACf,WAAO;AAAA,EACT;AACF;;;ACjHA,SAAS,OAAO,MAAoB,KAAa,OAAsB;AACrE,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI;AAC3D,OAAK,KAAK,EAAE,KAAK,OAAO,OAAO,KAAK,EAAE,CAAC;AACzC;AAEO,SAAS,2BACd,UACA,MACA,mBACuB;AACvB,QAAM,EAAE,QAAQ,IAAI;AAEpB,QAAM,UAAwB,SAAS,OAAO,IAAI,CAAC,OAAO;AAAA,IACxD,KAAK,EAAE;AAAA,IACP,OAAO,KAAK,UAAU,EAAE,WAAW,EAAE,WAAW,GAAI,EAAE,UAAU,CAAC,EAAG,CAAC;AAAA,EACvE,EAAE;AAEF,QAAM,UAAwB,CAAC;AAC/B,SAAO,SAAS,oBAAoB,SAAS,MAAM;AAEnD,QAAM,WAAyB,CAAC;AAChC,SAAO,UAAU,WAAW,SAAS,MAAM;AAC3C,SAAO,UAAU,cAAc,SAAS,SAAS;AACjD,SAAO,UAAU,YAAY,QAAQ,QAAQ;AAC7C,SAAO,UAAU,YAAY,QAAQ,QAAQ;AAC7C,MAAI,QAAQ,QAAQ;AAClB,WAAO,UAAU,eAAe,QAAQ,OAAO,WAAW;AAC1D,WAAO,UAAU,cAAc,QAAQ,OAAO,UAAU;AACxD,WAAO,UAAU,gBAAgB,QAAQ,OAAO,YAAY;AAC5D,WAAO,UAAU,eAAe,QAAQ,OAAO,WAAW;AAC1D,WAAO,UAAU,cAAc,QAAQ,OAAO,UAAU;AAAA,EAC1D;AACA,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,cAAc,CAAC,CAAC,GAAG;AAC7D,WAAO,UAAU,GAAG,CAAC;AAAA,EACvB;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,aAAa,KAAK;AAAA,IAClB,WAAW;AAAA;AAAA,IAEX,GAAI,oBAAoB,EAAE,WAAW,kBAAkB,IAAI,CAAC;AAAA,EAC9D;AACF;AAmBO,SAAS,mBAAmB,SAA6C;AAC9E,MAAI;AAEJ,SAAO,CAAC,aAAgC;AACtC,UAAM,OAAO,2BAA2B,UAAU,QAAQ,MAAM,iBAAiB;AACjF,UAAM,IAAI,QAAQ,cAAc,OAAO,UAAU,cAAc,QAAQ;AACvE,QAAI,CAAC,GAAG;AACN,cAAQ,MAAM,+DAA+D,IAAI;AACjF;AAAA,IACF;AACA,YAAQ,MAAM,iDAA4C,IAAI;AAC9D,MAAE,GAAG,QAAQ,OAAO,iBAAiB;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC,EACE,KAAK,OAAO,QAAQ;AACnB,UAAI,IAAI,IAAI;AACV,YAAI;AACF,gBAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,cAAI,MAAM,aAAa,KAAK,cAAc,mBAAmB;AAC3D,gCAAoB,KAAK;AACzB,oBAAQ,MAAM,mDAAmD,iBAAiB;AAAA,UACpF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,CAAC,QAAQ,QAAQ,MAAM,+CAA+C,GAAG,CAAC;AAAA,EACrF;AACF;;;AC7HA,IAAM,cAAc;AAGb,SAAS,gBAAgB,MAAsB;AACpD,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,MAAM,uBAAuB;AAC/C,kBAAc,EAAE,YAAY,EAAE,QAAQ;AAAA,EACxC,QAAQ;AACN,kBAAc;AAAA,EAChB;AAEA,gBAAc,YAAY,QAAQ,YAAY,EAAE;AAChD,QAAM,YAAY,YACf,MAAM,GAAG,EACT,IAAI,CAAC,QAAS,WAAW,KAAK,GAAG,KAAK,YAAY,KAAK,GAAG,IAAI,QAAQ,GAAI,EAC1E,KAAK,GAAG;AACX,SAAO,aAAa;AACtB;AAMO,IAAM,qBAAN,MAAyB;AAAA,EAQ9B,YAAY,UAAqC,CAAC,GAAG;AANrD,SAAQ,YAAY,oBAAI,IAAmB;AAC3C,SAAQ,gBAA+B;AACvC,SAAQ,UAAU;AAClB,SAAQ,YAAY;AACpB,SAAQ,cAAiC,CAAC;AAGxC,SAAK,MAAM,QAAQ,QAAQ,MAAM,KAAK,IAAI;AAAA,EAC5C;AAAA,EAEA,QAAQ,UAA+B;AACrC,SAAK,UAAU,IAAI,QAAQ;AAAA,EAC7B;AAAA;AAAA,EAGA,MAAM,MAAoB;AACxB,SAAK,gBAAgB,gBAAgB,IAAI;AACzC,SAAK,UAAU,KAAK,IAAI;AAAA,EAC1B;AAAA;AAAA,EAGA,MAAM,MAAoB;AACxB,UAAM,OAAO,gBAAgB,IAAI;AACjC,QAAI,SAAS,KAAK,cAAe;AACjC,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,UAAU,KAAK,IAAI;AAAA,EAC1B;AAAA;AAAA,EAGA,OAAa;AACX,SAAK,aAAa;AAClB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,eAAqB;AAC3B,QAAI,KAAK,iBAAiB,KAAM;AAChC,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,QAAqB;AAAA,MACzB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,iBAAiB,KAAK,IAAI,GAAG,KAAK,OAAO,OAAO,KAAK,WAAW,GAAI,CAAC;AAAA,IACvE;AACA,SAAK,UAAU,QAAQ,CAAC,MAAM;AAC5B,UAAI;AACF,UAAE,KAAK;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,UAAgB;AACd,QAAI,KAAK,aAAa,OAAO,WAAW,eAAe,OAAO,YAAY,YAAa;AACvF,SAAK,YAAY;AAEjB,UAAM,SAAS,MAAM,KAAK,MAAM,OAAO,SAAS,IAAI;AAEpD,UAAM,eAAe,QAAQ,UAAU,KAAK,OAAO;AACnD,UAAM,kBAAkB,QAAQ,aAAa,KAAK,OAAO;AACzD,YAAQ,YAAY,CAAC,MAAe,QAAgB,QAA8B;AAChF,YAAM,IAAI,aAAa,MAAe,QAAQ,GAAY;AAC1D,aAAO;AACP,aAAO;AAAA,IACT;AACA,YAAQ,eAAe,CAAC,MAAe,QAAgB,QAA8B;AACnF,YAAM,IAAI,gBAAgB,MAAe,QAAQ,GAAY;AAC7D,aAAO;AACP,aAAO;AAAA,IACT;AACA,WAAO,iBAAiB,YAAY,MAAM;AAC1C,WAAO,iBAAiB,cAAc,MAAM;AAE5C,SAAK,YAAY,KAAK,MAAM;AAC1B,cAAQ,YAAY;AACpB,cAAQ,eAAe;AACvB,aAAO,oBAAoB,YAAY,MAAM;AAC7C,aAAO,oBAAoB,cAAc,MAAM;AAAA,IACjD,CAAC;AAED,SAAK,MAAM,OAAO,SAAS,IAAI;AAAA,EACjC;AAAA,EAEA,YAAkB;AAChB,SAAK,YAAY,QAAQ,CAAC,QAAQ,IAAI,CAAC;AACvC,SAAK,cAAc,CAAC;AACpB,SAAK,YAAY;AAAA,EACnB;AACF;;;ACxHO,SAAS,gBAAgB,IAA6C;AAC3E,QAAM,KAAK,MAAM,IAAI,YAAY;AACjC,MAAI,4BAA4B,KAAK,CAAC,KAAM,UAAU,KAAK,CAAC,KAAK,CAAC,SAAS,KAAK,CAAC,GAAI;AACnF,WAAO;AAAA,EACT;AACA,MAAI,iCAAiC,KAAK,CAAC,KAAM,UAAU,KAAK,CAAC,KAAK,SAAS,KAAK,CAAC,GAAI;AACvF,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,YAAiC;AACjE,QAAM,KAAK,OAAO,cAAc,cAAc,UAAU,YAAY;AACpE,SAAO;AAAA,IACL,aAAa,gBAAgB,EAAE;AAAA,IAC/B,YAAY,MAAM;AAAA,IAClB,aAAa;AAAA,EACf;AACF;;;AC5BO,IAAM,oBAAN,MAAwB;AAAA,EAK7B,YAAY,MAAoB,MAAM,KAAK,IAAI,GAAG;AAHlD,SAAQ,WAAW;AACnB,SAAQ,eAA8B;AAGpC,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAGA,SAAe;AACb,QAAI,KAAK,iBAAiB,KAAM,MAAK,eAAe,KAAK,IAAI;AAAA,EAC/D;AAAA;AAAA,EAGA,QAAc;AACZ,QAAI,KAAK,iBAAiB,MAAM;AAC9B,WAAK,YAAY,KAAK,IAAI,IAAI,KAAK;AACnC,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA;AAAA,EAGA,UAAkB;AAChB,QAAI,KAAK,iBAAiB,MAAM;AAC9B,YAAM,IAAI,KAAK,IAAI;AACnB,WAAK,YAAY,IAAI,KAAK;AAC1B,WAAK,eAAe;AAAA,IACtB;AACA,UAAM,KAAK,KAAK;AAChB,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AACF;;;ACrBA,SAAS,gBAAgB,OAAkC;AACzD,QAAM,SAA4B,CAAC;AACnC,aAAW,OAAO,OAAO,KAAK,KAAK,EAAE,KAAK,GAAG;AAC3C,WAAO,GAAG,IAAI,MAAM,GAAG;AAAA,EACzB;AACA,SAAO,KAAK,UAAU,MAAM;AAC9B;AAOO,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YAAY,SAAgC;AAC1C,SAAK,UAAU,QAAQ;AACvB,SAAK,YAAY,QAAQ;AACzB,SAAK,SAAS,QAAQ;AACtB,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,YAAiD;AACnE,UAAM,aAAa,gBAAgB,UAAU;AAC7C,UAAM,OAAO,KAAK,QAAQ,QAAQ,aAAa,iBAAiB;AAChE,QAAI,SAAS,WAAY,QAAO;AAEhC,UAAM,KAAK,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,gBAAgB;AAAA,IAClB,CAAC;AACD,SAAK,QAAQ,QAAQ,aAAa,mBAAmB,UAAU;AAC/D,WAAO;AAAA,EACT;AACF;;;ACtCA,IAAM,yBAAyB;AAC/B,IAAM,YAAY,KAAK,KAAK,KAAK;AA0B1B,IAAM,iBAAN,MAAqB;AAAA,EAArB;AACH,SAAQ,SAAgC;AACxC,SAAQ,YAAwD,oBAAI,IAAI;AACxE,SAAQ,WAA4B,CAAC;AACrC,SAAQ,cAAc;AACtB,SAAQ,WAA0B,sBAAsB;AACxD,SAAQ,iBAAqC;AAC7C;AAAA,SAAQ,mBAAgD,CAAC;AACzD,SAAQ,eAAe;AACvB,SAAQ,oBAAoB;AAE5B,SAAQ,kBAA+B,oBAAI,IAAI;AAC/C,SAAQ,iBAAkD,oBAAI,IAAI;AAClE,SAAQ,YAAiC,oBAAI,IAAI;AACjD;AAAA,SAAQ,kBAAuC,oBAAI,IAAI;AACvD;AAAA,SAAQ,qBAA+B,CAAC;AAExC,SAAQ,UAAkB;AAC1B,SAAQ,MAAoC;AAG5C;AAAA,SAAQ,WAAmC;AAE3C;AAAA,SAAQ,YAAqC;AAE7C;AAAA,SAAQ,cAAyC;AAEjD;AAAA,SAAQ,aAAuC;AAE/C;AAAA,SAAQ,UAAiC;AAEzC;AAAA,SAAQ,aAAa;AAAA;AAAA;AAAA,EAGrB,KAAK,QAAkC;AACnC,QAAI,KAAK,aAAa;AAClB,WAAK,IAAI,yBAAyB;AAClC;AAAA,IACJ;AAEA,UAAM,MAAM,mBAAmB,OAAO,OAAO;AAE7C,SAAK,UAAU,IAAI;AACnB,SAAK,MAAM,OAAO,WAAW;AAE7B,SAAK,SAAS;AAAA,MACV,QAAQ,OAAO,UAAU;AAAA,MACzB,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,IAC7B;AAIA,UAAM,UAAU,OAAO,WAAW,qBAAqB;AACvD,SAAK,WAAW,IAAI,gBAAgB;AAAA,MAChC;AAAA,MACA,cAAc,KAAK,OAAO;AAAA,MAC1B,SAAS,OAAO,mBAAmB;AAAA,IACvC,CAAC;AAID,QAAI,KAAK,OAAO,QAAQ;AACpB,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,YAAY,KAAK,OAAO,UAAU;AACxC,WAAK,UAAU,IAAI,eAAe;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,CAAC,SAAS,KAAK,YAAY,IAAI;AAAA,MACzC,CAAC;AAED,UAAI,OAAO,mBAAmB;AAC1B,aAAK,KAAK,qBAAqB,OAAO,iBAAiB;AAAA,MAC3D;AAAA,IACJ;AACA,SAAK,IAAI,0BAAuB,KAAK,SAAS,UAAU,GAAG,kBAAe,KAAK,SAAS,UAAU,GAAG,iBAAc,KAAK,SAAS,kBAAkB,CAAC;AAIpJ,UAAM,gBAAgB,OAAO,YACvB,mBAAmB;AAAA,MACf,SAAS,KAAK;AAAA,MACd,MAAM,OAAO;AAAA,MACb,KAAK,IAAI,MAAM,KAAK,IAAI,GAAG,CAAC;AAAA,IAChC,CAAC,IACD;AACN,SAAK,YAAY,IAAI,iBAAiB;AAAA,MAClC,MAAM;AAAA,MACN,WAAW,OAAO,WAAW,aAAa,KAAK,OAAO;AAAA,MACtD,UAAU,OAAO,cAAc,cAAc,UAAU,WAAW;AAAA,MAClE,UAAU,OAAO,YAAY;AAAA,MAC7B,QAAQ,OAAO,UAAU,kBAAkB,OAAO,UAAU;AAAA,IAChE,CAAC;AAED,SAAK,cAAc,IAAI,mBAAmB;AAC1C,SAAK,YAAY,QAAQ,CAAC,MAAM,KAAK,MAAM,aAAa,EAAE,QAAQ,EAAE,QAAQ,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;AAClH,SAAK,YAAY,QAAQ;AAEzB,SAAK,aAAa,IAAI,kBAAkB;AACxC,SAAK,WAAW,OAAO;AACvB,SAAK,oBAAoB;AAEzB,SAAK,cAAc;AACnB,SAAK,IAAI,mBAAmB,KAAK,MAAM;AACvC,QAAI,KAAK,SAAS,KAAM,MAAK,SAAS,KAAK;AAC3C,SAAK,oBAAoB;AAGzB,SAAK,sBAAsB,EAAE,KAAK,CAAC,SAAS;AACxC,WAAK,mBAAmB,KAAK,yBAAyB,IAAI;AAC1D,WAAK,eAAe;AACpB,WAAK,IAAI,0BAA0B,KAAK,gBAAgB;AACxD,WAAK,iCAAiC;AACtC,WAAK,yBAAyB;AAC9B,UAAI,KAAK,mBAAmB;AACxB,aAAK,cAAc;AAAA,MACvB;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,YAA2B;AACvB,WAAO,KAAK,UAAU,UAAU,KAAK;AAAA,EACzC;AAAA;AAAA,EAGA,eAA8B;AAC1B,WAAO,KAAK,UAAU,aAAa,KAAK;AAAA,EAC5C;AAAA;AAAA,EAGA,mBAAmB,SAAwB;AACvC,SAAK,UAAU,mBAAmB,OAAO;AACzC,SAAK,IAAI,qCAAkC,SAAS,oBAAiB,KAAK,UAAU,aAAa,KAAK,IAAI;AAAA,EAC9G;AAAA;AAAA;AAAA,EAKA,MAAM,MAAc,QAAwC;AACxD,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,SAAK,WAAW,MAAM,MAAM,MAAM;AAClC,SAAK,IAAI,yBAAsB,MAAM,UAAU,CAAC,CAAC;AAAA,EACrD;AAAA;AAAA,EAGA,kBAAkB,YAA6D;AAC3E,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,SAAK,WAAW,kBAAkB,UAAU;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,YAAiD;AACxE,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG,QAAO;AAChD,QAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,WAAO,KAAK,QAAQ,cAAc,UAAU;AAAA,EAChD;AAAA;AAAA,EAGA,iBAAiB,MAAc,gBAA+B;AAC1D,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,SAAK,WAAW,iBAAiB,MAAM,cAAc;AACrD,SAAK,IAAI,oCAAiC,MAAM,kBAAkB,EAAE;AAAA,EACxE;AAAA;AAAA,EAGA,kBAAwB;AACpB,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,SAAK,WAAW,gBAAgB;AAChC,SAAK,IAAI,gCAA6B;AAAA,EAC1C;AAAA;AAAA,EAGA,YAAY,OAAe,cAAsB,QAAwC;AACrF,SAAK,MAAM,UAAU,EAAE,OAAO,eAAe,cAAc,aAAa,eAAe,GAAG,GAAI,UAAU,CAAC,EAAG,CAAC;AAAA,EACjH;AAAA;AAAA,EAGA,yBAAyB,eAAuB,QAAwC;AACpF,SAAK,MAAM,wBAAwB,EAAE,gBAAgB,eAAe,GAAI,UAAU,CAAC,EAAG,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,gBAAgB,QAAgB,MAAc,QAAgB,QAAwC;AAClG,SAAK,MAAM,eAAe,EAAE,QAAQ,MAAM,SAAS,QAAQ,GAAI,UAAU,CAAC,EAAG,CAAC;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAoB;AAC1B,QAAI,CAAC,KAAK,YAAa;AACvB,QAAI,CAAC,KAAK,YAAY;AAClB,WAAK,YAAY,MAAM,IAAI;AAC3B,WAAK,aAAa;AAAA,IACtB,OAAO;AACH,WAAK,YAAY,MAAM,IAAI;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA,EAGA,eAAqB;AACjB,SAAK,YAAY,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAqB;AACjB,SAAK,aAAa,KAAK;AACvB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,YAAY,MAAM;AACvB,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA,EAGA,mBAAsC;AAClC,WACI,KAAK,WAAW,aAAa,KAAK,kBAAkB,CAAC,KAAK;AAAA,MACtD,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS,EAAE,UAAU,OAAO,YAAY,CAAC,EAAE;AAAA,MAC3C,QAAQ,CAAC;AAAA,IACb;AAAA,EAER;AAAA;AAAA,EAGA,iBAAuB;AACnB,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,SAAK,WAAW,MAAM,KAAK,kBAAkB,CAAC;AAAA,EAClD;AAAA;AAAA,EAGQ,kBAAwB;AAC5B,QAAI,CAAC,KAAK,UAAU,kBAAkB,EAAG;AACzC,UAAM,KAAK,KAAK,YAAY,QAAQ,KAAK;AACzC,QAAI,KAAK,EAAG,MAAK,MAAM,mBAAmB,EAAE,sBAAsB,GAAG,CAAC;AAAA,EAC1E;AAAA,EAEQ,oBAAoB;AACxB,WAAO;AAAA,MACH,QAAQ,KAAK,UAAU,UAAU,KAAK;AAAA,MACtC,WAAW,KAAK,UAAU,aAAa,KAAK;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA,EAGQ,sBAA4B;AAChC,QAAI,OAAO,aAAa,eAAe,OAAO,WAAW,YAAa;AAEtE,WAAO,iBAAiB,YAAY,MAAM;AACtC,WAAK,aAAa,KAAK;AACvB,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AACrB,WAAK,eAAe;AAAA,IACxB,CAAC;AAED,aAAS,iBAAiB,oBAAoB,MAAM;AAChD,UAAI,SAAS,oBAAoB,UAAU;AACvC,aAAK,gBAAgB;AACrB,aAAK,YAAY,MAAM;AACvB,aAAK,eAAe;AAAA,MACxB,WAAW,SAAS,oBAAoB,WAAW;AAC/C,aAAK,YAAY,OAAO;AAAA,MAC5B;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,aAAmB;AACf,QAAI,CAAC,KAAK,aAAa;AACnB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC7D;AACA,QAAI,CAAC,KAAK,cAAc;AACpB,WAAK,oBAAoB;AACzB,WAAK,IAAI,8CAA8C;AACvD;AAAA,IACJ;AACA,SAAK,cAAc;AAAA,EACvB;AAAA;AAAA,EAGQ,gBAAsB;AAC1B,SAAK,IAAI,qBAAqB;AAC9B,SAAK,SAAS,QAAQ,CAAC,YAAY,aAAa,MAAM,OAAO,CAAC;AAAA,EAClE;AAAA;AAAA,EAGA,kBAAkB,UAAiC;AAC/C,QAAI,CAAC,KAAK,aAAa;AACnB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC7D;AACA,SAAK,WAAW;AAChB,SAAK,IAAI,uBAAuB,QAAQ;AAAA,EAC5C;AAAA;AAAA,EAGQ,mCAAyC;AAC7C,UAAM,UAA2B,CAAC;AAClC,SAAK,MAAM,+BAA+B,KAAK,gBAAgB;AAE/D,SAAK,iBAAiB,QAAQ,CAAC,QAAQ;AACnC,UAAI,SAAS,QAAQ,CAAC,YAAY;AAC9B,cAAM,OAAO,KAAK,oBAAoB,QAAQ,IAAI;AAClD,YAAI,CAAC,MAAM;AACP,eAAK,MAAM,4BAA4B,QAAQ,IAAI;AACnD;AAAA,QACJ;AACA,cAAM,QAAQ,SAAS,UAAU,OAAO,QAAQ,UAAU,WACpD,QAAQ,QAAQ,MAChB,QAAQ;AACd,gBAAQ,KAAK,EAAE,MAAM,OAAO,UAAU,IAAI,UAAU,SAAS,IAAI,GAAG,CAAC;AAAA,MACzE,CAAC;AAAA,IACL,CAAC;AAED,QAAI,QAAQ,QAAQ;AAChB,WAAK,kBAAkB,OAAO;AAAA,IAClC;AAAA,EACJ;AAAA;AAAA,EAGA,cAAc,UAAkB,SAAwB;AACpD,UAAM,MAAM,KAAK,oBAAoB,UAAU,OAAO;AACtD,QAAI,CAAC,KAAK;AACN,WAAK,MAAM,mCAAmC,EAAE,UAAU,QAAQ,CAAC;AACnE;AAAA,IACJ;AACA,QAAI,CAAC,KAAK,WAAW,GAAG,GAAG;AACvB,WAAK,MAAM,sCAAsC,IAAI,EAAE;AACvD;AAAA,IACJ;AACA,SAAK,eAAe,GAAG;AAAA,EAC3B;AAAA;AAAA,EAGO,aAAa,WAAyB;AACzC,QAAI,CAAC,KAAK,aAAa;AACnB,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC7D;AACA,UAAM,aAAa,OAAO,aAAa,EAAE,EAAE,KAAK;AAChD,QAAI,CAAC,YAAY;AACb,WAAK,MAAM,mCAAmC;AAC9C;AAAA,IACJ;AAEA,UAAM,aAAa,KAAK,iBAAiB,OAAO,CAAC,QAAQ;AACrD,aAAO,IAAI,SAAS,KAAK,CAAC,YAAY;AAClC,cAAM,eAAe,OAAO,QAAQ,SAAS,EAAE,EAAE,KAAK;AACtD,eAAO,QAAQ,SAAS,WAAW,iBAAiB;AAAA,MACxD,CAAC;AAAA,IACL,CAAC;AAED,QAAI,CAAC,WAAW,QAAQ;AACpB,WAAK,MAAM,oCAAoC,EAAE,WAAW,WAAW,CAAC;AACxE;AAAA,IACJ;AAEA,UAAM,UAAU,WAAW,KAAK,CAAC,QAAQ,KAAK,WAAW,GAAG,CAAC;AAC7D,QAAI,CAAC,SAAS;AACV,WAAK,MAAM,8CAA8C,EAAE,WAAW,WAAW,CAAC;AAClF;AAAA,IACJ;AAEA,SAAK,eAAe,OAAO;AAAA,EAC/B;AAAA,EAEQ,eAAe,KAA4B;AAC/C,SAAK,IAAI,8BAA8B,GAAG;AAC1C,SAAK,gBAAgB,IAAI,IAAI,UAAU,IAAI,EAAE;AAC7C,SAAK,UAAU,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;AACrC,SAAK,YAAY,IAAI,UAAU,IAAI,WAAW,IAAI,SAAS,IAAI,KAAK;AACpE,SAAK,UAAU,eAAe,IAAI,UAAU,EAAE,SAAS,IAAI,GAAG,CAAC;AAAA,EACnE;AAAA,EAEQ,WAAW,KAAgC,SAAkB,gBAAgB,OAAgB;AACjG,QAAI,CAAC,iBAAiB,CAAC,KAAK,oBAAoB,KAAK,OAAO,GAAG;AAC3D,aAAO;AAAA,IACX;AACA,QAAI,CAAC,KAAK,oBAAoB,GAAG,GAAG;AAChC,aAAO;AAAA,IACX;AAEA,UAAM,YAAY,IAAI,YAAY,CAAC;AACnC,QAAI,UAAU,UAAU,CAAC,UAAU,MAAM,CAAC,aAAa,KAAK,iBAAiB,KAAK,QAAQ,CAAC,GAAG;AAC1F,aAAO;AAAA,IACX;AAEA,UAAM,mBAAmB,IAAI,oBAAoB,CAAC;AAClD,QAAI,CAAC,iBAAiB,OAAQ,QAAO;AACrC,WAAO,iBAAiB,MAAM,CAAC,cAAc,KAAK,wBAAwB,KAAK,SAAS,CAAC;AAAA,EAC7F;AAAA,EAEQ,oBAAoB,KAA+B;AACvD,UAAM,QAAQ,IAAI,UAAU;AAC5B,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AAGzC,UAAM,eACF,OAAO,cAAc,cAAc,UAAU,WAAW,IAC1D,YAAY;AAEd,QAAI,CAAC,aAAa;AACd,WAAK,MAAM,uDAAuD,EAAE,SAAS,IAAI,IAAI,MAAM,CAAC;AAC5F,aAAO;AAAA,IACX;AAIA,UAAM,UAAU,MAAM,KAAK,CAAC,SAAS,YAAY,WAAW,KAAK,YAAY,CAAC,CAAC;AAC/E,QAAI,CAAC,SAAS;AACV,WAAK,MAAM,2BAA2B,EAAE,SAAS,IAAI,IAAI,OAAO,YAAY,CAAC;AAAA,IACjF;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,oBAAoB,KAAsB,SAA2B;AACzE,UAAM,QAAQ,IAAI,UAAU;AAC5B,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,QAAI,OAAO,WAAW,eAAe,CAAC,OAAO,UAAU;AACnD,WAAK,MAAM,oDAAoD,EAAE,SAAS,IAAI,IAAI,MAAM,CAAC;AACzF,aAAO;AAAA,IACX;AAEA,UAAM,iBAAiB,KAAK,aAAa,WAAW,OAAO,SAAS,QAAQ,EAAE;AAC9E,UAAM,aAAa,KAAK,aAAa,cAAc;AACnD,UAAM,iBAAiB,KAAK,aAAa,YAAY,YAAY,OAAO,SAAS,YAAY,EAAE;AAE/F,UAAM,UAAU,MAAM,KAAK,CAAC,iBAAiB;AACzC,YAAM,YAAY,KAAK,aAAa,YAAY;AAChD,UAAI,QAAQ;AACZ,UAAI,UAAU,WAAW,SAAS,KAAK,UAAU,WAAW,UAAU,GAAG;AACrE,gBAAQ,mBAAmB;AAAA,MAC/B,WAAW,UAAU,WAAW,GAAG,GAAG;AAClC,gBAAQ,eAAe,SAAS,SAAS;AAAA,MAC7C,OAAO;AACH,gBAAQ,mBAAmB;AAAA,MAC/B;AACA,WAAK,MAAM,mBAAmB;AAAA,QAC1B,SAAS,IAAI;AAAA,QACb;AAAA,QACA,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,MACJ,CAAC;AACD,aAAO;AAAA,IACX,CAAC;AAED,QAAI,CAAC,SAAS;AACV,WAAK,MAAM,2BAA2B,EAAE,SAAS,IAAI,IAAI,OAAO,aAAa,eAAe,CAAC;AAAA,IACjG;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,iBAAiB,KAAsB,WAA2C;AACtF,YAAQ,UAAU,UAAU;AAAA,MACxB,KAAK;AACD,eAAO,KAAK,mBAAmB,KAAK,UAAU,IAAI,IAAI,EAAE,GAAG,UAAU,YAAY;AAAA,MACrF,KAAK;AAAA,MACL,KAAK,aAAa;AACd,cAAM,WAAW,KAAK,eAAe,IAAI,IAAI,QAAQ;AACrD,YAAI,CAAC,YAAY,SAAS,WAAW,UAAU,UAAU;AACrD,iBAAO;AAAA,QACX;AACA,eAAO,KAAK,mBAAmB,SAAS,WAAW,UAAU,YAAY;AAAA,MAC7E;AAAA,MACA;AACI,eAAO;AAAA,IACf;AAAA,EACJ;AAAA,EAEQ,wBAAwB,KAAsB,WAAiD;AACnG,QAAI,CAAC,UAAU,YAAY,KAAK,gBAAgB,IAAI,IAAI,QAAQ,GAAG;AAC/D,aAAO;AAAA,IACX;AACA,WAAO,KAAK,mBAAmB,KAAK,UAAU,IAAI,IAAI,EAAE,GAAG,UAAU,YAAY;AAAA,EACrF;AAAA,EAEQ,mBAAmB,WAA+B,cAAgC;AACtF,QAAI,CAAC,aAAa,CAAC,cAAc;AAC7B,aAAO;AAAA,IACX;AACA,WAAO,KAAK,IAAI,IAAI,aAAa,eAAe;AAAA,EACpD;AAAA;AAAA,EAGO,mBAAmB,UAAwB;AAC9C,SAAK,gBAAgB,IAAI,QAAQ;AACjC,SAAK,mBAAmB,UAAU,WAAW;AAAA,EACjD;AAAA;AAAA,EAGO,eAAe,UAAkB,cAAsB,WAAoB,SAAwB;AACtG,UAAM,MAAM,KAAK,oBAAoB,UAAU,OAAO;AACtD,QAAI,CAAC,KAAK;AACN,WAAK,MAAM,wCAAwC,EAAE,UAAU,QAAQ,CAAC;AACxE;AAAA,IACJ;AAEA,UAAM,YAAY,cAAc,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AACvF,QAAI,CAAC,WAAW;AACZ,WAAK,MAAM,0CAA0C,EAAE,SAAS,CAAC;AACjE;AAAA,IACJ;AAEA,QAAI,CAAC,KAAK,WAAW,KAAK,SAAS,GAAG;AAClC,WAAK,MAAM,yCAAyC,EAAE,SAAS,IAAI,IAAI,WAAW,UAAU,CAAC;AAC7F;AAAA,IACJ;AAEA,UAAM,cAAc,OAAO,SAAS,YAAY,IAAI,KAAK,IAAI,GAAG,eAAe,GAAI,IAAI;AACvF,UAAM,WAA8B;AAAA,MAChC,IAAI,IAAI;AAAA,MACR,UAAU,IAAI;AAAA,MACd,WAAW,KAAK,aAAa,SAAS;AAAA,MACtC,OAAO,KAAK,IAAI,IAAI;AAAA,IACxB;AAEA,UAAM,QAAQ,KAAK,qBAAqB,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,OAAO,SAAS,MAAM,KAAK,cAAc,SAAS,UAAU;AAC9H,UAAM,KAAK,QAAQ;AACnB,SAAK,qBAAqB,KAAK;AAC/B,SAAK,0BAA0B,QAAQ;AACvC,SAAK,MAAM,qBAAqB,QAAQ;AAAA,EAC5C;AAAA,EAEQ,2BAAiC;AACrC,UAAM,QAAQ,KAAK,qBAAqB;AACxC,QAAI,CAAC,MAAM,OAAQ;AAEnB,UAAM,UAA+B,CAAC;AACtC,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAQ,CAAC,SAAS;AACpB,YAAM,MAAM,KAAK,iBAAiB,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,MAAM,MAAM,aAAa,KAAK,QAAQ;AAC1G,UAAI,CAAC,KAAK;AACN;AAAA,MACJ;AACA,UAAI,KAAK,SAAS,KAAK;AACnB,aAAK,yBAAyB,IAAI;AAClC;AAAA,MACJ;AACA,cAAQ,KAAK,IAAI;AACjB,WAAK,0BAA0B,IAAI;AAAA,IACvC,CAAC;AACD,SAAK,qBAAqB,OAAO;AAAA,EACrC;AAAA,EAEQ,0BAA0B,MAA+B;AAC7D,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,QAAQ,KAAK,IAAI,CAAC;AACjD,UAAM,QAAQ,OAAO,WAAW,MAAM,KAAK,yBAAyB,IAAI,GAAG,KAAK;AAChF,SAAK,mBAAmB,KAAK,KAAK;AAAA,EACtC;AAAA,EAEQ,yBAAyB,MAA+B;AAC5D,UAAM,MAAM,KAAK,iBAAiB,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,MAAM,MAAM,aAAa,KAAK,QAAQ;AAC1G,QAAI,CAAC,KAAK;AACN,WAAK,wBAAwB,IAAI;AACjC;AAAA,IACJ;AAEA,UAAM,aAAa,OAAO,WAAW,cAAc,KAAK,aAAa,OAAO,SAAS,QAAQ,EAAE,IAAI;AACnG,QAAI,CAAC,cAAc,eAAe,KAAK,aAAa,KAAK,SAAS,GAAG;AACjE,WAAK,wBAAwB,IAAI;AACjC,WAAK,MAAM,mDAAmD,IAAI;AAClE;AAAA,IACJ;AAEA,QAAI,CAAC,KAAK,WAAW,KAAK,QAAW,IAAI,GAAG;AACxC,WAAK,wBAAwB,IAAI;AACjC,WAAK,MAAM,gDAAgD,IAAI;AAC/D;AAAA,IACJ;AAEA,SAAK,eAAe,GAAG;AACvB,SAAK,wBAAwB,IAAI;AAAA,EACrC;AAAA,EAEQ,oBAAoB,UAAkB,SAAyD;AACnG,QAAI,SAAS;AACT,YAAM,OAAO,KAAK,iBAAiB,KAAK,CAAC,UAAU,MAAM,OAAO,OAAO;AACvE,UAAI,KAAM,QAAO;AAAA,IACrB;AACA,WAAO,KAAK,iBAAiB,KAAK,CAAC,UAAU,MAAM,aAAa,QAAQ;AAAA,EAC5E;AAAA,EAEQ,wBAAwB,MAA+B;AAC3D,UAAM,QAAQ,KAAK,qBAAqB,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,KAAK,MAAM,MAAM,cAAc,KAAK,UAAU;AACzH,SAAK,qBAAqB,KAAK;AAAA,EACnC;AAAA,EAEQ,uBAA4C;AAChD,QAAI,OAAO,WAAW,YAAa,QAAO,CAAC;AAC3C,QAAI;AACA,YAAM,MAAM,OAAO,eAAe,QAAQ,sBAAsB;AAChE,UAAI,CAAC,IAAK,QAAO,CAAC;AAClB,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,aAAO,OACF,OAAO,CAAC,UAA+C;AACpD,YAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,cAAM,OAAO;AACb,eAAO,OAAO,KAAK,OAAO,YACnB,OAAO,KAAK,aAAa,YACzB,OAAO,KAAK,cAAc,YAC1B,OAAO,KAAK,UAAU,YACtB,OAAO,SAAS,KAAK,KAAK;AAAA,MACrC,CAAC,EACA,IAAI,CAAC,UAAU;AAAA,QACZ,GAAG;AAAA,QACH,WAAW,KAAK,aAAa,KAAK,SAAS;AAAA,MAC/C,EAAE;AAAA,IACV,QAAQ;AACJ,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;AAAA,EAEQ,qBAAqB,OAAkC;AAC3D,QAAI,OAAO,WAAW,YAAa;AACnC,QAAI;AACA,UAAI,CAAC,MAAM,QAAQ;AACf,eAAO,eAAe,WAAW,sBAAsB;AACvD;AAAA,MACJ;AACA,aAAO,eAAe,QAAQ,wBAAwB,KAAK,UAAU,KAAK,CAAC;AAAA,IAC/E,QAAQ;AAAA,IAER;AAAA,EACJ;AAAA;AAAA,EAGA,MAAc,wBAA4C;AACtD,UAAM,SAAS,KAAK,QAAQ;AAC5B,UAAM,UAAU,KAAK;AACrB,UAAM,SAAS,KAAK,QAAQ;AAC5B,QAAI,CAAC,UAAU,CAAC,SAAS;AACrB,WAAK,IAAI,mDAAmD;AAC5D,aAAO,CAAC;AAAA,IACZ;AACA,UAAM,SAAS,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI;AAChD,UAAM,QAAQ,SAAS,WAAW,mBAAmB,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK;AACjF,UAAM,WAAW,GAAG,OAAO,QAAQ,mBAAmB,MAAM,CAAC,UAAU,KAAK;AAC5E,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,QAAQ;AACrC,UAAI,CAAC,SAAS,IAAI;AACd,aAAK,IAAI,0BAA0B,SAAS,QAAQ,SAAS,UAAU;AACvE,eAAO,CAAC;AAAA,MACZ;AACA,YAAM,MAAM,MAAM,SAAS,KAAK;AAChC,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AACxB,aAAK,IAAI,6BAA6B,MAAM;AAC5C,eAAO,CAAC;AAAA,MACZ;AACA,WAAK,MAAM,0BAA0B,MAAM;AAC3C,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,WAAK,IAAI,yBAAyB,KAAK;AACvC,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA,EAGA,MAAc,YAAY,MAA+F;AACrH,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,QAAS;AACd,UAAM,WAAW,GAAG,OAAO;AAC3B,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,UAAU;AAAA,QACnC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,MAC7B,CAAC;AACD,UAAI,CAAC,SAAS,IAAI;AACd,aAAK,IAAI,0BAA0B,SAAS,QAAQ,SAAS,UAAU;AACvE;AAAA,MACJ;AACA,WAAK,IAAI,0CAAuC,KAAK,MAAM;AAAA,IAC/D,SAAS,OAAO;AACZ,WAAK,IAAI,yBAAyB,KAAK;AAAA,IAC3C;AAAA,EACJ;AAAA;AAAA,EAGA,MAAc,eAAe,QAA4B,SAAiB,QAAgC;AACtG,UAAM,SAAS,KAAK,QAAQ;AAC5B,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,UAAU,CAAC,SAAS;AACrB;AAAA,IACJ;AACA,UAAM,WAAW,GAAG,OAAO;AAC3B,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,UAAU;AAAA,QACnC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACjB,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,QAAQ,UAAU;AAAA,QACtB,CAAC;AAAA,MACL,CAAC;AACD,UAAI,CAAC,SAAS,IAAI;AACd,aAAK,IAAI,8BAA8B,SAAS,QAAQ,SAAS,UAAU;AAC3E;AAAA,MACJ;AAGA,UAAI;AACA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAI,QAAQ,OAAO,KAAK,cAAc,UAAU;AAC5C,eAAK,UAAU,aAAa,KAAK,SAAS;AAC1C,eAAK,IAAI,0CAAuC,KAAK,SAAS;AAAA,QAClE;AAAA,MACJ,QAAQ;AAAA,MAER;AAAA,IACJ,SAAS,OAAO;AACZ,WAAK,IAAI,6BAA6B,KAAK;AAAA,IAC/C;AAAA,EACJ;AAAA;AAAA,EAGA,GAAG,WAA8B,UAA+B;AAC5D,QAAI,CAAC,KAAK,UAAU,IAAI,SAAS,GAAG;AAChC,WAAK,UAAU,IAAI,WAAW,oBAAI,IAAI,CAAC;AAAA,IAC3C;AACA,SAAK,UAAU,IAAI,SAAS,EAAG,IAAI,QAAQ;AAAA,EAC/C;AAAA;AAAA,EAGA,IAAI,WAA8B,UAA+B;AAC7D,UAAM,YAAY,KAAK,UAAU,IAAI,SAAS;AAC9C,QAAI,WAAW;AACX,gBAAU,OAAO,QAAQ;AAAA,IAC7B;AAAA,EACJ;AAAA;AAAA,EAGQ,sBAA4B;AAChC,QAAI,OAAO,aAAa,aAAa;AACjC;AAAA,IACJ;AACA,SAAK,iBAAiB,SAAS,cAAc,KAAK;AAClD,SAAK,eAAe,KAAK;AACzB,SAAK,eAAe,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYpC,aAAS,KAAK,YAAY,KAAK,cAAc;AAAA,EACjD;AAAA;AAAA,EAGQ,YAAY,UAAkB,WAAmB,SAAwB,OAA0B;AACvG,UAAM,SAAS,KAAK,UAAU,UAAU,KAAK,KAAK,QAAQ;AAC1D,UAAM,YAAY,KAAK,UAAU,aAAa,KAAK;AACnD,UAAM,cAAc,KAAK,WAAW,eAAe,KAAK;AACxD,SAAK,IAAI,wCAAgC,EAAE,QAAQ,UAAU,MAAM,WAAW,aAAa,MAAM,aAAa,eAAe,KAAK,CAAC;AACnI,QAAI,KAAK,UAAU;AACf,WAAK,SAAS;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA,CAAC,MAAM,IAAI,YAAY,KAAK,UAAU,MAAM,IAAI,OAAO;AAAA,QACvD,MAAM,KAAK,UAAU;AAAA,QACrB,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AACA;AAAA,IACJ;AAEA,QAAI,CAAC,KAAK,eAAgB;AAC1B,UAAM,YAAY,KAAK;AACvB,SAAK,OAAO,4BAAmB,EAAE,KAAK,CAAC,EAAE,YAAY,MAAM;AACvD;AAAA,QACI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,CAAC,MAAM,IAAI,YAAY,KAAK,UAAU,MAAM,IAAI,OAAO;AAAA,QACvD,MAAM,KAAK,UAAU;AAAA,QACrB,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA,EAGQ,YAAkB;AACtB,QAAI,KAAK,UAAU;AACf,WAAK,SAAS,KAAK;AACnB;AAAA,IACJ;AACA,QAAI,KAAK,gBAAgB;AACrB,WAAK,eAAe,MAAM,UAAU;AACpC,WAAK,eAAe,YAAY;AAAA,IACpC;AAAA,EACJ;AAAA;AAAA,EAGQ,UAAU,MAAyB,UAAkB,MAAsC;AAC/F,UAAM,QAAuB,EAAE,MAAM,UAAU,WAAW,KAAK,IAAI,GAAG,KAAK;AAC3E,SAAK,IAAI,iBAAiB,KAAK;AAE/B,UAAM,iBAAiB,SAAS,mBAAmB,MAAM,WAAW;AACpE,QAAI,gBAAgB;AAChB,WAAK,mBAAmB,UAAU,SAAS;AAAA,IAC/C;AACA,QAAI,SAAS,oBAAoB;AAC7B,WAAK,mBAAmB,QAAQ;AAAA,IACpC;AACA,QAAI,SAAS,iBAAiB,SAAS,sBAAsB,gBAAgB;AACzE,YAAM,kBAAkB,MAAM;AAC9B,YAAM,UAAU,mBAAmB,KAAK,gBAAgB,IAAI,QAAQ;AACpE,UAAI,SAAS;AACT,cAAM,iBAAiB,MAAM;AAC7B,cAAM,SAAS,SAAS,wCAElB,SAAS;AAGf,aAAK,KAAK,eAAe,QAAQ,SAAS,kBAAkB,KAAK,UAAU,UAAU,KAAK,KAAK,QAAQ,MAAM;AAAA,MACjH,OAAO;AACH,aAAK,MAAM,sCAAsC,EAAE,MAAM,SAAS,CAAC;AAAA,MACvE;AAAA,IACJ;AAEA,UAAM,YAAY,KAAK,UAAU,IAAI,IAAI;AACzC,QAAI,WAAW;AACX,gBAAU,QAAQ,CAAC,aAAa;AAC5B,YAAI;AACA,mBAAS,KAAK;AAAA,QAClB,SAAS,OAAO;AACZ,kBAAQ,MAAM,4BAA4B,KAAK;AAAA,QACnD;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ;AAAA;AAAA,EAGQ,OAAO,MAAuB;AAClC,QAAI,KAAK,QAAQ,OAAO;AACpB,cAAQ,IAAI,oBAAoB,GAAG,IAAI;AAAA,IAC3C;AAAA,EACJ;AAAA;AAAA,EAGO,SAAS,MAAuB;AACnC,SAAK,IAAI,GAAG,IAAI;AAAA,EACpB;AAAA;AAAA,EAGO,YAAY,UAA+B;AAC9C,SAAK,WAAW;AAChB,QAAI,KAAK,eAAe,KAAK,SAAS,MAAM;AACxC,WAAK,SAAS,KAAK;AAAA,IACvB;AAAA,EACJ;AAAA,EAEQ,aAAa,OAAuB;AACxC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,eAAe,MAAM,QAAQ,8BAA8B,EAAE;AACnE,WAAO,aAAa,SAAS,KAAK,aAAa,SAAS,GAAG,IAAI,aAAa,MAAM,GAAG,EAAE,IAAI;AAAA,EAC/F;AAAA,EAEQ,aAAa,KAAyB;AAC1C,QAAI,CAAC,IAAK,QAAO;AACjB,QAAI;AACA,aAAO,IAAI,IAAI,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,MAAS;AAAA,IACxF,QAAQ;AACJ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,oBAAoB,MAA0D;AAClF,YAAQ,MAAM;AAAA,MACV,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX,KAAK;AACD,eAAO;AAAA,MACX;AACI,eAAO;AAAA,IACf;AAAA,EACJ;AAAA,EAEQ,mBAAmB,UAAkB,QAA2C;AACpF,UAAM,UAAU,KAAK,eAAe,IAAI,QAAQ;AAChD,QAAI,SAAS,WAAW,eAAe,WAAW,aAAa;AAC3D;AAAA,IACJ;AACA,SAAK,eAAe,IAAI,UAAU,EAAE,QAAQ,WAAW,KAAK,IAAI,EAAE,CAAC;AAAA,EACvE;AAAA,EAEQ,kBAAkB,OAAoD;AAC1E,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,UAAM,QAAQ;AAEd,WAAO,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,YAAY,YACzB,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,cAAc,YAC3B,MAAM,QAAQ,MAAM,QAAQ,KAC5B,MAAM,SAAS,SAAS,KACxB,MAAM,SAAS,MAAM,CAAC,YAAY,KAAK,eAAe,OAAO,CAAC,MAC7D,CAAC,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,cAAc,KAAK,wBAAwB,SAAS,CAAC;AAAA,EAC1G;AAAA,EAEQ,eAAe,OAAuC;AAC1D,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,UAAM,UAAU;AAChB,WAAO,KAAK,mBAAmB,QAAQ,IAAI,MACnC,OAAO,QAAQ,UAAU,YAAY,OAAO,QAAQ,UAAU;AAAA,EAC1E;AAAA,EAEQ,mBAAmB,OAA+C;AACtE,WAAO,UAAU,kBACV,UAAU,YACV,UAAU,UACV,UAAU,WACV,UAAU;AAAA,EACrB;AAAA,EAEQ,wBAAwB,OAAgD;AAC5E,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,UAAM,YAAY;AAClB,WAAO,iCAAiC,SAAS,UAAU,QAAuC,KAC3F,OAAO,UAAU,iBAAiB,YAClC,OAAO,SAAS,UAAU,YAAY,KACtC,UAAU,gBAAgB;AAAA,EACrC;AAAA,EAEQ,8BAA8B,OAAsD;AACxF,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,UAAM,YAAY;AAClB,QAAI,UAAU,aAAa,UAAa,OAAO,UAAU,aAAa,WAAW;AAC7E,aAAO;AAAA,IACX;AACA,QAAI,UAAU,iBAAiB,QAAW;AACtC,aAAO,OAAO,UAAU,iBAAiB,YAClC,OAAO,SAAS,UAAU,YAAY,KACtC,UAAU,gBAAgB;AAAA,IACrC;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,kBAAkB,OAAgC;AACtD,UAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC,KAAK,IAAI,CAAC;AAChE,WAAO,MACF,OAAO,CAAC,YAAqC,KAAK,eAAe,OAAO,CAAC,EACzE,IAAI,CAAC,aAAa;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,IACnB,EAAE;AAAA,EACV;AAAA,EAEQ,kBAAkB,OAAyC;AAC/D,QAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,WAAO,MAAM,OAAO,CAAC,cAAkD,KAAK,wBAAwB,SAAS,CAAC;AAAA,EAClH;AAAA,EAEQ,0BAA0B,OAA+C;AAC7E,QAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,WAAO,MAAM,OAAO,CAAC,cAAwD,KAAK,8BAA8B,SAAS,CAAC;AAAA,EAC9H;AAAA,EAEQ,yBAAyB,KAAgD;AAC7E,QAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AACpD,UAAM,MAAM;AAOZ,UAAM,cAAc,IAAI,YAAY,IAAI;AACxC,UAAM,WAAW,KAAK,kBAAkB,WAAW;AACnD,QAAI,CAAC,SAAS,OAAQ,QAAO;AAE7B,UAAM,iBAAiB,MAAM,QAAQ,WAAW,IAAI,cAAc,cAAc,CAAC,WAAW,IAAI,CAAC;AACjG,UAAM,mBAAmB;AAAA,MACrB,GAAG,KAAK,0BAA0B,IAAI,UAAU;AAAA,MAChD,GAAG,eAAe,QAAQ,CAAC,YAAY,KAAK,0BAA2B,QAAoC,SAAS,CAAC;AAAA,IACzH;AACA,UAAM,WAAW,KAAK,kBAAkB,IAAI,QAAQ;AAEpD,WAAO;AAAA,MACH,GAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,yBAAyB,MAA8C;AAC3E,WAAO,KACF,IAAI,CAAC,QAAQ,KAAK,yBAAyB,GAAG,CAAC,EAC/C,OAAO,CAAC,QAA0C,CAAC,CAAC,OAAO,KAAK,kBAAkB,GAAG,CAAC;AAAA,EAC/F;AACJ;;;ACjhCO,SAAS,YAAY,MAAiC;AAC3D,SAAO;AAAA,IACL,SAAS,CAAC,MAAM,KAAK,UAAU,CAAC,KAAK;AAAA,IACrC,SAAS,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,CAAC;AAAA,IAChC,YAAY,CAAC,MAAM,KAAK,OAAO,CAAC;AAAA,EAClC;AACF;AAGO,SAAS,gBAAgB,GAA+B;AAC7D,SAAO;AAAA,IACL,aAAa,EAAE,WAAW,IAAI,WAAW;AAAA,IACzC,YAAY,EAAE,mBAAmB;AAAA,IACjC,cAAc,EAAE,cAAc;AAAA,IAC9B,aAAa,EAAE,aAAa;AAAA,EAC9B;AACF;AAOO,SAAS,iBACd,KACA,QACA,OAA6B,CAAC,GAClB;AACZ,MAAI,KAAK,SAAU,KAAI,YAAY,KAAK,QAAQ;AAEhD,QAAM,UAAU,KAAK,OAAO,YAAY,KAAK,IAAI,IAAI,OAAO;AAC5D,QAAM,SAAS,KAAK,aAAa,gBAAgB,KAAK,UAAU,IAAI,OAAO;AAC3E,QAAM,WAAW,KAAK,YAAY,OAAO;AAEzC,MAAI,KAAK,EAAE,GAAG,QAAQ,SAAS,QAAQ,SAAS,CAAC;AAEjD,MAAI;AACJ,MAAI,KAAK,UAAU,kBAAkB;AACnC,mBAAe,KAAK,SAAS,iBAAiB,UAAU,CAAC,UAAU;AACjE,UAAI,UAAU,SAAU,KAAI,aAAa;AAAA,UACpC,KAAI,aAAa;AAAA,IACxB,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACX,QAAI,gBAAgB,OAAO,aAAa,WAAW,WAAY,cAAa,OAAO;AAAA,EACrF;AACF;","names":[]}