@opendata-ai/openchart-vanilla 7.11.0 → 8.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-EQ6DYFO7.js → chunk-5EOV5JQZ.js} +431 -538
- package/dist/chunk-5EOV5JQZ.js.map +1 -0
- package/dist/chunk-ENXSUXC5.js +6513 -0
- package/dist/chunk-ENXSUXC5.js.map +1 -0
- package/dist/chunk-W34KN7FD.js +298 -0
- package/dist/chunk-W34KN7FD.js.map +1 -0
- package/dist/index.d.ts +110 -116
- package/dist/index.js +189 -4408
- package/dist/index.js.map +1 -1
- package/dist/mount-CUKQLeqD.d.ts +207 -0
- package/dist/static.js +16 -11
- package/dist/static.js.map +1 -1
- package/dist/story/index.d.ts +277 -0
- package/dist/story/index.js +537 -0
- package/dist/story/index.js.map +1 -0
- package/dist/styles.css +2 -1
- package/dist/styles.css.map +1 -0
- package/package.json +9 -3
- package/src/__test-fixtures__/specs.ts +1 -1
- package/src/__tests__/annotations-render.test.ts +201 -0
- package/src/__tests__/continuous-legend.test.ts +91 -0
- package/src/__tests__/edit-events.test.ts +155 -0
- package/src/__tests__/map.test.ts +293 -0
- package/src/__tests__/mount.test.ts +26 -0
- package/src/__tests__/pattern-fills.test.ts +105 -0
- package/src/__tests__/series-search.test.ts +311 -0
- package/src/__tests__/table-mount.test.ts +34 -0
- package/src/__tests__/tooltip.test.ts +26 -0
- package/src/__tests__/transition.test.ts +196 -11
- package/src/__tests__/you-draw-it.test.ts +273 -0
- package/src/animation-vars.ts +42 -0
- package/src/barlist-renderer.ts +2 -2
- package/src/dom-helpers.ts +17 -0
- package/src/export.ts +33 -16
- package/src/index.ts +7 -0
- package/src/interactions/editing-drags.ts +9 -6
- package/src/interactions/legend-interaction.ts +9 -1
- package/src/interactions/selection.ts +12 -3
- package/src/map-camera.ts +88 -0
- package/src/map-mount.ts +701 -0
- package/src/map-renderer.ts +338 -0
- package/src/map-transition.ts +83 -0
- package/src/mount.ts +212 -26
- package/src/pattern-utils.ts +110 -0
- package/src/renderers/annotations.ts +162 -117
- package/src/renderers/axes.ts +13 -6
- package/src/renderers/brand.ts +7 -2
- package/src/renderers/chrome.ts +32 -10
- package/src/renderers/legend.ts +171 -2
- package/src/renderers/marks.ts +33 -5
- package/src/sankey-renderer.ts +7 -11
- package/src/series-search.ts +392 -0
- package/src/static.ts +13 -8
- package/src/story/__tests__/camera-math.test.ts +145 -0
- package/src/story/__tests__/create-chart-story.test.ts +317 -0
- package/src/story/__tests__/progress-math.test.ts +95 -0
- package/src/story/__tests__/scroll-driver.test.ts +130 -0
- package/src/story/__tests__/tween.test.ts +159 -0
- package/src/story/camera-math.ts +125 -0
- package/src/story/create-chart-story.ts +353 -0
- package/src/story/crossfade.ts +70 -0
- package/src/story/index.ts +39 -0
- package/src/story/progress-math.ts +85 -0
- package/src/story/resolve-camera-target.ts +119 -0
- package/src/story/scroll-driver.ts +206 -0
- package/src/story/story-camera.ts +49 -0
- package/src/story/tween.ts +112 -0
- package/src/story/types.ts +76 -0
- package/src/svg-renderer.ts +60 -29
- package/src/table-mount.ts +12 -3
- package/src/table-renderer.ts +9 -28
- package/src/text-edit-overlay.ts +1 -1
- package/src/theme-tokens.ts +4 -4
- package/src/tilemap-mount.ts +27 -6
- package/src/tilemap-renderer.ts +30 -88
- package/src/tooltip.ts +11 -0
- package/src/transition.ts +376 -33
- package/src/you-draw-it.ts +480 -0
- package/dist/chunk-EQ6DYFO7.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/export.ts","../src/resize-observer.ts","../src/tooltip.ts","../src/story/tween.ts","../src/story/camera-math.ts","../src/map-mount.ts","../src/animation.ts","../src/map-camera.ts","../src/map-renderer.ts","../../../node_modules/.bun/d3-color@3.1.0/node_modules/d3-color/src/define.js","../../../node_modules/.bun/d3-color@3.1.0/node_modules/d3-color/src/color.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/basis.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/basisClosed.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/constant.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/color.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/rgb.js","../src/map-transition.ts","../src/measure-text.ts","../src/text-edit-overlay.ts","../src/you-draw-it.ts","../src/mount.ts","../src/interactions/chart-events.ts","../src/interactions/crosshair.ts","../src/interactions/drag-handler.ts","../src/interactions/editing-drags.ts","../src/interactions/keyboard-nav.ts","../src/interactions/legend-interaction.ts","../src/interactions/selection.ts","../src/interactions/tooltip-events.ts","../src/series-search.ts","../src/theme-tokens.ts","../src/transition.ts"],"sourcesContent":["/**\n * Export utilities: serialize charts to SVG, PNG, JPG, or CSV.\n *\n * - SVG: serializes the rendered DOM element via XMLSerializer\n * - SVG with fonts: async version that embeds @font-face data URIs\n * - PNG: renders SVG to canvas, then extracts as Blob\n * - JPG: same as PNG but with JPEG compression and background fill\n * - CSV: converts a data array to comma-separated text\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SVGExportOptions {\n /** Embed fonts as base64 data URIs in the SVG. Defaults to true. */\n embedFonts?: boolean;\n}\n\nexport interface PNGExportOptions extends SVGExportOptions {\n /** DPI scaling factor. Defaults to 2 for retina-quality output. */\n dpi?: number;\n}\n\nexport interface JPGExportOptions extends PNGExportOptions {\n /** JPEG quality from 0 to 1. Defaults to 0.92. */\n quality?: number;\n}\n\ninterface FontFaceData {\n family: string;\n weight: string;\n style: string;\n base64: string;\n format: string;\n}\n\n// ---------------------------------------------------------------------------\n// Dimension parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Extract dimensions from an SVG element, trying width/height attributes\n * first, then falling back to viewBox.\n */\nfunction getSVGDimensions(svg: SVGElement): { width: number; height: number } {\n const w = parseFloat(svg.getAttribute('width') || '');\n const h = parseFloat(svg.getAttribute('height') || '');\n if (w && h) return { width: w, height: h };\n\n const vb = svg.getAttribute('viewBox');\n if (vb) {\n const parts = vb.split(/[\\s,]+/).map(Number);\n if (parts.length >= 4 && parts[2] && parts[3]) {\n return { width: parts[2], height: parts[3] };\n }\n }\n\n return { width: 600, height: 400 };\n}\n\n/**\n * Ensure an SVG string has explicit width/height attributes.\n *\n * When an SVG only has a viewBox (no width/height), browsers loading it as\n * an Image blob may use 300x150 as the intrinsic size instead of the viewBox\n * dimensions. This causes clipping at non-1x DPI scaling. Injecting explicit\n * width/height into the root <svg> tag fixes the intrinsic size.\n */\nfunction ensureSVGDimensions(svgString: string, width: number, height: number): string {\n // If the <svg> already has a width attribute, leave it alone\n if (/^<svg[^>]*\\swidth\\s*=/.test(svgString)) return svgString;\n // Inject width and height right after <svg\n return svgString.replace(/^(<svg)/, `$1 width=\"${width}\" height=\"${height}\"`);\n}\n\n// ---------------------------------------------------------------------------\n// Font embedding\n// ---------------------------------------------------------------------------\n\n/**\n * Collect unique font-family + font-weight combos from all <text> elements.\n */\nfunction collectUsedFonts(svgElement: SVGElement): Map<string, Set<string>> {\n const fonts = new Map<string, Set<string>>();\n const textElements = svgElement.querySelectorAll('text');\n\n for (const el of textElements) {\n const family = el.getAttribute('font-family');\n const weight = el.getAttribute('font-weight') || '400';\n if (family) {\n // Take the first font in the stack (e.g., \"Inter, sans-serif\" → \"Inter\")\n const primary = family.split(',')[0].trim().replace(/[\"']/g, '');\n if (!fonts.has(primary)) fonts.set(primary, new Set());\n fonts.get(primary)!.add(String(weight));\n }\n }\n\n return fonts;\n}\n\n/**\n * Find @font-face rules in document stylesheets that match the requested fonts.\n * Returns the src URLs for .woff2 files.\n */\nfunction findFontFaceRules(\n usedFonts: Map<string, Set<string>>,\n): Array<{ family: string; weight: string; style: string; url: string; format: string }> {\n const results: Array<{\n family: string;\n weight: string;\n style: string;\n url: string;\n format: string;\n }> = [];\n\n try {\n for (const sheet of document.styleSheets) {\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n // Cross-origin stylesheet, skip\n continue;\n }\n\n for (const rule of rules) {\n if (!(rule instanceof CSSFontFaceRule)) continue;\n\n const familyRaw = rule.style.getPropertyValue('font-family').replace(/[\"']/g, '').trim();\n const weight = rule.style.getPropertyValue('font-weight') || '400';\n const style = rule.style.getPropertyValue('font-style') || 'normal';\n const src = rule.style.getPropertyValue('src');\n\n const weights = usedFonts.get(familyRaw);\n if (!weights) continue;\n\n // Check if this weight is used (handle ranges like \"100 900\")\n const weightMatch = weights.has(weight) || weight.includes(' ');\n if (!weightMatch) continue;\n\n // Extract woff2 URL from src descriptor\n const woff2Match = src.match(/url\\([\"']?([^\"')]+\\.woff2[^\"')]*?)[\"']?\\)/);\n if (woff2Match) {\n results.push({\n family: familyRaw,\n weight,\n style,\n url: woff2Match[1],\n format: 'woff2',\n });\n }\n }\n }\n } catch {\n // Stylesheet access failed entirely, return empty\n }\n\n return results;\n}\n\n/**\n * Fetch font files and convert to base64 data URIs.\n */\nasync function fetchFontsAsBase64(\n fontRules: Array<{ family: string; weight: string; style: string; url: string; format: string }>,\n): Promise<FontFaceData[]> {\n const results: FontFaceData[] = [];\n\n const fetches = fontRules.map(async (rule) => {\n try {\n const response = await fetch(rule.url);\n if (!response.ok) return;\n const buffer = await response.arrayBuffer();\n const base64 = arrayBufferToBase64(buffer);\n results.push({\n family: rule.family,\n weight: rule.weight,\n style: rule.style,\n base64,\n format: rule.format,\n });\n } catch {\n // Font fetch failed (CORS, network, etc.) - skip this font\n }\n });\n\n await Promise.all(fetches);\n return results;\n}\n\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Inject @font-face rules with base64 data URIs into the SVG's <defs>.\n */\nfunction injectFontsIntoSVG(svgElement: SVGElement, fonts: FontFaceData[]): void {\n if (fonts.length === 0) return;\n\n const cssRules = fonts\n .map(\n (f) =>\n `@font-face { font-family: '${f.family}'; font-weight: ${f.weight}; font-style: ${f.style}; src: url(data:font/${f.format};base64,${f.base64}) format('${f.format}'); }`,\n )\n .join('\\n');\n\n const ns = 'http://www.w3.org/2000/svg';\n let defs = svgElement.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS(ns, 'defs');\n svgElement.insertBefore(defs, svgElement.firstChild);\n }\n\n const styleEl = document.createElementNS(ns, 'style');\n styleEl.textContent = cssRules;\n defs.insertBefore(styleEl, defs.firstChild);\n}\n\n/**\n * Embed fonts into an SVG element by finding matching @font-face rules\n * in the page's stylesheets, fetching the font files, and injecting\n * them as base64 data URIs.\n *\n * Modifies the SVG element in place. Call this before serialization.\n * If font fetching fails for any font, that font is silently skipped\n * and the export proceeds with system font fallback for that face.\n */\nasync function embedFonts(svgElement: SVGElement): Promise<void> {\n const usedFonts = collectUsedFonts(svgElement);\n if (usedFonts.size === 0) return;\n\n const fontRules = findFontFaceRules(usedFonts);\n if (fontRules.length === 0) return;\n\n const fontData = await fetchFontsAsBase64(fontRules);\n injectFontsIntoSVG(svgElement, fontData);\n}\n\n// ---------------------------------------------------------------------------\n// SVG background color\n// ---------------------------------------------------------------------------\n\n/**\n * Read the chart's background color from its first rect element.\n */\nfunction getSVGBackgroundColor(svgElement: SVGElement): string {\n const firstRect = svgElement.querySelector('rect');\n return firstRect?.getAttribute('fill') || '#ffffff';\n}\n\n// ---------------------------------------------------------------------------\n// SVG export\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize an SVG element to an XML string.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @returns The SVG markup as a string.\n */\nexport function exportSVG(svgElement: SVGElement): string {\n if (!svgElement.getAttribute('xmlns')) {\n svgElement.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n }\n const serializer = new XMLSerializer();\n return serializer.serializeToString(svgElement);\n}\n\n/**\n * Serialize an SVG element with embedded fonts to an XML string.\n *\n * Collects font-family declarations from the SVG's text elements,\n * finds matching @font-face rules in the page's stylesheets, fetches\n * the font files, and embeds them as base64 data URIs. The resulting\n * SVG is self-contained and renders correctly without external fonts.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @param options - Export options.\n * @returns A Promise resolving to the SVG markup as a string.\n */\nexport async function exportSVGWithFonts(\n svgElement: SVGElement,\n options?: SVGExportOptions,\n): Promise<string> {\n const clone = svgElement.cloneNode(true) as SVGElement;\n const shouldEmbed = options?.embedFonts ?? true;\n if (shouldEmbed) {\n await embedFonts(clone);\n }\n return exportSVG(clone);\n}\n\n// ---------------------------------------------------------------------------\n// Raster export (PNG / JPG)\n// ---------------------------------------------------------------------------\n\n/**\n * Render an SVG element to a PNG Blob via a canvas.\n *\n * Embeds fonts by default so the exported image matches on-screen rendering.\n * Set `embedFonts: false` to skip font embedding for faster exports.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling and font embedding.\n * @returns A Promise resolving to the PNG Blob.\n */\nexport async function exportPNG(svgElement: SVGElement, options?: PNGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const shouldEmbed = options?.embedFonts ?? true;\n const { width, height } = getSVGDimensions(svgElement);\n const clone = svgElement.cloneNode(true) as SVGElement;\n\n if (shouldEmbed) {\n await embedFonts(clone);\n }\n\n const svgString = ensureSVGDimensions(exportSVG(clone), width, height);\n\n if (!width || !height) {\n throw new Error(`SVG has zero dimensions (width=${width}, height=${height})`);\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob((result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n }, 'image/png');\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(\n new Error(\n `Failed to load SVG as image (width=${width}, height=${height}, svgLength=${svgString.length})`,\n ),\n );\n };\n\n img.src = url;\n });\n}\n\n/**\n * Render an SVG element to a JPEG Blob via a canvas.\n *\n * Same pipeline as exportPNG but outputs JPEG with configurable quality.\n * The canvas is filled with the chart's background color before drawing\n * to avoid transparent backgrounds rendering as black in JPEG format.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling, JPEG quality, and font embedding.\n * @returns A Promise resolving to the JPEG Blob.\n */\nexport async function exportJPG(svgElement: SVGElement, options?: JPGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const quality = options?.quality ?? 0.92;\n const shouldEmbed = options?.embedFonts ?? true;\n const { width, height } = getSVGDimensions(svgElement);\n const backgroundColor = getSVGBackgroundColor(svgElement);\n const clone = svgElement.cloneNode(true) as SVGElement;\n\n if (shouldEmbed) {\n await embedFonts(clone);\n }\n\n const svgString = ensureSVGDimensions(exportSVG(clone), width, height);\n\n if (!width || !height) {\n throw new Error(`SVG has zero dimensions (width=${width}, height=${height})`);\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(\n (result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n },\n 'image/jpeg',\n quality,\n );\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(\n new Error(\n `Failed to load SVG as image (width=${width}, height=${height}, svgLength=${svgString.length})`,\n ),\n );\n };\n\n img.src = url;\n });\n}\n\n// ---------------------------------------------------------------------------\n// CSV export\n// ---------------------------------------------------------------------------\n\n/**\n * Convert an array of data objects to a CSV string.\n *\n * Uses the keys from the first row as column headers.\n * Values are quoted if they contain commas, quotes, or newlines.\n *\n * @param data - Array of row objects.\n * @returns CSV-formatted string.\n */\nexport function exportCSV(data: Record<string, unknown>[]): string {\n if (data.length === 0) return '';\n\n const headers = Object.keys(data[0]);\n const rows = [headers.map(csvEscape).join(',')];\n\n for (const row of data) {\n const values = headers.map((h) => csvEscape(String(row[h] ?? '')));\n rows.push(values.join(','));\n }\n\n return rows.join('\\n');\n}\n\nfunction csvEscape(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n') || value.includes('\\r')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n","/**\n * Resize observer: thin wrapper around ResizeObserver with debounce.\n *\n * Watches a container element for size changes and calls back with\n * the new width and height. Debounced at ~60fps (16ms) to avoid\n * excessive re-renders during drag resizes.\n */\n\nconst DEBOUNCE_MS = 16;\n\n/**\n * Observe a container element for size changes.\n *\n * @param container - The element to watch.\n * @param callback - Called with (width, height) when size changes.\n * @returns A cleanup function that disconnects the observer.\n */\nexport function observeResize(\n container: HTMLElement,\n callback: (width: number, height: number) => void,\n): () => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n // Debounce to ~60fps\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n callback(width, height);\n }\n timeoutId = null;\n }, DEBOUNCE_MS);\n });\n\n observer.observe(container);\n\n return () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n observer.disconnect();\n };\n}\n","/**\n * Tooltip manager: creates and positions a floating tooltip element.\n *\n * Shows tooltip content near the mouse/touch position with viewport\n * edge avoidance via @floating-ui/dom. Touch support via tap-to-show,\n * tap-outside-to-hide.\n */\n\nimport type { Placement } from '@floating-ui/dom';\nimport { computePosition, flip, offset, shift } from '@floating-ui/dom';\nimport type { TooltipContent } from '@opendata-ai/openchart-core';\n\nexport interface TooltipShowOptions {\n /**\n * Floating-ui placement. Defaults to 'bottom-start' for mark hover\n * (the legacy behavior). Line/area snap-tooltips pass 'right-start'\n * so the card sits beside the snapped point and flips to 'left-start'\n * via the flip middleware when crowding the right edge.\n */\n placement?: Placement;\n}\n\nexport interface TooltipManager {\n /** Show the tooltip with content at a given position. */\n show(content: TooltipContent, x: number, y: number, opts?: TooltipShowOptions): void;\n /** Hide the tooltip. */\n hide(): void;\n /** Remove the tooltip element and clean up event listeners. */\n destroy(): void;\n}\n\nconst TOOLTIP_OFFSET = 12;\n\n/**\n * Create a tooltip manager attached to a container element.\n *\n * The manager creates a floating div positioned relative to the container.\n * Content is rendered as a title line with optional color indicator,\n * followed by a compact list of field-value pairs.\n *\n * @param container - The parent element for the tooltip.\n * @returns TooltipManager with show/hide/destroy methods.\n */\nexport function createTooltipManager(container: HTMLElement): TooltipManager {\n const tooltip = document.createElement('div');\n tooltip.className = 'oc-tooltip';\n tooltip.setAttribute('role', 'tooltip');\n\n container.style.position = container.style.position || 'relative';\n container.appendChild(tooltip);\n\n // Track last content to skip innerHTML when only position changes\n let lastContentKey = '';\n // Generation counter to discard stale async position callbacks\n let currentPositionId = 0;\n\n // Hide on tap-outside for touch devices\n const handleDocumentTouch = (e: Event): void => {\n if (!container.contains(e.target as Node)) {\n hide();\n }\n };\n document.addEventListener('touchstart', handleDocumentTouch);\n\n // WCAG 1.4.13: hover-triggered content must be dismissible without moving\n // the pointer. Document-level so it works while hovering, when the chart\n // container does not have keyboard focus.\n const handleDocumentKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && tooltip.style.display === 'block') {\n hide();\n }\n };\n document.addEventListener('keydown', handleDocumentKeydown);\n\n function show(content: TooltipContent, x: number, y: number, opts?: TooltipShowOptions): void {\n // Fast content identity check: title + field count + first/last field values\n const contentKey = `${content.title}|${content.fields.length}|${content.fields[0]?.value}|${content.fields[content.fields.length - 1]?.value}`;\n\n if (contentKey !== lastContentKey) {\n lastContentKey = contentKey;\n\n let html = '';\n\n // Multi-series tooltips put a swatch on each row instead of in the\n // header, so detect that case once.\n const colorRowCount = content.fields.filter((f) => f.color).length;\n const perRowSwatches = colorRowCount > 1;\n\n // Title row: header dot only when there's a single color (single-series)\n if (content.title) {\n const titleColor = perRowSwatches ? undefined : content.fields.find((f) => f.color)?.color;\n html += '<div class=\"oc-tooltip-header\">';\n if (titleColor) {\n html += `<span class=\"oc-tooltip-dot\" style=\"background:${esc(titleColor)}\"></span>`;\n }\n html += `<span class=\"oc-tooltip-title\">${esc(content.title)}</span>`;\n html += '</div>';\n }\n\n // Field rows\n if (content.fields.length > 0) {\n html += '<div class=\"oc-tooltip-body\">';\n for (const field of content.fields) {\n html += '<div class=\"oc-tooltip-row\">';\n html += '<span class=\"oc-tooltip-label\">';\n if (perRowSwatches && field.color) {\n html += `<span class=\"oc-tooltip-row-swatch\" style=\"background:${esc(field.color)}\"></span>`;\n }\n html += `${esc(field.label)}</span>`;\n html += `<span class=\"oc-tooltip-value\">${esc(field.value)}</span>`;\n html += '</div>';\n }\n html += '</div>';\n }\n\n tooltip.innerHTML = html;\n }\n\n tooltip.style.display = 'block';\n\n // Position with viewport-aware edge avoidance via @floating-ui/dom.\n // Uses a virtual element since the reference point is a coordinate,\n // not a DOM element.\n const positionId = ++currentPositionId;\n const virtualRef = {\n getBoundingClientRect() {\n const rect = container.getBoundingClientRect();\n return {\n x: rect.left + x,\n y: rect.top + y,\n width: 0,\n height: 0,\n top: rect.top + y,\n left: rect.left + x,\n right: rect.left + x,\n bottom: rect.top + y,\n };\n },\n };\n\n computePosition(virtualRef, tooltip, {\n placement: opts?.placement ?? 'bottom-start',\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: 8 })],\n }).then(({ x: fx, y: fy }) => {\n // Discard stale callbacks from earlier show() calls\n if (positionId !== currentPositionId) return;\n // computePosition returns coordinates relative to the tooltip's offset\n // parent (the container with position: relative), so apply directly.\n tooltip.style.left = `${fx}px`;\n tooltip.style.top = `${fy}px`;\n });\n }\n\n function hide(): void {\n tooltip.style.display = 'none';\n lastContentKey = '';\n }\n\n function destroy(): void {\n document.removeEventListener('touchstart', handleDocumentTouch);\n document.removeEventListener('keydown', handleDocumentKeydown);\n if (tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n }\n }\n\n return { show, hide, destroy };\n}\n\nfunction esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n","/**\n * Numeric rAF tweening for scrollytelling story steps.\n *\n * Owns imperative numeric interpolation: the story driver and camera math\n * mutate scalar/vector values per frame using these primitives instead of\n * hand-rolling rAF loops. Ported from opendata/shared/lib/tween.ts.\n *\n * Everything here is SSR-safe: no `window`/`performance` access at module\n * scope. Callers are expected to invoke these client-side.\n */\n\nexport const clamp01 = (t: number): number => Math.min(1, Math.max(0, t));\n\nexport const lerp = (a: number, b: number, t: number): number => a + (b - a) * t;\n\nexport type EasingFn = (t: number) => number;\n\nexport const easingFns = {\n linear: (t: number) => t,\n easeOutCubic: (t: number) => 1 - (1 - t) ** 3,\n easeInOutCubic: (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n easeOutQuint: (t: number) => 1 - (1 - t) ** 5,\n} as const satisfies Record<string, EasingFn>;\n\n/**\n * Duration tokens (ms) for story state changes. Use these instead of\n * arbitrary numbers so all stories share one timing scale.\n */\nexport const storyMotion = {\n /** Small opacity/emphasis shifts */\n fast: 300,\n /** Step state transitions */\n base: 500,\n /** Whole-chart crossfade fallback (steps outside the morph gate) */\n crossfade: 400,\n /** Step-mode camera transitions */\n camera: 600,\n /** Scrub-mode camera damping time constant */\n cameraTau: 100,\n} as const;\n\nexport interface TweenConfig<T> {\n initial: T;\n lerp: (a: T, b: T, t: number) => T;\n /** Default `storyMotion.base` */\n duration?: number;\n /** Default `easingFns.easeOutCubic` */\n ease?: EasingFn;\n onFrame: (value: T) => void;\n}\n\nexport interface Tween<T> {\n /**\n * Retarget the tween. If a tween is mid-flight, the new tween starts FROM\n * THE LIVE INTERPOLATED VALUE, not the previous target -- fast retargeting\n * never jumps. `snap: true` applies the target synchronously with no rAF.\n */\n to: (target: T, opts?: { snap?: boolean }) => void;\n get: () => T;\n cancel: () => void;\n}\n\n/**\n * Retargetable tween over an arbitrary shape T.\n */\nexport function createTween<T>(config: TweenConfig<T>): Tween<T> {\n const {\n lerp: lerpT,\n duration = storyMotion.base,\n ease = easingFns.easeOutCubic,\n onFrame,\n } = config;\n\n let current = config.initial;\n let rafId = 0;\n let running = false;\n\n const stop = () => {\n if (running) {\n cancelAnimationFrame(rafId);\n running = false;\n }\n };\n\n const to = (target: T, opts?: { snap?: boolean }) => {\n stop();\n if (opts?.snap || duration <= 0) {\n current = target;\n onFrame(current);\n return;\n }\n\n const from = current;\n const start = performance.now();\n running = true;\n\n const tick = (now: number) => {\n const t = clamp01((now - start) / duration);\n current = lerpT(from, target, ease(t));\n onFrame(current);\n if (t < 1) {\n rafId = requestAnimationFrame(tick);\n } else {\n running = false;\n }\n };\n\n rafId = requestAnimationFrame(tick);\n };\n\n return { to, get: () => current, cancel: stop };\n}\n","import { lerp } from './tween';\n\n/**\n * Pure math for the scrollytelling camera. `createChartStory` owns DOM\n * writes; everything here is testable without a browser. Ported from\n * opendata/shared/lib/scrolly/camera-math.ts.\n *\n * The camera is a center + zoom over a fixed viewBox, applied as a\n * `transform` on a dedicated wrapper `<g>` around the marks group (NOT\n * viewBox interpolation -- that scales text and gives labels no way to\n * counter-scale). See .claude/rules/svg-animation.md: CSS transform\n * replaces SVG transform attributes, so the camera transform must compose\n * with, not replace, existing SVG transforms on marks.\n */\n\nexport interface Camera {\n cx: number;\n cy: number;\n /** Zoom factor. 1 = full viewBox visible. */\n k: number;\n}\n\nexport interface CameraTarget {\n x: number;\n y: number;\n width: number;\n height: number;\n /** ViewBox units added on all sides before fitting */\n padding?: number;\n}\n\nexport interface ViewBoxSize {\n width: number;\n height: number;\n}\n\nexport const FULL_VIEW = (vb: ViewBoxSize): CameraTarget => ({\n x: 0,\n y: 0,\n width: vb.width,\n height: vb.height,\n});\n\n/** Fit a target rect inside the viewBox, preserving aspect ratio. */\nexport function fitTarget(target: CameraTarget, vb: ViewBoxSize): Camera {\n const pad = target.padding ?? 0;\n const w = target.width + 2 * pad;\n const h = target.height + 2 * pad;\n return {\n cx: target.x + target.width / 2,\n cy: target.y + target.height / 2,\n k: Math.min(vb.width / w, vb.height / h),\n };\n}\n\n/**\n * Pan lerps linearly; zoom lerps in LOG space so the zoom rate reads\n * constant (a 1->4 zoom passes through 2 at the midpoint, not 2.5).\n */\nexport function interpolateCamera(a: Camera, b: Camera, t: number): Camera {\n return {\n cx: lerp(a.cx, b.cx, t),\n cy: lerp(a.cy, b.cy, t),\n k: Math.exp(lerp(Math.log(a.k), Math.log(b.k), t)),\n };\n}\n\n/** SVG transform string that frames the camera inside the viewBox. */\nexport function cameraTransform(c: Camera, vb: ViewBoxSize): string {\n return `translate(${vb.width / 2} ${vb.height / 2}) scale(${c.k}) translate(${-c.cx} ${-c.cy})`;\n}\n\n/**\n * Frame-rate-independent exponential damping: two 8ms steps land where one\n * 16ms step does. `tauMs` is the time constant (~63% of the gap per tau).\n */\nexport function damp(current: number, target: number, tauMs: number, dtMs: number): number {\n if (tauMs <= 0) return target;\n return current + (target - current) * (1 - Math.exp(-dtMs / tauMs));\n}\n\nexport function dampCamera(current: Camera, target: Camera, tauMs: number, dtMs: number): Camera {\n return {\n cx: damp(current.cx, target.cx, tauMs, dtMs),\n cy: damp(current.cy, target.cy, tauMs, dtMs),\n // k damped in log space, same rationale as interpolateCamera\n k: Math.exp(damp(Math.log(current.k), Math.log(target.k), tauMs, dtMs)),\n };\n}\n\nexport function camerasClose(a: Camera, b: Camera, epsilon = 1e-3): boolean {\n return (\n Math.abs(a.cx - b.cx) < epsilon &&\n Math.abs(a.cy - b.cy) < epsilon &&\n Math.abs(Math.log(a.k) - Math.log(b.k)) < epsilon\n );\n}\n\n/**\n * Where the scrub camera should point for a given frame.\n *\n * Hold-zone semantics: the camera DWELLS on the active step's target while\n * the reader reads, and only transitions toward the next step's target in\n * the tail of the span (`stepProgress > holdUntil`). Interpolating across\n * the whole span would mean the camera departs the moment a step activates\n * and never rests on what the text is describing.\n */\nexport function scrubCamera(\n step: number,\n stepProgress: number,\n fitted: Camera[],\n holdUntil: number,\n ease: (t: number) => number,\n): Camera {\n const n = fitted.length;\n if (n === 0) return { cx: 0, cy: 0, k: 1 };\n const clamped = Math.min(Math.max(step, 0), n - 1);\n const current = fitted[clamped]!;\n const next = fitted[Math.min(clamped + 1, n - 1)]!;\n if (step < 0 || clamped >= n - 1 || stepProgress <= holdUntil) {\n return current;\n }\n const t = (stepProgress - holdUntil) / (1 - holdUntil);\n return interpolateCamera(current, next, ease(t));\n}\n","/**\n * Map mount API: the main entry point for vanilla JS map usage.\n *\n * createMap() takes a container, MapSpec, and options, compiles the\n * map, renders it as SVG, sets up responsive resizing, tooltip interaction,\n * and returns a MapInstance with update/resize/export/destroy.\n */\n\nimport type {\n CompileOptions,\n DarkMode,\n MapLayout,\n MapSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { compileMap } from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport {\n applyMapCamera,\n cameraForTarget,\n focusTargetForFeatures,\n type MapCameraOptions,\n} from './map-camera';\nimport { renderMapSVG } from './map-renderer';\nimport { captureFeatureFills, runMapFillTransition } from './map-transition';\nimport { createMeasureText, resolveFontFamily, scheduleFontReload } from './measure-text';\nimport { observeResize } from './resize-observer';\nimport type { Camera } from './story/camera-math';\nimport { interpolateCamera } from './story/camera-math';\nimport type { Tween } from './story/tween';\nimport { createTween, easingFns, storyMotion } from './story/tween';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MapMountOptions {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Show tooltips on hover. Defaults to true. */\n tooltip?: boolean;\n /** Callback when a feature is clicked. */\n onMarkClick?: (feature: {\n id: string | number;\n name?: string;\n data: Record<string, unknown> | null;\n }) => void;\n /** Callback when a feature is hovered (null on mouse leave). */\n onMarkHover?: (\n feature: {\n id: string | number;\n name?: string;\n data: Record<string, unknown> | null;\n } | null,\n ) => void;\n}\n\nexport interface MapInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: MapSpec): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the map. */\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options?: JPGExportOptions | SVGExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout. */\n readonly layout: MapLayout;\n /** Zoom to one or more features by ID. */\n zoomTo(featureId: string | number | Array<string | number>, opts?: MapCameraOptions): void;\n /** Pan to a feature keeping the current zoom level. */\n panTo(featureId: string | number, opts?: MapCameraOptions): void;\n /** Fit the camera to an arbitrary bounding box, or reset to full view if no target. */\n fitBounds(\n target?: { x: number; y: number; width: number; height: number; padding?: number },\n opts?: MapCameraOptions,\n ): void;\n /** Reset the camera to the full map view. */\n resetView(opts?: MapCameraOptions): void;\n /** Get a snapshot of the current camera state. */\n getCamera(): Camera;\n /** Set the camera to an exact state (no animation). */\n setCamera(camera: Camera): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n try {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a map instance from a spec and mount it into a container.\n */\nexport function createMap(\n container: HTMLElement,\n spec: MapSpec,\n options?: MapMountOptions,\n): MapInstance {\n let currentSpec = spec;\n let currentLayout: MapLayout;\n let destroyed = false;\n\n // DOM\n let svgElement: SVGSVGElement | null = null;\n\n // Subsystems\n let tooltipManager: TooltipManager | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let disconnectResize: (() => void) | null = null;\n\n // Animation state\n let animationCleanup: (() => void) | null = null;\n let fillTransitionHandle: { cancel: () => void } | null = null;\n let pendingResize = false;\n\n // Camera state\n let currentCamera: Camera = { cx: 0, cy: 0, k: 1 };\n let currentFocusIds: Array<string | number> | null = null;\n let cameraTween: Tween<Camera> | null = null;\n\n // Track whether this is the first render (for snap-to-focus).\n let isFirstRender = true;\n\n // Set when webfonts have loaded and a recompile is owed.\n let fontsReloadPending = false;\n\n // Apply the root class up front so getComputedStyle sees --oc-font-family\n container.classList.add('oc-map-root');\n\n // Resolve the effective font the same way compile() will.\n function resolveEffectiveFont(): string {\n return (\n options?.theme?.fonts?.family ??\n currentSpec.theme?.fonts?.family ??\n resolveFontFamily(container)\n );\n }\n let fontFamily = resolveEffectiveFont();\n let measureText = createMeasureText(fontFamily);\n let renderGen = 0;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n let isAutoHeight: boolean | null = null;\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const width = Math.max(rect.width || 600, 100);\n\n if (isAutoHeight === null && (rect.width > 0 || rect.height > 0)) {\n isAutoHeight = rect.height === 0 && rect.width > 0;\n }\n\n // Explicit host height is a hard budget: return it as-is so the\n // compiler keeps the SVG inside its box.\n if (isAutoHeight === false && rect.height > 0) {\n return { width, height: Math.max(rect.height, 100) };\n }\n\n // Auto-height host: pick our own budget.\n return { width, height: Math.round(width * 0.625) };\n }\n\n function compile(): MapLayout {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n measureText,\n };\n\n return compileMap(currentSpec, compileOpts);\n }\n\n // ---------------------------------------------------------------------------\n // Tooltip and interaction wiring\n // ---------------------------------------------------------------------------\n\n function wireTooltipAndInteraction(svg: SVGSVGElement, layout: MapLayout): () => void {\n const cleanups: Array<() => void> = [];\n\n const featureElements = svg.querySelectorAll('.oc-map-feature');\n for (const el of featureElements) {\n const featureId = el.getAttribute('data-feature-id');\n if (!featureId) continue;\n\n const content = layout.tooltipDescriptors.get(featureId);\n const feature = layout.features.find((f) => String(f.id) === featureId);\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('cursor', 'pointer');\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('filter', 'brightness(1.1)');\n if (content && tooltipManager && options?.tooltip !== false) {\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n if (feature) {\n options?.onMarkHover?.({\n id: feature.id,\n name: feature.name,\n data: feature.data,\n });\n }\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager && options?.tooltip !== false) {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n const handleMouseLeave = () => {\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('cursor');\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('filter');\n tooltipManager?.hide();\n options?.onMarkHover?.(null);\n };\n\n const handleClick = () => {\n if (feature) {\n options?.onMarkClick?.({\n id: feature.id,\n name: feature.name,\n data: feature.data,\n });\n }\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('click', handleClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('click', handleClick);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n // ---------------------------------------------------------------------------\n // Camera helpers\n // ---------------------------------------------------------------------------\n\n function resolveCamera(): Camera {\n if (currentFocusIds && currentFocusIds.length > 0) {\n const target = focusTargetForFeatures(currentLayout, currentFocusIds);\n return cameraForTarget(currentLayout, target);\n }\n return cameraForTarget(currentLayout, null);\n }\n\n function animateCamera(target: Camera, duration: number): void {\n if (cameraTween) cameraTween.cancel();\n cameraTween = createTween<Camera>({\n initial: currentCamera,\n lerp: interpolateCamera,\n duration,\n ease: easingFns.easeInOutCubic,\n onFrame(cam) {\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n },\n });\n cameraTween.to(target);\n }\n\n function driveCamera(cam: Camera, duration: number): void {\n if (duration === 0 || prefersReducedMotion()) {\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n } else {\n animateCamera(cam, duration);\n }\n }\n\n function updateA11yLive(ids: Array<string | number> | null): void {\n let liveEl = container.querySelector('.oc-map-live') as HTMLElement | null;\n if (!liveEl) {\n liveEl = document.createElement('div');\n liveEl.className = 'oc-map-live oc-sr-only';\n liveEl.setAttribute('aria-live', 'polite');\n container.appendChild(liveEl);\n }\n if (!ids || ids.length === 0) {\n liveEl.textContent = 'Showing full map';\n return;\n }\n const names = ids.map((id) => {\n const f = currentLayout.features.find((feat) => String(feat.id) === String(id));\n return f?.name ?? String(id);\n });\n liveEl.textContent = `Zoomed to ${names.join(', ')}`;\n }\n\n function applyFocusDim(ids: Array<string | number> | null): void {\n if (!svgElement) return;\n const features = svgElement.querySelectorAll('.oc-map-feature');\n if (!ids || ids.length === 0) {\n for (const el of features) {\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('opacity');\n }\n return;\n }\n const focusSet = new Set(ids.map(String));\n for (const el of features) {\n const fid = el.getAttribute('data-feature-id');\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty(\n 'opacity',\n fid && focusSet.has(fid) ? '1' : '0.25',\n );\n }\n }\n\n // ---------------------------------------------------------------------------\n // Render + update\n // ---------------------------------------------------------------------------\n\n function render(animate = false): void {\n // Cancel running animations\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n }\n if (fillTransitionHandle) {\n fillTransitionHandle.cancel();\n fillTransitionHandle = null;\n }\n\n // Remove old SVG\n if (svgElement) {\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n svgElement.remove();\n }\n\n // Render new SVG\n const newSvg = renderMapSVG(currentLayout, { animate });\n container.appendChild(newSvg);\n svgElement = newSvg;\n\n // Wire interactions\n cleanupTooltipEvents = wireTooltipAndInteraction(newSvg, currentLayout);\n\n // Setup tooltips if enabled\n if (options?.tooltip !== false) {\n if (!tooltipManager) {\n tooltipManager = createTooltipManager(container);\n }\n }\n\n // Setup animation cleanup only when actually animating\n const isAnimating = animate && !!currentLayout.animation?.enter;\n if (isAnimating) {\n animationCleanup = setupAnimationCleanup(newSvg, () => {\n if (pendingResize && !destroyed) {\n pendingResize = false;\n resize();\n }\n // Apply deferred focus dim after animation completes\n if (currentFocusIds && currentFocusIds.length > 0) {\n applyFocusDim(currentFocusIds);\n }\n });\n }\n\n // Re-apply camera transform after render if zoomed or focused\n if (currentCamera.k > 1 + 1e-3 || (currentFocusIds && currentFocusIds.length > 0)) {\n applyMapCamera(newSvg, currentCamera, currentLayout);\n }\n\n renderGen += 1;\n container.dataset.ocRenderGen = String(renderGen);\n\n if (fontsReloadPending) {\n fontsReloadPending = false;\n container.dataset.ocFontsState = 'ready';\n }\n\n // On first render, snap to declarative focus if present\n if (isFirstRender && currentLayout.focus) {\n const target = currentLayout.focus.target;\n currentFocusIds = [...currentLayout.focus.ids];\n const cam = cameraForTarget(currentLayout, target);\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n if (!isAnimating) applyFocusDim(currentFocusIds);\n }\n isFirstRender = false;\n }\n\n function update(newSpec: MapSpec): void {\n currentSpec = newSpec;\n const nextFont = resolveEffectiveFont();\n if (nextFont !== fontFamily) {\n fontFamily = nextFont;\n measureText = createMeasureText(fontFamily);\n }\n\n // Capture fills optimistically; gate the tween on the *new* layout's animation config after compile\n const canAnimate = !animationCleanup && !prefersReducedMotion();\n const prevFills = canAnimate ? captureFeatureFills(svgElement) : null;\n\n // Remember previous focus to detect changes\n const prevFocusIds = currentFocusIds ? currentFocusIds.map(String).sort().join(',') : null;\n const prevFocusPadding = currentLayout.focus?.target.padding ?? null;\n\n currentLayout = compile();\n render();\n\n // Run fill tween if the *new* layout enables update animation\n if (\n canAnimate &&\n prevFills &&\n prevFills.size > 0 &&\n svgElement &&\n currentLayout.animation?.update\n ) {\n fillTransitionHandle = runMapFillTransition(svgElement, prevFills, {\n duration: currentLayout.animation.update.duration,\n });\n }\n\n // Declarative focus from spec: tween camera if focus changed\n const nextFocus = currentLayout.focus;\n const nextFocusIds = nextFocus ? nextFocus.ids.map(String).sort().join(',') : null;\n const nextFocusPadding = nextFocus?.target.padding ?? null;\n\n if (nextFocusIds !== prevFocusIds || nextFocusPadding !== prevFocusPadding) {\n if (nextFocus) {\n currentFocusIds = [...nextFocus.ids];\n const cam = cameraForTarget(currentLayout, nextFocus.target);\n driveCamera(cam, prefersReducedMotion() ? 0 : storyMotion.camera);\n applyFocusDim(currentFocusIds);\n } else if (prevFocusIds !== null) {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, null);\n driveCamera(cam, prefersReducedMotion() ? 0 : storyMotion.camera);\n applyFocusDim(null);\n }\n }\n }\n\n function resize(): void {\n if (destroyed) return;\n\n // If animation is running, queue the resize for after it completes\n if (animationCleanup) {\n pendingResize = true;\n return;\n }\n\n currentLayout = compile();\n render();\n\n // Re-resolve camera against new layout dimensions.\n // Imperative focus (set via zoomTo/panTo) takes precedence over declarative.\n if (currentFocusIds && currentFocusIds.length > 0) {\n currentCamera = resolveCamera();\n if (svgElement) applyMapCamera(svgElement, currentCamera, currentLayout);\n } else if (currentLayout.focus) {\n currentFocusIds = [...currentLayout.focus.ids];\n currentCamera = cameraForTarget(currentLayout, currentLayout.focus.target);\n if (svgElement) applyMapCamera(svgElement, currentCamera, currentLayout);\n }\n applyFocusDim(currentFocusIds);\n }\n\n // ---------------------------------------------------------------------------\n // Export\n // ---------------------------------------------------------------------------\n\n function exportChart(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options_?: JPGExportOptions | SVGExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) return '';\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement);\n case 'png':\n return exportPNG(svgElement, options_ as JPGExportOptions);\n case 'jpg':\n return exportJPG(svgElement, options_ as JPGExportOptions);\n default:\n return '';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Destroy\n // ---------------------------------------------------------------------------\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel running animations\n if (animationCleanup) {\n cancelAnimations(svgElement);\n animationCleanup();\n animationCleanup = null;\n }\n if (fillTransitionHandle) {\n fillTransitionHandle.cancel();\n fillTransitionHandle = null;\n }\n if (cameraTween) {\n cameraTween.cancel();\n cameraTween = null;\n }\n\n // Clean up events\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Remove SVG\n if (svgElement) {\n svgElement.remove();\n svgElement = null;\n }\n\n // Remove a11y live region\n const liveEl = container.querySelector('.oc-map-live');\n if (liveEl) liveEl.remove();\n\n // Unmount tooltip manager\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n\n // Disconnect resize observer\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n // Remove root classes\n container.classList.remove('oc-map-root', 'oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n if (resolveDarkMode(options?.darkMode)) {\n container.classList.add('oc-dark');\n }\n\n // Initial compile and render (animate on first mount)\n currentLayout = compile();\n render(true);\n\n // Recompile once after webfonts load\n const fontsPending = scheduleFontReload(\n fontFamily,\n () => !destroyed,\n () => {\n fontsReloadPending = true;\n resize();\n },\n );\n container.dataset.ocFontsState = fontsPending ? 'pending' : 'ready';\n\n // Setup responsive resizing\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n resize();\n });\n }\n\n return {\n update,\n resize,\n export: exportChart,\n destroy,\n get layout(): MapLayout {\n return currentLayout;\n },\n zoomTo(featureId: string | number | Array<string | number>, opts?: MapCameraOptions): void {\n const ids = Array.isArray(featureId) ? featureId : [featureId];\n const target = focusTargetForFeatures(currentLayout, ids, opts?.padding ?? 16);\n if (!target) {\n console.warn(`[openchart] zoomTo: no features found for ids: ${ids.join(', ')}`);\n return;\n }\n currentFocusIds = ids;\n const cam = cameraForTarget(currentLayout, target);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(ids);\n updateA11yLive(ids);\n },\n panTo(featureId: string | number, opts?: MapCameraOptions): void {\n const target = focusTargetForFeatures(currentLayout, [featureId], opts?.padding ?? 16);\n if (!target) {\n console.warn(`[openchart] panTo: no feature found for id: ${featureId}`);\n return;\n }\n const cam: Camera = {\n cx: target.x + target.width / 2,\n cy: target.y + target.height / 2,\n k: currentCamera.k,\n };\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n updateA11yLive([featureId]);\n },\n fitBounds(\n target?: { x: number; y: number; width: number; height: number; padding?: number },\n opts?: MapCameraOptions,\n ): void {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, target ?? null);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(null);\n },\n resetView(opts?: MapCameraOptions): void {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, null);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(null);\n updateA11yLive(null);\n },\n getCamera(): Camera {\n return { ...currentCamera };\n },\n setCamera(camera: Camera): void {\n currentCamera = camera;\n currentFocusIds = null;\n if (svgElement) applyMapCamera(svgElement, camera, currentLayout);\n },\n };\n}\n","/**\n * Animation runtime for entrance animations.\n *\n * All animations are CSS-driven (keyframes + clip-path + transforms + opacity).\n * This module handles lifecycle: cleanup after completion, cancellation on update.\n * No WAAPI needed since clip-path handles line/area drawing.\n */\n\n/**\n * Cancel entrance animations and clean up.\n * Called when update() is invoked during animation, or on destroy.\n */\nexport function cancelAnimations(svg: SVGElement | null): void {\n if (svg) {\n svg.classList.remove('oc-animate');\n }\n}\n\n/**\n * Set up animation cleanup that removes oc-animate after all animations complete.\n *\n * Uses the computed total animation time (duration + stagger * elementCount + annotation delay)\n * rather than animationend events, because animationend fires per-element and the first\n * element to finish would prematurely kill staggered animations still in progress.\n */\nexport function setupAnimationCleanup(svg: SVGElement, onComplete?: () => void): () => void {\n // Read the animation timing from the CSS custom properties set by the renderer\n const style = svg.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 600;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n const annotationDelay = parseFloat(style.getPropertyValue('--oc-annotation-delay')) || 200;\n\n // Count animated elements to compute total stagger span\n const animatedElements = svg.querySelectorAll('[data-animation-index]').length;\n const totalStagger = stagger * Math.max(0, animatedElements - 1);\n\n // Total time: last element's stagger delay + its duration + annotation delay + buffer\n const totalTime = totalStagger + duration + annotationDelay + 500;\n\n const timer = setTimeout(() => {\n svg.classList.remove('oc-animate');\n onComplete?.();\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n cancelAnimations(svg);\n };\n}\n\n/**\n * Set up animation cleanup for table entrance animations.\n *\n * Same timeout-based approach as chart animations: compute total time from\n * CSS custom properties and row count, then remove oc-animate after completion.\n */\nexport function setupTableAnimationCleanup(wrapper: HTMLElement): () => void {\n const style = wrapper.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 500;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n\n const rows = wrapper.querySelectorAll('tbody tr').length;\n const totalStagger = stagger * Math.max(0, rows - 1);\n\n // Total: last row stagger + duration + buffer\n const totalTime = totalStagger + duration + 300;\n\n const timer = setTimeout(() => {\n wrapper.classList.remove('oc-animate');\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n wrapper.classList.remove('oc-animate');\n };\n}\n","/**\n * Map camera utilities: zoom, pan, and focus for map visualizations.\n *\n * Reuses the existing camera-math infrastructure from the scrollytelling\n * system. The camera transform is applied as an SVG `transform` attribute\n * on the `[data-oc-map-camera]` group, never as a CSS transform.\n */\n\nimport type { MapLayout } from '@opendata-ai/openchart-core';\nimport type { Camera, CameraTarget } from './story/camera-math';\nimport { cameraTransform, FULL_VIEW, fitTarget } from './story/camera-math';\n\nexport type { Camera } from './story/camera-math';\n\nexport interface MapCameraOptions {\n /** Transition duration in ms. 0 snaps instantly. Default 600. */\n duration?: number;\n /** Padding in map-local units around the target. Default 16. */\n padding?: number;\n}\n\n/**\n * Compute a CameraTarget from the union of feature bounds.\n * Returns null if no matching features found.\n */\nexport function focusTargetForFeatures(\n layout: MapLayout,\n ids: Array<string | number>,\n padding = 16,\n): CameraTarget | null {\n const idSet = new Set(ids.map(String));\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let found = false;\n\n for (const f of layout.features) {\n if (idSet.has(String(f.id))) {\n found = true;\n minX = Math.min(minX, f.bounds.x);\n minY = Math.min(minY, f.bounds.y);\n maxX = Math.max(maxX, f.bounds.x + f.bounds.width);\n maxY = Math.max(maxY, f.bounds.y + f.bounds.height);\n }\n }\n\n if (!found) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY, padding };\n}\n\n/**\n * Compute the Camera for a target, fitting against mapSize.\n * Returns the full-view camera if no target provided.\n */\nexport function cameraForTarget(layout: MapLayout, target?: CameraTarget | null): Camera {\n const vb = layout.mapSize;\n if (!target) return fitTarget(FULL_VIEW(vb), vb);\n const cam = fitTarget(target, vb);\n return { ...cam, k: Math.max(1, Math.min(40, cam.k)) };\n}\n\n/**\n * Apply a camera transform to the map's camera group.\n * Toggles vector-effect=\"non-scaling-stroke\" on features/borders while zoomed.\n */\nexport function applyMapCamera(svg: SVGElement, camera: Camera, layout: MapLayout): void {\n const cameraGroup = svg.querySelector('[data-oc-map-camera]');\n if (!cameraGroup) return;\n\n const vb = layout.mapSize;\n const isZoomed = Math.abs(camera.k - 1) > 1e-3;\n\n if (isZoomed) {\n cameraGroup.setAttribute('transform', cameraTransform(camera, vb));\n // Toggle non-scaling-stroke so strokes don't fatten when zoomed\n const paths = svg.querySelectorAll('.oc-map-feature, .oc-map-borders path');\n for (const p of paths) {\n p.setAttribute('vector-effect', 'non-scaling-stroke');\n }\n } else {\n cameraGroup.removeAttribute('transform');\n const paths = svg.querySelectorAll('.oc-map-feature, .oc-map-borders path');\n for (const p of paths) {\n p.removeAttribute('vector-effect');\n }\n }\n}\n","/**\n * Map SVG renderer: converts a MapLayout into SVG DOM elements.\n *\n * Creates an <svg> with geo feature paths, border overlays, gradient or\n * categorical legend, and chrome. All styling via inline SVG attributes from\n * layout data. Animation is pure CSS, driven by data attributes.\n */\n\nimport type {\n MapBorders,\n MapFeatureMark,\n MapLayout,\n ResolvedAnimation,\n} from '@opendata-ai/openchart-core';\nimport { stampAnimationVars } from './animation-vars';\nimport { renderChromeElement } from './renderers/chrome';\nimport { renderLegend } from './renderers/legend';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\nconst BRAND_URL = 'https://tryopendata.ai';\n\n// Above this count, skip per-feature CSS fill animations (not GPU-compositable)\n// and fade the entire features group with a single opacity animation instead.\nconst BULK_ANIMATION_THRESHOLD = 200;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nfunction setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Chrome rendering (delegates to the shared helper for text wrapping)\n// ---------------------------------------------------------------------------\n\nfunction renderChrome(parent: SVGElement, layout: MapLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome, measureText } = layout;\n const bottomOffset = chrome.bottomAnchorY ?? layout.area.y + layout.area.height;\n\n if (chrome.title) {\n renderChromeElement(g, chrome.title, 'oc-title', 'title', measureText);\n }\n if (chrome.subtitle) {\n renderChromeElement(g, chrome.subtitle, 'oc-subtitle', 'subtitle', measureText);\n }\n if (chrome.source) {\n renderChromeElement(\n g,\n { ...chrome.source, y: bottomOffset + chrome.source.y },\n 'oc-source',\n 'source',\n measureText,\n );\n }\n if (chrome.byline) {\n renderChromeElement(\n g,\n { ...chrome.byline, y: bottomOffset + chrome.byline.y },\n 'oc-byline',\n 'byline',\n measureText,\n );\n }\n if (chrome.footer) {\n renderChromeElement(\n g,\n { ...chrome.footer, y: bottomOffset + chrome.footer.y },\n 'oc-footer',\n 'footer',\n measureText,\n );\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Watermark rendering\n// ---------------------------------------------------------------------------\n\nfunction renderWatermark(parent: SVGElement, layout: MapLayout): void {\n if (layout.width < 480) return;\n\n const { width, height, theme } = layout;\n const padding = theme.spacing.padding;\n const rightEdge = width - padding;\n const bottomEdge = height - padding;\n const fill = theme.colors.axis;\n\n const a = createSVGElement('a');\n a.setAttribute('href', BRAND_URL);\n a.setAttributeNS(XLINK_NS, 'xlink:href', BRAND_URL);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.setAttribute('class', 'oc-chrome-ref');\n\n const text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: bottomEdge,\n 'dominant-baseline': 'alphabetic',\n 'text-anchor': 'end',\n 'font-family': theme.fonts.family,\n 'font-size': 12,\n 'fill-opacity': 0.55,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', fill);\n\n const trySpan = createSVGElement('tspan');\n setAttrs(trySpan, { 'font-weight': 500 });\n trySpan.textContent = 'try';\n\n const openDataSpan = createSVGElement('tspan');\n setAttrs(openDataSpan, { 'font-weight': 600, 'font-size': 16 });\n openDataSpan.textContent = 'OpenData';\n\n const aiSpan = createSVGElement('tspan');\n setAttrs(aiSpan, { 'font-weight': 500 });\n aiSpan.textContent = '.ai';\n\n text.appendChild(trySpan);\n text.appendChild(openDataSpan);\n text.appendChild(aiSpan);\n a.appendChild(text);\n parent.appendChild(a);\n}\n\n// ---------------------------------------------------------------------------\n// Border rendering\n// ---------------------------------------------------------------------------\n\nfunction renderBorders(parent: SVGElement, borders: MapBorders): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-map-borders');\n\n // Interior borders (between features)\n if (borders.interiorPath) {\n const interior = createSVGElement('path');\n setAttrs(interior, {\n d: borders.interiorPath,\n fill: 'none',\n stroke: borders.interiorStroke,\n 'stroke-width': 0.5,\n 'stroke-linejoin': 'round',\n });\n interior.setAttribute('class', 'oc-map-border-interior');\n interior.setAttribute('pointer-events', 'none');\n g.appendChild(interior);\n }\n\n // Outline border (coastline / outer boundary)\n if (borders.outlinePath) {\n const outline = createSVGElement('path');\n setAttrs(outline, {\n d: borders.outlinePath,\n fill: 'none',\n stroke: borders.outlineStroke,\n 'stroke-width': 1,\n 'stroke-linejoin': 'round',\n });\n outline.setAttribute('class', 'oc-map-border-outline');\n outline.setAttribute('pointer-events', 'none');\n g.appendChild(outline);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Feature rendering\n// ---------------------------------------------------------------------------\n\nfunction renderFeatures(\n parent: SVGElement,\n features: MapFeatureMark[],\n animation?: ResolvedAnimation,\n staggerBudget = 0,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-map-features');\n g.setAttribute('role', 'list');\n\n const bulk = features.length > BULK_ANIMATION_THRESHOLD;\n\n if (bulk && animation?.enter) {\n g.setAttribute('data-bulk-animate', '');\n }\n\n const maxIdx = features.length - 1;\n\n // Build evenly spaced delays then shuffle for organic pop-in\n // (skipped in bulk mode where the whole group fades as one)\n const shuffledDelays: number[] = [];\n if (!bulk && staggerBudget > 0 && maxIdx > 0) {\n for (let i = 0; i <= maxIdx; i++) {\n shuffledDelays.push((i / maxIdx) * staggerBudget);\n }\n // Seeded Fisher-Yates shuffle (deterministic per-map via first feature id)\n let seed = 0x9e3779b9 ^ (features.length * 2654435761);\n for (let i = maxIdx; i > 0; i--) {\n seed = (seed + 0x6d2b79f5) | 0;\n let t = seed ^ (seed >>> 15);\n t = Math.imul(t, t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n const r = ((t ^ (t >>> 14)) >>> 0) % (i + 1);\n [shuffledDelays[i], shuffledDelays[r]] = [shuffledDelays[r], shuffledDelays[i]];\n }\n }\n\n for (let i = 0; i < features.length; i++) {\n const feature = features[i];\n const path = createSVGElement('path');\n path.setAttribute('class', 'oc-map-feature');\n path.setAttribute('role', 'listitem');\n setAttrs(path, {\n d: feature.path,\n fill: feature.fill,\n stroke: feature.stroke,\n 'stroke-width': feature.strokeWidth,\n });\n path.setAttribute('data-feature-id', String(feature.id));\n path.setAttribute('data-key', String(feature.id));\n if (feature.name) {\n path.setAttribute('data-feature-name', feature.name);\n }\n if (feature.aria?.label) {\n path.setAttribute('aria-label', feature.aria.label);\n }\n\n // Per-feature animation props only in non-bulk mode\n if (!bulk && animation?.enter) {\n const idx = feature.animationIndex ?? i;\n path.setAttribute('data-animation-index', String(idx));\n const s = (path as SVGElement & ElementCSSInlineStyle).style;\n s.setProperty('--oc-mark-index', String(idx));\n s.setProperty('--oc-feature-fill', feature.fill);\n if (staggerBudget > 0 && maxIdx > 0) {\n s.setProperty('--oc-map-delay', `${shuffledDelays[i]}ms`);\n }\n }\n\n g.appendChild(path);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Render a MapLayout to an SVG element.\n */\nexport function renderMapSVG(layout: MapLayout, opts?: { animate?: boolean }): SVGSVGElement {\n const { width, height, features, borders, a11y, watermark, animation } = layout;\n const animate = opts?.animate && !!animation?.enter;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('role', 'img');\n if (a11y.altText) {\n svg.setAttribute('aria-label', a11y.altText);\n }\n\n const classes = animate ? 'oc-map oc-animate' : 'oc-map';\n svg.setAttribute('class', classes);\n\n const bulk = features.length > BULK_ANIMATION_THRESHOLD;\n let mapStaggerBudget = 0;\n if (animate && animation?.enter) {\n const dur = animation.enter.duration;\n const perFeature = Math.min(dur, 500);\n if (!bulk) {\n mapStaggerBudget = Math.round(dur * 1.2);\n }\n const n = Math.max(features.length, 1);\n const stagger = !bulk && n > 1 ? mapStaggerBudget / (n - 1) : 0;\n stampAnimationVars(svg, {\n duration: perFeature,\n stagger,\n annotationDelay: animation.annotationDelay,\n ease: animation.enter.ease,\n });\n }\n\n // Empty defs element (will be filled by gradient legend)\n const defs = createSVGElement('defs');\n svg.appendChild(defs);\n\n // Render chrome\n renderChrome(svg, layout);\n\n // Create map group offset to the drawing area\n const mapGroup = createSVGElement('g');\n mapGroup.setAttribute('class', 'oc-map-group');\n mapGroup.setAttribute('transform', `translate(${layout.area.x},${layout.area.y})`);\n\n // Camera group wraps features + borders only (chrome, legend, watermark stay outside)\n const cameraGroup = createSVGElement('g');\n cameraGroup.setAttribute('class', 'oc-map-camera');\n cameraGroup.setAttribute('data-oc-map-camera', '');\n\n // Render features first (so borders overlay them)\n renderFeatures(cameraGroup, features, animate ? animation : undefined, mapStaggerBudget);\n\n // Render borders on top of features\n renderBorders(cameraGroup, borders);\n\n mapGroup.appendChild(cameraGroup);\n svg.appendChild(mapGroup);\n\n // Render legend (continuous for quantitative, categorical for nominal)\n if (layout.continuousLegend) {\n renderLegend(svg, layout.continuousLegend);\n } else if (layout.categoricalLegend) {\n renderLegend(svg, layout.categoricalLegend);\n }\n\n // Render watermark\n if (watermark) {\n renderWatermark(svg, layout);\n }\n\n return svg;\n}\n","export default function(constructor, factory, prototype) {\n constructor.prototype = factory.prototype = prototype;\n prototype.constructor = constructor;\n}\n\nexport function extend(parent, definition) {\n var prototype = Object.create(parent.prototype);\n for (var key in definition) prototype[key] = definition[key];\n return prototype;\n}\n","import define, {extend} from \"./define.js\";\n\nexport function Color() {}\n\nexport var darker = 0.7;\nexport var brighter = 1 / darker;\n\nvar reI = \"\\\\s*([+-]?\\\\d+)\\\\s*\",\n reN = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\",\n reP = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\",\n reHex = /^#([0-9a-f]{3,8})$/,\n reRgbInteger = new RegExp(`^rgb\\\\(${reI},${reI},${reI}\\\\)$`),\n reRgbPercent = new RegExp(`^rgb\\\\(${reP},${reP},${reP}\\\\)$`),\n reRgbaInteger = new RegExp(`^rgba\\\\(${reI},${reI},${reI},${reN}\\\\)$`),\n reRgbaPercent = new RegExp(`^rgba\\\\(${reP},${reP},${reP},${reN}\\\\)$`),\n reHslPercent = new RegExp(`^hsl\\\\(${reN},${reP},${reP}\\\\)$`),\n reHslaPercent = new RegExp(`^hsla\\\\(${reN},${reP},${reP},${reN}\\\\)$`);\n\nvar named = {\n aliceblue: 0xf0f8ff,\n antiquewhite: 0xfaebd7,\n aqua: 0x00ffff,\n aquamarine: 0x7fffd4,\n azure: 0xf0ffff,\n beige: 0xf5f5dc,\n bisque: 0xffe4c4,\n black: 0x000000,\n blanchedalmond: 0xffebcd,\n blue: 0x0000ff,\n blueviolet: 0x8a2be2,\n brown: 0xa52a2a,\n burlywood: 0xdeb887,\n cadetblue: 0x5f9ea0,\n chartreuse: 0x7fff00,\n chocolate: 0xd2691e,\n coral: 0xff7f50,\n cornflowerblue: 0x6495ed,\n cornsilk: 0xfff8dc,\n crimson: 0xdc143c,\n cyan: 0x00ffff,\n darkblue: 0x00008b,\n darkcyan: 0x008b8b,\n darkgoldenrod: 0xb8860b,\n darkgray: 0xa9a9a9,\n darkgreen: 0x006400,\n darkgrey: 0xa9a9a9,\n darkkhaki: 0xbdb76b,\n darkmagenta: 0x8b008b,\n darkolivegreen: 0x556b2f,\n darkorange: 0xff8c00,\n darkorchid: 0x9932cc,\n darkred: 0x8b0000,\n darksalmon: 0xe9967a,\n darkseagreen: 0x8fbc8f,\n darkslateblue: 0x483d8b,\n darkslategray: 0x2f4f4f,\n darkslategrey: 0x2f4f4f,\n darkturquoise: 0x00ced1,\n darkviolet: 0x9400d3,\n deeppink: 0xff1493,\n deepskyblue: 0x00bfff,\n dimgray: 0x696969,\n dimgrey: 0x696969,\n dodgerblue: 0x1e90ff,\n firebrick: 0xb22222,\n floralwhite: 0xfffaf0,\n forestgreen: 0x228b22,\n fuchsia: 0xff00ff,\n gainsboro: 0xdcdcdc,\n ghostwhite: 0xf8f8ff,\n gold: 0xffd700,\n goldenrod: 0xdaa520,\n gray: 0x808080,\n green: 0x008000,\n greenyellow: 0xadff2f,\n grey: 0x808080,\n honeydew: 0xf0fff0,\n hotpink: 0xff69b4,\n indianred: 0xcd5c5c,\n indigo: 0x4b0082,\n ivory: 0xfffff0,\n khaki: 0xf0e68c,\n lavender: 0xe6e6fa,\n lavenderblush: 0xfff0f5,\n lawngreen: 0x7cfc00,\n lemonchiffon: 0xfffacd,\n lightblue: 0xadd8e6,\n lightcoral: 0xf08080,\n lightcyan: 0xe0ffff,\n lightgoldenrodyellow: 0xfafad2,\n lightgray: 0xd3d3d3,\n lightgreen: 0x90ee90,\n lightgrey: 0xd3d3d3,\n lightpink: 0xffb6c1,\n lightsalmon: 0xffa07a,\n lightseagreen: 0x20b2aa,\n lightskyblue: 0x87cefa,\n lightslategray: 0x778899,\n lightslategrey: 0x778899,\n lightsteelblue: 0xb0c4de,\n lightyellow: 0xffffe0,\n lime: 0x00ff00,\n limegreen: 0x32cd32,\n linen: 0xfaf0e6,\n magenta: 0xff00ff,\n maroon: 0x800000,\n mediumaquamarine: 0x66cdaa,\n mediumblue: 0x0000cd,\n mediumorchid: 0xba55d3,\n mediumpurple: 0x9370db,\n mediumseagreen: 0x3cb371,\n mediumslateblue: 0x7b68ee,\n mediumspringgreen: 0x00fa9a,\n mediumturquoise: 0x48d1cc,\n mediumvioletred: 0xc71585,\n midnightblue: 0x191970,\n mintcream: 0xf5fffa,\n mistyrose: 0xffe4e1,\n moccasin: 0xffe4b5,\n navajowhite: 0xffdead,\n navy: 0x000080,\n oldlace: 0xfdf5e6,\n olive: 0x808000,\n olivedrab: 0x6b8e23,\n orange: 0xffa500,\n orangered: 0xff4500,\n orchid: 0xda70d6,\n palegoldenrod: 0xeee8aa,\n palegreen: 0x98fb98,\n paleturquoise: 0xafeeee,\n palevioletred: 0xdb7093,\n papayawhip: 0xffefd5,\n peachpuff: 0xffdab9,\n peru: 0xcd853f,\n pink: 0xffc0cb,\n plum: 0xdda0dd,\n powderblue: 0xb0e0e6,\n purple: 0x800080,\n rebeccapurple: 0x663399,\n red: 0xff0000,\n rosybrown: 0xbc8f8f,\n royalblue: 0x4169e1,\n saddlebrown: 0x8b4513,\n salmon: 0xfa8072,\n sandybrown: 0xf4a460,\n seagreen: 0x2e8b57,\n seashell: 0xfff5ee,\n sienna: 0xa0522d,\n silver: 0xc0c0c0,\n skyblue: 0x87ceeb,\n slateblue: 0x6a5acd,\n slategray: 0x708090,\n slategrey: 0x708090,\n snow: 0xfffafa,\n springgreen: 0x00ff7f,\n steelblue: 0x4682b4,\n tan: 0xd2b48c,\n teal: 0x008080,\n thistle: 0xd8bfd8,\n tomato: 0xff6347,\n turquoise: 0x40e0d0,\n violet: 0xee82ee,\n wheat: 0xf5deb3,\n white: 0xffffff,\n whitesmoke: 0xf5f5f5,\n yellow: 0xffff00,\n yellowgreen: 0x9acd32\n};\n\ndefine(Color, color, {\n copy(channels) {\n return Object.assign(new this.constructor, this, channels);\n },\n displayable() {\n return this.rgb().displayable();\n },\n hex: color_formatHex, // Deprecated! Use color.formatHex.\n formatHex: color_formatHex,\n formatHex8: color_formatHex8,\n formatHsl: color_formatHsl,\n formatRgb: color_formatRgb,\n toString: color_formatRgb\n});\n\nfunction color_formatHex() {\n return this.rgb().formatHex();\n}\n\nfunction color_formatHex8() {\n return this.rgb().formatHex8();\n}\n\nfunction color_formatHsl() {\n return hslConvert(this).formatHsl();\n}\n\nfunction color_formatRgb() {\n return this.rgb().formatRgb();\n}\n\nexport default function color(format) {\n var m, l;\n format = (format + \"\").trim().toLowerCase();\n return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000\n : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00\n : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000\n : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000\n : null) // invalid hex\n : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)\n : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)\n : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)\n : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)\n : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)\n : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)\n : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins\n : format === \"transparent\" ? new Rgb(NaN, NaN, NaN, 0)\n : null;\n}\n\nfunction rgbn(n) {\n return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);\n}\n\nfunction rgba(r, g, b, a) {\n if (a <= 0) r = g = b = NaN;\n return new Rgb(r, g, b, a);\n}\n\nexport function rgbConvert(o) {\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Rgb;\n o = o.rgb();\n return new Rgb(o.r, o.g, o.b, o.opacity);\n}\n\nexport function rgb(r, g, b, opacity) {\n return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);\n}\n\nexport function Rgb(r, g, b, opacity) {\n this.r = +r;\n this.g = +g;\n this.b = +b;\n this.opacity = +opacity;\n}\n\ndefine(Rgb, rgb, extend(Color, {\n brighter(k) {\n k = k == null ? brighter : Math.pow(brighter, k);\n return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);\n },\n darker(k) {\n k = k == null ? darker : Math.pow(darker, k);\n return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);\n },\n rgb() {\n return this;\n },\n clamp() {\n return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));\n },\n displayable() {\n return (-0.5 <= this.r && this.r < 255.5)\n && (-0.5 <= this.g && this.g < 255.5)\n && (-0.5 <= this.b && this.b < 255.5)\n && (0 <= this.opacity && this.opacity <= 1);\n },\n hex: rgb_formatHex, // Deprecated! Use color.formatHex.\n formatHex: rgb_formatHex,\n formatHex8: rgb_formatHex8,\n formatRgb: rgb_formatRgb,\n toString: rgb_formatRgb\n}));\n\nfunction rgb_formatHex() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;\n}\n\nfunction rgb_formatHex8() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;\n}\n\nfunction rgb_formatRgb() {\n const a = clampa(this.opacity);\n return `${a === 1 ? \"rgb(\" : \"rgba(\"}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? \")\" : `, ${a})`}`;\n}\n\nfunction clampa(opacity) {\n return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity));\n}\n\nfunction clampi(value) {\n return Math.max(0, Math.min(255, Math.round(value) || 0));\n}\n\nfunction hex(value) {\n value = clampi(value);\n return (value < 16 ? \"0\" : \"\") + value.toString(16);\n}\n\nfunction hsla(h, s, l, a) {\n if (a <= 0) h = s = l = NaN;\n else if (l <= 0 || l >= 1) h = s = NaN;\n else if (s <= 0) h = NaN;\n return new Hsl(h, s, l, a);\n}\n\nexport function hslConvert(o) {\n if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Hsl;\n if (o instanceof Hsl) return o;\n o = o.rgb();\n var r = o.r / 255,\n g = o.g / 255,\n b = o.b / 255,\n min = Math.min(r, g, b),\n max = Math.max(r, g, b),\n h = NaN,\n s = max - min,\n l = (max + min) / 2;\n if (s) {\n if (r === max) h = (g - b) / s + (g < b) * 6;\n else if (g === max) h = (b - r) / s + 2;\n else h = (r - g) / s + 4;\n s /= l < 0.5 ? max + min : 2 - max - min;\n h *= 60;\n } else {\n s = l > 0 && l < 1 ? 0 : h;\n }\n return new Hsl(h, s, l, o.opacity);\n}\n\nexport function hsl(h, s, l, opacity) {\n return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);\n}\n\nfunction Hsl(h, s, l, opacity) {\n this.h = +h;\n this.s = +s;\n this.l = +l;\n this.opacity = +opacity;\n}\n\ndefine(Hsl, hsl, extend(Color, {\n brighter(k) {\n k = k == null ? brighter : Math.pow(brighter, k);\n return new Hsl(this.h, this.s, this.l * k, this.opacity);\n },\n darker(k) {\n k = k == null ? darker : Math.pow(darker, k);\n return new Hsl(this.h, this.s, this.l * k, this.opacity);\n },\n rgb() {\n var h = this.h % 360 + (this.h < 0) * 360,\n s = isNaN(h) || isNaN(this.s) ? 0 : this.s,\n l = this.l,\n m2 = l + (l < 0.5 ? l : 1 - l) * s,\n m1 = 2 * l - m2;\n return new Rgb(\n hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),\n hsl2rgb(h, m1, m2),\n hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),\n this.opacity\n );\n },\n clamp() {\n return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));\n },\n displayable() {\n return (0 <= this.s && this.s <= 1 || isNaN(this.s))\n && (0 <= this.l && this.l <= 1)\n && (0 <= this.opacity && this.opacity <= 1);\n },\n formatHsl() {\n const a = clampa(this.opacity);\n return `${a === 1 ? \"hsl(\" : \"hsla(\"}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? \")\" : `, ${a})`}`;\n }\n}));\n\nfunction clamph(value) {\n value = (value || 0) % 360;\n return value < 0 ? value + 360 : value;\n}\n\nfunction clampt(value) {\n return Math.max(0, Math.min(1, value || 0));\n}\n\n/* From FvD 13.37, CSS Color Module Level 3 */\nfunction hsl2rgb(h, m1, m2) {\n return (h < 60 ? m1 + (m2 - m1) * h / 60\n : h < 180 ? m2\n : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60\n : m1) * 255;\n}\n","export function basis(t1, v0, v1, v2, v3) {\n var t2 = t1 * t1, t3 = t2 * t1;\n return ((1 - 3 * t1 + 3 * t2 - t3) * v0\n + (4 - 6 * t2 + 3 * t3) * v1\n + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2\n + t3 * v3) / 6;\n}\n\nexport default function(values) {\n var n = values.length - 1;\n return function(t) {\n var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),\n v1 = values[i],\n v2 = values[i + 1],\n v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,\n v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n","import {basis} from \"./basis.js\";\n\nexport default function(values) {\n var n = values.length;\n return function(t) {\n var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),\n v0 = values[(i + n - 1) % n],\n v1 = values[i % n],\n v2 = values[(i + 1) % n],\n v3 = values[(i + 2) % n];\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n","export default x => () => x;\n","import constant from \"./constant.js\";\n\nfunction linear(a, d) {\n return function(t) {\n return a + t * d;\n };\n}\n\nfunction exponential(a, b, y) {\n return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {\n return Math.pow(a + t * b, y);\n };\n}\n\nexport function hue(a, b) {\n var d = b - a;\n return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a);\n}\n\nexport function gamma(y) {\n return (y = +y) === 1 ? nogamma : function(a, b) {\n return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a);\n };\n}\n\nexport default function nogamma(a, b) {\n var d = b - a;\n return d ? linear(a, d) : constant(isNaN(a) ? b : a);\n}\n","import {rgb as colorRgb} from \"d3-color\";\nimport basis from \"./basis.js\";\nimport basisClosed from \"./basisClosed.js\";\nimport nogamma, {gamma} from \"./color.js\";\n\nexport default (function rgbGamma(y) {\n var color = gamma(y);\n\n function rgb(start, end) {\n var r = color((start = colorRgb(start)).r, (end = colorRgb(end)).r),\n g = color(start.g, end.g),\n b = color(start.b, end.b),\n opacity = nogamma(start.opacity, end.opacity);\n return function(t) {\n start.r = r(t);\n start.g = g(t);\n start.b = b(t);\n start.opacity = opacity(t);\n return start + \"\";\n };\n }\n\n rgb.gamma = rgbGamma;\n\n return rgb;\n})(1);\n\nfunction rgbSpline(spline) {\n return function(colors) {\n var n = colors.length,\n r = new Array(n),\n g = new Array(n),\n b = new Array(n),\n i, color;\n for (i = 0; i < n; ++i) {\n color = colorRgb(colors[i]);\n r[i] = color.r || 0;\n g[i] = color.g || 0;\n b[i] = color.b || 0;\n }\n r = spline(r);\n g = spline(g);\n b = spline(b);\n color.opacity = 1;\n return function(t) {\n color.r = r(t);\n color.g = g(t);\n color.b = b(t);\n return color + \"\";\n };\n };\n}\n\nexport var rgbBasis = rgbSpline(basis);\nexport var rgbBasisClosed = rgbSpline(basisClosed);\n","/**\n * Map fill transition: tweens feature fills between layout snapshots.\n *\n * Captures current fill colors before a re-render, then interpolates\n * from previous to new fills using a rAF loop. Same approach as the\n * main chart transition driver, but scoped to map-specific concerns\n * (no geometry tweening, just color).\n */\n\nimport { interpolateRgb } from 'd3-interpolate';\nimport { easingFns } from './story/tween';\n\nexport function captureFeatureFills(svg: SVGElement | null): Map<string, string> {\n const fills = new Map<string, string>();\n if (!svg) return fills;\n const paths = svg.querySelectorAll('.oc-map-feature[data-key]');\n for (const p of paths) {\n const key = p.getAttribute('data-key');\n const fill = p.getAttribute('fill');\n if (key && fill) fills.set(key, fill);\n }\n return fills;\n}\n\nexport function runMapFillTransition(\n svg: SVGElement,\n prevFills: Map<string, string>,\n opts: { duration: number },\n): { cancel: () => void } {\n const paths = svg.querySelectorAll('.oc-map-feature[data-key]');\n const tweens: Array<{ el: Element; from: string; to: string; interp: (t: number) => string }> =\n [];\n\n for (const p of paths) {\n const key = p.getAttribute('data-key');\n const to = p.getAttribute('fill');\n const from = key ? prevFills.get(key) : null;\n if (from && to && from !== to) {\n tweens.push({ el: p, from, to, interp: interpolateRgb(from, to) });\n // Synchronous from-state: set previous fill before first rAF\n p.setAttribute('fill', from);\n }\n }\n\n if (tweens.length === 0 || opts.duration <= 0) {\n for (const tw of tweens) tw.el.setAttribute('fill', tw.to);\n return { cancel: () => {} };\n }\n\n const duration = opts.duration;\n let startTime: number | null = null;\n let rafId = 0;\n let cancelled = false;\n\n function tick(now: number) {\n if (cancelled) return;\n if (startTime === null) startTime = now;\n const elapsed = now - startTime;\n const t = Math.min(1, elapsed / duration);\n const eased = easingFns.easeInOutCubic(t);\n\n for (const tw of tweens) {\n tw.el.setAttribute('fill', tw.interp(eased));\n }\n\n if (t < 1) {\n rafId = requestAnimationFrame(tick);\n }\n }\n\n rafId = requestAnimationFrame(tick);\n\n return {\n cancel() {\n cancelled = true;\n cancelAnimationFrame(rafId);\n // Snap to final state\n for (const tw of tweens) {\n tw.el.setAttribute('fill', tw.to);\n }\n },\n };\n}\n","/**\n * Canvas-backed text measurement factory.\n *\n * Shared by mount.ts (charts) and sankey-mount.ts (sankey diagrams) so both\n * pipelines get accurate browser-measured text widths instead of the heuristic\n * fallback. Falls back to the heuristic when canvas isn't available (e.g. SSR).\n *\n * The font family is passed in (resolved from the container's --oc-font-family\n * or the spec theme) rather than hardcoded, so measurement matches what the SVG\n * text actually renders with. This matters on real devices where the primary\n * webfont (e.g. Inter) loads late: measuring against the wrong font produces\n * wrong widths and mangles layout.\n */\n\nimport type { MeasureTextFn } from '@opendata-ai/openchart-core';\nimport { estimateTextWidth } from '@opendata-ai/openchart-core';\n\nconst DEFAULT_FONT_FAMILY = 'Inter, sans-serif';\n\nexport function createMeasureText(fontFamily: string = DEFAULT_FONT_FAMILY): MeasureTextFn {\n let canvas: HTMLCanvasElement | null = null;\n let ctx: CanvasRenderingContext2D | null = null;\n\n return (\n text: string,\n fontSize: number,\n fontWeight?: number,\n ): { width: number; height: number } => {\n if (!canvas) {\n canvas = document.createElement('canvas');\n ctx = canvas.getContext('2d');\n }\n if (!ctx) {\n // Fallback: heuristic estimation\n return {\n width: estimateTextWidth(text, fontSize, fontWeight ?? 400),\n height: fontSize * 1.2,\n };\n }\n\n const weight = fontWeight ?? 400;\n ctx.font = `${weight} ${fontSize}px ${fontFamily}`;\n const metrics = ctx.measureText(text);\n return {\n width: metrics.width,\n height: fontSize * 1.2,\n };\n };\n}\n\n/**\n * Resolve the font family a container's SVG text will actually render with.\n *\n * Reads the --oc-font-family custom property (set by tokens.css once .oc-root\n * is applied, or overridden per-spec by the theme resolver), falling back to\n * the container's computed fontFamily, then to the default Inter stack. Returns\n * the previous hardcoded stack when there is no DOM (SSR) or no computed style.\n */\nexport function resolveFontFamily(container: HTMLElement): string {\n if (typeof window === 'undefined' || typeof getComputedStyle !== 'function') {\n return DEFAULT_FONT_FAMILY;\n }\n try {\n const style = getComputedStyle(container);\n const custom = style.getPropertyValue('--oc-font-family').trim();\n if (custom) return custom;\n const computed = style.fontFamily?.trim();\n if (computed) return computed;\n } catch {\n // getComputedStyle can throw on detached nodes in some engines; fall through.\n }\n return DEFAULT_FONT_FAMILY;\n}\n\n/**\n * The first family in a CSS font stack, with surrounding quotes stripped, e.g.\n * `'\"Inter Variable\", Inter, sans-serif'` -> `Inter Variable`. Used to build a\n * representative check string for document.fonts.check().\n */\nexport function primaryFontName(fontFamily: string): string {\n const first = fontFamily.split(',')[0]?.trim() ?? '';\n return first.replace(/^[\"']|[\"']$/g, '').trim();\n}\n\n/**\n * True when the primary font of the resolved stack is not yet loaded and a\n * later document.fonts.ready may change text metrics. False when fonts are\n * ready, unavailable (SSR / no FontFaceSet), or the primary is a generic family.\n */\nexport function fontsPending(fontFamily: string): boolean {\n if (typeof document === 'undefined') return false;\n const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n if (!fonts || typeof fonts.check !== 'function') return false;\n const name = primaryFontName(fontFamily);\n if (!name) return false;\n const generics = new Set([\n 'sans-serif',\n 'serif',\n 'monospace',\n 'system-ui',\n 'cursive',\n 'fantasy',\n 'ui-sans-serif',\n 'ui-serif',\n 'ui-monospace',\n ]);\n if (generics.has(name.toLowerCase())) return false;\n try {\n return !fonts.check(`12px \"${name}\"`);\n } catch {\n return false;\n }\n}\n\n/**\n * Run `onReady` exactly once after webfonts finish loading, if they were\n * pending at call time. `isAlive` is checked before invoking so a destroyed\n * chart is never re-rendered. Returns the initial pending state so callers can\n * set their `ocFontsState` dataset flag. No-op (returns false) under SSR or\n * when the primary font is already loaded.\n */\nexport function scheduleFontReload(\n fontFamily: string,\n isAlive: () => boolean,\n onReady: () => void,\n): boolean {\n if (!fontsPending(fontFamily)) return false;\n const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n if (!fonts?.ready) return false;\n fonts.ready.then(() => {\n if (isAlive()) onReady();\n });\n return true;\n}\n","/**\n * Text edit overlay: creates a positioned textarea over an SVG text element\n * for inline editing. Handles commit (Enter), cancel (Escape), and\n * click-outside-to-commit behavior.\n */\n\nexport interface TextEditOverlayConfig {\n /** The container div that holds the SVG. */\n container: HTMLElement;\n /** The root SVG element. */\n svg: SVGSVGElement;\n /** The SVG text element being edited. */\n targetElement: SVGElement;\n /** Current text content to populate the textarea. */\n currentText: string;\n /** Called when the user commits the edit (Enter or click outside). */\n onCommit: (newText: string) => void;\n /** Called when the user cancels the edit (Escape). */\n onCancel: () => void;\n}\n\n/**\n * Get the viewBox-to-pixel scale factors for an SVG element.\n * Same approach used by the drag handlers in mount.ts.\n */\nfunction getScale(svg: SVGSVGElement): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1,\n scaleY: viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1,\n };\n}\n\n/**\n * Read computed font styles from an SVG text element and map them to CSS.\n */\nfunction getTextStyles(\n targetElement: SVGElement,\n scale: { scaleX: number; scaleY: number },\n): {\n fontFamily: string;\n fontSize: string;\n fontWeight: string;\n color: string;\n textAlign: string;\n lineHeight: string;\n} {\n const computed = window.getComputedStyle(targetElement);\n\n // Font size needs to be scaled from SVG viewBox units to pixel units\n const svgFontSize = parseFloat(\n targetElement.getAttribute('font-size') ?? computed.fontSize ?? '14',\n );\n const pixelFontSize = svgFontSize * scale.scaleY;\n\n const fontFamily = targetElement.getAttribute('font-family') ?? computed.fontFamily ?? 'inherit';\n const fontWeight = targetElement.getAttribute('font-weight') ?? computed.fontWeight ?? '400';\n\n // Get fill color from inline style or attribute\n const fill =\n (targetElement as SVGElement & ElementCSSInlineStyle).style.getPropertyValue('fill') ||\n targetElement.getAttribute('fill') ||\n computed.color ||\n '#000';\n\n // Map SVG text-anchor to CSS text-align\n const textAnchor = targetElement.getAttribute('text-anchor') ?? 'start';\n let textAlign = 'left';\n if (textAnchor === 'middle') textAlign = 'center';\n else if (textAnchor === 'end') textAlign = 'right';\n\n return {\n fontFamily,\n fontSize: `${pixelFontSize}px`,\n fontWeight,\n color: fill,\n textAlign,\n lineHeight: '1.3',\n };\n}\n\n/**\n * Compute the pixel position and size for the textarea based on the\n * target SVG element's bounding box.\n */\nfunction computePosition(\n targetElement: SVGElement,\n svg: SVGSVGElement,\n container: HTMLElement,\n): { top: number; left: number; width: number; height: number } {\n const bbox = (targetElement as SVGGraphicsElement).getBBox();\n const scale = getScale(svg);\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n\n // SVG viewBox coords -> pixel coords relative to the container\n const padding = 4;\n const left = bbox.x * scale.scaleX + (svgRect.left - containerRect.left) - padding;\n const top = bbox.y * scale.scaleY + (svgRect.top - containerRect.top) - padding;\n const width = bbox.width * scale.scaleX + padding * 2;\n const height = bbox.height * scale.scaleY + padding * 2;\n\n return {\n top: Math.max(0, top),\n left: Math.max(0, left),\n width: Math.max(width, 60),\n height: Math.max(height, 24),\n };\n}\n\n/**\n * Create an inline text editing overlay positioned over an SVG text element.\n * Returns an object with a `destroy()` method to clean up.\n */\nexport function createTextEditOverlay(config: TextEditOverlayConfig): { destroy: () => void } {\n const { container, svg, targetElement, currentText, onCommit, onCancel } = config;\n\n let destroyed = false;\n\n // Hide the underlying SVG text element (not display:none to preserve layout)\n const originalOpacity = targetElement.getAttribute('opacity');\n targetElement.setAttribute('opacity', '0');\n\n // Compute position and styles\n const scale = getScale(svg);\n const styles = getTextStyles(targetElement, scale);\n const position = computePosition(targetElement, svg, container);\n\n // Create the textarea\n const textarea = document.createElement('textarea');\n textarea.value = currentText;\n\n // Ensure container is positioned so absolute children work\n const containerPosition = window.getComputedStyle(container).position;\n const containerWasStatic = containerPosition === 'static';\n if (containerWasStatic) {\n container.style.position = 'relative';\n }\n\n // Style the textarea to match the SVG text\n Object.assign(textarea.style, {\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n width: `${position.width}px`,\n minHeight: `${position.height}px`,\n fontFamily: styles.fontFamily,\n fontSize: styles.fontSize,\n fontWeight: styles.fontWeight,\n color: styles.color,\n textAlign: styles.textAlign,\n lineHeight: styles.lineHeight,\n padding: '2px 4px',\n margin: '0',\n border: '1px solid rgba(79, 70, 229, 0.4)', // intentionally 0.4, not --oc-editable-hover (0.35)\n borderRadius: '3px',\n background: 'rgba(255, 255, 255, 0.95)',\n outline: 'none',\n resize: 'none',\n overflow: 'hidden',\n boxSizing: 'border-box',\n zIndex: '10000',\n // Remove default textarea appearance\n WebkitAppearance: 'none',\n appearance: 'none',\n } as Record<string, string>);\n\n container.appendChild(textarea);\n\n // Auto-select all text\n textarea.focus();\n textarea.select();\n\n // Cleanup function\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Restore SVG text visibility\n if (originalOpacity !== null) {\n targetElement.setAttribute('opacity', originalOpacity);\n } else {\n targetElement.removeAttribute('opacity');\n }\n\n // Remove event listeners\n textarea.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n resizeObserver.disconnect();\n\n // Restore container position if we changed it\n if (containerWasStatic) {\n container.style.position = '';\n }\n\n // Remove the textarea\n if (textarea.parentNode) {\n textarea.parentNode.removeChild(textarea);\n }\n }\n\n function commit(): void {\n if (destroyed) return;\n const newText = textarea.value;\n destroy();\n onCommit(newText);\n }\n\n function cancel(): void {\n if (destroyed) return;\n destroy();\n onCancel();\n }\n\n // Keyboard handling\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n commit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancel();\n }\n };\n\n textarea.addEventListener('keydown', handleKeyDown);\n\n // Click outside to commit\n const handleClickOutside = (e: MouseEvent) => {\n if (!textarea.contains(e.target as Node)) {\n commit();\n }\n };\n\n // Delay attaching click-outside so the current click event doesn't trigger it\n requestAnimationFrame(() => {\n if (!destroyed) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n });\n\n // Reposition on container resize\n const resizeObserver = new ResizeObserver(() => {\n if (destroyed) return;\n const newPosition = computePosition(targetElement, svg, container);\n textarea.style.top = `${newPosition.top}px`;\n textarea.style.left = `${newPosition.left}px`;\n textarea.style.width = `${newPosition.width}px`;\n textarea.style.minHeight = `${newPosition.height}px`;\n });\n resizeObserver.observe(container);\n\n return { destroy };\n}\n","/**\n * \"You draw it\" interaction layer: the DOM/SVG overlay for the `youDrawIt`\n * spec option (NYT-style draw-then-reveal engagement format).\n *\n * SVG-space elements (hatched drawing region, reader's guess path, reveal\n * clip rect, pointer-capture overlay) render inside the chart's own SVG so\n * they clip and scale with it. The prompt text and skip-to-reveal button are\n * a small HTML overlay positioned over the drawing region, following the\n * series-search precedent (`series-search.ts`): a native `<button>` gets\n * keyboard semantics for free instead of hand-rolling SVG focus handling.\n *\n * State (the reader's in-progress guess) lives in this module's closure,\n * matching mount.ts's per-instance-closure convention (StrictMode double-\n * mount safe): a fresh `createYouDrawIt()` call gets a fresh closure.\n */\n\nimport type { Point, ResolvedYouDrawIt } from '@opendata-ai/openchart-core';\nimport { createSVGElement, SVG_NS, setAttrs } from './renderers/svg-dom';\nimport { nextSvgId } from './svg-ids';\n\nexport interface YouDrawItOptions {\n /** The chart container (`.oc-root`). Must be position: relative. */\n container: HTMLElement;\n /** Fired once the drawing is revealed, with the guess in data coordinates ordered by x. */\n onReveal?: (guess: Array<{ x: string | number; y: number }>) => void;\n}\n\nexport interface YouDrawItController {\n /** Reposition, resync geometry, and (re)wire pointer capture against a freshly rendered layout + SVG. */\n update(config: ResolvedYouDrawIt, svg: SVGSVGElement): void;\n /** Hide (spec no longer wants youDrawIt on this render, e.g. mark type changed). */\n hide(): void;\n /** Reveal the real line and fire onReveal, without requiring reader interaction (skip-to-reveal). */\n reveal(): void;\n /** Clear the reader's guess and return to the drawing state. */\n reset(): void;\n /** Whether the drawing has been revealed. */\n readonly isRevealed: boolean;\n /** Remove all DOM elements. */\n destroy(): void;\n}\n\n/** Minimum touch target size (effective hit area), per WCAG 2.5.5 / mobile a11y conventions. */\nconst MIN_TOUCH_TARGET = 24;\n\n/** Build the \"M x,y L x,y ...\" path string for a straight-segment line through points, sorted by x. */\nfunction buildLinearPath(points: Point[]): string {\n if (points.length === 0) return '';\n const sorted = [...points].sort((a, b) => a.x - b.x);\n return sorted.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');\n}\n\n/**\n * Create the you-draw-it control. Mounted once per chart instance and kept\n * across re-renders so the in-progress drawing survives; `update()` re-syncs\n * geometry and re-wires pointer capture after each render.\n */\nexport function createYouDrawIt(options: YouDrawItOptions): YouDrawItController {\n const { container, onReveal } = options;\n\n let destroyed = false;\n let revealed = false;\n let config: ResolvedYouDrawIt | null = null;\n let svgEl: SVGSVGElement | null = null;\n /** Reader's guess: pixel y keyed by pixel x sample. */\n const guessByX = new Map<number, number>();\n let cleanupPointerEvents: (() => void) | null = null;\n\n // ---------------------------------------------------------------------------\n // SVG elements (rebuilt each update() since the SVG itself is rebuilt on render)\n // ---------------------------------------------------------------------------\n\n function buildHatchPattern(id: string, color: string): SVGElement {\n const pattern = document.createElementNS(SVG_NS, 'pattern');\n pattern.setAttribute('id', id);\n pattern.setAttribute('patternUnits', 'userSpaceOnUse');\n pattern.setAttribute('width', '8');\n pattern.setAttribute('height', '8');\n pattern.setAttribute('patternTransform', 'rotate(45)');\n const line = document.createElementNS(SVG_NS, 'line');\n setAttrs(line, { x1: 0, y1: 0, x2: 0, y2: 8, stroke: color, 'stroke-width': 1 });\n line.setAttribute('stroke-opacity', '0.5');\n pattern.appendChild(line);\n return pattern;\n }\n\n /** Locate the target line's <path> in the freshly rendered SVG. */\n function findTargetLinePath(svg: SVGSVGElement, seriesKey?: string): SVGPathElement | null {\n // Line marks render as <g data-mark-id=\"line-{seriesKey ?? index}\"> with a\n // single <path> child (see renderers/marks.ts). Prefer the seriesKey match;\n // fall back to the first line mark for single-series charts (no color enc).\n if (seriesKey) {\n const escaped =\n typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(seriesKey)\n : seriesKey.replace(/\"/g, '\\\\\"');\n const byKey = svg.querySelector<SVGPathElement>(`[data-mark-id=\"line-${escaped}\"] path`);\n if (byKey) return byKey;\n }\n return svg.querySelector<SVGPathElement>('.oc-mark-line path');\n }\n\n function render(cfg: ResolvedYouDrawIt, svg: SVGSVGElement): void {\n // Remove any previous you-draw-it group (SVG is rebuilt each render, but\n // defensive against re-entrant calls).\n svg.querySelector('[data-you-draw-it]')?.remove();\n\n const group = createSVGElement('g') as SVGGElement;\n group.setAttribute('data-you-draw-it', 'true');\n group.setAttribute('class', 'oc-ydi');\n\n const { area, fromX } = cfg;\n const regionWidth = Math.max(0, area.x + area.width - fromX);\n\n // Hatch pattern + reveal clip defs.\n const defs = createSVGElement('defs');\n const patternId = nextSvgId('oc-ydi-hatch');\n defs.appendChild(buildHatchPattern(patternId, cfg.lineColor));\n\n // Reveal clip: masks the real line's post-from segment until reveal.\n // Applied to the target line path element itself (not a <g>), matching\n // the SVG clip-path gotcha in .claude/rules/svg-animation.md.\n const clipId = nextSvgId('oc-ydi-clip');\n const clipPath = createSVGElement('clipPath');\n clipPath.setAttribute('id', clipId);\n const clipRect = createSVGElement('rect');\n setAttrs(clipRect, {\n x: area.x,\n y: area.y,\n width: revealed ? area.width : Math.max(0, fromX - area.x),\n height: area.height,\n });\n clipRect.setAttribute('data-ydi-clip-rect', 'true');\n clipRect.setAttribute('class', 'oc-ydi-clip-rect');\n clipPath.appendChild(clipRect);\n defs.appendChild(clipPath);\n group.appendChild(defs);\n\n // Hatched \"draw here\" region.\n const region = createSVGElement('rect');\n setAttrs(region, {\n x: fromX,\n y: area.y,\n width: regionWidth,\n height: area.height,\n fill: `url(#${patternId})`,\n });\n region.setAttribute('class', 'oc-ydi-region');\n region.setAttribute('data-ydi-region', 'true');\n region.setAttribute('pointer-events', 'none');\n if (revealed) region.setAttribute('data-ydi-hidden', 'true');\n group.appendChild(region);\n\n // \"from\" boundary marker: a thin dashed rule where drawing begins.\n const boundary = createSVGElement('line');\n setAttrs(boundary, { x1: fromX, y1: area.y, x2: fromX, y2: area.y + area.height });\n boundary.setAttribute('class', 'oc-ydi-boundary');\n boundary.setAttribute('pointer-events', 'none');\n group.appendChild(boundary);\n\n const targetLineEl = findTargetLinePath(svg, cfg.targetSeriesKey);\n if (targetLineEl) {\n targetLineEl.setAttribute('clip-path', `url(#${clipId})`);\n }\n\n // Optional comparison line (host-supplied \"everyone else's guess\").\n if (cfg.comparisonPoints && cfg.comparisonPoints.length > 0) {\n const compPath = createSVGElement('path');\n setAttrs(compPath, { d: buildLinearPath(cfg.comparisonPoints), fill: 'none' });\n compPath.setAttribute('class', 'oc-ydi-comparison');\n compPath.setAttribute('pointer-events', 'none');\n group.appendChild(compPath);\n }\n\n // Reader's guess path (pen style), populated as the reader draws.\n const guessPath = createSVGElement('path');\n setAttrs(guessPath, { d: '', fill: 'none' });\n guessPath.setAttribute('class', 'oc-ydi-guess');\n guessPath.setAttribute('data-ydi-guess-path', 'true');\n guessPath.setAttribute('pointer-events', 'none');\n group.appendChild(guessPath);\n\n // Pointer-capture overlay over the drawing region only.\n if (!revealed) {\n const overlay = createSVGElement('rect');\n setAttrs(overlay, {\n x: fromX,\n y: area.y,\n width: regionWidth,\n height: area.height,\n fill: 'transparent',\n });\n overlay.setAttribute('class', 'oc-ydi-overlay');\n overlay.setAttribute('data-ydi-overlay', 'true');\n overlay.setAttribute('role', 'img');\n overlay.setAttribute(\n 'aria-label',\n 'Drawing area: drag to sketch your guess of the trend, or use the reveal button to skip.',\n );\n overlay.style.touchAction = 'none';\n overlay.style.cursor = 'crosshair';\n group.appendChild(overlay);\n }\n\n svg.appendChild(group);\n }\n\n function redrawGuessPath(): void {\n if (!svgEl) return;\n const path = svgEl.querySelector<SVGPathElement>('[data-ydi-guess-path]');\n if (!path) return;\n const points: Point[] = Array.from(guessByX.entries()).map(([x, y]) => ({ x, y }));\n path.setAttribute('d', buildLinearPath(points));\n }\n\n function snapToNearestSample(px: number): number | null {\n if (!config || config.samples.length === 0) return null;\n let nearestPx = config.samples[0].px;\n let best = Math.abs(nearestPx - px);\n for (const s of config.samples) {\n const d = Math.abs(s.px - px);\n if (d < best) {\n best = d;\n nearestPx = s.px;\n }\n }\n return nearestPx;\n }\n\n function clampY(py: number): number {\n if (!config) return py;\n return Math.min(config.area.y + config.area.height, Math.max(config.area.y, py));\n }\n\n // ---------------------------------------------------------------------------\n // Pointer capture (mouse + touch), following the crosshair toSvgCoords pattern\n // ---------------------------------------------------------------------------\n\n function wirePointerEvents(svg: SVGSVGElement): () => void {\n const overlay = svg.querySelector('[data-ydi-overlay]');\n if (!overlay) return () => {};\n\n let dragging = false;\n\n const toSvgCoords = (clientX: number, clientY: number) => {\n const svgRect = svg.getBoundingClientRect();\n const viewBox = svg.viewBox?.baseVal;\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n return {\n svgX: (clientX - svgRect.left) * scaleX,\n svgY: (clientY - svgRect.top) * scaleY,\n };\n };\n\n const paintAt = (clientX: number, clientY: number) => {\n const { svgX, svgY } = toSvgCoords(clientX, clientY);\n const snapped = snapToNearestSample(svgX);\n if (snapped === null) return;\n guessByX.set(snapped, clampY(svgY));\n redrawGuessPath();\n };\n\n const handleMouseDown = (e: Event) => {\n const me = e as MouseEvent;\n dragging = true;\n paintAt(me.clientX, me.clientY);\n };\n const handleMouseMove = (e: Event) => {\n if (!dragging) return;\n const me = e as MouseEvent;\n paintAt(me.clientX, me.clientY);\n };\n const handleMouseUp = () => {\n dragging = false;\n };\n\n const handleTouchStart = (e: Event) => {\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n if (te.cancelable) te.preventDefault();\n dragging = true;\n paintAt(te.touches[0].clientX, te.touches[0].clientY);\n };\n const handleTouchMove = (e: Event) => {\n if (!dragging) return;\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n if (te.cancelable) te.preventDefault();\n paintAt(te.touches[0].clientX, te.touches[0].clientY);\n };\n const handleTouchEnd = () => {\n dragging = false;\n };\n\n overlay.addEventListener('mousedown', handleMouseDown);\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n overlay.addEventListener('touchstart', handleTouchStart, { passive: false });\n overlay.addEventListener('touchmove', handleTouchMove, { passive: false });\n overlay.addEventListener('touchend', handleTouchEnd);\n overlay.addEventListener('touchcancel', handleTouchEnd);\n\n return () => {\n overlay.removeEventListener('mousedown', handleMouseDown);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n overlay.removeEventListener('touchstart', handleTouchStart);\n overlay.removeEventListener('touchmove', handleTouchMove);\n overlay.removeEventListener('touchend', handleTouchEnd);\n overlay.removeEventListener('touchcancel', handleTouchEnd);\n };\n }\n\n // ---------------------------------------------------------------------------\n // Prompt + reveal button (HTML overlay, positioned over the drawing region)\n // ---------------------------------------------------------------------------\n\n const root = document.createElement('div');\n root.className = 'oc-ydi-controls';\n root.style.display = 'none';\n root.style.position = 'absolute';\n\n const prompt = document.createElement('div');\n prompt.className = 'oc-ydi-prompt';\n\n const revealButton = document.createElement('button');\n revealButton.type = 'button';\n revealButton.className = 'oc-ydi-reveal-button';\n\n root.append(prompt, revealButton);\n container.style.position = container.style.position || 'relative';\n container.appendChild(root);\n\n function reduceMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n !!window.matchMedia &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n }\n\n /**\n * Map a drawn pixel y back to a data value via the linear yInvert anchors.\n *\n * This interpolates linearly in pixel space between the top and bottom\n * anchors. For a linear y-scale that is exact. For a log or pow scale it is\n * an approximation: the true inverse is curved, so a guess drawn halfway up\n * the plot reads back as the arithmetic midpoint of the domain rather than\n * the geometric (log) or power midpoint. The you-draw-it guess is a rough\n * \"where did the reader think the line went\" signal, not a precise readout,\n * so the linear approximation is acceptable here; revisit if a non-linear\n * scale ever needs an exact guess value.\n */\n function pixelYToData(py: number): number {\n if (!config) return py;\n const inv = config.yInvert;\n if (!inv) {\n // No invertible scale: report the pixel y normalized to the area (1 at\n // top, 0 at bottom) so callers still get relative shape.\n const area = config.area;\n return 1 - (py - area.y) / (area.height || 1);\n }\n const span = inv.bottomPixel - inv.topPixel;\n if (span === 0) return inv.topData;\n const t = (py - inv.topPixel) / span;\n return inv.topData + t * (inv.bottomData - inv.topData);\n }\n\n function getGuessData(): Array<{ x: string | number; y: number }> {\n if (!config) return [];\n const valueByPx = new Map(config.samples.map((s) => [s.px, s.xValue]));\n return Array.from(guessByX.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([px, py]) => ({ x: valueByPx.get(px) ?? px, y: pixelYToData(py) }));\n }\n\n function doReveal(): void {\n if (destroyed || revealed || !svgEl || !config) return;\n revealed = true;\n\n const clipRect = svgEl.querySelector<SVGRectElement>('[data-ydi-clip-rect]');\n if (clipRect) {\n if (reduceMotion()) {\n clipRect.setAttribute('width', String(config.area.width));\n } else {\n clipRect.classList.add('oc-ydi-clip-animate');\n // Force layout so the transition on the width change is observed. The\n // update-transition rAF driver only tracks marks, so a scoped CSS\n // transition on the clip rect is the plan's accepted fallback.\n void clipRect.getBoundingClientRect();\n clipRect.setAttribute('width', String(config.area.width));\n }\n }\n const region = svgEl.querySelector<SVGRectElement>('[data-ydi-region]');\n region?.setAttribute('data-ydi-hidden', 'true');\n svgEl.querySelector('[data-ydi-overlay]')?.remove();\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n root.classList.add('oc-ydi-revealed');\n prompt.textContent = '';\n revealButton.disabled = true;\n\n onReveal?.(getGuessData());\n }\n\n revealButton.addEventListener('click', doReveal);\n\n return {\n update(cfg: ResolvedYouDrawIt, svg: SVGSVGElement): void {\n if (destroyed) return;\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n\n config = cfg;\n svgEl = svg;\n\n render(cfg, svg);\n redrawGuessPath();\n\n prompt.textContent = revealed ? '' : cfg.prompt;\n revealButton.textContent = cfg.revealLabel;\n revealButton.setAttribute('aria-label', cfg.revealLabel);\n revealButton.style.minHeight = `${MIN_TOUCH_TARGET}px`;\n revealButton.disabled = revealed;\n if (revealed) root.classList.add('oc-ydi-revealed');\n else root.classList.remove('oc-ydi-revealed');\n\n // Position the HTML controls over the drawing region. Same viewBox-scale\n // approach as series-search / the text edit overlay.\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const scaleX = viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1;\n const regionWidth = Math.max(0, cfg.area.x + cfg.area.width - cfg.fromX);\n root.style.left = `${cfg.fromX * scaleX + (svgRect.left - containerRect.left)}px`;\n root.style.top = `${cfg.area.y * scaleY + (svgRect.top - containerRect.top)}px`;\n root.style.width = `${regionWidth * scaleX}px`;\n root.style.height = `${cfg.area.height * scaleY}px`;\n root.style.display = 'flex';\n\n if (!revealed) {\n cleanupPointerEvents = wirePointerEvents(svg);\n }\n },\n hide(): void {\n root.style.display = 'none';\n svgEl?.querySelector('[data-you-draw-it]')?.remove();\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n },\n reveal(): void {\n doReveal();\n },\n reset(): void {\n if (destroyed) return;\n revealed = false;\n guessByX.clear();\n revealButton.disabled = false;\n root.classList.remove('oc-ydi-revealed');\n if (config && svgEl) {\n render(config, svgEl);\n prompt.textContent = config.prompt;\n cleanupPointerEvents?.();\n cleanupPointerEvents = wirePointerEvents(svgEl);\n }\n },\n get isRevealed(): boolean {\n return revealed;\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n root.remove();\n },\n };\n}\n","/**\n * Mount API: the main entry point for vanilla JS usage.\n *\n * createChart() takes a container, spec, and options, compiles the chart,\n * renders it as SVG, sets up responsive resizing, tooltip interaction\n * (mouse/touch/keyboard), keyboard navigation between data points,\n * and returns a ChartInstance with update/resize/export/destroy methods.\n */\n\nimport type {\n Annotation,\n ChartEventHandlers,\n ChartLayout,\n ChartSpec,\n CompileOptions,\n DarkMode,\n DataRow,\n ElementRef,\n GraphSpec,\n LayerSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { cssTokenDefault, isGraphSpec, isLayerSpec } from '@opendata-ai/openchart-core';\nimport {\n compileChart,\n compileLayer,\n facetMinHeight,\n legendGap,\n} from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport {\n buildElementRef,\n createScreenReaderTable,\n findElementByRef,\n getEditableElements,\n getElementText,\n isTextEditable,\n refsEqual,\n renderSelectionOverlay,\n wireAnnotationDrag,\n wireAnnotationLabelDrag,\n wireChartEvents,\n wireChromeDrag,\n wireConnectorEndpointDrag,\n wireKeyboardNav,\n wireLegendDrag,\n wireLegendInteraction,\n wireSeriesLabelDrag,\n wireTooltipEvents,\n wireVoronoiTooltipEvents,\n} from './interactions';\nimport { createMeasureText, resolveFontFamily, scheduleFontReload } from './measure-text';\nimport { observeResize } from './resize-observer';\nimport { createSeriesSearch, type SeriesSearchController } from './series-search';\nimport { renderChartSVG } from './svg-renderer';\nimport { createTextEditOverlay } from './text-edit-overlay';\nimport { stampThemeProperties } from './theme-tokens';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\nimport { canTransition, type GeometrySnapshot, runTransition } from './transition';\nimport { createYouDrawIt, type YouDrawItController } from './you-draw-it';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MountOptions extends ChartEventHandlers {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Callback when a data point is clicked. @deprecated Use onMarkClick instead. */\n onDataPointClick?: (data: Record<string, unknown>) => void;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Initial selected element. */\n selectedElement?: ElementRef;\n}\n\nexport interface UpdateOptions {\n /** Override the selected element after update. When omitted, preserves current selection. */\n selectedElement?: ElementRef;\n}\n\nexport interface ExportOptions extends JPGExportOptions {\n // Extensible for future formats (extends JPGExportOptions which extends PNGExportOptions)\n}\n\nexport interface ChartInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: ChartSpec | LayerSpec | GraphSpec, options?: UpdateOptions): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the chart. */\n export(format: 'svg'): string;\n export(format: 'svg-with-fonts', options?: SVGExportOptions): Promise<string>;\n export(format: 'png', options?: ExportOptions): Promise<Blob>;\n export(format: 'jpg', options?: ExportOptions): Promise<Blob>;\n export(format: 'csv'): string;\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n options?: ExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout (for hooks / debugging). */\n readonly layout: ChartLayout;\n /** Get the currently selected element, or null if none. */\n getSelectedElement(): ElementRef | null;\n /** Programmatically select an element. Silent no-op if element not found. */\n select(ref: ElementRef): void;\n /** Deselect the current element. */\n deselect(): void;\n /** Whether inline text editing is active. */\n readonly isEditing: boolean;\n /** Set highlight values on the color encoding and re-render. Pass null to clear. */\n setHighlight(values: string[] | null): void;\n /**\n * Reset a \"you draw it\" (`youDrawIt`) drawing: clears the reader's guess and\n * returns to the drawing state. No-op when youDrawIt isn't enabled.\n */\n resetDrawing(): void;\n /**\n * Reveal a \"you draw it\" drawing programmatically (equivalent to the\n * skip-to-reveal button). No-op when youDrawIt isn't enabled.\n */\n revealDrawing(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Container sizing\n// ---------------------------------------------------------------------------\n\n/**\n * Fallback height when the container doesn't constrain height. For\n * auto-height ChartSpec mounts this is the fixed budget for the\n * visualization itself (padding + axes + plot); chrome, the top legend\n * block, and the metrics bar grow the figure on top of it.\n */\nconst FALLBACK_HEIGHT = 400;\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Editable element helpers\n// ---------------------------------------------------------------------------\n\nconst EDITABLE_HOVER_CSS = `\n.oc-editable-hover {\n outline: 1.5px solid ${cssTokenDefault('--oc-editable-hover', 'light')};\n outline-offset: 2px;\n border-radius: 2px;\n}\n`;\n\nfunction makeEditable(svg: SVGElement): void {\n svg.setAttribute('tabindex', '0');\n svg.style.outline = 'none';\n\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n style.textContent = EDITABLE_HOVER_CSS;\n svg.insertBefore(style, svg.firstChild);\n}\n\nfunction hasEditingCallbacks(opts?: MountOptions): boolean {\n return !!(opts?.onEdit || opts?.onSelect || opts?.onDeselect || opts?.onTextEdit);\n}\n\n// ---------------------------------------------------------------------------\n// Series search helpers\n// ---------------------------------------------------------------------------\n\n/** The authored encoding.color.highlight as an array (empty when unset). */\nfunction authoredHighlight(spec: ChartSpec | LayerSpec | GraphSpec): string[] {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return [];\n const colorEnc = (spec as ChartSpec).encoding?.color;\n if (!colorEnc || typeof colorEnc !== 'object' || !('field' in colorEnc)) return [];\n const raw = (colorEnc as { highlight?: string | string[] }).highlight;\n if (raw == null) return [];\n return Array.isArray(raw) ? [...raw] : [raw];\n}\n\n/** True when the spec enables the series search input. */\nfunction wantsSeriesSearch(spec: ChartSpec | LayerSpec | GraphSpec): boolean {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return false;\n return !!(spec as ChartSpec).seriesSearch;\n}\n\n/** True when the spec enables the \"you draw it\" interactive format. */\nfunction wantsYouDrawIt(spec: ChartSpec | LayerSpec | GraphSpec): boolean {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return false;\n return !!(spec as ChartSpec).youDrawIt;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a chart instance from a spec and mount it into a container.\n */\nexport function createChart<TData extends DataRow = DataRow>(\n container: HTMLElement,\n spec: ChartSpec<TData> | LayerSpec<TData> | GraphSpec,\n options?: MountOptions,\n): ChartInstance {\n let currentSpec: ChartSpec | LayerSpec | GraphSpec = spec as ChartSpec | LayerSpec | GraphSpec;\n let currentLayout: ChartLayout;\n let svgElement: SVGElement | null = null;\n let tooltipManager: TooltipManager | null = null;\n let disconnectResize: (() => void) | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let cleanupVoronoiEvents: (() => void) | null = null;\n let cleanupKeyboardNav: (() => void) | null = null;\n let cleanupLegend: (() => void) | null = null;\n let cleanupChartEvents: (() => void) | null = null;\n let cleanupAnnotationDrag: (() => void) | null = null;\n let cleanupEditDrags: (() => void) | null = null;\n let cleanupSelection: (() => void) | null = null;\n let cleanupKeyboardEdit: (() => void) | null = null;\n let srTable: HTMLTableElement | null = null;\n let destroyed = false;\n let isDragging = false;\n let pendingRender = false;\n\n // Animation state\n let isFirstRender = true;\n let cleanupAnimations: (() => void) | null = null;\n let pendingResize = false;\n\n // Auto-height sizing state. `isAutoHeight` latches whether the host\n // constrains the container's height:\n // null = unknown — every measurement so far was an all-zero rect\n // (display:none / detached); keep re-checking each measure.\n // true = auto-height — the figure grows with chrome (ChartSpec only).\n // false = explicit height — fit inside the host's box (today's behavior).\n // The latch matters because the SVG's own style.height gives the container\n // a nonzero rect after the first render, so auto-height cannot be\n // re-derived per measure.\n let isAutoHeight: boolean | null = null;\n let lastRenderedWidth: number | null = null;\n let lastRenderedSvgHeight: number | null = null;\n\n // Data-update transition state\n let transitionHandle: import('./transition').TransitionHandle | null = null;\n let transitionSnapshot: GeometrySnapshot | null = null;\n\n // Set when webfonts have loaded and a recompile is owed to reflect final font\n // metrics. The next render() that actually recompiles flips\n // data-oc-fonts-state to 'ready' and clears this. Deferring the flip (rather\n // than setting it right after resize()) keeps the attribute honest when the\n // entrance animation makes resize() defer to pendingResize.\n let fontsReloadPending = false;\n\n // Selection and text editing state\n let selectedElement: ElementRef | null = options?.selectedElement ?? null;\n let overlayElement: SVGGElement | null = null;\n let isTextEditingActive = false;\n\n // Runtime legend-toggle state\n const runtimeHiddenSeries = new Set<string>();\n const runtimeShownSeries = new Set<string>();\n let textEditCleanup: (() => void) | null = null;\n\n // Series search state. The control persists across renders (so focus and\n // chips survive the re-render each selection triggers); the baseline is the\n // authored encoding.color.highlight, captured before setHighlight mutates\n // currentSpec, so clearing the search restores it exactly.\n let seriesSearch: SeriesSearchController | null = null;\n let searchBaseline: string[] = authoredHighlight(currentSpec);\n let editSuppressWarned = false;\n\n // \"You draw it\" state. The controller persists across renders so the reader's\n // in-progress guess (and revealed state) survive the re-render each resize\n // triggers; update() re-syncs geometry and re-wires pointer capture.\n let youDrawIt: YouDrawItController | null = null;\n let ydiEditSuppressWarned = false;\n\n // Apply the root class up front so getComputedStyle can read --oc-font-family\n // before we build the text measurer.\n container.classList.add('oc-root');\n\n // Resolve the effective font family the way compile() will. compile merges\n // { ...spec.theme, ...options.theme }, so options.theme wins over the\n // spec-level theme; fall back to the container's computed font. Measuring\n // against a different font than compile renders (e.g. a spec that sets\n // theme.fonts.family) desyncs layout metrics and the font-reload watcher.\n function resolveEffectiveFont(): string {\n return (\n options?.theme?.fonts?.family ??\n currentSpec.theme?.fonts?.family ??\n resolveFontFamily(container)\n );\n }\n let fontFamily = resolveEffectiveFont();\n let measureText = createMeasureText(fontFamily);\n let renderGen = 0;\n\n // ---------------------------------------------------------------------------\n // Compilation\n // ---------------------------------------------------------------------------\n\n function compileAt(width: number, height: number): ChartLayout {\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n measureText,\n };\n\n if (isLayerSpec(currentSpec)) {\n return compileLayer(withRuntimeHidden(currentSpec as LayerSpec) as LayerSpec, compileOpts);\n }\n return compileChart(withRuntimeHidden(currentSpec) as ChartSpec | GraphSpec, compileOpts);\n }\n\n /**\n * Vertical overheads that grow an auto-height figure beyond the\n * FALLBACK_HEIGHT budget: top+bottom chrome (bottom chrome already includes\n * a bottom legend's reservation), the top legend block (height + gap), and\n * the KPI metrics bar. topPad and the axis gap are plot clearance, not\n * chrome — they stay inside the budget.\n *\n * For faceted charts, extra rows beyond what the base budget can fit\n * also contribute: each additional row needs space for the panel itself\n * plus its header and gap.\n */\n function verticalOverheads(layout: ChartLayout, width: number): number {\n // Sum EVERY top legend, not just the primary. A chart can carry a color\n // legend and a size legend; counting one and growing the container by its\n // height alone leaves the other squeezing the plot.\n let topLegendBlock = 0;\n for (const legend of layout.legends ?? [layout.legend]) {\n if (legend.position !== 'top') continue;\n const hasContent =\n legend.type === 'continuous' || legend.type === 'size'\n ? legend.bounds.height > 0\n : 'entries' in legend && legend.entries.length > 0;\n if (hasContent) topLegendBlock += legend.bounds.height + legendGap(width);\n }\n\n let facetGrowth = 0;\n if (layout.facet) {\n const needed = facetMinHeight(layout.facet.panels.length, layout.facet.columns);\n const budgetForPanels =\n FALLBACK_HEIGHT - layout.chrome.topHeight - layout.chrome.bottomHeight - topLegendBlock;\n if (needed > budgetForPanels) {\n facetGrowth = needed - budgetForPanels;\n }\n }\n\n return (\n layout.chrome.topHeight +\n layout.chrome.bottomHeight +\n topLegendBlock +\n (layout.metrics?.height ?? 0) +\n facetGrowth\n );\n }\n\n function compile(): ChartLayout {\n const { width, height } = getContainerDimensions();\n\n // Auto-height growth applies to ChartSpec mounts only. GraphSpec,\n // LayerSpec, and sparkline mounts keep the fixed-fallback behavior.\n const growsWithChrome =\n isAutoHeight === true &&\n !isLayerSpec(currentSpec) &&\n !isGraphSpec(currentSpec as unknown as Record<string, unknown>) &&\n (currentSpec as ChartSpec).display !== 'sparkline';\n if (!growsWithChrome) {\n return compileAt(width, height);\n }\n\n // Bounded convergence loop, max 3 compiles. Chrome height depends on\n // width (text wrap), not height — but the engine's chrome-strip guardrail\n // strips chrome when the residual plot is too small, which makes chrome\n // height-dependent at the budget boundary: growing the figure can\n // un-strip chrome, changing the overheads once more. (Height classes are\n // not the issue — they only strip below 200/350px, and growing from 400\n // moves away from those thresholds.) Pass 3 is accepted unconditionally.\n let layout = compileAt(width, height);\n const overheads = verticalOverheads(layout, width);\n if (overheads > 0) {\n layout = compileAt(width, height + overheads);\n const overheads2 = verticalOverheads(layout, width);\n if (overheads2 !== overheads) {\n layout = compileAt(width, height + overheads2);\n }\n }\n return layout;\n }\n\n function withRuntimeHidden<T extends { hiddenSeries?: string[]; annotations?: Annotation[] }>(\n spec: T,\n ): T {\n if (runtimeHiddenSeries.size === 0 && runtimeShownSeries.size === 0) return spec;\n const userHidden = spec.hiddenSeries ?? [];\n const finalHidden = new Set<string>(userHidden);\n for (const s of runtimeHiddenSeries) finalHidden.add(s);\n for (const s of runtimeShownSeries) finalHidden.delete(s);\n const out: T = { ...spec, hiddenSeries: Array.from(finalHidden) };\n if (finalHidden.size > 0 && spec.annotations) {\n const filtered = spec.annotations.filter((a) => a.type !== 'text');\n out.annotations = filtered.length > 0 ? filtered : undefined;\n }\n return out;\n }\n\n // ---------------------------------------------------------------------------\n // Legend toggle\n // ---------------------------------------------------------------------------\n\n function countSeries(spec: ChartSpec | GraphSpec | LayerSpec): number {\n if (isLayerSpec(spec)) return Infinity;\n const enc = (spec as ChartSpec).encoding;\n const colorEnc = enc?.color;\n if (!colorEnc || 'condition' in colorEnc) return Infinity;\n if (!('field' in colorEnc) || !colorEnc.field) return Infinity;\n if (colorEnc.type === 'quantitative') return Infinity;\n const field = colorEnc.field;\n const seen = new Set<string>();\n for (const row of (spec as ChartSpec).data ?? []) {\n seen.add(String((row as Record<string, unknown>)[field]));\n }\n return seen.size;\n }\n\n function isSeriesHidden(series: string): boolean {\n if (runtimeShownSeries.has(series)) return false;\n if (runtimeHiddenSeries.has(series)) return true;\n const userHidden = (currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? [];\n return userHidden.includes(series);\n }\n\n function toggleSeriesVisibility(series: string): boolean {\n const wasHidden = isSeriesHidden(series);\n if (!wasHidden) {\n const total = countSeries(currentSpec);\n if (Number.isFinite(total)) {\n const userHidden = new Set((currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? []);\n let visibleAfter = 0;\n const seriesField = getColorField(currentSpec);\n if (seriesField) {\n const allSeries = new Set<string>();\n for (const row of (currentSpec as ChartSpec).data ?? []) {\n allSeries.add(String((row as Record<string, unknown>)[seriesField]));\n }\n for (const s of allSeries) {\n if (s === series) continue;\n if (runtimeShownSeries.has(s)) {\n visibleAfter++;\n continue;\n }\n if (runtimeHiddenSeries.has(s)) continue;\n if (!userHidden.has(s)) visibleAfter++;\n }\n }\n if (visibleAfter === 0) return false;\n }\n }\n if (wasHidden) {\n runtimeHiddenSeries.delete(series);\n const userHidden = (currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? [];\n if (userHidden.includes(series)) runtimeShownSeries.add(series);\n } else {\n runtimeShownSeries.delete(series);\n runtimeHiddenSeries.add(series);\n }\n render();\n return !wasHidden;\n }\n\n function getColorField(spec: ChartSpec | GraphSpec | LayerSpec): string | undefined {\n if (isLayerSpec(spec)) return undefined;\n const colorEnc = (spec as ChartSpec).encoding?.color;\n if (!colorEnc || 'condition' in colorEnc) return undefined;\n if (!('field' in colorEnc) || !colorEnc.field) return undefined;\n return colorEnc.field;\n }\n\n // ---------------------------------------------------------------------------\n // Container dimensions\n // ---------------------------------------------------------------------------\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const isSparkline =\n 'display' in currentSpec && (currentSpec as ChartSpec).display === 'sparkline';\n if (isSparkline) {\n let width = rect.width;\n let height = rect.height;\n if (!height && container.parentElement) {\n const parentRect = container.parentElement.getBoundingClientRect();\n height = parentRect.height;\n if (!width) width = parentRect.width;\n }\n return {\n width: Math.max(width || 200, 30),\n height: Math.max(height || 40, 20),\n };\n }\n // Latch auto-height on the first NONZERO measurement: height 0 with a\n // real width means the host doesn't constrain height. An all-zero rect\n // (display:none / detached) stays \"unknown\" — keep re-checking until the\n // container produces a real measurement.\n if (isAutoHeight === null && (rect.width > 0 || rect.height > 0)) {\n isAutoHeight = rect.height === 0 && rect.width > 0;\n }\n\n return {\n width: Math.max(rect.width || 600, 100),\n // Latched-auto mounts always compile against the fixed budget: after\n // the first render the container's measured height is just our own\n // SVG, so reading it back would re-pin whatever we rendered last.\n height:\n isAutoHeight === true ? FALLBACK_HEIGHT : Math.max(rect.height || FALLBACK_HEIGHT, 100),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Selection & text editing\n // ---------------------------------------------------------------------------\n\n function getSpecAnnotations(): Annotation[] {\n return 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n }\n\n function selectElement(ref: ElementRef): void {\n if (!svgElement) return;\n\n const target = findElementByRef(svgElement, ref);\n if (!target) return;\n\n if (selectedElement && !refsEqual(selectedElement, ref)) {\n deselectElement();\n }\n\n selectedElement = ref;\n overlayElement = renderSelectionOverlay(svgElement, ref, currentLayout);\n options?.onSelect?.(ref);\n\n (svgElement as SVGSVGElement).focus();\n }\n\n function deselectElement(): void {\n if (!selectedElement) return;\n\n if (isTextEditingActive && textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n\n const prev = selectedElement;\n selectedElement = null;\n\n if (overlayElement?.parentNode) {\n overlayElement.parentNode.removeChild(overlayElement);\n }\n overlayElement = null;\n\n options?.onDeselect?.(prev);\n }\n\n function enterTextEditing(): void {\n if (!svgElement || !selectedElement || isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n if (!isTextEditable(selectedElement, specAnnotations)) return;\n\n const currentText = getElementText(selectedElement, currentSpec);\n if (currentText === null) return;\n\n const target = findElementByRef(svgElement, selectedElement);\n if (!target) return;\n\n const textEl = target.tagName === 'text' ? target : target.querySelector('text');\n if (!textEl) return;\n\n isTextEditingActive = true;\n const editRef = selectedElement;\n\n const overlay = createTextEditOverlay({\n container,\n svg: svgElement as SVGSVGElement,\n targetElement: textEl as SVGElement,\n currentText,\n onCommit: (newText: string) => {\n isTextEditingActive = false;\n textEditCleanup = null;\n\n if (newText !== currentText) {\n options?.onTextEdit?.(editRef, currentText, newText);\n options?.onEdit?.({\n type: 'text-edit',\n element: editRef,\n oldText: currentText,\n newText,\n });\n }\n },\n onCancel: () => {\n isTextEditingActive = false;\n textEditCleanup = null;\n },\n });\n\n textEditCleanup = overlay.destroy;\n }\n\n function wireSelectionEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n const cleanups: Array<() => void> = [];\n\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n\n if (isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref) {\n selectElement(ref);\n } else {\n deselectElement();\n }\n };\n\n svg.addEventListener('click', handleClick);\n cleanups.push(() => svg.removeEventListener('click', handleClick));\n\n const handleMouseEnter = (e: Event) => {\n const target = (e.target as Element).closest(\n '[data-annotation-index], [data-chrome-key], .oc-mark-label[data-series], .oc-legend:not(.oc-legend--size), [data-legend-index]',\n );\n if (target) {\n (target as SVGElement).classList.add('oc-editable-hover');\n }\n };\n\n const handleMouseLeave = (e: Event) => {\n const target = (e.target as Element).closest('.oc-editable-hover');\n if (target) {\n (target as SVGElement).classList.remove('oc-editable-hover');\n }\n };\n\n svg.addEventListener('mouseenter', handleMouseEnter, true);\n svg.addEventListener('mouseleave', handleMouseLeave, true);\n cleanups.push(() => {\n svg.removeEventListener('mouseenter', handleMouseEnter, true);\n svg.removeEventListener('mouseleave', handleMouseLeave, true);\n });\n\n const handleDblClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref && isTextEditable(ref, specAnnotations)) {\n if (!refsEqual(selectedElement, ref)) {\n selectElement(ref);\n }\n enterTextEditing();\n }\n };\n\n svg.addEventListener('dblclick', handleDblClick);\n cleanups.push(() => svg.removeEventListener('dblclick', handleDblClick));\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n function wireKeyboardEditEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const specAnnotations = getSpecAnnotations();\n\n switch (e.key) {\n case 'Delete':\n case 'Backspace': {\n if (selectedElement && !isTextEditingActive) {\n e.preventDefault();\n options?.onEdit?.({ type: 'delete', element: selectedElement });\n }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n if (isTextEditingActive && textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n } else if (selectedElement) {\n deselectElement();\n }\n break;\n }\n\n case 'ArrowDown':\n case 'ArrowRight': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex >= editables.length - 1 ? 0 : currentIndex + 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'ArrowUp':\n case 'ArrowLeft': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex <= 0 ? editables.length - 1 : currentIndex - 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'Enter': {\n if (selectedElement && !isTextEditingActive) {\n if (isTextEditable(selectedElement, specAnnotations)) {\n e.preventDefault();\n enterTextEditing();\n }\n }\n break;\n }\n }\n };\n\n svg.addEventListener('keydown', handleKeyDown);\n\n return () => {\n svg.removeEventListener('keydown', handleKeyDown);\n };\n }\n\n // ---------------------------------------------------------------------------\n // Render cycle\n // ---------------------------------------------------------------------------\n\n function render(): void {\n if (isDragging) {\n pendingRender = true;\n return;\n }\n\n // Cancel any in-progress data-update transition\n if (transitionHandle) {\n transitionHandle.cancel();\n transitionHandle = null;\n }\n\n // Cancel any in-progress entrance animations before tearing down\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n cancelAnimations(svgElement);\n\n // Clean up previous render\n cleanupTooltipEvents?.();\n cleanupTooltipEvents = null;\n cleanupVoronoiEvents?.();\n cleanupVoronoiEvents = null;\n cleanupKeyboardNav?.();\n cleanupKeyboardNav = null;\n cleanupLegend?.();\n cleanupLegend = null;\n cleanupChartEvents?.();\n cleanupChartEvents = null;\n cleanupAnnotationDrag?.();\n cleanupAnnotationDrag = null;\n cleanupEditDrags?.();\n cleanupEditDrags = null;\n cleanupSelection?.();\n cleanupSelection = null;\n cleanupKeyboardEdit?.();\n cleanupKeyboardEdit = null;\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n overlayElement = null;\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n\n currentLayout = compile();\n // Recorded for the ResizeObserver's self-induced-resize guard.\n lastRenderedWidth = currentLayout.dimensions.width;\n lastRenderedSvgHeight = currentLayout.dimensions.height;\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enter;\n const crosshair = !!currentLayout.crosshair;\n svgElement = renderChartSVG(currentLayout, container, {\n animate: shouldAnimate,\n crosshair,\n });\n tooltipManager = createTooltipManager(container);\n\n // Wire tooltip events on mark elements\n cleanupTooltipEvents = wireTooltipEvents(\n svgElement,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n );\n\n // Wire voronoi overlay tooltip events for line/area charts\n cleanupVoronoiEvents = wireVoronoiTooltipEvents(svgElement, currentLayout, tooltipManager);\n\n // Wire keyboard navigation. Skipped when the author hid the chart from\n // assistive technology (a11y.hidden): a hidden chart must not be a tab stop.\n if (!currentLayout.a11y.hidden) {\n cleanupKeyboardNav = wireKeyboardNav(\n svgElement,\n container,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n currentLayout,\n );\n }\n\n // seriesSearch and edit mode are mutually exclusive per instance: when\n // the spec enables seriesSearch, edit interactions are suppressed\n // (search wins -- the engine already reserved the search band).\n const editSuppressed = wantsSeriesSearch(currentSpec);\n if (\n editSuppressed &&\n !editSuppressWarned &&\n (hasEditingCallbacks(options) || options?.onAnnotationEdit)\n ) {\n editSuppressWarned = true;\n console.warn(\n '[openchart] seriesSearch and edit mode are mutually exclusive; edit interactions are disabled while seriesSearch is enabled.',\n );\n }\n\n // Wire legend interactivity\n cleanupLegend = wireLegendInteraction(\n svgElement,\n currentLayout,\n toggleSeriesVisibility,\n options?.onLegendToggle,\n editSuppressed ? undefined : options?.onEdit,\n );\n\n // Wire chart event handlers (mark click/hover/leave, annotation click)\n if (\n options?.onMarkClick ||\n options?.onMarkHover ||\n options?.onMarkLeave ||\n options?.onAnnotationClick\n ) {\n const specAnnotations: Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n cleanupChartEvents = wireChartEvents(svgElement, currentLayout, specAnnotations, options);\n }\n\n // Shared setDragging callback for all drag handlers\n const setDragging = (dragging: boolean) => {\n isDragging = dragging;\n if (!dragging && pendingRender) {\n pendingRender = false;\n render();\n }\n };\n\n const dragAnnotations: Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n\n // Wire annotation drag editing\n if (!editSuppressed && (options?.onAnnotationEdit || options?.onEdit)) {\n cleanupAnnotationDrag = wireAnnotationDrag(\n svgElement,\n dragAnnotations,\n options?.onAnnotationEdit,\n options?.onEdit,\n setDragging,\n );\n }\n\n // Wire all edit drag handlers when onEdit is provided\n if (!editSuppressed && options?.onEdit) {\n const editCleanups: Array<() => void> = [];\n\n editCleanups.push(\n wireConnectorEndpointDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n editCleanups.push(\n wireAnnotationLabelDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n\n const editSpec = currentSpec as ChartSpec | GraphSpec;\n editCleanups.push(wireChromeDrag(svgElement, editSpec, options.onEdit, setDragging));\n editCleanups.push(wireLegendDrag(svgElement, editSpec, options.onEdit, setDragging));\n editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n cleanupEditDrags = () => {\n for (const cleanup of editCleanups) {\n cleanup();\n }\n };\n }\n\n // Wire selection and keyboard edit events when editing callbacks are provided\n if (!editSuppressed && hasEditingCallbacks(options)) {\n makeEditable(svgElement);\n cleanupSelection = wireSelectionEvents();\n cleanupKeyboardEdit = wireKeyboardEditEvents();\n\n if (selectedElement) {\n const target = findElementByRef(svgElement, selectedElement);\n if (target) {\n overlayElement = renderSelectionOverlay(svgElement, selectedElement, currentLayout);\n } else {\n selectedElement = null;\n overlayElement = null;\n }\n }\n }\n\n // Create hidden data table for screen readers (not when the author hid\n // the chart from assistive technology)\n if (!currentLayout.a11y.hidden) {\n srTable = createScreenReaderTable(currentLayout, container);\n }\n\n // Mount/refresh the series search overlay on its reserved band. Created\n // once and kept across renders so typing focus and chips survive the\n // re-render each selection triggers.\n if (currentLayout.seriesSearch) {\n if (!seriesSearch) {\n seriesSearch = createSeriesSearch({ container, onChange: handleSearchChange });\n }\n seriesSearch.update(currentLayout.seriesSearch, svgElement);\n } else if (seriesSearch) {\n if (wantsSeriesSearch(currentSpec)) {\n // The layout stripped the band (e.g. hidden chrome mode at cramped\n // sizes) but the spec still wants search: keep the control and its\n // chips, just hide it until the band comes back.\n seriesSearch.hide();\n } else {\n seriesSearch.destroy();\n seriesSearch = null;\n }\n }\n\n // Mount/refresh the \"you draw it\" overlay. Created once and kept across\n // renders so the reader's in-progress guess survives each resize's\n // re-render. Mutually exclusive with edit mode: when editing callbacks are\n // present, youDrawIt is disabled (warn once) per plans 11/17's rule.\n const ydiEditConflict = wantsYouDrawIt(currentSpec) && hasEditingCallbacks(options);\n if (ydiEditConflict && !ydiEditSuppressWarned) {\n ydiEditSuppressWarned = true;\n console.warn(\n '[openchart] youDrawIt and edit mode are mutually exclusive; youDrawIt is disabled while editing callbacks are provided.',\n );\n }\n if (currentLayout.youDrawIt && !ydiEditConflict) {\n if (!youDrawIt) {\n youDrawIt = createYouDrawIt({ container, onReveal: options?.onReveal });\n }\n youDrawIt.update(currentLayout.youDrawIt, svgElement as SVGSVGElement);\n } else if (youDrawIt) {\n if (wantsYouDrawIt(currentSpec) && !ydiEditConflict) {\n // Layout stripped the config (e.g. empty data at this size) but the\n // spec still wants it: keep the controller (and its guess), just hide.\n youDrawIt.hide();\n } else {\n youDrawIt.destroy();\n youDrawIt = null;\n }\n }\n\n // Apply container classes for CSS variable scoping and dark mode\n container.classList.add('oc-root');\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Stamp resolved theme as CSS custom properties on the container\n // so CSS consumers read from the same source of truth as the JS engine.\n stampThemeProperties(container, currentLayout.theme);\n\n // Set up animation cleanup on first render only\n if (shouldAnimate && svgElement) {\n cleanupAnimations = setupAnimationCleanup(svgElement, () => {\n cleanupAnimations = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n // Bump the render generation so tests (and consumers) can observe every\n // full recompile, including the post-font-load one.\n renderGen += 1;\n container.dataset.ocRenderGen = String(renderGen);\n\n // This render recompiled with the loaded webfonts, so the layout now\n // reflects final font metrics. Publish 'ready' only now (not right after\n // the fonts-ready resize(), which may have deferred to pendingResize while\n // the entrance animation was still running).\n if (fontsReloadPending) {\n fontsReloadPending = false;\n container.dataset.ocFontsState = 'ready';\n }\n\n if (isFirstRender) {\n isFirstRender = false;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API methods\n // ---------------------------------------------------------------------------\n\n function update(newSpec: ChartSpec | GraphSpec, updateOpts?: UpdateOptions): void {\n if (destroyed) return;\n\n // Capture pre-update state for transition gating\n const prevSpec = currentSpec;\n const prevLayout = currentLayout;\n const entranceWasRunning = cleanupAnimations != null;\n\n // Snapshot in-flight transition geometry before render() cancels it.\n // This enables retargeting: the next transition starts from the\n // interrupted position instead of snapping to the previous final state.\n if (transitionHandle?.running) {\n transitionSnapshot = transitionHandle.snapshot();\n }\n\n currentSpec = newSpec;\n // A new spec can change theme.fonts.family; rebuild the measurer so layout\n // measures the font compile will actually render with.\n const nextFont = resolveEffectiveFont();\n if (nextFont !== fontFamily) {\n fontFamily = nextFont;\n measureText = createMeasureText(fontFamily);\n }\n runtimeHiddenSeries.clear();\n runtimeShownSeries.clear();\n // The new spec is the source of truth: re-capture the authored highlight\n // baseline and drop any search selections layered on the previous spec.\n searchBaseline = authoredHighlight(newSpec);\n seriesSearch?.setSelected([]);\n // A new spec re-arms the conflict warnings (youDrawIt/edit and\n // seriesSearch/edit) so a newly-introduced conflict warns once again.\n ydiEditSuppressWarned = false;\n editSuppressWarned = false;\n if (updateOpts && 'selectedElement' in updateOpts) {\n selectedElement = updateOpts.selectedElement ?? null;\n }\n render();\n\n // After render, check if we can run a smooth transition instead of the\n // instant swap that render() already performed.\n if (\n svgElement &&\n canTransition({\n prevLayout,\n nextLayout: currentLayout,\n prevSpec,\n nextSpec: newSpec,\n isFirstRender: false,\n entranceInFlight: entranceWasRunning,\n })\n ) {\n // Consume snapshot (if any) for retargeting, then clear\n const snapshot = transitionSnapshot;\n transitionSnapshot = null;\n\n transitionHandle = runTransition({\n svg: svgElement as SVGSVGElement,\n prevLayout,\n nextLayout: currentLayout,\n animation: currentLayout.animation!,\n fromSnapshot: snapshot ?? undefined,\n onComplete: () => {\n transitionHandle = null;\n },\n });\n } else {\n // No transition started; clear any stale snapshot\n transitionSnapshot = null;\n }\n }\n\n function resize(): void {\n if (destroyed) return;\n if (cleanupAnimations) {\n pendingResize = true;\n return;\n }\n render();\n }\n\n /**\n * Apply a search selection change: the effective highlight is the authored\n * baseline plus the selected values, so clearing every chip restores the\n * authored highlight exactly. Fires onHighlightChange on every change.\n */\n function handleSearchChange(selected: string[]): void {\n const merged = [...searchBaseline];\n for (const v of selected) {\n if (!merged.includes(v)) merged.push(v);\n }\n setHighlight(merged.length > 0 ? merged : null);\n options?.onHighlightChange?.(merged);\n }\n\n function setHighlight(values: string[] | null): void {\n if (destroyed) return;\n if (isLayerSpec(currentSpec) || isGraphSpec(currentSpec as unknown as Record<string, unknown>))\n return;\n const spec = currentSpec as ChartSpec;\n const colorEnc = spec.encoding?.color;\n if (!colorEnc || typeof colorEnc !== 'object' || !('field' in colorEnc)) return;\n const current = (colorEnc as { highlight?: string | string[] }).highlight;\n if (!values?.length && !current) return;\n const updatedColor = { ...colorEnc };\n if (values && values.length > 0) {\n updatedColor.highlight = values;\n } else {\n delete updatedColor.highlight;\n }\n currentSpec = {\n ...spec,\n encoding: { ...spec.encoding, color: updatedColor },\n } as ChartSpec;\n render();\n }\n\n function doExport(format: 'svg'): string;\n function doExport(format: 'svg-with-fonts', exportOptions?: SVGExportOptions): Promise<string>;\n function doExport(format: 'png', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'jpg', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'csv'): string;\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n exportOptions?: ExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Chart is not rendered yet');\n }\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement, exportOptions);\n case 'png':\n return exportPNG(svgElement, exportOptions);\n case 'jpg':\n return exportJPG(svgElement, exportOptions);\n case 'csv':\n return exportCSV(\n 'data' in currentSpec && Array.isArray(currentSpec.data) ? currentSpec.data : [],\n );\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel any in-progress data-update transition\n if (transitionHandle) {\n transitionHandle.cancel();\n transitionHandle = null;\n }\n transitionSnapshot = null;\n\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n pendingResize = false;\n }\n cancelAnimations(svgElement);\n\n cleanupTooltipEvents?.();\n cleanupTooltipEvents = null;\n cleanupVoronoiEvents?.();\n cleanupVoronoiEvents = null;\n cleanupKeyboardNav?.();\n cleanupKeyboardNav = null;\n cleanupLegend?.();\n cleanupLegend = null;\n cleanupChartEvents?.();\n cleanupChartEvents = null;\n cleanupAnnotationDrag?.();\n cleanupAnnotationDrag = null;\n cleanupEditDrags?.();\n cleanupEditDrags = null;\n cleanupSelection?.();\n cleanupSelection = null;\n cleanupKeyboardEdit?.();\n cleanupKeyboardEdit = null;\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n selectedElement = null;\n overlayElement = null;\n if (seriesSearch) {\n seriesSearch.destroy();\n seriesSearch = null;\n }\n if (youDrawIt) {\n youDrawIt.destroy();\n youDrawIt = null;\n }\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n svgElement = null;\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n container.classList.remove('oc-dark');\n container.classList.remove('oc-root');\n }\n\n // Initial render\n render();\n\n // Recompile once after webfonts load. On real devices the primary font\n // (e.g. Inter via display=swap) often swaps in after first paint, changing\n // text metrics; without a re-measure, titles wrap wrong and labels collide.\n // Desktop Chrome has the font cached, so it renders 'ready' immediately.\n const pending = scheduleFontReload(\n fontFamily,\n () => !destroyed,\n () => {\n // Mark the reload owed, then trigger a recompile. render() flips the\n // attribute to 'ready' once it actually recompiles — including the\n // pendingResize replay after the entrance animation finishes.\n fontsReloadPending = true;\n resize();\n },\n );\n container.dataset.ocFontsState = pending ? 'pending' : 'ready';\n\n // Set up responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, (width, height) => {\n // Self-induced-resize guard, scoped to latched-auto mounts: growing\n // the SVG grows the container, which re-fires this observer. A fire\n // whose height matches the SVG we just rendered (and whose width is\n // unchanged) is our own echo — re-rendering on it would loop; the\n // 16ms debounce alone doesn't break the cycle.\n if (isAutoHeight === true) {\n const widthChanged = width !== lastRenderedWidth;\n const selfInducedHeight = height === lastRenderedSvgHeight;\n if (!widthChanged && selfInducedHeight) return;\n if (!selfInducedHeight) {\n // Any other height delta is host-driven: un-latch so the next\n // measure re-derives (and re-latches explicit if the container\n // now reports a height that isn't ours).\n isAutoHeight = null;\n }\n resize();\n return;\n }\n // Explicit-height (and not-yet-latched) mounts keep today's\n // re-render-on-every-fire behavior.\n resize();\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n destroy,\n get layout() {\n return currentLayout;\n },\n getSelectedElement(): ElementRef | null {\n return selectedElement;\n },\n select(ref: ElementRef): void {\n if (destroyed) return;\n selectElement(ref);\n },\n deselect(): void {\n if (destroyed) return;\n deselectElement();\n },\n get isEditing(): boolean {\n return isTextEditingActive;\n },\n setHighlight,\n resetDrawing(): void {\n if (destroyed) return;\n youDrawIt?.reset();\n },\n revealDrawing(): void {\n if (destroyed) return;\n youDrawIt?.reveal();\n },\n };\n}\n","import type { Annotation, ChartEventHandlers, ChartLayout } from '@opendata-ai/openchart-core';\n\n/**\n * Build a map from data-mark-id to { datum, series } so event handlers\n * can look up the data row associated with a clicked/hovered mark element.\n */\nfunction buildMarkDataMap(\n layout: ChartLayout,\n): Map<string, { datum: Record<string, unknown>; series?: string }> {\n const map = new Map<string, { datum: Record<string, unknown>; series?: string }>();\n\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n switch (mark.type) {\n case 'line':\n map.set(`line-${mark.seriesKey ?? i}`, {\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'area':\n map.set(`area-${mark.seriesKey ?? i}`, {\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'rect':\n map.set(`rect-${i}`, { datum: mark.data });\n break;\n case 'arc':\n map.set(`arc-${i}`, { datum: mark.data });\n break;\n case 'point':\n map.set(`point-${i}`, { datum: mark.data });\n break;\n }\n }\n\n return map;\n}\n\n/**\n * Wire chart event handlers (onMarkClick, onMarkHover, onMarkLeave) to mark\n * elements, onLegendToggle to legend entries, and onAnnotationClick to annotation\n * elements inside an SVG.\n *\n * Returns a cleanup function to remove all listeners.\n */\nexport function wireChartEvents(\n svg: SVGElement,\n layout: ChartLayout,\n specAnnotations: Annotation[],\n handlers: ChartEventHandlers,\n): () => void {\n const cleanups: Array<() => void> = [];\n const markDataMap = buildMarkDataMap(layout);\n\n if (handlers.onMarkClick || handlers.onMarkHover || handlers.onMarkLeave) {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const markInfo = markDataMap.get(markId);\n if (!markInfo) continue;\n\n const series = markInfo.series ?? el.getAttribute('data-series') ?? undefined;\n\n if (handlers.onMarkClick) {\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkClick!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n\n if (handlers.onMarkHover) {\n const handleEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkHover!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('mouseenter', handleEnter);\n cleanups.push(() => el.removeEventListener('mouseenter', handleEnter));\n }\n\n if (handlers.onMarkLeave) {\n const handleLeave = () => {\n handlers.onMarkLeave!();\n };\n el.addEventListener('mouseleave', handleLeave);\n cleanups.push(() => el.removeEventListener('mouseleave', handleLeave));\n }\n }\n }\n\n if (handlers.onAnnotationClick) {\n const annotationElements = svg.querySelectorAll('.oc-annotation');\n\n for (let i = 0; i < annotationElements.length; i++) {\n const el = annotationElements[i];\n const specAnnotation = specAnnotations[i];\n if (!specAnnotation) continue;\n\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n handlers.onAnnotationClick!(specAnnotation, mouseEvent);\n };\n\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n","import type { ChartLayout, TooltipContent } from '@opendata-ai/openchart-core';\nimport { getRepresentativeColor } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\n\ninterface SeriesPoint {\n x: number;\n y: number;\n datum: Record<string, unknown>;\n tooltip?: TooltipContent;\n}\n\ninterface SeriesGroup {\n seriesKey: string;\n color: string;\n pointsByX: Map<number, SeriesPoint>;\n}\n\nfunction snapKey(x: number): number {\n return Math.round(x);\n}\n\nfunction collectSeriesGroups(layout: ChartLayout): SeriesGroup[] {\n // Dedupe by seriesKey: area charts emit BOTH an AreaMark and a derived\n // LineMark per series. Without dedupe, single-series area charts show\n // \"line-0\" / \"area-1\" in the tooltip instead of the actual data fields.\n // Prefer the line mark (same logic as endpoint-labels).\n const byKey = new Map<string, SeriesGroup>();\n const markTypeByKey = new Map<string, 'line' | 'area'>();\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n if ((mark.type === 'line' || mark.type === 'area') && mark.dataPoints?.length) {\n const key = mark.seriesKey ?? '__default__';\n const existingType = markTypeByKey.get(key);\n if (existingType === 'line' && mark.type === 'area') continue;\n const color = mark.type === 'line' ? mark.stroke : getRepresentativeColor(mark.fill);\n const pointsByX = new Map<number, SeriesPoint>();\n for (const dp of mark.dataPoints) {\n pointsByX.set(snapKey(dp.x), { ...dp });\n }\n byKey.set(key, { seriesKey: key, color, pointsByX });\n markTypeByKey.set(key, mark.type);\n }\n }\n return Array.from(byKey.values());\n}\n\nfunction collectSnapXs(groups: SeriesGroup[]): number[] {\n const seen = new Set<number>();\n for (const g of groups) {\n for (const k of g.pointsByX.keys()) seen.add(k);\n }\n return Array.from(seen).sort((a, b) => a - b);\n}\n\nfunction findNearestX(sortedXs: number[], x: number): number | null {\n if (sortedXs.length === 0) return null;\n let lo = 0;\n let hi = sortedXs.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (sortedXs[mid] < x) lo = mid + 1;\n else hi = mid;\n }\n const candidate = sortedXs[lo];\n if (lo > 0) {\n const prev = sortedXs[lo - 1];\n if (Math.abs(prev - x) < Math.abs(candidate - x)) return prev;\n }\n return candidate;\n}\n\nfunction buildSliceTooltip(\n hits: Array<{ group: SeriesGroup; point: SeriesPoint }>,\n): TooltipContent | null {\n if (hits.length === 0) return null;\n\n const title = hits[0].point.tooltip?.title;\n const fields: Array<{ label: string; value: string; color?: string }> = [];\n\n const isMulti = hits.length > 1;\n for (const { group, point } of hits) {\n const tip = point.tooltip;\n if (!tip) continue;\n if (isMulti) {\n const yField =\n tip.fields.find((f) => !f.color && f.label !== title) ??\n tip.fields[tip.fields.length - 1] ??\n null;\n if (!yField) continue;\n fields.push({\n label: group.seriesKey,\n value: yField.value,\n color: group.color,\n });\n } else {\n for (const f of tip.fields) {\n fields.push({ ...f, color: f.color ?? group.color });\n }\n }\n }\n\n if (fields.length === 0) return null;\n return { title, fields };\n}\n\n/**\n * Wire snap-to-x multi-series tooltip events for line/area charts.\n * On mousemove over the chart area we find the nearest x in the union of all\n * series, render one snap dot per series at that x, and show one merged\n * tooltip listing every series' value.\n */\nexport function wireVoronoiTooltipEvents(\n svg: SVGElement,\n layout: ChartLayout,\n tooltipManager: TooltipManager,\n): () => void {\n const overlay = svg.querySelector('[data-voronoi-overlay]');\n if (!overlay) return () => {};\n\n const groups = collectSeriesGroups(layout);\n if (groups.length === 0) return () => {};\n\n const snapXs = collectSnapXs(groups);\n if (snapXs.length === 0) return () => {};\n\n const crosshair = svg.querySelector('[data-crosshair]') as SVGLineElement | null;\n const dotsLayer = svg.querySelector('[data-snap-dots]') as SVGGElement | null;\n\n const dots: SVGCircleElement[] = [];\n if (dotsLayer) {\n while (dotsLayer.firstChild) dotsLayer.removeChild(dotsLayer.firstChild);\n for (const group of groups) {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n circle.setAttribute('r', '4');\n circle.setAttribute('fill', layout.theme.colors.background);\n circle.setAttribute('stroke', group.color);\n circle.setAttribute('stroke-width', '2');\n circle.setAttribute('pointer-events', 'none');\n circle.style.display = 'none';\n dotsLayer.appendChild(circle);\n dots.push(circle);\n }\n }\n\n const positionAt = (svgX: number, _svgY: number, viewBoxToContainer: number): boolean => {\n const snappedX = findNearestX(snapXs, svgX);\n if (snappedX === null) return false;\n\n const hits: Array<{ group: SeriesGroup; point: SeriesPoint }> = [];\n let anchorY = 0;\n let anchorCount = 0;\n for (let i = 0; i < groups.length; i++) {\n const group = groups[i];\n const point = group.pointsByX.get(snappedX);\n const dot = dots[i];\n if (point) {\n hits.push({ group, point });\n anchorY += point.y;\n anchorCount += 1;\n if (dot) {\n dot.setAttribute('cx', String(point.x));\n dot.setAttribute('cy', String(point.y));\n dot.style.display = '';\n }\n } else if (dot) {\n dot.style.display = 'none';\n }\n }\n\n if (crosshair) {\n crosshair.setAttribute('x1', String(snappedX));\n crosshair.setAttribute('x2', String(snappedX));\n crosshair.style.display = '';\n }\n\n const tooltip = buildSliceTooltip(hits);\n if (!tooltip) return false;\n\n const containerAnchorX = snappedX * viewBoxToContainer;\n const containerAnchorY = anchorCount > 0 ? (anchorY / anchorCount) * viewBoxToContainer : 0;\n tooltipManager.show(tooltip, containerAnchorX, containerAnchorY, {\n placement: 'right',\n });\n return true;\n };\n\n const toSvgCoords = (clientX: number, clientY: number) => {\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n const svgX = (clientX - svgRect.left) * scaleX;\n const svgY = (clientY - svgRect.top) * scaleY;\n const viewBoxToContainer = scaleX > 0 ? 1 / scaleX : 1;\n return { svgX, svgY, viewBoxToContainer };\n };\n\n const handleMouseMove = (e: Event) => {\n const me = e as MouseEvent;\n const { svgX, svgY, viewBoxToContainer } = toSvgCoords(me.clientX, me.clientY);\n positionAt(svgX, svgY, viewBoxToContainer);\n };\n\n const hideAll = () => {\n if (crosshair) crosshair.style.display = 'none';\n for (const dot of dots) dot.style.display = 'none';\n tooltipManager.hide();\n };\n\n const handleTouch = (e: Event) => {\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n const t = te.touches[0];\n const { svgX, svgY, viewBoxToContainer } = toSvgCoords(t.clientX, t.clientY);\n if (te.cancelable) te.preventDefault();\n positionAt(svgX, svgY, viewBoxToContainer);\n };\n\n overlay.addEventListener('mousemove', handleMouseMove);\n overlay.addEventListener('mouseleave', hideAll);\n overlay.addEventListener('touchstart', handleTouch, { passive: false });\n overlay.addEventListener('touchmove', handleTouch, { passive: false });\n overlay.addEventListener('touchend', hideAll);\n\n return () => {\n overlay.removeEventListener('mousemove', handleMouseMove);\n overlay.removeEventListener('mouseleave', hideAll);\n overlay.removeEventListener('touchstart', handleTouch);\n overlay.removeEventListener('touchmove', handleTouch);\n overlay.removeEventListener('touchend', hideAll);\n };\n}\n","/**\n * Reusable drag handler for SVG elements.\n * Handles mouse and touch events, viewBox scaling, threshold detection,\n * click suppression after drag, and cursor state.\n */\n\nexport interface DragConfig {\n element: SVGElement;\n svg: SVGSVGElement;\n onMove: (dx: number, dy: number) => void;\n onEnd: (dx: number, dy: number, moved: boolean) => void;\n setDragging: (dragging: boolean) => void;\n threshold?: number;\n}\n\nexport function createDragHandler(config: DragConfig): () => void {\n const { element, svg, onMove, onEnd, setDragging, threshold = 3 } = config;\n const cleanups: Array<() => void> = [];\n\n let activeDocMouseMove: ((e: MouseEvent) => void) | null = null;\n let activeDocMouseUp: ((e: MouseEvent) => void) | null = null;\n let activeDocTouchMove: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchEnd: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchCancel: ((e: TouchEvent) => void) | null = null;\n\n function getScale(): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1,\n scaleY: viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1,\n };\n }\n\n function startDrag(startX: number, startY: number): void {\n setDragging(true);\n const { scaleX, scaleY } = getScale();\n\n element.style.cursor = 'grabbing';\n svg.style.userSelect = 'none';\n\n const handleMove = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n onMove(dx, dy);\n };\n\n const cleanupDocListeners = () => {\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n };\n\n const handleEnd = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n const moved = Math.abs(dx) > threshold || Math.abs(dy) > threshold;\n\n onEnd(dx, dy, moved);\n\n if (moved) {\n element.addEventListener(\n 'click',\n (clickE) => {\n clickE.stopPropagation();\n },\n { capture: true, once: true },\n );\n }\n\n element.style.cursor = 'grab';\n svg.style.userSelect = '';\n\n cleanupDocListeners();\n setDragging(false);\n };\n\n const onMouseMove = (moveEvent: MouseEvent) => {\n handleMove(moveEvent.clientX, moveEvent.clientY);\n };\n const onMouseUp = (upEvent: MouseEvent) => {\n handleEnd(upEvent.clientX, upEvent.clientY);\n };\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n activeDocMouseMove = onMouseMove;\n activeDocMouseUp = onMouseUp;\n\n const onTouchMove = (moveEvent: TouchEvent) => {\n if (moveEvent.touches.length > 0) {\n moveEvent.preventDefault();\n handleMove(moveEvent.touches[0].clientX, moveEvent.touches[0].clientY);\n }\n };\n const onTouchEnd = (endEvent: TouchEvent) => {\n const touch = endEvent.changedTouches[0];\n if (touch) {\n handleEnd(touch.clientX, touch.clientY);\n } else {\n handleEnd(startX, startY);\n }\n };\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', onTouchEnd);\n document.addEventListener('touchcancel', onTouchEnd);\n activeDocTouchMove = onTouchMove;\n activeDocTouchEnd = onTouchEnd;\n activeDocTouchCancel = onTouchEnd;\n }\n\n const handleMouseDown = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n mouseEvent.preventDefault();\n startDrag(mouseEvent.clientX, mouseEvent.clientY);\n };\n\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length === 1) {\n touchEvent.preventDefault();\n startDrag(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n }\n };\n\n element.addEventListener('mousedown', handleMouseDown);\n element.addEventListener('touchstart', handleTouchStart, { passive: false });\n cleanups.push(() => {\n element.removeEventListener('mousedown', handleMouseDown);\n element.removeEventListener('touchstart', handleTouchStart);\n });\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n svg.style.userSelect = '';\n };\n}\n","import type {\n Annotation,\n AnnotationOffset,\n ChartSpec,\n ChromeKey,\n ElementEdit,\n GraphSpec,\n RangeAnnotation,\n RefLineAnnotation,\n TextAnnotation,\n} from '@opendata-ai/openchart-core';\nimport { createDragHandler } from './drag-handler';\n\n/**\n * Wire drag-to-reposition on text annotation labels.\n * Returns a cleanup function to remove all listeners.\n */\nexport function wireAnnotationDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onAnnotationEdit:\n | ((annotation: TextAnnotation, updatedOffset: AnnotationOffset) => void)\n | undefined,\n onEdit: ((edit: ElementEdit) => void) | undefined,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const annotationElements = svg.querySelectorAll('.oc-annotation-text');\n const cleanups: Array<() => void> = [];\n\n for (const el of annotationElements) {\n const indexStr = el.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n const annotationG = el as SVGGElement;\n\n annotationG.style.cursor = 'grab';\n\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const origX2 = connectorLine ? Number(connectorLine.getAttribute('x2')) : 0;\n const origY2 = connectorLine ? Number(connectorLine.getAttribute('y2')) : 0;\n\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n const arrowhead = annotationG.querySelector('polyline.oc-annotation-arrowhead');\n const hasCurvedConnector = curvedPath !== null;\n\n const origDx = textAnnotation.offset?.dx ?? 0;\n const origDy = textAnnotation.offset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: annotationG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n annotationG.setAttribute('transform', `translate(${dx}, ${dy})`);\n\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2 - dx));\n connectorLine.setAttribute('y2', String(origY2 - dy));\n }\n\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.setAttribute('display', 'none');\n if (arrowhead) arrowhead.setAttribute('display', 'none');\n }\n },\n onEnd: (dx, dy, moved) => {\n annotationG.removeAttribute('transform');\n\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2));\n connectorLine.setAttribute('y2', String(origY2));\n }\n\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.removeAttribute('display');\n if (arrowhead) arrowhead.removeAttribute('display');\n }\n\n if (moved) {\n const newOffset: AnnotationOffset = {\n dx: origDx + dx,\n dy: origDy + dy,\n };\n onAnnotationEdit?.(textAnnotation, newOffset);\n onEdit?.({ type: 'annotation', annotation: textAnnotation, offset: newOffset });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n/**\n * Wire drag on connector endpoint handles for text annotations.\n * Returns a cleanup function that removes handles and all listeners.\n */\nexport function wireConnectorEndpointDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const SVG_NS = 'http://www.w3.org/2000/svg';\n const cleanups: Array<() => void> = [];\n const annotationGroups = svg.querySelectorAll('.oc-annotation-text');\n\n for (const el of annotationGroups) {\n const annotationG = el as SVGGElement;\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n if (!connectorLine && !curvedPath) continue;\n\n let fromX: number, fromY: number, toX: number, toY: number;\n if (connectorLine) {\n fromX = Number(connectorLine.getAttribute('x1')) || 0;\n fromY = Number(connectorLine.getAttribute('y1')) || 0;\n toX = Number(connectorLine.getAttribute('x2')) || 0;\n toY = Number(connectorLine.getAttribute('y2')) || 0;\n } else {\n const pathD = curvedPath!.getAttribute('d') ?? '';\n const mMatch = pathD.match(/M\\s*([\\d.e+-]+)\\s+([\\d.e+-]+)/);\n fromX = mMatch ? Number(mMatch[1]) : 0;\n fromY = mMatch ? Number(mMatch[2]) : 0;\n // The open-V arrowhead is a polyline \"baseLeft tip baseRight\": the tip is\n // the middle point.\n const arrowhead = annotationG.querySelector('polyline.oc-annotation-arrowhead');\n const points = arrowhead?.getAttribute('points')?.split(' ') ?? [];\n const [px, py] = (points[1] ?? '0,0').split(',');\n toX = Number(px) || 0;\n toY = Number(py) || 0;\n }\n\n const endpoints: Array<{ name: 'from' | 'to'; cx: number; cy: number }> = [\n { name: 'from', cx: fromX, cy: fromY },\n { name: 'to', cx: toX, cy: toY },\n ];\n\n const createdHandles: SVGCircleElement[] = [];\n\n for (const ep of endpoints) {\n if (!Number.isFinite(ep.cx) || !Number.isFinite(ep.cy)) continue;\n\n const handleEl = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n handleEl.setAttribute('class', 'oc-connector-handle');\n handleEl.setAttribute('data-endpoint', ep.name);\n handleEl.setAttribute('cx', String(ep.cx));\n handleEl.setAttribute('cy', String(ep.cy));\n handleEl.setAttribute('r', '4');\n handleEl.setAttribute('opacity', '0');\n handleEl.setAttribute('fill', 'currentColor');\n handleEl.setAttribute('stroke', 'currentColor');\n annotationG.appendChild(handleEl);\n createdHandles.push(handleEl);\n\n const origCx = ep.cx;\n const origCy = ep.cy;\n\n const stopProp = (e: Event) => {\n e.stopPropagation();\n };\n handleEl.addEventListener('mousedown', stopProp);\n handleEl.addEventListener('touchstart', stopProp);\n cleanups.push(() => {\n handleEl.removeEventListener('mousedown', stopProp);\n handleEl.removeEventListener('touchstart', stopProp);\n });\n\n const cleanup = createDragHandler({\n element: handleEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n handleEl.setAttribute('cx', String(origCx + dx));\n handleEl.setAttribute('cy', String(origCy + dy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx + dx));\n connectorLine.setAttribute('y1', String(origCy + dy));\n } else {\n connectorLine.setAttribute('x2', String(origCx + dx));\n connectorLine.setAttribute('y2', String(origCy + dy));\n }\n }\n },\n onEnd: (dx, dy, moved) => {\n handleEl.setAttribute('cx', String(origCx));\n handleEl.setAttribute('cy', String(origCy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx));\n connectorLine.setAttribute('y1', String(origCy));\n } else {\n connectorLine.setAttribute('x2', String(origCx));\n connectorLine.setAttribute('y2', String(origCy));\n }\n }\n\n if (moved) {\n const existingOffset = textAnnotation.connectorOffset?.[ep.name];\n const origEndDx = existingOffset?.dx ?? 0;\n const origEndDy = existingOffset?.dy ?? 0;\n onEdit({\n type: 'annotation-connector',\n annotation: textAnnotation,\n endpoint: ep.name,\n offset: { dx: origEndDx + dx, dy: origEndDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n const showHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0.6');\n }\n };\n const hideHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0');\n }\n };\n\n annotationG.addEventListener('mouseenter', showHandles);\n annotationG.addEventListener('mouseleave', hideHandles);\n cleanups.push(() => {\n annotationG.removeEventListener('mouseenter', showHandles);\n annotationG.removeEventListener('mouseleave', hideHandles);\n for (const h of createdHandles) {\n h.remove();\n }\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n/**\n * Wire drag on range and refline annotation labels.\n * Returns a cleanup function.\n */\nexport function wireAnnotationLabelDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const cleanups: Array<() => void> = [];\n\n const selectors = [\n '.oc-annotation-range .oc-annotation-label',\n '.oc-annotation-refline .oc-annotation-label',\n ];\n\n for (const selector of selectors) {\n const labels = svg.querySelectorAll(selector);\n\n for (const label of labels) {\n const annotationG = label.closest('.oc-annotation') as SVGGElement | null;\n if (!annotationG) continue;\n\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation) continue;\n\n const labelEl = label as SVGTextElement;\n labelEl.style.cursor = 'grab';\n\n const isRange = specAnnotation.type === 'range';\n const existingLabelOffset = isRange\n ? (specAnnotation as RangeAnnotation).labelOffset\n : (specAnnotation as RefLineAnnotation).labelOffset;\n const origLabelDx = existingLabelOffset?.dx ?? 0;\n const origLabelDy = existingLabelOffset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n if (isRange) {\n onEdit({\n type: 'range-label',\n annotation: specAnnotation as RangeAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n } else {\n onEdit({\n type: 'refline-label',\n annotation: specAnnotation as RefLineAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n }\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n/**\n * Wire drag on chrome text elements (title, subtitle, source, byline, footer).\n * Returns a cleanup function.\n */\nexport function wireChromeDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const chromeTexts = svg.querySelectorAll('.oc-chrome text[data-chrome-key]');\n const cleanups: Array<() => void> = [];\n\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n\n for (const el of chromeTexts) {\n const textEl = el as SVGTextElement;\n const key = textEl.getAttribute('data-chrome-key') as ChromeKey;\n if (!key) continue;\n\n const chromeEntry = chromeConfig?.[key];\n const existingOffset =\n typeof chromeEntry === 'object' && chromeEntry !== null ? chromeEntry.offset : undefined;\n const origChromeDx = existingOffset?.dx ?? 0;\n const origChromeDy = existingOffset?.dy ?? 0;\n\n textEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: textEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'chrome',\n key,\n text: textEl.textContent ?? '',\n offset: { dx: origChromeDx + dx, dy: origChromeDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n/**\n * Wire drag on the legend group.\n * Returns a cleanup function.\n */\nexport function wireLegendDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n // The color legend: it owns `spec.legend.offset`, which is what a drag writes\n // back. The size legend is not draggable and must not be picked up here.\n const legendG = svg.querySelector('.oc-legend:not(.oc-legend--size)') as SVGGElement | null;\n if (!legendG) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n const legendConfig = 'legend' in spec ? spec.legend : undefined;\n const origLegendDx = legendConfig?.offset?.dx ?? 0;\n const origLegendDy = legendConfig?.offset?.dy ?? 0;\n\n legendG.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: legendG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({ type: 'legend', offset: { dx: origLegendDx + dx, dy: origLegendDy + dy } });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n/**\n * Wire drag on series label elements (.oc-mark-label[data-series]).\n * Returns a cleanup function.\n */\nexport function wireSeriesLabelDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const labels = svg.querySelectorAll('.oc-mark-label');\n const cleanups: Array<() => void> = [];\n\n const rawLabels = 'labels' in spec ? spec.labels : undefined;\n const labelsConfig = typeof rawLabels === 'object' ? rawLabels : undefined;\n\n for (const label of labels) {\n const labelEl = label as SVGTextElement;\n const series =\n labelEl.getAttribute('data-series') ??\n labelEl.closest('[data-series]')?.getAttribute('data-series');\n if (!series) continue;\n\n const existingSeriesOffset = labelsConfig?.offsets?.[series];\n const origSeriesDx = existingSeriesOffset?.dx ?? 0;\n const origSeriesDy = existingSeriesOffset?.dy ?? 0;\n\n labelEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'series-label',\n series,\n offset: { dx: origSeriesDx + dx, dy: origSeriesDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n","import type { ChartLayout, TooltipContent } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\n\n/**\n * Wire keyboard navigation on the SVG element.\n * Arrow keys move focus between mark elements. Enter/Space shows tooltip.\n * Escape hides tooltip. Returns a cleanup function.\n */\nexport function wireKeyboardNav(\n svg: SVGElement,\n container: HTMLElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n layout: ChartLayout,\n): () => void {\n container.setAttribute('tabindex', '0');\n container.setAttribute('aria-roledescription', 'chart');\n container.setAttribute('aria-label', layout.a11y.altText);\n\n const markElements: SVGElement[] = [];\n const allMarkEls = svg.querySelectorAll('[data-mark-id]');\n for (const el of allMarkEls) {\n const markId = el.getAttribute('data-mark-id');\n if (markId && tooltipDescriptors.has(markId)) {\n markElements.push(el as SVGElement);\n }\n }\n\n let focusIndex = -1;\n\n function highlightMark(index: number): void {\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n markElements[focusIndex].classList.remove('oc-mark-focused');\n markElements[focusIndex].removeAttribute('aria-selected');\n }\n\n focusIndex = index;\n\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n const el = markElements[focusIndex];\n el.classList.add('oc-mark-focused');\n el.setAttribute('aria-selected', 'true');\n }\n }\n\n function showTooltipForFocused(): void {\n if (focusIndex < 0 || focusIndex >= markElements.length) return;\n\n const el = markElements[focusIndex];\n const markId = el.getAttribute('data-mark-id');\n if (!markId) return;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) return;\n\n const bbox = el.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const x = bbox.left + bbox.width / 2 - containerRect.left;\n const y = bbox.top - containerRect.top;\n tooltipManager.show(content, x, y);\n }\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (markElements.length === 0) return;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowDown': {\n e.preventDefault();\n const next = focusIndex < markElements.length - 1 ? focusIndex + 1 : 0;\n highlightMark(next);\n showTooltipForFocused();\n break;\n }\n case 'ArrowLeft':\n case 'ArrowUp': {\n e.preventDefault();\n const prev = focusIndex > 0 ? focusIndex - 1 : markElements.length - 1;\n highlightMark(prev);\n showTooltipForFocused();\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (focusIndex >= 0) {\n showTooltipForFocused();\n } else if (markElements.length > 0) {\n highlightMark(0);\n showTooltipForFocused();\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n tooltipManager.hide();\n highlightMark(-1);\n break;\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n container.removeAttribute('tabindex');\n container.removeAttribute('aria-roledescription');\n container.removeAttribute('aria-label');\n };\n}\n","import type { ChartLayout, ElementEdit } from '@opendata-ai/openchart-core';\n\n/**\n * Wire click handlers on legend entries to toggle series visibility.\n * Returns a cleanup function.\n */\nexport function wireLegendInteraction(\n svg: SVGElement,\n _layout: ChartLayout,\n toggleSeries: (series: string) => boolean,\n onLegendToggle?: (series: string, visible: boolean) => void,\n onEdit?: (edit: ElementEdit) => void,\n): () => void {\n // Scoped OUT of the size legend explicitly. Clicking a legend entry toggles a\n // *series*, and a size legend's circles are values, not series -- clicking\n // \"500M\" must not try to hide a series by that name. The size legend already\n // emits no `data-legend-index`, but a bare `[data-legend-index]` sweep would\n // silently pick one up the moment that changed, and the failure would be a\n // click that quietly hides the wrong thing rather than an error.\n const legendEntries = svg.querySelectorAll(\n '.oc-legend:not(.oc-legend--size) [data-legend-index]',\n );\n const cleanups: Array<() => void> = [];\n\n for (const entry of legendEntries) {\n if (entry.getAttribute('data-legend-overflow') === 'true') continue;\n\n const handleClick = () => {\n const label = entry.getAttribute('data-legend-label');\n if (!label) return;\n\n const nowHidden = toggleSeries(label);\n onLegendToggle?.(label, !nowHidden);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: nowHidden });\n };\n\n entry.addEventListener('click', handleClick);\n cleanups.push(() => entry.removeEventListener('click', handleClick));\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n","import type {\n Annotation,\n ChartLayout,\n ChartSpec,\n ChromeKey,\n ElementRef,\n GraphSpec,\n LayerSpec,\n TextAnnotation,\n} from '@opendata-ai/openchart-core';\nimport { elementRef } from '@opendata-ai/openchart-core';\n\n/**\n * Find a DOM element inside the SVG that matches the given ElementRef.\n */\nexport function findElementByRef(svg: SVGElement, ref: ElementRef): SVGElement | null {\n switch (ref.type) {\n case 'annotation': {\n if (ref.id) {\n const byId = svg.querySelector(`[data-annotation-id=\"${ref.id}\"]`);\n if (byId) return byId as SVGElement;\n }\n return svg.querySelector(`[data-annotation-index=\"${ref.index}\"]`) as SVGElement | null;\n }\n case 'chrome':\n return svg.querySelector(`[data-chrome-key=\"${ref.key}\"]`) as SVGElement | null;\n case 'series-label':\n return svg.querySelector(`.oc-mark-label[data-series=\"${ref.series}\"]`) as SVGElement | null;\n // The editable legend is the color legend. Excluding the size legend\n // explicitly rather than relying on it rendering second: `querySelector`\n // takes the first match, so a bare `.oc-legend` would silently retarget\n // (and drag) the wrong legend if render order ever changed.\n case 'legend':\n return svg.querySelector('.oc-legend:not(.oc-legend--size)') as SVGElement | null;\n case 'legend-entry':\n return svg.querySelector(\n `.oc-legend:not(.oc-legend--size) [data-legend-index=\"${ref.index}\"]`,\n ) as SVGElement | null;\n }\n}\n\n/**\n * Build an ElementRef from a DOM element's data attributes.\n */\nexport function buildElementRef(\n element: Element,\n _specAnnotations: Annotation[],\n): ElementRef | null {\n const annotationEl = element.closest('[data-annotation-index]');\n if (annotationEl) {\n const index = Number(annotationEl.getAttribute('data-annotation-index'));\n const id = annotationEl.getAttribute('data-annotation-id') ?? undefined;\n return elementRef.annotation(index, id);\n }\n\n const chromeEl = element.closest('[data-chrome-key]');\n if (chromeEl) {\n const key = chromeEl.getAttribute('data-chrome-key') as ChromeKey;\n if (key) return elementRef.chrome(key);\n }\n\n const seriesLabelEl = element.closest('.oc-mark-label[data-series]');\n if (seriesLabelEl) {\n const series = seriesLabelEl.getAttribute('data-series');\n if (series) return elementRef.seriesLabel(series);\n }\n\n const legendEntryEl = element.closest('[data-legend-index]');\n if (legendEntryEl) {\n const index = Number(legendEntryEl.getAttribute('data-legend-index'));\n const series = legendEntryEl.getAttribute('data-legend-label') ?? '';\n return elementRef.legendEntry(series, index);\n }\n\n // Only the color legend is selectable/editable. A click inside the size legend\n // resolves to no ref rather than reporting the *color* legend's ref, which is\n // what a bare `.oc-legend` match would do.\n const legendEl = element.closest('.oc-legend');\n if (legendEl && !legendEl.classList.contains('oc-legend--size')) return elementRef.legend();\n\n return null;\n}\n\n/**\n * Get an ordered list of all editable ElementRefs from the current spec and layout.\n */\nexport function getEditableElements(\n spec: ChartSpec | LayerSpec | GraphSpec,\n layout: ChartLayout,\n): ElementRef[] {\n const refs: ElementRef[] = [];\n\n const chromeKeys: ChromeKey[] = ['title', 'subtitle', 'source', 'byline', 'footer'];\n for (const key of chromeKeys) {\n if (layout.chrome[key]) {\n refs.push(elementRef.chrome(key));\n }\n }\n\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n for (let i = 0; i < annotations.length; i++) {\n refs.push(elementRef.annotation(i, annotations[i].id));\n }\n\n const seriesLabels: string[] = [];\n for (const mark of layout.marks) {\n if (mark.type === 'line' && mark.label?.visible && mark.seriesKey) {\n seriesLabels.push(mark.seriesKey);\n }\n }\n seriesLabels.sort();\n for (const series of seriesLabels) {\n refs.push(elementRef.seriesLabel(series));\n }\n\n if ('entries' in layout.legend && layout.legend.entries.length > 0) {\n refs.push(elementRef.legend());\n }\n\n return refs;\n}\n\n/**\n * Check if an ElementRef points to a text-editable element.\n */\nexport function isTextEditable(ref: ElementRef, specAnnotations: Annotation[]): boolean {\n if (ref.type === 'chrome') return true;\n if (ref.type === 'annotation') {\n const annotation = specAnnotations[ref.index];\n return annotation?.type === 'text';\n }\n return false;\n}\n\n/**\n * Get the current text content for an element ref.\n */\nexport function getElementText(\n ref: ElementRef,\n spec: ChartSpec | LayerSpec | GraphSpec,\n): string | null {\n if (ref.type === 'chrome') {\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n if (!chromeConfig) return null;\n const entry = chromeConfig[ref.key];\n if (typeof entry === 'string') return entry;\n if (typeof entry === 'object' && entry !== null && 'text' in entry) {\n return (entry as { text: string }).text;\n }\n return null;\n }\n if (ref.type === 'annotation') {\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n const annotation = annotations[ref.index];\n if (annotation?.type === 'text') return (annotation as TextAnnotation).text ?? null;\n if (annotation?.label) return annotation.label;\n return null;\n }\n return null;\n}\n\n/**\n * Compare two ElementRefs for equality.\n */\nexport function refsEqual(a: ElementRef | null, b: ElementRef | null): boolean {\n if (a === null || b === null) return a === b;\n if (a.type !== b.type) return false;\n switch (a.type) {\n case 'annotation': {\n const bAnno = b as typeof a;\n if (a.id && bAnno.id) return a.id === bAnno.id;\n return a.index === bAnno.index;\n }\n case 'chrome':\n return a.key === (b as typeof a).key;\n case 'series-label':\n return a.series === (b as typeof a).series;\n case 'legend':\n return true;\n case 'legend-entry': {\n const bEntry = b as typeof a;\n return a.index === bEntry.index && a.series === bEntry.series;\n }\n }\n}\n\n/**\n * Render a selection overlay rectangle around a target element.\n */\nexport function renderSelectionOverlay(\n svg: SVGElement,\n ref: ElementRef,\n layout: ChartLayout,\n): SVGGElement | null {\n const target = findElementByRef(svg, ref);\n if (!target) return null;\n\n const bbox = (target as SVGGraphicsElement).getBBox();\n const padding = 4;\n\n const accentColor = layout.theme.colors.categorical?.[0] ?? '#4f46e5';\n\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n g.setAttribute('class', 'oc-selection-overlay');\n\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n rect.setAttribute('x', String(bbox.x - padding));\n rect.setAttribute('y', String(bbox.y - padding));\n rect.setAttribute('width', String(bbox.width + padding * 2));\n rect.setAttribute('height', String(bbox.height + padding * 2));\n rect.setAttribute('rx', '3');\n rect.setAttribute('fill', 'transparent');\n rect.setAttribute('stroke', accentColor);\n rect.setAttribute('stroke-width', '1.5');\n rect.setAttribute('pointer-events', 'none');\n\n g.appendChild(rect);\n svg.appendChild(g);\n\n return g;\n}\n\n/**\n * Create a visually-hidden data table from the chart's a11y fallback data.\n */\nexport function createScreenReaderTable(\n layout: ChartLayout,\n container: HTMLElement,\n): HTMLTableElement | null {\n const data = layout.a11y.dataTableFallback;\n if (!data || data.length === 0) return null;\n\n const table = document.createElement('table');\n table.className = 'oc-sr-only';\n table.style.position = 'absolute';\n table.style.width = '1px';\n table.style.height = '1px';\n table.style.padding = '0';\n table.style.margin = '-1px';\n table.style.overflow = 'hidden';\n table.style.clipPath = 'inset(50%)';\n table.style.whiteSpace = 'nowrap';\n table.style.borderWidth = '0';\n table.setAttribute('role', 'table');\n table.setAttribute('aria-label', `Data table: ${layout.a11y.altText}`);\n\n if (data.length > 0) {\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const headers = data[0] as unknown[];\n for (const header of headers) {\n const th = document.createElement('th');\n th.textContent = String(header ?? '');\n th.setAttribute('scope', 'col');\n headerRow.appendChild(th);\n }\n thead.appendChild(headerRow);\n table.appendChild(thead);\n }\n\n if (data.length > 1) {\n const tbody = document.createElement('tbody');\n for (let i = 1; i < data.length; i++) {\n const tr = document.createElement('tr');\n const cells = data[i] as unknown[];\n for (const cell of cells) {\n const td = document.createElement('td');\n td.textContent = String(cell ?? '');\n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n table.appendChild(tbody);\n }\n\n container.appendChild(table);\n return table;\n}\n","import type { TooltipContent } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\n\n/**\n * Wire tooltip events on mark elements inside an SVG.\n * Returns a cleanup function to remove all listeners.\n */\nexport function wireTooltipEvents(\n svg: SVGElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n): () => void {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n const cleanups: Array<() => void> = [];\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) continue;\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n const handleMouseMove = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length > 0) {\n const touch = touchEvent.touches[0];\n const svgRect = svg.getBoundingClientRect();\n const x = touch.clientX - svgRect.left;\n const y = touch.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('touchstart', handleTouchStart);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('touchstart', handleTouchStart);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n","/**\n * Series search combobox: the DOM overlay for the `seriesSearch` spec option.\n *\n * Renders an ARIA 1.2 editable combobox (input + popup listbox) with\n * multi-select chips, absolutely positioned inside `.oc-root` over the band\n * the chrome layout reserves (`layout.seriesSearch`). Because the overlay is\n * position: absolute, mounting or updating it never changes the observed\n * container's size, so it cannot re-trigger the container ResizeObserver.\n *\n * Matching is a diacritic-insensitive normalized prefix/substring match\n * (prefix matches rank first). No fuzzy-ranking dependency.\n */\n\nimport type { ResolvedSeriesSearch } from '@opendata-ai/openchart-core';\n\nexport interface SeriesSearchOptions {\n /** The chart container (`.oc-root`). Must be position: relative. */\n container: HTMLElement;\n /** Fired with the full selection (insertion order) after every add/remove. */\n onChange: (selected: string[]) => void;\n}\n\nexport interface SeriesSearchController {\n /** Reposition and refresh the control against a freshly rendered layout. */\n update(band: ResolvedSeriesSearch, svg: SVGElement): void;\n /** Hide the control (layout stripped the band but the spec still wants it). */\n hide(): void;\n /** Currently selected values, in insertion order. */\n getSelected(): string[];\n /** Replace the selection without firing onChange (e.g. reset on spec update). */\n setSelected(values: string[]): void;\n /** Remove the control from the DOM. */\n destroy(): void;\n}\n\nlet seriesSearchIdCounter = 0;\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Fold a string for matching: lowercase with combining diacritical marks\n * stripped. `map[i]` is the index in the original string that produced\n * folded character `i`, so match ranges can be mapped back for emphasis.\n */\nfunction foldWithMap(s: string): { folded: string; map: number[] } {\n let folded = '';\n const map: number[] = [];\n for (let i = 0; i < s.length; i++) {\n const f = s[i]\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase();\n for (const ch of f) {\n folded += ch;\n map.push(i);\n }\n }\n return { folded, map };\n}\n\nfunction fold(s: string): string {\n return foldWithMap(s).folded;\n}\n\n/** Small stroke icon (magnifier or cross) built from SVG path data. */\nfunction createIcon(size: number, paths: string[]): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('width', String(size));\n svg.setAttribute('height', String(size));\n svg.setAttribute('viewBox', '0 0 16 16');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('aria-hidden', 'true');\n for (const d of paths) {\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute('d', d);\n path.setAttribute('stroke', 'currentColor');\n path.setAttribute('stroke-width', '1.5');\n path.setAttribute('stroke-linecap', 'round');\n svg.appendChild(path);\n }\n return svg;\n}\n\n/**\n * Create the series search control. Mounted once per chart instance and kept\n * across re-renders (so typing focus and chips survive highlight re-renders);\n * `update()` re-syncs position, values, and placeholder after each render.\n */\nexport function createSeriesSearch(options: SeriesSearchOptions): SeriesSearchController {\n const { container, onChange } = options;\n\n const id = `oc-series-search-${++seriesSearchIdCounter}`;\n const listboxId = `${id}-listbox`;\n\n let values: string[] = [];\n let selected: string[] = [];\n let matches: string[] = [];\n let activeIndex = -1;\n let open = false;\n let destroyed = false;\n\n // ---------------------------------------------------------------------------\n // DOM\n // ---------------------------------------------------------------------------\n\n const root = document.createElement('div');\n root.className = 'oc-series-search';\n root.style.display = 'none';\n\n const chips = document.createElement('div');\n chips.className = 'oc-series-search-chips';\n\n const box = document.createElement('div');\n box.className = 'oc-series-search-box';\n\n const icon = createIcon(14, [\n 'M7 11.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z',\n 'M10.5 10.5 13.5 13.5',\n ]);\n icon.classList.add('oc-series-search-icon');\n\n const input = document.createElement('input');\n input.className = 'oc-series-search-input';\n input.type = 'text';\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', listboxId);\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-haspopup', 'listbox');\n input.autocomplete = 'off';\n input.spellcheck = false;\n\n const listbox = document.createElement('ul');\n listbox.className = 'oc-series-search-listbox';\n listbox.id = listboxId;\n listbox.setAttribute('role', 'listbox');\n listbox.hidden = true;\n\n box.append(icon, input, listbox);\n root.append(chips, box);\n // Ensure absolute children position against the chart container, matching\n // the tooltip manager's approach.\n container.style.position = container.style.position || 'relative';\n // First child so the tab order matches the visual order (search above chart);\n // render() re-appends the SVG after this node on every re-render.\n container.insertBefore(root, container.firstChild);\n\n // ---------------------------------------------------------------------------\n // Matching\n // ---------------------------------------------------------------------------\n\n function computeMatches(): string[] {\n const q = fold(input.value.trim());\n const available = values.filter((v) => !selected.includes(v));\n if (!q) return available;\n const prefix: string[] = [];\n const substring: string[] = [];\n for (const v of available) {\n const idx = fold(v).indexOf(q);\n if (idx === 0) prefix.push(v);\n else if (idx > 0) substring.push(v);\n }\n return [...prefix, ...substring];\n }\n\n /** Append the option label with the matched substring emphasized. */\n function appendOptionText(li: HTMLLIElement, value: string): void {\n const q = fold(input.value.trim());\n if (!q) {\n li.textContent = value;\n return;\n }\n const { folded, map } = foldWithMap(value);\n const idx = folded.indexOf(q);\n if (idx < 0) {\n li.textContent = value;\n return;\n }\n const start = map[idx];\n const end = idx + q.length < folded.length ? map[idx + q.length] : value.length;\n li.append(document.createTextNode(value.slice(0, start)));\n const match = document.createElement('span');\n match.className = 'oc-series-search-match';\n match.textContent = value.slice(start, end);\n li.append(match, document.createTextNode(value.slice(end)));\n }\n\n // ---------------------------------------------------------------------------\n // Rendering\n // ---------------------------------------------------------------------------\n\n function renderChips(): void {\n chips.textContent = '';\n for (const value of selected) {\n const chip = document.createElement('span');\n chip.className = 'oc-series-search-chip';\n chip.append(document.createTextNode(value));\n\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'oc-series-search-chip-remove';\n remove.setAttribute('aria-label', `Remove ${value}`);\n remove.appendChild(createIcon(8, ['M3 3 13 13', 'M13 3 3 13']));\n remove.addEventListener('click', () => {\n removeValue(value);\n input.focus();\n });\n\n chip.appendChild(remove);\n chips.appendChild(chip);\n }\n }\n\n function renderList(): void {\n matches = computeMatches();\n if (activeIndex >= matches.length) activeIndex = matches.length - 1;\n listbox.textContent = '';\n\n if (matches.length === 0) {\n const empty = document.createElement('li');\n empty.className = 'oc-series-search-empty';\n empty.setAttribute('role', 'presentation');\n empty.textContent = 'No matches';\n listbox.appendChild(empty);\n input.removeAttribute('aria-activedescendant');\n return;\n }\n\n matches.forEach((value, i) => {\n const li = document.createElement('li');\n li.className = 'oc-series-search-option';\n li.id = `${id}-opt-${i}`;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(i === activeIndex));\n appendOptionText(li, value);\n li.addEventListener('click', () => selectValue(value));\n listbox.appendChild(li);\n });\n\n if (activeIndex >= 0) {\n input.setAttribute('aria-activedescendant', `${id}-opt-${activeIndex}`);\n const activeEl = listbox.children[activeIndex] as HTMLElement | undefined;\n activeEl?.scrollIntoView?.({ block: 'nearest' });\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n function openList(): void {\n if (open) return;\n open = true;\n listbox.hidden = false;\n input.setAttribute('aria-expanded', 'true');\n }\n\n function closeList(): void {\n if (!open) return;\n open = false;\n activeIndex = -1;\n listbox.hidden = true;\n input.setAttribute('aria-expanded', 'false');\n input.removeAttribute('aria-activedescendant');\n }\n\n // ---------------------------------------------------------------------------\n // Selection\n // ---------------------------------------------------------------------------\n\n function selectValue(value: string): void {\n if (!selected.includes(value)) selected.push(value);\n input.value = '';\n closeList();\n renderChips();\n onChange([...selected]);\n }\n\n function removeValue(value: string): void {\n const idx = selected.indexOf(value);\n if (idx < 0) return;\n selected.splice(idx, 1);\n renderChips();\n onChange([...selected]);\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n input.addEventListener('input', () => {\n openList();\n activeIndex = computeMatches().length > 0 ? 0 : -1;\n renderList();\n });\n\n input.addEventListener('keydown', (e: KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n e.preventDefault();\n const wasOpen = open;\n openList();\n if (!wasOpen) {\n matches = computeMatches();\n activeIndex = matches.length > 0 ? 0 : -1;\n } else if (matches.length > 0) {\n const delta = e.key === 'ArrowDown' ? 1 : -1;\n activeIndex = (activeIndex + delta + matches.length) % matches.length;\n }\n renderList();\n break;\n }\n case 'Enter': {\n if (open && activeIndex >= 0 && activeIndex < matches.length) {\n e.preventDefault();\n selectValue(matches[activeIndex]);\n }\n break;\n }\n case 'Escape': {\n if (open) {\n e.preventDefault();\n e.stopPropagation();\n closeList();\n }\n break;\n }\n case 'Backspace': {\n if (input.value === '' && selected.length > 0) {\n removeValue(selected[selected.length - 1]);\n }\n break;\n }\n case 'Tab': {\n closeList();\n break;\n }\n }\n });\n\n // Keep focus in the input while clicking options/chips inside the popup.\n listbox.addEventListener('mousedown', (e) => e.preventDefault());\n\n // Close when focus leaves the whole control.\n root.addEventListener('focusout', (e: FocusEvent) => {\n const next = e.relatedTarget as Node | null;\n if (!next || !root.contains(next)) closeList();\n });\n\n // ---------------------------------------------------------------------------\n // Controller\n // ---------------------------------------------------------------------------\n\n return {\n update(band: ResolvedSeriesSearch, svg: SVGElement): void {\n if (destroyed) return;\n values = band.values;\n input.placeholder = band.placeholder;\n input.setAttribute('aria-label', band.placeholder);\n\n // Layout coords -> pixel coords relative to the container, same\n // viewBox-scale approach as the text edit overlay.\n const viewBox = (svg as SVGSVGElement).viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const scaleX = viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1;\n root.style.left = `${band.x * scaleX + (svgRect.left - containerRect.left)}px`;\n root.style.top = `${band.y * scaleY + (svgRect.top - containerRect.top)}px`;\n root.style.width = `${band.width * scaleX}px`;\n root.style.height = `${band.height * scaleY}px`;\n root.style.display = 'flex';\n\n if (open) renderList();\n },\n hide(): void {\n root.style.display = 'none';\n closeList();\n },\n getSelected(): string[] {\n return [...selected];\n },\n setSelected(next: string[]): void {\n selected = [...next];\n renderChips();\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n root.remove();\n },\n };\n}\n","/**\n * Generate CSS custom properties from a resolved JS theme.\n *\n * Stamped on the .oc-root container at mount time so CSS consumers\n * read from the same source of truth as the JS engine. The static\n * values in tokens.css / dark.css serve as fallback defaults for\n * contexts where JS hasn't mounted (SSR, static HTML).\n */\n\nimport type { ResolvedTheme } from '@opendata-ai/openchart-core';\nimport { adaptForLightLineStroke, cssTokenDefault } from '@opendata-ai/openchart-core';\n\nexport function stampThemeProperties(el: HTMLElement, theme: ResolvedTheme): void {\n const accent = theme.colors.categorical[0] ?? cssTokenDefault('--oc-accent', 'light');\n const bg =\n theme.colors.background === 'transparent'\n ? theme.isDark\n ? cssTokenDefault('--oc-bg', 'dark')\n : cssTokenDefault('--oc-bg', 'light')\n : theme.colors.background;\n\n const props: [string, string][] = [\n ['--oc-font-family', theme.fonts.family],\n ['--oc-font-mono', theme.fonts.mono],\n ['--oc-title-size', `${theme.chrome.title.fontSize}px`],\n ['--oc-title-weight', `${theme.chrome.title.fontWeight}`],\n ['--oc-subtitle-size', `${theme.chrome.subtitle.fontSize}px`],\n ['--oc-subtitle-weight', `${theme.chrome.subtitle.fontWeight}`],\n ['--oc-source-size', `${theme.chrome.source.fontSize}px`],\n ['--oc-source-weight', `${theme.chrome.source.fontWeight}`],\n ['--oc-body-size', `${theme.fonts.sizes.body}px`],\n ['--oc-eyebrow-size', `${theme.chrome.eyebrow.fontSize}px`],\n ['--oc-eyebrow-weight', `${theme.chrome.eyebrow.fontWeight}`],\n ['--oc-bg', bg],\n ['--oc-text', theme.colors.text],\n ['--oc-text-muted', theme.colors.axis],\n ['--oc-gridline', theme.colors.gridline],\n ['--oc-axis', theme.colors.axis],\n ['--oc-border-radius', `${theme.borderRadius}px`],\n ['--oc-accent', accent],\n ['--oc-accent-strong', adaptForLightLineStroke(accent)],\n ['--oc-positive', theme.colors.positive],\n ['--oc-negative', theme.colors.negative],\n ['--oc-space-2', `${theme.spacing.chromeGap * 2}px`],\n ['--oc-space-4', `${theme.spacing.padding}px`],\n ];\n\n for (const [name, value] of props) {\n el.style.setProperty(name, value);\n }\n}\n","/**\n * Data-update transition driver for bar/column, line, area, scatter/dot,\n * rule, tick, and text charts. Also transitions axis ticks, tick labels,\n * and gridlines so the whole chart adjusts as one system.\n *\n * Matches marks across layout snapshots by `key`, then animates geometry\n * changes (position, size, path) using a single rAF loop. Enter/exit/update\n * choreography runs in one timeline with cubic-out easing for a smooth\n * deceleration feel.\n *\n * For rect marks: tweens position/size directly.\n * For line/area marks: normalizes point arrays to equal length, interpolates\n * point positions per frame, and rebuilds SVG paths via d3 curve generators.\n * For point marks (scatter/dot/line overlay): tweens cx/cy/r.\n * For rule/tick marks: tweens line endpoints (x1/y1/x2/y2).\n * For text marks: tweens x/y position.\n * For axis ticks/gridlines: matches by value key and tweens positions.\n *\n * Ghost elements handle exits: cloned into the marks container, they\n * collapse + fade out then get removed. No CSS animations are used here\n * because transitions tween computed geometry, not class-toggled states.\n */\n\nimport type {\n AreaMark,\n AxisLayout,\n ChartLayout,\n GradientDef,\n LineMark,\n Point,\n PointMark,\n RectMark,\n ResolvedAnimation,\n ResolvedAnnotation,\n RuleMarkLayout,\n TextMarkLayout,\n TickMarkLayout,\n} from '@opendata-ai/openchart-core';\nimport { isGradientDef } from '@opendata-ai/openchart-core';\nimport {\n buildAreaPath,\n buildLinePath,\n EXIT_DEFAULTS,\n serializeKeyValue,\n} from '@opendata-ai/openchart-engine';\nimport { interpolateRgb } from 'd3-interpolate';\nimport { buildGradientDefs, resolveMarkFill } from './gradient-utils';\nimport { rectPathWithCorners, renderSingleMark } from './renderers/marks';\n\n/**\n * Stable identity for an annotation across layout snapshots.\n *\n * Annotations have no engine-assigned `mark.key`. When the author supplies\n * `annotation.id` that is the identity; otherwise fall back to type + text,\n * which is stable as long as the annotation keeps saying the same thing.\n *\n * Deliberately NOT keyed on position: an annotation that moves is the same\n * annotation and should tween to its new spot, not cross-fade with itself.\n * And deliberately NOT `data-annotation-index`: that is positional, so\n * inserting an annotation ahead of another would renumber it and make every\n * later annotation look brand new and re-fade.\n *\n * Duplicate keys (same type and text twice) are disambiguated by occurrence\n * order in `keyAnnotations` below, not here.\n */\nfunction annotationKey(a: ResolvedAnnotation): string {\n if (a.id) return `id:${a.id}`;\n return `${a.type}:${a.label?.text ?? ''}`;\n}\n\n/**\n * Key a layout's annotations, suffixing duplicates so every key is unique\n * within the snapshot. Two annotations sharing a key would otherwise both\n * match the same element and fight over it.\n */\nfunction keyAnnotations(annotations: ResolvedAnnotation[]): string[] {\n const seen = new Map<string, number>();\n return annotations.map((a) => {\n const base = annotationKey(a);\n const n = seen.get(base) ?? 0;\n seen.set(base, n + 1);\n return n === 0 ? base : `${base}#${n}`;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Snapshot of in-flight tween geometry, keyed by mark key.\n * Used for interruption retargeting: the next transition starts from\n * whatever position the previous transition had reached.\n */\nexport type GeometrySnapshot = Map<string, SnapshotGeometry>;\n\nexport type SnapshotGeometry =\n | { type: 'rect'; x: number; y: number; width: number; height: number }\n | { type: 'point'; cx: number; cy: number; r?: number }\n | { type: 'rule'; x1: number; y1: number; x2: number; y2: number }\n | { type: 'tick'; x1: number; y1: number; x2: number; y2: number }\n | { type: 'textMark'; x: number; y: number }\n | { type: 'line'; d: string }\n | { type: 'area'; d: string; topD?: string };\n\nexport interface TransitionHandle {\n cancel(): void;\n readonly running: boolean;\n /** Capture current interpolated geometry for all in-flight tweens. */\n snapshot(): GeometrySnapshot;\n}\n\n// ---------------------------------------------------------------------------\n// Easing\n// ---------------------------------------------------------------------------\n\n/** Cubic-out easing: objects decelerate naturally into place. */\nfunction cubicOut(t: number): number {\n const f = 1 - t;\n return 1 - f * f * f;\n}\n\n// ---------------------------------------------------------------------------\n// canTransition gate\n// ---------------------------------------------------------------------------\n\n/** Mark types that support data-update transitions. */\nconst TRANSITIONABLE_MARKS = new Set(['bar', 'line', 'area', 'point']);\n\n/**\n * Spec-shape half of the transition gate (mark type + encoding identity),\n * usable before either spec has been compiled. Exported so callers that\n * need to predict transition eligibility ahead of a compile (e.g. the\n * scrollytelling story layer deciding whether to arm its crossfade\n * fallback) can reuse the exact same rule the post-compile gate enforces,\n * rather than re-deriving it and risking drift.\n *\n * This is gate checks 3-4 of `canTransition` in isolation; it does NOT\n * check layout-derived conditions (dimensions, mark count, geometry delta,\n * sparkline display) since those require a compiled `ChartLayout`.\n */\nexport function canTransitionSpecShape(prevSpec: unknown, nextSpec: unknown): boolean {\n const prev = prevSpec as Record<string, unknown>;\n const next = nextSpec as Record<string, unknown>;\n if (!prev || !next || !('mark' in prev) || !('mark' in next)) return false;\n const prevMark =\n typeof prev.mark === 'string' ? prev.mark : (prev.mark as Record<string, unknown>)?.type;\n const nextMark =\n typeof next.mark === 'string' ? next.mark : (next.mark as Record<string, unknown>)?.type;\n if (prevMark !== nextMark) return false;\n if (!TRANSITIONABLE_MARKS.has(prevMark as string)) return false;\n\n const prevEnc = (prev as { encoding?: Record<string, Record<string, unknown>> }).encoding;\n const nextEnc = (next as { encoding?: Record<string, Record<string, unknown>> }).encoding;\n if (!prevEnc || !nextEnc) return false;\n return !(\n prevEnc.x?.field !== nextEnc.x?.field ||\n prevEnc.x?.type !== nextEnc.x?.type ||\n prevEnc.y?.field !== nextEnc.y?.field ||\n prevEnc.y?.type !== nextEnc.y?.type ||\n prevEnc.color?.field !== nextEnc.color?.field\n );\n}\n\n/**\n * Determine whether a data-update transition should run instead of\n * a full tear-down + re-render.\n *\n * Ten gate checks must all pass. If any fails, the caller should fall\n * through to the standard render path (instant swap).\n */\nexport function canTransition(args: {\n prevLayout: ChartLayout | null;\n nextLayout: ChartLayout;\n prevSpec: unknown;\n nextSpec: unknown;\n isFirstRender: boolean;\n entranceInFlight: boolean;\n}): boolean {\n const { prevLayout, nextLayout, prevSpec, nextSpec, isFirstRender, entranceInFlight } = args;\n\n // 1. Previous layout + spec exist and not first render\n if (!prevLayout || !prevSpec || isFirstRender) return false;\n\n // 2. Resolved animation.update present on next layout\n if (!nextLayout.animation?.update) return false;\n\n // 3-4. Mark type + encoding identity unchanged (spec-shape half of the gate)\n if (!canTransitionSpecShape(prevSpec, nextSpec)) return false;\n\n // 5. Not sparkline\n if (nextLayout.display === 'sparkline') return false;\n\n // 6. Entrance animation not in flight\n if (entranceInFlight) return false;\n\n // 7. Layout dimensions unchanged\n if (\n prevLayout.dimensions.width !== nextLayout.dimensions.width ||\n prevLayout.dimensions.height !== nextLayout.dimensions.height\n ) {\n return false;\n }\n\n // 8. Mark count <= 500\n if (nextLayout.marks.length > 500) return false;\n\n // 9. Something visible actually changed (zero-delta check)\n if (!hasVisibleChange(prevLayout, nextLayout)) return false;\n\n // 10. prefers-reduced-motion not active\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n try {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return false;\n } catch {\n // happy-dom may not support matchMedia fully; treat as no preference\n }\n }\n\n return true;\n}\n\n/**\n * Check whether anything the transition can animate differs between layouts.\n *\n * Gate check 9. This is broader than geometry on purpose: a step that only\n * recolors (an `encoding.color.highlight` mute) or only adds an annotation\n * moves no mark by a single pixel. Testing geometry alone reported \"nothing\n * changed\" for those, vetoing the transition and leaving `render()`'s instant\n * swap as the only thing that happened -- so the highlight snapped and the\n * annotation popped in, even though the machinery to fade both already existed\n * further down this file.\n */\nfunction hasVisibleChange(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n return (\n hasGeometryChanged(prevLayout, nextLayout) ||\n hasColorChanged(prevLayout, nextLayout) ||\n hasAnnotationChanged(prevLayout, nextLayout)\n );\n}\n\n/** Check if any mark's fill or stroke differs (e.g. a highlight mute). */\nfunction hasColorChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prevMarks = prevLayout.marks;\n const nextMarks = nextLayout.marks;\n if (prevMarks.length !== nextMarks.length) return true;\n\n for (let i = 0; i < prevMarks.length; i++) {\n const p = prevMarks[i] as { fill?: string; stroke?: string };\n const n = nextMarks[i] as { fill?: string; stroke?: string };\n if (p.fill !== n.fill || p.stroke !== n.stroke) return true;\n }\n return false;\n}\n\n/** Check if annotations were added, removed, reordered, or moved. */\nfunction hasAnnotationChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prev = prevLayout.annotations ?? [];\n const next = nextLayout.annotations ?? [];\n if (prev.length !== next.length) return true;\n\n const prevKeys = keyAnnotations(prev);\n const nextKeys = keyAnnotations(next);\n\n for (let i = 0; i < prev.length; i++) {\n if (prevKeys[i] !== nextKeys[i]) return true;\n const p = prev[i];\n const n = next[i];\n if (p.label?.x !== n.label?.x || p.label?.y !== n.label?.y) return true;\n if (p.opacity !== n.opacity) return true;\n }\n return false;\n}\n\n/** Check if any mark geometry differs between prev and next layouts. */\nfunction hasGeometryChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prevMarks = prevLayout.marks;\n const nextMarks = nextLayout.marks;\n\n if (prevMarks.length !== nextMarks.length) return true;\n\n for (let i = 0; i < prevMarks.length; i++) {\n const p = prevMarks[i];\n const n = nextMarks[i];\n if (p.type !== n.type || p.key !== n.key) return true;\n\n if (p.type === 'rect' && n.type === 'rect') {\n if (p.x !== n.x || p.y !== n.y || p.width !== n.width || p.height !== n.height) return true;\n } else if (p.type === 'line' && n.type === 'line') {\n if (p.path !== n.path || p.points.length !== n.points.length) return true;\n for (let j = 0; j < p.points.length; j++) {\n if (p.points[j].x !== n.points[j].x || p.points[j].y !== n.points[j].y) return true;\n }\n } else if (p.type === 'area' && n.type === 'area') {\n if (p.path !== n.path) return true;\n } else if (p.type === 'point' && n.type === 'point') {\n if (p.cx !== n.cx || p.cy !== n.cy || p.r !== n.r) return true;\n } else if (p.type === 'rule' && n.type === 'rule') {\n if (p.x1 !== n.x1 || p.y1 !== n.y1 || p.x2 !== n.x2 || p.y2 !== n.y2) return true;\n } else if (p.type === 'tick' && n.type === 'tick') {\n if (p.x !== n.x || p.y !== n.y) return true;\n } else if (p.type === 'textMark' && n.type === 'textMark') {\n if (p.x !== n.x || p.y !== n.y) return true;\n }\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types for tweens\n// ---------------------------------------------------------------------------\n\ninterface RectGeom {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface RectTween {\n tweenType: 'rect';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n from: RectGeom;\n to: RectGeom;\n mark: RectMark;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface LineTween {\n tweenType: 'line';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromPts: Point[];\n toPts: Point[];\n /** The final mark's points (may differ from toPts which is the normalized array). */\n finalPoints: Point[];\n interpolate?: string;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface AreaTween {\n tweenType: 'area';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromTop: Point[];\n toTop: Point[];\n fromBottom: Point[];\n toBottom: Point[];\n /** Final mark's points for the exact path at t=1. */\n finalTopPoints: Point[];\n finalBottomPoints: Point[];\n interpolate?: string;\n /** Whether to also write the topPath stroke element. */\n hasStroke: boolean;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface PointTween {\n tweenType: 'point';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromCx: number;\n fromCy: number;\n toCx: number;\n toCy: number;\n fromR?: number;\n toR?: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n /** Whether this point has a renderer-set opacity (e.g. suppressed under endpoint marker). */\n suppressedOpacity?: string;\n}\n\ninterface RuleTween {\n tweenType: 'rule';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromX1: number;\n fromY1: number;\n fromX2: number;\n fromY2: number;\n toX1: number;\n toY1: number;\n toX2: number;\n toY2: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface TickTween {\n tweenType: 'tick';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromX1: number;\n fromY1: number;\n fromX2: number;\n fromY2: number;\n toX1: number;\n toY1: number;\n toX2: number;\n toY2: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface TextMarkTween {\n tweenType: 'textMark';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n fromX: number;\n fromY: number;\n toX: number;\n toY: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface AxisTickTween {\n tweenType: 'axisTick';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n /** Position attribute name: 'x' for x-axis ticks, 'y' for y-axis ticks. */\n posAttr: string;\n fromPos: number;\n toPos: number;\n /** Whether to crossfade instead of slide (for rotated labels). */\n crossfade: boolean;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ninterface GridlineTween {\n tweenType: 'gridline';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n /** Which attrs to tween: 'y' for horizontal gridlines, 'x' for vertical. */\n orientation: 'x' | 'y';\n fromPos: number;\n toPos: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\n/**\n * Fill/stroke interpolation, kept separate from the geometry tweens rather\n * than bolted onto each of them.\n *\n * Color is orthogonal to geometry: a highlight mute recolors marks that do not\n * move, and a normal data update moves marks that do not recolor. Threading\n * from/to colors through all nine geometry variants would touch every builder\n * to express something none of them need. A parallel tween on the same rAF\n * loop composes instead -- a mark that both moves and recolors simply gets two\n * tweens, each doing one job.\n *\n * Targets the shape element (rect/path/circle/line) rather than the mark <g>,\n * since that is where the renderer writes fill and stroke.\n */\ninterface ColorTween {\n tweenType: 'color';\n kind: 'update';\n el: SVGElement;\n attr: 'fill' | 'stroke';\n from: string;\n to: string;\n /** Never set; present so the shared opacity step can read the union. */\n fromOpacity?: number;\n toOpacity?: number;\n}\n\n/**\n * Annotation enter/update/exit. Entering annotations fade in, surviving ones\n * tween to their new position, exiting ones fade out.\n */\ninterface AnnotationTween {\n tweenType: 'annotation';\n kind: 'update' | 'enter' | 'exit';\n el: SVGElement;\n /** Pixel delta applied as a transform; annotations position via many child attrs. */\n fromDx: number;\n fromDy: number;\n ghost?: SVGElement;\n fromOpacity?: number;\n toOpacity?: number;\n}\n\ntype Tween =\n | RectTween\n | LineTween\n | AreaTween\n | PointTween\n | RuleTween\n | TickTween\n | TextMarkTween\n | AxisTickTween\n | GridlineTween\n | ColorTween\n | AnnotationTween;\n\n// ---------------------------------------------------------------------------\n// Geometry helpers (rect)\n// ---------------------------------------------------------------------------\n\nfunction geomFromMark(m: RectMark): RectGeom {\n return { x: m.x, y: m.y, width: m.width, height: m.height };\n}\n\nfunction applyGeomToElement(el: SVGElement, geom: RectGeom, mark: RectMark): void {\n const shapeEl = el.querySelector('rect, path') as SVGElement | null;\n if (!shapeEl) return;\n\n const sides = mark.cornerRadiusSides;\n const partialCorners =\n !!sides && (!sides.tl || !sides.tr || !sides.br || !sides.bl) && !!mark.cornerRadius;\n\n if (partialCorners && shapeEl.tagName === 'path') {\n const tempMark = { ...mark, ...geom };\n shapeEl.setAttribute('d', rectPathWithCorners(tempMark, sides));\n } else {\n shapeEl.setAttribute('x', String(geom.x));\n shapeEl.setAttribute('y', String(geom.y));\n shapeEl.setAttribute('width', String(geom.width));\n shapeEl.setAttribute('height', String(geom.height));\n }\n}\n\nfunction lerpGeom(from: RectGeom, to: RectGeom, t: number): RectGeom {\n return {\n x: from.x + (to.x - from.x) * t,\n y: from.y + (to.y - from.y) * t,\n width: from.width + (to.width - from.width) * t,\n height: from.height + (to.height - from.height) * t,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Point interpolation helpers (line/area morphing)\n// ---------------------------------------------------------------------------\n\nfunction lerpPoint(a: Point, b: Point, t: number): Point {\n return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };\n}\n\n/**\n * Normalize two point arrays (prev and next) to equal length by matching\n * on pointKeys. Inserted/removed points get synthetic positions interpolated\n * from surviving neighbors.\n *\n * Returns [fromPts, toPts] of equal length.\n */\nexport function normalizePointArrays(\n prevPoints: Point[],\n nextPoints: Point[],\n prevKeys: string[],\n nextKeys: string[],\n): [Point[], Point[]] {\n // Build merged key sequence preserving order from both sides\n const nextKeySet = new Set(nextKeys);\n\n // Check for zero survivors (no keys in common)\n const survivors = prevKeys.filter((k) => nextKeySet.has(k));\n if (survivors.length === 0) {\n // Crossfade path: return arrays as-is (caller handles opacity crossfade)\n return [prevPoints, nextPoints];\n }\n\n // Build key-to-point maps\n const prevByKey = new Map<string, Point>();\n for (let i = 0; i < prevKeys.length; i++) {\n prevByKey.set(prevKeys[i], prevPoints[i]);\n }\n const nextByKey = new Map<string, Point>();\n for (let i = 0; i < nextKeys.length; i++) {\n nextByKey.set(nextKeys[i], nextPoints[i]);\n }\n\n // Merge keys in order: walk both arrays maintaining relative order\n const merged = mergeKeyOrder(prevKeys, nextKeys);\n\n // Precompute merged index map for O(1) lookups in insertion/removal helpers\n const mergedIndex = new Map<string, number>();\n for (let i = 0; i < merged.length; i++) {\n mergedIndex.set(merged[i], i);\n }\n\n const fromPts: Point[] = [];\n const toPts: Point[] = [];\n\n for (const key of merged) {\n const inPrev = prevByKey.has(key);\n const inNext = nextByKey.has(key);\n\n if (inPrev && inNext) {\n // Matched point: straightforward interpolation\n fromPts.push(prevByKey.get(key)!);\n toPts.push(nextByKey.get(key)!);\n } else if (inNext && !inPrev) {\n // Inserted point: \"to\" is nextPoint; \"from\" is interpolated on prev line\n const nextPt = nextByKey.get(key)!;\n toPts.push(nextPt);\n fromPts.push(findInsertionPosition(key, merged, mergedIndex, prevByKey, nextByKey, nextPt));\n } else if (inPrev && !inNext) {\n // Removed point: \"from\" is prevPoint; \"to\" is collapse position\n const prevPt = prevByKey.get(key)!;\n fromPts.push(prevPt);\n toPts.push(findRemovalPosition(key, merged, mergedIndex, prevByKey, nextByKey, prevPt));\n }\n }\n\n return [fromPts, toPts];\n}\n\n/**\n * Merge two key arrays preserving the relative order from both.\n * Keys present in both appear once at their first occurrence position.\n */\nfunction mergeKeyOrder(prevKeys: string[], nextKeys: string[]): string[] {\n // Precompute index maps for O(1) lookups instead of indexOf\n const nextIndex = new Map<string, number>();\n for (let i = 0; i < nextKeys.length; i++) {\n if (!nextIndex.has(nextKeys[i])) nextIndex.set(nextKeys[i], i);\n }\n const prevIndex = new Map<string, number>();\n for (let i = 0; i < prevKeys.length; i++) {\n if (!prevIndex.has(prevKeys[i])) prevIndex.set(prevKeys[i], i);\n }\n\n const result: string[] = [];\n const added = new Set<string>();\n let pi = 0;\n let ni = 0;\n\n while (pi < prevKeys.length && ni < nextKeys.length) {\n const pk = prevKeys[pi];\n const nk = nextKeys[ni];\n\n if (added.has(pk)) {\n pi++;\n continue;\n }\n if (added.has(nk)) {\n ni++;\n continue;\n }\n\n if (pk === nk) {\n result.push(pk);\n added.add(pk);\n pi++;\n ni++;\n } else {\n const pkInNext = nextIndex.has(pk) && nextIndex.get(pk)! >= ni ? nextIndex.get(pk)! : -1;\n const nkInPrev = prevIndex.has(nk) && prevIndex.get(nk)! >= pi ? prevIndex.get(nk)! : -1;\n\n if (pkInNext === -1 && nkInPrev === -1) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else if (pkInNext === -1) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else if (nkInPrev === -1) {\n result.push(nk);\n added.add(nk);\n ni++;\n } else {\n if (pkInNext <= nkInPrev) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else {\n result.push(nk);\n added.add(nk);\n ni++;\n }\n }\n }\n }\n\n // Drain remaining\n while (pi < prevKeys.length) {\n if (!added.has(prevKeys[pi])) {\n result.push(prevKeys[pi]);\n added.add(prevKeys[pi]);\n }\n pi++;\n }\n while (ni < nextKeys.length) {\n if (!added.has(nextKeys[ni])) {\n result.push(nextKeys[ni]);\n added.add(nextKeys[ni]);\n }\n ni++;\n }\n\n return result;\n}\n\n/**\n * Find where an inserted point should start from on the previous line.\n * Interpolates between the nearest surviving neighbors' prev positions,\n * proportional to the new point's x between neighbors' next x positions.\n * If at head/tail, uses the nearest surviving endpoint's prev position.\n */\nfunction findInsertionPosition(\n key: string,\n merged: string[],\n mergedIndex: Map<string, number>,\n prevByKey: Map<string, Point>,\n nextByKey: Map<string, Point>,\n nextPt: Point,\n): Point {\n const idx = mergedIndex.get(key) ?? -1;\n\n // Find nearest surviving neighbor before\n let beforeKey: string | null = null;\n for (let i = idx - 1; i >= 0; i--) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n beforeKey = merged[i];\n break;\n }\n }\n\n // Find nearest surviving neighbor after\n let afterKey: string | null = null;\n for (let i = idx + 1; i < merged.length; i++) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n afterKey = merged[i];\n break;\n }\n }\n\n if (beforeKey && afterKey) {\n // Interpolate between neighbors\n const beforeNext = nextByKey.get(beforeKey)!;\n const afterNext = nextByKey.get(afterKey)!;\n const beforePrev = prevByKey.get(beforeKey)!;\n const afterPrev = prevByKey.get(afterKey)!;\n\n const range = afterNext.x - beforeNext.x;\n const t = range === 0 ? 0.5 : (nextPt.x - beforeNext.x) / range;\n return lerpPoint(beforePrev, afterPrev, Math.max(0, Math.min(1, t)));\n }\n\n if (beforeKey) {\n // At tail: unfold from nearest surviving endpoint\n return { ...prevByKey.get(beforeKey)! };\n }\n\n if (afterKey) {\n // At head: unfold from nearest surviving endpoint\n return { ...prevByKey.get(afterKey)! };\n }\n\n // No survivors (shouldn't happen since we check above, but safe fallback)\n return nextPt;\n}\n\n/**\n * Find where a removed point should collapse to on the next line.\n * Mirror of findInsertionPosition but for the destination side.\n */\nfunction findRemovalPosition(\n key: string,\n merged: string[],\n mergedIndex: Map<string, number>,\n prevByKey: Map<string, Point>,\n nextByKey: Map<string, Point>,\n prevPt: Point,\n): Point {\n const idx = mergedIndex.get(key) ?? -1;\n\n // Find nearest surviving neighbor before\n let beforeKey: string | null = null;\n for (let i = idx - 1; i >= 0; i--) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n beforeKey = merged[i];\n break;\n }\n }\n\n // Find nearest surviving neighbor after\n let afterKey: string | null = null;\n for (let i = idx + 1; i < merged.length; i++) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n afterKey = merged[i];\n break;\n }\n }\n\n if (beforeKey && afterKey) {\n const beforePrev = prevByKey.get(beforeKey)!;\n const afterPrev = prevByKey.get(afterKey)!;\n const beforeNext = nextByKey.get(beforeKey)!;\n const afterNext = nextByKey.get(afterKey)!;\n\n const range = afterPrev.x - beforePrev.x;\n const t = range === 0 ? 0.5 : (prevPt.x - beforePrev.x) / range;\n return lerpPoint(beforeNext, afterNext, Math.max(0, Math.min(1, t)));\n }\n\n if (beforeKey) {\n return { ...nextByKey.get(beforeKey)! };\n }\n\n if (afterKey) {\n return { ...nextByKey.get(afterKey)! };\n }\n\n return prevPt;\n}\n\n// ---------------------------------------------------------------------------\n// Line/area path application helpers\n// ---------------------------------------------------------------------------\n\n/** Interpolate a point array at parameter t. */\nfunction interpolatePoints(fromPts: Point[], toPts: Point[], t: number): Point[] {\n const len = Math.min(fromPts.length, toPts.length);\n const result: Point[] = new Array(len);\n for (let i = 0; i < len; i++) {\n result[i] = lerpPoint(fromPts[i], toPts[i], t);\n }\n return result;\n}\n\n/** Apply an interpolated path to a line mark's path element. */\nfunction applyLinePath(el: SVGElement, points: Point[], interpolate?: string): void {\n const pathEl = el.querySelector('path') as SVGElement | null;\n if (!pathEl) return;\n pathEl.setAttribute('d', buildLinePath(points, interpolate));\n}\n\n/** Apply interpolated paths to an area mark's fill and stroke path elements. */\nfunction applyAreaPaths(\n el: SVGElement,\n topPoints: Point[],\n bottomPoints: Point[],\n interpolate?: string,\n hasStroke?: boolean,\n): void {\n const paths = el.querySelectorAll('path');\n // First path is the area fill\n if (paths[0]) {\n paths[0].setAttribute('d', buildAreaPath(topPoints, bottomPoints, interpolate));\n }\n // Second path (if present) is the top-line stroke\n if (hasStroke && paths[1]) {\n paths[1].setAttribute('d', buildLinePath(topPoints, interpolate));\n }\n}\n\n/** Apply the exact final path from the mark data (not from interpolated points). */\nfunction applyFinalLinePath(el: SVGElement, mark: LineMark): void {\n const pathEl = el.querySelector('path') as SVGElement | null;\n if (!pathEl || !mark.path) return;\n pathEl.setAttribute('d', mark.path);\n}\n\n/** Apply the exact final paths from the area mark data. */\nfunction applyFinalAreaPaths(el: SVGElement, mark: AreaMark): void {\n const paths = el.querySelectorAll('path');\n if (paths[0]) {\n paths[0].setAttribute('d', mark.path);\n }\n if (paths[1] && mark.topPath) {\n paths[1].setAttribute('d', mark.topPath);\n }\n}\n\n// ---------------------------------------------------------------------------\n// runTransition\n// ---------------------------------------------------------------------------\n\nexport function runTransition(args: {\n svg: SVGSVGElement;\n prevLayout: ChartLayout;\n nextLayout: ChartLayout;\n animation: ResolvedAnimation;\n onComplete: () => void;\n /** Snapshot from a cancelled in-flight transition for retargeting. */\n fromSnapshot?: GeometrySnapshot;\n}): TransitionHandle {\n const { svg, prevLayout, nextLayout, animation, onComplete, fromSnapshot } = args;\n const update = animation.update!;\n const exit = animation.exit ?? { ...EXIT_DEFAULTS };\n\n // Total timeline\n const totalMs = Math.max(update.duration, exit.duration);\n const enterDelay = 0.4 * update.duration; // enters start at 40% of update duration\n const enterDuration = update.duration - enterDelay; // remaining 60%\n\n // Find the marks container in the SVG\n const marksContainer = svg.querySelector('.oc-marks') as SVGElement | null;\n if (!marksContainer) {\n onComplete();\n return {\n cancel() {},\n get running() {\n return false;\n },\n snapshot() {\n return new Map();\n },\n };\n }\n\n // Build all tweens\n const tweens: Tween[] = [];\n const ghosts: SVGElement[] = [];\n\n // Fix gradient ghosts: ensure exiting marks with gradient fills have valid\n // gradient defs in the new SVG. Build any missing gradients into <defs>.\n const defs = svg.querySelector('defs') as SVGElement | null;\n let ghostGradientMap = new Map<string, string>();\n if (defs) {\n // Collect gradient fills from exiting marks (marks in prev but not next)\n const nextKeySet = new Set(nextLayout.marks.filter((m) => m.key).map((m) => m.key));\n const exitingMarks = prevLayout.marks.filter(\n (m) => m.key && !nextKeySet.has(m.key) && 'fill' in m,\n );\n const gradientMarks = exitingMarks.filter(\n (m) => 'fill' in m && isGradientDef((m as { fill: unknown }).fill),\n );\n if (gradientMarks.length > 0) {\n ghostGradientMap = buildGradientDefs(gradientMarks as Array<{ fill?: unknown }>, defs);\n }\n }\n\n // Determine what mark types we're dealing with\n const hasRects =\n prevLayout.marks.some((m) => m.type === 'rect') ||\n nextLayout.marks.some((m) => m.type === 'rect');\n const hasLines =\n prevLayout.marks.some((m) => m.type === 'line') ||\n nextLayout.marks.some((m) => m.type === 'line');\n const hasAreas =\n prevLayout.marks.some((m) => m.type === 'area') ||\n nextLayout.marks.some((m) => m.type === 'area');\n const hasPoints =\n prevLayout.marks.some((m) => m.type === 'point') ||\n nextLayout.marks.some((m) => m.type === 'point');\n const hasRules =\n prevLayout.marks.some((m) => m.type === 'rule') ||\n nextLayout.marks.some((m) => m.type === 'rule');\n const hasTicks =\n prevLayout.marks.some((m) => m.type === 'tick') ||\n nextLayout.marks.some((m) => m.type === 'tick');\n const hasTextMarks =\n prevLayout.marks.some((m) => m.type === 'textMark') ||\n nextLayout.marks.some((m) => m.type === 'textMark');\n\n if (hasRects) {\n buildRectTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasLines) {\n buildLineTweens(prevLayout, nextLayout, marksContainer, tweens, ghosts, fromSnapshot);\n }\n if (hasAreas) {\n buildAreaTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasPoints) {\n buildPointTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasRules) {\n buildRuleTweens(prevLayout, nextLayout, marksContainer, tweens, ghosts, fromSnapshot);\n }\n if (hasTicks) {\n buildTickTweens(prevLayout, nextLayout, marksContainer, tweens, ghosts, fromSnapshot);\n }\n if (hasTextMarks) {\n buildTextMarkTweens(prevLayout, nextLayout, marksContainer, tweens, ghosts, fromSnapshot);\n }\n\n // Axis tick/gridline transitions\n buildAxisTweens(svg, prevLayout, nextLayout, tweens, ghosts);\n\n // Mark fill/stroke (a highlight mute recolors marks that never move)\n buildColorTweens(prevLayout, nextLayout, marksContainer, tweens);\n\n // Annotations: keyed diff, so only NEW annotations fade in and surviving\n // ones hold steady instead of blinking.\n buildAnnotationTweens(svg, prevLayout, nextLayout, tweens);\n\n // Secondary element crossfade: endpoint labels and mark labels still use the\n // blanket fade (annotations were promoted to the keyed path above).\n const secondaryEls = collectSecondaryElements(svg);\n // Store original opacities so we can restore them on completion\n const secondaryOriginalOpacity = secondaryEls.map((el) => el.style.opacity ?? '');\n\n // Apply all from-states SYNCHRONOUSLY before scheduling the first rAF\n for (const tw of tweens) {\n applyTweenState(tw, 0, update, exit, enterDelay, enterDuration);\n }\n // Set secondary elements to invisible at start\n for (const el of secondaryEls) {\n el.style.opacity = '0';\n }\n\n // Animation loop state\n let rafId: number | null = null;\n let running = true;\n let startTime: number | null = null;\n let lastElapsed = 0;\n\n // Track line/area marks that need final path snapping\n const nextLineMarks = nextLayout.marks.filter((m): m is LineMark => m.type === 'line');\n const nextAreaMarks = nextLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n\n function tick(now: number): void {\n if (!running) return;\n if (startTime === null) startTime = now;\n\n const elapsed = now - startTime;\n lastElapsed = elapsed;\n const tGlobal = Math.min(elapsed / totalMs, 1);\n\n for (const tw of tweens) {\n applyTweenState(tw, elapsed, update, exit, enterDelay, enterDuration);\n }\n\n // Crossfade secondary elements: delayed 40%, over 60% of update duration\n applySecondaryOpacity(secondaryEls, elapsed, enterDelay, enterDuration);\n\n if (tGlobal >= 1) {\n finish();\n } else {\n rafId = requestAnimationFrame(tick);\n }\n }\n\n function finish(): void {\n if (!running) return;\n running = false;\n rafId = null;\n\n snapToFinal();\n removeGhosts();\n // Restore secondary element opacities to their rendered values\n for (let i = 0; i < secondaryEls.length; i++) {\n secondaryEls[i].style.opacity = secondaryOriginalOpacity[i];\n }\n onComplete();\n }\n\n function snapToFinal(): void {\n for (const tw of tweens) {\n snapTweenToFinal(tw);\n }\n // Snap line/area paths to exact final mark paths (not interpolated)\n // to ensure round-trip invariant\n for (const mark of nextLineMarks) {\n if (!mark.key) continue;\n const el = marksContainer!.querySelector(`[data-key=\"${mark.key}\"]`) as SVGElement | null;\n if (el) applyFinalLinePath(el, mark);\n }\n for (const mark of nextAreaMarks) {\n if (!mark.key) continue;\n const el = marksContainer!.querySelector(`[data-key=\"${mark.key}\"]`) as SVGElement | null;\n if (el) applyFinalAreaPaths(el, mark);\n }\n }\n\n function removeGhosts(): void {\n for (const ghost of ghosts) {\n ghost.parentNode?.removeChild(ghost);\n }\n }\n\n /** Capture the current interpolated geometry of all in-flight tweens. */\n function captureSnapshot(): GeometrySnapshot {\n const snap: GeometrySnapshot = new Map();\n const tUpdate = Math.min(lastElapsed / update.duration, 1);\n const easedUpdate = cubicOut(tUpdate);\n\n for (const tw of tweens) {\n if (tw.kind !== 'update') continue;\n const key = getKeyForTween(tw);\n if (!key) continue;\n\n switch (tw.tweenType) {\n case 'rect': {\n const g = lerpGeom(tw.from, tw.to, easedUpdate);\n snap.set(key, { type: 'rect', ...g });\n break;\n }\n case 'point': {\n const cx = tw.fromCx + (tw.toCx - tw.fromCx) * easedUpdate;\n const cy = tw.fromCy + (tw.toCy - tw.fromCy) * easedUpdate;\n const entry: SnapshotGeometry = { type: 'point', cx, cy };\n if (tw.fromR !== undefined && tw.toR !== undefined) {\n entry.r = tw.fromR + (tw.toR - tw.fromR) * easedUpdate;\n }\n snap.set(key, entry);\n break;\n }\n case 'rule':\n case 'tick': {\n snap.set(key, {\n type: tw.tweenType,\n x1: tw.fromX1 + (tw.toX1 - tw.fromX1) * easedUpdate,\n y1: tw.fromY1 + (tw.toY1 - tw.fromY1) * easedUpdate,\n x2: tw.fromX2 + (tw.toX2 - tw.fromX2) * easedUpdate,\n y2: tw.fromY2 + (tw.toY2 - tw.fromY2) * easedUpdate,\n });\n break;\n }\n case 'textMark': {\n snap.set(key, {\n type: 'textMark',\n x: tw.fromX + (tw.toX - tw.fromX) * easedUpdate,\n y: tw.fromY + (tw.toY - tw.fromY) * easedUpdate,\n });\n break;\n }\n case 'line': {\n // Freeze the current interpolated path string\n const pts = interpolatePoints(tw.fromPts, tw.toPts, easedUpdate);\n const d = buildLinePath(pts, tw.interpolate);\n snap.set(key, { type: 'line', d });\n break;\n }\n case 'area': {\n const top = interpolatePoints(tw.fromTop, tw.toTop, easedUpdate);\n const bottom = interpolatePoints(tw.fromBottom, tw.toBottom, easedUpdate);\n const d = buildAreaPath(top, bottom, tw.interpolate);\n let topD: string | undefined;\n if (tw.hasStroke) {\n topD = buildLinePath(top, tw.interpolate);\n }\n snap.set(key, { type: 'area', d, topD });\n break;\n }\n }\n }\n return snap;\n }\n\n rafId = requestAnimationFrame(tick);\n\n return {\n cancel(): void {\n if (!running) return;\n running = false;\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n snapToFinal();\n removeGhosts();\n // Restore secondary element opacities on cancel\n for (let i = 0; i < secondaryEls.length; i++) {\n secondaryEls[i].style.opacity = secondaryOriginalOpacity[i];\n }\n },\n get running() {\n return running;\n },\n snapshot(): GeometrySnapshot {\n return captureSnapshot();\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Secondary element helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Collect endpoint-label and mark-label groups for the blanket crossfade.\n *\n * Annotations used to be in here, which is why an annotation that was already\n * on screen blinked out and back in on every update: the blanket fade drives\n * every element it collects from opacity 0, with no notion of which ones are\n * actually new. They now go through `buildAnnotationTweens` instead, which\n * diffs them by key. Do not re-add them here -- the blanket fade runs after the\n * tweens and would clobber the keyed opacity.\n */\nfunction collectSecondaryElements(svg: SVGSVGElement): SVGElement[] {\n const els: SVGElement[] = [];\n const epLabels = svg.querySelector('.oc-endpoint-labels') as SVGElement | null;\n if (epLabels) els.push(epLabels);\n const markLabels = svg.querySelector('.oc-mark-labels') as SVGElement | null;\n if (markLabels) els.push(markLabels);\n return els;\n}\n\n/** Apply delayed fade-in to secondary elements during transition. */\nfunction applySecondaryOpacity(\n els: SVGElement[],\n elapsed: number,\n enterDelay: number,\n enterDuration: number,\n): void {\n if (els.length === 0) return;\n let t: number;\n if (elapsed < enterDelay) {\n t = 0;\n } else {\n t = Math.min((elapsed - enterDelay) / enterDuration, 1);\n }\n const opacity = String(cubicOut(t));\n for (const el of els) {\n el.style.opacity = opacity;\n }\n}\n\n/** Get the data-key for a tween's element (used for snapshot keying). */\nfunction getKeyForTween(tw: Tween): string | null {\n if ('ghost' in tw && tw.ghost) return null; // ghosts don't carry keys\n return tw.el.getAttribute('data-key');\n}\n\n// ---------------------------------------------------------------------------\n// Tween state application (shared across all tween types)\n// ---------------------------------------------------------------------------\n\nfunction resolveLineElement(el: SVGElement): SVGElement {\n return el.tagName === 'line' ? el : ((el.querySelector('line') as SVGElement) ?? el);\n}\n\nfunction applyTweenState(\n tw: Tween,\n elapsed: number,\n update: { duration: number },\n exit: { duration: number },\n enterDelay: number,\n enterDuration: number,\n): void {\n let tLocal: number;\n\n if (tw.kind === 'exit') {\n tLocal = Math.min(elapsed / exit.duration, 1);\n } else if (tw.kind === 'enter') {\n if (elapsed < enterDelay) {\n tLocal = 0;\n } else {\n tLocal = Math.min((elapsed - enterDelay) / enterDuration, 1);\n }\n } else {\n tLocal = Math.min(elapsed / update.duration, 1);\n }\n\n const eased = cubicOut(tLocal);\n\n switch (tw.tweenType) {\n case 'rect': {\n const geom = lerpGeom(tw.from, tw.to, eased);\n applyGeomToElement(tw.el, geom, tw.mark);\n break;\n }\n case 'line': {\n const pts = interpolatePoints(tw.fromPts, tw.toPts, eased);\n applyLinePath(tw.el, pts, tw.interpolate);\n break;\n }\n case 'area': {\n const top = interpolatePoints(tw.fromTop, tw.toTop, eased);\n const bottom = interpolatePoints(tw.fromBottom, tw.toBottom, eased);\n applyAreaPaths(tw.el, top, bottom, tw.interpolate, tw.hasStroke);\n break;\n }\n case 'point': {\n const cx = tw.fromCx + (tw.toCx - tw.fromCx) * eased;\n const cy = tw.fromCy + (tw.toCy - tw.fromCy) * eased;\n tw.el.setAttribute('cx', String(cx));\n tw.el.setAttribute('cy', String(cy));\n if (tw.fromR !== undefined && tw.toR !== undefined) {\n const r = tw.fromR + (tw.toR - tw.fromR) * eased;\n tw.el.setAttribute('r', String(r));\n }\n break;\n }\n case 'rule':\n case 'tick': {\n const lineEl = resolveLineElement(tw.el);\n lineEl.setAttribute('x1', String(tw.fromX1 + (tw.toX1 - tw.fromX1) * eased));\n lineEl.setAttribute('y1', String(tw.fromY1 + (tw.toY1 - tw.fromY1) * eased));\n lineEl.setAttribute('x2', String(tw.fromX2 + (tw.toX2 - tw.fromX2) * eased));\n lineEl.setAttribute('y2', String(tw.fromY2 + (tw.toY2 - tw.fromY2) * eased));\n break;\n }\n case 'textMark': {\n const x = tw.fromX + (tw.toX - tw.fromX) * eased;\n const y = tw.fromY + (tw.toY - tw.fromY) * eased;\n tw.el.setAttribute('x', String(x));\n tw.el.setAttribute('y', String(y));\n break;\n }\n case 'axisTick': {\n if (tw.crossfade) {\n // Crossfade: only tween opacity, don't move\n break;\n }\n const pos = tw.fromPos + (tw.toPos - tw.fromPos) * eased;\n if (tw.posAttr === 'x') {\n tw.el.setAttribute('x', String(pos));\n } else {\n tw.el.setAttribute('y', String(pos));\n }\n break;\n }\n case 'gridline': {\n const pos = tw.fromPos + (tw.toPos - tw.fromPos) * eased;\n if (tw.orientation === 'y') {\n // Horizontal gridline: y1 and y2 share the same position\n tw.el.setAttribute('y1', String(pos));\n tw.el.setAttribute('y2', String(pos));\n } else {\n // Vertical gridline: x1 and x2 share the same position\n tw.el.setAttribute('x1', String(pos));\n tw.el.setAttribute('x2', String(pos));\n }\n break;\n }\n case 'color': {\n tw.el.setAttribute(tw.attr, interpolateRgb(tw.from, tw.to)(eased));\n break;\n }\n case 'annotation': {\n // Ease the offset back to zero: the group is already rendered at its\n // final position, so (0,0) is the destination. SVG transform attribute,\n // not CSS -- CSS transform would replace any SVG transform attribute\n // (see .claude/rules/svg-animation.md), and this composes cleanly since\n // the annotations renderer sets none.\n const dx = tw.fromDx * (1 - eased);\n const dy = tw.fromDy * (1 - eased);\n if (dx !== 0 || dy !== 0) {\n tw.el.setAttribute('transform', `translate(${dx} ${dy})`);\n }\n break;\n }\n }\n\n // Apply opacity interpolation if defined\n if (tw.fromOpacity !== undefined && tw.toOpacity !== undefined) {\n const opacity = tw.fromOpacity + (tw.toOpacity - tw.fromOpacity) * eased;\n tw.el.style.opacity = String(opacity);\n }\n}\n\nfunction snapTweenToFinal(tw: Tween): void {\n switch (tw.tweenType) {\n case 'rect':\n applyGeomToElement(tw.el, tw.to, tw.mark);\n break;\n case 'line':\n applyLinePath(tw.el, tw.toPts, tw.interpolate);\n break;\n case 'area':\n applyAreaPaths(tw.el, tw.toTop, tw.toBottom, tw.interpolate, tw.hasStroke);\n break;\n case 'point':\n tw.el.setAttribute('cx', String(tw.toCx));\n tw.el.setAttribute('cy', String(tw.toCy));\n if (tw.toR !== undefined) {\n tw.el.setAttribute('r', String(tw.toR));\n }\n break;\n case 'rule':\n case 'tick': {\n const lineEl = resolveLineElement(tw.el);\n lineEl.setAttribute('x1', String(tw.toX1));\n lineEl.setAttribute('y1', String(tw.toY1));\n lineEl.setAttribute('x2', String(tw.toX2));\n lineEl.setAttribute('y2', String(tw.toY2));\n break;\n }\n case 'textMark':\n tw.el.setAttribute('x', String(tw.toX));\n tw.el.setAttribute('y', String(tw.toY));\n break;\n case 'axisTick':\n if (!tw.crossfade) {\n if (tw.posAttr === 'x') {\n tw.el.setAttribute('x', String(tw.toPos));\n } else {\n tw.el.setAttribute('y', String(tw.toPos));\n }\n }\n break;\n case 'gridline':\n if (tw.orientation === 'y') {\n tw.el.setAttribute('y1', String(tw.toPos));\n tw.el.setAttribute('y2', String(tw.toPos));\n } else {\n tw.el.setAttribute('x1', String(tw.toPos));\n tw.el.setAttribute('x2', String(tw.toPos));\n }\n break;\n case 'color':\n tw.el.setAttribute(tw.attr, tw.to);\n break;\n case 'annotation':\n // The group is rendered at its final position; drop the offset entirely\n // rather than writing translate(0 0), so the DOM returns to the exact\n // shape render() produced.\n tw.el.removeAttribute('transform');\n break;\n }\n\n if (tw.toOpacity !== undefined) {\n tw.el.style.opacity = String(tw.toOpacity);\n }\n\n // Restore suppressed-point opacity\n if (tw.tweenType === 'point' && tw.suppressedOpacity !== undefined) {\n tw.el.setAttribute('opacity', tw.suppressedOpacity);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Gradient ghost helper\n// ---------------------------------------------------------------------------\n\n/**\n * For marks with gradient fills, resolve the gradient to a url(#id) reference\n * using the ghost gradient map. This ensures ghosts reference valid gradient\n * IDs in the new SVG's <defs>.\n */\nfunction resolveGhostGradientFill<T extends { fill?: string | GradientDef }>(\n mark: T,\n ghostGradientMap: Map<string, string>,\n): T {\n if (!mark.fill || typeof mark.fill === 'string' || ghostGradientMap.size === 0) return mark;\n const resolved = resolveMarkFill(mark.fill, ghostGradientMap);\n return { ...mark, fill: resolved };\n}\n\n// ---------------------------------------------------------------------------\n// Rect tween building (extracted from original runTransition)\n// ---------------------------------------------------------------------------\n\nfunction buildRectTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevRects = prevLayout.marks.filter((m): m is RectMark => m.type === 'rect');\n const nextRects = nextLayout.marks.filter((m): m is RectMark => m.type === 'rect');\n\n const prevByKey = new Map<string, RectMark>();\n for (const m of prevRects) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, RectMark>();\n for (const m of nextRects) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n // Retarget: use snapshot geometry if available (interrupted transition)\n let fromGeom = geomFromMark(prev);\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'rect') {\n fromGeom = { x: snap.x, y: snap.y, width: snap.width, height: snap.height };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'update',\n el,\n from: fromGeom,\n to: geomFromMark(next),\n mark: next,\n });\n }\n\n // Entered\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n let fromGeom: RectGeom;\n if (next.orient === 'horizontal') {\n fromGeom = { x: next.x, y: next.y, width: 0, height: next.height };\n } else {\n fromGeom = { x: next.x, y: next.y + next.height, width: next.width, height: 0 };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'enter',\n el,\n from: fromGeom,\n to: geomFromMark(next),\n mark: next,\n });\n }\n\n // Exited\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n // Resolve gradient fill for ghost if needed\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n let toGeom: RectGeom;\n if (prev.orient === 'horizontal') {\n toGeom = { x: prev.x, y: prev.y, width: 0, height: prev.height };\n } else {\n toGeom = { x: prev.x, y: prev.y + prev.height, width: prev.width, height: 0 };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'exit',\n el: ghost,\n from: geomFromMark(prev),\n to: toGeom,\n mark: prev,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Line tween building\n// ---------------------------------------------------------------------------\n\nfunction buildLineTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevLines = prevLayout.marks.filter((m): m is LineMark => m.type === 'line');\n const nextLines = nextLayout.marks.filter((m): m is LineMark => m.type === 'line');\n\n const prevByKey = new Map<string, LineMark>();\n for (const m of prevLines) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, LineMark>();\n for (const m of nextLines) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated series\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n // If interrupted mid-morph, freeze the current path and crossfade\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'line') {\n // Create ghost carrying the frozen mid-morph path\n const ghost = el.cloneNode(true) as SVGElement;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n const ghostPath = ghost.querySelector('path');\n if (ghostPath) ghostPath.setAttribute('d', snap.d);\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: next.points, // placeholder, not used for path\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n\n // Fade in the new final path\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n const prevPKs = prev.pointKeys ?? prev.points.map((_, i) => `${i}`);\n const nextPKs = next.pointKeys ?? next.points.map((_, i) => `${i}`);\n\n // Check if zero survivors (fully replaced dataset)\n const prevKeySet = new Set(prevPKs);\n const hasSurvivors = nextPKs.some((k) => prevKeySet.has(k));\n\n if (!hasSurvivors) {\n // Crossfade: fade out old (ghost), fade in new\n const ghost = renderSingleMark(prev, 0);\n if (ghost) {\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: prev.points,\n toPts: prev.points,\n finalPoints: prev.points,\n interpolate: prev.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n // Fade in the new one\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n } else {\n // Normal morph with point matching\n const [fromPts, toPts] = normalizePointArrays(prev.points, next.points, prevPKs, nextPKs);\n\n tweens.push({\n tweenType: 'line',\n kind: 'update',\n el,\n fromPts,\n toPts,\n finalPoints: next.points,\n interpolate: next.interpolate,\n });\n }\n }\n\n // Entering series (only in next)\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting series (only in prev)\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: prev.points,\n toPts: prev.points,\n finalPoints: prev.points,\n interpolate: prev.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Area tween building\n// ---------------------------------------------------------------------------\n\nfunction buildAreaTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevAreas = prevLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n const nextAreas = nextLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n\n const prevByKey = new Map<string, AreaMark>();\n for (const m of prevAreas) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, AreaMark>();\n for (const m of nextAreas) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated series\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n // If interrupted mid-morph, freeze and crossfade\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'area') {\n const ghost = el.cloneNode(true) as SVGElement;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n const ghostPaths = ghost.querySelectorAll('path');\n if (ghostPaths[0]) ghostPaths[0].setAttribute('d', snap.d);\n if (ghostPaths[1] && snap.topD) ghostPaths[1].setAttribute('d', snap.topD);\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n const prevPKs = prev.pointKeys ?? prev.topPoints.map((_, i) => `${i}`);\n const nextPKs = next.pointKeys ?? next.topPoints.map((_, i) => `${i}`);\n\n const prevKeySet = new Set(prevPKs);\n const hasSurvivors = nextPKs.some((k) => prevKeySet.has(k));\n\n if (!hasSurvivors) {\n // Crossfade\n const ghost = renderSingleMark(prev, 0);\n if (ghost) {\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: prev.topPoints,\n toTop: prev.topPoints,\n fromBottom: prev.bottomPoints,\n toBottom: prev.bottomPoints,\n finalTopPoints: prev.topPoints,\n finalBottomPoints: prev.bottomPoints,\n interpolate: prev.interpolate,\n hasStroke: !!prev.stroke && !!prev.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n } else {\n // Morph\n const [fromTop, toTop] = normalizePointArrays(\n prev.topPoints,\n next.topPoints,\n prevPKs,\n nextPKs,\n );\n const [fromBottom, toBottom] = normalizePointArrays(\n prev.bottomPoints,\n next.bottomPoints,\n prevPKs,\n nextPKs,\n );\n\n tweens.push({\n tweenType: 'area',\n kind: 'update',\n el,\n fromTop,\n toTop,\n fromBottom,\n toBottom,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n });\n }\n }\n\n // Entering series\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(`[data-key=\"${key}\"]`) as SVGElement | null;\n if (!el) continue;\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting series\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: prev.topPoints,\n toTop: prev.topPoints,\n fromBottom: prev.bottomPoints,\n toBottom: prev.bottomPoints,\n finalTopPoints: prev.topPoints,\n finalBottomPoints: prev.bottomPoints,\n interpolate: prev.interpolate,\n hasStroke: !!prev.stroke && !!prev.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Point tween building (scatter/dot/line overlay circle marks)\n// ---------------------------------------------------------------------------\n\nfunction buildPointTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevPoints = prevLayout.marks.filter((m): m is PointMark => m.type === 'point');\n const nextPoints = nextLayout.marks.filter((m): m is PointMark => m.type === 'point');\n\n const prevByKey = new Map<string, PointMark>();\n for (const m of prevPoints) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, PointMark>();\n for (const m of nextPoints) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated points: tween cx/cy/r\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(\n `circle.oc-mark-point[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n\n // Read the element's current opacity attribute (NOT style.opacity)\n // to detect suppressed points (opacity=\"0\" set by renderer for endpoint markers)\n const renderedOpacity = el.getAttribute('opacity');\n const isSuppressed = renderedOpacity === '0';\n\n // Retarget from snapshot if interrupted\n let fromCx = prev.cx;\n let fromCy = prev.cy;\n let fromR = prev.r !== next.r ? prev.r : undefined;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'point') {\n fromCx = snap.cx;\n fromCy = snap.cy;\n if (snap.r !== undefined && snap.r !== next.r) {\n fromR = snap.r;\n }\n }\n\n tweens.push({\n tweenType: 'point',\n kind: 'update',\n el,\n fromCx,\n fromCy,\n toCx: next.cx,\n toCy: next.cy,\n fromR: fromR,\n toR: fromR !== undefined ? next.r : undefined,\n // Do NOT tween opacity for updated points - preserve renderer state\n suppressedOpacity: isSuppressed ? '0' : undefined,\n });\n }\n\n // Entering points: fade in\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(\n `circle.oc-mark-point[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n\n // Read rendered opacity for the final value\n const renderedOpacity = el.getAttribute('opacity');\n const targetOpacity = renderedOpacity != null ? Number(renderedOpacity) : 1;\n\n tweens.push({\n tweenType: 'point',\n kind: 'enter',\n el,\n fromCx: next.cx,\n fromCy: next.cy,\n toCx: next.cx,\n toCy: next.cy,\n fromOpacity: 0,\n toOpacity: targetOpacity,\n suppressedOpacity: renderedOpacity === '0' ? '0' : undefined,\n });\n }\n\n // Exiting points: ghost fade out\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'point',\n kind: 'exit',\n el: ghost,\n fromCx: prev.cx,\n fromCy: prev.cy,\n toCx: prev.cx,\n toCy: prev.cy,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rule tween building\n// ---------------------------------------------------------------------------\n\nfunction buildRuleTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevRules = prevLayout.marks.filter((m): m is RuleMarkLayout => m.type === 'rule');\n const nextRules = nextLayout.marks.filter((m): m is RuleMarkLayout => m.type === 'rule');\n\n const prevByKey = new Map<string, RuleMarkLayout>();\n for (const m of prevRules) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, RuleMarkLayout>();\n for (const m of nextRules) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-rule[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n\n let fromX1 = prev.x1;\n let fromY1 = prev.y1;\n let fromX2 = prev.x2;\n let fromY2 = prev.y2;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'rule') {\n fromX1 = snap.x1;\n fromY1 = snap.y1;\n fromX2 = snap.x2;\n fromY2 = snap.y2;\n }\n\n tweens.push({\n tweenType: 'rule',\n kind: 'update',\n el,\n fromX1,\n fromY1,\n fromX2,\n fromY2,\n toX1: next.x1,\n toY1: next.y1,\n toX2: next.x2,\n toY2: next.y2,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-rule[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n tweens.push({\n tweenType: 'rule',\n kind: 'enter',\n el,\n fromX1: next.x1,\n fromY1: next.y1,\n fromX2: next.x2,\n fromY2: next.y2,\n toX1: next.x1,\n toY1: next.y1,\n toX2: next.x2,\n toY2: next.y2,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n tweens.push({\n tweenType: 'rule',\n kind: 'exit',\n el: ghost,\n fromX1: prev.x1,\n fromY1: prev.y1,\n fromX2: prev.x2,\n fromY2: prev.y2,\n toX1: prev.x1,\n toY1: prev.y1,\n toX2: prev.x2,\n toY2: prev.y2,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tick tween building\n// ---------------------------------------------------------------------------\n\nfunction buildTickTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevTicks = prevLayout.marks.filter((m): m is TickMarkLayout => m.type === 'tick');\n const nextTicks = nextLayout.marks.filter((m): m is TickMarkLayout => m.type === 'tick');\n\n const prevByKey = new Map<string, TickMarkLayout>();\n for (const m of prevTicks) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, TickMarkLayout>();\n for (const m of nextTicks) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n function tickEndpoints(t: TickMarkLayout) {\n const half = t.length / 2;\n if (t.orient === 'vertical') {\n return { x1: t.x, y1: t.y - half, x2: t.x, y2: t.y + half };\n }\n return { x1: t.x - half, y1: t.y, x2: t.x + half, y2: t.y };\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-tick[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n let pEnd = tickEndpoints(prev);\n const nEnd = tickEndpoints(next);\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'tick') {\n pEnd = { x1: snap.x1, y1: snap.y1, x2: snap.x2, y2: snap.y2 };\n }\n tweens.push({\n tweenType: 'tick',\n kind: 'update',\n el,\n fromX1: pEnd.x1,\n fromY1: pEnd.y1,\n fromX2: pEnd.x2,\n fromY2: pEnd.y2,\n toX1: nEnd.x1,\n toY1: nEnd.y1,\n toX2: nEnd.x2,\n toY2: nEnd.y2,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-tick[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n const nEnd = tickEndpoints(next);\n tweens.push({\n tweenType: 'tick',\n kind: 'enter',\n el,\n fromX1: nEnd.x1,\n fromY1: nEnd.y1,\n fromX2: nEnd.x2,\n fromY2: nEnd.y2,\n toX1: nEnd.x1,\n toY1: nEnd.y1,\n toX2: nEnd.x2,\n toY2: nEnd.y2,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n const pEnd = tickEndpoints(prev);\n tweens.push({\n tweenType: 'tick',\n kind: 'exit',\n el: ghost,\n fromX1: pEnd.x1,\n fromY1: pEnd.y1,\n fromX2: pEnd.x2,\n fromY2: pEnd.y2,\n toX1: pEnd.x1,\n toY1: pEnd.y1,\n toX2: pEnd.x2,\n toY2: pEnd.y2,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Text mark tween building\n// ---------------------------------------------------------------------------\n\nfunction buildTextMarkTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevTexts = prevLayout.marks.filter((m): m is TextMarkLayout => m.type === 'textMark');\n const nextTexts = nextLayout.marks.filter((m): m is TextMarkLayout => m.type === 'textMark');\n\n const prevByKey = new Map<string, TextMarkLayout>();\n for (const m of prevTexts) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, TextMarkLayout>();\n for (const m of nextTexts) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-text[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n\n let fromX = prev.x;\n let fromY = prev.y;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'textMark') {\n fromX = snap.x;\n fromY = snap.y;\n }\n\n tweens.push({\n tweenType: 'textMark',\n kind: 'update',\n el,\n fromX,\n fromY,\n toX: next.x,\n toY: next.y,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = marksContainer.querySelector(\n `.oc-mark-text[data-key=\"${key}\"]`,\n ) as SVGElement | null;\n if (!el) continue;\n tweens.push({\n tweenType: 'textMark',\n kind: 'enter',\n el,\n fromX: next.x,\n fromY: next.y,\n toX: next.x,\n toY: next.y,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n tweens.push({\n tweenType: 'textMark',\n kind: 'exit',\n el: ghost,\n fromX: prev.x,\n fromY: prev.y,\n toX: prev.x,\n toY: prev.y,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Color tween building\n// ---------------------------------------------------------------------------\n\n/**\n * The child element a mark's `fill` or `stroke` is actually written to.\n *\n * Resolved per attribute, not once per mark: an area is two stacked paths, and\n * they do not carry the same channels. `renderAreaMark` appends the closed fill\n * shape first (`stroke: 'none'`) and the `.oc-area-top` line second -- that\n * second path is the only thing carrying the stroke, and it traces the data\n * points alone rather than the baseline. A blanket `querySelector` returns the\n * *first* match, so writing a stroke through it would paint an outline around\n * the whole closed area (baseline included) and `snapTweenToFinal` would leave\n * it there for good.\n */\nfunction markShapeElement(el: SVGElement, attr: 'fill' | 'stroke'): SVGElement {\n if (el.tagName === 'circle' || el.tagName === 'rect' || el.tagName === 'path') return el;\n if (attr === 'stroke') {\n const areaTop = el.querySelector('.oc-area-top') as SVGElement | null;\n if (areaTop) return areaTop;\n }\n return (el.querySelector('rect, path, circle, line') as SVGElement | null) ?? el;\n}\n\n/** Gradient fills are `url(#id)` refs and cannot be interpolated numerically. */\nfunction isInterpolableColor(v: unknown): v is string {\n return typeof v === 'string' && v !== '' && v !== 'none' && !v.startsWith('url(');\n}\n\n/**\n * Build fill/stroke tweens for marks present in both layouts whose color moved.\n *\n * Mark-type agnostic on purpose: every mark carries `fill`/`stroke` resolved by\n * the compiler, so matching on `key` and diffing the two strings covers rects,\n * lines, areas and points in one pass. Marks whose color did not change emit no\n * tween, so the common data-update case costs nothing.\n */\nfunction buildColorTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n tweens: Tween[],\n): void {\n type Colored = { key?: string; fill?: unknown; stroke?: unknown };\n const prevByKey = new Map<string, Colored>();\n for (const m of prevLayout.marks as Colored[]) {\n if (m.key) prevByKey.set(m.key, m);\n }\n\n for (const next of nextLayout.marks as Colored[]) {\n if (!next.key) continue;\n const prev = prevByKey.get(next.key);\n if (!prev) continue;\n\n const group = marksContainer.querySelector(`[data-key=\"${next.key}\"]`) as SVGElement | null;\n if (!group) continue;\n\n for (const attr of ['fill', 'stroke'] as const) {\n const from = prev[attr];\n const to = next[attr];\n if (from === to) continue;\n if (!isInterpolableColor(from) || !isInterpolableColor(to)) continue;\n tweens.push({\n tweenType: 'color',\n kind: 'update',\n el: markShapeElement(group, attr),\n attr,\n from,\n to,\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Annotation tween building\n// ---------------------------------------------------------------------------\n\n/**\n * Build keyed enter/update/exit tweens for annotations.\n *\n * Follows the `buildAxisTweens` pattern rather than the mark builders': the\n * annotation group is a SIBLING of the clipped marks group, so it must be\n * queried from the `svg` root. A `marksContainer.querySelector` would never\n * find it.\n *\n * Surviving annotations tween from their old position to their new one via a\n * transform offset (the alternative -- re-resolving label x/y, connector path,\n * dot, subtitle and background rect individually -- is a lot of surface for no\n * extra fidelity). Entering ones fade in. See the note at the bottom for why\n * exiting ones do not fade out.\n */\nfunction buildAnnotationTweens(\n svg: SVGSVGElement,\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n tweens: Tween[],\n): void {\n const prev = prevLayout.annotations ?? [];\n const next = nextLayout.annotations ?? [];\n if (prev.length === 0 && next.length === 0) return;\n\n const container = svg.querySelector('.oc-annotations');\n if (!container) return;\n\n const prevByKey = new Map(keyAnnotations(prev).map((k, i) => [k, prev[i]]));\n const nextKeys = keyAnnotations(next);\n\n // The rendered DOM matches nextLayout, so index i is nextKeys[i].\n const els = container.querySelectorAll('.oc-annotation');\n\n for (let i = 0; i < next.length; i++) {\n const el = els[i] as SVGElement | undefined;\n if (!el) continue;\n const before = prevByKey.get(nextKeys[i]);\n\n if (!before) {\n // Entering: fade in on the annotation cadence.\n tweens.push({\n tweenType: 'annotation',\n kind: 'enter',\n el,\n fromDx: 0,\n fromDy: 0,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n // Surviving: hold at full opacity, slide from the old position if it moved.\n const dx = (before.label?.x ?? 0) - (next[i].label?.x ?? 0);\n const dy = (before.label?.y ?? 0) - (next[i].label?.y ?? 0);\n if (dx === 0 && dy === 0) continue;\n tweens.push({\n tweenType: 'annotation',\n kind: 'update',\n el,\n fromDx: dx,\n fromDy: dy,\n });\n }\n\n // Exiting annotations are NOT ghosted. render() has already torn down the old\n // SVG, so the removed node is gone and there is nothing left to clone -- the\n // elements still in the DOM belong to nextLayout, and cloning one by the old\n // index would ghost an annotation that actually survived. Building a faithful\n // ghost would mean re-rendering the annotation from prevLayout (the marks\n // path can do this via `renderSingleMark`; annotations have no such entry\n // point that takes a single ResolvedAnnotation).\n //\n // So a removed annotation disappears immediately. That matches the behavior\n // before this change and is not what the blink bug was about; adding a real\n // exit fade means exposing a single-annotation renderer first.\n}\n\n// ---------------------------------------------------------------------------\n// Axis tick and gridline tween building\n// ---------------------------------------------------------------------------\n\n/**\n * Build tweens for axis tick labels and gridlines across both x and y axes.\n * Matches ticks by `data-tick-key` (stamped at render time).\n */\nfunction buildAxisTweens(\n svg: SVGSVGElement,\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n tweens: Tween[],\n ghosts: SVGElement[],\n): void {\n // Process each axis orientation\n buildSingleAxisTweens(svg, prevLayout.axes.x, nextLayout.axes.x, 'x', nextLayout, tweens, ghosts);\n buildSingleAxisTweens(svg, prevLayout.axes.y, nextLayout.axes.y, 'y', nextLayout, tweens, ghosts);\n}\n\nfunction buildSingleAxisTweens(\n svg: SVGSVGElement,\n prevAxis: AxisLayout | undefined,\n nextAxis: AxisLayout | undefined,\n orientation: 'x' | 'y',\n layout: ChartLayout,\n tweens: Tween[],\n ghosts: SVGElement[],\n): void {\n if (!prevAxis || !nextAxis) return;\n\n const axisClass = `oc-axis-${orientation}`;\n const axisGroup = svg.querySelector(`.${axisClass}`) as SVGElement | null;\n if (!axisGroup) return;\n\n const isRotated = !!(nextAxis.tickAngle && Math.abs(nextAxis.tickAngle) > 10);\n\n // Build tick value -> position maps from layouts (NOT from DOM)\n const prevTickMap = new Map<string, number>();\n for (const tick of prevAxis.ticks) {\n prevTickMap.set(serializeKeyValue(tick.value), tick.position);\n }\n const nextTickMap = new Map<string, number>();\n for (const tick of nextAxis.ticks) {\n nextTickMap.set(serializeKeyValue(tick.value), tick.position);\n }\n\n // Position attribute: 'x' for x-axis tick labels, 'y' for y-axis tick labels\n const posAttr = orientation === 'x' ? 'x' : 'y';\n\n // Tick labels\n const tickLabels = axisGroup.querySelectorAll('.oc-axis-tick[data-tick-key]');\n const matchedNextKeys = new Set<string>();\n\n for (const labelEl of tickLabels) {\n const key = labelEl.getAttribute('data-tick-key');\n if (!key) continue;\n\n const nextPos = nextTickMap.get(key);\n const prevPos = prevTickMap.get(key);\n\n if (prevPos !== undefined && nextPos !== undefined) {\n // Updated tick: slide to new position\n matchedNextKeys.add(key);\n tweens.push({\n tweenType: 'axisTick',\n kind: 'update',\n el: labelEl as SVGElement,\n posAttr,\n fromPos: prevPos,\n toPos: nextPos,\n crossfade: isRotated,\n });\n } else if (prevPos === undefined && nextPos !== undefined) {\n // Entering tick: fade in\n matchedNextKeys.add(key);\n tweens.push({\n tweenType: 'axisTick',\n kind: 'enter',\n el: labelEl as SVGElement,\n posAttr,\n fromPos: nextPos,\n toPos: nextPos,\n crossfade: false,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n // Exiting ticks are handled below (they won't be in the new SVG's DOM,\n // so we clone from the prev state)\n }\n\n // Exiting tick labels: create ghost elements\n for (const [key, prevPos] of prevTickMap) {\n if (nextTickMap.has(key)) continue;\n // Find the tick label in the rendered SVG by data-tick-key\n // It won't be there since the SVG was already re-rendered from nextLayout,\n // so we need to create a ghost text element\n const prevTick = prevAxis.ticks.find((t) => serializeKeyValue(t.value) === key);\n if (!prevTick) continue;\n\n const ghost = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n ghost.setAttribute('class', 'oc-axis-tick oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.textContent = prevTick.label;\n // Copy positioning from prevAxis ticks\n const area = layout.area;\n if (orientation === 'x') {\n ghost.setAttribute('x', String(prevPos));\n const xLabelPad = nextAxis.labelPadding ?? layout.theme.spacing.xAxisLabelPadding;\n const fontSize = nextAxis.tickLabelStyle.fontSize;\n ghost.setAttribute('y', String(area.y + area.height + xLabelPad + fontSize * 0.8));\n ghost.setAttribute('text-anchor', 'middle');\n } else {\n const TICK_LABEL_OFFSET = 8;\n ghost.setAttribute('x', String(area.x - TICK_LABEL_OFFSET));\n ghost.setAttribute('y', String(prevPos));\n ghost.setAttribute('text-anchor', 'end');\n ghost.setAttribute('dominant-baseline', 'central');\n }\n axisGroup.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'axisTick',\n kind: 'exit',\n el: ghost,\n posAttr,\n fromPos: prevPos,\n toPos: prevPos,\n crossfade: false,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n // Gridlines\n const prevGridMap = new Map<string, number>();\n for (const gridline of prevAxis.gridlines) {\n // Gridlines share positions with their axis ticks\n prevGridMap.set(String(gridline.position), gridline.position);\n }\n // Build a value->position map for gridlines by matching tick values\n const prevGridByValue = new Map<string, number>();\n for (const tick of prevAxis.ticks) {\n const key = serializeKeyValue(tick.value);\n // Find matching gridline at same position\n const matchingGridline = prevAxis.gridlines.find((g) => g.position === tick.position);\n if (matchingGridline) {\n prevGridByValue.set(key, matchingGridline.position);\n }\n }\n const nextGridByValue = new Map<string, number>();\n for (const tick of nextAxis.ticks) {\n const key = serializeKeyValue(tick.value);\n const matchingGridline = nextAxis.gridlines.find((g) => g.position === tick.position);\n if (matchingGridline) {\n nextGridByValue.set(key, matchingGridline.position);\n }\n }\n\n const gridlines = axisGroup.querySelectorAll('.oc-gridline[data-tick-key]');\n const matchedGridKeys = new Set<string>();\n\n for (const glEl of gridlines) {\n const key = glEl.getAttribute('data-tick-key');\n if (!key) continue;\n\n const nextPos = nextGridByValue.get(key);\n const prevPos = prevGridByValue.get(key);\n\n if (prevPos !== undefined && nextPos !== undefined) {\n matchedGridKeys.add(key);\n tweens.push({\n tweenType: 'gridline',\n kind: 'update',\n el: glEl as SVGElement,\n orientation,\n fromPos: prevPos,\n toPos: nextPos,\n });\n } else if (prevPos === undefined && nextPos !== undefined) {\n matchedGridKeys.add(key);\n tweens.push({\n tweenType: 'gridline',\n kind: 'enter',\n el: glEl as SVGElement,\n orientation,\n fromPos: nextPos,\n toPos: nextPos,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n }\n\n // Exiting gridlines\n for (const [key, prevPos] of prevGridByValue) {\n if (nextGridByValue.has(key)) continue;\n\n const ghost = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n ghost.setAttribute('class', 'oc-gridline oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n if (orientation === 'y') {\n // Horizontal gridline at y=prevPos\n const area = layout.area;\n ghost.setAttribute('x1', String(area.x));\n ghost.setAttribute('y1', String(prevPos));\n ghost.setAttribute('x2', String(area.x + area.width));\n ghost.setAttribute('y2', String(prevPos));\n } else {\n // Vertical gridline at x=prevPos\n const area = layout.area;\n ghost.setAttribute('x1', String(prevPos));\n ghost.setAttribute('y1', String(area.y));\n ghost.setAttribute('x2', String(prevPos));\n ghost.setAttribute('y2', String(area.y + area.height));\n }\n axisGroup.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'gridline',\n kind: 'exit',\n el: ghost,\n orientation,\n fromPos: prevPos,\n toPos: prevPos,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA6CA,SAAS,iBAAiB,KAAoD;AAC5E,QAAM,IAAI,WAAW,IAAI,aAAa,OAAO,KAAK,EAAE;AACpD,QAAM,IAAI,WAAW,IAAI,aAAa,QAAQ,KAAK,EAAE;AACrD,MAAI,KAAK,EAAG,QAAO,EAAE,OAAO,GAAG,QAAQ,EAAE;AAEzC,QAAM,KAAK,IAAI,aAAa,SAAS;AACrC,MAAI,IAAI;AACN,UAAM,QAAQ,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM;AAC3C,QAAI,MAAM,UAAU,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC,GAAG;AAC7C,aAAO,EAAE,OAAO,MAAM,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,KAAK,QAAQ,IAAI;AACnC;AAUA,SAAS,oBAAoB,WAAmB,OAAe,QAAwB;AAErF,MAAI,wBAAwB,KAAK,SAAS,EAAG,QAAO;AAEpD,SAAO,UAAU,QAAQ,WAAW,aAAa,KAAK,aAAa,MAAM,GAAG;AAC9E;AASA,SAAS,iBAAiB,YAAkD;AAC1E,QAAM,QAAQ,oBAAI,IAAyB;AAC3C,QAAM,eAAe,WAAW,iBAAiB,MAAM;AAEvD,aAAW,MAAM,cAAc;AAC7B,UAAM,SAAS,GAAG,aAAa,aAAa;AAC5C,UAAM,SAAS,GAAG,aAAa,aAAa,KAAK;AACjD,QAAI,QAAQ;AAEV,YAAM,UAAU,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,SAAS,EAAE;AAC/D,UAAI,CAAC,MAAM,IAAI,OAAO,EAAG,OAAM,IAAI,SAAS,oBAAI,IAAI,CAAC;AACrD,YAAM,IAAI,OAAO,EAAG,IAAI,OAAO,MAAM,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,kBACP,WACuF;AACvF,QAAM,UAMD,CAAC;AAEN,MAAI;AACF,eAAW,SAAS,SAAS,aAAa;AACxC,UAAI;AACJ,UAAI;AACF,gBAAQ,MAAM;AAAA,MAChB,QAAQ;AAEN;AAAA,MACF;AAEA,iBAAW,QAAQ,OAAO;AACxB,YAAI,EAAE,gBAAgB,iBAAkB;AAExC,cAAM,YAAY,KAAK,MAAM,iBAAiB,aAAa,EAAE,QAAQ,SAAS,EAAE,EAAE,KAAK;AACvF,cAAM,SAAS,KAAK,MAAM,iBAAiB,aAAa,KAAK;AAC7D,cAAM,QAAQ,KAAK,MAAM,iBAAiB,YAAY,KAAK;AAC3D,cAAM,MAAM,KAAK,MAAM,iBAAiB,KAAK;AAE7C,cAAM,UAAU,UAAU,IAAI,SAAS;AACvC,YAAI,CAAC,QAAS;AAGd,cAAM,cAAc,QAAQ,IAAI,MAAM,KAAK,OAAO,SAAS,GAAG;AAC9D,YAAI,CAAC,YAAa;AAGlB,cAAM,aAAa,IAAI,MAAM,2CAA2C;AACxE,YAAI,YAAY;AACd,kBAAQ,KAAK;AAAA,YACX,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA,KAAK,WAAW,CAAC;AAAA,YACjB,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAe,mBACb,WACyB;AACzB,QAAM,UAA0B,CAAC;AAEjC,QAAM,UAAU,UAAU,IAAI,OAAO,SAAS;AAC5C,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,GAAG;AACrC,UAAI,CAAC,SAAS,GAAI;AAClB,YAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,YAAM,SAAS,oBAAoB,MAAM;AACzC,cAAQ,KAAK;AAAA,QACX,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,QAAQ,KAAK;AAAA,MACf,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAEA,SAAS,oBAAoB,QAA6B;AACxD,MAAI,SAAS;AACb,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,WAAS,IAAI,GAAG,IAAI,MAAM,YAAY,KAAK;AACzC,cAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,EACxC;AACA,SAAO,KAAK,MAAM;AACpB;AAKA,SAAS,mBAAmB,YAAwB,OAA6B;AAC/E,MAAI,MAAM,WAAW,EAAG;AAExB,QAAM,WAAW,MACd;AAAA,IACC,CAAC,MACC,8BAA8B,EAAE,MAAM,mBAAmB,EAAE,MAAM,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,WAAW,EAAE,MAAM,aAAa,EAAE,MAAM;AAAA,EACrK,EACC,KAAK,IAAI;AAEZ,QAAM,KAAK;AACX,MAAI,OAAO,WAAW,cAAc,MAAM;AAC1C,MAAI,CAAC,MAAM;AACT,WAAO,SAAS,gBAAgB,IAAI,MAAM;AAC1C,eAAW,aAAa,MAAM,WAAW,UAAU;AAAA,EACrD;AAEA,QAAM,UAAU,SAAS,gBAAgB,IAAI,OAAO;AACpD,UAAQ,cAAc;AACtB,OAAK,aAAa,SAAS,KAAK,UAAU;AAC5C;AAWA,eAAe,WAAW,YAAuC;AAC/D,QAAM,YAAY,iBAAiB,UAAU;AAC7C,MAAI,UAAU,SAAS,EAAG;AAE1B,QAAM,YAAY,kBAAkB,SAAS;AAC7C,MAAI,UAAU,WAAW,EAAG;AAE5B,QAAM,WAAW,MAAM,mBAAmB,SAAS;AACnD,qBAAmB,YAAY,QAAQ;AACzC;AASA,SAAS,sBAAsB,YAAgC;AAC7D,QAAM,YAAY,WAAW,cAAc,MAAM;AACjD,SAAO,WAAW,aAAa,MAAM,KAAK;AAC5C;AAYO,SAAS,UAAU,YAAgC;AACxD,MAAI,CAAC,WAAW,aAAa,OAAO,GAAG;AACrC,eAAW,aAAa,SAAS,4BAA4B;AAAA,EAC/D;AACA,QAAM,aAAa,IAAI,cAAc;AACrC,SAAO,WAAW,kBAAkB,UAAU;AAChD;AAcA,eAAsB,mBACpB,YACA,SACiB;AACjB,QAAM,QAAQ,WAAW,UAAU,IAAI;AACvC,QAAM,cAAc,SAAS,cAAc;AAC3C,MAAI,aAAa;AACf,UAAM,WAAW,KAAK;AAAA,EACxB;AACA,SAAO,UAAU,KAAK;AACxB;AAgBA,eAAsB,UAAU,YAAwB,SAA2C;AACjG,QAAM,MAAM,SAAS,OAAO;AAC5B,QAAM,cAAc,SAAS,cAAc;AAC3C,QAAM,EAAE,OAAO,OAAO,IAAI,iBAAiB,UAAU;AACrD,QAAM,QAAQ,WAAW,UAAU,IAAI;AAEvC,MAAI,aAAa;AACf,UAAM,WAAW,KAAK;AAAA,EACxB;AAEA,QAAM,YAAY,oBAAoB,UAAU,KAAK,GAAG,OAAO,MAAM;AAErE,MAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,UAAM,IAAI,MAAM,kCAAkC,KAAK,YAAY,MAAM,GAAG;AAAA,EAC9E;AAEA,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,QAAQ;AACvB,SAAO,SAAS,SAAS;AAEzB,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,MAAI,MAAM,KAAK,GAAG;AAElB,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,OAAO,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC1E,QAAM,MAAM,IAAI,gBAAgB,IAAI;AAEpC,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,QAAI,SAAS,MAAM;AACjB,UAAI,UAAU,KAAK,GAAG,GAAG,OAAO,MAAM;AACtC,UAAI,gBAAgB,GAAG;AAEvB,aAAO,OAAO,CAAC,WAAW;AACxB,YAAI,QAAQ;AACV,kBAAQ,MAAM;AAAA,QAChB,OAAO;AACL,iBAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,QACjD;AAAA,MACF,GAAG,WAAW;AAAA,IAChB;AAEA,QAAI,UAAU,MAAM;AAClB,UAAI,gBAAgB,GAAG;AACvB;AAAA,QACE,IAAI;AAAA,UACF,sCAAsC,KAAK,YAAY,MAAM,eAAe,UAAU,MAAM;AAAA,QAC9F;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM;AAAA,EACZ,CAAC;AACH;AAaA,eAAsB,UAAU,YAAwB,SAA2C;AACjG,QAAM,MAAM,SAAS,OAAO;AAC5B,QAAM,UAAU,SAAS,WAAW;AACpC,QAAM,cAAc,SAAS,cAAc;AAC3C,QAAM,EAAE,OAAO,OAAO,IAAI,iBAAiB,UAAU;AACrD,QAAM,kBAAkB,sBAAsB,UAAU;AACxD,QAAM,QAAQ,WAAW,UAAU,IAAI;AAEvC,MAAI,aAAa;AACf,UAAM,WAAW,KAAK;AAAA,EACxB;AAEA,QAAM,YAAY,oBAAoB,UAAU,KAAK,GAAG,OAAO,MAAM;AAErE,MAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,UAAM,IAAI,MAAM,kCAAkC,KAAK,YAAY,MAAM,GAAG;AAAA,EAC9E;AAEA,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,QAAQ;AACvB,SAAO,SAAS,SAAS;AAEzB,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,MAAI,YAAY;AAChB,MAAI,SAAS,GAAG,GAAG,OAAO,OAAO,OAAO,MAAM;AAE9C,MAAI,MAAM,KAAK,GAAG;AAElB,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,OAAO,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC1E,QAAM,MAAM,IAAI,gBAAgB,IAAI;AAEpC,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,QAAI,SAAS,MAAM;AACjB,UAAI,UAAU,KAAK,GAAG,GAAG,OAAO,MAAM;AACtC,UAAI,gBAAgB,GAAG;AAEvB,aAAO;AAAA,QACL,CAAC,WAAW;AACV,cAAI,QAAQ;AACV,oBAAQ,MAAM;AAAA,UAChB,OAAO;AACL,mBAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,UACjD;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,MAAM;AAClB,UAAI,gBAAgB,GAAG;AACvB;AAAA,QACE,IAAI;AAAA,UACF,sCAAsC,KAAK,YAAY,MAAM,eAAe,UAAU,MAAM;AAAA,QAC9F;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM;AAAA,EACZ,CAAC;AACH;AAeO,SAAS,UAAU,MAAyC;AACjE,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC;AACnC,QAAM,OAAO,CAAC,QAAQ,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;AAE9C,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,QAAQ,IAAI,CAAC,MAAM,UAAU,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACjE,SAAK,KAAK,OAAO,KAAK,GAAG,CAAC;AAAA,EAC5B;AAEA,SAAO,KAAK,KAAK,IAAI;AACvB;AAEA,SAAS,UAAU,OAAuB;AACxC,MAAI,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,IAAI,GAAG;AAC9F,WAAO,IAAI,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,EACtC;AACA,SAAO;AACT;;;ACzdA,IAAM,cAAc;AASb,SAAS,cACd,WACA,UACY;AACZ,MAAI,YAAkD;AAEtD,QAAM,WAAW,IAAI,eAAe,CAAC,YAAY;AAE/C,QAAI,cAAc,MAAM;AACtB,mBAAa,SAAS;AAAA,IACxB;AACA,gBAAY,WAAW,MAAM;AAC3B,iBAAW,SAAS,SAAS;AAC3B,cAAM,EAAE,OAAO,OAAO,IAAI,MAAM;AAChC,iBAAS,OAAO,MAAM;AAAA,MACxB;AACA,kBAAY;AAAA,IACd,GAAG,WAAW;AAAA,EAChB,CAAC;AAED,WAAS,QAAQ,SAAS;AAE1B,SAAO,MAAM;AACX,QAAI,cAAc,MAAM;AACtB,mBAAa,SAAS;AAAA,IACxB;AACA,aAAS,WAAW;AAAA,EACtB;AACF;;;ACpCA,SAAS,iBAAiB,MAAM,QAAQ,aAAa;AAsBrD,IAAM,iBAAiB;AAYhB,SAAS,qBAAqB,WAAwC;AAC3E,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,YAAY;AACpB,UAAQ,aAAa,QAAQ,SAAS;AAEtC,YAAU,MAAM,WAAW,UAAU,MAAM,YAAY;AACvD,YAAU,YAAY,OAAO;AAG7B,MAAI,iBAAiB;AAErB,MAAI,oBAAoB;AAGxB,QAAM,sBAAsB,CAAC,MAAmB;AAC9C,QAAI,CAAC,UAAU,SAAS,EAAE,MAAc,GAAG;AACzC,WAAK;AAAA,IACP;AAAA,EACF;AACA,WAAS,iBAAiB,cAAc,mBAAmB;AAK3D,QAAM,wBAAwB,CAAC,MAA2B;AACxD,QAAI,EAAE,QAAQ,YAAY,QAAQ,MAAM,YAAY,SAAS;AAC3D,WAAK;AAAA,IACP;AAAA,EACF;AACA,WAAS,iBAAiB,WAAW,qBAAqB;AAE1D,WAAS,KAAK,SAAyB,GAAW,GAAW,MAAiC;AAE5F,UAAM,aAAa,GAAG,QAAQ,KAAK,IAAI,QAAQ,OAAO,MAAM,IAAI,QAAQ,OAAO,CAAC,GAAG,KAAK,IAAI,QAAQ,OAAO,QAAQ,OAAO,SAAS,CAAC,GAAG,KAAK;AAE5I,QAAI,eAAe,gBAAgB;AACjC,uBAAiB;AAEjB,UAAI,OAAO;AAIX,YAAM,gBAAgB,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;AAC5D,YAAM,iBAAiB,gBAAgB;AAGvC,UAAI,QAAQ,OAAO;AACjB,cAAM,aAAa,iBAAiB,SAAY,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,KAAK,GAAG;AACrF,gBAAQ;AACR,YAAI,YAAY;AACd,kBAAQ,kDAAkD,IAAI,UAAU,CAAC;AAAA,QAC3E;AACA,gBAAQ,kCAAkC,IAAI,QAAQ,KAAK,CAAC;AAC5D,gBAAQ;AAAA,MACV;AAGA,UAAI,QAAQ,OAAO,SAAS,GAAG;AAC7B,gBAAQ;AACR,mBAAW,SAAS,QAAQ,QAAQ;AAClC,kBAAQ;AACR,kBAAQ;AACR,cAAI,kBAAkB,MAAM,OAAO;AACjC,oBAAQ,yDAAyD,IAAI,MAAM,KAAK,CAAC;AAAA,UACnF;AACA,kBAAQ,GAAG,IAAI,MAAM,KAAK,CAAC;AAC3B,kBAAQ,kCAAkC,IAAI,MAAM,KAAK,CAAC;AAC1D,kBAAQ;AAAA,QACV;AACA,gBAAQ;AAAA,MACV;AAEA,cAAQ,YAAY;AAAA,IACtB;AAEA,YAAQ,MAAM,UAAU;AAKxB,UAAM,aAAa,EAAE;AACrB,UAAM,aAAa;AAAA,MACjB,wBAAwB;AACtB,cAAM,OAAO,UAAU,sBAAsB;AAC7C,eAAO;AAAA,UACL,GAAG,KAAK,OAAO;AAAA,UACf,GAAG,KAAK,MAAM;AAAA,UACd,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,KAAK,KAAK,MAAM;AAAA,UAChB,MAAM,KAAK,OAAO;AAAA,UAClB,OAAO,KAAK,OAAO;AAAA,UACnB,QAAQ,KAAK,MAAM;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,oBAAgB,YAAY,SAAS;AAAA,MACnC,WAAW,MAAM,aAAa;AAAA,MAC9B,YAAY,CAAC,OAAO,cAAc,GAAG,KAAK,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAAA,IACpE,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,MAAM;AAE5B,UAAI,eAAe,kBAAmB;AAGtC,cAAQ,MAAM,OAAO,GAAG,EAAE;AAC1B,cAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,WAAS,OAAa;AACpB,YAAQ,MAAM,UAAU;AACxB,qBAAiB;AAAA,EACnB;AAEA,WAAS,UAAgB;AACvB,aAAS,oBAAoB,cAAc,mBAAmB;AAC9D,aAAS,oBAAoB,WAAW,qBAAqB;AAC7D,QAAI,QAAQ,YAAY;AACtB,cAAQ,WAAW,YAAY,OAAO;AAAA,IACxC;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,MAAM,QAAQ;AAC/B;AAEA,SAAS,IAAI,KAAqB;AAChC,SAAO,IACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;;;ACrKO,IAAM,UAAU,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAEjE,IAAM,OAAO,CAAC,GAAW,GAAW,MAAsB,KAAK,IAAI,KAAK;AAIxE,IAAM,YAAY;AAAA,EACvB,QAAQ,CAAC,MAAc;AAAA,EACvB,cAAc,CAAC,MAAc,KAAK,IAAI,MAAM;AAAA,EAC5C,gBAAgB,CAAC,MAAe,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI;AAAA,EAClF,cAAc,CAAC,MAAc,KAAK,IAAI,MAAM;AAC9C;AAMO,IAAM,cAAc;AAAA;AAAA,EAEzB,MAAM;AAAA;AAAA,EAEN,MAAM;AAAA;AAAA,EAEN,WAAW;AAAA;AAAA,EAEX,QAAQ;AAAA;AAAA,EAER,WAAW;AACb;AA0BO,SAAS,YAAe,QAAkC;AAC/D,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,WAAW,YAAY;AAAA,IACvB,OAAO,UAAU;AAAA,IACjB;AAAA,EACF,IAAI;AAEJ,MAAI,UAAU,OAAO;AACrB,MAAI,QAAQ;AACZ,MAAI,UAAU;AAEd,QAAM,OAAO,MAAM;AACjB,QAAI,SAAS;AACX,2BAAqB,KAAK;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,KAAK,CAAC,QAAW,SAA8B;AACnD,SAAK;AACL,QAAI,MAAM,QAAQ,YAAY,GAAG;AAC/B,gBAAU;AACV,cAAQ,OAAO;AACf;AAAA,IACF;AAEA,UAAM,OAAO;AACb,UAAM,QAAQ,YAAY,IAAI;AAC9B,cAAU;AAEV,UAAM,OAAO,CAAC,QAAgB;AAC5B,YAAM,IAAI,SAAS,MAAM,SAAS,QAAQ;AAC1C,gBAAU,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;AACrC,cAAQ,OAAO;AACf,UAAI,IAAI,GAAG;AACT,gBAAQ,sBAAsB,IAAI;AAAA,MACpC,OAAO;AACL,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,YAAQ,sBAAsB,IAAI;AAAA,EACpC;AAEA,SAAO,EAAE,IAAI,KAAK,MAAM,SAAS,QAAQ,KAAK;AAChD;;;AC3EO,IAAM,YAAY,CAAC,QAAmC;AAAA,EAC3D,GAAG;AAAA,EACH,GAAG;AAAA,EACH,OAAO,GAAG;AAAA,EACV,QAAQ,GAAG;AACb;AAGO,SAAS,UAAU,QAAsB,IAAyB;AACvE,QAAM,MAAM,OAAO,WAAW;AAC9B,QAAM,IAAI,OAAO,QAAQ,IAAI;AAC7B,QAAM,IAAI,OAAO,SAAS,IAAI;AAC9B,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,OAAO,QAAQ;AAAA,IAC9B,IAAI,OAAO,IAAI,OAAO,SAAS;AAAA,IAC/B,GAAG,KAAK,IAAI,GAAG,QAAQ,GAAG,GAAG,SAAS,CAAC;AAAA,EACzC;AACF;AAMO,SAAS,kBAAkB,GAAW,GAAW,GAAmB;AACzE,SAAO;AAAA,IACL,IAAI,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACtB,IAAI,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IACtB,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;AAAA,EACnD;AACF;AAGO,SAAS,gBAAgB,GAAW,IAAyB;AAClE,SAAO,aAAa,GAAG,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;AAC9F;AAMO,SAAS,KAAK,SAAiB,QAAgB,OAAe,MAAsB;AACzF,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO,WAAW,SAAS,YAAY,IAAI,KAAK,IAAI,CAAC,OAAO,KAAK;AACnE;AAEO,SAAS,WAAW,SAAiB,QAAgB,OAAe,MAAsB;AAC/F,SAAO;AAAA,IACL,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI;AAAA,IAC3C,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI;AAAA;AAAA,IAE3C,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,QAAQ,CAAC,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC;AAAA,EACxE;AACF;AAEO,SAAS,aAAa,GAAW,GAAW,UAAU,MAAe;AAC1E,SACE,KAAK,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,WACxB,KAAK,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,WACxB,KAAK,IAAI,KAAK,IAAI,EAAE,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI;AAE9C;AAWO,SAAS,YACd,MACA,cACA,QACA,WACA,MACQ;AACR,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,EAAG,QAAO,EAAE,IAAI,GAAG,IAAI,GAAG,GAAG,EAAE;AACzC,QAAM,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC;AACjD,QAAM,UAAU,OAAO,OAAO;AAC9B,QAAM,OAAO,OAAO,KAAK,IAAI,UAAU,GAAG,IAAI,CAAC,CAAC;AAChD,MAAI,OAAO,KAAK,WAAW,IAAI,KAAK,gBAAgB,WAAW;AAC7D,WAAO;AAAA,EACT;AACA,QAAM,KAAK,eAAe,cAAc,IAAI;AAC5C,SAAO,kBAAkB,SAAS,MAAM,KAAK,CAAC,CAAC;AACjD;;;AC7GA,SAAS,kBAAkB;;;ACHpB,SAAS,iBAAiB,KAA8B;AAC7D,MAAI,KAAK;AACP,QAAI,UAAU,OAAO,YAAY;AAAA,EACnC;AACF;AASO,SAAS,sBAAsB,KAAiB,YAAqC;AAE1F,QAAM,QAAQ,IAAI;AAClB,QAAM,WAAW,WAAW,MAAM,iBAAiB,yBAAyB,CAAC,KAAK;AAClF,QAAM,UAAU,WAAW,MAAM,iBAAiB,wBAAwB,CAAC,KAAK;AAChF,QAAM,kBAAkB,WAAW,MAAM,iBAAiB,uBAAuB,CAAC,KAAK;AAGvF,QAAM,mBAAmB,IAAI,iBAAiB,wBAAwB,EAAE;AACxE,QAAM,eAAe,UAAU,KAAK,IAAI,GAAG,mBAAmB,CAAC;AAG/D,QAAM,YAAY,eAAe,WAAW,kBAAkB;AAE9D,QAAM,QAAQ,WAAW,MAAM;AAC7B,QAAI,UAAU,OAAO,YAAY;AACjC,iBAAa;AAAA,EACf,GAAG,SAAS;AAEZ,SAAO,MAAM;AACX,iBAAa,KAAK;AAClB,qBAAiB,GAAG;AAAA,EACtB;AACF;AAQO,SAAS,2BAA2B,SAAkC;AAC3E,QAAM,QAAQ,QAAQ;AACtB,QAAM,WAAW,WAAW,MAAM,iBAAiB,yBAAyB,CAAC,KAAK;AAClF,QAAM,UAAU,WAAW,MAAM,iBAAiB,wBAAwB,CAAC,KAAK;AAEhF,QAAM,OAAO,QAAQ,iBAAiB,UAAU,EAAE;AAClD,QAAM,eAAe,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC;AAGnD,QAAM,YAAY,eAAe,WAAW;AAE5C,QAAM,QAAQ,WAAW,MAAM;AAC7B,YAAQ,UAAU,OAAO,YAAY;AAAA,EACvC,GAAG,SAAS;AAEZ,SAAO,MAAM;AACX,iBAAa,KAAK;AAClB,YAAQ,UAAU,OAAO,YAAY;AAAA,EACvC;AACF;;;AClDO,SAAS,uBACd,QACA,KACA,UAAU,IACW;AACrB,QAAM,QAAQ,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC;AACrC,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,QAAQ;AAEZ,aAAW,KAAK,OAAO,UAAU;AAC/B,QAAI,MAAM,IAAI,OAAO,EAAE,EAAE,CAAC,GAAG;AAC3B,cAAQ;AACR,aAAO,KAAK,IAAI,MAAM,EAAE,OAAO,CAAC;AAChC,aAAO,KAAK,IAAI,MAAM,EAAE,OAAO,CAAC;AAChC,aAAO,KAAK,IAAI,MAAM,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACjD,aAAO,KAAK,IAAI,MAAM,EAAE,OAAO,IAAI,EAAE,OAAO,MAAM;AAAA,IACpD;AAAA,EACF;AAEA,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,MAAM,QAAQ;AAC9E;AAMO,SAAS,gBAAgB,QAAmB,QAAsC;AACvF,QAAM,KAAK,OAAO;AAClB,MAAI,CAAC,OAAQ,QAAO,UAAU,UAAU,EAAE,GAAG,EAAE;AAC/C,QAAM,MAAM,UAAU,QAAQ,EAAE;AAChC,SAAO,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,EAAE;AACvD;AAMO,SAAS,eAAe,KAAiB,QAAgB,QAAyB;AACvF,QAAM,cAAc,IAAI,cAAc,sBAAsB;AAC5D,MAAI,CAAC,YAAa;AAElB,QAAM,KAAK,OAAO;AAClB,QAAM,WAAW,KAAK,IAAI,OAAO,IAAI,CAAC,IAAI;AAE1C,MAAI,UAAU;AACZ,gBAAY,aAAa,aAAa,gBAAgB,QAAQ,EAAE,CAAC;AAEjE,UAAM,QAAQ,IAAI,iBAAiB,uCAAuC;AAC1E,eAAW,KAAK,OAAO;AACrB,QAAE,aAAa,iBAAiB,oBAAoB;AAAA,IACtD;AAAA,EACF,OAAO;AACL,gBAAY,gBAAgB,WAAW;AACvC,UAAM,QAAQ,IAAI,iBAAiB,uCAAuC;AAC1E,eAAW,KAAK,OAAO;AACrB,QAAE,gBAAgB,eAAe;AAAA,IACnC;AAAA,EACF;AACF;;;ACrEA,IAAMA,UAAS;AACf,IAAM,WAAW;AACjB,IAAM,YAAY;AAIlB,IAAM,2BAA2B;AAMjC,SAASC,kBAAiB,KAAyB;AACjD,SAAO,SAAS,gBAAgBD,SAAQ,GAAG;AAC7C;AAEA,SAASE,UAAS,IAAgB,OAA8C;AAC9E,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,OAAG,aAAa,KAAK,OAAO,KAAK,CAAC;AAAA,EACpC;AACF;AAMA,SAAS,aAAa,QAAoB,QAAyB;AACjE,QAAM,IAAID,kBAAiB,GAAG;AAC9B,IAAE,aAAa,SAAS,WAAW;AAEnC,QAAM,EAAE,QAAQ,YAAY,IAAI;AAChC,QAAM,eAAe,OAAO,iBAAiB,OAAO,KAAK,IAAI,OAAO,KAAK;AAEzE,MAAI,OAAO,OAAO;AAChB,wBAAoB,GAAG,OAAO,OAAO,YAAY,SAAS,WAAW;AAAA,EACvE;AACA,MAAI,OAAO,UAAU;AACnB,wBAAoB,GAAG,OAAO,UAAU,eAAe,YAAY,WAAW;AAAA,EAChF;AACA,MAAI,OAAO,QAAQ;AACjB;AAAA,MACE;AAAA,MACA,EAAE,GAAG,OAAO,QAAQ,GAAG,eAAe,OAAO,OAAO,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,QAAQ;AACjB;AAAA,MACE;AAAA,MACA,EAAE,GAAG,OAAO,QAAQ,GAAG,eAAe,OAAO,OAAO,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,QAAQ;AACjB;AAAA,MACE;AAAA,MACA,EAAE,GAAG,OAAO,QAAQ,GAAG,eAAe,OAAO,OAAO,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,YAAY,CAAC;AACtB;AAMA,SAAS,gBAAgB,QAAoB,QAAyB;AACpE,MAAI,OAAO,QAAQ,IAAK;AAExB,QAAM,EAAE,OAAO,QAAQ,MAAM,IAAI;AACjC,QAAM,UAAU,MAAM,QAAQ;AAC9B,QAAM,YAAY,QAAQ;AAC1B,QAAM,aAAa,SAAS;AAC5B,QAAM,OAAO,MAAM,OAAO;AAE1B,QAAM,IAAIA,kBAAiB,GAAG;AAC9B,IAAE,aAAa,QAAQ,SAAS;AAChC,IAAE,eAAe,UAAU,cAAc,SAAS;AAClD,IAAE,aAAa,UAAU,QAAQ;AACjC,IAAE,aAAa,OAAO,UAAU;AAChC,IAAE,aAAa,SAAS,eAAe;AAEvC,QAAM,OAAOA,kBAAiB,MAAM;AACpC,EAAAC,UAAS,MAAM;AAAA,IACb,GAAG;AAAA,IACH,GAAG;AAAA,IACH,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,eAAe,MAAM,MAAM;AAAA,IAC3B,aAAa;AAAA,IACb,gBAAgB;AAAA,EAClB,CAAC;AACD,EAAC,KAA4C,MAAM,YAAY,QAAQ,IAAI;AAE3E,QAAM,UAAUD,kBAAiB,OAAO;AACxC,EAAAC,UAAS,SAAS,EAAE,eAAe,IAAI,CAAC;AACxC,UAAQ,cAAc;AAEtB,QAAM,eAAeD,kBAAiB,OAAO;AAC7C,EAAAC,UAAS,cAAc,EAAE,eAAe,KAAK,aAAa,GAAG,CAAC;AAC9D,eAAa,cAAc;AAE3B,QAAM,SAASD,kBAAiB,OAAO;AACvC,EAAAC,UAAS,QAAQ,EAAE,eAAe,IAAI,CAAC;AACvC,SAAO,cAAc;AAErB,OAAK,YAAY,OAAO;AACxB,OAAK,YAAY,YAAY;AAC7B,OAAK,YAAY,MAAM;AACvB,IAAE,YAAY,IAAI;AAClB,SAAO,YAAY,CAAC;AACtB;AAMA,SAAS,cAAc,QAAoB,SAA2B;AACpE,QAAM,IAAID,kBAAiB,GAAG;AAC9B,IAAE,aAAa,SAAS,gBAAgB;AAGxC,MAAI,QAAQ,cAAc;AACxB,UAAM,WAAWA,kBAAiB,MAAM;AACxC,IAAAC,UAAS,UAAU;AAAA,MACjB,GAAG,QAAQ;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,IACrB,CAAC;AACD,aAAS,aAAa,SAAS,wBAAwB;AACvD,aAAS,aAAa,kBAAkB,MAAM;AAC9C,MAAE,YAAY,QAAQ;AAAA,EACxB;AAGA,MAAI,QAAQ,aAAa;AACvB,UAAM,UAAUD,kBAAiB,MAAM;AACvC,IAAAC,UAAS,SAAS;AAAA,MAChB,GAAG,QAAQ;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,IACrB,CAAC;AACD,YAAQ,aAAa,SAAS,uBAAuB;AACrD,YAAQ,aAAa,kBAAkB,MAAM;AAC7C,MAAE,YAAY,OAAO;AAAA,EACvB;AAEA,SAAO,YAAY,CAAC;AACtB;AAMA,SAAS,eACP,QACA,UACA,WACA,gBAAgB,GACV;AACN,QAAM,IAAID,kBAAiB,GAAG;AAC9B,IAAE,aAAa,SAAS,iBAAiB;AACzC,IAAE,aAAa,QAAQ,MAAM;AAE7B,QAAM,OAAO,SAAS,SAAS;AAE/B,MAAI,QAAQ,WAAW,OAAO;AAC5B,MAAE,aAAa,qBAAqB,EAAE;AAAA,EACxC;AAEA,QAAM,SAAS,SAAS,SAAS;AAIjC,QAAM,iBAA2B,CAAC;AAClC,MAAI,CAAC,QAAQ,gBAAgB,KAAK,SAAS,GAAG;AAC5C,aAAS,IAAI,GAAG,KAAK,QAAQ,KAAK;AAChC,qBAAe,KAAM,IAAI,SAAU,aAAa;AAAA,IAClD;AAEA,QAAI,OAAO,aAAc,SAAS,SAAS;AAC3C,aAAS,IAAI,QAAQ,IAAI,GAAG,KAAK;AAC/B,aAAQ,OAAO,aAAc;AAC7B,UAAI,IAAI,OAAQ,SAAS;AACzB,UAAI,KAAK,KAAK,GAAG,IAAI,CAAC;AACtB,WAAK,IAAI,KAAK,KAAK,IAAK,MAAM,GAAI,IAAI,EAAE;AACxC,YAAM,MAAM,IAAK,MAAM,QAAS,MAAM,IAAI;AAC1C,OAAC,eAAe,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,eAAe,CAAC,CAAC;AAAA,IAChF;AAAA,EACF;AAEA,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,OAAOA,kBAAiB,MAAM;AACpC,SAAK,aAAa,SAAS,gBAAgB;AAC3C,SAAK,aAAa,QAAQ,UAAU;AACpC,IAAAC,UAAS,MAAM;AAAA,MACb,GAAG,QAAQ;AAAA,MACX,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,gBAAgB,QAAQ;AAAA,IAC1B,CAAC;AACD,SAAK,aAAa,mBAAmB,OAAO,QAAQ,EAAE,CAAC;AACvD,SAAK,aAAa,YAAY,OAAO,QAAQ,EAAE,CAAC;AAChD,QAAI,QAAQ,MAAM;AAChB,WAAK,aAAa,qBAAqB,QAAQ,IAAI;AAAA,IACrD;AACA,QAAI,QAAQ,MAAM,OAAO;AACvB,WAAK,aAAa,cAAc,QAAQ,KAAK,KAAK;AAAA,IACpD;AAGA,QAAI,CAAC,QAAQ,WAAW,OAAO;AAC7B,YAAM,MAAM,QAAQ,kBAAkB;AACtC,WAAK,aAAa,wBAAwB,OAAO,GAAG,CAAC;AACrD,YAAM,IAAK,KAA4C;AACvD,QAAE,YAAY,mBAAmB,OAAO,GAAG,CAAC;AAC5C,QAAE,YAAY,qBAAqB,QAAQ,IAAI;AAC/C,UAAI,gBAAgB,KAAK,SAAS,GAAG;AACnC,UAAE,YAAY,kBAAkB,GAAG,eAAe,CAAC,CAAC,IAAI;AAAA,MAC1D;AAAA,IACF;AAEA,MAAE,YAAY,IAAI;AAAA,EACpB;AAEA,SAAO,YAAY,CAAC;AACtB;AASO,SAAS,aAAa,QAAmB,MAA6C;AAC3F,QAAM,EAAE,OAAO,QAAQ,UAAU,SAAS,MAAM,WAAW,UAAU,IAAI;AACzE,QAAM,UAAU,MAAM,WAAW,CAAC,CAAC,WAAW;AAE9C,QAAM,MAAMD,kBAAiB,KAAK;AAClC,MAAI,aAAa,WAAW,OAAO,KAAK,IAAI,MAAM,EAAE;AACpD,MAAI,aAAa,QAAQ,KAAK;AAC9B,MAAI,KAAK,SAAS;AAChB,QAAI,aAAa,cAAc,KAAK,OAAO;AAAA,EAC7C;AAEA,QAAM,UAAU,UAAU,sBAAsB;AAChD,MAAI,aAAa,SAAS,OAAO;AAEjC,QAAM,OAAO,SAAS,SAAS;AAC/B,MAAI,mBAAmB;AACvB,MAAI,WAAW,WAAW,OAAO;AAC/B,UAAM,MAAM,UAAU,MAAM;AAC5B,UAAM,aAAa,KAAK,IAAI,KAAK,GAAG;AACpC,QAAI,CAAC,MAAM;AACT,yBAAmB,KAAK,MAAM,MAAM,GAAG;AAAA,IACzC;AACA,UAAM,IAAI,KAAK,IAAI,SAAS,QAAQ,CAAC;AACrC,UAAM,UAAU,CAAC,QAAQ,IAAI,IAAI,oBAAoB,IAAI,KAAK;AAC9D,uBAAmB,KAAK;AAAA,MACtB,UAAU;AAAA,MACV;AAAA,MACA,iBAAiB,UAAU;AAAA,MAC3B,MAAM,UAAU,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,QAAM,OAAOA,kBAAiB,MAAM;AACpC,MAAI,YAAY,IAAI;AAGpB,eAAa,KAAK,MAAM;AAGxB,QAAM,WAAWA,kBAAiB,GAAG;AACrC,WAAS,aAAa,SAAS,cAAc;AAC7C,WAAS,aAAa,aAAa,aAAa,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,GAAG;AAGjF,QAAM,cAAcA,kBAAiB,GAAG;AACxC,cAAY,aAAa,SAAS,eAAe;AACjD,cAAY,aAAa,sBAAsB,EAAE;AAGjD,iBAAe,aAAa,UAAU,UAAU,YAAY,QAAW,gBAAgB;AAGvF,gBAAc,aAAa,OAAO;AAElC,WAAS,YAAY,WAAW;AAChC,MAAI,YAAY,QAAQ;AAGxB,MAAI,OAAO,kBAAkB;AAC3B,iBAAa,KAAK,OAAO,gBAAgB;AAAA,EAC3C,WAAW,OAAO,mBAAmB;AACnC,iBAAa,KAAK,OAAO,iBAAiB;AAAA,EAC5C;AAGA,MAAI,WAAW;AACb,oBAAgB,KAAK,MAAM;AAAA,EAC7B;AAEA,SAAO;AACT;;;ACjVe,SAAR,eAAiB,aAAa,SAAS,WAAW;AACvD,cAAY,YAAY,QAAQ,YAAY;AAC5C,YAAU,cAAc;AAC1B;AAEO,SAAS,OAAO,QAAQ,YAAY;AACzC,MAAI,YAAY,OAAO,OAAO,OAAO,SAAS;AAC9C,WAAS,OAAO,WAAY,WAAU,GAAG,IAAI,WAAW,GAAG;AAC3D,SAAO;AACT;;;ACPO,SAAS,QAAQ;AAAC;AAElB,IAAI,SAAS;AACb,IAAI,WAAW,IAAI;AAE1B,IAAI,MAAM;AAAV,IACI,MAAM;AADV,IAEI,MAAM;AAFV,IAGI,QAAQ;AAHZ,IAII,eAAe,IAAI,OAAO,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AAJ/D,IAKI,eAAe,IAAI,OAAO,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AAL/D,IAMI,gBAAgB,IAAI,OAAO,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AANxE,IAOI,gBAAgB,IAAI,OAAO,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AAPxE,IAQI,eAAe,IAAI,OAAO,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AAR/D,IASI,gBAAgB,IAAI,OAAO,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM;AAExE,IAAI,QAAQ;AAAA,EACV,WAAW;AAAA,EACX,cAAc;AAAA,EACd,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,eAAe;AAAA,EACf,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,sBAAsB;AAAA,EACtB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,eAAe;AAAA,EACf,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,WAAW;AAAA,EACX,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,KAAK;AAAA,EACL,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,aAAa;AACf;AAEA,eAAO,OAAO,OAAO;AAAA,EACnB,KAAK,UAAU;AACb,WAAO,OAAO,OAAO,IAAI,KAAK,eAAa,MAAM,QAAQ;AAAA,EAC3D;AAAA,EACA,cAAc;AACZ,WAAO,KAAK,IAAI,EAAE,YAAY;AAAA,EAChC;AAAA,EACA,KAAK;AAAA;AAAA,EACL,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AACZ,CAAC;AAED,SAAS,kBAAkB;AACzB,SAAO,KAAK,IAAI,EAAE,UAAU;AAC9B;AAEA,SAAS,mBAAmB;AAC1B,SAAO,KAAK,IAAI,EAAE,WAAW;AAC/B;AAEA,SAAS,kBAAkB;AACzB,SAAO,WAAW,IAAI,EAAE,UAAU;AACpC;AAEA,SAAS,kBAAkB;AACzB,SAAO,KAAK,IAAI,EAAE,UAAU;AAC9B;AAEe,SAAR,MAAuB,QAAQ;AACpC,MAAI,GAAG;AACP,YAAU,SAAS,IAAI,KAAK,EAAE,YAAY;AAC1C,UAAQ,IAAI,MAAM,KAAK,MAAM,MAAM,IAAI,EAAE,CAAC,EAAE,QAAQ,IAAI,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,IACtF,MAAM,IAAI,IAAI,IAAK,KAAK,IAAI,KAAQ,KAAK,IAAI,KAAQ,KAAK,IAAI,KAAQ,IAAI,MAAS,IAAI,OAAQ,IAAM,IAAI,IAAM,CAAC,IAChH,MAAM,IAAI,KAAK,KAAK,KAAK,KAAM,KAAK,KAAK,KAAM,KAAK,IAAI,MAAO,IAAI,OAAQ,GAAI,IAC/E,MAAM,IAAI,KAAM,KAAK,KAAK,KAAQ,KAAK,IAAI,KAAQ,KAAK,IAAI,KAAQ,KAAK,IAAI,KAAQ,KAAK,IAAI,KAAQ,IAAI,OAAU,IAAI,OAAQ,IAAM,IAAI,MAAQ,GAAI,IACtJ,SACC,IAAI,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAC5D,IAAI,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,CAAC,KAChG,IAAI,cAAc,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,KAC7D,IAAI,cAAc,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,KACjG,IAAI,aAAa,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,KAAK,CAAC,KACrE,IAAI,cAAc,KAAK,MAAM,KAAK,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,IAC1E,MAAM,eAAe,MAAM,IAAI,KAAK,MAAM,MAAM,CAAC,IACjD,WAAW,gBAAgB,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC,IACnD;AACR;AAEA,SAAS,KAAK,GAAG;AACf,SAAO,IAAI,IAAI,KAAK,KAAK,KAAM,KAAK,IAAI,KAAM,IAAI,KAAM,CAAC;AAC3D;AAEA,SAAS,KAAK,GAAG,GAAG,GAAG,GAAG;AACxB,MAAI,KAAK,EAAG,KAAI,IAAI,IAAI;AACxB,SAAO,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC;AAC3B;AAEO,SAAS,WAAW,GAAG;AAC5B,MAAI,EAAE,aAAa,OAAQ,KAAI,MAAM,CAAC;AACtC,MAAI,CAAC,EAAG,QAAO,IAAI;AACnB,MAAI,EAAE,IAAI;AACV,SAAO,IAAI,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO;AACzC;AAEO,SAAS,IAAI,GAAG,GAAG,GAAG,SAAS;AACpC,SAAO,UAAU,WAAW,IAAI,WAAW,CAAC,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,WAAW,OAAO,IAAI,OAAO;AAChG;AAEO,SAAS,IAAI,GAAG,GAAG,GAAG,SAAS;AACpC,OAAK,IAAI,CAAC;AACV,OAAK,IAAI,CAAC;AACV,OAAK,IAAI,CAAC;AACV,OAAK,UAAU,CAAC;AAClB;AAEA,eAAO,KAAK,KAAK,OAAO,OAAO;AAAA,EAC7B,SAAS,GAAG;AACV,QAAI,KAAK,OAAO,WAAW,KAAK,IAAI,UAAU,CAAC;AAC/C,WAAO,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO;AAAA,EACjE;AAAA,EACA,OAAO,GAAG;AACR,QAAI,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,CAAC;AAC3C,WAAO,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO;AAAA,EACjE;AAAA,EACA,MAAM;AACJ,WAAO;AAAA,EACT;AAAA,EACA,QAAQ;AACN,WAAO,IAAI,IAAI,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,OAAO,CAAC;AAAA,EACrF;AAAA,EACA,cAAc;AACZ,WAAQ,QAAQ,KAAK,KAAK,KAAK,IAAI,UAC3B,QAAQ,KAAK,KAAK,KAAK,IAAI,WAC3B,QAAQ,KAAK,KAAK,KAAK,IAAI,WAC3B,KAAK,KAAK,WAAW,KAAK,WAAW;AAAA,EAC/C;AAAA,EACA,KAAK;AAAA;AAAA,EACL,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,UAAU;AACZ,CAAC,CAAC;AAEF,SAAS,gBAAgB;AACvB,SAAO,IAAI,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC;AACpD;AAEA,SAAS,iBAAiB;AACxB,SAAO,IAAI,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,GAAG,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,KAAK,WAAW,GAAG,CAAC;AAC1G;AAEA,SAAS,gBAAgB;AACvB,QAAM,IAAI,OAAO,KAAK,OAAO;AAC7B,SAAO,GAAG,MAAM,IAAI,SAAS,OAAO,GAAG,OAAO,KAAK,CAAC,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,GAAG,MAAM,IAAI,MAAM,KAAK,CAAC,GAAG;AACzH;AAEA,SAAS,OAAO,SAAS;AACvB,SAAO,MAAM,OAAO,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC;AAC9D;AAEA,SAAS,OAAO,OAAO;AACrB,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC;AAC1D;AAEA,SAAS,IAAI,OAAO;AAClB,UAAQ,OAAO,KAAK;AACpB,UAAQ,QAAQ,KAAK,MAAM,MAAM,MAAM,SAAS,EAAE;AACpD;AAEA,SAAS,KAAK,GAAG,GAAG,GAAG,GAAG;AACxB,MAAI,KAAK,EAAG,KAAI,IAAI,IAAI;AAAA,WACf,KAAK,KAAK,KAAK,EAAG,KAAI,IAAI;AAAA,WAC1B,KAAK,EAAG,KAAI;AACrB,SAAO,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC;AAC3B;AAEO,SAAS,WAAW,GAAG;AAC5B,MAAI,aAAa,IAAK,QAAO,IAAI,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO;AAC7D,MAAI,EAAE,aAAa,OAAQ,KAAI,MAAM,CAAC;AACtC,MAAI,CAAC,EAAG,QAAO,IAAI;AACnB,MAAI,aAAa,IAAK,QAAO;AAC7B,MAAI,EAAE,IAAI;AACV,MAAI,IAAI,EAAE,IAAI,KACV,IAAI,EAAE,IAAI,KACV,IAAI,EAAE,IAAI,KACV,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GACtB,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GACtB,IAAI,KACJ,IAAI,MAAM,KACV,KAAK,MAAM,OAAO;AACtB,MAAI,GAAG;AACL,QAAI,MAAM,IAAK,MAAK,IAAI,KAAK,KAAK,IAAI,KAAK;AAAA,aAClC,MAAM,IAAK,MAAK,IAAI,KAAK,IAAI;AAAA,QACjC,MAAK,IAAI,KAAK,IAAI;AACvB,SAAK,IAAI,MAAM,MAAM,MAAM,IAAI,MAAM;AACrC,SAAK;AAAA,EACP,OAAO;AACL,QAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,EAC3B;AACA,SAAO,IAAI,IAAI,GAAG,GAAG,GAAG,EAAE,OAAO;AACnC;AAEO,SAAS,IAAI,GAAG,GAAG,GAAG,SAAS;AACpC,SAAO,UAAU,WAAW,IAAI,WAAW,CAAC,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,WAAW,OAAO,IAAI,OAAO;AAChG;AAEA,SAAS,IAAI,GAAG,GAAG,GAAG,SAAS;AAC7B,OAAK,IAAI,CAAC;AACV,OAAK,IAAI,CAAC;AACV,OAAK,IAAI,CAAC;AACV,OAAK,UAAU,CAAC;AAClB;AAEA,eAAO,KAAK,KAAK,OAAO,OAAO;AAAA,EAC7B,SAAS,GAAG;AACV,QAAI,KAAK,OAAO,WAAW,KAAK,IAAI,UAAU,CAAC;AAC/C,WAAO,IAAI,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO;AAAA,EACzD;AAAA,EACA,OAAO,GAAG;AACR,QAAI,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,CAAC;AAC3C,WAAO,IAAI,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO;AAAA,EACzD;AAAA,EACA,MAAM;AACJ,QAAI,IAAI,KAAK,IAAI,OAAO,KAAK,IAAI,KAAK,KAClC,IAAI,MAAM,CAAC,KAAK,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,GACzC,IAAI,KAAK,GACT,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,GACjC,KAAK,IAAI,IAAI;AACjB,WAAO,IAAI;AAAA,MACT,QAAQ,KAAK,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAAA,MAC5C,QAAQ,GAAG,IAAI,EAAE;AAAA,MACjB,QAAQ,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAAA,MAC3C,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EACA,QAAQ;AACN,WAAO,IAAI,IAAI,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,OAAO,KAAK,OAAO,CAAC;AAAA,EACrF;AAAA,EACA,cAAc;AACZ,YAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,CAAC,OAC1C,KAAK,KAAK,KAAK,KAAK,KAAK,OACzB,KAAK,KAAK,WAAW,KAAK,WAAW;AAAA,EAC/C;AAAA,EACA,YAAY;AACV,UAAM,IAAI,OAAO,KAAK,OAAO;AAC7B,WAAO,GAAG,MAAM,IAAI,SAAS,OAAO,GAAG,OAAO,KAAK,CAAC,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,GAAG,MAAM,OAAO,KAAK,CAAC,IAAI,GAAG,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC,GAAG;AAAA,EACvI;AACF,CAAC,CAAC;AAEF,SAAS,OAAO,OAAO;AACrB,WAAS,SAAS,KAAK;AACvB,SAAO,QAAQ,IAAI,QAAQ,MAAM;AACnC;AAEA,SAAS,OAAO,OAAO;AACrB,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,CAAC,CAAC;AAC5C;AAGA,SAAS,QAAQ,GAAG,IAAI,IAAI;AAC1B,UAAQ,IAAI,KAAK,MAAM,KAAK,MAAM,IAAI,KAChC,IAAI,MAAM,KACV,IAAI,MAAM,MAAM,KAAK,OAAO,MAAM,KAAK,KACvC,MAAM;AACd;;;AC3YO,SAAS,MAAM,IAAI,IAAI,IAAI,IAAI,IAAI;AACxC,MAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AAC5B,WAAS,IAAI,IAAI,KAAK,IAAI,KAAK,MAAM,MAC9B,IAAI,IAAI,KAAK,IAAI,MAAM,MACvB,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,KACjC,KAAK,MAAM;AACnB;AAEe,SAAR,cAAiB,QAAQ;AAC9B,MAAI,IAAI,OAAO,SAAS;AACxB,SAAO,SAAS,GAAG;AACjB,QAAI,IAAI,KAAK,IAAK,IAAI,IAAK,KAAK,KAAK,IAAI,GAAG,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,GACjE,KAAK,OAAO,CAAC,GACb,KAAK,OAAO,IAAI,CAAC,GACjB,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,KAAK,IACtC,KAAK,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,KAAK;AAC9C,WAAO,OAAO,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,IAAI,EAAE;AAAA,EAC9C;AACF;;;AChBe,SAAR,oBAAiB,QAAQ;AAC9B,MAAI,IAAI,OAAO;AACf,SAAO,SAAS,GAAG;AACjB,QAAI,IAAI,KAAK,QAAQ,KAAK,KAAK,IAAI,EAAE,IAAI,KAAK,CAAC,GAC3C,KAAK,QAAQ,IAAI,IAAI,KAAK,CAAC,GAC3B,KAAK,OAAO,IAAI,CAAC,GACjB,KAAK,QAAQ,IAAI,KAAK,CAAC,GACvB,KAAK,QAAQ,IAAI,KAAK,CAAC;AAC3B,WAAO,OAAO,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,IAAI,EAAE;AAAA,EAC9C;AACF;;;ACZA,IAAO,mBAAQ,OAAK,MAAM;;;ACE1B,SAAS,OAAO,GAAG,GAAG;AACpB,SAAO,SAAS,GAAG;AACjB,WAAO,IAAI,IAAI;AAAA,EACjB;AACF;AAEA,SAAS,YAAY,GAAG,GAAG,GAAG;AAC5B,SAAO,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,GAAG,SAAS,GAAG;AACxE,WAAO,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC;AAAA,EAC9B;AACF;AAOO,SAAS,MAAM,GAAG;AACvB,UAAQ,IAAI,CAAC,OAAO,IAAI,UAAU,SAAS,GAAG,GAAG;AAC/C,WAAO,IAAI,IAAI,YAAY,GAAG,GAAG,CAAC,IAAI,iBAAS,MAAM,CAAC,IAAI,IAAI,CAAC;AAAA,EACjE;AACF;AAEe,SAAR,QAAyB,GAAG,GAAG;AACpC,MAAI,IAAI,IAAI;AACZ,SAAO,IAAI,OAAO,GAAG,CAAC,IAAI,iBAAS,MAAM,CAAC,IAAI,IAAI,CAAC;AACrD;;;ACvBA,IAAO,eAAS,SAAS,SAAS,GAAG;AACnC,MAAIE,SAAQ,MAAM,CAAC;AAEnB,WAASC,KAAI,OAAO,KAAK;AACvB,QAAI,IAAID,QAAO,QAAQ,IAAS,KAAK,GAAG,IAAI,MAAM,IAAS,GAAG,GAAG,CAAC,GAC9D,IAAIA,OAAM,MAAM,GAAG,IAAI,CAAC,GACxB,IAAIA,OAAM,MAAM,GAAG,IAAI,CAAC,GACxB,UAAU,QAAQ,MAAM,SAAS,IAAI,OAAO;AAChD,WAAO,SAAS,GAAG;AACjB,YAAM,IAAI,EAAE,CAAC;AACb,YAAM,IAAI,EAAE,CAAC;AACb,YAAM,IAAI,EAAE,CAAC;AACb,YAAM,UAAU,QAAQ,CAAC;AACzB,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAEA,EAAAC,KAAI,QAAQ;AAEZ,SAAOA;AACT,GAAG,CAAC;AAEJ,SAAS,UAAU,QAAQ;AACzB,SAAO,SAAS,QAAQ;AACtB,QAAI,IAAI,OAAO,QACX,IAAI,IAAI,MAAM,CAAC,GACf,IAAI,IAAI,MAAM,CAAC,GACf,IAAI,IAAI,MAAM,CAAC,GACf,GAAGD;AACP,SAAK,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG;AACtB,MAAAA,SAAQ,IAAS,OAAO,CAAC,CAAC;AAC1B,QAAE,CAAC,IAAIA,OAAM,KAAK;AAClB,QAAE,CAAC,IAAIA,OAAM,KAAK;AAClB,QAAE,CAAC,IAAIA,OAAM,KAAK;AAAA,IACpB;AACA,QAAI,OAAO,CAAC;AACZ,QAAI,OAAO,CAAC;AACZ,QAAI,OAAO,CAAC;AACZ,IAAAA,OAAM,UAAU;AAChB,WAAO,SAAS,GAAG;AACjB,MAAAA,OAAM,IAAI,EAAE,CAAC;AACb,MAAAA,OAAM,IAAI,EAAE,CAAC;AACb,MAAAA,OAAM,IAAI,EAAE,CAAC;AACb,aAAOA,SAAQ;AAAA,IACjB;AAAA,EACF;AACF;AAEO,IAAI,WAAW,UAAU,aAAK;AAC9B,IAAI,iBAAiB,UAAU,mBAAW;;;AC1C1C,SAAS,oBAAoB,KAA6C;AAC/E,QAAM,QAAQ,oBAAI,IAAoB;AACtC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,IAAI,iBAAiB,2BAA2B;AAC9D,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,EAAE,aAAa,UAAU;AACrC,UAAM,OAAO,EAAE,aAAa,MAAM;AAClC,QAAI,OAAO,KAAM,OAAM,IAAI,KAAK,IAAI;AAAA,EACtC;AACA,SAAO;AACT;AAEO,SAAS,qBACd,KACA,WACA,MACwB;AACxB,QAAM,QAAQ,IAAI,iBAAiB,2BAA2B;AAC9D,QAAM,SACJ,CAAC;AAEH,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,EAAE,aAAa,UAAU;AACrC,UAAM,KAAK,EAAE,aAAa,MAAM;AAChC,UAAM,OAAO,MAAM,UAAU,IAAI,GAAG,IAAI;AACxC,QAAI,QAAQ,MAAM,SAAS,IAAI;AAC7B,aAAO,KAAK,EAAE,IAAI,GAAG,MAAM,IAAI,QAAQ,YAAe,MAAM,EAAE,EAAE,CAAC;AAEjE,QAAE,aAAa,QAAQ,IAAI;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,KAAK,KAAK,YAAY,GAAG;AAC7C,eAAW,MAAM,OAAQ,IAAG,GAAG,aAAa,QAAQ,GAAG,EAAE;AACzD,WAAO,EAAE,QAAQ,MAAM;AAAA,IAAC,EAAE;AAAA,EAC5B;AAEA,QAAM,WAAW,KAAK;AACtB,MAAI,YAA2B;AAC/B,MAAI,QAAQ;AACZ,MAAI,YAAY;AAEhB,WAAS,KAAK,KAAa;AACzB,QAAI,UAAW;AACf,QAAI,cAAc,KAAM,aAAY;AACpC,UAAM,UAAU,MAAM;AACtB,UAAM,IAAI,KAAK,IAAI,GAAG,UAAU,QAAQ;AACxC,UAAM,QAAQ,UAAU,eAAe,CAAC;AAExC,eAAW,MAAM,QAAQ;AACvB,SAAG,GAAG,aAAa,QAAQ,GAAG,OAAO,KAAK,CAAC;AAAA,IAC7C;AAEA,QAAI,IAAI,GAAG;AACT,cAAQ,sBAAsB,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,UAAQ,sBAAsB,IAAI;AAElC,SAAO;AAAA,IACL,SAAS;AACP,kBAAY;AACZ,2BAAqB,KAAK;AAE1B,iBAAW,MAAM,QAAQ;AACvB,WAAG,GAAG,aAAa,QAAQ,GAAG,EAAE;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF;;;ACnEA,SAAS,yBAAyB;AAElC,IAAM,sBAAsB;AAErB,SAAS,kBAAkB,aAAqB,qBAAoC;AACzF,MAAI,SAAmC;AACvC,MAAI,MAAuC;AAE3C,SAAO,CACL,MACA,UACA,eACsC;AACtC,QAAI,CAAC,QAAQ;AACX,eAAS,SAAS,cAAc,QAAQ;AACxC,YAAM,OAAO,WAAW,IAAI;AAAA,IAC9B;AACA,QAAI,CAAC,KAAK;AAER,aAAO;AAAA,QACL,OAAO,kBAAkB,MAAM,UAAU,cAAc,GAAG;AAAA,QAC1D,QAAQ,WAAW;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,SAAS,cAAc;AAC7B,QAAI,OAAO,GAAG,MAAM,IAAI,QAAQ,MAAM,UAAU;AAChD,UAAM,UAAU,IAAI,YAAY,IAAI;AACpC,WAAO;AAAA,MACL,OAAO,QAAQ;AAAA,MACf,QAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACF;AAUO,SAAS,kBAAkB,WAAgC;AAChE,MAAI,OAAO,WAAW,eAAe,OAAO,qBAAqB,YAAY;AAC3E,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,QAAQ,iBAAiB,SAAS;AACxC,UAAM,SAAS,MAAM,iBAAiB,kBAAkB,EAAE,KAAK;AAC/D,QAAI,OAAQ,QAAO;AACnB,UAAM,WAAW,MAAM,YAAY,KAAK;AACxC,QAAI,SAAU,QAAO;AAAA,EACvB,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAOO,SAAS,gBAAgB,YAA4B;AAC1D,QAAM,QAAQ,WAAW,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAAK;AAClD,SAAO,MAAM,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAChD;AAOO,SAAS,aAAa,YAA6B;AACxD,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,QAAS,SAAgD;AAC/D,MAAI,CAAC,SAAS,OAAO,MAAM,UAAU,WAAY,QAAO;AACxD,QAAM,OAAO,gBAAgB,UAAU;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,WAAW,oBAAI,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,SAAS,IAAI,KAAK,YAAY,CAAC,EAAG,QAAO;AAC7C,MAAI;AACF,WAAO,CAAC,MAAM,MAAM,SAAS,IAAI,GAAG;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASO,SAAS,mBACd,YACA,SACA,SACS;AACT,MAAI,CAAC,aAAa,UAAU,EAAG,QAAO;AACtC,QAAM,QAAS,SAAgD;AAC/D,MAAI,CAAC,OAAO,MAAO,QAAO;AAC1B,QAAM,MAAM,KAAK,MAAM;AACrB,QAAI,QAAQ,EAAG,SAAQ;AAAA,EACzB,CAAC;AACD,SAAO;AACT;;;AZ1BA,SAAS,uBAAgC;AACvC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,WAAY,QAAO;AACrF,MAAI;AACF,WAAO,OAAO,WAAW,kCAAkC,EAAE;AAAA,EAC/D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,MAA0B;AACjD,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,SAAS,SAAS,SAAS,OAAW,QAAO;AACjD,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACtD,WAAO,OAAO,WAAW,8BAA8B,EAAE;AAAA,EAC3D;AACA,SAAO;AACT;AASO,SAAS,UACd,WACA,MACA,SACa;AACb,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI,YAAY;AAGhB,MAAI,aAAmC;AAGvC,MAAI,iBAAwC;AAC5C,MAAI,uBAA4C;AAChD,MAAI,mBAAwC;AAG5C,MAAI,mBAAwC;AAC5C,MAAI,uBAAsD;AAC1D,MAAI,gBAAgB;AAGpB,MAAI,gBAAwB,EAAE,IAAI,GAAG,IAAI,GAAG,GAAG,EAAE;AACjD,MAAI,kBAAiD;AACrD,MAAI,cAAoC;AAGxC,MAAI,gBAAgB;AAGpB,MAAI,qBAAqB;AAGzB,YAAU,UAAU,IAAI,aAAa;AAGrC,WAAS,uBAA+B;AACtC,WACE,SAAS,OAAO,OAAO,UACvB,YAAY,OAAO,OAAO,UAC1B,kBAAkB,SAAS;AAAA,EAE/B;AACA,MAAI,aAAa,qBAAqB;AACtC,MAAI,cAAc,kBAAkB,UAAU;AAC9C,MAAI,YAAY;AAMhB,MAAI,eAA+B;AAEnC,WAAS,yBAA4D;AACnE,UAAM,OAAO,UAAU,sBAAsB;AAC7C,UAAM,QAAQ,KAAK,IAAI,KAAK,SAAS,KAAK,GAAG;AAE7C,QAAI,iBAAiB,SAAS,KAAK,QAAQ,KAAK,KAAK,SAAS,IAAI;AAChE,qBAAe,KAAK,WAAW,KAAK,KAAK,QAAQ;AAAA,IACnD;AAIA,QAAI,iBAAiB,SAAS,KAAK,SAAS,GAAG;AAC7C,aAAO,EAAE,OAAO,QAAQ,KAAK,IAAI,KAAK,QAAQ,GAAG,EAAE;AAAA,IACrD;AAGA,WAAO,EAAE,OAAO,QAAQ,KAAK,MAAM,QAAQ,KAAK,EAAE;AAAA,EACpD;AAEA,WAAS,UAAqB;AAC5B,UAAM,EAAE,OAAO,OAAO,IAAI,uBAAuB;AACjD,UAAM,WAAW,gBAAgB,SAAS,QAAQ;AAElD,UAAM,cAA8B;AAAA,MAClC;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB;AAAA,MACA,WAAW,SAAS;AAAA,MACpB;AAAA,IACF;AAEA,WAAO,WAAW,aAAa,WAAW;AAAA,EAC5C;AAMA,WAAS,0BAA0B,KAAoB,QAA+B;AACpF,UAAM,WAA8B,CAAC;AAErC,UAAM,kBAAkB,IAAI,iBAAiB,iBAAiB;AAC9D,eAAW,MAAM,iBAAiB;AAChC,YAAM,YAAY,GAAG,aAAa,iBAAiB;AACnD,UAAI,CAAC,UAAW;AAEhB,YAAM,UAAU,OAAO,mBAAmB,IAAI,SAAS;AACvD,YAAM,UAAU,OAAO,SAAS,KAAK,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,SAAS;AAEtE,YAAM,mBAAmB,CAAC,MAAa;AACrC,cAAM,aAAa;AACnB,QAAC,GAA0C,MAAM,YAAY,UAAU,SAAS;AAChF,QAAC,GAA0C,MAAM,YAAY,UAAU,iBAAiB;AACxF,YAAI,WAAW,kBAAkB,SAAS,YAAY,OAAO;AAC3D,gBAAM,UAAU,IAAI,sBAAsB;AAC1C,gBAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,gBAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,yBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,QACnC;AACA,YAAI,SAAS;AACX,mBAAS,cAAc;AAAA,YACrB,IAAI,QAAQ;AAAA,YACZ,MAAM,QAAQ;AAAA,YACd,MAAM,QAAQ;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,kBAAkB,CAAC,MAAa;AACpC,YAAI,WAAW,kBAAkB,SAAS,YAAY,OAAO;AAC3D,gBAAM,aAAa;AACnB,gBAAM,UAAU,IAAI,sBAAsB;AAC1C,gBAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,gBAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,yBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,QACnC;AAAA,MACF;AAEA,YAAM,mBAAmB,MAAM;AAC7B,QAAC,GAA0C,MAAM,eAAe,QAAQ;AACxE,QAAC,GAA0C,MAAM,eAAe,QAAQ;AACxE,wBAAgB,KAAK;AACrB,iBAAS,cAAc,IAAI;AAAA,MAC7B;AAEA,YAAM,cAAc,MAAM;AACxB,YAAI,SAAS;AACX,mBAAS,cAAc;AAAA,YACrB,IAAI,QAAQ;AAAA,YACZ,MAAM,QAAQ;AAAA,YACd,MAAM,QAAQ;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,SAAG,iBAAiB,cAAc,gBAAgB;AAClD,SAAG,iBAAiB,aAAa,eAAe;AAChD,SAAG,iBAAiB,cAAc,gBAAgB;AAClD,SAAG,iBAAiB,SAAS,WAAW;AAExC,eAAS,KAAK,MAAM;AAClB,WAAG,oBAAoB,cAAc,gBAAgB;AACrD,WAAG,oBAAoB,aAAa,eAAe;AACnD,WAAG,oBAAoB,cAAc,gBAAgB;AACrD,WAAG,oBAAoB,SAAS,WAAW;AAAA,MAC7C,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,iBAAW,WAAW,UAAU;AAC9B,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAMA,WAAS,gBAAwB;AAC/B,QAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,YAAM,SAAS,uBAAuB,eAAe,eAAe;AACpE,aAAO,gBAAgB,eAAe,MAAM;AAAA,IAC9C;AACA,WAAO,gBAAgB,eAAe,IAAI;AAAA,EAC5C;AAEA,WAAS,cAAc,QAAgB,UAAwB;AAC7D,QAAI,YAAa,aAAY,OAAO;AACpC,kBAAc,YAAoB;AAAA,MAChC,SAAS;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA,MAAM,UAAU;AAAA,MAChB,QAAQ,KAAK;AACX,wBAAgB;AAChB,YAAI,WAAY,gBAAe,YAAY,KAAK,aAAa;AAAA,MAC/D;AAAA,IACF,CAAC;AACD,gBAAY,GAAG,MAAM;AAAA,EACvB;AAEA,WAAS,YAAY,KAAa,UAAwB;AACxD,QAAI,aAAa,KAAK,qBAAqB,GAAG;AAC5C,sBAAgB;AAChB,UAAI,WAAY,gBAAe,YAAY,KAAK,aAAa;AAAA,IAC/D,OAAO;AACL,oBAAc,KAAK,QAAQ;AAAA,IAC7B;AAAA,EACF;AAEA,WAAS,eAAe,KAA0C;AAChE,QAAI,SAAS,UAAU,cAAc,cAAc;AACnD,QAAI,CAAC,QAAQ;AACX,eAAS,SAAS,cAAc,KAAK;AACrC,aAAO,YAAY;AACnB,aAAO,aAAa,aAAa,QAAQ;AACzC,gBAAU,YAAY,MAAM;AAAA,IAC9B;AACA,QAAI,CAAC,OAAO,IAAI,WAAW,GAAG;AAC5B,aAAO,cAAc;AACrB;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,IAAI,CAAC,OAAO;AAC5B,YAAM,IAAI,cAAc,SAAS,KAAK,CAAC,SAAS,OAAO,KAAK,EAAE,MAAM,OAAO,EAAE,CAAC;AAC9E,aAAO,GAAG,QAAQ,OAAO,EAAE;AAAA,IAC7B,CAAC;AACD,WAAO,cAAc,aAAa,MAAM,KAAK,IAAI,CAAC;AAAA,EACpD;AAEA,WAAS,cAAc,KAA0C;AAC/D,QAAI,CAAC,WAAY;AACjB,UAAM,WAAW,WAAW,iBAAiB,iBAAiB;AAC9D,QAAI,CAAC,OAAO,IAAI,WAAW,GAAG;AAC5B,iBAAW,MAAM,UAAU;AACzB,QAAC,GAA0C,MAAM,eAAe,SAAS;AAAA,MAC3E;AACA;AAAA,IACF;AACA,UAAM,WAAW,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC;AACxC,eAAW,MAAM,UAAU;AACzB,YAAM,MAAM,GAAG,aAAa,iBAAiB;AAC7C,MAAC,GAA0C,MAAM;AAAA,QAC/C;AAAA,QACA,OAAO,SAAS,IAAI,GAAG,IAAI,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAMA,WAAS,OAAO,UAAU,OAAa;AAErC,QAAI,kBAAkB;AACpB,uBAAiB;AACjB,yBAAmB;AAAA,IACrB;AACA,QAAI,sBAAsB;AACxB,2BAAqB,OAAO;AAC5B,6BAAuB;AAAA,IACzB;AAGA,QAAI,YAAY;AACd,UAAI,sBAAsB;AACxB,6BAAqB;AACrB,+BAAuB;AAAA,MACzB;AACA,iBAAW,OAAO;AAAA,IACpB;AAGA,UAAM,SAAS,aAAa,eAAe,EAAE,QAAQ,CAAC;AACtD,cAAU,YAAY,MAAM;AAC5B,iBAAa;AAGb,2BAAuB,0BAA0B,QAAQ,aAAa;AAGtE,QAAI,SAAS,YAAY,OAAO;AAC9B,UAAI,CAAC,gBAAgB;AACnB,yBAAiB,qBAAqB,SAAS;AAAA,MACjD;AAAA,IACF;AAGA,UAAM,cAAc,WAAW,CAAC,CAAC,cAAc,WAAW;AAC1D,QAAI,aAAa;AACf,yBAAmB,sBAAsB,QAAQ,MAAM;AACrD,YAAI,iBAAiB,CAAC,WAAW;AAC/B,0BAAgB;AAChB,iBAAO;AAAA,QACT;AAEA,YAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,wBAAc,eAAe;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,cAAc,IAAI,IAAI,QAAS,mBAAmB,gBAAgB,SAAS,GAAI;AACjF,qBAAe,QAAQ,eAAe,aAAa;AAAA,IACrD;AAEA,iBAAa;AACb,cAAU,QAAQ,cAAc,OAAO,SAAS;AAEhD,QAAI,oBAAoB;AACtB,2BAAqB;AACrB,gBAAU,QAAQ,eAAe;AAAA,IACnC;AAGA,QAAI,iBAAiB,cAAc,OAAO;AACxC,YAAM,SAAS,cAAc,MAAM;AACnC,wBAAkB,CAAC,GAAG,cAAc,MAAM,GAAG;AAC7C,YAAM,MAAM,gBAAgB,eAAe,MAAM;AACjD,sBAAgB;AAChB,UAAI,WAAY,gBAAe,YAAY,KAAK,aAAa;AAC7D,UAAI,CAAC,YAAa,eAAc,eAAe;AAAA,IACjD;AACA,oBAAgB;AAAA,EAClB;AAEA,WAAS,OAAO,SAAwB;AACtC,kBAAc;AACd,UAAM,WAAW,qBAAqB;AACtC,QAAI,aAAa,YAAY;AAC3B,mBAAa;AACb,oBAAc,kBAAkB,UAAU;AAAA,IAC5C;AAGA,UAAM,aAAa,CAAC,oBAAoB,CAAC,qBAAqB;AAC9D,UAAM,YAAY,aAAa,oBAAoB,UAAU,IAAI;AAGjE,UAAM,eAAe,kBAAkB,gBAAgB,IAAI,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;AACtF,UAAM,mBAAmB,cAAc,OAAO,OAAO,WAAW;AAEhE,oBAAgB,QAAQ;AACxB,WAAO;AAGP,QACE,cACA,aACA,UAAU,OAAO,KACjB,cACA,cAAc,WAAW,QACzB;AACA,6BAAuB,qBAAqB,YAAY,WAAW;AAAA,QACjE,UAAU,cAAc,UAAU,OAAO;AAAA,MAC3C,CAAC;AAAA,IACH;AAGA,UAAM,YAAY,cAAc;AAChC,UAAM,eAAe,YAAY,UAAU,IAAI,IAAI,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;AAC9E,UAAM,mBAAmB,WAAW,OAAO,WAAW;AAEtD,QAAI,iBAAiB,gBAAgB,qBAAqB,kBAAkB;AAC1E,UAAI,WAAW;AACb,0BAAkB,CAAC,GAAG,UAAU,GAAG;AACnC,cAAM,MAAM,gBAAgB,eAAe,UAAU,MAAM;AAC3D,oBAAY,KAAK,qBAAqB,IAAI,IAAI,YAAY,MAAM;AAChE,sBAAc,eAAe;AAAA,MAC/B,WAAW,iBAAiB,MAAM;AAChC,0BAAkB;AAClB,cAAM,MAAM,gBAAgB,eAAe,IAAI;AAC/C,oBAAY,KAAK,qBAAqB,IAAI,IAAI,YAAY,MAAM;AAChE,sBAAc,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,QAAI,UAAW;AAGf,QAAI,kBAAkB;AACpB,sBAAgB;AAChB;AAAA,IACF;AAEA,oBAAgB,QAAQ;AACxB,WAAO;AAIP,QAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,sBAAgB,cAAc;AAC9B,UAAI,WAAY,gBAAe,YAAY,eAAe,aAAa;AAAA,IACzE,WAAW,cAAc,OAAO;AAC9B,wBAAkB,CAAC,GAAG,cAAc,MAAM,GAAG;AAC7C,sBAAgB,gBAAgB,eAAe,cAAc,MAAM,MAAM;AACzE,UAAI,WAAY,gBAAe,YAAY,eAAe,aAAa;AAAA,IACzE;AACA,kBAAc,eAAe;AAAA,EAC/B;AAMA,WAAS,YACP,QACA,UAC0C;AAC1C,QAAI,CAAC,WAAY,QAAO;AAExB,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,UAAU,UAAU;AAAA,MAC7B,KAAK;AACH,eAAO,mBAAmB,UAAU;AAAA,MACtC,KAAK;AACH,eAAO,UAAU,YAAY,QAA4B;AAAA,MAC3D,KAAK;AACH,eAAO,UAAU,YAAY,QAA4B;AAAA,MAC3D;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAMA,WAAS,UAAgB;AACvB,QAAI,UAAW;AACf,gBAAY;AAGZ,QAAI,kBAAkB;AACpB,uBAAiB,UAAU;AAC3B,uBAAiB;AACjB,yBAAmB;AAAA,IACrB;AACA,QAAI,sBAAsB;AACxB,2BAAqB,OAAO;AAC5B,6BAAuB;AAAA,IACzB;AACA,QAAI,aAAa;AACf,kBAAY,OAAO;AACnB,oBAAc;AAAA,IAChB;AAGA,QAAI,sBAAsB;AACxB,2BAAqB;AACrB,6BAAuB;AAAA,IACzB;AAGA,QAAI,YAAY;AACd,iBAAW,OAAO;AAClB,mBAAa;AAAA,IACf;AAGA,UAAM,SAAS,UAAU,cAAc,cAAc;AACrD,QAAI,OAAQ,QAAO,OAAO;AAG1B,QAAI,gBAAgB;AAClB,qBAAe,QAAQ;AACvB,uBAAiB;AAAA,IACnB;AAGA,QAAI,kBAAkB;AACpB,uBAAiB;AACjB,yBAAmB;AAAA,IACrB;AAGA,cAAU,UAAU,OAAO,eAAe,SAAS;AAAA,EACrD;AAMA,MAAI,gBAAgB,SAAS,QAAQ,GAAG;AACtC,cAAU,UAAU,IAAI,SAAS;AAAA,EACnC;AAGA,kBAAgB,QAAQ;AACxB,SAAO,IAAI;AAGX,QAAME,gBAAe;AAAA,IACnB;AAAA,IACA,MAAM,CAAC;AAAA,IACP,MAAM;AACJ,2BAAqB;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AACA,YAAU,QAAQ,eAAeA,gBAAe,YAAY;AAG5D,MAAI,SAAS,eAAe,OAAO;AACjC,uBAAmB,cAAc,WAAW,MAAM;AAChD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,IAAI,SAAoB;AACtB,aAAO;AAAA,IACT;AAAA,IACA,OAAO,WAAqD,MAA+B;AACzF,YAAM,MAAM,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AAC7D,YAAM,SAAS,uBAAuB,eAAe,KAAK,MAAM,WAAW,EAAE;AAC7E,UAAI,CAAC,QAAQ;AACX,gBAAQ,KAAK,kDAAkD,IAAI,KAAK,IAAI,CAAC,EAAE;AAC/E;AAAA,MACF;AACA,wBAAkB;AAClB,YAAM,MAAM,gBAAgB,eAAe,MAAM;AACjD,kBAAY,KAAK,MAAM,YAAY,YAAY,MAAM;AACrD,oBAAc,GAAG;AACjB,qBAAe,GAAG;AAAA,IACpB;AAAA,IACA,MAAM,WAA4B,MAA+B;AAC/D,YAAM,SAAS,uBAAuB,eAAe,CAAC,SAAS,GAAG,MAAM,WAAW,EAAE;AACrF,UAAI,CAAC,QAAQ;AACX,gBAAQ,KAAK,+CAA+C,SAAS,EAAE;AACvE;AAAA,MACF;AACA,YAAM,MAAc;AAAA,QAClB,IAAI,OAAO,IAAI,OAAO,QAAQ;AAAA,QAC9B,IAAI,OAAO,IAAI,OAAO,SAAS;AAAA,QAC/B,GAAG,cAAc;AAAA,MACnB;AACA,kBAAY,KAAK,MAAM,YAAY,YAAY,MAAM;AACrD,qBAAe,CAAC,SAAS,CAAC;AAAA,IAC5B;AAAA,IACA,UACE,QACA,MACM;AACN,wBAAkB;AAClB,YAAM,MAAM,gBAAgB,eAAe,UAAU,IAAI;AACzD,kBAAY,KAAK,MAAM,YAAY,YAAY,MAAM;AACrD,oBAAc,IAAI;AAAA,IACpB;AAAA,IACA,UAAU,MAA+B;AACvC,wBAAkB;AAClB,YAAM,MAAM,gBAAgB,eAAe,IAAI;AAC/C,kBAAY,KAAK,MAAM,YAAY,YAAY,MAAM;AACrD,oBAAc,IAAI;AAClB,qBAAe,IAAI;AAAA,IACrB;AAAA,IACA,YAAoB;AAClB,aAAO,EAAE,GAAG,cAAc;AAAA,IAC5B;AAAA,IACA,UAAU,QAAsB;AAC9B,sBAAgB;AAChB,wBAAkB;AAClB,UAAI,WAAY,gBAAe,YAAY,QAAQ,aAAa;AAAA,IAClE;AAAA,EACF;AACF;;;AanqBA,SAAS,SAAS,KAAwD;AACxE,QAAM,UAAU,IAAI,SAAS;AAC7B,QAAM,UAAU,IAAI,sBAAsB;AAC1C,SAAO;AAAA,IACL,QAAQ,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,IAC1E,QAAQ,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AAAA,EAChF;AACF;AAKA,SAAS,cACP,eACA,OAQA;AACA,QAAM,WAAW,OAAO,iBAAiB,aAAa;AAGtD,QAAM,cAAc;AAAA,IAClB,cAAc,aAAa,WAAW,KAAK,SAAS,YAAY;AAAA,EAClE;AACA,QAAM,gBAAgB,cAAc,MAAM;AAE1C,QAAM,aAAa,cAAc,aAAa,aAAa,KAAK,SAAS,cAAc;AACvF,QAAM,aAAa,cAAc,aAAa,aAAa,KAAK,SAAS,cAAc;AAGvF,QAAM,OACH,cAAqD,MAAM,iBAAiB,MAAM,KACnF,cAAc,aAAa,MAAM,KACjC,SAAS,SACT;AAGF,QAAM,aAAa,cAAc,aAAa,aAAa,KAAK;AAChE,MAAI,YAAY;AAChB,MAAI,eAAe,SAAU,aAAY;AAAA,WAChC,eAAe,MAAO,aAAY;AAE3C,SAAO;AAAA,IACL;AAAA,IACA,UAAU,GAAG,aAAa;AAAA,IAC1B;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,YAAY;AAAA,EACd;AACF;AAMA,SAASC,iBACP,eACA,KACA,WAC8D;AAC9D,QAAM,OAAQ,cAAqC,QAAQ;AAC3D,QAAM,QAAQ,SAAS,GAAG;AAC1B,QAAM,UAAU,IAAI,sBAAsB;AAC1C,QAAM,gBAAgB,UAAU,sBAAsB;AAGtD,QAAM,UAAU;AAChB,QAAM,OAAO,KAAK,IAAI,MAAM,UAAU,QAAQ,OAAO,cAAc,QAAQ;AAC3E,QAAM,MAAM,KAAK,IAAI,MAAM,UAAU,QAAQ,MAAM,cAAc,OAAO;AACxE,QAAM,QAAQ,KAAK,QAAQ,MAAM,SAAS,UAAU;AACpD,QAAM,SAAS,KAAK,SAAS,MAAM,SAAS,UAAU;AAEtD,SAAO;AAAA,IACL,KAAK,KAAK,IAAI,GAAG,GAAG;AAAA,IACpB,MAAM,KAAK,IAAI,GAAG,IAAI;AAAA,IACtB,OAAO,KAAK,IAAI,OAAO,EAAE;AAAA,IACzB,QAAQ,KAAK,IAAI,QAAQ,EAAE;AAAA,EAC7B;AACF;AAMO,SAAS,sBAAsB,QAAwD;AAC5F,QAAM,EAAE,WAAW,KAAK,eAAe,aAAa,UAAU,SAAS,IAAI;AAE3E,MAAI,YAAY;AAGhB,QAAM,kBAAkB,cAAc,aAAa,SAAS;AAC5D,gBAAc,aAAa,WAAW,GAAG;AAGzC,QAAM,QAAQ,SAAS,GAAG;AAC1B,QAAM,SAAS,cAAc,eAAe,KAAK;AACjD,QAAM,WAAWA,iBAAgB,eAAe,KAAK,SAAS;AAG9D,QAAM,WAAW,SAAS,cAAc,UAAU;AAClD,WAAS,QAAQ;AAGjB,QAAM,oBAAoB,OAAO,iBAAiB,SAAS,EAAE;AAC7D,QAAM,qBAAqB,sBAAsB;AACjD,MAAI,oBAAoB;AACtB,cAAU,MAAM,WAAW;AAAA,EAC7B;AAGA,SAAO,OAAO,SAAS,OAAO;AAAA,IAC5B,UAAU;AAAA,IACV,KAAK,GAAG,SAAS,GAAG;AAAA,IACpB,MAAM,GAAG,SAAS,IAAI;AAAA,IACtB,OAAO,GAAG,SAAS,KAAK;AAAA,IACxB,WAAW,GAAG,SAAS,MAAM;AAAA,IAC7B,YAAY,OAAO;AAAA,IACnB,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,IACnB,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,IACnB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,IACX,QAAQ;AAAA;AAAA,IAER,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACd,CAA2B;AAE3B,YAAU,YAAY,QAAQ;AAG9B,WAAS,MAAM;AACf,WAAS,OAAO;AAGhB,WAAS,UAAgB;AACvB,QAAI,UAAW;AACf,gBAAY;AAGZ,QAAI,oBAAoB,MAAM;AAC5B,oBAAc,aAAa,WAAW,eAAe;AAAA,IACvD,OAAO;AACL,oBAAc,gBAAgB,SAAS;AAAA,IACzC;AAGA,aAAS,oBAAoB,WAAW,aAAa;AACrD,aAAS,oBAAoB,aAAa,kBAAkB;AAC5D,mBAAe,WAAW;AAG1B,QAAI,oBAAoB;AACtB,gBAAU,MAAM,WAAW;AAAA,IAC7B;AAGA,QAAI,SAAS,YAAY;AACvB,eAAS,WAAW,YAAY,QAAQ;AAAA,IAC1C;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,QAAI,UAAW;AACf,UAAM,UAAU,SAAS;AACzB,YAAQ;AACR,aAAS,OAAO;AAAA,EAClB;AAEA,WAAS,SAAe;AACtB,QAAI,UAAW;AACf,YAAQ;AACR,aAAS;AAAA,EACX;AAGA,QAAM,gBAAgB,CAAC,MAAqB;AAC1C,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,QAAE,eAAe;AACjB,aAAO;AAAA,IACT,WAAW,EAAE,QAAQ,UAAU;AAC7B,QAAE,eAAe;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,WAAS,iBAAiB,WAAW,aAAa;AAGlD,QAAM,qBAAqB,CAAC,MAAkB;AAC5C,QAAI,CAAC,SAAS,SAAS,EAAE,MAAc,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,wBAAsB,MAAM;AAC1B,QAAI,CAAC,WAAW;AACd,eAAS,iBAAiB,aAAa,kBAAkB;AAAA,IAC3D;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,IAAI,eAAe,MAAM;AAC9C,QAAI,UAAW;AACf,UAAM,cAAcA,iBAAgB,eAAe,KAAK,SAAS;AACjE,aAAS,MAAM,MAAM,GAAG,YAAY,GAAG;AACvC,aAAS,MAAM,OAAO,GAAG,YAAY,IAAI;AACzC,aAAS,MAAM,QAAQ,GAAG,YAAY,KAAK;AAC3C,aAAS,MAAM,YAAY,GAAG,YAAY,MAAM;AAAA,EAClD,CAAC;AACD,iBAAe,QAAQ,SAAS;AAEhC,SAAO,EAAE,QAAQ;AACnB;;;ACnNA,IAAM,mBAAmB;AAGzB,SAAS,gBAAgB,QAAyB;AAChD,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AACnD,SAAO,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG;AAC7E;AAOO,SAAS,gBAAgB,SAAgD;AAC9E,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,MAAI,YAAY;AAChB,MAAI,WAAW;AACf,MAAI,SAAmC;AACvC,MAAI,QAA8B;AAElC,QAAM,WAAW,oBAAI,IAAoB;AACzC,MAAI,uBAA4C;AAMhD,WAAS,kBAAkB,IAAYC,QAA2B;AAChE,UAAM,UAAU,SAAS,gBAAgB,QAAQ,SAAS;AAC1D,YAAQ,aAAa,MAAM,EAAE;AAC7B,YAAQ,aAAa,gBAAgB,gBAAgB;AACrD,YAAQ,aAAa,SAAS,GAAG;AACjC,YAAQ,aAAa,UAAU,GAAG;AAClC,YAAQ,aAAa,oBAAoB,YAAY;AACrD,UAAM,OAAO,SAAS,gBAAgB,QAAQ,MAAM;AACpD,aAAS,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,QAAQA,QAAO,gBAAgB,EAAE,CAAC;AAC/E,SAAK,aAAa,kBAAkB,KAAK;AACzC,YAAQ,YAAY,IAAI;AACxB,WAAO;AAAA,EACT;AAGA,WAAS,mBAAmB,KAAoB,WAA2C;AAIzF,QAAI,WAAW;AACb,YAAM,UACJ,OAAO,QAAQ,eAAe,OAAO,IAAI,WAAW,aAChD,IAAI,OAAO,SAAS,IACpB,UAAU,QAAQ,MAAM,KAAK;AACnC,YAAM,QAAQ,IAAI,cAA8B,uBAAuB,OAAO,SAAS;AACvF,UAAI,MAAO,QAAO;AAAA,IACpB;AACA,WAAO,IAAI,cAA8B,oBAAoB;AAAA,EAC/D;AAEA,WAAS,OAAO,KAAwB,KAA0B;AAGhE,QAAI,cAAc,oBAAoB,GAAG,OAAO;AAEhD,UAAM,QAAQ,iBAAiB,GAAG;AAClC,UAAM,aAAa,oBAAoB,MAAM;AAC7C,UAAM,aAAa,SAAS,QAAQ;AAEpC,UAAM,EAAE,MAAM,MAAM,IAAI;AACxB,UAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,KAAK;AAG3D,UAAM,OAAO,iBAAiB,MAAM;AACpC,UAAM,YAAY,UAAU,cAAc;AAC1C,SAAK,YAAY,kBAAkB,WAAW,IAAI,SAAS,CAAC;AAK5D,UAAM,SAAS,UAAU,aAAa;AACtC,UAAM,WAAW,iBAAiB,UAAU;AAC5C,aAAS,aAAa,MAAM,MAAM;AAClC,UAAM,WAAW,iBAAiB,MAAM;AACxC,aAAS,UAAU;AAAA,MACjB,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,MACR,OAAO,WAAW,KAAK,QAAQ,KAAK,IAAI,GAAG,QAAQ,KAAK,CAAC;AAAA,MACzD,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,aAAS,aAAa,sBAAsB,MAAM;AAClD,aAAS,aAAa,SAAS,kBAAkB;AACjD,aAAS,YAAY,QAAQ;AAC7B,SAAK,YAAY,QAAQ;AACzB,UAAM,YAAY,IAAI;AAGtB,UAAM,SAAS,iBAAiB,MAAM;AACtC,aAAS,QAAQ;AAAA,MACf,GAAG;AAAA,MACH,GAAG,KAAK;AAAA,MACR,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,MAAM,QAAQ,SAAS;AAAA,IACzB,CAAC;AACD,WAAO,aAAa,SAAS,eAAe;AAC5C,WAAO,aAAa,mBAAmB,MAAM;AAC7C,WAAO,aAAa,kBAAkB,MAAM;AAC5C,QAAI,SAAU,QAAO,aAAa,mBAAmB,MAAM;AAC3D,UAAM,YAAY,MAAM;AAGxB,UAAM,WAAW,iBAAiB,MAAM;AACxC,aAAS,UAAU,EAAE,IAAI,OAAO,IAAI,KAAK,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI,KAAK,OAAO,CAAC;AACjF,aAAS,aAAa,SAAS,iBAAiB;AAChD,aAAS,aAAa,kBAAkB,MAAM;AAC9C,UAAM,YAAY,QAAQ;AAE1B,UAAM,eAAe,mBAAmB,KAAK,IAAI,eAAe;AAChE,QAAI,cAAc;AAChB,mBAAa,aAAa,aAAa,QAAQ,MAAM,GAAG;AAAA,IAC1D;AAGA,QAAI,IAAI,oBAAoB,IAAI,iBAAiB,SAAS,GAAG;AAC3D,YAAM,WAAW,iBAAiB,MAAM;AACxC,eAAS,UAAU,EAAE,GAAG,gBAAgB,IAAI,gBAAgB,GAAG,MAAM,OAAO,CAAC;AAC7E,eAAS,aAAa,SAAS,mBAAmB;AAClD,eAAS,aAAa,kBAAkB,MAAM;AAC9C,YAAM,YAAY,QAAQ;AAAA,IAC5B;AAGA,UAAM,YAAY,iBAAiB,MAAM;AACzC,aAAS,WAAW,EAAE,GAAG,IAAI,MAAM,OAAO,CAAC;AAC3C,cAAU,aAAa,SAAS,cAAc;AAC9C,cAAU,aAAa,uBAAuB,MAAM;AACpD,cAAU,aAAa,kBAAkB,MAAM;AAC/C,UAAM,YAAY,SAAS;AAG3B,QAAI,CAAC,UAAU;AACb,YAAM,UAAU,iBAAiB,MAAM;AACvC,eAAS,SAAS;AAAA,QAChB,GAAG;AAAA,QACH,GAAG,KAAK;AAAA,QACR,OAAO;AAAA,QACP,QAAQ,KAAK;AAAA,QACb,MAAM;AAAA,MACR,CAAC;AACD,cAAQ,aAAa,SAAS,gBAAgB;AAC9C,cAAQ,aAAa,oBAAoB,MAAM;AAC/C,cAAQ,aAAa,QAAQ,KAAK;AAClC,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MACF;AACA,cAAQ,MAAM,cAAc;AAC5B,cAAQ,MAAM,SAAS;AACvB,YAAM,YAAY,OAAO;AAAA,IAC3B;AAEA,QAAI,YAAY,KAAK;AAAA,EACvB;AAEA,WAAS,kBAAwB;AAC/B,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,MAAM,cAA8B,uBAAuB;AACxE,QAAI,CAAC,KAAM;AACX,UAAM,SAAkB,MAAM,KAAK,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AACjF,SAAK,aAAa,KAAK,gBAAgB,MAAM,CAAC;AAAA,EAChD;AAEA,WAAS,oBAAoB,IAA2B;AACtD,QAAI,CAAC,UAAU,OAAO,QAAQ,WAAW,EAAG,QAAO;AACnD,QAAI,YAAY,OAAO,QAAQ,CAAC,EAAE;AAClC,QAAI,OAAO,KAAK,IAAI,YAAY,EAAE;AAClC,eAAW,KAAK,OAAO,SAAS;AAC9B,YAAM,IAAI,KAAK,IAAI,EAAE,KAAK,EAAE;AAC5B,UAAI,IAAI,MAAM;AACZ,eAAO;AACP,oBAAY,EAAE;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,OAAO,IAAoB;AAClC,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,QAAQ,KAAK,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;AAAA,EACjF;AAMA,WAAS,kBAAkB,KAAgC;AACzD,UAAM,UAAU,IAAI,cAAc,oBAAoB;AACtD,QAAI,CAAC,QAAS,QAAO,MAAM;AAAA,IAAC;AAE5B,QAAI,WAAW;AAEf,UAAM,cAAc,CAAC,SAAiB,YAAoB;AACxD,YAAM,UAAU,IAAI,sBAAsB;AAC1C,YAAM,UAAU,IAAI,SAAS;AAC7B,YAAM,SAAS,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AACjF,YAAM,SAAS,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AACrF,aAAO;AAAA,QACL,OAAO,UAAU,QAAQ,QAAQ;AAAA,QACjC,OAAO,UAAU,QAAQ,OAAO;AAAA,MAClC;AAAA,IACF;AAEA,UAAM,UAAU,CAAC,SAAiB,YAAoB;AACpD,YAAM,EAAE,MAAM,KAAK,IAAI,YAAY,SAAS,OAAO;AACnD,YAAM,UAAU,oBAAoB,IAAI;AACxC,UAAI,YAAY,KAAM;AACtB,eAAS,IAAI,SAAS,OAAO,IAAI,CAAC;AAClC,sBAAgB;AAAA,IAClB;AAEA,UAAM,kBAAkB,CAAC,MAAa;AACpC,YAAM,KAAK;AACX,iBAAW;AACX,cAAQ,GAAG,SAAS,GAAG,OAAO;AAAA,IAChC;AACA,UAAM,kBAAkB,CAAC,MAAa;AACpC,UAAI,CAAC,SAAU;AACf,YAAM,KAAK;AACX,cAAQ,GAAG,SAAS,GAAG,OAAO;AAAA,IAChC;AACA,UAAM,gBAAgB,MAAM;AAC1B,iBAAW;AAAA,IACb;AAEA,UAAM,mBAAmB,CAAC,MAAa;AACrC,YAAM,KAAK;AACX,UAAI,GAAG,QAAQ,WAAW,EAAG;AAC7B,UAAI,GAAG,WAAY,IAAG,eAAe;AACrC,iBAAW;AACX,cAAQ,GAAG,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE,OAAO;AAAA,IACtD;AACA,UAAM,kBAAkB,CAAC,MAAa;AACpC,UAAI,CAAC,SAAU;AACf,YAAM,KAAK;AACX,UAAI,GAAG,QAAQ,WAAW,EAAG;AAC7B,UAAI,GAAG,WAAY,IAAG,eAAe;AACrC,cAAQ,GAAG,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE,OAAO;AAAA,IACtD;AACA,UAAM,iBAAiB,MAAM;AAC3B,iBAAW;AAAA,IACb;AAEA,YAAQ,iBAAiB,aAAa,eAAe;AACrD,aAAS,iBAAiB,aAAa,eAAe;AACtD,aAAS,iBAAiB,WAAW,aAAa;AAClD,YAAQ,iBAAiB,cAAc,kBAAkB,EAAE,SAAS,MAAM,CAAC;AAC3E,YAAQ,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,MAAM,CAAC;AACzE,YAAQ,iBAAiB,YAAY,cAAc;AACnD,YAAQ,iBAAiB,eAAe,cAAc;AAEtD,WAAO,MAAM;AACX,cAAQ,oBAAoB,aAAa,eAAe;AACxD,eAAS,oBAAoB,aAAa,eAAe;AACzD,eAAS,oBAAoB,WAAW,aAAa;AACrD,cAAQ,oBAAoB,cAAc,gBAAgB;AAC1D,cAAQ,oBAAoB,aAAa,eAAe;AACxD,cAAQ,oBAAoB,YAAY,cAAc;AACtD,cAAQ,oBAAoB,eAAe,cAAc;AAAA,IAC3D;AAAA,EACF;AAMA,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY;AACjB,OAAK,MAAM,UAAU;AACrB,OAAK,MAAM,WAAW;AAEtB,QAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,SAAO,YAAY;AAEnB,QAAM,eAAe,SAAS,cAAc,QAAQ;AACpD,eAAa,OAAO;AACpB,eAAa,YAAY;AAEzB,OAAK,OAAO,QAAQ,YAAY;AAChC,YAAU,MAAM,WAAW,UAAU,MAAM,YAAY;AACvD,YAAU,YAAY,IAAI;AAE1B,WAAS,eAAwB;AAC/B,WACE,OAAO,WAAW,eAClB,CAAC,CAAC,OAAO,cACT,OAAO,WAAW,kCAAkC,EAAE;AAAA,EAE1D;AAcA,WAAS,aAAa,IAAoB;AACxC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,MAAM,OAAO;AACnB,QAAI,CAAC,KAAK;AAGR,YAAM,OAAO,OAAO;AACpB,aAAO,KAAK,KAAK,KAAK,MAAM,KAAK,UAAU;AAAA,IAC7C;AACA,UAAM,OAAO,IAAI,cAAc,IAAI;AACnC,QAAI,SAAS,EAAG,QAAO,IAAI;AAC3B,UAAM,KAAK,KAAK,IAAI,YAAY;AAChC,WAAO,IAAI,UAAU,KAAK,IAAI,aAAa,IAAI;AAAA,EACjD;AAEA,WAAS,eAAyD;AAChE,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAM,YAAY,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACrE,WAAO,MAAM,KAAK,SAAS,QAAQ,CAAC,EACjC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,UAAU,IAAI,EAAE,KAAK,IAAI,GAAG,aAAa,EAAE,EAAE,EAAE;AAAA,EAC5E;AAEA,WAAS,WAAiB;AACxB,QAAI,aAAa,YAAY,CAAC,SAAS,CAAC,OAAQ;AAChD,eAAW;AAEX,UAAM,WAAW,MAAM,cAA8B,sBAAsB;AAC3E,QAAI,UAAU;AACZ,UAAI,aAAa,GAAG;AAClB,iBAAS,aAAa,SAAS,OAAO,OAAO,KAAK,KAAK,CAAC;AAAA,MAC1D,OAAO;AACL,iBAAS,UAAU,IAAI,qBAAqB;AAI5C,aAAK,SAAS,sBAAsB;AACpC,iBAAS,aAAa,SAAS,OAAO,OAAO,KAAK,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF;AACA,UAAM,SAAS,MAAM,cAA8B,mBAAmB;AACtE,YAAQ,aAAa,mBAAmB,MAAM;AAC9C,UAAM,cAAc,oBAAoB,GAAG,OAAO;AAClD,2BAAuB;AACvB,2BAAuB;AACvB,SAAK,UAAU,IAAI,iBAAiB;AACpC,WAAO,cAAc;AACrB,iBAAa,WAAW;AAExB,eAAW,aAAa,CAAC;AAAA,EAC3B;AAEA,eAAa,iBAAiB,SAAS,QAAQ;AAE/C,SAAO;AAAA,IACL,OAAO,KAAwB,KAA0B;AACvD,UAAI,UAAW;AACf,6BAAuB;AACvB,6BAAuB;AAEvB,eAAS;AACT,cAAQ;AAER,aAAO,KAAK,GAAG;AACf,sBAAgB;AAEhB,aAAO,cAAc,WAAW,KAAK,IAAI;AACzC,mBAAa,cAAc,IAAI;AAC/B,mBAAa,aAAa,cAAc,IAAI,WAAW;AACvD,mBAAa,MAAM,YAAY,GAAG,gBAAgB;AAClD,mBAAa,WAAW;AACxB,UAAI,SAAU,MAAK,UAAU,IAAI,iBAAiB;AAAA,UAC7C,MAAK,UAAU,OAAO,iBAAiB;AAI5C,YAAM,UAAU,IAAI,SAAS;AAC7B,YAAM,UAAU,IAAI,sBAAsB;AAC1C,YAAM,gBAAgB,UAAU,sBAAsB;AACtD,YAAM,SAAS,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AACjF,YAAM,SAAS,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AACrF,YAAM,cAAc,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,KAAK,QAAQ,IAAI,KAAK;AACvE,WAAK,MAAM,OAAO,GAAG,IAAI,QAAQ,UAAU,QAAQ,OAAO,cAAc,KAAK;AAC7E,WAAK,MAAM,MAAM,GAAG,IAAI,KAAK,IAAI,UAAU,QAAQ,MAAM,cAAc,IAAI;AAC3E,WAAK,MAAM,QAAQ,GAAG,cAAc,MAAM;AAC1C,WAAK,MAAM,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM;AAC/C,WAAK,MAAM,UAAU;AAErB,UAAI,CAAC,UAAU;AACb,+BAAuB,kBAAkB,GAAG;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,OAAa;AACX,WAAK,MAAM,UAAU;AACrB,aAAO,cAAc,oBAAoB,GAAG,OAAO;AACnD,6BAAuB;AACvB,6BAAuB;AAAA,IACzB;AAAA,IACA,SAAe;AACb,eAAS;AAAA,IACX;AAAA,IACA,QAAc;AACZ,UAAI,UAAW;AACf,iBAAW;AACX,eAAS,MAAM;AACf,mBAAa,WAAW;AACxB,WAAK,UAAU,OAAO,iBAAiB;AACvC,UAAI,UAAU,OAAO;AACnB,eAAO,QAAQ,KAAK;AACpB,eAAO,cAAc,OAAO;AAC5B,+BAAuB;AACvB,+BAAuB,kBAAkB,KAAK;AAAA,MAChD;AAAA,IACF;AAAA,IACA,IAAI,aAAsB;AACxB,aAAO;AAAA,IACT;AAAA,IACA,UAAgB;AACd,UAAI,UAAW;AACf,kBAAY;AACZ,6BAAuB;AACvB,6BAAuB;AACvB,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AACF;;;ACzcA,SAAS,mBAAAC,kBAAiB,aAAa,mBAAmB;AAC1D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACtBP,SAAS,iBACP,QACkE;AAClE,QAAM,MAAM,oBAAI,IAAiE;AAEjF,WAAS,IAAI,GAAG,IAAI,OAAO,MAAM,QAAQ,KAAK;AAC5C,UAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,YAAI,IAAI,QAAQ,KAAK,aAAa,CAAC,IAAI;AAAA,UACrC,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC;AAAA,UACxB,QAAQ,KAAK;AAAA,QACf,CAAC;AACD;AAAA,MACF,KAAK;AACH,YAAI,IAAI,QAAQ,KAAK,aAAa,CAAC,IAAI;AAAA,UACrC,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC;AAAA,UACxB,QAAQ,KAAK;AAAA,QACf,CAAC;AACD;AAAA,MACF,KAAK;AACH,YAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC;AACzC;AAAA,MACF,KAAK;AACH,YAAI,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC;AACxC;AAAA,MACF,KAAK;AACH,YAAI,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC;AAC1C;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,gBACd,KACA,QACA,iBACA,UACY;AACZ,QAAM,WAA8B,CAAC;AACrC,QAAM,cAAc,iBAAiB,MAAM;AAE3C,MAAI,SAAS,eAAe,SAAS,eAAe,SAAS,aAAa;AACxE,UAAM,eAAe,IAAI,iBAAiB,gBAAgB;AAE1D,eAAW,MAAM,cAAc;AAC7B,YAAM,SAAS,GAAG,aAAa,cAAc;AAC7C,UAAI,CAAC,OAAQ;AAEb,YAAM,WAAW,YAAY,IAAI,MAAM;AACvC,UAAI,CAAC,SAAU;AAEf,YAAM,SAAS,SAAS,UAAU,GAAG,aAAa,aAAa,KAAK;AAEpE,UAAI,SAAS,aAAa;AACxB,cAAM,cAAc,CAAC,MAAa;AAChC,gBAAM,aAAa;AACnB,gBAAM,UAAU,IAAI,sBAAsB;AAC1C,mBAAS,YAAa;AAAA,YACpB,OAAO,SAAS;AAAA,YAChB;AAAA,YACA,UAAU;AAAA,cACR,GAAG,WAAW,UAAU,QAAQ;AAAA,cAChC,GAAG,WAAW,UAAU,QAAQ;AAAA,YAClC;AAAA,YACA,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA,WAAG,iBAAiB,SAAS,WAAW;AACxC,iBAAS,KAAK,MAAM,GAAG,oBAAoB,SAAS,WAAW,CAAC;AAAA,MAClE;AAEA,UAAI,SAAS,aAAa;AACxB,cAAM,cAAc,CAAC,MAAa;AAChC,gBAAM,aAAa;AACnB,gBAAM,UAAU,IAAI,sBAAsB;AAC1C,mBAAS,YAAa;AAAA,YACpB,OAAO,SAAS;AAAA,YAChB;AAAA,YACA,UAAU;AAAA,cACR,GAAG,WAAW,UAAU,QAAQ;AAAA,cAChC,GAAG,WAAW,UAAU,QAAQ;AAAA,YAClC;AAAA,YACA,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA,WAAG,iBAAiB,cAAc,WAAW;AAC7C,iBAAS,KAAK,MAAM,GAAG,oBAAoB,cAAc,WAAW,CAAC;AAAA,MACvE;AAEA,UAAI,SAAS,aAAa;AACxB,cAAM,cAAc,MAAM;AACxB,mBAAS,YAAa;AAAA,QACxB;AACA,WAAG,iBAAiB,cAAc,WAAW;AAC7C,iBAAS,KAAK,MAAM,GAAG,oBAAoB,cAAc,WAAW,CAAC;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,mBAAmB;AAC9B,UAAM,qBAAqB,IAAI,iBAAiB,gBAAgB;AAEhE,aAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,KAAK;AAClD,YAAM,KAAK,mBAAmB,CAAC;AAC/B,YAAM,iBAAiB,gBAAgB,CAAC;AACxC,UAAI,CAAC,eAAgB;AAErB,YAAM,cAAc,CAAC,MAAa;AAChC,cAAM,aAAa;AACnB,iBAAS,kBAAmB,gBAAgB,UAAU;AAAA,MACxD;AAEA,SAAG,iBAAiB,SAAS,WAAW;AACxC,eAAS,KAAK,MAAM,GAAG,oBAAoB,SAAS,WAAW,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACzIA,SAAS,8BAA8B;AAgBvC,SAAS,QAAQ,GAAmB;AAClC,SAAO,KAAK,MAAM,CAAC;AACrB;AAEA,SAAS,oBAAoB,QAAoC;AAK/D,QAAM,QAAQ,oBAAI,IAAyB;AAC3C,QAAM,gBAAgB,oBAAI,IAA6B;AACvD,WAAS,IAAI,GAAG,IAAI,OAAO,MAAM,QAAQ,KAAK;AAC5C,UAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,SAAK,KAAK,SAAS,UAAU,KAAK,SAAS,WAAW,KAAK,YAAY,QAAQ;AAC7E,YAAM,MAAM,KAAK,aAAa;AAC9B,YAAM,eAAe,cAAc,IAAI,GAAG;AAC1C,UAAI,iBAAiB,UAAU,KAAK,SAAS,OAAQ;AACrD,YAAMC,SAAQ,KAAK,SAAS,SAAS,KAAK,SAAS,uBAAuB,KAAK,IAAI;AACnF,YAAM,YAAY,oBAAI,IAAyB;AAC/C,iBAAW,MAAM,KAAK,YAAY;AAChC,kBAAU,IAAI,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC;AAAA,MACxC;AACA,YAAM,IAAI,KAAK,EAAE,WAAW,KAAK,OAAAA,QAAO,UAAU,CAAC;AACnD,oBAAc,IAAI,KAAK,KAAK,IAAI;AAAA,IAClC;AAAA,EACF;AACA,SAAO,MAAM,KAAK,MAAM,OAAO,CAAC;AAClC;AAEA,SAAS,cAAc,QAAiC;AACtD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,QAAQ;AACtB,eAAW,KAAK,EAAE,UAAU,KAAK,EAAG,MAAK,IAAI,CAAC;AAAA,EAChD;AACA,SAAO,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAC9C;AAEA,SAAS,aAAa,UAAoB,GAA0B;AAClE,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,MAAI,KAAK;AACT,MAAI,KAAK,SAAS,SAAS;AAC3B,SAAO,KAAK,IAAI;AACd,UAAM,MAAO,KAAK,MAAO;AACzB,QAAI,SAAS,GAAG,IAAI,EAAG,MAAK,MAAM;AAAA,QAC7B,MAAK;AAAA,EACZ;AACA,QAAM,YAAY,SAAS,EAAE;AAC7B,MAAI,KAAK,GAAG;AACV,UAAM,OAAO,SAAS,KAAK,CAAC;AAC5B,QAAI,KAAK,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,YAAY,CAAC,EAAG,QAAO;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,kBACP,MACuB;AACvB,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,QAAQ,KAAK,CAAC,EAAE,MAAM,SAAS;AACrC,QAAM,SAAkE,CAAC;AAEzE,QAAM,UAAU,KAAK,SAAS;AAC9B,aAAW,EAAE,OAAO,MAAM,KAAK,MAAM;AACnC,UAAM,MAAM,MAAM;AAClB,QAAI,CAAC,IAAK;AACV,QAAI,SAAS;AACX,YAAM,SACJ,IAAI,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,KAAK,KACpD,IAAI,OAAO,IAAI,OAAO,SAAS,CAAC,KAChC;AACF,UAAI,CAAC,OAAQ;AACb,aAAO,KAAK;AAAA,QACV,OAAO,MAAM;AAAA,QACb,OAAO,OAAO;AAAA,QACd,OAAO,MAAM;AAAA,MACf,CAAC;AAAA,IACH,OAAO;AACL,iBAAW,KAAK,IAAI,QAAQ;AAC1B,eAAO,KAAK,EAAE,GAAG,GAAG,OAAO,EAAE,SAAS,MAAM,MAAM,CAAC;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,SAAO,EAAE,OAAO,OAAO;AACzB;AAQO,SAAS,yBACd,KACA,QACA,gBACY;AACZ,QAAM,UAAU,IAAI,cAAc,wBAAwB;AAC1D,MAAI,CAAC,QAAS,QAAO,MAAM;AAAA,EAAC;AAE5B,QAAM,SAAS,oBAAoB,MAAM;AACzC,MAAI,OAAO,WAAW,EAAG,QAAO,MAAM;AAAA,EAAC;AAEvC,QAAM,SAAS,cAAc,MAAM;AACnC,MAAI,OAAO,WAAW,EAAG,QAAO,MAAM;AAAA,EAAC;AAEvC,QAAM,YAAY,IAAI,cAAc,kBAAkB;AACtD,QAAM,YAAY,IAAI,cAAc,kBAAkB;AAEtD,QAAM,OAA2B,CAAC;AAClC,MAAI,WAAW;AACb,WAAO,UAAU,WAAY,WAAU,YAAY,UAAU,UAAU;AACvE,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,SAAS,gBAAgB,8BAA8B,QAAQ;AAC9E,aAAO,aAAa,KAAK,GAAG;AAC5B,aAAO,aAAa,QAAQ,OAAO,MAAM,OAAO,UAAU;AAC1D,aAAO,aAAa,UAAU,MAAM,KAAK;AACzC,aAAO,aAAa,gBAAgB,GAAG;AACvC,aAAO,aAAa,kBAAkB,MAAM;AAC5C,aAAO,MAAM,UAAU;AACvB,gBAAU,YAAY,MAAM;AAC5B,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,MAAc,OAAe,uBAAwC;AACvF,UAAM,WAAW,aAAa,QAAQ,IAAI;AAC1C,QAAI,aAAa,KAAM,QAAO;AAE9B,UAAM,OAA0D,CAAC;AACjE,QAAI,UAAU;AACd,QAAI,cAAc;AAClB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,QAAQ,OAAO,CAAC;AACtB,YAAM,QAAQ,MAAM,UAAU,IAAI,QAAQ;AAC1C,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,OAAO;AACT,aAAK,KAAK,EAAE,OAAO,MAAM,CAAC;AAC1B,mBAAW,MAAM;AACjB,uBAAe;AACf,YAAI,KAAK;AACP,cAAI,aAAa,MAAM,OAAO,MAAM,CAAC,CAAC;AACtC,cAAI,aAAa,MAAM,OAAO,MAAM,CAAC,CAAC;AACtC,cAAI,MAAM,UAAU;AAAA,QACtB;AAAA,MACF,WAAW,KAAK;AACd,YAAI,MAAM,UAAU;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,WAAW;AACb,gBAAU,aAAa,MAAM,OAAO,QAAQ,CAAC;AAC7C,gBAAU,aAAa,MAAM,OAAO,QAAQ,CAAC;AAC7C,gBAAU,MAAM,UAAU;AAAA,IAC5B;AAEA,UAAM,UAAU,kBAAkB,IAAI;AACtC,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,mBAAmB,WAAW;AACpC,UAAM,mBAAmB,cAAc,IAAK,UAAU,cAAe,qBAAqB;AAC1F,mBAAe,KAAK,SAAS,kBAAkB,kBAAkB;AAAA,MAC/D,WAAW;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,CAAC,SAAiB,YAAoB;AACxD,UAAM,QAAQ;AACd,UAAM,UAAU,MAAM,sBAAsB;AAC5C,UAAM,UAAU,MAAM,SAAS;AAC/B,UAAM,SAAS,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AACjF,UAAM,SAAS,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AACrF,UAAM,QAAQ,UAAU,QAAQ,QAAQ;AACxC,UAAM,QAAQ,UAAU,QAAQ,OAAO;AACvC,UAAM,qBAAqB,SAAS,IAAI,IAAI,SAAS;AACrD,WAAO,EAAE,MAAM,MAAM,mBAAmB;AAAA,EAC1C;AAEA,QAAM,kBAAkB,CAAC,MAAa;AACpC,UAAM,KAAK;AACX,UAAM,EAAE,MAAM,MAAM,mBAAmB,IAAI,YAAY,GAAG,SAAS,GAAG,OAAO;AAC7E,eAAW,MAAM,MAAM,kBAAkB;AAAA,EAC3C;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,UAAW,WAAU,MAAM,UAAU;AACzC,eAAW,OAAO,KAAM,KAAI,MAAM,UAAU;AAC5C,mBAAe,KAAK;AAAA,EACtB;AAEA,QAAM,cAAc,CAAC,MAAa;AAChC,UAAM,KAAK;AACX,QAAI,GAAG,QAAQ,WAAW,EAAG;AAC7B,UAAM,IAAI,GAAG,QAAQ,CAAC;AACtB,UAAM,EAAE,MAAM,MAAM,mBAAmB,IAAI,YAAY,EAAE,SAAS,EAAE,OAAO;AAC3E,QAAI,GAAG,WAAY,IAAG,eAAe;AACrC,eAAW,MAAM,MAAM,kBAAkB;AAAA,EAC3C;AAEA,UAAQ,iBAAiB,aAAa,eAAe;AACrD,UAAQ,iBAAiB,cAAc,OAAO;AAC9C,UAAQ,iBAAiB,cAAc,aAAa,EAAE,SAAS,MAAM,CAAC;AACtE,UAAQ,iBAAiB,aAAa,aAAa,EAAE,SAAS,MAAM,CAAC;AACrE,UAAQ,iBAAiB,YAAY,OAAO;AAE5C,SAAO,MAAM;AACX,YAAQ,oBAAoB,aAAa,eAAe;AACxD,YAAQ,oBAAoB,cAAc,OAAO;AACjD,YAAQ,oBAAoB,cAAc,WAAW;AACrD,YAAQ,oBAAoB,aAAa,WAAW;AACpD,YAAQ,oBAAoB,YAAY,OAAO;AAAA,EACjD;AACF;;;ACzNO,SAAS,kBAAkB,QAAgC;AAChE,QAAM,EAAE,SAAS,KAAK,QAAQ,OAAO,aAAa,YAAY,EAAE,IAAI;AACpE,QAAM,WAA8B,CAAC;AAErC,MAAI,qBAAuD;AAC3D,MAAI,mBAAqD;AACzD,MAAI,qBAAuD;AAC3D,MAAI,oBAAsD;AAC1D,MAAI,uBAAyD;AAE7D,WAASC,YAA+C;AACtD,UAAM,UAAU,IAAI,SAAS;AAC7B,UAAM,UAAU,IAAI,sBAAsB;AAC1C,WAAO;AAAA,MACL,QAAQ,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,MAC1E,QAAQ,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AAAA,IAChF;AAAA,EACF;AAEA,WAAS,UAAU,QAAgB,QAAsB;AACvD,gBAAY,IAAI;AAChB,UAAM,EAAE,QAAQ,OAAO,IAAIA,UAAS;AAEpC,YAAQ,MAAM,SAAS;AACvB,QAAI,MAAM,aAAa;AAEvB,UAAM,aAAa,CAAC,SAAiB,YAAoB;AACvD,YAAM,MAAM,UAAU,UAAU;AAChC,YAAM,MAAM,UAAU,UAAU;AAChC,aAAO,IAAI,EAAE;AAAA,IACf;AAEA,UAAM,sBAAsB,MAAM;AAChC,UAAI,oBAAoB;AACtB,iBAAS,oBAAoB,aAAa,kBAAkB;AAC5D,6BAAqB;AAAA,MACvB;AACA,UAAI,kBAAkB;AACpB,iBAAS,oBAAoB,WAAW,gBAAgB;AACxD,2BAAmB;AAAA,MACrB;AACA,UAAI,oBAAoB;AACtB,iBAAS,oBAAoB,aAAa,kBAAkB;AAC5D,6BAAqB;AAAA,MACvB;AACA,UAAI,mBAAmB;AACrB,iBAAS,oBAAoB,YAAY,iBAAiB;AAC1D,4BAAoB;AAAA,MACtB;AACA,UAAI,sBAAsB;AACxB,iBAAS,oBAAoB,eAAe,oBAAoB;AAChE,+BAAuB;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,YAAY,CAAC,SAAiB,YAAoB;AACtD,YAAM,MAAM,UAAU,UAAU;AAChC,YAAM,MAAM,UAAU,UAAU;AAChC,YAAM,QAAQ,KAAK,IAAI,EAAE,IAAI,aAAa,KAAK,IAAI,EAAE,IAAI;AAEzD,YAAM,IAAI,IAAI,KAAK;AAEnB,UAAI,OAAO;AACT,gBAAQ;AAAA,UACN;AAAA,UACA,CAAC,WAAW;AACV,mBAAO,gBAAgB;AAAA,UACzB;AAAA,UACA,EAAE,SAAS,MAAM,MAAM,KAAK;AAAA,QAC9B;AAAA,MACF;AAEA,cAAQ,MAAM,SAAS;AACvB,UAAI,MAAM,aAAa;AAEvB,0BAAoB;AACpB,kBAAY,KAAK;AAAA,IACnB;AAEA,UAAM,cAAc,CAAC,cAA0B;AAC7C,iBAAW,UAAU,SAAS,UAAU,OAAO;AAAA,IACjD;AACA,UAAM,YAAY,CAAC,YAAwB;AACzC,gBAAU,QAAQ,SAAS,QAAQ,OAAO;AAAA,IAC5C;AACA,aAAS,iBAAiB,aAAa,WAAW;AAClD,aAAS,iBAAiB,WAAW,SAAS;AAC9C,yBAAqB;AACrB,uBAAmB;AAEnB,UAAM,cAAc,CAAC,cAA0B;AAC7C,UAAI,UAAU,QAAQ,SAAS,GAAG;AAChC,kBAAU,eAAe;AACzB,mBAAW,UAAU,QAAQ,CAAC,EAAE,SAAS,UAAU,QAAQ,CAAC,EAAE,OAAO;AAAA,MACvE;AAAA,IACF;AACA,UAAM,aAAa,CAAC,aAAyB;AAC3C,YAAM,QAAQ,SAAS,eAAe,CAAC;AACvC,UAAI,OAAO;AACT,kBAAU,MAAM,SAAS,MAAM,OAAO;AAAA,MACxC,OAAO;AACL,kBAAU,QAAQ,MAAM;AAAA,MAC1B;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,aAAa,EAAE,SAAS,MAAM,CAAC;AACtE,aAAS,iBAAiB,YAAY,UAAU;AAChD,aAAS,iBAAiB,eAAe,UAAU;AACnD,yBAAqB;AACrB,wBAAoB;AACpB,2BAAuB;AAAA,EACzB;AAEA,QAAM,kBAAkB,CAAC,MAAa;AACpC,UAAM,aAAa;AACnB,eAAW,eAAe;AAC1B,cAAU,WAAW,SAAS,WAAW,OAAO;AAAA,EAClD;AAEA,QAAM,mBAAmB,CAAC,MAAa;AACrC,UAAM,aAAa;AACnB,QAAI,WAAW,QAAQ,WAAW,GAAG;AACnC,iBAAW,eAAe;AAC1B,gBAAU,WAAW,QAAQ,CAAC,EAAE,SAAS,WAAW,QAAQ,CAAC,EAAE,OAAO;AAAA,IACxE;AAAA,EACF;AAEA,UAAQ,iBAAiB,aAAa,eAAe;AACrD,UAAQ,iBAAiB,cAAc,kBAAkB,EAAE,SAAS,MAAM,CAAC;AAC3E,WAAS,KAAK,MAAM;AAClB,YAAQ,oBAAoB,aAAa,eAAe;AACxD,YAAQ,oBAAoB,cAAc,gBAAgB;AAAA,EAC5D,CAAC;AAED,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AACA,QAAI,oBAAoB;AACtB,eAAS,oBAAoB,aAAa,kBAAkB;AAC5D,2BAAqB;AAAA,IACvB;AACA,QAAI,kBAAkB;AACpB,eAAS,oBAAoB,WAAW,gBAAgB;AACxD,yBAAmB;AAAA,IACrB;AACA,QAAI,oBAAoB;AACtB,eAAS,oBAAoB,aAAa,kBAAkB;AAC5D,2BAAqB;AAAA,IACvB;AACA,QAAI,mBAAmB;AACrB,eAAS,oBAAoB,YAAY,iBAAiB;AAC1D,0BAAoB;AAAA,IACtB;AACA,QAAI,sBAAsB;AACxB,eAAS,oBAAoB,eAAe,oBAAoB;AAChE,6BAAuB;AAAA,IACzB;AACA,QAAI,MAAM,aAAa;AAAA,EACzB;AACF;;;AC7JO,SAAS,mBACd,KACA,iBACA,kBAGA,QACA,aACY;AACZ,QAAM,qBAAqB,IAAI,iBAAiB,qBAAqB;AACrE,QAAM,WAA8B,CAAC;AAErC,aAAW,MAAM,oBAAoB;AACnC,UAAM,WAAW,GAAG,aAAa,uBAAuB;AACxD,QAAI,aAAa,KAAM;AAEvB,UAAM,QAAQ,OAAO,QAAQ;AAC7B,UAAM,iBAAiB,gBAAgB,KAAK;AAC5C,QAAI,CAAC,kBAAkB,eAAe,SAAS,OAAQ;AAEvD,UAAM,iBAAiB;AACvB,UAAM,cAAc;AAEpB,gBAAY,MAAM,SAAS;AAE3B,UAAM,gBAAgB,YAAY,cAAc,8BAA8B;AAC9E,UAAM,SAAS,gBAAgB,OAAO,cAAc,aAAa,IAAI,CAAC,IAAI;AAC1E,UAAM,SAAS,gBAAgB,OAAO,cAAc,aAAa,IAAI,CAAC,IAAI;AAE1E,UAAM,aAAa,YAAY,cAAc,8BAA8B;AAC3E,UAAM,YAAY,YAAY,cAAc,kCAAkC;AAC9E,UAAM,qBAAqB,eAAe;AAE1C,UAAM,SAAS,eAAe,QAAQ,MAAM;AAC5C,UAAM,SAAS,eAAe,QAAQ,MAAM;AAE5C,UAAM,UAAU,kBAAkB;AAAA,MAChC,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,CAAC,IAAI,OAAO;AAClB,oBAAY,aAAa,aAAa,aAAa,EAAE,KAAK,EAAE,GAAG;AAE/D,YAAI,iBAAiB,CAAC,oBAAoB;AACxC,wBAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AACpD,wBAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AAAA,QACtD;AAEA,YAAI,oBAAoB;AACtB,cAAI,WAAY,YAAW,aAAa,WAAW,MAAM;AACzD,cAAI,UAAW,WAAU,aAAa,WAAW,MAAM;AAAA,QACzD;AAAA,MACF;AAAA,MACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,oBAAY,gBAAgB,WAAW;AAEvC,YAAI,iBAAiB,CAAC,oBAAoB;AACxC,wBAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAC/C,wBAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAAA,QACjD;AAEA,YAAI,oBAAoB;AACtB,cAAI,WAAY,YAAW,gBAAgB,SAAS;AACpD,cAAI,UAAW,WAAU,gBAAgB,SAAS;AAAA,QACpD;AAEA,YAAI,OAAO;AACT,gBAAM,YAA8B;AAAA,YAClC,IAAI,SAAS;AAAA,YACb,IAAI,SAAS;AAAA,UACf;AACA,6BAAmB,gBAAgB,SAAS;AAC5C,mBAAS,EAAE,MAAM,cAAc,YAAY,gBAAgB,QAAQ,UAAU,CAAC;AAAA,QAChF;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAED,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMO,SAAS,0BACd,KACA,iBACA,QACA,aACY;AACZ,QAAMC,UAAS;AACf,QAAM,WAA8B,CAAC;AACrC,QAAM,mBAAmB,IAAI,iBAAiB,qBAAqB;AAEnE,aAAW,MAAM,kBAAkB;AACjC,UAAM,cAAc;AACpB,UAAM,WAAW,YAAY,aAAa,uBAAuB;AACjE,QAAI,aAAa,KAAM;AAEvB,UAAM,QAAQ,OAAO,QAAQ;AAC7B,UAAM,iBAAiB,gBAAgB,KAAK;AAC5C,QAAI,CAAC,kBAAkB,eAAe,SAAS,OAAQ;AAEvD,UAAM,iBAAiB;AAEvB,UAAM,gBAAgB,YAAY,cAAc,8BAA8B;AAC9E,UAAM,aAAa,YAAY,cAAc,8BAA8B;AAC3E,QAAI,CAAC,iBAAiB,CAAC,WAAY;AAEnC,QAAI,OAAe,OAAe,KAAa;AAC/C,QAAI,eAAe;AACjB,cAAQ,OAAO,cAAc,aAAa,IAAI,CAAC,KAAK;AACpD,cAAQ,OAAO,cAAc,aAAa,IAAI,CAAC,KAAK;AACpD,YAAM,OAAO,cAAc,aAAa,IAAI,CAAC,KAAK;AAClD,YAAM,OAAO,cAAc,aAAa,IAAI,CAAC,KAAK;AAAA,IACpD,OAAO;AACL,YAAM,QAAQ,WAAY,aAAa,GAAG,KAAK;AAC/C,YAAM,SAAS,MAAM,MAAM,+BAA+B;AAC1D,cAAQ,SAAS,OAAO,OAAO,CAAC,CAAC,IAAI;AACrC,cAAQ,SAAS,OAAO,OAAO,CAAC,CAAC,IAAI;AAGrC,YAAM,YAAY,YAAY,cAAc,kCAAkC;AAC9E,YAAM,SAAS,WAAW,aAAa,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AACjE,YAAM,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,KAAK,OAAO,MAAM,GAAG;AAC/C,YAAM,OAAO,EAAE,KAAK;AACpB,YAAM,OAAO,EAAE,KAAK;AAAA,IACtB;AAEA,UAAM,YAAoE;AAAA,MACxE,EAAE,MAAM,QAAQ,IAAI,OAAO,IAAI,MAAM;AAAA,MACrC,EAAE,MAAM,MAAM,IAAI,KAAK,IAAI,IAAI;AAAA,IACjC;AAEA,UAAM,iBAAqC,CAAC;AAE5C,eAAW,MAAM,WAAW;AAC1B,UAAI,CAAC,OAAO,SAAS,GAAG,EAAE,KAAK,CAAC,OAAO,SAAS,GAAG,EAAE,EAAG;AAExD,YAAM,WAAW,SAAS,gBAAgBA,SAAQ,QAAQ;AAC1D,eAAS,aAAa,SAAS,qBAAqB;AACpD,eAAS,aAAa,iBAAiB,GAAG,IAAI;AAC9C,eAAS,aAAa,MAAM,OAAO,GAAG,EAAE,CAAC;AACzC,eAAS,aAAa,MAAM,OAAO,GAAG,EAAE,CAAC;AACzC,eAAS,aAAa,KAAK,GAAG;AAC9B,eAAS,aAAa,WAAW,GAAG;AACpC,eAAS,aAAa,QAAQ,cAAc;AAC5C,eAAS,aAAa,UAAU,cAAc;AAC9C,kBAAY,YAAY,QAAQ;AAChC,qBAAe,KAAK,QAAQ;AAE5B,YAAM,SAAS,GAAG;AAClB,YAAM,SAAS,GAAG;AAElB,YAAM,WAAW,CAAC,MAAa;AAC7B,UAAE,gBAAgB;AAAA,MACpB;AACA,eAAS,iBAAiB,aAAa,QAAQ;AAC/C,eAAS,iBAAiB,cAAc,QAAQ;AAChD,eAAS,KAAK,MAAM;AAClB,iBAAS,oBAAoB,aAAa,QAAQ;AAClD,iBAAS,oBAAoB,cAAc,QAAQ;AAAA,MACrD,CAAC;AAED,YAAM,UAAU,kBAAkB;AAAA,QAChC,SAAS;AAAA,QACT;AAAA,QACA,QAAQ,CAAC,IAAI,OAAO;AAClB,mBAAS,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AAC/C,mBAAS,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AAE/C,cAAI,eAAe;AACjB,gBAAI,GAAG,SAAS,QAAQ;AACtB,4BAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AACpD,4BAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AAAA,YACtD,OAAO;AACL,4BAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AACpD,4BAAc,aAAa,MAAM,OAAO,SAAS,EAAE,CAAC;AAAA,YACtD;AAAA,UACF;AAAA,QACF;AAAA,QACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,mBAAS,aAAa,MAAM,OAAO,MAAM,CAAC;AAC1C,mBAAS,aAAa,MAAM,OAAO,MAAM,CAAC;AAE1C,cAAI,eAAe;AACjB,gBAAI,GAAG,SAAS,QAAQ;AACtB,4BAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAC/C,4BAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAAA,YACjD,OAAO;AACL,4BAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAC/C,4BAAc,aAAa,MAAM,OAAO,MAAM,CAAC;AAAA,YACjD;AAAA,UACF;AAEA,cAAI,OAAO;AACT,kBAAM,iBAAiB,eAAe,kBAAkB,GAAG,IAAI;AAC/D,kBAAM,YAAY,gBAAgB,MAAM;AACxC,kBAAM,YAAY,gBAAgB,MAAM;AACxC,mBAAO;AAAA,cACL,MAAM;AAAA,cACN,YAAY;AAAA,cACZ,UAAU,GAAG;AAAA,cACb,QAAQ,EAAE,IAAI,YAAY,IAAI,IAAI,YAAY,GAAG;AAAA,YACnD,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA;AAAA,MACF,CAAC;AAED,eAAS,KAAK,OAAO;AAAA,IACvB;AAEA,UAAM,cAAc,MAAM;AACxB,iBAAW,KAAK,gBAAgB;AAC9B,UAAE,aAAa,WAAW,KAAK;AAAA,MACjC;AAAA,IACF;AACA,UAAM,cAAc,MAAM;AACxB,iBAAW,KAAK,gBAAgB;AAC9B,UAAE,aAAa,WAAW,GAAG;AAAA,MAC/B;AAAA,IACF;AAEA,gBAAY,iBAAiB,cAAc,WAAW;AACtD,gBAAY,iBAAiB,cAAc,WAAW;AACtD,aAAS,KAAK,MAAM;AAClB,kBAAY,oBAAoB,cAAc,WAAW;AACzD,kBAAY,oBAAoB,cAAc,WAAW;AACzD,iBAAW,KAAK,gBAAgB;AAC9B,UAAE,OAAO;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMO,SAAS,wBACd,KACA,iBACA,QACA,aACY;AACZ,QAAM,WAA8B,CAAC;AAErC,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AAEA,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS,IAAI,iBAAiB,QAAQ;AAE5C,eAAW,SAAS,QAAQ;AAC1B,YAAM,cAAc,MAAM,QAAQ,gBAAgB;AAClD,UAAI,CAAC,YAAa;AAElB,YAAM,WAAW,YAAY,aAAa,uBAAuB;AACjE,UAAI,aAAa,KAAM;AAEvB,YAAM,QAAQ,OAAO,QAAQ;AAC7B,YAAM,iBAAiB,gBAAgB,KAAK;AAC5C,UAAI,CAAC,eAAgB;AAErB,YAAM,UAAU;AAChB,cAAQ,MAAM,SAAS;AAEvB,YAAM,UAAU,eAAe,SAAS;AACxC,YAAM,sBAAsB,UACvB,eAAmC,cACnC,eAAqC;AAC1C,YAAM,cAAc,qBAAqB,MAAM;AAC/C,YAAM,cAAc,qBAAqB,MAAM;AAE/C,YAAM,UAAU,kBAAkB;AAAA,QAChC,SAAS;AAAA,QACT;AAAA,QACA,QAAQ,CAAC,IAAI,OAAO;AAClB,UAAC,QAA+C,MAAM,YACpD,aAAa,EAAE,OAAO,EAAE;AAAA,QAC5B;AAAA,QACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,UAAC,QAA+C,MAAM,YAAY;AAElE,cAAI,OAAO;AACT,gBAAI,SAAS;AACX,qBAAO;AAAA,gBACL,MAAM;AAAA,gBACN,YAAY;AAAA,gBACZ,aAAa,EAAE,IAAI,cAAc,IAAI,IAAI,cAAc,GAAG;AAAA,cAC5D,CAAC;AAAA,YACH,OAAO;AACL,qBAAO;AAAA,gBACL,MAAM;AAAA,gBACN,YAAY;AAAA,gBACZ,aAAa,EAAE,IAAI,cAAc,IAAI,IAAI,cAAc,GAAG;AAAA,cAC5D,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,MACF,CAAC;AAED,eAAS,KAAK,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMO,SAAS,eACd,KACA,MACA,QACA,aACY;AACZ,QAAM,cAAc,IAAI,iBAAiB,kCAAkC;AAC3E,QAAM,WAA8B,CAAC;AAErC,QAAM,eAAe,YAAY,OAAO,KAAK,SAAS;AAEtD,aAAW,MAAM,aAAa;AAC5B,UAAM,SAAS;AACf,UAAM,MAAM,OAAO,aAAa,iBAAiB;AACjD,QAAI,CAAC,IAAK;AAEV,UAAM,cAAc,eAAe,GAAG;AACtC,UAAM,iBACJ,OAAO,gBAAgB,YAAY,gBAAgB,OAAO,YAAY,SAAS;AACjF,UAAM,eAAe,gBAAgB,MAAM;AAC3C,UAAM,eAAe,gBAAgB,MAAM;AAE3C,WAAO,MAAM,SAAS;AAEtB,UAAM,UAAU,kBAAkB;AAAA,MAChC,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,CAAC,IAAI,OAAO;AAClB,QAAC,OAA8C,MAAM,YACnD,aAAa,EAAE,OAAO,EAAE;AAAA,MAC5B;AAAA,MACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,QAAC,OAA8C,MAAM,YAAY;AAEjE,YAAI,OAAO;AACT,iBAAO;AAAA,YACL,MAAM;AAAA,YACN;AAAA,YACA,MAAM,OAAO,eAAe;AAAA,YAC5B,QAAQ,EAAE,IAAI,eAAe,IAAI,IAAI,eAAe,GAAG;AAAA,UACzD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAED,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMO,SAAS,eACd,KACA,MACA,QACA,aACY;AAGZ,QAAM,UAAU,IAAI,cAAc,kCAAkC;AACpE,MAAI,CAAC,QAAS,QAAO,MAAM;AAAA,EAAC;AAE5B,QAAM,WAA8B,CAAC;AAErC,QAAM,eAAe,YAAY,OAAO,KAAK,SAAS;AACtD,QAAM,eAAe,cAAc,QAAQ,MAAM;AACjD,QAAM,eAAe,cAAc,QAAQ,MAAM;AAEjD,UAAQ,MAAM,SAAS;AAEvB,QAAM,UAAU,kBAAkB;AAAA,IAChC,SAAS;AAAA,IACT;AAAA,IACA,QAAQ,CAAC,IAAI,OAAO;AAClB,MAAC,QAA+C,MAAM,YACpD,aAAa,EAAE,OAAO,EAAE;AAAA,IAC5B;AAAA,IACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,MAAC,QAA+C,MAAM,YAAY;AAElE,UAAI,OAAO;AACT,eAAO,EAAE,MAAM,UAAU,QAAQ,EAAE,IAAI,eAAe,IAAI,IAAI,eAAe,GAAG,EAAE,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,IACA;AAAA,EACF,CAAC;AAED,WAAS,KAAK,OAAO;AAErB,SAAO,MAAM;AACX,eAAWC,YAAW,UAAU;AAC9B,MAAAA,SAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMO,SAAS,oBACd,KACA,MACA,QACA,aACY;AACZ,QAAM,SAAS,IAAI,iBAAiB,gBAAgB;AACpD,QAAM,WAA8B,CAAC;AAErC,QAAM,YAAY,YAAY,OAAO,KAAK,SAAS;AACnD,QAAM,eAAe,OAAO,cAAc,WAAW,YAAY;AAEjE,aAAW,SAAS,QAAQ;AAC1B,UAAM,UAAU;AAChB,UAAM,SACJ,QAAQ,aAAa,aAAa,KAClC,QAAQ,QAAQ,eAAe,GAAG,aAAa,aAAa;AAC9D,QAAI,CAAC,OAAQ;AAEb,UAAM,uBAAuB,cAAc,UAAU,MAAM;AAC3D,UAAM,eAAe,sBAAsB,MAAM;AACjD,UAAM,eAAe,sBAAsB,MAAM;AAEjD,YAAQ,MAAM,SAAS;AAEvB,UAAM,UAAU,kBAAkB;AAAA,MAChC,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,CAAC,IAAI,OAAO;AAClB,QAAC,QAA+C,MAAM,YACpD,aAAa,EAAE,OAAO,EAAE;AAAA,MAC5B;AAAA,MACA,OAAO,CAAC,IAAI,IAAI,UAAU;AACxB,QAAC,QAA+C,MAAM,YAAY;AAElE,YAAI,OAAO;AACT,iBAAO;AAAA,YACL,MAAM;AAAA,YACN;AAAA,YACA,QAAQ,EAAE,IAAI,eAAe,IAAI,IAAI,eAAe,GAAG;AAAA,UACzD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAED,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;AC1fO,SAAS,gBACd,KACA,WACA,oBACA,gBACA,QACY;AACZ,YAAU,aAAa,YAAY,GAAG;AACtC,YAAU,aAAa,wBAAwB,OAAO;AACtD,YAAU,aAAa,cAAc,OAAO,KAAK,OAAO;AAExD,QAAM,eAA6B,CAAC;AACpC,QAAM,aAAa,IAAI,iBAAiB,gBAAgB;AACxD,aAAW,MAAM,YAAY;AAC3B,UAAM,SAAS,GAAG,aAAa,cAAc;AAC7C,QAAI,UAAU,mBAAmB,IAAI,MAAM,GAAG;AAC5C,mBAAa,KAAK,EAAgB;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,aAAa;AAEjB,WAAS,cAAc,OAAqB;AAC1C,QAAI,cAAc,KAAK,aAAa,aAAa,QAAQ;AACvD,mBAAa,UAAU,EAAE,UAAU,OAAO,iBAAiB;AAC3D,mBAAa,UAAU,EAAE,gBAAgB,eAAe;AAAA,IAC1D;AAEA,iBAAa;AAEb,QAAI,cAAc,KAAK,aAAa,aAAa,QAAQ;AACvD,YAAM,KAAK,aAAa,UAAU;AAClC,SAAG,UAAU,IAAI,iBAAiB;AAClC,SAAG,aAAa,iBAAiB,MAAM;AAAA,IACzC;AAAA,EACF;AAEA,WAAS,wBAA8B;AACrC,QAAI,aAAa,KAAK,cAAc,aAAa,OAAQ;AAEzD,UAAM,KAAK,aAAa,UAAU;AAClC,UAAM,SAAS,GAAG,aAAa,cAAc;AAC7C,QAAI,CAAC,OAAQ;AAEb,UAAM,UAAU,mBAAmB,IAAI,MAAM;AAC7C,QAAI,CAAC,QAAS;AAEd,UAAM,OAAO,GAAG,sBAAsB;AACtC,UAAM,gBAAgB,UAAU,sBAAsB;AACtD,UAAM,IAAI,KAAK,OAAO,KAAK,QAAQ,IAAI,cAAc;AACrD,UAAM,IAAI,KAAK,MAAM,cAAc;AACnC,mBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,EACnC;AAEA,QAAM,gBAAgB,CAAC,MAAqB;AAC1C,QAAI,aAAa,WAAW,EAAG;AAE/B,YAAQ,EAAE,KAAK;AAAA,MACb,KAAK;AAAA,MACL,KAAK,aAAa;AAChB,UAAE,eAAe;AACjB,cAAM,OAAO,aAAa,aAAa,SAAS,IAAI,aAAa,IAAI;AACrE,sBAAc,IAAI;AAClB,8BAAsB;AACtB;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK,WAAW;AACd,UAAE,eAAe;AACjB,cAAM,OAAO,aAAa,IAAI,aAAa,IAAI,aAAa,SAAS;AACrE,sBAAc,IAAI;AAClB,8BAAsB;AACtB;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK,KAAK;AACR,UAAE,eAAe;AACjB,YAAI,cAAc,GAAG;AACnB,gCAAsB;AAAA,QACxB,WAAW,aAAa,SAAS,GAAG;AAClC,wBAAc,CAAC;AACf,gCAAsB;AAAA,QACxB;AACA;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,UAAE,eAAe;AACjB,uBAAe,KAAK;AACpB,sBAAc,EAAE;AAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,YAAU,iBAAiB,WAAW,aAAa;AAEnD,SAAO,MAAM;AACX,cAAU,oBAAoB,WAAW,aAAa;AACtD,cAAU,gBAAgB,UAAU;AACpC,cAAU,gBAAgB,sBAAsB;AAChD,cAAU,gBAAgB,YAAY;AAAA,EACxC;AACF;;;ACxGO,SAAS,sBACd,KACA,SACA,cACA,gBACA,QACY;AAOZ,QAAM,gBAAgB,IAAI;AAAA,IACxB;AAAA,EACF;AACA,QAAM,WAA8B,CAAC;AAErC,aAAW,SAAS,eAAe;AACjC,QAAI,MAAM,aAAa,sBAAsB,MAAM,OAAQ;AAE3D,UAAM,cAAc,MAAM;AACxB,YAAM,QAAQ,MAAM,aAAa,mBAAmB;AACpD,UAAI,CAAC,MAAO;AAEZ,YAAM,YAAY,aAAa,KAAK;AACpC,uBAAiB,OAAO,CAAC,SAAS;AAClC,eAAS,EAAE,MAAM,iBAAiB,QAAQ,OAAO,QAAQ,UAAU,CAAC;AAAA,IACtE;AAEA,UAAM,iBAAiB,SAAS,WAAW;AAC3C,aAAS,KAAK,MAAM,MAAM,oBAAoB,SAAS,WAAW,CAAC;AAAA,EACrE;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACnCA,SAAS,kBAAkB;AAKpB,SAAS,iBAAiB,KAAiB,KAAoC;AACpF,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK,cAAc;AACjB,UAAI,IAAI,IAAI;AACV,cAAM,OAAO,IAAI,cAAc,wBAAwB,IAAI,EAAE,IAAI;AACjE,YAAI,KAAM,QAAO;AAAA,MACnB;AACA,aAAO,IAAI,cAAc,2BAA2B,IAAI,KAAK,IAAI;AAAA,IACnE;AAAA,IACA,KAAK;AACH,aAAO,IAAI,cAAc,qBAAqB,IAAI,GAAG,IAAI;AAAA,IAC3D,KAAK;AACH,aAAO,IAAI,cAAc,+BAA+B,IAAI,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,IAKxE,KAAK;AACH,aAAO,IAAI,cAAc,kCAAkC;AAAA,IAC7D,KAAK;AACH,aAAO,IAAI;AAAA,QACT,wDAAwD,IAAI,KAAK;AAAA,MACnE;AAAA,EACJ;AACF;AAKO,SAAS,gBACd,SACA,kBACmB;AACnB,QAAM,eAAe,QAAQ,QAAQ,yBAAyB;AAC9D,MAAI,cAAc;AAChB,UAAM,QAAQ,OAAO,aAAa,aAAa,uBAAuB,CAAC;AACvE,UAAM,KAAK,aAAa,aAAa,oBAAoB,KAAK;AAC9D,WAAO,WAAW,WAAW,OAAO,EAAE;AAAA,EACxC;AAEA,QAAM,WAAW,QAAQ,QAAQ,mBAAmB;AACpD,MAAI,UAAU;AACZ,UAAM,MAAM,SAAS,aAAa,iBAAiB;AACnD,QAAI,IAAK,QAAO,WAAW,OAAO,GAAG;AAAA,EACvC;AAEA,QAAM,gBAAgB,QAAQ,QAAQ,6BAA6B;AACnE,MAAI,eAAe;AACjB,UAAM,SAAS,cAAc,aAAa,aAAa;AACvD,QAAI,OAAQ,QAAO,WAAW,YAAY,MAAM;AAAA,EAClD;AAEA,QAAM,gBAAgB,QAAQ,QAAQ,qBAAqB;AAC3D,MAAI,eAAe;AACjB,UAAM,QAAQ,OAAO,cAAc,aAAa,mBAAmB,CAAC;AACpE,UAAM,SAAS,cAAc,aAAa,mBAAmB,KAAK;AAClE,WAAO,WAAW,YAAY,QAAQ,KAAK;AAAA,EAC7C;AAKA,QAAM,WAAW,QAAQ,QAAQ,YAAY;AAC7C,MAAI,YAAY,CAAC,SAAS,UAAU,SAAS,iBAAiB,EAAG,QAAO,WAAW,OAAO;AAE1F,SAAO;AACT;AAKO,SAAS,oBACd,MACA,QACc;AACd,QAAM,OAAqB,CAAC;AAE5B,QAAM,aAA0B,CAAC,SAAS,YAAY,UAAU,UAAU,QAAQ;AAClF,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,OAAO,GAAG,GAAG;AACtB,WAAK,KAAK,WAAW,OAAO,GAAG,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,cACJ,iBAAiB,QAAQ,MAAM,QAAQ,KAAK,WAAW,IAAI,KAAK,cAAc,CAAC;AACjF,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,SAAK,KAAK,WAAW,WAAW,GAAG,YAAY,CAAC,EAAE,EAAE,CAAC;AAAA,EACvD;AAEA,QAAM,eAAyB,CAAC;AAChC,aAAW,QAAQ,OAAO,OAAO;AAC/B,QAAI,KAAK,SAAS,UAAU,KAAK,OAAO,WAAW,KAAK,WAAW;AACjE,mBAAa,KAAK,KAAK,SAAS;AAAA,IAClC;AAAA,EACF;AACA,eAAa,KAAK;AAClB,aAAW,UAAU,cAAc;AACjC,SAAK,KAAK,WAAW,YAAY,MAAM,CAAC;AAAA,EAC1C;AAEA,MAAI,aAAa,OAAO,UAAU,OAAO,OAAO,QAAQ,SAAS,GAAG;AAClE,SAAK,KAAK,WAAW,OAAO,CAAC;AAAA,EAC/B;AAEA,SAAO;AACT;AAKO,SAAS,eAAe,KAAiB,iBAAwC;AACtF,MAAI,IAAI,SAAS,SAAU,QAAO;AAClC,MAAI,IAAI,SAAS,cAAc;AAC7B,UAAM,aAAa,gBAAgB,IAAI,KAAK;AAC5C,WAAO,YAAY,SAAS;AAAA,EAC9B;AACA,SAAO;AACT;AAKO,SAAS,eACd,KACA,MACe;AACf,MAAI,IAAI,SAAS,UAAU;AACzB,UAAM,eAAe,YAAY,OAAO,KAAK,SAAS;AACtD,QAAI,CAAC,aAAc,QAAO;AAC1B,UAAM,QAAQ,aAAa,IAAI,GAAG;AAClC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,OAAO;AAClE,aAAQ,MAA2B;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AACA,MAAI,IAAI,SAAS,cAAc;AAC7B,UAAM,cACJ,iBAAiB,QAAQ,MAAM,QAAQ,KAAK,WAAW,IAAI,KAAK,cAAc,CAAC;AACjF,UAAM,aAAa,YAAY,IAAI,KAAK;AACxC,QAAI,YAAY,SAAS,OAAQ,QAAQ,WAA8B,QAAQ;AAC/E,QAAI,YAAY,MAAO,QAAO,WAAW;AACzC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,UAAU,GAAsB,GAA+B;AAC7E,MAAI,MAAM,QAAQ,MAAM,KAAM,QAAO,MAAM;AAC3C,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,UAAQ,EAAE,MAAM;AAAA,IACd,KAAK,cAAc;AACjB,YAAM,QAAQ;AACd,UAAI,EAAE,MAAM,MAAM,GAAI,QAAO,EAAE,OAAO,MAAM;AAC5C,aAAO,EAAE,UAAU,MAAM;AAAA,IAC3B;AAAA,IACA,KAAK;AACH,aAAO,EAAE,QAAS,EAAe;AAAA,IACnC,KAAK;AACH,aAAO,EAAE,WAAY,EAAe;AAAA,IACtC,KAAK;AACH,aAAO;AAAA,IACT,KAAK,gBAAgB;AACnB,YAAM,SAAS;AACf,aAAO,EAAE,UAAU,OAAO,SAAS,EAAE,WAAW,OAAO;AAAA,IACzD;AAAA,EACF;AACF;AAKO,SAAS,uBACd,KACA,KACA,QACoB;AACpB,QAAM,SAAS,iBAAiB,KAAK,GAAG;AACxC,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,OAAQ,OAA8B,QAAQ;AACpD,QAAM,UAAU;AAEhB,QAAM,cAAc,OAAO,MAAM,OAAO,cAAc,CAAC,KAAK;AAE5D,QAAM,IAAI,SAAS,gBAAgB,8BAA8B,GAAG;AACpE,IAAE,aAAa,SAAS,sBAAsB;AAE9C,QAAM,OAAO,SAAS,gBAAgB,8BAA8B,MAAM;AAC1E,OAAK,aAAa,KAAK,OAAO,KAAK,IAAI,OAAO,CAAC;AAC/C,OAAK,aAAa,KAAK,OAAO,KAAK,IAAI,OAAO,CAAC;AAC/C,OAAK,aAAa,SAAS,OAAO,KAAK,QAAQ,UAAU,CAAC,CAAC;AAC3D,OAAK,aAAa,UAAU,OAAO,KAAK,SAAS,UAAU,CAAC,CAAC;AAC7D,OAAK,aAAa,MAAM,GAAG;AAC3B,OAAK,aAAa,QAAQ,aAAa;AACvC,OAAK,aAAa,UAAU,WAAW;AACvC,OAAK,aAAa,gBAAgB,KAAK;AACvC,OAAK,aAAa,kBAAkB,MAAM;AAE1C,IAAE,YAAY,IAAI;AAClB,MAAI,YAAY,CAAC;AAEjB,SAAO;AACT;AAKO,SAAS,wBACd,QACA,WACyB;AACzB,QAAM,OAAO,OAAO,KAAK;AACzB,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AAEvC,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,YAAY;AAClB,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,QAAQ;AACpB,QAAM,MAAM,SAAS;AACrB,QAAM,MAAM,UAAU;AACtB,QAAM,MAAM,SAAS;AACrB,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,WAAW;AACvB,QAAM,MAAM,aAAa;AACzB,QAAM,MAAM,cAAc;AAC1B,QAAM,aAAa,QAAQ,OAAO;AAClC,QAAM,aAAa,cAAc,eAAe,OAAO,KAAK,OAAO,EAAE;AAErE,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,YAAY,SAAS,cAAc,IAAI;AAC7C,UAAM,UAAU,KAAK,CAAC;AACtB,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,SAAS,cAAc,IAAI;AACtC,SAAG,cAAc,OAAO,UAAU,EAAE;AACpC,SAAG,aAAa,SAAS,KAAK;AAC9B,gBAAU,YAAY,EAAE;AAAA,IAC1B;AACA,UAAM,YAAY,SAAS;AAC3B,UAAM,YAAY,KAAK;AAAA,EACzB;AAEA,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,KAAK,SAAS,cAAc,IAAI;AACtC,YAAM,QAAQ,KAAK,CAAC;AACpB,iBAAW,QAAQ,OAAO;AACxB,cAAM,KAAK,SAAS,cAAc,IAAI;AACtC,WAAG,cAAc,OAAO,QAAQ,EAAE;AAClC,WAAG,YAAY,EAAE;AAAA,MACnB;AACA,YAAM,YAAY,EAAE;AAAA,IACtB;AACA,UAAM,YAAY,KAAK;AAAA,EACzB;AAEA,YAAU,YAAY,KAAK;AAC3B,SAAO;AACT;;;AChRO,SAAS,kBACd,KACA,oBACA,gBACY;AACZ,QAAM,eAAe,IAAI,iBAAiB,gBAAgB;AAC1D,QAAM,WAA8B,CAAC;AAErC,aAAW,MAAM,cAAc;AAC7B,UAAM,SAAS,GAAG,aAAa,cAAc;AAC7C,QAAI,CAAC,OAAQ;AAEb,UAAM,UAAU,mBAAmB,IAAI,MAAM;AAC7C,QAAI,CAAC,QAAS;AAEd,UAAM,mBAAmB,CAAC,MAAa;AACrC,YAAM,aAAa;AACnB,YAAM,UAAU,IAAI,sBAAsB;AAC1C,YAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,YAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,qBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,IACnC;AAEA,UAAM,kBAAkB,CAAC,MAAa;AACpC,YAAM,aAAa;AACnB,YAAM,UAAU,IAAI,sBAAsB;AAC1C,YAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,YAAM,IAAI,WAAW,UAAU,QAAQ;AACvC,qBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,IACnC;AAEA,UAAM,mBAAmB,MAAM;AAC7B,qBAAe,KAAK;AAAA,IACtB;AAEA,UAAM,mBAAmB,CAAC,MAAa;AACrC,YAAM,aAAa;AACnB,UAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,cAAM,QAAQ,WAAW,QAAQ,CAAC;AAClC,cAAM,UAAU,IAAI,sBAAsB;AAC1C,cAAM,IAAI,MAAM,UAAU,QAAQ;AAClC,cAAM,IAAI,MAAM,UAAU,QAAQ;AAClC,uBAAe,KAAK,SAAS,GAAG,CAAC;AAAA,MACnC;AAAA,IACF;AAEA,OAAG,iBAAiB,cAAc,gBAAgB;AAClD,OAAG,iBAAiB,aAAa,eAAe;AAChD,OAAG,iBAAiB,cAAc,gBAAgB;AAClD,OAAG,iBAAiB,cAAc,gBAAgB;AAElD,aAAS,KAAK,MAAM;AAClB,SAAG,oBAAoB,cAAc,gBAAgB;AACrD,SAAG,oBAAoB,aAAa,eAAe;AACnD,SAAG,oBAAoB,cAAc,gBAAgB;AACrD,SAAG,oBAAoB,cAAc,gBAAgB;AAAA,IACvD,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACX,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACpCA,IAAI,wBAAwB;AAE5B,IAAMC,UAAS;AAOf,SAAS,YAAY,GAA8C;AACjE,MAAI,SAAS;AACb,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,UAAM,IAAI,EAAE,CAAC,EACV,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,YAAY;AACf,eAAW,MAAM,GAAG;AAClB,gBAAU;AACV,UAAI,KAAK,CAAC;AAAA,IACZ;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,IAAI;AACvB;AAEA,SAAS,KAAK,GAAmB;AAC/B,SAAO,YAAY,CAAC,EAAE;AACxB;AAGA,SAAS,WAAW,MAAc,OAAgC;AAChE,QAAM,MAAM,SAAS,gBAAgBA,SAAQ,KAAK;AAClD,MAAI,aAAa,SAAS,OAAO,IAAI,CAAC;AACtC,MAAI,aAAa,UAAU,OAAO,IAAI,CAAC;AACvC,MAAI,aAAa,WAAW,WAAW;AACvC,MAAI,aAAa,QAAQ,MAAM;AAC/B,MAAI,aAAa,eAAe,MAAM;AACtC,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,SAAS,gBAAgBA,SAAQ,MAAM;AACpD,SAAK,aAAa,KAAK,CAAC;AACxB,SAAK,aAAa,UAAU,cAAc;AAC1C,SAAK,aAAa,gBAAgB,KAAK;AACvC,SAAK,aAAa,kBAAkB,OAAO;AAC3C,QAAI,YAAY,IAAI;AAAA,EACtB;AACA,SAAO;AACT;AAOO,SAAS,mBAAmB,SAAsD;AACvF,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,QAAM,KAAK,oBAAoB,EAAE,qBAAqB;AACtD,QAAM,YAAY,GAAG,EAAE;AAEvB,MAAI,SAAmB,CAAC;AACxB,MAAI,WAAqB,CAAC;AAC1B,MAAI,UAAoB,CAAC;AACzB,MAAI,cAAc;AAClB,MAAI,OAAO;AACX,MAAI,YAAY;AAMhB,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY;AACjB,OAAK,MAAM,UAAU;AAErB,QAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,QAAM,YAAY;AAElB,QAAM,MAAM,SAAS,cAAc,KAAK;AACxC,MAAI,YAAY;AAEhB,QAAM,OAAO,WAAW,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,EACF,CAAC;AACD,OAAK,UAAU,IAAI,uBAAuB;AAE1C,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,YAAY;AAClB,QAAM,OAAO;AACb,QAAM,aAAa,QAAQ,UAAU;AACrC,QAAM,aAAa,iBAAiB,OAAO;AAC3C,QAAM,aAAa,iBAAiB,SAAS;AAC7C,QAAM,aAAa,qBAAqB,MAAM;AAC9C,QAAM,aAAa,iBAAiB,SAAS;AAC7C,QAAM,eAAe;AACrB,QAAM,aAAa;AAEnB,QAAM,UAAU,SAAS,cAAc,IAAI;AAC3C,UAAQ,YAAY;AACpB,UAAQ,KAAK;AACb,UAAQ,aAAa,QAAQ,SAAS;AACtC,UAAQ,SAAS;AAEjB,MAAI,OAAO,MAAM,OAAO,OAAO;AAC/B,OAAK,OAAO,OAAO,GAAG;AAGtB,YAAU,MAAM,WAAW,UAAU,MAAM,YAAY;AAGvD,YAAU,aAAa,MAAM,UAAU,UAAU;AAMjD,WAAS,iBAA2B;AAClC,UAAM,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC;AACjC,UAAM,YAAY,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,SAAS,CAAC,CAAC;AAC5D,QAAI,CAAC,EAAG,QAAO;AACf,UAAM,SAAmB,CAAC;AAC1B,UAAM,YAAsB,CAAC;AAC7B,eAAW,KAAK,WAAW;AACzB,YAAM,MAAM,KAAK,CAAC,EAAE,QAAQ,CAAC;AAC7B,UAAI,QAAQ,EAAG,QAAO,KAAK,CAAC;AAAA,eACnB,MAAM,EAAG,WAAU,KAAK,CAAC;AAAA,IACpC;AACA,WAAO,CAAC,GAAG,QAAQ,GAAG,SAAS;AAAA,EACjC;AAGA,WAAS,iBAAiB,IAAmB,OAAqB;AAChE,UAAM,IAAI,KAAK,MAAM,MAAM,KAAK,CAAC;AACjC,QAAI,CAAC,GAAG;AACN,SAAG,cAAc;AACjB;AAAA,IACF;AACA,UAAM,EAAE,QAAQ,IAAI,IAAI,YAAY,KAAK;AACzC,UAAM,MAAM,OAAO,QAAQ,CAAC;AAC5B,QAAI,MAAM,GAAG;AACX,SAAG,cAAc;AACjB;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,GAAG;AACrB,UAAM,MAAM,MAAM,EAAE,SAAS,OAAO,SAAS,IAAI,MAAM,EAAE,MAAM,IAAI,MAAM;AACzE,OAAG,OAAO,SAAS,eAAe,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC;AACxD,UAAM,QAAQ,SAAS,cAAc,MAAM;AAC3C,UAAM,YAAY;AAClB,UAAM,cAAc,MAAM,MAAM,OAAO,GAAG;AAC1C,OAAG,OAAO,OAAO,SAAS,eAAe,MAAM,MAAM,GAAG,CAAC,CAAC;AAAA,EAC5D;AAMA,WAAS,cAAoB;AAC3B,UAAM,cAAc;AACpB,eAAW,SAAS,UAAU;AAC5B,YAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,WAAK,YAAY;AACjB,WAAK,OAAO,SAAS,eAAe,KAAK,CAAC;AAE1C,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,OAAO;AACd,aAAO,YAAY;AACnB,aAAO,aAAa,cAAc,UAAU,KAAK,EAAE;AACnD,aAAO,YAAY,WAAW,GAAG,CAAC,cAAc,YAAY,CAAC,CAAC;AAC9D,aAAO,iBAAiB,SAAS,MAAM;AACrC,oBAAY,KAAK;AACjB,cAAM,MAAM;AAAA,MACd,CAAC;AAED,WAAK,YAAY,MAAM;AACvB,YAAM,YAAY,IAAI;AAAA,IACxB;AAAA,EACF;AAEA,WAAS,aAAmB;AAC1B,cAAU,eAAe;AACzB,QAAI,eAAe,QAAQ,OAAQ,eAAc,QAAQ,SAAS;AAClE,YAAQ,cAAc;AAEtB,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,QAAQ,SAAS,cAAc,IAAI;AACzC,YAAM,YAAY;AAClB,YAAM,aAAa,QAAQ,cAAc;AACzC,YAAM,cAAc;AACpB,cAAQ,YAAY,KAAK;AACzB,YAAM,gBAAgB,uBAAuB;AAC7C;AAAA,IACF;AAEA,YAAQ,QAAQ,CAAC,OAAO,MAAM;AAC5B,YAAM,KAAK,SAAS,cAAc,IAAI;AACtC,SAAG,YAAY;AACf,SAAG,KAAK,GAAG,EAAE,QAAQ,CAAC;AACtB,SAAG,aAAa,QAAQ,QAAQ;AAChC,SAAG,aAAa,iBAAiB,OAAO,MAAM,WAAW,CAAC;AAC1D,uBAAiB,IAAI,KAAK;AAC1B,SAAG,iBAAiB,SAAS,MAAM,YAAY,KAAK,CAAC;AACrD,cAAQ,YAAY,EAAE;AAAA,IACxB,CAAC;AAED,QAAI,eAAe,GAAG;AACpB,YAAM,aAAa,yBAAyB,GAAG,EAAE,QAAQ,WAAW,EAAE;AACtE,YAAM,WAAW,QAAQ,SAAS,WAAW;AAC7C,gBAAU,iBAAiB,EAAE,OAAO,UAAU,CAAC;AAAA,IACjD,OAAO;AACL,YAAM,gBAAgB,uBAAuB;AAAA,IAC/C;AAAA,EACF;AAEA,WAAS,WAAiB;AACxB,QAAI,KAAM;AACV,WAAO;AACP,YAAQ,SAAS;AACjB,UAAM,aAAa,iBAAiB,MAAM;AAAA,EAC5C;AAEA,WAAS,YAAkB;AACzB,QAAI,CAAC,KAAM;AACX,WAAO;AACP,kBAAc;AACd,YAAQ,SAAS;AACjB,UAAM,aAAa,iBAAiB,OAAO;AAC3C,UAAM,gBAAgB,uBAAuB;AAAA,EAC/C;AAMA,WAAS,YAAY,OAAqB;AACxC,QAAI,CAAC,SAAS,SAAS,KAAK,EAAG,UAAS,KAAK,KAAK;AAClD,UAAM,QAAQ;AACd,cAAU;AACV,gBAAY;AACZ,aAAS,CAAC,GAAG,QAAQ,CAAC;AAAA,EACxB;AAEA,WAAS,YAAY,OAAqB;AACxC,UAAM,MAAM,SAAS,QAAQ,KAAK;AAClC,QAAI,MAAM,EAAG;AACb,aAAS,OAAO,KAAK,CAAC;AACtB,gBAAY;AACZ,aAAS,CAAC,GAAG,QAAQ,CAAC;AAAA,EACxB;AAMA,QAAM,iBAAiB,SAAS,MAAM;AACpC,aAAS;AACT,kBAAc,eAAe,EAAE,SAAS,IAAI,IAAI;AAChD,eAAW;AAAA,EACb,CAAC;AAED,QAAM,iBAAiB,WAAW,CAAC,MAAqB;AACtD,YAAQ,EAAE,KAAK;AAAA,MACb,KAAK;AAAA,MACL,KAAK,WAAW;AACd,UAAE,eAAe;AACjB,cAAM,UAAU;AAChB,iBAAS;AACT,YAAI,CAAC,SAAS;AACZ,oBAAU,eAAe;AACzB,wBAAc,QAAQ,SAAS,IAAI,IAAI;AAAA,QACzC,WAAW,QAAQ,SAAS,GAAG;AAC7B,gBAAM,QAAQ,EAAE,QAAQ,cAAc,IAAI;AAC1C,yBAAe,cAAc,QAAQ,QAAQ,UAAU,QAAQ;AAAA,QACjE;AACA,mBAAW;AACX;AAAA,MACF;AAAA,MACA,KAAK,SAAS;AACZ,YAAI,QAAQ,eAAe,KAAK,cAAc,QAAQ,QAAQ;AAC5D,YAAE,eAAe;AACjB,sBAAY,QAAQ,WAAW,CAAC;AAAA,QAClC;AACA;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,YAAI,MAAM;AACR,YAAE,eAAe;AACjB,YAAE,gBAAgB;AAClB,oBAAU;AAAA,QACZ;AACA;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAChB,YAAI,MAAM,UAAU,MAAM,SAAS,SAAS,GAAG;AAC7C,sBAAY,SAAS,SAAS,SAAS,CAAC,CAAC;AAAA,QAC3C;AACA;AAAA,MACF;AAAA,MACA,KAAK,OAAO;AACV,kBAAU;AACV;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAGD,UAAQ,iBAAiB,aAAa,CAAC,MAAM,EAAE,eAAe,CAAC;AAG/D,OAAK,iBAAiB,YAAY,CAAC,MAAkB;AACnD,UAAM,OAAO,EAAE;AACf,QAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,EAAG,WAAU;AAAA,EAC/C,CAAC;AAMD,SAAO;AAAA,IACL,OAAO,MAA4B,KAAuB;AACxD,UAAI,UAAW;AACf,eAAS,KAAK;AACd,YAAM,cAAc,KAAK;AACzB,YAAM,aAAa,cAAc,KAAK,WAAW;AAIjD,YAAM,UAAW,IAAsB,SAAS;AAChD,YAAM,UAAU,IAAI,sBAAsB;AAC1C,YAAM,gBAAgB,UAAU,sBAAsB;AACtD,YAAM,SAAS,SAAS,SAAS,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AACjF,YAAM,SAAS,SAAS,UAAU,QAAQ,SAAS,QAAQ,SAAS,QAAQ,SAAS;AACrF,WAAK,MAAM,OAAO,GAAG,KAAK,IAAI,UAAU,QAAQ,OAAO,cAAc,KAAK;AAC1E,WAAK,MAAM,MAAM,GAAG,KAAK,IAAI,UAAU,QAAQ,MAAM,cAAc,IAAI;AACvE,WAAK,MAAM,QAAQ,GAAG,KAAK,QAAQ,MAAM;AACzC,WAAK,MAAM,SAAS,GAAG,KAAK,SAAS,MAAM;AAC3C,WAAK,MAAM,UAAU;AAErB,UAAI,KAAM,YAAW;AAAA,IACvB;AAAA,IACA,OAAa;AACX,WAAK,MAAM,UAAU;AACrB,gBAAU;AAAA,IACZ;AAAA,IACA,cAAwB;AACtB,aAAO,CAAC,GAAG,QAAQ;AAAA,IACrB;AAAA,IACA,YAAY,MAAsB;AAChC,iBAAW,CAAC,GAAG,IAAI;AACnB,kBAAY;AAAA,IACd;AAAA,IACA,UAAgB;AACd,UAAI,UAAW;AACf,kBAAY;AACZ,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AACF;;;AC7XA,SAAS,yBAAyB,uBAAuB;AAElD,SAAS,qBAAqB,IAAiB,OAA4B;AAChF,QAAM,SAAS,MAAM,OAAO,YAAY,CAAC,KAAK,gBAAgB,eAAe,OAAO;AACpF,QAAM,KACJ,MAAM,OAAO,eAAe,gBACxB,MAAM,SACJ,gBAAgB,WAAW,MAAM,IACjC,gBAAgB,WAAW,OAAO,IACpC,MAAM,OAAO;AAEnB,QAAM,QAA4B;AAAA,IAChC,CAAC,oBAAoB,MAAM,MAAM,MAAM;AAAA,IACvC,CAAC,kBAAkB,MAAM,MAAM,IAAI;AAAA,IACnC,CAAC,mBAAmB,GAAG,MAAM,OAAO,MAAM,QAAQ,IAAI;AAAA,IACtD,CAAC,qBAAqB,GAAG,MAAM,OAAO,MAAM,UAAU,EAAE;AAAA,IACxD,CAAC,sBAAsB,GAAG,MAAM,OAAO,SAAS,QAAQ,IAAI;AAAA,IAC5D,CAAC,wBAAwB,GAAG,MAAM,OAAO,SAAS,UAAU,EAAE;AAAA,IAC9D,CAAC,oBAAoB,GAAG,MAAM,OAAO,OAAO,QAAQ,IAAI;AAAA,IACxD,CAAC,sBAAsB,GAAG,MAAM,OAAO,OAAO,UAAU,EAAE;AAAA,IAC1D,CAAC,kBAAkB,GAAG,MAAM,MAAM,MAAM,IAAI,IAAI;AAAA,IAChD,CAAC,qBAAqB,GAAG,MAAM,OAAO,QAAQ,QAAQ,IAAI;AAAA,IAC1D,CAAC,uBAAuB,GAAG,MAAM,OAAO,QAAQ,UAAU,EAAE;AAAA,IAC5D,CAAC,WAAW,EAAE;AAAA,IACd,CAAC,aAAa,MAAM,OAAO,IAAI;AAAA,IAC/B,CAAC,mBAAmB,MAAM,OAAO,IAAI;AAAA,IACrC,CAAC,iBAAiB,MAAM,OAAO,QAAQ;AAAA,IACvC,CAAC,aAAa,MAAM,OAAO,IAAI;AAAA,IAC/B,CAAC,sBAAsB,GAAG,MAAM,YAAY,IAAI;AAAA,IAChD,CAAC,eAAe,MAAM;AAAA,IACtB,CAAC,sBAAsB,wBAAwB,MAAM,CAAC;AAAA,IACtD,CAAC,iBAAiB,MAAM,OAAO,QAAQ;AAAA,IACvC,CAAC,iBAAiB,MAAM,OAAO,QAAQ;AAAA,IACvC,CAAC,gBAAgB,GAAG,MAAM,QAAQ,YAAY,CAAC,IAAI;AAAA,IACnD,CAAC,gBAAgB,GAAG,MAAM,QAAQ,OAAO,IAAI;AAAA,EAC/C;AAEA,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO;AACjC,OAAG,MAAM,YAAY,MAAM,KAAK;AAAA,EAClC;AACF;;;ACZA,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAqBP,SAAS,cAAc,GAA+B;AACpD,MAAI,EAAE,GAAI,QAAO,MAAM,EAAE,EAAE;AAC3B,SAAO,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,QAAQ,EAAE;AACzC;AAOA,SAAS,eAAe,aAA6C;AACnE,QAAM,OAAO,oBAAI,IAAoB;AACrC,SAAO,YAAY,IAAI,CAAC,MAAM;AAC5B,UAAM,OAAO,cAAc,CAAC;AAC5B,UAAM,IAAI,KAAK,IAAI,IAAI,KAAK;AAC5B,SAAK,IAAI,MAAM,IAAI,CAAC;AACpB,WAAO,MAAM,IAAI,OAAO,GAAG,IAAI,IAAI,CAAC;AAAA,EACtC,CAAC;AACH;AAkCA,SAAS,SAAS,GAAmB;AACnC,QAAM,IAAI,IAAI;AACd,SAAO,IAAI,IAAI,IAAI;AACrB;AAOA,IAAM,uBAAuB,oBAAI,IAAI,CAAC,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAc9D,SAAS,uBAAuB,UAAmB,UAA4B;AACpF,QAAM,OAAO;AACb,QAAM,OAAO;AACb,MAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,SAAS,EAAE,UAAU,MAAO,QAAO;AACrE,QAAM,WACJ,OAAO,KAAK,SAAS,WAAW,KAAK,OAAQ,KAAK,MAAkC;AACtF,QAAM,WACJ,OAAO,KAAK,SAAS,WAAW,KAAK,OAAQ,KAAK,MAAkC;AACtF,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,CAAC,qBAAqB,IAAI,QAAkB,EAAG,QAAO;AAE1D,QAAM,UAAW,KAAgE;AACjF,QAAM,UAAW,KAAgE;AACjF,MAAI,CAAC,WAAW,CAAC,QAAS,QAAO;AACjC,SAAO,EACL,QAAQ,GAAG,UAAU,QAAQ,GAAG,SAChC,QAAQ,GAAG,SAAS,QAAQ,GAAG,QAC/B,QAAQ,GAAG,UAAU,QAAQ,GAAG,SAChC,QAAQ,GAAG,SAAS,QAAQ,GAAG,QAC/B,QAAQ,OAAO,UAAU,QAAQ,OAAO;AAE5C;AASO,SAAS,cAAc,MAOlB;AACV,QAAM,EAAE,YAAY,YAAY,UAAU,UAAU,eAAe,iBAAiB,IAAI;AAGxF,MAAI,CAAC,cAAc,CAAC,YAAY,cAAe,QAAO;AAGtD,MAAI,CAAC,WAAW,WAAW,OAAQ,QAAO;AAG1C,MAAI,CAAC,uBAAuB,UAAU,QAAQ,EAAG,QAAO;AAGxD,MAAI,WAAW,YAAY,YAAa,QAAO;AAG/C,MAAI,iBAAkB,QAAO;AAG7B,MACE,WAAW,WAAW,UAAU,WAAW,WAAW,SACtD,WAAW,WAAW,WAAW,WAAW,WAAW,QACvD;AACA,WAAO;AAAA,EACT;AAGA,MAAI,WAAW,MAAM,SAAS,IAAK,QAAO;AAG1C,MAAI,CAAC,iBAAiB,YAAY,UAAU,EAAG,QAAO;AAGtD,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,QAAI;AACF,UAAI,OAAO,WAAW,kCAAkC,EAAE,QAAS,QAAO;AAAA,IAC5E,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAaA,SAAS,iBAAiB,YAAyB,YAAkC;AACnF,SACE,mBAAmB,YAAY,UAAU,KACzC,gBAAgB,YAAY,UAAU,KACtC,qBAAqB,YAAY,UAAU;AAE/C;AAGA,SAAS,gBAAgB,YAAyB,YAAkC;AAClF,QAAM,YAAY,WAAW;AAC7B,QAAM,YAAY,WAAW;AAC7B,MAAI,UAAU,WAAW,UAAU,OAAQ,QAAO;AAElD,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,UAAU,CAAC;AACrB,QAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAQ,QAAO;AAAA,EACzD;AACA,SAAO;AACT;AAGA,SAAS,qBAAqB,YAAyB,YAAkC;AACvF,QAAM,OAAO,WAAW,eAAe,CAAC;AACxC,QAAM,OAAO,WAAW,eAAe,CAAC;AACxC,MAAI,KAAK,WAAW,KAAK,OAAQ,QAAO;AAExC,QAAM,WAAW,eAAe,IAAI;AACpC,QAAM,WAAW,eAAe,IAAI;AAEpC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,SAAS,CAAC,MAAM,SAAS,CAAC,EAAG,QAAO;AACxC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,OAAO,MAAM,EAAE,OAAO,EAAG,QAAO;AACnE,QAAI,EAAE,YAAY,EAAE,QAAS,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAGA,SAAS,mBAAmB,YAAyB,YAAkC;AACrF,QAAM,YAAY,WAAW;AAC7B,QAAM,YAAY,WAAW;AAE7B,MAAI,UAAU,WAAW,UAAU,OAAQ,QAAO;AAElD,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,UAAU,CAAC;AACrB,QAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAK,QAAO;AAEjD,QAAI,EAAE,SAAS,UAAU,EAAE,SAAS,QAAQ;AAC1C,UAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,OAAQ,QAAO;AAAA,IACzF,WAAW,EAAE,SAAS,UAAU,EAAE,SAAS,QAAQ;AACjD,UAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,OAAQ,QAAO;AACrE,eAAS,IAAI,GAAG,IAAI,EAAE,OAAO,QAAQ,KAAK;AACxC,YAAI,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAG,QAAO;AAAA,MACjF;AAAA,IACF,WAAW,EAAE,SAAS,UAAU,EAAE,SAAS,QAAQ;AACjD,UAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAAA,IAChC,WAAW,EAAE,SAAS,WAAW,EAAE,SAAS,SAAS;AACnD,UAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAG,QAAO;AAAA,IAC5D,WAAW,EAAE,SAAS,UAAU,EAAE,SAAS,QAAQ;AACjD,UAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAI,QAAO;AAAA,IAC/E,WAAW,EAAE,SAAS,UAAU,EAAE,SAAS,QAAQ;AACjD,UAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAG,QAAO;AAAA,IACzC,WAAW,EAAE,SAAS,cAAc,EAAE,SAAS,YAAY;AACzD,UAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAG,QAAO;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAiNA,SAAS,aAAa,GAAuB;AAC3C,SAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO;AAC5D;AAEA,SAAS,mBAAmB,IAAgB,MAAgB,MAAsB;AAChF,QAAM,UAAU,GAAG,cAAc,YAAY;AAC7C,MAAI,CAAC,QAAS;AAEd,QAAM,QAAQ,KAAK;AACnB,QAAM,iBACJ,CAAC,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,MAAM,CAAC,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC,KAAK;AAE1E,MAAI,kBAAkB,QAAQ,YAAY,QAAQ;AAChD,UAAM,WAAW,EAAE,GAAG,MAAM,GAAG,KAAK;AACpC,YAAQ,aAAa,KAAK,oBAAoB,UAAU,KAAK,CAAC;AAAA,EAChE,OAAO;AACL,YAAQ,aAAa,KAAK,OAAO,KAAK,CAAC,CAAC;AACxC,YAAQ,aAAa,KAAK,OAAO,KAAK,CAAC,CAAC;AACxC,YAAQ,aAAa,SAAS,OAAO,KAAK,KAAK,CAAC;AAChD,YAAQ,aAAa,UAAU,OAAO,KAAK,MAAM,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,SAAS,MAAgB,IAAc,GAAqB;AACnE,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK;AAAA,IAC9B,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK;AAAA,IAC9B,OAAO,KAAK,SAAS,GAAG,QAAQ,KAAK,SAAS;AAAA,IAC9C,QAAQ,KAAK,UAAU,GAAG,SAAS,KAAK,UAAU;AAAA,EACpD;AACF;AAMA,SAAS,UAAU,GAAU,GAAU,GAAkB;AACvD,SAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;AAC9D;AASO,SAAS,qBACd,YACA,YACA,UACA,UACoB;AAEpB,QAAM,aAAa,IAAI,IAAI,QAAQ;AAGnC,QAAM,YAAY,SAAS,OAAO,CAAC,MAAM,WAAW,IAAI,CAAC,CAAC;AAC1D,MAAI,UAAU,WAAW,GAAG;AAE1B,WAAO,CAAC,YAAY,UAAU;AAAA,EAChC;AAGA,QAAM,YAAY,oBAAI,IAAmB;AACzC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAU,IAAI,SAAS,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,EAC1C;AACA,QAAM,YAAY,oBAAI,IAAmB;AACzC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAU,IAAI,SAAS,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,EAC1C;AAGA,QAAM,SAAS,cAAc,UAAU,QAAQ;AAG/C,QAAM,cAAc,oBAAI,IAAoB;AAC5C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,gBAAY,IAAI,OAAO,CAAC,GAAG,CAAC;AAAA,EAC9B;AAEA,QAAM,UAAmB,CAAC;AAC1B,QAAM,QAAiB,CAAC;AAExB,aAAW,OAAO,QAAQ;AACxB,UAAM,SAAS,UAAU,IAAI,GAAG;AAChC,UAAM,SAAS,UAAU,IAAI,GAAG;AAEhC,QAAI,UAAU,QAAQ;AAEpB,cAAQ,KAAK,UAAU,IAAI,GAAG,CAAE;AAChC,YAAM,KAAK,UAAU,IAAI,GAAG,CAAE;AAAA,IAChC,WAAW,UAAU,CAAC,QAAQ;AAE5B,YAAM,SAAS,UAAU,IAAI,GAAG;AAChC,YAAM,KAAK,MAAM;AACjB,cAAQ,KAAK,sBAAsB,KAAK,QAAQ,aAAa,WAAW,WAAW,MAAM,CAAC;AAAA,IAC5F,WAAW,UAAU,CAAC,QAAQ;AAE5B,YAAM,SAAS,UAAU,IAAI,GAAG;AAChC,cAAQ,KAAK,MAAM;AACnB,YAAM,KAAK,oBAAoB,KAAK,QAAQ,aAAa,WAAW,WAAW,MAAM,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO,CAAC,SAAS,KAAK;AACxB;AAMA,SAAS,cAAc,UAAoB,UAA8B;AAEvE,QAAM,YAAY,oBAAI,IAAoB;AAC1C,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,EAAG,WAAU,IAAI,SAAS,CAAC,GAAG,CAAC;AAAA,EAC/D;AACA,QAAM,YAAY,oBAAI,IAAoB;AAC1C,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,EAAG,WAAU,IAAI,SAAS,CAAC,GAAG,CAAC;AAAA,EAC/D;AAEA,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,MAAI,KAAK;AACT,MAAI,KAAK;AAET,SAAO,KAAK,SAAS,UAAU,KAAK,SAAS,QAAQ;AACnD,UAAM,KAAK,SAAS,EAAE;AACtB,UAAM,KAAK,SAAS,EAAE;AAEtB,QAAI,MAAM,IAAI,EAAE,GAAG;AACjB;AACA;AAAA,IACF;AACA,QAAI,MAAM,IAAI,EAAE,GAAG;AACjB;AACA;AAAA,IACF;AAEA,QAAI,OAAO,IAAI;AACb,aAAO,KAAK,EAAE;AACd,YAAM,IAAI,EAAE;AACZ;AACA;AAAA,IACF,OAAO;AACL,YAAM,WAAW,UAAU,IAAI,EAAE,KAAK,UAAU,IAAI,EAAE,KAAM,KAAK,UAAU,IAAI,EAAE,IAAK;AACtF,YAAM,WAAW,UAAU,IAAI,EAAE,KAAK,UAAU,IAAI,EAAE,KAAM,KAAK,UAAU,IAAI,EAAE,IAAK;AAEtF,UAAI,aAAa,MAAM,aAAa,IAAI;AACtC,eAAO,KAAK,EAAE;AACd,cAAM,IAAI,EAAE;AACZ;AAAA,MACF,WAAW,aAAa,IAAI;AAC1B,eAAO,KAAK,EAAE;AACd,cAAM,IAAI,EAAE;AACZ;AAAA,MACF,WAAW,aAAa,IAAI;AAC1B,eAAO,KAAK,EAAE;AACd,cAAM,IAAI,EAAE;AACZ;AAAA,MACF,OAAO;AACL,YAAI,YAAY,UAAU;AACxB,iBAAO,KAAK,EAAE;AACd,gBAAM,IAAI,EAAE;AACZ;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,EAAE;AACd,gBAAM,IAAI,EAAE;AACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO,KAAK,SAAS,QAAQ;AAC3B,QAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,GAAG;AAC5B,aAAO,KAAK,SAAS,EAAE,CAAC;AACxB,YAAM,IAAI,SAAS,EAAE,CAAC;AAAA,IACxB;AACA;AAAA,EACF;AACA,SAAO,KAAK,SAAS,QAAQ;AAC3B,QAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,GAAG;AAC5B,aAAO,KAAK,SAAS,EAAE,CAAC;AACxB,YAAM,IAAI,SAAS,EAAE,CAAC;AAAA,IACxB;AACA;AAAA,EACF;AAEA,SAAO;AACT;AAQA,SAAS,sBACP,KACA,QACA,aACA,WACA,WACA,QACO;AACP,QAAM,MAAM,YAAY,IAAI,GAAG,KAAK;AAGpC,MAAI,YAA2B;AAC/B,WAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,QAAI,UAAU,IAAI,OAAO,CAAC,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,GAAG;AACxD,kBAAY,OAAO,CAAC;AACpB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAA0B;AAC9B,WAAS,IAAI,MAAM,GAAG,IAAI,OAAO,QAAQ,KAAK;AAC5C,QAAI,UAAU,IAAI,OAAO,CAAC,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,GAAG;AACxD,iBAAW,OAAO,CAAC;AACnB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,UAAU;AAEzB,UAAM,aAAa,UAAU,IAAI,SAAS;AAC1C,UAAM,YAAY,UAAU,IAAI,QAAQ;AACxC,UAAM,aAAa,UAAU,IAAI,SAAS;AAC1C,UAAM,YAAY,UAAU,IAAI,QAAQ;AAExC,UAAM,QAAQ,UAAU,IAAI,WAAW;AACvC,UAAM,IAAI,UAAU,IAAI,OAAO,OAAO,IAAI,WAAW,KAAK;AAC1D,WAAO,UAAU,YAAY,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,EACrE;AAEA,MAAI,WAAW;AAEb,WAAO,EAAE,GAAG,UAAU,IAAI,SAAS,EAAG;AAAA,EACxC;AAEA,MAAI,UAAU;AAEZ,WAAO,EAAE,GAAG,UAAU,IAAI,QAAQ,EAAG;AAAA,EACvC;AAGA,SAAO;AACT;AAMA,SAAS,oBACP,KACA,QACA,aACA,WACA,WACA,QACO;AACP,QAAM,MAAM,YAAY,IAAI,GAAG,KAAK;AAGpC,MAAI,YAA2B;AAC/B,WAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,QAAI,UAAU,IAAI,OAAO,CAAC,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,GAAG;AACxD,kBAAY,OAAO,CAAC;AACpB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAA0B;AAC9B,WAAS,IAAI,MAAM,GAAG,IAAI,OAAO,QAAQ,KAAK;AAC5C,QAAI,UAAU,IAAI,OAAO,CAAC,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,GAAG;AACxD,iBAAW,OAAO,CAAC;AACnB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,UAAU;AACzB,UAAM,aAAa,UAAU,IAAI,SAAS;AAC1C,UAAM,YAAY,UAAU,IAAI,QAAQ;AACxC,UAAM,aAAa,UAAU,IAAI,SAAS;AAC1C,UAAM,YAAY,UAAU,IAAI,QAAQ;AAExC,UAAM,QAAQ,UAAU,IAAI,WAAW;AACvC,UAAM,IAAI,UAAU,IAAI,OAAO,OAAO,IAAI,WAAW,KAAK;AAC1D,WAAO,UAAU,YAAY,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,EACrE;AAEA,MAAI,WAAW;AACb,WAAO,EAAE,GAAG,UAAU,IAAI,SAAS,EAAG;AAAA,EACxC;AAEA,MAAI,UAAU;AACZ,WAAO,EAAE,GAAG,UAAU,IAAI,QAAQ,EAAG;AAAA,EACvC;AAEA,SAAO;AACT;AAOA,SAAS,kBAAkB,SAAkB,OAAgB,GAAoB;AAC/E,QAAM,MAAM,KAAK,IAAI,QAAQ,QAAQ,MAAM,MAAM;AACjD,QAAM,SAAkB,IAAI,MAAM,GAAG;AACrC,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,WAAO,CAAC,IAAI,UAAU,QAAQ,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;AAAA,EAC/C;AACA,SAAO;AACT;AAGA,SAAS,cAAc,IAAgB,QAAiB,aAA4B;AAClF,QAAM,SAAS,GAAG,cAAc,MAAM;AACtC,MAAI,CAAC,OAAQ;AACb,SAAO,aAAa,KAAK,cAAc,QAAQ,WAAW,CAAC;AAC7D;AAGA,SAAS,eACP,IACA,WACA,cACA,aACA,WACM;AACN,QAAM,QAAQ,GAAG,iBAAiB,MAAM;AAExC,MAAI,MAAM,CAAC,GAAG;AACZ,UAAM,CAAC,EAAE,aAAa,KAAK,cAAc,WAAW,cAAc,WAAW,CAAC;AAAA,EAChF;AAEA,MAAI,aAAa,MAAM,CAAC,GAAG;AACzB,UAAM,CAAC,EAAE,aAAa,KAAK,cAAc,WAAW,WAAW,CAAC;AAAA,EAClE;AACF;AAGA,SAAS,mBAAmB,IAAgB,MAAsB;AAChE,QAAM,SAAS,GAAG,cAAc,MAAM;AACtC,MAAI,CAAC,UAAU,CAAC,KAAK,KAAM;AAC3B,SAAO,aAAa,KAAK,KAAK,IAAI;AACpC;AAGA,SAAS,oBAAoB,IAAgB,MAAsB;AACjE,QAAM,QAAQ,GAAG,iBAAiB,MAAM;AACxC,MAAI,MAAM,CAAC,GAAG;AACZ,UAAM,CAAC,EAAE,aAAa,KAAK,KAAK,IAAI;AAAA,EACtC;AACA,MAAI,MAAM,CAAC,KAAK,KAAK,SAAS;AAC5B,UAAM,CAAC,EAAE,aAAa,KAAK,KAAK,OAAO;AAAA,EACzC;AACF;AAMO,SAAS,cAAc,MAQT;AACnB,QAAM,EAAE,KAAK,YAAY,YAAY,WAAW,YAAY,aAAa,IAAI;AAC7E,QAAM,SAAS,UAAU;AACzB,QAAM,OAAO,UAAU,QAAQ,EAAE,GAAG,cAAc;AAGlD,QAAM,UAAU,KAAK,IAAI,OAAO,UAAU,KAAK,QAAQ;AACvD,QAAM,aAAa,MAAM,OAAO;AAChC,QAAM,gBAAgB,OAAO,WAAW;AAGxC,QAAM,iBAAiB,IAAI,cAAc,WAAW;AACpD,MAAI,CAAC,gBAAgB;AACnB,eAAW;AACX,WAAO;AAAA,MACL,SAAS;AAAA,MAAC;AAAA,MACV,IAAI,UAAU;AACZ,eAAO;AAAA,MACT;AAAA,MACA,WAAW;AACT,eAAO,oBAAI,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAkB,CAAC;AACzB,QAAM,SAAuB,CAAC;AAI9B,QAAM,OAAO,IAAI,cAAc,MAAM;AACrC,MAAI,mBAAmB,oBAAI,IAAoB;AAC/C,MAAI,MAAM;AAER,UAAM,aAAa,IAAI,IAAI,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAClF,UAAM,eAAe,WAAW,MAAM;AAAA,MACpC,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE,GAAG,KAAK,UAAU;AAAA,IACtD;AACA,UAAM,gBAAgB,aAAa;AAAA,MACjC,CAAC,MAAM,UAAU,KAAK,cAAe,EAAwB,IAAI;AAAA,IACnE;AACA,QAAI,cAAc,SAAS,GAAG;AAC5B,yBAAmB,kBAAkB,eAA4C,IAAI;AAAA,IACvF;AAAA,EACF;AAGA,QAAM,WACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC9C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChD,QAAM,WACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC9C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChD,QAAM,WACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC9C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChD,QAAM,YACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,KAC/C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AACjD,QAAM,WACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC9C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChD,QAAM,WACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC9C,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChD,QAAM,eACJ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,KAClD,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU;AAEpD,MAAI,UAAU;AACZ;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU;AACZ,oBAAgB,YAAY,YAAY,gBAAgB,QAAQ,QAAQ,YAAY;AAAA,EACtF;AACA,MAAI,UAAU;AACZ;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW;AACb;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU;AACZ,oBAAgB,YAAY,YAAY,gBAAgB,QAAQ,QAAQ,YAAY;AAAA,EACtF;AACA,MAAI,UAAU;AACZ,oBAAgB,YAAY,YAAY,gBAAgB,QAAQ,QAAQ,YAAY;AAAA,EACtF;AACA,MAAI,cAAc;AAChB,wBAAoB,YAAY,YAAY,gBAAgB,QAAQ,QAAQ,YAAY;AAAA,EAC1F;AAGA,kBAAgB,KAAK,YAAY,YAAY,QAAQ,MAAM;AAG3D,mBAAiB,YAAY,YAAY,gBAAgB,MAAM;AAI/D,wBAAsB,KAAK,YAAY,YAAY,MAAM;AAIzD,QAAM,eAAe,yBAAyB,GAAG;AAEjD,QAAM,2BAA2B,aAAa,IAAI,CAAC,OAAO,GAAG,MAAM,WAAW,EAAE;AAGhF,aAAW,MAAM,QAAQ;AACvB,oBAAgB,IAAI,GAAG,QAAQ,MAAM,YAAY,aAAa;AAAA,EAChE;AAEA,aAAW,MAAM,cAAc;AAC7B,OAAG,MAAM,UAAU;AAAA,EACrB;AAGA,MAAI,QAAuB;AAC3B,MAAI,UAAU;AACd,MAAI,YAA2B;AAC/B,MAAI,cAAc;AAGlB,QAAM,gBAAgB,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AACrF,QAAM,gBAAgB,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AAErF,WAAS,KAAK,KAAmB;AAC/B,QAAI,CAAC,QAAS;AACd,QAAI,cAAc,KAAM,aAAY;AAEpC,UAAM,UAAU,MAAM;AACtB,kBAAc;AACd,UAAM,UAAU,KAAK,IAAI,UAAU,SAAS,CAAC;AAE7C,eAAW,MAAM,QAAQ;AACvB,sBAAgB,IAAI,SAAS,QAAQ,MAAM,YAAY,aAAa;AAAA,IACtE;AAGA,0BAAsB,cAAc,SAAS,YAAY,aAAa;AAEtE,QAAI,WAAW,GAAG;AAChB,aAAO;AAAA,IACT,OAAO;AACL,cAAQ,sBAAsB,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,QAAI,CAAC,QAAS;AACd,cAAU;AACV,YAAQ;AAER,gBAAY;AACZ,iBAAa;AAEb,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,mBAAa,CAAC,EAAE,MAAM,UAAU,yBAAyB,CAAC;AAAA,IAC5D;AACA,eAAW;AAAA,EACb;AAEA,WAAS,cAAoB;AAC3B,eAAW,MAAM,QAAQ;AACvB,uBAAiB,EAAE;AAAA,IACrB;AAGA,eAAW,QAAQ,eAAe;AAChC,UAAI,CAAC,KAAK,IAAK;AACf,YAAM,KAAK,eAAgB,cAAc,cAAc,KAAK,GAAG,IAAI;AACnE,UAAI,GAAI,oBAAmB,IAAI,IAAI;AAAA,IACrC;AACA,eAAW,QAAQ,eAAe;AAChC,UAAI,CAAC,KAAK,IAAK;AACf,YAAM,KAAK,eAAgB,cAAc,cAAc,KAAK,GAAG,IAAI;AACnE,UAAI,GAAI,qBAAoB,IAAI,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,WAAS,eAAqB;AAC5B,eAAW,SAAS,QAAQ;AAC1B,YAAM,YAAY,YAAY,KAAK;AAAA,IACrC;AAAA,EACF;AAGA,WAAS,kBAAoC;AAC3C,UAAM,OAAyB,oBAAI,IAAI;AACvC,UAAM,UAAU,KAAK,IAAI,cAAc,OAAO,UAAU,CAAC;AACzD,UAAM,cAAc,SAAS,OAAO;AAEpC,eAAW,MAAM,QAAQ;AACvB,UAAI,GAAG,SAAS,SAAU;AAC1B,YAAM,MAAM,eAAe,EAAE;AAC7B,UAAI,CAAC,IAAK;AAEV,cAAQ,GAAG,WAAW;AAAA,QACpB,KAAK,QAAQ;AACX,gBAAM,IAAI,SAAS,GAAG,MAAM,GAAG,IAAI,WAAW;AAC9C,eAAK,IAAI,KAAK,EAAE,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpC;AAAA,QACF;AAAA,QACA,KAAK,SAAS;AACZ,gBAAM,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAC/C,gBAAM,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAC/C,gBAAM,QAA0B,EAAE,MAAM,SAAS,IAAI,GAAG;AACxD,cAAI,GAAG,UAAU,UAAa,GAAG,QAAQ,QAAW;AAClD,kBAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAAA,UAC7C;AACA,eAAK,IAAI,KAAK,KAAK;AACnB;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK,QAAQ;AACX,eAAK,IAAI,KAAK;AAAA,YACZ,MAAM,GAAG;AAAA,YACT,IAAI,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAAA,YACxC,IAAI,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAAA,YACxC,IAAI,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAAA,YACxC,IAAI,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAAA,UAC1C,CAAC;AACD;AAAA,QACF;AAAA,QACA,KAAK,YAAY;AACf,eAAK,IAAI,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,GAAG,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAAA,YACpC,GAAG,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAAA,UACtC,CAAC;AACD;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AAEX,gBAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,WAAW;AAC/D,gBAAM,IAAI,cAAc,KAAK,GAAG,WAAW;AAC3C,eAAK,IAAI,KAAK,EAAE,MAAM,QAAQ,EAAE,CAAC;AACjC;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AACX,gBAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,WAAW;AAC/D,gBAAM,SAAS,kBAAkB,GAAG,YAAY,GAAG,UAAU,WAAW;AACxE,gBAAM,IAAI,cAAc,KAAK,QAAQ,GAAG,WAAW;AACnD,cAAI;AACJ,cAAI,GAAG,WAAW;AAChB,mBAAO,cAAc,KAAK,GAAG,WAAW;AAAA,UAC1C;AACA,eAAK,IAAI,KAAK,EAAE,MAAM,QAAQ,GAAG,KAAK,CAAC;AACvC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,UAAQ,sBAAsB,IAAI;AAElC,SAAO;AAAA,IACL,SAAe;AACb,UAAI,CAAC,QAAS;AACd,gBAAU;AACV,UAAI,UAAU,MAAM;AAClB,6BAAqB,KAAK;AAC1B,gBAAQ;AAAA,MACV;AACA,kBAAY;AACZ,mBAAa;AAEb,eAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,qBAAa,CAAC,EAAE,MAAM,UAAU,yBAAyB,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,IACA,IAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAAA,IACA,WAA6B;AAC3B,aAAO,gBAAgB;AAAA,IACzB;AAAA,EACF;AACF;AAgBA,SAAS,yBAAyB,KAAkC;AAClE,QAAM,MAAoB,CAAC;AAC3B,QAAM,WAAW,IAAI,cAAc,qBAAqB;AACxD,MAAI,SAAU,KAAI,KAAK,QAAQ;AAC/B,QAAM,aAAa,IAAI,cAAc,iBAAiB;AACtD,MAAI,WAAY,KAAI,KAAK,UAAU;AACnC,SAAO;AACT;AAGA,SAAS,sBACP,KACA,SACA,YACA,eACM;AACN,MAAI,IAAI,WAAW,EAAG;AACtB,MAAI;AACJ,MAAI,UAAU,YAAY;AACxB,QAAI;AAAA,EACN,OAAO;AACL,QAAI,KAAK,KAAK,UAAU,cAAc,eAAe,CAAC;AAAA,EACxD;AACA,QAAM,UAAU,OAAO,SAAS,CAAC,CAAC;AAClC,aAAW,MAAM,KAAK;AACpB,OAAG,MAAM,UAAU;AAAA,EACrB;AACF;AAGA,SAAS,eAAe,IAA0B;AAChD,MAAI,WAAW,MAAM,GAAG,MAAO,QAAO;AACtC,SAAO,GAAG,GAAG,aAAa,UAAU;AACtC;AAMA,SAAS,mBAAmB,IAA4B;AACtD,SAAO,GAAG,YAAY,SAAS,KAAO,GAAG,cAAc,MAAM,KAAoB;AACnF;AAEA,SAAS,gBACP,IACA,SACA,QACA,MACA,YACA,eACM;AACN,MAAI;AAEJ,MAAI,GAAG,SAAS,QAAQ;AACtB,aAAS,KAAK,IAAI,UAAU,KAAK,UAAU,CAAC;AAAA,EAC9C,WAAW,GAAG,SAAS,SAAS;AAC9B,QAAI,UAAU,YAAY;AACxB,eAAS;AAAA,IACX,OAAO;AACL,eAAS,KAAK,KAAK,UAAU,cAAc,eAAe,CAAC;AAAA,IAC7D;AAAA,EACF,OAAO;AACL,aAAS,KAAK,IAAI,UAAU,OAAO,UAAU,CAAC;AAAA,EAChD;AAEA,QAAM,QAAQ,SAAS,MAAM;AAE7B,UAAQ,GAAG,WAAW;AAAA,IACpB,KAAK,QAAQ;AACX,YAAM,OAAO,SAAS,GAAG,MAAM,GAAG,IAAI,KAAK;AAC3C,yBAAmB,GAAG,IAAI,MAAM,GAAG,IAAI;AACvC;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,KAAK;AACzD,oBAAc,GAAG,IAAI,KAAK,GAAG,WAAW;AACxC;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,KAAK;AACzD,YAAM,SAAS,kBAAkB,GAAG,YAAY,GAAG,UAAU,KAAK;AAClE,qBAAe,GAAG,IAAI,KAAK,QAAQ,GAAG,aAAa,GAAG,SAAS;AAC/D;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAC/C,YAAM,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU;AAC/C,SAAG,GAAG,aAAa,MAAM,OAAO,EAAE,CAAC;AACnC,SAAG,GAAG,aAAa,MAAM,OAAO,EAAE,CAAC;AACnC,UAAI,GAAG,UAAU,UAAa,GAAG,QAAQ,QAAW;AAClD,cAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAC3C,WAAG,GAAG,aAAa,KAAK,OAAO,CAAC,CAAC;AAAA,MACnC;AACA;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,SAAS,mBAAmB,GAAG,EAAE;AACvC,aAAO,aAAa,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAC3E,aAAO,aAAa,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAC3E,aAAO,aAAa,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAC3E,aAAO,aAAa,MAAM,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAC3E;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAC3C,YAAM,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;AAC3C,SAAG,GAAG,aAAa,KAAK,OAAO,CAAC,CAAC;AACjC,SAAG,GAAG,aAAa,KAAK,OAAO,CAAC,CAAC;AACjC;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,UAAI,GAAG,WAAW;AAEhB;AAAA,MACF;AACA,YAAM,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW;AACnD,UAAI,GAAG,YAAY,KAAK;AACtB,WAAG,GAAG,aAAa,KAAK,OAAO,GAAG,CAAC;AAAA,MACrC,OAAO;AACL,WAAG,GAAG,aAAa,KAAK,OAAO,GAAG,CAAC;AAAA,MACrC;AACA;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW;AACnD,UAAI,GAAG,gBAAgB,KAAK;AAE1B,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,CAAC;AACpC,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,CAAC;AAAA,MACtC,OAAO;AAEL,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,CAAC;AACpC,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,CAAC;AAAA,MACtC;AACA;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,SAAG,GAAG,aAAa,GAAG,MAAM,YAAe,GAAG,MAAM,GAAG,EAAE,EAAE,KAAK,CAAC;AACjE;AAAA,IACF;AAAA,IACA,KAAK,cAAc;AAMjB,YAAM,KAAK,GAAG,UAAU,IAAI;AAC5B,YAAM,KAAK,GAAG,UAAU,IAAI;AAC5B,UAAI,OAAO,KAAK,OAAO,GAAG;AACxB,WAAG,GAAG,aAAa,aAAa,aAAa,EAAE,IAAI,EAAE,GAAG;AAAA,MAC1D;AACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,GAAG,gBAAgB,UAAa,GAAG,cAAc,QAAW;AAC9D,UAAM,UAAU,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe;AACnE,OAAG,GAAG,MAAM,UAAU,OAAO,OAAO;AAAA,EACtC;AACF;AAEA,SAAS,iBAAiB,IAAiB;AACzC,UAAQ,GAAG,WAAW;AAAA,IACpB,KAAK;AACH,yBAAmB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;AACxC;AAAA,IACF,KAAK;AACH,oBAAc,GAAG,IAAI,GAAG,OAAO,GAAG,WAAW;AAC7C;AAAA,IACF,KAAK;AACH,qBAAe,GAAG,IAAI,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS;AACzE;AAAA,IACF,KAAK;AACH,SAAG,GAAG,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACxC,SAAG,GAAG,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACxC,UAAI,GAAG,QAAQ,QAAW;AACxB,WAAG,GAAG,aAAa,KAAK,OAAO,GAAG,GAAG,CAAC;AAAA,MACxC;AACA;AAAA,IACF,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,SAAS,mBAAmB,GAAG,EAAE;AACvC,aAAO,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACzC,aAAO,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACzC,aAAO,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACzC,aAAO,aAAa,MAAM,OAAO,GAAG,IAAI,CAAC;AACzC;AAAA,IACF;AAAA,IACA,KAAK;AACH,SAAG,GAAG,aAAa,KAAK,OAAO,GAAG,GAAG,CAAC;AACtC,SAAG,GAAG,aAAa,KAAK,OAAO,GAAG,GAAG,CAAC;AACtC;AAAA,IACF,KAAK;AACH,UAAI,CAAC,GAAG,WAAW;AACjB,YAAI,GAAG,YAAY,KAAK;AACtB,aAAG,GAAG,aAAa,KAAK,OAAO,GAAG,KAAK,CAAC;AAAA,QAC1C,OAAO;AACL,aAAG,GAAG,aAAa,KAAK,OAAO,GAAG,KAAK,CAAC;AAAA,QAC1C;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,UAAI,GAAG,gBAAgB,KAAK;AAC1B,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,KAAK,CAAC;AACzC,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,KAAK,CAAC;AAAA,MAC3C,OAAO;AACL,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,KAAK,CAAC;AACzC,WAAG,GAAG,aAAa,MAAM,OAAO,GAAG,KAAK,CAAC;AAAA,MAC3C;AACA;AAAA,IACF,KAAK;AACH,SAAG,GAAG,aAAa,GAAG,MAAM,GAAG,EAAE;AACjC;AAAA,IACF,KAAK;AAIH,SAAG,GAAG,gBAAgB,WAAW;AACjC;AAAA,EACJ;AAEA,MAAI,GAAG,cAAc,QAAW;AAC9B,OAAG,GAAG,MAAM,UAAU,OAAO,GAAG,SAAS;AAAA,EAC3C;AAGA,MAAI,GAAG,cAAc,WAAW,GAAG,sBAAsB,QAAW;AAClE,OAAG,GAAG,aAAa,WAAW,GAAG,iBAAiB;AAAA,EACpD;AACF;AAWA,SAAS,yBACP,MACA,kBACG;AACH,MAAI,CAAC,KAAK,QAAQ,OAAO,KAAK,SAAS,YAAY,iBAAiB,SAAS,EAAG,QAAO;AACvF,QAAM,WAAW,gBAAgB,KAAK,MAAM,gBAAgB;AAC5D,SAAO,EAAE,GAAG,MAAM,MAAM,SAAS;AACnC;AAMA,SAAS,gBACP,YACA,YACA,gBACA,QACA,QACA,kBACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AACjF,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AAEjF,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAGT,QAAI,WAAW,aAAa,IAAI;AAChC,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,iBAAW,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,IAC5E;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,IAAI,aAAa,IAAI;AAAA,MACrB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAET,QAAI;AACJ,QAAI,KAAK,WAAW,cAAc;AAChC,iBAAW,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,KAAK,OAAO;AAAA,IACnE,OAAO;AACL,iBAAW,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,KAAK,QAAQ,OAAO,KAAK,OAAO,QAAQ,EAAE;AAAA,IAChF;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,IAAI,aAAa,IAAI;AAAA,MACrB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AAExB,UAAM,YAAY,yBAAyB,MAAM,gBAAgB;AACjE,UAAM,QAAQ,iBAAiB,WAAW,CAAC;AAC3C,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AAEjB,QAAI;AACJ,QAAI,KAAK,WAAW,cAAc;AAChC,eAAS,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,KAAK,OAAO;AAAA,IACjE,OAAO;AACL,eAAS,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,KAAK,QAAQ,OAAO,KAAK,OAAO,QAAQ,EAAE;AAAA,IAC9E;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM,aAAa,IAAI;AAAA,MACvB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,gBACP,YACA,YACA,gBACA,QACA,QACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AACjF,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AAEjF,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAGT,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,QAAQ;AAEhC,YAAM,QAAQ,GAAG,UAAU,IAAI;AAC/B,YAAM,UAAU,IAAI,UAAU;AAC9B,YAAM,aAAa,eAAe,MAAM;AACxC,YAAM,aAAa,kBAAkB,MAAM;AAC3C,YAAM,gBAAgB,UAAU;AAChC,YAAM,YAAY,MAAM,cAAc,MAAM;AAC5C,UAAI,UAAW,WAAU,aAAa,KAAK,KAAK,CAAC;AACjD,qBAAe,YAAY,KAAK;AAChC,aAAO,KAAK,KAAK;AAEjB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,SAAS,KAAK;AAAA;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB;AAAA,QACA,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAGD,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,aAAa,KAAK,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;AAClE,UAAM,UAAU,KAAK,aAAa,KAAK,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;AAGlE,UAAM,aAAa,IAAI,IAAI,OAAO;AAClC,UAAM,eAAe,QAAQ,KAAK,CAAC,MAAM,WAAW,IAAI,CAAC,CAAC;AAE1D,QAAI,CAAC,cAAc;AAEjB,YAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,UAAI,OAAO;AACT,cAAM,UAAU,IAAI,UAAU;AAC9B,cAAM,aAAa,eAAe,MAAM;AACxC,cAAM,aAAa,kBAAkB,MAAM;AAC3C,cAAM,gBAAgB,UAAU;AAChC,uBAAe,YAAY,KAAK;AAChC,eAAO,KAAK,KAAK;AAEjB,eAAO,KAAK;AAAA,UACV,WAAW;AAAA,UACX,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,SAAS,KAAK;AAAA,UACd,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK;AAAA,UAClB,aAAa,KAAK;AAAA,UAClB;AAAA,UACA,aAAa;AAAA,UACb,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAGA,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,CAAC,SAAS,KAAK,IAAI,qBAAqB,KAAK,QAAQ,KAAK,QAAQ,SAAS,OAAO;AAExF,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAET,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AAExB,UAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AAEjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,gBACP,YACA,YACA,gBACA,QACA,QACA,kBACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AACjF,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAAqB,EAAE,SAAS,MAAM;AAEjF,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAAsB;AAC5C,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAGT,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,YAAM,QAAQ,GAAG,UAAU,IAAI;AAC/B,YAAM,UAAU,IAAI,UAAU;AAC9B,YAAM,aAAa,eAAe,MAAM;AACxC,YAAM,aAAa,kBAAkB,MAAM;AAC3C,YAAM,gBAAgB,UAAU;AAChC,YAAM,aAAa,MAAM,iBAAiB,MAAM;AAChD,UAAI,WAAW,CAAC,EAAG,YAAW,CAAC,EAAE,aAAa,KAAK,KAAK,CAAC;AACzD,UAAI,WAAW,CAAC,KAAK,KAAK,KAAM,YAAW,CAAC,EAAE,aAAa,KAAK,KAAK,IAAI;AACzE,qBAAe,YAAY,KAAK;AAChC,aAAO,KAAK,KAAK;AAEjB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,mBAAmB,KAAK;AAAA,QACxB,aAAa,KAAK;AAAA,QAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,QACnC;AAAA,QACA,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAED,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,mBAAmB,KAAK;AAAA,QACxB,aAAa,KAAK;AAAA,QAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,QACnC,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,aAAa,KAAK,UAAU,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;AACrE,UAAM,UAAU,KAAK,aAAa,KAAK,UAAU,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;AAErE,UAAM,aAAa,IAAI,IAAI,OAAO;AAClC,UAAM,eAAe,QAAQ,KAAK,CAAC,MAAM,WAAW,IAAI,CAAC,CAAC;AAE1D,QAAI,CAAC,cAAc;AAEjB,YAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,UAAI,OAAO;AACT,cAAM,UAAU,IAAI,UAAU;AAC9B,cAAM,aAAa,eAAe,MAAM;AACxC,cAAM,aAAa,kBAAkB,MAAM;AAC3C,cAAM,gBAAgB,UAAU;AAChC,uBAAe,YAAY,KAAK;AAChC,eAAO,KAAK,KAAK;AAEjB,eAAO,KAAK;AAAA,UACV,WAAW;AAAA,UACX,MAAM;AAAA,UACN,IAAI;AAAA,UACJ,SAAS,KAAK;AAAA,UACd,OAAO,KAAK;AAAA,UACZ,YAAY,KAAK;AAAA,UACjB,UAAU,KAAK;AAAA,UACf,gBAAgB,KAAK;AAAA,UACrB,mBAAmB,KAAK;AAAA,UACxB,aAAa,KAAK;AAAA,UAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,UACnC;AAAA,UACA,aAAa;AAAA,UACb,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAEA,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB,UAAU,KAAK;AAAA,QACf,gBAAgB,KAAK;AAAA,QACrB,mBAAmB,KAAK;AAAA,QACxB,aAAa,KAAK;AAAA,QAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,QACnC,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,CAAC,SAAS,KAAK,IAAI;AAAA,QACvB,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,YAAM,CAAC,YAAY,QAAQ,IAAI;AAAA,QAC7B,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAEA,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,KAAK;AAAA,QACrB,mBAAmB,KAAK;AAAA,QACxB,aAAa,KAAK;AAAA,QAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,MACrC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe,cAAc,cAAc,GAAG,IAAI;AAC7D,QAAI,CAAC,GAAI;AAET,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,MACxB,aAAa,KAAK;AAAA,MAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,MACnC,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AAExB,UAAM,YAAY,yBAAyB,MAAM,gBAAgB;AACjE,UAAM,QAAQ,iBAAiB,WAAW,CAAC;AAC3C,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AAEjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,MACxB,aAAa,KAAK;AAAA,MAClB,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,KAAK;AAAA,MACnC;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,iBACP,YACA,YACA,gBACA,QACA,QACA,kBACA,cACM;AACN,QAAM,aAAa,WAAW,MAAM,OAAO,CAAC,MAAsB,EAAE,SAAS,OAAO;AACpF,QAAM,aAAa,WAAW,MAAM,OAAO,CAAC,MAAsB,EAAE,SAAS,OAAO;AAEpF,QAAM,YAAY,oBAAI,IAAuB;AAC7C,aAAW,KAAK,YAAY;AAC1B,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAAuB;AAC7C,aAAW,KAAK,YAAY;AAC1B,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe;AAAA,MACxB,kCAAkC,GAAG;AAAA,IACvC;AACA,QAAI,CAAC,GAAI;AAIT,UAAM,kBAAkB,GAAG,aAAa,SAAS;AACjD,UAAM,eAAe,oBAAoB;AAGzC,QAAI,SAAS,KAAK;AAClB,QAAI,SAAS,KAAK;AAClB,QAAI,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI;AACzC,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,SAAS;AACjC,eAAS,KAAK;AACd,eAAS,KAAK;AACd,UAAI,KAAK,MAAM,UAAa,KAAK,MAAM,KAAK,GAAG;AAC7C,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA,KAAK,UAAU,SAAY,KAAK,IAAI;AAAA;AAAA,MAEpC,mBAAmB,eAAe,MAAM;AAAA,IAC1C,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe;AAAA,MACxB,kCAAkC,GAAG;AAAA,IACvC;AACA,QAAI,CAAC,GAAI;AAGT,UAAM,kBAAkB,GAAG,aAAa,SAAS;AACjD,UAAM,gBAAgB,mBAAmB,OAAO,OAAO,eAAe,IAAI;AAE1E,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,aAAa;AAAA,MACb,WAAW;AAAA,MACX,mBAAmB,oBAAoB,MAAM,MAAM;AAAA,IACrD,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AAExB,UAAM,YAAY,yBAAyB,MAAM,gBAAgB;AACjE,UAAM,QAAQ,iBAAiB,WAAW,CAAC;AAC3C,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AAEjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,gBACP,YACA,YACA,gBACA,QACA,QACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,MAAM;AACvF,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,MAAM;AAEvF,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AAET,QAAI,SAAS,KAAK;AAClB,QAAI,SAAS,KAAK;AAClB,QAAI,SAAS,KAAK;AAClB,QAAI,SAAS,KAAK;AAClB,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,eAAS,KAAK;AACd,eAAS,KAAK;AACd,eAAS,KAAK;AACd,eAAS,KAAK;AAAA,IAChB;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AACT,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AACjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,gBACP,YACA,YACA,gBACA,QACA,QACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,MAAM;AACvF,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,MAAM;AAEvF,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAEA,WAAS,cAAc,GAAmB;AACxC,UAAM,OAAO,EAAE,SAAS;AACxB,QAAI,EAAE,WAAW,YAAY;AAC3B,aAAO,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,EAAE;AAAA,EAC5D;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AACT,QAAI,OAAO,cAAc,IAAI;AAC7B,UAAM,OAAO,cAAc,IAAI;AAC/B,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,aAAO,EAAE,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,GAAG;AAAA,IAC9D;AACA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AACT,UAAM,OAAO,cAAc,IAAI;AAC/B,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AACjB,UAAM,OAAO,cAAc,IAAI;AAC/B,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAMA,SAAS,oBACP,YACA,YACA,gBACA,QACA,QACA,cACM;AACN,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,UAAU;AAC3F,QAAM,YAAY,WAAW,MAAM,OAAO,CAAC,MAA2B,EAAE,SAAS,UAAU;AAE3F,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AACA,QAAM,YAAY,oBAAI,IAA4B;AAClD,aAAW,KAAK,WAAW;AACzB,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AAET,QAAI,QAAQ,KAAK;AACjB,QAAI,QAAQ,KAAK;AACjB,UAAM,OAAO,cAAc,IAAI,GAAG;AAClC,QAAI,QAAQ,KAAK,SAAS,YAAY;AACpC,cAAQ,KAAK;AACb,cAAQ,KAAK;AAAA,IACf;AAEA,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,KAAK,eAAe;AAAA,MACxB,2BAA2B,GAAG;AAAA,IAChC;AACA,QAAI,CAAC,GAAI;AACT,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,MACV,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,WAAW;AACnC,QAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAM,QAAQ,iBAAiB,MAAM,CAAC;AACtC,QAAI,CAAC,MAAO;AACZ,UAAM,UAAU,IAAI,UAAU;AAC9B,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,gBAAgB,UAAU;AAChC,mBAAe,YAAY,KAAK;AAChC,WAAO,KAAK,KAAK;AACjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,MACV;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;AAkBA,SAAS,iBAAiB,IAAgB,MAAqC;AAC7E,MAAI,GAAG,YAAY,YAAY,GAAG,YAAY,UAAU,GAAG,YAAY,OAAQ,QAAO;AACtF,MAAI,SAAS,UAAU;AACrB,UAAM,UAAU,GAAG,cAAc,cAAc;AAC/C,QAAI,QAAS,QAAO;AAAA,EACtB;AACA,SAAQ,GAAG,cAAc,0BAA0B,KAA2B;AAChF;AAGA,SAAS,oBAAoB,GAAyB;AACpD,SAAO,OAAO,MAAM,YAAY,MAAM,MAAM,MAAM,UAAU,CAAC,EAAE,WAAW,MAAM;AAClF;AAUA,SAAS,iBACP,YACA,YACA,gBACA,QACM;AAEN,QAAM,YAAY,oBAAI,IAAqB;AAC3C,aAAW,KAAK,WAAW,OAAoB;AAC7C,QAAI,EAAE,IAAK,WAAU,IAAI,EAAE,KAAK,CAAC;AAAA,EACnC;AAEA,aAAW,QAAQ,WAAW,OAAoB;AAChD,QAAI,CAAC,KAAK,IAAK;AACf,UAAM,OAAO,UAAU,IAAI,KAAK,GAAG;AACnC,QAAI,CAAC,KAAM;AAEX,UAAM,QAAQ,eAAe,cAAc,cAAc,KAAK,GAAG,IAAI;AACrE,QAAI,CAAC,MAAO;AAEZ,eAAW,QAAQ,CAAC,QAAQ,QAAQ,GAAY;AAC9C,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,KAAK,KAAK,IAAI;AACpB,UAAI,SAAS,GAAI;AACjB,UAAI,CAAC,oBAAoB,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAG;AAC5D,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI,iBAAiB,OAAO,IAAI;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAoBA,SAAS,sBACP,KACA,YACA,YACA,QACM;AACN,QAAM,OAAO,WAAW,eAAe,CAAC;AACxC,QAAM,OAAO,WAAW,eAAe,CAAC;AACxC,MAAI,KAAK,WAAW,KAAK,KAAK,WAAW,EAAG;AAE5C,QAAM,YAAY,IAAI,cAAc,iBAAiB;AACrD,MAAI,CAAC,UAAW;AAEhB,QAAM,YAAY,IAAI,IAAI,eAAe,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1E,QAAM,WAAW,eAAe,IAAI;AAGpC,QAAM,MAAM,UAAU,iBAAiB,gBAAgB;AAEvD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,UAAU,IAAI,SAAS,CAAC,CAAC;AAExC,QAAI,CAAC,QAAQ;AAEX,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAGA,UAAM,MAAM,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;AACzD,UAAM,MAAM,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;AACzD,QAAI,OAAO,KAAK,OAAO,EAAG;AAC1B,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAaF;AAUA,SAAS,gBACP,KACA,YACA,YACA,QACA,QACM;AAEN,wBAAsB,KAAK,WAAW,KAAK,GAAG,WAAW,KAAK,GAAG,KAAK,YAAY,QAAQ,MAAM;AAChG,wBAAsB,KAAK,WAAW,KAAK,GAAG,WAAW,KAAK,GAAG,KAAK,YAAY,QAAQ,MAAM;AAClG;AAEA,SAAS,sBACP,KACA,UACA,UACA,aACA,QACA,QACA,QACM;AACN,MAAI,CAAC,YAAY,CAAC,SAAU;AAE5B,QAAM,YAAY,WAAW,WAAW;AACxC,QAAM,YAAY,IAAI,cAAc,IAAI,SAAS,EAAE;AACnD,MAAI,CAAC,UAAW;AAEhB,QAAM,YAAY,CAAC,EAAE,SAAS,aAAa,KAAK,IAAI,SAAS,SAAS,IAAI;AAG1E,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,QAAQ,SAAS,OAAO;AACjC,gBAAY,IAAI,kBAAkB,KAAK,KAAK,GAAG,KAAK,QAAQ;AAAA,EAC9D;AACA,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,QAAQ,SAAS,OAAO;AACjC,gBAAY,IAAI,kBAAkB,KAAK,KAAK,GAAG,KAAK,QAAQ;AAAA,EAC9D;AAGA,QAAM,UAAU,gBAAgB,MAAM,MAAM;AAG5C,QAAM,aAAa,UAAU,iBAAiB,8BAA8B;AAC5E,QAAM,kBAAkB,oBAAI,IAAY;AAExC,aAAW,WAAW,YAAY;AAChC,UAAM,MAAM,QAAQ,aAAa,eAAe;AAChD,QAAI,CAAC,IAAK;AAEV,UAAM,UAAU,YAAY,IAAI,GAAG;AACnC,UAAM,UAAU,YAAY,IAAI,GAAG;AAEnC,QAAI,YAAY,UAAa,YAAY,QAAW;AAElD,sBAAgB,IAAI,GAAG;AACvB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW;AAAA,MACb,CAAC;AAAA,IACH,WAAW,YAAY,UAAa,YAAY,QAAW;AAEzD,sBAAgB,IAAI,GAAG;AACvB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EAGF;AAGA,aAAW,CAAC,KAAK,OAAO,KAAK,aAAa;AACxC,QAAI,YAAY,IAAI,GAAG,EAAG;AAI1B,UAAM,WAAW,SAAS,MAAM,KAAK,CAAC,MAAM,kBAAkB,EAAE,KAAK,MAAM,GAAG;AAC9E,QAAI,CAAC,SAAU;AAEf,UAAM,QAAQ,SAAS,gBAAgB,8BAA8B,MAAM;AAC3E,UAAM,aAAa,SAAS,uBAAuB;AACnD,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,UAAM,cAAc,SAAS;AAE7B,UAAM,OAAO,OAAO;AACpB,QAAI,gBAAgB,KAAK;AACvB,YAAM,aAAa,KAAK,OAAO,OAAO,CAAC;AACvC,YAAM,YAAY,SAAS,gBAAgB,OAAO,MAAM,QAAQ;AAChE,YAAM,WAAW,SAAS,eAAe;AACzC,YAAM,aAAa,KAAK,OAAO,KAAK,IAAI,KAAK,SAAS,YAAY,WAAW,GAAG,CAAC;AACjF,YAAM,aAAa,eAAe,QAAQ;AAAA,IAC5C,OAAO;AACL,YAAM,oBAAoB;AAC1B,YAAM,aAAa,KAAK,OAAO,KAAK,IAAI,iBAAiB,CAAC;AAC1D,YAAM,aAAa,KAAK,OAAO,OAAO,CAAC;AACvC,YAAM,aAAa,eAAe,KAAK;AACvC,YAAM,aAAa,qBAAqB,SAAS;AAAA,IACnD;AACA,cAAU,YAAY,KAAK;AAC3B,WAAO,KAAK,KAAK;AAEjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP,WAAW;AAAA,MACX;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAGA,QAAM,cAAc,oBAAI,IAAoB;AAC5C,aAAW,YAAY,SAAS,WAAW;AAEzC,gBAAY,IAAI,OAAO,SAAS,QAAQ,GAAG,SAAS,QAAQ;AAAA,EAC9D;AAEA,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,aAAW,QAAQ,SAAS,OAAO;AACjC,UAAM,MAAM,kBAAkB,KAAK,KAAK;AAExC,UAAM,mBAAmB,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,aAAa,KAAK,QAAQ;AACpF,QAAI,kBAAkB;AACpB,sBAAgB,IAAI,KAAK,iBAAiB,QAAQ;AAAA,IACpD;AAAA,EACF;AACA,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,aAAW,QAAQ,SAAS,OAAO;AACjC,UAAM,MAAM,kBAAkB,KAAK,KAAK;AACxC,UAAM,mBAAmB,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,aAAa,KAAK,QAAQ;AACpF,QAAI,kBAAkB;AACpB,sBAAgB,IAAI,KAAK,iBAAiB,QAAQ;AAAA,IACpD;AAAA,EACF;AAEA,QAAM,YAAY,UAAU,iBAAiB,6BAA6B;AAC1E,QAAM,kBAAkB,oBAAI,IAAY;AAExC,aAAW,QAAQ,WAAW;AAC5B,UAAM,MAAM,KAAK,aAAa,eAAe;AAC7C,QAAI,CAAC,IAAK;AAEV,UAAM,UAAU,gBAAgB,IAAI,GAAG;AACvC,UAAM,UAAU,gBAAgB,IAAI,GAAG;AAEvC,QAAI,YAAY,UAAa,YAAY,QAAW;AAClD,sBAAgB,IAAI,GAAG;AACvB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AAAA,IACH,WAAW,YAAY,UAAa,YAAY,QAAW;AACzD,sBAAgB,IAAI,GAAG;AACvB,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,aAAa;AAAA,QACb,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,CAAC,KAAK,OAAO,KAAK,iBAAiB;AAC5C,QAAI,gBAAgB,IAAI,GAAG,EAAG;AAE9B,UAAM,QAAQ,SAAS,gBAAgB,8BAA8B,MAAM;AAC3E,UAAM,aAAa,SAAS,sBAAsB;AAClD,UAAM,aAAa,eAAe,MAAM;AACxC,UAAM,aAAa,kBAAkB,MAAM;AAC3C,QAAI,gBAAgB,KAAK;AAEvB,YAAM,OAAO,OAAO;AACpB,YAAM,aAAa,MAAM,OAAO,KAAK,CAAC,CAAC;AACvC,YAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AACxC,YAAM,aAAa,MAAM,OAAO,KAAK,IAAI,KAAK,KAAK,CAAC;AACpD,YAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AAAA,IAC1C,OAAO;AAEL,YAAM,OAAO,OAAO;AACpB,YAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AACxC,YAAM,aAAa,MAAM,OAAO,KAAK,CAAC,CAAC;AACvC,YAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AACxC,YAAM,aAAa,MAAM,OAAO,KAAK,IAAI,KAAK,MAAM,CAAC;AAAA,IACvD;AACA,cAAU,YAAY,KAAK;AAC3B,WAAO,KAAK,KAAK;AAEjB,WAAO,KAAK;AAAA,MACV,WAAW;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP;AAAA,MACA,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AACF;;;AX1mFA,IAAM,kBAAkB;AAMxB,SAASC,iBAAgB,MAA0B;AACjD,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,SAAS,SAAS,SAAS,OAAW,QAAO;AACjD,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACtD,WAAO,OAAO,WAAW,8BAA8B,EAAE;AAAA,EAC3D;AACA,SAAO;AACT;AAMA,IAAM,qBAAqB;AAAA;AAAA,yBAEFC,iBAAgB,uBAAuB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAMxE,SAAS,aAAa,KAAuB;AAC3C,MAAI,aAAa,YAAY,GAAG;AAChC,MAAI,MAAM,UAAU;AAEpB,QAAM,QAAQ,SAAS,gBAAgB,8BAA8B,OAAO;AAC5E,QAAM,cAAc;AACpB,MAAI,aAAa,OAAO,IAAI,UAAU;AACxC;AAEA,SAAS,oBAAoB,MAA8B;AACzD,SAAO,CAAC,EAAE,MAAM,UAAU,MAAM,YAAY,MAAM,cAAc,MAAM;AACxE;AAOA,SAAS,kBAAkB,MAAmD;AAC5E,MAAI,YAAY,IAAI,KAAK,YAAY,IAA0C,EAAG,QAAO,CAAC;AAC1F,QAAM,WAAY,KAAmB,UAAU;AAC/C,MAAI,CAAC,YAAY,OAAO,aAAa,YAAY,EAAE,WAAW,UAAW,QAAO,CAAC;AACjF,QAAM,MAAO,SAA+C;AAC5D,MAAI,OAAO,KAAM,QAAO,CAAC;AACzB,SAAO,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG;AAC7C;AAGA,SAAS,kBAAkB,MAAkD;AAC3E,MAAI,YAAY,IAAI,KAAK,YAAY,IAA0C,EAAG,QAAO;AACzF,SAAO,CAAC,CAAE,KAAmB;AAC/B;AAGA,SAAS,eAAe,MAAkD;AACxE,MAAI,YAAY,IAAI,KAAK,YAAY,IAA0C,EAAG,QAAO;AACzF,SAAO,CAAC,CAAE,KAAmB;AAC/B;AASO,SAAS,YACd,WACA,MACA,SACe;AACf,MAAI,cAAiD;AACrD,MAAI;AACJ,MAAI,aAAgC;AACpC,MAAI,iBAAwC;AAC5C,MAAI,mBAAwC;AAC5C,MAAI,uBAA4C;AAChD,MAAI,uBAA4C;AAChD,MAAI,qBAA0C;AAC9C,MAAI,gBAAqC;AACzC,MAAI,qBAA0C;AAC9C,MAAI,wBAA6C;AACjD,MAAI,mBAAwC;AAC5C,MAAI,mBAAwC;AAC5C,MAAI,sBAA2C;AAC/C,MAAI,UAAmC;AACvC,MAAI,YAAY;AAChB,MAAI,aAAa;AACjB,MAAI,gBAAgB;AAGpB,MAAI,gBAAgB;AACpB,MAAI,oBAAyC;AAC7C,MAAI,gBAAgB;AAWpB,MAAI,eAA+B;AACnC,MAAI,oBAAmC;AACvC,MAAI,wBAAuC;AAG3C,MAAI,mBAAmE;AACvE,MAAI,qBAA8C;AAOlD,MAAI,qBAAqB;AAGzB,MAAI,kBAAqC,SAAS,mBAAmB;AACrE,MAAI,iBAAqC;AACzC,MAAI,sBAAsB;AAG1B,QAAM,sBAAsB,oBAAI,IAAY;AAC5C,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,MAAI,kBAAuC;AAM3C,MAAI,eAA8C;AAClD,MAAI,iBAA2B,kBAAkB,WAAW;AAC5D,MAAI,qBAAqB;AAKzB,MAAI,YAAwC;AAC5C,MAAI,wBAAwB;AAI5B,YAAU,UAAU,IAAI,SAAS;AAOjC,WAAS,uBAA+B;AACtC,WACE,SAAS,OAAO,OAAO,UACvB,YAAY,OAAO,OAAO,UAC1B,kBAAkB,SAAS;AAAA,EAE/B;AACA,MAAI,aAAa,qBAAqB;AACtC,MAAI,cAAc,kBAAkB,UAAU;AAC9C,MAAI,YAAY;AAMhB,WAAS,UAAU,OAAe,QAA6B;AAC7D,UAAM,WAAWD,iBAAgB,SAAS,QAAQ;AAElD,UAAM,cAA8B;AAAA,MAClC;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB;AAAA,MACA,WAAW,SAAS;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,YAAY,WAAW,GAAG;AAC5B,aAAO,aAAa,kBAAkB,WAAwB,GAAgB,WAAW;AAAA,IAC3F;AACA,WAAO,aAAa,kBAAkB,WAAW,GAA4B,WAAW;AAAA,EAC1F;AAaA,WAAS,kBAAkB,QAAqB,OAAuB;AAIrE,QAAI,iBAAiB;AACrB,eAAW,UAAU,OAAO,WAAW,CAAC,OAAO,MAAM,GAAG;AACtD,UAAI,OAAO,aAAa,MAAO;AAC/B,YAAM,aACJ,OAAO,SAAS,gBAAgB,OAAO,SAAS,SAC5C,OAAO,OAAO,SAAS,IACvB,aAAa,UAAU,OAAO,QAAQ,SAAS;AACrD,UAAI,WAAY,mBAAkB,OAAO,OAAO,SAAS,UAAU,KAAK;AAAA,IAC1E;AAEA,QAAI,cAAc;AAClB,QAAI,OAAO,OAAO;AAChB,YAAM,SAAS,eAAe,OAAO,MAAM,OAAO,QAAQ,OAAO,MAAM,OAAO;AAC9E,YAAM,kBACJ,kBAAkB,OAAO,OAAO,YAAY,OAAO,OAAO,eAAe;AAC3E,UAAI,SAAS,iBAAiB;AAC5B,sBAAc,SAAS;AAAA,MACzB;AAAA,IACF;AAEA,WACE,OAAO,OAAO,YACd,OAAO,OAAO,eACd,kBACC,OAAO,SAAS,UAAU,KAC3B;AAAA,EAEJ;AAEA,WAAS,UAAuB;AAC9B,UAAM,EAAE,OAAO,OAAO,IAAI,uBAAuB;AAIjD,UAAM,kBACJ,iBAAiB,QACjB,CAAC,YAAY,WAAW,KACxB,CAAC,YAAY,WAAiD,KAC7D,YAA0B,YAAY;AACzC,QAAI,CAAC,iBAAiB;AACpB,aAAO,UAAU,OAAO,MAAM;AAAA,IAChC;AASA,QAAI,SAAS,UAAU,OAAO,MAAM;AACpC,UAAM,YAAY,kBAAkB,QAAQ,KAAK;AACjD,QAAI,YAAY,GAAG;AACjB,eAAS,UAAU,OAAO,SAAS,SAAS;AAC5C,YAAM,aAAa,kBAAkB,QAAQ,KAAK;AAClD,UAAI,eAAe,WAAW;AAC5B,iBAAS,UAAU,OAAO,SAAS,UAAU;AAAA,MAC/C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,kBACPE,OACG;AACH,QAAI,oBAAoB,SAAS,KAAK,mBAAmB,SAAS,EAAG,QAAOA;AAC5E,UAAM,aAAaA,MAAK,gBAAgB,CAAC;AACzC,UAAM,cAAc,IAAI,IAAY,UAAU;AAC9C,eAAW,KAAK,oBAAqB,aAAY,IAAI,CAAC;AACtD,eAAW,KAAK,mBAAoB,aAAY,OAAO,CAAC;AACxD,UAAM,MAAS,EAAE,GAAGA,OAAM,cAAc,MAAM,KAAK,WAAW,EAAE;AAChE,QAAI,YAAY,OAAO,KAAKA,MAAK,aAAa;AAC5C,YAAM,WAAWA,MAAK,YAAY,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AACjE,UAAI,cAAc,SAAS,SAAS,IAAI,WAAW;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAMA,WAAS,YAAYA,OAAiD;AACpE,QAAI,YAAYA,KAAI,EAAG,QAAO;AAC9B,UAAM,MAAOA,MAAmB;AAChC,UAAM,WAAW,KAAK;AACtB,QAAI,CAAC,YAAY,eAAe,SAAU,QAAO;AACjD,QAAI,EAAE,WAAW,aAAa,CAAC,SAAS,MAAO,QAAO;AACtD,QAAI,SAAS,SAAS,eAAgB,QAAO;AAC7C,UAAM,QAAQ,SAAS;AACvB,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,OAAQA,MAAmB,QAAQ,CAAC,GAAG;AAChD,WAAK,IAAI,OAAQ,IAAgC,KAAK,CAAC,CAAC;AAAA,IAC1D;AACA,WAAO,KAAK;AAAA,EACd;AAEA,WAAS,eAAe,QAAyB;AAC/C,QAAI,mBAAmB,IAAI,MAAM,EAAG,QAAO;AAC3C,QAAI,oBAAoB,IAAI,MAAM,EAAG,QAAO;AAC5C,UAAM,aAAc,YAA4C,gBAAgB,CAAC;AACjF,WAAO,WAAW,SAAS,MAAM;AAAA,EACnC;AAEA,WAAS,uBAAuB,QAAyB;AACvD,UAAM,YAAY,eAAe,MAAM;AACvC,QAAI,CAAC,WAAW;AACd,YAAM,QAAQ,YAAY,WAAW;AACrC,UAAI,OAAO,SAAS,KAAK,GAAG;AAC1B,cAAM,aAAa,IAAI,IAAK,YAA4C,gBAAgB,CAAC,CAAC;AAC1F,YAAI,eAAe;AACnB,cAAM,cAAc,cAAc,WAAW;AAC7C,YAAI,aAAa;AACf,gBAAM,YAAY,oBAAI,IAAY;AAClC,qBAAW,OAAQ,YAA0B,QAAQ,CAAC,GAAG;AACvD,sBAAU,IAAI,OAAQ,IAAgC,WAAW,CAAC,CAAC;AAAA,UACrE;AACA,qBAAW,KAAK,WAAW;AACzB,gBAAI,MAAM,OAAQ;AAClB,gBAAI,mBAAmB,IAAI,CAAC,GAAG;AAC7B;AACA;AAAA,YACF;AACA,gBAAI,oBAAoB,IAAI,CAAC,EAAG;AAChC,gBAAI,CAAC,WAAW,IAAI,CAAC,EAAG;AAAA,UAC1B;AAAA,QACF;AACA,YAAI,iBAAiB,EAAG,QAAO;AAAA,MACjC;AAAA,IACF;AACA,QAAI,WAAW;AACb,0BAAoB,OAAO,MAAM;AACjC,YAAM,aAAc,YAA4C,gBAAgB,CAAC;AACjF,UAAI,WAAW,SAAS,MAAM,EAAG,oBAAmB,IAAI,MAAM;AAAA,IAChE,OAAO;AACL,yBAAmB,OAAO,MAAM;AAChC,0BAAoB,IAAI,MAAM;AAAA,IAChC;AACA,WAAO;AACP,WAAO,CAAC;AAAA,EACV;AAEA,WAAS,cAAcA,OAA6D;AAClF,QAAI,YAAYA,KAAI,EAAG,QAAO;AAC9B,UAAM,WAAYA,MAAmB,UAAU;AAC/C,QAAI,CAAC,YAAY,eAAe,SAAU,QAAO;AACjD,QAAI,EAAE,WAAW,aAAa,CAAC,SAAS,MAAO,QAAO;AACtD,WAAO,SAAS;AAAA,EAClB;AAMA,WAAS,yBAA4D;AACnE,UAAM,OAAO,UAAU,sBAAsB;AAC7C,UAAM,cACJ,aAAa,eAAgB,YAA0B,YAAY;AACrE,QAAI,aAAa;AACf,UAAI,QAAQ,KAAK;AACjB,UAAI,SAAS,KAAK;AAClB,UAAI,CAAC,UAAU,UAAU,eAAe;AACtC,cAAM,aAAa,UAAU,cAAc,sBAAsB;AACjE,iBAAS,WAAW;AACpB,YAAI,CAAC,MAAO,SAAQ,WAAW;AAAA,MACjC;AACA,aAAO;AAAA,QACL,OAAO,KAAK,IAAI,SAAS,KAAK,EAAE;AAAA,QAChC,QAAQ,KAAK,IAAI,UAAU,IAAI,EAAE;AAAA,MACnC;AAAA,IACF;AAKA,QAAI,iBAAiB,SAAS,KAAK,QAAQ,KAAK,KAAK,SAAS,IAAI;AAChE,qBAAe,KAAK,WAAW,KAAK,KAAK,QAAQ;AAAA,IACnD;AAEA,WAAO;AAAA,MACL,OAAO,KAAK,IAAI,KAAK,SAAS,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA,MAItC,QACE,iBAAiB,OAAO,kBAAkB,KAAK,IAAI,KAAK,UAAU,iBAAiB,GAAG;AAAA,IAC1F;AAAA,EACF;AAMA,WAAS,qBAAmC;AAC1C,WAAO,iBAAiB,eAAe,MAAM,QAAQ,YAAY,WAAW,IACxE,YAAY,cACZ,CAAC;AAAA,EACP;AAEA,WAAS,cAAc,KAAuB;AAC5C,QAAI,CAAC,WAAY;AAEjB,UAAM,SAAS,iBAAiB,YAAY,GAAG;AAC/C,QAAI,CAAC,OAAQ;AAEb,QAAI,mBAAmB,CAAC,UAAU,iBAAiB,GAAG,GAAG;AACvD,sBAAgB;AAAA,IAClB;AAEA,sBAAkB;AAClB,qBAAiB,uBAAuB,YAAY,KAAK,aAAa;AACtE,aAAS,WAAW,GAAG;AAEvB,IAAC,WAA6B,MAAM;AAAA,EACtC;AAEA,WAAS,kBAAwB;AAC/B,QAAI,CAAC,gBAAiB;AAEtB,QAAI,uBAAuB,iBAAiB;AAC1C,sBAAgB;AAChB,wBAAkB;AAClB,4BAAsB;AAAA,IACxB;AAEA,UAAM,OAAO;AACb,sBAAkB;AAElB,QAAI,gBAAgB,YAAY;AAC9B,qBAAe,WAAW,YAAY,cAAc;AAAA,IACtD;AACA,qBAAiB;AAEjB,aAAS,aAAa,IAAI;AAAA,EAC5B;AAEA,WAAS,mBAAyB;AAChC,QAAI,CAAC,cAAc,CAAC,mBAAmB,oBAAqB;AAE5D,UAAM,kBAAkB,mBAAmB;AAC3C,QAAI,CAAC,eAAe,iBAAiB,eAAe,EAAG;AAEvD,UAAM,cAAc,eAAe,iBAAiB,WAAW;AAC/D,QAAI,gBAAgB,KAAM;AAE1B,UAAM,SAAS,iBAAiB,YAAY,eAAe;AAC3D,QAAI,CAAC,OAAQ;AAEb,UAAM,SAAS,OAAO,YAAY,SAAS,SAAS,OAAO,cAAc,MAAM;AAC/E,QAAI,CAAC,OAAQ;AAEb,0BAAsB;AACtB,UAAM,UAAU;AAEhB,UAAM,UAAU,sBAAsB;AAAA,MACpC;AAAA,MACA,KAAK;AAAA,MACL,eAAe;AAAA,MACf;AAAA,MACA,UAAU,CAAC,YAAoB;AAC7B,8BAAsB;AACtB,0BAAkB;AAElB,YAAI,YAAY,aAAa;AAC3B,mBAAS,aAAa,SAAS,aAAa,OAAO;AACnD,mBAAS,SAAS;AAAA,YAChB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,UAAU,MAAM;AACd,8BAAsB;AACtB,0BAAkB;AAAA,MACpB;AAAA,IACF,CAAC;AAED,sBAAkB,QAAQ;AAAA,EAC5B;AAEA,WAAS,sBAAkC;AACzC,QAAI,CAAC,WAAY,QAAO,MAAM;AAAA,IAAC;AAE/B,UAAM,MAAM;AACZ,UAAM,WAA8B,CAAC;AAErC,UAAM,cAAc,CAAC,MAAa;AAChC,YAAM,aAAa;AACnB,YAAM,SAAS,WAAW;AAE1B,UAAI,oBAAqB;AAEzB,YAAM,kBAAkB,mBAAmB;AAC3C,YAAM,MAAM,gBAAgB,QAAQ,eAAe;AAEnD,UAAI,KAAK;AACP,sBAAc,GAAG;AAAA,MACnB,OAAO;AACL,wBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,iBAAiB,SAAS,WAAW;AACzC,aAAS,KAAK,MAAM,IAAI,oBAAoB,SAAS,WAAW,CAAC;AAEjE,UAAM,mBAAmB,CAAC,MAAa;AACrC,YAAM,SAAU,EAAE,OAAmB;AAAA,QACnC;AAAA,MACF;AACA,UAAI,QAAQ;AACV,QAAC,OAAsB,UAAU,IAAI,mBAAmB;AAAA,MAC1D;AAAA,IACF;AAEA,UAAM,mBAAmB,CAAC,MAAa;AACrC,YAAM,SAAU,EAAE,OAAmB,QAAQ,oBAAoB;AACjE,UAAI,QAAQ;AACV,QAAC,OAAsB,UAAU,OAAO,mBAAmB;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,iBAAiB,cAAc,kBAAkB,IAAI;AACzD,QAAI,iBAAiB,cAAc,kBAAkB,IAAI;AACzD,aAAS,KAAK,MAAM;AAClB,UAAI,oBAAoB,cAAc,kBAAkB,IAAI;AAC5D,UAAI,oBAAoB,cAAc,kBAAkB,IAAI;AAAA,IAC9D,CAAC;AAED,UAAM,iBAAiB,CAAC,MAAa;AACnC,YAAM,aAAa;AACnB,YAAM,SAAS,WAAW;AAC1B,YAAM,kBAAkB,mBAAmB;AAC3C,YAAM,MAAM,gBAAgB,QAAQ,eAAe;AAEnD,UAAI,OAAO,eAAe,KAAK,eAAe,GAAG;AAC/C,YAAI,CAAC,UAAU,iBAAiB,GAAG,GAAG;AACpC,wBAAc,GAAG;AAAA,QACnB;AACA,yBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,QAAI,iBAAiB,YAAY,cAAc;AAC/C,aAAS,KAAK,MAAM,IAAI,oBAAoB,YAAY,cAAc,CAAC;AAEvE,WAAO,MAAM;AACX,iBAAW,WAAW,UAAU;AAC9B,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,WAAS,yBAAqC;AAC5C,QAAI,CAAC,WAAY,QAAO,MAAM;AAAA,IAAC;AAE/B,UAAM,MAAM;AAEZ,UAAM,gBAAgB,CAAC,MAAqB;AAC1C,YAAM,kBAAkB,mBAAmB;AAE3C,cAAQ,EAAE,KAAK;AAAA,QACb,KAAK;AAAA,QACL,KAAK,aAAa;AAChB,cAAI,mBAAmB,CAAC,qBAAqB;AAC3C,cAAE,eAAe;AACjB,qBAAS,SAAS,EAAE,MAAM,UAAU,SAAS,gBAAgB,CAAC;AAAA,UAChE;AACA;AAAA,QACF;AAAA,QAEA,KAAK,UAAU;AACb,YAAE,eAAe;AACjB,cAAI,uBAAuB,iBAAiB;AAC1C,4BAAgB;AAChB,8BAAkB;AAClB,kCAAsB;AAAA,UACxB,WAAW,iBAAiB;AAC1B,4BAAgB;AAAA,UAClB;AACA;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,cAAc;AACjB,cAAI,CAAC,uBAAuB,iBAAiB;AAC3C,cAAE,eAAe;AACjB,kBAAM,YAAY,oBAAoB,aAAa,aAAa;AAChE,gBAAI,UAAU,WAAW,EAAG;AAE5B,kBAAM,eAAe,UAAU,UAAU,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC;AAC7E,kBAAM,YAAY,gBAAgB,UAAU,SAAS,IAAI,IAAI,eAAe;AAE5E,0BAAc,UAAU,SAAS,CAAC;AAAA,UACpC;AACA;AAAA,QACF;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,aAAa;AAChB,cAAI,CAAC,uBAAuB,iBAAiB;AAC3C,cAAE,eAAe;AACjB,kBAAM,YAAY,oBAAoB,aAAa,aAAa;AAChE,gBAAI,UAAU,WAAW,EAAG;AAE5B,kBAAM,eAAe,UAAU,UAAU,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC;AAC7E,kBAAM,YAAY,gBAAgB,IAAI,UAAU,SAAS,IAAI,eAAe;AAE5E,0BAAc,UAAU,SAAS,CAAC;AAAA,UACpC;AACA;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,cAAI,mBAAmB,CAAC,qBAAqB;AAC3C,gBAAI,eAAe,iBAAiB,eAAe,GAAG;AACpD,gBAAE,eAAe;AACjB,+BAAiB;AAAA,YACnB;AAAA,UACF;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,iBAAiB,WAAW,aAAa;AAE7C,WAAO,MAAM;AACX,UAAI,oBAAoB,WAAW,aAAa;AAAA,IAClD;AAAA,EACF;AAMA,WAAS,SAAe;AACtB,QAAI,YAAY;AACd,sBAAgB;AAChB;AAAA,IACF;AAGA,QAAI,kBAAkB;AACpB,uBAAiB,OAAO;AACxB,yBAAmB;AAAA,IACrB;AAGA,QAAI,mBAAmB;AACrB,wBAAkB;AAClB,0BAAoB;AAAA,IACtB;AACA,qBAAiB,UAAU;AAG3B,2BAAuB;AACvB,2BAAuB;AACvB,2BAAuB;AACvB,2BAAuB;AACvB,yBAAqB;AACrB,yBAAqB;AACrB,oBAAgB;AAChB,oBAAgB;AAChB,yBAAqB;AACrB,yBAAqB;AACrB,4BAAwB;AACxB,4BAAwB;AACxB,uBAAmB;AACnB,uBAAmB;AACnB,uBAAmB;AACnB,uBAAmB;AACnB,0BAAsB;AACtB,0BAAsB;AACtB,QAAI,iBAAiB;AACnB,sBAAgB;AAChB,wBAAkB;AAClB,4BAAsB;AAAA,IACxB;AACA,qBAAiB;AACjB,QAAI,YAAY,YAAY;AAC1B,iBAAW,WAAW,YAAY,UAAU;AAAA,IAC9C;AACA,QAAI,gBAAgB;AAClB,qBAAe,QAAQ;AAAA,IACzB;AACA,QAAI,SAAS,YAAY;AACvB,cAAQ,WAAW,YAAY,OAAO;AACtC,gBAAU;AAAA,IACZ;AAEA,oBAAgB,QAAQ;AAExB,wBAAoB,cAAc,WAAW;AAC7C,4BAAwB,cAAc,WAAW;AACjD,UAAM,gBAAgB,iBAAiB,CAAC,CAAC,cAAc,WAAW;AAClE,UAAM,YAAY,CAAC,CAAC,cAAc;AAClC,iBAAa,eAAe,eAAe,WAAW;AAAA,MACpD,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AACD,qBAAiB,qBAAqB,SAAS;AAG/C,2BAAuB;AAAA,MACrB;AAAA,MACA,cAAc;AAAA,MACd;AAAA,IACF;AAGA,2BAAuB,yBAAyB,YAAY,eAAe,cAAc;AAIzF,QAAI,CAAC,cAAc,KAAK,QAAQ;AAC9B,2BAAqB;AAAA,QACnB;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAKA,UAAM,iBAAiB,kBAAkB,WAAW;AACpD,QACE,kBACA,CAAC,uBACA,oBAAoB,OAAO,KAAK,SAAS,mBAC1C;AACA,2BAAqB;AACrB,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAGA,oBAAgB;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,iBAAiB,SAAY,SAAS;AAAA,IACxC;AAGA,QACE,SAAS,eACT,SAAS,eACT,SAAS,eACT,SAAS,mBACT;AACA,YAAM,kBACJ,iBAAiB,eAAe,MAAM,QAAQ,YAAY,WAAW,IACjE,YAAY,cACZ,CAAC;AACP,2BAAqB,gBAAgB,YAAY,eAAe,iBAAiB,OAAO;AAAA,IAC1F;AAGA,UAAM,cAAc,CAAC,aAAsB;AACzC,mBAAa;AACb,UAAI,CAAC,YAAY,eAAe;AAC9B,wBAAgB;AAChB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,kBACJ,iBAAiB,eAAe,MAAM,QAAQ,YAAY,WAAW,IACjE,YAAY,cACZ,CAAC;AAGP,QAAI,CAAC,mBAAmB,SAAS,oBAAoB,SAAS,SAAS;AACrE,8BAAwB;AAAA,QACtB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,kBAAkB,SAAS,QAAQ;AACtC,YAAM,eAAkC,CAAC;AAEzC,mBAAa;AAAA,QACX,0BAA0B,YAAY,iBAAiB,QAAQ,QAAQ,WAAW;AAAA,MACpF;AACA,mBAAa;AAAA,QACX,wBAAwB,YAAY,iBAAiB,QAAQ,QAAQ,WAAW;AAAA,MAClF;AAEA,YAAM,WAAW;AACjB,mBAAa,KAAK,eAAe,YAAY,UAAU,QAAQ,QAAQ,WAAW,CAAC;AACnF,mBAAa,KAAK,eAAe,YAAY,UAAU,QAAQ,QAAQ,WAAW,CAAC;AACnF,mBAAa,KAAK,oBAAoB,YAAY,UAAU,QAAQ,QAAQ,WAAW,CAAC;AAExF,yBAAmB,MAAM;AACvB,mBAAW,WAAW,cAAc;AAClC,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,kBAAkB,oBAAoB,OAAO,GAAG;AACnD,mBAAa,UAAU;AACvB,yBAAmB,oBAAoB;AACvC,4BAAsB,uBAAuB;AAE7C,UAAI,iBAAiB;AACnB,cAAM,SAAS,iBAAiB,YAAY,eAAe;AAC3D,YAAI,QAAQ;AACV,2BAAiB,uBAAuB,YAAY,iBAAiB,aAAa;AAAA,QACpF,OAAO;AACL,4BAAkB;AAClB,2BAAiB;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAIA,QAAI,CAAC,cAAc,KAAK,QAAQ;AAC9B,gBAAU,wBAAwB,eAAe,SAAS;AAAA,IAC5D;AAKA,QAAI,cAAc,cAAc;AAC9B,UAAI,CAAC,cAAc;AACjB,uBAAe,mBAAmB,EAAE,WAAW,UAAU,mBAAmB,CAAC;AAAA,MAC/E;AACA,mBAAa,OAAO,cAAc,cAAc,UAAU;AAAA,IAC5D,WAAW,cAAc;AACvB,UAAI,kBAAkB,WAAW,GAAG;AAIlC,qBAAa,KAAK;AAAA,MACpB,OAAO;AACL,qBAAa,QAAQ;AACrB,uBAAe;AAAA,MACjB;AAAA,IACF;AAMA,UAAM,kBAAkB,eAAe,WAAW,KAAK,oBAAoB,OAAO;AAClF,QAAI,mBAAmB,CAAC,uBAAuB;AAC7C,8BAAwB;AACxB,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,QAAI,cAAc,aAAa,CAAC,iBAAiB;AAC/C,UAAI,CAAC,WAAW;AACd,oBAAY,gBAAgB,EAAE,WAAW,UAAU,SAAS,SAAS,CAAC;AAAA,MACxE;AACA,gBAAU,OAAO,cAAc,WAAW,UAA2B;AAAA,IACvE,WAAW,WAAW;AACpB,UAAI,eAAe,WAAW,KAAK,CAAC,iBAAiB;AAGnD,kBAAU,KAAK;AAAA,MACjB,OAAO;AACL,kBAAU,QAAQ;AAClB,oBAAY;AAAA,MACd;AAAA,IACF;AAGA,cAAU,UAAU,IAAI,SAAS;AACjC,UAAM,SAASF,iBAAgB,SAAS,QAAQ;AAChD,QAAI,QAAQ;AACV,gBAAU,UAAU,IAAI,SAAS;AAAA,IACnC,OAAO;AACL,gBAAU,UAAU,OAAO,SAAS;AAAA,IACtC;AAIA,yBAAqB,WAAW,cAAc,KAAK;AAGnD,QAAI,iBAAiB,YAAY;AAC/B,0BAAoB,sBAAsB,YAAY,MAAM;AAC1D,4BAAoB;AACpB,YAAI,eAAe;AACjB,0BAAgB;AAChB,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAGA,iBAAa;AACb,cAAU,QAAQ,cAAc,OAAO,SAAS;AAMhD,QAAI,oBAAoB;AACtB,2BAAqB;AACrB,gBAAU,QAAQ,eAAe;AAAA,IACnC;AAEA,QAAI,eAAe;AACjB,sBAAgB;AAAA,IAClB;AAAA,EACF;AAMA,WAAS,OAAO,SAAgC,YAAkC;AAChF,QAAI,UAAW;AAGf,UAAM,WAAW;AACjB,UAAM,aAAa;AACnB,UAAM,qBAAqB,qBAAqB;AAKhD,QAAI,kBAAkB,SAAS;AAC7B,2BAAqB,iBAAiB,SAAS;AAAA,IACjD;AAEA,kBAAc;AAGd,UAAM,WAAW,qBAAqB;AACtC,QAAI,aAAa,YAAY;AAC3B,mBAAa;AACb,oBAAc,kBAAkB,UAAU;AAAA,IAC5C;AACA,wBAAoB,MAAM;AAC1B,uBAAmB,MAAM;AAGzB,qBAAiB,kBAAkB,OAAO;AAC1C,kBAAc,YAAY,CAAC,CAAC;AAG5B,4BAAwB;AACxB,yBAAqB;AACrB,QAAI,cAAc,qBAAqB,YAAY;AACjD,wBAAkB,WAAW,mBAAmB;AAAA,IAClD;AACA,WAAO;AAIP,QACE,cACA,cAAc;AAAA,MACZ;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA,UAAU;AAAA,MACV,eAAe;AAAA,MACf,kBAAkB;AAAA,IACpB,CAAC,GACD;AAEA,YAAM,WAAW;AACjB,2BAAqB;AAErB,yBAAmB,cAAc;AAAA,QAC/B,KAAK;AAAA,QACL;AAAA,QACA,YAAY;AAAA,QACZ,WAAW,cAAc;AAAA,QACzB,cAAc,YAAY;AAAA,QAC1B,YAAY,MAAM;AAChB,6BAAmB;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AAEL,2BAAqB;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,SAAe;AACtB,QAAI,UAAW;AACf,QAAI,mBAAmB;AACrB,sBAAgB;AAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAOA,WAAS,mBAAmB,UAA0B;AACpD,UAAM,SAAS,CAAC,GAAG,cAAc;AACjC,eAAW,KAAK,UAAU;AACxB,UAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO,KAAK,CAAC;AAAA,IACxC;AACA,iBAAa,OAAO,SAAS,IAAI,SAAS,IAAI;AAC9C,aAAS,oBAAoB,MAAM;AAAA,EACrC;AAEA,WAAS,aAAa,QAA+B;AACnD,QAAI,UAAW;AACf,QAAI,YAAY,WAAW,KAAK,YAAY,WAAiD;AAC3F;AACF,UAAME,QAAO;AACb,UAAM,WAAWA,MAAK,UAAU;AAChC,QAAI,CAAC,YAAY,OAAO,aAAa,YAAY,EAAE,WAAW,UAAW;AACzE,UAAM,UAAW,SAA+C;AAChE,QAAI,CAAC,QAAQ,UAAU,CAAC,QAAS;AACjC,UAAM,eAAe,EAAE,GAAG,SAAS;AACnC,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,mBAAa,YAAY;AAAA,IAC3B,OAAO;AACL,aAAO,aAAa;AAAA,IACtB;AACA,kBAAc;AAAA,MACZ,GAAGA;AAAA,MACH,UAAU,EAAE,GAAGA,MAAK,UAAU,OAAO,aAAa;AAAA,IACpD;AACA,WAAO;AAAA,EACT;AAOA,WAAS,SACP,QACA,eAC0C;AAC1C,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAEA,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,UAAU,UAAU;AAAA,MAC7B,KAAK;AACH,eAAO,mBAAmB,YAAY,aAAa;AAAA,MACrD,KAAK;AACH,eAAO,UAAU,YAAY,aAAa;AAAA,MAC5C,KAAK;AACH,eAAO,UAAU,YAAY,aAAa;AAAA,MAC5C,KAAK;AACH,eAAO;AAAA,UACL,UAAU,eAAe,MAAM,QAAQ,YAAY,IAAI,IAAI,YAAY,OAAO,CAAC;AAAA,QACjF;AAAA,MACF;AACE,cAAM,IAAI,MAAM,8BAA8B,MAAM,EAAE;AAAA,IAC1D;AAAA,EACF;AAEA,WAAS,UAAgB;AACvB,QAAI,UAAW;AACf,gBAAY;AAGZ,QAAI,kBAAkB;AACpB,uBAAiB,OAAO;AACxB,yBAAmB;AAAA,IACrB;AACA,yBAAqB;AAErB,QAAI,mBAAmB;AACrB,wBAAkB;AAClB,0BAAoB;AACpB,sBAAgB;AAAA,IAClB;AACA,qBAAiB,UAAU;AAE3B,2BAAuB;AACvB,2BAAuB;AACvB,2BAAuB;AACvB,2BAAuB;AACvB,yBAAqB;AACrB,yBAAqB;AACrB,oBAAgB;AAChB,oBAAgB;AAChB,yBAAqB;AACrB,yBAAqB;AACrB,4BAAwB;AACxB,4BAAwB;AACxB,uBAAmB;AACnB,uBAAmB;AACnB,uBAAmB;AACnB,uBAAmB;AACnB,0BAAsB;AACtB,0BAAsB;AACtB,QAAI,iBAAiB;AACnB,sBAAgB;AAChB,wBAAkB;AAClB,4BAAsB;AAAA,IACxB;AACA,sBAAkB;AAClB,qBAAiB;AACjB,QAAI,cAAc;AAChB,mBAAa,QAAQ;AACrB,qBAAe;AAAA,IACjB;AACA,QAAI,WAAW;AACb,gBAAU,QAAQ;AAClB,kBAAY;AAAA,IACd;AACA,QAAI,kBAAkB;AACpB,uBAAiB;AACjB,yBAAmB;AAAA,IACrB;AACA,QAAI,gBAAgB;AAClB,qBAAe,QAAQ;AACvB,uBAAiB;AAAA,IACnB;AACA,QAAI,YAAY,YAAY;AAC1B,iBAAW,WAAW,YAAY,UAAU;AAC5C,mBAAa;AAAA,IACf;AACA,QAAI,SAAS,YAAY;AACvB,cAAQ,WAAW,YAAY,OAAO;AACtC,gBAAU;AAAA,IACZ;AACA,cAAU,UAAU,OAAO,SAAS;AACpC,cAAU,UAAU,OAAO,SAAS;AAAA,EACtC;AAGA,SAAO;AAMP,QAAM,UAAU;AAAA,IACd;AAAA,IACA,MAAM,CAAC;AAAA,IACP,MAAM;AAIJ,2BAAqB;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AACA,YAAU,QAAQ,eAAe,UAAU,YAAY;AAGvD,MAAI,SAAS,eAAe,OAAO;AACjC,uBAAmB,cAAc,WAAW,CAAC,OAAO,WAAW;AAM7D,UAAI,iBAAiB,MAAM;AACzB,cAAM,eAAe,UAAU;AAC/B,cAAM,oBAAoB,WAAW;AACrC,YAAI,CAAC,gBAAgB,kBAAmB;AACxC,YAAI,CAAC,mBAAmB;AAItB,yBAAe;AAAA,QACjB;AACA,eAAO;AACP;AAAA,MACF;AAGA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,qBAAwC;AACtC,aAAO;AAAA,IACT;AAAA,IACA,OAAO,KAAuB;AAC5B,UAAI,UAAW;AACf,oBAAc,GAAG;AAAA,IACnB;AAAA,IACA,WAAiB;AACf,UAAI,UAAW;AACf,sBAAgB;AAAA,IAClB;AAAA,IACA,IAAI,YAAqB;AACvB,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA,eAAqB;AACnB,UAAI,UAAW;AACf,iBAAW,MAAM;AAAA,IACnB;AAAA,IACA,gBAAsB;AACpB,UAAI,UAAW;AACf,iBAAW,OAAO;AAAA,IACpB;AAAA,EACF;AACF;","names":["SVG_NS","createSVGElement","setAttrs","color","rgb","fontsPending","computePosition","color","cssTokenDefault","color","getScale","SVG_NS","cleanup","SVG_NS","resolveDarkMode","cssTokenDefault","spec"]}
|