{"version":3,"sources":["../src/products.ts","../src/ai/enrich.ts"],"sourcesContent":["import { filter, isNonNullish } from \"remeda\";\nimport {\n  classifyProduct,\n  enrichProduct,\n  generateSEOContent as generateSEOContentLLM,\n} from \"./ai/enrich\";\nimport type { StoreInfo } from \"./store\";\nimport type {\n  CurrencyCode,\n  Product,\n  ProductClassification,\n  SEOContent,\n  ShopifyProduct,\n  ShopifySingleProduct,\n} from \"./types\";\nimport { formatPrice } from \"./utils/func\";\nimport { rateLimitedFetch } from \"./utils/rate-limit\";\n\n/**\n * Interface for product operations\n */\nexport interface ProductOperations {\n  /**\n   * Fetches all products from the store across all pages.\n   */\n  all(options?: { currency?: CurrencyCode }): Promise<Product[] | null>;\n\n  /**\n   * Fetches products with pagination support.\n   */\n  paginated(options?: {\n    page?: number;\n    limit?: number;\n    currency?: CurrencyCode;\n  }): Promise<Product[] | null>;\n\n  /**\n   * Finds a specific product by its handle.\n   */\n  find(\n    productHandle: string,\n    options?: { currency?: CurrencyCode }\n  ): Promise<Product | null>;\n\n  /**\n   * Finds a product by handle and enriches its content using LLM.\n   * Requires an OpenAI API key via options.apiKey or process.env.OPENAI_API_KEY.\n   */\n  enriched(\n    productHandle: string,\n    options?: {\n      apiKey?: string;\n      useGfm?: boolean;\n      inputType?: \"markdown\" | \"html\";\n      model?: string;\n      outputFormat?: \"markdown\" | \"json\";\n    }\n  ): Promise<Product | null>;\n  classify(\n    productHandle: string,\n    options?: { apiKey?: string; model?: string }\n  ): Promise<ProductClassification | null>;\n\n  /**\n   * Generate SEO and marketing content for a product.\n   */\n  generateSEOContent(\n    productHandle: string,\n    options?: { apiKey?: string; model?: string }\n  ): Promise<SEOContent | null>;\n\n  /**\n   * Fetches products that are showcased/featured on the store's homepage.\n   */\n  showcased(): Promise<Product[]>;\n\n  /**\n   * Creates a filter map of variant options and their distinct values from all products.\n   */\n  filter(): Promise<Record<string, string[]> | null>;\n}\n\n/**\n * Creates product operations for a store instance\n */\nexport function createProductOperations(\n  baseUrl: string,\n  storeDomain: string,\n  fetchProducts: (page: number, limit: number) => Promise<Product[] | null>,\n  productsDto: (products: ShopifyProduct[]) => Product[] | null,\n  productDto: (product: ShopifySingleProduct) => Product,\n  getStoreInfo: () => Promise<StoreInfo>,\n  findProduct: (handle: string) => Promise<Product | null>\n): ProductOperations {\n  // Use shared formatter from utils\n\n  function applyCurrencyOverride(\n    product: Product,\n    currency: CurrencyCode\n  ): Product {\n    const priceMin = product.priceMin ?? product.price ?? 0;\n    const priceMax = product.priceMax ?? product.price ?? 0;\n    const compareAtMin =\n      product.compareAtPriceMin ?? product.compareAtPrice ?? 0;\n    return {\n      ...product,\n      currency,\n      localizedPricing: {\n        currency,\n        priceFormatted: formatPrice(priceMin, currency),\n        priceMinFormatted: formatPrice(priceMin, currency),\n        priceMaxFormatted: formatPrice(priceMax, currency),\n        compareAtPriceFormatted: formatPrice(compareAtMin, currency),\n      },\n    };\n  }\n\n  function maybeOverrideProductsCurrency(\n    products: Product[] | null,\n    currency?: CurrencyCode\n  ): Product[] | null {\n    if (!products || !currency) return products;\n    return products.map((p) => applyCurrencyOverride(p, currency));\n  }\n\n  const operations: ProductOperations = {\n    /**\n     * Fetches all products from the store across all pages.\n     *\n     * @returns {Promise<Product[] | null>} Array of all products or null if error occurs\n     *\n     * @throws {Error} When there's a network error or API failure\n     *\n     * @example\n     * ```typescript\n     * const shop = new ShopClient('https://exampleshop.com');\n     * const allProducts = await shop.products.all();\n     *\n     * console.log(`Found ${allProducts?.length} products`);\n     * allProducts?.forEach(product => {\n     *   console.log(product.title, product.price);\n     * });\n     * ```\n     */\n    all: async (options?: {\n      currency?: CurrencyCode;\n    }): Promise<Product[] | null> => {\n      const limit = 250;\n      const allProducts: Product[] = [];\n\n      async function fetchAll() {\n        let currentPage = 1;\n\n        while (true) {\n          const products = await fetchProducts(currentPage, limit);\n\n          if (!products || products.length === 0 || products.length < limit) {\n            if (products && products.length > 0) {\n              allProducts.push(...products);\n            }\n            break;\n          }\n\n          allProducts.push(...products);\n          currentPage++;\n        }\n        return allProducts;\n      }\n\n      try {\n        const products = await fetchAll();\n        return maybeOverrideProductsCurrency(products, options?.currency);\n      } catch (error) {\n        console.error(\"Failed to fetch all products:\", storeDomain, error);\n        throw error;\n      }\n    },\n\n    /**\n     * Fetches products with pagination support.\n     *\n     * @param options - Pagination options\n     * @param options.page - Page number (default: 1)\n     * @param options.limit - Number of products per page (default: 250, max: 250)\n     *\n     * @returns {Promise<Product[] | null>} Array of products for the specified page or null if error occurs\n     *\n     * @throws {Error} When there's a network error or API failure\n     *\n     * @example\n     * ```typescript\n     * const shop = new ShopClient('https://example.myshopify.com');\n     *\n     * // Get first page with default limit (250)\n     * const firstPage = await shop.products.paginated();\n     *\n     * // Get second page with custom limit\n     * const secondPage = await shop.products.paginated({ page: 2, limit: 50 });\n     * ```\n     */\n    paginated: async (options?: {\n      page?: number;\n      limit?: number;\n      currency?: CurrencyCode;\n    }): Promise<Product[] | null> => {\n      const page = options?.page ?? 1;\n      const limit = Math.min(options?.limit ?? 250, 250);\n      const url = `${baseUrl}products.json?limit=${limit}&page=${page}`;\n\n      try {\n        const response = await rateLimitedFetch(url);\n        if (!response.ok) {\n          console.error(\n            `HTTP error! status: ${response.status} for ${storeDomain} page ${page}`\n          );\n          throw new Error(`HTTP error! status: ${response.status}`);\n        }\n\n        const data = (await response.json()) as {\n          products: ShopifyProduct[];\n        };\n        if (data.products.length === 0) {\n          return [];\n        }\n        const normalized = productsDto(data.products);\n        return maybeOverrideProductsCurrency(normalized, options?.currency);\n      } catch (error) {\n        console.error(\n          `Error fetching products for ${storeDomain} page ${page} with limit ${limit}:`,\n          error\n        );\n        return null;\n      }\n    },\n\n    /**\n     * Finds a specific product by its handle.\n     *\n     * @param productHandle - The product handle (URL slug) to search for\n     *\n     * @returns {Promise<Product | null>} The product if found, null if not found\n     *\n     * @throws {Error} When the handle is invalid or there's a network error\n     *\n     * @example\n     * ```typescript\n     * const shop = new ShopClient('https://exampleshop.com');\n     *\n     * // Find product by handle\n     * const product = await shop.products.find('awesome-t-shirt');\n     *\n     * if (product) {\n     *   console.log(product.title, product.price);\n     *   console.log('Available variants:', product.variants.length);\n     * }\n     *\n     * // Handle with query string\n     * const productWithVariant = await shop.products.find('t-shirt?variant=123');\n     * ```\n     */\n    find: async (\n      productHandle: string,\n      options?: { currency?: CurrencyCode }\n    ): Promise<Product | null> => {\n      // Validate product handle\n      if (!productHandle || typeof productHandle !== \"string\") {\n        throw new Error(\"Product handle is required and must be a string\");\n      }\n\n      try {\n        let qs: string | null = null;\n        if (productHandle.includes(\"?\")) {\n          const parts = productHandle.split(\"?\");\n          const handlePart = parts[0] ?? productHandle;\n          const qsPart = parts[1] ?? null;\n          productHandle = handlePart;\n          qs = qsPart;\n        }\n\n        // Sanitize handle - remove potentially dangerous characters\n        const sanitizedHandle = productHandle\n          .trim()\n          .replace(/[^a-zA-Z0-9\\-_]/g, \"\");\n        if (!sanitizedHandle) {\n          throw new Error(\"Invalid product handle format\");\n        }\n\n        // Check handle length (reasonable limits)\n        if (sanitizedHandle.length > 255) {\n          throw new Error(\"Product handle is too long\");\n        }\n\n        // Resolve canonical handle via HTML redirect if handle has changed\n        let finalHandle = sanitizedHandle;\n        try {\n          const htmlResp = await rateLimitedFetch(\n            `${baseUrl}products/${encodeURIComponent(sanitizedHandle)}`\n          );\n          if (htmlResp.ok) {\n            const finalUrl = htmlResp.url;\n            if (finalUrl) {\n              const pathname = new URL(finalUrl).pathname.replace(/\\/$/, \"\");\n              const parts = pathname.split(\"/\").filter(Boolean);\n              const idx = parts.indexOf(\"products\");\n              const maybeHandle = idx >= 0 ? parts[idx + 1] : undefined;\n              if (typeof maybeHandle === \"string\" && maybeHandle.length) {\n                finalHandle = maybeHandle;\n              }\n            }\n          }\n        } catch {\n          // Ignore redirect resolution errors and proceed with original handle\n        }\n\n        const url = `${baseUrl}products/${encodeURIComponent(finalHandle)}.js${qs ? `?${qs}` : \"\"}`;\n        const response = await rateLimitedFetch(url);\n\n        if (!response.ok) {\n          if (response.status === 404) {\n            return null;\n          }\n          throw new Error(`HTTP error! status: ${response.status}`);\n        }\n\n        const product = (await response.json()) as ShopifySingleProduct;\n        const productData = productDto(product);\n        return options?.currency\n          ? applyCurrencyOverride(productData, options.currency)\n          : productData;\n      } catch (error) {\n        if (error instanceof Error) {\n          console.error(\n            `Error fetching product ${productHandle}:`,\n            baseUrl,\n            error.message\n          );\n        }\n        throw error;\n      }\n    },\n\n    /**\n     * Enrich a product by generating merged markdown from body_html and product page.\n     * Adds `enriched_content` to the returned product.\n     */\n    enriched: async (\n      productHandle: string,\n      options?: {\n        apiKey?: string;\n        useGfm?: boolean;\n        inputType?: \"markdown\" | \"html\";\n        model?: string;\n        outputFormat?: \"markdown\" | \"json\";\n      }\n    ): Promise<Product | null> => {\n      if (!productHandle || typeof productHandle !== \"string\") {\n        throw new Error(\"Product handle is required and must be a string\");\n      }\n\n      const apiKey = options?.apiKey || process.env.OPENROUTER_API_KEY;\n      if (!apiKey) {\n        throw new Error(\n          \"Missing OpenRouter API key. Pass options.apiKey or set OPENROUTER_API_KEY.\"\n        );\n      }\n\n      // Reuse find() for validation and normalized product\n      const baseProduct = await operations.find(productHandle);\n      if (!baseProduct) {\n        return null;\n      }\n\n      // Use the normalized handle from the found product\n      const handle = baseProduct.handle;\n      const enriched = await enrichProduct(storeDomain, handle, {\n        apiKey,\n        useGfm: options?.useGfm,\n        inputType: options?.inputType,\n        model: options?.model,\n        outputFormat: options?.outputFormat,\n      });\n\n      return {\n        ...baseProduct,\n        enriched_content: enriched.mergedMarkdown,\n      };\n    },\n    classify: async (\n      productHandle: string,\n      options?: { apiKey?: string; model?: string }\n    ): Promise<ProductClassification | null> => {\n      if (!productHandle || typeof productHandle !== \"string\") {\n        throw new Error(\"Product handle is required and must be a string\");\n      }\n      const apiKey = options?.apiKey || process.env.OPENROUTER_API_KEY;\n      if (!apiKey) {\n        throw new Error(\n          \"Missing OpenRouter API key. Pass options.apiKey or set OPENROUTER_API_KEY.\"\n        );\n      }\n      const enrichedProduct = await operations.enriched(productHandle, {\n        apiKey,\n        inputType: \"html\",\n        model: options?.model,\n        outputFormat: \"json\",\n      });\n      if (!enrichedProduct || !enrichedProduct.enriched_content) return null;\n\n      let productContent = enrichedProduct.enriched_content;\n      try {\n        const obj = JSON.parse(enrichedProduct.enriched_content);\n        const lines: string[] = [];\n        if (obj.title && typeof obj.title === \"string\")\n          lines.push(`Title: ${obj.title}`);\n        if (obj.description && typeof obj.description === \"string\")\n          lines.push(`Description: ${obj.description}`);\n        if (Array.isArray(obj.materials) && obj.materials.length)\n          lines.push(`Materials: ${obj.materials.join(\", \")}`);\n        if (Array.isArray(obj.care) && obj.care.length)\n          lines.push(`Care: ${obj.care.join(\", \")}`);\n        if (obj.fit && typeof obj.fit === \"string\")\n          lines.push(`Fit: ${obj.fit}`);\n        if (obj.returnPolicy && typeof obj.returnPolicy === \"string\")\n          lines.push(`ReturnPolicy: ${obj.returnPolicy}`);\n        productContent = lines.join(\"\\n\");\n      } catch {\n        // keep as-is if not JSON\n      }\n\n      const classification = await classifyProduct(productContent, {\n        apiKey,\n        model: options?.model,\n      });\n      return classification;\n    },\n\n    generateSEOContent: async (\n      productHandle: string,\n      options?: { apiKey?: string; model?: string }\n    ): Promise<SEOContent | null> => {\n      if (!productHandle || typeof productHandle !== \"string\") {\n        throw new Error(\"Product handle is required and must be a string\");\n      }\n      const apiKey = options?.apiKey || process.env.OPENROUTER_API_KEY;\n      if (!apiKey) {\n        throw new Error(\n          \"Missing OpenRouter API key. Pass options.apiKey or set OPENROUTER_API_KEY.\"\n        );\n      }\n\n      const baseProduct = await operations.find(productHandle);\n      if (!baseProduct) return null;\n\n      const payload = {\n        title: baseProduct.title,\n        description: baseProduct.bodyHtml || undefined,\n        vendor: baseProduct.vendor,\n        price: baseProduct.price,\n        tags: baseProduct.tags,\n      };\n\n      const seo = await generateSEOContentLLM(payload, {\n        apiKey,\n        model: options?.model,\n      });\n      return seo;\n    },\n\n    /**\n     * Fetches products that are showcased/featured on the store's homepage.\n     *\n     * @returns {Promise<Product[]>} Array of showcased products found on the homepage\n     *\n     * @throws {Error} When there's a network error or API failure\n     *\n     * @example\n     * ```typescript\n     * const shop = new ShopClient('https://exampleshop.com');\n     * const showcasedProducts = await shop.products.showcased();\n     *\n     * console.log(`Found ${showcasedProducts.length} showcased products`);\n     * showcasedProducts.forEach(product => {\n     *   console.log(`Featured: ${product.title} - ${product.price}`);\n     * });\n     * ```\n     */\n    showcased: async () => {\n      const storeInfo = await getStoreInfo();\n      const products = await Promise.all(\n        storeInfo.showcase.products.map((productHandle: string) =>\n          findProduct(productHandle)\n        )\n      );\n      return filter(products, isNonNullish);\n    },\n\n    /**\n     * Creates a filter map of variant options and their distinct values from all products.\n     *\n     * @returns {Promise<Record<string, string[]> | null>} Map of option names to their distinct values or null if error occurs\n     *\n     * @throws {Error} When there's a network error or API failure\n     *\n     * @example\n     * ```typescript\n     * const shop = new ShopClient('https://exampleshop.com');\n     * const filters = await shop.products.filter();\n     *\n     * console.log('Available filters:', filters);\n     * // Output: { \"Size\": [\"S\", \"M\", \"L\", \"XL\"], \"Color\": [\"Red\", \"Blue\", \"Green\"] }\n     *\n     * // Use filters for UI components\n     * Object.entries(filters || {}).forEach(([optionName, values]) => {\n     *   console.log(`${optionName}: ${values.join(', ')}`);\n     * });\n     * ```\n     */\n    filter: async (): Promise<Record<string, string[]> | null> => {\n      try {\n        // Use the existing all() method to get all products across all pages\n        const products = await operations.all();\n        if (!products || products.length === 0) {\n          return {};\n        }\n\n        // Create a map to store option names and their distinct values\n        const filterMap: Record<string, Set<string>> = {};\n\n        // Process each product and its variants\n        products.forEach((product) => {\n          if (product.variants && product.variants.length > 0) {\n            // Process product options\n            if (product.options && product.options.length > 0) {\n              product.options.forEach((option) => {\n                const lowercaseOptionName = option.name.toLowerCase();\n                if (!filterMap[lowercaseOptionName]) {\n                  filterMap[lowercaseOptionName] = new Set();\n                }\n                // Add all values from this option (converted to lowercase)\n                option.values.forEach((value) => {\n                  const trimmed = value?.trim();\n                  if (trimmed) {\n                    let set = filterMap[lowercaseOptionName];\n                    if (!set) {\n                      set = new Set<string>();\n                      filterMap[lowercaseOptionName] = set;\n                    }\n                    set.add(trimmed.toLowerCase());\n                  }\n                });\n              });\n            }\n\n            // Also process individual variant options as fallback\n            product.variants.forEach((variant) => {\n              if (variant.option1) {\n                const optionName = (\n                  product.options?.[0]?.name || \"Option 1\"\n                ).toLowerCase();\n                let set1 = filterMap[optionName];\n                if (!set1) {\n                  set1 = new Set<string>();\n                  filterMap[optionName] = set1;\n                }\n                set1.add(variant.option1.trim().toLowerCase());\n              }\n\n              if (variant.option2) {\n                const optionName = (\n                  product.options?.[1]?.name || \"Option 2\"\n                ).toLowerCase();\n                let set2 = filterMap[optionName];\n                if (!set2) {\n                  set2 = new Set<string>();\n                  filterMap[optionName] = set2;\n                }\n                set2.add(variant.option2.trim().toLowerCase());\n              }\n\n              if (variant.option3) {\n                const optionName = (\n                  product.options?.[2]?.name || \"Option 3\"\n                ).toLowerCase();\n                if (!filterMap[optionName]) {\n                  filterMap[optionName] = new Set();\n                }\n                filterMap[optionName].add(variant.option3.trim().toLowerCase());\n              }\n            });\n          }\n        });\n\n        // Convert Sets to sorted arrays (values are already lowercase and unique due to Set)\n        const result: Record<string, string[]> = {};\n        Object.entries(filterMap).forEach(([optionName, valueSet]) => {\n          result[optionName] = Array.from(valueSet).sort();\n        });\n\n        return result;\n      } catch (error) {\n        console.error(\"Failed to create product filters:\", storeDomain, error);\n        throw error;\n      }\n    },\n  };\n\n  return operations;\n}\n","import TurndownService from \"turndown\";\n// @ts-expect-error\nimport { gfm } from \"turndown-plugin-gfm\";\nimport type {\n  ProductClassification,\n  SEOContent,\n  ShopifySingleProduct,\n} from \"../types\";\nimport { rateLimitedFetch } from \"../utils/rate-limit\";\n\nfunction ensureOpenRouter(apiKey?: string) {\n  const key = apiKey || process.env.OPENROUTER_API_KEY;\n  if (!key) {\n    throw new Error(\n      \"Missing OpenRouter API key. Set OPENROUTER_API_KEY or pass apiKey.\"\n    );\n  }\n  return key;\n}\n\nfunction normalizeDomainToBase(domain: string): string {\n  // Accept both bare domains (example.com) and full URLs (https://example.com)\n  if (domain.startsWith(\"http://\") || domain.startsWith(\"https://\")) {\n    try {\n      const u = new URL(domain);\n      return `${u.protocol}//${u.hostname}`;\n    } catch {\n      // Fallback to https\n      return domain;\n    }\n  }\n  return `https://${domain}`;\n}\n\nexport interface EnrichedProductResult {\n  bodyHtml: string;\n  pageHtml: string;\n  extractedMainHtml: string;\n  mergedMarkdown: string;\n}\n\n/**\n * Fetch Shopify Product AJAX API\n * /products/{handle}.js\n */\nexport async function fetchAjaxProduct(\n  domain: string,\n  handle: string\n): Promise<ShopifySingleProduct> {\n  const base = normalizeDomainToBase(domain);\n  const url = `${base}/products/${handle}.js`;\n  const res = await rateLimitedFetch(url);\n  if (!res.ok) throw new Error(`Failed to fetch AJAX product: ${url}`);\n  const data: ShopifySingleProduct = await res.json();\n  return data;\n}\n\n/**\n * Fetch full product page HTML\n */\nexport async function fetchProductPage(\n  domain: string,\n  handle: string\n): Promise<string> {\n  const base = normalizeDomainToBase(domain);\n  const url = `${base}/products/${handle}`;\n  const res = await rateLimitedFetch(url);\n  if (!res.ok) throw new Error(`Failed to fetch product page: ${url}`);\n  return res.text();\n}\n\n/**\n * Extract the main Shopify product section WITHOUT cheerio\n * Uses regex + indexing (fast & reliable)\n */\nexport function extractMainSection(html: string): string | null {\n  const startMatch = html.match(\n    /<section[^>]*id=\"shopify-section-template--.*?__main\"[^>]*>/\n  );\n\n  if (!startMatch) return null;\n\n  const startIndex = html.indexOf(startMatch[0]);\n  if (startIndex === -1) return null;\n\n  const endIndex = html.indexOf(\"</section>\", startIndex);\n  if (endIndex === -1) return null;\n\n  return html.substring(startIndex, endIndex + \"</section>\".length);\n}\n\n/**\n * Convert HTML → Clean Markdown using Turndown\n * Includes Shopify cleanup rules + GFM support\n */\nexport function htmlToMarkdown(\n  html: string | null,\n  options?: { useGfm?: boolean }\n): string {\n  if (!html) return \"\";\n\n  const td = new TurndownService({\n    headingStyle: \"atx\",\n    codeBlockStyle: \"fenced\",\n    bulletListMarker: \"-\",\n    emDelimiter: \"*\",\n    strongDelimiter: \"**\",\n    linkStyle: \"inlined\",\n  });\n\n  // Enable GitHub flavored markdown\n  const useGfm = options?.useGfm ?? true;\n  if (useGfm) {\n    td.use(gfm);\n  }\n\n  // Remove noise: scripts, styles, theme blocks\n  [\"script\", \"style\", \"nav\", \"footer\"].forEach((tag) => {\n    td.remove((node) => node.nodeName?.toLowerCase() === tag);\n  });\n\n  // Remove Shopify-specific junk\n  const removeByClass = (className: string) =>\n    td.remove((node: any) => {\n      const cls =\n        typeof node.getAttribute === \"function\"\n          ? node.getAttribute(\"class\") || \"\"\n          : \"\";\n      return (cls as string).split(/\\s+/).includes(className);\n    });\n  [\n    \"product-form\",\n    \"shopify-payment-button\",\n    \"shopify-payment-buttons\",\n    \"product__actions\",\n    \"product__media-wrapper\",\n    \"loox-rating\",\n    \"jdgm-widget\",\n    \"stamped-reviews\",\n  ].forEach(removeByClass);\n\n  // Remove UI input elements\n  [\"button\", \"input\", \"select\", \"label\"].forEach((tag) => {\n    td.remove((node) => node.nodeName?.toLowerCase() === tag);\n  });\n\n  // Remove add-to-cart + quantity controls\n  [\"quantity-selector\", \"product-atc-wrapper\"].forEach(removeByClass);\n\n  return td.turndown(html);\n}\n\n/**\n * Merge the two markdown sources using OpenAI GPT\n */\nexport async function mergeWithLLM(\n  bodyInput: string,\n  pageInput: string,\n  options?: {\n    apiKey?: string;\n    inputType?: \"markdown\" | \"html\";\n    model?: string;\n    outputFormat?: \"markdown\" | \"json\";\n  }\n): Promise<string> {\n  const inputType = options?.inputType ?? \"markdown\";\n  const bodyLabel = inputType === \"html\" ? \"BODY HTML\" : \"BODY MARKDOWN\";\n  const pageLabel = inputType === \"html\" ? \"PAGE HTML\" : \"PAGE MARKDOWN\";\n  const prompt =\n    options?.outputFormat === \"json\"\n      ? `You are extracting structured buyer-useful information from Shopify product content.\n\nInputs:\n1) ${bodyLabel}: ${inputType === \"html\" ? \"Raw Shopify product body_html\" : \"Cleaned version of Shopify product body_html\"}\n2) ${pageLabel}: ${inputType === \"html\" ? \"Raw product page HTML (main section)\" : \"Extracted product page HTML converted to markdown\"}\n\nReturn ONLY valid JSON (no markdown, no code fences) with this shape:\n{\n  \"title\": null | string,\n  \"description\": null | string,\n  \"materials\": string[] | [],\n  \"care\": string[] | [],\n  \"fit\": null | string,\n  \"images\": null | string[],\n  \"returnPolicy\": null | string\n}\n\nRules:\n- Do not invent facts; if a field is unavailable, use null or []\n- Prefer concise, factual statements\n - Do NOT include product gallery/hero images in \"images\"; include only documentation images like size charts or measurement guides. If none, set \"images\": null.\n\n${bodyLabel}:\n${bodyInput}\n\n${pageLabel}:\n${pageInput}\n`\n      : `\nYou are enriching a Shopify product for a modern shopping-discovery app.\n\nInputs:\n1) ${bodyLabel}: ${inputType === \"html\" ? \"Raw Shopify product body_html\" : \"Cleaned version of Shopify product body_html\"}\n2) ${pageLabel}: ${inputType === \"html\" ? \"Raw product page HTML (main section)\" : \"Extracted product page HTML converted to markdown\"}\n\nYour tasks:\n- Merge them into a single clean markdown document\n- Remove duplicate content\n- Remove product images\n- Remove UI text, buttons, menus, review widgets, theme junk\n- Remove product options\n- Keep only available buyer-useful info: features, materials, care, fit, size chart, return policy, size chart, care instructions\n- Include image of size-chart if present\n- Don't include statements like information not available.\n- Maintain structured headings (## Description, ## Materials, etc.)\n- Output ONLY markdown (no commentary)\n\n${bodyLabel}:\n${bodyInput}\n\n${pageLabel}:\n${pageInput}\n`;\n  const apiKey = ensureOpenRouter(options?.apiKey);\n\n  // Default model via environment or safe fallback (OpenRouter slug)\n  const defaultModel = process.env.OPENROUTER_MODEL || \"openai/gpt-4o-mini\";\n  const model = options?.model ?? defaultModel;\n\n  // OpenRouter path only\n  const result = await callOpenRouter(model, prompt, apiKey);\n  if (options?.outputFormat === \"json\") {\n    const cleaned = result.replace(/```json|```/g, \"\").trim();\n    // Validate shape early to fail fast on malformed JSON responses\n    const obj = safeParseJson(cleaned);\n    if (!obj.ok) {\n      throw new Error(`LLM returned invalid JSON: ${obj.error}`);\n    }\n    const schema = validateStructuredJson(obj.value);\n    if (!schema.ok) {\n      throw new Error(`LLM JSON schema invalid: ${schema.error}`);\n    }\n\n    // Sanitize any returned image URLs to avoid product gallery/hero images\n    const value = obj.value as any;\n    if (Array.isArray(value.images)) {\n      const filtered = value.images.filter((url: string) => {\n        if (typeof url !== \"string\") return false;\n        const u = url.toLowerCase();\n        // Common Shopify product image patterns to exclude\n        const productPatterns = [\n          \"cdn.shopify.com\",\n          \"/products/\",\n          \"%2Fproducts%2F\",\n          \"_large\",\n          \"_grande\",\n          \"_1024x1024\",\n          \"_2048x\",\n        ];\n        const looksLikeProductImage = productPatterns.some((p) =>\n          u.includes(p)\n        );\n        return !looksLikeProductImage;\n      });\n      value.images = filtered.length > 0 ? filtered : null;\n    }\n    return JSON.stringify(value);\n  }\n  return result;\n}\n\n// Runtime JSON parse helper with descriptive errors\nfunction safeParseJson(\n  input: string\n): { ok: true; value: unknown } | { ok: false; error: string } {\n  try {\n    const v = JSON.parse(input);\n    return { ok: true, value: v };\n  } catch (err: any) {\n    return { ok: false, error: err?.message || \"Failed to parse JSON\" };\n  }\n}\n\n// Validate relaxed schema of structured product JSON from LLM\nfunction validateStructuredJson(\n  obj: unknown\n): { ok: true } | { ok: false; error: string } {\n  if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n    return { ok: false, error: \"Top-level must be a JSON object\" };\n  }\n  const o = obj as any;\n\n  // Optional fields must match expected types when present\n  if (\"title\" in o && !(o.title === null || typeof o.title === \"string\")) {\n    return { ok: false, error: \"title must be null or string\" };\n  }\n  if (\n    \"description\" in o &&\n    !(o.description === null || typeof o.description === \"string\")\n  ) {\n    return { ok: false, error: \"description must be null or string\" };\n  }\n  if (\"fit\" in o && !(o.fit === null || typeof o.fit === \"string\")) {\n    return { ok: false, error: \"fit must be null or string\" };\n  }\n  if (\n    \"returnPolicy\" in o &&\n    !(o.returnPolicy === null || typeof o.returnPolicy === \"string\")\n  ) {\n    return { ok: false, error: \"returnPolicy must be null or string\" };\n  }\n\n  const validateStringArray = (\n    arr: unknown,\n    field: string\n  ): { ok: true } | { ok: false; error: string } => {\n    if (!Array.isArray(arr))\n      return { ok: false, error: `${field} must be an array` };\n    for (const item of arr) {\n      if (typeof item !== \"string\")\n        return { ok: false, error: `${field} items must be strings` };\n    }\n    return { ok: true };\n  };\n\n  if (\"materials\" in o) {\n    const res = validateStringArray(o.materials, \"materials\");\n    if (!res.ok) return res;\n  }\n  if (\"care\" in o) {\n    const res = validateStringArray(o.care, \"care\");\n    if (!res.ok) return res;\n  }\n\n  if (\"images\" in o) {\n    if (!(o.images === null || Array.isArray(o.images))) {\n      return { ok: false, error: \"images must be null or an array\" };\n    }\n    if (Array.isArray(o.images)) {\n      const res = validateStringArray(o.images, \"images\");\n      if (!res.ok) return res;\n    }\n  }\n\n  return { ok: true };\n}\n\n// OpenRouter handler (OpenAI-compatible payload, single key to access many models)\nasync function callOpenRouter(\n  model: string,\n  prompt: string,\n  apiKey: string\n): Promise<string> {\n  // Offline fallback for environments without network egress.\n  // Enable by setting OPENROUTER_OFFLINE=1.\n  if (process.env.OPENROUTER_OFFLINE === \"1\") {\n    return mockOpenRouterResponse(prompt);\n  }\n  const headers: Record<string, string> = {\n    \"Content-Type\": \"application/json\",\n    Authorization: `Bearer ${apiKey}`,\n  };\n  const referer = process.env.OPENROUTER_SITE_URL || process.env.SITE_URL;\n  const title = process.env.OPENROUTER_APP_TITLE || \"Shop Search\";\n  if (referer) headers[\"HTTP-Referer\"] = referer;\n  if (title) headers[\"X-Title\"] = title;\n\n  const buildPayload = (m: string) => ({\n    model: m,\n    messages: [{ role: \"user\", content: prompt }],\n    temperature: 0.2,\n  });\n\n  // Use Quickstart-recommended base: https://openrouter.ai/api/v1\n  // Allow override via OPENROUTER_BASE_URL\n  const base = (\n    process.env.OPENROUTER_BASE_URL || \"https://openrouter.ai/api/v1\"\n  ).replace(/\\/$/, \"\");\n  const endpoints = [`${base}/chat/completions`];\n\n  // Prepare fallback models\n  const fallbackEnv = (process.env.OPENROUTER_FALLBACK_MODELS || \"\")\n    .split(\",\")\n    .map((s) => s.trim())\n    .filter(Boolean);\n  const defaultModel = process.env.OPENROUTER_MODEL || \"openai/gpt-4o-mini\";\n  const modelsToTry = Array.from(\n    new Set([model, ...fallbackEnv, defaultModel])\n  ).filter(Boolean);\n\n  let lastErrorText = \"\";\n  for (const m of modelsToTry) {\n    for (const url of endpoints) {\n      try {\n        const controller = new AbortController();\n        const timeout = setTimeout(() => controller.abort(), 15000);\n        const response = await rateLimitedFetch(url, {\n          method: \"POST\",\n          headers,\n          body: JSON.stringify(buildPayload(m)),\n          signal: controller.signal,\n        });\n        clearTimeout(timeout);\n        if (!response.ok) {\n          const text = await response.text();\n          // If server error, try next model; otherwise capture and continue to next endpoint/model\n          lastErrorText = text || `${url}: HTTP ${response.status}`;\n          // Small delay before trying next\n          await new Promise((r) => setTimeout(r, 300));\n          continue;\n        }\n        const data = await response.json();\n        const content = data?.choices?.[0]?.message?.content;\n        if (typeof content === \"string\") return content;\n        // If content missing, still capture and try fallback\n        lastErrorText = JSON.stringify(data);\n        await new Promise((r) => setTimeout(r, 200));\n      } catch (err: any) {\n        lastErrorText = `${url}: ${err?.message || String(err)}`;\n        await new Promise((r) => setTimeout(r, 200));\n      }\n    }\n  }\n  throw new Error(`OpenRouter request failed: ${lastErrorText}`);\n}\n\n// Generate a deterministic offline response tailored to the prompt.\nfunction mockOpenRouterResponse(prompt: string): string {\n  const p = prompt.toLowerCase();\n  // Classification prompt contains \"keys:\" section\n  if (p.includes(\"return only valid json\") && p.includes('\"audience\":')) {\n    return JSON.stringify({\n      audience: \"generic\",\n      vertical: \"clothing\",\n      category: null,\n      subCategory: null,\n    });\n  }\n\n  // Structured merge prompt contains \"with this shape:\" section\n  if (p.includes(\"return only valid json\") && p.includes('\"materials\":')) {\n    return JSON.stringify({\n      title: null,\n      description: null,\n      materials: [],\n      care: [],\n      fit: null,\n      images: null,\n      returnPolicy: null,\n    });\n  }\n\n  // Markdown merge fallback\n  return [\n    \"## Description\",\n    \"Offline merge of product body and page.\",\n    \"\",\n    \"## Materials\",\n    \"- Not available\",\n  ].join(\"\\n\");\n}\n\n/**\n * MAIN WORKFLOW\n */\nexport async function enrichProduct(\n  domain: string,\n  handle: string,\n  options?: {\n    apiKey?: string;\n    useGfm?: boolean;\n    inputType?: \"markdown\" | \"html\";\n    model?: string;\n    outputFormat?: \"markdown\" | \"json\";\n  }\n): Promise<EnrichedProductResult> {\n  // STEP 1: Fetch Shopify single product (AJAX) and use its description\n  const ajaxProduct = await fetchAjaxProduct(domain, handle);\n  const bodyHtml = ajaxProduct.description || \"\";\n\n  // STEP 2: Full product page HTML\n  const pageHtml = await fetchProductPage(domain, handle);\n\n  // STEP 3: Extract main section\n  const extractedHtml = extractMainSection(pageHtml);\n\n  // STEP 4: Prepare inputs based on desired input type\n  const inputType = options?.inputType ?? \"markdown\";\n  const bodyInput =\n    inputType === \"html\"\n      ? bodyHtml\n      : htmlToMarkdown(bodyHtml, { useGfm: options?.useGfm });\n  const pageInput =\n    inputType === \"html\"\n      ? extractedHtml || pageHtml\n      : htmlToMarkdown(extractedHtml, { useGfm: options?.useGfm });\n\n  // STEP 5: Merge using LLM\n  const mergedMarkdown = await mergeWithLLM(bodyInput, pageInput, {\n    apiKey: options?.apiKey,\n    inputType,\n    model: options?.model,\n    outputFormat: options?.outputFormat,\n  });\n\n  // If JSON output requested, further sanitize images using Shopify REST data\n  if (options?.outputFormat === \"json\") {\n    try {\n      const obj = JSON.parse(mergedMarkdown);\n      if (obj && Array.isArray(obj.images)) {\n        const productImageCandidates: string[] = [];\n        // Collect featured_image (string URL)\n        if (ajaxProduct.featured_image) {\n          productImageCandidates.push(String(ajaxProduct.featured_image));\n        }\n        // Collect images (string[])\n        if (Array.isArray(ajaxProduct.images)) {\n          for (const img of ajaxProduct.images) {\n            if (typeof img === \"string\" && img.length > 0) {\n              productImageCandidates.push(img);\n            }\n          }\n        }\n        // Collect media[].src\n        if (Array.isArray(ajaxProduct.media)) {\n          for (const m of ajaxProduct.media) {\n            if (m?.src) productImageCandidates.push(String(m.src));\n          }\n        }\n        // Collect variants[].featured_image?.src\n        if (Array.isArray(ajaxProduct.variants)) {\n          for (const v of ajaxProduct.variants) {\n            const fi = v?.featured_image;\n            if (fi?.src) productImageCandidates.push(String(fi.src));\n          }\n        }\n\n        const productSet = new Set(\n          productImageCandidates.map((u) => String(u).toLowerCase())\n        );\n        const filtered = obj.images.filter((url: string) => {\n          if (typeof url !== \"string\") return false;\n          const u = url.toLowerCase();\n          if (productSet.has(u)) return false;\n          // Also exclude common Shopify product image patterns\n          const productPatterns = [\n            \"cdn.shopify.com\",\n            \"/products/\",\n            \"%2Fproducts%2F\",\n            \"_large\",\n            \"_grande\",\n            \"_1024x1024\",\n            \"_2048x\",\n          ];\n          const looksLikeProductImage = productPatterns.some((p) =>\n            u.includes(p)\n          );\n          return !looksLikeProductImage;\n        });\n        obj.images = filtered.length > 0 ? filtered : null;\n        const sanitized = JSON.stringify(obj);\n        return {\n          bodyHtml,\n          pageHtml,\n          extractedMainHtml: extractedHtml || \"\",\n          mergedMarkdown: sanitized,\n        };\n      }\n    } catch {\n      // fallthrough to default return\n    }\n  }\n\n  return {\n    bodyHtml,\n    pageHtml,\n    extractedMainHtml: extractedHtml || \"\",\n    mergedMarkdown,\n  };\n}\n\n/**\n * Classify product content into a three-tier hierarchy using LLM.\n * Returns strictly validated JSON with audience, vertical, and optional category/subCategory.\n */\nexport async function classifyProduct(\n  productContent: string,\n  options?: { apiKey?: string; model?: string }\n): Promise<ProductClassification> {\n  const apiKey = ensureOpenRouter(options?.apiKey);\n  const defaultModel = process.env.OPENROUTER_MODEL || \"openai/gpt-4o-mini\";\n  const model = options?.model ?? defaultModel;\n\n  const prompt = `Classify the following product using a three-tiered hierarchy:\n\nProduct Content:\n${productContent}\n\nClassification Rules:\n1. First determine the vertical (main product category)\n2. Then determine the category (specific type within that vertical)\n3. Finally determine the subCategory (sub-type within that category)\n\nVertical must be one of: clothing, beauty, accessories, home-decor, food-and-beverages\nAudience must be one of: adult_male, adult_female, kid_male, kid_female, generic\n\nHierarchy Examples:\n- Clothing → tops → t-shirts\n- Clothing → footwear → sneakers\n- Beauty → skincare → moisturizers\n- Accessories → bags → backpacks\n- Home-decor → furniture → chairs\n- Food-and-beverages → snacks → chips\n\nIMPORTANT CONSTRAINTS:\n- Category must be relevant to the chosen vertical\n- subCategory must be relevant to both vertical and category\n- subCategory must be a single word or hyphenated words (no spaces)\n- subCategory should NOT be material (e.g., \"cotton\", \"leather\") or color (e.g., \"red\", \"blue\")\n- Focus on product type/function, not attributes\n\nIf you're not confident about category or sub-category, you can leave them optional.\n\nReturn ONLY valid JSON (no markdown, no code fences) with keys:\n{\n  \"audience\": \"adult_male\" | \"adult_female\" | \"kid_male\" | \"kid_female\" | \"generic\",\n  \"vertical\": \"clothing\" | \"beauty\" | \"accessories\" | \"home-decor\" | \"food-and-beverages\",\n  \"category\": null | string,\n  \"subCategory\": null | string\n}`;\n\n  const raw = await callOpenRouter(model, prompt, apiKey);\n  const cleaned = raw.replace(/```json|```/g, \"\").trim();\n\n  // Parse and validate\n  const parsed = safeParseJson(cleaned);\n  if (!parsed.ok) {\n    throw new Error(`LLM returned invalid JSON: ${parsed.error}`);\n  }\n  const validated = validateClassification(parsed.value);\n  if (!validated.ok) {\n    throw new Error(`LLM JSON schema invalid: ${validated.error}`);\n  }\n  return validated.value as ProductClassification;\n}\n\n// Validate product classification schema\nfunction validateClassification(\n  obj: unknown\n): { ok: true; value: ProductClassification } | { ok: false; error: string } {\n  if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n    return { ok: false, error: \"Top-level must be a JSON object\" };\n  }\n  const o = obj as any;\n\n  const audienceValues = [\n    \"adult_male\",\n    \"adult_female\",\n    \"kid_male\",\n    \"kid_female\",\n    \"generic\",\n  ] as const;\n  if (typeof o.audience !== \"string\" || !audienceValues.includes(o.audience)) {\n    return {\n      ok: false,\n      error:\n        \"audience must be one of: adult_male, adult_female, kid_male, kid_female, generic\",\n    };\n  }\n\n  const verticalValues = [\n    \"clothing\",\n    \"beauty\",\n    \"accessories\",\n    \"home-decor\",\n    \"food-and-beverages\",\n  ] as const;\n  if (typeof o.vertical !== \"string\" || !verticalValues.includes(o.vertical)) {\n    return {\n      ok: false,\n      error:\n        \"vertical must be one of: clothing, beauty, accessories, home-decor, food-and-beverages\",\n    };\n  }\n\n  // Optional fields\n  if (\n    \"category\" in o &&\n    !(o.category === null || typeof o.category === \"string\")\n  ) {\n    return { ok: false, error: \"category must be null or string\" };\n  }\n  if (\n    \"subCategory\" in o &&\n    !(o.subCategory === null || typeof o.subCategory === \"string\")\n  ) {\n    return { ok: false, error: \"subCategory must be null or string\" };\n  }\n\n  // Enforce subCategory format when provided: single word or hyphenated (no spaces)\n  if (typeof o.subCategory === \"string\") {\n    const sc = o.subCategory.trim();\n    if (!/^[A-Za-z0-9-]+$/.test(sc)) {\n      return {\n        ok: false,\n        error: \"subCategory must be single word or hyphenated, no spaces\",\n      };\n    }\n  }\n\n  return {\n    ok: true,\n    value: {\n      audience: o.audience,\n      vertical: o.vertical,\n      category:\n        typeof o.category === \"string\" ? o.category : (o.category ?? null),\n      subCategory:\n        typeof o.subCategory === \"string\"\n          ? o.subCategory\n          : (o.subCategory ?? null),\n    },\n  };\n}\n\n/**\n * Generate SEO and marketing content for a product. Returns strictly validated JSON.\n */\nexport async function generateSEOContent(\n  product: {\n    title: string;\n    description?: string;\n    vendor?: string;\n    price?: number;\n    tags?: string[];\n  },\n  options?: { apiKey?: string; model?: string }\n): Promise<SEOContent> {\n  const apiKey = ensureOpenRouter(options?.apiKey);\n  const defaultModel = process.env.OPENROUTER_MODEL || \"openai/gpt-4o-mini\";\n  const model = options?.model ?? defaultModel;\n\n  // Offline deterministic mock\n  if (process.env.OPENROUTER_OFFLINE === \"1\") {\n    const baseTags = Array.isArray(product.tags)\n      ? product.tags.slice(0, 6)\n      : [];\n    const titlePart = product.title.trim().slice(0, 50);\n    const vendorPart = (product.vendor || \"\").trim();\n    const pricePart =\n      typeof product.price === \"number\" ? `$${product.price}` : \"\";\n    const metaTitle = vendorPart ? `${titlePart} | ${vendorPart}` : titlePart;\n    const metaDescription =\n      `Discover ${product.title}. ${pricePart ? `Priced at ${pricePart}. ` : \"\"}Crafted to delight customers with quality and style.`.slice(\n        0,\n        160\n      );\n    const shortDescription = `${product.title} — ${vendorPart || \"Premium\"} quality, designed to impress.`;\n    const longDescription =\n      product.description ||\n      `Introducing ${product.title}, combining performance and style for everyday use.`;\n    const marketingCopy = `Get ${product.title} today${pricePart ? ` for ${pricePart}` : \"\"}. Limited availability — don’t miss out!`;\n    const res: SEOContent = {\n      metaTitle,\n      metaDescription,\n      shortDescription,\n      longDescription,\n      tags: baseTags.length ? baseTags : [\"new\", \"featured\", \"popular\"],\n      marketingCopy,\n    };\n    const validated = validateSEOContent(res);\n    if (!validated.ok)\n      throw new Error(`Offline SEO content invalid: ${validated.error}`);\n    return validated.value;\n  }\n\n  const prompt = `Generate SEO-optimized content for this product:\\n\\nTitle: ${product.title}\\nDescription: ${product.description || \"N/A\"}\\nVendor: ${product.vendor || \"N/A\"}\\nPrice: ${typeof product.price === \"number\" ? `$${product.price}` : \"N/A\"}\\nTags: ${Array.isArray(product.tags) && product.tags.length ? product.tags.join(\", \") : \"N/A\"}\\n\\nCreate compelling, SEO-friendly content that will help this product rank well and convert customers.\\n\\nReturn ONLY valid JSON (no markdown, no code fences) with keys: {\\n  \"metaTitle\": string,\\n  \"metaDescription\": string,\\n  \"shortDescription\": string,\\n  \"longDescription\": string,\\n  \"tags\": string[],\\n  \"marketingCopy\": string\\n}`;\n\n  const raw = await callOpenRouter(model, prompt, apiKey);\n  const cleaned = raw.replace(/```json|```/g, \"\").trim();\n  const parsed = safeParseJson(cleaned);\n  if (!parsed.ok) {\n    throw new Error(`LLM returned invalid JSON: ${parsed.error}`);\n  }\n  const validated = validateSEOContent(parsed.value);\n  if (!validated.ok) {\n    throw new Error(`LLM JSON schema invalid: ${validated.error}`);\n  }\n  return validated.value as SEOContent;\n}\n\nfunction validateSEOContent(\n  obj: unknown\n): { ok: true; value: SEOContent } | { ok: false; error: string } {\n  if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n    return { ok: false, error: \"Top-level must be a JSON object\" };\n  }\n  const o = obj as any;\n  const requiredStrings = [\n    \"metaTitle\",\n    \"metaDescription\",\n    \"shortDescription\",\n    \"longDescription\",\n    \"marketingCopy\",\n  ];\n  for (const key of requiredStrings) {\n    if (typeof o[key] !== \"string\" || !o[key].trim()) {\n      return { ok: false, error: `${key} must be a non-empty string` };\n    }\n  }\n  if (!Array.isArray(o.tags)) {\n    return { ok: false, error: \"tags must be an array\" };\n  }\n  for (const t of o.tags) {\n    if (typeof t !== \"string\")\n      return { ok: false, error: \"tags items must be strings\" };\n  }\n  // Light heuristic: metaTitle ~50-80 chars, metaDescription ~80-180 chars (do not hard-fail)\n  return {\n    ok: true,\n    value: {\n      metaTitle: String(o.metaTitle),\n      metaDescription: String(o.metaDescription),\n      shortDescription: String(o.shortDescription),\n      longDescription: String(o.longDescription),\n      tags: o.tags as string[],\n      marketingCopy: String(o.marketingCopy),\n    },\n  };\n}\n\n/**\n * Determine store type (primary vertical and audience) from store information.\n * Accepts flexible input for showcase products/collections (titles or handles) and returns\n * strictly validated `vertical` and `audience` values.\n */\nexport async function determineStoreType(\n  storeInfo: {\n    title: string;\n    description?: string | null;\n    showcase: {\n      products:\n        | Array<{ title: string; productType?: string | null }>\n        | string[];\n      collections: Array<{ title: string }> | string[];\n    };\n  },\n  options?: { apiKey?: string; model?: string }\n): Promise<\n  Partial<\n    Record<\n      ProductClassification[\"audience\"],\n      Partial<Record<ProductClassification[\"vertical\"], string[]>>\n    >\n  >\n> {\n  const apiKey = ensureOpenRouter(options?.apiKey);\n  const defaultModel = process.env.OPENROUTER_MODEL || \"openai/gpt-4o-mini\";\n  const model = options?.model ?? defaultModel;\n\n  // Normalize showcase items to titles for readable prompt content\n  const productLines = (\n    Array.isArray(storeInfo.showcase.products)\n      ? storeInfo.showcase.products.slice(0, 10).map((p: any) => {\n          if (typeof p === \"string\") return `- ${p}`;\n          const pt =\n            typeof p?.productType === \"string\" && p.productType.trim()\n              ? p.productType\n              : \"N/A\";\n          return `- ${String(p?.title || \"N/A\")}: ${pt}`;\n        })\n      : []\n  ) as string[];\n  const collectionLines = (\n    Array.isArray(storeInfo.showcase.collections)\n      ? storeInfo.showcase.collections.slice(0, 5).map((c: any) => {\n          if (typeof c === \"string\") return `- ${c}`;\n          return `- ${String(c?.title || \"N/A\")}`;\n        })\n      : []\n  ) as string[];\n\n  const storeContent = `Store Title: ${storeInfo.title}\nStore Description: ${storeInfo.description ?? \"N/A\"}\n\nSample Products:\\n${productLines.join(\"\\n\") || \"- N/A\"}\n\nSample Collections:\\n${collectionLines.join(\"\\n\") || \"- N/A\"}`;\n  const textNormalized =\n    `${storeInfo.title} ${storeInfo.description ?? \"\"} ${productLines.join(\" \")} ${collectionLines.join(\" \")}`.toLowerCase();\n\n  // Offline deterministic mock with light heuristics\n  if (process.env.OPENROUTER_OFFLINE === \"1\") {\n    const text =\n      `${storeInfo.title} ${storeInfo.description ?? \"\"} ${productLines.join(\" \")} ${collectionLines.join(\" \")}`.toLowerCase();\n    const verticalKeywords: Record<string, RegExp> = {\n      clothing:\n        /(dress|shirt|pant|jean|hoodie|tee|t[- ]?shirt|sneaker|apparel|clothing)/,\n      beauty: /(skincare|moisturizer|serum|beauty|cosmetic|makeup)/,\n      accessories:\n        /(bag|belt|watch|wallet|accessor(y|ies)|sunglasses|jewell?ery)/,\n      \"home-decor\": /(sofa|chair|table|decor|home|candle|lamp|rug)/,\n      \"food-and-beverages\":\n        /(snack|food|beverage|coffee|tea|chocolate|gourmet)/,\n    };\n    // Use strict word-boundary matching to avoid false positives like \"boyfriend\" or \"girlfriend\"\n    const audienceKeywords: Record<string, RegExp> = {\n      kid: /(\\bkid\\b|\\bchild\\b|\\bchildren\\b|\\btoddler\\b|\\bboy\\b|\\bgirl\\b)/,\n      kid_male: /\\bboys\\b|\\bboy\\b/,\n      kid_female: /\\bgirls\\b|\\bgirl\\b/,\n      adult_male: /\\bmen\\b|\\bmale\\b|\\bman\\b|\\bmens\\b/,\n      adult_female: /\\bwomen\\b|\\bfemale\\b|\\bwoman\\b|\\bwomens\\b/,\n    };\n    const audiences: ProductClassification[\"audience\"][] = [];\n    if (audienceKeywords.kid?.test(text)) {\n      if (audienceKeywords.kid_male?.test(text)) audiences.push(\"kid_male\");\n      if (audienceKeywords.kid_female?.test(text)) audiences.push(\"kid_female\");\n      if (\n        !audienceKeywords.kid_male?.test(text) &&\n        !audienceKeywords.kid_female?.test(text)\n      )\n        audiences.push(\"generic\");\n    } else {\n      if (audienceKeywords.adult_male?.test(text)) audiences.push(\"adult_male\");\n      if (audienceKeywords.adult_female?.test(text))\n        audiences.push(\"adult_female\");\n      if (audiences.length === 0) audiences.push(\"generic\");\n    }\n\n    // Determine verticals present\n    const verticals = Object.entries(verticalKeywords)\n      .filter(([, rx]) => rx.test(text))\n      .map(([k]) => k as ProductClassification[\"vertical\"]);\n    if (verticals.length === 0) verticals.push(\"accessories\");\n\n    // Derive categories from showcase product titles\n    const allTitles = productLines.join(\" \").toLowerCase();\n    const categoryMap: Record<string, RegExp> = {\n      shirts: /(shirt|t[- ]?shirt|tee)/,\n      pants: /(pant|trouser|chino)/,\n      shorts: /shorts?/,\n      jeans: /jeans?/,\n      dresses: /dress/,\n      skincare: /(serum|moisturizer|skincare|cream)/,\n      accessories: /(belt|watch|wallet|bag)/,\n      footwear: /(sneaker|shoe|boot)/,\n      decor: /(candle|lamp|rug|sofa|chair|table)/,\n      beverages: /(coffee|tea|chocolate)/,\n    };\n    const categories = Object.entries(categoryMap)\n      .filter(([, rx]) => rx.test(allTitles))\n      .map(([name]) => name);\n    const defaultCategories = categories.length ? categories : [\"general\"];\n\n    const breakdown: Partial<\n      Record<\n        ProductClassification[\"audience\"],\n        Partial<Record<ProductClassification[\"vertical\"], string[]>>\n      >\n    > = {};\n    for (const aud of audiences) {\n      breakdown[aud] = breakdown[aud] || {};\n      for (const v of verticals) {\n        breakdown[aud]![v] = Array.from(new Set(defaultCategories));\n      }\n    }\n    // Apply pruning even in offline mode to drop un-signaled audiences/verticals\n    return pruneBreakdownForSignals(breakdown, textNormalized);\n  }\n\n  const prompt = `Analyze this store and build a multi-audience breakdown of verticals and categories.\nStore Information:\n${storeContent}\n\nReturn ONLY valid JSON (no markdown, no code fences) using this shape:\n{\n  \"adult_male\": { \"clothing\": [\"shirts\", \"pants\"], \"accessories\": [\"belts\"] },\n  \"adult_female\": { \"beauty\": [\"skincare\"], \"clothing\": [\"dresses\"] },\n  \"generic\": { \"clothing\": [\"t-shirts\"] }\n}\n\nRules:\n- Keys MUST be audience: \"adult_male\" | \"adult_female\" | \"kid_male\" | \"kid_female\" | \"generic\".\n- Nested keys MUST be vertical: \"clothing\" | \"beauty\" | \"accessories\" | \"home-decor\" | \"food-and-beverages\".\n- Values MUST be non-empty arrays of category strings.\n`;\n\n  const raw = await callOpenRouter(model, prompt, apiKey);\n  const cleaned = raw.replace(/```json|```/g, \"\").trim();\n  const parsed = safeParseJson(cleaned);\n  if (!parsed.ok) {\n    throw new Error(`LLM returned invalid JSON: ${parsed.error}`);\n  }\n  const validated = validateStoreTypeBreakdown(parsed.value);\n  if (!validated.ok) {\n    throw new Error(`LLM JSON schema invalid: ${validated.error}`);\n  }\n  return pruneBreakdownForSignals(validated.value, textNormalized);\n}\n\nfunction validateStoreTypeBreakdown(obj: unknown):\n  | {\n      ok: true;\n      value: Partial<\n        Record<\n          ProductClassification[\"audience\"],\n          Partial<Record<ProductClassification[\"vertical\"], string[]>>\n        >\n      >;\n    }\n  | { ok: false; error: string } {\n  if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n    return {\n      ok: false,\n      error: \"Top-level must be an object keyed by audience\",\n    };\n  }\n  const audienceKeys = [\n    \"adult_male\",\n    \"adult_female\",\n    \"kid_male\",\n    \"kid_female\",\n    \"generic\",\n  ] as const;\n  const verticalKeys = [\n    \"clothing\",\n    \"beauty\",\n    \"accessories\",\n    \"home-decor\",\n    \"food-and-beverages\",\n  ] as const;\n  const o = obj as Record<string, unknown>;\n  const out: Partial<\n    Record<\n      ProductClassification[\"audience\"],\n      Partial<Record<ProductClassification[\"vertical\"], string[]>>\n    >\n  > = {};\n  const keys = Object.keys(o);\n  if (keys.length === 0) {\n    return { ok: false, error: \"At least one audience key is required\" };\n  }\n  for (const aKey of keys) {\n    if (!audienceKeys.includes(aKey as any)) {\n      return { ok: false, error: `Invalid audience key: ${aKey}` };\n    }\n    const vObj = o[aKey];\n    if (!vObj || typeof vObj !== \"object\" || Array.isArray(vObj)) {\n      return {\n        ok: false,\n        error: `Audience ${aKey} must map to an object of verticals`,\n      };\n    }\n    const vOut: Partial<Record<ProductClassification[\"vertical\"], string[]>> =\n      {};\n    for (const vKey of Object.keys(vObj as Record<string, unknown>)) {\n      if (!verticalKeys.includes(vKey as any)) {\n        return {\n          ok: false,\n          error: `Invalid vertical key ${vKey} for audience ${aKey}`,\n        };\n      }\n      const cats = (vObj as any)[vKey];\n      if (\n        !Array.isArray(cats) ||\n        cats.length === 0 ||\n        !cats.every((c) => typeof c === \"string\" && c.trim())\n      ) {\n        return {\n          ok: false,\n          error: `Vertical ${vKey} for audience ${aKey} must be a non-empty array of strings`,\n        };\n      }\n      vOut[vKey as ProductClassification[\"vertical\"]] = cats.map((c: string) =>\n        c.trim()\n      );\n    }\n    out[aKey as ProductClassification[\"audience\"]] = vOut;\n  }\n  return { ok: true, value: out };\n}\n\nexport function pruneBreakdownForSignals(\n  breakdown: Partial<\n    Record<\n      ProductClassification[\"audience\"],\n      Partial<Record<ProductClassification[\"vertical\"], string[]>>\n    >\n  >,\n  text: string\n): Partial<\n  Record<\n    ProductClassification[\"audience\"],\n    Partial<Record<ProductClassification[\"vertical\"], string[]>>\n  >\n> {\n  const audienceKeywords: Record<string, RegExp> = {\n    kid: /(\\bkid\\b|\\bchild\\b|\\bchildren\\b|\\btoddler\\b|\\bboy\\b|\\bgirl\\b)/,\n    kid_male: /\\bboys\\b|\\bboy\\b/,\n    kid_female: /\\bgirls\\b|\\bgirl\\b/,\n    adult_male: /\\bmen\\b|\\bmale\\b|\\bman\\b|\\bmens\\b/,\n    adult_female: /\\bwomen\\b|\\bfemale\\b|\\bwoman\\b|\\bwomens\\b/,\n  };\n  const verticalKeywords: Record<string, RegExp> = {\n    clothing:\n      /(dress|shirt|pant|jean|hoodie|tee|t[- ]?shirt|sneaker|apparel|clothing)/,\n    beauty: /(skincare|moisturizer|serum|beauty|cosmetic|makeup)/,\n    accessories:\n      /(bag|belt|watch|wallet|accessor(y|ies)|sunglasses|jewell?ery)/,\n    // Tighten home-decor detection to avoid matching generic \"Home\" nav labels\n    // and other unrelated uses. Require specific furniture/decor terms or phrases.\n    \"home-decor\":\n      /(sofa|chair|table|candle|lamp|rug|furniture|home[- ]?decor|homeware|housewares|living\\s?room|dining\\s?table|bed(?:room)?|wall\\s?(art|mirror|clock))/,\n    \"food-and-beverages\": /(snack|food|beverage|coffee|tea|chocolate|gourmet)/,\n  };\n\n  const signaledAudiences = new Set<ProductClassification[\"audience\"]>();\n  if (audienceKeywords.kid?.test(text)) {\n    if (audienceKeywords.kid_male?.test(text))\n      signaledAudiences.add(\"kid_male\");\n    if (audienceKeywords.kid_female?.test(text))\n      signaledAudiences.add(\"kid_female\");\n    if (\n      !audienceKeywords.kid_male?.test(text) &&\n      !audienceKeywords.kid_female?.test(text)\n    )\n      signaledAudiences.add(\"generic\");\n  } else {\n    if (audienceKeywords.adult_male?.test(text))\n      signaledAudiences.add(\"adult_male\");\n    if (audienceKeywords.adult_female?.test(text))\n      signaledAudiences.add(\"adult_female\");\n    if (signaledAudiences.size === 0) signaledAudiences.add(\"generic\");\n  }\n\n  const signaledVerticals = new Set<ProductClassification[\"vertical\"]>(\n    Object.entries(verticalKeywords)\n      .filter(([, rx]) => rx.test(text))\n      .map(([k]) => k as ProductClassification[\"vertical\"]) || []\n  );\n  if (signaledVerticals.size === 0) signaledVerticals.add(\"accessories\");\n\n  const pruned: Partial<\n    Record<\n      ProductClassification[\"audience\"],\n      Partial<Record<ProductClassification[\"vertical\"], string[]>>\n    >\n  > = {};\n  for (const [audience, verticals] of Object.entries(breakdown)) {\n    const a = audience as ProductClassification[\"audience\"];\n    if (!signaledAudiences.has(a)) continue;\n    const vOut: Partial<Record<ProductClassification[\"vertical\"], string[]>> =\n      {};\n    for (const [vertical, categories] of Object.entries(verticals || {})) {\n      const v = vertical as ProductClassification[\"vertical\"];\n      if (!signaledVerticals.has(v)) continue;\n      vOut[v] = categories as string[];\n    }\n    if (Object.keys(vOut).length > 0) {\n      pruned[a] = vOut;\n    }\n  }\n\n  // If pruning removes all audiences, fall back to generic with any verticals present in original or signaled\n  if (Object.keys(pruned).length === 0) {\n    const vOut: Partial<Record<ProductClassification[\"vertical\"], string[]>> =\n      {};\n    for (const v of Array.from(signaledVerticals)) {\n      vOut[v] = [\"general\"];\n    }\n    pruned.generic = vOut;\n  }\n\n  // Remove generic when adult audiences exist and have verticals\n  const adultHasData =\n    (pruned.adult_male && Object.keys(pruned.adult_male).length > 0) ||\n    (pruned.adult_female && Object.keys(pruned.adult_female).length > 0);\n  if (adultHasData) {\n    delete pruned.generic;\n  }\n\n  return pruned;\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,QAAQ,oBAAoB;;;ACArC,OAAO,qBAAqB;AAE5B,SAAS,WAAW;AAQpB,SAAS,iBAAiB,QAAiB;AACzC,QAAM,MAAM,UAAU,QAAQ,IAAI;AAClC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,QAAwB;AAErD,MAAI,OAAO,WAAW,SAAS,KAAK,OAAO,WAAW,UAAU,GAAG;AACjE,QAAI;AACF,YAAM,IAAI,IAAI,IAAI,MAAM;AACxB,aAAO,GAAG,EAAE,QAAQ,KAAK,EAAE,QAAQ;AAAA,IACrC,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,WAAW,MAAM;AAC1B;AAaA,eAAsB,iBACpB,QACA,QAC+B;AAC/B,QAAM,OAAO,sBAAsB,MAAM;AACzC,QAAM,MAAM,GAAG,IAAI,aAAa,MAAM;AACtC,QAAM,MAAM,MAAM,iBAAiB,GAAG;AACtC,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,iCAAiC,GAAG,EAAE;AACnE,QAAM,OAA6B,MAAM,IAAI,KAAK;AAClD,SAAO;AACT;AAKA,eAAsB,iBACpB,QACA,QACiB;AACjB,QAAM,OAAO,sBAAsB,MAAM;AACzC,QAAM,MAAM,GAAG,IAAI,aAAa,MAAM;AACtC,QAAM,MAAM,MAAM,iBAAiB,GAAG;AACtC,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,iCAAiC,GAAG,EAAE;AACnE,SAAO,IAAI,KAAK;AAClB;AAMO,SAAS,mBAAmB,MAA6B;AAC9D,QAAM,aAAa,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,aAAa,KAAK,QAAQ,WAAW,CAAC,CAAC;AAC7C,MAAI,eAAe,GAAI,QAAO;AAE9B,QAAM,WAAW,KAAK,QAAQ,cAAc,UAAU;AACtD,MAAI,aAAa,GAAI,QAAO;AAE5B,SAAO,KAAK,UAAU,YAAY,WAAW,aAAa,MAAM;AAClE;AAMO,SAAS,eACd,MACA,SACQ;AAlGV;AAmGE,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,KAAK,IAAI,gBAAgB;AAAA,IAC7B,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,WAAW;AAAA,EACb,CAAC;AAGD,QAAM,UAAS,wCAAS,WAAT,YAAmB;AAClC,MAAI,QAAQ;AACV,OAAG,IAAI,GAAG;AAAA,EACZ;AAGA,GAAC,UAAU,SAAS,OAAO,QAAQ,EAAE,QAAQ,CAAC,QAAQ;AACpD,OAAG,OAAO,CAAC,SAAM;AAtHrB,UAAAA;AAsHwB,eAAAA,MAAA,KAAK,aAAL,gBAAAA,IAAe,mBAAkB;AAAA,KAAG;AAAA,EAC1D,CAAC;AAGD,QAAM,gBAAgB,CAAC,cACrB,GAAG,OAAO,CAAC,SAAc;AACvB,UAAM,MACJ,OAAO,KAAK,iBAAiB,aACzB,KAAK,aAAa,OAAO,KAAK,KAC9B;AACN,WAAQ,IAAe,MAAM,KAAK,EAAE,SAAS,SAAS;AAAA,EACxD,CAAC;AACH;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,QAAQ,aAAa;AAGvB,GAAC,UAAU,SAAS,UAAU,OAAO,EAAE,QAAQ,CAAC,QAAQ;AACtD,OAAG,OAAO,CAAC,SAAM;AA/IrB,UAAAA;AA+IwB,eAAAA,MAAA,KAAK,aAAL,gBAAAA,IAAe,mBAAkB;AAAA,KAAG;AAAA,EAC1D,CAAC;AAGD,GAAC,qBAAqB,qBAAqB,EAAE,QAAQ,aAAa;AAElE,SAAO,GAAG,SAAS,IAAI;AACzB;AAKA,eAAsB,aACpB,WACA,WACA,SAMiB;AApKnB;AAqKE,QAAM,aAAY,wCAAS,cAAT,YAAsB;AACxC,QAAM,YAAY,cAAc,SAAS,cAAc;AACvD,QAAM,YAAY,cAAc,SAAS,cAAc;AACvD,QAAM,UACJ,mCAAS,kBAAiB,SACtB;AAAA;AAAA;AAAA,KAGH,SAAS,KAAK,cAAc,SAAS,kCAAkC,8CAA8C;AAAA,KACrH,SAAS,KAAK,cAAc,SAAS,yCAAyC,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBpI,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,EAET,SAAS;AAAA,EACT,SAAS;AAAA,IAEH;AAAA;AAAA;AAAA;AAAA,KAIH,SAAS,KAAK,cAAc,SAAS,kCAAkC,8CAA8C;AAAA,KACrH,SAAS,KAAK,cAAc,SAAS,yCAAyC,mDAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcpI,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,EAET,SAAS;AAAA,EACT,SAAS;AAAA;AAET,QAAM,SAAS,iBAAiB,mCAAS,MAAM;AAG/C,QAAM,eAAe,QAAQ,IAAI,oBAAoB;AACrD,QAAM,SAAQ,wCAAS,UAAT,YAAkB;AAGhC,QAAM,SAAS,MAAM,eAAe,OAAO,QAAQ,MAAM;AACzD,OAAI,mCAAS,kBAAiB,QAAQ;AACpC,UAAM,UAAU,OAAO,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAExD,UAAM,MAAM,cAAc,OAAO;AACjC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,8BAA8B,IAAI,KAAK,EAAE;AAAA,IAC3D;AACA,UAAM,SAAS,uBAAuB,IAAI,KAAK;AAC/C,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,IAAI,MAAM,4BAA4B,OAAO,KAAK,EAAE;AAAA,IAC5D;AAGA,UAAM,QAAQ,IAAI;AAClB,QAAI,MAAM,QAAQ,MAAM,MAAM,GAAG;AAC/B,YAAM,WAAW,MAAM,OAAO,OAAO,CAAC,QAAgB;AACpD,YAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,cAAM,IAAI,IAAI,YAAY;AAE1B,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,wBAAwB,gBAAgB;AAAA,UAAK,CAAC,MAClD,EAAE,SAAS,CAAC;AAAA,QACd;AACA,eAAO,CAAC;AAAA,MACV,CAAC;AACD,YAAM,SAAS,SAAS,SAAS,IAAI,WAAW;AAAA,IAClD;AACA,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACA,SAAO;AACT;AAGA,SAAS,cACP,OAC6D;AAC7D,MAAI;AACF,UAAM,IAAI,KAAK,MAAM,KAAK;AAC1B,WAAO,EAAE,IAAI,MAAM,OAAO,EAAE;AAAA,EAC9B,SAAS,KAAU;AACjB,WAAO,EAAE,IAAI,OAAO,QAAO,2BAAK,YAAW,uBAAuB;AAAA,EACpE;AACF;AAGA,SAAS,uBACP,KAC6C;AAC7C,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,WAAO,EAAE,IAAI,OAAO,OAAO,kCAAkC;AAAA,EAC/D;AACA,QAAM,IAAI;AAGV,MAAI,WAAW,KAAK,EAAE,EAAE,UAAU,QAAQ,OAAO,EAAE,UAAU,WAAW;AACtE,WAAO,EAAE,IAAI,OAAO,OAAO,+BAA+B;AAAA,EAC5D;AACA,MACE,iBAAiB,KACjB,EAAE,EAAE,gBAAgB,QAAQ,OAAO,EAAE,gBAAgB,WACrD;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,qCAAqC;AAAA,EAClE;AACA,MAAI,SAAS,KAAK,EAAE,EAAE,QAAQ,QAAQ,OAAO,EAAE,QAAQ,WAAW;AAChE,WAAO,EAAE,IAAI,OAAO,OAAO,6BAA6B;AAAA,EAC1D;AACA,MACE,kBAAkB,KAClB,EAAE,EAAE,iBAAiB,QAAQ,OAAO,EAAE,iBAAiB,WACvD;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,sCAAsC;AAAA,EACnE;AAEA,QAAM,sBAAsB,CAC1B,KACA,UACgD;AAChD,QAAI,CAAC,MAAM,QAAQ,GAAG;AACpB,aAAO,EAAE,IAAI,OAAO,OAAO,GAAG,KAAK,oBAAoB;AACzD,eAAW,QAAQ,KAAK;AACtB,UAAI,OAAO,SAAS;AAClB,eAAO,EAAE,IAAI,OAAO,OAAO,GAAG,KAAK,yBAAyB;AAAA,IAChE;AACA,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,MAAI,eAAe,GAAG;AACpB,UAAM,MAAM,oBAAoB,EAAE,WAAW,WAAW;AACxD,QAAI,CAAC,IAAI,GAAI,QAAO;AAAA,EACtB;AACA,MAAI,UAAU,GAAG;AACf,UAAM,MAAM,oBAAoB,EAAE,MAAM,MAAM;AAC9C,QAAI,CAAC,IAAI,GAAI,QAAO;AAAA,EACtB;AAEA,MAAI,YAAY,GAAG;AACjB,QAAI,EAAE,EAAE,WAAW,QAAQ,MAAM,QAAQ,EAAE,MAAM,IAAI;AACnD,aAAO,EAAE,IAAI,OAAO,OAAO,kCAAkC;AAAA,IAC/D;AACA,QAAI,MAAM,QAAQ,EAAE,MAAM,GAAG;AAC3B,YAAM,MAAM,oBAAoB,EAAE,QAAQ,QAAQ;AAClD,UAAI,CAAC,IAAI,GAAI,QAAO;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;AAGA,eAAe,eACb,OACA,QACA,QACiB;AAhWnB;AAmWE,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,WAAO,uBAAuB,MAAM;AAAA,EACtC;AACA,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,eAAe,UAAU,MAAM;AAAA,EACjC;AACA,QAAM,UAAU,QAAQ,IAAI,uBAAuB,QAAQ,IAAI;AAC/D,QAAM,QAAQ,QAAQ,IAAI,wBAAwB;AAClD,MAAI,QAAS,SAAQ,cAAc,IAAI;AACvC,MAAI,MAAO,SAAQ,SAAS,IAAI;AAEhC,QAAM,eAAe,CAAC,OAAe;AAAA,IACnC,OAAO;AAAA,IACP,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,OAAO,CAAC;AAAA,IAC5C,aAAa;AAAA,EACf;AAIA,QAAM,QACJ,QAAQ,IAAI,uBAAuB,gCACnC,QAAQ,OAAO,EAAE;AACnB,QAAM,YAAY,CAAC,GAAG,IAAI,mBAAmB;AAG7C,QAAM,eAAe,QAAQ,IAAI,8BAA8B,IAC5D,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACjB,QAAM,eAAe,QAAQ,IAAI,oBAAoB;AACrD,QAAM,cAAc,MAAM;AAAA,IACxB,oBAAI,IAAI,CAAC,OAAO,GAAG,aAAa,YAAY,CAAC;AAAA,EAC/C,EAAE,OAAO,OAAO;AAEhB,MAAI,gBAAgB;AACpB,aAAW,KAAK,aAAa;AAC3B,eAAW,OAAO,WAAW;AAC3B,UAAI;AACF,cAAM,aAAa,IAAI,gBAAgB;AACvC,cAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAK;AAC1D,cAAM,WAAW,MAAM,iBAAiB,KAAK;AAAA,UAC3C,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,aAAa,CAAC,CAAC;AAAA,UACpC,QAAQ,WAAW;AAAA,QACrB,CAAC;AACD,qBAAa,OAAO;AACpB,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,0BAAgB,QAAQ,GAAG,GAAG,UAAU,SAAS,MAAM;AAEvD,gBAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC3C;AAAA,QACF;AACA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,cAAM,WAAU,8CAAM,YAAN,mBAAgB,OAAhB,mBAAoB,YAApB,mBAA6B;AAC7C,YAAI,OAAO,YAAY,SAAU,QAAO;AAExC,wBAAgB,KAAK,UAAU,IAAI;AACnC,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAAA,MAC7C,SAAS,KAAU;AACjB,wBAAgB,GAAG,GAAG,MAAK,2BAAK,YAAW,OAAO,GAAG,CAAC;AACtD,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,MAAM,8BAA8B,aAAa,EAAE;AAC/D;AAGA,SAAS,uBAAuB,QAAwB;AACtD,QAAM,IAAI,OAAO,YAAY;AAE7B,MAAI,EAAE,SAAS,wBAAwB,KAAK,EAAE,SAAS,aAAa,GAAG;AACrE,WAAO,KAAK,UAAU;AAAA,MACpB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAGA,MAAI,EAAE,SAAS,wBAAwB,KAAK,EAAE,SAAS,cAAc,GAAG;AACtE,WAAO,KAAK,UAAU;AAAA,MACpB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW,CAAC;AAAA,MACZ,MAAM,CAAC;AAAA,MACP,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAKA,eAAsB,cACpB,QACA,QACA,SAOgC;AA3dlC;AA6dE,QAAM,cAAc,MAAM,iBAAiB,QAAQ,MAAM;AACzD,QAAM,WAAW,YAAY,eAAe;AAG5C,QAAM,WAAW,MAAM,iBAAiB,QAAQ,MAAM;AAGtD,QAAM,gBAAgB,mBAAmB,QAAQ;AAGjD,QAAM,aAAY,wCAAS,cAAT,YAAsB;AACxC,QAAM,YACJ,cAAc,SACV,WACA,eAAe,UAAU,EAAE,QAAQ,mCAAS,OAAO,CAAC;AAC1D,QAAM,YACJ,cAAc,SACV,iBAAiB,WACjB,eAAe,eAAe,EAAE,QAAQ,mCAAS,OAAO,CAAC;AAG/D,QAAM,iBAAiB,MAAM,aAAa,WAAW,WAAW;AAAA,IAC9D,QAAQ,mCAAS;AAAA,IACjB;AAAA,IACA,OAAO,mCAAS;AAAA,IAChB,cAAc,mCAAS;AAAA,EACzB,CAAC;AAGD,OAAI,mCAAS,kBAAiB,QAAQ;AACpC,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,cAAc;AACrC,UAAI,OAAO,MAAM,QAAQ,IAAI,MAAM,GAAG;AACpC,cAAM,yBAAmC,CAAC;AAE1C,YAAI,YAAY,gBAAgB;AAC9B,iCAAuB,KAAK,OAAO,YAAY,cAAc,CAAC;AAAA,QAChE;AAEA,YAAI,MAAM,QAAQ,YAAY,MAAM,GAAG;AACrC,qBAAW,OAAO,YAAY,QAAQ;AACpC,gBAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAC7C,qCAAuB,KAAK,GAAG;AAAA,YACjC;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,QAAQ,YAAY,KAAK,GAAG;AACpC,qBAAW,KAAK,YAAY,OAAO;AACjC,gBAAI,uBAAG,IAAK,wBAAuB,KAAK,OAAO,EAAE,GAAG,CAAC;AAAA,UACvD;AAAA,QACF;AAEA,YAAI,MAAM,QAAQ,YAAY,QAAQ,GAAG;AACvC,qBAAW,KAAK,YAAY,UAAU;AACpC,kBAAM,KAAK,uBAAG;AACd,gBAAI,yBAAI,IAAK,wBAAuB,KAAK,OAAO,GAAG,GAAG,CAAC;AAAA,UACzD;AAAA,QACF;AAEA,cAAM,aAAa,IAAI;AAAA,UACrB,uBAAuB,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,YAAY,CAAC;AAAA,QAC3D;AACA,cAAM,WAAW,IAAI,OAAO,OAAO,CAAC,QAAgB;AAClD,cAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,gBAAM,IAAI,IAAI,YAAY;AAC1B,cAAI,WAAW,IAAI,CAAC,EAAG,QAAO;AAE9B,gBAAM,kBAAkB;AAAA,YACtB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,gBAAM,wBAAwB,gBAAgB;AAAA,YAAK,CAAC,MAClD,EAAE,SAAS,CAAC;AAAA,UACd;AACA,iBAAO,CAAC;AAAA,QACV,CAAC;AACD,YAAI,SAAS,SAAS,SAAS,IAAI,WAAW;AAC9C,cAAM,YAAY,KAAK,UAAU,GAAG;AACpC,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,mBAAmB,iBAAiB;AAAA,UACpC,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,mBAAmB,iBAAiB;AAAA,IACpC;AAAA,EACF;AACF;AAMA,eAAsB,gBACpB,gBACA,SACgC;AA5kBlC;AA6kBE,QAAM,SAAS,iBAAiB,mCAAS,MAAM;AAC/C,QAAM,eAAe,QAAQ,IAAI,oBAAoB;AACrD,QAAM,SAAQ,wCAAS,UAAT,YAAkB;AAEhC,QAAM,SAAS;AAAA;AAAA;AAAA,EAGf,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCd,QAAM,MAAM,MAAM,eAAe,OAAO,QAAQ,MAAM;AACtD,QAAM,UAAU,IAAI,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAGrD,QAAM,SAAS,cAAc,OAAO;AACpC,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,EAC9D;AACA,QAAM,YAAY,uBAAuB,OAAO,KAAK;AACrD,MAAI,CAAC,UAAU,IAAI;AACjB,UAAM,IAAI,MAAM,4BAA4B,UAAU,KAAK,EAAE;AAAA,EAC/D;AACA,SAAO,UAAU;AACnB;AAGA,SAAS,uBACP,KAC2E;AAzoB7E;AA0oBE,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,WAAO,EAAE,IAAI,OAAO,OAAO,kCAAkC;AAAA,EAC/D;AACA,QAAM,IAAI;AAEV,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,OAAO,EAAE,aAAa,YAAY,CAAC,eAAe,SAAS,EAAE,QAAQ,GAAG;AAC1E,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OACE;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,OAAO,EAAE,aAAa,YAAY,CAAC,eAAe,SAAS,EAAE,QAAQ,GAAG;AAC1E,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OACE;AAAA,IACJ;AAAA,EACF;AAGA,MACE,cAAc,KACd,EAAE,EAAE,aAAa,QAAQ,OAAO,EAAE,aAAa,WAC/C;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,kCAAkC;AAAA,EAC/D;AACA,MACE,iBAAiB,KACjB,EAAE,EAAE,gBAAgB,QAAQ,OAAO,EAAE,gBAAgB,WACrD;AACA,WAAO,EAAE,IAAI,OAAO,OAAO,qCAAqC;AAAA,EAClE;AAGA,MAAI,OAAO,EAAE,gBAAgB,UAAU;AACrC,UAAM,KAAK,EAAE,YAAY,KAAK;AAC9B,QAAI,CAAC,kBAAkB,KAAK,EAAE,GAAG;AAC/B,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,UAAU,EAAE;AAAA,MACZ,UAAU,EAAE;AAAA,MACZ,UACE,OAAO,EAAE,aAAa,WAAW,EAAE,YAAY,OAAE,aAAF,YAAc;AAAA,MAC/D,aACE,OAAO,EAAE,gBAAgB,WACrB,EAAE,eACD,OAAE,gBAAF,YAAiB;AAAA,IAC1B;AAAA,EACF;AACF;AAKA,eAAsB,mBACpB,SAOA,SACqB;AAjuBvB;AAkuBE,QAAM,SAAS,iBAAiB,mCAAS,MAAM;AAC/C,QAAM,eAAe,QAAQ,IAAI,oBAAoB;AACrD,QAAM,SAAQ,wCAAS,UAAT,YAAkB;AAGhC,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,WAAW,MAAM,QAAQ,QAAQ,IAAI,IACvC,QAAQ,KAAK,MAAM,GAAG,CAAC,IACvB,CAAC;AACL,UAAM,YAAY,QAAQ,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AAClD,UAAM,cAAc,QAAQ,UAAU,IAAI,KAAK;AAC/C,UAAM,YACJ,OAAO,QAAQ,UAAU,WAAW,IAAI,QAAQ,KAAK,KAAK;AAC5D,UAAM,YAAY,aAAa,GAAG,SAAS,MAAM,UAAU,KAAK;AAChE,UAAM,kBACJ,YAAY,QAAQ,KAAK,KAAK,YAAY,aAAa,SAAS,OAAO,EAAE,uDAAuD;AAAA,MAC9H;AAAA,MACA;AAAA,IACF;AACF,UAAM,mBAAmB,GAAG,QAAQ,KAAK,WAAM,cAAc,SAAS;AACtE,UAAM,kBACJ,QAAQ,eACR,eAAe,QAAQ,KAAK;AAC9B,UAAM,gBAAgB,OAAO,QAAQ,KAAK,SAAS,YAAY,QAAQ,SAAS,KAAK,EAAE;AACvF,UAAM,MAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,SAAS,SAAS,WAAW,CAAC,OAAO,YAAY,SAAS;AAAA,MAChE;AAAA,IACF;AACA,UAAMC,aAAY,mBAAmB,GAAG;AACxC,QAAI,CAACA,WAAU;AACb,YAAM,IAAI,MAAM,gCAAgCA,WAAU,KAAK,EAAE;AACnE,WAAOA,WAAU;AAAA,EACnB;AAEA,QAAM,SAAS;AAAA;AAAA,SAA8D,QAAQ,KAAK;AAAA,eAAkB,QAAQ,eAAe,KAAK;AAAA,UAAa,QAAQ,UAAU,KAAK;AAAA,SAAY,OAAO,QAAQ,UAAU,WAAW,IAAI,QAAQ,KAAK,KAAK,KAAK;AAAA,QAAW,MAAM,QAAQ,QAAQ,IAAI,KAAK,QAAQ,KAAK,SAAS,QAAQ,KAAK,KAAK,IAAI,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEtV,QAAM,MAAM,MAAM,eAAe,OAAO,QAAQ,MAAM;AACtD,QAAM,UAAU,IAAI,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AACrD,QAAM,SAAS,cAAc,OAAO;AACpC,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,EAC9D;AACA,QAAM,YAAY,mBAAmB,OAAO,KAAK;AACjD,MAAI,CAAC,UAAU,IAAI;AACjB,UAAM,IAAI,MAAM,4BAA4B,UAAU,KAAK,EAAE;AAAA,EAC/D;AACA,SAAO,UAAU;AACnB;AAEA,SAAS,mBACP,KACgE;AAChE,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,WAAO,EAAE,IAAI,OAAO,OAAO,kCAAkC;AAAA,EAC/D;AACA,QAAM,IAAI;AACV,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,OAAO,iBAAiB;AACjC,QAAI,OAAO,EAAE,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,GAAG;AAChD,aAAO,EAAE,IAAI,OAAO,OAAO,GAAG,GAAG,8BAA8B;AAAA,IACjE;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,EAAE,IAAI,GAAG;AAC1B,WAAO,EAAE,IAAI,OAAO,OAAO,wBAAwB;AAAA,EACrD;AACA,aAAW,KAAK,EAAE,MAAM;AACtB,QAAI,OAAO,MAAM;AACf,aAAO,EAAE,IAAI,OAAO,OAAO,6BAA6B;AAAA,EAC5D;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,WAAW,OAAO,EAAE,SAAS;AAAA,MAC7B,iBAAiB,OAAO,EAAE,eAAe;AAAA,MACzC,kBAAkB,OAAO,EAAE,gBAAgB;AAAA,MAC3C,iBAAiB,OAAO,EAAE,eAAe;AAAA,MACzC,MAAM,EAAE;AAAA,MACR,eAAe,OAAO,EAAE,aAAa;AAAA,IACvC;AAAA,EACF;AACF;AAOA,eAAsB,mBACpB,WAUA,SAQA;AAv1BF;AAw1BE,QAAM,SAAS,iBAAiB,mCAAS,MAAM;AAC/C,QAAM,eAAe,QAAQ,IAAI,oBAAoB;AACrD,QAAM,SAAQ,wCAAS,UAAT,YAAkB;AAGhC,QAAM,eACJ,MAAM,QAAQ,UAAU,SAAS,QAAQ,IACrC,UAAU,SAAS,SAAS,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,MAAW;AACvD,QAAI,OAAO,MAAM,SAAU,QAAO,KAAK,CAAC;AACxC,UAAM,KACJ,QAAO,uBAAG,iBAAgB,YAAY,EAAE,YAAY,KAAK,IACrD,EAAE,cACF;AACN,WAAO,KAAK,QAAO,uBAAG,UAAS,KAAK,CAAC,KAAK,EAAE;AAAA,EAC9C,CAAC,IACD,CAAC;AAEP,QAAM,kBACJ,MAAM,QAAQ,UAAU,SAAS,WAAW,IACxC,UAAU,SAAS,YAAY,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAW;AACzD,QAAI,OAAO,MAAM,SAAU,QAAO,KAAK,CAAC;AACxC,WAAO,KAAK,QAAO,uBAAG,UAAS,KAAK,CAAC;AAAA,EACvC,CAAC,IACD,CAAC;AAGP,QAAM,eAAe,gBAAgB,UAAU,KAAK;AAAA,sBACjC,eAAU,gBAAV,YAAyB,KAAK;AAAA;AAAA;AAAA,EAE/B,aAAa,KAAK,IAAI,KAAK,OAAO;AAAA;AAAA;AAAA,EAE/B,gBAAgB,KAAK,IAAI,KAAK,OAAO;AAC1D,QAAM,iBACJ,GAAG,UAAU,KAAK,KAAI,eAAU,gBAAV,YAAyB,EAAE,IAAI,aAAa,KAAK,GAAG,CAAC,IAAI,gBAAgB,KAAK,GAAG,CAAC,GAAG,YAAY;AAGzH,MAAI,QAAQ,IAAI,uBAAuB,KAAK;AAC1C,UAAM,OACJ,GAAG,UAAU,KAAK,KAAI,eAAU,gBAAV,YAAyB,EAAE,IAAI,aAAa,KAAK,GAAG,CAAC,IAAI,gBAAgB,KAAK,GAAG,CAAC,GAAG,YAAY;AACzH,UAAM,mBAA2C;AAAA,MAC/C,UACE;AAAA,MACF,QAAQ;AAAA,MACR,aACE;AAAA,MACF,cAAc;AAAA,MACd,sBACE;AAAA,IACJ;AAEA,UAAM,mBAA2C;AAAA,MAC/C,KAAK;AAAA,MACL,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AACA,UAAM,YAAiD,CAAC;AACxD,SAAI,sBAAiB,QAAjB,mBAAsB,KAAK,OAAO;AACpC,WAAI,sBAAiB,aAAjB,mBAA2B,KAAK,MAAO,WAAU,KAAK,UAAU;AACpE,WAAI,sBAAiB,eAAjB,mBAA6B,KAAK,MAAO,WAAU,KAAK,YAAY;AACxE,UACE,GAAC,sBAAiB,aAAjB,mBAA2B,KAAK,UACjC,GAAC,sBAAiB,eAAjB,mBAA6B,KAAK;AAEnC,kBAAU,KAAK,SAAS;AAAA,IAC5B,OAAO;AACL,WAAI,sBAAiB,eAAjB,mBAA6B,KAAK,MAAO,WAAU,KAAK,YAAY;AACxE,WAAI,sBAAiB,iBAAjB,mBAA+B,KAAK;AACtC,kBAAU,KAAK,cAAc;AAC/B,UAAI,UAAU,WAAW,EAAG,WAAU,KAAK,SAAS;AAAA,IACtD;AAGA,UAAM,YAAY,OAAO,QAAQ,gBAAgB,EAC9C,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,IAAI,CAAC,EAChC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAsC;AACtD,QAAI,UAAU,WAAW,EAAG,WAAU,KAAK,aAAa;AAGxD,UAAM,YAAY,aAAa,KAAK,GAAG,EAAE,YAAY;AACrD,UAAM,cAAsC;AAAA,MAC1C,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO;AAAA,MACP,WAAW;AAAA,IACb;AACA,UAAM,aAAa,OAAO,QAAQ,WAAW,EAC1C,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,SAAS,CAAC,EACrC,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AACvB,UAAM,oBAAoB,WAAW,SAAS,aAAa,CAAC,SAAS;AAErE,UAAM,YAKF,CAAC;AACL,eAAW,OAAO,WAAW;AAC3B,gBAAU,GAAG,IAAI,UAAU,GAAG,KAAK,CAAC;AACpC,iBAAW,KAAK,WAAW;AACzB,kBAAU,GAAG,EAAG,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,iBAAiB,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,WAAO,yBAAyB,WAAW,cAAc;AAAA,EAC3D;AAEA,QAAM,SAAS;AAAA;AAAA,EAEf,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeZ,QAAM,MAAM,MAAM,eAAe,OAAO,QAAQ,MAAM;AACtD,QAAM,UAAU,IAAI,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AACrD,QAAM,SAAS,cAAc,OAAO;AACpC,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,8BAA8B,OAAO,KAAK,EAAE;AAAA,EAC9D;AACA,QAAM,YAAY,2BAA2B,OAAO,KAAK;AACzD,MAAI,CAAC,UAAU,IAAI;AACjB,UAAM,IAAI,MAAM,4BAA4B,UAAU,KAAK,EAAE;AAAA,EAC/D;AACA,SAAO,yBAAyB,UAAU,OAAO,cAAc;AACjE;AAEA,SAAS,2BAA2B,KAUH;AAC/B,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACzD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,IAAI;AACV,QAAM,MAKF,CAAC;AACL,QAAM,OAAO,OAAO,KAAK,CAAC;AAC1B,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO,EAAE,IAAI,OAAO,OAAO,wCAAwC;AAAA,EACrE;AACA,aAAW,QAAQ,MAAM;AACvB,QAAI,CAAC,aAAa,SAAS,IAAW,GAAG;AACvC,aAAO,EAAE,IAAI,OAAO,OAAO,yBAAyB,IAAI,GAAG;AAAA,IAC7D;AACA,UAAM,OAAO,EAAE,IAAI;AACnB,QAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GAAG;AAC5D,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF;AACA,UAAM,OACJ,CAAC;AACH,eAAW,QAAQ,OAAO,KAAK,IAA+B,GAAG;AAC/D,UAAI,CAAC,aAAa,SAAS,IAAW,GAAG;AACvC,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,OAAO,wBAAwB,IAAI,iBAAiB,IAAI;AAAA,QAC1D;AAAA,MACF;AACA,YAAM,OAAQ,KAAa,IAAI;AAC/B,UACE,CAAC,MAAM,QAAQ,IAAI,KACnB,KAAK,WAAW,KAChB,CAAC,KAAK,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,KAAK,CAAC,GACpD;AACA,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,OAAO,YAAY,IAAI,iBAAiB,IAAI;AAAA,QAC9C;AAAA,MACF;AACA,WAAK,IAAyC,IAAI,KAAK;AAAA,QAAI,CAAC,MAC1D,EAAE,KAAK;AAAA,MACT;AAAA,IACF;AACA,QAAI,IAAyC,IAAI;AAAA,EACnD;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,IAAI;AAChC;AAEO,SAAS,yBACd,WAMA,MAMA;AAvkCF;AAwkCE,QAAM,mBAA2C;AAAA,IAC/C,KAAK;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AACA,QAAM,mBAA2C;AAAA,IAC/C,UACE;AAAA,IACF,QAAQ;AAAA,IACR,aACE;AAAA;AAAA;AAAA,IAGF,cACE;AAAA,IACF,sBAAsB;AAAA,EACxB;AAEA,QAAM,oBAAoB,oBAAI,IAAuC;AACrE,OAAI,sBAAiB,QAAjB,mBAAsB,KAAK,OAAO;AACpC,SAAI,sBAAiB,aAAjB,mBAA2B,KAAK;AAClC,wBAAkB,IAAI,UAAU;AAClC,SAAI,sBAAiB,eAAjB,mBAA6B,KAAK;AACpC,wBAAkB,IAAI,YAAY;AACpC,QACE,GAAC,sBAAiB,aAAjB,mBAA2B,KAAK,UACjC,GAAC,sBAAiB,eAAjB,mBAA6B,KAAK;AAEnC,wBAAkB,IAAI,SAAS;AAAA,EACnC,OAAO;AACL,SAAI,sBAAiB,eAAjB,mBAA6B,KAAK;AACpC,wBAAkB,IAAI,YAAY;AACpC,SAAI,sBAAiB,iBAAjB,mBAA+B,KAAK;AACtC,wBAAkB,IAAI,cAAc;AACtC,QAAI,kBAAkB,SAAS,EAAG,mBAAkB,IAAI,SAAS;AAAA,EACnE;AAEA,QAAM,oBAAoB,IAAI;AAAA,IAC5B,OAAO,QAAQ,gBAAgB,EAC5B,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,IAAI,CAAC,EAChC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAsC,KAAK,CAAC;AAAA,EAC9D;AACA,MAAI,kBAAkB,SAAS,EAAG,mBAAkB,IAAI,aAAa;AAErE,QAAM,SAKF,CAAC;AACL,aAAW,CAAC,UAAU,SAAS,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC7D,UAAM,IAAI;AACV,QAAI,CAAC,kBAAkB,IAAI,CAAC,EAAG;AAC/B,UAAM,OACJ,CAAC;AACH,eAAW,CAAC,UAAU,UAAU,KAAK,OAAO,QAAQ,aAAa,CAAC,CAAC,GAAG;AACpE,YAAM,IAAI;AACV,UAAI,CAAC,kBAAkB,IAAI,CAAC,EAAG;AAC/B,WAAK,CAAC,IAAI;AAAA,IACZ;AACA,QAAI,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAChC,aAAO,CAAC,IAAI;AAAA,IACd;AAAA,EACF;AAGA,MAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AACpC,UAAM,OACJ,CAAC;AACH,eAAW,KAAK,MAAM,KAAK,iBAAiB,GAAG;AAC7C,WAAK,CAAC,IAAI,CAAC,SAAS;AAAA,IACtB;AACA,WAAO,UAAU;AAAA,EACnB;AAGA,QAAM,eACH,OAAO,cAAc,OAAO,KAAK,OAAO,UAAU,EAAE,SAAS,KAC7D,OAAO,gBAAgB,OAAO,KAAK,OAAO,YAAY,EAAE,SAAS;AACpE,MAAI,cAAc;AAChB,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO;AACT;;;ADzkCO,SAAS,wBACd,SACA,aACA,eACA,aACA,YACA,cACA,aACmB;AAGnB,WAAS,sBACP,SACA,UACS;AAnGb;AAoGI,UAAM,YAAW,mBAAQ,aAAR,YAAoB,QAAQ,UAA5B,YAAqC;AACtD,UAAM,YAAW,mBAAQ,aAAR,YAAoB,QAAQ,UAA5B,YAAqC;AACtD,UAAM,gBACJ,mBAAQ,sBAAR,YAA6B,QAAQ,mBAArC,YAAuD;AACzD,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,kBAAkB;AAAA,QAChB;AAAA,QACA,gBAAgB,YAAY,UAAU,QAAQ;AAAA,QAC9C,mBAAmB,YAAY,UAAU,QAAQ;AAAA,QACjD,mBAAmB,YAAY,UAAU,QAAQ;AAAA,QACjD,yBAAyB,YAAY,cAAc,QAAQ;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAEA,WAAS,8BACP,UACA,UACkB;AAClB,QAAI,CAAC,YAAY,CAAC,SAAU,QAAO;AACnC,WAAO,SAAS,IAAI,CAAC,MAAM,sBAAsB,GAAG,QAAQ,CAAC;AAAA,EAC/D;AAEA,QAAM,aAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmBpC,KAAK,OAAO,YAEqB;AAC/B,YAAM,QAAQ;AACd,YAAM,cAAyB,CAAC;AAEhC,qBAAe,WAAW;AACxB,YAAI,cAAc;AAElB,eAAO,MAAM;AACX,gBAAM,WAAW,MAAM,cAAc,aAAa,KAAK;AAEvD,cAAI,CAAC,YAAY,SAAS,WAAW,KAAK,SAAS,SAAS,OAAO;AACjE,gBAAI,YAAY,SAAS,SAAS,GAAG;AACnC,0BAAY,KAAK,GAAG,QAAQ;AAAA,YAC9B;AACA;AAAA,UACF;AAEA,sBAAY,KAAK,GAAG,QAAQ;AAC5B;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,SAAS;AAChC,eAAO,8BAA8B,UAAU,mCAAS,QAAQ;AAAA,MAClE,SAAS,OAAO;AACd,gBAAQ,MAAM,iCAAiC,aAAa,KAAK;AACjE,cAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAwBA,WAAW,OAAO,YAIe;AA5MrC;AA6MM,YAAM,QAAO,wCAAS,SAAT,YAAiB;AAC9B,YAAM,QAAQ,KAAK,KAAI,wCAAS,UAAT,YAAkB,KAAK,GAAG;AACjD,YAAM,MAAM,GAAG,OAAO,uBAAuB,KAAK,SAAS,IAAI;AAE/D,UAAI;AACF,cAAM,WAAW,MAAM,iBAAiB,GAAG;AAC3C,YAAI,CAAC,SAAS,IAAI;AAChB,kBAAQ;AAAA,YACN,uBAAuB,SAAS,MAAM,QAAQ,WAAW,SAAS,IAAI;AAAA,UACxE;AACA,gBAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,EAAE;AAAA,QAC1D;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAGlC,YAAI,KAAK,SAAS,WAAW,GAAG;AAC9B,iBAAO,CAAC;AAAA,QACV;AACA,cAAM,aAAa,YAAY,KAAK,QAAQ;AAC5C,eAAO,8BAA8B,YAAY,mCAAS,QAAQ;AAAA,MACpE,SAAS,OAAO;AACd,gBAAQ;AAAA,UACN,+BAA+B,WAAW,SAAS,IAAI,eAAe,KAAK;AAAA,UAC3E;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA2BA,MAAM,OACJ,eACA,YAC4B;AAvQlC;AAyQM,UAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAEA,UAAI;AACF,YAAI,KAAoB;AACxB,YAAI,cAAc,SAAS,GAAG,GAAG;AAC/B,gBAAM,QAAQ,cAAc,MAAM,GAAG;AACrC,gBAAM,cAAa,WAAM,CAAC,MAAP,YAAY;AAC/B,gBAAM,UAAS,WAAM,CAAC,MAAP,YAAY;AAC3B,0BAAgB;AAChB,eAAK;AAAA,QACP;AAGA,cAAM,kBAAkB,cACrB,KAAK,EACL,QAAQ,oBAAoB,EAAE;AACjC,YAAI,CAAC,iBAAiB;AACpB,gBAAM,IAAI,MAAM,+BAA+B;AAAA,QACjD;AAGA,YAAI,gBAAgB,SAAS,KAAK;AAChC,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAGA,YAAI,cAAc;AAClB,YAAI;AACF,gBAAM,WAAW,MAAM;AAAA,YACrB,GAAG,OAAO,YAAY,mBAAmB,eAAe,CAAC;AAAA,UAC3D;AACA,cAAI,SAAS,IAAI;AACf,kBAAM,WAAW,SAAS;AAC1B,gBAAI,UAAU;AACZ,oBAAM,WAAW,IAAI,IAAI,QAAQ,EAAE,SAAS,QAAQ,OAAO,EAAE;AAC7D,oBAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAChD,oBAAM,MAAM,MAAM,QAAQ,UAAU;AACpC,oBAAM,cAAc,OAAO,IAAI,MAAM,MAAM,CAAC,IAAI;AAChD,kBAAI,OAAO,gBAAgB,YAAY,YAAY,QAAQ;AACzD,8BAAc;AAAA,cAChB;AAAA,YACF;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAEA,cAAM,MAAM,GAAG,OAAO,YAAY,mBAAmB,WAAW,CAAC,MAAM,KAAK,IAAI,EAAE,KAAK,EAAE;AACzF,cAAM,WAAW,MAAM,iBAAiB,GAAG;AAE3C,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,mBAAO;AAAA,UACT;AACA,gBAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,EAAE;AAAA,QAC1D;AAEA,cAAM,UAAW,MAAM,SAAS,KAAK;AACrC,cAAM,cAAc,WAAW,OAAO;AACtC,gBAAO,mCAAS,YACZ,sBAAsB,aAAa,QAAQ,QAAQ,IACnD;AAAA,MACN,SAAS,OAAO;AACd,YAAI,iBAAiB,OAAO;AAC1B,kBAAQ;AAAA,YACN,0BAA0B,aAAa;AAAA,YACvC;AAAA,YACA,MAAM;AAAA,UACR;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,UAAU,OACR,eACA,YAO4B;AAC5B,UAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAEA,YAAM,UAAS,mCAAS,WAAU,QAAQ,IAAI;AAC9C,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAGA,YAAM,cAAc,MAAM,WAAW,KAAK,aAAa;AACvD,UAAI,CAAC,aAAa;AAChB,eAAO;AAAA,MACT;AAGA,YAAM,SAAS,YAAY;AAC3B,YAAM,WAAW,MAAM,cAAc,aAAa,QAAQ;AAAA,QACxD;AAAA,QACA,QAAQ,mCAAS;AAAA,QACjB,WAAW,mCAAS;AAAA,QACpB,OAAO,mCAAS;AAAA,QAChB,cAAc,mCAAS;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,QACL,GAAG;AAAA,QACH,kBAAkB,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,UAAU,OACR,eACA,YAC0C;AAC1C,UAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AACA,YAAM,UAAS,mCAAS,WAAU,QAAQ,IAAI;AAC9C,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,kBAAkB,MAAM,WAAW,SAAS,eAAe;AAAA,QAC/D;AAAA,QACA,WAAW;AAAA,QACX,OAAO,mCAAS;AAAA,QAChB,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,CAAC,mBAAmB,CAAC,gBAAgB,iBAAkB,QAAO;AAElE,UAAI,iBAAiB,gBAAgB;AACrC,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,gBAAgB,gBAAgB;AACvD,cAAM,QAAkB,CAAC;AACzB,YAAI,IAAI,SAAS,OAAO,IAAI,UAAU;AACpC,gBAAM,KAAK,UAAU,IAAI,KAAK,EAAE;AAClC,YAAI,IAAI,eAAe,OAAO,IAAI,gBAAgB;AAChD,gBAAM,KAAK,gBAAgB,IAAI,WAAW,EAAE;AAC9C,YAAI,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU;AAChD,gBAAM,KAAK,cAAc,IAAI,UAAU,KAAK,IAAI,CAAC,EAAE;AACrD,YAAI,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,KAAK;AACtC,gBAAM,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE;AAC3C,YAAI,IAAI,OAAO,OAAO,IAAI,QAAQ;AAChC,gBAAM,KAAK,QAAQ,IAAI,GAAG,EAAE;AAC9B,YAAI,IAAI,gBAAgB,OAAO,IAAI,iBAAiB;AAClD,gBAAM,KAAK,iBAAiB,IAAI,YAAY,EAAE;AAChD,yBAAiB,MAAM,KAAK,IAAI;AAAA,MAClC,QAAQ;AAAA,MAER;AAEA,YAAM,iBAAiB,MAAM,gBAAgB,gBAAgB;AAAA,QAC3D;AAAA,QACA,OAAO,mCAAS;AAAA,MAClB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,oBAAoB,OAClB,eACA,YAC+B;AAC/B,UAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AACA,YAAM,UAAS,mCAAS,WAAU,QAAQ,IAAI;AAC9C,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,YAAM,cAAc,MAAM,WAAW,KAAK,aAAa;AACvD,UAAI,CAAC,YAAa,QAAO;AAEzB,YAAM,UAAU;AAAA,QACd,OAAO,YAAY;AAAA,QACnB,aAAa,YAAY,YAAY;AAAA,QACrC,QAAQ,YAAY;AAAA,QACpB,OAAO,YAAY;AAAA,QACnB,MAAM,YAAY;AAAA,MACpB;AAEA,YAAM,MAAM,MAAM,mBAAsB,SAAS;AAAA,QAC/C;AAAA,QACA,OAAO,mCAAS;AAAA,MAClB,CAAC;AACD,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAoBA,WAAW,YAAY;AACrB,YAAM,YAAY,MAAM,aAAa;AACrC,YAAM,WAAW,MAAM,QAAQ;AAAA,QAC7B,UAAU,SAAS,SAAS;AAAA,UAAI,CAAC,kBAC/B,YAAY,aAAa;AAAA,QAC3B;AAAA,MACF;AACA,aAAO,OAAO,UAAU,YAAY;AAAA,IACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAuBA,QAAQ,YAAsD;AAC5D,UAAI;AAEF,cAAM,WAAW,MAAM,WAAW,IAAI;AACtC,YAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,iBAAO,CAAC;AAAA,QACV;AAGA,cAAM,YAAyC,CAAC;AAGhD,iBAAS,QAAQ,CAAC,YAAY;AAC5B,cAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AAEnD,gBAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,GAAG;AACjD,sBAAQ,QAAQ,QAAQ,CAAC,WAAW;AAClC,sBAAM,sBAAsB,OAAO,KAAK,YAAY;AACpD,oBAAI,CAAC,UAAU,mBAAmB,GAAG;AACnC,4BAAU,mBAAmB,IAAI,oBAAI,IAAI;AAAA,gBAC3C;AAEA,uBAAO,OAAO,QAAQ,CAAC,UAAU;AAC/B,wBAAM,UAAU,+BAAO;AACvB,sBAAI,SAAS;AACX,wBAAI,MAAM,UAAU,mBAAmB;AACvC,wBAAI,CAAC,KAAK;AACR,4BAAM,oBAAI,IAAY;AACtB,gCAAU,mBAAmB,IAAI;AAAA,oBACnC;AACA,wBAAI,IAAI,QAAQ,YAAY,CAAC;AAAA,kBAC/B;AAAA,gBACF,CAAC;AAAA,cACH,CAAC;AAAA,YACH;AAGA,oBAAQ,SAAS,QAAQ,CAAC,YAAY;AA1iBlD;AA2iBc,kBAAI,QAAQ,SAAS;AACnB,sBAAM,gBACJ,mBAAQ,YAAR,mBAAkB,OAAlB,mBAAsB,SAAQ,YAC9B,YAAY;AACd,oBAAI,OAAO,UAAU,UAAU;AAC/B,oBAAI,CAAC,MAAM;AACT,yBAAO,oBAAI,IAAY;AACvB,4BAAU,UAAU,IAAI;AAAA,gBAC1B;AACA,qBAAK,IAAI,QAAQ,QAAQ,KAAK,EAAE,YAAY,CAAC;AAAA,cAC/C;AAEA,kBAAI,QAAQ,SAAS;AACnB,sBAAM,gBACJ,mBAAQ,YAAR,mBAAkB,OAAlB,mBAAsB,SAAQ,YAC9B,YAAY;AACd,oBAAI,OAAO,UAAU,UAAU;AAC/B,oBAAI,CAAC,MAAM;AACT,yBAAO,oBAAI,IAAY;AACvB,4BAAU,UAAU,IAAI;AAAA,gBAC1B;AACA,qBAAK,IAAI,QAAQ,QAAQ,KAAK,EAAE,YAAY,CAAC;AAAA,cAC/C;AAEA,kBAAI,QAAQ,SAAS;AACnB,sBAAM,gBACJ,mBAAQ,YAAR,mBAAkB,OAAlB,mBAAsB,SAAQ,YAC9B,YAAY;AACd,oBAAI,CAAC,UAAU,UAAU,GAAG;AAC1B,4BAAU,UAAU,IAAI,oBAAI,IAAI;AAAA,gBAClC;AACA,0BAAU,UAAU,EAAE,IAAI,QAAQ,QAAQ,KAAK,EAAE,YAAY,CAAC;AAAA,cAChE;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAGD,cAAM,SAAmC,CAAC;AAC1C,eAAO,QAAQ,SAAS,EAAE,QAAQ,CAAC,CAAC,YAAY,QAAQ,MAAM;AAC5D,iBAAO,UAAU,IAAI,MAAM,KAAK,QAAQ,EAAE,KAAK;AAAA,QACjD,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,qCAAqC,aAAa,KAAK;AACrE,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":["_a","validated"]}