{"version":3,"sources":["jsdelivr-header.js","/npm/@chartts/core@0.1.6/src/constants.ts","/npm/@chartts/core@0.1.6/src/theme/presets.ts","/npm/@chartts/core@0.1.6/src/theme/engine.ts","/npm/@chartts/core@0.1.6/src/events/bus.ts","/npm/@chartts/core@0.1.6/src/scales/nice.ts","/npm/@chartts/core@0.1.6/src/scales/linear.ts","/npm/@chartts/core@0.1.6/src/scales/categorical.ts","/npm/@chartts/core@0.1.6/src/interaction/zoom-pan.ts","/npm/@chartts/core@0.1.6/src/interaction/brush.ts","/npm/@chartts/core@0.1.6/src/debug/debug.ts","/npm/@chartts/core@0.1.6/src/data/decimate.ts","/npm/@chartts/core@0.1.6/src/styles/chart.ts","/npm/@chartts/core@0.1.6/src/render/svg.ts","/npm/@chartts/core@0.1.6/src/render/canvas.ts","/npm/@chartts/core@0.1.6/src/render/webgl.ts","/npm/@chartts/core@0.1.6/src/layout/compute.ts","/npm/@chartts/core@0.1.6/src/render/tree.ts","/npm/@chartts/core@0.1.6/src/axis/axis.ts","/npm/@chartts/core@0.1.6/src/legend/legend.ts","/npm/@chartts/core@0.1.6/src/tooltip/tooltip.ts","/npm/@chartts/core@0.1.6/src/interaction/highlight.ts","/npm/@chartts/core@0.1.6/src/interaction/interaction.ts","/npm/@chartts/core@0.1.6/src/render/states.ts","/npm/@chartts/core@0.1.6/src/render/effects.ts","/npm/@chartts/core@0.1.6/src/api/create.ts","/npm/@chartts/core@0.1.6/src/api/renderer-manager.ts","/npm/@chartts/core@0.1.6/src/api/state-manager.ts","/npm/@chartts/core@0.1.6/src/api/exporter.ts","/npm/@chartts/core@0.1.6/src/layout/responsive.ts","/npm/@chartts/core@0.1.6/src/data/validate.ts","/npm/@chartts/core@0.1.6/src/data/prepare.ts","/npm/@chartts/core@0.1.6/src/api/define.ts","/npm/@chartts/core@0.1.6/src/render/string.ts","/npm/@chartts/core@0.1.6/src/utils/prepare.ts","/npm/@chartts/core@0.1.6/src/charts/voronoi/voronoi-type.ts","/npm/@chartts/core@0.1.6/src/charts/wordcloud/wordcloud-type.ts","/npm/@chartts/core@0.1.6/src/charts/pillar/pillar-type.ts","/npm/@chartts/core@0.1.6/src/finance/moving-averages.ts","/npm/@chartts/core@0.1.6/src/finance/oscillators.ts","/npm/@chartts/core@0.1.6/src/finance/macd.ts","/npm/@chartts/core@0.1.6/src/finance/bollinger.ts","/npm/@chartts/core@0.1.6/src/finance/volatility.ts","/npm/@chartts/core@0.1.6/src/finance/volume.ts","/npm/@chartts/core@0.1.6/src/finance/returns.ts","/npm/@chartts/core@0.1.6/src/finance/builders.ts","/npm/@chartts/core@0.1.6/src/utils/format.ts","/npm/@chartts/core@0.1.6/src/utils/curves.ts","/npm/@chartts/core@0.1.6/src/utils/hit-test.ts","/npm/@chartts/core@0.1.6/src/charts/line/line-type.ts","/npm/@chartts/core@0.1.6/src/charts/step/step-type.ts","/npm/@chartts/core@0.1.6/src/utils/scale.ts","/npm/@chartts/core@0.1.6/src/charts/volume/volume-type.ts","/npm/@chartts/core@0.1.6/src/charts/range/range-type.ts","/npm/@chartts/core@0.1.6/src/charts/baseline/baseline-type.ts","/npm/@chartts/core@0.1.6/src/charts/kagi/kagi-type.ts","/npm/@chartts/core@0.1.6/src/charts/renko/renko-type.ts","/npm/@chartts/core@0.1.6/src/charts/violin/violin-type.ts","/npm/@chartts/core@0.1.6/src/charts/pack/pack-type.ts","/npm/@chartts/core@0.1.6/src/charts/themeriver/themeriver-type.ts","/npm/@chartts/core@0.1.6/src/charts/pictorialbar/pictorialbar-type.ts","/npm/@chartts/core@0.1.6/src/charts/chord/chord-type.ts","/npm/@chartts/core@0.1.6/src/charts/geo/world-regions.ts","/npm/@chartts/core@0.1.6/src/charts/geo/geo-type.ts","/npm/@chartts/core@0.1.6/src/charts/lines/lines-type.ts","/npm/@chartts/core@0.1.6/src/charts/matrix/matrix-type.ts","/npm/@chartts/core@0.1.6/src/charts/custom/custom-type.ts","/npm/@chartts/core@0.1.6/src/charts/ohlc/ohlc-type.ts","/npm/@chartts/core@0.1.6/src/charts/dumbbell/dumbbell-type.ts","/npm/@chartts/core@0.1.6/src/charts/calendar/calendar-type.ts","/npm/@chartts/core@0.1.6/src/charts/combo/combo-type.ts","/npm/@chartts/core@0.1.6/src/charts/sankey/sankey-type.ts","/npm/@chartts/core@0.1.6/src/utils/slice-path.ts","/npm/@chartts/core@0.1.6/src/charts/sunburst/sunburst-type.ts","/npm/@chartts/core@0.1.6/src/charts/tree/tree-type.ts","/npm/@chartts/core@0.1.6/src/charts/graph/parse.ts","/npm/@chartts/core@0.1.6/src/charts/graph/text-measure.ts","/npm/@chartts/core@0.1.6/src/charts/graph/shapes.ts","/npm/@chartts/core@0.1.6/src/charts/graph/edges.ts","/npm/@chartts/core@0.1.6/src/charts/graph/layout-hierarchy.ts","/npm/@chartts/core@0.1.6/src/charts/graph/layout-circular.ts","/npm/@chartts/core@0.1.6/src/charts/graph/graph-type.ts","/npm/@chartts/core@0.1.6/src/charts/graph/layout-force.ts","/npm/@chartts/core@0.1.6/src/charts/parallel/parallel-type.ts","/npm/@chartts/core@0.1.6/src/charts/heatmap/heatmap-type.ts","/npm/@chartts/core@0.1.6/src/charts/boxplot/boxplot-type.ts","/npm/@chartts/core@0.1.6/src/charts/histogram/histogram-type.ts","/npm/@chartts/core@0.1.6/src/charts/treemap/treemap-type.ts","/npm/@chartts/core@0.1.6/src/charts/polar/polar-type.ts","/npm/@chartts/core@0.1.6/src/charts/radialbar/radialbar-type.ts","/npm/@chartts/core@0.1.6/src/charts/lollipop/lollipop-type.ts","/npm/@chartts/core@0.1.6/src/charts/bullet/bullet-type.ts","/npm/@chartts/core@0.1.6/src/charts/sparkline/sparkline-type.ts","/npm/@chartts/core@0.1.6/src/charts/area/area-type.ts","/npm/@chartts/core@0.1.6/src/charts/radar/radar-type.ts","/npm/@chartts/core@0.1.6/src/charts/bubble/bubble-type.ts","/npm/@chartts/core@0.1.6/src/charts/candlestick/candlestick-type.ts","/npm/@chartts/core@0.1.6/src/charts/gauge/gauge-type.ts","/npm/@chartts/core@0.1.6/src/charts/waterfall/waterfall-type.ts","/npm/@chartts/core@0.1.6/src/charts/funnel/funnel-type.ts","/npm/@chartts/core@0.1.6/src/charts/bar/bar-type.ts","/npm/@chartts/core@0.1.6/src/charts/bar/stacked-bar-type.ts","/npm/@chartts/core@0.1.6/src/charts/bar/horizontal-bar-type.ts","/npm/@chartts/core@0.1.6/src/charts/pie/pie-type.ts","/npm/@chartts/core@0.1.6/src/charts/scatter/scatter-type.ts","/npm/@chartts/core@0.1.6/src/charts/gantt/gantt-type.ts","/npm/@chartts/core@0.1.6/src/charts/org/org-type.ts","/npm/@chartts/core@0.1.6/src/charts/flow/flow-type.ts","/npm/@chartts/core@0.1.6/src/charts/pareto/pareto-type.ts","/npm/@chartts/core@0.1.6/src/api/chart-types.ts","/npm/@chartts/core@0.1.6/src/api/convenience.ts","/npm/@chartts/core@0.1.6/src/interaction/link.ts","/npm/@chartts/core@0.1.6/src/data/streaming.ts","/npm/@chartts/core@0.1.6/src/features/dataset.ts","/npm/@chartts/core@0.1.6/src/features/datazoom.ts","/npm/@chartts/core@0.1.6/src/features/datazoom-widget.ts","/npm/@chartts/core@0.1.6/src/features/graphic.ts","/npm/@chartts/core@0.1.6/src/features/richtext.ts","/npm/@chartts/core@0.1.6/src/registry/registry.ts","/npm/@chartts/core@0.1.6/src/scales/time.ts"],"names":[],"mappings":"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","file":"/npm/@chartts/core@0.1.6/dist/index.js/+esm","sourceRoot":"","sourcesContent":["/**\n * Bundled by jsDelivr using Rollup v4.62.2 and Terser v5.48.0.\n * Original file: /npm/@chartts/core@0.1.6/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\n * Chartts constants and default values.\n *\n * RULES:\n * - Imports ONLY from types.ts.\n * - Single source of truth for all default values.\n * - Colors use var(--color-*) with hex fallbacks — Tailwind-first.\n * - Every other module reads defaults from here. No duplicates.\n */\n\nimport type { ThemeConfig, ResolvedOptions, ChartOptions } from './types'\n\n// ---------------------------------------------------------------------------\n// CSS custom property prefix\n// ---------------------------------------------------------------------------\n\nexport const CSS_PREFIX = '--chartts' as const\n\n// ---------------------------------------------------------------------------\n// Color palette — Tailwind CSS var() references with hex fallbacks\n//\n// Tailwind v4: exposes --color-blue-500 etc. automatically.\n// Tailwind v3: @chartts/tailwind plugin bridges the gap.\n// No Tailwind: hex fallbacks work perfectly on their own.\n// ---------------------------------------------------------------------------\n\nexport const PALETTE = [\n  'var(--color-blue-500, #3b82f6)',\n  'var(--color-red-500, #ef4444)',\n  'var(--color-emerald-500, #10b981)',\n  'var(--color-amber-500, #f59e0b)',\n  'var(--color-violet-500, #8b5cf6)',\n  'var(--color-pink-500, #ec4899)',\n  'var(--color-cyan-500, #06b6d4)',\n  'var(--color-lime-500, #84cc16)',\n  'var(--color-orange-500, #f97316)',\n  'var(--color-indigo-500, #6366f1)',\n] as const\n\n// ---------------------------------------------------------------------------\n// Font stack\n// ---------------------------------------------------------------------------\n\nexport const FONT_FAMILY =\n  'var(--font-sans, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif)'\n\n// ---------------------------------------------------------------------------\n// Theme presets\n// ---------------------------------------------------------------------------\n\nexport const LIGHT_THEME: ThemeConfig = {\n  colors: [...PALETTE],\n  background: 'transparent',\n  textColor: 'var(--color-gray-800, #1f2937)',\n  textMuted: 'var(--color-gray-500, #6b7280)',\n  axisColor: 'var(--color-gray-300, #d1d5db)',\n  gridColor: 'var(--color-gray-200, #e5e7eb)',\n  tooltipBackground: 'var(--color-white, #ffffff)',\n  tooltipText: 'var(--color-gray-800, #1f2937)',\n  tooltipBorder: 'var(--color-gray-200, #e5e7eb)',\n  fontFamily: FONT_FAMILY,\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 14,\n  borderRadius: 8,\n  gridStyle: 'dashed',\n  gridWidth: 1,\n  axisWidth: 1,\n  pointRadius: 4,\n  lineWidth: 2.5,\n}\n\nexport const DARK_THEME: ThemeConfig = {\n  colors: [...PALETTE],\n  background: 'transparent',\n  textColor: 'var(--color-gray-100, #f3f4f6)',\n  textMuted: 'var(--color-gray-500, #6b7280)',\n  axisColor: 'var(--color-gray-700, #374151)',\n  gridColor: 'var(--color-gray-800, #1f2937)',\n  tooltipBackground: 'var(--color-gray-900, #111827)',\n  tooltipText: 'var(--color-gray-100, #f3f4f6)',\n  tooltipBorder: 'var(--color-gray-700, #374151)',\n  fontFamily: FONT_FAMILY,\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 14,\n  borderRadius: 8,\n  gridStyle: 'dashed',\n  gridWidth: 1,\n  axisWidth: 1,\n  pointRadius: 4,\n  lineWidth: 2.5,\n}\n\n// ---------------------------------------------------------------------------\n// Chart type classification sets\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated Use `chartType.suppressAxes` flag instead.\n * Kept for backwards compatibility only.\n */\nexport const NO_AXES_TYPES = new Set([\n  'sparkline', 'gauge', 'funnel', 'radar', 'pie', 'donut',\n  'heatmap', 'horizontal-bar', 'treemap', 'polar',\n  'radial-bar', 'bullet', 'dumbbell', 'calendar', 'sankey',\n  'sunburst', 'tree', 'graph', 'parallel', 'themeriver',\n  'pictorialbar', 'chord', 'geo', 'lines', 'matrix', 'custom',\n  'kagi', 'renko', 'pack', 'voronoi', 'wordcloud',\n])\n\n/**\n * @deprecated Use `chartType.useBandScale` flag instead.\n * Kept for backwards compatibility only.\n */\nexport const BAND_SCALE_TYPES = new Set([\n  'bar', 'stacked-bar', 'horizontal-bar', 'candlestick',\n  'waterfall', 'histogram', 'boxplot', 'lollipop', 'combo',\n  'ohlc', 'volume', 'violin',\n])\n\n// ---------------------------------------------------------------------------\n// Default options resolver\n// ---------------------------------------------------------------------------\n\nexport function resolveOptions(\n  opts: ChartOptions,\n  seriesCount: number,\n): ResolvedOptions {\n  const multi = seriesCount > 1\n\n  // Spread original opts first so chart-type-specific properties (ohlc, sizes,\n  // totals, gaugeMin, etc.) survive into RenderContext.options.\n  return {\n    ...opts,\n    width: opts.width ?? 0,\n    height: opts.height ?? 0,\n    padding: opts.padding ?? [12, 16, 8, 8],\n    renderer: opts.renderer ?? 'svg',\n    theme: opts.theme ?? 'auto',\n\n    xLabel: opts.xLabel ?? '',\n    yLabel: opts.yLabel ?? '',\n    xFormat: opts.xFormat ?? formatX,\n    yFormat: opts.yFormat ?? formatY,\n    xGrid: opts.xGrid ?? false,\n    yGrid: opts.yGrid ?? true,\n    xAxis: opts.xAxis ?? true,\n    yAxis: opts.yAxis ?? true,\n    xTicks: opts.xTicks ?? 0,\n    yTicks: opts.yTicks ?? 5,\n    yMin: opts.yMin,\n    yMax: opts.yMax,\n\n    legend: opts.legend === undefined\n      ? (multi ? 'top' : false)\n      : opts.legend === true ? 'top' : opts.legend,\n    tooltip: opts.tooltip === undefined || opts.tooltip === true\n      ? { enabled: true }\n      : opts.tooltip === false ? false : opts.tooltip,\n\n    animate: opts.animate ?? true,\n    duration: opts.duration ?? 300,\n\n    zoom: opts.zoom ?? false,\n    pan: opts.pan ?? false,\n    crosshair: !opts.crosshair\n      ? false\n      : opts.crosshair === true\n        ? { enabled: true, mode: 'vertical' as const }\n        : { enabled: opts.crosshair.enabled ?? true, mode: opts.crosshair.mode ?? 'vertical' as const },\n    brush: opts.brush ?? false,\n\n    colors: opts.colors ?? [...PALETTE],\n    fontFamily: opts.fontFamily ?? FONT_FAMILY,\n    fontSize: opts.fontSize ?? 12,\n    curve: opts.curve ?? 'monotone',\n    barRadius: opts.barRadius ?? 4,\n    barGap: opts.barGap ?? 0.2,\n\n    ariaLabel: opts.ariaLabel ?? 'Chart',\n    ariaDescription: opts.ariaDescription ?? '',\n\n    onClick: opts.onClick,\n    onHover: opts.onHover,\n\n    className: opts.className ?? '',\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Default formatters\n// ---------------------------------------------------------------------------\n\nfunction formatX(value: string | number | Date): string {\n  if (value instanceof Date) return value.toLocaleDateString()\n  return String(value)\n}\n\nfunction formatY(value: number): string {\n  const abs = Math.abs(value)\n  if (abs >= 1e12) return trim(value / 1e12, 'T')\n  if (abs >= 1e9) return trim(value / 1e9, 'B')\n  if (abs >= 1e6) return trim(value / 1e6, 'M')\n  if (abs >= 1e3) return trim(value / 1e3, 'K')\n  if (Number.isInteger(value)) return String(value)\n  return value.toFixed(1)\n}\n\n/** Format with suffix, dropping trailing .0 (e.g. 1.0K → 1K) */\nfunction trim(v: number, suffix: string): string {\n  const s = v.toFixed(1)\n  return (s.endsWith('.0') ? s.slice(0, -2) : s) + suffix\n}\n","import type { ThemeConfig } from '../types'\nimport { FONT_FAMILY } from '../constants'\n\n/**\n * Named theme presets for different use cases.\n *\n * Each preset defines a complete ThemeConfig with a curated color palette,\n * typography, and styling tuned for a specific aesthetic.\n */\n\n// ---------------------------------------------------------------------------\n// Corporate / Finance — muted blues and grays, solid grid, conservative\n// ---------------------------------------------------------------------------\n\nexport const CORPORATE_THEME: ThemeConfig = {\n  colors: [\n    '#1e40af', '#2563eb', '#3b82f6', '#60a5fa', '#93c5fd',\n    '#1e3a5f', '#0f766e', '#4f46e5', '#7c3aed', '#be185d',\n  ],\n  background: 'transparent',\n  textColor: '#1e293b',\n  textMuted: '#64748b',\n  axisColor: '#94a3b8',\n  gridColor: '#e2e8f0',\n  tooltipBackground: '#ffffff',\n  tooltipText: '#1e293b',\n  tooltipBorder: '#cbd5e1',\n  fontFamily: '\"Inter\", \"Segoe UI\", -apple-system, sans-serif',\n  fontSize: 11,\n  fontSizeSmall: 9,\n  fontSizeLarge: 13,\n  borderRadius: 4,\n  gridStyle: 'solid',\n  gridWidth: 1,\n  axisWidth: 1,\n  pointRadius: 3,\n  lineWidth: 2,\n}\n\n// ---------------------------------------------------------------------------\n// SaaS / Dashboard — vibrant, modern, slightly rounded\n// ---------------------------------------------------------------------------\n\nexport const SAAS_THEME: ThemeConfig = {\n  colors: [\n    '#6366f1', '#8b5cf6', '#ec4899', '#f43f5e', '#f97316',\n    '#eab308', '#22c55e', '#06b6d4', '#0ea5e9', '#a855f7',\n  ],\n  background: 'transparent',\n  textColor: '#0f172a',\n  textMuted: '#475569',\n  axisColor: '#cbd5e1',\n  gridColor: '#f1f5f9',\n  tooltipBackground: '#0f172a',\n  tooltipText: '#f8fafc',\n  tooltipBorder: '#334155',\n  fontFamily: FONT_FAMILY,\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 14,\n  borderRadius: 8,\n  gridStyle: 'dashed',\n  gridWidth: 1,\n  axisWidth: 1,\n  pointRadius: 4,\n  lineWidth: 2.5,\n}\n\n// ---------------------------------------------------------------------------\n// Startup / Bold — high contrast, energetic palette\n// ---------------------------------------------------------------------------\n\nexport const STARTUP_THEME: ThemeConfig = {\n  colors: [\n    '#ff6b6b', '#feca57', '#48dbfb', '#ff9ff3', '#54a0ff',\n    '#5f27cd', '#01a3a4', '#f368e0', '#ff6348', '#2ed573',\n  ],\n  background: 'transparent',\n  textColor: '#2d3436',\n  textMuted: '#636e72',\n  axisColor: '#b2bec3',\n  gridColor: '#dfe6e9',\n  tooltipBackground: '#2d3436',\n  tooltipText: '#dfe6e9',\n  tooltipBorder: '#636e72',\n  fontFamily: '\"DM Sans\", \"Inter\", -apple-system, sans-serif',\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 15,\n  borderRadius: 10,\n  gridStyle: 'dotted',\n  gridWidth: 1,\n  axisWidth: 2,\n  pointRadius: 5,\n  lineWidth: 3,\n}\n\n// ---------------------------------------------------------------------------\n// Editorial / Minimal — newspaper-inspired, serif accents, restrained palette\n// ---------------------------------------------------------------------------\n\nexport const EDITORIAL_THEME: ThemeConfig = {\n  colors: [\n    '#1a1a1a', '#c0392b', '#2980b9', '#8e44ad', '#27ae60',\n    '#d35400', '#2c3e50', '#16a085', '#f39c12', '#7f8c8d',\n  ],\n  background: 'transparent',\n  textColor: '#1a1a1a',\n  textMuted: '#7f8c8d',\n  axisColor: '#bdc3c7',\n  gridColor: '#ecf0f1',\n  tooltipBackground: '#1a1a1a',\n  tooltipText: '#ecf0f1',\n  tooltipBorder: '#34495e',\n  fontFamily: '\"Georgia\", \"Times New Roman\", serif',\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 14,\n  borderRadius: 0,\n  gridStyle: 'solid',\n  gridWidth: 0.5,\n  axisWidth: 1.5,\n  pointRadius: 3,\n  lineWidth: 1.5,\n}\n\n// ---------------------------------------------------------------------------\n// Ocean / Dark — rich dark mode with ocean-inspired gradients\n// ---------------------------------------------------------------------------\n\nexport const OCEAN_THEME: ThemeConfig = {\n  colors: [\n    '#00d2ff', '#3a7bd5', '#00b894', '#fdcb6e', '#e17055',\n    '#a29bfe', '#fd79a8', '#55efc4', '#74b9ff', '#ffeaa7',\n  ],\n  background: 'transparent',\n  textColor: '#dfe6e9',\n  textMuted: '#636e72',\n  axisColor: '#2d3436',\n  gridColor: '#2d3436',\n  tooltipBackground: '#0a0a23',\n  tooltipText: '#dfe6e9',\n  tooltipBorder: '#2d3436',\n  fontFamily: FONT_FAMILY,\n  fontSize: 12,\n  fontSizeSmall: 10,\n  fontSizeLarge: 14,\n  borderRadius: 6,\n  gridStyle: 'dashed',\n  gridWidth: 1,\n  axisWidth: 1,\n  pointRadius: 3.5,\n  lineWidth: 2,\n}\n\n/** All named presets keyed by name */\nexport const THEME_PRESETS: Record<string, ThemeConfig> = {\n  corporate: CORPORATE_THEME,\n  saas: SAAS_THEME,\n  startup: STARTUP_THEME,\n  editorial: EDITORIAL_THEME,\n  ocean: OCEAN_THEME,\n}\n","import type { ThemeConfig } from '../types'\nimport { CSS_PREFIX, LIGHT_THEME, DARK_THEME } from '../constants'\nimport { THEME_PRESETS } from './presets'\n\nexport function resolveTheme(theme: string | ThemeConfig): ThemeConfig {\n  if (typeof theme === 'object') return { ...LIGHT_THEME, ...theme }\n\n  switch (theme) {\n    case 'dark': return DARK_THEME\n    case 'light': return LIGHT_THEME\n    case 'auto': return detectScheme() === 'dark' ? DARK_THEME : LIGHT_THEME\n    default: {\n      const preset = THEME_PRESETS[theme]\n      if (preset) return preset\n      return LIGHT_THEME\n    }\n  }\n}\n\n/**\n * Apply theme as CSS custom properties on a DOM element.\n * Every token becomes --chartts-* so users can override via CSS or Tailwind.\n */\nexport function applyTheme(el: HTMLElement | SVGElement, theme: ThemeConfig): void {\n  const s = el.style\n\n  theme.colors.forEach((c, i) => s.setProperty(`${CSS_PREFIX}-color-${i + 1}`, c))\n\n  s.setProperty(`${CSS_PREFIX}-bg`, theme.background)\n  s.setProperty(`${CSS_PREFIX}-text`, theme.textColor)\n  s.setProperty(`${CSS_PREFIX}-text-muted`, theme.textMuted)\n  s.setProperty(`${CSS_PREFIX}-axis`, theme.axisColor)\n  s.setProperty(`${CSS_PREFIX}-grid`, theme.gridColor)\n  s.setProperty(`${CSS_PREFIX}-tooltip-bg`, theme.tooltipBackground)\n  s.setProperty(`${CSS_PREFIX}-tooltip-text`, theme.tooltipText)\n  s.setProperty(`${CSS_PREFIX}-tooltip-border`, theme.tooltipBorder)\n  s.setProperty(`${CSS_PREFIX}-font-family`, theme.fontFamily)\n  s.setProperty(`${CSS_PREFIX}-font-size`, `${theme.fontSize}px`)\n  s.setProperty(`${CSS_PREFIX}-font-size-sm`, `${theme.fontSizeSmall}px`)\n  s.setProperty(`${CSS_PREFIX}-font-size-lg`, `${theme.fontSizeLarge}px`)\n  s.setProperty(`${CSS_PREFIX}-radius`, `${theme.borderRadius}px`)\n  s.setProperty(`${CSS_PREFIX}-grid-width`, String(theme.gridWidth))\n  s.setProperty(`${CSS_PREFIX}-axis-width`, String(theme.axisWidth))\n  s.setProperty(`${CSS_PREFIX}-point-r`, String(theme.pointRadius))\n  s.setProperty(`${CSS_PREFIX}-line-w`, String(theme.lineWidth))\n}\n\n/** Watch for system color scheme changes. Returns unsubscribe function. */\nexport function watchScheme(cb: (scheme: 'light' | 'dark') => void): () => void {\n  if (typeof window === 'undefined' || !window.matchMedia) return () => {}\n  const mql = window.matchMedia('(prefers-color-scheme: dark)')\n  const handler = (e: MediaQueryListEvent): void => cb(e.matches ? 'dark' : 'light')\n  mql.addEventListener('change', handler)\n  return () => mql.removeEventListener('change', handler)\n}\n\nfunction detectScheme(): 'light' | 'dark' {\n  if (typeof window === 'undefined' || !window.matchMedia) return 'light'\n  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n","import type { ChartEvents, EventHandler, Unsubscribe, EventBus } from '../types'\n\nexport function createEventBus(): EventBus {\n  const listeners = new Map<string, Set<EventHandler<unknown>>>()\n\n  return {\n    on<K extends keyof ChartEvents>(\n      event: K,\n      handler: EventHandler<ChartEvents[K]>,\n    ): Unsubscribe {\n      let set = listeners.get(event as string)\n      if (!set) {\n        set = new Set()\n        listeners.set(event as string, set)\n      }\n      set.add(handler as EventHandler<unknown>)\n      return () => {\n        set.delete(handler as EventHandler<unknown>)\n        if (set.size === 0) listeners.delete(event as string)\n      }\n    },\n\n    emit<K extends keyof ChartEvents>(event: K, payload: ChartEvents[K]): void {\n      const set = listeners.get(event as string)\n      if (set) for (const h of set) h(payload)\n    },\n\n    off<K extends keyof ChartEvents>(\n      event: K,\n      handler: EventHandler<ChartEvents[K]>,\n    ): void {\n      const set = listeners.get(event as string)\n      if (!set) return\n      set.delete(handler as EventHandler<unknown>)\n      if (set.size === 0) listeners.delete(event as string)\n    },\n\n    destroy(): void {\n      listeners.clear()\n    },\n  }\n}\n","/**\n * Nice number algorithms for human-readable axis ticks.\n * Produces values like 0, 20, 40, 60, 80, 100 — not 0, 17, 34, 51, 68, 85.\n */\n\nexport function niceNumber(value: number, round: boolean): number {\n  if (value === 0) return 0\n  const exp = Math.floor(Math.log10(Math.abs(value)))\n  const frac = value / Math.pow(10, exp)\n\n  let nice: number\n  if (round) {\n    nice = frac < 1.5 ? 1 : frac < 3 ? 2 : frac < 7 ? 5 : 10\n  } else {\n    nice = frac <= 1 ? 1 : frac <= 2 ? 2 : frac <= 5 ? 5 : 10\n  }\n\n  return nice * Math.pow(10, exp)\n}\n\nexport function niceRange(\n  dataMin: number,\n  dataMax: number,\n  tickCount: number,\n): { min: number; max: number; spacing: number } {\n  if (tickCount < 2) tickCount = 2\n\n  if (dataMin === dataMax) {\n    if (dataMin === 0) return { min: 0, max: 1, spacing: 0.2 }\n    const pad = Math.abs(dataMin) * 0.1 || 1\n    return niceRange(dataMin - pad, dataMax + pad, tickCount)\n  }\n\n  const range = niceNumber(dataMax - dataMin, false)\n  const spacing = niceNumber(range / (tickCount - 1), true)\n  const min = Math.floor(dataMin / spacing) * spacing\n  const max = Math.ceil(dataMax / spacing) * spacing\n\n  return { min, max, spacing }\n}\n\nexport function generateTicks(min: number, max: number, spacing: number): number[] {\n  if (spacing <= 0) return [min]\n\n  const ticks: number[] = []\n  const eps = spacing * 1e-10\n\n  for (let v = min; v <= max + eps; v += spacing) {\n    ticks.push(Math.round(v * 1e12) / 1e12)\n  }\n  return ticks\n}\n","import type { Scale, Tick } from '../types'\nimport { niceRange, generateTicks } from './nice'\n\nexport interface LinearScaleOpts {\n  domain?: [number, number]\n  range?: [number, number]\n  nice?: boolean\n  clamp?: boolean\n  format?: (value: number) => string\n}\n\nexport function createLinearScale(opts?: LinearScaleOpts): Scale {\n  let dMin = opts?.domain?.[0] ?? 0\n  let dMax = opts?.domain?.[1] ?? 1\n  let rMin = opts?.range?.[0] ?? 0\n  let rMax = opts?.range?.[1] ?? 1\n  const useNice = opts?.nice ?? true\n  const clamp = opts?.clamp ?? false\n  const fmt = opts?.format ?? defaultFmt\n\n  // When nice is enabled, adjust the domain to nice values\n  // so ticks always map within the chart area\n  if (useNice && dMin !== dMax) {\n    const { min, max } = niceRange(dMin, dMax, 5)\n    dMin = min\n    dMax = max\n  }\n\n  function map(value: number | string | Date): number {\n    const v = Number(value)\n    const span = dMax - dMin\n    if (span === 0) return (rMin + rMax) / 2\n    let t = (v - dMin) / span\n    if (clamp) t = Math.max(0, Math.min(1, t))\n    return round2(rMin + t * (rMax - rMin))\n  }\n\n  function invert(px: number): number {\n    const span = rMax - rMin\n    if (span === 0) return (dMin + dMax) / 2\n    return dMin + ((px - rMin) / span) * (dMax - dMin)\n  }\n\n  function ticks(count = 5): Tick[] {\n    const { min, max, spacing } = niceRange(dMin, dMax, count)\n    const vals = generateTicks(useNice ? min : dMin, useNice ? max : dMax, spacing)\n    return vals.map((v) => ({ value: v, position: map(v), label: fmt(v) }))\n  }\n\n  return {\n    map,\n    invert,\n    ticks,\n    setDomain(min, max) { dMin = Number(min); dMax = Number(max) },\n    setRange(min, max) { rMin = min; rMax = max },\n    getDomain() { return [dMin, dMax] },\n    getRange() { return [rMin, rMax] },\n    bandwidth() { return 0 },\n  }\n}\n\nfunction round2(n: number): number {\n  return Math.round(n * 100) / 100\n}\n\nfunction defaultFmt(v: number): string {\n  const abs = Math.abs(v)\n  if (abs >= 1e12) return trimSuffix(v / 1e12, 'T')\n  if (abs >= 1e9) return trimSuffix(v / 1e9, 'B')\n  if (abs >= 1e6) return trimSuffix(v / 1e6, 'M')\n  if (abs >= 1e3) return trimSuffix(v / 1e3, 'K')\n  if (Number.isInteger(v)) return String(v)\n  return v.toFixed(1)\n}\n\nfunction trimSuffix(v: number, suffix: string): string {\n  const s = v.toFixed(1)\n  return (s.endsWith('.0') ? s.slice(0, -2) : s) + suffix\n}\n","import type { Scale, Tick } from '../types'\n\nexport interface CategoricalScaleOpts {\n  categories?: (string | number | Date)[]\n  range?: [number, number]\n  format?: (value: string | number | Date) => string\n  /**\n   * When true, distributes categories into equal-width bands with\n   * each category centered in its band. This prevents items at\n   * the edges from overflowing the chart area (critical for bar charts).\n   * When false (default), positions are edge-to-edge.\n   */\n  band?: boolean\n}\n\nexport function createCategoricalScale(opts?: CategoricalScaleOpts): Scale & {\n  setCategories(cats: (string | number | Date)[]): void\n  /** Get the width of one band (only meaningful in band mode) */\n  bandwidth(): number\n} {\n  let cats: (string | number | Date)[] = opts?.categories ?? []\n  let rMin = opts?.range?.[0] ?? 0\n  let rMax = opts?.range?.[1] ?? 1\n  const fmt = opts?.format ?? String\n  const useBand = opts?.band ?? false\n\n  function round2(n: number): number {\n    return Math.round(n * 100) / 100\n  }\n\n  function pos(index: number): number {\n    const n = cats.length\n    if (n === 0) return round2((rMin + rMax) / 2)\n    if (useBand) {\n      const slotWidth = (rMax - rMin) / n\n      return round2(rMin + (index + 0.5) * slotWidth)\n    }\n    if (n <= 1) return round2((rMin + rMax) / 2)\n    return round2(rMin + (index / (n - 1)) * (rMax - rMin))\n  }\n\n  function bandwidth(): number {\n    const n = cats.length\n    if (n === 0) return 0\n    if (useBand) return (rMax - rMin) / n\n    // For point mode, approximate bandwidth from spacing\n    if (n <= 1) return rMax - rMin\n    return (rMax - rMin) / (n - 1)\n  }\n\n  function map(value: number | string | Date): number {\n    if (typeof value === 'number' && Number.isFinite(value)) return pos(value)\n\n    const idx = cats.findIndex((c) =>\n      c instanceof Date && value instanceof Date\n        ? c.getTime() === value.getTime()\n        : String(c) === String(value),\n    )\n    return idx === -1 ? (rMin + rMax) / 2 : pos(idx)\n  }\n\n  function invert(px: number): number {\n    const n = cats.length\n    if (n === 0) return 0\n    if (useBand) {\n      const slotWidth = (rMax - rMin) / n\n      return Math.floor((px - rMin) / slotWidth)\n    }\n    if (n <= 1) return 0\n    const t = (px - rMin) / (rMax - rMin)\n    return Math.round(t * (n - 1))\n  }\n\n  function ticks(): Tick[] {\n    return cats.map((c, i) => ({ value: c, position: pos(i), label: fmt(c) }))\n  }\n\n  return {\n    map,\n    invert,\n    ticks,\n    setDomain() {},\n    setRange(min, max) { rMin = min; rMax = max },\n    getDomain() { return [cats[0] ?? '', cats[cats.length - 1] ?? ''] },\n    getRange() { return [rMin, rMax] },\n    setCategories(c) { cats = c },\n    bandwidth,\n  }\n}\n","/**\n * Zoom & Pan interaction module.\n *\n * Works with all renderers — modifies scale domains, not DOM elements.\n * Wheel zoom on the x-axis, drag to pan. Touch pinch support.\n */\n\nimport type { Scale, ChartArea } from '../types'\n\nexport interface ZoomPanConfig {\n  /** Enable x-axis zoom. Default true. */\n  x?: boolean\n  /** Enable y-axis zoom. Default false. */\n  y?: boolean\n  /** Enable wheel zoom. Default true. */\n  wheel?: boolean\n  /** Enable drag pan. Default true. */\n  drag?: boolean\n  /** Enable pinch zoom. Default true. */\n  pinch?: boolean\n  /** Minimum zoom level (1 = no zoom). Default 1. */\n  minZoom?: number\n  /** Maximum zoom level. Default 20. */\n  maxZoom?: number\n  /** When false, drag uses pixel-proportional deltas without zoom normalization.\n   *  For chart types that apply pan directly to pixel transforms (geo, pie, etc).\n   *  Default true (axis-scale behavior). */\n  normalizedPan?: boolean\n}\n\nexport interface ZoomPanState {\n  zoomX: number\n  zoomY: number\n  panX: number\n  panY: number\n}\n\nexport interface ZoomPanInstance {\n  attach(el: HTMLElement | SVGElement, getArea: () => ChartArea, getScales: () => { xScale: Scale; yScale: Scale }): void\n  reset(): void\n  getState(): ZoomPanState\n  applyToScales(xScale: Scale, yScale: Scale, area: ChartArea): void\n  destroy(): void\n}\n\n/**\n * Create a zoom & pan controller.\n *\n * Usage:\n * ```ts\n * const zp = createZoomPan({ x: true, y: false }, () => render())\n * zp.attach(svgElement, () => chartArea, () => ({ xScale, yScale }))\n * // On each render, apply to scales:\n * zp.applyToScales(xScale, yScale, area)\n * ```\n */\nexport function createZoomPan(\n  config: ZoomPanConfig,\n  onUpdate: () => void,\n  interactionState?: { isPanning: boolean },\n): ZoomPanInstance {\n  const cfg = {\n    x: config.x ?? true,\n    y: config.y ?? false,\n    wheel: config.wheel ?? true,\n    drag: config.drag ?? true,\n    pinch: config.pinch ?? true,\n    minZoom: config.minZoom ?? 1,\n    maxZoom: config.maxZoom ?? 20,\n    normalizedPan: config.normalizedPan ?? true,\n  }\n\n  const state: ZoomPanState = {\n    zoomX: 1,\n    zoomY: 1,\n    panX: 0,\n    panY: 0,\n  }\n\n  let el: HTMLElement | SVGElement | null = null\n  let getArea: (() => ChartArea) | null = null\n  let isDragging = false\n  let dragStartX = 0\n  let dragStartY = 0\n  let dragStartPanX = 0\n  let dragStartPanY = 0\n\n  // Touch state\n  let lastPinchDist = 0\n\n  // -----------------------------------------------------------------------\n  // Wheel zoom\n  // -----------------------------------------------------------------------\n\n  function onWheel(e: WheelEvent): void {\n    if (!cfg.wheel || !getArea) return\n    e.preventDefault()\n\n    const area = getArea()\n    const rect = el!.getBoundingClientRect()\n    const mouseX = e.clientX - rect.left\n    const relX = (mouseX - area.x) / area.width\n\n    // Zoom factor\n    const delta = e.deltaY > 0 ? 0.9 : 1.1\n\n    if (cfg.x) {\n      const newZoom = clamp(state.zoomX * delta, cfg.minZoom, cfg.maxZoom)\n      // Adjust pan to zoom around cursor position\n      const zoomRatio = newZoom / state.zoomX\n      state.panX = relX - (relX - state.panX) * zoomRatio\n      state.zoomX = newZoom\n    }\n\n    if (cfg.y) {\n      const mouseY = e.clientY - rect.top\n      const relY = (mouseY - area.y) / area.height\n      const newZoomY = clamp(state.zoomY * delta, cfg.minZoom, cfg.maxZoom)\n      const zoomRatioY = newZoomY / state.zoomY\n      state.panY = relY - (relY - state.panY) * zoomRatioY\n      state.zoomY = newZoomY\n    }\n\n    clampPan()\n    onUpdate()\n  }\n\n  // -----------------------------------------------------------------------\n  // Drag pan\n  // -----------------------------------------------------------------------\n\n  function onPointerDown(e: PointerEvent): void {\n    if (!cfg.drag) return\n    // Don't start pan if shift is held (reserved for brush selection)\n    if (e.shiftKey) return\n    isDragging = true\n    if (interactionState) interactionState.isPanning = true\n    dragStartX = e.clientX\n    dragStartY = e.clientY\n    dragStartPanX = state.panX\n    dragStartPanY = state.panY\n    el!.setPointerCapture(e.pointerId)\n    ;(el as HTMLElement).style.cursor = 'grabbing'\n  }\n\n  function onPointerMove(e: PointerEvent): void {\n    if (!isDragging || !getArea) return\n    const area = getArea()\n    const dx = e.clientX - dragStartX\n    const dy = e.clientY - dragStartY\n\n    if (cfg.x) {\n      state.panX = dragStartPanX + dx / (cfg.normalizedPan ? area.width * state.zoomX : area.width)\n    }\n    if (cfg.y) {\n      state.panY = dragStartPanY + dy / (cfg.normalizedPan ? area.height * state.zoomY : area.height)\n    }\n\n    clampPan()\n    onUpdate()\n  }\n\n  function onPointerUp(e: PointerEvent): void {\n    if (!isDragging) return\n    isDragging = false\n    if (interactionState) interactionState.isPanning = false\n    el!.releasePointerCapture(e.pointerId)\n    ;(el as HTMLElement).style.cursor = 'crosshair'\n  }\n\n  // -----------------------------------------------------------------------\n  // Touch pinch\n  // -----------------------------------------------------------------------\n\n  let lastPinchCenterX = 0\n  let lastPinchCenterY = 0\n\n  function onTouchStart(e: TouchEvent): void {\n    if (!cfg.pinch || e.touches.length !== 2) return\n    lastPinchDist = pinchDistance(e)\n    lastPinchCenterX = (e.touches[0]!.clientX + e.touches[1]!.clientX) / 2\n    lastPinchCenterY = (e.touches[0]!.clientY + e.touches[1]!.clientY) / 2\n  }\n\n  function onTouchMove(e: TouchEvent): void {\n    if (!cfg.pinch || e.touches.length !== 2 || !getArea) return\n    e.preventDefault()\n\n    const area = getArea()\n    const rect = el!.getBoundingClientRect()\n    const dist = pinchDistance(e)\n    const scaleFactor = dist / lastPinchDist\n    lastPinchDist = dist\n\n    // Pinch center in chart-relative coords\n    const cx = (lastPinchCenterX - rect.left - area.x) / area.width\n    const cy = (lastPinchCenterY - rect.top - area.y) / area.height\n\n    // Update pinch center for next frame\n    lastPinchCenterX = (e.touches[0]!.clientX + e.touches[1]!.clientX) / 2\n    lastPinchCenterY = (e.touches[0]!.clientY + e.touches[1]!.clientY) / 2\n\n    // Zoom toward pinch center (same formula as wheel zoom)\n    if (cfg.x) {\n      const newZoom = clamp(state.zoomX * scaleFactor, cfg.minZoom, cfg.maxZoom)\n      const ratio = newZoom / state.zoomX\n      state.panX = cx - (cx - state.panX) * ratio\n      state.zoomX = newZoom\n    }\n    if (cfg.y) {\n      const newZoom = clamp(state.zoomY * scaleFactor, cfg.minZoom, cfg.maxZoom)\n      const ratio = newZoom / state.zoomY\n      state.panY = cy - (cy - state.panY) * ratio\n      state.zoomY = newZoom\n    }\n\n    clampPan()\n    onUpdate()\n  }\n\n  // -----------------------------------------------------------------------\n  // Helpers\n  // -----------------------------------------------------------------------\n\n  function clampPan(): void {\n    // Keep visible window within bounds.\n    // With normalizedPan (axis charts): pan is fraction of content, range ±(1-1/zoom)/2\n    // Without normalizedPan (geo etc): pan is fraction of area pixels, range scaled by zoom\n    const halfVisX = (1 - 1 / state.zoomX) / 2\n    const limitX = cfg.normalizedPan ? halfVisX : state.zoomX - 1\n    state.panX = clamp(state.panX, -limitX, limitX)\n\n    const halfVisY = (1 - 1 / state.zoomY) / 2\n    const limitY = cfg.normalizedPan ? halfVisY : state.zoomY - 1\n    state.panY = clamp(state.panY, -limitY, limitY)\n  }\n\n  function pinchDistance(e: TouchEvent): number {\n    const dx = e.touches[0]!.clientX - e.touches[1]!.clientX\n    const dy = e.touches[0]!.clientY - e.touches[1]!.clientY\n    return Math.sqrt(dx * dx + dy * dy)\n  }\n\n  function clamp(v: number, min: number, max: number): number {\n    return Math.min(Math.max(v, min), max)\n  }\n\n  // -----------------------------------------------------------------------\n  // Public API\n  // -----------------------------------------------------------------------\n\n  return {\n    attach(element, areaFn, _scalesFn) {\n      el = element\n      getArea = areaFn\n\n      if (cfg.wheel) {\n        el.addEventListener('wheel', onWheel as EventListener, { passive: false })\n      }\n      if (cfg.drag) {\n        el.addEventListener('pointerdown', onPointerDown as EventListener)\n        el.addEventListener('pointermove', onPointerMove as EventListener)\n        el.addEventListener('pointerup', onPointerUp as EventListener)\n      }\n      if (cfg.pinch) {\n        el.addEventListener('touchstart', onTouchStart as EventListener, { passive: false })\n        el.addEventListener('touchmove', onTouchMove as EventListener, { passive: false })\n      }\n    },\n\n    reset() {\n      state.zoomX = 1\n      state.zoomY = 1\n      state.panX = 0\n      state.panY = 0\n      onUpdate()\n    },\n\n    getState() {\n      return { ...state }\n    },\n\n    /**\n     * Apply current zoom/pan to scales by adjusting their domains.\n     * Call this at the start of each render, after creating scales.\n     */\n    applyToScales(xScale, yScale, area) {\n      if (state.zoomX === 1 && state.zoomY === 1 && state.panX === 0 && state.panY === 0) return\n\n      if (cfg.x && state.zoomX !== 1) {\n        const [xMin, xMax] = xScale.getRange()\n        const fullWidth = xMax - xMin\n        const visibleWidth = fullWidth / state.zoomX\n        const offset = -state.panX * fullWidth\n        xScale.setRange(area.x + offset, area.x + offset + visibleWidth)\n      }\n\n      if (cfg.y && state.zoomY !== 1) {\n        const [yMin, yMax] = yScale.getDomain() as [number, number]\n        const fullRange = yMax - yMin\n        const visibleRange = fullRange / state.zoomY\n        const offset = -state.panY * fullRange\n        yScale.setDomain(yMin + offset, yMin + offset + visibleRange)\n      }\n    },\n\n    destroy() {\n      if (!el) return\n      el.removeEventListener('wheel', onWheel as EventListener)\n      el.removeEventListener('pointerdown', onPointerDown as EventListener)\n      el.removeEventListener('pointermove', onPointerMove as EventListener)\n      el.removeEventListener('pointerup', onPointerUp as EventListener)\n      el.removeEventListener('touchstart', onTouchStart as EventListener)\n      el.removeEventListener('touchmove', onTouchMove as EventListener)\n      el = null\n      getArea = null\n    },\n  }\n}\n","/**\n * Brush selection module.\n *\n * Click-drag to select a data range on the chart area.\n * When pan is also enabled, requires Shift+drag to activate.\n * Emits brush:end event with start/end label indices.\n */\n\nimport type { ChartArea, Scale, EventBus, PreparedData } from '../types'\n\nexport interface BrushConfig {\n  /** Fill color of selection rect. Default rgba(59,130,246,0.15). */\n  fillColor?: string\n  /** Border color of selection rect. Default rgba(59,130,246,0.5). */\n  strokeColor?: string\n}\n\nexport interface BrushInstance {\n  destroy(): void\n}\n\nexport function createBrush(\n  config: BrushConfig,\n  bus: EventBus,\n  el: HTMLElement | SVGElement,\n  getArea: () => ChartArea,\n  getXScale: () => Scale,\n  getData: () => PreparedData,\n  isPanEnabled: boolean,\n): BrushInstance {\n  const fillColor = config.fillColor ?? 'rgba(59,130,246,0.15)'\n  const strokeColor = config.strokeColor ?? 'rgba(59,130,246,0.5)'\n\n  let isBrushing = false\n  let startClientX = 0\n  let brushRect: HTMLDivElement | null = null\n  let parentEl: HTMLElement | null = null\n\n  // We need a parent element for absolute positioning\n  function getParent(): HTMLElement {\n    if (parentEl) return parentEl\n    parentEl = el.parentElement as HTMLElement\n    if (!parentEl) parentEl = el as unknown as HTMLElement\n    parentEl.style.position = 'relative'\n    return parentEl\n  }\n\n  function toLocalX(clientX: number): number {\n    const r = el.getBoundingClientRect()\n    return clientX - r.left\n  }\n\n  function onPointerDown(e: PointerEvent): void {\n    // If pan is enabled, require Shift for brush\n    if (isPanEnabled && !e.shiftKey) return\n    // If pan is NOT enabled, any click starts brush\n    if (!isPanEnabled && e.shiftKey) return // shift reserved for other uses when no pan\n\n    const area = getArea()\n    const localX = toLocalX(e.clientX)\n    const r = el.getBoundingClientRect()\n    const localY = e.clientY - r.top\n\n    // Only start if within chart area\n    if (localX < area.x || localX > area.x + area.width) return\n    if (localY < area.y || localY > area.y + area.height) return\n\n    isBrushing = true\n    startClientX = e.clientX\n    ;(el as HTMLElement).setPointerCapture(e.pointerId)\n\n    // Create selection rect\n    brushRect = document.createElement('div')\n    brushRect.className = 'chartts-brush-rect'\n    brushRect.style.cssText = `\n      position: absolute;\n      top: ${area.y}px;\n      height: ${area.height}px;\n      left: ${localX}px;\n      width: 0px;\n      background: ${fillColor};\n      border-left: 1px solid ${strokeColor};\n      border-right: 1px solid ${strokeColor};\n      pointer-events: none;\n      z-index: 10;\n    `\n    getParent().appendChild(brushRect)\n  }\n\n  function onPointerMove(e: PointerEvent): void {\n    if (!isBrushing || !brushRect) return\n\n    const area = getArea()\n    const startX = Math.max(toLocalX(startClientX), area.x)\n    const currentX = Math.min(Math.max(toLocalX(e.clientX), area.x), area.x + area.width)\n\n    const left = Math.min(startX, currentX)\n    const width = Math.abs(currentX - startX)\n\n    brushRect.style.left = `${left}px`\n    brushRect.style.width = `${width}px`\n  }\n\n  function onPointerUp(e: PointerEvent): void {\n    if (!isBrushing) return\n    isBrushing = false\n    ;(el as HTMLElement).releasePointerCapture(e.pointerId)\n\n    const area = getArea()\n    const xScale = getXScale()\n    const data = getData()\n\n    const startX = Math.max(toLocalX(startClientX), area.x)\n    const endX = Math.min(Math.max(toLocalX(e.clientX), area.x), area.x + area.width)\n\n    // Remove rect\n    brushRect?.remove()\n    brushRect = null\n\n    // Minimum drag distance to count as selection (5px)\n    if (Math.abs(endX - startX) < 5) return\n\n    // Convert pixel positions to data indices\n    const leftX = Math.min(startX, endX)\n    const rightX = Math.max(startX, endX)\n\n    // Find nearest label indices\n    let startIdx = 0\n    let endIdx = data.labels.length - 1\n    let bestStartDist = Infinity\n    let bestEndDist = Infinity\n\n    for (let i = 0; i < data.labels.length; i++) {\n      const pos = xScale.map(data.labels[i]!)\n      const distToStart = Math.abs(pos - leftX)\n      const distToEnd = Math.abs(pos - rightX)\n      if (distToStart < bestStartDist) { bestStartDist = distToStart; startIdx = i }\n      if (distToEnd < bestEndDist) { bestEndDist = distToEnd; endIdx = i }\n    }\n\n    if (startIdx > endIdx) [startIdx, endIdx] = [endIdx, startIdx]\n\n    bus.emit('brush:end', {\n      startIndex: startIdx,\n      endIndex: endIdx,\n      startLabel: data.labels[startIdx]!,\n      endLabel: data.labels[endIdx]!,\n    })\n  }\n\n  function onKeyDown(e: KeyboardEvent): void {\n    if (e.key === 'Escape' && isBrushing) {\n      isBrushing = false\n      brushRect?.remove()\n      brushRect = null\n    }\n  }\n\n  // Attach listeners\n  el.addEventListener('pointerdown', onPointerDown as EventListener)\n  el.addEventListener('pointermove', onPointerMove as EventListener)\n  el.addEventListener('pointerup', onPointerUp as EventListener)\n  document.addEventListener('keydown', onKeyDown)\n\n  return {\n    destroy(): void {\n      el.removeEventListener('pointerdown', onPointerDown as EventListener)\n      el.removeEventListener('pointermove', onPointerMove as EventListener)\n      el.removeEventListener('pointerup', onPointerUp as EventListener)\n      document.removeEventListener('keydown', onKeyDown)\n      brushRect?.remove()\n    },\n  }\n}\n","import type { RenderNode, RenderContext } from '../types'\n\n/**\n * Debug utilities for Chartts.\n * Attach to a chart to get render tree inspection, event logging, and an overlay panel.\n */\nexport interface DebugPanel {\n  attach(container: HTMLElement, svg: SVGElement): void\n  update(ctx: RenderContext, nodes: RenderNode[]): void\n  destroy(): void\n}\n\nexport function createDebugPanel(): DebugPanel {\n  let panel: HTMLDivElement | null = null\n  let treeEl: HTMLPreElement | null = null\n  let statsEl: HTMLDivElement | null = null\n\n  function attach(container: HTMLElement, svg: SVGElement): void {\n    panel = document.createElement('div')\n    panel.className = 'chartts-debug'\n    panel.style.cssText = `\n      position: absolute;\n      top: 0;\n      right: 0;\n      width: 320px;\n      max-height: 100%;\n      overflow-y: auto;\n      background: rgba(0,0,0,0.9);\n      color: #e5e7eb;\n      font-family: \"SF Mono\", \"Fira Code\", monospace;\n      font-size: 11px;\n      padding: 12px;\n      border-left: 1px solid #333;\n      z-index: 10000;\n    `\n\n    // Stats section\n    statsEl = document.createElement('div')\n    statsEl.style.cssText = 'margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid #333;'\n    panel.appendChild(statsEl)\n\n    // Render tree section\n    const treeLabel = document.createElement('div')\n    treeLabel.textContent = 'RENDER TREE'\n    treeLabel.style.cssText = 'color: #8b5cf6; font-weight: 700; margin-bottom: 8px; font-size: 10px; letter-spacing: 0.05em;'\n    panel.appendChild(treeLabel)\n\n    treeEl = document.createElement('pre')\n    treeEl.style.cssText = 'margin: 0; white-space: pre-wrap; word-break: break-all; line-height: 1.4;'\n    panel.appendChild(treeEl)\n\n    container.style.position = 'relative'\n    container.appendChild(panel)\n\n    // Add SVG element outline on hover\n    svg.addEventListener('mouseover', (e) => {\n      const target = e.target as SVGElement\n      if (target !== svg) {\n        target.style.outline = '1px solid rgba(139, 92, 246, 0.5)'\n      }\n    })\n    svg.addEventListener('mouseout', (e) => {\n      const target = e.target as SVGElement\n      target.style.outline = ''\n    })\n  }\n\n  function update(ctx: RenderContext, nodes: RenderNode[]): void {\n    if (!statsEl || !treeEl) return\n\n    // Stats\n    const nodeCount = countNodes(nodes)\n    const { data, options, area } = ctx\n    statsEl.innerHTML = `\n      <div style=\"color:#8b5cf6;font-weight:700;font-size:10px;letter-spacing:0.05em;margin-bottom:8px;\">CHART INFO</div>\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:4px;\">\n        <span style=\"color:#6b7280;\">Series:</span><span>${data.series.length}</span>\n        <span style=\"color:#6b7280;\">Points:</span><span>${data.series[0]?.values.length ?? 0}</span>\n        <span style=\"color:#6b7280;\">SVG nodes:</span><span>${nodeCount}</span>\n        <span style=\"color:#6b7280;\">Area:</span><span>${Math.round(area.width)}x${Math.round(area.height)}</span>\n        <span style=\"color:#6b7280;\">Y range:</span><span>${data.bounds.yMin} — ${data.bounds.yMax}</span>\n        <span style=\"color:#6b7280;\">Theme:</span><span>${typeof options.theme === 'string' ? options.theme : 'custom'}</span>\n        <span style=\"color:#6b7280;\">Curve:</span><span>${options.curve}</span>\n        <span style=\"color:#6b7280;\">Animate:</span><span>${options.animate}</span>\n      </div>\n    `\n\n    // Render tree\n    treeEl.innerHTML = renderTreeToString(nodes, 0)\n  }\n\n  function destroy(): void {\n    panel?.remove()\n    panel = null\n    treeEl = null\n    statsEl = null\n  }\n\n  return { attach, update, destroy }\n}\n\nfunction countNodes(nodes: RenderNode[]): number {\n  let count = 0\n  for (const node of nodes) {\n    count++\n    if ('children' in node && Array.isArray(node.children)) {\n      count += countNodes(node.children)\n    }\n  }\n  return count\n}\n\nfunction renderTreeToString(nodes: RenderNode[], depth: number): string {\n  const indent = '  '.repeat(depth)\n  let result = ''\n\n  for (const node of nodes) {\n    const attrs = 'attrs' in node ? node.attrs : undefined\n    const cls = attrs?.class ? ` <span style=\"color:#3b82f6\">.${attrs.class}</span>` : ''\n    const type = `<span style=\"color:#10b981\">${node.type}</span>`\n\n    if ('children' in node && Array.isArray(node.children)) {\n      result += `${indent}${type}${cls} (${node.children.length})\\n`\n      result += renderTreeToString(node.children, depth + 1)\n    } else if (node.type === 'text') {\n      result += `${indent}${type}${cls} \"${(node as { content: string }).content}\"\\n`\n    } else if (node.type === 'path') {\n      const d = (node as { d: string }).d\n      result += `${indent}${type}${cls} d=\"${d.length > 40 ? d.slice(0, 40) + '...' : d}\"\\n`\n    } else {\n      result += `${indent}${type}${cls}\\n`\n    }\n  }\n\n  return result\n}\n","/**\n * Data decimation algorithms for large datasets.\n *\n * Reduces data point count while preserving visual shape.\n * Sits in the pipeline between raw data and render.\n */\n\nimport type { ChartData, Series } from '../types'\n\nexport interface DecimateOptions {\n  /** Decimation algorithm. Default 'lttb'. */\n  algorithm?: 'lttb' | 'min-max'\n  /** Target number of output points. Default: 2x container pixel width. */\n  threshold?: number\n}\n\n/**\n * Decimate chart data to `threshold` points per series.\n * Returns original data if already below threshold.\n */\nexport function decimateData(\n  data: ChartData,\n  opts: DecimateOptions,\n): ChartData {\n  const threshold = opts.threshold ?? 1000\n  const algo = opts.algorithm ?? 'lttb'\n\n  // Check if any series exceeds threshold\n  const needsDecimation = data.series.some(s => s.values.length > threshold)\n  if (!needsDecimation) return data\n\n  const decimated: Series[] = data.series.map(s => {\n    if (s.values.length <= threshold) return s\n\n    const values = algo === 'lttb'\n      ? lttb(s.values, threshold)\n      : minMax(s.values, threshold)\n\n    return { ...s, values: values.map(p => p.value) }\n  })\n\n  // Decimate labels to match\n  const primarySeries = data.series[0]\n  let labels = data.labels\n  if (labels && primarySeries && primarySeries.values.length > threshold) {\n    const indices = (decimated[0]!.values.length === threshold)\n      ? getDecimatedIndices(primarySeries.values, threshold, algo)\n      : undefined\n    if (indices) {\n      labels = indices.map(i => labels![i]!) as typeof labels\n    }\n  }\n\n  return { labels, series: decimated }\n}\n\n// ---------------------------------------------------------------------------\n// LTTB — Largest Triangle Three Buckets\n// ---------------------------------------------------------------------------\n\ninterface IndexedPoint {\n  index: number\n  value: number\n}\n\n/**\n * Largest Triangle Three Buckets algorithm.\n * Selects points that maximize the visual triangle area,\n * preserving the shape of the data while reducing point count.\n *\n * Reference: Sveinn Steinarsson, \"Downsampling Time Series for Visual\n * Representation\" (2013)\n */\nfunction lttb(values: number[], threshold: number): IndexedPoint[] {\n  const len = values.length\n  if (len <= threshold) {\n    return values.map((v, i) => ({ index: i, value: v }))\n  }\n\n  const sampled: IndexedPoint[] = []\n\n  // Always keep first point\n  sampled.push({ index: 0, value: values[0]! })\n\n  // Bucket size (excluding first and last points)\n  const bucketSize = (len - 2) / (threshold - 2)\n\n  let prevIndex = 0\n\n  for (let i = 1; i < threshold - 1; i++) {\n    // Current bucket range\n    const bucketStart = Math.floor((i - 1) * bucketSize) + 1\n    const bucketEnd = Math.min(Math.floor(i * bucketSize) + 1, len - 1)\n\n    // Next bucket average (for triangle computation)\n    const nextBucketStart = Math.floor(i * bucketSize) + 1\n    const nextBucketEnd = Math.min(Math.floor((i + 1) * bucketSize) + 1, len - 1)\n\n    let avgX = 0\n    let avgY = 0\n    let avgCount = 0\n    for (let j = nextBucketStart; j < nextBucketEnd; j++) {\n      avgX += j\n      avgY += values[j]!\n      avgCount++\n    }\n    if (avgCount > 0) {\n      avgX /= avgCount\n      avgY /= avgCount\n    }\n\n    // Find point in current bucket that creates largest triangle\n    let maxArea = -1\n    let bestIndex = bucketStart\n\n    const px = prevIndex\n    const py = values[prevIndex]!\n\n    for (let j = bucketStart; j < bucketEnd; j++) {\n      // Triangle area = 0.5 * |x1(y2-y3) + x2(y3-y1) + x3(y1-y2)|\n      const area = Math.abs(\n        (px - avgX) * (values[j]! - py) -\n        (px - j) * (avgY - py),\n      ) * 0.5\n\n      if (area > maxArea) {\n        maxArea = area\n        bestIndex = j\n      }\n    }\n\n    sampled.push({ index: bestIndex, value: values[bestIndex]! })\n    prevIndex = bestIndex\n  }\n\n  // Always keep last point\n  sampled.push({ index: len - 1, value: values[len - 1]! })\n\n  return sampled\n}\n\n// ---------------------------------------------------------------------------\n// Min-Max — preserves peaks and valleys\n// ---------------------------------------------------------------------------\n\n/**\n * Min-Max decimation. Each bucket keeps both the minimum and maximum values,\n * ensuring peaks and valleys are always visible.\n */\nfunction minMax(values: number[], threshold: number): IndexedPoint[] {\n  const len = values.length\n  if (len <= threshold) {\n    return values.map((v, i) => ({ index: i, value: v }))\n  }\n\n  const sampled: IndexedPoint[] = []\n  const bucketSize = len / (threshold / 2)\n\n  // Always keep first\n  sampled.push({ index: 0, value: values[0]! })\n\n  for (let i = 0; i < threshold / 2 - 1; i++) {\n    const start = Math.floor(i * bucketSize)\n    const end = Math.min(Math.floor((i + 1) * bucketSize), len)\n\n    let minVal = Infinity\n    let maxVal = -Infinity\n    let minIdx = start\n    let maxIdx = start\n\n    for (let j = start; j < end; j++) {\n      const v = values[j]!\n      if (v < minVal) { minVal = v; minIdx = j }\n      if (v > maxVal) { maxVal = v; maxIdx = j }\n    }\n\n    // Add in index order so line doesn't cross itself\n    if (minIdx < maxIdx) {\n      sampled.push({ index: minIdx, value: minVal })\n      sampled.push({ index: maxIdx, value: maxVal })\n    } else {\n      sampled.push({ index: maxIdx, value: maxVal })\n      sampled.push({ index: minIdx, value: minVal })\n    }\n  }\n\n  // Always keep last\n  sampled.push({ index: len - 1, value: values[len - 1]! })\n\n  return sampled\n}\n\n// ---------------------------------------------------------------------------\n// Helper: get decimated indices (for label mapping)\n// ---------------------------------------------------------------------------\n\nfunction getDecimatedIndices(values: number[], threshold: number, algo: string): number[] {\n  if (algo === 'lttb') {\n    return lttb(values, threshold).map(p => p.index)\n  }\n  return minMax(values, threshold).map(p => p.index)\n}\n","/**\n * Embedded CSS for chart animations, hover effects, and visual polish.\n * Injected into SVG <defs> as a <style> element.\n */\n\nexport const CHART_CSS = /* css */ `\n/* ---- Base ---- */\n.chartts {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n/* ---- Lines ---- */\n.chartts-line {\n  stroke-linecap: round;\n  stroke-linejoin: round;\n  transition: stroke-width 0.2s ease, opacity 0.2s ease;\n}\n.chartts-series:hover .chartts-line {\n  stroke-width: 2.5;\n}\n\n/* Line draw animation */\n@keyframes chartts-draw {\n  from { stroke-dashoffset: var(--chartts-path-len); }\n  to { stroke-dashoffset: 0; }\n}\n.chartts-line[style*=\"--chartts-path-len\"] {\n  animation: chartts-draw 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n/* ---- Area fills ---- */\n@keyframes chartts-fade-up {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-area {\n  animation: chartts-fade-up 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n  transition: opacity 0.2s ease;\n}\n\n/* ---- Line glow ---- */\n.chartts-line-glow {\n  stroke-linecap: round;\n  stroke-linejoin: round;\n  pointer-events: none;\n}\n\n/* ---- Point glow ---- */\n.chartts-point-glow, .chartts-dot-glow {\n  pointer-events: none;\n}\n\n/* ---- Data points ---- */\n@keyframes chartts-point-pop {\n  0% { opacity: 0; transform: scale(0); }\n  60% { transform: scale(1.3); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-point {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-point-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 10ms + 0.4s);\n  opacity: 0;\n  transition: opacity 0.15s ease, stroke-width 0.15s ease;\n  cursor: pointer;\n}\n.chartts-point:hover {\n  stroke-width: 3;\n  filter: brightness(1.15);\n}\n\n/* ---- Bars ---- */\n@keyframes chartts-bar-in {\n  from { opacity: 0; transform: scaleY(0.3); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-bar {\n  transform-origin: bottom center;\n  transform-box: fill-box;\n  animation: chartts-bar-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-bar:hover {\n  filter: brightness(1.12) saturate(1.1);\n}\n.chartts-bar-horizontal {\n  transform-origin: left center;\n  animation-name: chartts-hbar-in;\n}\n@keyframes chartts-hbar-in {\n  from { opacity: 0; transform: scaleX(0.3); }\n  to { opacity: 1; transform: scaleX(1); }\n}\n\n/* ---- Pie / Donut slices ---- */\n@keyframes chartts-slice-in {\n  from { opacity: 0; transform: scale(0.85); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-slice {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-slice-in 0.5s cubic-bezier(0.34, 1.3, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 25ms);\n  opacity: 0;\n  transition: filter 0.2s ease, opacity 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.3, 0.64, 1);\n  cursor: pointer;\n  pointer-events: all;\n}\n.chartts-slice:hover {\n  filter: brightness(1.08) saturate(1.15) drop-shadow(0 2px 8px rgba(0,0,0,0.2));\n  transform: scale(1.04);\n}\n\n/* ---- Sparkline ---- */\n.chartts-sparkline-line {\n  stroke-linecap: round;\n  stroke-linejoin: round;\n}\n.chartts-sparkline-line[style*=\"--chartts-path-len\"] {\n  animation: chartts-draw 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n/* ---- Radar ---- */\n@keyframes chartts-radar-in {\n  from { opacity: 0; transform: scale(0.3); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-radar-area {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-radar-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-radar-i, 0) * 35ms);\n  opacity: 0;\n  transition: opacity 0.2s ease, fill-opacity 0.2s ease;\n}\n.chartts-radar-area:hover {\n  fill-opacity: 0.35;\n}\n.chartts-radar-point {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-point-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 10ms + 0.5s);\n  opacity: 0;\n  transition: r 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-radar-point:hover {\n  filter: brightness(1.15);\n}\n\n/* ---- Gauge ---- */\n@keyframes chartts-gauge-draw {\n  from { stroke-dashoffset: var(--chartts-path-len); }\n  to { stroke-dashoffset: 0; }\n}\n@keyframes chartts-gauge-fade {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-gauge-fill[style*=\"--chartts-path-len\"] {\n  animation: chartts-gauge-draw 1s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n}\n.chartts-gauge-needle {\n  animation: chartts-gauge-fade 0.4s ease 0.6s forwards;\n  opacity: 0;\n}\n.chartts-gauge-needle-cap {\n  animation: chartts-gauge-fade 0.3s ease 0.65s forwards;\n  opacity: 0;\n}\n.chartts-gauge-tick {\n  opacity: 0.5;\n}\n\n/* ---- Funnel ---- */\n@keyframes chartts-funnel-slide {\n  from { opacity: 0; transform: translateY(-8px); }\n  to { opacity: 1; transform: translateY(0); }\n}\n.chartts-funnel-step {\n  animation: chartts-funnel-slide 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 25ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-funnel-step:hover {\n  filter: brightness(1.1);\n}\n\n/* ---- Waterfall ---- */\n@keyframes chartts-waterfall-in {\n  from { opacity: 0; transform: translateY(6px); }\n  to { opacity: 1; transform: translateY(0); }\n}\n.chartts-waterfall-bar {\n  animation: chartts-waterfall-in 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-waterfall-bar:hover {\n  filter: brightness(1.12);\n}\n\n/* ---- Candlestick ---- */\n@keyframes chartts-candle-in {\n  from { opacity: 0; transform: scaleY(0.5); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-candle {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-candle-in 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-candle:hover {\n  filter: brightness(1.15);\n}\n.chartts-wick {\n  transition: opacity 0.15s ease;\n}\n\n/* ---- Bubble ---- */\n@keyframes chartts-bubble-pop {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.08); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-bubble {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-bubble-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-bubble:hover {\n  filter: brightness(1.1) saturate(1.1);\n}\n\n/* ---- Scatter dots ---- */\n.chartts-dot {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-point-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 10ms);\n  opacity: 0;\n  transition: filter 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-dot:hover {\n  filter: brightness(1.15);\n  opacity: 1;\n}\n\n/* ---- Heatmap ---- */\n@keyframes chartts-cell-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-heatmap-cell {\n  animation: chartts-cell-in 0.3s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-heatmap-cell:hover {\n  filter: brightness(1.2) saturate(1.2);\n  stroke: currentColor;\n  stroke-width: 1.5;\n}\n\n/* ---- Boxplot ---- */\n@keyframes chartts-boxplot-in {\n  from { opacity: 0; transform: scaleY(0.4); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-boxplot-box {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-boxplot-in 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 3ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-boxplot-box:hover {\n  filter: brightness(1.15);\n}\n.chartts-boxplot-whisker, .chartts-boxplot-cap, .chartts-boxplot-median {\n  pointer-events: none;\n}\n\n/* ---- Treemap ---- */\n@keyframes chartts-cell-grow {\n  from { opacity: 0; transform: scale(0.85); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-treemap-cell {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-cell-grow 0.4s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 12ms);\n  cursor: pointer;\n  transition: filter 0.15s ease;\n}\n.chartts-treemap-cell:hover {\n  filter: brightness(1.15);\n}\n.chartts-treemap-label, .chartts-treemap-value {\n  pointer-events: none;\n}\n\n/* ---- Polar ---- */\n@keyframes chartts-wedge-in {\n  from { opacity: 0; transform: scale(0); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-polar-wedge {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-wedge-in 0.5s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  cursor: pointer;\n  transition: filter 0.15s ease;\n}\n.chartts-polar-wedge:hover {\n  filter: brightness(1.15);\n}\n.chartts-polar-label {\n  pointer-events: none;\n}\n.chartts-polar-grid {\n  pointer-events: none;\n}\n\n/* ---- Radial Bar ---- */\n@keyframes chartts-radialbar-in {\n  from { opacity: 0; stroke-dashoffset: var(--chartts-path-len, 200); }\n  to { opacity: 1; stroke-dashoffset: 0; }\n}\n.chartts-radialbar-arc {\n  animation: chartts-radialbar-in 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 30ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-radialbar-arc:hover {\n  filter: brightness(1.15);\n}\n.chartts-radialbar-track {\n  pointer-events: none;\n}\n\n/* ---- Lollipop ---- */\n@keyframes chartts-lollipop-in {\n  from { opacity: 0; transform: scaleY(0.3); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-lollipop-stem {\n  transform-origin: bottom center;\n  transform-box: fill-box;\n  animation: chartts-lollipop-in 0.4s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 12ms);\n}\n.chartts-lollipop-dot {\n  cursor: pointer;\n  transition: r 0.15s ease, filter 0.15s ease;\n}\n.chartts-lollipop-dot:hover {\n  filter: brightness(1.15);\n}\n\n/* ---- Bullet ---- */\n@keyframes chartts-bullet-in {\n  from { transform: scaleX(0); }\n  to { transform: scaleX(1); }\n}\n.chartts-bullet-bar {\n  transform-origin: left center;\n  transform-box: fill-box;\n  animation: chartts-bullet-in 0.5s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 25ms);\n  cursor: pointer;\n  transition: filter 0.15s ease;\n}\n.chartts-bullet-bar:hover {\n  filter: brightness(1.15);\n}\n.chartts-bullet-range, .chartts-bullet-target, .chartts-bullet-label {\n  pointer-events: none;\n}\n\n/* ---- Dumbbell ---- */\n@keyframes chartts-dumbbell-in {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.15); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-dumbbell-dot {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-dumbbell-in 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 3ms);\n  opacity: 0;\n  cursor: pointer;\n  transition: filter 0.15s ease;\n}\n.chartts-dumbbell-dot:hover {\n  filter: brightness(1.15);\n}\n.chartts-dumbbell-connector, .chartts-dumbbell-label {\n  pointer-events: none;\n}\n\n/* ---- Calendar ---- */\n.chartts-calendar-cell {\n  cursor: pointer;\n  transition: filter 0.15s ease;\n  animation: chartts-cell-in 0.3s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 3ms);\n}\n.chartts-calendar-cell:hover {\n  filter: brightness(1.2);\n}\n.chartts-calendar-daylabel {\n  pointer-events: none;\n}\n\n/* ---- Sankey ---- */\n@keyframes chartts-sankey-link-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-sankey-link {\n  animation: chartts-sankey-link-in 0.5s ease forwards;\n  opacity: 0;\n  transition: fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-sankey-link:hover {\n  fill-opacity: 0.5 !important;\n}\n.chartts-sankey-node {\n  cursor: pointer;\n  transition: filter 0.15s ease;\n}\n.chartts-sankey-node:hover {\n  filter: brightness(1.15);\n}\n.chartts-sankey-label {\n  pointer-events: none;\n}\n\n/* ---- Combo ---- */\n.chartts-combo-line {\n  pointer-events: none;\n}\n.chartts-combo-point {\n  cursor: pointer;\n  transition: r 0.15s ease;\n}\n\n/* ---- Sunburst ---- */\n@keyframes chartts-sunburst-in {\n  from { opacity: 0; transform: scale(0.85); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-sunburst-sector {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-sunburst-in 0.5s cubic-bezier(0.34, 1.3, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 10ms);\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-sunburst-sector:hover {\n  filter: brightness(1.15);\n  fill-opacity: 0.95 !important;\n}\n.chartts-sunburst-label {\n  pointer-events: none;\n}\n\n/* ---- Tree ---- */\n@keyframes chartts-tree-node-in {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.2); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-tree-node {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-tree-node-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 15ms);\n  opacity: 0;\n  transition: filter 0.15s ease, r 0.15s ease;\n  cursor: pointer;\n}\n.chartts-tree-node:hover {\n  filter: brightness(1.15);\n}\n.chartts-tree-edge {\n  opacity: 0.6;\n  pointer-events: none;\n}\n.chartts-tree-label {\n  pointer-events: none;\n}\n\n/* ---- Graph ---- */\n@keyframes chartts-graph-node-in {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.15); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-graph-node {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-graph-node-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 12ms);\n  opacity: 0;\n  transition: filter 0.15s ease, r 0.15s ease;\n  cursor: pointer;\n}\n.chartts-graph-node:hover {\n  filter: brightness(1.15) saturate(1.2);\n}\n.chartts-graph-edge {\n  pointer-events: none;\n  animation: chartts-sankey-link-in 0.5s ease forwards;\n  opacity: 0;\n}\n.chartts-graph-label {\n  pointer-events: none;\n}\n\n/* ---- Parallel ---- */\n@keyframes chartts-parallel-in {\n  from { opacity: 0; stroke-dashoffset: var(--chartts-path-len, 1000); }\n  to { opacity: 1; stroke-dashoffset: 0; }\n}\n.chartts-parallel-line {\n  transition: opacity 0.2s ease, stroke-width 0.2s ease;\n  cursor: pointer;\n}\n.chartts-parallel-line:hover {\n  opacity: 1 !important;\n  stroke-width: 3;\n}\n.chartts-parallel-axis {\n  pointer-events: none;\n}\n.chartts-parallel-label, .chartts-parallel-tick {\n  pointer-events: none;\n}\n\n/* ---- ThemeRiver ---- */\n@keyframes chartts-stream-in {\n  from { opacity: 0; transform: scaleY(0.3); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-themeriver-stream {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-stream-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 25ms);\n  opacity: 0;\n  transition: fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-themeriver-stream:hover {\n  fill-opacity: 0.9 !important;\n}\n.chartts-themeriver-label {\n  pointer-events: none;\n}\n\n/* ---- PictorialBar ---- */\n@keyframes chartts-pictorial-in {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.1); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-pictorialbar-symbol {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-pictorial-in 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 3ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-pictorialbar-symbol:hover {\n  filter: brightness(1.15);\n}\n.chartts-pictorialbar-value, .chartts-pictorialbar-label {\n  pointer-events: none;\n}\n\n/* ---- Chord ---- */\n@keyframes chartts-chord-arc-in {\n  from { opacity: 0; transform: scale(0.9); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-chord-arc {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-chord-arc-in 0.5s ease forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 3ms);\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-chord-arc:hover {\n  filter: brightness(1.15);\n}\n@keyframes chartts-chord-ribbon-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-chord-ribbon {\n  animation: chartts-chord-ribbon-in 0.6s ease 0.3s forwards;\n  opacity: 0;\n  transition: fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-chord-ribbon:hover {\n  fill-opacity: 0.55 !important;\n}\n.chartts-chord-label {\n  pointer-events: none;\n}\n\n/* ---- States (empty / loading / error) ---- */\n.chartts-state {\n  opacity: 1;\n}\n@keyframes chartts-shimmer {\n  0% { opacity: 0.3; }\n  50% { opacity: 0.7; }\n  100% { opacity: 0.3; }\n}\n.chartts-skeleton-bar {\n  animation: chartts-shimmer 1.5s ease-in-out infinite;\n  animation-delay: calc(var(--chartts-i, 0) * 40ms);\n}\n\n/* ---- Grid ---- */\n.chartts-grid-h, .chartts-grid-v {\n  opacity: 0.6;\n}\n\n/* ---- GEO/Map ---- */\n@keyframes chartts-geo-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-geo-region {\n  animation: chartts-geo-in 0.4s ease calc(var(--chartts-i, 0) * 3ms) forwards;\n  opacity: 0;\n  transition: fill-opacity 0.15s ease, filter 0.15s ease, stroke-width 0.15s ease, stroke 0.15s ease;\n  cursor: pointer;\n}\n.chartts-geo-region:hover {\n  filter: brightness(1.15) drop-shadow(0 0 2px rgba(0,0,0,0.3));\n  fill-opacity: 0.95 !important;\n  stroke: #fff !important;\n  stroke-width: 1.5px !important;\n}\n.chartts-geo-label {\n  pointer-events: none;\n  text-shadow: 0 0 3px rgba(0,0,0,0.5), 0 0 6px rgba(0,0,0,0.3);\n}\n.chartts-geo-scatter {\n  transition: r 0.15s ease, opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-geo-scatter:hover {\n  opacity: 0.9;\n  filter: drop-shadow(0 0 4px currentColor);\n}\n.chartts-geo-legend text {\n  user-select: none;\n}\n\n/* ---- Lines (flow) ---- */\n@keyframes chartts-lines-flow-in {\n  from { stroke-dashoffset: 300; opacity: 0; }\n  to { stroke-dashoffset: 0; opacity: 1; }\n}\n.chartts-lines-flow {\n  stroke-dasharray: 300;\n  animation: chartts-lines-flow-in 0.8s ease calc(var(--chartts-i, 0) * 8ms) forwards;\n  opacity: 0;\n  transition: stroke-width 0.2s ease, stroke-opacity 0.2s ease;\n  cursor: pointer;\n}\n.chartts-lines-flow:hover {\n  stroke-opacity: 0.9;\n  stroke-width: 4;\n}\n.chartts-lines-node {\n  transition: r 0.15s ease;\n  cursor: pointer;\n}\n\n/* ---- Matrix ---- */\n@keyframes chartts-matrix-in {\n  from { opacity: 0; transform: scale(0.8); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-matrix-cell {\n  animation: chartts-matrix-in 0.3s ease calc(var(--chartts-i, 0) * 5ms) forwards;\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-matrix-cell:hover {\n  filter: brightness(1.15);\n}\n\n/* ---- OHLC ---- */\n@keyframes chartts-ohlc-in {\n  from { opacity: 0; transform: scaleY(0.5); }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-ohlc-stem, .chartts-ohlc-tick {\n  animation: chartts-ohlc-in 0.3s ease calc(var(--chartts-i, 0) * 8ms) forwards;\n  opacity: 0;\n  transition: stroke-width 0.15s ease;\n}\n.chartts-ohlc-stem:hover, .chartts-ohlc-tick:hover {\n  stroke-width: 2.5;\n}\n\n/* ---- Volume ---- */\n@keyframes chartts-volume-in {\n  from { opacity: 0; transform: scaleY(0); transform-origin: bottom; }\n  to { opacity: 1; transform: scaleY(1); }\n}\n.chartts-volume-bar {\n  animation: chartts-volume-in 0.3s ease calc(var(--chartts-i, 0) * 8ms) forwards;\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-volume-bar:hover {\n  filter: brightness(1.1);\n  fill-opacity: 1 !important;\n}\n\n/* ---- Range / Band ---- */\n@keyframes chartts-range-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-range-band {\n  animation: chartts-range-in 0.5s ease forwards;\n  opacity: 0;\n}\n.chartts-range-center {\n  animation: chartts-range-in 0.6s ease 0.1s forwards;\n  opacity: 0;\n}\n.chartts-range-bound {\n  animation: chartts-range-in 0.5s ease 0.05s forwards;\n  opacity: 0;\n}\n\n/* ---- Baseline ---- */\n@keyframes chartts-baseline-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n.chartts-baseline-pos, .chartts-baseline-neg {\n  animation: chartts-baseline-in 0.5s ease forwards;\n  opacity: 0;\n}\n.chartts-baseline-line {\n  animation: chartts-baseline-in 0.6s ease 0.1s forwards;\n  opacity: 0;\n}\n.chartts-baseline-ref {\n  animation: chartts-baseline-in 0.3s ease forwards;\n  opacity: 0;\n}\n\n/* ---- Kagi ---- */\n@keyframes chartts-kagi-in {\n  from { stroke-dashoffset: 200; opacity: 0; }\n  to { stroke-dashoffset: 0; opacity: 1; }\n}\n.chartts-kagi-line {\n  stroke-dasharray: 200;\n  animation: chartts-kagi-in 0.6s ease calc(var(--chartts-i, 0) * 12ms) forwards;\n  opacity: 0;\n  transition: stroke-width 0.15s ease;\n}\n\n/* ---- Renko ---- */\n@keyframes chartts-renko-in {\n  from { opacity: 0; transform: scale(0.8); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-renko-brick {\n  animation: chartts-renko-in 0.3s ease calc(var(--chartts-i, 0) * 8ms) forwards;\n  opacity: 0;\n  transition: filter 0.15s ease;\n  cursor: pointer;\n}\n.chartts-renko-brick:hover {\n  filter: brightness(1.15);\n}\n\n/* ---- Violin ---- */\n@keyframes chartts-violin-in {\n  from { opacity: 0; transform: scaleX(0); }\n  to { opacity: 1; transform: scaleX(1); }\n}\n.chartts-violin-shape {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-violin-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 30ms);\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-violin-shape:hover {\n  filter: brightness(1.15);\n  fill-opacity: 0.45 !important;\n}\n.chartts-violin-box, .chartts-violin-median {\n  pointer-events: none;\n}\n\n/* ---- Pack (Circle Packing) ---- */\n@keyframes chartts-pack-in {\n  0% { opacity: 0; transform: scale(0); }\n  70% { transform: scale(1.08); }\n  100% { opacity: 1; transform: scale(1); }\n}\n.chartts-pack-circle {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-pack-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 20ms);\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-pack-circle:hover {\n  filter: brightness(1.15) saturate(1.1);\n}\n.chartts-pack-label {\n  pointer-events: none;\n}\n\n/* ---- Voronoi ---- */\n@keyframes chartts-voronoi-in {\n  from { opacity: 0; transform: scale(0.85); }\n  to { opacity: 1; transform: scale(1); }\n}\n.chartts-voronoi-cell {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-voronoi-in 0.4s ease calc(var(--chartts-i, 0) * 20ms) forwards;\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-voronoi-cell:hover {\n  filter: brightness(1.2) saturate(1.2);\n  fill-opacity: 0.9 !important;\n}\n.chartts-voronoi-seed, .chartts-voronoi-label {\n  pointer-events: none;\n}\n\n/* ---- Word Cloud ---- */\n@keyframes chartts-wordcloud-in {\n  0% { opacity: 0; transform: scale(0.3) rotate(-8deg); }\n  70% { transform: scale(1.05) rotate(1deg); }\n  100% { opacity: 1; transform: scale(1) rotate(0deg); }\n}\n.chartts-wordcloud-word {\n  transform-origin: center;\n  transform-box: fill-box;\n  animation: chartts-wordcloud-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;\n  animation-delay: calc(var(--chartts-i, 0) * 40ms);\n  opacity: 0;\n  transition: filter 0.15s ease, fill-opacity 0.15s ease;\n  cursor: pointer;\n}\n.chartts-wordcloud-word:hover {\n  filter: brightness(1.2) saturate(1.3);\n  fill-opacity: 1 !important;\n}\n\n/* ---- DataZoom ---- */\n.chartts-datazoom-handle {\n  cursor: ew-resize;\n  transition: fill 0.15s ease;\n}\n.chartts-datazoom-handle:hover {\n  fill: #374151;\n}\n.chartts-datazoom-selected {\n  cursor: grab;\n}\n\n/* ---- Text ---- */\n.chartts-x-label, .chartts-y-label,\n.chartts-x-axis-label, .chartts-y-axis-label,\n.chartts-legend text, .chartts-slice-label {\n  user-select: none;\n  pointer-events: none;\n}\n\n/* ---- Legend ---- */\n.chartts-legend-item {\n  cursor: pointer;\n  transition: opacity 0.15s ease;\n}\n.chartts-legend-item:hover {\n  opacity: 0.7;\n}\n\n/* ---- Skip animations on data update ---- */\n.chartts-skip-anim .chartts-line, .chartts-skip-anim .chartts-area, .chartts-skip-anim .chartts-point,\n.chartts-skip-anim .chartts-bar, .chartts-skip-anim .chartts-slice, .chartts-skip-anim .chartts-bubble,\n.chartts-skip-anim .chartts-funnel-step, .chartts-skip-anim .chartts-waterfall-bar,\n.chartts-skip-anim .chartts-sparkline-line, .chartts-skip-anim .chartts-gauge-fill,\n.chartts-skip-anim .chartts-gauge-needle, .chartts-skip-anim .chartts-gauge-needle-cap,\n.chartts-skip-anim .chartts-radar-area, .chartts-skip-anim .chartts-radar-point,\n.chartts-skip-anim .chartts-treemap-cell, .chartts-skip-anim .chartts-polar-wedge,\n.chartts-skip-anim .chartts-lollipop-stem, .chartts-skip-anim .chartts-bullet-bar,\n.chartts-skip-anim .chartts-dumbbell-dot, .chartts-skip-anim .chartts-boxplot-box,\n.chartts-skip-anim .chartts-radialbar-arc, .chartts-skip-anim .chartts-sankey-link,\n.chartts-skip-anim .chartts-calendar-cell,\n.chartts-skip-anim .chartts-sunburst-sector, .chartts-skip-anim .chartts-tree-node,\n.chartts-skip-anim .chartts-graph-node, .chartts-skip-anim .chartts-graph-edge,\n.chartts-skip-anim .chartts-themeriver-stream, .chartts-skip-anim .chartts-pictorialbar-symbol,\n.chartts-skip-anim .chartts-chord-arc, .chartts-skip-anim .chartts-chord-ribbon,\n.chartts-skip-anim .chartts-geo-region, .chartts-skip-anim .chartts-lines-flow,\n.chartts-skip-anim .chartts-lines-node, .chartts-skip-anim .chartts-matrix-cell,\n.chartts-skip-anim .chartts-ohlc-stem, .chartts-skip-anim .chartts-ohlc-tick,\n.chartts-skip-anim .chartts-volume-bar, .chartts-skip-anim .chartts-range-band,\n.chartts-skip-anim .chartts-baseline-pos, .chartts-skip-anim .chartts-baseline-neg,\n.chartts-skip-anim .chartts-baseline-line, .chartts-skip-anim .chartts-kagi-line,\n.chartts-skip-anim .chartts-renko-brick,\n.chartts-skip-anim .chartts-violin-shape, .chartts-skip-anim .chartts-pack-circle,\n.chartts-skip-anim .chartts-voronoi-cell, .chartts-skip-anim .chartts-wordcloud-word {\n  animation: none !important;\n  opacity: 1 !important;\n}\n.chartts-skip-anim .chartts-line,\n.chartts-skip-anim .chartts-sparkline-line,\n.chartts-skip-anim .chartts-gauge-fill {\n  stroke-dashoffset: 0 !important;\n}\n\n/* ---- Reduced motion ---- */\n@media (prefers-reduced-motion: reduce) {\n  .chartts-line, .chartts-area, .chartts-point,\n  .chartts-bar, .chartts-slice, .chartts-bubble,\n  .chartts-funnel-step, .chartts-waterfall-bar,\n  .chartts-sparkline-line, .chartts-gauge-fill,\n  .chartts-gauge-needle, .chartts-gauge-needle-cap,\n  .chartts-radar-area, .chartts-radar-point,\n  .chartts-treemap-cell, .chartts-polar-wedge,\n  .chartts-lollipop-stem, .chartts-bullet-bar,\n  .chartts-dumbbell-dot, .chartts-boxplot-box,\n  .chartts-radialbar-arc, .chartts-sankey-link,\n  .chartts-calendar-cell,\n  .chartts-sunburst-sector, .chartts-tree-node,\n  .chartts-graph-node, .chartts-graph-edge,\n  .chartts-themeriver-stream, .chartts-pictorialbar-symbol,\n  .chartts-chord-arc, .chartts-chord-ribbon,\n  .chartts-geo-region, .chartts-lines-flow,\n  .chartts-lines-node, .chartts-matrix-cell,\n  .chartts-ohlc-stem, .chartts-ohlc-tick,\n  .chartts-volume-bar, .chartts-range-band,\n  .chartts-baseline-pos, .chartts-baseline-neg,\n  .chartts-baseline-line, .chartts-kagi-line,\n  .chartts-renko-brick,\n  .chartts-violin-shape, .chartts-pack-circle,\n  .chartts-voronoi-cell, .chartts-wordcloud-word {\n    animation: none !important;\n    opacity: 1 !important;\n  }\n  .chartts-line,\n  .chartts-sparkline-line,\n  .chartts-gauge-fill {\n    stroke-dashoffset: 0 !important;\n  }\n}\n`\n","import type { Renderer, RenderNode, RenderAttrs } from '../types'\nimport { CHART_CSS } from '../styles/chart'\n\nconst NS = 'http://www.w3.org/2000/svg'\n\n/**\n * SVG DOM Renderer.\n *\n * Converts render tree nodes into real SVG elements.\n * All color attributes reference CSS custom properties (var(--chartts-*))\n * so they're overridable via CSS, Tailwind, or theme config.\n */\nexport function createSVGRenderer(): Renderer {\n  return {\n    createRoot(target, width, height, attrs) {\n      const svg = document.createElementNS(NS, 'svg')\n      svg.setAttribute('xmlns', NS)\n      svg.setAttribute('width', '100%')\n      svg.setAttribute('height', '100%')\n      svg.setAttribute('viewBox', `0 0 ${width} ${height}`)\n      svg.setAttribute('preserveAspectRatio', 'xMidYMid meet')\n      svg.classList.add('chartts')\n      if (attrs) applyAttrs(svg, attrs)\n\n      // Inject chart CSS once\n      const styleEl = document.createElementNS(NS, 'style')\n      styleEl.textContent = CHART_CSS\n      svg.appendChild(styleEl)\n\n      target.appendChild(svg)\n      return { element: svg }\n    },\n\n    render(root, nodes) {\n      // Keep the <style> element, clear everything else\n      const styleEl = root.element.querySelector('style')\n      clear(root.element)\n      if (styleEl) root.element.appendChild(styleEl)\n      appendNodes(root.element, nodes)\n      applyEntryAnimations(root.element)\n    },\n\n    update(root, nodes) {\n      const styleEl = root.element.querySelector('style')\n      clear(root.element)\n      if (styleEl) root.element.appendChild(styleEl)\n      appendNodes(root.element, nodes)\n      applyEntryAnimations(root.element)\n    },\n\n    clear(root) {\n      clear(root.element)\n    },\n\n    destroy(root) {\n      root.element.remove()\n    },\n  }\n}\n\nfunction clear(el: Element): void {\n  while (el.firstChild) el.removeChild(el.firstChild)\n}\n\nfunction appendNodes(parent: Element, nodes: RenderNode[]): void {\n  for (const node of nodes) {\n    const el = createNode(node)\n    if (el) parent.appendChild(el)\n  }\n}\n\nfunction createNode(node: RenderNode): SVGElement | null {\n  switch (node.type) {\n    case 'group': {\n      const g = el('g')\n      if (node.attrs) applyAttrs(g, node.attrs)\n      for (const child of node.children) {\n        const c = createNode(child)\n        if (c) g.appendChild(c)\n      }\n      return g\n    }\n\n    case 'path': {\n      const p = el('path')\n      p.setAttribute('d', node.d)\n      if (!node.attrs?.fill) p.setAttribute('fill', 'none')\n      if (node.attrs) applyAttrs(p, node.attrs)\n      return p\n    }\n\n    case 'rect': {\n      const r = el('rect')\n      setNum(r, 'x', node.x)\n      setNum(r, 'y', node.y)\n      setNum(r, 'width', node.width)\n      setNum(r, 'height', node.height)\n      if (node.rx != null) setNum(r, 'rx', node.rx)\n      if (node.ry != null) setNum(r, 'ry', node.ry)\n      if (node.attrs) applyAttrs(r, node.attrs)\n      return r\n    }\n\n    case 'circle': {\n      const c = el('circle')\n      setNum(c, 'cx', node.cx)\n      setNum(c, 'cy', node.cy)\n      setNum(c, 'r', node.r)\n      if (node.attrs) applyAttrs(c, node.attrs)\n      return c\n    }\n\n    case 'line': {\n      const l = el('line')\n      setNum(l, 'x1', node.x1)\n      setNum(l, 'y1', node.y1)\n      setNum(l, 'x2', node.x2)\n      setNum(l, 'y2', node.y2)\n      if (node.attrs) applyAttrs(l, node.attrs)\n      return l\n    }\n\n    case 'text': {\n      const t = el('text')\n      setNum(t, 'x', node.x)\n      setNum(t, 'y', node.y)\n      t.textContent = node.content\n      if (node.attrs) {\n        const a = node.attrs\n        if ('textAnchor' in a && a.textAnchor) t.setAttribute('text-anchor', a.textAnchor)\n        if ('dominantBaseline' in a && a.dominantBaseline) t.setAttribute('dominant-baseline', a.dominantBaseline)\n        if ('fontSize' in a && a.fontSize) t.setAttribute('font-size', String(a.fontSize))\n        if ('fontFamily' in a && a.fontFamily) t.setAttribute('font-family', a.fontFamily as string)\n        if ('fontWeight' in a && a.fontWeight) t.setAttribute('font-weight', String(a.fontWeight))\n        applyAttrs(t, a)\n      }\n      return t\n    }\n\n    case 'clipPath': {\n      const cp = el('clipPath')\n      cp.setAttribute('id', node.id)\n      for (const child of node.children) {\n        const c = createNode(child)\n        if (c) cp.appendChild(c)\n      }\n      return cp\n    }\n\n    case 'defs': {\n      const d = el('defs')\n      for (const child of node.children) {\n        const c = createNode(child)\n        if (c) d.appendChild(c)\n      }\n      return d\n    }\n\n    default:\n      return null\n  }\n}\n\nfunction el(tag: string): SVGElement {\n  return document.createElementNS(NS, tag)\n}\n\nfunction setNum(el: SVGElement, attr: string, val: number): void {\n  el.setAttribute(attr, String(val))\n}\n\n/** Static attribute name mapping — RenderAttrs keys to SVG attribute names */\nconst ATTR_MAP: Record<string, string> = {\n  class: 'class',\n  style: 'style',\n  stroke: 'stroke',\n  strokeWidth: 'stroke-width',\n  strokeDasharray: 'stroke-dasharray',\n  strokeOpacity: 'stroke-opacity',\n  strokeLinecap: 'stroke-linecap',\n  strokeLinejoin: 'stroke-linejoin',\n  fill: 'fill',\n  fillOpacity: 'fill-opacity',\n  opacity: 'opacity',\n  transform: 'transform',\n  filter: 'filter',\n  cursor: 'cursor',\n  pointerEvents: 'pointer-events',\n  role: 'role',\n  ariaLabel: 'aria-label',\n  tabindex: 'tabindex',\n}\n\n/** Map RenderAttrs to SVG DOM attributes */\nfunction applyAttrs(el: SVGElement, attrs: RenderAttrs): void {\n  for (const [key, value] of Object.entries(attrs)) {\n    if (value == null) continue\n    // Skip non-SVG attrs handled elsewhere\n    if (['textAnchor', 'dominantBaseline', 'fontSize', 'fontFamily', 'fontWeight', 'rx', 'ry'].includes(key)) continue\n\n    if (key === 'clipPath') {\n      el.setAttribute('clip-path', `url(#${value as string})`)\n    } else if (key.startsWith('data-')) {\n      el.setAttribute(key, String(value))\n    } else if (ATTR_MAP[key]) {\n      el.setAttribute(ATTR_MAP[key]!, String(value))\n    }\n  }\n}\n\n/**\n * Apply entry animations after rendering:\n * - Line draw animation using getTotalLength()\n * - Staggered index CSS variable for bars/points/slices\n */\nfunction applyEntryAnimations(svg: Element): void {\n  // Skip entry animation setup entirely if animations are disabled (subsequent renders)\n  const skipAnim = svg.classList.contains('chartts-skip-anim')\n\n  // Line draw animation — skip dashed/dotted lines (they already have a dasharray pattern)\n  if (!skipAnim) {\n    svg.querySelectorAll<SVGPathElement>('.chartts-line, .chartts-sparkline-line').forEach((p) => {\n      try {\n        const existing = p.getAttribute('stroke-dasharray')\n        if (existing && existing.includes(',')) return // preserve dashed/dotted pattern\n        const len = p.getTotalLength()\n        p.style.setProperty('--chartts-path-len', String(len))\n        p.setAttribute('stroke-dasharray', String(len))\n        p.setAttribute('stroke-dashoffset', String(len))\n      } catch { /* ignore for non-path elements */ }\n    })\n  }\n\n  // Stagger animations for all chart element types\n  const STAGGER_SELECTORS = [\n    '.chartts-point', '.chartts-bar', '.chartts-slice', '.chartts-bubble',\n    '.chartts-funnel-step', '.chartts-waterfall-bar', '.chartts-candle',\n    '.chartts-dot', '.chartts-radar-point',\n    '.chartts-heatmap-cell', '.chartts-treemap-cell', '.chartts-polar-wedge',\n    '.chartts-lollipop-stem', '.chartts-bullet-bar', '.chartts-calendar-cell',\n    '.chartts-radialbar-arc', '.chartts-dumbbell-dot', '.chartts-boxplot-box',\n    '.chartts-sankey-link',\n    '.chartts-sunburst-sector', '.chartts-tree-node',\n    '.chartts-graph-node', '.chartts-themeriver-stream',\n    '.chartts-pictorialbar-symbol', '.chartts-chord-arc',\n    '.chartts-chord-ribbon',\n    '.chartts-geo-region', '.chartts-lines-flow',\n    '.chartts-lines-node', '.chartts-matrix-cell',\n    '.chartts-ohlc-stem', '.chartts-volume-bar',\n    '.chartts-kagi-line', '.chartts-renko-brick',\n  ]\n  for (const selector of STAGGER_SELECTORS) {\n    svg.querySelectorAll(selector).forEach((el, i) => {\n      ;(el as SVGElement).style.setProperty('--chartts-i', String(i))\n    })\n  }\n\n  // Gauge fill draw animation (same technique as line draw)\n  if (!skipAnim) {\n    svg.querySelectorAll<SVGPathElement>('.chartts-gauge-fill').forEach((p) => {\n      try {\n        const len = p.getTotalLength()\n        p.style.setProperty('--chartts-path-len', String(len))\n        p.setAttribute('stroke-dasharray', String(len))\n        p.setAttribute('stroke-dashoffset', String(len))\n      } catch { /* ignore */ }\n    })\n  }\n\n  // Stagger for radar areas (per series) — uses a different CSS variable\n  svg.querySelectorAll('.chartts-radar-area').forEach((el, i) => {\n    ;(el as SVGElement).style.setProperty('--chartts-radar-i', String(i))\n  })\n}\n","import type { Renderer, RenderNode, RenderAttrs, ThemeConfig } from '../types'\n\n/**\n * Canvas 2D Renderer.\n *\n * Converts the same RenderNode tree used by the SVG renderer into\n * Canvas 2D drawing commands. Designed for 1k–100k data points\n * where SVG DOM overhead becomes a bottleneck.\n *\n * Color resolution: Chart colors use `var(--token, #hex)` strings.\n * Canvas can't interpret CSS variables, so we extract the hex fallback.\n */\n\n// ---------------------------------------------------------------------------\n// Color utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a color value for Canvas 2D.\n * Handles: hex, rgb(), var(--token, #fallback), var(--chartts-*) via theme lookup.\n * Canvas can't interpret CSS variables, so we extract hex fallbacks or look up\n * the --chartts-* token from the current theme's CSS variable map.\n */\nlet cssVarMap: Record<string, string> = {}\n\nfunction buildCssVarMap(theme: import('../types').ThemeConfig): void {\n  const p = '--chartts'\n  cssVarMap = {\n    [`${p}-bg`]: theme.background,\n    [`${p}-text`]: theme.textColor,\n    [`${p}-text-muted`]: theme.textMuted,\n    [`${p}-axis`]: theme.axisColor,\n    [`${p}-grid`]: theme.gridColor,\n    [`${p}-tooltip-bg`]: theme.tooltipBackground,\n    [`${p}-tooltip-text`]: theme.tooltipText,\n    [`${p}-tooltip-border`]: theme.tooltipBorder,\n  }\n  theme.colors.forEach((c, i) => {\n    cssVarMap[`${p}-color-${i + 1}`] = typeof c === 'string' ? c : String(c)\n  })\n}\n\nfunction resolveColor(value: string | undefined, fallback: string = '#000'): string {\n  if (!value) return fallback\n  if (value === 'none' || value === 'transparent') return 'transparent'\n  if (value.startsWith('url(')) return value\n\n  // var(--token, #fallback) — try theme lookup first, then extract fallback\n  const varMatch = value.match(/var\\(\\s*([^,)]+)(?:,\\s*([^)]+))?\\)/)\n  if (varMatch) {\n    const token = varMatch[1]!.trim()\n    // Look up --chartts-* in our theme map\n    const mapped = cssVarMap[token]\n    if (mapped) {\n      // The mapped value might itself be var(--color-gray-800, #hex) — recurse once\n      return resolveColor(mapped, varMatch[2]?.trim() ?? fallback)\n    }\n    // No theme mapping — use the inline fallback if present\n    return varMatch[2]?.trim() ?? fallback\n  }\n\n  return value\n}\n\n/** Parse hex to rgba string */\nfunction hexToRgba(hex: string, alpha: number): string {\n  const h = hex.replace('#', '')\n  const full = h.length === 3\n    ? h[0]! + h[0]! + h[1]! + h[1]! + h[2]! + h[2]!\n    : h\n  const r = parseInt(full.substring(0, 2), 16)\n  const g = parseInt(full.substring(2, 4), 16)\n  const b = parseInt(full.substring(4, 6), 16)\n  return `rgba(${r},${g},${b},${alpha})`\n}\n\n// ---------------------------------------------------------------------------\n// Gradient cache (per-render)\n// ---------------------------------------------------------------------------\n\n/** Well-known gradient patterns generated by effects.ts */\nfunction resolveGradientRef(\n  id: string,\n  colors: string[],\n  ctx: CanvasRenderingContext2D,\n  x: number, y: number, _w: number, h: number,\n): CanvasGradient | string | null {\n  // Area gradient: chartts-area-N\n  const areaMatch = id.match(/^chartts-area-(\\d+)$/)\n  if (areaMatch) {\n    const color = resolveColor(colors[parseInt(areaMatch[1]!)])\n    const grad = ctx.createLinearGradient(x, y, x, y + h)\n    grad.addColorStop(0, hexToRgba(color, 0.35))\n    grad.addColorStop(1, hexToRgba(color, 0.02))\n    return grad\n  }\n\n  // Bar gradient: chartts-bar-N\n  const barMatch = id.match(/^chartts-bar-(\\d+)$/)\n  if (barMatch) {\n    const color = resolveColor(colors[parseInt(barMatch[1]!)])\n    const grad = ctx.createLinearGradient(x, y, x, y + h)\n    grad.addColorStop(0, hexToRgba(color, 1))\n    grad.addColorStop(1, hexToRgba(color, 0.75))\n    return grad\n  }\n\n  // Pie gradient: chartts-pie-N\n  const pieMatch = id.match(/^chartts-pie-(\\d+)$/)\n  if (pieMatch) {\n    const color = resolveColor(colors[parseInt(pieMatch[1]!)])\n    return color\n  }\n\n  // Point glow: chartts-pglow-N\n  const glowMatch = id.match(/^chartts-pglow-(\\d+)$/)\n  if (glowMatch) {\n    const color = resolveColor(colors[parseInt(glowMatch[1]!)])\n    return hexToRgba(color, 0.4)\n  }\n\n  return null\n}\n\n/** Parse url(#id) and return the id */\nfunction parseUrlRef(value: string): string | null {\n  const match = value.match(/url\\(#([^)]+)\\)/)\n  return match ? match[1]! : null\n}\n\n// ---------------------------------------------------------------------------\n// Text alignment mapping\n// ---------------------------------------------------------------------------\n\nfunction mapTextAlign(anchor?: string): CanvasTextAlign {\n  switch (anchor) {\n    case 'middle': return 'center'\n    case 'end': return 'right'\n    default: return 'left'\n  }\n}\n\nfunction mapTextBaseline(baseline?: string): CanvasTextBaseline {\n  switch (baseline) {\n    case 'middle':\n    case 'central': return 'middle'\n    case 'hanging': return 'hanging'\n    default: return 'alphabetic'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Canvas Renderer\n// ---------------------------------------------------------------------------\n\nexport interface CanvasRendererRoot {\n  element: HTMLCanvasElement\n  ctx: CanvasRenderingContext2D\n  width: number\n  height: number\n  dpr: number\n}\n\nexport function createCanvasRenderer(getTheme: ThemeConfig | (() => ThemeConfig)): Renderer {\n  // Support both a static theme or a getter function for live theme switching\n  const resolveTheme = typeof getTheme === 'function' ? getTheme : () => getTheme\n\n  // Clip path registry (id → Path2D)\n  let clipPaths: Map<string, Path2D> = new Map()\n  // Current colors — refreshed each render from theme\n  let currentColors: string[] = []\n\n  return {\n    createRoot(target, width, height, attrs) {\n      const canvas = document.createElement('canvas')\n      const dpr = window.devicePixelRatio || 1\n      canvas.width = Math.round(width * dpr)\n      canvas.height = Math.round(height * dpr)\n      canvas.style.width = `${width}px`\n      canvas.style.height = `${height}px`\n      canvas.style.display = 'block'\n\n      if (attrs?.class) canvas.className = attrs.class\n      if (attrs?.role) canvas.setAttribute('role', attrs.role)\n      if (attrs?.ariaLabel) canvas.setAttribute('aria-label', attrs.ariaLabel)\n\n      const ctx2d = canvas.getContext('2d')!\n      ctx2d.setTransform(dpr, 0, 0, dpr, 0, 0)\n\n      target.appendChild(canvas)\n\n      const root = { element: canvas } as unknown as { element: HTMLCanvasElement }\n      ;(root as unknown as CanvasRendererRoot).ctx = ctx2d\n      ;(root as unknown as CanvasRendererRoot).width = width\n      ;(root as unknown as CanvasRendererRoot).height = height\n      ;(root as unknown as CanvasRendererRoot).dpr = dpr\n\n      return root as unknown as import('../types').RendererRoot\n    },\n\n    render(root, nodes) {\n      const cr = root as unknown as CanvasRendererRoot\n      const canvas = cr.element\n      const dpr = window.devicePixelRatio || 1\n      const theme = resolveTheme()\n      const colors = theme.colors as unknown as string[]\n\n      // Rebuild CSS variable lookup so resolveColor can resolve var(--chartts-*) tokens\n      buildCssVarMap(theme)\n\n      // Sync dimensions from actual canvas state\n      cr.width = canvas.width / dpr\n      cr.height = canvas.height / dpr\n      cr.dpr = dpr\n\n      clipPaths = new Map()\n      currentColors = colors\n\n      const ctx = cr.ctx\n\n      // High-quality rendering settings\n      ctx.imageSmoothingEnabled = true\n      ctx.imageSmoothingQuality = 'high'\n\n      // Paint background — 'transparent' means clear the canvas (let container bg show)\n      ctx.save()\n      const bg = resolveColor(theme.background, '#ffffff')\n      if (bg === 'transparent') {\n        ctx.clearRect(0, 0, cr.width, cr.height)\n      } else {\n        ctx.fillStyle = bg\n        ctx.fillRect(0, 0, cr.width, cr.height)\n      }\n      ctx.restore()\n\n      // First pass: collect clip path defs\n      collectClipPaths(nodes)\n\n      // Second pass: draw\n      drawNodes(cr.ctx, nodes, cr.width, cr.height)\n    },\n\n    update(root, nodes) {\n      this.render(root, nodes)\n    },\n\n    clear(root) {\n      const cr = root as unknown as CanvasRendererRoot\n      cr.ctx.clearRect(0, 0, cr.width, cr.height)\n    },\n\n    destroy(root) {\n      root.element.remove()\n    },\n  }\n\n  // -----------------------------------------------------------------------\n  // Collect clip path definitions (first pass)\n  // -----------------------------------------------------------------------\n\n  function collectClipPaths(nodes: RenderNode[]): void {\n    for (const node of nodes) {\n      if (node.type === 'defs') {\n        for (const child of node.children) {\n          if (child.type === 'clipPath') {\n            const path = new Path2D()\n            for (const cp of child.children) {\n              if (cp.type === 'rect') {\n                path.rect(cp.x, cp.y, cp.width, cp.height)\n              }\n            }\n            clipPaths.set(child.id, path)\n          }\n        }\n      } else if (node.type === 'group') {\n        collectClipPaths(node.children)\n      }\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Draw node tree\n  // -----------------------------------------------------------------------\n\n  function drawNodes(ctx: CanvasRenderingContext2D, nodes: RenderNode[], cw: number, ch: number): void {\n    for (const node of nodes) {\n      drawNode(ctx, node, cw, ch)\n    }\n  }\n\n  function drawNode(ctx: CanvasRenderingContext2D, node: RenderNode, cw: number, ch: number): void {\n    switch (node.type) {\n      case 'group': {\n        ctx.save()\n        applyClip(ctx, node.attrs)\n        applyTransform(ctx, node.attrs)\n        applyOpacity(ctx, node.attrs)\n        drawNodes(ctx, node.children, cw, ch)\n        ctx.restore()\n        break\n      }\n\n      case 'path': {\n        const fill = resolveFill(ctx, node.attrs?.fill, 0, 0, cw, ch)\n        const stroke = resolveColor(node.attrs?.stroke)\n        const strokeWidth = node.attrs?.strokeWidth ?? 0\n        const opacity = node.attrs?.opacity ?? 1\n        const fillOpacity = node.attrs?.fillOpacity ?? 1\n        const strokeOpacity = node.attrs?.strokeOpacity ?? 1\n\n        ctx.save()\n        applyClip(ctx, node.attrs)\n        ctx.globalAlpha = opacity\n        applyLineCaps(ctx, node.attrs)\n\n        const p = new Path2D(node.d)\n\n        if (fill && fill !== 'transparent' && fill !== 'none' && node.attrs?.fill) {\n          ctx.save()\n          ctx.globalAlpha = opacity * fillOpacity\n          ctx.fillStyle = typeof fill === 'object' ? fill : fill\n          ctx.fill(p)\n          ctx.restore()\n        }\n\n        if (stroke && stroke !== 'transparent' && stroke !== 'none' && strokeWidth > 0) {\n          ctx.save()\n          ctx.globalAlpha = opacity * strokeOpacity\n          ctx.strokeStyle = typeof stroke === 'string' ? stroke : '#000'\n          ctx.lineWidth = strokeWidth\n          applyDash(ctx, node.attrs?.strokeDasharray)\n          ctx.stroke(p)\n          ctx.restore()\n        }\n\n        ctx.restore()\n        break\n      }\n\n      case 'rect': {\n        const fill = resolveFill(ctx, node.attrs?.fill, node.x, node.y, node.width, node.height)\n        const stroke = resolveColor(node.attrs?.stroke)\n        const strokeWidth = node.attrs?.strokeWidth ?? 0\n        const opacity = node.attrs?.opacity ?? 1\n        const fillOpacity = node.attrs?.fillOpacity ?? 1\n        const strokeOpacity = node.attrs?.strokeOpacity ?? 1\n        const rx = node.rx ?? 0\n\n        ctx.save()\n        applyClip(ctx, node.attrs)\n        ctx.globalAlpha = opacity\n\n        if (fill && fill !== 'transparent' && fill !== 'none') {\n          ctx.save()\n          ctx.globalAlpha = opacity * fillOpacity\n          ctx.fillStyle = typeof fill === 'object' ? fill : fill\n          if (rx > 0) {\n            roundRect(ctx, node.x, node.y, node.width, node.height, rx)\n            ctx.fill()\n          } else {\n            ctx.fillRect(node.x, node.y, node.width, node.height)\n          }\n          ctx.restore()\n        }\n\n        if (stroke && stroke !== 'transparent' && stroke !== 'none' && strokeWidth > 0) {\n          ctx.save()\n          ctx.globalAlpha = opacity * strokeOpacity\n          ctx.strokeStyle = typeof stroke === 'string' ? stroke : '#000'\n          ctx.lineWidth = strokeWidth\n          applyDash(ctx, node.attrs?.strokeDasharray)\n          if (rx > 0) {\n            roundRect(ctx, node.x, node.y, node.width, node.height, rx)\n            ctx.stroke()\n          } else {\n            ctx.strokeRect(node.x, node.y, node.width, node.height)\n          }\n          ctx.restore()\n        }\n\n        ctx.restore()\n        break\n      }\n\n      case 'circle': {\n        const fill = resolveFill(ctx, node.attrs?.fill, node.cx - node.r, node.cy - node.r, node.r * 2, node.r * 2)\n        const stroke = resolveColor(node.attrs?.stroke)\n        const strokeWidth = node.attrs?.strokeWidth ?? 0\n        const opacity = node.attrs?.opacity ?? 1\n        const fillOpacity = node.attrs?.fillOpacity ?? 1\n        const strokeOpacity = node.attrs?.strokeOpacity ?? 1\n\n        ctx.save()\n        ctx.globalAlpha = opacity\n\n        ctx.beginPath()\n        ctx.arc(node.cx, node.cy, node.r, 0, Math.PI * 2)\n\n        if (fill && fill !== 'transparent' && fill !== 'none') {\n          ctx.save()\n          ctx.globalAlpha = opacity * fillOpacity\n          ctx.fillStyle = typeof fill === 'object' ? fill : fill\n          ctx.fill()\n          ctx.restore()\n        }\n\n        if (stroke && stroke !== 'transparent' && stroke !== 'none' && strokeWidth > 0) {\n          ctx.save()\n          ctx.globalAlpha = opacity * strokeOpacity\n          ctx.strokeStyle = typeof stroke === 'string' ? stroke : '#000'\n          ctx.lineWidth = strokeWidth\n          ctx.stroke()\n          ctx.restore()\n        }\n\n        ctx.restore()\n        break\n      }\n\n      case 'line': {\n        const stroke = resolveColor(node.attrs?.stroke, '#000')\n        const strokeWidth = node.attrs?.strokeWidth ?? 1\n        const opacity = node.attrs?.opacity ?? 1\n        const strokeOpacity = node.attrs?.strokeOpacity ?? 1\n\n        if (stroke === 'transparent' || stroke === 'none') break\n\n        ctx.save()\n        ctx.globalAlpha = opacity * strokeOpacity\n        ctx.strokeStyle = stroke\n        ctx.lineWidth = strokeWidth\n        applyLineCaps(ctx, node.attrs)\n        applyDash(ctx, node.attrs?.strokeDasharray)\n\n        // Subpixel alignment for crisp 1px lines\n        const offset = strokeWidth % 2 === 1 ? 0.5 : 0\n        ctx.beginPath()\n        ctx.moveTo(snapPixel(node.x1, offset), snapPixel(node.y1, offset))\n        ctx.lineTo(snapPixel(node.x2, offset), snapPixel(node.y2, offset))\n        ctx.stroke()\n        ctx.setLineDash([])\n        ctx.restore()\n        break\n      }\n\n      case 'text': {\n        const t = resolveTheme()\n        const fill = resolveColor(node.attrs?.fill, t.textColor)\n        const resolvedFill = resolveColor(fill)\n        const opacity = node.attrs?.opacity ?? 1\n        const extra = node.attrs as Record<string, unknown> | undefined\n        const fontSize = (extra?.fontSize as number) ?? t.fontSize\n        const fontFamily = (extra?.fontFamily as string) ?? t.fontFamily\n        const fontWeight = (extra?.fontWeight as string) ?? 'normal'\n        const textAnchor = extra?.textAnchor as string | undefined\n        const baseline = extra?.dominantBaseline as string | undefined\n\n        ctx.save()\n        ctx.globalAlpha = opacity\n        ctx.fillStyle = resolvedFill\n        ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`\n        ctx.textAlign = mapTextAlign(textAnchor)\n        ctx.textBaseline = mapTextBaseline(baseline)\n\n        // Handle transform (rotation for y-axis label)\n        applyTransform(ctx, node.attrs)\n\n        ctx.fillText(node.content, node.x, node.y)\n        ctx.restore()\n        break\n      }\n\n      case 'defs':\n      case 'clipPath':\n        // Already processed in first pass\n        break\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Helpers\n  // -----------------------------------------------------------------------\n\n  function resolveFill(\n    ctx: CanvasRenderingContext2D,\n    fill: string | undefined,\n    x: number, y: number, w: number, h: number,\n  ): CanvasGradient | string {\n    if (!fill) return 'transparent'\n    const urlId = parseUrlRef(fill)\n    if (urlId) {\n      const grad = resolveGradientRef(urlId, currentColors, ctx, x, y, w, h)\n      return grad ?? resolveColor(fill)\n    }\n    return resolveColor(fill)\n  }\n\n  function applyClip(ctx: CanvasRenderingContext2D, attrs?: RenderAttrs): void {\n    if (!attrs?.clipPath) return\n    const clipId = attrs.clipPath\n    const path = clipPaths.get(clipId)\n    if (path) {\n      ctx.clip(path)\n    }\n  }\n\n  function applyTransform(ctx: CanvasRenderingContext2D, attrs?: RenderAttrs): void {\n    if (!attrs?.transform) return\n    const t = attrs.transform\n\n    // translate(x, y)\n    const translateMatch = t.match(/translate\\(\\s*([^,)]+)[,\\s]+([^)]+)\\)/)\n    if (translateMatch) {\n      ctx.translate(parseFloat(translateMatch[1]!), parseFloat(translateMatch[2]!))\n    }\n\n    // rotate(deg) or rotate(deg, cx, cy)\n    const rotateMatch = t.match(/rotate\\(\\s*([^,)]+)(?:[,\\s]+([^,)]+)[,\\s]+([^)]+))?\\)/)\n    if (rotateMatch) {\n      const angle = parseFloat(rotateMatch[1]!) * Math.PI / 180\n      if (rotateMatch[2] && rotateMatch[3]) {\n        const cx = parseFloat(rotateMatch[2])\n        const cy = parseFloat(rotateMatch[3])\n        ctx.translate(cx, cy)\n        ctx.rotate(angle)\n        ctx.translate(-cx, -cy)\n      } else {\n        ctx.rotate(angle)\n      }\n    }\n\n    // scale(x, y)\n    const scaleMatch = t.match(/scale\\(\\s*([^,)]+)(?:[,\\s]+([^)]+))?\\)/)\n    if (scaleMatch) {\n      const sx = parseFloat(scaleMatch[1]!)\n      const sy = scaleMatch[2] ? parseFloat(scaleMatch[2]) : sx\n      ctx.scale(sx, sy)\n    }\n  }\n\n  function applyOpacity(ctx: CanvasRenderingContext2D, attrs?: RenderAttrs): void {\n    if (attrs?.opacity != null) {\n      ctx.globalAlpha *= attrs.opacity\n    }\n  }\n\n  function applyLineCaps(ctx: CanvasRenderingContext2D, attrs?: RenderAttrs): void {\n    if (attrs?.strokeLinecap) ctx.lineCap = attrs.strokeLinecap\n    if (attrs?.strokeLinejoin) ctx.lineJoin = attrs.strokeLinejoin\n  }\n\n  function applyDash(ctx: CanvasRenderingContext2D, dasharray?: string): void {\n    if (!dasharray) return\n    const segments = dasharray.split(/[\\s,]+/).map(Number).filter(n => !isNaN(n))\n    if (segments.length > 0) {\n      ctx.setLineDash(segments)\n    }\n  }\n\n  /** Snap to pixel grid for crisp lines */\n  function snapPixel(v: number, offset: number): number {\n    return Math.round(v) + offset\n  }\n\n  function roundRect(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void {\n    r = Math.min(r, w / 2, h / 2)\n    ctx.beginPath()\n    ctx.moveTo(x + r, y)\n    ctx.lineTo(x + w - r, y)\n    ctx.arcTo(x + w, y, x + w, y + r, r)\n    ctx.lineTo(x + w, y + h - r)\n    ctx.arcTo(x + w, y + h, x + w - r, y + h, r)\n    ctx.lineTo(x + r, y + h)\n    ctx.arcTo(x, y + h, x, y + h - r, r)\n    ctx.lineTo(x, y + r)\n    ctx.arcTo(x, y, x + r, y, r)\n    ctx.closePath()\n  }\n}\n","/**\n * WebGL Renderer.\n *\n * GPU-accelerated rendering for 100k–1M+ data points.\n * Uses a dual-layer approach:\n *   - WebGL canvas: lines, points, bars (data-heavy elements)\n *   - 2D canvas overlay: axes, text, grid, legends (needs Canvas2D text API)\n *\n * Falls back to the Canvas 2D renderer if WebGL is not available.\n */\n\nimport type { Renderer, RenderNode, RenderAttrs, RendererRoot, ThemeConfig } from '../types'\n\n// ---------------------------------------------------------------------------\n// Shader sources\n// ---------------------------------------------------------------------------\n\nconst LINE_VERT = `\nattribute vec2 a_position;\nattribute vec4 a_color;\nuniform vec2 u_resolution;\nvarying vec4 v_color;\nvoid main() {\n  vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;\n  gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);\n  v_color = a_color;\n}\n`\n\nconst LINE_FRAG = `\nprecision mediump float;\nvarying vec4 v_color;\nvoid main() {\n  gl_FragColor = v_color;\n}\n`\n\nconst POINT_VERT = `\nattribute vec2 a_position;\nattribute float a_radius;\nattribute vec4 a_color;\nuniform vec2 u_resolution;\nvarying vec4 v_color;\nvoid main() {\n  vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;\n  gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);\n  gl_PointSize = a_radius * 2.0;\n  v_color = a_color;\n}\n`\n\nconst POINT_FRAG = `\nprecision mediump float;\nvarying vec4 v_color;\nvoid main() {\n  vec2 coord = gl_PointCoord - vec2(0.5);\n  float dist = length(coord);\n  if (dist > 0.5) discard;\n  float alpha = 1.0 - smoothstep(0.4, 0.5, dist);\n  gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);\n}\n`\n\nconst RECT_VERT = `\nattribute vec2 a_position;\nattribute vec4 a_color;\nuniform vec2 u_resolution;\nvarying vec4 v_color;\nvoid main() {\n  vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;\n  gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);\n  v_color = a_color;\n}\n`\n\nconst RECT_FRAG = `\nprecision mediump float;\nvarying vec4 v_color;\nvoid main() {\n  gl_FragColor = v_color;\n}\n`\n\n// ---------------------------------------------------------------------------\n// Color utilities\n// ---------------------------------------------------------------------------\n\nfunction resolveColor(value: string | undefined, fallback = '#000'): string {\n  if (!value) return fallback\n  if (value === 'none' || value === 'transparent') return 'transparent'\n  if (value.startsWith('url(')) return fallback\n  const match = value.match(/var\\([^,]+,\\s*([^)]+)\\)/)\n  return match ? match[1]!.trim() : value\n}\n\nfunction hexToRGBA(hex: string, alpha = 1): [number, number, number, number] {\n  const h = hex.replace('#', '')\n  const full = h.length === 3\n    ? h[0]! + h[0]! + h[1]! + h[1]! + h[2]! + h[2]!\n    : h\n  return [\n    parseInt(full.substring(0, 2), 16) / 255,\n    parseInt(full.substring(2, 4), 16) / 255,\n    parseInt(full.substring(4, 6), 16) / 255,\n    alpha,\n  ]\n}\n\nfunction colorToRGBA(color: string, alpha = 1): [number, number, number, number] {\n  const resolved = resolveColor(color)\n  if (resolved === 'transparent') return [0, 0, 0, 0]\n  if (resolved.startsWith('#')) return hexToRGBA(resolved, alpha)\n  // rgba() parse\n  const rgbaMatch = resolved.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(?:,\\s*([\\d.]+))?\\s*\\)/)\n  if (rgbaMatch) {\n    return [\n      parseInt(rgbaMatch[1]!) / 255,\n      parseInt(rgbaMatch[2]!) / 255,\n      parseInt(rgbaMatch[3]!) / 255,\n      rgbaMatch[4] ? parseFloat(rgbaMatch[4]) * alpha : alpha,\n    ]\n  }\n  return [0, 0, 0, alpha]\n}\n\n// ---------------------------------------------------------------------------\n// WebGL helpers\n// ---------------------------------------------------------------------------\n\nfunction createShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader | null {\n  const shader = gl.createShader(type)\n  if (!shader) return null\n  gl.shaderSource(shader, source)\n  gl.compileShader(shader)\n  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n    gl.deleteShader(shader)\n    return null\n  }\n  return shader\n}\n\nfunction createProgram(gl: WebGLRenderingContext, vertSrc: string, fragSrc: string): WebGLProgram | null {\n  const vert = createShader(gl, gl.VERTEX_SHADER, vertSrc)\n  const frag = createShader(gl, gl.FRAGMENT_SHADER, fragSrc)\n  if (!vert || !frag) return null\n\n  const program = gl.createProgram()\n  if (!program) return null\n  gl.attachShader(program, vert)\n  gl.attachShader(program, frag)\n  gl.linkProgram(program)\n\n  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n    gl.deleteProgram(program)\n    return null\n  }\n  return program\n}\n\n// ---------------------------------------------------------------------------\n// WebGL Renderer Root\n// ---------------------------------------------------------------------------\n\ninterface WebGLRendererRoot {\n  container: HTMLDivElement\n  glCanvas: HTMLCanvasElement\n  gl: WebGLRenderingContext\n  overlay: HTMLCanvasElement\n  ctx2d: CanvasRenderingContext2D\n  width: number\n  height: number\n  dpr: number\n  programs: {\n    line: WebGLProgram\n    point: WebGLProgram\n    rect: WebGLProgram\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Text alignment helpers (reused from canvas.ts)\n// ---------------------------------------------------------------------------\n\nfunction mapTextAlign(anchor?: string): CanvasTextAlign {\n  switch (anchor) {\n    case 'middle': return 'center'\n    case 'end': return 'right'\n    default: return 'left'\n  }\n}\n\nfunction mapTextBaseline(baseline?: string): CanvasTextBaseline {\n  switch (baseline) {\n    case 'middle':\n    case 'central': return 'middle'\n    case 'hanging': return 'hanging'\n    default: return 'alphabetic'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function createWebGLRenderer(theme: ThemeConfig): Renderer {\n  return {\n    createRoot(target, width, height, attrs) {\n      // Container div holds both canvases\n      const container = document.createElement('div')\n      container.style.cssText = `position:relative;width:${width}px;height:${height}px;`\n      if (attrs?.class) container.className = attrs.class\n      if (attrs?.role) container.setAttribute('role', attrs.role)\n      if (attrs?.ariaLabel) container.setAttribute('aria-label', attrs.ariaLabel)\n\n      const dpr = window.devicePixelRatio || 1\n\n      // WebGL canvas (bottom layer — data rendering)\n      const glCanvas = document.createElement('canvas')\n      glCanvas.width = width * dpr\n      glCanvas.height = height * dpr\n      glCanvas.style.cssText = `position:absolute;top:0;left:0;width:${width}px;height:${height}px;`\n      container.appendChild(glCanvas)\n\n      const gl = glCanvas.getContext('webgl', {\n        alpha: true,\n        antialias: true,\n        premultipliedAlpha: false,\n      })!\n\n      // 2D overlay canvas (top layer — text, axes, legends)\n      const overlay = document.createElement('canvas')\n      overlay.width = width * dpr\n      overlay.height = height * dpr\n      overlay.style.cssText = `position:absolute;top:0;left:0;width:${width}px;height:${height}px;`\n      container.appendChild(overlay)\n\n      const ctx2d = overlay.getContext('2d')!\n      ctx2d.scale(dpr, dpr)\n\n      // Compile shader programs\n      const lineProgram = createProgram(gl, LINE_VERT, LINE_FRAG)!\n      const pointProgram = createProgram(gl, POINT_VERT, POINT_FRAG)!\n      const rectProgram = createProgram(gl, RECT_VERT, RECT_FRAG)!\n\n      // WebGL setup\n      gl.viewport(0, 0, width * dpr, height * dpr)\n      gl.enable(gl.BLEND)\n      gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)\n\n      target.appendChild(container)\n\n      const webglRoot: WebGLRendererRoot = {\n        container,\n        glCanvas,\n        gl,\n        overlay,\n        ctx2d,\n        width,\n        height,\n        dpr,\n        programs: {\n          line: lineProgram,\n          point: pointProgram,\n          rect: rectProgram,\n        },\n      }\n\n      // Store WebGL root data for retrieval in render/update/destroy\n      ;(container as unknown as Record<string, unknown>).__chartts_webgl = webglRoot\n\n      return { element: container } as unknown as RendererRoot & { _webgl: WebGLRendererRoot }\n    },\n\n    render(root, nodes) {\n      const wr = getWebGLRoot(root)\n      if (!wr) return\n\n      // Clear both canvases\n      const { gl, ctx2d, width, height, dpr } = wr\n      gl.viewport(0, 0, width * dpr, height * dpr)\n      gl.clearColor(0, 0, 0, 0)\n      gl.clear(gl.COLOR_BUFFER_BIT)\n\n      ctx2d.setTransform(dpr, 0, 0, dpr, 0, 0)\n      ctx2d.clearRect(0, 0, width, height)\n\n      // Collect draw commands from the node tree\n      const lines: GLLine[] = []\n      const points: GLPoint[] = []\n      const rects: GLRect[] = []\n\n      collectGLNodes(nodes, lines, points, rects)\n\n      // Batch draw with WebGL\n      drawGLLines(wr, lines)\n      drawGLPoints(wr, points)\n      drawGLRects(wr, rects)\n\n      // Draw text/axes/grid with 2D canvas\n      draw2DNodes(ctx2d, nodes, width, height, theme)\n    },\n\n    update(root, nodes) {\n      this.render(root, nodes)\n    },\n\n    clear(root) {\n      const wr = getWebGLRoot(root)\n      if (!wr) return\n      wr.gl.clear(wr.gl.COLOR_BUFFER_BIT)\n      wr.ctx2d.clearRect(0, 0, wr.width, wr.height)\n    },\n\n    destroy(root) {\n      const el = root.element as HTMLElement\n      el.remove()\n    },\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Internal types for batched GL draw commands\n// ---------------------------------------------------------------------------\n\ninterface GLLine {\n  x1: number; y1: number; x2: number; y2: number\n  color: [number, number, number, number]\n  width: number\n}\n\ninterface GLPoint {\n  x: number; y: number\n  radius: number\n  color: [number, number, number, number]\n}\n\ninterface GLRect {\n  x: number; y: number; w: number; h: number\n  color: [number, number, number, number]\n}\n\n// ---------------------------------------------------------------------------\n// Extract WebGLRendererRoot from RendererRoot\n// ---------------------------------------------------------------------------\n\nfunction getWebGLRoot(root: RendererRoot): WebGLRendererRoot | null {\n  // We store the WebGL root data on the container's dataset\n  const container = root.element as HTMLDivElement\n  const glCanvas = container.querySelector('canvas:first-child') as HTMLCanvasElement | null\n  const overlay = container.querySelector('canvas:last-child') as HTMLCanvasElement | null\n  if (!glCanvas || !overlay) return null\n\n  const gl = glCanvas.getContext('webgl')\n  const ctx2d = overlay.getContext('2d')\n  if (!gl || !ctx2d) return null\n\n  const dpr = window.devicePixelRatio || 1\n  const width = parseInt(container.style.width) || 400\n  const height = parseInt(container.style.height) || 300\n\n  // Re-compile programs (cached in WebGL context)\n  const lineProgram = createProgram(gl, LINE_VERT, LINE_FRAG)!\n  const pointProgram = createProgram(gl, POINT_VERT, POINT_FRAG)!\n  const rectProgram = createProgram(gl, RECT_VERT, RECT_FRAG)!\n\n  return {\n    container,\n    glCanvas,\n    gl,\n    overlay,\n    ctx2d,\n    width,\n    height,\n    dpr,\n    programs: {\n      line: lineProgram,\n      point: pointProgram,\n      rect: rectProgram,\n    },\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Collect GL-renderable nodes from the render tree\n// ---------------------------------------------------------------------------\n\nfunction collectGLNodes(\n  nodes: RenderNode[],\n  lines: GLLine[],\n  points: GLPoint[],\n  rects: GLRect[],\n  _parentAttrs?: RenderAttrs,\n): void {\n  for (const node of nodes) {\n    switch (node.type) {\n      case 'group':\n        collectGLNodes(node.children, lines, points, rects, node.attrs)\n        break\n\n      case 'line': {\n        const stroke = resolveColor(node.attrs?.stroke, '#000')\n        if (stroke === 'transparent' || stroke === 'none') break\n        const opacity = node.attrs?.opacity ?? 1\n        lines.push({\n          x1: node.x1, y1: node.y1,\n          x2: node.x2, y2: node.y2,\n          color: colorToRGBA(stroke, opacity),\n          width: node.attrs?.strokeWidth ?? 1,\n        })\n        break\n      }\n\n      case 'circle': {\n        const fill = resolveColor(node.attrs?.fill)\n        if (fill === 'transparent' || fill === 'none') break\n        const opacity = (node.attrs?.opacity ?? 1) * (node.attrs?.fillOpacity ?? 1)\n        points.push({\n          x: node.cx, y: node.cy,\n          radius: node.r,\n          color: colorToRGBA(fill, opacity),\n        })\n        break\n      }\n\n      case 'rect': {\n        const fill = resolveColor(node.attrs?.fill)\n        if (fill === 'transparent' || fill === 'none') break\n        const opacity = (node.attrs?.opacity ?? 1) * (node.attrs?.fillOpacity ?? 1)\n        rects.push({\n          x: node.x, y: node.y,\n          w: node.width, h: node.height,\n          color: colorToRGBA(fill, opacity),\n        })\n        break\n      }\n\n      case 'path': {\n        // Paths with stroke → approximate as line segments for WebGL\n        // Complex paths fall through to 2D overlay\n        const stroke = resolveColor(node.attrs?.stroke)\n        if (stroke && stroke !== 'transparent' && stroke !== 'none') {\n          const segs = pathToSegments(node.d)\n          const opacity = node.attrs?.opacity ?? 1\n          const color = colorToRGBA(stroke, opacity)\n          const width = node.attrs?.strokeWidth ?? 2\n          for (const seg of segs) {\n            lines.push({ ...seg, color, width })\n          }\n        }\n        // Filled paths → handled by 2D overlay for accuracy\n        break\n      }\n\n      // text, defs, clipPath → handled by 2D overlay\n      default:\n        break\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Parse SVG path d-string into line segments (for GL rendering)\n// ---------------------------------------------------------------------------\n\nfunction pathToSegments(d: string): Array<{ x1: number; y1: number; x2: number; y2: number }> {\n  const segments: Array<{ x1: number; y1: number; x2: number; y2: number }> = []\n  const commands = d.match(/[MLHVCSQTAZmlhvcsqtaz][^MLHVCSQTAZmlhvcsqtaz]*/g)\n  if (!commands) return segments\n\n  let cx = 0, cy = 0\n  let startX = 0, startY = 0\n\n  for (const cmd of commands) {\n    const type = cmd[0]!\n    const nums = (cmd.slice(1).match(/-?[\\d.]+(?:e[+-]?\\d+)?/gi) ?? []).map(Number)\n\n    switch (type) {\n      case 'M':\n        cx = nums[0] ?? 0\n        cy = nums[1] ?? 0\n        startX = cx\n        startY = cy\n        // M can have implicit L commands after first pair\n        for (let i = 2; i < nums.length; i += 2) {\n          const nx = nums[i] ?? 0\n          const ny = nums[i + 1] ?? 0\n          segments.push({ x1: cx, y1: cy, x2: nx, y2: ny })\n          cx = nx; cy = ny\n        }\n        break\n\n      case 'm':\n        cx += nums[0] ?? 0\n        cy += nums[1] ?? 0\n        startX = cx\n        startY = cy\n        for (let i = 2; i < nums.length; i += 2) {\n          const nx = cx + (nums[i] ?? 0)\n          const ny = cy + (nums[i + 1] ?? 0)\n          segments.push({ x1: cx, y1: cy, x2: nx, y2: ny })\n          cx = nx; cy = ny\n        }\n        break\n\n      case 'L':\n        for (let i = 0; i < nums.length; i += 2) {\n          const nx = nums[i] ?? 0\n          const ny = nums[i + 1] ?? 0\n          segments.push({ x1: cx, y1: cy, x2: nx, y2: ny })\n          cx = nx; cy = ny\n        }\n        break\n\n      case 'l':\n        for (let i = 0; i < nums.length; i += 2) {\n          const nx = cx + (nums[i] ?? 0)\n          const ny = cy + (nums[i + 1] ?? 0)\n          segments.push({ x1: cx, y1: cy, x2: nx, y2: ny })\n          cx = nx; cy = ny\n        }\n        break\n\n      case 'H':\n        for (const n of nums) {\n          segments.push({ x1: cx, y1: cy, x2: n, y2: cy })\n          cx = n\n        }\n        break\n\n      case 'h':\n        for (const n of nums) {\n          const nx = cx + n\n          segments.push({ x1: cx, y1: cy, x2: nx, y2: cy })\n          cx = nx\n        }\n        break\n\n      case 'V':\n        for (const n of nums) {\n          segments.push({ x1: cx, y1: cy, x2: cx, y2: n })\n          cy = n\n        }\n        break\n\n      case 'v':\n        for (const n of nums) {\n          const ny = cy + n\n          segments.push({ x1: cx, y1: cy, x2: cx, y2: ny })\n          cy = ny\n        }\n        break\n\n      case 'C': {\n        // Cubic bezier — approximate with line segments\n        for (let i = 0; i < nums.length; i += 6) {\n          const cp1x = nums[i]!, cp1y = nums[i + 1]!\n          const cp2x = nums[i + 2]!, cp2y = nums[i + 3]!\n          const ex = nums[i + 4]!, ey = nums[i + 5]!\n          approximateCubic(segments, cx, cy, cp1x, cp1y, cp2x, cp2y, ex, ey)\n          cx = ex; cy = ey\n        }\n        break\n      }\n\n      case 'c': {\n        for (let i = 0; i < nums.length; i += 6) {\n          const cp1x = cx + nums[i]!, cp1y = cy + nums[i + 1]!\n          const cp2x = cx + nums[i + 2]!, cp2y = cy + nums[i + 3]!\n          const ex = cx + nums[i + 4]!, ey = cy + nums[i + 5]!\n          approximateCubic(segments, cx, cy, cp1x, cp1y, cp2x, cp2y, ex, ey)\n          cx = ex; cy = ey\n        }\n        break\n      }\n\n      case 'S': {\n        for (let i = 0; i < nums.length; i += 4) {\n          const cp2x = nums[i]!, cp2y = nums[i + 1]!\n          const ex = nums[i + 2]!, ey = nums[i + 3]!\n          approximateCubic(segments, cx, cy, cx, cy, cp2x, cp2y, ex, ey)\n          cx = ex; cy = ey\n        }\n        break\n      }\n\n      case 'Q': {\n        // Quadratic bezier\n        for (let i = 0; i < nums.length; i += 4) {\n          const cpx = nums[i]!, cpy = nums[i + 1]!\n          const ex = nums[i + 2]!, ey = nums[i + 3]!\n          approximateQuadratic(segments, cx, cy, cpx, cpy, ex, ey)\n          cx = ex; cy = ey\n        }\n        break\n      }\n\n      case 'Z':\n      case 'z':\n        if (cx !== startX || cy !== startY) {\n          segments.push({ x1: cx, y1: cy, x2: startX, y2: startY })\n        }\n        cx = startX; cy = startY\n        break\n\n      // A (arc) — simplified: just connect endpoints\n      case 'A':\n        if (nums.length >= 7) {\n          const ex = nums[5]!, ey = nums[6]!\n          segments.push({ x1: cx, y1: cy, x2: ex, y2: ey })\n          cx = ex; cy = ey\n        }\n        break\n\n      default:\n        // Skip unrecognized\n        break\n    }\n  }\n\n  return segments\n}\n\nfunction approximateCubic(\n  out: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n  x0: number, y0: number,\n  cp1x: number, cp1y: number,\n  cp2x: number, cp2y: number,\n  x3: number, y3: number,\n  steps = 8,\n): void {\n  let px = x0, py = y0\n  for (let i = 1; i <= steps; i++) {\n    const t = i / steps\n    const t2 = t * t\n    const t3 = t2 * t\n    const mt = 1 - t\n    const mt2 = mt * mt\n    const mt3 = mt2 * mt\n    const nx = mt3 * x0 + 3 * mt2 * t * cp1x + 3 * mt * t2 * cp2x + t3 * x3\n    const ny = mt3 * y0 + 3 * mt2 * t * cp1y + 3 * mt * t2 * cp2y + t3 * y3\n    out.push({ x1: px, y1: py, x2: nx, y2: ny })\n    px = nx; py = ny\n  }\n}\n\nfunction approximateQuadratic(\n  out: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n  x0: number, y0: number,\n  cpx: number, cpy: number,\n  x2: number, y2: number,\n  steps = 6,\n): void {\n  let px = x0, py = y0\n  for (let i = 1; i <= steps; i++) {\n    const t = i / steps\n    const mt = 1 - t\n    const nx = mt * mt * x0 + 2 * mt * t * cpx + t * t * x2\n    const ny = mt * mt * y0 + 2 * mt * t * cpy + t * t * y2\n    out.push({ x1: px, y1: py, x2: nx, y2: ny })\n    px = nx; py = ny\n  }\n}\n\n// ---------------------------------------------------------------------------\n// WebGL batch draw: Lines\n// ---------------------------------------------------------------------------\n\nfunction drawGLLines(wr: WebGLRendererRoot, lines: GLLine[]): void {\n  if (lines.length === 0) return\n  const { gl, programs, width, height, dpr } = wr\n\n  gl.useProgram(programs.line)\n\n  const posLoc = gl.getAttribLocation(programs.line, 'a_position')\n  const colorLoc = gl.getAttribLocation(programs.line, 'a_color')\n  const resLoc = gl.getUniformLocation(programs.line, 'u_resolution')\n\n  gl.uniform2f(resLoc, width, height)\n\n  // Build interleaved buffer: [x1,y1,r,g,b,a, x2,y2,r,g,b,a] per line\n  const data = new Float32Array(lines.length * 12)\n  for (let i = 0; i < lines.length; i++) {\n    const l = lines[i]!\n    const off = i * 12\n    data[off] = l.x1; data[off + 1] = l.y1\n    data[off + 2] = l.color[0]; data[off + 3] = l.color[1]\n    data[off + 4] = l.color[2]; data[off + 5] = l.color[3]\n    data[off + 6] = l.x2; data[off + 7] = l.y2\n    data[off + 8] = l.color[0]; data[off + 9] = l.color[1]\n    data[off + 10] = l.color[2]; data[off + 11] = l.color[3]\n  }\n\n  const buf = gl.createBuffer()!\n  gl.bindBuffer(gl.ARRAY_BUFFER, buf)\n  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)\n\n  const stride = 24 // 6 floats * 4 bytes\n  gl.enableVertexAttribArray(posLoc)\n  gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, stride, 0)\n  gl.enableVertexAttribArray(colorLoc)\n  gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, stride, 8)\n\n  // Set line width (WebGL limits this, but try)\n  const maxWidth = lines.reduce((m, l) => Math.max(m, l.width), 1)\n  gl.lineWidth(Math.min(maxWidth * dpr, gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE)[1]))\n\n  gl.drawArrays(gl.LINES, 0, lines.length * 2)\n\n  gl.disableVertexAttribArray(posLoc)\n  gl.disableVertexAttribArray(colorLoc)\n  gl.deleteBuffer(buf)\n}\n\n// ---------------------------------------------------------------------------\n// WebGL batch draw: Points\n// ---------------------------------------------------------------------------\n\nfunction drawGLPoints(wr: WebGLRendererRoot, points: GLPoint[]): void {\n  if (points.length === 0) return\n  const { gl, programs, width, height, dpr } = wr\n\n  gl.useProgram(programs.point)\n\n  const posLoc = gl.getAttribLocation(programs.point, 'a_position')\n  const radiusLoc = gl.getAttribLocation(programs.point, 'a_radius')\n  const colorLoc = gl.getAttribLocation(programs.point, 'a_color')\n  const resLoc = gl.getUniformLocation(programs.point, 'u_resolution')\n\n  gl.uniform2f(resLoc, width, height)\n\n  // Interleaved: [x, y, radius, r, g, b, a] per point\n  const data = new Float32Array(points.length * 7)\n  for (let i = 0; i < points.length; i++) {\n    const p = points[i]!\n    const off = i * 7\n    data[off] = p.x; data[off + 1] = p.y\n    data[off + 2] = p.radius * dpr\n    data[off + 3] = p.color[0]; data[off + 4] = p.color[1]\n    data[off + 5] = p.color[2]; data[off + 6] = p.color[3]\n  }\n\n  const buf = gl.createBuffer()!\n  gl.bindBuffer(gl.ARRAY_BUFFER, buf)\n  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)\n\n  const stride = 28 // 7 floats * 4 bytes\n  gl.enableVertexAttribArray(posLoc)\n  gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, stride, 0)\n  gl.enableVertexAttribArray(radiusLoc)\n  gl.vertexAttribPointer(radiusLoc, 1, gl.FLOAT, false, stride, 8)\n  gl.enableVertexAttribArray(colorLoc)\n  gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, stride, 12)\n\n  gl.drawArrays(gl.POINTS, 0, points.length)\n\n  gl.disableVertexAttribArray(posLoc)\n  gl.disableVertexAttribArray(radiusLoc)\n  gl.disableVertexAttribArray(colorLoc)\n  gl.deleteBuffer(buf)\n}\n\n// ---------------------------------------------------------------------------\n// WebGL batch draw: Rects (as triangle pairs)\n// ---------------------------------------------------------------------------\n\nfunction drawGLRects(wr: WebGLRendererRoot, rects: GLRect[]): void {\n  if (rects.length === 0) return\n  const { gl, programs, width, height } = wr\n\n  gl.useProgram(programs.rect)\n\n  const posLoc = gl.getAttribLocation(programs.rect, 'a_position')\n  const colorLoc = gl.getAttribLocation(programs.rect, 'a_color')\n  const resLoc = gl.getUniformLocation(programs.rect, 'u_resolution')\n\n  gl.uniform2f(resLoc, width, height)\n\n  // 6 vertices per rect (2 triangles), 6 floats per vertex (x,y,r,g,b,a)\n  const data = new Float32Array(rects.length * 36)\n  for (let i = 0; i < rects.length; i++) {\n    const r = rects[i]!\n    const off = i * 36\n    const x0 = r.x, y0 = r.y, x1 = r.x + r.w, y1 = r.y + r.h\n    const c = r.color\n\n    // Triangle 1: top-left, top-right, bottom-left\n    data[off] = x0; data[off + 1] = y0; data[off + 2] = c[0]; data[off + 3] = c[1]; data[off + 4] = c[2]; data[off + 5] = c[3]\n    data[off + 6] = x1; data[off + 7] = y0; data[off + 8] = c[0]; data[off + 9] = c[1]; data[off + 10] = c[2]; data[off + 11] = c[3]\n    data[off + 12] = x0; data[off + 13] = y1; data[off + 14] = c[0]; data[off + 15] = c[1]; data[off + 16] = c[2]; data[off + 17] = c[3]\n\n    // Triangle 2: top-right, bottom-right, bottom-left\n    data[off + 18] = x1; data[off + 19] = y0; data[off + 20] = c[0]; data[off + 21] = c[1]; data[off + 22] = c[2]; data[off + 23] = c[3]\n    data[off + 24] = x1; data[off + 25] = y1; data[off + 26] = c[0]; data[off + 27] = c[1]; data[off + 28] = c[2]; data[off + 29] = c[3]\n    data[off + 30] = x0; data[off + 31] = y1; data[off + 32] = c[0]; data[off + 33] = c[1]; data[off + 34] = c[2]; data[off + 35] = c[3]\n  }\n\n  const buf = gl.createBuffer()!\n  gl.bindBuffer(gl.ARRAY_BUFFER, buf)\n  gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW)\n\n  const stride = 24\n  gl.enableVertexAttribArray(posLoc)\n  gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, stride, 0)\n  gl.enableVertexAttribArray(colorLoc)\n  gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, stride, 8)\n\n  gl.drawArrays(gl.TRIANGLES, 0, rects.length * 6)\n\n  gl.disableVertexAttribArray(posLoc)\n  gl.disableVertexAttribArray(colorLoc)\n  gl.deleteBuffer(buf)\n}\n\n// ---------------------------------------------------------------------------\n// 2D canvas overlay: text, axes, complex shapes\n// ---------------------------------------------------------------------------\n\nfunction draw2DNodes(\n  ctx: CanvasRenderingContext2D,\n  nodes: RenderNode[],\n  _cw: number, _ch: number,\n  theme: ThemeConfig,\n): void {\n  for (const node of nodes) {\n    draw2DNode(ctx, node, theme)\n  }\n}\n\nfunction draw2DNode(\n  ctx: CanvasRenderingContext2D,\n  node: RenderNode,\n  theme: ThemeConfig,\n): void {\n  switch (node.type) {\n    case 'group':\n      ctx.save()\n      if (node.attrs?.transform) apply2DTransform(ctx, node.attrs.transform)\n      if (node.attrs?.opacity != null) ctx.globalAlpha *= node.attrs.opacity\n      for (const child of node.children) draw2DNode(ctx, child, theme)\n      ctx.restore()\n      break\n\n    case 'text': {\n      const fill = resolveColor(node.attrs?.fill, resolveColor(theme.textColor))\n      const opacity = node.attrs?.opacity ?? 1\n      const fontSize = (node.attrs as Record<string, unknown>)?.fontSize as number ?? theme.fontSize\n      const fontFamily = (node.attrs as Record<string, unknown>)?.fontFamily as string ?? theme.fontFamily\n      const fontWeight = (node.attrs as Record<string, unknown>)?.fontWeight as string ?? 'normal'\n      const textAnchor = (node.attrs as Record<string, unknown>)?.textAnchor as string | undefined\n      const baseline = (node.attrs as Record<string, unknown>)?.dominantBaseline as string | undefined\n\n      ctx.save()\n      ctx.globalAlpha = opacity\n      ctx.fillStyle = resolveColor(fill)\n      ctx.font = `${fontWeight} ${fontSize}px ${resolveColor(fontFamily)}`\n      ctx.textAlign = mapTextAlign(textAnchor)\n      ctx.textBaseline = mapTextBaseline(baseline)\n\n      if (node.attrs?.transform) apply2DTransform(ctx, node.attrs.transform)\n      ctx.fillText(node.content, node.x, node.y)\n      ctx.restore()\n      break\n    }\n\n    case 'path': {\n      // Only draw filled paths on 2D overlay (stroked paths handled by WebGL)\n      const fill = resolveColor(node.attrs?.fill)\n      if (fill && fill !== 'transparent' && fill !== 'none' && node.attrs?.fill) {\n        const opacity = (node.attrs?.opacity ?? 1) * (node.attrs?.fillOpacity ?? 1)\n        ctx.save()\n        ctx.globalAlpha = opacity\n        ctx.fillStyle = fill\n        const p = new Path2D(node.d)\n        ctx.fill(p)\n        ctx.restore()\n      }\n      break\n    }\n\n    // line, rect, circle — already handled by WebGL, skip\n    default:\n      break\n  }\n}\n\nfunction apply2DTransform(ctx: CanvasRenderingContext2D, t: string): void {\n  const translateMatch = t.match(/translate\\(\\s*([^,)]+)[,\\s]+([^)]+)\\)/)\n  if (translateMatch) {\n    ctx.translate(parseFloat(translateMatch[1]!), parseFloat(translateMatch[2]!))\n  }\n\n  const rotateMatch = t.match(/rotate\\(\\s*([^,)]+)(?:[,\\s]+([^,)]+)[,\\s]+([^)]+))?\\)/)\n  if (rotateMatch) {\n    const angle = parseFloat(rotateMatch[1]!) * Math.PI / 180\n    if (rotateMatch[2] && rotateMatch[3]) {\n      const cx = parseFloat(rotateMatch[2])\n      const cy = parseFloat(rotateMatch[3])\n      ctx.translate(cx, cy)\n      ctx.rotate(angle)\n      ctx.translate(-cx, -cy)\n    } else {\n      ctx.rotate(angle)\n    }\n  }\n}\n","import type { ChartArea, ResolvedOptions, PreparedData } from '../types'\n\n/** Margins around the chart drawing area */\nexport interface Margins {\n  top: number\n  right: number\n  bottom: number\n  left: number\n}\n\n/**\n * Compute the chart drawing area given container dimensions,\n * padding, axis labels, and legend position.\n */\nexport function computeLayout(\n  width: number,\n  height: number,\n  options: ResolvedOptions,\n  data: PreparedData,\n): { area: ChartArea; margins: Margins } {\n  const [pt, pr, pb, pl] = options.padding\n\n  // Base margins from padding\n  let top = pt\n  let right = pr\n  let bottom = pb\n  let left = pl\n\n  // Reserve space for y-axis labels + ticks\n  if (options.yAxis) {\n    const maxLabel = estimateYLabelWidth(data, options)\n    left += maxLabel + 10 // label width + tick mark + gap\n  }\n\n  // Reserve space for y-axis label text (rotated)\n  if (options.yLabel) {\n    left += options.fontSize + 4\n  }\n\n  // Reserve space for x-axis labels + ticks\n  if (options.xAxis) {\n    bottom += options.fontSize + 8 // font height + tick mark + gap\n  }\n\n  // Reserve space for x-axis label text\n  if (options.xLabel) {\n    bottom += options.fontSize + 4\n  }\n\n  // Reserve space for legend\n  if (options.legend) {\n    switch (options.legend) {\n      case 'top':    top += 20; break\n      case 'bottom': bottom += 20; break\n      case 'left':   left += 80; break\n      case 'right':  right += 80; break\n    }\n  }\n\n  const area: ChartArea = {\n    x: left,\n    y: top,\n    width: Math.max(0, width - left - right),\n    height: Math.max(0, height - top - bottom),\n  }\n\n  return { area, margins: { top, right, bottom, left } }\n}\n\n/** Estimate the pixel width of the widest y-axis label */\nfunction estimateYLabelWidth(data: PreparedData, options: ResolvedOptions): number {\n  const { yMin, yMax } = data.bounds\n  const labels = [options.yFormat(yMin), options.yFormat(yMax)]\n  const maxLen = Math.max(...labels.map((l) => l.length))\n  // Approximate: each character ≈ 0.55em at the given font size\n  return maxLen * (options.fontSize * 0.55)\n}\n","import type { RenderNode, RenderAttrs } from '../types'\n\n/**\n * Render tree node constructors.\n * Charts describe what to draw using these — they never touch the DOM.\n */\n\nexport function group(children: RenderNode[], attrs?: RenderAttrs): RenderNode {\n  return { type: 'group', children, attrs }\n}\n\nexport function path(d: string, attrs?: RenderAttrs): RenderNode {\n  return { type: 'path', d, attrs }\n}\n\nexport function rect(\n  x: number, y: number, width: number, height: number,\n  attrs?: RenderAttrs & { rx?: number; ry?: number },\n): RenderNode {\n  return { type: 'rect', x, y, width, height, rx: attrs?.rx, ry: attrs?.ry, attrs }\n}\n\nexport function circle(cx: number, cy: number, r: number, attrs?: RenderAttrs): RenderNode {\n  return { type: 'circle', cx, cy, r, attrs }\n}\n\nexport function line(\n  x1: number, y1: number, x2: number, y2: number,\n  attrs?: RenderAttrs,\n): RenderNode {\n  return { type: 'line', x1, y1, x2, y2, attrs }\n}\n\nexport function text(\n  x: number, y: number, content: string,\n  attrs?: RenderAttrs & {\n    textAnchor?: 'start' | 'middle' | 'end'\n    dominantBaseline?: 'auto' | 'middle' | 'hanging' | 'central'\n    fontSize?: number\n    fontFamily?: string\n    fontWeight?: string | number\n  },\n): RenderNode {\n  return { type: 'text', x, y, content, attrs }\n}\n\nexport function defs(children: RenderNode[]): RenderNode {\n  return { type: 'defs', children }\n}\n\nexport function clipPathDef(id: string, children: RenderNode[]): RenderNode {\n  return { type: 'clipPath', id, children }\n}\n\n/**\n * SVG path string builder.\n */\nexport class PathBuilder {\n  private cmds: string[] = []\n\n  moveTo(x: number, y: number): this {\n    this.cmds.push(`M${n(x)},${n(y)}`); return this\n  }\n  lineTo(x: number, y: number): this {\n    this.cmds.push(`L${n(x)},${n(y)}`); return this\n  }\n  curveTo(cx1: number, cy1: number, cx2: number, cy2: number, x: number, y: number): this {\n    this.cmds.push(`C${n(cx1)},${n(cy1)},${n(cx2)},${n(cy2)},${n(x)},${n(y)}`); return this\n  }\n  quadTo(cx: number, cy: number, x: number, y: number): this {\n    this.cmds.push(`Q${n(cx)},${n(cy)},${n(x)},${n(y)}`); return this\n  }\n  arc(rx: number, ry: number, rot: number, large: boolean, sweep: boolean, x: number, y: number): this {\n    this.cmds.push(`A${n(rx)},${n(ry)},${rot},${large?1:0},${sweep?1:0},${n(x)},${n(y)}`); return this\n  }\n  hTo(x: number): this { this.cmds.push(`H${n(x)}`); return this }\n  vTo(y: number): this { this.cmds.push(`V${n(y)}`); return this }\n  close(): this { this.cmds.push('Z'); return this }\n  build(): string { return this.cmds.join('') }\n  reset(): this { this.cmds = []; return this }\n}\n\nfunction n(v: number): string {\n  return Number.isInteger(v) ? String(v) : v.toFixed(2)\n}\n","import type { RenderNode, Scale, ChartArea, ResolvedOptions, ThemeConfig } from '../types'\nimport { CSS_PREFIX } from '../constants'\nimport { group, line, text } from '../render/tree'\n\n/**\n * Render x-axis: axis line, tick marks, tick labels.\n * All colors reference CSS custom properties for Tailwind compatibility.\n */\nexport function renderXAxis(\n  scale: Scale,\n  area: ChartArea,\n  options: ResolvedOptions,\n  theme: ThemeConfig,\n): RenderNode {\n  const nodes: RenderNode[] = []\n  const y = area.y + area.height\n\n  // Axis line\n  if (options.xAxis) {\n    nodes.push(line(area.x, y, area.x + area.width, y, {\n      class: 'chartts-x-axis',\n      stroke: `var(${CSS_PREFIX}-axis)`,\n      strokeWidth: theme.axisWidth,\n    }))\n  }\n\n  // Ticks + labels\n  const ticks = scale.ticks(options.xTicks || undefined)\n  for (const tick of ticks) {\n    const x = tick.position\n\n    // Skip ticks outside chart area\n    if (x < area.x - 1 || x > area.x + area.width + 1) continue\n\n    // Tick mark\n    nodes.push(line(x, y, x, y + 4, {\n      class: 'chartts-x-tick',\n      stroke: `var(${CSS_PREFIX}-axis)`,\n      strokeWidth: theme.axisWidth,\n    }))\n\n    // Tick label\n    nodes.push(text(x, y + 14, tick.label, {\n      class: 'chartts-x-label',\n      fill: `var(${CSS_PREFIX}-text-muted)`,\n      textAnchor: 'middle',\n      fontSize: theme.fontSizeSmall,\n      fontFamily: `var(${CSS_PREFIX}-font-family)`,\n    }))\n  }\n\n  // Axis label\n  if (options.xLabel) {\n    nodes.push(text(\n      area.x + area.width / 2,\n      y + 30,\n      options.xLabel,\n      {\n        class: 'chartts-x-axis-label',\n        fill: `var(${CSS_PREFIX}-text)`,\n        textAnchor: 'middle',\n        fontSize: theme.fontSize,\n        fontFamily: `var(${CSS_PREFIX}-font-family)`,\n        fontWeight: 500,\n      },\n    ))\n  }\n\n  return group(nodes, { class: 'chartts-x-axis-group' })\n}\n\n/**\n * Render y-axis: axis line, tick marks, tick labels.\n */\nexport function renderYAxis(\n  scale: Scale,\n  area: ChartArea,\n  options: ResolvedOptions,\n  theme: ThemeConfig,\n): RenderNode {\n  const nodes: RenderNode[] = []\n\n  // Axis line\n  if (options.yAxis) {\n    nodes.push(line(area.x, area.y, area.x, area.y + area.height, {\n      class: 'chartts-y-axis',\n      stroke: `var(${CSS_PREFIX}-axis)`,\n      strokeWidth: theme.axisWidth,\n    }))\n  }\n\n  // Ticks + labels\n  const ticks = scale.ticks(options.yTicks)\n  for (const tick of ticks) {\n    const y = tick.position\n\n    // Skip ticks outside chart area (with small tolerance)\n    if (y < area.y - 1 || y > area.y + area.height + 1) continue\n\n    // Tick mark\n    nodes.push(line(area.x - 4, y, area.x, y, {\n      class: 'chartts-y-tick',\n      stroke: `var(${CSS_PREFIX}-axis)`,\n      strokeWidth: theme.axisWidth,\n    }))\n\n    // Tick label\n    nodes.push(text(area.x - 7, y, tick.label, {\n      class: 'chartts-y-label',\n      fill: `var(${CSS_PREFIX}-text-muted)`,\n      textAnchor: 'end',\n      dominantBaseline: 'middle',\n      fontSize: theme.fontSizeSmall,\n      fontFamily: `var(${CSS_PREFIX}-font-family)`,\n    }))\n  }\n\n  // Axis label (rotated)\n  if (options.yLabel) {\n    nodes.push(text(\n      12,\n      area.y + area.height / 2,\n      options.yLabel,\n      {\n        class: 'chartts-y-axis-label',\n        fill: `var(${CSS_PREFIX}-text)`,\n        textAnchor: 'middle',\n        fontSize: theme.fontSize,\n        fontFamily: `var(${CSS_PREFIX}-font-family)`,\n        fontWeight: 500,\n        transform: `rotate(-90, 12, ${area.y + area.height / 2})`,\n      },\n    ))\n  }\n\n  return group(nodes, { class: 'chartts-y-axis-group' })\n}\n\n/**\n * Render grid lines.\n */\nexport function renderGrid(\n  xScale: Scale,\n  yScale: Scale,\n  area: ChartArea,\n  options: ResolvedOptions,\n  theme: ThemeConfig,\n): RenderNode {\n  const nodes: RenderNode[] = []\n\n  const dasharray = theme.gridStyle === 'dashed' ? '4,4'\n    : theme.gridStyle === 'dotted' ? '2,2' : undefined\n\n  // Horizontal grid lines (from y-axis ticks)\n  if (options.yGrid) {\n    const ticks = yScale.ticks(options.yTicks)\n    for (const tick of ticks) {\n      // Skip ticks outside chart area or on axis boundaries\n      if (tick.position < area.y - 1 || tick.position > area.y + area.height + 1) continue\n      if (Math.abs(tick.position - area.y) < 1 || Math.abs(tick.position - (area.y + area.height)) < 1) continue\n\n      nodes.push(line(area.x, tick.position, area.x + area.width, tick.position, {\n        class: 'chartts-grid-h',\n        stroke: `var(${CSS_PREFIX}-grid)`,\n        strokeWidth: theme.gridWidth,\n        strokeDasharray: dasharray,\n      }))\n    }\n  }\n\n  // Vertical grid lines (from x-axis ticks)\n  if (options.xGrid) {\n    const ticks = xScale.ticks(options.xTicks || undefined)\n    for (const tick of ticks) {\n      // Skip ticks outside chart area or on axis boundaries\n      if (tick.position < area.x - 1 || tick.position > area.x + area.width + 1) continue\n      if (Math.abs(tick.position - area.x) < 1 || Math.abs(tick.position - (area.x + area.width)) < 1) continue\n\n      nodes.push(line(tick.position, area.y, tick.position, area.y + area.height, {\n        class: 'chartts-grid-v',\n        stroke: `var(${CSS_PREFIX}-grid)`,\n        strokeWidth: theme.gridWidth,\n        strokeDasharray: dasharray,\n      }))\n    }\n  }\n\n  return group(nodes, { class: 'chartts-grid-group' })\n}\n","import type { RenderNode, PreparedData, ResolvedOptions, ChartArea, ThemeConfig } from '../types'\nimport { CSS_PREFIX } from '../constants'\nimport { group, circle, text } from '../render/tree'\n\n/**\n * Render legend — series names with color indicators.\n * Positioned based on options.legend (top, bottom, left, right).\n */\nexport function renderLegend(\n  data: PreparedData,\n  area: ChartArea,\n  options: ResolvedOptions,\n  theme: ThemeConfig,\n): RenderNode | null {\n  if (!options.legend || data.series.length <= 1) return null\n\n  const items: RenderNode[] = []\n  const pos = options.legend\n\n  if (pos === 'top' || pos === 'bottom') {\n    // Horizontal layout — centered above or below chart area\n    const totalWidth = estimateLegendWidth(data, theme)\n    let x = area.x + Math.max(0, (area.width - totalWidth) / 2)\n    const y = pos === 'top' ? area.y - 10 : area.y + area.height + 32\n\n    for (const series of data.series) {\n      // Color dot\n      items.push(circle(x + 4, y, 3.5, {\n        class: 'chartts-legend-dot',\n        fill: series.color,\n      }))\n\n      // Series name\n      items.push(text(x + 12, y, series.name, {\n        class: 'chartts-legend-text',\n        fill: `var(${CSS_PREFIX}-text-muted)`,\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: `var(${CSS_PREFIX}-font-family)`,\n      }))\n\n      // Advance x position (estimate width from name length)\n      x += 12 + series.name.length * (theme.fontSizeSmall * 0.58) + 14\n    }\n  } else {\n    // Vertical layout (left or right)\n    const x = pos === 'left' ? 8 : area.x + area.width + 16\n    let y = area.y + 4\n\n    for (const series of data.series) {\n      items.push(circle(x + 4, y + 5, 3.5, {\n        class: 'chartts-legend-dot',\n        fill: series.color,\n      }))\n\n      items.push(text(x + 12, y + 5, series.name, {\n        class: 'chartts-legend-text',\n        fill: `var(${CSS_PREFIX}-text-muted)`,\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: `var(${CSS_PREFIX}-font-family)`,\n      }))\n\n      y += 18\n    }\n  }\n\n  return group(items, {\n    class: 'chartts-legend',\n    role: 'list',\n    ariaLabel: 'Chart legend',\n  })\n}\n\nfunction estimateLegendWidth(data: PreparedData, theme: ThemeConfig): number {\n  let width = 0\n  for (const series of data.series) {\n    width += 12 + series.name.length * (theme.fontSizeSmall * 0.58) + 14\n  }\n  return width\n}\n","import type { DataPoint, TooltipConfig, ThemeConfig } from '../types'\nimport { CSS_PREFIX } from '../constants'\n\n/**\n * DOM-based tooltip.\n * A real HTML element — style it with CSS, Tailwind, whatever you want.\n */\nexport interface TooltipInstance {\n  show(point: DataPoint, color: string, x: number, y: number, container: HTMLElement): void\n  hide(): void\n  destroy(): void\n}\n\nexport function createTooltip(config: TooltipConfig, theme: ThemeConfig): TooltipInstance {\n  let el: HTMLDivElement | null = null\n\n  function getOrCreate(): HTMLDivElement {\n    if (el) return el\n\n    el = document.createElement('div')\n    el.className = 'chartts-tooltip'\n    el.style.cssText = `\n      position: absolute;\n      pointer-events: none;\n      z-index: 9999;\n      padding: 10px 14px;\n      border-radius: var(${CSS_PREFIX}-radius, 8px);\n      background: var(${CSS_PREFIX}-tooltip-bg, ${theme.tooltipBackground});\n      color: var(${CSS_PREFIX}-tooltip-text, ${theme.tooltipText});\n      border: 1px solid var(${CSS_PREFIX}-tooltip-border, ${theme.tooltipBorder});\n      font-family: var(${CSS_PREFIX}-font-family, ${theme.fontFamily});\n      font-size: var(${CSS_PREFIX}-font-size-sm, ${theme.fontSizeSmall}px);\n      box-shadow: 0 8px 32px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);\n      backdrop-filter: blur(12px) saturate(1.5);\n      -webkit-backdrop-filter: blur(12px) saturate(1.5);\n      transition: opacity 0.15s ease, transform 0.1s ease;\n      opacity: 0;\n      transform: translateY(4px);\n      white-space: nowrap;\n    `\n    return el\n  }\n\n  function show(\n    point: DataPoint,\n    color: string,\n    x: number,\n    y: number,\n    container: HTMLElement,\n  ): void {\n    const tip = getOrCreate()\n\n    // Content\n    if (config.render) {\n      const result = config.render({ ...point, color })\n      if (typeof result === 'string') {\n        tip.innerHTML = result\n      } else {\n        tip.innerHTML = ''\n        tip.appendChild(result)\n      }\n    } else if (config.format) {\n      tip.textContent = config.format(point)\n    } else {\n      tip.innerHTML = `\n        <div style=\"display:flex;align-items:center;gap:8px;margin-bottom:4px;\">\n          <span style=\"width:8px;height:8px;border-radius:50%;background:${color};display:inline-block;box-shadow:0 0 6px ${color};\"></span>\n          <span style=\"font-weight:600;letter-spacing:-0.01em;\">${point.seriesName}</span>\n        </div>\n        <div style=\"display:flex;justify-content:space-between;align-items:baseline;gap:16px;\">\n          <span style=\"color:var(${CSS_PREFIX}-text-muted, #6b7280);font-size:0.9em;\">${point.label}</span>\n          <span style=\"font-size:1.15em;font-weight:700;font-variant-numeric:tabular-nums;\">${point.value}</span>\n        </div>\n      `\n    }\n\n    // Position\n    if (!tip.parentElement) {\n      container.style.position = 'relative'\n      container.appendChild(tip)\n    }\n\n    const tipRect = tip.getBoundingClientRect()\n    const containerRect = container.getBoundingClientRect()\n\n    let left = x - tipRect.width / 2\n    let top = y - tipRect.height - 12\n\n    // Keep within container bounds\n    if (left < 0) left = 0\n    if (left + tipRect.width > containerRect.width) left = containerRect.width - tipRect.width\n    if (top < 0) top = y + 16\n\n    tip.style.left = `${left}px`\n    tip.style.top = `${top}px`\n    tip.style.opacity = '1'\n    tip.style.transform = 'translateY(0)'\n  }\n\n  function hide(): void {\n    if (el) {\n      el.style.opacity = '0'\n      el.style.transform = 'translateY(4px)'\n    }\n  }\n\n  function destroy(): void {\n    el?.remove()\n    el = null\n  }\n\n  return { show, hide, destroy }\n}\n","import type { RenderContext, RenderNode, HitResult, ThemeConfig } from '../types'\nimport { circle } from '../render/tree'\n\n/**\n * Default highlight nodes: glow ring + solid dot at hit.x, hit.y.\n * Used when the chart type doesn't implement getHighlightNodes.\n */\nexport function defaultHighlightNodes(hit: HitResult, ctx: RenderContext): RenderNode[] {\n  const color = resolveHighlightColor(ctx.data.series[hit.seriesIndex]?.color, ctx.theme)\n  const r = ctx.theme.pointRadius\n\n  return [\n    // Outer glow\n    circle(hit.x, hit.y, r * 3, {\n      class: 'chartts-highlight-glow',\n      fill: color,\n      fillOpacity: 0.2,\n    }),\n    // Solid dot\n    circle(hit.x, hit.y, r + 1, {\n      class: 'chartts-highlight-dot',\n      fill: color,\n      stroke: ctx.theme.background === 'transparent' ? '#fff' : ctx.theme.background,\n      strokeWidth: 2,\n    }),\n  ]\n}\n\n/**\n * Walk a RenderNode tree and dim all series groups except the active one.\n * Returns a new tree (immutable).\n */\nexport function applyDimming(nodes: RenderNode[], hit: HitResult): RenderNode[] {\n  return nodes.map(node => dimNode(node, hit.seriesIndex))\n}\n\nfunction dimNode(node: RenderNode, activeSeriesIndex: number): RenderNode {\n  if (node.type === 'group') {\n    const cls = node.attrs?.class ?? ''\n    // Match chartts-series-N pattern\n    const seriesMatch = cls.match(/chartts-series-(\\d+)/)\n    if (seriesMatch) {\n      const idx = parseInt(seriesMatch[1]!, 10)\n      if (idx !== activeSeriesIndex) {\n        return {\n          ...node,\n          attrs: { ...node.attrs, opacity: 0.3 },\n          children: node.children,\n        }\n      }\n    }\n    // Recurse into children\n    return {\n      ...node,\n      children: node.children.map(c => dimNode(c, activeSeriesIndex)),\n    }\n  }\n  return node\n}\n\n/**\n * Extract a usable hex/rgb color from a CSS var string like 'var(--color-blue-500, #3b82f6)'.\n */\nexport function resolveHighlightColor(cssVarString: string | undefined, theme: ThemeConfig): string {\n  if (!cssVarString) return theme.colors[0] ?? '#3b82f6'\n  // Try to extract fallback from var(--token, #hex)\n  const m = cssVarString.match(/,\\s*([^)]+)\\)/)\n  if (m) return m[1]!.trim()\n  // If it's already a plain color\n  if (cssVarString.startsWith('#') || cssVarString.startsWith('rgb')) return cssVarString\n  // Fallback\n  return theme.colors[0] ?? '#3b82f6'\n}\n","import type {\n  ChartTypePlugin, RenderContext, EventBus, DataPoint,\n  PreparedData, TooltipConfig, ThemeConfig, CrosshairConfig,\n  Renderer, RendererRoot, RenderNode, HitResult,\n} from '../types'\nimport { createTooltip, type TooltipInstance } from '../tooltip/tooltip'\nimport { CSS_PREFIX } from '../constants'\nimport { defaultHighlightNodes, applyDimming } from './highlight'\n\nexport interface CanvasHighlightConfig {\n  renderer: Renderer\n  root: RendererRoot\n  getLastNodes: () => RenderNode[]\n}\n\nexport interface InteractionLayer {\n  attach(svg: SVGElement | HTMLCanvasElement, container: HTMLElement): void\n  detach(): void\n  destroy(): void\n}\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/**\n * Interaction layer — handles mouse/touch events on the chart.\n * Provides: hover highlights, tooltips, crosshair (vertical/horizontal/both), click events.\n *\n * For SVG renderer, interaction elements are appended directly to the SVG.\n * For Canvas renderer, a transparent SVG overlay is created on top of the\n * canvas to host crosshair lines, highlight dots, and other visual feedback.\n */\nexport function createInteractionLayer(\n  chartType: ChartTypePlugin,\n  getContext: () => RenderContext,\n  getData: () => PreparedData,\n  bus: EventBus,\n  tooltipConfig: false | TooltipConfig,\n  theme: ThemeConfig,\n  onClick?: (point: DataPoint, event: MouseEvent) => void,\n  onHover?: (point: DataPoint | null, event: MouseEvent) => void,\n  interactionState?: { isPanning: boolean },\n  canvasHighlight?: CanvasHighlightConfig,\n): InteractionLayer {\n  let targetEl: SVGElement | HTMLCanvasElement | null = null\n  let container: HTMLElement | null = null\n  let tooltip: TooltipInstance | null = null\n  let crosshairVLineEl: SVGLineElement | null = null\n  let crosshairHLineEl: SVGLineElement | null = null\n  let crosshairTipEl: HTMLDivElement | null = null\n  let crosshairYTipEl: HTMLDivElement | null = null\n  let crosshairDots: SVGCircleElement[] = []\n  let activePoint: { seriesIndex: number; pointIndex: number } | null = null\n  let activeCrosshairIndex = -1\n  let linkedUnsubs: (() => void)[] = []\n\n  // Canvas overlay — a transparent SVG positioned over the canvas\n  let overlayEl: SVGSVGElement | null = null\n  let isCanvas = false\n\n  // Create tooltip if configured\n  if (tooltipConfig) {\n    tooltip = createTooltip(\n      typeof tooltipConfig === 'object' ? tooltipConfig : { enabled: true },\n      theme,\n    )\n  }\n\n  /** Get the SVG element where interaction visuals should be drawn */\n  function getOverlay(): SVGElement | null {\n    if (isCanvas) return overlayEl\n    return targetEl as SVGElement | null\n  }\n\n  /** Sync overlay SVG to match the canvas CSS pixel dimensions exactly */\n  function syncOverlay(): void {\n    if (!overlayEl || !targetEl) return\n    const canvas = targetEl as HTMLCanvasElement\n    // CSS pixel width/height = chart coordinate system\n    const w = canvas.offsetWidth || canvas.clientWidth || parseInt(canvas.style.width) || 400\n    const h = canvas.offsetHeight || canvas.clientHeight || parseInt(canvas.style.height) || 300\n    overlayEl.setAttribute('viewBox', `0 0 ${w} ${h}`)\n    overlayEl.style.width = `${w}px`\n    overlayEl.style.height = `${h}px`\n  }\n\n  function getCrosshairConfig(): false | CrosshairConfig {\n    try {\n      return getContext().options.crosshair\n    } catch { return false }\n  }\n\n  // -----------------------------------------------------------------------\n  // Crosshair helpers\n  // -----------------------------------------------------------------------\n\n  function ensureCrosshairVLine(): SVGLineElement {\n    if (crosshairVLineEl) return crosshairVLineEl\n    crosshairVLineEl = document.createElementNS(SVG_NS, 'line')\n    crosshairVLineEl.setAttribute('class', 'chartts-crosshair-line chartts-crosshair-vline')\n    crosshairVLineEl.setAttribute('stroke', theme.textMuted)\n    crosshairVLineEl.setAttribute('stroke-width', '1')\n    crosshairVLineEl.setAttribute('stroke-dasharray', '4,3')\n    crosshairVLineEl.style.pointerEvents = 'none'\n    crosshairVLineEl.style.opacity = '0'\n    crosshairVLineEl.style.transition = 'opacity 0.12s ease'\n    return crosshairVLineEl\n  }\n\n  function ensureCrosshairHLine(): SVGLineElement {\n    if (crosshairHLineEl) return crosshairHLineEl\n    crosshairHLineEl = document.createElementNS(SVG_NS, 'line')\n    crosshairHLineEl.setAttribute('class', 'chartts-crosshair-line chartts-crosshair-hline')\n    crosshairHLineEl.setAttribute('stroke', theme.textMuted)\n    crosshairHLineEl.setAttribute('stroke-width', '1')\n    crosshairHLineEl.setAttribute('stroke-dasharray', '4,3')\n    crosshairHLineEl.style.pointerEvents = 'none'\n    crosshairHLineEl.style.opacity = '0'\n    crosshairHLineEl.style.transition = 'opacity 0.12s ease'\n    return crosshairHLineEl\n  }\n\n  function ensureCrosshairTip(): HTMLDivElement {\n    if (crosshairTipEl) return crosshairTipEl\n    crosshairTipEl = document.createElement('div')\n    crosshairTipEl.className = 'chartts-crosshair-tooltip'\n    crosshairTipEl.style.cssText = `\n      position: absolute;\n      pointer-events: none;\n      z-index: 9999;\n      padding: 10px 14px;\n      border-radius: var(${CSS_PREFIX}-radius, 8px);\n      background: var(${CSS_PREFIX}-tooltip-bg, ${theme.tooltipBackground});\n      color: var(${CSS_PREFIX}-tooltip-text, ${theme.tooltipText});\n      border: 1px solid var(${CSS_PREFIX}-tooltip-border, ${theme.tooltipBorder});\n      font-family: var(${CSS_PREFIX}-font-family, ${theme.fontFamily});\n      font-size: var(${CSS_PREFIX}-font-size-sm, ${theme.fontSizeSmall}px);\n      box-shadow: 0 8px 32px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08);\n      backdrop-filter: blur(12px) saturate(1.5);\n      -webkit-backdrop-filter: blur(12px) saturate(1.5);\n      transition: opacity 0.15s ease, transform 0.1s ease;\n      opacity: 0;\n      transform: translateY(4px);\n      white-space: nowrap;\n    `\n    return crosshairTipEl\n  }\n\n  function ensureCrosshairYTip(): HTMLDivElement {\n    if (crosshairYTipEl) return crosshairYTipEl\n    crosshairYTipEl = document.createElement('div')\n    crosshairYTipEl.className = 'chartts-crosshair-ytip'\n    crosshairYTipEl.style.cssText = `\n      position: absolute;\n      pointer-events: none;\n      z-index: 9998;\n      padding: 2px 6px;\n      border-radius: 3px;\n      background: ${theme.textMuted};\n      color: ${theme.tooltipBackground};\n      font-family: ${theme.fontFamily};\n      font-size: ${theme.fontSizeSmall - 1}px;\n      font-variant-numeric: tabular-nums;\n      opacity: 0;\n      transition: opacity 0.12s ease;\n      white-space: nowrap;\n    `\n    return crosshairYTipEl\n  }\n\n  function clearCrosshairDots(): void {\n    for (const d of crosshairDots) d.remove()\n    crosshairDots = []\n  }\n\n  function showCrosshair(pointIndex: number, mouseX: number, mouseY: number, svgY: number): void {\n    if (!targetEl || !container) return\n    const overlay = getOverlay()\n    if (!overlay) return\n\n    if (isCanvas) syncOverlay()\n\n    const ctx = getContext()\n    const data = getData()\n    const { area, xScale } = ctx\n    const chConfig = getCrosshairConfig()\n    if (!chConfig) return\n    const mode = chConfig.mode ?? 'vertical'\n\n    const label = data.labels[pointIndex]!\n    const xPos = xScale.map(label)\n\n    // Vertical line\n    if (mode === 'vertical' || mode === 'both') {\n      const vline = ensureCrosshairVLine()\n      vline.setAttribute('x1', String(xPos))\n      vline.setAttribute('y1', String(area.y))\n      vline.setAttribute('x2', String(xPos))\n      vline.setAttribute('y2', String(area.y + area.height))\n      vline.style.opacity = '0.6'\n      if (!vline.parentElement) overlay.appendChild(vline)\n    }\n\n    // Horizontal line\n    if (mode === 'horizontal' || mode === 'both') {\n      const hline = ensureCrosshairHLine()\n      hline.setAttribute('x1', String(area.x))\n      hline.setAttribute('y1', String(svgY))\n      hline.setAttribute('x2', String(area.x + area.width))\n      hline.setAttribute('y2', String(svgY))\n      hline.style.opacity = '0.6'\n      if (!hline.parentElement) overlay.appendChild(hline)\n\n      // Y-value label on left axis\n      const yVal = ctx.yScale.invert(svgY)\n      const yTip = ensureCrosshairYTip()\n      yTip.textContent = ctx.options.yFormat(yVal)\n      if (!yTip.parentElement) {\n        container.style.position = 'relative'\n        container.appendChild(yTip)\n      }\n      // Position at left edge\n      yTip.style.left = '0px'\n      yTip.style.top = `${mouseY - 10}px`\n      yTip.style.opacity = '1'\n    }\n\n    // Dots on each series at this x\n    if (mode === 'vertical' || mode === 'both') {\n      clearCrosshairDots()\n      for (const series of data.series) {\n        const val = series.values[pointIndex]\n        if (val == null || isNaN(val)) continue\n        const yPos = ctx.yScale.map(val)\n        const dot = document.createElementNS(SVG_NS, 'circle')\n        dot.setAttribute('cx', String(xPos))\n        dot.setAttribute('cy', String(yPos))\n        dot.setAttribute('r', '5')\n        dot.setAttribute('fill', series.color)\n        dot.setAttribute('stroke', theme.tooltipBackground)\n        dot.setAttribute('stroke-width', '2')\n        dot.style.pointerEvents = 'none'\n        dot.style.transition = 'cx 0.1s ease, cy 0.1s ease'\n        overlay.appendChild(dot)\n        crosshairDots.push(dot)\n      }\n    }\n\n    // Multi-series tooltip\n    const tip = ensureCrosshairTip()\n    let html = `<div style=\"font-weight:600;margin-bottom:6px;letter-spacing:-0.01em;\">${formatLabel(label)}</div>`\n    for (const series of data.series) {\n      const val = series.values[pointIndex]\n      if (val == null || isNaN(val)) continue\n      html += `<div style=\"display:flex;align-items:center;gap:8px;margin-top:3px;\">\n        <span style=\"width:8px;height:8px;border-radius:50%;background:${series.color};display:inline-block;box-shadow:0 0 6px ${series.color};flex-shrink:0;\"></span>\n        <span style=\"flex:1;color:var(${CSS_PREFIX}-text-muted, #6b7280);\">${series.name}</span>\n        <span style=\"font-weight:700;font-variant-numeric:tabular-nums;margin-left:12px;\">${ctx.options.yFormat(val)}</span>\n      </div>`\n    }\n    tip.innerHTML = html\n    if (!tip.parentElement) {\n      container.style.position = 'relative'\n      container.appendChild(tip)\n    }\n\n    // Position tooltip\n    requestAnimationFrame(() => {\n      if (!tip.parentElement || !container) return\n      const tipRect = tip.getBoundingClientRect()\n      const containerRect = container.getBoundingClientRect()\n      let left = mouseX + 16\n      let top = mouseY - tipRect.height / 2\n      if (left + tipRect.width > containerRect.width) left = mouseX - tipRect.width - 16\n      if (top < 0) top = 4\n      if (top + tipRect.height > containerRect.height) top = containerRect.height - tipRect.height - 4\n      tip.style.left = `${left}px`\n      tip.style.top = `${top}px`\n      tip.style.opacity = '1'\n      tip.style.transform = 'translateY(0)'\n    })\n\n    activeCrosshairIndex = pointIndex\n    bus.emit('crosshair:move', { x: xPos, label })\n  }\n\n  function hideCrosshair(): void {\n    if (activeCrosshairIndex === -1) return\n    if (crosshairVLineEl) crosshairVLineEl.style.opacity = '0'\n    if (crosshairHLineEl) crosshairHLineEl.style.opacity = '0'\n    if (crosshairTipEl) {\n      crosshairTipEl.style.opacity = '0'\n      crosshairTipEl.style.transform = 'translateY(4px)'\n    }\n    if (crosshairYTipEl) {\n      crosshairYTipEl.style.opacity = '0'\n    }\n    clearCrosshairDots()\n    activeCrosshairIndex = -1\n    bus.emit('crosshair:hide', undefined as never)\n  }\n\n  function formatLabel(label: string | number | Date): string {\n    try { return getContext().options.xFormat(label) } catch { return String(label) }\n  }\n\n  /** Find nearest label index given an svgX coordinate */\n  function nearestLabelIndex(svgX: number): number {\n    const data = getData()\n    const ctx = getContext()\n    let bestIdx = 0\n    let bestDist = Infinity\n    for (let i = 0; i < data.labels.length; i++) {\n      const pos = ctx.xScale.map(data.labels[i]!)\n      const dist = Math.abs(svgX - pos)\n      if (dist < bestDist) { bestDist = dist; bestIdx = i }\n    }\n    return bestIdx\n  }\n\n  // -----------------------------------------------------------------------\n  // Event handlers\n  // -----------------------------------------------------------------------\n\n  function toChartCoords(el: SVGElement | HTMLCanvasElement, clientX: number, clientY: number): { x: number; y: number; svgX: number; svgY: number } {\n    const r = el.getBoundingClientRect()\n    const x = clientX - r.left\n    const y = clientY - r.top\n\n    // Canvas: coords are CSS pixels (matching our coordinate system)\n    if (el instanceof HTMLCanvasElement) {\n      return { x, y, svgX: x, svgY: y }\n    }\n    // SVG: scale to viewBox coords\n    const viewBox = el.getAttribute('viewBox')?.split(' ').map(Number) ?? [0, 0, r.width, r.height]\n    const scaleX = viewBox[2]! / r.width\n    const scaleY = viewBox[3]! / r.height\n    return { x, y, svgX: x * scaleX, svgY: y * scaleY }\n  }\n\n  function onMouseMove(e: MouseEvent): void {\n    if (!targetEl || !container) return\n    // Skip tooltip/crosshair updates during active pan drag\n    if (interactionState?.isPanning) return\n\n    const { x, y, svgX, svgY } = toChartCoords(targetEl, e.clientX, e.clientY)\n\n    const ctx = getContext()\n    const chConfig = getCrosshairConfig()\n\n    // Crosshair mode — snap to nearest label\n    if (chConfig) {\n      const { area } = ctx\n      if (svgX >= area.x && svgX <= area.x + area.width && svgY >= area.y && svgY <= area.y + area.height) {\n        const idx = nearestLabelIndex(svgX)\n        if (idx !== activeCrosshairIndex) {\n          showCrosshair(idx, x, y, svgY)\n        } else {\n          // Update horizontal line position and reposition tooltip\n          if (chConfig.mode === 'horizontal' || chConfig.mode === 'both') {\n            if (crosshairHLineEl) {\n              crosshairHLineEl.setAttribute('y1', String(svgY))\n              crosshairHLineEl.setAttribute('y2', String(svgY))\n            }\n            if (crosshairYTipEl) {\n              const yVal = ctx.yScale.invert(svgY)\n              crosshairYTipEl.textContent = ctx.options.yFormat(yVal)\n              crosshairYTipEl.style.top = `${y - 10}px`\n            }\n          }\n          if (crosshairTipEl) {\n            const tipRect = crosshairTipEl.getBoundingClientRect()\n            const containerRect = container.getBoundingClientRect()\n            let left = x + 16\n            let top = y - tipRect.height / 2\n            if (left + tipRect.width > containerRect.width) left = x - tipRect.width - 16\n            if (top < 0) top = 4\n            if (top + tipRect.height > containerRect.height) top = containerRect.height - tipRect.height - 4\n            crosshairTipEl.style.left = `${left}px`\n            crosshairTipEl.style.top = `${top}px`\n          }\n        }\n      } else {\n        hideCrosshair()\n      }\n      // In crosshair mode, skip single-point tooltip\n      return\n    }\n\n    // Standard single-point mode\n    const hit = chartType.hitTest(ctx, svgX, svgY)\n\n    if (hit) {\n      const data = getData()\n      const series = data.series[hit.seriesIndex]!\n      const point: DataPoint = {\n        label: data.labels[hit.pointIndex]!,\n        value: series.values[hit.pointIndex]!,\n        index: hit.pointIndex,\n        seriesIndex: hit.seriesIndex,\n        seriesName: series.name,\n      }\n\n      // Update hover highlights\n      if (!activePoint || activePoint.seriesIndex !== hit.seriesIndex || activePoint.pointIndex !== hit.pointIndex) {\n        clearHighlights()\n        highlightPoint(hit)\n        activePoint = { seriesIndex: hit.seriesIndex, pointIndex: hit.pointIndex }\n\n        bus.emit('point:enter', { point, event: e })\n        onHover?.(point, e)\n      }\n\n      // Show tooltip\n      if (tooltip) {\n        tooltip.show(point, series.color, x, y, container)\n        bus.emit('tooltip:show', { point, x: svgX, y: svgY })\n      }\n    } else {\n      if (activePoint) {\n        clearHighlights()\n        activePoint = null\n        bus.emit('point:leave', { event: e })\n        onHover?.(null, e)\n      }\n      if (tooltip) {\n        tooltip.hide()\n        bus.emit('tooltip:hide', undefined as never)\n      }\n    }\n  }\n\n  function onMouseLeave(e: MouseEvent): void {\n    clearHighlights()\n    activePoint = null\n    tooltip?.hide()\n    hideCrosshair()\n    bus.emit('point:leave', { event: e })\n    onHover?.(null, e)\n  }\n\n  function onClickHandler(e: MouseEvent): void {\n    if (!targetEl || !onClick) return\n\n    const { svgX, svgY } = toChartCoords(targetEl, e.clientX, e.clientY)\n\n    const ctx = getContext()\n    const hit = chartType.hitTest(ctx, svgX, svgY)\n\n    if (hit) {\n      const data = getData()\n      const series = data.series[hit.seriesIndex]!\n      const point: DataPoint = {\n        label: data.labels[hit.pointIndex]!,\n        value: series.values[hit.pointIndex]!,\n        index: hit.pointIndex,\n        seriesIndex: hit.seriesIndex,\n        seriesName: series.name,\n      }\n      onClick(point, e)\n      bus.emit('point:click', { point, event: e })\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Linked chart crosshair — respond to bus events from linkCharts\n  // -----------------------------------------------------------------------\n\n  function setupLinkedCrosshair(): void {\n    const unsub1 = bus.on('crosshair:move', ((payload: { x: number; label: string | number | Date }) => {\n      if (!targetEl || !container) return\n      const data = getData()\n      const idx = data.labels.findIndex(l => String(l) === String(payload.label))\n      if (idx < 0) return\n      if (idx === activeCrosshairIndex) return\n      // Show crosshair at this index with approximate positioning\n      const ctx = getContext()\n      const xPos = ctx.xScale.map(data.labels[idx]!)\n      const rect = targetEl.getBoundingClientRect()\n      showCrosshair(idx, xPos, rect.height / 2, ctx.area.y + ctx.area.height / 2)\n    }) as never)\n\n    const unsub2 = bus.on('crosshair:hide', (() => {\n      hideCrosshair()\n    }) as never)\n\n    linkedUnsubs.push(unsub1, unsub2)\n  }\n\n  // -----------------------------------------------------------------------\n  // Highlight / dim\n  // -----------------------------------------------------------------------\n\n  let highlightRafId = 0\n\n  function highlightPoint(hit: HitResult): void {\n    if (isCanvas && canvasHighlight) {\n      // Canvas: re-render with dimmed series + highlight nodes\n      if (highlightRafId) return // already scheduled\n      highlightRafId = requestAnimationFrame(() => {\n        highlightRafId = 0\n        const ctx = getContext()\n        const baseNodes = canvasHighlight!.getLastNodes()\n        const dimmed = applyDimming(baseNodes, hit)\n        const highlight = chartType.getHighlightNodes\n          ? chartType.getHighlightNodes(ctx, hit)\n          : defaultHighlightNodes(hit, ctx)\n        canvasHighlight!.renderer.render(canvasHighlight!.root, [...dimmed, ...highlight])\n      })\n      return\n    }\n\n    // SVG mode: manipulate DOM elements directly\n    const svg = targetEl as SVGElement\n    if (!svg) return\n    const target = svg.querySelector(\n      `[data-series=\"${hit.seriesIndex}\"][data-index=\"${hit.pointIndex}\"]`,\n    ) as SVGElement | null\n\n    if (target?.classList.contains('chartts-point')) {\n      target.style.transition = 'r 0.15s ease, stroke-width 0.15s ease'\n      target.setAttribute('r', '6')\n      target.setAttribute('stroke-width', '3')\n    }\n\n    const targetGroup = target?.closest('.chartts-series')\n    svg.querySelectorAll('.chartts-series').forEach((el) => {\n      if (el !== targetGroup) {\n        ;(el as SVGElement).style.opacity = '0.3'\n        ;(el as SVGElement).style.transition = 'opacity 0.15s ease'\n      }\n    })\n  }\n\n  function clearHighlights(): void {\n    if (isCanvas && canvasHighlight) {\n      // Cancel pending highlight RAF\n      if (highlightRafId) {\n        cancelAnimationFrame(highlightRafId)\n        highlightRafId = 0\n      }\n      // Re-render without dimming/highlight\n      canvasHighlight.renderer.render(canvasHighlight.root, canvasHighlight.getLastNodes())\n      return\n    }\n\n    const svg = targetEl as SVGElement | null\n    if (!svg) return\n\n    svg.querySelectorAll('.chartts-point').forEach((p) => {\n      const el = p as SVGElement\n      el.setAttribute('r', el.getAttribute('data-original-r') || '3.5')\n      el.setAttribute('stroke-width', '2')\n    })\n\n    svg.querySelectorAll('.chartts-series').forEach((el) => {\n      ;(el as SVGElement).style.opacity = ''\n    })\n  }\n\n  // -----------------------------------------------------------------------\n  // Public API\n  // -----------------------------------------------------------------------\n\n  return {\n    attach(svgEl: SVGElement | HTMLCanvasElement, containerEl: HTMLElement): void {\n      targetEl = svgEl\n      container = containerEl\n      isCanvas = svgEl instanceof HTMLCanvasElement\n\n      if (isCanvas) {\n        containerEl.style.position = 'relative'\n        overlayEl = document.createElementNS(SVG_NS, 'svg') as SVGSVGElement\n        const canvas = svgEl as unknown as HTMLCanvasElement\n        const w = canvas.offsetWidth || canvas.clientWidth || parseInt(canvas.style.width) || 400\n        const h = canvas.offsetHeight || canvas.clientHeight || parseInt(canvas.style.height) || 300\n        overlayEl.setAttribute('viewBox', `0 0 ${w} ${h}`)\n        overlayEl.style.cssText = `position:absolute;top:0;left:0;width:${w}px;height:${h}px;pointer-events:none;overflow:visible;`\n        containerEl.appendChild(overlayEl)\n      }\n\n      svgEl.style.cursor = 'crosshair'\n      const el = svgEl as unknown as HTMLElement\n      el.addEventListener('mousemove', onMouseMove as EventListener)\n      el.addEventListener('mouseleave', onMouseLeave as EventListener)\n      el.addEventListener('click', onClickHandler as EventListener)\n\n      // Set up linked chart crosshair listener\n      setupLinkedCrosshair()\n    },\n\n    detach(): void {\n      if (!targetEl) return\n      const el = targetEl as unknown as HTMLElement\n      el.removeEventListener('mousemove', onMouseMove as EventListener)\n      el.removeEventListener('mouseleave', onMouseLeave as EventListener)\n      el.removeEventListener('click', onClickHandler as EventListener)\n      for (const unsub of linkedUnsubs) unsub()\n      linkedUnsubs = []\n    },\n\n    destroy(): void {\n      this.detach()\n      tooltip?.destroy()\n      crosshairVLineEl?.remove()\n      crosshairHLineEl?.remove()\n      crosshairTipEl?.remove()\n      crosshairYTipEl?.remove()\n      clearCrosshairDots()\n      overlayEl?.remove()\n      overlayEl = null\n      targetEl = null\n      container = null\n    },\n  }\n}\n","import type { RenderNode, ThemeConfig } from '../types'\nimport { group, rect, text } from './tree'\n\n/**\n * Render an \"empty data\" placeholder inside the chart area.\n */\nexport function renderEmptyState(\n  width: number,\n  height: number,\n  theme: ThemeConfig,\n  message = 'No data to display',\n): RenderNode[] {\n  const cx = width / 2\n  const cy = height / 2\n\n  return [group([\n    // Empty chart icon — simple bar chart outline\n    ...emptyBars(cx, cy - 16, theme),\n    // Message\n    text(cx, cy + 28, message, {\n      class: 'chartts-state-text',\n      fill: theme.textMuted,\n      textAnchor: 'middle',\n      dominantBaseline: 'middle',\n      fontSize: theme.fontSize,\n      fontFamily: theme.fontFamily,\n    }),\n  ], { class: 'chartts-state chartts-state-empty' })]\n}\n\n/**\n * Render a loading skeleton with animated shimmer bars.\n */\nexport function renderLoadingState(\n  width: number,\n  height: number,\n  theme: ThemeConfig,\n): RenderNode[] {\n  const barCount = 5\n  const padding = width * 0.15\n  const barAreaW = width - padding * 2\n  const barW = barAreaW / barCount * 0.6\n  const gap = barAreaW / barCount * 0.4\n  const maxH = height * 0.6\n  const baseY = height * 0.8\n\n  const bars: RenderNode[] = []\n  const heights = [0.6, 0.85, 0.45, 0.95, 0.7]\n\n  for (let i = 0; i < barCount; i++) {\n    const x = padding + i * (barW + gap)\n    const h = maxH * heights[i]!\n    const y = baseY - h\n\n    bars.push(rect(x, y, barW, h, {\n      class: 'chartts-skeleton-bar',\n      fill: theme.gridColor,\n      rx: 3,\n      ry: 3,\n      opacity: 0.6,\n    }))\n  }\n\n  // Baseline\n  bars.push(rect(padding, baseY, barAreaW, 1, {\n    fill: theme.axisColor,\n    opacity: 0.4,\n  }))\n\n  return [group(bars, { class: 'chartts-state chartts-state-loading' })]\n}\n\n/**\n * Render an error state with message.\n */\nexport function renderErrorState(\n  width: number,\n  height: number,\n  theme: ThemeConfig,\n  message = 'Failed to render chart',\n): RenderNode[] {\n  const cx = width / 2\n  const cy = height / 2\n\n  return [group([\n    // Error icon — circle with exclamation\n    ...errorIcon(cx, cy - 18, theme),\n    // Message\n    text(cx, cy + 24, message, {\n      class: 'chartts-state-text',\n      fill: theme.textMuted,\n      textAnchor: 'middle',\n      dominantBaseline: 'middle',\n      fontSize: theme.fontSize,\n      fontFamily: theme.fontFamily,\n    }),\n  ], { class: 'chartts-state chartts-state-error' })]\n}\n\n/** Small bar chart icon for empty state */\nfunction emptyBars(cx: number, cy: number, theme: ThemeConfig): RenderNode[] {\n  const barW = 6\n  const gap = 4\n  const heights = [14, 22, 10, 18]\n  const totalW = heights.length * barW + (heights.length - 1) * gap\n  const startX = cx - totalW / 2\n\n  return heights.map((h, i) =>\n    rect(startX + i * (barW + gap), cy - h / 2, barW, h, {\n      fill: theme.gridColor,\n      rx: 1,\n      ry: 1,\n    }),\n  )\n}\n\n/** Circle with \"!\" for error state */\nfunction errorIcon(cx: number, cy: number, theme: ThemeConfig): RenderNode[] {\n  return [\n    // Circle outline\n    rect(cx - 14, cy - 14, 28, 28, {\n      fill: 'none',\n      stroke: theme.textMuted,\n      strokeWidth: 1.5,\n      rx: 14,\n      ry: 14,\n      opacity: 0.6,\n    }),\n    // Exclamation line\n    rect(cx - 1, cy - 7, 2, 10, {\n      fill: theme.textMuted,\n      opacity: 0.6,\n    }),\n    // Exclamation dot\n    rect(cx - 1, cy + 5, 2, 2, {\n      fill: theme.textMuted,\n      opacity: 0.6,\n    }),\n  ]\n}\n","/**\n * SVG gradient and filter definitions for premium visual effects.\n *\n * Generated per-chart based on the resolved color palette.\n * Injected into <defs> by both the DOM and string renderers.\n */\n\n/**\n * Extract a hex color from a CSS var() expression.\n * 'var(--color-blue-500, #3b82f6)' → '#3b82f6'\n * '#3b82f6' → '#3b82f6'\n */\nfunction extractHex(css: string): string {\n  const match = css.match(/#[0-9a-fA-F]{3,8}/)\n  return match ? match[0] : css\n}\n\n/**\n * Parse hex color to {r, g, b}\n */\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n  const h = hex.replace('#', '')\n  const full = h.length === 3\n    ? h[0]! + h[0]! + h[1]! + h[1]! + h[2]! + h[2]!\n    : h\n  return {\n    r: parseInt(full.substring(0, 2), 16),\n    g: parseInt(full.substring(2, 4), 16),\n    b: parseInt(full.substring(4, 6), 16),\n  }\n}\n\n/**\n * Generate SVG defs string with gradients and filters for chart effects.\n */\nexport function createEffectDefs(colors: string[]): string {\n  let svg = ''\n\n  for (let i = 0; i < colors.length; i++) {\n    const hex = extractHex(colors[i]!)\n    const { r, g, b } = hexToRgb(hex)\n    const rgba = (a: number) => `rgba(${r},${g},${b},${a})`\n\n    // Area fill gradient (vertical: color at top → transparent at bottom)\n    svg += `<linearGradient id=\"chartts-area-${i}\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">`\n    svg += `<stop offset=\"0%\" stop-color=\"${hex}\" stop-opacity=\"0.35\"/>`\n    svg += `<stop offset=\"100%\" stop-color=\"${hex}\" stop-opacity=\"0.02\"/>`\n    svg += `</linearGradient>`\n\n    // Bar gradient (vertical: lighter at top → color at bottom)\n    svg += `<linearGradient id=\"chartts-bar-${i}\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">`\n    svg += `<stop offset=\"0%\" stop-color=\"${hex}\" stop-opacity=\"1\"/>`\n    svg += `<stop offset=\"100%\" stop-color=\"${hex}\" stop-opacity=\"0.75\"/>`\n    svg += `</linearGradient>`\n\n    // Radial glow for points/bubbles\n    svg += `<radialGradient id=\"chartts-pglow-${i}\">`\n    svg += `<stop offset=\"0%\" stop-color=\"${hex}\" stop-opacity=\"0.4\"/>`\n    svg += `<stop offset=\"100%\" stop-color=\"${hex}\" stop-opacity=\"0\"/>`\n    svg += `</radialGradient>`\n\n    // Pie slice radial gradient (center lighter → edge)\n    svg += `<radialGradient id=\"chartts-pie-${i}\" cx=\"30%\" cy=\"30%\" r=\"70%\">`\n    svg += `<stop offset=\"0%\" stop-color=\"${hex}\" stop-opacity=\"1\"/>`\n    svg += `<stop offset=\"100%\" stop-color=\"${rgba(0.85)}\"/>`\n    svg += `</radialGradient>`\n  }\n\n  // Line glow filter\n  svg += `<filter id=\"chartts-glow\" filterUnits=\"userSpaceOnUse\">`\n  svg += `<feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"3.5\" result=\"blur\"/>`\n  svg += `<feColorMatrix in=\"blur\" type=\"saturate\" values=\"2\" result=\"saturated\"/>`\n  svg += `<feMerge><feMergeNode in=\"saturated\"/><feMergeNode in=\"SourceGraphic\"/></feMerge>`\n  svg += `</filter>`\n\n  // Drop shadow filter (for tooltips, floating elements)\n  svg += `<filter id=\"chartts-shadow\">`\n  svg += `<feDropShadow dx=\"0\" dy=\"2\" stdDeviation=\"4\" flood-opacity=\"0.12\"/>`\n  svg += `</filter>`\n\n  return svg\n}\n","import type {\n  ChartData, ChartOptions, ChartInstance, ChartTypePlugin,\n  RenderNode, RenderContext, EventBus, PreparedData,\n} from '../types'\nimport { resolveOptions } from '../constants'\nimport { resolveTheme, watchScheme } from '../theme/engine'\nimport { createEventBus } from '../events/bus'\nimport { computeLayout } from '../layout/compute'\nimport { observeResize } from '../layout/responsive'\nimport { renderXAxis, renderYAxis, renderGrid } from '../axis/axis'\nimport { renderLegend } from '../legend/legend'\nimport { createLinearScale } from '../scales/linear'\nimport { createCategoricalScale } from '../scales/categorical'\nimport { group, defs, clipPathDef, rect } from '../render/tree'\nimport { createInteractionLayer } from '../interaction/interaction'\nimport { createZoomPan, type ZoomPanInstance } from '../interaction/zoom-pan'\nimport { createBrush, type BrushInstance } from '../interaction/brush'\nimport { createDebugPanel, type DebugPanel } from '../debug/debug'\nimport { renderEmptyState, renderLoadingState, renderErrorState } from '../render/states'\nimport { decimateData } from '../data/decimate'\nimport { resolveRendererType, createRendererManager } from './renderer-manager'\nimport { createStateManager } from './state-manager'\nimport { createExporter } from './exporter'\n\n/** Extended options for createChart (includes debug flag) */\ninterface CreateChartOptions extends ChartOptions {\n  debug?: boolean\n}\n\n/**\n * Create a chart instance.\n * This is the core factory — all convenience functions (Line, Bar) call this.\n */\nexport function createChart(\n  target: string | HTMLElement,\n  chartType: ChartTypePlugin,\n  data: ChartData,\n  options: CreateChartOptions = {},\n): ChartInstance {\n  const container = typeof target === 'string'\n    ? document.querySelector<HTMLElement>(target)\n    : target\n\n  if (!container) {\n    throw new Error(`[chartts] Target element not found: ${target}`)\n  }\n\n  // State\n  let currentData = data\n  let currentOptions = resolveOptions(options, data.series.length)\n  let currentTheme = resolveTheme(currentOptions.theme)\n  let width = currentOptions.width || container.clientWidth || 400\n  let height = currentOptions.height || container.clientHeight || 300\n  let lastCtx: RenderContext | null = null\n  let lastPrepared: PreparedData | null = null\n  let lastRenderedNodes: RenderNode[] = []\n\n  // Renderer subsystem\n  const rendererType = resolveRendererType(currentOptions.renderer, data)\n  const rm = createRendererManager({\n    container,\n    rendererType,\n    theme: currentTheme,\n    width,\n    height,\n    className: currentOptions.className,\n    ariaLabel: currentOptions.ariaLabel,\n  })\n\n  // State manager\n  const stateManager = createStateManager(() => render())\n\n  // Exporter\n  const exporter = createExporter({\n    getRoot: () => rm.root,\n    getWidth: () => width,\n    getHeight: () => height,\n    isCanvas: rm.useCanvas,\n  })\n\n  // Event bus\n  const bus: EventBus = createEventBus()\n\n  // Shared interaction state — coordinates between zoom-pan and interaction layer\n  const interactionState = { isPanning: false }\n\n  // Interaction layer\n  const interaction = createInteractionLayer(\n    chartType,\n    () => lastCtx!,\n    () => lastPrepared!,\n    bus,\n    currentOptions.tooltip,\n    currentTheme,\n    currentOptions.onClick,\n    currentOptions.onHover,\n    interactionState,\n    rm.useCanvas ? { renderer: rm.renderer, root: rm.root, getLastNodes: () => lastRenderedNodes } : undefined,\n  )\n  if (rm.useCanvas) {\n    interaction.attach(rm.root.element as unknown as SVGElement, container)\n  } else {\n    interaction.attach(rm.root.element as SVGElement, container)\n  }\n\n  // Zoom & Pan\n  let zoomPan: ZoomPanInstance | null = null\n  if (currentOptions.zoom || currentOptions.pan) {\n    const needs2DZoom = !!chartType.suppressAxes\n    zoomPan = createZoomPan(\n      {\n        x: true,\n        y: needs2DZoom,\n        wheel: currentOptions.zoom,\n        drag: currentOptions.pan,\n        pinch: currentOptions.zoom,\n        normalizedPan: !needs2DZoom,\n      },\n      () => {\n        render()\n        const state = zoomPan!.getState()\n        bus.emit('zoom:change', state)\n      },\n      interactionState,\n    )\n    zoomPan.attach(\n      rm.root.element as HTMLElement | SVGElement,\n      () => lastCtx!.area,\n      () => ({ xScale: lastCtx!.xScale, yScale: lastCtx!.yScale }),\n    )\n  }\n\n  // Brush selection\n  let brush: BrushInstance | null = null\n  if (currentOptions.brush) {\n    brush = createBrush(\n      {},\n      bus,\n      rm.root.element as HTMLElement | SVGElement,\n      () => lastCtx!.area,\n      () => lastCtx!.xScale,\n      () => lastPrepared!,\n      !!currentOptions.pan,\n    )\n  }\n\n  // Debug panel\n  let debug: DebugPanel | null = null\n  if (options.debug) {\n    debug = createDebugPanel()\n    debug.attach(container, rm.root.element as SVGElement)\n  }\n\n  // Auto-resize\n  const stopResize = currentOptions.width && currentOptions.height\n    ? () => {}\n    : observeResize(container, (w, h) => {\n        width = w\n        height = h\n        render()\n        bus.emit('resize', { width: w, height: h })\n      })\n\n  // Theme watch\n  const stopThemeWatch = currentOptions.theme === 'auto'\n    ? watchScheme(() => {\n        currentTheme = resolveTheme('auto')\n        rm.applyTheme(currentTheme)\n        render()\n      })\n    : () => {}\n\n  // Initial render\n  render()\n  requestAnimationFrame(() => {\n    rm.root.element.classList.add('chartts-skip-anim')\n  })\n\n  // -----------------------------------------------------------------------\n  function render(): void {\n    rm.updateViewport(width, height)\n\n    // Render state overlays (loading / error / empty)\n    if (stateManager.state === 'loading') {\n      rm.renderer.render(rm.root, renderLoadingState(width, height, currentTheme))\n      return\n    }\n    if (stateManager.state === 'error') {\n      rm.renderer.render(rm.root, renderErrorState(width, height, currentTheme, stateManager.message))\n      return\n    }\n\n    const hasRichGraphData = chartType.type === 'graph' &&\n      ((options as Record<string, unknown>).nodes || (options as Record<string, unknown>).edges)\n    const isEmpty = !hasRichGraphData && (\n      !currentData.series.length ||\n      currentData.series.every(s => s.values.length === 0)\n    )\n    if (stateManager.state === 'empty' || isEmpty) {\n      rm.renderer.render(rm.root, renderEmptyState(width, height, currentTheme, stateManager.message))\n      return\n    }\n\n    // Decimate large datasets before preparing\n    const decimateOpt = (options as Record<string, unknown>).decimate\n    const dataForRender = decimateOpt\n      ? decimateData(currentData, typeof decimateOpt === 'object' ? decimateOpt : { threshold: Math.max(width * 2, 500) })\n      : currentData\n\n    const prepared = chartType.prepareData(dataForRender, currentOptions)\n    lastPrepared = prepared\n\n    // Chart types that suppress axes/grid don't need axis margins\n    const suppressAxes = !!chartType.suppressAxes\n    const layoutOpts = suppressAxes\n      ? { ...currentOptions, xAxis: false, yAxis: false, xLabel: '', yLabel: '', legend: false as const, padding: [4, 4, 4, 4] as [number, number, number, number] }\n      : currentOptions\n    const { area } = computeLayout(width, height, layoutOpts, prepared)\n\n    // Use band mode for bar-like charts so bars don't overflow the chart area\n    const useBand = !!chartType.useBandScale\n    const xScale = createCategoricalScale({\n      categories: prepared.labels,\n      range: [area.x, area.x + area.width],\n      format: currentOptions.xFormat,\n      band: useBand,\n    })\n\n    const yScale = createLinearScale({\n      domain: [prepared.bounds.yMin, prepared.bounds.yMax],\n      range: [area.y + area.height, area.y],\n      nice: true,\n      format: currentOptions.yFormat,\n    })\n\n    // Apply zoom/pan state to scales\n    if (zoomPan) {\n      zoomPan.applyToScales(xScale, yScale, area)\n    }\n\n    const ctx: RenderContext = {\n      data: prepared,\n      options: currentOptions,\n      area,\n      xScale,\n      yScale,\n      theme: currentTheme,\n      zoomPan: zoomPan ? zoomPan.getState() : undefined,\n    }\n    lastCtx = ctx\n\n    const clipId = 'chartts-clip'\n    const nodes: RenderNode[] = []\n\n    nodes.push(defs([\n      clipPathDef(clipId, [rect(area.x, area.y, area.width, area.height)]),\n    ]))\n\n    if (!suppressAxes) {\n      nodes.push(renderGrid(xScale, yScale, area, currentOptions, currentTheme))\n      nodes.push(renderXAxis(xScale, area, currentOptions, currentTheme))\n      nodes.push(renderYAxis(yScale, area, currentOptions, currentTheme))\n    }\n\n    const chartNodes = chartType.render(ctx)\n    nodes.push(group(chartNodes, { class: 'chartts-content', clipPath: clipId }))\n\n    if (!suppressAxes) {\n      const legend = renderLegend(prepared, area, currentOptions, currentTheme)\n      if (legend) nodes.push(legend)\n    }\n\n    lastRenderedNodes = nodes\n    rm.renderer.render(rm.root, nodes)\n\n    // SVG-only: inject effect gradient/filter defs\n    rm.injectEffectDefs(currentOptions.colors)\n\n    // Update debug panel\n    debug?.update(ctx, nodes)\n  }\n  // -----------------------------------------------------------------------\n\n  const instance: ChartInstance = {\n    setData(newData: ChartData): void {\n      const prev = currentData\n      currentData = newData\n      currentOptions = resolveOptions(options, newData.series.length)\n      stateManager.reset()\n      render()\n      bus.emit('data:change', { previous: prev, current: newData })\n    },\n\n    setOptions(newOpts: Partial<ChartOptions>): void {\n      Object.assign(options, newOpts)\n      currentOptions = resolveOptions(options, currentData.series.length)\n      currentTheme = resolveTheme(currentOptions.theme)\n      rm.applyTheme(currentTheme)\n      render()\n    },\n\n    getData() { return currentData },\n    getOptions() { return currentOptions },\n\n    setLoading(loading = true) { stateManager.setLoading(loading) },\n    setError(message?: string) { stateManager.setError(message) },\n    setEmpty(message?: string) { stateManager.setEmpty(message) },\n\n    toSVG: () => exporter.toSVG(),\n    toPNG: (opts) => exporter.toPNG(opts),\n    toClipboard: () => exporter.toClipboard(),\n\n    on(event, handler) {\n      return bus.on(event as never, handler as never)\n    },\n\n    resize(w: number, h: number): void {\n      width = w\n      height = h\n      render()\n    },\n\n    resetZoom(): void {\n      if (zoomPan) {\n        zoomPan.reset()\n        bus.emit('zoom:reset', undefined as never)\n      }\n    },\n\n    destroy(): void {\n      stopResize()\n      stopThemeWatch()\n      interaction.destroy()\n      zoomPan?.destroy()\n      brush?.destroy()\n      debug?.destroy()\n      bus.emit('destroy', undefined as never)\n      bus.destroy()\n      rm.destroy()\n    },\n\n    get element(): SVGElement | HTMLCanvasElement {\n      return rm.root.element as SVGElement | HTMLCanvasElement\n    },\n\n    get _bus(): EventBus {\n      return bus\n    },\n  }\n\n  return instance\n}\n","import type { ChartData, Renderer, RendererRoot, ThemeConfig } from '../types'\nimport { createSVGRenderer } from '../render/svg'\nimport { createCanvasRenderer } from '../render/canvas'\nimport { createWebGLRenderer } from '../render/webgl'\nimport { applyTheme } from '../theme/engine'\nimport { createEffectDefs } from '../render/effects'\n\n/**\n * Renderer subsystem — selection, root creation, theme application.\n * Extracted from createChart to keep the orchestrator lean.\n */\n\nexport type RendererType = 'svg' | 'canvas' | 'webgl'\n\nexport interface RendererManager {\n  readonly renderer: Renderer\n  readonly root: RendererRoot\n  readonly useCanvas: boolean\n  applyTheme(theme: ThemeConfig): void\n  updateViewport(width: number, height: number): void\n  injectEffectDefs(colors: string[]): void\n  destroy(): void\n}\n\n/**\n * Resolve renderer type from option string, auto-detecting based on data volume.\n */\nexport function resolveRendererType(renderer: string, data: ChartData): RendererType {\n  if (renderer === 'canvas' || renderer === 'webgl' || renderer === 'svg') return renderer\n  // 'auto' — choose based on data volume\n  const totalPoints = data.series.reduce((sum, s) => sum + s.values.length, 0)\n  return totalPoints > 100_000 ? 'webgl' : totalPoints > 5_000 ? 'canvas' : 'svg'\n}\n\nexport function createRendererManager(config: {\n  container: HTMLElement\n  rendererType: RendererType\n  theme: ThemeConfig\n  width: number\n  height: number\n  className: string\n  ariaLabel: string\n}): RendererManager {\n  const { container, rendererType, className, ariaLabel } = config\n  const useCanvas = rendererType === 'canvas' || rendererType === 'webgl'\n\n  const renderer: Renderer = rendererType === 'webgl'\n    ? createWebGLRenderer(config.theme)\n    : rendererType === 'canvas'\n      ? createCanvasRenderer(() => config.theme)\n      : createSVGRenderer()\n\n  const root: RendererRoot = renderer.createRoot(container, config.width, config.height, {\n    class: `chartts ${className}`.trim(),\n    role: 'img',\n    ariaLabel,\n  })\n\n  if (!useCanvas) {\n    applyTheme(root.element, config.theme)\n  } else {\n    container.style.position = 'relative'\n    container.style.background = config.theme.background\n  }\n\n  return {\n    renderer,\n    root,\n    useCanvas,\n\n    applyTheme(theme: ThemeConfig) {\n      if (useCanvas) {\n        container.style.background = theme.background\n      } else {\n        applyTheme(root.element, theme)\n      }\n    },\n\n    updateViewport(width: number, height: number) {\n      if (useCanvas) {\n        const canvas = root.element as HTMLCanvasElement\n        const dpr = window.devicePixelRatio || 1\n        canvas.width = Math.round(width * dpr)\n        canvas.height = Math.round(height * dpr)\n        canvas.style.width = `${width}px`\n        canvas.style.height = `${height}px`\n        const ctx2d = canvas.getContext('2d')!\n        ctx2d.setTransform(dpr, 0, 0, dpr, 0, 0)\n      } else {\n        root.element.setAttribute('viewBox', `0 0 ${width} ${height}`)\n      }\n    },\n\n    injectEffectDefs(colors: string[]) {\n      if (useCanvas) return\n      const NS = 'http://www.w3.org/2000/svg'\n      let fxDefs = root.element.querySelector('defs.chartts-fx') as SVGElement\n      if (!fxDefs) {\n        fxDefs = document.createElementNS(NS, 'defs')\n        fxDefs.classList.add('chartts-fx')\n        root.element.insertBefore(fxDefs, root.element.firstChild)\n      }\n      fxDefs.innerHTML = createEffectDefs(colors)\n    },\n\n    destroy() {\n      renderer.destroy(root)\n    },\n  }\n}\n","/**\n * Chart state machine — manages loading/error/empty overlays.\n * Extracted from createChart to keep the orchestrator lean.\n */\n\nexport type ChartState = 'ready' | 'loading' | 'error' | 'empty'\n\nexport interface StateManager {\n  readonly state: ChartState\n  readonly message: string | undefined\n  setLoading(loading?: boolean): void\n  setError(message?: string): void\n  setEmpty(message?: string): void\n  reset(): void\n}\n\nexport function createStateManager(onRender: () => void): StateManager {\n  let state: ChartState = 'ready'\n  let message: string | undefined\n\n  return {\n    get state() { return state },\n    get message() { return message },\n\n    setLoading(loading = true) {\n      state = loading ? 'loading' : 'ready'\n      message = undefined\n      onRender()\n    },\n\n    setError(msg?: string) {\n      state = 'error'\n      message = msg\n      onRender()\n    },\n\n    setEmpty(msg?: string) {\n      state = 'empty'\n      message = msg\n      onRender()\n    },\n\n    reset() {\n      state = 'ready'\n      message = undefined\n    },\n  }\n}\n","import type { RendererRoot } from '../types'\n\n/**\n * Chart export subsystem — toSVG, toPNG, toClipboard.\n * Extracted from createChart to keep the orchestrator lean.\n */\n\nexport interface ExporterDeps {\n  getRoot: () => RendererRoot\n  getWidth: () => number\n  getHeight: () => number\n  isCanvas: boolean\n}\n\nexport interface Exporter {\n  toSVG(): string\n  toPNG(opts?: { scale?: number }): Promise<Blob>\n  toClipboard(): Promise<void>\n}\n\nexport function createExporter(deps: ExporterDeps): Exporter {\n  const { getRoot, getWidth, getHeight, isCanvas } = deps\n\n  function toSVG(): string {\n    if (isCanvas) throw new Error('[chartts] toSVG() is not available with canvas renderer')\n    return getRoot().element.outerHTML\n  }\n\n  async function toPNG(opts?: { scale?: number }): Promise<Blob> {\n    // Canvas renderer: export directly from the canvas\n    if (isCanvas) {\n      const canvas = getRoot().element as HTMLCanvasElement\n      return new Promise((resolve, reject) => {\n        canvas.toBlob((b) => b ? resolve(b) : reject(new Error('PNG export failed')), 'image/png')\n      })\n    }\n\n    // SVG renderer: rasterize via Image\n    const scale = opts?.scale ?? 2\n    const w = getWidth()\n    const h = getHeight()\n    const canvas = document.createElement('canvas')\n    canvas.width = w * scale\n    canvas.height = h * scale\n    const canvasCtx = canvas.getContext('2d')!\n    const svgStr = toSVG()\n    const blob = new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' })\n    const url = URL.createObjectURL(blob)\n    const img = new Image()\n    img.width = w * scale\n    img.height = h * scale\n\n    return new Promise((resolve, reject) => {\n      img.onload = () => {\n        canvasCtx.drawImage(img, 0, 0, w * scale, h * scale)\n        URL.revokeObjectURL(url)\n        canvas.toBlob((b) => b ? resolve(b) : reject(new Error('PNG export failed')), 'image/png')\n      }\n      img.onerror = reject\n      img.src = url\n    })\n  }\n\n  async function toClipboard(): Promise<void> {\n    const blob = await toPNG()\n    await navigator.clipboard.write([\n      new ClipboardItem({ 'image/png': blob }),\n    ])\n  }\n\n  return { toSVG, toPNG, toClipboard }\n}\n","/**\n * ResizeObserver wrapper for auto-resizing charts to fit their container.\n */\nexport function observeResize(\n  element: HTMLElement,\n  callback: (width: number, height: number) => void,\n): () => void {\n  if (typeof ResizeObserver === 'undefined') return () => {}\n\n  const observer = new ResizeObserver((entries) => {\n    const entry = entries[0]\n    if (!entry) return\n    const { width, height } = entry.contentRect\n    if (width > 0 && height > 0) {\n      callback(Math.floor(width), Math.floor(height))\n    }\n  })\n\n  observer.observe(element)\n  return () => observer.disconnect()\n}\n","import type { ChartData } from '../types'\n\nexport class CharttsError extends Error {\n  constructor(message: string) {\n    super(`[chartts] ${message}`)\n    this.name = 'CharttsError'\n  }\n}\n\nexport function validateData(data: ChartData): void {\n  if (!data) {\n    throw new CharttsError('No data provided. Pass { series: [{ name, values }] }')\n  }\n\n  if (!Array.isArray(data.series) || data.series.length === 0) {\n    throw new CharttsError('data.series must be a non-empty array.')\n  }\n\n  const len = data.series[0]!.values.length\n\n  for (let i = 0; i < data.series.length; i++) {\n    const s = data.series[i]!\n\n    if (!s.name || typeof s.name !== 'string') {\n      throw new CharttsError(`series[${i}].name must be a non-empty string.`)\n    }\n\n    if (!Array.isArray(s.values)) {\n      throw new CharttsError(`series[${i}] (\"${s.name}\").values must be an array.`)\n    }\n\n    if (s.values.length !== len) {\n      throw new CharttsError(\n        `Series length mismatch: \"${data.series[0]!.name}\" has ${len} values ` +\n        `but \"${s.name}\" has ${s.values.length}. All series must have equal length.`,\n      )\n    }\n\n    for (let j = 0; j < s.values.length; j++) {\n      const v = s.values[j]\n      // Allow NaN (used for missing data / indicator warmup periods)\n      if (typeof v !== 'number' || (!Number.isFinite(v) && !Number.isNaN(v))) {\n        throw new CharttsError(\n          `series[${i}] (\"${s.name}\").values[${j}] must be a finite number (or NaN for missing data). ` +\n          `Got: ${JSON.stringify(v)}`,\n        )\n      }\n    }\n  }\n\n  if (data.labels && data.labels.length > 0 && data.labels.length !== len) {\n    throw new CharttsError(\n      `labels has ${data.labels.length} entries but series have ${len} values. They must match.`,\n    )\n  }\n}\n","import type { ChartData, PreparedData, PreparedSeries, DataBounds, ResolvedOptions } from '../types'\nimport { validateData } from './validate'\n\n/**\n * Validate, normalize, and compute bounds for chart data.\n * This is the single entry point for data preparation.\n */\nexport function prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n  validateData(data)\n\n  const count = data.series[0]!.values.length\n  const labels = data.labels ?? Array.from({ length: count }, (_, i) => i)\n\n  const series: PreparedSeries[] = data.series.map((s, i) => ({\n    name: s.name,\n    values: s.values,\n    color: s.color ?? options.colors[i % options.colors.length]!,\n    style: s.style ?? 'solid',\n    fill: s.fill ?? false,\n    fillOpacity: s.fillOpacity ?? 0.15,\n    showPoints: s.showPoints ?? true,\n    index: i,\n  }))\n\n  const bounds = computeBounds(series, options)\n\n  return { labels, series, bounds }\n}\n\nfunction computeBounds(series: PreparedSeries[], options: ResolvedOptions): DataBounds {\n  let yMin = Infinity\n  let yMax = -Infinity\n\n  for (const s of series) {\n    for (const v of s.values) {\n      if (isNaN(v)) continue // skip NaN (missing data / indicator warmup)\n      if (v < yMin) yMin = v\n      if (v > yMax) yMax = v\n    }\n  }\n\n  // Handle edge case: all values identical\n  if (yMin === yMax) {\n    yMin = yMin === 0 ? 0 : yMin - Math.abs(yMin) * 0.1\n    yMax = yMax === 0 ? 1 : yMax + Math.abs(yMax) * 0.1\n  }\n\n  // Apply forced bounds\n  if (options.yMin !== undefined) yMin = options.yMin\n  if (options.yMax !== undefined) yMax = options.yMax\n\n  const count = series[0]?.values.length ?? 0\n\n  return {\n    xMin: 0,\n    xMax: Math.max(0, count - 1),\n    yMin,\n    yMax,\n  }\n}\n","import type {\n  ChartTypePlugin, ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult, ScaleType,\n} from '../types'\nimport { prepareData } from '../data/prepare'\n\n/**\n * Define a chart type with sensible defaults.\n *\n * Only `type` and `render` are required. Everything else has defaults:\n * - getScaleTypes: categorical x, linear y\n * - prepareData: standard data preparation\n * - hitTest: returns null (no interaction)\n */\nexport function defineChartType(\n  config: {\n    type: string\n    suppressAxes?: boolean\n    useBandScale?: boolean\n    getScaleTypes?: () => { x: ScaleType; y: ScaleType }\n    prepareData?: (data: ChartData, options: ResolvedOptions) => PreparedData\n    render: (ctx: RenderContext) => RenderNode[]\n    hitTest?: (ctx: RenderContext, x: number, y: number) => HitResult | null\n    getHighlightNodes?: (ctx: RenderContext, hit: HitResult) => RenderNode[]\n  },\n): ChartTypePlugin {\n  return {\n    type: config.type,\n    suppressAxes: config.suppressAxes,\n    useBandScale: config.useBandScale,\n    getScaleTypes: config.getScaleTypes ?? (() => ({ x: 'categorical' as ScaleType, y: 'linear' as ScaleType })),\n    prepareData: config.prepareData ?? ((data, options) => prepareData(data, options)),\n    render: config.render,\n    hitTest: config.hitTest ?? (() => null),\n    getHighlightNodes: config.getHighlightNodes,\n  }\n}\n","import type {\n  ChartData, ChartOptions, ChartTypePlugin,\n  RenderNode, RenderContext, RenderAttrs,\n} from '../types'\nimport { CHART_CSS } from '../styles/chart'\nimport { createEffectDefs } from './effects'\nimport { resolveOptions } from '../constants'\nimport { resolveTheme } from '../theme/engine'\nimport { computeLayout } from '../layout/compute'\nimport { renderXAxis, renderYAxis, renderGrid } from '../axis/axis'\nimport { renderLegend } from '../legend/legend'\nimport { createLinearScale } from '../scales/linear'\nimport { createCategoricalScale } from '../scales/categorical'\nimport { group, defs, clipPathDef, rect } from './tree'\n\n/**\n * Render a chart to an SVG string. No DOM required — works in Node.js / SSR.\n *\n * @example\n * ```ts\n * import { renderToString, lineChartType } from '@chartts/core'\n *\n * const svg = renderToString(lineChartType, {\n *   labels: ['Jan', 'Feb', 'Mar'],\n *   series: [{ name: 'Sales', values: [10, 20, 15] }],\n * }, { width: 600, height: 400 })\n *\n * // svg is a full <svg>...</svg> string\n * ```\n */\nexport function renderToString(\n  chartType: ChartTypePlugin,\n  data: ChartData,\n  options: ChartOptions & { width?: number; height?: number } = {},\n): string {\n  const width = options.width ?? 600\n  const height = options.height ?? 400\n  const resolved = resolveOptions({ ...options, width, height }, data.series.length)\n  const theme = resolveTheme(resolved.theme)\n  const prepared = chartType.prepareData(data, resolved)\n\n  // Chart types that suppress axes don't need axis margins\n  const suppressAxes = !!chartType.suppressAxes\n  const layoutOpts = suppressAxes\n    ? { ...resolved, xAxis: false, yAxis: false, xLabel: '', yLabel: '', legend: false as const, padding: [4, 4, 4, 4] as [number, number, number, number] }\n    : resolved\n  const { area } = computeLayout(width, height, layoutOpts, prepared)\n\n  const useBand = !!chartType.useBandScale\n  const xScale = createCategoricalScale({\n    categories: prepared.labels,\n    range: [area.x, area.x + area.width],\n    format: resolved.xFormat,\n    band: useBand,\n  })\n\n  const yScale = createLinearScale({\n    domain: [prepared.bounds.yMin, prepared.bounds.yMax],\n    range: [area.y + area.height, area.y],\n    nice: true,\n    format: resolved.yFormat,\n  })\n\n  const ctx: RenderContext = { data: prepared, options: resolved, area, xScale, yScale, theme }\n\n  const clipId = 'chartts-clip'\n  const nodes: RenderNode[] = []\n\n  nodes.push(defs([\n    clipPathDef(clipId, [rect(area.x, area.y, area.width, area.height)]),\n  ]))\n  if (!suppressAxes) {\n    nodes.push(renderGrid(xScale, yScale, area, resolved, theme))\n    nodes.push(renderXAxis(xScale, area, resolved, theme))\n    nodes.push(renderYAxis(yScale, area, resolved, theme))\n  }\n\n  const chartNodes = chartType.render(ctx)\n  nodes.push(group(chartNodes, { class: 'chartts-content', clipPath: clipId }))\n\n  if (!suppressAxes) {\n    const legend = renderLegend(prepared, area, resolved, theme)\n    if (legend) nodes.push(legend)\n  }\n\n  const childrenStr = nodes.map(nodeToString).join('')\n  const styleStr = `<style>${CHART_CSS}</style>`\n  const fxDefsStr = `<defs class=\"chartts-fx\">${createEffectDefs(resolved.colors)}</defs>`\n\n  return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\" preserveAspectRatio=\"xMidYMid meet\" role=\"img\" aria-label=\"${escapeAttr(resolved.ariaLabel)}\" class=\"chartts\">${styleStr}${fxDefsStr}${childrenStr}</svg>`\n}\n\n// ---------------------------------------------------------------------------\n// Node serialization\n// ---------------------------------------------------------------------------\n\nfunction nodeToString(node: RenderNode): string {\n  switch (node.type) {\n    case 'group': {\n      const attrs = renderAttrs(node.attrs)\n      const children = node.children.map(nodeToString).join('')\n      return `<g${attrs}>${children}</g>`\n    }\n\n    case 'path': {\n      const attrs = renderAttrs(node.attrs)\n      const fill = node.attrs?.fill ? '' : ' fill=\"none\"'\n      return `<path d=\"${escapeAttr(node.d)}\"${fill}${attrs}/>`\n    }\n\n    case 'rect': {\n      const attrs = renderAttrs(node.attrs)\n      const rx = node.rx != null ? ` rx=\"${node.rx}\"` : ''\n      const ry = node.ry != null ? ` ry=\"${node.ry}\"` : ''\n      return `<rect x=\"${node.x}\" y=\"${node.y}\" width=\"${node.width}\" height=\"${node.height}\"${rx}${ry}${attrs}/>`\n    }\n\n    case 'circle': {\n      const attrs = renderAttrs(node.attrs)\n      return `<circle cx=\"${node.cx}\" cy=\"${node.cy}\" r=\"${node.r}\"${attrs}/>`\n    }\n\n    case 'line': {\n      const attrs = renderAttrs(node.attrs)\n      return `<line x1=\"${node.x1}\" y1=\"${node.y1}\" x2=\"${node.x2}\" y2=\"${node.y2}\"${attrs}/>`\n    }\n\n    case 'text': {\n      const a = node.attrs\n      let attrs = renderAttrs(a)\n      if (a) {\n        if ('textAnchor' in a && a.textAnchor) attrs += ` text-anchor=\"${a.textAnchor}\"`\n        if ('dominantBaseline' in a && a.dominantBaseline) attrs += ` dominant-baseline=\"${a.dominantBaseline}\"`\n        if ('fontSize' in a && a.fontSize) attrs += ` font-size=\"${a.fontSize}\"`\n        if ('fontFamily' in a && a.fontFamily) attrs += ` font-family=\"${escapeAttr(a.fontFamily as string)}\"`\n        if ('fontWeight' in a && a.fontWeight) attrs += ` font-weight=\"${a.fontWeight}\"`\n      }\n      return `<text x=\"${node.x}\" y=\"${node.y}\"${attrs}>${escapeXml(node.content)}</text>`\n    }\n\n    case 'clipPath': {\n      const children = node.children.map(nodeToString).join('')\n      return `<clipPath id=\"${escapeAttr(node.id)}\">${children}</clipPath>`\n    }\n\n    case 'defs': {\n      const children = node.children.map(nodeToString).join('')\n      return `<defs>${children}</defs>`\n    }\n  }\n}\n\nconst ATTR_MAP: Record<string, string> = {\n  class: 'class',\n  style: 'style',\n  stroke: 'stroke',\n  strokeWidth: 'stroke-width',\n  strokeDasharray: 'stroke-dasharray',\n  fill: 'fill',\n  fillOpacity: 'fill-opacity',\n  opacity: 'opacity',\n  transform: 'transform',\n  role: 'role',\n  ariaLabel: 'aria-label',\n  tabindex: 'tabindex',\n}\n\nconst SKIP_KEYS = new Set([\n  'textAnchor', 'dominantBaseline', 'fontSize', 'fontFamily', 'fontWeight', 'rx', 'ry',\n])\n\nfunction renderAttrs(attrs?: RenderAttrs): string {\n  if (!attrs) return ''\n  let result = ''\n\n  for (const [key, value] of Object.entries(attrs)) {\n    if (value == null) continue\n    if (SKIP_KEYS.has(key)) continue\n\n    if (key === 'clipPath') {\n      result += ` clip-path=\"url(#${escapeAttr(String(value))})\"`\n    } else if (key.startsWith('data-')) {\n      result += ` ${key}=\"${escapeAttr(String(value))}\"`\n    } else if (ATTR_MAP[key]) {\n      result += ` ${ATTR_MAP[key]}=\"${escapeAttr(String(value))}\"`\n    }\n  }\n\n  return result\n}\n\nfunction escapeAttr(s: string): string {\n  return s.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\n\nfunction escapeXml(s: string): string {\n  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\n","import type { ChartData, ResolvedOptions, PreparedData } from '../types'\nimport { prepareData } from '../data/prepare'\n\n/**\n * Prepare data with axes, grid, and legend suppressed.\n * Used by chart types that render their own layout (pie, gauge, treemap, etc.).\n */\nexport function prepareNoAxes(data: ChartData, options: ResolvedOptions): PreparedData {\n  return prepareData(data, {\n    ...options,\n    xAxis: false,\n    yAxis: false,\n    xGrid: false,\n    yGrid: false,\n    legend: false,\n  })\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\n\n/**\n * Voronoi chart — weighted tessellation where cell AREA is proportional to value.\n *\n * Uses a power diagram: the bisector between two seeds shifts toward the\n * lighter seed, giving heavier seeds (higher values) larger cells.\n * Labels are the cell names, series[0] values control cell size.\n */\nexport const voronoiChartType = defineChartType({\n  type: 'voronoi',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const n = series.values.length\n    const values = series.values\n    const minVal = Math.min(...values)\n    const maxVal = Math.max(...values)\n    const range = maxVal - minVal || 1\n\n    // Compute weights from values — higher value = higher weight = larger cell\n    const weights = values.map(v => ((v - minVal) / range))\n\n    // Distribute seed points using Fibonacci for even initial spacing\n    const seeds = fibonacciSeeds(n, area)\n\n    // Compute weighted Voronoi cells (power diagram)\n    const cells = computeWeightedVoronoi(seeds, weights, area)\n\n    const padding = 3\n\n    for (let i = 0; i < n; i++) {\n      const cell = cells[i]\n      if (!cell || cell.length < 3) continue\n\n      const t = weights[i]!\n      const label = String(data.labels[i] ?? `${i}`)\n      const color = options.colors[i % options.colors.length] ?? '#3b82f6'\n      const opacity = 0.25 + t * 0.65\n\n      // Shrink cell toward centroid for visual padding\n      const centroid = cell.reduce(\n        (acc, p) => ({ x: acc.x + p.x / cell.length, y: acc.y + p.y / cell.length }),\n        { x: 0, y: 0 },\n      )\n      const paddedCell = cell.map(p => {\n        const dx = p.x - centroid.x\n        const dy = p.y - centroid.y\n        const dist = Math.sqrt(dx * dx + dy * dy) || 1\n        const shrink = Math.min(padding / dist, 0.3)\n        return { x: p.x - dx * shrink, y: p.y - dy * shrink }\n      })\n\n      const d = paddedCell.map((p, j) => `${j === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ') + ' Z'\n\n      const cellNodes: RenderNode[] = []\n\n      cellNodes.push(path(d, {\n        class: 'chartts-voronoi-cell',\n        fill: color,\n        fillOpacity: opacity,\n        stroke: theme.background,\n        strokeWidth: 2,\n        style: `--chartts-i:${i}`,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label}: ${values[i]}`,\n      }))\n\n      // Label at centroid\n      if (n <= 20) {\n        const cellArea = polygonArea(paddedCell)\n        const minCellDim = Math.sqrt(cellArea)\n        const fontSize = Math.max(8, Math.min(theme.fontSize, minCellDim * 0.2))\n\n        cellNodes.push(text(centroid.x, centroid.y - fontSize * 0.4, label, {\n          class: 'chartts-voronoi-label',\n          fill: theme.textColor,\n          textAnchor: 'middle',\n          dominantBaseline: 'auto',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n          pointerEvents: 'none',\n        }))\n\n        // Value below label\n        if (minCellDim > 40) {\n          cellNodes.push(text(centroid.x, centroid.y + fontSize * 0.7, String(values[i]), {\n            class: 'chartts-voronoi-value',\n            fill: theme.textMuted,\n            textAnchor: 'middle',\n            dominantBaseline: 'auto',\n            fontSize: fontSize * 0.8,\n            fontFamily: theme.fontFamily,\n            pointerEvents: 'none',\n          }))\n        }\n      }\n\n      nodes.push(group(cellNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': label,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const values = series.values\n    const minVal = Math.min(...values)\n    const maxVal = Math.max(...values)\n    const range = maxVal - minVal || 1\n    const weights = values.map(v => ((v - minVal) / range))\n\n    const seeds = fibonacciSeeds(values.length, area)\n    const cells = computeWeightedVoronoi(seeds, weights, area)\n\n    // Point-in-polygon test on each cell\n    for (let i = 0; i < cells.length; i++) {\n      const cell = cells[i]\n      if (!cell || cell.length < 3) continue\n      if (pointInPolygon(mx, my, cell)) {\n        const centroid = cell.reduce(\n          (acc, p) => ({ x: acc.x + p.x / cell.length, y: acc.y + p.y / cell.length }),\n          { x: 0, y: 0 },\n        )\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: centroid.x, y: centroid.y }\n      }\n    }\n\n    return null\n  },\n})\n\ninterface Pt { x: number; y: number }\n\n/** Ray-casting point-in-polygon test. */\nfunction pointInPolygon(px: number, py: number, poly: Pt[]): boolean {\n  let inside = false\n  for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n    const a = poly[i]!, b = poly[j]!\n    if ((a.y > py) !== (b.y > py) &&\n        px < (b.x - a.x) * (py - a.y) / (b.y - a.y) + a.x) {\n      inside = !inside\n    }\n  }\n  return inside\n}\n\n/** Scale factor for weights based on chart area. */\nfunction weightScale(area: { width: number; height: number }): number {\n  return (area.width * area.height) * 0.15\n}\n\n/** Fibonacci/sunflower seed distribution for even spacing. */\nfunction fibonacciSeeds(n: number, area: { x: number; y: number; width: number; height: number }): Pt[] {\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n  const maxR = Math.min(area.width, area.height) * 0.45\n  const golden = (1 + Math.sqrt(5)) / 2\n  const pts: Pt[] = []\n\n  for (let i = 0; i < n; i++) {\n    const r = maxR * Math.sqrt((i + 0.5) / n)\n    const theta = 2 * Math.PI * i / (golden * golden)\n    pts.push({\n      x: cx + r * Math.cos(theta) * (area.width / Math.min(area.width, area.height)),\n      y: cy + r * Math.sin(theta) * (area.height / Math.min(area.width, area.height)),\n    })\n  }\n\n  return pts\n}\n\n/**\n * Compute weighted Voronoi cells (power diagram).\n *\n * Instead of clipping at the perpendicular bisector (equidistant line),\n * we shift the bisector toward the lighter seed. For seeds i and j with\n * weights wi and wj, the dividing plane shifts along the i→j axis by:\n *   shift = (wi - wj) * scale / (2 * |si - sj|)\n * This gives heavier seeds proportionally larger cells.\n */\nfunction computeWeightedVoronoi(\n  seeds: Pt[],\n  weights: number[],\n  area: { x: number; y: number; width: number; height: number },\n): Pt[][] {\n  const cells: Pt[][] = []\n  const { x: ax, y: ay, width: aw, height: ah } = area\n  const wScale = weightScale(area)\n\n  for (let i = 0; i < seeds.length; i++) {\n    let polygon: Pt[] = [\n      { x: ax, y: ay },\n      { x: ax + aw, y: ay },\n      { x: ax + aw, y: ay + ah },\n      { x: ax, y: ay + ah },\n    ]\n\n    const si = seeds[i]!\n    const wi = weights[i]!\n\n    for (let j = 0; j < seeds.length; j++) {\n      if (i === j) continue\n      const sj = seeds[j]!\n      const wj = weights[j]!\n\n      // Direction from j to i\n      const dx = si.x - sj.x\n      const dy = si.y - sj.y\n      const len2 = dx * dx + dy * dy\n      if (len2 === 0) continue\n      const len = Math.sqrt(len2)\n\n      // Shift bisector toward the lighter seed\n      // Positive shift = toward sj = seed i gets more area\n      const shift = (wi - wj) * wScale / (2 * len2)\n\n      // Shifted midpoint\n      const mx = (si.x + sj.x) / 2 + dx * shift\n      const my = (si.y + sj.y) / 2 + dy * shift\n\n      // Normal pointing toward seed i\n      const nx = dx / len\n      const ny = dy / len\n\n      polygon = clipPolygon(polygon, mx, my, nx, ny)\n      if (polygon.length < 3) break\n    }\n\n    cells.push(polygon)\n  }\n\n  return cells\n}\n\n/** Approximate polygon area via shoelace formula. */\nfunction polygonArea(pts: Pt[]): number {\n  let area = 0\n  for (let i = 0; i < pts.length; i++) {\n    const a = pts[i]!\n    const b = pts[(i + 1) % pts.length]!\n    area += a.x * b.y - b.x * a.y\n  }\n  return Math.abs(area) / 2\n}\n\n/** Sutherland-Hodgman clip: keep the side where dot(p - m, n) >= 0. */\nfunction clipPolygon(poly: Pt[], mx: number, my: number, nx: number, ny: number): Pt[] {\n  if (poly.length < 3) return poly\n  const out: Pt[] = []\n\n  for (let i = 0; i < poly.length; i++) {\n    const a = poly[i]!\n    const b = poly[(i + 1) % poly.length]!\n    const da = (a.x - mx) * nx + (a.y - my) * ny\n    const db = (b.x - mx) * nx + (b.y - my) * ny\n\n    if (da >= 0) out.push(a)\n    if ((da >= 0) !== (db >= 0)) {\n      const t = da / (da - db)\n      out.push({ x: a.x + t * (b.x - a.x), y: a.y + t * (b.y - a.y) })\n    }\n  }\n\n  return out\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { text } from '../../render/tree'\n\n/**\n * Word Cloud chart — words sized proportional to their value.\n *\n * Labels are the words, series[0] values control font size.\n * Uses Archimedean spiral placement with bounding-box collision detection.\n */\nexport const wordcloudChartType = defineChartType({\n  type: 'wordcloud',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const values = series.values\n    const maxVal = Math.max(...values.map(Math.abs))\n    const minVal = Math.min(...values.filter(v => v > 0))\n    const valRange = maxVal - minVal || 1\n\n    // Map values to font sizes\n    const minFont = Math.max(10, area.height * 0.03)\n    const maxFont = Math.min(area.height * 0.15, area.width * 0.08)\n\n    const items = values\n      .map((v, i) => ({\n        index: i,\n        label: String(data.labels[i] ?? ''),\n        value: Math.abs(v),\n        fontSize: minFont + ((Math.abs(v) - minVal) / valRange) * (maxFont - minFont),\n      }))\n      .filter(d => d.value > 0 && d.label.length > 0)\n      .sort((a, b) => b.value - a.value)\n\n    if (items.length === 0) return nodes\n\n    // Place words using Archimedean spiral\n    const placed = placeWords(items, area)\n\n    for (let idx = 0; idx < placed.length; idx++) {\n      const pw = placed[idx]!\n      const color = options.colors[pw.index % options.colors.length]!\n      const opacity = 0.5 + (pw.value - minVal) / valRange * 0.5\n\n      nodes.push(text(pw.x, pw.y, pw.label, {\n        class: 'chartts-wordcloud-word',\n        fill: color,\n        fillOpacity: opacity,\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize: pw.fontSize,\n        fontFamily: theme.fontFamily,\n        fontWeight: pw.fontSize > (minFont + maxFont) / 2 ? 700 : 500,\n        style: `--chartts-i:${idx}`,\n        'data-series': 0,\n        'data-index': pw.index,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${pw.label}: ${pw.value}`,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const values = series.values\n    const maxVal = Math.max(...values.map(Math.abs))\n    const minVal = Math.min(...values.filter(v => v > 0))\n    const valRange = maxVal - minVal || 1\n    const minFont = Math.max(10, area.height * 0.03)\n    const maxFont = Math.min(area.height * 0.15, area.width * 0.08)\n\n    const items = values\n      .map((v, i) => ({\n        index: i,\n        label: String(data.labels[i] ?? ''),\n        value: Math.abs(v),\n        fontSize: minFont + ((Math.abs(v) - minVal) / valRange) * (maxFont - minFont),\n      }))\n      .filter(d => d.value > 0 && d.label.length > 0)\n      .sort((a, b) => b.value - a.value)\n\n    const placed = placeWords(items, area)\n\n    // Check bounding boxes (smallest first for specificity)\n    for (let i = placed.length - 1; i >= 0; i--) {\n      const pw = placed[i]!\n      const halfW = pw.label.length * pw.fontSize * 0.35\n      const halfH = pw.fontSize * 0.6\n\n      if (mx >= pw.x - halfW && mx <= pw.x + halfW &&\n          my >= pw.y - halfH && my <= pw.y + halfH) {\n        return { seriesIndex: 0, pointIndex: pw.index, distance: 0, x: pw.x, y: pw.y }\n      }\n    }\n\n    return null\n  },\n})\n\ninterface WordItem {\n  index: number\n  label: string\n  value: number\n  fontSize: number\n}\n\ninterface PlacedWord extends WordItem {\n  x: number\n  y: number\n}\n\ninterface BBox {\n  x1: number; y1: number; x2: number; y2: number\n}\n\nfunction placeWords(\n  items: WordItem[],\n  area: { x: number; y: number; width: number; height: number },\n): PlacedWord[] {\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n  const placed: PlacedWord[] = []\n  const boxes: BBox[] = []\n\n  for (const item of items) {\n    // Approximate word bbox dimensions\n    const halfW = item.label.length * item.fontSize * 0.35\n    const halfH = item.fontSize * 0.6\n\n    // Archimedean spiral search\n    let found = false\n    for (let t = 0; t < 600; t++) {\n      const angle = t * 0.15\n      const r = 2 * angle\n      const x = cx + r * Math.cos(angle) * (area.width / area.height)\n      const y = cy + r * Math.sin(angle)\n\n      // Check bounds\n      if (x - halfW < area.x || x + halfW > area.x + area.width ||\n          y - halfH < area.y || y + halfH > area.y + area.height) {\n        continue\n      }\n\n      // Check overlap with placed words\n      const newBox: BBox = { x1: x - halfW, y1: y - halfH, x2: x + halfW, y2: y + halfH }\n      let overlaps = false\n\n      for (const box of boxes) {\n        if (newBox.x1 < box.x2 && newBox.x2 > box.x1 &&\n            newBox.y1 < box.y2 && newBox.y2 > box.y1) {\n          overlaps = true\n          break\n        }\n      }\n\n      if (!overlaps) {\n        placed.push({ ...item, x, y })\n        boxes.push(newBox)\n        found = true\n        break\n      }\n    }\n\n    // Skip words that don't fit\n    if (!found) continue\n  }\n\n  return placed\n}\n","/**\n * Pillar chart — stacked rounded-rectangle bars.\n * Each data value = one segment. Width proportional to value.\n * Symmetric rounded rectangles stacked along an axis.\n */\n\nimport type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, text } from '../../render/tree'\n\nexport interface PillarOptions extends ResolvedOptions {\n  /** Scale for ring width. Default 1. */\n  intensity?: number\n  /** Show value labels. Default true. */\n  showLabels?: boolean\n  /** Orientation: 'vertical' (default) or 'horizontal'. */\n  orientation?: 'vertical' | 'horizontal'\n}\n\nexport const pillarChartType = defineChartType({\n  type: 'pillar',\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const opts = options as PillarOptions\n    const intensity = opts.intensity ?? 1\n    const showLabels = opts.showLabels ?? true\n    const horizontal = opts.orientation === 'horizontal'\n\n    const values = series.values\n    const numRings = values.length\n    let maxVal = 0\n    for (const v of values) if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    if (maxVal === 0) maxVal = 1\n\n    const gap = 3\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n\n    if (horizontal) {\n      // Rings stacked left to right, width = data value, height = ring thickness\n      const totalW = area.width * 0.9\n      const ringW = (totalW - gap * (numRings - 1)) / numRings\n      const maxH = area.height * 0.85 * intensity\n      const startX = cx - totalW / 2\n\n      for (let i = 0; i < numRings; i++) {\n        const norm = Math.abs(values[i]!) / maxVal\n        const h = maxH * (0.15 + norm * 0.85)\n        const x = startX + i * (ringW + gap)\n        const y = cy - h / 2\n        const color = options.colors[i % options.colors.length]!\n        const colorIndex = i % options.colors.length\n        const r = Math.min(ringW * 0.25, h * 0.15, 8)\n\n        const segNodes: RenderNode[] = []\n        segNodes.push(rect(x, y, ringW, h, {\n          fill: `url(#chartts-bar-${colorIndex})`,\n          stroke: color,\n          strokeWidth: 1,\n          rx: r, ry: r,\n          opacity: 0.92,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? `Ring ${i + 1}`}: ${values[i]}`,\n        }))\n\n        if (showLabels) {\n          const label = data.labels[i] != null ? String(data.labels[i]) : ''\n          const valStr = label ? `${label}\\n${values[i]}` : String(values[i])\n          segNodes.push(text(x + ringW / 2, cy, valStr, {\n            fill: theme.textColor,\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: theme.fontSize - 1,\n            fontFamily: theme.fontFamily,\n            fontWeight: 600,\n          }))\n        }\n\n        nodes.push(group(segNodes, {\n          class: `chartts-series chartts-series-${i}`,\n          'data-series-name': String(data.labels[i] ?? `Ring ${i + 1}`),\n        }))\n      }\n    } else {\n      // Vertical: rings stacked top to bottom, height = ring thickness, width = data value\n      const totalH = area.height * 0.9\n      const ringH = (totalH - gap * (numRings - 1)) / numRings\n      const maxW = area.width * 0.85 * intensity\n      const startY = cy - totalH / 2\n\n      for (let i = 0; i < numRings; i++) {\n        const norm = Math.abs(values[i]!) / maxVal\n        const w = maxW * (0.15 + norm * 0.85)\n        const x = cx - w / 2\n        const y = startY + i * (ringH + gap)\n        const color = options.colors[i % options.colors.length]!\n        const colorIndex = i % options.colors.length\n        const r = Math.min(w * 0.08, ringH * 0.25, 8)\n\n        const segNodes: RenderNode[] = []\n        segNodes.push(rect(x, y, w, ringH, {\n          fill: `url(#chartts-bar-${colorIndex})`,\n          stroke: color,\n          strokeWidth: 1,\n          rx: r, ry: r,\n          opacity: 0.92,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? `Ring ${i + 1}`}: ${values[i]}`,\n        }))\n\n        if (showLabels) {\n          const label = data.labels[i] != null ? String(data.labels[i]) : ''\n          const valStr = label ? `${label}: ${values[i]}` : String(values[i])\n          segNodes.push(text(cx, y + ringH / 2, valStr, {\n            fill: theme.textColor,\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: theme.fontSize - 1,\n            fontFamily: theme.fontFamily,\n            fontWeight: 600,\n          }))\n        }\n\n        nodes.push(group(segNodes, {\n          class: `chartts-series chartts-series-${i}`,\n          'data-series-name': String(data.labels[i] ?? `Ring ${i + 1}`),\n        }))\n      }\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const opts = options as PillarOptions\n    const horizontal = opts.orientation === 'horizontal'\n    const numRings = series.values.length\n    const gap = 3\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n\n    if (horizontal) {\n      const totalW = area.width * 0.9\n      const ringW = (totalW - gap * (numRings - 1)) / numRings\n      const startX = cx - totalW / 2\n      const idx = Math.floor((mx - startX) / (ringW + gap))\n      if (idx < 0 || idx >= numRings) return null\n      const ringCx = startX + idx * (ringW + gap) + ringW / 2\n      return { seriesIndex: 0, pointIndex: idx, distance: Math.abs(mx - ringCx), x: ringCx, y: cy }\n    } else {\n      const totalH = area.height * 0.9\n      const ringH = (totalH - gap * (numRings - 1)) / numRings\n      const startY = cy - totalH / 2\n      const idx = Math.floor((my - startY) / (ringH + gap))\n      if (idx < 0 || idx >= numRings) return null\n      const ringCy = startY + idx * (ringH + gap) + ringH / 2\n      return { seriesIndex: 0, pointIndex: idx, distance: Math.abs(my - ringCy), x: cx, y: ringCy }\n    }\n  },\n})\n","/**\n * Moving average indicators — SMA, EMA, WMA.\n * Pure functions, zero dependencies.\n */\n\n/**\n * Simple Moving Average.\n * O(n) using running sum. First (period-1) values are NaN.\n */\nexport function sma(values: number[], period: number): number[] {\n  const n = values.length\n  const out = new Array<number>(n)\n  if (period < 1 || period > n) { out.fill(NaN); return out }\n\n  let sum = 0\n  for (let i = 0; i < n; i++) {\n    sum += values[i]!\n    if (i < period - 1) {\n      out[i] = NaN\n    } else {\n      if (i >= period) sum -= values[i - period]!\n      out[i] = sum / period\n    }\n  }\n  return out\n}\n\n/**\n * Exponential Moving Average.\n * Seeded with SMA of first `period` values. Smoothing k = 2/(period+1).\n * First (period-1) values are NaN. O(n).\n */\nexport function ema(values: number[], period: number): number[] {\n  const n = values.length\n  const out = new Array<number>(n)\n  if (period < 1 || period > n) { out.fill(NaN); return out }\n\n  const k = 2 / (period + 1)\n\n  // Seed: SMA of first `period` values\n  let sum = 0\n  for (let i = 0; i < period; i++) {\n    sum += values[i]!\n    out[i] = i < period - 1 ? NaN : sum / period\n  }\n\n  // EMA from period onward\n  let prev = out[period - 1]!\n  for (let i = period; i < n; i++) {\n    prev = values[i]! * k + prev * (1 - k)\n    out[i] = prev\n  }\n  return out\n}\n\n/**\n * Weighted Moving Average.\n * Weights increase linearly: [1, 2, ..., period].\n * First (period-1) values are NaN. O(n*period).\n */\nexport function wma(values: number[], period: number): number[] {\n  const n = values.length\n  const out = new Array<number>(n)\n  if (period < 1 || period > n) { out.fill(NaN); return out }\n\n  const denom = (period * (period + 1)) / 2\n\n  for (let i = 0; i < period - 1; i++) out[i] = NaN\n\n  for (let i = period - 1; i < n; i++) {\n    let wSum = 0\n    for (let j = 0; j < period; j++) {\n      wSum += values[i - period + 1 + j]! * (j + 1)\n    }\n    out[i] = wSum / denom\n  }\n  return out\n}\n","/**\n * Oscillator indicators — RSI, Stochastic.\n * Pure functions, zero dependencies.\n */\n\nimport type { StochasticResult } from './types'\n\n/**\n * Relative Strength Index (Wilder's smoothing).\n * Returns 0-100 scaled values. First `period` values are NaN.\n * Default period: 14. O(n).\n */\nexport function rsi(values: number[], period: number = 14): number[] {\n  const n = values.length\n  const out = new Array<number>(n).fill(NaN)\n  if (period < 1 || n < period + 1) return out\n\n  // Compute deltas\n  let gainSum = 0\n  let lossSum = 0\n  for (let i = 1; i <= period; i++) {\n    const delta = values[i]! - values[i - 1]!\n    if (delta > 0) gainSum += delta\n    else lossSum -= delta\n  }\n\n  let avgGain = gainSum / period\n  let avgLoss = lossSum / period\n\n  out[period] = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss)\n\n  // Wilder's smoothing for subsequent values\n  for (let i = period + 1; i < n; i++) {\n    const delta = values[i]! - values[i - 1]!\n    const gain = delta > 0 ? delta : 0\n    const loss = delta < 0 ? -delta : 0\n    avgGain = (avgGain * (period - 1) + gain) / period\n    avgLoss = (avgLoss * (period - 1) + loss) / period\n    out[i] = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss)\n  }\n  return out\n}\n\n/**\n * Stochastic Oscillator.\n * %K = 100 * (close - lowestLow) / (highestHigh - lowestLow) over kPeriod.\n * %D = SMA(%K, dPeriod).\n * Default: kPeriod=14, dPeriod=3.\n */\nexport function stochastic(\n  high: number[],\n  low: number[],\n  close: number[],\n  kPeriod: number = 14,\n  dPeriod: number = 3,\n): StochasticResult {\n  const n = close.length\n  const k = new Array<number>(n).fill(NaN)\n  const d = new Array<number>(n).fill(NaN)\n\n  // Compute %K\n  for (let i = kPeriod - 1; i < n; i++) {\n    let hh = -Infinity\n    let ll = Infinity\n    for (let j = i - kPeriod + 1; j <= i; j++) {\n      if (high[j]! > hh) hh = high[j]!\n      if (low[j]! < ll) ll = low[j]!\n    }\n    const range = hh - ll\n    k[i] = range === 0 ? 50 : 100 * (close[i]! - ll) / range\n  }\n\n  // Compute %D = SMA(%K, dPeriod)\n  const firstK = kPeriod - 1\n  for (let i = firstK + dPeriod - 1; i < n; i++) {\n    let sum = 0\n    for (let j = i - dPeriod + 1; j <= i; j++) sum += k[j]!\n    d[i] = sum / dPeriod\n  }\n\n  return { k, d }\n}\n","/**\n * MACD (Moving Average Convergence Divergence).\n * Depends on EMA from moving-averages.\n */\n\nimport { ema } from './moving-averages'\nimport type { MACDResult } from './types'\n\n/**\n * Compute MACD.\n * MACD line = EMA(fast) - EMA(slow).\n * Signal = EMA(MACD line, signalPeriod).\n * Histogram = MACD - Signal.\n * Default: fast=12, slow=26, signal=9.\n */\nexport function macd(\n  values: number[],\n  fastPeriod: number = 12,\n  slowPeriod: number = 26,\n  signalPeriod: number = 9,\n): MACDResult {\n  const n = values.length\n  const fastEma = ema(values, fastPeriod)\n  const slowEma = ema(values, slowPeriod)\n\n  // MACD line\n  const macdLine = new Array<number>(n)\n  for (let i = 0; i < n; i++) {\n    macdLine[i] = isNaN(fastEma[i]!) || isNaN(slowEma[i]!) ? NaN : fastEma[i]! - slowEma[i]!\n  }\n\n  // Signal line = EMA of MACD (skip NaN warmup)\n  // Find first non-NaN in macdLine\n  let firstValid = -1\n  for (let i = 0; i < n; i++) {\n    if (!isNaN(macdLine[i]!)) { firstValid = i; break }\n  }\n\n  const signalLine = new Array<number>(n).fill(NaN)\n  const histogram = new Array<number>(n).fill(NaN)\n\n  if (firstValid >= 0) {\n    const validSlice = macdLine.slice(firstValid)\n    const signalEma = ema(validSlice, signalPeriod)\n    for (let i = 0; i < validSlice.length; i++) {\n      signalLine[firstValid + i] = signalEma[i]!\n      if (!isNaN(macdLine[firstValid + i]!) && !isNaN(signalEma[i]!)) {\n        histogram[firstValid + i] = macdLine[firstValid + i]! - signalEma[i]!\n      }\n    }\n  }\n\n  return { macd: macdLine, signal: signalLine, histogram }\n}\n","/**\n * Bollinger Bands.\n * Depends on SMA from moving-averages.\n */\n\nimport { sma } from './moving-averages'\nimport type { BollingerResult } from './types'\n\n/**\n * Compute Bollinger Bands.\n * Middle = SMA(period). Upper = middle + k*stddev. Lower = middle - k*stddev.\n * Default: period=20, k=2.\n * First (period-1) values are NaN.\n */\nexport function bollingerBands(\n  values: number[],\n  period: number = 20,\n  k: number = 2,\n): BollingerResult {\n  const n = values.length\n  const middle = sma(values, period)\n  const upper = new Array<number>(n)\n  const lower = new Array<number>(n)\n\n  for (let i = 0; i < n; i++) {\n    if (isNaN(middle[i]!)) {\n      upper[i] = NaN\n      lower[i] = NaN\n      continue\n    }\n    // Rolling standard deviation\n    let sumSq = 0\n    const mean = middle[i]!\n    for (let j = i - period + 1; j <= i; j++) {\n      const diff = values[j]! - mean\n      sumSq += diff * diff\n    }\n    const std = Math.sqrt(sumSq / period)\n    upper[i] = mean + k * std\n    lower[i] = mean - k * std\n  }\n\n  return { upper, middle, lower }\n}\n","/**\n * Average True Range (ATR).\n * Pure function, zero dependencies.\n */\n\n/**\n * Average True Range using Wilder's smoothing.\n * True Range = max(high-low, |high-prevClose|, |low-prevClose|).\n * First `period` values are NaN. Default period: 14. O(n).\n */\nexport function atr(\n  high: number[],\n  low: number[],\n  close: number[],\n  period: number = 14,\n): number[] {\n  const n = high.length\n  const out = new Array<number>(n).fill(NaN)\n  if (period < 1 || n < period + 1) return out\n\n  // True Range array\n  const tr = new Array<number>(n)\n  tr[0] = high[0]! - low[0]!\n  for (let i = 1; i < n; i++) {\n    const hl = high[i]! - low[i]!\n    const hpc = Math.abs(high[i]! - close[i - 1]!)\n    const lpc = Math.abs(low[i]! - close[i - 1]!)\n    tr[i] = Math.max(hl, hpc, lpc)\n  }\n\n  // First ATR = simple average of first `period` TRs (starting from index 1)\n  let sum = 0\n  for (let i = 1; i <= period; i++) sum += tr[i]!\n  out[period] = sum / period\n\n  // Wilder's smoothing\n  let prev = out[period]!\n  for (let i = period + 1; i < n; i++) {\n    prev = (prev * (period - 1) + tr[i]!) / period\n    out[i] = prev\n  }\n  return out\n}\n","/**\n * Volume-based indicators — VWAP, OBV.\n * Pure functions, zero dependencies.\n */\n\n/**\n * Volume Weighted Average Price.\n * VWAP[i] = cumulative(price*volume) / cumulative(volume).\n * Full length output (no NaN padding). O(n).\n */\nexport function vwap(price: number[], volume: number[]): number[] {\n  const n = price.length\n  const out = new Array<number>(n)\n  let cumPV = 0\n  let cumV = 0\n  for (let i = 0; i < n; i++) {\n    cumPV += price[i]! * volume[i]!\n    cumV += volume[i]!\n    out[i] = cumV === 0 ? price[i]! : cumPV / cumV\n  }\n  return out\n}\n\n/**\n * On-Balance Volume.\n * Starts at 0. If close > prevClose, add volume. If close < prevClose, subtract.\n * Full length output. O(n).\n */\nexport function obv(close: number[], volume: number[]): number[] {\n  const n = close.length\n  const out = new Array<number>(n)\n  out[0] = 0\n  for (let i = 1; i < n; i++) {\n    if (close[i]! > close[i - 1]!) out[i] = out[i - 1]! + volume[i]!\n    else if (close[i]! < close[i - 1]!) out[i] = out[i - 1]! - volume[i]!\n    else out[i] = out[i - 1]!\n  }\n  return out\n}\n","/**\n * Portfolio & returns analytics.\n * Pure functions, zero dependencies.\n */\n\n/** Simple percentage returns. First value is NaN. */\nexport function simpleReturns(prices: number[]): number[] {\n  const n = prices.length\n  const out = new Array<number>(n)\n  out[0] = NaN\n  for (let i = 1; i < n; i++) {\n    out[i] = (prices[i]! - prices[i - 1]!) / prices[i - 1]!\n  }\n  return out\n}\n\n/** Log returns. First value is NaN. */\nexport function logReturns(prices: number[]): number[] {\n  const n = prices.length\n  const out = new Array<number>(n)\n  out[0] = NaN\n  for (let i = 1; i < n; i++) {\n    out[i] = Math.log(prices[i]! / prices[i - 1]!)\n  }\n  return out\n}\n\n/** Cumulative returns (growth from initial price). First value is 0. */\nexport function cumulativeReturns(prices: number[]): number[] {\n  const n = prices.length\n  const out = new Array<number>(n)\n  const p0 = prices[0]!\n  for (let i = 0; i < n; i++) {\n    out[i] = (prices[i]! - p0) / p0\n  }\n  return out\n}\n\n/** Drawdown at each point (always <= 0). */\nexport function drawdown(prices: number[]): number[] {\n  const n = prices.length\n  const out = new Array<number>(n)\n  let peak = -Infinity\n  for (let i = 0; i < n; i++) {\n    if (prices[i]! > peak) peak = prices[i]!\n    out[i] = (prices[i]! - peak) / peak\n  }\n  return out\n}\n\n/** Maximum drawdown (single number, deepest trough). Always <= 0. */\nexport function maxDrawdown(prices: number[]): number {\n  const dd = drawdown(prices)\n  let min = 0\n  for (const v of dd) if (v < min) min = v\n  return min\n}\n\n/**\n * Annualized Sharpe ratio.\n * sharpe = mean(excess) / std(excess) * sqrt(annualizationFactor).\n * Filters out NaN values from returns array.\n */\nexport function sharpeRatio(\n  returns: number[],\n  riskFreeRate: number = 0,\n  annualizationFactor: number = 252,\n): number {\n  const valid = returns.filter(v => !isNaN(v))\n  if (valid.length < 2) return NaN\n\n  const excess = valid.map(r => r - riskFreeRate / annualizationFactor)\n  const mean = excess.reduce((s, v) => s + v, 0) / excess.length\n  const variance = excess.reduce((s, v) => s + (v - mean) ** 2, 0) / (excess.length - 1)\n  const std = Math.sqrt(variance)\n  return std === 0 ? 0 : (mean / std) * Math.sqrt(annualizationFactor)\n}\n\n/**\n * Volatility (standard deviation of returns).\n * If rollingPeriod provided: returns number[] with NaN padding.\n * Otherwise returns single annualized number.\n */\nexport function volatility(\n  returns: number[],\n  rollingPeriod?: number,\n  annualizationFactor: number = 252,\n): number | number[] {\n  const valid = returns.filter(v => !isNaN(v))\n\n  if (rollingPeriod != null) {\n    const n = returns.length\n    const out = new Array<number>(n).fill(NaN)\n    for (let i = rollingPeriod - 1; i < n; i++) {\n      // Collect valid values in window\n      const window: number[] = []\n      for (let j = i - rollingPeriod + 1; j <= i; j++) {\n        if (!isNaN(returns[j]!)) window.push(returns[j]!)\n      }\n      if (window.length < 2) continue\n      const mean = window.reduce((s, v) => s + v, 0) / window.length\n      const variance = window.reduce((s, v) => s + (v - mean) ** 2, 0) / (window.length - 1)\n      out[i] = Math.sqrt(variance) * Math.sqrt(annualizationFactor)\n    }\n    return out\n  }\n\n  // Overall annualized volatility\n  if (valid.length < 2) return NaN\n  const mean = valid.reduce((s, v) => s + v, 0) / valid.length\n  const variance = valid.reduce((s, v) => s + (v - mean) ** 2, 0) / (valid.length - 1)\n  return Math.sqrt(variance) * Math.sqrt(annualizationFactor)\n}\n","/**\n * Financial data builders — bridge indicator output to chart data formats.\n */\n\nimport { bollingerBands } from './bollinger'\nimport { macd } from './macd'\nimport type { BollingerResult, MACDResult, OHLCAggregation } from './types'\n\n/**\n * Aggregate tick-level data into OHLC bars.\n * @param timestamps - epoch milliseconds\n * @param prices - price at each tick\n * @param interval - bar size in milliseconds\n * @param volumes - optional volume at each tick\n */\nexport function toOHLC(\n  timestamps: number[],\n  prices: number[],\n  interval: number,\n  volumes?: number[],\n): OHLCAggregation {\n  const buckets = new Map<number, { open: number; high: number; low: number; close: number; vol: number; ts: number }>()\n\n  for (let i = 0; i < timestamps.length; i++) {\n    const key = Math.floor(timestamps[i]! / interval) * interval\n    const p = prices[i]!\n    const v = volumes ? volumes[i]! : 0\n    const b = buckets.get(key)\n    if (b) {\n      if (p > b.high) b.high = p\n      if (p < b.low) b.low = p\n      b.close = p\n      b.vol += v\n    } else {\n      buckets.set(key, { open: p, high: p, low: p, close: p, vol: v, ts: key })\n    }\n  }\n\n  const sorted = [...buckets.values()].sort((a, b) => a.ts - b.ts)\n  const labels: string[] = []\n  const open: number[] = []\n  const high: number[] = []\n  const low: number[] = []\n  const close: number[] = []\n  const volume: number[] = []\n\n  for (const bar of sorted) {\n    const d = new Date(bar.ts)\n    labels.push(`${d.getMonth() + 1}/${d.getDate()}`)\n    open.push(bar.open)\n    high.push(bar.high)\n    low.push(bar.low)\n    close.push(bar.close)\n    volume.push(bar.vol)\n  }\n\n  return volumes\n    ? { labels, open, high, low, close, volume }\n    : { labels, open, high, low, close }\n}\n\n/**\n * Determine volume bar directions from consecutive close prices.\n * Returns 'up'|'down' array for Volume chart's `directions` option.\n */\nexport function volumeDirections(values: number[]): ('up' | 'down')[] {\n  return values.map((v, i) => i === 0 ? 'up' as const : (v >= values[i - 1]! ? 'up' as const : 'down' as const))\n}\n\n/**\n * Compute Bollinger Bands in Range chart format.\n * Output: { upper, lower, middle } — middle goes into series[0].values,\n * upper/lower into the range option.\n */\nexport function toBollingerData(\n  close: number[],\n  period: number = 20,\n  k: number = 2,\n): BollingerResult {\n  return bollingerBands(close, period, k)\n}\n\n/**\n * Compute MACD in Combo chart format.\n * series[0] = histogram (bars), series[1] = MACD line, series[2] = signal line.\n */\nexport function toMACDData(\n  close: number[],\n  fastPeriod: number = 12,\n  slowPeriod: number = 26,\n  signalPeriod: number = 9,\n): MACDResult {\n  return macd(close, fastPeriod, slowPeriod, signalPeriod)\n}\n","/**\n * Shared number formatting for SVG path data strings.\n * Outputs integers as-is, decimals with 2 decimal places.\n */\nexport function formatNum(v: number): string {\n  return Number.isInteger(v) ? String(v) : v.toFixed(2)\n}\n\n/**\n * Human-readable value formatter with SI suffixes.\n * 1500 → \"1.5K\", 2000000 → \"2M\", 3000000000 → \"3B\"\n */\nexport function formatValue(value: number): string {\n  const abs = Math.abs(value)\n  if (abs >= 1e12) return trimSuffix(value / 1e12, 'T')\n  if (abs >= 1e9) return trimSuffix(value / 1e9, 'B')\n  if (abs >= 1e6) return trimSuffix(value / 1e6, 'M')\n  if (abs >= 1e3) return trimSuffix(value / 1e3, 'K')\n  if (Number.isInteger(value)) return String(value)\n  return value.toFixed(1)\n}\n\n/**\n * Percentage formatter: 0.75 → \"75%\", 42 → \"42%\"\n * Values <= 1 are treated as ratios and multiplied by 100.\n */\nexport function formatPercent(value: number): string {\n  const v = Math.abs(value) <= 1 ? value * 100 : value\n  const s = v.toFixed(1)\n  return (s.endsWith('.0') ? s.slice(0, -2) : s) + '%'\n}\n\nfunction trimSuffix(v: number, suffix: string): string {\n  const s = v.toFixed(1)\n  return (s.endsWith('.0') ? s.slice(0, -2) : s) + suffix\n}\n","import { PathBuilder } from '../render/tree'\nimport { formatNum } from './format'\n\nexport type CurveInterpolation = 'linear' | 'monotone' | 'step'\nexport type Point = { x: number; y: number }\n\n/**\n * Split values into contiguous segments, breaking at NaN gaps.\n * Maps indices to pixel coordinates via xScale/yScale.\n */\nexport function segmentValues(\n  values: number[],\n  xScale: { map(v: number | string | Date): number },\n  yScale: { map(v: number | string | Date): number },\n): Point[][] {\n  const segments: Point[][] = []\n  let current: Point[] = []\n  for (let i = 0; i < values.length; i++) {\n    if (isNaN(values[i]!)) {\n      if (current.length > 0) { segments.push(current); current = [] }\n    } else {\n      current.push({ x: xScale.map(i), y: yScale.map(values[i]!) })\n    }\n  }\n  if (current.length > 0) segments.push(current)\n  return segments\n}\n\n/**\n * Build a line path string using specified interpolation, skipping NaN gaps.\n */\nexport function buildLinePath(\n  values: number[],\n  xScale: { map(v: number | string | Date): number },\n  yScale: { map(v: number | string | Date): number },\n  curve: CurveInterpolation,\n): string {\n  if (values.length === 0) return ''\n  const segments = segmentValues(values, xScale, yScale)\n  const builder = curveBuilder(curve)\n  return segments.map(s => builder(s)).join('')\n}\n\n/**\n * Build an area fill path (line path + close along x-axis), skipping NaN gaps.\n */\nexport function buildAreaPath(\n  values: number[],\n  xScale: { map(v: number | string | Date): number },\n  yScale: { map(v: number | string | Date): number },\n  area: { y: number; height: number },\n  curve: CurveInterpolation,\n): string {\n  if (values.length === 0) return ''\n  const baseline = area.y + area.height\n  const segments = segmentValues(values, xScale, yScale)\n  const builder = curveBuilder(curve)\n\n  return segments.map(pts => {\n    const linePart = builder(pts)\n    const first = pts[0]!\n    const last = pts[pts.length - 1]!\n    return `${linePart}L${formatNum(last.x)},${formatNum(baseline)}L${formatNum(first.x)},${formatNum(baseline)}Z`\n  }).join('')\n}\n\n/** Select a curve builder function by interpolation type. */\nfunction curveBuilder(curve: CurveInterpolation): (points: Point[]) => string {\n  if (curve === 'step') return buildStepPath\n  if (curve === 'monotone') return buildMonotonePath\n  return buildLinearPath\n}\n\nexport function buildLinearPath(points: Point[]): string {\n  if (points.length === 0) return ''\n  const pb = new PathBuilder()\n  pb.moveTo(points[0]!.x, points[0]!.y)\n  for (let i = 1; i < points.length; i++) {\n    pb.lineTo(points[i]!.x, points[i]!.y)\n  }\n  return pb.build()\n}\n\nexport function buildStepPath(points: Point[]): string {\n  if (points.length === 0) return ''\n  const pb = new PathBuilder()\n  pb.moveTo(points[0]!.x, points[0]!.y)\n  for (let i = 1; i < points.length; i++) {\n    const midX = (points[i - 1]!.x + points[i]!.x) / 2\n    pb.hTo(midX).vTo(points[i]!.y).hTo(points[i]!.x)\n  }\n  return pb.build()\n}\n\n/**\n * Monotone cubic interpolation (Fritsch-Carlson).\n * Produces smooth curves that never overshoot the data.\n */\nexport function buildMonotonePath(points: Point[]): string {\n  if (points.length < 2) return buildLinearPath(points)\n  if (points.length === 2) return buildLinearPath(points)\n\n  const n = points.length\n  const dx: number[] = []\n  const dy: number[] = []\n  const m: number[] = []\n\n  for (let i = 0; i < n - 1; i++) {\n    dx.push(points[i + 1]!.x - points[i]!.x)\n    dy.push(points[i + 1]!.y - points[i]!.y)\n    m.push(dy[i]! / (dx[i]! || 1))\n  }\n\n  const tangents: number[] = [m[0]!]\n  for (let i = 1; i < n - 1; i++) {\n    if (m[i - 1]! * m[i]! <= 0) {\n      tangents.push(0)\n    } else {\n      tangents.push((m[i - 1]! + m[i]!) / 2)\n    }\n  }\n  tangents.push(m[n - 2]!)\n\n  const pb = new PathBuilder()\n  pb.moveTo(points[0]!.x, points[0]!.y)\n\n  for (let i = 0; i < n - 1; i++) {\n    const d = dx[i]! / 3\n    pb.curveTo(\n      points[i]!.x + d,\n      points[i]!.y + tangents[i]! * d,\n      points[i + 1]!.x - d,\n      points[i + 1]!.y - tangents[i + 1]! * d,\n      points[i + 1]!.x,\n      points[i + 1]!.y,\n    )\n  }\n\n  return pb.build()\n}\n","import type { RenderContext, HitResult } from '../types'\n\n/**\n * Generic nearest-point hit test for point-based charts (line, scatter, etc.).\n * Iterates all series/points and finds the closest one within maxDistance.\n */\nexport function nearestPointHitTest(\n  ctx: RenderContext,\n  mx: number,\n  my: number,\n  maxDistance: number,\n): HitResult | null {\n  const { data, xScale, yScale } = ctx\n  let best: HitResult | null = null\n  let bestDist = Infinity\n\n  for (const series of data.series) {\n    for (let i = 0; i < series.values.length; i++) {\n      if (isNaN(series.values[i]!)) continue\n      const x = xScale.map(i)\n      const y = yScale.map(series.values[i]!)\n      const dist = Math.sqrt((mx - x) ** 2 + (my - y) ** 2)\n      if (dist < bestDist && dist < maxDistance) {\n        bestDist = dist\n        best = { seriesIndex: series.index, pointIndex: i, distance: dist, x, y }\n      }\n    }\n  }\n\n  return best\n}\n","import type {\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { CSS_PREFIX } from '../../constants'\nimport { group, path, circle } from '../../render/tree'\nimport { buildLinePath, buildAreaPath } from '../../utils/curves'\nimport { nearestPointHitTest } from '../../utils/hit-test'\n\nexport const lineChartType = defineChartType({\n  type: 'line',\n\n\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, area, xScale, yScale, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    for (const series of data.series) {\n      const seriesNodes: RenderNode[] = []\n\n      // Build line path\n      const linePath = buildLinePath(series.values, xScale, yScale, options.curve)\n\n      // Area fill (if enabled) — use gradient for premium look\n      if (series.fill) {\n        const areaPath = buildAreaPath(\n          series.values, xScale, yScale, area, options.curve,\n        )\n        seriesNodes.push(path(areaPath, {\n          class: 'chartts-area',\n          fill: `url(#chartts-area-${series.index})`,\n          'data-series': series.index,\n        }))\n      }\n\n      const dash = series.style === 'dashed' ? '6,4'\n        : series.style === 'dotted' ? '2,3' : undefined\n\n      // Main line\n      seriesNodes.push(path(linePath, {\n        class: 'chartts-line',\n        stroke: series.color,\n        strokeWidth: theme.lineWidth,\n        strokeDasharray: dash,\n        'data-series': series.index,\n      }))\n\n      // Data points with ambient glow\n      if (series.showPoints) {\n        for (let i = 0; i < series.values.length; i++) {\n          if (isNaN(series.values[i]!)) continue // skip missing data\n          const x = xScale.map(i)\n          const y = yScale.map(series.values[i]!)\n\n          // Ambient glow behind point\n          seriesNodes.push(circle(x, y, theme.pointRadius * 3, {\n            class: 'chartts-point-glow',\n            fill: `url(#chartts-pglow-${series.index})`,\n          }))\n\n          seriesNodes.push(circle(x, y, theme.pointRadius, {\n            class: 'chartts-point',\n            fill: series.color,\n            stroke: `var(${CSS_PREFIX}-bg, #fff)`,\n            strokeWidth: 2,\n            'data-series': series.index,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${series.values[i]}`,\n          }))\n        }\n      }\n\n      nodes.push(group(seriesNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    return nearestPointHitTest(ctx, mx, my, 30)\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { lineChartType } from '../line/line-type'\n\n/**\n * Step chart — line chart with stair-step interpolation.\n *\n * Delegates entirely to lineChartType after forcing curve:'step'.\n * Used for: interest rates, order books, discrete pricing tiers.\n */\nexport const stepChartType = defineChartType({\n  type: 'step',\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return lineChartType.prepareData(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    // Force step interpolation\n    const stepCtx = {\n      ...ctx,\n      options: { ...ctx.options, curve: 'step' as const },\n    }\n    return lineChartType.render(stepCtx)\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    return lineChartType.hitTest(ctx, mx, my)\n  },\n})\n","import type { Scale, ChartArea } from '../types'\n\n/** Safely get bandwidth from a scale. Returns 0 for scales without band mode. */\nexport function getBandwidth(scale: Scale): number {\n  return scale.bandwidth ? scale.bandwidth() : 0\n}\n\n/**\n * Create a horizontal value mapper — maps yScale values to x positions.\n * Used by horizontal-bar, dumbbell, and other horizontal layout charts.\n */\nexport function createHorizontalMapper(\n  yScale: Scale,\n  area: ChartArea,\n  chartX: number,\n  chartW: number,\n): (v: number) => number {\n  return (v: number) => {\n    const yPos = yScale.map(v)\n    const fraction = (yPos - area.y) / area.height\n    return chartX + chartW * (1 - fraction)\n  }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\nexport interface VolumeOptions extends ResolvedOptions {\n  /** Explicit direction per bar: 'up' or 'down'. Auto-detected if omitted. */\n  directions?: ('up' | 'down')[]\n  /** Up color (volume on up-price day). Default green. */\n  upColor?: string\n  /** Down color (volume on down-price day). Default red. */\n  downColor?: string\n  /** Gap between bars as fraction of bandwidth. Default 0.2. */\n  gap?: number\n}\n\n/**\n * Volume chart — vertical bars colored by price direction.\n *\n * Essential companion to candlestick/OHLC price charts.\n * Green bars = volume on up days, red bars = volume on down days.\n */\nexport const volumeChartType = defineChartType({\n  type: 'volume',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n    // Volume always starts at zero\n    if (prepared.bounds.yMin > 0) prepared.bounds.yMin = 0\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, area, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series) return nodes\n\n    const opts = options as VolumeOptions\n    const upColor = opts.upColor ?? 'var(--color-emerald-500, #10b981)'\n    const downColor = opts.downColor ?? 'var(--color-red-500, #ef4444)'\n    const gapFrac = opts.gap ?? 0.2\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - gapFrac)\n    const baseline = area.y + area.height\n\n    // Auto-detect direction: current value vs previous\n    const directions = opts.directions ?? series.values.map((v, i) =>\n      i === 0 ? 'up' as const : (v >= series.values[i - 1]! ? 'up' as const : 'down' as const),\n    )\n\n    const barNodes: RenderNode[] = []\n\n    for (let i = 0; i < series.values.length; i++) {\n      const val = series.values[i]!\n      const cx = xScale.map(i)\n      const yTop = yScale.map(val)\n      const barHeight = Math.max(baseline - yTop, 1)\n      const dir = directions[i] ?? 'up'\n      const color = dir === 'up' ? upColor : downColor\n\n      barNodes.push(rect(cx - barWidth / 2, yTop, barWidth, barHeight, {\n        rx: 1, ry: 1,\n        class: 'chartts-volume-bar',\n        fill: color,\n        fillOpacity: 0.85,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? i}: ${val} (${dir})`,\n      }))\n    }\n\n    nodes.push(group(barNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, area, options } = ctx\n    const series = data.series[0]\n    if (!series) return null\n\n    const opts = options as VolumeOptions\n    const gapFrac = opts.gap ?? 0.2\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - gapFrac)\n    const baseline = area.y + area.height\n\n    for (let i = 0; i < series.values.length; i++) {\n      const cx = xScale.map(i)\n      const yTop = yScale.map(series.values[i]!)\n      if (mx >= cx - barWidth / 2 && mx <= cx + barWidth / 2 && my >= yTop && my <= baseline) {\n        return { seriesIndex: 0, pointIndex: i, distance: Math.abs(mx - cx), x: cx, y: yTop }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { CSS_PREFIX } from '../../constants'\nimport { prepareData } from '../../data/prepare'\nimport { group, path, circle } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\nexport interface RangeOptions extends ResolvedOptions {\n  /** Upper and lower bound arrays. */\n  range?: {\n    upper: number[]\n    lower: number[]\n  }\n  /** Band fill color. Default uses series color with opacity. */\n  bandColor?: string\n  /** Band fill opacity. Default 0.2. */\n  bandOpacity?: number\n  /** Show center line (series[0].values). Default true. */\n  showCenter?: boolean\n  /** Show data points on center line. Default false. */\n  showPoints?: boolean\n}\n\n/**\n * Range / Band chart — shaded area between upper and lower bounds.\n *\n * Used for: Bollinger bands, confidence intervals, forecast ranges,\n * bid-ask spread visualization.\n */\nexport const rangeChartType = defineChartType({\n  type: 'range',\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const opts = options as RangeOptions\n    const range = opts.range\n    const prepared = prepareData(data, options)\n\n    // Support range from options OR from 2 series\n    const resolvedRange = range ?? (data.series.length >= 2\n      ? { lower: data.series[0]!.values, upper: data.series[1]!.values }\n      : null)\n\n    if (resolvedRange) {\n      let yMin = prepared.bounds.yMin\n      let yMax = prepared.bounds.yMax\n      for (let i = 0; i < resolvedRange.upper.length; i++) {\n        const u = resolvedRange.upper[i]!\n        const l = resolvedRange.lower[i]!\n        if (!isNaN(u) && u > yMax) yMax = u\n        if (!isNaN(l) && l < yMin) yMin = l\n      }\n      prepared.bounds.yMin = yMin\n      prepared.bounds.yMax = yMax\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, options, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const opts = options as RangeOptions\n\n    // Support range from options OR from 2 series (Low/High)\n    let range = opts.range\n    if (!range && data.series.length >= 2) {\n      range = { lower: data.series[0]!.values, upper: data.series[1]!.values }\n    }\n    if (!range) return nodes\n\n    const series = data.series.length >= 2\n      ? { ...data.series[0]!, values: data.series[0]!.values.map((v, i) => (v + data.series[1]!.values[i]!) / 2) }\n      : data.series[0]!\n    if (!series) return nodes\n\n    const showCenter = opts.showCenter ?? true\n    const showPoints = opts.showPoints ?? false\n    const bandOpacity = opts.bandOpacity ?? 0.2\n\n    const seriesNodes: RenderNode[] = []\n\n    // Build band polygon: upper path forward, lower path backward\n    const pb = new PathBuilder()\n    const n = range.upper.length\n\n    // Upper path (left to right) — skip NaN\n    let bandStarted = false\n    for (let i = 0; i < n; i++) {\n      if (isNaN(range.upper[i]!)) continue\n      const x = xScale.map(i)\n      const y = yScale.map(range.upper[i]!)\n      if (!bandStarted) { pb.moveTo(x, y); bandStarted = true }\n      else pb.lineTo(x, y)\n    }\n\n    // Lower path (right to left) — skip NaN\n    for (let i = n - 1; i >= 0; i--) {\n      if (isNaN(range.lower[i]!)) continue\n      const x = xScale.map(i)\n      const y = yScale.map(range.lower[i]!)\n      pb.lineTo(x, y)\n    }\n    if (bandStarted) pb.close()\n\n    seriesNodes.push(path(pb.build(), {\n      class: 'chartts-range-band',\n      fill: opts.bandColor ?? series.color,\n      fillOpacity: bandOpacity,\n      'data-series': 0,\n    }))\n\n    // Upper bound line\n    const upperPath = buildLinePath(range.upper, xScale, yScale)\n    seriesNodes.push(path(upperPath, {\n      class: 'chartts-range-bound',\n      stroke: series.color,\n      strokeWidth: 1,\n      strokeDasharray: '4,3',\n      opacity: 0.6,\n      'data-series': 0,\n    }))\n\n    // Lower bound line\n    const lowerPath = buildLinePath(range.lower, xScale, yScale)\n    seriesNodes.push(path(lowerPath, {\n      class: 'chartts-range-bound',\n      stroke: series.color,\n      strokeWidth: 1,\n      strokeDasharray: '4,3',\n      opacity: 0.6,\n      'data-series': 0,\n    }))\n\n    // Center line\n    if (showCenter && series.values.length > 0) {\n      const centerPath = buildLinePath(series.values, xScale, yScale)\n      seriesNodes.push(path(centerPath, {\n        class: 'chartts-range-center',\n        stroke: series.color,\n        strokeWidth: theme.lineWidth,\n        'data-series': 0,\n      }))\n\n      if (showPoints) {\n        for (let i = 0; i < series.values.length; i++) {\n          if (isNaN(series.values[i]!)) continue\n          const x = xScale.map(i)\n          const y = yScale.map(series.values[i]!)\n          seriesNodes.push(circle(x, y, theme.pointRadius, {\n            class: 'chartts-point',\n            fill: series.color,\n            stroke: `var(${CSS_PREFIX}-bg, #fff)`,\n            strokeWidth: 2,\n            'data-series': 0,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${data.labels[i] ?? i}: ${series.values[i]} [${range.lower[i]}–${range.upper[i]}]`,\n          }))\n        }\n      }\n    }\n\n    nodes.push(group(seriesNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale } = ctx\n    const series = data.series[0]\n    if (!series) return null\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    for (let i = 0; i < series.values.length; i++) {\n      if (isNaN(series.values[i]!)) continue\n      const x = xScale.map(i)\n      const y = yScale.map(series.values[i]!)\n      const dist = Math.sqrt((mx - x) ** 2 + (my - y) ** 2)\n      if (dist < bestDist) {\n        bestDist = dist\n        best = { seriesIndex: 0, pointIndex: i, distance: dist, x, y }\n      }\n    }\n\n    return best && best.distance < 30 ? best : null\n  },\n})\n\nfunction buildLinePath(\n  values: number[],\n  xScale: { map(v: number | string | Date): number },\n  yScale: { map(v: number | string | Date): number },\n): string {\n  if (values.length === 0) return ''\n  const pb = new PathBuilder()\n  let started = false\n  for (let i = 0; i < values.length; i++) {\n    if (isNaN(values[i]!)) { started = false; continue }\n    const x = xScale.map(i)\n    const y = yScale.map(values[i]!)\n    if (!started) { pb.moveTo(x, y); started = true }\n    else pb.lineTo(x, y)\n  }\n  return pb.build()\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { CSS_PREFIX } from '../../constants'\nimport { prepareData } from '../../data/prepare'\nimport { group, path, circle, line } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\nexport interface BaselineOptions extends ResolvedOptions {\n  /** Reference value for positive/negative split. Default 0. */\n  baseline?: number\n  /** Color for values above baseline. Default green. */\n  positiveColor?: string\n  /** Color for values below baseline. Default red. */\n  negativeColor?: string\n  /** Fill opacity for shaded areas. Default 0.15. */\n  fillOpacity?: number\n  /** Show the baseline reference line. Default true. */\n  showBaseline?: boolean\n  /** Show data points. Default true. */\n  showPoints?: boolean\n}\n\n/**\n * Baseline chart — line with positive/negative shading.\n *\n * Values above the baseline are shaded green, below shaded red.\n * Used for: performance vs benchmark, P&L, temperature anomalies.\n */\nexport const baselineChartType = defineChartType({\n  type: 'baseline',\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const opts = options as BaselineOptions\n    const bv = opts.baseline ?? 0\n    const prepared = prepareData(data, options)\n    // Ensure baseline value is visible in the scale\n    if (bv < prepared.bounds.yMin) prepared.bounds.yMin = bv\n    if (bv > prepared.bounds.yMax) prepared.bounds.yMax = bv\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, area, options, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const opts = options as BaselineOptions\n    const bv = opts.baseline ?? 0\n    const posColor = opts.positiveColor ?? 'var(--color-emerald-500, #10b981)'\n    const negColor = opts.negativeColor ?? 'var(--color-red-500, #ef4444)'\n    const fillOp = opts.fillOpacity ?? 0.15\n    const showBaseline = opts.showBaseline ?? true\n    const showPoints = opts.showPoints ?? true\n\n    const baseY = yScale.map(bv)\n\n    for (const series of data.series) {\n      const seriesNodes: RenderNode[] = []\n      const values = series.values\n      if (values.length === 0) continue\n\n      // Filter out NaN for path building — only use valid data points\n      const validPoints: { x: number; y: number; idx: number; val: number }[] = []\n      for (let i = 0; i < values.length; i++) {\n        if (!isNaN(values[i]!)) {\n          validPoints.push({ x: xScale.map(i), y: yScale.map(values[i]!), idx: i, val: values[i]! })\n        }\n      }\n      const points = validPoints.map(p => ({ x: p.x, y: p.y }))\n\n      // Positive fill (above baseline, clipped at baseline)\n      const posFill = buildClippedArea(points, baseY, 'above')\n      if (posFill) {\n        seriesNodes.push(path(posFill, {\n          class: 'chartts-baseline-pos',\n          fill: posColor,\n          fillOpacity: fillOp,\n          'data-series': series.index,\n        }))\n      }\n\n      // Negative fill (below baseline, clipped at baseline)\n      const negFill = buildClippedArea(points, baseY, 'below')\n      if (negFill) {\n        seriesNodes.push(path(negFill, {\n          class: 'chartts-baseline-neg',\n          fill: negColor,\n          fillOpacity: fillOp,\n          'data-series': series.index,\n        }))\n      }\n\n      // Main line (using valid points only)\n      const linePath = new PathBuilder()\n      if (points.length > 0) {\n        linePath.moveTo(points[0]!.x, points[0]!.y)\n        for (let i = 1; i < points.length; i++) {\n          linePath.lineTo(points[i]!.x, points[i]!.y)\n        }\n      }\n      seriesNodes.push(path(linePath.build(), {\n        class: 'chartts-baseline-line',\n        stroke: series.color,\n        strokeWidth: theme.lineWidth,\n        'data-series': series.index,\n      }))\n\n      // Data points (only for valid points)\n      if (showPoints) {\n        for (const vp of validPoints) {\n          const color = vp.val >= bv ? posColor : negColor\n          seriesNodes.push(circle(vp.x, vp.y, theme.pointRadius, {\n            class: 'chartts-point',\n            fill: color,\n            stroke: `var(${CSS_PREFIX}-bg, #fff)`,\n            strokeWidth: 2,\n            'data-series': series.index,\n            'data-index': vp.idx,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${vp.val} (${vp.val >= bv ? '+' : ''}${(vp.val - bv).toFixed(1)})`,\n          }))\n        }\n      }\n\n      nodes.push(group(seriesNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    // Baseline reference line\n    if (showBaseline) {\n      nodes.push(line(area.x, baseY, area.x + area.width, baseY, {\n        class: 'chartts-baseline-ref',\n        stroke: theme.textMuted,\n        strokeWidth: 1,\n        strokeDasharray: '6,4',\n        opacity: 0.5,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale } = ctx\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    for (const series of data.series) {\n      for (let i = 0; i < series.values.length; i++) {\n        if (isNaN(series.values[i]!)) continue\n        const x = xScale.map(i)\n        const y = yScale.map(series.values[i]!)\n        const dist = Math.sqrt((mx - x) ** 2 + (my - y) ** 2)\n        if (dist < bestDist) {\n          bestDist = dist\n          best = { seriesIndex: series.index, pointIndex: i, distance: dist, x, y }\n        }\n      }\n    }\n\n    return best && best.distance < 30 ? best : null\n  },\n})\n\n/**\n * Build a filled area path clipped to one side of the baseline.\n * Interpolates intersection points where the line crosses the baseline.\n */\nfunction buildClippedArea(\n  points: { x: number; y: number }[],\n  baseY: number,\n  side: 'above' | 'below',\n): string | null {\n  if (points.length < 2) return null\n\n  // Collect segments that are on the desired side\n  const segments: { x: number; y: number }[][] = []\n  let current: { x: number; y: number }[] = []\n\n  for (let i = 0; i < points.length; i++) {\n    const p = points[i]!\n    const onSide = side === 'above' ? p.y <= baseY : p.y >= baseY\n\n    if (i > 0) {\n      const prev = points[i - 1]!\n      const prevOnSide = side === 'above' ? prev.y <= baseY : prev.y >= baseY\n\n      // Crossing detected — compute intersection\n      if (onSide !== prevOnSide) {\n        const t = (baseY - prev.y) / (p.y - prev.y)\n        const ix = prev.x + t * (p.x - prev.x)\n        const cross = { x: ix, y: baseY }\n\n        if (prevOnSide) {\n          // Was on side, now leaving — close current segment\n          current.push(cross)\n          if (current.length >= 2) segments.push(current)\n          current = []\n        } else {\n          // Was off side, now entering — start new segment\n          current = [cross]\n        }\n      }\n    }\n\n    if (onSide) current.push(p)\n  }\n  if (current.length >= 2) segments.push(current)\n  if (segments.length === 0) return null\n\n  // Build SVG path for all segments\n  const pb = new PathBuilder()\n  for (const seg of segments) {\n    pb.moveTo(seg[0]!.x, seg[0]!.y)\n    for (let i = 1; i < seg.length; i++) {\n      pb.lineTo(seg[i]!.x, seg[i]!.y)\n    }\n    // Close down/up to baseline\n    pb.lineTo(seg[seg.length - 1]!.x, baseY)\n    pb.lineTo(seg[0]!.x, baseY)\n    pb.close()\n  }\n\n  return pb.build()\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\nexport interface KagiOptions extends ResolvedOptions {\n  /** Reversal amount. If < 1, treated as percentage of range. Default 0.04 (4%). */\n  reversalAmount?: number\n  /** Yang (up-trend) color. Default green. */\n  yangColor?: string\n  /** Yin (down-trend) color. Default red. */\n  yinColor?: string\n  /** Yang line width (thick). Default 3. */\n  yangWidth?: number\n  /** Yin line width (thin). Default 1.5. */\n  yinWidth?: number\n  /** Show price labels at turning points. Default false. */\n  showLabels?: boolean\n}\n\ninterface KagiSegment {\n  startY: number\n  endY: number\n  x: number\n  isYang: boolean   // thick = up trend\n  priceStart: number\n  priceEnd: number\n}\n\n/**\n * Kagi chart — Japanese reversal chart.\n *\n * Lines change direction only on significant price moves.\n * Thick lines (yang) = up trend, thin lines (yin) = down trend.\n * Thickness changes when price breaks prior high/low.\n */\nexport const kagiChartType = defineChartType({\n  type: 'kagi',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, options, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length < 2) return nodes\n\n    const opts = options as KagiOptions\n    const yangColor = opts.yangColor ?? 'var(--color-emerald-500, #10b981)'\n    const yinColor = opts.yinColor ?? 'var(--color-red-500, #ef4444)'\n    const yangWidth = opts.yangWidth ?? 3\n    const yinWidth = opts.yinWidth ?? 1.5\n    const showLabels = opts.showLabels ?? false\n\n    const values = series.values\n    const vMin = Math.min(...values)\n    const vMax = Math.max(...values)\n    const vRange = vMax - vMin || 1\n\n    // Reversal amount\n    let reversal = opts.reversalAmount ?? 0.04\n    if (reversal < 1) reversal = reversal * vRange\n\n    // Build kagi segments\n    const segments = computeKagiSegments(values, reversal)\n    if (segments.length === 0) return nodes\n\n    // Map to pixel coordinates\n    const padding = 20\n    const usableWidth = area.width - padding * 2\n    const usableHeight = area.height - padding * 2\n    const colWidth = segments.length > 1 ? usableWidth / (segments.length - 1) : usableWidth\n\n    const mapY = (v: number) => area.y + padding + (1 - (v - vMin) / vRange) * usableHeight\n    const actualColWidth = Math.min(colWidth, 20)\n    const totalWidth = actualColWidth * (segments.length - 1)\n    const xOffset = area.x + (area.width - totalWidth) / 2\n\n    const kagiNodes: RenderNode[] = []\n\n    // Draw segments\n    for (let i = 0; i < segments.length; i++) {\n      const seg = segments[i]!\n      const x = xOffset + i * actualColWidth\n      const y1 = mapY(seg.priceStart)\n      const y2 = mapY(seg.priceEnd)\n      const color = seg.isYang ? yangColor : yinColor\n      const width = seg.isYang ? yangWidth : yinWidth\n\n      // Vertical segment\n      const pb = new PathBuilder()\n      pb.moveTo(x, y1).lineTo(x, y2)\n\n      // Horizontal connector to next segment\n      if (i < segments.length - 1) {\n        const nextX = xOffset + (i + 1) * actualColWidth\n        pb.lineTo(nextX, y2)\n      }\n\n      kagiNodes.push(path(pb.build(), {\n        class: 'chartts-kagi-line',\n        stroke: color,\n        strokeWidth: width,\n        strokeLinecap: 'round',\n        strokeLinejoin: 'round',\n        'data-series': 0,\n        'data-index': i,\n      }))\n\n      // Price labels at turning points\n      if (showLabels && (i === 0 || i === segments.length - 1)) {\n        kagiNodes.push(text(x, y2 + (seg.priceEnd > seg.priceStart ? -8 : 14), seg.priceEnd.toFixed(1), {\n          class: 'chartts-kagi-label',\n          fill: theme.textMuted,\n          fontSize: theme.fontSizeSmall,\n          textAnchor: 'middle',\n        }))\n      }\n    }\n\n    nodes.push(group(kagiNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length < 2) return null\n\n    // Approximate: map mouse X to data index\n    const frac = (mx - area.x) / area.width\n    const idx = Math.round(frac * (series.values.length - 1))\n    if (idx >= 0 && idx < series.values.length) {\n      return { seriesIndex: 0, pointIndex: idx, distance: 10, x: mx, y: my }\n    }\n    return null\n  },\n})\n\n/**\n * Compute kagi line segments from raw price data.\n */\nfunction computeKagiSegments(values: number[], reversal: number): KagiSegment[] {\n  const segments: KagiSegment[] = []\n  if (values.length < 2) return segments\n\n  let direction: 'up' | 'down' = values[1]! >= values[0]! ? 'up' : 'down'\n  let currentStart = values[0]!\n  let currentEnd = values[1]!\n  let priorHigh = Math.max(values[0]!, values[1]!)\n  let priorLow = Math.min(values[0]!, values[1]!)\n  let isYang = direction === 'up'\n\n  for (let i = 2; i < values.length; i++) {\n    const v = values[i]!\n\n    if (direction === 'up') {\n      if (v >= currentEnd) {\n        // Continue up\n        currentEnd = v\n        if (v > priorHigh) isYang = true\n      } else if (currentEnd - v >= reversal) {\n        // Reversal down\n        segments.push({\n          startY: 0, endY: 0, x: 0,\n          isYang,\n          priceStart: currentStart,\n          priceEnd: currentEnd,\n        })\n        priorHigh = currentEnd\n        currentStart = currentEnd\n        currentEnd = v\n        direction = 'down'\n        if (v < priorLow) isYang = false\n      }\n    } else {\n      if (v <= currentEnd) {\n        // Continue down\n        currentEnd = v\n        if (v < priorLow) isYang = false\n      } else if (v - currentEnd >= reversal) {\n        // Reversal up\n        segments.push({\n          startY: 0, endY: 0, x: 0,\n          isYang,\n          priceStart: currentStart,\n          priceEnd: currentEnd,\n        })\n        priorLow = currentEnd\n        currentStart = currentEnd\n        currentEnd = v\n        direction = 'up'\n        if (v > priorHigh) isYang = true\n      }\n    }\n  }\n\n  // Push final segment\n  segments.push({\n    startY: 0, endY: 0, x: 0,\n    isYang,\n    priceStart: currentStart,\n    priceEnd: currentEnd,\n  })\n\n  return segments\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect } from '../../render/tree'\n\nexport interface RenkoOptions extends ResolvedOptions {\n  /** Brick size in data units. Auto-calculated from ATR if omitted. */\n  brickSize?: number\n  /** Up brick color. Default green. */\n  upColor?: string\n  /** Down brick color. Default red. */\n  downColor?: string\n  /** Gap between bricks in pixels. Default 1. */\n  gap?: number\n  /** Corner radius for bricks. Default 2. */\n  borderRadius?: number\n}\n\ninterface RenkoBrick {\n  open: number\n  close: number\n  isUp: boolean\n}\n\n/**\n * Renko chart — brick-based reversal chart.\n *\n * Uniform bricks form only when price moves by the brick size.\n * Up bricks (green) for rising prices, down bricks (red) for falling.\n * Filters out noise and shows pure price action.\n */\nexport const renkoChartType = defineChartType({\n  type: 'renko',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length < 2) return nodes\n\n    const opts = options as RenkoOptions\n    const upColor = opts.upColor ?? 'var(--color-emerald-500, #10b981)'\n    const downColor = opts.downColor ?? 'var(--color-red-500, #ef4444)'\n    const gap = opts.gap ?? 1\n    const borderRadius = opts.borderRadius ?? 2\n\n    const values = series.values\n\n    // Auto-calculate brick size: ATR-like approach (average absolute change)\n    let brickSize = opts.brickSize\n    if (!brickSize) {\n      let totalChange = 0\n      for (let i = 1; i < values.length; i++) {\n        totalChange += Math.abs(values[i]! - values[i - 1]!)\n      }\n      const avgChange = totalChange / (values.length - 1)\n      brickSize = Math.max(avgChange * 1.5, (Math.max(...values) - Math.min(...values)) / 20)\n    }\n\n    // Build bricks\n    const bricks = computeRenkoBricks(values, brickSize)\n    if (bricks.length === 0) return nodes\n\n    // Find price range from bricks\n    let minPrice = Infinity\n    let maxPrice = -Infinity\n    for (const b of bricks) {\n      minPrice = Math.min(minPrice, b.open, b.close)\n      maxPrice = Math.max(maxPrice, b.open, b.close)\n    }\n    const priceRange = maxPrice - minPrice || 1\n\n    // Layout: each brick gets equal horizontal space\n    const padding = 16\n    const usableWidth = area.width - padding * 2\n    const usableHeight = area.height - padding * 2\n    const brickWidth = Math.min(\n      (usableWidth - gap * (bricks.length - 1)) / bricks.length,\n      30,\n    )\n\n    const totalBrickWidth = bricks.length * brickWidth + (bricks.length - 1) * gap\n    const xStart = area.x + (area.width - totalBrickWidth) / 2\n\n    const mapY = (v: number) => area.y + padding + (1 - (v - minPrice) / priceRange) * usableHeight\n    const brickPixelHeight = (brickSize / priceRange) * usableHeight\n\n    const brickNodes: RenderNode[] = []\n\n    for (let i = 0; i < bricks.length; i++) {\n      const b = bricks[i]!\n      const x = xStart + i * (brickWidth + gap)\n      const yTop = mapY(Math.max(b.open, b.close))\n      const h = Math.max(brickPixelHeight, 3)\n\n      brickNodes.push(rect(x, yTop, brickWidth, h, {\n        rx: borderRadius, ry: borderRadius,\n        class: 'chartts-renko-brick',\n        fill: b.isUp ? upColor : downColor,\n        fillOpacity: b.isUp ? 0.9 : 0.9,\n        stroke: b.isUp ? upColor : downColor,\n        strokeWidth: 1,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `Brick ${i + 1}: ${b.isUp ? 'Up' : 'Down'} ${b.open.toFixed(1)}→${b.close.toFixed(1)}`,\n      }))\n    }\n\n    nodes.push(group(brickNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series) return null\n\n    const frac = (mx - area.x) / area.width\n    const idx = Math.round(frac * (series.values.length - 1))\n    if (idx >= 0 && idx < series.values.length) {\n      return { seriesIndex: 0, pointIndex: idx, distance: 10, x: mx, y: my }\n    }\n    return null\n  },\n})\n\n/**\n * Compute renko bricks from raw price data.\n */\nfunction computeRenkoBricks(values: number[], brickSize: number): RenkoBrick[] {\n  const bricks: RenkoBrick[] = []\n  if (values.length < 2 || brickSize <= 0) return bricks\n\n  let currentPrice = Math.round(values[0]! / brickSize) * brickSize\n\n  for (let i = 1; i < values.length; i++) {\n    const v = values[i]!\n    const diff = v - currentPrice\n\n    if (Math.abs(diff) >= brickSize) {\n      const numBricks = Math.floor(Math.abs(diff) / brickSize)\n      const isUp = diff > 0\n\n      for (let j = 0; j < numBricks; j++) {\n        const open = currentPrice\n        currentPrice += isUp ? brickSize : -brickSize\n        bricks.push({ open, close: currentPrice, isUp })\n      }\n    }\n  }\n\n  return bricks\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, path, line, rect } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Violin chart — shows the full distribution shape for each category.\n *\n * Data format: same as boxplot — single series with N*5 values per label:\n * [min, Q1, median, Q3, max] repeated per category.\n *\n * Additionally accepts raw sample values via options.violin.samples\n * for true KDE computation. Falls back to a smooth approximation\n * from the 5-number summary when samples aren't provided.\n */\nexport interface ViolinOptions extends ResolvedOptions {\n  /** KDE bandwidth (smoothing). Default 0.3 of data range. */\n  bandwidth?: number\n  /** Show inner box + median line. Default true. */\n  showBox?: boolean\n  /** Width ratio relative to band. Default 0.7. */\n  violinWidth?: number\n}\n\nexport const violinChartType = defineChartType({\n  type: 'violin',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const labelCount = data.labels?.length ?? 0\n    const valLen = data.series[0]?.values.length ?? 0\n    const syntheticData = { ...data }\n    if (labelCount > 0 && valLen > labelCount) {\n      const padded: string[] = (data.labels ?? []).map(String)\n      while (padded.length < valLen) padded.push('')\n      syntheticData.labels = padded\n    }\n    const prepared = prepareData(syntheticData, options)\n    if (data.labels && data.labels.length < valLen) {\n      prepared.labels = [...data.labels]\n    }\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    const seriesCount = data.series.length\n    if (seriesCount === 0) return nodes\n\n    const vOpts = options as ViolinOptions\n    const widthRatio = vOpts.violinWidth ?? 0.7\n    const showBox = vOpts.showBox !== false\n\n    const bw = getBandwidth(xScale)\n    const halfW = (bw * widthRatio) / 2\n\n    for (let i = 0; i < data.labels.length; i++) {\n      let vals: number[]\n      if (data.series.length === 5 && data.series[0]!.values.length === data.labels.length) {\n        // Boxplot format: 5 series (Min, Q1, Median, Q3, Max), each with one value per label\n        vals = [\n          data.series[0]!.values[i]!,\n          data.series[1]!.values[i]!,\n          data.series[2]!.values[i]!,\n          data.series[3]!.values[i]!,\n          data.series[4]!.values[i]!,\n        ]\n      } else if (data.series.length === 1) {\n        const s = data.series[0]!\n        if (s.values.length >= (i + 1) * 5) {\n          vals = s.values.slice(i * 5, i * 5 + 5)\n        } else continue\n      } else if (data.series.length > i && data.series[i]!.values.length >= 5) {\n        vals = data.series[i]!.values.slice(0, 5)\n      } else continue\n\n      const [vMin, q1, median, q3, vMax] = vals as [number, number, number, number, number]\n      const cx = xScale.map(i)\n      const color = options.colors[i % options.colors.length]!\n      const seriesIdx = Math.min(i, data.series.length - 1)\n\n      // Generate KDE-like density profile from 5-number summary\n      const steps = 32\n      const range = vMax - vMin || 1\n      const densities: number[] = []\n      let maxDensity = 0\n\n      for (let s = 0; s <= steps; s++) {\n        const v = vMin + (s / steps) * range\n        // Approximate density using a smooth curve peaked at the median\n        // with mass concentrated between Q1 and Q3\n        const dQ1 = gaussianKernel(v, q1, range * 0.15)\n        const dMed = gaussianKernel(v, median, range * 0.12)\n        const dQ3 = gaussianKernel(v, q3, range * 0.15)\n        const dMin = gaussianKernel(v, vMin, range * 0.08)\n        const dMax = gaussianKernel(v, vMax, range * 0.08)\n        const density = dMin * 0.3 + dQ1 * 1.0 + dMed * 1.5 + dQ3 * 1.0 + dMax * 0.3\n        densities.push(density)\n        if (density > maxDensity) maxDensity = density\n      }\n\n      if (maxDensity === 0) continue\n\n      // Build mirrored violin path\n      const rightPoints: string[] = []\n      const leftPoints: string[] = []\n\n      for (let s = 0; s <= steps; s++) {\n        const v = vMin + (s / steps) * range\n        const py = yScale.map(v)\n        const w = (densities[s]! / maxDensity) * halfW\n\n        if (s === 0) rightPoints.push(`M ${cx + w} ${py}`)\n        else rightPoints.push(`L ${cx + w} ${py}`)\n\n        leftPoints.unshift(`L ${cx - w} ${py}`)\n      }\n\n      const d = rightPoints.join(' ') + ' ' + leftPoints.join(' ') + ' Z'\n\n      const violinNodes: RenderNode[] = []\n\n      violinNodes.push(path(d, {\n        class: 'chartts-violin-shape',\n        fill: color,\n        fillOpacity: 0.3,\n        stroke: color,\n        strokeWidth: 1.5,\n        style: `--chartts-i:${i}`,\n        'data-series': seriesIdx,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i]}: min=${vMin}, Q1=${q1}, median=${median}, Q3=${q3}, max=${vMax}`,\n      }))\n\n      if (showBox) {\n        // Inner IQR box\n        const yQ1 = yScale.map(q1)\n        const yQ3 = yScale.map(q3)\n        const boxTop = Math.min(yQ1, yQ3)\n        const boxH = Math.abs(yQ3 - yQ1)\n        const boxW = halfW * 0.3\n\n        violinNodes.push(rect(cx - boxW, boxTop, boxW * 2, boxH, {\n          class: 'chartts-violin-box',\n          fill: color,\n          fillOpacity: 0.5,\n          stroke: color,\n          strokeWidth: 1,\n          rx: 2,\n        }))\n\n        // Median line\n        const yMed = yScale.map(median)\n        violinNodes.push(line(cx - boxW, yMed, cx + boxW, yMed, {\n          class: 'chartts-violin-median',\n          stroke: '#fff',\n          strokeWidth: 2,\n        }))\n      }\n\n      nodes.push(group(violinNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i]),\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    if (data.labels.length === 0) return null\n\n    const vOpts = options as ViolinOptions\n    const widthRatio = vOpts.violinWidth ?? 0.7\n    const bw = getBandwidth(xScale)\n    const halfW = (bw * widthRatio) / 2\n\n    for (let i = 0; i < data.labels.length; i++) {\n      let vals: number[]\n      if (data.series.length === 5 && data.series[0]!.values.length === data.labels.length) {\n        vals = [\n          data.series[0]!.values[i]!,\n          data.series[1]!.values[i]!,\n          data.series[2]!.values[i]!,\n          data.series[3]!.values[i]!,\n          data.series[4]!.values[i]!,\n        ]\n      } else if (data.series.length === 1) {\n        const s = data.series[0]!\n        if (s.values.length >= (i + 1) * 5) vals = s.values.slice(i * 5, i * 5 + 5)\n        else continue\n      } else if (data.series.length > i && data.series[i]!.values.length >= 5) {\n        vals = data.series[i]!.values.slice(0, 5)\n      } else continue\n\n      const cx = xScale.map(i)\n      const yMin = yScale.map(vals[0]!)\n      const yMax = yScale.map(vals[4]!)\n      const top = Math.min(yMin, yMax)\n      const bottom = Math.max(yMin, yMax)\n\n      if (mx >= cx - halfW - 4 && mx <= cx + halfW + 4 &&\n          my >= top - 4 && my <= bottom + 4) {\n        const seriesIdx = Math.min(i, data.series.length - 1)\n        return { seriesIndex: seriesIdx, pointIndex: i, distance: 0, x: cx, y: yScale.map(vals[2]!) }\n      }\n    }\n\n    return null\n  },\n})\n\nfunction gaussianKernel(x: number, mu: number, sigma: number): number {\n  const z = (x - mu) / sigma\n  return Math.exp(-0.5 * z * z)\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, circle, text } from '../../render/tree'\n\n/**\n * Pack (Circle Packing) chart — nested circles where area is proportional to value.\n *\n * Uses a front-chain packing algorithm to arrange circles tightly.\n */\nexport const packChartType = defineChartType({\n  type: 'pack',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const items = series.values\n      .map((v, i) => ({ value: Math.abs(v), index: i }))\n      .filter(d => d.value > 0)\n      .sort((a, b) => b.value - a.value)\n\n    if (items.length === 0) return nodes\n\n    // Compute radii proportional to sqrt(value) so AREA is proportional to value\n    const maxVal = items[0]!.value\n    const maxR = Math.min(area.width, area.height) * 0.35\n    const minR = Math.max(8, maxR * 0.06)\n\n    const radii = items.map(d => minR + Math.sqrt(d.value / maxVal) * (maxR - minR))\n\n    // Pack circles using a simple greedy placement\n    const placed = packCircles(radii, area)\n\n    for (let k = 0; k < items.length; k++) {\n      const item = items[k]!\n      const p = placed[k]\n      if (!p) continue\n\n      const color = options.colors[item.index % options.colors.length]!\n      const label = String(data.labels[item.index] ?? `Item ${item.index + 1}`)\n      const r = radii[k]!\n\n      const cellNodes: RenderNode[] = []\n\n      cellNodes.push(circle(p.x, p.y, r, {\n        class: 'chartts-pack-circle',\n        fill: color,\n        fillOpacity: 0.6,\n        stroke: color,\n        strokeWidth: 1.5,\n        style: `--chartts-i:${k}`,\n        'data-series': 0,\n        'data-index': item.index,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label}: ${series.values[item.index]}`,\n      }))\n\n      // Label if circle is big enough\n      if (r > 18) {\n        const fontSize = Math.min(theme.fontSizeSmall, r * 0.45)\n        cellNodes.push(text(p.x, p.y - fontSize * 0.3, label, {\n          class: 'chartts-pack-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n          pointerEvents: 'none',\n        }))\n\n        if (r > 28) {\n          cellNodes.push(text(p.x, p.y + fontSize * 0.8, String(series.values[item.index]), {\n            class: 'chartts-pack-value',\n            fill: 'rgba(255,255,255,0.7)',\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: fontSize * 0.8,\n            fontFamily: theme.fontFamily,\n            pointerEvents: 'none',\n          }))\n        }\n      }\n\n      nodes.push(group(cellNodes, {\n        class: `chartts-series chartts-series-${item.index}`,\n        'data-series-name': label,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const items = series.values\n      .map((v, i) => ({ value: Math.abs(v), index: i }))\n      .filter(d => d.value > 0)\n      .sort((a, b) => b.value - a.value)\n\n    if (items.length === 0) return null\n\n    const maxVal = items[0]!.value\n    const maxR = Math.min(area.width, area.height) * 0.35\n    const minR = Math.max(8, maxR * 0.06)\n    const radii = items.map(d => minR + Math.sqrt(d.value / maxVal) * (maxR - minR))\n    const placed = packCircles(radii, area)\n\n    // Find smallest circle containing the mouse (most specific)\n    let best: { idx: number; r: number; x: number; y: number } | null = null\n\n    for (let k = 0; k < items.length; k++) {\n      const p = placed[k]\n      if (!p) continue\n      const r = radii[k]!\n      const dist = Math.sqrt((mx - p.x) ** 2 + (my - p.y) ** 2)\n      if (dist <= r && (!best || r < best.r)) {\n        best = { idx: items[k]!.index, r, x: p.x, y: p.y }\n      }\n    }\n\n    if (!best) return null\n    return { seriesIndex: 0, pointIndex: best.idx, distance: 0, x: best.x, y: best.y }\n  },\n})\n\ninterface Pos { x: number; y: number }\n\n/** Greedy circle packing within a rectangular area. */\nfunction packCircles(radii: number[], area: { x: number; y: number; width: number; height: number }): Pos[] {\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n  const result: Pos[] = []\n\n  if (radii.length === 0) return result\n\n  // Place first circle at center\n  result.push({ x: cx, y: cy })\n\n  for (let i = 1; i < radii.length; i++) {\n    const r = radii[i]!\n    let bestPos: Pos = { x: cx, y: cy }\n    let bestDist = Infinity\n\n    // Try placing tangent to each existing circle, at various angles\n    for (let j = 0; j < result.length; j++) {\n      const pj = result[j]!\n      const rj = radii[j]!\n      const gap = rj + r + 2\n\n      for (let a = 0; a < 12; a++) {\n        const angle = (a / 12) * Math.PI * 2\n        const tx = pj.x + Math.cos(angle) * gap\n        const ty = pj.y + Math.sin(angle) * gap\n\n        // Check overlap with all placed circles\n        let overlaps = false\n        for (let k = 0; k < result.length; k++) {\n          const pk = result[k]!\n          const rk = radii[k]!\n          const dist = Math.sqrt((tx - pk.x) ** 2 + (ty - pk.y) ** 2)\n          if (dist < rk + r + 1) { overlaps = true; break }\n        }\n\n        if (!overlaps) {\n          // Prefer positions closer to center\n          const distFromCenter = Math.sqrt((tx - cx) ** 2 + (ty - cy) ** 2)\n          if (distFromCenter < bestDist) {\n            bestDist = distFromCenter\n            bestPos = { x: tx, y: ty }\n          }\n        }\n      }\n    }\n\n    result.push(bestPos)\n  }\n\n  return result\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * ThemeRiver / StreamGraph chart — stacked area chart with a center baseline.\n *\n * Data convention:\n * - labels: time points (x-axis categories)\n * - series[i]: a stream layer. values[j] = thickness at time j\n *\n * The streams are stacked symmetrically around the horizontal center,\n * creating an organic river-like visualization.\n */\n\nexport const themeRiverChartType = defineChartType({\n  type: 'themeriver',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const timeCount = data.labels.length\n    if (timeCount < 2 || data.series.length === 0) return nodes\n\n    const seriesCount = data.series.length\n\n    // Compute stacked values\n    const stacks: number[][] = []\n    for (let t = 0; t < timeCount; t++) {\n      const column: number[] = []\n      for (let si = 0; si < seriesCount; si++) {\n        column.push(Math.abs(data.series[si]!.values[t] ?? 0))\n      }\n      stacks.push(column)\n    }\n\n    // Compute baseline offsets (wiggle / silhouette centering)\n    const baselines: number[] = []\n    for (let t = 0; t < timeCount; t++) {\n      const total = stacks[t]!.reduce((s, v) => s + v, 0)\n      baselines.push(-total / 2) // Center around 0\n    }\n\n    // Find global min/max for y-scale\n    let yMin = Infinity\n    let yMax = -Infinity\n    for (let t = 0; t < timeCount; t++) {\n      let cumulative = baselines[t]!\n      if (cumulative < yMin) yMin = cumulative\n      for (let si = 0; si < seriesCount; si++) {\n        cumulative += stacks[t]![si]!\n      }\n      if (cumulative > yMax) yMax = cumulative\n    }\n    if (yMin === yMax) { yMin -= 1; yMax += 1 }\n\n    const xStep = area.width / Math.max(timeCount - 1, 1)\n    const mapX = (t: number) => area.x + t * xStep\n    const mapY = (val: number) => {\n      const frac = (val - yMin) / (yMax - yMin)\n      return area.y + area.height - frac * area.height\n    }\n\n    // Render each series as a stream band\n    for (let si = 0; si < seriesCount; si++) {\n      const series = data.series[si]!\n      const color = series.color ?? options.colors[si % options.colors.length]!\n\n      // Compute top and bottom edges for this series\n      const tops: { x: number; y: number }[] = []\n      const bottoms: { x: number; y: number }[] = []\n\n      for (let t = 0; t < timeCount; t++) {\n        let cumBottom = baselines[t]!\n        for (let s = 0; s < si; s++) {\n          cumBottom += stacks[t]![s]!\n        }\n        const cumTop = cumBottom + stacks[t]![si]!\n\n        tops.push({ x: mapX(t), y: mapY(cumTop) })\n        bottoms.push({ x: mapX(t), y: mapY(cumBottom) })\n      }\n\n      // Build smooth path: top edge forward, bottom edge backward\n      const pb = new PathBuilder()\n\n      // Top edge (left to right)\n      pb.moveTo(tops[0]!.x, tops[0]!.y)\n      for (let t = 1; t < timeCount; t++) {\n        const prev = tops[t - 1]!\n        const curr = tops[t]!\n        const cpx = (prev.x + curr.x) / 2\n        pb.curveTo(cpx, prev.y, cpx, curr.y, curr.x, curr.y)\n      }\n\n      // Bottom edge (right to left)\n      pb.lineTo(bottoms[timeCount - 1]!.x, bottoms[timeCount - 1]!.y)\n      for (let t = timeCount - 2; t >= 0; t--) {\n        const prev = bottoms[t + 1]!\n        const curr = bottoms[t]!\n        const cpx = (prev.x + curr.x) / 2\n        pb.curveTo(cpx, prev.y, cpx, curr.y, curr.x, curr.y)\n      }\n\n      pb.close()\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-themeriver-stream',\n        fill: color,\n        fillOpacity: 0.75,\n        stroke: color,\n        strokeWidth: 0.5,\n        'data-series': si,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${series.name}`,\n      }))\n\n      // Label at the widest point\n      let maxWidth = 0\n      let maxT = 0\n      for (let t = 0; t < timeCount; t++) {\n        const width = Math.abs(tops[t]!.y - bottoms[t]!.y)\n        if (width > maxWidth) {\n          maxWidth = width\n          maxT = t\n        }\n      }\n\n      if (maxWidth > 16) {\n        const midY = (tops[maxT]!.y + bottoms[maxT]!.y) / 2\n        const fontSize = Math.min(theme.fontSizeSmall, maxWidth * 0.4)\n        nodes.push(text(tops[maxT]!.x, midY, series.name, {\n          class: 'chartts-themeriver-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n      }\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const timeCount = data.labels.length\n    if (timeCount < 2 || data.series.length === 0) return null\n\n    const seriesCount = data.series.length\n    const xStep = area.width / Math.max(timeCount - 1, 1)\n\n    // Find closest time index\n    const t = Math.round((mx - area.x) / xStep)\n    if (t < 0 || t >= timeCount) return null\n\n    // Compute stacks at this time\n    const column: number[] = []\n    for (let si = 0; si < seriesCount; si++) {\n      column.push(Math.abs(data.series[si]!.values[t] ?? 0))\n    }\n    const total = column.reduce((s, v) => s + v, 0)\n    const baseline = -total / 2\n\n    // Find global scale\n    let yMin = Infinity\n    let yMax = -Infinity\n    for (let tt = 0; tt < timeCount; tt++) {\n      let cum = 0\n      for (let si = 0; si < seriesCount; si++) {\n        cum += Math.abs(data.series[si]!.values[tt] ?? 0)\n      }\n      const bl = -cum / 2\n      if (bl < yMin) yMin = bl\n      if (bl + cum > yMax) yMax = bl + cum\n    }\n    if (yMin === yMax) { yMin -= 1; yMax += 1 }\n\n    const mapY = (val: number) => {\n      const frac = (val - yMin) / (yMax - yMin)\n      return area.y + area.height - frac * area.height\n    }\n\n    // Check which stream the y coordinate falls in\n    let cumBottom = baseline\n    for (let si = 0; si < seriesCount; si++) {\n      const cumTop = cumBottom + column[si]!\n      const topY = mapY(cumTop)\n      const bottomY = mapY(cumBottom)\n\n      if (my >= topY && my <= bottomY) {\n        return { seriesIndex: si, pointIndex: t, distance: 0, x: area.x + t * xStep, y: mapY((cumBottom + cumTop) / 2) }\n      }\n      cumBottom = cumTop\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\n\n/**\n * PictorialBar chart — bar chart where bars are filled with repeated symbols.\n *\n * Data convention:\n * - labels: category names\n * - series[0].values: bar values\n *\n * The bars are made of stacked symbols (circles, diamonds, or custom shapes)\n * creating a pictograph/isotype visualization.\n */\n\nexport interface PictorialBarOptions extends ResolvedOptions {\n  /** Symbol shape. Default 'circle'. */\n  symbol?: 'circle' | 'diamond' | 'square' | 'triangle' | 'star'\n  /** Symbol size in px. Default 12. */\n  symbolSize?: number\n  /** Gap between symbols. Default 2. */\n  symbolGap?: number\n  /** Show value labels. Default true. */\n  showValues?: boolean\n}\n\n// SVG path data for symbols (centered at 0,0, size 1x1)\nconst SYMBOL_PATHS: Record<string, string> = {\n  circle: 'M0.5,0A0.5,0.5,0,1,1,-0.5,0A0.5,0.5,0,1,1,0.5,0Z',\n  diamond: 'M0,-0.5L0.5,0L0,0.5L-0.5,0Z',\n  square: 'M-0.4,-0.4L0.4,-0.4L0.4,0.4L-0.4,0.4Z',\n  triangle: 'M0,-0.5L0.5,0.4L-0.5,0.4Z',\n  star: 'M0,-0.5L0.15,-0.15L0.5,-0.15L0.22,0.07L0.31,0.45L0,0.22L-0.31,0.45L-0.22,0.07L-0.5,-0.15L-0.15,-0.15Z',\n}\n\nexport const pictorialBarChartType = defineChartType({\n  type: 'pictorialbar',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const pOpts = options as PictorialBarOptions\n    const symbolShape = pOpts.symbol ?? 'circle'\n    const symbolSize = pOpts.symbolSize ?? 14\n    const symbolGap = pOpts.symbolGap ?? 2\n    const showValues = pOpts.showValues ?? true\n\n    const values = series.values\n    const maxVal = Math.max(...values.map(Math.abs))\n    if (maxVal === 0) return nodes\n\n    const barCount = values.length\n    const barGap = 16\n    const barWidth = Math.min(\n      (area.width - barGap * (barCount + 1)) / barCount,\n      symbolSize * 3,\n    )\n    const totalWidth = barCount * barWidth + (barCount - 1) * barGap\n    const startX = area.x + (area.width - totalWidth) / 2\n\n    const symbolStep = symbolSize + symbolGap\n    const maxSymbols = Math.floor((area.height - 30) / symbolStep)\n\n    for (let i = 0; i < barCount; i++) {\n      const val = Math.abs(values[i]!)\n      const symbolCount = Math.max(1, Math.round((val / maxVal) * maxSymbols))\n      const color = options.colors[i % options.colors.length]!\n      const cx = startX + i * (barWidth + barGap) + barWidth / 2\n      const barNodes: RenderNode[] = []\n\n      for (let s = 0; s < symbolCount; s++) {\n        const sy = area.y + area.height - 20 - s * symbolStep - symbolSize / 2\n\n        if (symbolShape === 'circle') {\n          barNodes.push({\n            type: 'circle',\n            cx,\n            cy: sy,\n            r: symbolSize / 2,\n            attrs: {\n              class: 'chartts-pictorialbar-symbol',\n              fill: color,\n              fillOpacity: 0.85,\n              'data-series': 0,\n              'data-index': i,\n            },\n          })\n        } else {\n          // Use path-based symbols\n          const symbolPath = SYMBOL_PATHS[symbolShape] ?? SYMBOL_PATHS.circle!\n          barNodes.push(path(symbolPath, {\n            class: 'chartts-pictorialbar-symbol',\n            fill: color,\n            fillOpacity: 0.85,\n            transform: `translate(${cx},${sy}) scale(${symbolSize})`,\n            'data-series': 0,\n            'data-index': i,\n          }))\n        }\n      }\n\n      // Value label above bar\n      if (showValues) {\n        const topY = area.y + area.height - 20 - (symbolCount - 1) * symbolStep - symbolSize\n        barNodes.push(text(cx, topY - 8, String(values[i]!), {\n          class: 'chartts-pictorialbar-value',\n          fill: theme.textColor,\n          textAnchor: 'middle',\n          dominantBaseline: 'auto',\n          fontSize: theme.fontSizeSmall,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n      }\n\n      // Category label below\n      barNodes.push(text(cx, area.y + area.height - 4, String(data.labels[i] ?? `Cat ${i + 1}`), {\n        class: 'chartts-pictorialbar-label',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'auto',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      nodes.push(group(barNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i] ?? `Cat ${i + 1}`),\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, _my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const pOpts = ctx.options as PictorialBarOptions\n    const symbolSize = pOpts.symbolSize ?? 14\n\n    const barCount = series.values.length\n    const barGap = 16\n    const barWidth = Math.min(\n      (area.width - barGap * (barCount + 1)) / barCount,\n      symbolSize * 3,\n    )\n    const totalWidth = barCount * barWidth + (barCount - 1) * barGap\n    const startX = area.x + (area.width - totalWidth) / 2\n\n    for (let i = 0; i < barCount; i++) {\n      const cx = startX + i * (barWidth + barGap) + barWidth / 2\n      if (Math.abs(mx - cx) < barWidth / 2 + 5) {\n        return { seriesIndex: 0, pointIndex: i, distance: Math.abs(mx - cx), x: cx, y: area.y + area.height / 2 }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Chord diagram — shows relationships between entities via ribbons\n * connecting arcs on a circle.\n *\n * Data convention:\n * - labels: entity names (placed around the circle as arcs)\n * - series[i].values[j]: flow from entity i to entity j (adjacency matrix)\n *   series.length should equal labels.length for a square matrix.\n *\n * Alternative: arrow notation like Sankey\n * - series names contain \"→\" or \"->\" (e.g., \"A → B\")\n */\n\ninterface ChordArc {\n  index: number\n  name: string\n  total: number\n  startAngle: number\n  endAngle: number\n}\n\ninterface ChordRibbon {\n  source: number\n  target: number\n  value: number\n  sourceStart: number\n  sourceEnd: number\n  targetStart: number\n  targetEnd: number\n}\n\nexport const chordChartType = defineChartType({\n  type: 'chord',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const { arcs, ribbons } = buildChordLayout(data, options)\n    if (arcs.length === 0) return nodes\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 20\n    const innerR = outerR - 14\n\n    // Render arcs\n    for (const arc of arcs) {\n      if (arc.endAngle - arc.startAngle < 0.01) continue\n\n      const color = options.colors[arc.index % options.colors.length]!\n      const pb = new PathBuilder()\n\n      const x1o = cx + outerR * Math.cos(arc.startAngle)\n      const y1o = cy + outerR * Math.sin(arc.startAngle)\n      const x2o = cx + outerR * Math.cos(arc.endAngle)\n      const y2o = cy + outerR * Math.sin(arc.endAngle)\n      const x1i = cx + innerR * Math.cos(arc.endAngle)\n      const y1i = cy + innerR * Math.sin(arc.endAngle)\n      const x2i = cx + innerR * Math.cos(arc.startAngle)\n      const y2i = cy + innerR * Math.sin(arc.startAngle)\n      const largeArc = (arc.endAngle - arc.startAngle) > Math.PI\n\n      pb.moveTo(x1o, y1o)\n      pb.arc(outerR, outerR, 0, largeArc, true, x2o, y2o)\n      pb.lineTo(x1i, y1i)\n      pb.arc(innerR, innerR, 0, largeArc, false, x2i, y2i)\n      pb.close()\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-chord-arc',\n        fill: color,\n        stroke: color,\n        strokeWidth: 0.5,\n        'data-series': arc.index,\n        'data-index': 0,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${arc.name}: ${arc.total}`,\n      }))\n\n      // Label\n      const midAngle = (arc.startAngle + arc.endAngle) / 2\n      const labelR = outerR + 12\n      const lx = cx + labelR * Math.cos(midAngle)\n      const ly = cy + labelR * Math.sin(midAngle)\n      const anchor = Math.abs(Math.cos(midAngle)) < 0.01 ? 'middle' as const\n        : Math.cos(midAngle) > 0 ? 'start' as const : 'end' as const\n\n      nodes.push(text(lx, ly, arc.name, {\n        class: 'chartts-chord-label',\n        fill: theme.textColor,\n        textAnchor: anchor,\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    // Render ribbons\n    for (let ri = 0; ri < ribbons.length; ri++) {\n      const ribbon = ribbons[ri]!\n      const color = options.colors[ribbon.source % options.colors.length]!\n\n      const pb = new PathBuilder()\n      // Source arc on inner ring\n      const sx1 = cx + innerR * Math.cos(ribbon.sourceStart)\n      const sy1 = cy + innerR * Math.sin(ribbon.sourceStart)\n      const sx2 = cx + innerR * Math.cos(ribbon.sourceEnd)\n      const sy2 = cy + innerR * Math.sin(ribbon.sourceEnd)\n      // Target arc on inner ring\n      const tx1 = cx + innerR * Math.cos(ribbon.targetStart)\n      const ty1 = cy + innerR * Math.sin(ribbon.targetStart)\n      const tx2 = cx + innerR * Math.cos(ribbon.targetEnd)\n      const ty2 = cy + innerR * Math.sin(ribbon.targetEnd)\n\n      const srcLarge = (ribbon.sourceEnd - ribbon.sourceStart) > Math.PI\n      const tgtLarge = (ribbon.targetEnd - ribbon.targetStart) > Math.PI\n\n      pb.moveTo(sx1, sy1)\n      pb.arc(innerR, innerR, 0, srcLarge, true, sx2, sy2)\n      // Bezier to target\n      pb.quadTo(cx, cy, tx1, ty1)\n      pb.arc(innerR, innerR, 0, tgtLarge, true, tx2, ty2)\n      // Bezier back to source\n      pb.quadTo(cx, cy, sx1, sy1)\n      pb.close()\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-chord-ribbon',\n        fill: color,\n        fillOpacity: 0.35,\n        stroke: color,\n        strokeWidth: 0.3,\n        'data-series': ribbon.source,\n        'data-index': ri,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${arcs[ribbon.source]!.name} → ${arcs[ribbon.target]!.name}: ${ribbon.value}`,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const { arcs } = buildChordLayout(data, options)\n    if (arcs.length === 0) return null\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 20\n    const innerR = outerR - 14\n\n    const dx = mx - cx\n    const dy = my - cy\n    const dist = Math.sqrt(dx * dx + dy * dy)\n\n    // Check arc hits\n    if (dist >= innerR && dist <= outerR) {\n      let angle = Math.atan2(dy, dx)\n      if (angle < -Math.PI / 2) angle += Math.PI * 2\n\n      for (const arc of arcs) {\n        if (angle >= arc.startAngle && angle <= arc.endAngle) {\n          const midAngle = (arc.startAngle + arc.endAngle) / 2\n          const midR = (innerR + outerR) / 2\n          return { seriesIndex: arc.index, pointIndex: 0, distance: 0, x: cx + midR * Math.cos(midAngle), y: cy + midR * Math.sin(midAngle) }\n        }\n      }\n    }\n\n    return null\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Layout computation\n// ---------------------------------------------------------------------------\n\nfunction buildChordLayout(\n  data: PreparedData,\n  _options: ResolvedOptions,\n): { arcs: ChordArc[]; ribbons: ChordRibbon[]; matrix: number[][] } {\n  const arcs: ChordArc[] = []\n  const ribbons: ChordRibbon[] = []\n\n  // Check for arrow notation\n  const hasArrows = data.series.some(s => s.name.includes('→') || s.name.includes('->'))\n\n  // Build adjacency matrix\n  const nodeNames: string[] = []\n  const nodeMap = new Map<string, number>()\n\n  function getOrCreate(name: string): number {\n    if (nodeMap.has(name)) return nodeMap.get(name)!\n    const idx = nodeNames.length\n    nodeMap.set(name, idx)\n    nodeNames.push(name)\n    return idx\n  }\n\n  if (hasArrows) {\n    // Parse arrow notation\n    for (const series of data.series) {\n      const parts = series.name.split(/\\s*(?:→|->)\\s*/)\n      if (parts.length < 2) continue\n      getOrCreate(parts[0]!.trim())\n      getOrCreate(parts[1]!.trim())\n    }\n  } else {\n    for (let i = 0; i < data.labels.length; i++) {\n      getOrCreate(String(data.labels[i]))\n    }\n  }\n\n  const n = nodeNames.length\n  if (n === 0) return { arcs, ribbons, matrix: [] }\n\n  const matrix: number[][] = Array.from({ length: n }, () => new Array(n).fill(0))\n\n  if (hasArrows) {\n    for (const series of data.series) {\n      const parts = series.name.split(/\\s*(?:→|->)\\s*/)\n      if (parts.length < 2) continue\n      const src = getOrCreate(parts[0]!.trim())\n      const tgt = getOrCreate(parts[1]!.trim())\n      const val = series.values[0] ?? 0\n      if (val > 0) matrix[src]![tgt]! += val\n    }\n  } else {\n    for (let si = 0; si < data.series.length && si < n; si++) {\n      for (let j = 0; j < data.series[si]!.values.length && j < n; j++) {\n        const val = data.series[si]!.values[j]!\n        if (val > 0) matrix[si]![j]! = val\n      }\n    }\n  }\n\n  // Compute totals per node\n  const totals = nodeNames.map((_, i) => {\n    let total = 0\n    for (let j = 0; j < n; j++) {\n      total += matrix[i]![j]!\n      total += matrix[j]![i]!\n    }\n    return total\n  })\n\n  const grandTotal = totals.reduce((s, t) => s + t, 0)\n  if (grandTotal === 0) return { arcs, ribbons, matrix }\n\n  // Layout arcs\n  const padAngle = 0.04\n  const totalPad = padAngle * n\n  const available = Math.PI * 2 - totalPad\n\n  let angle = -Math.PI / 2\n  for (let i = 0; i < n; i++) {\n    const span = (totals[i]! / grandTotal) * available\n    arcs.push({\n      index: i,\n      name: nodeNames[i]!,\n      total: totals[i]!,\n      startAngle: angle,\n      endAngle: angle + span,\n    })\n    angle += span + padAngle\n  }\n\n  // Layout ribbons — track offsets within each arc\n  const arcOffsets = arcs.map(a => a.startAngle)\n\n  for (let i = 0; i < n; i++) {\n    for (let j = i; j < n; j++) {\n      const val = matrix[i]![j]! + matrix[j]![i]!\n      if (val <= 0) continue\n\n      const srcSpan = (matrix[i]![j]! / Math.max(totals[i]!, 1)) * (arcs[i]!.endAngle - arcs[i]!.startAngle)\n      const tgtSpan = (matrix[j]![i]! / Math.max(totals[j]!, 1)) * (arcs[j]!.endAngle - arcs[j]!.startAngle)\n\n      ribbons.push({\n        source: i,\n        target: j,\n        value: val,\n        sourceStart: arcOffsets[i]!,\n        sourceEnd: arcOffsets[i]! + srcSpan,\n        targetStart: arcOffsets[j]!,\n        targetEnd: arcOffsets[j]! + tgtSpan,\n      })\n\n      arcOffsets[i]! += srcSpan\n      arcOffsets[j]! += tgtSpan\n    }\n  }\n\n  return { arcs, ribbons, matrix }\n}\n","import type { GeoRegion } from './geo-type';\n\nexport const WORLD_REGIONS: GeoRegion[] = [\n  { name: 'Afghanistan', path: 'M659.821,141.370L662.760,142.578L664.634,142.153L664.844,140.710L666.790,140.230L668.029,139.261L667.942,136.714L669.980,136.098L670.111,134.964L671.539,135.816L672.344,135.914L673.793,135.936L675.915,136.608L676.805,136.996L678.424,135.973L679.453,136.589L679.917,135.130L681.481,135.196L681.758,134.728L681.699,133.444L682.522,132.336L684.107,133.060L684.082,134.034L684.904,134.185L685.366,136.861L686.669,137.904L687.397,137.235L688.464,136.918L689.697,135.492L691.544,135.727L694.216,135.732L694.930,136.646L693.519,137.004L692.360,137.592L689.479,137.962L686.866,138.631L685.711,140.018L686.682,141.368L687.398,142.952L686.405,144.279L686.777,145.488L686.301,146.620L683.779,146.522L685.260,148.602L683.752,149.398L683.035,151.296L683.581,153.184L682.731,154.068L681.690,153.775L679.749,154.185L679.641,155.065L677.664,155.060L676.546,156.840L676.978,159.515L673.706,160.823L671.806,160.547L671.367,161.236L669.711,160.835L667.107,161.306L662.406,159.700L664.313,156.849L663.713,154.825L661.605,154.295L661.026,152.299L659.695,149.788L660.502,148.066L659.270,147.602L659.568,145.314L659.821,141.370' },\n  { name: 'Albania', path: 'M552.172,121.840L551.948,122.881L552.433,124.192L553.561,124.937L553.588,125.741L552.801,126.184L552.742,127.178L551.673,128.709L551.220,128.486L551.117,127.785L549.611,126.748L549.259,125.290L549.287,123.204L549.548,122.254L549.078,121.772L548.821,120.799L549.781,119.293L549.994,119.868L550.648,119.598L551.262,120.418L551.896,120.731L552.172,121.840' },\n  { name: 'Algeria', path: 'M532.526,179.692L523.321,185.685L515.500,191.863L511.659,193.265L508.629,193.573L508.589,191.572L507.323,191.061L505.622,190.161L504.969,188.688L495.793,181.827L486.693,174.966L476.678,167.352L476.742,166.743L476.745,166.533L476.796,162.807L481.154,160.486L483.827,160.007L486.021,159.162L487.064,157.587L490.191,156.343L490.331,154.014L491.867,153.740L493.075,152.577L496.541,152.047L497.030,150.825L496.337,150.157L495.443,146.837L495.297,144.925L494.322,142.904L496.845,141.163L499.668,140.610L501.312,139.295L503.814,138.326L508.213,137.758L512.505,137.500L513.824,137.973L516.242,136.717L519.013,136.693L520.089,137.434L521.859,137.241L521.381,138.875L521.887,141.912L521.345,144.525L519.769,146.279L520.056,148.647L522.259,150.521L522.301,151.282L523.965,152.551L525.258,158.196L526.189,160.972L526.367,162.433L525.953,164.999L526.179,166.432L525.876,168.153L526.155,170.131L525.115,171.445L526.760,173.737L526.891,175.084L527.882,176.838L529.137,176.262L531.299,177.723L532.526,179.692' },\n  { name: 'American Samoa', path: 'M30.170,298.628L30.057,298.655L29.891,298.505L30.147,298.392L30.225,298.333L30.562,298.363L30.371,298.411L30.170,298.628' },\n  { name: 'Andorra', path: 'M504.307,119.858L504.238,119.879L504.006,120.003L503.874,120.047L503.754,120.069L503.659,120.060L503.606,119.987L503.611,119.875L503.589,119.774L503.571,119.721L503.604,119.575L503.681,119.497L503.788,119.432L503.956,119.456L504.314,119.549L504.390,119.636L504.392,119.695L504.327,119.790L504.307,119.858' },\n  { name: 'Angola', path: 'M534.483,271.375L533.775,271.707L533.050,269.342L534.174,267.985L535.014,267.456L536.050,268.534L535.039,269.195L534.579,270.004L534.483,271.375M545.263,271.982L545.924,274.325L546.702,276.211L547.328,277.228L548.373,278.872L550.206,278.618L551.124,278.175L552.649,278.620L553.073,277.833L553.788,276.001L555.507,275.878L555.663,275.333L557.076,275.321L556.822,276.454L560.183,276.427L560.209,278.405L560.755,279.618L560.324,281.514L560.503,283.448L561.411,284.615L561.187,288.357L561.877,288.068L563.076,288.146L564.797,287.675L566.051,287.860L566.320,288.836L565.971,290.361L566.423,291.836L565.985,293.014L566.195,294.100L560.456,294.060L560.089,304.066L561.861,306.638L563.588,308.603L558.516,309.884L551.900,309.439L550.041,307.932L538.932,308.068L538.513,308.289L536.907,306.867L535.131,306.773L533.481,307.309L532.152,307.907L531.926,305.930L532.350,303.165L533.344,300.286L533.503,298.936L534.430,296.102L535.102,294.813L536.711,292.756L537.614,291.356L537.934,289.027L537.813,287.245L537.001,286.120L536.285,284.213L535.619,282.326L535.773,281.672L536.633,280.426L535.815,277.388L535.263,275.283L533.889,273.293L534.157,272.682L535.304,272.259L536.107,272.318L537.082,271.940L545.263,271.982' },\n  { name: 'Antigua and Barbuda', path: 'M330.884,198.234L330.837,198.317L330.625,198.168L330.581,197.887L330.593,197.828L330.633,197.797L330.718,197.851L330.834,197.871L330.901,197.963L330.884,198.234M330.826,199.926L330.727,200.051L330.426,200.000L330.378,199.844L330.373,199.734L330.583,199.511L330.791,199.607L330.865,199.712L330.924,199.733L330.915,199.823L330.887,199.889L330.826,199.926' },\n  { name: 'Argentina', path: 'M323.443,322.919L325.279,325.190L326.075,322.660L329.188,322.790L329.695,323.464L335.197,328.594L337.458,329.073L340.989,331.395L343.909,332.625L344.480,334.012L342.467,338.792L345.290,339.648L348.369,340.128L350.427,339.623L352.560,337.214L352.652,334.439L353.913,333.836L355.490,335.651L355.745,338.163L353.698,339.896L352.057,341.177L349.425,344.229L346.453,348.517L346.232,351.034L346.096,354.266L346.678,357.398L346.231,358.098L346.390,360.131L346.504,361.772L350.341,364.477L350.448,366.673L352.366,368.061L352.559,369.617L350.933,373.701L347.478,375.409L342.463,376.072L339.563,375.752L340.539,377.651L340.586,380.013L341.500,381.556L340.282,382.632L337.797,383.054L335.019,381.940L334.276,382.741L335.542,385.780L337.524,386.700L338.623,385.736L339.843,387.324L337.801,388.274L336.350,390.176L336.908,393.252L336.817,394.890L334.469,394.899L333.060,396.471L333.145,398.772L336.340,401.018L338.898,401.639L338.984,404.392L336.698,406.122L336.368,409.720L334.638,410.914L334.244,412.323L336.325,415.446L338.629,417.188L337.567,417.036L335.173,416.564L329.266,416.162L327.511,414.408L326.567,412.156L325.057,412.350L323.726,411.259L322.221,408.028L323.576,406.679L323.625,404.732L322.766,403.180L323.097,400.561L322.506,396.498L321.582,394.697L322.478,394.117L321.832,392.965L320.471,392.352L320.872,391.069L319.356,389.910L317.595,386.382L318.405,385.759L316.740,382.031L316.336,378.874L316.274,376.033L317.513,374.877L315.916,371.767L315.142,368.841L316.571,366.761L315.821,364.100L316.634,361.024L316.024,358.132L315.217,357.557L312.832,352.129L313.775,348.895L312.978,345.849L313.475,342.992L314.761,340.042L316.349,338.087L315.350,336.853L315.753,335.841L314.914,330.600L317.691,329.049L318.264,325.782L317.849,324.995L319.805,322.153L323.443,322.919M348.341,425.743L346.209,425.889L344.564,424.847L343.132,424.767L340.645,424.765L337.842,418.049L339.328,419.443L341.434,421.699L345.205,423.504L348.763,424.255L348.341,425.743' },\n  { name: 'Armenia', path: 'M610.900,124.174L614.337,123.697L615.031,124.501L616.112,125.030L615.760,125.797L617.342,126.846L616.815,127.833L618.049,128.699L619.290,129.221L619.725,131.430L618.809,131.524L617.447,129.681L617.376,129.190L616.244,129.197L615.342,128.343L614.823,128.429L613.661,127.499L611.604,126.739L611.550,125.251L610.900,124.174' },\n  { name: 'Aruba', path: 'M307.243,214.344L307.246,214.435L307.122,214.386L306.964,214.191L306.803,214.045L306.855,213.888L306.902,213.834L307.063,213.980L307.214,214.254L307.243,214.344' },\n  { name: 'Australia', path: 'M895.327,296.781L895.981,299.248L897.910,298.062L898.637,299.393L899.787,300.621L899.228,302.015L899.274,304.711L899.375,306.281L899.989,306.665L900.192,309.353L899.599,310.983L900.055,313.116L902.682,314.758L904.306,316.253L905.810,317.621L905.269,318.383L906.349,320.355L906.580,323.757L907.833,323.067L908.602,324.429L909.383,323.946L909.034,327.279L910.482,329.209L911.442,330.409L912.838,332.955L912.708,335.483L912.147,337.275L911.277,339.222L911.615,341.894L910.480,344.677L909.504,346.133L907.669,348.938L906.880,350.741L905.300,352.995L902.797,355.856L900.123,357.401L898.033,359.837L896.439,361.391L894.355,364.112L892.467,365.700L890.490,368.083L888.944,370.277L888.520,371.285L886.426,372.391L883.469,372.507L880.374,373.813L878.521,375.047L876.228,376.414L874.852,375.006L873.573,374.445L874.859,372.785L873.126,373.387L869.646,375.693L867.874,374.830L866.676,374.326L865.321,374.098L863.300,373.177L862.642,371.213L863.405,368.795L863.628,367.186L863.009,365.894L860.693,365.510L862.339,363.965L862.729,361.625L860.509,363.804L857.885,364.390L860.059,362.640L861.219,360.825L862.882,359.285L863.653,356.956L860.384,359.638L858.292,360.713L856.246,363.214L854.735,361.920L855.506,360.252L854.800,357.971L853.892,356.793L854.686,356.067L852.071,354.161L850.247,354.072L848.316,352.541L843.449,352.838L839.574,353.964L836.153,355.014L833.710,354.805L830.289,356.418L827.724,357.143L826.591,358.792L825.136,360.070L822.876,360.146L821.120,360.426L819.010,359.852L816.993,360.196L815.135,360.340L812.960,362.017L812.247,361.875L810.609,362.764L808.972,363.766L807.116,363.641L805.361,363.640L803.300,361.630L802.099,361.033L802.790,359.231L804.248,358.803L804.947,358.087L805.254,356.957L806.350,354.771L806.713,352.907L806.430,349.729L806.625,347.934L807.221,346.142L806.697,344.096L806.872,343.172L806.015,341.919L806.326,339.456L805.440,336.967L805.416,335.625L806.245,336.985L806.097,334.068L807.196,334.980L807.675,336.197L808.052,334.587L807.364,332.111L807.288,331.120L806.834,330.179L807.463,328.361L808.161,327.587L808.822,326.014L808.872,324.176L810.414,321.913L810.175,324.308L811.725,322.144L814.131,321.093L815.710,319.752L818.010,318.598L819.295,318.352L819.971,318.740L822.344,317.568L824.065,317.219L824.612,316.530L825.385,316.243L826.881,316.317L829.902,315.397L831.619,314.001L832.598,312.320L834.471,310.724L834.805,309.469L835.165,307.759L837.536,305.087L838.230,307.802L839.503,307.175L838.779,305.689L839.901,304.163L840.995,304.844L841.739,302.452L843.506,300.905L844.330,299.663L845.777,299.128L845.926,298.249L847.091,298.616L847.235,297.826L848.500,297.375L849.882,296.952L851.740,298.395L853.040,300.257L854.758,300.279L856.471,300.573L856.101,298.847L857.732,296.325L859.076,295.503L858.744,294.717L860.164,292.922L861.973,291.812L863.338,292.186L865.730,291.593L865.883,289.986L863.992,288.951L865.520,288.494L867.250,289.274L868.552,290.563L870.773,291.368L871.602,291.050L873.188,292.017L874.916,291.116L875.917,291.390L876.641,290.786L877.705,292.342L876.750,294.025L875.539,295.295L874.578,295.400L874.734,296.657L873.722,298.228L872.544,299.774L872.626,300.661L874.487,302.399L876.413,303.407L877.622,304.489L879.251,306.353L880.024,306.350L881.305,307.155L881.535,308.126L883.945,309.193L885.961,308.118L886.826,306.429L887.654,305.036L888.330,303.312L889.653,300.810L889.486,299.289L889.808,298.374L889.732,296.575L890.413,294.205L891.028,293.567L890.741,292.517L891.633,290.849L892.391,289.122L892.583,288.225L893.769,287.047L894.339,288.585L894.262,290.558L894.897,290.938L894.835,292.259L895.618,293.858L895.581,295.639L895.327,296.781M870.593,381.909L872.342,382.965L874.012,382.546L876.400,381.957L877.788,382.163L875.483,385.793L873.897,386.847L871.957,389.307L871.648,388.470L868.455,390.601L868.047,390.437L866.568,390.342L866.778,387.724L867.786,385.705L868.104,383.041L869.106,381.638L870.593,381.909' },\n  { name: 'Austria', path: 'M541.436,102.638L541.359,103.892L539.982,103.898L540.512,104.563L539.863,106.539L539.436,107.057L537.288,107.133L536.097,107.829L534.043,107.591L530.467,106.799L529.850,105.732L527.453,106.265L527.201,106.849L525.686,106.412L524.426,106.329L523.286,105.770L523.625,105.019L523.503,104.475L524.234,104.305L525.519,105.158L525.824,104.348L527.992,104.479L529.709,103.928L530.888,104.023L531.693,104.651L531.887,104.129L531.408,102.130L532.257,101.740L533.018,100.326L534.894,101.313L536.168,100.058L537.004,99.829L538.964,100.765L540.092,100.606L541.263,101.185L541.101,101.575L541.436,102.638' },\n  { name: 'Azerbaijan', path: 'M620.460,123.784L621.631,123.993L621.895,123.215L623.136,121.982L624.834,123.593L626.623,125.762L627.845,125.905L628.823,126.730L626.774,126.976L626.800,129.427L626.560,130.543L625.751,131.287L626.104,132.865L625.490,133.024L623.586,131.356L624.193,129.780L623.269,128.845L622.349,129.080L619.725,131.430L619.290,129.221L618.049,128.699L616.815,127.833L617.342,126.846L615.760,125.797L616.112,125.030L615.031,124.501L614.337,123.697L614.856,123.198L616.935,124.077L618.346,124.259L618.615,123.901L617.010,122.246L617.578,121.824L618.313,121.926L620.460,123.784M615.342,128.343L616.244,129.197L617.376,129.190L617.447,129.681L618.809,131.524L616.972,131.101L615.429,129.630L614.823,128.429L615.342,128.343' },\n  { name: 'Bahamas', path: 'M292.770,169.886L291.910,172.121L291.486,171.718L291.822,170.075L290.838,168.832L290.897,168.471L292.770,169.886M290.558,169.917L287.533,170.421L287.556,169.257L288.865,169.006L290.623,169.100L290.558,169.917M289.950,178.786L289.265,178.942L288.807,177.131L287.909,176.220L288.786,174.225L289.576,174.351L290.165,176.961L289.950,178.786' },\n  { name: 'Bahrain', path: 'M636.457,172.109L636.398,172.349L636.305,172.265L636.046,171.850L636.076,171.558L635.928,171.141L635.961,171.021L636.208,170.966L636.269,170.984L636.209,171.118L636.376,171.350L636.441,171.734L636.457,172.109' },\n  { name: 'Bangladesh', path: 'M751.875,184.190L752.159,186.445L751.138,185.969L751.695,188.499L750.672,186.860L750.275,185.258L749.532,183.744L748.124,181.914L745.606,181.788L746.044,183.084L745.447,184.834L744.197,184.196L743.886,184.769L743.066,184.426L741.973,184.144L741.176,181.555L739.896,179.190L740.084,177.295L738.297,176.453L738.733,175.307L740.209,174.135L737.922,172.471L738.441,170.337L740.852,171.696L742.171,171.851L742.860,174.038L745.520,174.469L748.016,174.422L749.683,174.959L748.835,177.620L747.650,177.802L747.080,179.592L748.807,181.221L748.950,179.212L749.697,179.202L751.875,184.190' },\n  { name: 'Barbados', path: 'M336.051,212.363L335.969,212.425L335.729,212.300L335.651,212.148L335.668,211.667L335.822,211.622L336.086,212.002L336.245,212.140L336.051,212.363' },\n  { name: 'Belarus', path: 'M554.937,85.113L557.201,85.133L559.565,84.000L559.841,82.303L561.580,81.353L561.123,80.042L562.433,79.550L564.688,78.421L567.253,79.155L567.728,79.881L568.866,79.532L571.266,80.230L571.786,81.604L571.446,82.408L573.278,84.377L574.334,84.926L574.298,85.469L575.982,85.999L576.816,86.801L576.031,87.458L574.112,87.354L573.713,87.635L574.457,88.633L575.410,90.559L573.407,90.738L572.798,91.398L572.926,92.912L571.924,92.621L569.797,92.765L569.048,92.062L568.246,92.586L567.274,92.152L565.388,92.091L562.614,91.370L560.177,91.134L558.346,91.201L557.163,92.016L556.041,92.133L555.804,90.794L554.876,89.400L556.205,88.787L556.045,87.588L555.229,86.444L554.937,85.113' },\n  { name: 'Belgium', path: 'M507.910,92.833L509.663,93.069L511.857,92.444L513.411,93.761L514.752,94.463L514.555,96.495L513.931,96.609L513.721,98.324L511.571,96.925L510.339,97.164L508.626,95.740L507.485,94.533L506.370,94.484L506.007,93.426L507.910,92.833' },\n  { name: 'Belize', path: 'M255.941,197.501L255.977,197.038L256.326,196.893L256.777,197.265L257.989,195.367L258.514,195.326L258.468,195.787L258.985,195.801L258.835,196.657L258.227,198.017L258.407,198.503L257.983,199.628L258.120,199.929L257.609,201.518L256.968,202.352L256.460,202.452L255.783,203.541L254.963,203.542L255.614,199.993L255.941,197.501' },\n  { name: 'Benin', path: 'M507.460,233.819L505.170,234.186L504.486,232.016L504.605,224.795L504.047,224.147L503.941,222.603L502.980,221.502L502.134,220.574L502.485,218.918L503.434,218.562L503.995,217.187L505.343,216.894L505.945,215.953L506.869,215.032L507.857,215.024L509.967,216.834L509.863,217.879L510.491,219.744L509.951,221.010L510.245,221.856L508.907,223.802L508.057,224.766L507.539,226.750L507.612,228.750L507.460,233.819' },\n  { name: 'Bermuda', path: 'M328.813,151.951L328.554,152.058L328.490,152.049L328.450,152.013L328.713,151.906L328.965,151.657L329.032,151.673L328.813,151.951' },\n  { name: 'Bhutan', path: 'M746.000,166.170L747.304,167.173L747.524,169.105L745.349,169.198L743.035,168.988L741.445,169.479L738.756,168.286L738.570,167.656L739.867,165.318L741.150,164.520L743.216,165.248L744.648,165.324L746.000,166.170' },\n  { name: 'Bolivia', path: 'M329.188,322.790L326.075,322.660L325.279,325.190L323.443,322.919L319.805,322.153L317.849,324.995L315.938,325.425L314.394,321.090L312.538,317.563L313.090,314.521L311.531,313.189L310.951,310.920L309.404,308.781L310.809,305.388L309.377,302.744L309.906,301.687L309.307,300.521L310.278,298.950L310.156,296.275L310.146,294.064L310.669,293.000L307.949,287.938L310.020,288.205L311.438,288.136L311.992,287.185L314.326,285.910L315.713,284.730L319.312,284.197L319.145,286.554L319.561,287.763L319.470,289.871L322.640,292.688L325.760,293.207L326.915,294.381L328.815,295.004L330.009,295.918L331.740,295.887L333.394,296.819L333.620,298.637L334.209,299.555L334.330,300.911L333.531,300.964L334.892,304.625L340.165,304.755L339.908,306.571L340.302,307.812L341.869,308.695L342.670,310.650L342.381,313.127L341.742,314.505L342.148,316.297L341.355,316.947L341.223,315.977L338.550,314.369L336.010,314.325L331.328,315.240L330.281,318.007L330.384,319.698L329.695,323.464L329.188,322.790' },\n  { name: 'Bosnia and Herzegovina', path: 'M547.351,112.650L548.253,112.642L547.748,113.987L549.058,115.163L548.823,116.602L548.244,116.737L547.799,117.017L547.044,117.727L546.820,119.410L544.492,118.252L543.440,116.974L542.430,116.297L541.190,115.155L540.576,114.207L539.249,112.777L539.671,111.505L540.622,112.210L541.108,111.573L542.263,111.505L544.447,112.015L546.163,111.972L547.351,112.650' },\n  { name: 'Botswana', path: 'M570.142,311.788L570.672,312.349L571.466,314.168L574.419,317.622L575.572,317.961L575.528,319.070L576.239,321.064L578.320,321.547L579.986,322.968L576.035,325.283L573.495,327.631L572.502,329.726L571.637,330.908L570.155,331.159L569.607,332.664L569.276,333.645L567.507,334.377L565.320,334.222L564.080,333.341L562.962,332.959L561.606,333.688L560.868,335.194L559.543,336.140L558.127,337.543L556.184,337.864L555.636,336.760L555.976,334.844L554.512,331.856L553.797,331.384L554.093,322.206L556.777,322.097L557.210,310.895L559.249,310.791L563.503,309.690L564.507,310.987L566.295,309.754L567.125,309.747L568.693,309.039L569.177,309.274L570.142,311.788' },\n  { name: 'Brazil', path: 'M346.453,348.517L349.425,344.229L352.057,341.177L353.698,339.896L355.745,338.163L355.490,335.651L353.913,333.836L352.652,334.439L352.954,332.624L353.138,330.764L352.987,329.036L351.961,328.465L350.991,328.974L349.969,328.834L349.543,327.624L349.030,324.742L348.437,323.803L346.524,322.952L345.472,323.568L342.547,322.964L342.326,318.695L341.355,316.947L342.148,316.297L341.742,314.505L342.381,313.127L342.670,310.650L341.869,308.695L340.302,307.812L339.908,306.571L340.165,304.755L334.892,304.625L333.531,300.964L334.330,300.911L334.209,299.555L333.620,298.637L333.394,296.819L331.740,295.887L330.009,295.918L328.815,295.004L326.915,294.381L325.760,293.207L322.640,292.688L319.470,289.871L319.561,287.763L319.145,286.554L319.312,284.197L315.713,284.730L314.326,285.910L311.992,287.185L311.438,288.136L310.020,288.205L307.949,287.938L306.427,288.480L305.146,288.119L305.054,283.342L302.866,285.195L300.420,285.114L299.301,283.437L297.458,283.255L297.987,281.904L296.370,279.991L295.100,277.159L295.806,276.584L295.748,275.256L297.385,274.348L297.038,272.648L297.701,271.554L297.841,270.086L300.955,267.946L303.218,267.341L303.582,266.868L306.085,267.016L307.184,258.394L307.226,257.030L306.760,255.229L305.508,254.082L305.542,251.797L307.115,251.279L307.665,251.605L307.779,250.400L306.157,250.075L306.157,248.108L311.566,248.178L312.502,247.094L313.257,248.091L313.767,249.946L314.298,249.559L315.799,251.222L317.962,251.018L318.515,250.056L320.592,249.322L321.743,248.806L322.087,247.474L324.084,246.579L323.944,245.918L321.597,245.648L321.243,243.668L321.389,241.559L320.160,240.744L320.684,240.455L322.732,240.857L324.926,241.643L325.739,240.900L327.741,240.412L330.863,239.235L331.895,238.035L331.553,237.147L333.000,237.008L333.621,237.733L333.239,239.114L334.185,239.590L334.800,241.051L334.014,242.159L333.533,244.836L334.220,246.426L334.399,247.881L336.086,249.356L337.447,249.512L337.762,248.897L338.642,248.761L339.906,248.209L340.821,247.373L342.353,247.639L343.030,247.527L344.536,247.784L344.795,247.142L344.338,246.517L344.628,245.606L345.744,245.885L347.059,245.564L348.640,246.230L349.844,246.879L350.715,246.026L351.334,246.158L351.701,247.043L353.033,246.818L354.112,245.624L354.995,243.308L356.673,240.430L357.620,240.282L358.285,242.021L359.772,247.520L361.251,248.040L361.299,250.210L359.178,252.799L360.036,253.747L364.952,254.241L365.090,257.392L367.175,255.329L370.682,256.459L375.316,258.380L376.692,260.222L376.256,261.963L379.473,260.994L384.892,262.657L389.037,262.535L393.165,265.137L396.742,268.660L398.891,269.567L401.265,269.693L402.290,270.685L403.310,274.689L403.808,276.591L402.808,281.790L401.442,283.843L397.682,288.218L396.050,291.773L394.108,294.499L393.421,294.561L392.737,296.874L393.186,302.766L392.682,307.613L392.503,309.686L391.705,310.927L391.450,315.131L388.941,319.236L388.694,322.483L386.587,323.846L386.079,325.731L383.131,325.723L378.951,326.932L377.144,328.331L374.180,329.249L371.187,331.753L369.235,334.872L369.105,337.220L369.745,338.956L369.598,342.133L369.163,343.668L367.489,345.398L365.288,350.933L363.345,353.427L361.778,354.898L361.054,357.889L359.603,359.687L358.583,357.906L359.503,356.414L357.624,354.275L355.257,352.537L352.186,350.522L351.213,350.614L348.124,348.182L346.453,348.517' },\n  { name: 'Brunei', path: 'M816.831,239.268L817.896,238.092L820.156,236.369L820.127,237.918L820.022,239.926L818.694,239.826L818.141,240.898L816.831,239.268' },\n  { name: 'Bulgaria', path: 'M556.648,114.563L557.501,115.820L558.448,115.596L560.425,116.073L564.127,116.234L565.276,115.454L568.135,114.743L570.099,115.855L571.615,116.176L570.477,117.443L569.838,119.630L570.879,121.375L568.647,120.965L566.186,121.927L566.342,123.450L564.066,123.739L562.154,122.670L560.214,123.511L558.325,123.422L557.931,121.400L556.561,120.418L556.932,119.987L556.621,119.623L556.944,118.650L557.803,117.694L556.444,116.374L556.103,115.256L556.648,114.563' },\n  { name: 'Burkina Faso', path: 'M492.180,223.179L490.289,222.368L488.993,222.487L488.024,223.278L486.782,222.614L486.303,221.574L485.063,220.889L484.889,219.063L485.649,217.730L485.591,216.665L487.793,214.059L488.206,211.902L488.964,211.135L490.295,211.559L491.451,210.919L491.828,210.111L493.968,208.701L494.495,207.718L497.067,206.414L498.582,205.966L499.268,206.570L501.031,206.555L500.814,208.079L501.184,209.512L502.736,211.565L502.823,213.087L506.003,213.800L505.945,215.953L505.343,216.894L503.995,217.187L503.434,218.562L502.485,218.918L500.066,218.851L498.788,218.601L497.896,219.108L496.676,218.879L491.878,219.027L491.808,220.811L492.180,223.179' },\n  { name: 'Burundi', path: 'M581.397,267.650L581.248,263.858L580.561,262.428L582.244,262.675L583.107,260.885L584.581,261.091L584.732,262.329L585.325,263.042L585.343,264.064L584.653,264.722L583.561,266.362L582.546,267.501L581.397,267.650' },\n  { name: 'Cambodia', path: 'M785.974,220.065L784.689,218.427L782.974,215.178L781.950,211.381L783.457,208.766L786.956,208.166L789.581,208.617L791.977,209.850L793.002,207.682L795.559,208.839L796.413,210.937L796.460,214.705L792.068,217.125L793.474,219.030L790.597,219.258L788.332,220.524L785.974,220.065' },\n  { name: 'Cameroon', path: 'M536.299,246.371L535.953,246.200L534.311,246.605L532.622,246.183L531.304,246.390L526.786,246.318L527.185,243.835L526.096,241.757L524.829,241.223L524.262,239.814L523.550,239.363L523.580,238.494L524.285,236.269L525.588,233.235L526.390,233.207L528.030,231.366L529.080,231.314L530.644,232.606L532.540,231.547L532.790,230.240L533.404,228.973L533.822,227.382L535.293,226.086L535.835,223.885L536.417,223.184L536.792,221.550L537.497,219.543L539.791,217.110L539.922,216.065L540.215,215.497L539.106,214.244L539.181,213.243L539.957,213.063L541.081,215.076L541.295,217.163L541.224,219.252L542.769,222.110L541.225,222.079L540.446,222.303L539.183,221.987L538.595,223.471L540.242,225.306L541.452,225.840L541.853,227.142L542.744,229.309L542.318,230.161L540.951,233.348L540.291,233.919L540.097,236.357L540.384,237.681L540.164,238.618L541.481,240.260L541.722,241.389L542.753,243.012L544.026,244.024L544.156,245.458L544.452,246.369L544.259,248.067L542.050,247.324L539.802,246.494L536.299,246.371' },\n  { name: 'Canada', path: 'M387.585,9.492L391.830,9.638L395.136,9.876L397.692,10.381L397.169,10.878L392.353,11.686L387.936,12.062L386.005,12.479L389.683,12.470L384.585,13.599L381.276,14.126L376.745,15.738L372.823,16.124L371.282,16.597L365.769,16.846L367.902,17.138L366.300,17.552L366.679,18.698L364.244,19.495L360.861,20.152L359.130,21.061L355.931,21.755L355.664,22.281L358.849,22.191L358.340,22.758L352.087,24.152L347.951,23.511L342.196,23.871L339.775,23.590L336.452,23.468L337.462,22.354L341.388,21.828L342.334,20.152L343.601,19.989L347.315,20.991L346.461,19.502L344.063,19.056L346.471,18.157L350.181,17.604L351.534,16.794L350.045,15.886L350.566,14.806L355.166,14.886L356.278,15.088L359.780,14.409L356.188,14.194L350.052,14.313L347.854,13.681L347.430,12.928L346.185,12.383L346.669,11.748L349.627,11.393L351.655,11.332L355.312,11.031L358.627,10.337L360.557,10.434L361.709,10.955L364.187,9.950L366.716,9.652L369.902,9.447L375.003,9.369L375.651,9.570L380.728,9.256L384.153,9.374L387.585,9.492M348.965,16.064L350.258,16.814L347.114,17.505L341.943,19.252L338.614,19.419L335.274,19.122L334.472,18.175L335.482,17.333L337.582,16.714L334.372,16.731L333.371,15.959L333.511,14.980L335.869,14.153L337.847,13.585L339.770,13.455L339.620,13.028L343.686,12.933L344.518,13.927L346.867,14.326L349.221,14.678L348.965,16.064M322.480,19.165L321.971,20.134L319.380,19.876L317.408,19.122L313.572,19.036L316.176,18.346L314.776,17.786L315.814,16.896L318.834,17.213L322.505,18.060L322.480,19.165M329.244,19.787L326.029,20.267L325.230,19.727L325.533,18.856L326.570,17.894L328.734,17.987L329.575,18.141L330.723,18.948L329.244,19.787M306.319,18.521L303.544,18.974L300.605,18.972L301.096,18.641L303.872,17.945L304.670,18.051L306.319,18.521M302.519,20.623L298.248,21.292L296.635,20.542L299.122,19.801L302.051,19.564L304.063,19.928L302.519,20.623M331.338,21.035L330.441,21.101L327.248,20.953L327.546,20.304L331.107,20.338L331.861,20.769L331.338,21.035M291.571,20.744L288.748,22.528L286.178,23.334L284.306,23.448L279.429,24.442L275.948,24.798L274.216,24.295L274.216,24.295L279.949,22.557L285.903,21.053L288.613,21.085L291.571,20.744M328.668,22.015L329.809,22.762L333.396,22.757L334.105,23.521L332.704,24.394L334.228,24.919L334.789,25.471L337.176,25.573L339.672,25.768L343.153,25.264L347.122,25.067L349.960,25.230L351.070,26.106L350.556,27.084L348.849,27.759L345.603,28.305L343.447,27.996L337.717,28.388L333.808,28.433L331.043,28.119L326.792,27.301L327.558,25.990L328.660,24.838L327.990,23.824L324.538,23.540L323.287,22.821L325.116,21.868L328.668,22.015M301.394,24.097L301.006,24.924L303.166,24.536L304.962,24.637L303.793,25.775L301.210,26.876L294.446,27.270L288.493,28.370L285.561,28.428L286.257,27.599L291.469,26.511L282.642,26.788L280.636,26.372L286.455,24.103L289.114,23.453L293.161,24.237L294.532,25.613L297.533,25.789L297.926,23.567L300.752,22.721L302.267,22.990L301.394,24.097M320.690,22.893L320.776,23.970L319.387,25.161L316.441,26.888L313.099,27.149L311.514,26.755L313.250,25.400L309.987,25.579L312.155,23.784L314.034,23.856L317.777,23.064L320.176,23.198L320.690,22.893M324.897,26.939L322.958,27.924L320.408,27.735L318.768,27.072L320.989,26.011L324.399,25.385L325.065,26.200L324.897,26.939M263.752,36.078L257.094,37.302L257.419,36.189L254.567,34.845L256.744,33.769L260.386,31.913L264.106,30.243L264.175,28.686L271.035,28.289L273.096,28.816L277.757,28.957L278.741,29.694L279.552,30.763L276.410,31.404L269.601,33.190L265.078,34.969L263.752,36.078M320.486,32.550L316.642,34.449L314.513,34.354L315.428,32.122L316.662,30.859L318.683,29.779L321.216,29.087L325.077,29.175L328.137,29.793L323.233,32.056L320.486,32.550M309.407,29.826L311.145,30.361L314.854,30.039L314.638,30.776L311.670,31.995L313.529,33.088L310.986,35.375L306.821,36.359L305.138,36.147L304.744,35.177L301.888,33.216L302.753,32.402L306.369,32.718L305.920,31.056L309.407,29.826M334.106,31.570L334.267,33.154L337.778,31.106L343.477,30.062L344.636,32.691L343.016,34.354L347.438,33.617L350.051,32.607L353.361,33.892L355.140,35.103L354.577,36.212L358.633,35.637L359.529,37.256L363.606,38.259L364.643,39.284L365.078,41.790L360.647,43.047L364.426,44.809L367.340,45.401L368.949,47.881L372.105,48.060L370.465,49.954L365.112,53.088L363.152,51.935L361.314,49.339L358.430,49.678L357.276,51.223L358.588,52.792L360.788,54.078L361.285,54.828L361.284,57.625L359.535,59.655L357.198,58.890L352.984,56.628L354.750,59.063L356.130,60.769L355.984,61.755L350.676,60.627L346.914,58.987L345.062,57.611L346.249,56.814L343.873,55.362L341.560,53.991L341.124,54.810L334.716,55.261L333.500,54.291L336.165,52.250L340.148,52.202L344.692,51.858L344.596,50.894L346.168,49.548L350.476,46.920L350.646,45.727L350.430,44.803L348.134,43.493L344.621,42.576L346.356,41.893L345.319,40.215L343.657,40.062L342.725,39.169L341.092,39.939L337.228,40.286L330.376,39.683L326.789,38.933L323.900,38.550L323.042,37.657L326.127,36.498L323.345,36.487L325.026,33.914L328.534,31.641L331.416,30.604L336.916,29.928L334.106,31.570M353.591,31.710L353.230,32.412L351.240,32.337L349.209,32.284L346.834,32.625L346.398,32.471L345.362,31.124L346.176,30.209L347.226,30.040L351.365,30.314L353.591,31.710M300.421,30.903L296.986,32.580L295.868,30.802L296.894,30.446L299.553,30.344L300.421,30.903M281.098,31.662L278.785,32.853L283.937,32.084L285.195,33.367L288.796,32.069L289.651,32.902L288.549,35.399L290.657,34.345L292.076,31.743L294.161,31.371L295.634,31.777L296.710,32.802L295.346,35.278L294.093,37.070L296.119,38.329L298.493,39.532L297.255,40.715L293.774,40.932L294.158,41.969L292.621,42.959L289.331,42.535L286.508,41.806L284.017,41.970L279.388,42.885L273.877,43.290L270.025,43.545L270.153,42.272L268.114,41.536L266.030,41.838L265.669,39.701L267.300,39.424L270.875,38.990L273.551,39.105L276.644,38.662L273.475,38.069L269.008,38.271L266.256,38.220L266.312,37.283L272.059,36.267L268.990,36.302L266.354,35.633L270.237,33.729L272.770,32.718L279.700,31.171L281.098,31.662M318.219,40.949L316.096,43.708L320.407,41.594L321.520,43.330L319.420,45.332L320.052,47.152L323.627,45.202L326.805,42.873L329.058,39.912L331.752,40.119L334.431,40.516L336.200,41.855L335.401,43.194L332.895,44.632L333.339,46.077L332.174,47.389L326.806,49.276L323.617,49.692L322.055,48.880L320.449,50.235L316.763,52.510L315.300,53.719L311.553,55.630L308.376,55.817L305.865,57.011L304.449,58.847L301.694,59.201L297.423,61.490L292.771,64.671L290.306,66.899L287.945,70.286L290.922,70.774L290.176,73.514L289.818,75.734L293.367,75.156L296.812,76.423L298.417,77.536L299.221,78.918L301.622,79.724L303.340,80.957L307.063,81.126L309.419,81.408L307.712,84.001L306.929,87.024L306.967,90.390L309.108,93.246L311.418,92.267L314.185,89.175L315.234,84.424L314.355,82.842L318.769,81.443L322.487,79.392L324.841,77.352L325.690,75.396L325.473,72.910L323.925,70.708L328.211,67.641L328.748,65.069L330.648,60.657L332.544,60.005L335.808,60.773L337.881,61.048L340.098,60.306L341.581,61.263L343.359,62.901L343.423,63.997L347.222,64.211L345.892,66.585L344.835,70.261L346.665,70.719L347.484,72.442L351.492,70.817L355.094,67.588L357.201,66.262L357.741,68.841L359.032,72.574L360.037,76.085L358.335,77.922L360.695,79.573L362.077,81.245L365.472,82.006L366.627,82.966L366.669,85.511L368.356,85.910L368.914,87.044L367.941,90.424L365.833,91.555L363.759,92.610L359.447,93.679L355.537,96.150L351.285,96.638L346.378,96.005L342.776,95.983L340.201,96.192L337.388,98.379L333.828,99.739L328.873,103.800L325.026,106.633L327.297,106.129L332.661,102.097L338.646,99.540L342.375,99.235L344.026,100.739L341.043,102.800L340.718,106.107L340.755,108.422L343.468,109.955L347.702,109.511L351.254,106.061L350.736,108.287L351.989,109.399L348.299,111.409L342.236,113.232L339.396,114.469L335.938,116.672L334.101,116.447L334.795,113.859L339.912,111.327L335.901,111.427L333.010,111.801L331.986,110.066L333.442,105.882L332.660,104.997L330.832,105.518L330.302,104.712L327.602,107.028L325.991,109.415L324.607,110.811L323.379,111.286L322.527,111.440L322.001,112.198L317.413,112.200L313.623,112.221L312.304,112.784L308.895,114.987L308.498,115.225L307.274,116.416L304.972,116.416L302.503,116.428L301.193,116.913L301.380,117.514L301.267,118.447L301.105,118.757L297.246,120.278L294.463,120.759L290.904,122.391L290.268,122.391L289.591,121.909L289.474,121.472L289.652,121.153L290.619,120.083L292.445,118.401L293.867,116.593L294.374,113.935L294.945,111.156L292.974,109.716L293.513,109.171L293.311,108.796L292.632,108.796L292.344,108.309L292.533,107.583L291.916,107.900L291.296,107.805L291.578,107.501L291.129,107.199L291.241,106.392L289.763,105.410L288.229,104.388L286.365,103.201L284.577,102.088L281.999,102.957L281.186,102.987L278.553,102.189L276.391,102.588L274.476,101.637L272.224,101.148L270.617,100.959L270.113,100.440L270.500,98.755L269.673,98.770L269.091,99.949L264.070,99.947L255.767,99.949L247.521,99.949L240.237,99.949L232.958,99.949L225.799,99.949L218.403,99.949L216.017,99.949L208.813,99.949L201.922,99.949L201.601,99.941L198.832,96.928L198.096,95.627L194.709,94.382L195.445,91.720L197.218,89.874L195.193,88.593L196.684,86.168L195.578,83.985L196.758,82.435L199.268,81.008L200.862,79.162L198.645,77.300L199.367,73.962L199.886,71.862L199.050,70.543L198.656,69.345L198.888,67.831L195.763,68.779L192.041,70.414L191.889,68.491L191.565,67.210L190.242,66.428L188.154,66.344L205.686,50.386L217.649,40.371L220.620,41.021L222.270,42.319L224.089,42.567L227.155,41.441L230.550,40.599L233.157,40.928L237.482,39.743L241.549,39.101L241.636,40.189L243.818,39.561L245.786,38.364L246.814,38.635L247.485,40.995L252.131,39.191L250.200,41.213L253.131,40.771L254.705,39.983L256.967,40.139L258.877,41.272L262.597,42.261L264.925,42.719L267.075,42.546L268.483,43.914L264.317,45.253L267.456,45.831L273.285,45.513L275.467,45.041L276.153,46.659L279.635,45.294L278.602,44.149L280.762,43.226L283.341,43.101L285.204,42.831L286.263,43.476L287.008,44.941L289.476,44.726L292.035,45.943L295.579,45.514L298.510,45.579L299.674,43.900L301.871,43.429L304.270,44.344L302.181,46.897L305.230,44.745L306.812,44.818L309.898,42.105L309.079,40.441L307.651,39.365L310.497,36.557L314.565,34.713L316.753,35.121L317.694,36.243L317.758,39.107L314.912,40.403L318.219,40.949M307.128,42.001L305.103,42.947L303.050,42.130L301.161,42.425L299.426,41.212L301.895,40.376L304.301,39.229L305.753,39.971L306.555,40.457L306.739,40.969L307.128,42.001M343.624,47.287L341.226,47.422L341.574,46.101L343.428,44.589L345.537,44.215L346.651,44.962L345.939,46.118L345.471,46.489L343.624,47.287M321.564,51.311L321.100,52.498L322.474,52.082L323.194,52.789L324.878,53.744L326.751,54.624L326.101,55.967L327.807,55.747L328.754,56.684L326.306,57.573L323.397,56.894L323.004,55.622L319.925,57.125L315.922,58.587L316.268,56.934L313.188,57.206L315.972,55.808L317.712,53.585L320.210,51.091L321.564,51.311M323.120,59.552L319.602,61.110L318.111,61.045L318.126,60.281L320.566,58.977L323.509,59.004L323.120,59.552M327.860,61.112L326.104,62.596L325.287,62.356L325.232,61.513L325.454,61.318L326.811,60.470L327.660,60.532L327.860,61.112M189.076,84.339L189.858,84.730L192.294,84.489L188.854,87.904L188.977,90.322L188.036,90.317L187.712,88.941L187.955,87.557L187.524,86.620L188.160,85.298L189.076,84.339M365.375,94.814L362.907,97.456L364.802,96.429L366.211,97.077L365.059,98.147L366.967,98.988L368.293,98.241L370.446,99.184L369.077,101.432L370.923,100.907L370.791,102.535L371.034,104.442L369.269,107.143L368.123,107.257L366.664,106.678L367.892,104.167L367.318,103.777L363.725,106.439L362.288,106.332L364.433,104.890L362.295,104.145L359.611,104.328L354.886,104.234L354.787,103.326L356.635,102.246L355.827,101.412L358.424,99.563L362.471,94.720L364.548,93.008L366.971,91.972L368.031,92.103L367.296,92.919L365.375,94.814M199.345,101.452L197.849,101.879L194.745,100.486L194.720,99.397L193.248,98.323L193.382,97.448L191.260,96.896L191.607,95.259L192.357,94.563L194.366,95.218L195.488,95.675L197.504,95.993L197.547,97.034L197.806,98.490L199.417,99.757L199.345,101.452M350.126,99.626L348.928,99.681L346.098,98.719L344.326,97.270L345.246,97.012L348.169,97.781L350.233,99.063L350.126,99.626M343.062,107.467L344.717,107.878L347.031,107.795L345.416,109.052L344.435,109.252L341.725,107.949L341.447,106.922L342.688,105.975L343.062,107.467' },\n  { name: 'Cape Verde', path: 'M430.995,200.211L430.726,200.275L430.614,200.244L430.586,199.994L430.538,199.829L430.553,199.756L431.177,199.433L431.391,199.487L431.533,199.745L431.425,199.887L430.995,200.211M431.757,200.614L431.529,200.690L431.390,200.680L431.193,200.569L431.260,200.449L431.482,200.315L431.632,200.287L431.746,200.525L431.757,200.614M437.222,201.114L437.129,201.275L437.029,201.039L436.973,200.983L436.955,200.644L437.117,200.542L437.195,200.534L437.186,200.885L437.222,201.114M433.928,201.229L434.038,201.322L434.074,201.388L433.904,201.423L433.500,201.302L433.388,201.376L433.271,201.636L433.076,201.242L433.095,201.098L433.141,201.056L433.427,201.159L433.928,201.229M437.099,202.441L437.326,202.498L437.414,202.478L437.560,202.490L437.710,202.655L437.734,202.831L437.650,203.051L437.341,203.231L437.167,203.210L436.966,203.045L437.095,202.720L437.099,202.441M435.529,206.306L435.356,206.595L434.992,206.572L434.807,206.453L434.599,206.090L434.615,205.809L434.700,205.566L434.694,205.354L434.727,205.298L434.838,205.335L434.851,205.477L435.171,205.826L435.292,205.894L435.529,206.306M436.263,205.901L436.186,205.913L436.075,205.771L436.107,205.575L436.096,205.523L436.204,205.314L436.403,205.332L436.449,205.487L436.448,205.807L436.263,205.901M433.142,206.783L432.925,206.903L432.776,206.851L432.637,206.727L432.573,206.548L432.632,206.394L432.926,206.211L433.096,206.270L433.181,206.553L433.142,206.783' },\n  { name: 'Cayman Islands', path: 'M282.116,191.515L281.983,191.562L281.886,191.544L282.124,191.413L282.187,191.369L282.238,191.346L282.290,191.345L282.353,191.372L282.350,191.392L282.116,191.515M281.689,191.526L281.661,191.544L281.575,191.531L281.360,191.659L281.275,191.652L281.306,191.607L281.352,191.564L281.403,191.533L281.448,191.521L281.591,191.495L281.658,191.491L281.701,191.521L281.689,191.526M277.767,192.656L277.849,192.717L277.964,192.680L278.003,192.613L278.419,192.663L278.469,192.794L278.147,192.797L277.994,192.881L277.920,192.898L277.646,192.878L277.641,192.575L277.721,192.543L277.767,192.656' },\n  { name: 'Central African Republic', path: 'M542.318,230.161L544.605,229.925L545.108,229.116L545.568,229.177L546.266,229.890L549.740,228.687L550.903,227.459L552.335,226.360L552.049,225.253L552.826,224.964L555.500,225.159L558.087,223.702L560.029,220.271L561.404,218.998L563.141,218.462L563.484,219.808L565.121,221.774L565.149,223.057L564.717,224.365L564.908,225.343L565.880,226.248L568.006,227.623L569.540,228.893L569.580,229.915L571.466,231.553L572.641,232.914L573.369,234.800L575.460,236.045L575.922,237.042L575.011,237.375L573.231,237.303L571.140,236.972L570.113,237.241L569.706,238.006L568.808,238.100L567.707,237.435L564.631,239.005L563.365,238.689L562.985,238.931L562.166,240.830L560.093,240.216L558.062,239.907L556.289,238.747L554.000,237.678L552.520,238.691L551.448,240.287L551.208,242.480L549.423,242.305L547.542,241.776L545.895,243.443L544.452,246.369L544.156,245.458L544.026,244.024L542.753,243.012L541.722,241.389L541.481,240.260L540.164,238.618L540.384,237.681L540.097,236.357L540.291,233.919L540.951,233.348L542.318,230.161' },\n  { name: 'Chad', path: 'M539.957,213.063L540.212,211.582L538.444,211.509L538.423,209.486L537.262,208.322L538.382,204.179L541.824,201.214L541.882,197.124L542.799,190.743L543.358,189.390L542.196,188.312L542.127,187.312L541.088,186.494L540.302,181.606L542.997,179.887L554.004,185.907L565.080,191.928L565.626,204.411L563.250,204.191L562.066,206.507L561.380,208.448L561.969,209.183L561.085,210.148L561.424,211.450L560.739,212.761L560.485,213.916L561.449,213.734L562.053,214.947L562.123,216.773L563.158,217.700L563.141,218.462L561.404,218.998L560.029,220.271L558.087,223.702L555.500,225.159L552.826,224.964L552.049,225.253L552.335,226.360L550.903,227.459L549.740,228.687L546.266,229.890L545.568,229.177L545.108,229.116L544.605,229.925L542.318,230.161L542.744,229.309L541.853,227.142L541.452,225.840L540.242,225.306L538.595,223.471L539.183,221.987L540.446,222.303L541.225,222.079L542.769,222.110L541.224,219.252L541.295,217.163L541.081,215.076L539.957,213.063' },\n  { name: 'Chile', path: 'M493.923,98.431L493.836,98.633L493.615,98.565L493.598,98.512L493.851,98.394L493.903,98.395L493.923,98.431' },\n  { name: 'Chile', path: 'M314.394,321.090L315.938,325.425L317.849,324.995L318.264,325.782L317.691,329.049L314.914,330.600L315.753,335.841L315.350,336.853L316.349,338.087L314.761,340.042L313.475,342.992L312.978,345.849L313.775,348.895L312.832,352.129L315.217,357.557L316.024,358.132L316.634,361.024L315.821,364.100L316.571,366.761L315.142,368.841L315.916,371.767L317.513,374.877L316.274,376.033L316.336,378.874L316.740,382.031L318.405,385.759L317.595,386.382L319.356,389.910L320.872,391.069L320.471,392.352L321.832,392.965L322.478,394.117L321.582,394.697L322.506,396.498L323.097,400.561L322.766,403.180L323.625,404.732L323.576,406.679L322.221,408.028L323.726,411.259L325.057,412.350L326.567,412.156L327.511,414.408L329.266,416.162L335.173,416.564L337.567,417.036L335.450,417.013L334.624,417.753L332.958,418.839L333.791,421.649L332.830,421.718L329.758,420.741L326.134,418.646L326.134,418.646L322.416,416.925L320.802,415.020L320.674,413.258L318.553,411.258L316.145,406.050L316.042,403.099L317.726,400.728L313.647,399.833L314.955,397.121L313.964,392.034L317.109,393.110L316.288,386.775L314.317,385.962L314.825,389.779L313.093,389.349L312.389,384.975L311.337,379.301L311.927,377.124L310.346,374.016L309.162,370.428L310.226,370.324L310.444,365.181L311.069,360.129L311.158,355.443L309.518,350.732L309.745,348.138L308.772,344.257L309.711,340.417L309.207,334.334L309.220,327.803L309.267,320.773L308.494,315.626L307.496,311.196L308.826,310.394L309.404,308.781L310.951,310.920L311.531,313.189L313.090,314.521L312.538,317.563L314.394,321.090M337.842,418.049L340.645,424.765L343.132,424.767L344.564,424.847L344.332,426.039L342.776,426.948L341.598,426.855L340.119,426.618L338.017,425.738L335.384,425.315L331.721,423.639L328.623,422.022L323.873,418.654L326.101,419.285L330.292,421.294L333.866,422.374L334.480,420.995L334.361,418.936L336.011,417.694L337.842,418.049' },\n  { name: 'China', path: 'M808.242,97.616L813.095,98.597L817.420,100.778L820.340,103.661L824.058,103.665L825.351,102.454L828.757,101.550L829.380,104.311L829.200,105.434L830.663,108.796L831.036,111.781L827.651,111.237L826.239,112.321L828.482,114.940L830.308,118.554L829.071,118.636L830.023,120.190L827.309,118.384L827.333,120.098L824.210,121.415L825.560,123.029L823.299,122.917L821.533,121.959L821.054,124.128L819.199,125.772L818.224,127.742L815.063,128.668L813.844,130.157L811.464,131.026L812.171,129.550L811.080,128.310L812.023,126.223L809.775,124.620L808.156,125.700L806.420,127.839L805.743,129.896L803.291,130.049L802.623,131.535L804.916,133.689L807.258,134.212L807.970,135.642L810.429,136.572L812.324,134.297L815.175,135.537L816.887,135.622L818.059,137.291L814.780,138.180L814.330,139.900L812.500,141.498L812.114,143.724L815.568,145.452L817.740,148.545L820.411,151.426L823.106,153.842L823.933,156.178L822.583,157.036L823.842,158.714L825.727,159.690L826.034,162.251L826.051,164.743L824.633,165.026L823.617,168.429L822.573,172.556L820.978,176.309L817.811,179.211L814.540,181.858L811.549,182.219L810.149,183.616L809.021,182.595L807.772,184.158L804.260,185.733L801.469,186.215L801.136,189.536L799.658,189.720L798.536,187.438L798.964,186.222L795.135,185.215L793.940,185.727L791.059,184.911L789.543,183.633L789.658,181.822L787.078,181.248L785.569,180.068L783.542,181.744L780.964,182.107L778.797,182.091L777.468,182.858L776.136,183.319L777.142,186.916L775.676,186.830L775.310,186.091L775.015,184.791L773.170,185.707L771.898,185.128L769.688,183.948L770.056,181.335L768.240,180.726L767.129,177.831L764.354,178.353L764.069,174.623L766.033,171.997L765.554,169.403L764.929,166.997L763.588,166.247L762.275,164.396L760.761,164.630L757.768,164.160L758.380,162.839L756.694,160.884L755.080,162.208L752.669,161.435L750.019,163.438L748.080,165.776L746.000,166.170L744.648,165.324L743.216,165.248L741.150,164.520L739.867,165.318L738.570,167.656L737.840,165.179L736.339,165.840L733.151,165.533L729.976,164.812L727.531,163.431L725.331,162.811L724.143,161.301L722.555,160.849L719.449,158.801L717.071,157.834L716.154,158.586L711.914,156.387L708.823,154.396L707.248,150.930L709.246,151.353L708.944,149.747L707.507,148.138L707.155,145.572L703.375,141.867L698.717,140.579L697.262,138.131L694.930,136.646L694.216,135.732L693.328,133.917L693.077,132.678L691.312,131.953L690.553,132.274L689.100,129.326L689.632,128.597L689.077,127.852L691.042,126.394L692.599,125.795L695.445,126.206L695.718,124.253L698.851,123.889L699.318,122.675L702.704,121.019L702.804,120.327L701.957,118.584L703.388,117.788L699.164,112.475L703.594,111.250L704.577,110.567L704.026,105.073L709.333,106.083L710.090,104.696L708.855,101.619L710.751,101.332L711.689,99.289L712.523,99.037L714.125,101.178L716.910,102.805L720.926,103.958L723.766,106.429L724.483,110.014L725.995,111.345L729.196,111.870L732.747,112.298L736.588,114.204L738.281,114.543L740.666,117.362L742.949,119.179L745.696,119.107L751.215,119.793L754.375,119.368L757.079,119.823L761.699,121.681L764.762,121.678L766.344,122.629L768.495,120.987L772.054,119.925L775.780,119.809L778.181,118.733L779.150,117.095L780.377,116.067L779.451,115.057L778.048,113.882L778.323,111.910L779.883,112.187L782.768,112.807L784.331,111.180L787.412,109.991L788.015,107.963L789.227,107.090L792.557,106.683L794.711,107.029L794.311,105.938L790.778,103.793L788.222,102.813L787.026,103.945L784.327,103.467L783.174,103.856L781.801,102.602L781.700,99.536L781.498,97.222L785.094,98.381L787.273,96.451L786.292,95.127L786.129,91.937L786.745,90.973L785.497,89.312L783.678,88.598L784.527,87.101L787.046,86.559L790.098,86.478L794.293,87.373L797.207,88.481L800.998,91.514L802.888,92.808L805.148,94.655L808.242,97.616M801.674,194.765L799.540,196.276L797.150,195.301L796.666,192.596L797.798,191.171L800.637,190.290L802.219,190.365L803.019,191.565L802.030,192.949L801.674,194.765' },\n  { name: 'Colombia', path: 'M290.639,253.978L289.445,253.233L288.102,252.192L287.303,252.692L284.954,252.256L284.304,250.903L283.785,250.953L281.042,249.158L280.685,248.181L281.725,247.945L281.633,246.370L282.306,245.231L283.687,245.020L284.894,243.044L285.987,241.395L284.979,240.646L285.537,238.821L285.012,235.944L285.642,235.119L285.321,232.459L284.273,230.784L284.695,229.256L285.578,229.482L286.141,228.547L285.579,226.695L285.935,226.235L287.361,226.335L289.531,224.140L290.685,223.805L290.757,222.765L291.437,220.108L293.126,218.649L294.870,218.589L295.136,217.933L297.278,218.196L299.561,216.608L300.685,215.905L302.125,214.390L303.088,214.583L303.756,215.410L303.148,216.469L301.339,216.996L300.531,218.568L299.400,219.470L298.515,220.638L298.045,222.882L297.201,224.721L298.621,224.932L298.916,226.377L299.498,227.069L299.665,228.335L299.289,229.499L299.359,230.155L300.030,230.418L300.645,231.514L304.220,231.212L305.813,231.613L307.657,234.319L308.790,233.982L310.780,234.151L312.374,233.792L313.333,234.332L312.770,236.026L312.110,237.082L311.840,239.337L312.364,241.426L313.137,242.361L313.220,243.065L311.788,244.630L312.783,245.323L313.503,246.423L314.298,249.559L313.767,249.946L313.257,248.091L312.502,247.094L311.566,248.178L306.157,248.108L306.157,250.075L307.779,250.400L307.665,251.605L307.115,251.279L305.542,251.797L305.508,254.082L306.760,255.229L307.226,257.030L307.184,258.394L306.085,267.016L304.667,265.344L303.837,265.270L305.572,262.069L303.420,260.597L301.759,260.867L300.747,260.323L299.232,261.155L297.158,260.761L295.462,257.464L294.162,256.653L293.249,255.169L291.374,253.680L290.639,253.978' },\n  { name: 'Comoros', path: 'M619.935,290.924L619.881,290.966L619.636,290.787L619.494,290.744L619.295,290.454L619.417,289.449L619.490,289.320L619.543,289.268L619.661,289.249L619.798,289.375L619.734,290.021L619.904,290.457L620.011,290.801L619.935,290.924M622.699,291.491L622.820,291.925L622.805,292.252L622.742,292.356L622.621,292.289L622.404,292.028L621.981,291.774L622.181,291.753L622.296,291.779L622.420,291.756L622.503,291.613L622.522,291.527L622.633,291.459L622.699,291.491M620.773,292.200L620.958,292.393L620.423,292.313L620.346,292.139L620.347,292.012L620.547,292.040L620.773,292.200' },\n  { name: 'Costa Rica', path: 'M270.338,227.636L268.869,226.938L268.338,226.278L268.682,225.732L268.615,225.037L267.883,224.284L266.824,223.666L265.891,223.263L265.754,222.343L265.064,221.782L265.189,222.696L264.601,223.447L264.011,222.575L263.138,222.264L262.805,221.630L262.899,220.673L263.346,219.682L262.602,219.239L263.285,218.632L263.734,218.227L265.486,219.060L266.154,218.650L267.009,218.912L267.415,219.559L268.213,219.769L268.928,219.102L269.492,220.811L270.461,222.076L271.696,223.419L270.613,223.700L270.570,224.965L271.123,225.433L270.692,225.805L270.773,226.374L270.513,227.012L270.338,227.636' },\n  { name: 'Croatia', path: 'M546.607,109.434L547.324,110.623L548.199,111.497L547.351,112.650L546.163,111.972L544.447,112.015L542.263,111.505L541.108,111.573L540.622,112.210L539.671,111.505L539.249,112.777L540.576,114.207L541.190,115.155L542.430,116.297L543.440,116.974L544.492,118.252L546.820,119.410L546.586,119.930L544.121,118.798L542.574,117.697L540.207,116.788L537.938,114.537L538.426,114.309L537.198,113.023L537.079,111.989L535.444,111.505L534.772,112.828L533.969,111.803L533.950,110.737L534.035,110.688L535.772,110.792L536.188,110.274L537.070,110.775L538.048,110.835L537.972,109.977L538.808,109.663L538.948,108.424L540.846,107.609L541.662,107.986L543.625,109.302L545.725,109.892L546.607,109.434' },\n  { name: 'Cuba', path: 'M276.886,180.582L279.199,180.806L281.325,180.842L283.734,181.913L284.666,183.064L287.248,182.709L288.116,183.448L290.173,185.395L291.690,186.814L292.591,186.771L294.136,187.412L293.828,188.297L295.821,188.427L297.726,189.714L297.313,190.450L295.455,190.849L293.602,191.006L291.748,190.757L287.808,191.063L289.849,189.309L288.841,188.492L287.111,188.282L286.285,187.374L285.869,185.583L284.316,185.706L281.889,184.863L281.160,184.203L277.682,183.716L276.815,183.102L277.938,182.317L275.297,182.156L273.125,183.790L271.993,183.834L271.498,184.601L270.106,184.945L268.984,184.647L270.552,183.675L271.296,182.541L272.619,181.841L274.088,181.228L276.182,180.927L276.886,180.582' },\n  { name: 'Curacao', path: 'M310.328,215.577L310.181,215.622L309.672,215.319L309.267,214.827L309.270,214.569L309.380,214.592L309.488,214.690L309.641,215.038L310.138,215.267L310.328,215.577' },\n  { name: 'Cyprus', path: 'M588.940,143.254L589.053,143.509L586.497,144.786L585.173,144.378L584.429,143.111L585.658,142.994L586.170,143.160L586.847,142.889L587.356,142.922L587.568,143.117L587.660,143.439L587.776,143.317L588.176,143.383L588.646,143.142L588.940,143.254' },\n  { name: 'Czech Republic', path: 'M541.263,101.185L540.092,100.606L538.964,100.765L537.004,99.829L536.168,100.058L534.894,101.313L533.018,100.326L531.558,99.007L530.275,98.269L529.937,96.975L529.449,96.079L531.146,95.424L531.977,94.675L533.649,94.093L534.200,93.520L534.861,93.866L535.900,93.552L537.124,94.520L538.942,94.782L538.873,95.609L540.242,96.231L540.522,95.455L542.205,95.791L542.534,96.733L544.346,96.915L545.601,98.426L544.880,98.430L544.557,98.982L544.014,99.116L543.920,99.814L543.469,99.960L543.430,100.245L542.629,100.562L541.548,100.510L541.263,101.185' },\n  { name: 'Denmark', path: 'M524.988,77.574L524.510,78.678L523.803,78.360L522.291,80.467L523.016,81.893L521.558,82.351L519.782,81.954L518.750,80.327L518.512,77.335L518.848,76.545L519.451,75.667L521.446,75.486L522.190,74.678L523.956,73.853L523.989,75.358L523.383,76.311L523.715,77.131L524.988,77.574M529.277,80.057L528.086,82.444L525.533,80.774L525.119,79.560L528.416,78.590L529.277,80.057' },\n  { name: 'Djibouti', path: 'M618.771,213.565L619.463,214.538L619.430,215.844L617.887,216.597L619.108,217.457L618.159,219.140L617.523,218.579L616.867,218.802L615.323,218.750L615.240,217.793L614.991,216.925L615.865,215.451L616.779,214.060L617.971,214.333L618.771,213.565' },\n  { name: 'Dominica', path: 'M331.541,205.548L331.278,205.617L331.213,205.074L331.067,204.680L331.118,204.434L331.159,204.341L331.525,204.492L331.627,204.675L331.659,205.158L331.541,205.548' },\n  { name: 'Dominican Republic', path: 'M304.256,191.507L304.650,190.971L306.779,190.985L308.317,191.795L309.044,191.716L309.433,192.831L310.933,192.768L310.756,193.705L311.961,193.819L313.195,194.973L312.058,196.253L310.822,195.569L309.554,195.701L308.669,195.551L308.120,196.125L307.051,196.318L306.709,195.555L305.760,196.007L304.453,198.160L303.798,197.660L303.748,196.756L303.889,195.902L303.279,194.958L303.998,194.428L304.326,193.219L304.256,191.507' },\n  { name: 'DR Congo', path: 'M585.565,242.465L585.426,246.142L586.541,246.568L585.657,247.684L584.597,248.520L583.548,250.159L582.974,251.621L582.827,254.146L582.175,255.347L582.134,257.718L581.329,258.594L581.213,260.466L580.830,260.708L580.561,262.428L581.248,263.858L581.397,267.650L581.863,270.543L581.559,272.179L582.083,274.003L583.660,275.763L585.087,279.726L584.002,279.406L580.275,279.936L579.527,280.312L578.706,282.320L579.303,283.706L578.724,287.429L578.297,290.586L579.027,291.145L580.922,292.369L581.695,291.797L581.829,295.188L579.721,295.162L578.637,293.432L577.657,292.092L575.555,291.652L574.979,290.004L573.266,290.997L571.067,290.559L570.180,289.131L568.433,288.841L567.138,288.917L567.002,287.939L566.051,287.860L564.797,287.675L563.076,288.146L561.877,288.068L561.187,288.357L561.411,284.615L560.503,283.448L560.324,281.514L560.755,279.618L560.209,278.405L560.183,276.427L556.822,276.454L557.076,275.321L555.663,275.333L555.507,275.878L553.788,276.001L553.073,277.833L552.649,278.620L551.124,278.175L550.206,278.618L548.373,278.872L547.328,277.228L546.702,276.211L545.924,274.325L545.263,271.982L537.082,271.940L536.107,272.318L535.304,272.259L534.157,272.682L533.775,271.707L534.483,271.375L534.579,270.004L535.039,269.195L536.050,268.534L536.778,268.855L537.731,267.651L539.242,267.682L539.417,268.572L540.451,269.129L542.090,267.158L543.713,265.623L544.418,264.616L544.335,262.029L545.553,258.974L546.832,257.355L548.667,255.839L548.990,254.836L549.065,253.683L549.514,252.591L549.361,250.809L549.695,248.023L550.229,246.061L551.052,244.379L551.208,242.480L551.448,240.287L552.520,238.691L554.000,237.678L556.289,238.747L558.062,239.907L560.093,240.216L562.166,240.830L562.985,238.931L563.365,238.689L564.631,239.005L567.707,237.435L568.808,238.100L569.706,238.006L570.113,237.241L571.140,236.972L573.231,237.303L575.011,237.375L575.922,237.042L577.626,239.637L578.875,240.019L579.614,239.491L580.898,239.698L582.438,239.032L583.107,240.376L585.565,242.465' },\n  { name: 'East Timor', path: 'M845.784,281.464L846.162,280.722L848.595,280.015L850.533,279.909L851.426,279.516L852.447,279.906L851.367,280.758L848.385,282.134L846.005,283.037L846.021,282.084L845.784,281.464' },\n  { name: 'Ecuador', path: 'M277.150,264.207L278.581,261.857L277.953,260.483L276.921,261.944L275.231,260.566L275.777,259.679L275.251,256.825L276.214,256.351L276.686,254.392L277.742,252.367L277.574,251.084L279.109,250.409L281.042,249.158L283.785,250.953L284.304,250.903L284.954,252.256L287.303,252.692L288.102,252.192L289.445,253.233L290.639,253.978L291.071,256.366L290.245,258.411L287.279,261.703L283.965,262.943L282.318,265.679L281.834,267.801L280.291,269.094L279.095,267.507L277.968,267.167L276.826,267.417L276.728,266.265L277.505,265.516L277.150,264.207' },\n  { name: 'Egypt', path: 'M593.253,160.731L592.603,161.995L592.216,164.370L591.616,166.008L591.033,166.557L590.060,165.542L588.743,164.139L586.497,159.631L586.244,159.916L587.599,163.235L589.484,166.396L591.896,171.294L593.026,173.004L594.035,174.780L596.664,178.261L596.158,178.809L596.363,180.853L599.691,183.675L600.207,184.320L589.426,184.320L578.880,184.320L567.953,184.320L567.446,172.740L566.804,161.557L565.856,159.024L566.395,157.083L565.881,155.738L566.727,154.229L570.250,154.177L572.872,155.008L575.587,155.937L576.861,156.427L578.817,155.431L579.827,154.530L582.142,154.271L584.066,154.668L584.941,156.227L585.457,155.200L587.659,155.943L589.748,156.121L590.973,155.329L593.253,160.731' },\n  { name: 'El Salvador', path: 'M258.143,211.412L257.776,212.152L256.184,212.105L255.217,211.804L254.131,211.179L252.617,210.984L251.895,210.308L252.020,209.847L253.032,209.054L253.578,208.706L253.463,208.336L254.124,208.142L254.913,208.407L255.452,209.034L256.241,209.538L256.307,209.962L257.547,209.587L258.095,209.812L258.441,210.152L258.143,211.412' },\n  { name: 'Equatorial Guinea', path: 'M526.362,250.324L525.841,249.849L526.786,246.318L531.304,246.390L531.338,250.174L527.298,250.142L526.362,250.324' },\n  { name: 'Eritrea', path: 'M616.779,214.060L615.796,213.043L614.589,211.199L613.328,210.189L612.574,209.103L610.130,207.842L608.242,207.805L607.554,207.147L605.968,207.887L604.246,206.459L603.472,208.806L600.244,208.149L599.908,206.890L600.867,202.269L601.032,200.179L601.846,199.215L603.837,198.698L605.129,196.903L606.913,200.544L607.825,203.430L609.414,204.962L613.306,207.932L614.906,209.724L616.471,211.539L617.377,212.619L618.771,213.565L617.971,214.333L616.779,214.060' },\n  { name: 'Estonia', path: 'M555.019,73.667L554.990,71.941L554.224,72.310L552.625,71.270L552.159,69.588L554.846,68.773L557.579,68.348L560.084,68.832L562.368,68.745L562.803,69.256L561.534,70.942L562.722,73.672L561.928,74.601L560.055,74.595L557.910,73.509L556.856,73.150L555.019,73.667' },\n  { name: 'Eswatini', path: 'M586.281,337.566L585.631,338.963L584.034,339.302L582.551,337.598L582.602,336.510L583.421,335.330L583.741,334.414L584.537,334.190L585.857,334.766L586.152,336.176L586.281,337.566' },\n  { name: 'Eswatini', path: 'M588.750,143.151L588.770,143.151L588.795,143.183L588.780,143.208L588.764,143.215L588.761,143.220L588.760,143.220L588.742,143.245L588.690,143.208L588.678,143.225L588.662,143.248L588.632,143.270L588.597,143.277L588.578,143.260L588.556,143.245L588.523,143.262L588.501,143.282L588.491,143.317L588.556,143.344L588.579,143.367L588.586,143.436L588.586,143.436L588.617,143.461L588.666,143.466L588.672,143.520L588.650,143.525L588.621,143.554L588.642,143.567L588.690,143.557L588.763,143.572L588.745,143.600L588.723,143.625L588.692,143.636L588.652,143.621L588.572,143.551L588.529,143.526L588.469,143.515L588.477,143.515L588.485,143.513L588.497,143.510L588.501,143.510L588.492,143.496L588.479,143.488L588.468,143.488L588.456,143.488L588.445,143.476L588.424,143.471L588.411,143.471L588.406,143.476L588.423,143.486L588.434,143.491L588.439,143.503L588.451,143.503L588.464,143.505L588.467,143.515L588.467,143.515L588.412,143.504L588.300,143.510L588.260,143.525L588.259,143.478L588.282,143.486L588.289,143.449L588.245,143.432L588.235,143.412L588.255,143.392L588.244,143.369L588.196,143.347L588.180,143.332L588.180,143.332L588.169,143.322L588.161,143.292L588.170,143.262L588.210,143.255L588.235,143.228L588.259,143.228L588.273,143.240L588.261,143.310L588.255,143.347L588.283,143.337L588.332,143.290L588.408,143.340L588.429,143.312L588.458,143.317L588.478,143.312L588.484,143.273L588.545,143.228L588.575,143.238L588.598,143.260L588.626,143.255L588.658,143.228L588.667,143.208L588.680,143.196L588.662,143.168L588.657,143.121L588.661,143.061L588.696,143.061L588.706,143.088L588.725,143.094L588.741,143.123L588.748,143.133L588.750,143.151' },\n  { name: 'Ethiopia', path: 'M604.246,206.459L605.968,207.887L607.554,207.147L608.242,207.805L610.130,207.842L612.574,209.103L613.328,210.189L614.589,211.199L615.796,213.043L616.779,214.060L615.865,215.451L614.991,216.925L615.240,217.793L615.323,218.750L616.867,218.802L617.523,218.579L618.159,219.140L617.602,220.254L618.693,221.985L619.752,223.499L620.835,224.622L629.979,228.353L632.307,228.334L624.724,237.772L621.112,237.911L618.663,240.127L616.885,240.186L616.137,241.177L614.241,241.176L613.111,240.114L610.589,241.429L609.782,242.739L607.929,242.492L607.311,242.129L606.662,242.216L605.785,242.184L602.248,239.513L600.317,239.513L599.360,238.479L599.332,236.714L597.881,236.186L596.175,232.764L594.895,232.035L594.386,230.778L592.953,229.245L591.248,229.020L592.158,227.228L593.625,227.151L594.020,226.191L593.929,223.364L594.657,220.073L595.937,219.192L596.172,217.907L597.275,215.505L598.886,213.947L599.899,210.849L600.244,208.149L603.472,208.806L604.246,206.459' },\n  { name: 'Falkland Islands', path: 'M354.526,415.684L356.721,413.879L359.021,414.631L360.023,413.428L362.410,414.781L362.067,415.834L359.185,416.736L357.735,415.684L356.214,417.037L354.526,415.684' },\n  { name: 'Faroe Islands', path: 'M486.102,60.829L485.988,61.033L485.836,61.001L485.795,60.979L485.764,60.926L485.788,60.774L485.793,60.555L485.961,60.735L486.102,60.829M485.609,60.916L485.536,61.295L485.448,61.293L485.296,61.188L485.179,61.167L485.139,61.223L485.141,61.290L485.200,61.333L485.376,61.587L485.390,61.661L485.365,61.697L485.185,61.624L484.759,61.294L484.444,60.753L484.912,60.666L485.240,60.808L485.609,60.916M484.389,61.166L484.578,61.276L484.644,61.353L484.527,61.427L484.390,61.447L484.227,61.429L483.962,61.348L483.878,61.163L484.064,61.168L484.286,61.133L484.389,61.166M485.566,62.108L485.518,62.214L485.458,62.213L485.260,62.081L485.101,62.010L485.050,61.949L485.010,61.845L485.104,61.832L485.214,61.855L485.489,61.950L485.563,62.049L485.566,62.108M485.348,63.129L485.386,63.214L485.336,63.205L485.193,63.107L484.948,62.874L484.869,62.682L484.861,62.593L484.924,62.603L484.973,62.682L485.214,62.734L485.276,62.773L485.270,62.870L485.346,62.984L485.348,63.129' },\n  { name: 'Fiji', path: 'M6.398,305.391L6.213,305.559L5.832,304.024L6.364,303.879L6.398,305.391M991.851,306.333L989.936,306.995L989.873,305.823L991.403,305.178L992.315,305.005L994.168,304.024L993.787,305.559L991.851,306.333M988.719,308.027L989.439,308.934L988.582,310.576L986.780,311.008L985.367,310.619L985.441,309.236L986.762,308.156L987.912,308.545L988.719,308.027' },\n  { name: 'Finland', path: 'M557.683,42.117L557.843,44.006L561.414,45.804L560.023,47.839L563.212,50.910L562.380,53.230L564.770,55.332L564.323,57.173L567.960,59.109L567.492,60.549L565.856,62.181L561.963,65.787L558.002,66.012L554.311,67.048L550.804,67.659L549.260,66.103L546.968,65.175L547.000,62.392L545.530,59.844L546.290,58.199L547.934,56.424L552.240,53.361L553.532,52.784L553.069,51.643L549.893,50.368L548.979,49.318L548.097,45.163L544.566,43.326L541.632,42.005L542.713,41.292L545.217,42.719L547.831,42.585L550.138,43.237L551.811,42.043L552.362,40.065L555.242,39.176L558.073,40.224L557.683,42.117' },\n  { name: 'France', path: 'M508.626,95.740L510.339,97.164L511.571,96.925L513.721,98.324L514.270,98.591L514.966,98.526L516.135,99.329L519.651,99.894L518.506,101.995L518.280,104.182L517.628,104.706L516.501,104.423L516.607,105.203L514.866,106.927L514.872,108.317L516.036,107.836L516.930,109.181L516.858,110.049L517.630,111.201L516.801,112.135L517.519,114.502L518.887,114.890L518.647,116.217L516.427,117.945L511.447,117.117L507.803,118.109L507.540,119.951L504.616,120.348L501.768,118.964L500.853,119.625L496.217,118.235L495.224,117.046L496.535,115.212L497.047,109.109L494.531,105.888L492.743,104.336L489.027,103.156L488.834,100.918L491.997,100.250L496.068,101.040L495.332,97.567L497.604,98.883L503.224,96.498L503.923,94.033L506.007,93.426L506.370,94.484L507.485,94.533L508.626,95.740M524.183,120.931L523.448,123.294L522.270,122.671L521.601,120.613L522.065,119.477L523.640,118.309L524.183,120.931M354.112,245.624L353.033,246.818L351.701,247.043L351.334,246.158L350.715,246.026L349.844,246.879L348.640,246.230L349.362,244.888L349.623,243.456L350.120,242.109L349.068,240.253L348.878,238.102L350.399,235.398L351.330,235.744L353.349,236.488L356.230,239.143L356.673,240.430L354.995,243.308L354.112,245.624' },\n  { name: 'French Polynesia', path: 'M112.428,281.519L112.163,281.593L112.032,281.580L111.914,281.323L111.937,281.164L111.976,281.114L112.442,281.177L112.490,281.293L112.492,281.404L112.428,281.519M113.864,281.613L113.687,281.637L113.645,281.482L113.694,281.400L113.767,281.361L113.908,281.409L113.986,281.477L113.986,281.536L113.864,281.613M112.548,283.141L112.492,283.198L112.365,283.010L112.341,282.931L112.537,282.833L112.651,282.885L112.548,283.141M115.522,283.987L115.950,284.151L116.079,284.133L115.960,284.294L115.554,284.382L115.423,284.460L115.252,284.409L115.148,284.223L115.522,283.987M115.483,284.730L115.299,284.976L115.276,284.714L115.347,284.680L115.414,284.680L115.483,284.730M116.844,286.566L116.750,286.620L116.698,286.284L116.838,286.348L116.896,286.402L116.886,286.493L116.844,286.566M101.647,303.360L101.658,303.502L101.579,303.365L101.366,303.147L101.284,303.049L101.362,303.065L101.647,303.360M108.770,304.116L108.727,304.150L108.741,303.900L108.805,303.869L108.770,304.116M100.750,304.850L100.773,304.904L100.716,304.900L100.582,304.741L100.518,304.603L100.422,304.447L100.310,304.333L100.279,304.228L100.243,304.062L100.395,304.316L100.531,304.519L100.634,304.687L100.750,304.850M84.555,305.881L84.510,305.905L84.445,305.847L84.404,305.760L84.393,305.618L84.545,305.711L84.611,305.773L84.555,305.881M106.196,305.809L106.092,305.827L105.789,305.640L105.891,305.640L106.066,305.757L106.196,305.809M106.545,305.762L106.725,305.916L106.506,305.811L106.244,305.766L106.335,305.738L106.475,305.742L106.545,305.762M84.855,306.573L84.747,306.578L84.638,306.529L84.596,306.205L84.608,306.139L84.783,306.248L84.970,306.531L84.855,306.573M89.665,308.671L89.596,308.753L89.470,308.696L89.403,308.617L89.367,308.534L89.373,308.434L89.632,308.448L89.713,308.492L89.665,308.671M91.106,309.127L91.530,309.274L91.653,309.511L91.600,309.669L91.393,309.630L91.277,309.544L91.080,309.261L90.708,309.325L90.431,309.269L90.207,308.900L90.166,308.732L90.210,308.629L90.470,308.519L90.840,308.600L91.018,308.810L91.106,309.127M114.517,309.651L114.542,309.711L114.441,309.703L114.408,309.683L114.388,309.571L114.435,309.435L114.469,309.321L114.564,309.215L114.749,309.108L114.840,309.064L114.877,309.090L114.842,309.106L114.545,309.329L114.469,309.485L114.443,309.594L114.458,309.628L114.517,309.651M114.664,310.698L114.701,310.784L114.587,310.727L114.459,310.567L114.248,310.370L114.192,310.288L114.339,310.366L114.449,310.481L114.664,310.698M125.311,311.178L125.324,311.237L125.004,310.937L125.112,310.960L125.311,311.178M115.176,311.297L115.235,311.411L115.158,311.357L114.926,311.246L114.884,311.153L115.176,311.297M127.285,311.814L127.243,311.883L127.225,311.817L127.142,311.784L127.024,311.717L126.865,311.640L126.784,311.627L126.737,311.583L126.786,311.559L126.882,311.594L127.021,311.664L127.178,311.735L127.285,311.814M122.717,319.087L122.651,319.146L122.663,319.066L122.562,318.892L122.497,318.866L122.545,318.816L122.661,318.949L122.717,319.087' },\n  { name: 'Gabon', path: 'M530.782,266.012L527.938,262.838L526.110,260.243L524.431,256.995L524.523,255.950L525.131,254.944L525.807,252.655L526.362,250.324L527.298,250.142L531.338,250.174L531.304,246.390L532.622,246.183L534.311,246.605L535.953,246.200L536.299,246.371L536.101,247.743L536.883,249.367L538.948,249.111L539.643,249.736L538.453,253.378L539.762,255.238L540.056,257.693L539.698,259.784L538.841,261.270L536.391,261.137L534.912,259.627L534.687,261.021L532.813,261.406L531.859,262.197L532.899,264.276L530.782,266.012' },\n  { name: 'Gambia', path: 'M453.592,212.145L453.967,210.750L456.968,210.660L457.601,209.915L458.474,209.864L459.550,210.638L460.405,210.653L461.320,210.124L461.864,211.033L460.663,211.738L459.466,211.683L458.294,211.018L457.262,211.745L456.768,211.771L456.100,212.211L453.592,212.145' },\n  { name: 'Georgia', path: 'M605.478,122.818L605.605,121.511L604.574,119.425L602.903,118.298L601.443,117.946L600.348,117.009L600.588,116.648L602.808,117.171L606.603,117.666L610.323,119.132L610.880,119.701L612.312,119.220L614.798,119.860L615.836,121.115L617.578,121.824L617.010,122.246L618.615,123.901L618.346,124.259L616.935,124.077L614.856,123.198L614.337,123.697L610.900,124.174L608.154,122.673L605.478,122.818' },\n  { name: 'Germany', path: 'M523.016,81.893L523.128,83.055L525.526,83.756L525.572,84.824L527.907,84.259L529.157,83.435L531.885,84.623L533.071,85.581L533.751,87.111L533.164,87.914L534.114,88.986L534.842,90.595L534.749,91.631L535.900,93.552L534.861,93.866L534.200,93.520L533.649,94.093L531.977,94.675L531.146,95.424L529.449,96.079L529.937,96.975L530.275,98.269L531.558,99.007L533.018,100.326L532.257,101.740L531.408,102.130L531.887,104.129L531.693,104.651L530.888,104.023L529.709,103.928L527.992,104.479L525.824,104.348L525.519,105.158L524.234,104.305L523.503,104.475L520.837,103.536L520.364,104.203L518.280,104.182L518.506,101.995L519.651,99.894L516.135,99.329L514.966,98.526L515.060,97.180L514.555,96.495L514.752,94.463L514.235,91.311L515.663,91.310L516.218,90.178L516.690,87.424L516.208,86.407L516.639,85.770L518.589,85.607L519.056,86.270L520.570,84.787L519.977,83.660L519.782,81.954L521.558,82.351L523.016,81.893' },\n  { name: 'Ghana', path: 'M502.939,234.856L498.592,236.697L497.050,237.775L494.550,238.688L492.077,237.795L492.205,236.554L491.008,233.845L491.736,230.294L492.907,227.653L492.180,223.179L491.808,220.811L491.878,219.027L496.676,218.879L497.896,219.108L498.788,218.601L500.066,218.851L499.862,219.831L501.016,221.453L501.012,223.737L501.276,226.214L501.971,227.361L501.360,230.193L501.580,231.757L502.320,233.752L502.939,234.856' },\n  { name: 'Gibraltar', path: 'M486.040,139.806L486.091,139.806L486.088,139.842L486.089,139.861L486.081,139.903L486.060,139.875L486.040,139.806' },\n  { name: 'Greece', path: 'M567.520,122.737L566.967,124.651L566.403,124.994L564.840,124.907L563.477,124.618L560.480,125.413L562.441,127.132L561.195,127.636L559.769,127.639L558.251,126.059L557.841,126.730L558.587,128.600L559.998,130.094L559.088,130.792L560.648,132.260L562.005,133.184L562.203,134.984L559.738,134.140L560.640,135.764L559.023,136.098L560.246,138.909L558.521,138.949L556.277,137.564L555.103,135.016L554.486,132.896L553.368,131.432L551.914,129.616L551.673,128.709L552.742,127.178L552.801,126.184L553.588,125.741L553.561,124.937L555.201,124.666L556.104,123.998L557.489,124.057L557.851,123.524L558.325,123.422L560.214,123.511L562.154,122.670L564.066,123.739L566.342,123.450L566.186,121.927L567.520,122.737M561.865,141.195L563.388,142.268L565.406,142.087L567.373,142.313L567.362,142.867L568.751,142.485L568.514,143.424L564.764,143.692L564.747,143.169L561.499,142.548L561.865,141.195' },\n  { name: 'Greenland', path: 'M422.646,10.382L428.906,9.271L434.605,9.354L437.084,8.668L442.933,8.489L455.831,8.722L465.575,10.198L462.287,10.915L455.897,10.997L446.860,11.179L447.546,11.511L453.544,11.306L458.334,11.948L461.780,11.378L462.952,12.045L460.742,13.128L465.265,12.436L473.609,11.714L478.560,12.074L479.360,12.870L472.152,14.194L471.081,14.622L465.500,14.944L469.463,15.033L467.055,16.668L465.283,18.174L464.707,20.759L466.513,22.276L463.658,22.372L460.477,23.107L463.538,24.338L463.490,26.311L461.443,26.526L463.429,28.678L459.196,28.861L461.178,29.894L460.370,30.790L457.593,31.184L454.925,31.191L456.940,32.912L456.716,34.044L453.129,32.992L451.968,33.672L454.435,34.308L456.640,35.861L456.942,37.907L453.299,38.397L452.006,37.417L449.934,35.957L450.173,37.682L447.528,39.018L452.748,39.126L455.462,39.265L449.615,41.593L443.644,43.721L437.459,44.653L435.207,44.664L432.809,45.704L429.136,48.552L424.098,50.443L422.620,50.555L419.624,51.217L416.402,51.848L414.036,53.537L413.391,55.517L411.730,57.372L407.495,59.632L407.648,61.840L405.903,64.176L403.864,66.934L400.682,67.106L398.225,64.799L393.832,64.785L392.281,63.236L391.875,60.477L389.507,56.964L389.157,55.123L389.893,52.608L388.106,50.118L389.754,48.129L388.808,47.178L392.258,44.025L395.756,43.021L397.044,41.893L398.373,39.785L395.670,40.740L394.400,41.142L392.421,41.526L390.359,40.646L391.112,38.858L392.620,37.506L394.471,37.470L398.158,38.146L395.602,36.532L394.309,35.662L392.165,36.019L390.878,35.390L394.346,33.022L393.691,32.076L393.144,30.319L392.386,27.625L390.591,26.659L391.320,25.687L387.375,24.328L383.606,24.159L378.622,24.252L373.993,24.423L372.498,23.683L370.612,22.223L375.994,21.492L379.725,21.369L372.549,20.765L369.368,19.817L370.433,18.914L378.100,17.797L385.447,16.681L386.806,15.836L382.821,15.056L385.053,14.314L392.192,13.014L394.836,12.815L394.900,11.978L399.307,11.488L404.688,11.196L409.821,11.179L411.188,11.759L416.386,10.734L419.857,11.430L422.101,11.577L425.178,12.183L421.872,11.179L422.646,10.382' },\n  { name: 'Grenada', path: 'M329.729,215.725L329.545,215.739L329.624,215.622L329.652,215.424L329.763,215.183L329.923,215.020L330.067,215.063L329.981,215.596L329.729,215.725' },\n  { name: 'Guam', path: 'M898.796,211.805L898.680,211.811L898.564,211.705L898.519,211.635L898.467,211.273L898.813,210.964L898.900,210.664L899.009,210.688L899.111,210.737L899.209,210.827L898.835,211.328L898.796,211.805' },\n  { name: 'Guatemala', path: 'M251.895,210.308L250.530,209.760L248.817,209.703L247.613,209.079L246.246,207.782L246.394,206.866L246.786,206.128L246.470,205.541L248.117,202.978L251.642,202.968L251.846,201.897L251.425,201.707L251.206,201.025L250.283,200.299L249.394,199.249L250.633,199.242L250.857,197.471L253.414,197.466L255.941,197.501L255.614,199.993L254.963,203.542L255.783,203.541L256.609,204.110L256.903,203.642L257.659,204.043L256.261,205.243L254.850,206.123L254.597,206.727L254.764,207.344L254.124,208.142L253.463,208.336L253.578,208.706L253.032,209.054L252.020,209.847L251.895,210.308' },\n  { name: 'Guinea', path: 'M476.631,229.331L475.848,229.250L475.277,230.516L474.494,230.501L473.958,229.831L474.148,228.568L473.001,226.642L472.276,226.996L471.685,227.066L470.922,227.246L470.959,226.093L470.520,225.271L470.615,224.356L470.024,223.035L469.262,221.910L467.050,221.907L466.401,222.499L465.639,222.571L465.162,223.249L464.837,224.121L463.347,225.504L462.148,223.643L461.082,222.412L460.378,222.005L459.697,221.380L459.402,219.991L459.008,219.298L458.212,218.783L459.461,217.250L460.298,217.308L461.025,216.781L461.634,216.776L462.075,216.359L461.854,215.317L462.160,214.988L462.224,213.922L463.555,213.954L465.528,214.721L466.136,214.651L466.347,214.301L467.848,214.550L468.248,214.372L468.395,215.524L468.833,215.520L469.557,215.101L470.013,215.206L470.771,216.004L471.949,216.256L472.713,215.575L473.608,215.154L474.274,214.714L474.826,214.796L475.433,215.487L475.754,216.355L476.875,217.672L476.302,218.481L476.186,219.504L476.777,219.195L477.119,219.562L476.965,220.498L477.802,221.405L477.249,221.649L477.021,222.716L477.652,224.016L478.324,226.533L477.295,226.911L477.028,227.348L477.239,227.956L477.070,229.327L476.631,229.331' },\n  { name: 'Guinea-Bissau', path: 'M458.212,218.783L456.757,217.468L455.598,217.260L454.978,216.374L455.002,215.895L454.171,215.228L454.006,214.555L455.475,214.043L456.387,214.144L457.131,213.790L462.224,213.922L462.160,214.988L461.854,215.317L462.075,216.359L461.634,216.776L461.025,216.781L460.298,217.308L459.461,217.250L458.212,218.783' },\n  { name: 'Guyana', path: 'M334.595,227.189L336.374,228.346L338.019,230.395L338.043,232.014L339.085,232.088L340.519,233.622L341.578,234.717L341.044,237.546L339.344,238.366L339.483,239.108L338.948,240.730L340.145,243.014L341.033,243.018L341.373,244.793L343.030,247.527L342.353,247.639L340.821,247.373L339.906,248.209L338.642,248.761L337.762,248.897L337.447,249.512L336.086,249.356L334.399,247.881L334.220,246.426L333.533,244.836L334.014,242.159L334.800,241.051L334.185,239.590L333.239,239.114L333.621,237.733L333.000,237.008L331.553,237.147L329.759,234.761L330.540,233.896L330.535,232.444L332.258,231.939L332.966,231.350L332.057,230.183L332.339,229.037L334.595,227.189' },\n  { name: 'Haiti', path: 'M300.287,190.874L301.938,191.013L304.256,191.507L304.326,193.219L303.998,194.428L303.279,194.958L303.889,195.902L303.748,196.756L301.984,196.222L300.671,196.440L299.024,196.213L297.684,196.800L296.319,195.821L296.664,194.807L299.136,195.244L301.174,195.496L302.229,194.796L301.117,193.434L301.258,192.233L299.585,191.742L300.287,190.874' },\n  { name: 'Honduras', path: 'M259.351,212.669L258.957,211.685L258.143,211.412L258.441,210.152L258.095,209.812L257.547,209.587L256.307,209.962L256.241,209.538L255.452,209.034L254.913,208.407L254.124,208.142L254.764,207.344L254.597,206.727L254.850,206.123L256.261,205.243L257.659,204.043L257.930,204.166L258.599,203.613L259.391,203.568L259.614,203.824L260.059,203.668L261.301,203.952L262.581,203.870L263.506,203.522L263.869,203.170L264.725,203.333L265.357,203.546L266.084,203.473L266.662,203.200L267.865,203.636L268.293,203.705L269.063,204.293L269.776,204.998L270.719,205.480L271.344,206.345L270.408,206.280L269.991,206.709L269.004,207.119L268.309,207.122L267.668,207.521L267.129,207.379L266.699,206.899L266.404,206.990L265.990,207.742L265.729,207.715L265.630,208.362L264.599,209.228L264.061,209.602L263.747,209.992L262.987,209.356L262.323,210.195L261.751,210.173L261.099,210.247L261.030,211.793L260.623,211.821L260.219,212.540L259.351,212.669' },\n  { name: 'Hong Kong', path: 'M810.544,183.074L810.436,183.144L810.457,183.297L810.420,183.390L810.039,183.224L809.735,183.138L809.482,183.172L809.369,183.074L809.334,182.973L809.601,182.797L809.608,182.710L809.615,182.702L809.685,182.612L809.809,182.586L809.869,182.543L810.046,182.543L810.162,182.578L810.272,182.618L810.284,182.632L810.364,182.749L810.371,182.881L810.493,182.944L810.544,183.074M809.736,183.658L809.409,183.658L809.333,183.626L809.286,183.560L809.380,183.438L809.790,183.271L809.712,183.447L809.736,183.658M810.372,183.657L810.314,183.706L810.085,183.476L810.060,183.401L810.201,183.387L810.382,183.491L810.390,183.585L810.372,183.657' },\n  { name: 'Hungary', path: 'M539.863,106.539L540.512,104.563L539.982,103.898L541.359,103.892L541.436,102.638L542.748,103.424L543.680,103.759L545.697,103.383L545.835,102.766L546.796,102.676L547.936,102.199L548.220,102.395L549.325,102.012L549.821,101.290L550.599,101.103L553.308,102.035L553.793,101.722L555.242,102.556L555.507,103.379L554.088,104.022L553.160,106.103L551.898,108.184L549.979,108.763L548.422,108.627L546.607,109.434L545.725,109.892L543.625,109.302L541.662,107.986L540.846,107.609L540.280,106.573L539.863,106.539' },\n  { name: 'Iceland', path: 'M469.865,49.156L469.167,50.902L471.319,52.743L468.331,54.881L461.941,56.817L460.024,57.332L457.266,56.916L451.452,56.022L453.760,54.774L449.392,53.392L453.228,52.855L453.286,52.063L449.004,51.436L450.773,49.678L454.002,49.279L456.922,51.109L460.340,49.640L462.844,50.403L466.445,48.965L469.865,49.156' },\n  { name: 'India', path: 'M703.375,141.867L707.155,145.572L707.507,148.138L708.944,149.747L709.246,151.353L707.248,150.930L708.823,154.396L711.914,156.387L716.154,158.586L714.762,160.012L714.266,162.954L717.080,164.144L719.895,165.687L723.730,167.451L727.491,167.858L729.354,169.458L731.492,169.757L734.876,170.490L737.108,170.438L737.164,169.193L736.406,167.195L736.339,165.840L737.840,165.179L738.570,167.656L738.756,168.286L741.445,169.479L743.035,168.988L745.349,169.198L747.524,169.105L747.304,167.173L746.000,166.170L748.080,165.776L750.019,163.438L752.669,161.435L755.080,162.208L756.694,160.884L758.380,162.839L757.768,164.160L760.761,164.630L761.230,165.822L760.418,166.398L761.070,168.333L759.023,167.765L756.020,169.938L756.495,171.737L755.581,174.375L755.712,175.907L754.902,178.500L752.677,177.783L753.065,181.038L752.614,182.109L753.103,183.444L751.875,184.190L749.697,179.202L748.950,179.212L748.807,181.221L747.080,179.592L747.650,177.802L748.835,177.620L749.683,174.959L748.016,174.422L745.520,174.469L742.860,174.038L742.171,171.851L740.852,171.696L738.441,170.337L737.922,172.471L740.209,174.135L738.733,175.307L738.297,176.453L740.084,177.295L739.896,179.190L741.176,181.555L741.973,184.144L741.750,185.293L739.894,185.253L736.634,185.906L737.125,188.271L735.932,190.132L732.265,192.248L729.637,195.948L727.807,197.932L725.312,199.990L725.471,201.436L724.191,202.211L721.845,203.338L720.580,203.504L720.022,205.903L720.922,209.993L721.268,212.601L720.327,215.588L720.722,220.931L719.303,221.083L718.182,223.482L719.070,224.518L716.587,225.409L715.749,227.548L714.678,228.452L711.929,225.516L710.431,221.112L709.142,217.940L708.067,216.453L706.385,213.432L705.421,209.499L704.806,207.535L701.903,203.216L700.152,197.122L698.930,193.098L698.533,189.290L697.657,186.345L693.914,188.227L691.951,187.850L687.964,184.039L689.142,182.902L688.201,181.668L684.722,178.999L686.292,176.901L692.248,176.909L691.367,174.209L689.592,172.615L688.895,170.195L686.907,168.782L689.336,165.486L692.489,165.725L694.743,162.428L695.881,159.237L697.756,156.082L697.205,153.840L699.047,152.021L696.559,150.469L695.160,148.341L693.606,145.586L694.585,144.230L698.739,144.997L701.553,144.530L703.375,141.867' },\n  { name: 'Indonesia', path: 'M793.366,271.903L790.292,271.969L788.112,269.340L784.620,266.771L783.480,264.865L781.443,262.304L780.124,259.947L778.122,255.545L775.718,252.924L774.836,250.221L773.753,247.766L771.201,245.786L769.686,243.095L767.554,241.334L764.578,237.869L764.251,236.268L766.043,236.395L770.370,237.003L772.921,240.078L775.119,242.210L776.682,243.518L779.395,246.898L782.219,246.948L784.606,249.102L786.280,251.735L788.432,253.171L787.270,255.739L788.833,256.831L789.829,256.911L790.243,259.105L791.164,260.860L793.195,261.138L794.493,263.128L793.694,267.039L793.366,271.903M827.265,247.753L830.463,250.663L827.183,251.034L826.319,253.178L826.376,256.027L823.643,258.178L823.480,261.310L822.271,266.118L821.895,265.000L818.702,266.415L817.657,264.492L815.684,264.315L814.328,263.307L810.997,264.438L810.027,262.916L808.204,263.089L805.926,262.726L805.616,258.509L804.254,257.635L802.994,254.945L802.611,252.194L802.856,249.280L804.449,247.191L804.970,249.292L806.917,251.069L808.691,250.429L810.470,250.656L812.044,249.066L813.368,248.790L816.020,249.671L818.265,249.001L819.564,244.628L820.602,243.534L821.461,239.958L824.650,239.959L827.071,240.489L825.575,243.329L827.702,246.306L827.265,247.753M857.354,249.939L857.296,252.687L855.854,252.379L855.442,254.293L856.533,255.953L855.744,256.330L854.686,254.338L853.787,250.319L854.266,247.806L855.151,246.662L855.405,248.379L857.053,248.655L857.354,249.939M847.752,249.035L845.617,252.154L843.548,252.759L840.856,252.144L836.233,252.301L833.820,252.754L833.398,255.134L835.801,257.930L837.343,256.506L842.554,255.436L842.281,256.884L841.085,256.427L839.824,258.270L837.343,259.489L839.848,263.519L839.308,264.599L841.693,268.228L841.564,270.294L840.020,271.218L839.009,270.113L840.462,267.538L837.702,268.755L837.038,267.885L837.435,266.671L835.490,264.827L835.787,261.763L833.908,262.719L834.033,266.385L833.948,270.884L832.159,271.340L831.030,270.417L831.956,267.523L831.616,264.488L830.450,264.465L829.652,262.311L830.859,260.252L831.328,257.755L832.836,253.015L833.380,251.719L835.671,249.383L837.867,250.312L841.382,250.748L844.571,250.616L847.246,248.333L847.752,249.035M872.500,257.122L873.107,262.208L875.916,264.090L878.348,260.755L881.598,258.857L884.066,258.854L886.403,259.950L888.423,261.075L891.382,261.676L890.950,271.924L890.180,282.172L887.921,279.591L885.159,278.959L884.407,279.854L880.893,279.951L882.268,277.392L884.079,276.519L883.625,273.100L882.500,270.460L877.267,267.797L874.988,267.534L870.918,264.628L870.048,266.156L868.974,266.434L868.382,265.280L868.419,263.914L866.349,262.369L869.375,261.237L871.353,261.298L871.148,260.464L867.085,260.457L866.046,258.585L863.584,258.005L862.459,256.449L866.227,255.687L867.684,254.662L872.101,255.953L872.500,257.122M862.106,263.229L863.037,265.633L860.736,264.337L858.427,264.074L856.853,264.282L854.937,264.171L855.650,262.442L859.082,262.312L862.106,263.229M853.128,264.377L852.056,265.421L850.157,264.844L849.658,263.491L852.470,263.340L853.128,264.377M873.420,273.042L871.832,275.183L871.742,272.815L872.320,271.685L872.981,270.622L873.541,271.542L873.420,273.042M800.966,274.813L806.255,275.126L806.946,273.830L811.991,275.342L812.869,277.381L816.987,277.954L820.261,279.823L817.025,281.021L814.063,279.754L811.552,279.839L808.695,279.607L806.140,279.042L803.007,277.841L800.994,277.530L799.818,277.923L794.846,276.628L794.447,275.276L791.925,275.045L794.007,272.040L797.359,272.226L799.521,273.455L800.656,273.694L800.966,274.813M840.245,278.953L839.718,280.700L835.499,281.592L831.845,281.205L831.913,280.055L834.156,279.402L835.825,280.344L837.684,280.105L840.245,278.953M826.393,278.957L827.335,279.796L829.062,279.539L829.659,280.876L826.417,281.508L824.473,281.930L822.987,281.905L824.058,280.094L825.577,280.069L826.393,278.957M844.013,285.386L841.565,286.078L841.278,285.700L841.638,284.631L842.961,282.713L845.784,281.464L846.021,282.084L846.005,283.037L844.013,285.386M833.692,285.699L832.522,285.759L829.039,283.556L831.660,282.937L833.049,283.895L833.951,284.850L833.692,285.699' },\n  { name: 'Iran', path: 'M639.810,136.436L641.964,135.820L643.434,133.999L645.182,134.091L646.192,133.498L648.090,133.792L651.294,135.406L653.437,135.755L657.025,138.575L658.989,138.689L659.821,141.370L659.568,145.314L659.270,147.602L660.502,148.066L659.695,149.788L661.026,152.299L661.605,154.295L663.713,154.825L664.313,156.849L662.406,159.700L663.960,161.354L665.305,163.253L668.063,164.636L668.536,167.405L669.895,167.914L670.328,169.362L666.678,170.987L666.179,174.640L660.965,173.690L657.924,172.968L654.825,172.559L653.170,168.703L651.811,168.146L649.818,168.708L647.298,170.230L643.880,169.187L640.873,166.770L638.183,165.875L636.043,162.891L633.569,158.698L632.210,159.208L630.361,158.166L629.540,159.393L627.830,157.740L627.558,156.065L626.709,156.066L626.812,153.788L625.102,151.399L621.621,149.675L619.379,146.686L619.646,144.232L620.803,143.143L620.290,141.283L618.418,140.327L616.103,136.527L614.270,133.975L614.614,132.989L613.215,129.336L614.823,128.429L615.429,129.630L616.972,131.101L618.809,131.524L619.725,131.430L622.349,129.080L623.269,128.845L624.193,129.780L623.586,131.356L625.490,133.024L626.104,132.865L627.345,135.213L629.922,135.877L632.020,137.475L635.817,138.024L639.709,137.181L639.810,136.436' },\n  { name: 'Iraq', path: 'M618.418,140.327L620.290,141.283L620.803,143.143L619.646,144.232L619.379,146.686L621.621,149.675L625.102,151.399L626.812,153.788L626.709,156.066L627.558,156.065L627.830,157.740L629.540,159.393L627.940,159.239L626.113,158.977L624.486,161.996L619.490,161.745L611.228,155.421L606.999,153.220L603.707,152.368L602.187,148.539L607.608,145.266L608.064,141.439L607.464,139.112L608.767,138.325L609.790,136.338L610.826,135.843L613.906,136.254L614.948,137.065L616.103,136.527L618.418,140.327' },\n  { name: 'Ireland', path: 'M485.496,85.248L485.803,87.397L483.914,90.083L479.621,91.860L476.279,91.405L478.382,88.265L477.330,85.207L480.633,82.851L482.457,81.457L482.860,83.058L482.307,84.670L483.753,84.628L485.496,85.248' },\n  { name: 'Isle of Man', path: 'M489.701,84.292L489.218,84.673L489.029,84.605L488.865,84.641L488.820,84.630L488.917,84.493L489.035,84.173L489.234,84.047L489.491,83.717L489.689,83.625L489.757,83.638L489.799,83.669L489.880,84.041L489.750,84.172L489.701,84.292' },\n  { name: 'Israel', path: 'M594.323,150.644L593.971,151.635L592.967,151.199L592.638,153.293L593.342,153.646L592.711,154.079L592.685,154.907L593.887,154.481L594.081,155.704L593.253,160.731L590.973,155.329L591.636,154.293L591.436,154.114L591.981,152.645L592.265,150.272L592.557,149.476L592.626,149.443L593.509,149.449L593.692,148.898L594.395,148.857L594.576,150.144L594.270,150.622L594.323,150.644' },\n  { name: 'Italy', path: 'M530.467,106.799L534.043,107.591L533.882,109.103L534.567,110.409L532.563,109.962L530.617,111.051L530.849,112.573L530.593,113.445L531.502,115.002L533.944,116.542L535.370,119.070L538.347,121.535L540.330,121.516L540.998,122.192L540.331,122.801L542.690,123.907L544.632,124.832L546.952,126.427L547.265,126.998L546.872,128.117L545.341,126.665L543.081,126.162L542.148,128.166L544.075,129.347L543.875,131.009L542.811,131.198L541.599,133.930L540.536,134.175L540.490,133.201L540.916,131.493L541.435,130.813L540.324,128.967L539.448,127.367L538.360,126.986L537.515,125.666L535.839,125.110L534.659,123.880L532.766,123.682L530.702,122.301L528.279,120.311L526.476,118.549L525.548,115.526L524.286,115.170L522.208,114.161L521.074,114.574L519.681,115.993L518.647,116.217L518.887,114.890L517.519,114.502L516.801,112.135L517.630,111.201L516.858,110.049L516.930,109.181L518.019,109.839L519.208,109.693L520.552,108.652L521.001,109.138L522.175,109.041L522.652,107.804L524.497,108.188L525.557,107.670L525.686,106.412L527.201,106.849L527.453,106.265L529.850,105.732L530.467,106.799M523.420,123.814L525.044,125.985L524.847,130.135L523.672,129.934L522.659,130.997L521.658,130.152L521.429,126.357L520.780,124.609L522.187,124.762L523.420,123.814M540.054,133.149L539.264,135.656L539.708,136.642L539.254,138.280L537.203,137.081L535.866,136.737L532.171,135.118L532.458,133.482L535.494,133.773L538.110,133.427L540.054,133.149' },\n  { name: 'Ivory Coast', path: 'M492.077,237.795L490.815,237.827L488.881,237.212L487.103,237.248L483.816,237.797L481.888,238.705L479.139,239.858L478.604,239.775L478.823,237.185L479.090,236.792L479.011,235.553L477.842,234.236L476.963,234.026L476.159,233.162L476.768,231.765L476.498,230.245L476.631,229.331L477.070,229.327L477.239,227.956L477.028,227.348L477.295,226.911L478.324,226.533L477.652,224.016L477.021,222.716L477.249,221.649L477.802,221.405L478.165,221.119L478.926,221.591L481.061,221.617L481.576,220.700L482.052,220.761L482.852,220.406L483.272,221.751L483.920,221.355L485.063,220.889L486.303,221.574L486.782,222.614L488.024,223.278L488.993,222.487L490.289,222.368L492.180,223.179L492.907,227.653L491.736,230.294L491.008,233.845L492.205,236.554L492.077,237.795' },\n  { name: 'Jamaica', path: 'M287.857,195.355L289.668,195.637L291.041,196.392L291.404,197.254L289.474,197.312L288.586,197.838L287.108,197.333L285.666,196.187L286.072,195.469L287.245,195.249L287.857,195.355' },\n  { name: 'Japan', path: 'M859.934,114.749L862.128,115.401L863.030,114.104L865.891,117.538L862.718,118.375L862.519,121.412L857.172,119.322L857.978,122.668L855.185,122.714L852.875,119.674L852.599,117.320L855.173,117.150L853.140,112.920L852.190,110.531L857.335,113.720L859.934,114.749M865.622,136.617L865.961,139.159L867.242,140.756L867.042,143.000L864.367,144.485L859.839,144.678L857.593,148.268L855.324,147.059L854.244,144.709L849.966,145.403L847.458,146.884L844.405,146.944L848.004,149.258L848.390,154.602L847.204,155.925L845.432,154.703L844.952,151.869L842.916,150.955L840.990,148.798L843.095,147.830L843.685,145.853L845.671,144.227L846.600,142.060L851.332,141.110L854.448,141.761L854.332,136.099L856.830,137.620L859.012,134.434L859.847,133.197L859.462,129.302L856.990,125.792L856.817,123.860L859.155,123.298L863.314,127.541L864.587,130.124L863.873,133.331L865.622,136.617M853.667,146.115L854.447,147.194L853.747,149.097L852.252,148.088L851.200,148.819L851.249,150.658L849.165,149.763L848.583,148.271L849.278,146.395L850.920,146.759L851.460,145.437L853.667,146.115' },\n  { name: 'Jordan', path: 'M593.971,151.635L594.323,150.644L597.405,151.890L602.187,148.539L603.707,152.368L603.259,152.842L598.136,154.420L601.145,157.564L600.326,158.098L600.008,159.151L598.010,159.587L597.467,160.719L596.393,161.687L593.379,161.186L593.253,160.731L594.081,155.704L593.887,154.481L594.178,153.558L593.971,151.635' },\n  { name: 'Kazakhstan', path: 'M679.394,120.584L678.128,121.149L675.470,123.281L675.052,125.469L674.107,125.489L672.954,124.040L669.688,123.941L668.402,121.436L667.162,121.414L666.415,118.347L662.732,116.113L658.501,116.351L655.687,116.797L652.513,114.040L650.148,112.883L645.644,110.688L645.101,110.422L639.235,112.235L642.245,123.512L640.980,123.661L638.594,121.263L636.670,120.407L633.956,121.043L633.085,122.061L632.762,121.315L633.075,120.040L632.335,118.975L629.167,117.933L627.387,115.186L625.825,114.413L625.510,113.416L628.006,113.707L627.552,111.468L629.533,110.970L631.826,111.428L631.457,108.434L630.502,106.537L628.079,106.685L625.791,105.936L623.291,107.286L621.154,107.929L619.778,107.433L619.634,105.854L617.563,103.804L615.768,103.889L613.196,101.808L614.042,99.482L613.184,98.856L614.239,95.513L617.209,97.265L616.875,95.060L620.819,91.789L624.512,91.711L630.447,93.794L633.691,95.010L635.799,93.742L639.570,93.681L643.193,95.240L643.565,94.347L646.978,94.477L647.046,93.053L642.423,90.984L644.160,89.519L643.414,88.700L645.388,87.918L642.923,85.857L643.615,84.831L651.947,83.784L652.789,83.041L658.151,81.931L659.662,80.715L664.125,81.346L666.226,84.449L668.343,83.717L671.795,84.743L672.334,86.384L674.507,86.213L679.061,83.375L678.647,84.317L682.724,86.641L691.687,94.280L692.193,92.705L696.342,94.438L699.393,93.665L700.989,94.206L703.033,95.944L705.017,96.528L706.639,97.823L709.568,97.412L711.689,99.289L710.751,101.332L708.855,101.619L710.090,104.696L709.333,106.083L704.026,105.073L704.577,110.567L703.594,111.250L699.164,112.475L703.388,117.788L701.957,118.584L702.804,120.327L701.082,119.879L699.414,118.780L695.561,118.460L691.356,118.376L690.559,118.713L686.531,117.427L685.319,118.060L685.540,119.866L681.038,118.812L679.520,119.244L679.394,120.584' },\n  { name: 'Kenya', path: 'M613.842,256.199L615.460,258.793L613.503,260.049L612.804,261.361L611.761,261.591L611.345,263.807L610.442,265.076L609.880,267.168L608.752,268.206L604.800,265.063L604.628,263.239L594.618,256.833L594.152,256.487L594.146,253.155L594.931,251.881L596.280,249.799L597.270,247.507L596.018,243.897L595.680,242.319L594.346,240.136L596.037,238.258L597.881,236.186L599.332,236.714L599.360,238.479L600.317,239.513L602.248,239.513L605.785,242.184L606.662,242.216L607.311,242.129L607.929,242.492L609.782,242.739L610.589,241.429L613.111,240.114L614.241,241.176L616.137,241.177L613.747,244.744L613.842,256.199' },\n  { name: 'Kiribati', path: 'M57.878,241.162L58.089,241.427L58.040,241.561L57.881,241.549L57.810,241.502L57.936,241.479L57.958,241.430L57.904,241.352L57.830,241.297L57.778,241.297L57.761,241.404L57.677,241.320L57.731,241.238L57.794,241.183L57.878,241.162M980.050,243.660L979.879,243.765L979.825,243.748L980.028,243.598L980.028,243.617L980.050,243.660M979.713,243.905L979.513,244.027L979.455,243.962L979.529,243.960L979.662,243.843L979.829,243.834L979.812,243.898L979.713,243.905M63.166,247.665L63.613,248.029L63.417,248.054L62.941,247.879L62.514,247.519L62.649,247.441L62.708,247.570L62.904,247.691L63.033,247.438L63.113,247.380L62.770,247.119L62.909,247.132L63.236,247.310L63.166,247.665M980.359,247.696L980.376,247.769L980.209,247.571L980.110,247.444L980.113,247.388L980.157,247.423L980.213,247.485L980.249,247.535L980.359,247.696M980.406,248.100L980.306,248.113L980.380,248.068L980.398,248.005L980.378,247.810L980.417,247.826L980.435,247.907L980.447,248.024L980.406,248.100M980.482,249.280L980.407,249.291L980.452,249.227L980.768,249.156L980.795,249.137L980.848,249.176L980.848,249.213L980.826,249.231L980.668,249.233L980.546,249.266L980.482,249.280M980.510,250.314L980.665,250.439L980.649,250.524L980.603,250.622L980.418,250.873L980.359,250.850L980.540,250.624L980.607,250.473L980.492,250.358L980.450,250.384L980.433,250.384L980.390,250.277L980.428,250.277L980.510,250.314M984.638,256.021L984.544,256.107L984.513,256.029L984.561,255.933L984.503,255.535L984.381,255.480L984.312,255.361L984.348,255.361L984.467,255.470L984.565,255.519L984.611,255.782L984.638,256.021M970.860,256.248L970.834,256.255L970.783,256.222L970.792,256.181L970.829,256.163L970.874,256.193L970.860,256.248M985.316,257.311L985.325,257.473L985.262,257.451L985.244,257.388L985.231,257.225L985.170,257.065L985.244,257.108L985.301,257.233L985.316,257.311M23.432,262.199L23.525,262.259L23.598,262.340L23.637,262.452L23.636,262.480L23.583,262.480L23.517,262.445L23.469,262.398L23.444,262.386L23.437,262.375L23.493,262.382L23.559,262.430L23.606,262.452L23.601,262.397L23.540,262.300L23.504,262.267L23.460,262.239L23.409,262.220L23.376,262.238L23.358,262.246L23.349,262.223L23.355,262.204L23.372,262.183L23.432,262.199M25.181,263.360L25.169,263.384L25.149,263.364L25.161,263.327L25.171,263.295L25.190,263.312L25.181,263.360M70.059,266.355L70.052,266.373L70.017,266.348L69.950,266.302L69.893,266.251L69.891,266.229L69.967,266.200L70.066,266.176L70.089,266.209L70.072,266.254L70.059,266.355M24.947,267.536L24.920,267.550L24.888,267.545L24.867,267.524L24.865,267.491L24.891,267.467L24.927,267.475L24.949,267.505L24.947,267.536M22.230,267.686L22.249,267.707L22.288,267.701L22.324,267.697L22.303,267.719L22.230,267.727L22.192,267.673L22.235,267.632L22.274,267.624L22.279,267.636L22.277,267.649L22.259,267.649L22.229,267.659L22.230,267.686M15.876,268.201L15.911,268.243L15.912,268.263L15.896,268.259L15.848,268.247L15.832,268.222L15.867,268.238L15.882,268.234L15.848,268.198L15.819,268.170L15.798,268.159L15.797,268.145L15.823,268.152L15.876,268.201M67.825,271.193L67.762,271.210L67.686,271.209L67.645,271.168L67.640,271.134L67.665,271.133L67.690,271.139L67.797,271.145L67.827,271.170L67.825,271.193M80.977,289.477L80.962,289.527L80.915,289.509L80.881,289.446L80.862,289.377L80.870,289.322L80.900,289.325L80.942,289.393L80.977,289.477' },\n  { name: 'Kosovo', path: 'M552.550,121.239L552.496,121.865L552.172,121.840L551.896,120.731L551.262,120.418L550.648,119.598L551.055,118.912L551.637,118.692L551.889,117.677L552.324,117.507L552.723,117.939L553.212,118.129L553.589,118.616L554.017,118.760L554.563,119.327L554.920,119.310L554.711,120.055L554.446,120.418L554.553,120.648L553.998,120.765L552.550,121.239' },\n  { name: 'Kuwait', path: 'M627.940,159.239L628.651,160.627L628.491,161.344L629.616,163.716L627.731,163.798L626.901,162.300L624.486,161.996L626.113,158.977L627.940,159.239' },\n  { name: 'Kyrgyzstan', path: 'M679.394,120.584L679.520,119.244L681.038,118.812L685.540,119.866L685.319,118.060L686.531,117.427L690.559,118.713L691.356,118.376L695.561,118.460L699.414,118.780L701.082,119.879L702.804,120.327L702.704,121.019L699.318,122.675L698.851,123.889L695.718,124.253L695.445,126.206L692.599,125.795L691.042,126.394L689.077,127.852L689.632,128.597L689.100,129.326L684.375,129.810L680.933,128.775L678.216,129.022L677.971,127.199L680.912,127.719L681.551,126.767L683.596,127.068L686.129,124.866L682.575,123.255L681.016,124.017L678.765,122.866L680.244,120.885L679.394,120.584' },\n  { name: 'Laos', path: 'M789.581,208.617L790.334,207.200L790.109,204.538L787.488,201.797L786.869,198.694L784.420,196.140L782.320,195.924L781.925,197.018L780.334,197.109L779.437,196.555L776.813,198.431L776.356,195.612L776.567,192.299L774.702,192.155L774.275,190.265L772.936,189.295L773.328,188.137L775.310,186.091L775.676,186.830L777.142,186.916L776.136,183.319L777.468,182.858L779.470,185.341L781.170,188.198L784.528,188.223L786.042,190.965L784.416,191.789L783.795,192.919L787.340,194.800L790.155,198.516L792.288,201.287L794.687,203.475L795.708,205.696L795.559,208.839L793.002,207.682L791.977,209.850L789.581,208.617' },\n  { name: 'Latvia', path: 'M548.399,78.825L548.157,76.622L549.005,74.784L550.990,73.785L553.140,75.971L554.959,75.914L555.019,73.667L556.856,73.150L557.910,73.509L560.055,74.595L561.928,74.601L563.151,75.274L563.618,76.694L564.688,78.421L562.433,79.550L561.123,80.042L558.654,78.622L557.400,78.434L556.973,77.826L554.769,78.115L550.894,77.927L548.399,78.825' },\n  { name: 'Lebanon', path: 'M594.395,148.857L593.692,148.898L593.509,149.449L592.626,149.443L593.287,146.882L594.351,144.666L594.389,144.557L595.586,144.717L596.153,145.950L594.851,147.135L594.395,148.857' },\n  { name: 'Lesotho', path: 'M577.494,344.553L578.358,345.502L577.436,347.031L576.910,348.057L575.381,348.548L574.805,349.553L573.826,349.866L572.022,347.447L573.571,345.456L575.098,344.225L576.390,343.584L577.494,344.553' },\n  { name: 'Liberia', path: 'M478.604,239.775L477.877,239.803L475.021,238.304L472.512,235.911L470.160,234.190L468.306,232.161L468.975,231.155L469.128,230.241L470.388,228.534L471.685,227.066L472.276,226.996L473.001,226.642L474.148,228.568L473.958,229.831L474.494,230.501L475.277,230.516L475.848,229.250L476.631,229.331L476.498,230.245L476.768,231.765L476.159,233.162L476.963,234.026L477.842,234.236L479.011,235.553L479.090,236.792L478.823,237.185L478.604,239.775' },\n  { name: 'Libya', path: 'M540.302,181.606L538.409,182.775L536.844,181.048L532.526,179.692L531.299,177.723L529.137,176.262L527.882,176.838L526.891,175.084L526.760,173.737L525.115,171.445L526.155,170.131L525.876,168.153L526.179,166.432L525.953,164.999L526.367,162.433L526.189,160.972L525.258,158.196L526.535,157.467L526.725,156.138L526.402,154.836L528.185,153.624L528.967,152.617L530.226,151.714L530.290,149.299L533.429,150.381L534.527,150.110L536.754,150.635L540.323,152.040L541.696,154.835L544.109,155.446L547.924,156.762L550.848,158.325L552.099,157.510L553.286,156.063L552.521,153.654L553.257,152.125L555.070,150.651L556.859,150.222L560.475,150.866L561.475,152.272L562.461,152.285L563.343,152.821L566.001,153.190L566.727,154.229L565.881,155.738L566.395,157.083L565.856,159.024L566.804,161.557L567.446,172.740L567.953,184.320L568.208,190.599L565.071,190.609L565.080,191.928L554.004,185.907L542.997,179.887L540.302,181.606' },\n  { name: 'Liechtenstein', path: 'M523.540,105.910L523.347,105.893L523.311,105.895L523.286,105.787L523.287,105.556L523.378,105.255L523.403,105.304L523.420,105.367L523.445,105.435L523.460,105.517L523.504,105.601L523.580,105.681L523.607,105.757L523.575,105.853L523.540,105.910' },\n  { name: 'Lithuania', path: 'M553.003,83.865L552.711,83.097L552.845,82.274L551.753,81.797L549.249,81.285L548.399,78.825L550.894,77.927L554.769,78.115L556.973,77.826L557.400,78.434L558.654,78.622L561.123,80.042L561.580,81.353L559.841,82.303L559.565,84.000L557.201,85.133L554.937,85.113L554.244,84.186L553.003,83.865' },\n  { name: 'Luxembourg', path: 'M514.555,96.495L515.060,97.180L514.966,98.526L514.270,98.591L513.721,98.324L513.931,96.609L514.555,96.495' },\n  { name: 'Macau', path: 'M808.335,183.705L808.328,183.636L808.350,183.560L808.436,183.546L808.507,183.620L808.501,183.623L808.385,183.685L808.348,183.698L808.335,183.705' },\n  { name: 'Madagascar', path: 'M636.621,292.712L637.289,294.050L637.872,296.127L638.134,299.910L638.761,301.381L638.383,302.889L637.833,303.814L637.027,301.971L636.447,302.902L636.811,305.231L636.476,306.565L635.669,307.291L635.315,309.955L633.990,313.620L632.333,317.954L630.185,323.912L628.807,328.284L627.303,331.931L625.032,332.675L622.535,334.005L621.063,333.202L619.032,332.077L618.404,330.418L618.424,327.630L617.646,325.123L617.557,322.861L618.204,320.594L619.496,320.049L619.578,319.003L621.052,316.619L621.422,314.616L620.880,313.127L620.482,311.144L620.439,308.247L621.504,306.487L621.994,304.493L623.369,304.377L624.940,303.732L625.993,303.164L627.202,303.121L628.883,301.329L631.247,299.393L632.145,297.811L631.832,296.467L632.984,296.845L634.604,294.660L634.743,292.769L635.722,291.362L636.621,292.712' },\n  { name: 'Malawi', path: 'M595.401,289.725L594.550,292.115L595.187,296.203L596.145,296.157L597.105,297.171L598.180,299.445L598.234,303.489L597.013,304.151L596.070,306.333L594.372,304.390L594.274,302.174L594.922,300.712L594.804,299.452L593.744,298.656L592.977,298.945L591.441,297.435L590.019,296.621L590.947,293.700L591.849,292.605L591.401,290.000L592.037,287.450L592.535,286.598L591.904,283.929L590.624,282.526L593.325,283.113L593.865,283.982L594.768,285.449L595.401,289.725' },\n  { name: 'Malaysia', path: 'M829.082,239.418L827.071,240.489L824.650,239.959L821.461,239.958L820.602,243.534L819.564,244.628L818.265,249.001L816.020,249.671L813.368,248.790L812.044,249.066L810.470,250.656L808.691,250.429L806.917,251.069L804.970,249.292L804.449,247.191L806.513,248.268L808.642,247.681L809.128,245.018L810.296,244.425L813.604,243.744L815.525,241.257L816.831,239.268L818.141,240.898L818.694,239.826L820.022,239.926L820.127,237.918L820.156,236.369L822.147,234.182L823.383,231.725L824.503,231.714L826.032,233.305L826.250,234.672L828.134,235.549L830.511,236.495L830.396,237.726L828.542,237.882L829.082,239.418M780.156,233.988L780.466,235.603L782.275,235.228L783.106,233.936L783.761,234.229L785.508,236.128L786.780,238.233L786.993,240.351L786.734,241.781L787.032,242.862L787.282,244.723L788.282,245.590L789.445,248.371L789.420,249.434L787.456,249.644L784.770,247.314L781.423,244.818L781.058,243.216L779.401,241.113L778.953,238.509L777.879,236.795L778.053,234.505L777.366,233.172L777.816,232.611L780.156,233.988' },\n  { name: 'Maldives', path: 'M703.962,240.404L703.915,240.434L703.870,240.422L703.853,240.385L703.875,240.330L703.911,240.260L703.936,240.184L703.973,240.143L704.003,240.157L704.000,240.199L703.987,240.258L703.980,240.334L703.962,240.404M703.750,243.339L703.692,243.345L703.654,243.291L703.660,243.213L703.705,243.158L703.778,243.155L703.821,243.204L703.800,243.280L703.750,243.339' },\n  { name: 'Mali', path: 'M466.516,207.536L467.449,206.963L467.938,205.111L468.810,205.038L470.716,205.914L472.276,205.292L473.335,205.501L473.757,204.802L484.783,204.754L485.411,202.552L484.938,202.165L483.728,188.594L482.555,175.022L486.693,174.966L495.793,181.827L504.969,188.688L505.622,190.161L507.323,191.061L508.589,191.572L508.629,193.573L511.659,193.265L511.709,200.507L510.220,202.607L509.996,204.545L507.558,205.044L503.808,205.314L502.794,206.432L501.031,206.555L499.268,206.570L498.582,205.966L497.067,206.414L494.495,207.718L493.968,208.701L491.828,210.111L491.451,210.919L490.295,211.559L488.964,211.135L488.206,211.902L487.793,214.059L485.591,216.665L485.649,217.730L484.889,219.063L485.063,220.889L483.920,221.355L483.272,221.751L482.852,220.406L482.052,220.761L481.576,220.700L481.061,221.617L478.926,221.591L478.165,221.119L477.802,221.405L476.965,220.498L477.119,219.562L476.777,219.195L476.186,219.504L476.302,218.481L476.875,217.672L475.754,216.355L475.433,215.487L474.826,214.796L474.274,214.714L473.608,215.154L472.713,215.575L471.949,216.256L470.771,216.004L470.013,215.206L469.557,215.101L468.833,215.520L468.395,215.524L468.248,214.372L468.386,213.393L468.164,212.177L467.142,211.293L466.620,209.493L466.516,207.536' },\n  { name: 'Malta', path: 'M537.309,140.167L537.156,140.216L536.996,140.121L536.957,140.063L537.170,140.014L537.278,140.057L537.327,140.140L537.309,140.167M537.998,140.724L537.916,140.828L537.664,140.823L537.436,140.662L537.416,140.324L537.672,140.391L537.916,140.617L537.998,140.724' },\n  { name: 'Marshall Islands', path: 'M960.874,218.428L960.806,218.450L960.748,218.427L960.781,218.387L960.860,218.379L960.894,218.391L960.874,218.428M967.623,230.516L967.587,230.565L967.318,230.536L967.190,230.476L967.197,230.431L967.412,230.474L967.623,230.516M973.967,231.053L974.329,231.215L974.784,231.139L974.715,231.188L974.546,231.233L974.435,231.272L974.358,231.272L974.265,231.257L973.958,231.144L973.779,230.997L973.814,230.948L973.967,231.053M975.312,231.336L975.422,231.404L975.625,231.399L975.832,231.572L975.758,231.562L975.648,231.488L975.551,231.456L975.426,231.465L975.364,231.437L975.312,231.336M970.298,235.167L970.253,235.262L970.184,235.256L970.237,235.185L970.269,235.086L970.308,234.805L970.435,234.705L970.519,234.588L970.508,234.709L970.371,234.836L970.298,235.167' },\n  { name: 'Mauritania', path: 'M466.516,207.536L464.733,205.377L463.112,203.063L461.306,202.230L460.013,201.306L458.481,201.340L457.128,202.026L455.770,201.754L454.807,202.762L454.608,201.068L455.409,199.517L455.815,196.557L455.582,193.449L455.287,191.886L455.596,190.318L454.931,188.823L453.532,187.465L454.155,186.416L464.813,186.436L464.393,181.894L465.091,180.279L467.637,179.997L467.730,171.951L476.575,172.115L476.678,167.352L486.693,174.966L482.555,175.022L483.728,188.594L484.938,202.165L485.411,202.552L484.783,204.754L473.757,204.802L473.335,205.501L472.276,205.292L470.716,205.914L468.810,205.038L467.938,205.111L467.449,206.963L466.516,207.536' },\n  { name: 'Mauritius', path: 'M657.149,317.916L656.796,318.005L656.413,317.975L656.279,317.806L656.256,317.736L656.392,317.669L656.404,317.453L656.500,317.110L656.596,316.969L656.800,316.844L656.904,316.567L657.087,316.382L657.309,316.360L657.497,316.701L657.613,317.060L657.548,317.419L657.384,317.551L657.315,317.759L657.149,317.916' },\n  { name: 'Mexico', path: 'M238.063,172.150L236.399,174.911L235.567,177.174L234.700,181.387L234.194,182.923L234.393,184.638L234.993,186.172L235.151,188.611L236.600,190.952L236.999,192.746L237.863,194.294L240.657,195.128L241.616,196.444L244.129,195.565L246.255,195.247L248.375,194.682L250.164,194.143L252.062,192.860L252.942,191.026L253.545,188.384L254.151,187.465L256.116,186.641L259.099,185.912L261.492,186.021L263.180,185.755L263.739,186.422L263.433,187.936L261.703,189.806L260.806,191.720L261.243,192.268L260.670,193.627L259.689,196.081L259.093,195.273L258.514,195.326L257.989,195.367L256.777,197.265L256.326,196.893L255.977,197.038L255.941,197.501L253.414,197.466L250.857,197.471L250.633,199.242L249.394,199.249L250.283,200.299L251.206,201.025L251.425,201.707L251.846,201.897L251.642,202.968L248.117,202.978L246.470,205.541L246.786,206.128L246.394,206.866L246.246,207.782L243.510,204.396L242.226,203.375L240.091,202.555L238.528,202.783L236.166,203.967L234.740,204.276L232.912,203.448L230.934,202.850L228.565,201.407L226.569,200.966L223.667,199.504L221.585,198.001L221.012,197.162L219.507,196.974L216.849,195.979L215.915,194.544L213.236,192.759L212.155,190.776L211.764,189.244L212.726,188.937L212.600,188.040L213.365,187.224L213.565,186.137L212.889,184.725L212.859,183.473L212.221,181.886L210.373,178.761L208.080,176.304L207.149,174.344L205.152,173.060L204.849,172.292L205.748,170.348L204.560,169.615L203.359,168.087L203.247,165.893L201.870,165.637L200.738,163.981L199.877,162.451L200.014,161.468L199.197,159.097L199.086,156.689L199.544,155.481L198.057,154.234L197.124,154.371L195.915,153.504L195.041,154.781L194.951,156.290L194.382,158.651L194.911,159.948L196.327,162.114L196.574,162.854L196.923,163.079L196.995,164.159L197.482,164.115L197.495,166.143L198.103,166.943L198.387,168.057L199.666,169.657L199.811,172.582L200.261,173.959L200.677,175.433L200.527,177.091L201.814,177.195L202.644,178.624L203.377,180.028L203.211,180.591L201.863,181.746L201.385,181.731L201.012,179.820L199.562,178.027L197.885,176.507L196.647,175.708L197.267,173.408L197.297,171.704L196.265,170.729L194.779,169.326L194.318,169.730L193.854,168.911L192.395,168.150L191.294,166.324L191.552,166.087L192.610,166.265L193.914,165.091L194.386,163.672L192.917,161.429L191.580,160.558L191.168,158.595L190.912,156.533L190.578,154.019L190.513,151.190L193.602,150.948L197.076,150.607L196.613,151.222L200.074,152.751L205.361,154.966L210.646,154.943L212.751,154.942L213.186,153.645L217.776,153.646L218.380,154.761L219.416,155.755L220.551,157.138L220.907,158.780L221.125,160.509L222.279,161.459L224.273,162.402L226.542,159.918L228.738,159.857L230.328,161.110L231.172,163.263L231.673,165.106L232.845,166.899L232.934,169.100L233.351,170.578L235.231,171.553L236.990,172.244L238.063,172.150' },\n  { name: 'Micronesia', path: 'M882.087,223.624L881.898,223.881L881.877,223.797L881.929,223.644L882.004,223.469L882.079,223.364L882.184,223.333L882.272,223.478L882.196,223.603L882.087,223.624M920.646,230.129L920.599,230.146L920.575,230.130L920.579,230.050L920.592,230.022L920.637,230.019L920.719,230.041L920.726,230.061L920.646,230.129M920.021,230.399L920.002,230.441L919.831,230.425L919.806,230.402L919.819,230.383L919.898,230.365L919.903,230.308L919.861,230.295L919.893,230.266L919.959,230.260L920.000,230.295L920.025,230.347L920.021,230.399M938.637,232.074L938.482,232.145L938.277,232.113L938.191,231.857L938.093,231.788L938.102,231.662L938.235,231.558L938.543,231.642L938.671,231.824L938.611,231.945L938.637,232.074M952.003,236.753L952.045,236.905L951.862,236.831L951.833,236.777L951.931,236.724L952.003,236.753' },\n  { name: 'Moldova', path: 'M564.919,102.340L565.439,101.887L567.016,101.584L568.949,102.540L569.969,102.655L571.195,103.480L571.174,104.520L572.142,105.022L572.691,106.305L573.669,107.085L573.565,107.542L574.073,107.853L573.454,108.080L571.986,107.991L571.680,107.566L571.200,107.811L571.456,108.360L570.924,109.338L570.645,110.391L570.069,110.724L569.423,109.324L569.496,108.014L569.223,106.667L567.545,104.843L566.587,103.549L565.704,102.639L564.919,102.340' },\n  { name: 'Monaco', path: 'M518.649,116.044L518.498,116.102L518.502,116.036L518.538,115.999L518.586,115.982L518.644,116.011L518.649,116.044' },\n  { name: 'Mongolia', path: 'M712.523,99.037L714.835,98.505L718.145,95.882L721.010,94.468L723.616,95.391L726.147,95.435L728.562,96.840L731.026,96.949L734.896,97.721L736.062,95.610L734.034,93.840L734.639,90.723L738.053,91.966L740.431,92.318L743.712,93.091L745.568,95.345L749.776,96.610L751.699,96.052L754.489,95.659L757.155,96.055L760.402,97.513L762.739,99.082L764.967,99.050L768.301,99.550L770.095,98.789L772.988,98.281L775.190,96.134L776.860,96.459L778.771,97.478L781.498,97.222L781.700,99.536L781.801,102.602L783.174,103.856L784.327,103.467L787.026,103.945L788.222,102.813L790.778,103.793L794.311,105.938L794.711,107.029L792.557,106.683L789.227,107.090L788.015,107.963L787.412,109.991L784.331,111.180L782.768,112.807L779.883,112.187L778.323,111.910L778.048,113.882L779.451,115.057L780.377,116.067L779.150,117.095L778.181,118.733L775.780,119.809L772.054,119.925L768.495,120.987L766.344,122.629L764.762,121.678L761.699,121.681L757.079,119.823L754.375,119.368L751.215,119.793L745.696,119.107L742.949,119.179L740.666,117.362L738.281,114.543L736.588,114.204L732.747,112.298L729.196,111.870L725.995,111.345L724.483,110.014L723.766,106.429L720.926,103.958L716.910,102.805L714.125,101.178L712.523,99.037' },\n  { name: 'Montenegro', path: 'M549.994,119.868L549.781,119.293L548.821,120.799L549.078,121.772L548.527,121.535L547.730,120.537L546.586,119.930L546.820,119.410L547.044,117.727L547.799,117.017L548.244,116.737L548.957,117.262L549.363,117.686L550.219,118.015L551.238,118.650L551.055,118.912L550.648,119.598L549.994,119.868' },\n  { name: 'Morocco', path: 'M486.445,141.035L487.996,142.387L490.485,142.167L493.186,142.870L494.322,142.904L495.297,144.925L495.443,146.837L496.337,150.157L497.030,150.825L496.541,152.047L493.075,152.577L491.867,153.740L490.331,154.014L490.191,156.343L487.064,157.587L486.021,159.162L483.827,160.007L481.154,160.486L476.796,162.807L476.745,166.533L476.337,166.533L476.337,166.533L476.364,168.217L474.701,168.319L473.818,169.034L472.597,169.034L471.634,168.626L469.363,168.963L468.422,171.414L467.573,171.644L466.198,175.609L462.362,179.002L461.368,183.344L460.221,184.757L459.868,185.890L453.734,186.141L453.686,186.136L453.855,184.679L454.922,183.822L455.855,182.183L455.708,181.119L456.698,178.900L458.256,176.901L459.180,176.394L459.943,174.560L460.064,172.885L461.103,170.941L462.934,169.795L464.736,166.584L464.787,166.540L466.171,165.332L468.673,164.985L470.839,162.835L472.200,161.998L474.489,159.372L473.939,155.460L475.025,152.754L475.427,151.098L477.183,148.974L479.861,147.537L481.840,146.237L483.659,142.976L484.524,141.020L486.445,141.035' },\n  { name: 'Mozambique', path: 'M595.401,289.725L597.486,289.471L600.773,290.357L601.507,289.960L603.432,289.879L604.449,288.935L606.104,288.987L609.169,287.766L611.437,285.943L611.830,287.353L611.595,290.485L611.830,293.245L611.746,298.159L612.170,299.699L611.241,301.946L610.054,304.130L608.200,306.080L605.630,307.275L602.461,308.801L599.198,312.177L598.118,312.751L596.101,314.985L594.941,315.712L594.590,317.954L595.747,320.336L596.178,322.180L596.157,323.121L596.647,322.963L596.391,326.048L595.867,327.508L596.474,328.047L595.996,329.355L594.801,330.474L592.510,331.537L589.142,333.239L587.871,334.401L588.003,335.726L588.675,335.938L588.319,337.593L586.281,337.566L586.152,336.176L585.857,334.766L585.709,333.637L586.404,330.131L585.815,327.897L584.742,323.471L587.791,319.902L588.629,317.634L589.056,317.348L589.455,315.497L589.058,314.566L589.281,312.216L589.913,310.036L590.087,306.056L588.708,305.046L587.411,304.817L586.853,304.039L585.610,303.376L583.316,303.438L583.188,302.265L583.012,300.027L591.441,297.435L592.977,298.945L593.744,298.656L594.804,299.452L594.922,300.712L594.274,302.174L594.372,304.390L596.070,306.333L597.013,304.151L598.234,303.489L598.180,299.445L597.105,297.171L596.145,296.157L595.187,296.203L594.550,292.115L595.401,289.725' },\n  { name: 'Myanmar', path: 'M771.492,190.022L770.101,191.385L768.193,191.526L767.407,194.926L766.330,195.497L768.024,198.256L770.073,200.552L771.479,202.628L770.846,205.361L769.976,205.943L770.796,207.520L772.867,210.019L773.348,211.774L773.443,213.235L774.793,216.102L773.555,219.034L772.512,222.265L772.035,219.931L772.657,217.522L771.554,215.661L771.456,212.236L770.185,210.607L768.936,206.843L767.926,202.871L766.390,200.266L764.794,201.843L761.970,204.085L760.393,203.805L758.596,203.068L759.034,199.171L758.080,196.226L755.468,192.601L755.655,191.467L754.007,191.064L751.695,188.499L751.138,185.969L752.159,186.445L751.875,184.190L753.103,183.444L752.614,182.109L753.065,181.038L752.677,177.783L754.902,178.500L755.712,175.907L755.581,174.375L756.495,171.737L756.020,169.938L759.023,167.765L761.070,168.333L760.418,166.398L761.230,165.822L760.761,164.630L762.275,164.396L763.588,166.247L764.929,166.997L765.554,169.403L766.033,171.997L764.069,174.623L764.354,178.353L767.129,177.831L768.240,180.726L770.056,181.335L769.688,183.948L771.898,185.128L773.170,185.707L775.015,184.791L775.310,186.091L773.328,188.137L772.936,189.295L771.492,190.022' },\n  { name: 'Namibia', path: 'M543.755,343.361L541.850,340.986L540.881,338.689L540.393,335.628L539.806,333.350L539.026,328.507L539.054,324.745L538.746,323.030L537.718,321.734L536.370,319.136L535.014,315.364L534.453,313.389L532.279,310.320L532.152,307.907L533.481,307.309L535.131,306.773L536.907,306.867L538.513,308.289L538.932,308.068L550.041,307.932L551.900,309.439L558.516,309.884L563.588,308.603L565.854,307.888L567.625,308.069L568.681,308.778L568.693,309.039L567.125,309.747L566.295,309.754L564.507,310.987L563.503,309.690L559.249,310.791L557.210,310.895L556.777,322.097L554.093,322.206L553.797,331.384L553.274,342.998L550.813,344.606L549.367,344.835L547.710,344.241L546.519,344.012L546.122,342.667L545.097,341.806L543.755,343.361' },\n  { name: 'Nepal', path: 'M736.339,165.840L736.406,167.195L737.164,169.193L737.108,170.438L734.876,170.490L731.492,169.757L729.354,169.458L727.491,167.858L723.730,167.451L719.895,165.687L717.080,164.144L714.266,162.954L714.762,160.012L716.154,158.586L717.071,157.834L719.449,158.801L722.555,160.849L724.143,161.301L725.331,162.811L727.531,163.431L729.976,164.812L733.151,165.533L736.339,165.840' },\n  { name: 'Netherlands', path: 'M514.254,86.322L516.208,86.407L516.690,87.424L516.218,90.178L515.663,91.310L514.235,91.311L514.752,94.463L513.411,93.761L511.857,92.444L509.663,93.069L507.910,92.833L509.121,92.006L511.079,87.581L514.254,86.322' },\n  { name: 'New Caledonia', path: 'M951.388,319.787L953.093,321.737L954.114,323.184L952.877,323.938L951.612,323.088L950.049,321.673L948.742,320.007L947.532,317.790L947.439,316.724L948.601,316.769L949.842,317.838L950.753,318.907L951.388,319.787' },\n  { name: 'New Zealand', path: 'M954.874,367.243L954.598,370.596L956.056,368.421L956.668,369.290L955.496,371.699L956.904,372.737L958.484,372.992L960.757,371.777L961.826,372.145L959.345,374.972L957.344,376.830L955.424,376.765L954.108,377.733L953.453,379.103L952.663,379.687L950.354,381.335L947.389,383.430L944.438,384.649L944.651,383.846L943.947,383.406L947.447,380.890L947.931,379.195L945.990,377.921L946.801,376.767L949.372,375.656L951.383,373.204L952.587,371.144L952.907,369.010L953.337,368.448L952.936,367.133L952.681,364.315L952.848,362.079L953.952,361.832L954.451,363.579L955.958,364.405L954.874,367.243M940.688,382.296L940.257,383.559L943.059,382.320L942.756,383.612L941.724,384.899L939.644,386.315L936.190,388.569L933.922,389.799L933.674,391.270L931.711,391.308L928.655,392.461L926.404,394.463L922.303,397.566L919.166,398.937L917.174,399.813L914.961,399.748L914.235,398.736L911.736,398.521L912.283,397.394L915.561,395.118L921.063,392.098L923.127,391.523L925.837,390.359L929.249,388.757L932.013,387.170L934.939,384.891L936.514,384.117L938.247,382.410L941.160,380.996L940.688,382.296' },\n  { name: 'Nicaragua', path: 'M263.285,218.632L262.411,217.641L261.225,216.373L260.705,215.313L259.625,214.324L258.362,212.904L258.709,212.418L259.124,212.891L259.351,212.669L260.219,212.540L260.623,211.821L261.030,211.793L261.099,210.247L261.751,210.173L262.323,210.195L262.987,209.356L263.747,209.992L264.061,209.602L264.599,209.228L265.630,208.362L265.729,207.715L265.990,207.742L266.404,206.990L266.699,206.899L267.129,207.379L267.668,207.521L268.309,207.122L269.004,207.119L269.991,206.709L270.408,206.280L271.344,206.345L271.084,206.646L270.888,207.348L271.077,208.499L270.358,209.570L269.962,210.835L269.762,212.221L269.845,213.032L269.802,214.447L269.356,214.756L268.991,216.101L269.114,216.932L268.485,217.736L268.546,218.586L268.928,219.102L268.213,219.769L267.415,219.559L267.009,218.912L266.154,218.650L265.486,219.060L263.734,218.227L263.285,218.632' },\n  { name: 'Niger', path: 'M505.945,215.953L506.003,213.800L502.823,213.087L502.736,211.565L501.184,209.512L500.814,208.079L501.031,206.555L502.794,206.432L503.808,205.314L507.558,205.044L509.996,204.545L510.220,202.607L511.709,200.507L511.659,193.265L515.500,191.863L523.321,185.685L532.526,179.692L536.844,181.048L538.409,182.775L540.302,181.606L541.088,186.494L542.127,187.312L542.196,188.312L543.358,189.390L542.799,190.743L541.882,197.124L541.824,201.214L538.382,204.179L537.262,208.322L538.423,209.486L538.444,211.509L540.212,211.582L539.957,213.063L539.181,213.243L539.106,214.244L538.594,214.314L536.684,210.871L536.036,210.746L533.903,212.504L531.759,211.586L530.275,211.403L529.484,211.844L527.868,211.749L526.255,213.089L524.850,213.166L521.502,211.540L520.201,212.312L518.795,212.259L517.754,211.071L514.987,209.898L512.029,210.270L511.315,210.950L510.934,212.759L510.149,214.027L509.967,216.834L507.857,215.024L506.869,215.032L505.945,215.953' },\n  { name: 'Nigeria', path: 'M523.580,238.494L520.702,239.626L519.649,239.460L518.584,240.165L516.364,240.096L514.876,238.129L513.957,235.853L511.989,233.782L509.906,233.820L507.460,233.819L507.612,228.750L507.539,226.750L508.057,224.766L508.907,223.802L510.245,221.856L509.951,221.010L510.491,219.744L509.863,217.879L509.967,216.834L510.149,214.027L510.934,212.759L511.315,210.950L512.029,210.270L514.987,209.898L517.754,211.071L518.795,212.259L520.201,212.312L521.502,211.540L524.850,213.166L526.255,213.089L527.868,211.749L529.484,211.844L530.275,211.403L531.759,211.586L533.903,212.504L536.036,210.746L536.684,210.871L538.594,214.314L539.106,214.244L540.215,215.497L539.922,216.065L539.791,217.110L537.497,219.543L536.792,221.550L536.417,223.184L535.835,223.885L535.293,226.086L533.822,227.382L533.404,228.973L532.790,230.240L532.540,231.547L530.644,232.606L529.080,231.314L528.030,231.366L526.390,233.207L525.588,233.235L524.285,236.269L523.580,238.494' },\n  { name: 'North Korea', path: 'M830.023,120.190L830.700,120.725L829.629,120.541L829.152,121.577L829.019,122.618L830.429,124.815L829.515,125.490L829.383,126.030L828.957,126.934L827.551,127.437L826.849,128.289L827.416,129.668L827.281,130.020L828.547,130.538L830.663,131.935L830.656,132.705L829.656,132.915L827.905,133.069L827.570,134.507L826.363,134.393L826.336,134.682L824.799,134.076L824.764,134.674L824.128,134.939L823.760,134.340L822.957,134.048L822.029,133.540L822.091,132.138L822.527,131.764L822.029,131.182L821.889,129.464L821.481,128.943L819.825,128.596L818.224,127.742L819.199,125.772L821.054,124.128L821.533,121.959L823.299,122.917L825.560,123.029L824.210,121.415L827.333,120.098L827.309,118.384L830.023,120.190' },\n  { name: 'North Macedonia', path: 'M552.172,121.840L552.496,121.865L552.550,121.239L553.998,120.765L554.553,120.648L555.395,120.469L556.561,120.418L557.931,121.400L558.325,123.422L557.851,123.524L557.489,124.057L556.104,123.998L555.201,124.666L553.561,124.937L552.433,124.192L551.948,122.881L552.172,121.840' },\n  { name: 'Northern Cyprus', path: 'M585.658,142.994L585.841,142.977L586.126,142.209L588.014,142.251L590.270,141.301L588.675,142.657L588.940,143.254L588.646,143.142L588.176,143.383L587.776,143.317L587.660,143.439L587.568,143.117L587.356,142.922L586.847,142.889L586.170,143.160L585.658,142.994' },\n  { name: 'Northern Mariana Islands', path: 'M898.322,194.500L898.263,194.617L898.176,194.531L898.123,194.361L898.248,194.377L898.300,194.412L898.322,194.500M898.943,196.650L898.825,196.719L898.927,196.409L898.966,196.355L899.065,196.468L898.943,196.650M899.863,202.121L899.807,202.143L899.717,202.131L899.646,202.082L899.616,201.998L899.792,201.993L899.870,202.056L899.863,202.121M900.734,205.913L900.743,205.994L900.598,205.975L900.553,205.938L900.575,205.655L900.750,205.524L900.842,205.497L900.778,205.631L900.791,205.782L900.734,205.913M900.584,206.424L900.493,206.585L900.377,206.335L900.344,206.235L900.430,206.142L900.493,206.145L900.584,206.424M899.845,208.979L899.729,209.126L899.627,209.096L899.559,209.046L899.533,208.962L899.742,208.880L899.837,208.909L899.845,208.979' },\n  { name: 'Norway', path: 'M543.636,14.516L547.259,15.169L545.102,16.394L540.135,16.668L534.897,16.280L534.430,15.640L531.937,15.599L529.823,14.680L534.970,14.160L537.596,14.608L539.144,14.051L543.636,14.516M531.657,15.967L537.830,17.699L533.627,18.613L533.037,20.322L531.563,20.761L531.118,22.685L528.945,22.776L524.791,21.359L526.275,20.534L523.480,19.862L519.734,17.900L518.130,16.081L522.727,15.254L523.810,16.063L526.276,16.030L526.783,15.244L529.300,15.179L531.657,15.967M544.200,20.259L540.471,21.209L537.158,20.670L538.236,20.071L536.965,19.328L540.514,18.863L541.469,19.735L544.200,20.259M555.379,36.581L562.107,38.440L559.753,39.120L562.395,40.786L559.251,41.868L557.683,42.117L558.073,40.224L555.242,39.176L552.362,40.065L551.811,42.043L550.138,43.237L547.831,42.585L545.217,42.719L542.713,41.292L541.632,42.005L540.400,42.116L540.403,43.891L536.506,43.459L536.195,44.961L534.233,44.952L533.147,46.872L531.471,49.863L528.669,53.686L529.542,54.651L528.919,55.771L526.801,55.723L525.659,58.372L526.136,62.124L527.667,63.555L527.255,66.877L525.572,68.871L524.717,70.557L523.085,68.761L518.880,72.146L515.910,72.832L512.730,71.342L511.812,68.195L510.861,61.642L512.783,59.824L518.336,57.452L522.333,54.537L525.831,50.711L530.203,45.501L533.347,43.470L538.373,40.086L542.536,38.945L545.841,39.080L548.360,36.975L551.982,37.087L555.379,36.581' },\n  { name: 'Oman', path: 'M652.049,172.068L651.771,172.639L651.120,171.567L651.766,170.496L652.134,170.769L652.049,172.068M660.258,187.106L659.446,189.260L658.194,189.095L657.698,189.845L657.397,191.439L657.900,193.541L657.673,193.927L656.415,193.917L654.800,195.092L654.653,196.624L654.078,197.288L652.373,197.262L651.362,198.054L651.472,199.324L650.212,200.197L648.677,199.901L646.922,200.962L645.669,201.140L644.614,198.943L642.099,193.753L650.058,190.609L651.308,184.320L649.863,182.092L649.820,180.826L650.493,179.525L650.384,178.239L651.554,177.620L651.034,177.183L651.071,175.135L652.450,175.123L653.860,177.270L655.478,178.412L657.503,178.823L659.163,179.396L660.559,181.199L661.391,182.243L662.402,182.642L662.465,183.343L661.657,185.217L661.308,186.100L660.258,187.106' },\n  { name: 'Pakistan', path: 'M694.930,136.646L697.262,138.131L698.717,140.579L703.375,141.867L701.553,144.530L698.739,144.997L694.585,144.230L693.606,145.586L695.160,148.341L696.559,150.469L699.047,152.021L697.205,153.840L697.756,156.082L695.881,159.237L694.743,162.428L692.489,165.725L689.336,165.486L686.907,168.782L688.895,170.195L689.592,172.615L691.367,174.209L692.248,176.909L686.292,176.901L684.722,178.999L682.649,178.204L681.595,175.944L679.187,173.549L674.301,174.140L669.921,174.199L666.179,174.640L666.678,170.987L670.328,169.362L669.895,167.914L668.536,167.405L668.063,164.636L665.305,163.253L663.960,161.354L662.406,159.700L667.107,161.306L669.711,160.835L671.367,161.236L671.806,160.547L673.706,160.823L676.978,159.515L676.546,156.840L677.664,155.060L679.641,155.065L679.749,154.185L681.690,153.775L682.731,154.068L683.581,153.184L683.035,151.296L683.752,149.398L685.260,148.602L683.779,146.522L686.301,146.620L686.777,145.488L686.405,144.279L687.398,142.952L686.682,141.368L685.711,140.018L686.866,138.631L689.479,137.962L692.360,137.592L693.519,137.004L694.930,136.646' },\n  { name: 'Palau', path: 'M872.783,230.287L872.620,230.354L872.523,230.114L872.528,229.835L872.623,229.620L872.739,229.552L872.762,229.527L872.858,229.249L872.893,229.402L872.858,229.912L872.777,230.110L872.783,230.287M864.059,243.984L863.996,243.998L863.955,243.987L863.959,243.942L863.998,243.896L864.055,243.876L864.099,243.891L864.096,243.934L864.059,243.984' },\n  { name: 'Panama', path: 'M284.273,230.784L283.390,229.877L282.872,228.180L283.593,227.340L282.901,227.124L282.431,226.085L281.091,225.211L279.871,225.412L279.261,226.505L278.108,227.295L277.499,227.405L277.198,228.059L278.441,229.766L277.667,230.168L277.245,230.634L275.949,230.795L275.556,228.916L275.171,229.451L274.266,229.266L273.766,228.001L272.640,227.792L271.939,227.424L270.751,227.429L270.633,228.111L270.338,227.636L270.513,227.012L270.773,226.374L270.692,225.805L271.123,225.433L270.570,224.965L270.613,223.700L271.696,223.419L272.637,224.547L272.549,225.213L273.647,225.354L273.920,225.098L274.645,225.871L276.016,225.644L277.230,224.850L278.938,224.215L279.925,223.276L281.444,223.460L281.327,223.769L282.864,223.877L284.071,224.420L284.932,225.366L285.935,226.235L285.579,226.695L286.141,228.547L285.578,229.482L284.695,229.256L284.273,230.784' },\n  { name: 'Papua New Guinea', path: 'M924.853,267.650L923.954,268.488L923.501,266.632L922.901,265.417L921.683,264.387L920.154,263.045L918.184,262.121L918.984,261.361L920.450,262.242L921.368,262.934L922.505,263.688L923.566,265.009L924.582,266.015L924.853,267.650M907.669,276.732L909.969,278.795L911.487,282.130L913.080,282.026L912.851,283.419L914.941,283.953L914.062,284.546L916.834,285.869L916.396,286.778L914.535,286.997L913.971,286.182L911.647,285.829L908.922,285.356L906.962,283.350L905.536,281.620L904.326,278.869L900.827,277.493L898.409,278.390L896.634,279.428L896.799,281.748L894.538,282.829L893.031,282.303L890.180,282.172L890.950,271.924L891.382,261.676L896.122,263.843L901.188,265.642L903.042,267.254L904.530,268.834L904.817,270.687L909.275,272.630L909.809,274.298L907.231,274.637L907.669,276.732M921.454,270.726L919.980,270.985L919.467,271.867L917.886,272.631L916.400,273.367L914.928,273.363L912.733,272.449L911.223,271.572L911.535,270.599L913.982,271.058L915.520,270.812L916.066,269.305L916.471,269.227L916.598,270.896L918.201,270.656L919.075,269.580L920.683,268.459L920.447,266.606L922.111,266.546L922.652,267.062L922.531,268.807L921.454,270.726M931.890,274.946L931.086,275.260L929.992,274.053L928.954,272.056L928.567,269.660L928.977,269.356L929.193,270.292L929.971,271.005L931.140,272.998L932.355,274.066L931.890,274.946' },\n  { name: 'Paraguay', path: 'M329.695,323.464L330.384,319.698L330.281,318.007L331.328,315.240L336.010,314.325L338.550,314.369L341.223,315.977L341.355,316.947L342.326,318.695L342.547,322.964L345.472,323.568L346.524,322.952L348.437,323.803L349.030,324.742L349.543,327.624L349.969,328.834L350.991,328.974L351.961,328.465L352.987,329.036L353.138,330.764L352.954,332.624L352.652,334.439L352.560,337.214L350.427,339.623L348.369,340.128L345.290,339.648L342.467,338.792L344.480,334.012L343.909,332.625L340.989,331.395L337.458,329.073L335.197,328.594L329.695,323.464' },\n  { name: 'Peru', path: 'M309.404,308.781L308.826,310.394L307.496,311.196L304.576,309.391L304.211,308.101L298.460,304.943L293.182,301.504L290.895,299.566L289.566,296.968L289.952,296.062L287.316,291.935L284.164,286.133L281.236,279.872L280.040,278.439L279.064,276.123L276.819,274.071L274.786,272.798L275.619,271.394L274.158,268.395L274.978,266.193L277.150,264.207L277.505,265.516L276.728,266.265L276.826,267.417L277.968,267.167L279.095,267.507L280.291,269.094L281.834,267.801L282.318,265.679L283.965,262.943L287.279,261.703L290.245,258.411L291.071,256.366L290.639,253.978L291.374,253.680L293.249,255.169L294.162,256.653L295.462,257.464L297.158,260.761L299.232,261.155L300.747,260.323L301.759,260.867L303.420,260.597L305.572,262.069L303.837,265.270L304.667,265.344L306.085,267.016L303.582,266.868L303.218,267.341L300.955,267.946L297.841,270.086L297.701,271.554L297.038,272.648L297.385,274.348L295.748,275.256L295.806,276.584L295.100,277.159L296.370,279.991L297.987,281.904L297.458,283.255L299.301,283.437L300.420,285.114L302.866,285.195L305.054,283.342L305.146,288.119L306.427,288.480L307.949,287.938L310.669,293.000L310.146,294.064L310.156,296.275L310.278,298.950L309.307,300.521L309.906,301.687L309.377,302.744L310.809,305.388L309.404,308.781' },\n  { name: 'Philippines', path: 'M831.791,195.313L833.628,196.211L834.334,195.392L834.717,196.191L834.491,197.494L835.807,199.748L835.525,202.362L834.082,203.404L834.073,205.939L835.000,208.443L836.499,208.790L837.673,208.418L841.316,210.161L841.256,211.873L842.245,212.628L842.130,214.078L839.799,212.534L838.587,210.882L838.014,212.036L836.040,210.154L833.593,210.619L832.142,209.924L832.132,208.624L832.900,207.824L831.995,207.097L831.770,208.230L830.204,206.423L829.571,205.054L828.972,202.043L830.249,203.078L829.717,198.159L830.135,195.309L831.791,195.313M834.904,212.402L834.488,215.119L833.125,213.550L831.443,211.154L833.816,211.269L834.904,212.402M846.200,215.254L847.397,218.765L845.166,217.930L845.350,218.986L846.257,220.926L845.027,221.631L844.648,219.419L843.797,219.256L843.139,217.352L844.793,217.603L844.615,216.412L842.644,214.011L845.300,214.081L846.200,215.254M836.316,216.106L838.086,217.079L839.842,217.074L839.943,218.388L838.821,219.723L837.176,220.668L836.908,219.206L836.918,217.602L836.316,216.106M827.809,224.204L824.327,227.188L825.537,224.989L827.406,223.046L828.866,220.871L829.958,217.747L830.743,220.311L829.115,222.043L827.809,224.204M842.708,221.178L841.829,222.211L841.101,224.198L840.297,225.129L838.443,222.956L838.955,222.114L839.548,221.233L839.624,219.281L841.126,219.096L840.930,221.214L842.617,218.178L842.708,221.178M849.788,227.039L850.219,229.129L850.508,230.893L849.770,233.770L848.529,230.564L847.347,232.159L848.397,234.476L847.706,235.950L844.315,234.125L843.377,231.849L844.117,230.354L842.258,228.867L841.479,230.171L840.168,230.050L838.239,231.804L837.717,230.884L838.621,228.234L840.304,227.349L841.730,226.164L842.808,227.588L844.852,226.727L845.205,225.323L847.154,225.240L846.818,222.808L849.166,224.299L849.511,225.883L849.788,227.039' },\n  { name: 'Poland', path: 'M535.900,93.552L534.749,91.631L534.842,90.595L534.114,88.986L533.164,87.914L533.751,87.111L533.071,85.581L534.591,84.697L538.100,83.306L540.923,82.289L543.298,82.797L543.557,83.530L545.808,83.568L548.721,83.910L553.003,83.865L554.244,84.186L554.937,85.113L555.229,86.444L556.045,87.588L556.205,88.787L554.876,89.400L555.804,90.794L556.041,92.133L557.622,94.759L557.488,95.602L556.345,95.952L554.473,98.486L555.258,99.865L554.708,99.686L552.273,98.506L550.578,98.940L549.402,98.625L548.039,99.283L546.709,98.195L545.756,98.611L545.601,98.426L544.346,96.915L542.534,96.733L542.205,95.791L540.522,95.455L540.242,96.231L538.873,95.609L538.942,94.782L537.124,94.520L535.900,93.552' },\n  { name: 'Portugal', path: 'M477.111,121.763L478.061,120.986L479.110,120.540L479.689,122.037L481.186,122.034L481.633,121.648L483.106,121.754L483.769,123.288L482.569,124.116L482.460,126.503L482.031,126.950L481.886,128.432L480.771,128.694L481.748,130.604L480.982,132.697L481.846,133.643L481.469,134.509L480.478,135.704L480.665,136.758L479.598,137.585L478.243,137.137L476.892,137.488L477.369,134.995L477.190,133.037L476.045,132.743L475.471,131.536L475.748,129.451L476.810,128.295L477.038,127.027L477.646,125.188L477.642,123.892L477.179,122.794L477.111,121.763' },\n  { name: 'Puerto Rico', path: 'M318.733,195.279L320.106,195.556L320.542,196.181L319.769,196.974L317.711,196.955L316.101,197.066L316.067,195.720L316.497,195.261L318.733,195.279' },\n  { name: 'Qatar', path: 'M637.392,175.657L636.973,173.369L637.507,171.719L638.203,171.381L639.135,172.367L639.401,174.208L638.993,176.058L638.261,176.281L637.392,175.657' },\n  { name: 'Republic of the Congo', path: 'M536.050,268.534L535.014,267.456L534.174,267.985L533.050,269.342L530.782,266.012L532.899,264.276L531.859,262.197L532.813,261.406L534.687,261.021L534.912,259.627L536.391,261.137L538.841,261.270L539.698,259.784L540.056,257.693L539.762,255.238L538.453,253.378L539.643,249.736L538.948,249.111L536.883,249.367L536.101,247.743L536.299,246.371L539.802,246.494L542.050,247.324L544.259,248.067L544.452,246.369L545.895,243.443L547.542,241.776L549.423,242.305L551.208,242.480L551.052,244.379L550.229,246.061L549.695,248.023L549.361,250.809L549.514,252.591L549.065,253.683L548.990,254.836L548.667,255.839L546.832,257.355L545.553,258.974L544.335,262.029L544.418,264.616L543.713,265.623L542.090,267.158L540.451,269.129L539.417,268.572L539.242,267.682L537.731,267.651L536.778,268.855L536.050,268.534' },\n  { name: 'Romania', path: 'M555.507,103.379L556.485,102.722L558.036,103.062L559.604,103.073L560.833,103.823L561.607,103.352L563.372,103.057L563.890,102.340L564.919,102.340L565.704,102.639L566.587,103.549L567.545,104.843L569.223,106.667L569.496,108.014L569.423,109.324L570.069,110.724L571.260,111.290L572.354,110.796L573.559,111.323L573.737,112.114L572.620,112.773L571.825,112.486L571.615,116.176L570.099,115.855L568.135,114.743L565.276,115.454L564.127,116.234L560.425,116.073L558.448,115.596L557.501,115.820L556.648,114.563L556.135,114.030L556.660,113.513L556.005,113.133L555.292,113.818L553.748,112.929L553.421,111.667L551.829,110.945L551.446,109.969L549.979,108.763L551.898,108.184L553.160,106.103L554.088,104.022L555.507,103.379' },\n  { name: 'Russia', path: 'M675.704,17.873L672.220,18.163L666.523,17.493L662.585,16.606L659.355,15.006L656.514,14.638L659.224,13.367L662.306,12.946L666.937,13.883L673.541,15.785L675.704,17.873M587.489,14.255L585.371,14.501L583.931,14.642L583.910,14.947L582.112,15.255L579.942,14.814L580.521,14.233L576.677,14.176L579.782,13.837L582.356,13.814L583.061,14.316L583.724,13.870L585.106,13.563L587.937,13.971L587.489,14.255M686.472,19.207L677.574,20.103L677.003,17.053L678.108,16.792L679.612,16.943L685.764,18.263L686.472,19.207M693.945,22.303L695.963,23.450L696.873,22.885L702.238,22.916L707.936,24.049L710.641,24.919L711.889,26.127L710.793,26.814L707.437,28.218L706.841,28.972L709.576,29.328L713.091,29.969L714.263,29.488L717.068,31.119L717.161,30.459L719.747,30.057L726.343,30.477L728.211,31.666L736.689,32.044L734.425,30.103L739.014,30.547L742.040,30.534L746.827,31.872L749.794,33.498L750.005,34.562L755.024,36.562L759.461,37.594L757.867,34.927L762.514,36.071L764.937,35.387L769.787,36.169L770.254,35.457L773.947,35.813L769.275,33.454L770.295,32.353L790.123,34.003L794.026,35.512L802.093,37.453L809.319,36.973L813.901,37.391L817.212,38.442L819.810,40.344L823.323,41.112L825.253,40.559L828.710,40.489L833.236,41.018L836.618,40.719L843.553,43.118L844.817,42.255L840.703,40.530L839.827,39.347L847.336,40.086L851.257,39.925L858.952,41.212L863.559,42.390L879.929,53.142L879.935,53.157L878.918,54.399L875.889,54.191L879.851,55.695L884.305,58.023L886.341,58.784L888.196,59.953L888.663,60.701L883.787,60.085L880.579,62.212L879.077,62.541L878.352,64.526L877.426,66.260L878.258,67.556L872.584,65.590L869.609,67.829L867.315,66.758L866.646,67.995L863.219,67.594L864.674,69.519L865.164,72.351L866.569,73.534L869.885,74.189L874.381,78.450L872.371,78.558L874.123,81.006L876.452,82.278L873.888,83.814L876.419,87.248L873.619,87.982L875.851,91.037L875.097,93.839L872.242,91.767L867.064,87.379L859.322,80.727L856.061,76.668L856.096,74.922L854.732,73.554L857.531,72.900L857.487,69.215L857.886,66.241L859.038,63.987L855.791,60.004L853.460,60.243L855.056,62.570L853.320,65.672L847.278,62.198L842.800,63.158L842.861,67.918L846.620,69.712L842.437,70.476L839.287,70.778L837.237,68.661L833.313,68.217L832.032,69.655L824.692,69.152L818.203,70.019L816.439,75.732L814.086,82.656L818.063,83.035L820.777,84.918L823.609,85.587L823.841,84.084L826.566,84.279L832.778,87.588L835.057,90.147L835.771,93.152L838.637,96.743L841.086,101.647L840.568,106.087L841.248,108.209L840.402,111.782L839.291,115.315L838.798,117.122L836.557,118.916L834.992,118.956L832.501,117.469L830.479,119.707L830.700,120.725L830.023,120.190L829.071,118.636L830.308,118.554L828.482,114.940L826.239,112.321L827.651,111.237L831.036,111.781L830.663,108.796L829.200,105.434L829.380,104.311L828.757,101.550L825.351,102.454L824.058,103.665L820.339,103.661L817.420,100.778L813.095,98.597L808.242,97.616L805.148,94.655L802.888,92.808L800.998,91.514L797.207,88.481L794.293,87.373L790.098,86.478L787.046,86.559L784.527,87.101L783.678,88.598L785.497,89.312L786.745,90.973L786.129,91.937L786.292,95.127L787.273,96.451L785.094,98.381L781.498,97.222L778.771,97.478L776.860,96.459L775.190,96.134L772.988,98.281L770.095,98.789L768.301,99.550L764.967,99.050L762.739,99.082L760.402,97.513L757.155,96.055L754.489,95.659L751.699,96.052L749.776,96.610L745.568,95.345L743.712,93.091L740.431,92.318L738.053,91.966L734.639,90.723L734.034,93.840L736.062,95.610L734.896,97.721L731.026,96.950L728.562,96.840L726.147,95.435L723.616,95.391L721.010,94.468L718.145,95.882L714.835,98.505L712.523,99.037L711.689,99.289L709.568,97.412L706.639,97.823L705.017,96.528L703.033,95.944L700.989,94.206L699.393,93.665L696.342,94.438L692.193,92.705L691.687,94.280L682.724,86.641L678.647,84.317L679.061,83.375L674.507,86.213L672.334,86.384L671.795,84.743L668.343,83.717L666.226,84.449L664.125,81.346L659.662,80.715L658.151,81.931L652.789,83.042L651.947,83.784L643.615,84.831L642.923,85.857L645.388,87.918L643.414,88.700L644.160,89.519L642.423,90.984L647.046,93.053L646.978,94.477L643.565,94.347L643.193,95.240L639.570,93.681L635.799,93.742L633.691,95.010L630.447,93.794L624.512,91.711L620.819,91.789L616.875,95.060L617.209,97.265L614.239,95.513L613.184,98.856L614.042,99.482L613.196,101.808L615.768,103.889L617.563,103.804L619.634,105.854L619.778,107.433L621.154,107.929L620.483,109.749L618.206,110.254L616.470,113.418L619.375,116.320L619.579,118.381L623.136,121.982L621.895,123.215L621.631,123.993L620.460,123.784L618.313,121.926L617.578,121.824L615.836,121.115L614.798,119.860L612.312,119.220L610.880,119.701L610.323,119.132L606.603,117.666L602.808,117.171L600.588,116.648L600.348,117.009L596.685,114.425L593.633,113.271L591.160,111.472L592.875,110.982L594.433,108.415L592.817,107.201L596.197,105.948L595.998,105.278L593.892,105.772L593.702,104.409L594.795,103.552L597.115,103.327L597.290,102.304L596.408,100.612L597.065,99.005L596.851,98.105L593.091,97.106L591.688,97.139L589.887,95.726L588.149,96.202L584.865,95.144L584.790,94.553L583.660,93.248L581.725,93.103L581.333,92.169L581.801,91.560L579.932,89.857L577.534,90.148L576.784,89.997L576.319,90.681L575.410,90.559L574.457,88.633L573.713,87.635L574.112,87.354L576.031,87.458L576.816,86.801L575.982,85.999L574.298,85.469L574.334,84.926L573.278,84.377L571.446,82.408L571.786,81.604L571.266,80.230L568.866,79.532L567.728,79.881L567.253,79.155L564.688,78.421L563.618,76.694L563.151,75.274L561.928,74.601L562.722,73.672L561.534,70.942L562.803,69.256L562.368,68.745L564.575,67.131L561.963,65.787L565.856,62.181L567.492,60.549L567.960,59.109L564.323,57.173L564.770,55.332L562.380,53.230L563.212,50.910L560.023,47.839L561.414,45.804L557.843,44.006L557.683,42.117L559.251,41.868L562.395,40.786L564.209,39.847L567.958,41.478L573.667,42.121L582.330,45.172L584.344,46.455L585.105,48.251L583.288,49.668L580.123,50.388L570.215,48.337L568.791,48.680L572.753,50.656L573.256,51.908L574.184,54.739L577.155,55.601L579.027,56.334L578.914,54.964L577.295,53.750L578.330,52.698L583.963,54.438L585.536,53.750L583.459,51.744L587.409,49.101L589.382,49.257L591.673,50.200L592.190,48.346L589.869,46.737L590.272,45.123L588.155,43.450L594.168,44.315L595.930,45.826L593.464,46.160L594.057,47.661L596.045,48.585L599.009,48.000L598.814,46.279L602.555,44.994L608.627,42.677L610.214,42.809L608.960,44.447L611.618,44.728L612.646,43.806L616.418,43.732L618.878,42.613L622.006,44.239L623.395,42.452L620.484,40.889L621.072,39.998L627.417,40.815L630.658,41.658L639.742,44.741L640.279,43.329L637.396,41.902L637.007,41.330L634.433,41.065L634.367,39.786L631.997,37.792L631.399,36.979L633.469,34.678L633.161,32.368L634.245,31.869L639.810,32.539L641.233,33.952L640.864,36.013L642.666,36.823L644.583,38.600L646.470,42.235L649.727,43.889L649.971,45.690L648.272,49.523L650.893,49.921L651.124,48.949L652.973,48.256L652.685,46.921L653.650,45.636L651.490,44.102L651.310,42.321L648.963,42.099L647.543,40.598L647.325,37.988L643.250,35.916L645.484,34.203L643.695,32.397L644.612,32.339L646.681,33.748L647.749,36.200L650.201,36.664L647.923,34.832L650.416,33.833L654.333,33.698L659.086,35.147L655.657,33.030L653.301,30.323L656.193,29.811L660.855,29.923L664.686,29.590L662.010,28.261L662.709,26.618L664.784,26.554L667.121,25.402L671.653,25.092L671.533,24.456L676.107,24.240L678.236,24.762L680.858,23.527L684.265,23.566L683.512,22.563L683.996,21.575L687.020,20.621L691.085,21.374L689.376,21.947L693.945,22.303M613.802,37.763L612.760,37.986L606.113,37.656L604.991,36.527L601.084,35.846L600.096,34.474L601.802,33.928L601.014,32.543L603.664,30.376L601.748,30.065L605.063,27.835L603.901,26.699L607.198,25.473L612.180,23.980L617.936,23.546L620.360,22.684L623.642,22.383L625.687,23.300L625.072,24.023L619.497,25.175L614.698,26.282L610.371,28.644L608.961,31.124L607.309,33.568L608.868,35.679L613.802,37.763M768.958,25.581L770.496,27.346L763.488,27.275L761.208,27.876L755.109,26.281L753.384,24.684L755.064,24.248L760.094,24.350L768.958,25.581M781.503,26.693L780.881,27.679L777.545,27.452L772.514,26.487L771.594,25.734L775.698,26.085L781.503,26.693M775.014,31.431L772.135,31.448L767.816,31.165L767.295,31.031L767.704,30.026L769.750,29.791L773.831,30.763L775.014,31.431M147.332,37.324L144.478,37.479L147.581,35.742L148.022,35.636L149.671,35.641L151.221,36.368L150.440,36.715L147.332,37.324M855.522,37.479L853.586,37.609L851.802,36.801L852.419,35.742L855.522,37.479M137.003,48.810L137.411,49.481L139.825,47.520L144.840,47.923L145.256,50.448L141.485,51.624L137.638,51.903L133.850,54.608L132.223,55.196L130.344,55.111L130.040,54.126L128.333,53.303L129.589,52.122L128.116,51.681L125.201,52.031L125.489,51.087L127.460,50.084L123.987,50.725L123.003,51.994L120.071,53.142L136.441,42.390L138.293,44.450L139.664,47.133L137.003,48.810M553.003,83.865L548.721,83.910L545.808,83.568L546.179,82.245L549.249,81.285L551.753,81.797L552.845,82.274L552.711,83.097L553.003,83.865M844.349,94.632L851.065,100.021L846.729,99.008L848.478,103.442L853.174,106.587L854.681,108.731L851.456,106.881L851.570,109.256L849.240,106.681L847.339,103.692L844.653,100.381L843.526,98.061L840.297,94.016L836.351,91.059L833.022,86.949L833.995,85.565L831.861,84.172L832.533,83.749L834.866,85.738L838.201,88.637L840.717,91.597L844.349,94.632' },\n  { name: 'Rwanda', path: 'M584.471,257.068L585.560,258.842L585.385,260.692L584.581,261.091L583.107,260.885L582.244,262.675L580.561,262.428L580.830,260.708L581.213,260.466L581.329,258.594L582.134,257.718L582.804,258.039L584.471,257.068' },\n  { name: 'Saint Kitts and Nevis', path: 'M328.374,199.288L328.299,199.337L328.191,199.143L327.994,199.090L327.830,198.976L327.828,198.951L327.836,198.894L327.875,198.827L327.969,198.776L328.177,198.932L328.264,199.128L328.353,199.218L328.374,199.288M328.611,199.659L328.468,199.726L328.359,199.635L328.405,199.416L328.516,199.410L328.619,199.507L328.611,199.659' },\n  { name: 'Saint Lucia', path: 'M332.323,210.036L332.149,210.364L331.860,210.158L331.841,209.899L331.877,209.742L332.078,209.442L332.233,209.247L332.337,209.183L332.381,209.441L332.323,210.036' },\n  { name: 'Saint Martin', path: 'M327.557,196.681L327.251,196.681L327.279,196.613L327.428,196.535L327.532,196.542L327.572,196.570L327.557,196.681' },\n  { name: 'Saint Vincent and the Grenadines', path: 'M331.432,212.123L331.348,212.173L331.158,211.962L331.197,211.716L331.327,211.581L331.447,211.501L331.567,211.493L331.596,211.696L331.550,211.983L331.432,212.123M331.260,212.638L331.213,212.672L331.234,212.672L331.212,212.695L331.200,212.672L331.178,212.658L331.151,212.652L331.119,212.652L331.120,212.629L331.160,212.643L331.224,212.629L331.226,212.604L331.209,212.581L331.201,212.565L331.226,212.540L331.305,212.485L331.339,212.455L331.342,212.467L331.343,212.479L331.346,212.490L331.357,212.500L331.315,212.543L331.260,212.638M330.906,213.579L330.878,213.581L330.854,213.570L330.861,213.560L330.893,213.553L330.909,213.532L330.905,213.504L330.909,213.473L330.935,213.455L330.954,213.453L330.962,213.464L330.965,213.493L330.949,213.515L330.932,213.533L330.923,213.560L330.906,213.579' },\n  { name: 'Samoa', path: 'M25.289,295.842L25.647,296.139L25.834,296.532L25.764,296.909L25.457,296.815L25.047,296.896L24.901,296.869L24.486,296.407L24.217,296.199L24.090,296.004L24.394,296.027L24.810,295.898L25.289,295.842M28.011,297.670L27.257,297.673L26.860,297.530L26.727,297.529L26.359,297.231L26.284,297.075L26.435,296.972L26.775,296.917L27.512,297.144L27.651,297.345L27.816,297.366L27.955,297.454L28.011,297.595L28.011,297.670' },\n  { name: 'San Marino', path: 'M531.275,115.583L531.129,115.605L531.048,115.481L531.150,115.335L531.306,115.312L531.339,115.425L531.275,115.583' },\n  { name: 'Sao Tome and Principe', path: 'M520.613,248.570L520.510,248.652L520.387,248.583L520.354,248.458L520.511,248.217L520.586,248.157L520.649,248.208L520.686,248.274L520.692,248.371L520.613,248.570M518.499,253.121L518.213,253.351L518.110,253.291L518.047,253.131L517.966,252.785L517.992,252.619L518.121,252.430L518.403,252.241L518.573,252.228L518.748,252.476L518.749,252.734L518.499,253.121' },\n  { name: 'Saudi Arabia', path: 'M617.393,202.093L616.958,200.751L616.076,199.804L615.792,198.550L614.312,197.423L612.703,194.786L611.787,192.223L609.773,190.060L608.523,189.543L606.527,186.546L606.073,184.361L606.071,182.497L604.295,179.010L602.949,177.783L601.447,177.133L600.448,175.331L600.546,174.620L599.657,172.990L598.810,172.288L597.562,169.948L595.716,167.413L594.172,165.253L592.838,165.268L593.117,163.542L593.148,162.441L593.379,161.186L596.393,161.687L597.467,160.719L598.010,159.587L600.008,159.151L600.326,158.098L601.145,157.564L598.136,154.420L603.259,152.842L603.707,152.368L606.999,153.220L611.228,155.421L619.490,161.745L624.486,161.996L626.901,162.300L627.731,163.798L629.616,163.716L630.968,166.428L632.369,167.146L632.955,168.251L634.939,169.573L635.251,170.870L635.103,171.917L635.567,172.974L636.445,173.855L636.924,174.886L637.392,175.657L638.261,176.281L638.993,176.058L639.607,177.258L639.771,177.986L641.078,181.171L649.375,182.757L649.863,182.092L651.308,184.320L650.058,190.609L642.099,193.753L634.301,194.959L631.843,196.374L630.098,199.675L628.853,200.200L628.100,199.151L627.060,199.309L624.391,198.994L623.869,198.680L620.712,198.752L619.986,199.036L618.812,198.219L618.178,199.764L618.538,201.090L617.393,202.093' },\n  { name: 'Senegal', path: 'M453.967,210.750L452.871,208.302L451.517,207.182L452.737,206.585L454.118,204.377L454.807,202.762L455.770,201.754L457.128,202.026L458.481,201.340L460.013,201.306L461.306,202.230L463.112,203.063L464.733,205.377L466.516,207.536L466.620,209.493L467.142,211.293L468.164,212.177L468.386,213.393L468.248,214.372L467.848,214.550L466.347,214.301L466.136,214.651L465.528,214.721L463.555,213.954L462.224,213.922L457.131,213.790L456.387,214.144L455.475,214.043L454.006,214.555L453.592,212.145L456.100,212.211L456.768,211.771L457.262,211.745L458.294,211.018L459.466,211.683L460.663,211.738L461.864,211.033L461.320,210.124L460.405,210.653L459.550,210.638L458.474,209.864L457.601,209.915L456.968,210.660L453.967,210.750' },\n  { name: 'Serbia', path: 'M551.829,110.945L553.421,111.667L553.748,112.929L555.292,113.818L556.005,113.133L556.660,113.513L556.135,114.030L556.648,114.563L556.103,115.256L556.444,116.374L557.803,117.694L556.944,118.650L556.621,119.623L556.932,119.987L556.561,120.418L555.395,120.469L554.553,120.648L554.446,120.418L554.711,120.055L554.920,119.310L554.563,119.327L554.017,118.760L553.589,118.616L553.212,118.129L552.723,117.939L552.324,117.507L551.889,117.677L551.637,118.692L551.055,118.912L551.238,118.650L550.219,118.015L549.363,117.686L548.957,117.262L548.244,116.737L548.823,116.602L549.058,115.163L547.748,113.987L548.253,112.642L547.351,112.650L548.199,111.497L547.324,110.623L546.607,109.434L548.422,108.627L549.979,108.763L551.446,109.969L551.829,110.945' },\n  { name: 'Seychelles', path: 'M654.076,268.258L654.079,268.548L653.947,268.451L653.912,268.263L653.735,268.123L653.644,267.994L653.847,267.835L654.076,268.258' },\n  { name: 'Sierra Leone', path: 'M468.306,232.161L467.561,231.928L465.576,230.661L464.145,228.977L463.669,227.828L463.347,225.504L464.837,224.121L465.162,223.249L465.639,222.571L466.401,222.499L467.050,221.907L469.262,221.910L470.024,223.035L470.615,224.356L470.520,225.271L470.959,226.093L470.922,227.246L471.685,227.066L470.388,228.534L469.128,230.241L468.975,231.155L468.306,232.161' },\n  { name: 'Singapore', path: 'M788.697,249.313L788.286,249.521L787.810,249.332L787.955,249.024L788.266,248.950L788.522,249.047L788.668,249.122L788.768,249.207L788.697,249.313' },\n  { name: 'Sint Maarten', path: 'M327.251,196.681L327.557,196.681L327.548,196.755L327.511,196.837L327.333,196.768L327.245,196.696L327.251,196.681' },\n  { name: 'Slovakia', path: 'M545.601,98.426L545.756,98.611L546.709,98.195L548.039,99.283L549.402,98.625L550.578,98.940L552.273,98.506L554.708,99.686L554.127,100.485L553.793,101.722L553.308,102.035L550.599,101.103L549.821,101.290L549.325,102.012L548.220,102.395L547.936,102.199L546.796,102.676L545.835,102.766L545.697,103.383L543.680,103.759L542.748,103.424L541.436,102.638L541.101,101.575L541.263,101.185L541.548,100.510L542.629,100.562L543.430,100.245L543.469,99.960L543.920,99.814L544.014,99.116L544.557,98.982L544.880,98.430L545.601,98.426' },\n  { name: 'Slovenia', path: 'M534.043,107.591L536.097,107.829L537.288,107.133L539.436,107.057L539.863,106.539L540.280,106.573L540.846,107.609L538.948,108.424L538.808,109.663L537.972,109.977L538.048,110.835L537.070,110.775L536.188,110.274L535.772,110.792L534.035,110.688L534.567,110.409L533.882,109.103L534.043,107.591' },\n  { name: 'Solomon Islands', path: 'M635.362,223.778L634.166,225.710L632.307,228.334L629.979,228.353L620.835,224.622L619.752,223.499L618.693,221.985L617.602,220.254L618.159,219.140L619.108,217.457L620.030,218.037L620.625,219.337L621.927,220.653L623.299,220.664L625.870,219.859L628.860,219.487L631.248,218.510L632.608,218.303L633.568,217.729L635.135,217.619L635.120,217.670L635.171,218.965L635.317,222.138L635.362,223.778' },\n  { name: 'Solomon Islands', path: 'M936.337,276.606L935.769,276.785L934.622,276.068L933.598,274.776L933.787,274.252L935.324,275.580L936.337,276.606M942.527,279.717L942.587,280.349L940.538,279.016L939.124,277.886L938.179,276.839L938.620,276.518L939.826,277.273L941.967,278.720L942.527,279.717M947.160,283.688L946.691,284.267L944.889,281.542L944.483,279.663L945.424,279.663L946.192,282.178L947.160,283.688M944.793,284.546L943.709,284.616L942.042,284.298L941.507,283.814L941.794,282.565L943.575,283.060L944.415,283.720L944.793,284.546M948.024,286.464L948.630,287.544L946.703,287.524L945.950,285.590L947.485,286.350L948.024,286.464' },\n  { name: 'Somalia', path: 'M637.264,217.089L638.712,216.773L639.966,215.696L641.012,215.688L641.117,216.557L640.951,218.386L641.042,220.039L640.514,221.175L639.849,224.574L638.617,228.086L637.018,232.102L634.767,236.711L632.457,240.232L629.243,244.521L626.494,247.067L622.375,250.189L619.812,252.581L616.752,256.390L616.094,258.049L615.460,258.793L613.842,256.199L613.747,244.744L616.137,241.177L616.885,240.186L618.663,240.127L621.112,237.911L624.724,237.772L632.307,228.334L634.166,225.710L635.362,223.778L635.317,222.138L635.171,218.965L635.120,217.670L635.135,217.619L636.014,217.557L637.264,217.089' },\n  { name: 'South Africa', path: 'M584.225,345.502L583.670,345.956L582.425,347.554L581.536,349.170L579.819,351.423L576.531,354.667L574.501,356.554L572.387,357.984L569.534,359.204L568.179,359.368L567.771,360.241L566.209,359.776L564.862,360.375L562.057,359.769L560.437,360.152L559.359,359.988L556.566,361.229L554.292,361.727L552.598,362.916L551.402,362.991L550.359,361.870L549.475,361.812L548.424,360.409L548.276,360.845L547.974,359.999L548.091,358.156L547.351,356.048L548.235,355.476L548.300,353.062L546.723,350.119L545.520,347.455L545.516,347.447L543.755,343.361L545.097,341.806L546.122,342.667L546.519,344.012L547.710,344.241L549.367,344.835L550.813,344.606L553.274,342.998L553.797,331.384L554.512,331.856L555.976,334.844L555.636,336.760L556.184,337.864L558.127,337.543L559.543,336.140L560.868,335.194L561.606,333.688L562.962,332.959L564.080,333.341L565.320,334.222L567.507,334.377L569.276,333.645L569.607,332.664L570.155,331.159L571.637,330.908L572.502,329.726L573.495,327.631L576.035,325.283L579.986,322.968L581.090,323.002L582.379,323.535L583.313,323.157L584.742,323.471L585.815,327.897L586.404,330.131L585.709,333.637L585.857,334.766L584.537,334.190L583.741,334.414L583.421,335.330L582.602,336.510L582.551,337.598L584.034,339.302L585.631,338.963L586.281,337.566L588.319,337.593L587.476,339.882L586.964,342.494L586.166,343.914L584.225,345.502' },\n  { name: 'South Korea', path: 'M830.663,131.935L834.674,135.693L836.299,137.757L838.068,141.427L837.915,143.177L835.804,143.785L834.218,145.089L831.958,145.358L831.004,143.646L830.394,141.260L827.702,137.944L829.381,137.408L826.336,134.682L826.363,134.393L827.570,134.507L827.905,133.069L829.656,132.915L830.656,132.705L830.663,131.935' },\n  { name: 'South Sudan', path: 'M593.941,223.739L594.020,226.191L593.625,227.151L592.158,227.228L591.248,229.020L592.953,229.245L594.386,230.778L594.895,232.035L596.175,232.764L597.881,236.186L596.037,238.258L594.346,240.136L592.652,241.582L590.699,241.575L588.471,242.311L586.701,241.608L585.565,242.465L583.107,240.376L582.438,239.032L580.898,239.698L579.614,239.491L578.875,240.019L577.626,239.637L575.922,237.042L575.460,236.045L573.369,234.800L572.641,232.914L571.466,231.553L569.580,229.915L569.540,228.893L568.006,227.623L566.106,226.395L566.951,226.052L567.893,225.458L568.566,222.651L569.297,221.193L571.279,220.762L571.775,221.625L573.231,223.461L573.995,223.731L574.984,223.191L576.979,223.299L577.369,223.947L580.124,223.947L580.208,223.299L581.622,222.705L581.889,221.787L582.915,221.140L585.283,222.975L586.701,222.651L588.016,220.384L589.481,218.656L589.186,216.767L588.494,215.849L590.147,215.687L590.315,214.985L591.600,215.201L591.342,217.523L591.745,219.790L593.208,221.032L593.575,222.111L593.557,223.677L593.941,223.739' },\n  { name: 'Spain', path: 'M477.111,121.763L477.329,119.585L476.355,118.258L479.998,116.051L483.049,116.603L486.419,116.583L489.078,117.106L491.167,116.945L495.224,117.046L496.217,118.235L500.853,119.625L501.768,118.964L504.616,120.348L507.540,119.951L507.700,121.728L505.319,123.765L502.063,124.411L501.840,125.440L500.273,127.135L499.284,129.712L500.287,131.533L498.795,132.954L498.232,135.024L496.275,135.659L494.421,138.108L491.122,138.156L488.645,138.096L486.997,139.221L485.979,140.424L484.709,140.160L483.769,139.084L483.075,137.252L480.665,136.758L480.478,135.704L481.469,134.509L481.846,133.643L480.982,132.697L481.748,130.604L480.771,128.694L481.886,128.432L482.031,126.950L482.460,126.503L482.569,124.116L483.769,123.288L483.106,121.754L481.633,121.648L481.186,122.034L479.689,122.037L479.110,120.540L478.061,120.986L477.111,121.763' },\n  { name: 'Sri Lanka', path: 'M726.504,229.843L726.238,233.118L725.117,234.013L722.739,234.732L721.307,232.232L720.612,227.712L721.634,222.608L723.624,224.355L725.014,226.569L726.504,229.843' },\n  { name: 'Sudan', path: 'M593.941,223.739L593.557,223.677L593.575,222.111L593.208,221.032L591.745,219.790L591.342,217.523L591.600,215.201L590.315,214.985L590.147,215.687L588.494,215.849L589.186,216.767L589.481,218.656L588.016,220.384L586.701,222.651L585.283,222.975L582.915,221.140L581.889,221.787L581.622,222.705L580.208,223.299L580.124,223.947L577.369,223.947L576.979,223.299L574.984,223.191L573.995,223.731L573.231,223.461L571.775,221.625L571.279,220.762L569.297,221.193L568.566,222.651L567.893,225.458L566.951,226.052L566.106,226.395L565.880,226.248L564.908,225.343L564.717,224.365L565.149,223.057L565.121,221.774L563.484,219.808L563.141,218.462L563.158,217.700L562.123,216.773L562.053,214.947L561.449,213.734L560.485,213.916L560.739,212.761L561.424,211.450L561.085,210.148L561.969,209.183L561.380,208.448L562.066,206.507L563.250,204.191L565.626,204.411L565.080,191.928L565.071,190.609L568.208,190.599L567.953,184.320L578.880,184.320L589.426,184.320L600.207,184.320L601.270,187.405L600.707,187.975L601.292,191.213L602.488,194.967L603.570,195.741L605.129,196.903L603.837,198.698L601.846,199.215L601.032,200.179L600.867,202.269L599.908,206.890L600.244,208.149L599.899,210.849L598.886,213.947L597.275,215.505L596.172,217.907L595.937,219.192L594.657,220.073L593.929,223.364L593.941,223.739' },\n  { name: 'Suriname', path: 'M341.578,234.717L344.880,235.347L345.196,234.780L347.444,234.553L350.399,235.398L348.878,238.102L349.068,240.253L350.133,242.117L349.630,243.470L349.366,244.908L348.640,246.230L347.059,245.564L345.744,245.885L344.628,245.606L344.338,246.517L344.795,247.142L344.536,247.784L343.030,247.527L341.373,244.793L341.033,243.018L340.145,243.014L338.948,240.730L339.483,239.108L339.344,238.366L341.044,237.546L341.578,234.717' },\n  { name: 'Sweden', path: 'M546.446,51.132L544.754,53.014L545.367,54.741L542.333,57.013L538.532,59.443L537.481,63.421L539.311,65.411L541.644,66.978L540.018,70.272L537.768,70.956L537.471,75.869L536.478,78.611L533.662,78.328L532.590,80.649L529.926,80.784L528.950,78.017L526.759,74.696L524.717,70.557L525.572,68.871L527.255,66.877L527.667,63.555L526.136,62.124L525.659,58.372L526.801,55.723L528.919,55.771L529.542,54.651L528.669,53.686L531.471,49.863L533.147,46.872L534.233,44.952L536.195,44.961L536.506,43.459L540.403,43.891L540.400,42.116L541.632,42.005L544.566,43.326L548.097,45.163L548.979,49.318L549.893,50.368L546.446,51.132' },\n  { name: 'Switzerland', path: 'M523.503,104.475L523.625,105.019L523.286,105.770L524.426,106.329L525.686,106.412L525.557,107.670L524.497,108.188L522.652,107.804L522.175,109.041L521.001,109.138L520.552,108.652L519.208,109.693L518.019,109.839L516.930,109.181L516.036,107.836L514.872,108.317L514.866,106.927L516.607,105.203L516.501,104.423L517.628,104.706L518.280,104.182L520.364,104.203L520.837,103.536L523.503,104.475' },\n  { name: 'Syria', path: 'M602.187,148.539L597.405,151.890L594.323,150.644L594.270,150.622L594.576,150.144L594.395,148.857L594.851,147.135L596.153,145.950L595.586,144.717L594.389,144.557L593.849,142.134L594.314,140.824L594.919,140.126L595.523,139.428L595.424,137.651L596.358,138.271L599.096,137.385L600.563,137.984L602.699,137.974L605.510,136.779L606.916,136.833L609.790,136.338L608.767,138.325L607.464,139.112L608.064,141.439L607.608,145.266L602.187,148.539' },\n  { name: 'Taiwan', path: 'M829.515,176.791L828.879,181.833L828.222,184.412L826.271,181.757L825.507,179.426L826.496,176.337L828.115,173.957L829.609,174.893L829.515,176.791' },\n  { name: 'Tajikistan', path: 'M681.551,126.767L680.912,127.719L677.971,127.199L678.216,129.022L680.933,128.775L684.375,129.810L689.100,129.326L690.553,132.274L691.312,131.953L693.077,132.678L693.328,133.917L694.216,135.732L691.544,135.727L689.697,135.492L688.464,136.918L687.397,137.235L686.669,137.904L685.366,136.861L684.904,134.185L684.082,134.034L684.107,133.060L682.522,132.336L681.699,133.444L681.758,134.728L681.481,135.196L679.917,135.130L679.453,136.589L678.424,135.973L676.805,136.996L675.915,136.608L676.561,133.385L675.408,131.013L673.332,130.253L673.649,128.851L675.828,129.001L676.586,127.251L676.771,125.289L679.949,124.578L679.879,125.996L680.522,126.846L681.551,126.767' },\n  { name: 'Tanzania', path: 'M594.152,256.487L594.618,256.833L604.628,263.239L604.800,265.063L608.752,268.206L607.399,272.081L607.524,273.863L609.273,275.009L609.338,275.826L608.533,277.725L608.671,278.681L608.456,280.183L609.379,282.154L610.449,285.255L611.437,285.943L609.169,287.766L606.104,288.987L604.449,288.935L603.432,289.879L601.507,289.960L600.773,290.357L597.486,289.471L595.401,289.725L594.768,285.449L593.865,283.982L593.325,283.113L590.624,282.526L589.072,281.582L587.323,281.053L586.229,280.526L585.087,279.726L583.660,275.764L582.083,274.003L581.559,272.179L581.863,270.543L581.397,267.650L582.546,267.501L583.561,266.362L584.653,264.722L585.343,264.064L585.325,263.042L584.732,262.329L584.581,261.090L585.385,260.692L585.560,258.842L584.471,257.068L585.448,256.690L588.492,256.731L594.152,256.487' },\n  { name: 'Thailand', path: 'M782.974,215.178L780.358,213.735L778.005,213.793L778.172,211.323L775.747,211.341L775.860,214.800L774.807,219.393L774.167,222.171L774.484,224.447L776.292,224.545L777.577,227.415L778.229,230.137L779.877,231.938L781.577,232.304L783.106,233.936L782.275,235.228L780.466,235.603L780.156,233.988L777.816,232.611L777.366,233.172L776.203,231.965L775.642,230.408L774.071,228.633L772.646,227.141L772.295,228.990L771.673,227.243L771.866,225.281L772.512,222.265L773.555,219.034L774.793,216.102L773.443,213.235L773.348,211.774L772.867,210.019L770.796,207.520L769.976,205.943L770.846,205.361L771.479,202.628L770.073,200.552L768.024,198.256L766.330,195.497L767.407,194.926L768.193,191.526L770.101,191.385L771.492,190.022L772.936,189.295L774.275,190.265L774.702,192.155L776.567,192.299L776.356,195.612L776.813,198.431L779.437,196.555L780.334,197.109L781.925,197.018L782.320,195.924L784.420,196.140L786.869,198.694L787.488,201.797L790.109,204.538L790.334,207.200L789.581,208.617L786.956,208.166L783.457,208.766L781.950,211.381L782.974,215.178' },\n  { name: 'Togo', path: 'M505.170,234.186L502.939,234.856L502.320,233.752L501.580,231.757L501.360,230.193L501.971,227.361L501.276,226.214L501.012,223.737L501.016,221.453L499.862,219.831L500.066,218.851L502.485,218.918L502.134,220.574L502.980,221.502L503.941,222.603L504.047,224.147L504.605,224.795L504.486,232.016L505.170,234.186' },\n  { name: 'Tonga', path: 'M24.371,312.113L24.313,312.299L24.263,312.296L24.117,312.188L24.056,312.115L24.186,311.897L24.276,311.880L24.419,311.953L24.429,312.016L24.371,312.113M23.147,320.068L23.186,320.069L23.202,319.975L23.339,319.942L23.351,320.041L23.246,320.365L23.085,320.238L22.664,320.032L22.545,319.872L22.631,319.751L22.647,319.848L22.720,319.892L22.929,319.909L23.137,319.997L23.032,320.025L23.147,320.068M23.941,320.481L24.060,320.953L23.866,320.736L23.823,320.636L23.916,320.490L23.941,320.481' },\n  { name: 'Trinidad and Tobago', path: 'M329.595,219.664L331.208,219.256L331.782,219.366L331.535,221.708L329.206,222.054L328.725,221.771L329.578,220.907L329.595,219.664' },\n  { name: 'Tunisia', path: 'M525.258,158.196L523.965,152.551L522.301,151.282L522.259,150.521L520.056,148.647L519.769,146.279L521.345,144.525L521.887,141.912L521.381,138.875L521.859,137.241L524.641,135.955L526.469,136.337L526.453,137.949L528.610,136.777L528.819,137.388L527.582,138.949L527.622,140.422L528.557,141.214L528.319,143.964L526.643,145.545L527.196,147.259L528.558,147.312L529.271,148.807L530.290,149.299L530.226,151.714L528.967,152.617L528.185,153.624L526.402,154.836L526.725,156.138L526.535,157.467L525.258,158.196' },\n  { name: 'Turkey', path: 'M569.348,125.403L567.420,127.050L566.444,125.625L566.403,124.994L566.967,124.651L567.520,122.737L566.186,121.927L568.647,120.965L570.879,121.375L571.332,122.551L573.679,123.539L573.316,124.288L570.315,124.457L569.348,125.403M593.802,123.431L597.657,124.613L600.537,124.142L602.778,124.414L605.478,122.818L608.154,122.673L610.900,124.174L611.550,125.251L611.604,126.739L613.661,127.499L614.823,128.429L613.215,129.336L614.614,132.989L614.270,133.975L616.103,136.527L614.948,137.065L613.906,136.254L610.826,135.843L609.790,136.338L606.916,136.833L605.510,136.779L602.699,137.974L600.563,137.984L599.096,137.385L596.358,138.271L595.424,137.651L595.523,139.428L594.919,140.126L594.314,140.824L593.165,139.379L593.991,138.183L592.442,138.454L590.173,137.721L588.617,139.554L584.707,139.912L582.398,138.203L579.584,138.096L579.133,139.417L577.374,139.795L574.676,138.099L571.844,138.157L569.989,134.989L567.927,133.222L568.939,130.745L567.162,129.223L569.675,126.230L573.592,126.108L574.351,123.783L579.256,124.188L582.018,122.204L584.839,121.340L589.017,121.275L593.802,123.431' },\n  { name: 'Turkmenistan', path: 'M659.821,141.370L658.989,138.689L657.025,138.575L653.437,135.755L651.294,135.406L648.090,133.792L646.192,133.498L645.182,134.091L643.434,133.999L641.964,135.820L639.810,136.436L638.882,134.184L638.597,130.852L636.380,129.774L636.611,127.593L634.872,127.412L634.809,124.834L637.397,125.585L639.392,124.606L637.079,122.770L635.918,121.021L634.072,121.801L634.359,124.042L633.085,122.061L633.956,121.043L636.670,120.407L638.594,121.263L640.980,123.661L642.245,123.512L645.101,123.470L644.279,121.930L646.164,120.876L647.814,119.099L651.658,120.716L652.605,123.156L653.752,123.782L656.461,123.642L657.472,124.197L659.631,127.350L663.080,129.543L665.109,131.042L668.174,132.602L671.938,133.965L672.344,135.914L671.539,135.816L670.111,134.964L669.980,136.098L667.942,136.714L668.029,139.261L666.790,140.230L664.844,140.710L664.634,142.153L662.760,142.578L659.821,141.370' },\n  { name: 'Turks and Caicos Islands', path: 'M304.564,184.821L304.512,184.855L304.367,184.746L304.355,184.659L304.299,184.655L304.214,184.577L304.249,184.475L304.464,184.471L304.518,184.752L304.564,184.821M305.130,185.058L305.115,185.100L304.975,184.979L304.680,184.978L304.653,184.812L304.769,184.785L305.136,184.843L305.205,184.988L305.130,185.058M303.336,184.787L303.626,184.960L303.817,184.934L303.827,184.971L303.721,185.011L303.693,185.044L303.388,185.089L303.295,185.081L303.290,184.963L303.336,184.787' },\n  { name: 'Tuvalu', path: 'M988.379,271.384L988.395,271.445L988.363,271.401L988.339,271.358L988.353,271.353L988.379,271.384M991.614,272.741L991.579,272.748L991.570,272.727L991.566,272.716L991.564,272.708L991.596,272.715L991.616,272.727L991.614,272.741M988.693,273.295L988.668,273.318L988.686,273.277L988.696,273.276L988.693,273.295M990.711,276.138L990.709,276.142L990.710,276.133L990.710,276.125L990.706,276.111L990.706,276.104L990.711,276.125L990.711,276.138M994.885,277.065L994.876,277.080L994.855,277.057L994.823,276.970L994.818,276.940L994.876,277.004L994.883,277.007L994.886,277.034L994.885,277.065M993.876,278.740L993.834,278.877L993.815,278.874L993.825,278.833L993.851,278.780L993.876,278.740M995.983,280.323L995.928,280.361L995.957,280.322L995.971,280.288L995.969,280.259L995.961,280.222L995.965,280.171L995.977,280.105L995.992,280.147L995.986,280.224L996.005,280.264L996.008,280.294L995.983,280.323M997.568,282.936L997.564,282.942L997.553,282.902L997.543,282.884L997.545,282.880L997.559,282.892L997.568,282.936M997.626,283.118L997.623,283.124L997.626,283.060L997.616,283.017L997.623,283.021L997.634,283.057L997.626,283.118' },\n  { name: 'Uganda', path: 'M588.492,256.731L585.448,256.690L584.471,257.068L582.804,258.039L582.134,257.718L582.175,255.347L582.827,254.146L582.974,251.621L583.548,250.159L584.597,248.520L585.657,247.684L586.541,246.568L585.425,246.142L585.565,242.465L586.701,241.608L588.471,242.311L590.699,241.575L592.652,241.582L594.346,240.136L595.680,242.319L596.018,243.897L597.270,247.507L596.280,249.799L594.931,251.881L594.146,253.155L594.152,256.487L588.492,256.731' },\n  { name: 'Ukraine', path: 'M575.410,90.559L576.319,90.681L576.784,89.997L577.534,90.148L579.932,89.857L581.801,91.560L581.333,92.169L581.725,93.103L583.660,93.248L584.790,94.553L584.865,95.144L588.149,96.202L589.887,95.726L591.688,97.139L593.091,97.106L596.851,98.105L597.065,99.005L596.408,100.612L597.290,102.304L597.115,103.327L594.795,103.552L593.702,104.409L593.892,105.772L591.978,106.018L590.530,107.010L588.254,107.172L586.337,108.316L586.824,110.225L588.171,110.965L590.669,110.781L590.389,111.875L587.758,112.406L584.654,114.176L583.169,113.554L583.495,112.116L580.626,111.218L580.966,110.630L583.166,109.610L582.329,108.907L578.360,108.131L578.004,106.987L575.782,107.365L575.130,109.055L573.559,111.323L572.354,110.796L571.260,111.290L570.069,110.724L570.645,110.391L570.924,109.338L571.456,108.360L571.200,107.811L571.680,107.566L571.986,107.991L573.454,108.080L574.073,107.853L573.565,107.542L573.669,107.085L572.691,106.305L572.142,105.022L571.174,104.520L571.195,103.480L569.969,102.655L568.949,102.540L567.016,101.584L565.439,101.887L564.919,102.340L563.890,102.340L563.372,103.057L561.607,103.352L560.833,103.823L559.604,103.073L558.036,103.062L556.485,102.722L555.507,103.379L555.242,102.556L553.793,101.722L554.127,100.485L554.708,99.686L555.258,99.865L554.473,98.486L556.345,95.952L557.488,95.602L557.622,94.759L556.041,92.133L557.163,92.016L558.346,91.201L560.177,91.134L562.614,91.370L565.388,92.091L567.274,92.152L568.246,92.586L569.048,92.062L569.797,92.765L571.924,92.621L572.926,92.912L572.798,91.398L573.407,90.738L575.410,90.559' },\n  { name: 'United Arab Emirates', path: 'M639.607,177.258L640.076,177.106L640.248,177.968L642.325,177.472L644.571,177.555L646.214,177.648L647.880,175.521L649.664,173.505L651.120,171.567L651.771,172.639L652.450,175.123L651.071,175.135L651.034,177.183L651.554,177.620L650.384,178.239L650.493,179.525L649.820,180.826L649.863,182.092L649.375,182.757L641.078,181.171L639.771,177.986L639.607,177.258' },\n  { name: 'United Kingdom', path: 'M493.251,71.204L490.761,74.371L493.080,73.970L495.562,73.985L494.935,76.370L492.827,78.992L495.202,79.179L495.381,79.487L497.406,82.970L498.997,83.453L500.435,86.880L501.108,88.068L503.970,88.641L503.701,90.564L502.498,91.446L503.461,93.002L501.319,94.577L498.113,94.549L494.020,95.376L492.911,94.784L491.294,96.194L489.077,95.852L487.352,97.003L486.091,96.400L489.705,93.241L491.856,92.591L491.838,92.589L488.129,92.088L487.493,90.891L489.998,89.959L488.748,88.339L489.251,86.369L492.734,86.641L492.738,86.641L493.115,84.895L491.590,83.042L491.555,83.000L488.746,82.471L488.218,81.662L489.103,80.354L488.372,79.548L487.078,80.932L487.052,78.111L485.957,76.618L486.908,73.593L488.747,71.219L490.534,71.451L493.251,71.204M486.821,83.182L485.496,85.248L483.753,84.628L482.307,84.670L482.860,83.058L482.457,81.457L484.405,81.336L486.821,83.182' },\n  { name: 'United States', path: 'M194.957,36.677L194.623,37.824L196.253,37.332L199.358,37.484L198.357,38.069L200.741,38.501L203.144,38.247L206.144,39.050L209.628,39.289L210.690,39.620L213.932,39.206L215.927,39.993L217.649,40.371L217.649,40.371L205.686,50.386L188.154,66.344L190.242,66.428L191.565,67.210L191.889,68.491L192.041,70.414L195.763,68.779L198.888,67.831L198.656,69.345L199.050,70.543L199.886,71.862L199.367,73.962L198.645,77.300L200.862,79.162L199.268,81.008L196.758,82.435L196.428,81.319L195.238,80.385L196.917,77.833L196.147,75.466L197.481,72.703L195.491,72.513L191.974,72.442L190.134,71.600L188.419,68.563L186.827,68.007L183.983,66.971L180.649,67.212L177.735,65.914L176.464,64.711L173.345,65.309L171.582,67.273L170.163,67.461L166.962,68.071L163.977,69.059L160.852,69.680L162.342,67.956L166.498,65.159L169.839,64.290L170.053,63.581L165.432,65.155L161.734,67.036L156.311,69.111L156.438,70.532L152.080,72.634L148.340,73.859L145.110,74.752L143.145,76.048L137.936,77.559L135.708,78.933L131.638,80.184L130.303,79.959L127.241,80.775L123.778,81.771L120.845,82.775L115.994,83.634L116.136,83.129L120.094,81.727L123.378,80.824L127.633,79.223L130.855,78.892L133.315,77.692L138.412,75.940L139.562,75.354L142.368,74.321L145.175,72.102L148.196,70.374L144.643,71.261L144.470,70.757L142.086,71.821L142.255,70.337L140.490,71.387L141.266,69.928L137.724,71.100L136.348,71.097L138.106,69.355L139.710,68.282L139.447,67.240L135.927,67.801L135.676,66.454L135.020,65.776L137.034,64.176L136.873,62.972L139.778,61.348L143.539,59.771L146.135,58.321L148.134,58.115L149.044,58.567L152.472,57.204L153.727,57.447L156.438,56.570L157.630,55.280L157.067,54.772L159.980,53.682L158.641,53.714L155.632,54.329L154.209,54.953L153.314,54.330L149.915,54.647L147.669,53.970L148.249,52.845L147.812,51.277L152.348,50.148L158.834,48.830L160.539,48.830L158.389,50.178L162.935,50.073L163.541,48.402L162.418,47.374L162.828,46.025L162.471,44.875L160.871,44.022L163.998,42.607L167.706,42.520L171.954,41.290L174.244,39.976L178.173,38.746L180.573,38.456L186.117,37.328L187.665,37.498L192.810,36.143L194.957,36.677M133.080,56.524L133.695,57.062L135.408,56.771L136.170,57.517L137.812,57.894L137.238,58.202L134.834,58.800L133.995,58.185L133.845,57.673L131.739,57.837L131.555,57.588L133.080,56.524M132.389,67.473L130.504,67.928L129.677,67.381L129.299,66.608L132.101,66.125L133.530,66.380L132.389,67.473M151.657,75.650L148.196,76.766L147.834,76.010L148.947,74.640L152.114,73.600L153.794,73.154L155.086,73.351L155.089,74.260L151.657,75.650M270.500,98.755L270.113,100.440L270.617,100.959L272.224,101.148L274.476,101.637L276.391,102.588L278.553,102.189L281.186,102.987L281.999,102.957L284.577,102.088L286.365,103.201L288.229,104.388L289.763,105.410L291.241,106.392L291.129,107.199L291.578,107.501L291.296,107.805L291.916,107.900L292.533,107.583L292.344,108.309L292.632,108.796L293.311,108.796L293.513,109.171L292.974,109.716L294.945,111.156L294.374,113.935L293.867,116.593L292.445,118.401L290.619,120.083L289.652,121.153L289.474,121.472L289.591,121.909L290.268,122.391L290.904,122.391L294.463,120.759L297.246,120.278L301.105,118.757L301.267,118.447L301.380,117.514L301.193,116.913L302.503,116.428L304.972,116.416L307.274,116.416L308.498,115.225L308.895,114.987L312.304,112.784L313.623,112.221L317.413,112.200L322.001,112.198L322.527,111.440L323.379,111.286L324.607,110.811L325.991,109.415L327.602,107.028L330.302,104.712L330.832,105.518L332.660,104.997L333.442,105.882L331.986,110.066L333.010,111.801L333.115,112.805L329.989,114.287L327.085,115.342L324.148,116.247L322.228,118.063L321.577,118.751L321.022,120.373L321.328,121.994L322.355,122.071L322.451,120.954L322.991,121.634L322.506,122.507L320.632,123.003L319.432,122.944L317.377,123.477L316.220,123.630L314.692,123.781L312.271,124.667L316.204,124.091L316.765,124.670L312.889,125.588L311.262,125.594L311.466,125.218L310.399,126.066L311.102,126.207L309.851,128.441L307.309,130.892L307.344,130.074L306.825,129.908L306.204,129.112L306.263,130.827L306.744,131.394L306.451,132.598L305.280,133.835L303.116,136.379L302.915,136.253L304.320,134.085L303.342,132.868L303.783,130.222L302.900,131.599L302.882,133.620L301.317,133.120L302.806,134.146L302.066,137.177L302.749,137.397L302.711,138.499L302.188,141.686L299.894,144.042L296.963,144.975L294.798,146.819L293.437,147.021L291.826,148.176L291.195,149.231L287.800,151.272L285.940,152.769L284.229,154.633L283.264,156.868L283.191,159.051L283.574,161.742L284.350,163.968L284.113,165.326L284.712,168.974L284.237,171.094L283.895,172.317L282.868,174.238L281.987,174.634L280.728,174.253L280.559,172.873L279.669,172.150L278.751,169.446L277.957,167.040L277.788,165.810L278.734,163.723L278.314,161.993L276.736,159.363L275.806,158.880L272.819,160.307L272.372,160.150L271.398,158.683L269.932,157.905L266.816,158.300L264.546,157.953L262.456,158.169L261.221,158.660L261.495,159.496L261.190,160.771L261.629,161.392L261.035,161.806L260.139,161.342L259.013,161.938L257.094,161.841L255.448,160.179L253.037,160.571L251.251,159.843L249.543,160.064L247.138,160.798L244.195,163.129L241.235,164.485L239.438,165.987L238.504,167.402L237.992,169.572L237.789,171.081L238.063,172.150L236.990,172.244L235.231,171.553L233.351,170.578L232.934,169.100L232.845,166.899L231.673,165.106L231.172,163.263L230.328,161.110L228.738,159.857L226.542,159.918L224.273,162.402L222.279,161.459L221.125,160.509L220.907,158.780L220.551,157.138L219.416,155.755L218.380,154.761L217.776,153.646L213.186,153.645L212.751,154.942L210.646,154.943L205.361,154.966L200.074,152.751L196.613,151.222L197.076,150.607L193.602,150.948L190.513,151.190L190.645,149.584L189.588,147.776L188.496,147.399L188.535,146.497L187.118,146.339L186.488,145.489L184.164,145.179L183.682,144.671L184.040,142.941L182.934,139.741L182.762,135.312L183.186,134.575L182.521,133.523L181.738,130.854L182.567,128.257L182.091,126.557L184.103,124.022L185.518,121.399L186.057,119.055L188.692,116.173L190.586,113.398L192.580,110.617L194.748,106.501L195.644,103.876L195.841,102.451L196.519,101.852L199.384,102.895L198.865,105.791L199.981,104.981L201.168,102.465L201.922,99.949L208.813,99.949L216.017,99.949L218.403,99.949L225.799,99.949L232.958,99.949L240.237,99.949L247.521,99.949L255.767,99.949L264.070,99.947L269.091,99.949L269.673,98.770L270.500,98.755M66.868,184.376L66.465,184.688L65.698,184.114L65.898,183.885L66.392,183.577L67.001,183.644L66.868,184.376M70.936,186.451L70.742,186.633L70.557,186.592L69.638,186.482L69.476,185.769L69.402,185.643L70.241,185.210L70.417,185.412L70.936,186.451M73.254,186.908L73.083,187.248L71.647,187.157L71.949,186.774L73.254,186.908M74.677,188.584L73.707,188.809L73.406,188.146L73.158,187.891L73.184,187.694L73.519,187.425L74.411,187.724L75.001,188.206L74.677,188.584M75.012,193.491L74.500,194.017L73.917,193.566L74.184,192.688L73.979,191.543L74.190,191.193L74.774,190.680L74.739,190.062L74.972,189.768L75.164,189.827L76.075,190.358L76.491,190.631L76.844,191.052L77.304,192.154L77.201,192.328L75.991,192.999L75.012,193.491' },\n  { name: 'Uruguay', path: 'M346.453,348.517L348.124,348.182L351.213,350.614L352.186,350.522L355.257,352.537L357.624,354.275L359.503,356.414L358.583,357.906L359.603,359.687L358.790,361.663L356.119,363.411L354.079,362.782L352.718,363.119L350.061,361.769L348.299,361.870L346.390,360.131L346.231,358.098L346.678,357.398L346.096,354.266L346.232,351.034L346.453,348.517' },\n  { name: 'US Virgin Islands', path: 'M322.612,195.860L322.404,195.888L322.134,195.742L322.362,195.687L322.504,195.721L322.612,195.860M323.125,195.784L322.937,195.867L322.816,195.855L322.772,195.825L322.877,195.728L323.125,195.784M322.679,197.545L322.896,197.683L323.173,197.683L322.871,197.822L322.315,197.836L322.346,197.614L322.679,197.545' },\n  { name: 'Uzbekistan', path: 'M672.344,135.914L671.938,133.965L668.174,132.602L665.109,131.042L663.080,129.543L659.631,127.350L657.472,124.197L656.461,123.642L653.752,123.782L652.605,123.156L651.658,120.716L647.814,119.099L646.164,120.876L644.279,121.930L645.101,123.470L642.245,123.512L639.235,112.235L645.101,110.422L645.644,110.688L650.148,112.883L652.513,114.040L655.687,116.797L658.501,116.351L662.732,116.113L666.415,118.347L667.162,121.414L668.402,121.436L669.688,123.941L672.954,124.040L674.107,125.489L675.052,125.469L675.470,123.281L678.128,121.149L679.394,120.584L680.244,120.885L678.765,122.866L681.016,124.017L682.575,123.255L686.129,124.866L683.596,127.068L681.551,126.767L680.522,126.846L679.879,125.996L679.949,124.578L676.771,125.289L676.586,127.251L675.828,129.001L673.649,128.851L673.332,130.253L675.408,131.013L676.561,133.385L675.915,136.608L673.793,135.936L672.344,135.914' },\n  { name: 'Vanuatu', path: 'M959.579,300.461L959.456,302.996L958.809,302.601L958.198,302.772L958.004,301.903L958.417,299.494L959.579,300.461M960.507,305.279L959.507,305.693L958.905,304.316L959.200,303.473L960.507,305.279' },\n  { name: 'Venezuela', path: 'M303.148,216.469L303.019,217.212L301.374,217.579L302.177,219.006L302.031,220.650L300.698,222.477L301.643,224.972L302.844,224.767L303.557,222.495L302.762,221.388L302.785,219.007L306.310,217.729L306.027,216.247L307.061,215.255L307.904,217.465L309.837,217.516L311.516,219.269L311.557,220.310L314.036,220.338L317.009,220.015L318.503,221.423L320.593,221.812L322.204,220.829L322.284,220.037L325.718,219.848L329.032,219.804L326.630,220.733L327.490,222.217L329.693,222.453L331.736,224.000L332.091,226.519L333.536,226.448L334.595,227.189L332.339,229.037L332.057,230.183L332.966,231.350L332.258,231.939L330.535,232.444L330.540,233.896L329.759,234.761L331.553,237.147L331.895,238.035L330.863,239.235L327.741,240.412L325.739,240.900L324.926,241.643L322.732,240.857L320.684,240.455L320.160,240.744L321.389,241.559L321.243,243.668L321.597,245.648L323.944,245.918L324.084,246.579L322.087,247.474L321.743,248.806L320.592,249.322L318.515,250.056L317.962,251.018L315.799,251.222L314.298,249.559L313.503,246.423L312.783,245.323L311.788,244.630L313.220,243.065L313.137,242.361L312.364,241.426L311.840,239.337L312.110,237.082L312.770,236.026L313.333,234.332L312.374,233.792L310.780,234.151L308.790,233.982L307.657,234.319L305.813,231.613L304.220,231.212L300.645,231.514L300.030,230.418L299.359,230.155L299.289,229.499L299.665,228.335L299.498,227.069L298.916,226.377L298.621,224.932L297.201,224.721L298.045,222.882L298.515,220.638L299.400,219.470L300.531,218.568L301.339,216.996L303.148,216.469' },\n  { name: 'Vietnam', path: 'M793.940,185.727L790.774,188.417L788.994,191.388L788.712,193.570L791.288,196.885L794.456,200.994L797.235,202.936L799.282,205.461L801.188,211.281L801.392,216.813L799.305,218.884L796.349,220.908L794.299,223.530L791.024,226.457L789.900,224.441L790.551,222.311L788.332,220.524L790.597,219.258L793.474,219.030L792.068,217.125L796.460,214.705L796.413,210.937L795.559,208.839L795.708,205.696L794.687,203.475L792.288,201.287L790.155,198.516L787.340,194.800L783.795,192.919L784.416,191.789L786.042,190.965L784.528,188.223L781.170,188.198L779.470,185.341L777.468,182.858L778.797,182.091L780.964,182.107L783.542,181.744L785.569,180.068L787.078,181.248L789.658,181.822L789.543,183.633L791.059,184.911L793.940,185.727' },\n  { name: 'West Bank and Gaza', path: 'M593.971,151.635L594.178,153.558L593.887,154.481L592.685,154.907L592.711,154.079L593.342,153.646L592.638,153.293L592.967,151.199L593.971,151.635' },\n  { name: 'Western Sahara', path: 'M476.364,168.217L476.337,166.533L476.745,166.533L476.742,166.743L476.678,167.352L476.575,172.115L467.730,171.951L467.637,179.997L465.091,180.279L464.393,181.894L464.813,186.436L454.155,186.416L453.532,187.465L453.686,186.136L453.734,186.141L459.868,185.890L460.221,184.757L461.368,183.344L462.362,179.002L466.198,175.609L467.573,171.644L468.422,171.414L469.363,168.963L471.634,168.626L472.597,169.034L473.818,169.034L474.701,168.319L476.364,168.217' },\n  { name: 'Yemen', path: 'M645.669,201.140L643.746,201.984L643.315,203.381L643.327,204.453L640.686,205.780L636.373,207.247L634.013,209.466L632.809,209.639L631.975,209.453L630.425,210.758L628.696,211.364L626.391,211.527L625.703,211.706L625.137,212.536L624.424,212.765L624.032,213.565L622.664,213.496L621.801,213.923L619.886,213.763L619.094,211.926L619.101,210.207L618.613,209.279L617.979,206.953L617.124,205.661L617.665,205.508L617.299,204.071L617.596,203.464L617.393,202.093L618.538,201.090L618.178,199.764L618.812,198.219L619.986,199.036L620.712,198.752L623.869,198.680L624.391,198.994L627.060,199.309L628.100,199.151L628.853,200.200L630.098,199.675L631.843,196.374L634.301,194.959L642.099,193.753L644.614,198.943L645.669,201.140' },\n  { name: 'Zambia', path: 'M590.624,282.526L591.904,283.929L592.535,286.598L592.037,287.450L591.401,290.000L591.849,292.605L590.947,293.700L590.019,296.621L591.441,297.435L583.012,300.027L583.188,302.265L581.089,302.696L579.475,303.948L579.098,305.039L578.106,305.286L575.621,307.872L574.028,309.907L573.101,309.980L572.225,309.618L569.177,309.274L568.693,309.039L568.681,308.778L567.625,308.069L565.854,307.888L563.588,308.603L561.861,306.638L560.089,304.066L560.456,294.060L566.195,294.100L565.985,293.014L566.423,291.836L565.971,290.361L566.320,288.836L566.051,287.860L567.002,287.939L567.138,288.917L568.433,288.841L570.180,289.131L571.067,290.559L573.266,290.997L574.979,290.004L575.555,291.652L577.657,292.092L578.637,293.432L579.721,295.162L581.829,295.188L581.695,291.797L580.922,292.369L579.027,291.145L578.297,290.586L578.724,287.429L579.303,283.706L578.706,282.320L579.527,280.312L580.275,279.936L584.002,279.406L585.087,279.726L586.229,280.526L587.323,281.053L589.072,281.582L590.624,282.526' },\n  { name: 'Zimbabwe', path: 'M584.742,323.471L583.313,323.157L582.379,323.535L581.090,323.002L579.986,322.968L578.320,321.547L576.239,321.064L575.528,319.070L575.572,317.961L574.419,317.622L571.466,314.168L570.672,312.349L570.142,311.788L569.177,309.274L572.225,309.618L573.101,309.980L574.028,309.907L575.621,307.872L578.106,305.286L579.098,305.039L579.475,303.948L581.089,302.696L583.188,302.265L583.316,303.438L585.610,303.376L586.853,304.039L587.411,304.817L588.708,305.046L590.087,306.056L589.913,310.036L589.281,312.216L589.058,314.566L589.455,315.497L589.056,317.348L588.629,317.634L587.791,319.902L584.742,323.471' },\n];\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, rect, circle, text, group } from '../../render/tree'\nimport { WORLD_REGIONS } from './world-regions'\n\nexport interface GeoRegion {\n  name: string\n  path: string\n}\n\nexport interface GeoOptions extends ResolvedOptions {\n  regions?: GeoRegion[]\n  viewBox?: { x: number; y: number; width: number; height: number }\n  showLabels?: boolean | 'data'\n  scatterSeries?: number\n  legendPosition?: 'bottom' | 'none'\n}\n\n/** Built-in world map with SVG paths. */\nexport const WORLD_SIMPLE: GeoRegion[] = WORLD_REGIONS\n\ninterface BBox { minX: number; minY: number; maxX: number; maxY: number }\n\n// Caches to avoid recomputing every frame\nconst centroidCache = new WeakMap<GeoRegion[], Map<string, { x: number; y: number }>>()\nconst bboxCache = new WeakMap<GeoRegion[], Map<string, BBox>>()\n\nfunction getCentroids(regions: GeoRegion[]): Map<string, { x: number; y: number }> {\n  let cached = centroidCache.get(regions)\n  if (cached) return cached\n  cached = new Map()\n  for (const r of regions) {\n    const c = getPathCentroid(r.path)\n    if (c) cached.set(r.name, c)\n  }\n  centroidCache.set(regions, cached)\n  return cached\n}\n\nfunction getBBoxes(regions: GeoRegion[]): Map<string, BBox> {\n  let cached = bboxCache.get(regions)\n  if (cached) return cached\n  cached = new Map()\n  for (const r of regions) {\n    const bb = getPathBBox(r.path)\n    if (bb) cached.set(r.name, bb)\n  }\n  bboxCache.set(regions, cached)\n  return cached\n}\n\n/** Default viewBox matching Guardian world-map coordinate space. */\nconst DEFAULT_VB = { x: 0, y: 0, width: 1000, height: 430 }\n\n/** Compute transform params for fitting map into chart area, with optional zoom/pan. */\nfunction computeMapTransform(\n  area: { x: number; y: number; width: number; height: number },\n  vb: typeof DEFAULT_VB,\n  legendHeight: number,\n  zp?: { zoomX: number; zoomY: number; panX: number; panY: number },\n) {\n  const fitHeight = area.height - legendHeight\n  const baseScale = Math.min(area.width / vb.width, fitHeight / vb.height) * 0.88\n\n  // Base offsets center the map at zoom=1\n  const baseOX = area.x + area.width / 2 - (vb.x + vb.width / 2) * baseScale\n  const baseOY = area.y + fitHeight / 2 - (vb.y + vb.height / 2) * baseScale\n\n  const zoom = zp ? Math.max(zp.zoomX, zp.zoomY) : 1\n  const scale = baseScale * zoom\n\n  if (!zp || (zoom === 1 && zp.panX === 0 && zp.panY === 0)) {\n    return { scale, offsetX: baseOX, offsetY: baseOY }\n  }\n\n  // Cursor-relative zoom: keeps the viewBox point under the cursor fixed.\n  // Derived from invariant: cursorPx = offset + cursorVx * scale\n  // The zoom-pan system encodes cursor position into panX/panY via:\n  //   panX = relX - (relX - oldPanX) * zoomRatio\n  // This formula correctly resolves both zoom anchoring and drag panning.\n  const offsetX = baseOX * zoom + area.x * (1 - zoom) + zp.panX * area.width\n  const offsetY = baseOY * zoom + area.y * (1 - zoom) + zp.panY * area.height\n\n  return { scale, offsetX, offsetY }\n}\n\nfunction formatValue(v: number): string {\n  if (Math.abs(v) >= 1e12) return (v / 1e12).toFixed(1) + 'T'\n  if (Math.abs(v) >= 1e9) return (v / 1e9).toFixed(1) + 'B'\n  if (Math.abs(v) >= 1e6) return (v / 1e6).toFixed(1) + 'M'\n  if (Math.abs(v) >= 1e3) return (v / 1e3).toFixed(1) + 'K'\n  return v % 1 === 0 ? String(v) : v.toFixed(1)\n}\n\nexport const geoChartType = defineChartType({\n  type: 'geo',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const gOpts = options as GeoOptions\n    const regions = gOpts.regions ?? WORLD_SIMPLE\n    const showLabels = gOpts.showLabels\n    const showLegend = gOpts.legendPosition !== 'none'\n\n    if (regions.length === 0) return nodes\n\n    // Map region names to data values\n    const valueMap = new Map<string, number>()\n    const series = data.series[0]\n    if (series) {\n      for (let i = 0; i < data.labels.length; i++) {\n        valueMap.set(String(data.labels[i]), series.values[i] ?? 0)\n      }\n    }\n\n    // Color range\n    const values = [...valueMap.values()]\n    const minVal = values.length > 0 ? Math.min(...values) : 0\n    const maxVal = values.length > 0 ? Math.max(...values) : 1\n    const range = maxVal - minVal || 1\n\n    const baseColor = options.colors[0] ?? '#3b82f6'\n    const legendH = showLegend && values.length > 0 ? 28 : 0\n\n    // Coordinate system\n    const vb = gOpts.viewBox ?? DEFAULT_VB\n    const { scale, offsetX, offsetY } = computeMapTransform(area, vb, legendH, ctx.zoomPan)\n    const transform = `translate(${offsetX},${offsetY}) scale(${scale})`\n\n    const centroids = getCentroids(regions)\n\n    // Render regions\n    for (let i = 0; i < regions.length; i++) {\n      const region = regions[i]!\n      const val = valueMap.get(region.name)\n      const hasData = val !== undefined\n      const t = hasData ? (val - minVal) / range : 0\n      const fillOpacity = hasData ? 0.2 + t * 0.75 : 0.06\n\n      nodes.push(path(region.path, {\n        class: 'chartts-geo-region',\n        fill: hasData ? baseColor : theme.gridColor,\n        fillOpacity,\n        stroke: theme.textMuted,\n        strokeWidth: 0.4 / scale,\n        transform,\n        'data-series': 0,\n        'data-index': i,\n        'data-name': region.name,\n      }))\n    }\n\n    // Region labels — only for countries with data by default\n    const shouldLabel = showLabels === true ? 'all' : showLabels === 'data' || showLabels === undefined ? 'data' : 'none'\n    if (shouldLabel !== 'none' && values.length > 0) {\n      const labelNodes: RenderNode[] = []\n      const fontSize = Math.max(6, Math.min(9, area.width / 80))\n\n      for (const [name] of valueMap) {\n        const centroid = centroids.get(name)\n        if (!centroid) continue\n\n        const lx = offsetX + centroid.x * scale\n        const ly = offsetY + centroid.y * scale\n\n        labelNodes.push(text(lx, ly, name, {\n          class: 'chartts-geo-label',\n          fill: theme.textColor,\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n          pointerEvents: 'none',\n        }))\n      }\n      if (shouldLabel === 'all') {\n        for (const region of regions) {\n          if (valueMap.has(region.name)) continue\n          const centroid = centroids.get(region.name)\n          if (!centroid) continue\n          const lx = offsetX + centroid.x * scale\n          const ly = offsetY + centroid.y * scale\n          labelNodes.push(text(lx, ly, region.name, {\n            class: 'chartts-geo-label',\n            fill: theme.textMuted,\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: fontSize * 0.85,\n            fontFamily: theme.fontFamily,\n            pointerEvents: 'none',\n          }))\n        }\n      }\n      nodes.push(group(labelNodes, { class: 'chartts-geo-labels', pointerEvents: 'none' }))\n    }\n\n    // Scatter overlay — only if explicitly configured\n    if (gOpts.scatterSeries !== undefined) {\n      const scatterSeries = data.series[gOpts.scatterSeries]\n      if (scatterSeries) {\n        const scatterNodes: RenderNode[] = []\n        const maxScatter = Math.max(...scatterSeries.values.map(Math.abs), 1)\n\n        for (let i = 0; i < data.labels.length; i++) {\n          const name = String(data.labels[i])\n          const val = scatterSeries.values[i] ?? 0\n          if (val <= 0) continue\n\n          const centroid = centroids.get(name)\n          if (!centroid) continue\n\n          const sx = offsetX + centroid.x * scale\n          const sy = offsetY + centroid.y * scale\n          const r = 3 + (val / maxScatter) * 12\n          const color = options.colors[1 % options.colors.length]!\n\n          scatterNodes.push(circle(sx, sy, r, {\n            class: 'chartts-geo-scatter',\n            fill: color,\n            fillOpacity: 0.5,\n            stroke: color,\n            strokeWidth: 1,\n            'data-series': gOpts.scatterSeries,\n            'data-index': i,\n          }))\n        }\n\n        if (scatterNodes.length > 0) {\n          nodes.push(group(scatterNodes, { class: 'chartts-geo-scatter-layer' }))\n        }\n      }\n    }\n\n    // Color legend bar\n    if (showLegend && values.length > 0) {\n      const legendNodes: RenderNode[] = []\n      const lw = Math.min(200, area.width * 0.4)\n      const lh = 8\n      const lx = area.x + (area.width - lw) / 2\n      const ly = area.y + area.height - 20\n\n      // Gradient steps\n      const steps = 10\n      const stepW = lw / steps\n      for (let s = 0; s < steps; s++) {\n        const t = s / (steps - 1)\n        const opacity = 0.2 + t * 0.75\n        legendNodes.push(rect(lx + s * stepW, ly, stepW + 0.5, lh, {\n          fill: baseColor,\n          fillOpacity: opacity,\n          stroke: 'none',\n        }))\n      }\n\n      // Border\n      legendNodes.push(rect(lx, ly, lw, lh, {\n        fill: 'none',\n        stroke: theme.textMuted,\n        strokeWidth: 0.5,\n        rx: 2,\n      }))\n\n      // Min/max labels\n      const labelSize = Math.max(8, theme.fontSizeSmall * 0.8)\n      const seriesName = series?.name ?? ''\n      legendNodes.push(text(lx, ly + lh + labelSize + 2, formatValue(minVal), {\n        fill: theme.textMuted,\n        fontSize: labelSize,\n        fontFamily: theme.fontFamily,\n        textAnchor: 'start',\n      }))\n      legendNodes.push(text(lx + lw, ly + lh + labelSize + 2, formatValue(maxVal), {\n        fill: theme.textMuted,\n        fontSize: labelSize,\n        fontFamily: theme.fontFamily,\n        textAnchor: 'end',\n      }))\n      if (seriesName) {\n        legendNodes.push(text(lx + lw / 2, ly + lh + labelSize + 2, seriesName, {\n          fill: theme.textColor,\n          fontSize: labelSize,\n          fontFamily: theme.fontFamily,\n          textAnchor: 'middle',\n          fontWeight: 600,\n        }))\n      }\n\n      nodes.push(group(legendNodes, { class: 'chartts-geo-legend' }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    if (!data.series[0] || data.series[0].values.length === 0) return null\n\n    const gOpts = options as GeoOptions\n    const regions = gOpts.regions ?? WORLD_SIMPLE\n    const showLegend = gOpts.legendPosition !== 'none'\n    const values = [...new Map(data.labels.map((l, i) => [String(l), data.series[0]!.values[i] ?? 0])).values()]\n    const legendH = showLegend && values.length > 0 ? 28 : 0\n\n    const vb = gOpts.viewBox ?? DEFAULT_VB\n    const { scale, offsetX, offsetY } = computeMapTransform(area, vb, legendH, ctx.zoomPan)\n\n    // Convert mouse to map space\n    const mapX = (mx - offsetX) / scale\n    const mapY = (my - offsetY) / scale\n\n    if (mapX < vb.x || mapX > vb.x + vb.width || mapY < vb.y || mapY > vb.y + vb.height) return null\n\n    const bboxes = getBBoxes(regions)\n    const centroids = getCentroids(regions)\n\n    // Phase 1: find ALL regions whose bbox contains the mouse point\n    const candidates: { idx: number; area: number; dist: number }[] = []\n\n    for (let i = 0; i < data.labels.length; i++) {\n      const name = String(data.labels[i])\n      const bb = bboxes.get(name)\n      if (!bb) continue\n\n      // Expand bbox slightly for small regions\n      const pad = 3\n      if (mapX >= bb.minX - pad && mapX <= bb.maxX + pad &&\n          mapY >= bb.minY - pad && mapY <= bb.maxY + pad) {\n        const bboxArea = (bb.maxX - bb.minX) * (bb.maxY - bb.minY)\n        const centroid = centroids.get(name)\n        const dist = centroid ? Math.sqrt((mapX - centroid.x) ** 2 + (mapY - centroid.y) ** 2) : 999\n        candidates.push({ idx: i, area: bboxArea, dist })\n      }\n    }\n\n    if (candidates.length === 0) return null\n\n    // Phase 2: pick the smallest bbox (most specific region) among candidates.\n    // If tied, pick closest centroid.\n    candidates.sort((a, b) => a.area - b.area || a.dist - b.dist)\n    const best = candidates[0]!\n\n    // Convert centroid back to chart pixel space for highlight positioning\n    const centroid = centroids.get(String(data.labels[best.idx]))\n    const px = centroid ? offsetX + centroid.x * scale : mx\n    const py = centroid ? offsetY + centroid.y * scale : my\n\n    return { seriesIndex: 0, pointIndex: best.idx, distance: best.dist, x: px, y: py }\n  },\n})\n\n/** Extract all x,y coordinate pairs from SVG path string. */\nfunction extractCoords(d: string): number[] {\n  const nums = d.match(/-?\\d+(?:\\.\\d+)?/g)\n  return nums ? nums.map(Number) : []\n}\n\n/** Rough centroid by averaging path command coordinates. */\nfunction getPathCentroid(d: string): { x: number; y: number } | null {\n  const nums = extractCoords(d)\n  if (nums.length < 2) return null\n\n  let sx = 0, sy = 0, count = 0\n  for (let i = 0; i + 1 < nums.length; i += 2) {\n    sx += nums[i]!\n    sy += nums[i + 1]!\n    count++\n  }\n  return count > 0 ? { x: sx / count, y: sy / count } : null\n}\n\n/** Compute bounding box from SVG path coordinates. */\nfunction getPathBBox(d: string): BBox | null {\n  const nums = extractCoords(d)\n  if (nums.length < 2) return null\n\n  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\n  for (let i = 0; i + 1 < nums.length; i += 2) {\n    const x = nums[i]!, y = nums[i + 1]!\n    if (x < minX) minX = x\n    if (x > maxX) maxX = x\n    if (y < minY) minY = y\n    if (y > maxY) maxY = y\n  }\n  return { minX, minY, maxX, maxY }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { circle, text, group } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\nimport { path } from '../../render/tree'\n\n/**\n * Lines (flow lines) chart — curved connection lines between named points.\n *\n * Data convention:\n * - labels: point/city names\n * - series use arrow notation: \"A → B\" with values[0] = flow magnitude\n *\n * Options:\n * - points: array of {name, x, y} defining positions in 0..1 normalized space\n * - showNodes: show circles at point positions (default true)\n * - showArrows: show arrowheads (default true)\n * - showLabels: show point name labels (default true)\n * - curvature: bezier curve amount 0..1 (default 0.3)\n */\n\nexport interface LinesPoint {\n  name: string\n  x: number  // 0..1 normalized\n  y: number  // 0..1 normalized\n}\n\nexport interface LinesOptions extends ResolvedOptions {\n  points?: LinesPoint[]\n  showNodes?: boolean\n  showArrows?: boolean\n  showLabels?: boolean\n  curvature?: number\n}\n\ninterface ParsedFlow {\n  source: string\n  target: string\n  value: number\n}\n\nexport const linesChartType = defineChartType({\n  type: 'lines',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const lOpts = options as LinesOptions\n    const showNodes = lOpts.showNodes !== false\n    const showArrows = lOpts.showArrows !== false\n    const showLabels = lOpts.showLabels !== false\n    const curvature = lOpts.curvature ?? 0.3\n\n    // Build point positions\n    const pointMap = new Map<string, { x: number; y: number }>()\n\n    if (lOpts.points) {\n      for (const p of lOpts.points) {\n        pointMap.set(p.name, {\n          x: area.x + p.x * area.width,\n          y: area.y + p.y * area.height,\n        })\n      }\n    } else {\n      // Auto-layout: arrange points in a circle\n      const names = new Set<string>()\n      for (const s of data.series) {\n        const parts = s.name.split(/\\s*(?:→|->)\\s*/)\n        if (parts.length >= 2) {\n          names.add(parts[0]!.trim())\n          names.add(parts[1]!.trim())\n        }\n      }\n      // Also add labels\n      for (const l of data.labels) names.add(String(l))\n\n      const nameArr = [...names]\n      const cx = area.x + area.width / 2\n      const cy = area.y + area.height / 2\n      const r = Math.min(area.width, area.height) / 2 - 40\n\n      nameArr.forEach((name, i) => {\n        const angle = (i / nameArr.length) * Math.PI * 2 - Math.PI / 2\n        pointMap.set(name, {\n          x: cx + r * Math.cos(angle),\n          y: cy + r * Math.sin(angle),\n        })\n      })\n    }\n\n    // Parse flows from series\n    const flows: ParsedFlow[] = []\n    for (const s of data.series) {\n      const parts = s.name.split(/\\s*(?:→|->)\\s*/)\n      if (parts.length >= 2) {\n        flows.push({\n          source: parts[0]!.trim(),\n          target: parts[1]!.trim(),\n          value: s.values[0] ?? 1,\n        })\n      }\n    }\n\n    if (flows.length === 0 && pointMap.size === 0) return nodes\n\n    // Max flow for line width scaling\n    const maxFlow = Math.max(...flows.map(f => Math.abs(f.value)), 1)\n\n    // Render flow lines\n    for (let fi = 0; fi < flows.length; fi++) {\n      const flow = flows[fi]!\n      const src = pointMap.get(flow.source)\n      const tgt = pointMap.get(flow.target)\n      if (!src || !tgt) continue\n\n      const color = options.colors[fi % options.colors.length]!\n      const lineWidth = 1 + (Math.abs(flow.value) / maxFlow) * 4\n\n      // Curved bezier\n      const dx = tgt.x - src.x\n      const dy = tgt.y - src.y\n      const mx = (src.x + tgt.x) / 2\n      const my = (src.y + tgt.y) / 2\n      const cpx = mx - dy * curvature\n      const cpy = my + dx * curvature\n\n      const pb = new PathBuilder()\n      pb.moveTo(src.x, src.y)\n      pb.quadTo(cpx, cpy, tgt.x, tgt.y)\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-lines-flow',\n        fill: 'none',\n        stroke: color,\n        strokeWidth: lineWidth,\n        strokeOpacity: 0.6,\n        strokeLinecap: 'round',\n        'data-series': fi,\n        'data-index': 0,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${flow.source} → ${flow.target}: ${flow.value}`,\n      }))\n\n      // Arrowhead at target\n      if (showArrows) {\n        const t = 0.95 // position along curve for arrow direction\n        const ax = (1 - t) * (1 - t) * src.x + 2 * (1 - t) * t * cpx + t * t * tgt.x\n        const ay = (1 - t) * (1 - t) * src.y + 2 * (1 - t) * t * cpy + t * t * tgt.y\n        const angle = Math.atan2(tgt.y - ay, tgt.x - ax)\n        const arrowSize = 6 + lineWidth\n\n        const apb = new PathBuilder()\n        apb.moveTo(tgt.x, tgt.y)\n        apb.lineTo(\n          tgt.x - arrowSize * Math.cos(angle - 0.4),\n          tgt.y - arrowSize * Math.sin(angle - 0.4),\n        )\n        apb.lineTo(\n          tgt.x - arrowSize * Math.cos(angle + 0.4),\n          tgt.y - arrowSize * Math.sin(angle + 0.4),\n        )\n        apb.close()\n\n        nodes.push(path(apb.build(), {\n          class: 'chartts-lines-arrow',\n          fill: color,\n          fillOpacity: 0.8,\n        }))\n      }\n    }\n\n    // Render nodes\n    if (showNodes) {\n      const nodeNodes: RenderNode[] = []\n      let idx = 0\n      for (const [name, pos] of pointMap) {\n        const color = options.colors[idx % options.colors.length]!\n\n        nodeNodes.push(circle(pos.x, pos.y, 6, {\n          class: 'chartts-lines-node',\n          fill: color,\n          stroke: theme.background === 'transparent' ? '#fff' : theme.background,\n          strokeWidth: 2,\n          'data-series': idx,\n          'data-index': 0,\n        }))\n\n        if (showLabels) {\n          nodeNodes.push(text(pos.x, pos.y - 14, name, {\n            class: 'chartts-lines-label',\n            fill: theme.textColor,\n            textAnchor: 'middle',\n            dominantBaseline: 'auto',\n            fontSize: theme.fontSizeSmall,\n            fontFamily: theme.fontFamily,\n            fontWeight: 600,\n          }))\n        }\n        idx++\n      }\n      nodes.push(group(nodeNodes, { class: 'chartts-lines-nodes' }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { options } = ctx\n    const lOpts = options as LinesOptions\n    const pointMap = new Map<string, { x: number; y: number }>()\n\n    if (lOpts.points) {\n      const { area } = ctx\n      for (const p of lOpts.points) {\n        pointMap.set(p.name, {\n          x: area.x + p.x * area.width,\n          y: area.y + p.y * area.height,\n        })\n      }\n    }\n\n    let idx = 0\n    for (const [, pos] of pointMap) {\n      const dx = mx - pos.x\n      const dy = my - pos.y\n      const dist = Math.sqrt(dx * dx + dy * dy)\n      if (dist < 12) {\n        return { seriesIndex: idx, pointIndex: 0, distance: dist, x: pos.x, y: pos.y }\n      }\n      idx++\n    }\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult, ScaleType,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { rect, text, group } from '../../render/tree'\n\n/**\n * Matrix chart — grid layout with color-coded cells.\n *\n * Data convention:\n * - labels: row/column names (for square matrices) or column names\n * - series[i].name: row name, series[i].values[j]: cell value at row i, col j\n *\n * Options:\n * - showValues: display values in cells (default true)\n * - cellRadius: border-radius for cells (default 2)\n * - colorScale: 'sequential' | 'diverging' (default 'sequential')\n * - minColor: color for minimum value\n * - maxColor: color for maximum value\n */\n\nexport interface MatrixOptions extends ResolvedOptions {\n  showValues?: boolean\n  cellRadius?: number\n  colorScale?: 'sequential' | 'diverging'\n  minColor?: string\n  maxColor?: string\n}\n\nexport const matrixChartType = defineChartType({\n  type: 'matrix',\n  suppressAxes: true,\n\n  getScaleTypes(): { x: ScaleType; y: ScaleType } {\n    return { x: 'categorical', y: 'categorical' }\n  },\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const mOpts = options as MatrixOptions\n    const showValues = mOpts.showValues !== false\n    const cellRadius = mOpts.cellRadius ?? 2\n    const colorScale = mOpts.colorScale ?? 'sequential'\n\n    const rows = data.series.length\n    const cols = data.labels.length\n    if (rows === 0 || cols === 0) return nodes\n\n    // Gather all values for color scale\n    let allMin = Infinity, allMax = -Infinity\n    for (const s of data.series) {\n      for (const v of s.values) {\n        if (v < allMin) allMin = v\n        if (v > allMax) allMax = v\n      }\n    }\n    if (!isFinite(allMin)) allMin = 0\n    if (!isFinite(allMax)) allMax = 1\n    const valRange = allMax - allMin || 1\n\n    // Layout\n    const labelPadLeft = 60\n    const labelPadTop = 30\n    const gap = 2\n    const gridW = area.width - labelPadLeft - 10\n    const gridH = area.height - labelPadTop - 10\n    const cellW = (gridW - gap * (cols - 1)) / cols\n    const cellH = (gridH - gap * (rows - 1)) / rows\n    const gridX = area.x + labelPadLeft\n    const gridY = area.y + labelPadTop\n\n    // Column headers\n    for (let c = 0; c < cols; c++) {\n      const cx = gridX + c * (cellW + gap) + cellW / 2\n      nodes.push(text(cx, gridY - 8, String(data.labels[c] ?? ''), {\n        class: 'chartts-matrix-col-label',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'auto',\n        fontSize: Math.min(theme.fontSizeSmall, cellW * 0.35),\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    // Row labels + cells\n    for (let r = 0; r < rows; r++) {\n      const series = data.series[r]!\n      const ry = gridY + r * (cellH + gap)\n\n      // Row label\n      nodes.push(text(gridX - 6, ry + cellH / 2, series.name, {\n        class: 'chartts-matrix-row-label',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: Math.min(theme.fontSizeSmall, cellH * 0.4),\n        fontFamily: theme.fontFamily,\n      }))\n\n      const rowNodes: RenderNode[] = []\n      for (let c = 0; c < cols; c++) {\n        const val = series.values[c] ?? 0\n        const cx = gridX + c * (cellW + gap)\n\n        // Color interpolation\n        const color = getCellColor(val, allMin, allMax, valRange, colorScale, options.colors)\n        const textColor = getContrastColor(val, allMin, allMax, valRange, colorScale)\n\n        rowNodes.push(rect(cx, ry, cellW, cellH, {\n          class: 'chartts-matrix-cell',\n          fill: color,\n          rx: cellRadius,\n          ry: cellRadius,\n          'data-series': r,\n          'data-index': c,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name} × ${data.labels[c]}: ${val}`,\n        }))\n\n        // Value text\n        if (showValues && cellW > 18 && cellH > 14) {\n          const displayVal = Number.isInteger(val) ? String(val)\n            : Math.abs(val) < 10 ? val.toFixed(2) : val.toFixed(1)\n\n          rowNodes.push(text(cx + cellW / 2, ry + cellH / 2, displayVal, {\n            class: 'chartts-matrix-value',\n            fill: textColor,\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: Math.min(theme.fontSizeSmall, cellW * 0.3, cellH * 0.4),\n            fontFamily: theme.fontFamily,\n            fontWeight: 600,\n            pointerEvents: 'none',\n          }))\n        }\n      }\n\n      nodes.push(group(rowNodes, {\n        class: `chartts-series chartts-series-${r}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const rows = data.series.length\n    const cols = data.labels.length\n    if (rows === 0 || cols === 0) return null\n\n    const labelPadLeft = 60\n    const labelPadTop = 30\n    const gap = 2\n    const gridW = area.width - labelPadLeft - 10\n    const gridH = area.height - labelPadTop - 10\n    const cellW = (gridW - gap * (cols - 1)) / cols\n    const cellH = (gridH - gap * (rows - 1)) / rows\n    const gridX = area.x + labelPadLeft\n    const gridY = area.y + labelPadTop\n\n    const col = Math.floor((mx - gridX) / (cellW + gap))\n    const row = Math.floor((my - gridY) / (cellH + gap))\n\n    if (row >= 0 && row < rows && col >= 0 && col < cols) {\n      return { seriesIndex: row, pointIndex: col, distance: 0, x: gridX + col * (cellW + gap) + cellW / 2, y: gridY + row * (cellH + gap) + cellH / 2 }\n    }\n    return null\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Color helpers\n// ---------------------------------------------------------------------------\n\nfunction getCellColor(\n  val: number, min: number, max: number, range: number,\n  scale: string, colors: readonly string[],\n): string {\n  if (scale === 'diverging') {\n    const mid = (min + max) / 2\n    if (val >= mid) {\n      const t = (val - mid) / ((max - mid) || 1)\n      return interpolateOpacity(colors[0] ?? '#3b82f6', 0.15 + t * 0.85)\n    } else {\n      const t = (mid - val) / ((mid - min) || 1)\n      return interpolateOpacity(colors[1] ?? '#ef4444', 0.15 + t * 0.85)\n    }\n  }\n  // Sequential\n  const t = (val - min) / range\n  return interpolateOpacity(colors[0] ?? '#3b82f6', 0.08 + t * 0.9)\n}\n\nfunction getContrastColor(\n  val: number, min: number, max: number, range: number, scale: string,\n): string {\n  if (scale === 'diverging') {\n    const mid = (min + max) / 2\n    const t = Math.abs(val - mid) / ((max - min) / 2 || 1)\n    return t > 0.5 ? '#ffffff' : '#1f2937'\n  }\n  const t = (val - min) / range\n  return t > 0.55 ? '#ffffff' : '#1f2937'\n}\n\nfunction interpolateOpacity(baseColor: string, opacity: number): string {\n  // For CSS var() colors, we use opacity approach\n  // Return as rgba-compatible format\n  const hex = baseColor.includes('#') ? baseColor : '#3b82f6'\n  const r = parseInt(hex.slice(1, 3), 16) || 59\n  const g = parseInt(hex.slice(3, 5), 16) || 130\n  const b = parseInt(hex.slice(5, 7), 16) || 246\n  return `rgba(${r},${g},${b},${opacity.toFixed(2)})`\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult, ScaleType,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { text } from '../../render/tree'\n\n/**\n * Custom chart — meta chart type that delegates rendering to a user function.\n *\n * Options:\n * - renderFn: (ctx: RenderContext) => RenderNode[]\n * - hitTestFn: (ctx: RenderContext, mx: number, my: number) => HitResult | null\n * - scaleTypes: { x: ScaleType; y: ScaleType } (default categorical/linear)\n *\n * If no renderFn is provided, renders a placeholder message.\n */\n\nexport interface CustomChartOptions extends ResolvedOptions {\n  renderFn?: (ctx: RenderContext) => RenderNode[]\n  hitTestFn?: (ctx: RenderContext, mx: number, my: number) => HitResult | null\n  scaleTypes?: { x: ScaleType; y: ScaleType }\n}\n\nexport const customChartType = defineChartType({\n  type: 'custom',\n  suppressAxes: true,\n\n  getScaleTypes(_data?: ChartData, options?: ResolvedOptions): { x: ScaleType; y: ScaleType } {\n    const cOpts = options as CustomChartOptions | undefined\n    return cOpts?.scaleTypes ?? { x: 'categorical', y: 'linear' }\n  },\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const cOpts = ctx.options as CustomChartOptions\n\n    if (cOpts.renderFn) {\n      return cOpts.renderFn(ctx)\n    }\n\n    // Placeholder when no render function is provided\n    const { area, theme } = ctx\n    return [\n      text(\n        area.x + area.width / 2,\n        area.y + area.height / 2,\n        'Custom chart — provide renderFn in options',\n        {\n          class: 'chartts-custom-placeholder',\n          fill: theme.textMuted,\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize: theme.fontSize,\n          fontFamily: theme.fontFamily,\n        },\n      ),\n    ]\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const cOpts = ctx.options as CustomChartOptions\n    if (cOpts.hitTestFn) {\n      const result = cOpts.hitTestFn(ctx, mx, my)\n      if (result && result.x === undefined) result.x = mx\n      if (result && result.y === undefined) result.y = my\n      return result\n    }\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, line } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\nexport interface OHLCOptions extends ResolvedOptions {\n  /** OHLC data arrays. */\n  ohlc?: {\n    open: number[]\n    high: number[]\n    low: number[]\n    close: number[]\n  }\n  /** Up color (close >= open). Default green. */\n  upColor?: string\n  /** Down color (close < open). Default red. */\n  downColor?: string\n  /** Line width for stems and ticks. Default 1.5. */\n  lineWidth?: number\n}\n\n/**\n * OHLC (Open-High-Low-Close) chart — tick-mark style.\n *\n * Each bar is a vertical line (high→low) with horizontal ticks:\n * - Left tick = open price\n * - Right tick = close price\n * Color indicates direction (green=up, red=down).\n */\nexport const ohlcChartType = defineChartType({\n  type: 'ohlc',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const opts = options as OHLCOptions\n    const prepared = prepareData(data, options)\n\n    // Support ohlc from options OR from 4 series named Open/High/Low/Close\n    let ohlc = opts.ohlc\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n\n    if (ohlc) {\n      let yMin = prepared.bounds.yMin\n      let yMax = prepared.bounds.yMax\n      for (let i = 0; i < ohlc.high.length; i++) {\n        if (ohlc.high[i]! < yMin) yMin = ohlc.high[i]!\n        if (ohlc.high[i]! > yMax) yMax = ohlc.high[i]!\n        if (ohlc.low[i]! < yMin) yMin = ohlc.low[i]!\n        if (ohlc.low[i]! > yMax) yMax = ohlc.low[i]!\n      }\n      prepared.bounds.yMin = yMin\n      prepared.bounds.yMax = yMax\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const opts = options as OHLCOptions\n\n    // Support ohlc from options OR from 4 series named Open/High/Low/Close\n    let ohlc = opts.ohlc\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n    if (!ohlc) return nodes\n\n    const series = data.series[0]\n    if (!series) return nodes\n\n    const upColor = opts.upColor ?? 'var(--color-emerald-500, #10b981)'\n    const downColor = opts.downColor ?? 'var(--color-red-500, #ef4444)'\n    const lw = opts.lineWidth ?? 1.5\n\n    const bw = getBandwidth(xScale)\n    const tickWidth = bw * 0.3\n\n    const tickNodes: RenderNode[] = []\n\n    for (let i = 0; i < ohlc.open.length; i++) {\n      const open = ohlc.open[i]!\n      const high = ohlc.high[i]!\n      const low = ohlc.low[i]!\n      const close = ohlc.close[i]!\n\n      const cx = xScale.map(i)\n      const isUp = close >= open\n      const color = isUp ? upColor : downColor\n\n      const yHigh = yScale.map(high)\n      const yLow = yScale.map(low)\n      const yOpen = yScale.map(open)\n      const yClose = yScale.map(close)\n\n      // Vertical stem (high → low)\n      tickNodes.push(line(cx, yHigh, cx, yLow, {\n        class: 'chartts-ohlc-stem',\n        stroke: color,\n        strokeWidth: lw,\n        'data-series': 0,\n        'data-index': i,\n      }))\n\n      // Left tick (open)\n      tickNodes.push(line(cx - tickWidth, yOpen, cx, yOpen, {\n        class: 'chartts-ohlc-tick',\n        stroke: color,\n        strokeWidth: lw,\n        'data-series': 0,\n        'data-index': i,\n      }))\n\n      // Right tick (close)\n      tickNodes.push(line(cx, yClose, cx + tickWidth, yClose, {\n        class: 'chartts-ohlc-tick',\n        stroke: color,\n        strokeWidth: lw,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? i}: O${open} H${high} L${low} C${close}`,\n      }))\n    }\n\n    nodes.push(group(tickNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, _my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const opts = options as OHLCOptions\n    let ohlc = opts.ohlc\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n    if (!ohlc) return null\n\n    const bw = getBandwidth(xScale)\n    const half = bw * 0.35\n\n    for (let i = 0; i < ohlc.open.length; i++) {\n      const cx = xScale.map(i)\n      if (mx >= cx - half && mx <= cx + half) {\n        return { seriesIndex: 0, pointIndex: i, distance: Math.abs(mx - cx), x: cx, y: yScale.map(ohlc.close[i]!) }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, line, circle, text } from '../../render/tree'\nimport { createHorizontalMapper } from '../../utils/scale'\n\n/**\n * Dumbbell / connected dot chart.\n *\n * Two dots per category connected by a line.\n * Horizontal layout — categories on y-axis, values on x-axis.\n * Requires exactly 2 series. Shows before/after or comparison.\n */\nexport const dumbbellChartType = defineChartType({\n  type: 'dumbbell',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    if (data.series.length < 2) return nodes\n    const s1 = data.series[0]!\n    const s2 = data.series[1]!\n    const count = Math.min(s1.values.length, s2.values.length)\n    if (count === 0) return nodes\n\n    const labelWidth = Math.min(80, area.width * 0.2)\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n    const rowHeight = area.height / count\n    const dotR = Math.min(6, rowHeight * 0.2)\n\n    const color1 = options.colors[0]!\n    const color2 = options.colors[1 % options.colors.length]!\n\n    const valueToX = createHorizontalMapper(yScale, area, chartX, chartW)\n\n    for (let i = 0; i < count; i++) {\n      const cy = area.y + rowHeight * (i + 0.5)\n      const v1 = s1.values[i]!\n      const v2 = s2.values[i]!\n      const x1 = valueToX(v1)\n      const x2 = valueToX(v2)\n      const label = String(data.labels[i] ?? `Item ${i + 1}`)\n\n      const rowNodes: RenderNode[] = []\n\n      // Label\n      rowNodes.push(text(area.x + labelWidth - 8, cy, label, {\n        class: 'chartts-dumbbell-label',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      // Connecting line\n      rowNodes.push(line(x1, cy, x2, cy, {\n        class: 'chartts-dumbbell-connector',\n        stroke: theme.gridColor,\n        strokeWidth: 2,\n      }))\n\n      // Dot 1 (series 0)\n      rowNodes.push(circle(x1, cy, dotR, {\n        class: 'chartts-dumbbell-dot',\n        fill: color1,\n        stroke: '#fff',\n        strokeWidth: 1.5,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label} — ${s1.name}: ${v1}`,\n      }))\n\n      // Dot 2 (series 1)\n      rowNodes.push(circle(x2, cy, dotR, {\n        class: 'chartts-dumbbell-dot',\n        fill: color2,\n        stroke: '#fff',\n        strokeWidth: 1.5,\n        'data-series': 1,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label} — ${s2.name}: ${v2}`,\n      }))\n\n      nodes.push(group(rowNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': label,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, yScale } = ctx\n    if (data.series.length < 2) return null\n    const s1 = data.series[0]!\n    const s2 = data.series[1]!\n    const count = Math.min(s1.values.length, s2.values.length)\n    if (count === 0) return null\n\n    const labelWidth = Math.min(80, area.width * 0.2)\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n    const rowHeight = area.height / count\n\n    const valueToX = createHorizontalMapper(yScale, area, chartX, chartW)\n\n    let best: HitResult | null = null\n    let bestDist = 15\n\n    for (let i = 0; i < count; i++) {\n      const cy = area.y + rowHeight * (i + 0.5)\n\n      for (const [si, series] of [s1, s2].entries()) {\n        const vx = valueToX(series.values[i]!)\n        const dx = mx - vx\n        const dy = my - cy\n        const dist = Math.sqrt(dx * dx + dy * dy)\n\n        if (dist < bestDist) {\n          bestDist = dist\n          best = { seriesIndex: si, pointIndex: i, distance: dist, x: vx, y: cy }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, text } from '../../render/tree'\n\n/**\n * Calendar heatmap — GitHub-style contribution grid.\n *\n * Data format:\n * - labels: dates as strings (YYYY-MM-DD) or numbers (day index)\n * - series[0]: values for each day (intensity)\n *\n * Renders a 7-row (days of week) x N-column (weeks) grid.\n * If labels aren't dates, treats data as a flat grid: 7 rows.\n */\nexport const calendarChartType = defineChartType({\n  type: 'calendar',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const values = series.values\n    const count = values.length\n    const rows = 7 // days of week\n    const cols = Math.ceil(count / rows)\n\n    let maxVal = 0\n    for (const v of values) {\n      if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    }\n    if (maxVal === 0) maxVal = 1\n\n    // Detect date mode (labels are YYYY-MM-DD)\n    const isDateMode = data.labels.length > 0 &&\n      typeof data.labels[0] === 'string' &&\n      /^\\d{4}-\\d{2}-\\d{2}$/.test(data.labels[0] as string)\n\n    // Day labels\n    const dayLabels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\n    const labelW = 30\n    const gridX = area.x + labelW\n    const gridW = area.width - labelW\n    // Reserve space for month labels at top when in date mode\n    const monthLabelH = isDateMode ? 14 : 0\n    const gridY = area.y + monthLabelH\n    const gridH = area.height - monthLabelH\n\n    const cellW = Math.min(gridW / cols, gridH / rows) - 1\n    const cellH = cellW // square cells\n    const gap = Math.max(1, cellW * 0.12)\n\n    const color = options.colors[0] ?? '#10b981'\n    const labelFontSize = Math.min(theme.fontSizeSmall * 0.8, cellH * 0.6)\n\n    // Month labels along the top (date mode only)\n    if (isDateMode) {\n      const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n      let lastMonth = -1\n      for (let idx = 0; idx < count; idx++) {\n        const dateStr = data.labels[idx] as string\n        const month = parseInt(dateStr.substring(5, 7), 10) - 1\n        if (month !== lastMonth) {\n          const col = Math.floor(idx / rows)\n          nodes.push(text(gridX + col * (cellW + gap), area.y + monthLabelH - 3, monthNames[month]!, {\n            class: 'chartts-calendar-monthlabel',\n            fill: theme.textMuted,\n            textAnchor: 'start',\n            fontSize: labelFontSize,\n            fontFamily: theme.fontFamily,\n          }))\n          lastMonth = month\n        }\n      }\n    }\n\n    // Day-of-week labels\n    for (let r = 0; r < rows; r++) {\n      if (r % 2 === 0) { // show Mon, Wed, Fri, Sun\n        nodes.push(text(area.x + labelW - 4, gridY + r * (cellH + gap) + cellH / 2, dayLabels[r]!, {\n          class: 'chartts-calendar-daylabel',\n          fill: theme.textMuted,\n          textAnchor: 'end',\n          dominantBaseline: 'central',\n          fontSize: labelFontSize,\n          fontFamily: theme.fontFamily,\n        }))\n      }\n    }\n\n    // Cells\n    for (let idx = 0; idx < count; idx++) {\n      const col = Math.floor(idx / rows)\n      const row = idx % rows\n      const val = Math.abs(values[idx]!)\n      const intensity = val / maxVal\n\n      const x = gridX + col * (cellW + gap)\n      const y = gridY + row * (cellH + gap)\n\n      const cellColor = intensity === 0\n        ? (theme.gridColor ?? '#e5e7eb')\n        : interpolateOpacity(color, intensity)\n\n      const cellNodes: RenderNode[] = [\n        rect(x, y, cellW, cellH, {\n          class: 'chartts-calendar-cell',\n          fill: cellColor,\n          rx: 3,\n          ry: 3,\n          'data-series': 0,\n          'data-index': idx,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[idx] ?? `Day ${idx + 1}`}: ${values[idx]}`,\n        }),\n      ]\n\n      nodes.push(group(cellNodes, {\n        class: `chartts-series chartts-series-${idx}`,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const count = series.values.length\n    const rows = 7\n    const cols = Math.ceil(count / rows)\n    const labelW = 30\n    const gridX = area.x + labelW\n    const gridW = area.width - labelW\n\n    const isDateMode = data.labels.length > 0 &&\n      typeof data.labels[0] === 'string' &&\n      /^\\d{4}-\\d{2}-\\d{2}$/.test(data.labels[0] as string)\n    const monthLabelH = isDateMode ? 14 : 0\n    const gridY = area.y + monthLabelH\n    const gridH = area.height - monthLabelH\n\n    const cellW = Math.min(gridW / cols, gridH / rows) - 1\n    const cellH = cellW\n    const gap = Math.max(1, cellW * 0.12)\n\n    const col = Math.floor((mx - gridX) / (cellW + gap))\n    const row = Math.floor((my - gridY) / (cellH + gap))\n\n    if (col < 0 || col >= cols || row < 0 || row >= rows) return null\n\n    const idx = col * rows + row\n    if (idx >= count) return null\n\n    // Check if actually within the cell bounds\n    const cellX = gridX + col * (cellW + gap)\n    const cellY = gridY + row * (cellH + gap)\n    if (mx >= cellX && mx <= cellX + cellW && my >= cellY && my <= cellY + cellH) {\n      return { seriesIndex: 0, pointIndex: idx, distance: 0, x: cellX + cellW / 2, y: cellY + cellH / 2 }\n    }\n\n    return null\n  },\n})\n\nfunction interpolateOpacity(color: string, t: number): string {\n  // Extract hex from CSS variable fallback: var(--name, #hex) → #hex\n  let hex = color\n  const varMatch = color.match(/#[0-9a-fA-F]{3,8}/)\n  if (varMatch) hex = varMatch[0]\n\n  const h = hex.replace('#', '')\n  const r = parseInt(h.substring(0, 2), 16)\n  const g = parseInt(h.substring(2, 4), 16)\n  const b = parseInt(h.substring(4, 6), 16)\n\n  if (isNaN(r) || isNaN(g) || isNaN(b)) {\n    // Fallback: just use the color with opacity\n    const alpha = 0.15 + t * 0.85\n    return `rgba(16,185,129,${alpha})`\n  }\n\n  // Blend with a minimum opacity of 0.15 up to 1.0\n  const alpha = 0.15 + t * 0.85\n  return `rgba(${r},${g},${b},${alpha})`\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, path, circle } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\nimport { formatNum } from '../../utils/format'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Combo / Mixed chart — overlays bar + line on the same axes.\n *\n * Convention: series with `fill: true` or series at index 0 render as bars.\n * Remaining series render as lines with points.\n * Use the series `fill` flag to control: fill=false (or omitted after first) → line.\n *\n * Simple heuristic:\n * - series[0] → bars\n * - series[1..N] → lines\n */\nexport const comboChartType = defineChartType({\n  type: 'combo',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n    if (options.yMax === undefined && prepared.bounds.yMax < 0) {\n      prepared.bounds.yMax = 0\n    }\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    if (data.series.length === 0) return nodes\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return nodes\n\n    // Bars for series[0]\n    const barSeries = data.series[0]!\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    const barNodes: RenderNode[] = []\n    for (let i = 0; i < barSeries.values.length; i++) {\n      if (isNaN(barSeries.values[i]!)) continue // skip missing data\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(barSeries.values[i]!)\n      const isPositive = barSeries.values[i]! >= 0\n      const y = isPositive ? vy : baseline\n      const h = Math.abs(vy - baseline)\n\n      const barFill = `url(#chartts-bar-${barSeries.index})`\n      const r = Math.min(options.barRadius, barWidth / 2, h / 2)\n\n      if (r > 0 && h > r * 2) {\n        const d = isPositive\n          ? `M${formatNum(barX)},${formatNum(y + h)}V${formatNum(y + r)}Q${formatNum(barX)},${formatNum(y)},${formatNum(barX + r)},${formatNum(y)}H${formatNum(barX + barWidth - r)}Q${formatNum(barX + barWidth)},${formatNum(y)},${formatNum(barX + barWidth)},${formatNum(y + r)}V${formatNum(y + h)}Z`\n          : `M${formatNum(barX)},${formatNum(y)}V${formatNum(y + h - r)}Q${formatNum(barX)},${formatNum(y + h)},${formatNum(barX + r)},${formatNum(y + h)}H${formatNum(barX + barWidth - r)}Q${formatNum(barX + barWidth)},${formatNum(y + h)},${formatNum(barX + barWidth)},${formatNum(y + h - r)}V${formatNum(y)}Z`\n        barNodes.push(path(d, {\n          class: 'chartts-bar',\n          fill: barFill,\n          'data-series': barSeries.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${barSeries.name}: ${barSeries.values[i]}`,\n        }))\n      } else {\n        barNodes.push(rect(barX, y, barWidth, h, {\n          class: 'chartts-bar',\n          fill: barFill,\n          'data-series': barSeries.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${barSeries.name}: ${barSeries.values[i]}`,\n        }))\n      }\n    }\n    nodes.push(group(barNodes, {\n      class: `chartts-series chartts-series-${barSeries.index}`,\n      'data-series-name': barSeries.name,\n    }))\n\n    // Lines for series[1..N]\n    for (let si = 1; si < data.series.length; si++) {\n      const series = data.series[si]!\n      const color = options.colors[series.index % options.colors.length]!\n      const lineNodes: RenderNode[] = []\n\n      // Build line path\n      const pb = new PathBuilder()\n      let started = false\n      for (let i = 0; i < series.values.length; i++) {\n        if (isNaN(series.values[i]!)) { started = false; continue } // break line at NaN\n        const px = xScale.map(i)\n        const py = yScale.map(series.values[i]!)\n        if (!started) {\n          pb.moveTo(px, py)\n          started = true\n        } else {\n          pb.lineTo(px, py)\n        }\n      }\n\n      lineNodes.push(path(pb.build(), {\n        class: 'chartts-line chartts-combo-line',\n        stroke: color,\n        strokeWidth: 2,\n        fill: 'none',\n      }))\n\n      // Points\n      for (let i = 0; i < series.values.length; i++) {\n        if (isNaN(series.values[i]!)) continue // skip missing data\n        const px = xScale.map(i)\n        const py = yScale.map(series.values[i]!)\n        lineNodes.push(circle(px, py, 4, {\n          class: 'chartts-point chartts-combo-point',\n          fill: color,\n          stroke: '#fff',\n          strokeWidth: 1.5,\n          'data-series': series.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name}: ${series.values[i]}`,\n        }))\n      }\n\n      nodes.push(group(lineNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    if (data.series.length === 0) return null\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    // Check bar hits first (series[0])\n    const barSeries = data.series[0]!\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    for (let i = 0; i < barSeries.values.length; i++) {\n      if (isNaN(barSeries.values[i]!)) continue\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(barSeries.values[i]!)\n      const y = barSeries.values[i]! >= 0 ? vy : baseline\n      const h = Math.abs(vy - baseline)\n\n      if (mx >= barX - 2 && mx <= barX + barWidth + 2 && my >= y - 2 && my <= y + h + 2) {\n        best = { seriesIndex: barSeries.index, pointIndex: i, distance: 0, x: cx, y: vy }\n        return best\n      }\n    }\n\n    // Check line point hits (series[1..N])\n    for (let si = 1; si < data.series.length; si++) {\n      const series = data.series[si]!\n      for (let i = 0; i < series.values.length; i++) {\n        if (isNaN(series.values[i]!)) continue\n        const px = xScale.map(i)\n        const py = yScale.map(series.values[i]!)\n        const dx = mx - px\n        const dy = my - py\n        const dist = Math.sqrt(dx * dx + dy * dy)\n\n        if (dist < bestDist && dist < 20) {\n          bestDist = dist\n          best = { seriesIndex: series.index, pointIndex: i, distance: dist, x: px, y: py }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, rect, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Sankey / flow diagram.\n *\n * Data convention:\n * - labels: node names (unique). First N are source layer, rest are target layer.\n * - series[i]: a flow. series[i].name = \"Source → Target\", series[i].values = [flowValue]\n *\n * Alternative (simpler): encode flows as a flat list.\n * - labels: all unique node names\n * - series[0].values: flat list of flow values\n * - options.links: array of { source: number, target: number, value: number }\n *\n * This implementation auto-detects the format:\n * If series names contain \"→\" or \"->\", parse as source→target flows.\n * Otherwise treat as adjacency: series[i] = from node i, values[j] = flow to node j.\n */\n\ninterface SankeyNode {\n  name: string\n  index: number\n  column: number\n  y: number\n  height: number\n  totalIn: number\n  totalOut: number\n}\n\ninterface SankeyLink {\n  source: number\n  target: number\n  value: number\n  sy: number   // source y offset\n  ty: number   // target y offset\n  width: number\n}\n\nexport const sankeyChartType = defineChartType({\n  type: 'sankey',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const { sankeyNodes, sankeyLinks } = parseSankeyData(data, options)\n    if (sankeyNodes.length === 0 || sankeyLinks.length === 0) return nodes\n\n    // Layout\n    const columns = layoutColumns(sankeyNodes, sankeyLinks, area)\n    const nodeWidth = Math.min(20, area.width * 0.04)\n    const nodePadding = 8\n\n    // Position nodes within columns\n    for (const col of columns) {\n      const colNodes = sankeyNodes.filter(n => n.column === col)\n      const totalHeight = colNodes.reduce((s, n) => s + n.height, 0)\n      const gaps = Math.max(0, colNodes.length - 1) * nodePadding\n      const scale = (area.height - gaps) / Math.max(totalHeight, 1)\n\n      let y = area.y\n      for (const node of colNodes) {\n        node.height = node.height * scale\n        node.y = y\n        y += node.height + nodePadding\n      }\n    }\n\n    // Compute link positions\n    computeLinkPositions(sankeyNodes, sankeyLinks)\n\n    // Render links (curved bands)\n    for (let li = 0; li < sankeyLinks.length; li++) {\n      const link = sankeyLinks[li]!\n      const src = sankeyNodes[link.source]!\n      const tgt = sankeyNodes[link.target]!\n      const x0 = src.y !== undefined ? getNodeX(src, columns, area, nodeWidth) + nodeWidth : 0\n      const x1 = tgt.y !== undefined ? getNodeX(tgt, columns, area, nodeWidth) : 0\n      const y0 = src.y + link.sy\n      const y1 = tgt.y + link.ty\n      const w = link.width\n\n      const pb = new PathBuilder()\n      const cx = (x0 + x1) / 2\n      pb.moveTo(x0, y0)\n      pb.curveTo(cx, y0, cx, y1, x1, y1)\n      pb.vTo(y1 + w)\n      pb.curveTo(cx, y1 + w, cx, y0 + w, x0, y0 + w)\n      pb.close()\n\n      const color = options.colors[link.source % options.colors.length]!\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-sankey-link',\n        fill: color,\n        fillOpacity: 0.3,\n        'data-series': link.source,\n        'data-index': li,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${src.name} → ${tgt.name}: ${link.value}`,\n      }))\n    }\n\n    // Render nodes (rectangles + labels)\n    for (let ni = 0; ni < sankeyNodes.length; ni++) {\n      const node = sankeyNodes[ni]!\n      const x = getNodeX(node, columns, area, nodeWidth)\n      const color = options.colors[ni % options.colors.length]!\n      const nodeGroup: RenderNode[] = []\n\n      nodeGroup.push(rect(x, node.y, nodeWidth, Math.max(node.height, 2), {\n        rx: 3, ry: 3,\n        class: 'chartts-sankey-node',\n        fill: color,\n        'data-series': ni,\n        'data-index': 0,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${node.name}: ${Math.max(node.totalIn, node.totalOut)}`,\n      }))\n\n      // Label\n      const isLeft = node.column < columns.length / 2\n      const labelX = isLeft ? x + nodeWidth + 6 : x - 6\n      const anchor = isLeft ? 'start' : 'end'\n\n      nodeGroup.push(text(labelX, node.y + node.height / 2, node.name, {\n        class: 'chartts-sankey-label',\n        fill: theme.textColor,\n        textAnchor: anchor as 'start' | 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      nodes.push(group(nodeGroup, {\n        class: `chartts-series chartts-series-${ni}`,\n        'data-series-name': node.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const { sankeyNodes, sankeyLinks } = parseSankeyData(data, options)\n    if (sankeyNodes.length === 0) return null\n\n    const columns = layoutColumns(sankeyNodes, sankeyLinks, area)\n    const nodeWidth = Math.min(20, area.width * 0.04)\n    const nodePadding = 8\n\n    // Re-layout (same as render)\n    for (const col of columns) {\n      const colNodes = sankeyNodes.filter(n => n.column === col)\n      const totalHeight = colNodes.reduce((s, n) => s + n.height, 0)\n      const gaps = Math.max(0, colNodes.length - 1) * nodePadding\n      const scale = (area.height - gaps) / Math.max(totalHeight, 1)\n      let y = area.y\n      for (const node of colNodes) {\n        node.height = node.height * scale\n        node.y = y\n        y += node.height + nodePadding\n      }\n    }\n\n    // Check node hits\n    for (let ni = 0; ni < sankeyNodes.length; ni++) {\n      const node = sankeyNodes[ni]!\n      const x = getNodeX(node, columns, area, nodeWidth)\n      if (mx >= x && mx <= x + nodeWidth && my >= node.y && my <= node.y + node.height) {\n        return { seriesIndex: ni, pointIndex: 0, distance: 0, x: x + nodeWidth / 2, y: node.y + node.height / 2 }\n      }\n    }\n\n    return null\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Parsing helpers\n// ---------------------------------------------------------------------------\n\nfunction parseSankeyData(\n  data: PreparedData,\n  _options: ResolvedOptions,\n): { sankeyNodes: SankeyNode[]; sankeyLinks: SankeyLink[] } {\n  const sankeyNodes: SankeyNode[] = []\n  const sankeyLinks: SankeyLink[] = []\n  const nodeMap = new Map<string, number>()\n\n  function getOrCreateNode(name: string): number {\n    if (nodeMap.has(name)) return nodeMap.get(name)!\n    const idx = sankeyNodes.length\n    nodeMap.set(name, idx)\n    sankeyNodes.push({\n      name,\n      index: idx,\n      column: -1,\n      y: 0,\n      height: 0,\n      totalIn: 0,\n      totalOut: 0,\n    })\n    return idx\n  }\n\n  // Check if series names contain arrow notation\n  const hasArrows = data.series.some(s => s.name.includes('→') || s.name.includes('->'))\n\n  if (hasArrows) {\n    // Format: each series is a flow \"Source → Target\"\n    for (const series of data.series) {\n      const parts = series.name.split(/\\s*(?:→|->)\\s*/)\n      if (parts.length < 2) continue\n      const srcName = parts[0]!.trim()\n      const tgtName = parts[1]!.trim()\n      const value = series.values[0] ?? 0\n      if (value <= 0) continue\n\n      const src = getOrCreateNode(srcName)\n      const tgt = getOrCreateNode(tgtName)\n      sankeyLinks.push({ source: src, target: tgt, value, sy: 0, ty: 0, width: 0 })\n      sankeyNodes[src]!.totalOut += value\n      sankeyNodes[tgt]!.totalIn += value\n    }\n  } else {\n    // Format: adjacency matrix. labels = node names, series[i].values[j] = flow i→j\n    for (let i = 0; i < data.labels.length; i++) {\n      getOrCreateNode(String(data.labels[i]))\n    }\n    for (let si = 0; si < data.series.length; si++) {\n      for (let j = 0; j < data.series[si]!.values.length; j++) {\n        const value = data.series[si]!.values[j]!\n        if (value <= 0 || si === j) continue\n        if (si >= sankeyNodes.length || j >= sankeyNodes.length) continue\n        sankeyLinks.push({ source: si, target: j, value, sy: 0, ty: 0, width: 0 })\n        sankeyNodes[si]!.totalOut += value\n        sankeyNodes[j]!.totalIn += value\n      }\n    }\n  }\n\n  return { sankeyNodes, sankeyLinks }\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\nfunction layoutColumns(\n  nodes: SankeyNode[],\n  links: SankeyLink[],\n  _area: { width: number; height: number },\n): number[] {\n  // Assign columns via topological ordering (longest path from source)\n  const adj = new Map<number, number[]>()\n  const inDegree = new Map<number, number>()\n\n  for (const n of nodes) {\n    adj.set(n.index, [])\n    inDegree.set(n.index, 0)\n  }\n  for (const l of links) {\n    adj.get(l.source)!.push(l.target)\n    inDegree.set(l.target, (inDegree.get(l.target) ?? 0) + 1)\n  }\n\n  // BFS for column assignment\n  const queue: number[] = []\n  for (const n of nodes) {\n    if ((inDegree.get(n.index) ?? 0) === 0) {\n      n.column = 0\n      queue.push(n.index)\n    }\n  }\n\n  while (queue.length > 0) {\n    const idx = queue.shift()!\n    const node = nodes[idx]!\n    for (const tgt of adj.get(idx)!) {\n      const tgtNode = nodes[tgt]!\n      tgtNode.column = Math.max(tgtNode.column, node.column + 1)\n      // Only add to queue once all predecessors processed\n      const allPredsDone = links\n        .filter(l => l.target === tgt)\n        .every(l => nodes[l.source]!.column >= 0)\n      if (allPredsDone && !queue.includes(tgt)) {\n        queue.push(tgt)\n      }\n    }\n  }\n\n  // Handle any unassigned nodes (cycles or disconnected)\n  for (const n of nodes) {\n    if (n.column < 0) n.column = 0\n  }\n\n  // Set initial heights proportional to flow\n  for (const n of nodes) {\n    n.height = Math.max(n.totalIn, n.totalOut, 1)\n  }\n\n  // Get unique columns sorted\n  const cols = [...new Set(nodes.map(n => n.column))].sort((a, b) => a - b)\n  return cols\n}\n\nfunction getNodeX(\n  node: SankeyNode,\n  columns: number[],\n  area: { x: number; width: number },\n  nodeWidth: number,\n): number {\n  const maxCol = Math.max(...columns, 1)\n  if (maxCol === 0) return area.x\n  const usableWidth = area.width - nodeWidth\n  return area.x + (node.column / maxCol) * usableWidth\n}\n\nfunction computeLinkPositions(nodes: SankeyNode[], links: SankeyLink[]): void {\n  // Total flow for normalization\n  const sourceOffsets = new Map<number, number>()\n  const targetOffsets = new Map<number, number>()\n\n  for (const n of nodes) {\n    sourceOffsets.set(n.index, 0)\n    targetOffsets.set(n.index, 0)\n  }\n\n  // Sort links by target position for visual clarity\n  links.sort((a, b) => {\n    const na = nodes[a.target]!\n    const nb = nodes[b.target]!\n    return na.y - nb.y || na.column - nb.column\n  })\n\n  for (const link of links) {\n    const src = nodes[link.source]!\n    const tgt = nodes[link.target]!\n\n    const srcTotal = Math.max(src.totalOut, 1)\n    const tgtTotal = Math.max(tgt.totalIn, 1)\n\n    link.width = (link.value / srcTotal) * src.height\n    const tgtWidth = (link.value / tgtTotal) * tgt.height\n\n    link.sy = sourceOffsets.get(link.source)!\n    link.ty = targetOffsets.get(link.target)!\n\n    sourceOffsets.set(link.source, link.sy + link.width)\n    targetOffsets.set(link.target, link.ty + tgtWidth)\n  }\n}\n","import { PathBuilder } from '../render/tree'\n\n/**\n * Build a rounded annular sector (pie/donut slice) SVG path string.\n *\n * Supports different angular offsets at inner vs outer radius for uniform\n * pixel-width gaps between slices.\n *\n * @param cx - Center x\n * @param cy - Center y\n * @param outerR - Outer radius\n * @param innerR - Inner radius (0 for full pie, >0 for donut)\n * @param outerStart - Start angle on outer arc (radians)\n * @param outerEnd - End angle on outer arc (radians)\n * @param innerStart - Start angle on inner arc (radians)\n * @param innerEnd - End angle on inner arc (radians)\n * @param cornerRadius - Corner rounding radius in px\n */\nexport function roundedSlicePath(\n  cx: number, cy: number,\n  outerR: number, innerR: number,\n  outerStart: number, outerEnd: number,\n  innerStart: number, innerEnd: number,\n  cornerRadius: number,\n): string {\n  const pb = new PathBuilder()\n  const outerSliceAngle = outerEnd - outerStart\n  const innerSliceAngle = innerEnd - innerStart\n  const radialThickness = outerR - innerR\n  const outerArcLen = outerSliceAngle * outerR\n  const innerArcLen = innerSliceAngle * innerR\n\n  // Separate corner radii for outer and inner edges.\n  // Inner corners need aggressive clamping — when innerR is small, the angular\n  // span of a corner becomes huge relative to the slice, causing path distortion.\n  const outerCr = Math.min(\n    cornerRadius,\n    radialThickness / 2,\n    outerArcLen / 4,\n  )\n  // Skip inner rounding entirely when inner radius is too small (<20px)\n  // — the angular span of any rounding would dominate the inner edge.\n  const innerCr = innerR >= 20\n    ? Math.min(\n        cornerRadius,\n        radialThickness / 2,\n        innerArcLen / 4,\n        innerR * 0.25,\n      )\n    : 0\n\n  if (outerCr < 0.5 && innerCr < 0.5) {\n    // No rounding — standard path with per-radius angles\n    const x1o = cx + outerR * Math.cos(outerStart)\n    const y1o = cy + outerR * Math.sin(outerStart)\n    const x2o = cx + outerR * Math.cos(outerEnd)\n    const y2o = cy + outerR * Math.sin(outerEnd)\n    const x1i = cx + innerR * Math.cos(innerEnd)\n    const y1i = cy + innerR * Math.sin(innerEnd)\n    const x2i = cx + innerR * Math.cos(innerStart)\n    const y2i = cy + innerR * Math.sin(innerStart)\n\n    pb.moveTo(x1o, y1o)\n    pb.arc(outerR, outerR, 0, outerSliceAngle > Math.PI, true, x2o, y2o)\n    pb.lineTo(x1i, y1i)\n    if (innerR > 0) {\n      pb.arc(innerR, innerR, 0, innerSliceAngle > Math.PI, false, x2i, y2i)\n    }\n    pb.close()\n    return pb.build()\n  }\n\n  // Angular offsets for rounding on each arc (separate for outer/inner)\n  const outerCrAngle = outerCr / outerR\n  const innerCrAngle = innerR > 0 && innerCr > 0.5 ? innerCr / innerR : 0\n\n  // Outer arc inset by corner angles\n  const oa1 = outerStart + outerCrAngle\n  const oa2 = outerEnd - outerCrAngle\n  // Inner arc inset by corner angles (reverse direction)\n  const ia1 = innerEnd - innerCrAngle\n  const ia2 = innerStart + innerCrAngle\n\n  // -- Corner 1: outer-start (start radial meets outer arc) --\n  pb.moveTo(\n    cx + (outerR - outerCr) * Math.cos(outerStart),\n    cy + (outerR - outerCr) * Math.sin(outerStart),\n  )\n  if (outerCr >= 0.5) {\n    pb.quadTo(\n      cx + outerR * Math.cos(outerStart),\n      cy + outerR * Math.sin(outerStart),\n      cx + outerR * Math.cos(oa1),\n      cy + outerR * Math.sin(oa1),\n    )\n  }\n\n  // -- Outer arc from oa1 to oa2 --\n  if (oa2 > oa1) {\n    pb.arc(outerR, outerR, 0, (oa2 - oa1) > Math.PI, true,\n      cx + outerR * Math.cos(oa2),\n      cy + outerR * Math.sin(oa2),\n    )\n  }\n\n  // -- Corner 2: outer-end (outer arc meets end radial) --\n  if (outerCr >= 0.5) {\n    pb.quadTo(\n      cx + outerR * Math.cos(outerEnd),\n      cy + outerR * Math.sin(outerEnd),\n      cx + (outerR - outerCr) * Math.cos(outerEnd),\n      cy + (outerR - outerCr) * Math.sin(outerEnd),\n    )\n  }\n\n  // -- Inner edge --\n  if (innerCr >= 0.5 && innerR > 0) {\n    // Line down to inner-end corner\n    pb.lineTo(\n      cx + (innerR + innerCr) * Math.cos(innerEnd),\n      cy + (innerR + innerCr) * Math.sin(innerEnd),\n    )\n\n    // Corner 3: inner-end (end radial meets inner arc)\n    pb.quadTo(\n      cx + innerR * Math.cos(innerEnd),\n      cy + innerR * Math.sin(innerEnd),\n      cx + innerR * Math.cos(ia1),\n      cy + innerR * Math.sin(ia1),\n    )\n\n    // Inner arc from ia1 to ia2 (reverse)\n    if (ia1 > ia2) {\n      pb.arc(innerR, innerR, 0, (ia1 - ia2) > Math.PI, false,\n        cx + innerR * Math.cos(ia2),\n        cy + innerR * Math.sin(ia2),\n      )\n    }\n\n    // Corner 4: inner-start (inner arc meets start radial)\n    pb.quadTo(\n      cx + innerR * Math.cos(innerStart),\n      cy + innerR * Math.sin(innerStart),\n      cx + (innerR + innerCr) * Math.cos(innerStart),\n      cy + (innerR + innerCr) * Math.sin(innerStart),\n    )\n  } else if (innerR > 0) {\n    // No inner rounding — sharp inner corners\n    pb.lineTo(\n      cx + innerR * Math.cos(innerEnd),\n      cy + innerR * Math.sin(innerEnd),\n    )\n    pb.arc(innerR, innerR, 0, innerSliceAngle > Math.PI, false,\n      cx + innerR * Math.cos(innerStart),\n      cy + innerR * Math.sin(innerStart),\n    )\n  }\n\n  pb.close()\n  return pb.build()\n}\n\n/**\n * Compute angular offsets for a uniform pixel gap at different radii.\n * Returns the padded start/end angles for both outer and inner arcs.\n */\nexport function uniformGapAngles(\n  startAngle: number, endAngle: number,\n  outerR: number, innerR: number,\n  gapPx: number,\n): { outerStart: number; outerEnd: number; innerStart: number; innerEnd: number } {\n  const halfGap = gapPx / 2\n  const outerPad = halfGap / outerR\n  const innerPad = innerR > 0 ? halfGap / innerR : 0\n  return {\n    outerStart: startAngle + outerPad,\n    outerEnd: endAngle - outerPad,\n    innerStart: startAngle + innerPad,\n    innerEnd: endAngle - innerPad,\n  }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, text } from '../../render/tree'\nimport { roundedSlicePath } from '../../utils/slice-path'\n\n/**\n * Sunburst chart — hierarchical radial visualization.\n *\n * Data convention:\n * - labels: leaf node names\n * - series[0].values: leaf values (sizes)\n * - Hierarchy is encoded via label separators: \"A/B/C\" means root→A→B→C\n *   If no separators, falls back to flat ring layout (single ring).\n *\n * The chart draws concentric rings from center outward, one ring per depth level.\n */\n\ninterface SunburstNode {\n  name: string\n  fullPath: string\n  value: number\n  children: SunburstNode[]\n  depth: number\n  startAngle: number\n  endAngle: number\n  // Computed during layout\n  totalValue: number\n}\n\nexport const sunburstChartType = defineChartType({\n  type: 'sunburst',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    // Build tree from labels\n    const root = buildTree(data.labels, series.values)\n    if (root.totalValue === 0) return nodes\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const maxRadius = Math.min(area.width, area.height) / 2 - 4\n    const innerRadius = maxRadius * 0.15\n\n    // Compute max depth for ring sizing\n    const maxDepth = getMaxDepth(root)\n    const ringWidth = (maxRadius - innerRadius) / Math.max(maxDepth, 1)\n\n    // Layout angles recursively\n    layoutAngles(root, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2)\n\n    // Render all non-root nodes\n    let colorIdx = 0\n    const renderNode = (node: SunburstNode, parentColorIdx: number) => {\n      if (node.depth === 0) {\n        // Root — render children with cycling colors\n        for (let i = 0; i < node.children.length; i++) {\n          renderNode(node.children[i]!, i)\n        }\n        return\n      }\n\n      const ci = node.depth === 1 ? parentColorIdx : parentColorIdx\n      const color = options.colors[ci % options.colors.length]!\n      const r0 = innerRadius + (node.depth - 1) * ringWidth\n      const r1 = r0 + ringWidth - 1 // 1px gap between rings\n\n      const sliceAngle = node.endAngle - node.startAngle\n      if (sliceAngle < 0.005) return // Skip tiny slices\n\n      // Uniform pixel gap: different angular offsets at different radii\n      const gapPx = 3\n      const halfGap = gapPx / 2\n      const outerPadAngle = halfGap / r1\n      const innerPadAngle = r0 > 0 ? halfGap / r0 : 0\n\n      if (sliceAngle < outerPadAngle * 2 + 0.005) return\n\n      const cr = Math.min(4, ringWidth * 0.2)\n\n      const d = roundedSlicePath(\n        cx, cy, r1, r0,\n        node.startAngle + outerPadAngle, node.endAngle - outerPadAngle,\n        node.startAngle + innerPadAngle, node.endAngle - innerPadAngle,\n        cr,\n      )\n\n      const opacity = 1 - (node.depth - 1) * 0.15\n\n      nodes.push(path(d, {\n        class: 'chartts-sunburst-sector',\n        fill: color,\n        fillOpacity: Math.max(0.4, opacity),\n        'data-series': 0,\n        'data-index': colorIdx,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${node.name}: ${node.totalValue}`,\n      }))\n\n      // Label for larger sectors\n      if (sliceAngle > 0.3 && ringWidth > 20) {\n        const midAngle = (node.startAngle + node.endAngle) / 2\n        const labelR = (r0 + r1) / 2\n        const lx = cx + labelR * Math.cos(midAngle)\n        const ly = cy + labelR * Math.sin(midAngle)\n\n        const fontSize = Math.min(theme.fontSizeSmall, ringWidth * 0.35)\n        nodes.push(text(lx, ly, node.name, {\n          class: 'chartts-sunburst-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n      }\n\n      colorIdx++\n\n      // Render children\n      for (let i = 0; i < node.children.length; i++) {\n        renderNode(node.children[i]!, parentColorIdx)\n      }\n    }\n\n    renderNode(root, 0)\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const maxRadius = Math.min(area.width, area.height) / 2 - 4\n    const innerRadius = maxRadius * 0.15\n\n    const dx = mx - cx\n    const dy = my - cy\n    const dist = Math.sqrt(dx * dx + dy * dy)\n\n    if (dist > maxRadius || dist < innerRadius) return null\n\n    const root = buildTree(data.labels, series.values)\n    const maxDepth = getMaxDepth(root)\n    const ringWidth = (maxRadius - innerRadius) / Math.max(maxDepth, 1)\n\n    layoutAngles(root, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2)\n\n    let angle = Math.atan2(dy, dx)\n    if (angle < -Math.PI / 2) angle += Math.PI * 2\n\n    // Find which ring (depth) the point is in\n    const depthFloat = (dist - innerRadius) / ringWidth\n    const depth = Math.floor(depthFloat) + 1\n\n    // Find sector at this depth and angle\n    const hit = findSector(root, depth, angle)\n    if (hit) {\n      return { seriesIndex: 0, pointIndex: hit, distance: 0, x: mx, y: my }\n    }\n\n    return null\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Tree building\n// ---------------------------------------------------------------------------\n\nfunction buildTree(labels: (string | number | Date)[], values: number[]): SunburstNode {\n  const root: SunburstNode = {\n    name: 'root', fullPath: '', value: 0,\n    children: [], depth: 0, startAngle: 0, endAngle: 0, totalValue: 0,\n  }\n\n  for (let i = 0; i < labels.length; i++) {\n    const label = String(labels[i] ?? `Item ${i}`)\n    const value = Math.abs(values[i] ?? 0)\n    if (value <= 0) continue\n\n    const parts = label.includes('/') ? label.split('/') : [label]\n    let current = root\n\n    for (let p = 0; p < parts.length; p++) {\n      const part = parts[p]!.trim()\n      let child = current.children.find(c => c.name === part)\n\n      if (!child) {\n        child = {\n          name: part,\n          fullPath: parts.slice(0, p + 1).join('/'),\n          value: 0,\n          children: [],\n          depth: p + 1,\n          startAngle: 0,\n          endAngle: 0,\n          totalValue: 0,\n        }\n        current.children.push(child)\n      }\n\n      if (p === parts.length - 1) {\n        child.value = value\n      }\n      current = child\n    }\n  }\n\n  // Compute totals bottom-up\n  computeTotals(root)\n\n  return root\n}\n\nfunction computeTotals(node: SunburstNode): number {\n  if (node.children.length === 0) {\n    node.totalValue = node.value\n    return node.totalValue\n  }\n  let sum = 0\n  for (const child of node.children) {\n    sum += computeTotals(child)\n  }\n  node.totalValue = Math.max(sum, node.value)\n  return node.totalValue\n}\n\nfunction layoutAngles(node: SunburstNode, start: number, end: number): void {\n  node.startAngle = start\n  node.endAngle = end\n\n  if (node.children.length === 0 || node.totalValue === 0) return\n\n  let current = start\n  for (const child of node.children) {\n    const fraction = child.totalValue / node.totalValue\n    const childEnd = current + fraction * (end - start)\n    layoutAngles(child, current, childEnd)\n    current = childEnd\n  }\n}\n\nfunction getMaxDepth(node: SunburstNode): number {\n  if (node.children.length === 0) return node.depth\n  let max = node.depth\n  for (const child of node.children) {\n    max = Math.max(max, getMaxDepth(child))\n  }\n  return max\n}\n\nfunction findSector(node: SunburstNode, targetDepth: number, angle: number): number | null {\n  if (node.depth === targetDepth) {\n    if (angle >= node.startAngle && angle < node.endAngle) {\n      return node.depth // Return something non-null to indicate a hit\n    }\n    return null\n  }\n\n  for (const child of node.children) {\n    if (angle >= child.startAngle && angle < child.endAngle) {\n      const result = findSector(child, targetDepth, angle)\n      if (result !== null) return result\n    }\n  }\n\n  return null\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, circle, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Tree chart — hierarchical node-link diagram.\n *\n * Data convention:\n * - labels: node names. Hierarchy encoded via \"Parent/Child/Grandchild\" separators.\n * - series[0].values: node values (sizes for circles, optional).\n *\n * Layout: top-to-bottom by default. Configurable via treeLayout option.\n */\n\ninterface TreeNode {\n  name: string\n  value: number\n  children: TreeNode[]\n  depth: number\n  index: number\n  // Computed during layout\n  x: number\n  y: number\n  leafCount: number\n}\n\nexport interface TreeOptions extends ResolvedOptions {\n  /** Layout direction. Default 'top-down'. */\n  treeLayout?: 'top-down' | 'left-right' | 'radial'\n  /** Node radius. Default 6. */\n  nodeRadius?: number\n  /** Show labels. Default true. */\n  showLabels?: boolean\n}\n\nexport const treeChartType = defineChartType({\n  type: 'tree',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const treeOpts = options as TreeOptions\n    const layout = treeOpts.treeLayout ?? 'top-down'\n    const nodeRadius = treeOpts.nodeRadius ?? 6\n    const showLabels = treeOpts.showLabels ?? true\n\n    // Build tree\n    const root = buildTree(data.labels, series.values)\n    if (!root) return nodes\n\n    // Compute leaf counts for spacing\n    computeLeafCounts(root)\n\n    // Layout nodes\n    const maxDepth = getMaxDepth(root)\n    const isHorizontal = layout === 'left-right'\n\n    if (isHorizontal) {\n      const levelWidth = area.width / Math.max(maxDepth + 1, 1)\n      layoutHorizontal(root, area.x, area.y, area.y + area.height, levelWidth)\n    } else {\n      const levelHeight = area.height / Math.max(maxDepth + 1, 1)\n      layoutVertical(root, area.y, area.x, area.x + area.width, levelHeight)\n    }\n\n    // Render edges first (below nodes)\n    const edgeNodes: RenderNode[] = []\n    renderEdges(root, edgeNodes, theme, isHorizontal)\n    nodes.push(...edgeNodes)\n\n    // Render nodes\n    let nodeIdx = 0\n    const renderTreeNode = (node: TreeNode) => {\n      const color = options.colors[node.depth % options.colors.length]!\n      const nodeGroup: RenderNode[] = []\n\n      nodeGroup.push(circle(node.x, node.y, nodeRadius, {\n        class: 'chartts-tree-node',\n        fill: color,\n        stroke: theme.background === 'transparent' ? '#fff' : theme.background,\n        strokeWidth: 1.5,\n        'data-series': 0,\n        'data-index': nodeIdx,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${node.name}: ${node.value}`,\n      }))\n\n      if (showLabels) {\n        const fontSize = theme.fontSizeSmall\n        let labelX: number, labelY: number\n        let anchor: 'start' | 'middle' | 'end'\n\n        if (isHorizontal) {\n          labelX = node.x\n          labelY = node.y - nodeRadius - 4\n          anchor = 'middle'\n        } else {\n          labelX = node.x + nodeRadius + 4\n          labelY = node.y\n          anchor = 'start'\n          // For root, put label above\n          if (node.depth === 0) {\n            labelX = node.x\n            labelY = node.y - nodeRadius - 4\n            anchor = 'middle'\n          }\n        }\n\n        nodeGroup.push(text(labelX, labelY, node.name, {\n          class: 'chartts-tree-label',\n          fill: theme.textColor,\n          textAnchor: anchor,\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n        }))\n      }\n\n      nodes.push(group(nodeGroup, {\n        class: `chartts-series chartts-series-${nodeIdx}`,\n        'data-series-name': node.name,\n      }))\n\n      nodeIdx++\n      for (const child of node.children) {\n        renderTreeNode(child)\n      }\n    }\n\n    renderTreeNode(root)\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const treeOpts = options as TreeOptions\n    const layout = treeOpts.treeLayout ?? 'top-down'\n    const nodeRadius = treeOpts.nodeRadius ?? 6\n    const hitRadius = nodeRadius + 5\n\n    const root = buildTree(data.labels, series.values)\n    if (!root) return null\n\n    computeLeafCounts(root)\n    const maxDepth = getMaxDepth(root)\n    const isHorizontal = layout === 'left-right'\n\n    if (isHorizontal) {\n      const levelWidth = area.width / Math.max(maxDepth + 1, 1)\n      layoutHorizontal(root, area.x, area.y, area.y + area.height, levelWidth)\n    } else {\n      const levelHeight = area.height / Math.max(maxDepth + 1, 1)\n      layoutVertical(root, area.y, area.x, area.x + area.width, levelHeight)\n    }\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n    let idx = 0\n\n    const checkNode = (node: TreeNode) => {\n      const dist = Math.sqrt((mx - node.x) ** 2 + (my - node.y) ** 2)\n      if (dist < bestDist && dist < hitRadius) {\n        bestDist = dist\n        best = { seriesIndex: 0, pointIndex: idx, distance: dist, x: node.x, y: node.y }\n      }\n      idx++\n      for (const child of node.children) {\n        checkNode(child)\n      }\n    }\n\n    checkNode(root)\n    return best\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Tree building\n// ---------------------------------------------------------------------------\n\nfunction buildTree(labels: (string | number | Date)[], values: number[]): TreeNode | null {\n  const root: TreeNode = {\n    name: 'Root', value: 0, children: [], depth: 0, index: 0,\n    x: 0, y: 0, leafCount: 0,\n  }\n\n  // Check if labels use \"/\" separators for hierarchy\n  const hasHierarchy = labels.some(l => String(l).includes('/'))\n\n  if (hasHierarchy) {\n    for (let i = 0; i < labels.length; i++) {\n      const parts = String(labels[i] ?? '').split('/')\n      const value = Math.abs(values[i] ?? 1)\n      let current = root\n\n      for (let p = 0; p < parts.length; p++) {\n        const part = parts[p]!.trim()\n        if (!part) continue\n\n        let child = current.children.find(c => c.name === part)\n        if (!child) {\n          child = {\n            name: part, value: 0, children: [], depth: current.depth + 1,\n            index: i, x: 0, y: 0, leafCount: 0,\n          }\n          current.children.push(child)\n        }\n        if (p === parts.length - 1) {\n          child.value = value\n        }\n        current = child\n      }\n    }\n  } else {\n    // Flat list — all labels are direct children of root\n    root.name = String(labels[0] ?? 'Root')\n    root.value = Math.abs(values[0] ?? 1)\n\n    for (let i = 1; i < labels.length; i++) {\n      root.children.push({\n        name: String(labels[i] ?? `Node ${i}`),\n        value: Math.abs(values[i] ?? 1),\n        children: [],\n        depth: 1,\n        index: i,\n        x: 0, y: 0, leafCount: 0,\n      })\n    }\n  }\n\n  if (root.children.length === 0 && labels.length > 0) {\n    // Single node\n    root.name = String(labels[0] ?? 'Root')\n    root.value = Math.abs(values[0] ?? 1)\n  }\n\n  return root\n}\n\nfunction computeLeafCounts(node: TreeNode): number {\n  if (node.children.length === 0) {\n    node.leafCount = 1\n    return 1\n  }\n  let count = 0\n  for (const child of node.children) {\n    count += computeLeafCounts(child)\n  }\n  node.leafCount = count\n  return count\n}\n\nfunction getMaxDepth(node: TreeNode): number {\n  if (node.children.length === 0) return node.depth\n  let max = node.depth\n  for (const child of node.children) {\n    max = Math.max(max, getMaxDepth(child))\n  }\n  return max\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\nfunction layoutVertical(\n  node: TreeNode, topY: number, leftX: number, rightX: number, levelHeight: number,\n): void {\n  node.y = topY + node.depth * levelHeight + levelHeight / 2\n  const totalLeaves = node.leafCount || 1\n  const slotWidth = (rightX - leftX) / totalLeaves\n\n  if (node.children.length === 0) {\n    node.x = leftX + slotWidth / 2\n    return\n  }\n\n  let currentX = leftX\n  for (const child of node.children) {\n    const childWidth = (child.leafCount / totalLeaves) * (rightX - leftX)\n    layoutVertical(child, topY, currentX, currentX + childWidth, levelHeight)\n    currentX += childWidth\n  }\n\n  // Center parent above children\n  const firstChild = node.children[0]!\n  const lastChild = node.children[node.children.length - 1]!\n  node.x = (firstChild.x + lastChild.x) / 2\n}\n\nfunction layoutHorizontal(\n  node: TreeNode, leftX: number, topY: number, bottomY: number, levelWidth: number,\n): void {\n  node.x = leftX + node.depth * levelWidth + levelWidth / 2\n  const totalLeaves = node.leafCount || 1\n  const slotHeight = (bottomY - topY) / totalLeaves\n\n  if (node.children.length === 0) {\n    node.y = topY + slotHeight / 2\n    return\n  }\n\n  let currentY = topY\n  for (const child of node.children) {\n    const childHeight = (child.leafCount / totalLeaves) * (bottomY - topY)\n    layoutHorizontal(child, leftX, currentY, currentY + childHeight, levelWidth)\n    currentY += childHeight\n  }\n\n  const firstChild = node.children[0]!\n  const lastChild = node.children[node.children.length - 1]!\n  node.y = (firstChild.y + lastChild.y) / 2\n}\n\n// ---------------------------------------------------------------------------\n// Rendering edges\n// ---------------------------------------------------------------------------\n\nfunction renderEdges(\n  node: TreeNode,\n  nodes: RenderNode[],\n  theme: RenderContext['theme'],\n  isHorizontal: boolean,\n): void {\n  for (const child of node.children) {\n    const pb = new PathBuilder()\n    if (isHorizontal) {\n      const midX = (node.x + child.x) / 2\n      pb.moveTo(node.x, node.y)\n      pb.curveTo(midX, node.y, midX, child.y, child.x, child.y)\n    } else {\n      const midY = (node.y + child.y) / 2\n      pb.moveTo(node.x, node.y)\n      pb.curveTo(node.x, midY, child.x, midY, child.x, child.y)\n    }\n\n    nodes.push(path(pb.build(), {\n      class: 'chartts-tree-edge',\n      stroke: theme.gridColor,\n      strokeWidth: 1.5,\n      fill: 'none',\n    }))\n\n    renderEdges(child, nodes, theme, isHorizontal)\n  }\n}\n","import type { PreparedData, ResolvedOptions } from '../../types'\nimport type { GraphNode, GraphEdge, GraphOptions, NodeShape } from './types'\n\n/**\n * Parse graph data from three possible input formats into internal\n * GraphNode[] and GraphEdge[] arrays.\n *\n * Auto-detection order:\n * 1. Rich format — options contain `.nodes` or `.edges`\n * 2. Arrow notation — any series name contains `→` or `->`\n * 3. Adjacency matrix — fallback\n */\nexport function parseGraphData(\n  data: PreparedData,\n  options: ResolvedOptions,\n): { graphNodes: GraphNode[]; graphEdges: GraphEdge[] } {\n  const opts = options as GraphOptions\n  const defaultShape: NodeShape = opts.nodeShape ?? 'rect'\n\n  // --- 1. Rich format ---\n  if (opts.nodes || opts.edges) {\n    return parseRichFormat(data, opts, defaultShape)\n  }\n\n  // --- 2. Arrow notation ---\n  const hasArrow = data.series.some(\n    (s) => s.name.includes('→') || s.name.includes('->'),\n  )\n  if (hasArrow) {\n    return parseArrowNotation(data, defaultShape)\n  }\n\n  // --- 3. Adjacency matrix ---\n  return parseAdjacencyMatrix(data, defaultShape)\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction makeNode(\n  id: string,\n  label: string,\n  index: number,\n  value: number,\n  shape: NodeShape,\n  color: string | null,\n  pin: { x: number; y: number } | null,\n): GraphNode {\n  return {\n    id,\n    label,\n    index,\n    value,\n    shape,\n    color,\n    pin,\n    x: 0,\n    y: 0,\n    vx: 0,\n    vy: 0,\n    width: 0,\n    height: 0,\n  }\n}\n\nfunction makeEdge(\n  source: number,\n  target: number,\n  weight: number,\n  label: string | null,\n  style: 'solid' | 'dashed' | 'dotted',\n  color: string | null,\n): GraphEdge {\n  return { source, target, weight, label, style, color }\n}\n\n// ---------------------------------------------------------------------------\n// Rich format\n// ---------------------------------------------------------------------------\n\nfunction parseRichFormat(\n  _data: PreparedData,\n  opts: GraphOptions,\n  defaultShape: NodeShape,\n): { graphNodes: GraphNode[]; graphEdges: GraphEdge[] } {\n  const graphNodes: GraphNode[] = []\n  const idToIndex = new Map<string, number>()\n\n  // Create nodes from opts.nodes\n  if (opts.nodes) {\n    for (const nodeDef of opts.nodes) {\n      const idx = graphNodes.length\n      idToIndex.set(nodeDef.id, idx)\n      graphNodes.push(\n        makeNode(\n          nodeDef.id,\n          nodeDef.label ?? nodeDef.id,\n          idx,\n          1,\n          nodeDef.shape ?? defaultShape,\n          nodeDef.color ?? null,\n          nodeDef.pin ?? null,\n        ),\n      )\n    }\n  }\n\n  const graphEdges: GraphEdge[] = []\n\n  if (opts.edges) {\n    for (const edgeDef of opts.edges) {\n      // Auto-create source node if not declared\n      if (!idToIndex.has(edgeDef.source)) {\n        const idx = graphNodes.length\n        idToIndex.set(edgeDef.source, idx)\n        graphNodes.push(\n          makeNode(edgeDef.source, edgeDef.source, idx, 1, defaultShape, null, null),\n        )\n      }\n\n      // Auto-create target node if not declared\n      if (!idToIndex.has(edgeDef.target)) {\n        const idx = graphNodes.length\n        idToIndex.set(edgeDef.target, idx)\n        graphNodes.push(\n          makeNode(edgeDef.target, edgeDef.target, idx, 1, defaultShape, null, null),\n        )\n      }\n\n      const srcIdx = idToIndex.get(edgeDef.source)!\n      const tgtIdx = idToIndex.get(edgeDef.target)!\n\n      graphEdges.push(\n        makeEdge(\n          srcIdx,\n          tgtIdx,\n          edgeDef.weight ?? 1,\n          edgeDef.label ?? null,\n          edgeDef.style ?? 'solid',\n          edgeDef.color ?? null,\n        ),\n      )\n    }\n  }\n\n  return { graphNodes, graphEdges }\n}\n\n// ---------------------------------------------------------------------------\n// Arrow notation\n// ---------------------------------------------------------------------------\n\nconst ARROW_RE = /\\s*(?:→|->)\\s*/\n\nfunction parseArrowNotation(\n  data: PreparedData,\n  defaultShape: NodeShape,\n): { graphNodes: GraphNode[]; graphEdges: GraphEdge[] } {\n  const graphNodes: GraphNode[] = []\n  const nameToIndex = new Map<string, number>()\n  const graphEdges: GraphEdge[] = []\n\n  function getOrCreateNode(name: string): number {\n    let idx = nameToIndex.get(name)\n    if (idx !== undefined) return idx\n    idx = graphNodes.length\n    nameToIndex.set(name, idx)\n    graphNodes.push(makeNode(name, name, idx, 0, defaultShape, null, null))\n    return idx\n  }\n\n  for (const series of data.series) {\n    const parts = series.name.split(ARROW_RE)\n    if (parts.length < 2) continue\n\n    const srcName = parts[0]!\n    const tgtName = parts[1]!\n    const weight = series.values[0] ?? 1\n\n    const srcIdx = getOrCreateNode(srcName)\n    const tgtIdx = getOrCreateNode(tgtName)\n\n    // Accumulate value from edge weights\n    graphNodes[srcIdx]!.value += weight\n    graphNodes[tgtIdx]!.value += weight\n\n    graphEdges.push(makeEdge(srcIdx, tgtIdx, weight, null, 'solid', null))\n  }\n\n  return { graphNodes, graphEdges }\n}\n\n// ---------------------------------------------------------------------------\n// Adjacency matrix\n// ---------------------------------------------------------------------------\n\nfunction parseAdjacencyMatrix(\n  data: PreparedData,\n  defaultShape: NodeShape,\n): { graphNodes: GraphNode[]; graphEdges: GraphEdge[] } {\n  const graphNodes: GraphNode[] = []\n\n  // Create nodes from labels\n  for (let i = 0; i < data.labels.length; i++) {\n    const name = String(data.labels[i])\n    const value = Math.abs(data.series[0]?.values[i] ?? 1)\n    graphNodes.push(makeNode(name, name, i, value, defaultShape, null, null))\n  }\n\n  const graphEdges: GraphEdge[] = []\n\n  // If series count > 1 and matches label count, treat as adjacency matrix\n  if (data.series.length > 1 && data.series.length === data.labels.length) {\n    for (let i = 0; i < data.series.length; i++) {\n      const row = data.series[i]!\n      for (let j = 0; j < row.values.length; j++) {\n        const weight = row.values[j] ?? 0\n        if (weight > 0) {\n          graphEdges.push(makeEdge(i, j, weight, null, 'solid', null))\n        }\n      }\n    }\n  }\n\n  return { graphNodes, graphEdges }\n}\n","import type { NodeShape } from './types'\n\nconst CHAR_WIDTH_RATIO = 0.6\nconst PADDING_H = 16\nconst PADDING_V = 10\n\n/**\n * Heuristic text measurement (no DOM access).\n * Returns the bounding box needed for the node shape to contain the label.\n */\nexport function measureNodeSize(\n  label: string,\n  fontSize: number,\n  shape: NodeShape,\n): { width: number; height: number } {\n  const charWidth = fontSize * CHAR_WIDTH_RATIO\n  const textWidth = label.length * charWidth\n  const textHeight = fontSize * 1.2\n\n  let w = textWidth + PADDING_H * 2\n  let h = textHeight + PADDING_V * 2\n\n  // Enforce minimums\n  w = Math.max(w, 40)\n  h = Math.max(h, 28)\n\n  switch (shape) {\n    case 'circle': {\n      // Circle must contain the text bbox\n      const d = Math.sqrt(w * w + h * h)\n      return { width: d, height: d }\n    }\n    case 'diamond': {\n      // Diamond needs ~1.4x bbox dimensions\n      return { width: w * 1.45, height: h * 1.45 }\n    }\n    case 'hexagon': {\n      // Hexagon needs slightly wider to contain text\n      return { width: w * 1.25, height: h * 1.15 }\n    }\n    case 'stadium':\n    case 'rect':\n    default:\n      return { width: w, height: h }\n  }\n}\n","import type { RenderNode, ThemeConfig } from '../../types'\nimport type { GraphNode } from './types'\nimport { path, rect, circle, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n// ---------------------------------------------------------------------------\n// renderNodeShape — returns [shape, label] RenderNodes for a graph node\n// ---------------------------------------------------------------------------\n\nexport function renderNodeShape(\n  node: GraphNode,\n  color: string,\n  theme: ThemeConfig,\n): RenderNode[] {\n  const cx = node.x\n  const cy = node.y\n  const w = node.width\n  const h = node.height\n\n  const baseAttrs = {\n    class: 'chartts-graph-node',\n    fill: color,\n    fillOpacity: 0.85,\n    stroke: color,\n    strokeWidth: 1.5,\n    'data-series': node.index,\n    'data-index': 0,\n    tabindex: 0,\n    role: 'img',\n    ariaLabel: `${node.label}: ${node.value}`,\n  } as const\n\n  let shapeNode: RenderNode\n\n  switch (node.shape) {\n    case 'circle': {\n      const r = Math.max(w, h) / 2\n      shapeNode = circle(cx, cy, r, { ...baseAttrs })\n      break\n    }\n\n    case 'diamond': {\n      const pb = new PathBuilder()\n      pb.moveTo(cx, cy - h / 2)\n        .lineTo(cx + w / 2, cy)\n        .lineTo(cx, cy + h / 2)\n        .lineTo(cx - w / 2, cy)\n        .close()\n      shapeNode = path(pb.build(), { ...baseAttrs })\n      break\n    }\n\n    case 'hexagon': {\n      const rx = w / 2\n      const ry = h / 2\n      const pb = new PathBuilder()\n      // flat-top hexagon: vertices at 0°, 60°, 120°, 180°, 240°, 300°\n      for (let i = 0; i < 6; i++) {\n        const angle = (Math.PI / 180) * (i * 60)\n        const px = cx + rx * Math.cos(angle)\n        const py = cy + ry * Math.sin(angle)\n        if (i === 0) pb.moveTo(px, py)\n        else pb.lineTo(px, py)\n      }\n      pb.close()\n      shapeNode = path(pb.build(), { ...baseAttrs })\n      break\n    }\n\n    case 'stadium': {\n      shapeNode = rect(cx - w / 2, cy - h / 2, w, h, {\n        ...baseAttrs,\n        rx: h / 2,\n      })\n      break\n    }\n\n    // 'rect' is the default\n    default: {\n      shapeNode = rect(cx - w / 2, cy - h / 2, w, h, {\n        ...baseAttrs,\n        rx: 8,\n      })\n      break\n    }\n  }\n\n  const labelNode = text(cx, cy, node.label, {\n    class: 'chartts-graph-label',\n    fill: '#fff',\n    textAnchor: 'middle',\n    dominantBaseline: 'central',\n    fontSize: theme.fontSizeSmall,\n    fontFamily: theme.fontFamily,\n    fontWeight: 600,\n  })\n\n  return [shapeNode, labelNode]\n}\n\n// ---------------------------------------------------------------------------\n// clipToNodeBoundary — find the point on a shape boundary at given angle\n// ---------------------------------------------------------------------------\n\n/** Small outward padding so edges don't touch the shape directly. */\nconst PAD = 3\n\nexport function clipToNodeBoundary(\n  node: GraphNode,\n  angle: number,\n): { x: number; y: number } {\n  const cx = node.x\n  const cy = node.y\n  const w = node.width\n  const h = node.height\n  const cos = Math.cos(angle)\n  const sin = Math.sin(angle)\n\n  let bx: number\n  let by: number\n\n  switch (node.shape) {\n    case 'circle': {\n      const r = Math.max(w, h) / 2\n      bx = cx + r * cos\n      by = cy + r * sin\n      break\n    }\n\n    case 'diamond': {\n      // Diamond has 4 edges.  The half-extents along x/y are w/2 and h/2.\n      // For a diamond with vertices at (0,-h/2), (w/2,0), (0,h/2), (-w/2,0)\n      // the boundary along direction (cos,sin) can be found via the Minkowski\n      // support function.  For a rhombus the implicit equation is\n      //   |x|/(w/2) + |y|/(h/2) = 1\n      // so the ray t*(cos,sin) hits the boundary at\n      //   t = 1 / (|cos|/(w/2) + |sin|/(h/2))\n      const hw = w / 2\n      const hh = h / 2\n      const t = 1 / (Math.abs(cos) / hw + Math.abs(sin) / hh)\n      bx = cx + t * cos\n      by = cy + t * sin\n      break\n    }\n\n    case 'hexagon': {\n      // Flat-top hexagon with rx = w/2, ry = h/2.\n      // Vertices at angles 0°,60°,120°,180°,240°,300°.\n      // Find which edge segment the ray intersects and compute intersection.\n      const rx = w / 2\n      const ry = h / 2\n      const pt = hexBoundary(cx, cy, rx, ry, angle, cos, sin)\n      bx = pt.x\n      by = pt.y\n      break\n    }\n\n    // rect and stadium share the same rectangular bounding box logic\n    default: {\n      const hw = w / 2\n      const hh = h / 2\n      const cornerAngle = Math.atan2(hh, hw)\n      // Normalize angle into [0, 2π)\n      let a = ((angle % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI)\n\n      if (a < cornerAngle || a >= 2 * Math.PI - cornerAngle) {\n        // hits right edge\n        const t = hw / Math.abs(cos)\n        bx = cx + hw\n        by = cy + t * sin\n      } else if (a < Math.PI - cornerAngle) {\n        // hits bottom edge\n        const t = hh / Math.abs(sin)\n        bx = cx + t * cos\n        by = cy + hh\n      } else if (a < Math.PI + cornerAngle) {\n        // hits left edge\n        const t = hw / Math.abs(cos)\n        bx = cx - hw\n        by = cy + t * sin\n      } else {\n        // hits top edge\n        const t = hh / Math.abs(sin)\n        bx = cx + t * cos\n        by = cy - hh\n      }\n      break\n    }\n  }\n\n  // Apply outward padding\n  bx += PAD * cos\n  by += PAD * sin\n\n  return { x: bx, y: by }\n}\n\n// ---------------------------------------------------------------------------\n// Hexagon boundary helper\n// ---------------------------------------------------------------------------\n\nfunction hexBoundary(\n  cx: number,\n  cy: number,\n  rx: number,\n  ry: number,\n  _angle: number,\n  cos: number,\n  sin: number,\n): { x: number; y: number } {\n  // Compute the 6 vertices of the flat-top hexagon\n  const verts: Array<{ x: number; y: number }> = []\n  for (let i = 0; i < 6; i++) {\n    const a = (Math.PI / 180) * (i * 60)\n    verts.push({ x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) })\n  }\n\n  // Ray from center: P(t) = (cx + t*cos, cy + t*sin), t > 0\n  // Test intersection with each of the 6 edges\n  let bestT = Infinity\n  let bestPt = { x: cx + rx * cos, y: cy + ry * sin } // fallback\n\n  for (let i = 0; i < 6; i++) {\n    const v0 = verts[i]!\n    const v1 = verts[(i + 1) % 6]!\n\n    // Edge: Q(s) = v0 + s*(v1 - v0), s in [0,1]\n    // Solve: (cx + t*cos, cy + t*sin) = (v0.x + s*dx, v0.y + s*dy)\n    const dx = v1.x - v0.x\n    const dy = v1.y - v0.y\n\n    const denom = cos * dy - sin * dx\n    if (Math.abs(denom) < 1e-12) continue // parallel\n\n    const t = ((v0.x - cx) * dy - (v0.y - cy) * dx) / denom\n    const s = cos !== 0\n      ? ((cx + t * cos) - v0.x) / dx\n      : ((cy + t * sin) - v0.y) / dy\n\n    if (t > 1e-6 && s >= -1e-6 && s <= 1 + 1e-6 && t < bestT) {\n      bestT = t\n      bestPt = { x: cx + t * cos, y: cy + t * sin }\n    }\n  }\n\n  return bestPt\n}\n","import type { RenderNode, ThemeConfig } from '../../types'\nimport type { GraphNode, GraphEdge, GraphOptions } from './types'\nimport { path, rect, text, line } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\nimport { clipToNodeBoundary } from './shapes'\n\n// ---------------------------------------------------------------------------\n// Arrowhead helper\n// ---------------------------------------------------------------------------\n\nfunction renderArrowhead(\n  tipX: number,\n  tipY: number,\n  angle: number,\n  size: number,\n  color: string,\n): RenderNode {\n  const cosA = Math.cos(angle)\n  const sinA = Math.sin(angle)\n\n  // Base center (back from the tip along the edge direction)\n  const baseX = tipX - cosA * size\n  const baseY = tipY - sinA * size\n\n  // Perpendicular offset\n  const perpX = -sinA * size * 0.4\n  const perpY = cosA * size * 0.4\n\n  const leftX = baseX + perpX\n  const leftY = baseY + perpY\n  const rightX = baseX - perpX\n  const rightY = baseY - perpY\n\n  const pb = new PathBuilder()\n  pb.moveTo(tipX, tipY)\n    .lineTo(leftX, leftY)\n    .lineTo(rightX, rightY)\n    .close()\n\n  return path(pb.build(), {\n    fill: color,\n    class: 'chartts-graph-arrow',\n  })\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport function renderEdges(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  options: GraphOptions,\n  theme: ThemeConfig,\n): RenderNode[] {\n  const result: RenderNode[] = []\n\n  // Build a map of (source,target) pair counts so we can alternate curve\n  // direction for multi-edges between the same pair.\n  const pairIndex = new Map<string, number>()\n\n  for (const edge of edges) {\n    const src = nodes[edge.source]\n    const tgt = nodes[edge.target]\n    if (!src || !tgt) continue\n\n    // --- 1. Connection points ------------------------------------------\n    const angle = Math.atan2(tgt.y - src.y, tgt.x - src.x)\n    const start = clipToNodeBoundary(src, angle)\n    const end = clipToNodeBoundary(tgt, angle + Math.PI)\n\n    // Edge attrs shared between straight / curved\n    const edgeColor = edge.color ?? theme.gridColor\n    const edgeAttrs = {\n      class: 'chartts-graph-edge',\n      stroke: edgeColor,\n      strokeWidth: Math.max(1, Math.min(3, edge.weight * 0.5)),\n      strokeDasharray:\n        edge.style === 'dashed'\n          ? '8,4'\n          : edge.style === 'dotted'\n            ? '2,4'\n            : undefined,\n      opacity: 0.6,\n      fill: 'none',\n    }\n\n    // --- 2. Edge path ---------------------------------------------------\n    let arrowAngle = angle // angle at the target end for the arrowhead\n    let labelX = (start.x + end.x) / 2\n    let labelY = (start.y + end.y) / 2\n\n    if (options.edgeStyle === 'straight' || options.edgeStyle === undefined) {\n      // Default: straight line\n      result.push(line(start.x, start.y, end.x, end.y, edgeAttrs))\n    } else {\n      // Curved: quadratic bezier\n      const pairKey =\n        Math.min(edge.source, edge.target) +\n        ':' +\n        Math.max(edge.source, edge.target)\n      const idx = pairIndex.get(pairKey) ?? 0\n      pairIndex.set(pairKey, idx + 1)\n\n      // Alternate direction: even indices go one way, odd the other\n      const sign = idx % 2 === 0 ? 1 : -1\n\n      const offset = Math.max(edge.weight * 8, 15)\n\n      const mx = (start.x + end.x) / 2\n      const my = (start.y + end.y) / 2\n\n      // Perpendicular direction to the edge\n      const perpAngle = angle + Math.PI / 2\n      const cx = mx + Math.cos(perpAngle) * offset * sign\n      const cy = my + Math.sin(perpAngle) * offset * sign\n\n      const pb = new PathBuilder()\n      pb.moveTo(start.x, start.y).quadTo(cx, cy, end.x, end.y)\n\n      result.push(path(pb.build(), edgeAttrs))\n\n      // For curved edges the arrow should follow the last segment direction\n      // (from control point to end point)\n      arrowAngle = Math.atan2(end.y - cy, end.x - cx)\n\n      // Label at the midpoint of the quadratic bezier: Q(0.5) = 0.25*P0 + 0.5*CP + 0.25*P1\n      labelX = 0.25 * start.x + 0.5 * cx + 0.25 * end.x\n      labelY = 0.25 * start.y + 0.5 * cy + 0.25 * end.y\n    }\n\n    // --- 3. Arrowhead ---------------------------------------------------\n    if (options.arrows !== false) {\n      const arrowSize = 8\n      result.push(renderArrowhead(end.x, end.y, arrowAngle, arrowSize, edgeColor))\n    }\n\n    // --- 4. Edge label --------------------------------------------------\n    if (edge.label != null) {\n      const lx = labelX\n      const ly = labelY\n\n      // Estimate label dimensions for background rect\n      const charWidth = (theme.fontSizeSmall - 1) * 0.6\n      const pw = edge.label.length * charWidth + 8\n      const ph = (theme.fontSizeSmall - 1) + 6\n\n      const bgFill =\n        theme.background === 'transparent' ? '#fff' : theme.background\n\n      result.push(\n        rect(lx - pw / 2, ly - ph / 2, pw, ph, {\n          fill: bgFill,\n          rx: 3,\n        }),\n      )\n\n      result.push(\n        text(lx, ly, edge.label, {\n          fill: theme.textMuted,\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize: theme.fontSizeSmall - 1,\n          fontFamily: theme.fontFamily,\n        }),\n      )\n    }\n  }\n\n  return result\n}\n","import type { GraphNode, GraphEdge, LayoutDirection } from './types'\n\n/**\n * Hierarchical layout — simplified Sugiyama algorithm.\n *\n * Steps:\n * 1. Layer assignment (longest-path from roots)\n * 2. Ordering (barycenter heuristic, 3 passes)\n * 3. Coordinate assignment (even distribution per layer)\n * 4. Direction mapping (TB / BT / LR / RL)\n *\n * Cycles are handled by detecting back-edges and temporarily reversing them\n * during layout, then restoring original direction.\n */\n\nexport interface HierarchyLayoutOpts {\n  area: { x: number; y: number; width: number; height: number }\n  direction: LayoutDirection\n}\n\nexport function hierarchyLayout(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  opts: HierarchyLayoutOpts,\n): void {\n  const n = nodes.length\n  if (n === 0) return\n\n  const { area, direction } = opts\n\n  // Build adjacency lists\n  const outgoing = new Array<number[]>(n)\n  const incoming = new Array<number[]>(n)\n  for (let i = 0; i < n; i++) {\n    outgoing[i] = []\n    incoming[i] = []\n  }\n\n  // Detect and break cycles via DFS\n  const edgesCopy = edges.map(e => ({ ...e }))\n  breakCycles(edgesCopy, n, outgoing, incoming)\n\n  // 1. Layer assignment (longest path from roots)\n  const layers = assignLayers(n, outgoing, incoming)\n\n  // 2. Ordering within layers (barycenter heuristic)\n  const layerGroups = groupByLayer(layers, n)\n  orderLayers(layerGroups, outgoing, incoming, 3)\n\n  // 3. Node-size-aware coordinate assignment\n  const maxLayer = Math.max(...layers, 0)\n  const layerCount = maxLayer + 1\n  const isVertical = direction === 'TB' || direction === 'BT'\n\n  // Compute the max \"thickness\" per layer (height for TB/BT, width for LR/RL)\n  const layerThickness: number[] = new Array(layerCount).fill(0)\n  for (let layer = 0; layer < layerCount; layer++) {\n    const grp = layerGroups[layer] ?? []\n    for (const idx of grp) {\n      const nd = nodes[idx]!\n      const thick = isVertical ? nd.height : nd.width\n      if (thick > layerThickness[layer]!) layerThickness[layer] = thick\n    }\n  }\n\n  // Total thickness of all layers + gaps between them\n  const gap = 24 // min gap between layer edges\n  const totalThickness = layerThickness.reduce((s, t) => s + t, 0) + gap * (layerCount - 1)\n  const availableThickness = isVertical ? area.height : area.width\n  // Scale factor if nodes are too tightly packed\n  const scale = totalThickness > availableThickness ? availableThickness / totalThickness : 1\n\n  // Compute cumulative layer center positions\n  const layerCenter: number[] = new Array(layerCount).fill(0)\n  // Center the layout within the available space\n  const usedThickness = totalThickness * scale\n  const offset = (availableThickness - usedThickness) / 2\n  let cursor = offset + (layerThickness[0]! * scale) / 2\n  layerCenter[0] = cursor\n  for (let layer = 1; layer < layerCount; layer++) {\n    cursor += (layerThickness[layer - 1]! * scale) / 2 + gap * scale + (layerThickness[layer]! * scale) / 2\n    layerCenter[layer] = cursor\n  }\n\n  // Reverse order for BT/RL\n  if (direction === 'BT' || direction === 'RL') {\n    layerCenter.reverse()\n  }\n\n  for (let layer = 0; layer <= maxLayer; layer++) {\n    const grp = layerGroups[layer] ?? []\n    if (grp.length === 0) continue\n\n    for (let pos = 0; pos < grp.length; pos++) {\n      const node = nodes[grp[pos]!]!\n\n      // Pinned nodes override layout\n      if (node.pin) {\n        node.x = area.x + node.pin.x * area.width\n        node.y = area.y + node.pin.y * area.height\n        continue\n      }\n\n      const posFrac = (pos + 1) / (grp.length + 1)\n      const layerPos = layerCenter[layer]!\n\n      switch (direction) {\n        case 'TB':\n        case 'BT':\n          node.x = area.x + posFrac * area.width\n          node.y = area.y + layerPos\n          break\n        case 'LR':\n        case 'RL':\n          node.x = area.x + layerPos\n          node.y = area.y + posFrac * area.height\n          break\n      }\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Cycle breaking via DFS\n// ---------------------------------------------------------------------------\n\nfunction breakCycles(\n  edges: GraphEdge[],\n  n: number,\n  outgoing: number[][],\n  incoming: number[][],\n): void {\n  // Build adjacency from edges\n  for (const e of edges) {\n    outgoing[e.source]!.push(e.target)\n    incoming[e.target]!.push(e.source)\n  }\n\n  // DFS-based cycle detection — reverse back-edges\n  const WHITE = 0, GRAY = 1, BLACK = 2\n  const color = new Array<number>(n).fill(WHITE)\n\n  function dfs(u: number): void {\n    color[u] = GRAY\n    const out = outgoing[u]!\n    for (let i = 0; i < out.length; i++) {\n      const v = out[i]!\n      if (color[v] === GRAY) {\n        // Back-edge: reverse it in the edges list\n        // Find the edge u → v and reverse it\n        for (const e of edges) {\n          if (e.source === u && e.target === v) {\n            e.source = v\n            e.target = u\n            break\n          }\n        }\n        // Update adjacency\n        out.splice(i, 1)\n        i--\n        outgoing[v]!.push(u)\n        incoming[u]!.push(v)\n        const idx = incoming[v]!.indexOf(u)\n        if (idx >= 0) incoming[v]!.splice(idx, 1)\n      } else if (color[v] === WHITE) {\n        dfs(v)\n      }\n    }\n    color[u] = BLACK\n  }\n\n  for (let i = 0; i < n; i++) {\n    if (color[i] === WHITE) dfs(i)\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Layer assignment (longest path from roots)\n// ---------------------------------------------------------------------------\n\nfunction assignLayers(\n  n: number,\n  outgoing: number[][],\n  incoming: number[][],\n): number[] {\n  const layers = new Array<number>(n).fill(-1)\n\n  // Roots = nodes with no incoming edges\n  const roots: number[] = []\n  for (let i = 0; i < n; i++) {\n    if (incoming[i]!.length === 0) roots.push(i)\n  }\n\n  // If no roots (all cycles broken), pick node 0\n  if (roots.length === 0 && n > 0) roots.push(0)\n\n  // BFS from roots\n  const queue: number[] = []\n  for (const r of roots) {\n    layers[r] = 0\n    queue.push(r)\n  }\n\n  let qi = 0\n  while (qi < queue.length) {\n    const u = queue[qi++]!\n    for (const v of outgoing[u]!) {\n      const newLayer = layers[u]! + 1\n      if (layers[v]! < newLayer) {\n        layers[v] = newLayer\n        queue.push(v)\n      }\n    }\n  }\n\n  // Any unassigned nodes get layer 0\n  for (let i = 0; i < n; i++) {\n    if (layers[i]! < 0) layers[i] = 0\n  }\n\n  return layers\n}\n\n// ---------------------------------------------------------------------------\n// Group nodes by layer\n// ---------------------------------------------------------------------------\n\nfunction groupByLayer(layers: number[], n: number): number[][] {\n  const maxLayer = Math.max(...layers, 0)\n  const groups: number[][] = new Array(maxLayer + 1)\n  for (let i = 0; i <= maxLayer; i++) groups[i] = []\n\n  for (let i = 0; i < n; i++) {\n    groups[layers[i]!]!.push(i)\n  }\n  return groups\n}\n\n// ---------------------------------------------------------------------------\n// Barycenter ordering\n// ---------------------------------------------------------------------------\n\nfunction orderLayers(\n  layerGroups: number[][],\n  outgoing: number[][],\n  incoming: number[][],\n  passes: number,\n): void {\n  for (let pass = 0; pass < passes; pass++) {\n    // Forward pass: order each layer based on positions of predecessors\n    for (let l = 1; l < layerGroups.length; l++) {\n      const layer = layerGroups[l]!\n      const posMap = new Map<number, number>()\n      const prevLayer = layerGroups[l - 1]!\n      for (let i = 0; i < prevLayer.length; i++) posMap.set(prevLayer[i]!, i)\n\n      layer.sort((a, b) => {\n        const ba = barycenter(a, incoming, posMap)\n        const bb = barycenter(b, incoming, posMap)\n        return ba - bb\n      })\n    }\n\n    // Backward pass: order each layer based on positions of successors\n    for (let l = layerGroups.length - 2; l >= 0; l--) {\n      const layer = layerGroups[l]!\n      const posMap = new Map<number, number>()\n      const nextLayer = layerGroups[l + 1]!\n      for (let i = 0; i < nextLayer.length; i++) posMap.set(nextLayer[i]!, i)\n\n      layer.sort((a, b) => {\n        const ba = barycenter(a, outgoing, posMap)\n        const bb = barycenter(b, outgoing, posMap)\n        return ba - bb\n      })\n    }\n  }\n}\n\nfunction barycenter(\n  nodeIdx: number,\n  adj: number[][],\n  posMap: Map<number, number>,\n): number {\n  const neighbors = adj[nodeIdx]!\n  if (neighbors.length === 0) return 0\n\n  let sum = 0\n  let count = 0\n  for (const nb of neighbors) {\n    const pos = posMap.get(nb)\n    if (pos !== undefined) {\n      sum += pos\n      count++\n    }\n  }\n  return count > 0 ? sum / count : 0\n}\n","import type { GraphNode, GraphEdge } from './types'\n\n/**\n * Circular layout — nodes arranged equally around a circle.\n *\n * Features:\n * - Connectivity-based ordering to reduce edge crossings\n * - Pin support: pinned nodes keep their position, others fill gaps\n */\n\nexport interface CircularLayoutOpts {\n  area: { x: number; y: number; width: number; height: number }\n}\n\nexport function circularLayout(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  opts: CircularLayoutOpts,\n): void {\n  const n = nodes.length\n  if (n === 0) return\n\n  const { area } = opts\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n\n  // Order nodes to reduce crossings (BFS from most-connected node)\n  const order = connectivityOrder(nodes, edges)\n\n  // Count unpinned nodes to distribute them evenly\n  const unpinned: number[] = []\n  for (const idx of order) {\n    if (!nodes[idx]!.pin) unpinned.push(idx)\n  }\n\n  const count = Math.max(unpinned.length, 1)\n  const angleStep = (2 * Math.PI) / count\n\n  // Use elliptical layout to fill non-square areas better\n  const maxNodeW = Math.max(...nodes.map(nd => nd.width), 40)\n  const maxNodeH = Math.max(...nodes.map(nd => nd.height), 40)\n  const margin = 10\n\n  // Radii: fill the area minus room for the largest node\n  let rx = area.width / 2 - maxNodeW / 2 - margin\n  let ry = area.height / 2 - maxNodeH / 2 - margin\n\n  // Ensure nodes don't overlap along the ellipse:\n  // minimum arc spacing ≈ max(node diagonal) + gap\n  if (count > 1) {\n    const maxDiag = Math.max(\n      ...nodes.map(nd => Math.sqrt(nd.width * nd.width + nd.height * nd.height)),\n      40,\n    )\n    const minSpacing = maxDiag + 16\n    // Approximate ellipse perimeter ≈ π * (3(a+b) - √((3a+b)(a+3b)))\n    const perimApprox = Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)))\n    const spacingPerNode = perimApprox / count\n    if (spacingPerNode < minSpacing) {\n      const scale = minSpacing / spacingPerNode\n      rx *= scale\n      ry *= scale\n    }\n  }\n\n  // Clamp so nodes stay within area\n  rx = Math.max(20, Math.min(rx, area.width / 2 - margin))\n  ry = Math.max(20, Math.min(ry, area.height / 2 - margin))\n\n  const startAngle = -Math.PI / 2 // 12 o'clock\n\n  for (let i = 0; i < unpinned.length; i++) {\n    const node = nodes[unpinned[i]!]!\n    const angle = startAngle + angleStep * i\n    node.x = cx + rx * Math.cos(angle)\n    node.y = cy + ry * Math.sin(angle)\n  }\n\n  // Apply pinned positions\n  for (const node of nodes) {\n    if (node.pin) {\n      node.x = area.x + node.pin.x * area.width\n      node.y = area.y + node.pin.y * area.height\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Connectivity-based ordering (BFS from most-connected node)\n// ---------------------------------------------------------------------------\n\nfunction connectivityOrder(nodes: GraphNode[], edges: GraphEdge[]): number[] {\n  const n = nodes.length\n  if (n === 0) return []\n\n  // Build adjacency list\n  const adj = new Array<number[]>(n)\n  for (let i = 0; i < n; i++) adj[i] = []\n\n  for (const e of edges) {\n    adj[e.source]!.push(e.target)\n    adj[e.target]!.push(e.source)\n  }\n\n  // Find most-connected node as BFS start\n  let startNode = 0\n  let maxDeg = 0\n  for (let i = 0; i < n; i++) {\n    if (adj[i]!.length > maxDeg) {\n      maxDeg = adj[i]!.length\n      startNode = i\n    }\n  }\n\n  // BFS\n  const visited = new Set<number>()\n  const order: number[] = []\n  const queue: number[] = [startNode]\n  visited.add(startNode)\n\n  while (queue.length > 0) {\n    const u = queue.shift()!\n    order.push(u)\n\n    // Sort neighbors by degree (descending) for better ordering\n    const neighbors = adj[u]!.filter(v => !visited.has(v))\n    neighbors.sort((a, b) => adj[b]!.length - adj[a]!.length)\n\n    for (const v of neighbors) {\n      if (!visited.has(v)) {\n        visited.add(v)\n        queue.push(v)\n      }\n    }\n  }\n\n  // Add any disconnected nodes\n  for (let i = 0; i < n; i++) {\n    if (!visited.has(i)) order.push(i)\n  }\n\n  return order\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, circle, text, line } from '../../render/tree'\nimport type { GraphNode as RichGraphNode, GraphEdge as RichGraphEdge, GraphOptions, GraphLayout } from './types'\nimport { parseGraphData } from './parse'\nimport { measureNodeSize } from './text-measure'\nimport { renderNodeShape } from './shapes'\nimport { renderEdges } from './edges'\nimport { forceLayout as richForceLayout } from './layout-force'\nimport { hierarchyLayout } from './layout-hierarchy'\nimport { circularLayout } from './layout-circular'\n\n/**\n * Graph / Network chart — node-link diagram with force-directed layout.\n *\n * Data convention:\n * - labels: node names\n * - series[0].values: node values (controls circle radius)\n * - Edge encoding: series names contain \"→\" or \"->\" (e.g., \"A → B\")\n *   with values[0] = edge weight. Same as Sankey convention.\n *\n * Alternative: adjacency matrix\n * - series[i].values[j] > 0 means there's an edge from node i to node j.\n *\n * Rich format (via options):\n * - options.nodes: Array of { id, label, shape, color, pin }\n * - options.edges: Array of { source, target, label, style, color, weight }\n * - options.layout: 'force' | 'hierarchical' | 'circular'\n *\n * Uses a simple force simulation (no external deps):\n * - Repulsion between all nodes (Coulomb's law)\n * - Attraction along edges (Hooke's law)\n * - Gravity toward center\n */\n\ninterface GraphNode {\n  name: string\n  index: number\n  value: number\n  x: number\n  y: number\n  vx: number\n  vy: number\n}\n\ninterface GraphEdge {\n  source: number\n  target: number\n  weight: number\n}\n\nexport const graphChartType = defineChartType({\n  type: 'graph',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const opts = options as GraphOptions\n    // Rich format: data lives in options.nodes/edges, not series\n    if ((opts.nodes || opts.edges) && (!data.series.length || data.series.every(s => s.values.length === 0))) {\n      return {\n        series: [],\n        labels: [],\n        bounds: { xMin: 0, xMax: 1, yMin: 0, yMax: 1 },\n      }\n    }\n    // Pad edge series to match label count so validation passes\n    const labelLen = data.labels?.length ?? 0\n    const paddedSeries = data.series.map(s => {\n      if (s.values.length < labelLen) {\n        const padded = new Array(labelLen).fill(0)\n        for (let i = 0; i < s.values.length; i++) padded[i] = s.values[i]!\n        return { ...s, values: padded }\n      }\n      return s\n    })\n    return prepareNoAxes({ ...data, series: paddedSeries }, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const graphOpts = options as GraphOptions\n\n    // Rich format — use the new modular pipeline\n    if (graphOpts.nodes || graphOpts.edges) {\n      return renderRichGraph(ctx)\n    }\n\n    // Legacy format — original rendering pipeline\n    const nodes: RenderNode[] = []\n\n    const { graphNodes, graphEdges } = parseLegacyGraphData(data, options)\n    if (graphNodes.length === 0) return nodes\n\n    // Run force simulation\n    forceLayout(graphNodes, graphEdges, area, 80)\n\n    // Render edges\n    for (let ei = 0; ei < graphEdges.length; ei++) {\n      const edge = graphEdges[ei]!\n      const src = graphNodes[edge.source]!\n      const tgt = graphNodes[edge.target]!\n\n      nodes.push(line(src.x, src.y, tgt.x, tgt.y, {\n        class: 'chartts-graph-edge',\n        stroke: theme.gridColor,\n        strokeWidth: Math.max(1, Math.min(3, edge.weight * 0.5)),\n        opacity: 0.5,\n      }))\n    }\n\n    // Compute node radii\n    const maxVal = Math.max(...graphNodes.map(n => n.value), 1)\n    const minR = 5\n    const maxR = Math.min(20, Math.min(area.width, area.height) * 0.06)\n\n    // Render nodes\n    for (let ni = 0; ni < graphNodes.length; ni++) {\n      const gn = graphNodes[ni]!\n      const color = options.colors[ni % options.colors.length]!\n      const r = minR + (gn.value / maxVal) * (maxR - minR)\n      const nodeGroup: RenderNode[] = []\n\n      nodeGroup.push(circle(gn.x, gn.y, r, {\n        class: 'chartts-graph-node',\n        fill: color,\n        fillOpacity: 0.85,\n        stroke: color,\n        strokeWidth: 1.5,\n        'data-series': ni,\n        'data-index': 0,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${gn.name}: ${gn.value}`,\n      }))\n\n      // Label\n      nodeGroup.push(text(gn.x, gn.y - r - 5, gn.name, {\n        class: 'chartts-graph-label',\n        fill: theme.textColor,\n        textAnchor: 'middle',\n        dominantBaseline: 'auto',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      nodes.push(group(nodeGroup, {\n        class: `chartts-series chartts-series-${ni}`,\n        'data-series-name': gn.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const graphOpts = options as GraphOptions\n\n    // Rich format — use modular hit test\n    if (graphOpts.nodes || graphOpts.edges) {\n      return richHitTest(ctx, mx, my)\n    }\n\n    // Legacy format — original hit test\n    const { graphNodes, graphEdges } = parseLegacyGraphData(data, options)\n    if (graphNodes.length === 0) return null\n\n    forceLayout(graphNodes, graphEdges, area, 80)\n\n    const maxVal = Math.max(...graphNodes.map(n => n.value), 1)\n    const minR = 5\n    const maxR = Math.min(20, Math.min(area.width, area.height) * 0.06)\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    for (let ni = 0; ni < graphNodes.length; ni++) {\n      const gn = graphNodes[ni]!\n      const r = minR + (gn.value / maxVal) * (maxR - minR)\n      const dist = Math.sqrt((mx - gn.x) ** 2 + (my - gn.y) ** 2)\n      if (dist < bestDist && dist < r + 8) {\n        bestDist = dist\n        best = { seriesIndex: ni, pointIndex: 0, distance: dist, x: gn.x, y: gn.y }\n      }\n    }\n\n    return best\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Rich format rendering (new — shapes, layouts, edge arrows)\n// ---------------------------------------------------------------------------\n\nfunction renderRichGraph(ctx: RenderContext): RenderNode[] {\n  const { data, area, theme, options } = ctx\n  const graphOpts = options as GraphOptions\n  const result: RenderNode[] = []\n\n  const { graphNodes, graphEdges } = parseGraphData(data, options)\n  if (graphNodes.length === 0) return result\n\n  // Measure text for each node\n  for (const node of graphNodes) {\n    const size = measureNodeSize(node.label, theme.fontSizeSmall, node.shape)\n    node.width = size.width\n    node.height = size.height\n  }\n\n  // Layout\n  runLayout(graphNodes, graphEdges, graphOpts, area)\n\n\n  // Render edges first (behind nodes)\n  const edgeNodes = renderEdges(graphNodes, graphEdges, graphOpts, theme)\n  if (edgeNodes.length > 0) {\n    result.push(group(edgeNodes, { class: 'chartts-graph-edges' }))\n  }\n\n  // Render node shapes\n  for (const node of graphNodes) {\n    const color = node.color ?? options.colors[node.index % options.colors.length]!\n    const shapeNodes = renderNodeShape(node, color, theme)\n\n    result.push(group(shapeNodes, {\n      class: `chartts-series chartts-series-${node.index}`,\n      'data-series-name': node.label,\n    }))\n  }\n\n  return result\n}\n\nfunction richHitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n  const { data, area, theme, options } = ctx\n  const graphOpts = options as GraphOptions\n\n  const { graphNodes, graphEdges } = parseGraphData(data, options)\n  if (graphNodes.length === 0) return null\n\n  for (const node of graphNodes) {\n    const size = measureNodeSize(node.label, theme.fontSizeSmall, node.shape)\n    node.width = size.width\n    node.height = size.height\n  }\n  runLayout(graphNodes, graphEdges, graphOpts, area)\n\n  let best: HitResult | null = null\n  let bestDist = Infinity\n\n  for (const node of graphNodes) {\n    const dist = shapeDistance(node, mx, my)\n    if (dist < bestDist && dist < 8) {\n      bestDist = dist\n      best = { seriesIndex: node.index, pointIndex: 0, distance: dist, x: node.x, y: node.y }\n    }\n  }\n\n  return best\n}\n\n// ---------------------------------------------------------------------------\n// Layout dispatcher\n// ---------------------------------------------------------------------------\n\nfunction runLayout(\n  nodes: RichGraphNode[],\n  edges: RichGraphEdge[],\n  opts: GraphOptions,\n  area: { x: number; y: number; width: number; height: number },\n): void {\n  const layout: GraphLayout = opts.layout ?? 'force'\n\n  switch (layout) {\n    case 'hierarchical':\n      hierarchyLayout(nodes, edges, {\n        area,\n        direction: opts.direction ?? 'TB',\n      })\n      break\n\n    case 'circular':\n      circularLayout(nodes, edges, { area })\n      break\n\n    case 'force':\n    default:\n      richForceLayout(nodes, edges, {\n        area,\n        iterations: opts.iterations ?? 120,\n      })\n      break\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Shape-aware distance (0 = inside shape, >0 = outside)\n// ---------------------------------------------------------------------------\n\nfunction shapeDistance(node: RichGraphNode, mx: number, my: number): number {\n  const dx = mx - node.x\n  const dy = my - node.y\n  const absDx = Math.abs(dx)\n  const absDy = Math.abs(dy)\n\n  switch (node.shape) {\n    case 'circle': {\n      const r = Math.max(node.width, node.height) / 2\n      const dist = Math.sqrt(dx * dx + dy * dy)\n      return Math.max(0, dist - r)\n    }\n\n    case 'diamond': {\n      const hw = node.width / 2\n      const hh = node.height / 2\n      const d = absDx / hw + absDy / hh\n      return d <= 1 ? 0 : Math.sqrt(dx * dx + dy * dy) * (d - 1)\n    }\n\n    case 'hexagon': {\n      const rx = node.width / 2\n      const ry = node.height / 2\n      const d = (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry)\n      return d <= 1 ? 0 : Math.sqrt(dx * dx + dy * dy) * (Math.sqrt(d) - 1)\n    }\n\n    default: {\n      const hw = node.width / 2\n      const hh = node.height / 2\n      const ox = Math.max(0, absDx - hw)\n      const oy = Math.max(0, absDy - hh)\n      return Math.sqrt(ox * ox + oy * oy)\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Legacy data parsing (original code, untouched)\n// ---------------------------------------------------------------------------\n\nfunction parseLegacyGraphData(\n  data: PreparedData,\n  _options: ResolvedOptions,\n): { graphNodes: GraphNode[]; graphEdges: GraphEdge[] } {\n  const graphNodes: GraphNode[] = []\n  const graphEdges: GraphEdge[] = []\n  const nodeMap = new Map<string, number>()\n\n  function getOrCreateNode(name: string, value = 1): number {\n    if (nodeMap.has(name)) return nodeMap.get(name)!\n    const idx = graphNodes.length\n    nodeMap.set(name, idx)\n    graphNodes.push({\n      name, index: idx, value,\n      x: 0, y: 0, vx: 0, vy: 0,\n    })\n    return idx\n  }\n\n  const hasArrows = data.series.some(s => s.name.includes('→') || s.name.includes('->'))\n\n  if (hasArrows) {\n    // Edge list format\n    for (const series of data.series) {\n      const parts = series.name.split(/\\s*(?:→|->)\\s*/)\n      if (parts.length < 2) continue\n      const srcName = parts[0]!.trim()\n      const tgtName = parts[1]!.trim()\n      const weight = series.values[0] ?? 1\n\n      const src = getOrCreateNode(srcName)\n      const tgt = getOrCreateNode(tgtName)\n      graphEdges.push({ source: src, target: tgt, weight })\n      graphNodes[src]!.value += weight\n      graphNodes[tgt]!.value += weight\n    }\n  } else {\n    // Adjacency matrix or node list\n    for (let i = 0; i < data.labels.length; i++) {\n      getOrCreateNode(String(data.labels[i]), Math.abs(data.series[0]?.values[i] ?? 1))\n    }\n\n    // If multiple series with matching dimensions, treat as adjacency matrix\n    if (data.series.length > 1 && data.series.length === data.labels.length) {\n      for (let si = 0; si < data.series.length; si++) {\n        for (let j = 0; j < data.series[si]!.values.length; j++) {\n          const val = data.series[si]!.values[j]!\n          if (val > 0 && si !== j) {\n            graphEdges.push({ source: si, target: j, weight: val })\n          }\n        }\n      }\n    }\n  }\n\n  return { graphNodes, graphEdges }\n}\n\n// ---------------------------------------------------------------------------\n// Legacy force-directed layout (original code, untouched)\n// ---------------------------------------------------------------------------\n\nfunction forceLayout(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  area: { x: number; y: number; width: number; height: number },\n  iterations: number,\n): void {\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n  const n = nodes.length\n\n  if (n === 0) return\n\n  // Initialize positions in a circle\n  for (let i = 0; i < n; i++) {\n    const angle = (2 * Math.PI * i) / n\n    const r = Math.min(area.width, area.height) * 0.3\n    nodes[i]!.x = cx + r * Math.cos(angle)\n    nodes[i]!.y = cy + r * Math.sin(angle)\n    nodes[i]!.vx = 0\n    nodes[i]!.vy = 0\n  }\n\n  const k = Math.sqrt((area.width * area.height) / Math.max(n, 1))\n  const repulsion = k * k\n\n  for (let iter = 0; iter < iterations; iter++) {\n    const temp = 0.1 * (1 - iter / iterations) * Math.min(area.width, area.height) * 0.5\n\n    // Reset velocities\n    for (const node of nodes) {\n      node.vx = 0\n      node.vy = 0\n    }\n\n    // Repulsion between all pairs\n    for (let i = 0; i < n; i++) {\n      for (let j = i + 1; j < n; j++) {\n        const dx = nodes[i]!.x - nodes[j]!.x\n        const dy = nodes[i]!.y - nodes[j]!.y\n        const dist = Math.max(Math.sqrt(dx * dx + dy * dy), 1)\n        const force = repulsion / (dist * dist)\n        const fx = (dx / dist) * force\n        const fy = (dy / dist) * force\n        nodes[i]!.vx += fx\n        nodes[i]!.vy += fy\n        nodes[j]!.vx -= fx\n        nodes[j]!.vy -= fy\n      }\n    }\n\n    // Attraction along edges\n    for (const edge of edges) {\n      const src = nodes[edge.source]!\n      const tgt = nodes[edge.target]!\n      const dx = tgt.x - src.x\n      const dy = tgt.y - src.y\n      const dist = Math.max(Math.sqrt(dx * dx + dy * dy), 1)\n      const force = (dist * dist) / k\n      const fx = (dx / dist) * force * 0.1\n      const fy = (dy / dist) * force * 0.1\n      src.vx += fx\n      src.vy += fy\n      tgt.vx -= fx\n      tgt.vy -= fy\n    }\n\n    // Gravity toward center\n    for (const node of nodes) {\n      const dx = cx - node.x\n      const dy = cy - node.y\n      node.vx += dx * 0.01\n      node.vy += dy * 0.01\n    }\n\n    // Apply velocities with temperature damping\n    for (const node of nodes) {\n      const speed = Math.sqrt(node.vx * node.vx + node.vy * node.vy)\n      if (speed > 0) {\n        const capped = Math.min(speed, temp)\n        node.x += (node.vx / speed) * capped\n        node.y += (node.vy / speed) * capped\n      }\n\n      // Constrain to area\n      const margin = 20\n      node.x = Math.max(area.x + margin, Math.min(area.x + area.width - margin, node.x))\n      node.y = Math.max(area.y + margin, Math.min(area.y + area.height - margin, node.y))\n    }\n  }\n}\n","import type { GraphNode, GraphEdge } from './types'\n\n/**\n * Force-directed layout (Fruchterman-Reingold style).\n *\n * - Node-size-aware repulsion (prevents shape overlap)\n * - Pin support (pinned nodes keep position, still repel)\n * - Velocity damping (0.8x per iteration)\n */\n\nexport interface ForceLayoutOpts {\n  iterations: number\n  area: { x: number; y: number; width: number; height: number }\n}\n\nexport function forceLayout(\n  nodes: GraphNode[],\n  edges: GraphEdge[],\n  opts: ForceLayoutOpts,\n): void {\n  const { area, iterations } = opts\n  const n = nodes.length\n  if (n === 0) return\n\n  const cx = area.x + area.width / 2\n  const cy = area.y + area.height / 2\n\n  // Initialize positions: pinned nodes get their pin, others in a circle\n  // Use large initial spread so force simulation pushes nodes apart, not together\n  for (let i = 0; i < n; i++) {\n    const node = nodes[i]!\n    if (node.pin) {\n      node.x = area.x + node.pin.x * area.width\n      node.y = area.y + node.pin.y * area.height\n    } else {\n      const angle = (2 * Math.PI * i) / n\n      const r = Math.min(area.width, area.height) * 0.4\n      node.x = cx + r * Math.cos(angle)\n      node.y = cy + r * Math.sin(angle)\n    }\n    node.vx = 0\n    node.vy = 0\n  }\n\n  // k = ideal edge length, scaled up for node sizes\n  const avgNodeSize = nodes.reduce((s, nd) => s + Math.max(nd.width, nd.height), 0) / n\n  const k = Math.max(\n    Math.sqrt((area.width * area.height) / Math.max(n, 1)),\n    avgNodeSize * 2,\n  )\n  const repulsion = k * k * 1.5\n\n  for (let iter = 0; iter < iterations; iter++) {\n    const temp = 0.1 * (1 - iter / iterations) * Math.min(area.width, area.height) * 0.5\n\n    // Reset velocities\n    for (const node of nodes) {\n      node.vx = 0\n      node.vy = 0\n    }\n\n    // Repulsion between all pairs (node-size-aware)\n    for (let i = 0; i < n; i++) {\n      for (let j = i + 1; j < n; j++) {\n        const ni = nodes[i]!\n        const nj = nodes[j]!\n        const dx = ni.x - nj.x\n        const dy = ni.y - nj.y\n        const dist = Math.max(Math.sqrt(dx * dx + dy * dy), 1)\n\n        // Minimum separation = sum of half-diagonals + gap\n        const ri = Math.sqrt(ni.width * ni.width + ni.height * ni.height) / 2\n        const rj = Math.sqrt(nj.width * nj.width + nj.height * nj.height) / 2\n        const minDist = ri + rj + 12\n        const effectiveDist = Math.max(dist - minDist * 0.5, 1)\n\n        const force = repulsion / (effectiveDist * effectiveDist)\n        const fx = (dx / dist) * force\n        const fy = (dy / dist) * force\n\n        ni.vx += fx\n        ni.vy += fy\n        nj.vx -= fx\n        nj.vy -= fy\n      }\n    }\n\n    // Attraction along edges (weaker to let repulsion separate nodes)\n    for (const edge of edges) {\n      const src = nodes[edge.source]!\n      const tgt = nodes[edge.target]!\n      const dx = tgt.x - src.x\n      const dy = tgt.y - src.y\n      const dist = Math.max(Math.sqrt(dx * dx + dy * dy), 1)\n      const force = (dist * dist) / k\n      const fx = (dx / dist) * force * 0.08\n      const fy = (dy / dist) * force * 0.08\n\n      src.vx += fx\n      src.vy += fy\n      tgt.vx -= fx\n      tgt.vy -= fy\n    }\n\n    // Gravity toward center\n    for (const node of nodes) {\n      const dx = cx - node.x\n      const dy = cy - node.y\n      node.vx += dx * 0.01\n      node.vy += dy * 0.01\n    }\n\n    // Apply velocities with temperature damping\n    for (const node of nodes) {\n      if (node.pin) continue\n\n      node.vx *= 0.8\n      node.vy *= 0.8\n\n      const speed = Math.sqrt(node.vx * node.vx + node.vy * node.vy)\n      if (speed > 0) {\n        const capped = Math.min(speed, temp)\n        node.x += (node.vx / speed) * capped\n        node.y += (node.vy / speed) * capped\n      }\n\n      // Constrain to area with margin for node size\n      const mx = Math.max(20, node.width / 2 + 5)\n      const my = Math.max(20, node.height / 2 + 5)\n      node.x = Math.max(area.x + mx, Math.min(area.x + area.width - mx, node.x))\n      node.y = Math.max(area.y + my, Math.min(area.y + area.height - my, node.y))\n    }\n  }\n\n  // Post-layout overlap resolution: push apart any nodes that still overlap\n  for (let pass = 0; pass < 10; pass++) {\n    let moved = false\n    for (let i = 0; i < n; i++) {\n      for (let j = i + 1; j < n; j++) {\n        const ni = nodes[i]!\n        const nj = nodes[j]!\n        if (ni.pin && nj.pin) continue\n\n        // Axis-aligned overlap check\n        const overlapX = (ni.width + nj.width) / 2 + 8 - Math.abs(ni.x - nj.x)\n        const overlapY = (ni.height + nj.height) / 2 + 8 - Math.abs(ni.y - nj.y)\n        if (overlapX <= 0 || overlapY <= 0) continue\n\n        // Push apart along the axis with less overlap\n        const pushX = overlapX < overlapY\n        const push = (pushX ? overlapX : overlapY) / 2 + 1\n\n        if (pushX) {\n          const dir = ni.x >= nj.x ? 1 : -1\n          if (!ni.pin) ni.x += dir * push\n          if (!nj.pin) nj.x -= dir * push\n        } else {\n          const dir = ni.y >= nj.y ? 1 : -1\n          if (!ni.pin) ni.y += dir * push\n          if (!nj.pin) nj.y -= dir * push\n        }\n        moved = true\n      }\n    }\n    if (!moved) break\n\n    // Re-constrain\n    for (const node of nodes) {\n      if (node.pin) continue\n      const mx = Math.max(20, node.width / 2 + 5)\n      const my = Math.max(20, node.height / 2 + 5)\n      node.x = Math.max(area.x + mx, Math.min(area.x + area.width - mx, node.x))\n      node.y = Math.max(area.y + my, Math.min(area.y + area.height - my, node.y))\n    }\n  }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, text, line } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Parallel coordinates chart — multi-dimensional data on parallel vertical axes.\n *\n * Data convention:\n * - labels: axis names (dimensions), one per axis\n * - series[i]: one data record. series[i].values[j] = value for dimension j\n *\n * Each series becomes a polyline crossing all axes.\n */\n\nexport const parallelChartType = defineChartType({\n  type: 'parallel',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const dimCount = data.labels.length\n    if (dimCount < 2 || data.series.length === 0) return nodes\n\n    const padding = 24\n    const axisSpacing = (area.width - padding * 2) / Math.max(dimCount - 1, 1)\n    const axisTop = area.y + padding\n    const axisBottom = area.y + area.height - padding\n\n    // Compute min/max per dimension\n    const mins: number[] = new Array(dimCount).fill(Infinity)\n    const maxs: number[] = new Array(dimCount).fill(-Infinity)\n    for (const series of data.series) {\n      for (let d = 0; d < dimCount; d++) {\n        const v = series.values[d] ?? 0\n        if (v < mins[d]!) mins[d] = v\n        if (v > maxs[d]!) maxs[d] = v\n      }\n    }\n\n    // Ensure min !== max\n    for (let d = 0; d < dimCount; d++) {\n      if (mins[d] === maxs[d]) {\n        mins[d] = mins[d]! - 1\n        maxs[d] = maxs[d]! + 1\n      }\n    }\n\n    const axisX = (dim: number) => area.x + padding + dim * axisSpacing\n    const valueToY = (dim: number, value: number) => {\n      const frac = (value - mins[dim]!) / (maxs[dim]! - mins[dim]!)\n      return axisBottom - frac * (axisBottom - axisTop) // invert: higher values = higher on axis\n    }\n\n    // Draw axes\n    for (let d = 0; d < dimCount; d++) {\n      const x = axisX(d)\n\n      // Axis line\n      nodes.push(line(x, axisTop, x, axisBottom, {\n        class: 'chartts-parallel-axis',\n        stroke: theme.axisColor,\n        strokeWidth: theme.axisWidth,\n      }))\n\n      // Axis label at bottom\n      nodes.push(text(x, axisBottom + 14, String(data.labels[d]!), {\n        class: 'chartts-parallel-label',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'auto',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      // Min/max ticks\n      nodes.push(text(x - 6, axisTop, String(Math.round(maxs[d]!)), {\n        class: 'chartts-parallel-tick',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall * 0.85,\n        fontFamily: theme.fontFamily,\n      }))\n      nodes.push(text(x - 6, axisBottom, String(Math.round(mins[d]!)), {\n        class: 'chartts-parallel-tick',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall * 0.85,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    // Draw series lines\n    for (let si = 0; si < data.series.length; si++) {\n      const series = data.series[si]!\n      const color = series.color ?? options.colors[si % options.colors.length]!\n\n      const pb = new PathBuilder()\n      for (let d = 0; d < dimCount; d++) {\n        const x = axisX(d)\n        const y = valueToY(d, series.values[d] ?? 0)\n        if (d === 0) pb.moveTo(x, y)\n        else pb.lineTo(x, y)\n      }\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-parallel-line',\n        stroke: color,\n        strokeWidth: theme.lineWidth,\n        fill: 'none',\n        fillOpacity: 0,\n        opacity: Math.max(0.3, 1 - data.series.length * 0.03),\n        'data-series': si,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${series.name}: ${series.values.join(', ')}`,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const dimCount = data.labels.length\n    if (dimCount < 2 || data.series.length === 0) return null\n\n    const padding = 24\n    const axisSpacing = (area.width - padding * 2) / Math.max(dimCount - 1, 1)\n    const axisTop = area.y + padding\n    const axisBottom = area.y + area.height - padding\n\n    const mins: number[] = new Array(dimCount).fill(Infinity)\n    const maxs: number[] = new Array(dimCount).fill(-Infinity)\n    for (const series of data.series) {\n      for (let d = 0; d < dimCount; d++) {\n        const v = series.values[d] ?? 0\n        if (v < mins[d]!) mins[d] = v\n        if (v > maxs[d]!) maxs[d] = v\n      }\n    }\n    for (let d = 0; d < dimCount; d++) {\n      if (mins[d] === maxs[d]) { mins[d] = mins[d]! - 1; maxs[d] = maxs[d]! + 1 }\n    }\n\n    const axisX = (dim: number) => area.x + padding + dim * axisSpacing\n    const valueToY = (dim: number, value: number) => {\n      const frac = (value - mins[dim]!) / (maxs[dim]! - mins[dim]!)\n      return axisBottom - frac * (axisBottom - axisTop)\n    }\n\n    // Find closest series line\n    let best: HitResult | null = null\n    let bestDist = 20 // max hit distance\n\n    for (let si = 0; si < data.series.length; si++) {\n      const series = data.series[si]!\n      for (let d = 0; d < dimCount; d++) {\n        const x = axisX(d)\n        const y = valueToY(d, series.values[d] ?? 0)\n        const dist = Math.sqrt((mx - x) ** 2 + (my - y) ** 2)\n        if (dist < bestDist) {\n          bestDist = dist\n          best = { seriesIndex: si, pointIndex: d, distance: dist, x, y }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, text } from '../../render/tree'\n\n/**\n * Heatmap chart — displays a matrix of colored cells.\n *\n * Data format: each series is a row, each value is a cell.\n * Labels are column headers, series names are row headers.\n * Cell color intensity is proportional to value.\n */\nexport const heatmapChartType = defineChartType({\n  type: 'heatmap',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const rowCount = data.series.length\n    const colCount = data.labels.length\n    if (rowCount === 0 || colCount === 0) return nodes\n\n    // Find min/max values for color interpolation\n    let vMin = Infinity\n    let vMax = -Infinity\n    for (const s of data.series) {\n      for (const v of s.values) {\n        if (v < vMin) vMin = v\n        if (v > vMax) vMax = v\n      }\n    }\n    if (vMin === vMax) vMax = vMin + 1\n\n    // Layout: leave space for labels\n    const labelW = Math.min(60, area.width * 0.15)\n    const labelH = Math.min(24, area.height * 0.1)\n    const gridX = area.x + labelW\n    const gridY = area.y + labelH\n    const gridW = area.width - labelW\n    const gridH = area.height - labelH\n    const cellW = gridW / colCount\n    const cellH = gridH / rowCount\n    const gap = 1.5\n\n    // Column labels (top)\n    for (let c = 0; c < colCount; c++) {\n      const x = gridX + cellW * (c + 0.5)\n      nodes.push(text(x, area.y + labelH * 0.5, String(data.labels[c]!), {\n        class: 'chartts-heatmap-col-label',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize: Math.min(theme.fontSizeSmall, cellW * 0.35),\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    // Row labels (left) + cells\n    for (let r = 0; r < rowCount; r++) {\n      const series = data.series[r]!\n      const ry = gridY + cellH * r\n\n      // Row label\n      nodes.push(text(area.x + labelW - 4, ry + cellH / 2, series.name, {\n        class: 'chartts-heatmap-row-label',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: Math.min(theme.fontSizeSmall, cellH * 0.45),\n        fontFamily: theme.fontFamily,\n      }))\n\n      const cellNodes: RenderNode[] = []\n\n      for (let c = 0; c < colCount; c++) {\n        const value = series.values[c] ?? 0\n        const t = (value - vMin) / (vMax - vMin)\n        const color = interpolateColor(options.colors[0]!, t)\n\n        cellNodes.push(rect(\n          gridX + cellW * c + gap / 2,\n          ry + gap / 2,\n          cellW - gap,\n          cellH - gap,\n          {\n            class: 'chartts-heatmap-cell',\n            fill: color,\n            rx: 4,\n            ry: 2,\n            'data-series': r,\n            'data-index': c,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}, ${data.labels[c]}: ${value}`,\n          },\n        ))\n      }\n\n      nodes.push(group(cellNodes, {\n        class: `chartts-series chartts-series-${r}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  getHighlightNodes(ctx: RenderContext, hit: HitResult): RenderNode[] {\n    const { data, area, options } = ctx\n    const rowCount = data.series.length\n    const colCount = data.labels.length\n    if (rowCount === 0 || colCount === 0) return []\n\n    const labelW = Math.min(60, area.width * 0.15)\n    const labelH = Math.min(24, area.height * 0.1)\n    const gridX = area.x + labelW\n    const gridY = area.y + labelH\n    const gridW = area.width - labelW\n    const gridH = area.height - labelH\n    const cellW = gridW / colCount\n    const cellH = gridH / rowCount\n\n    const col = hit.pointIndex\n    const row = hit.seriesIndex\n    const color = options.colors[0] ?? '#3b82f6'\n\n    return [\n      rect(gridX + cellW * col, gridY + cellH * row, cellW, cellH, {\n        class: 'chartts-highlight-cell',\n        fill: 'none',\n        stroke: color,\n        strokeWidth: 2,\n      }),\n    ]\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const rowCount = data.series.length\n    const colCount = data.labels.length\n    if (rowCount === 0 || colCount === 0) return null\n\n    const labelW = Math.min(60, area.width * 0.15)\n    const labelH = Math.min(24, area.height * 0.1)\n    const gridX = area.x + labelW\n    const gridY = area.y + labelH\n    const gridW = area.width - labelW\n    const gridH = area.height - labelH\n    const cellW = gridW / colCount\n    const cellH = gridH / rowCount\n\n    if (mx < gridX || mx > gridX + gridW || my < gridY || my > gridY + gridH) return null\n\n    const col = Math.floor((mx - gridX) / cellW)\n    const row = Math.floor((my - gridY) / cellH)\n\n    if (row >= 0 && row < rowCount && col >= 0 && col < colCount) {\n      return { seriesIndex: row, pointIndex: col, distance: 0, x: gridX + col * cellW + cellW / 2, y: gridY + row * cellH + cellH / 2 }\n    }\n\n    return null\n  },\n})\n\n/** Interpolate from transparent to the given color based on t (0..1) */\nfunction interpolateColor(baseColor: string, t: number): string {\n  // Extract hex fallback from var(--color-xxx, #hex) format\n  const hexMatch = baseColor.match(/#([0-9a-fA-F]{6})/)\n  if (!hexMatch) return `rgba(59, 130, 246, ${(0.1 + t * 0.9).toFixed(2)})`\n\n  const hex = hexMatch[1]!\n  const r = parseInt(hex.slice(0, 2), 16)\n  const g = parseInt(hex.slice(2, 4), 16)\n  const b = parseInt(hex.slice(4, 6), 16)\n\n  const opacity = 0.1 + t * 0.9\n  return `rgba(${r}, ${g}, ${b}, ${opacity.toFixed(2)})`\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, line } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Boxplot / Whisker chart — displays statistical distribution for each category.\n *\n * Data format: each series has exactly 5 values per label:\n * [min, Q1, median, Q3, max]\n *\n * For simplicity, if there are N labels, series[0] has N*5 values:\n * [min1, q1_1, med1, q3_1, max1, min2, q1_2, med2, q3_2, max2, ...]\n *\n * Or use multiple series where each series has 5 values for its category.\n */\nexport interface BoxplotOptions extends ResolvedOptions {\n  /** Width ratio of boxes. Default 0.6. */\n  boxWidth?: number\n}\n\nexport const boxplotChartType = defineChartType({\n  type: 'boxplot',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    // Boxplot: single series with N*5 values. Create synthetic labels if needed.\n    // We need to trick the validator: expand labels to match values length.\n    const labelCount = data.labels?.length ?? 0\n    const valLen = data.series[0]?.values.length ?? 0\n    const syntheticData = { ...data }\n    if (labelCount > 0 && valLen > labelCount) {\n      // Pad labels to match values length (validator needs them equal)\n      const padded: string[] = (data.labels ?? []).map(String)\n      while (padded.length < valLen) padded.push('')\n      syntheticData.labels = padded\n    }\n\n    const prepared = prepareData(syntheticData, options)\n\n    // Restore original labels for rendering\n    if (data.labels && data.labels.length < valLen) {\n      prepared.labels = [...data.labels]\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    // Each series represents one boxplot: 5 values = [min, Q1, median, Q3, max]\n    const seriesCount = data.series.length\n    if (seriesCount === 0) return nodes\n\n    const bOpts = options as BoxplotOptions\n    const boxWidthRatio = bOpts.boxWidth ?? 0.6\n\n    const bw = getBandwidth(xScale)\n    const boxWidth = bw * boxWidthRatio\n\n    // Detect \"5 named series\" format: Min, Q1, Median, Q3, Max each with N values\n    const fiveSeriesFormat = data.series.length === 5 && data.series.every(s => s.values.length === data.labels.length)\n\n    for (let i = 0; i < data.labels.length; i++) {\n      let vals: number[]\n      if (fiveSeriesFormat) {\n        // Each series[j].values[i] gives the j-th stat for the i-th label\n        vals = data.series.map(s => s.values[i]!)\n      } else if (data.series.length === 1) {\n        const s = data.series[0]!\n        if (s.values.length >= (i + 1) * 5) {\n          vals = s.values.slice(i * 5, i * 5 + 5)\n        } else continue\n      } else if (data.series.length > i && data.series[i]!.values.length >= 5) {\n        vals = data.series[i]!.values.slice(0, 5)\n      } else continue\n\n      const [vMin, q1, median, q3, vMax] = vals as [number, number, number, number, number]\n      const cx = xScale.map(i)\n      const boxX = cx - boxWidth / 2\n\n      const yMin = yScale.map(vMin)\n      const yQ1 = yScale.map(q1)\n      const yMed = yScale.map(median)\n      const yQ3 = yScale.map(q3)\n      const yMax = yScale.map(vMax)\n\n      const color = options.colors[i % options.colors.length]!\n      const seriesIdx = Math.min(i, data.series.length - 1)\n      const boxNodes: RenderNode[] = []\n\n      // Whisker line (min to max)\n      boxNodes.push(line(cx, yMin, cx, yMax, {\n        class: 'chartts-boxplot-whisker',\n        stroke: color,\n        strokeWidth: 1.5,\n      }))\n\n      // Min whisker cap\n      boxNodes.push(line(cx - boxWidth * 0.3, yMin, cx + boxWidth * 0.3, yMin, {\n        class: 'chartts-boxplot-cap',\n        stroke: color,\n        strokeWidth: 1.5,\n      }))\n\n      // Max whisker cap\n      boxNodes.push(line(cx - boxWidth * 0.3, yMax, cx + boxWidth * 0.3, yMax, {\n        class: 'chartts-boxplot-cap',\n        stroke: color,\n        strokeWidth: 1.5,\n      }))\n\n      // IQR box (Q1 to Q3)\n      const boxTop = Math.min(yQ1, yQ3)\n      const boxH = Math.abs(yQ3 - yQ1)\n      boxNodes.push(rect(boxX, boxTop, boxWidth, boxH, {\n        class: 'chartts-boxplot-box',\n        fill: color,\n        fillOpacity: 0.25,\n        stroke: color,\n        strokeWidth: 1.5,\n        rx: 4,\n        ry: 4,\n        'data-series': seriesIdx,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i]}: min=${vMin}, Q1=${q1}, median=${median}, Q3=${q3}, max=${vMax}`,\n      }))\n\n      // Median line\n      boxNodes.push(line(boxX, yMed, boxX + boxWidth, yMed, {\n        class: 'chartts-boxplot-median',\n        stroke: color,\n        strokeWidth: 2.5,\n      }))\n\n      nodes.push(group(boxNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i]),\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    if (data.labels.length === 0) return null\n\n    const bOpts = options as BoxplotOptions\n    const boxWidthRatio = bOpts.boxWidth ?? 0.6\n    const bw = getBandwidth(xScale)\n    const boxWidth = bw * boxWidthRatio\n\n    const fiveSeriesFormat = data.series.length === 5 && data.series.every(s => s.values.length === data.labels.length)\n\n    for (let i = 0; i < data.labels.length; i++) {\n      let vals: number[]\n      if (fiveSeriesFormat) {\n        vals = data.series.map(s => s.values[i]!)\n      } else if (data.series.length === 1) {\n        const s = data.series[0]!\n        if (s.values.length >= (i + 1) * 5) vals = s.values.slice(i * 5, i * 5 + 5)\n        else continue\n      } else if (data.series.length > i && data.series[i]!.values.length >= 5) {\n        vals = data.series[i]!.values.slice(0, 5)\n      } else continue\n\n      const cx = xScale.map(i)\n      const yMin = yScale.map(vals[0]!)\n      const yMax = yScale.map(vals[4]!)\n\n      const top = Math.min(yMin, yMax)\n      const bottom = Math.max(yMin, yMax)\n\n      if (mx >= cx - boxWidth / 2 - 4 && mx <= cx + boxWidth / 2 + 4 &&\n          my >= top - 4 && my <= bottom + 4) {\n        const seriesIdx = Math.min(i, data.series.length - 1)\n        return { seriesIndex: seriesIdx, pointIndex: i, distance: 0, x: cx, y: yScale.map(vals[2]!) }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Histogram chart — bars touch each other (no gap), representing frequency distribution.\n *\n * Uses the same data format as bar chart. The key differences:\n * - Zero gap between bars\n * - Bars fill the full bandwidth\n * - Designed for continuous data ranges\n */\nexport const histogramChartType = defineChartType({\n  type: 'histogram',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const bw = getBandwidth(xScale)\n    // Histograms have no gap — bars touch\n    const barWidth = bw\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    const barNodes: RenderNode[] = []\n\n    for (let i = 0; i < series.values.length; i++) {\n      const value = series.values[i]!\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(value)\n\n      const y = value >= 0 ? vy : baseline\n      const h = Math.abs(vy - baseline)\n      if (h < 0.5) continue\n\n      const colorIndex = i % options.colors.length\n      const barFill = `url(#chartts-bar-${colorIndex})`\n\n      barNodes.push(rect(barX, y, barWidth, h, {\n        rx: 2, ry: 2,\n        class: 'chartts-bar chartts-histogram-bar',\n        fill: barFill,\n        stroke: series.color,\n        strokeWidth: 0.5,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i]}: ${value}`,\n      }))\n    }\n\n    nodes.push(group(barNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    for (let i = 0; i < series.values.length; i++) {\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(series.values[i]!)\n      const y = series.values[i]! >= 0 ? vy : baseline\n      const h = Math.abs(vy - baseline)\n\n      if (mx >= barX - 1 && mx <= barX + barWidth + 1 && my >= y - 2 && my <= y + h + 2) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: cx, y: vy }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, text } from '../../render/tree'\n\n/**\n * Treemap chart — rectangular space-filling visualization.\n *\n * Uses the first series' values as areas. Labels are cell labels.\n * Implements a simple squarified treemap layout.\n */\nexport const treemapChartType = defineChartType({\n  type: 'treemap',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    // Build items sorted by value descending\n    const items = series.values\n      .map((v, i) => ({ value: Math.abs(v), index: i }))\n      .filter(d => d.value > 0)\n      .sort((a, b) => b.value - a.value)\n\n    if (items.length === 0) return nodes\n\n    const total = items.reduce((s, d) => s + d.value, 0)\n    const gap = 2\n\n    // Layout using slice-and-dice (simpler, works well)\n    const rects = squarify(items.map(d => d.value / total), area.x, area.y, area.width, area.height)\n\n    for (let k = 0; k < items.length; k++) {\n      const item = items[k]!\n      const r = rects[k]!\n      const colorIndex = item.index % options.colors.length\n      const color = options.colors[colorIndex]!\n      const label = String(data.labels[item.index] ?? `Item ${item.index + 1}`)\n\n      const cellNodes: RenderNode[] = []\n\n      cellNodes.push(rect(r.x + gap / 2, r.y + gap / 2, r.w - gap, r.h - gap, {\n        class: 'chartts-treemap-cell',\n        fill: color,\n        fillOpacity: 0.75,\n        rx: 5,\n        ry: 5,\n        'data-series': 0,\n        'data-index': item.index,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label}: ${series.values[item.index]}`,\n      }))\n\n      // Only show label if cell is big enough\n      if (r.w > 30 && r.h > 20) {\n        const fontSize = Math.min(theme.fontSizeSmall, r.w * 0.15, r.h * 0.3)\n        cellNodes.push(text(r.x + r.w / 2, r.y + r.h / 2 - fontSize * 0.3, label, {\n          class: 'chartts-treemap-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n\n        // Show value below label\n        if (r.h > 35) {\n          cellNodes.push(text(r.x + r.w / 2, r.y + r.h / 2 + fontSize * 0.8, String(series.values[item.index]), {\n            class: 'chartts-treemap-value',\n            fill: 'rgba(255,255,255,0.7)',\n            textAnchor: 'middle',\n            dominantBaseline: 'central',\n            fontSize: fontSize * 0.85,\n            fontFamily: theme.fontFamily,\n          }))\n        }\n      }\n\n      nodes.push(group(cellNodes, {\n        class: `chartts-series chartts-series-${item.index}`,\n        'data-series-name': label,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const items = series.values\n      .map((v, i) => ({ value: Math.abs(v), index: i }))\n      .filter(d => d.value > 0)\n      .sort((a, b) => b.value - a.value)\n\n    if (items.length === 0) return null\n    const total = items.reduce((s, d) => s + d.value, 0)\n    const rects = squarify(items.map(d => d.value / total), area.x, area.y, area.width, area.height)\n\n    for (let k = 0; k < items.length; k++) {\n      const r = rects[k]!\n      if (mx >= r.x && mx <= r.x + r.w && my >= r.y && my <= r.y + r.h) {\n        return { seriesIndex: 0, pointIndex: items[k]!.index, distance: 0, x: r.x + r.w / 2, y: r.y + r.h / 2 }\n      }\n    }\n\n    return null\n  },\n})\n\ninterface Rect { x: number; y: number; w: number; h: number }\n\n/**\n * Squarified treemap layout.\n * Takes normalized values (sum to 1) and fills a rectangle.\n */\nfunction squarify(values: number[], x: number, y: number, w: number, h: number): Rect[] {\n  const rects: Rect[] = []\n  layoutRow(values, 0, x, y, w, h, rects)\n  return rects\n}\n\nfunction layoutRow(\n  values: number[], start: number,\n  x: number, y: number, w: number, h: number,\n  rects: Rect[],\n): void {\n  if (start >= values.length) return\n  if (values.length - start === 1) {\n    rects.push({ x, y, w, h })\n    return\n  }\n\n  const isWide = w >= h\n\n  // Greedily add items to the current row until aspect ratio gets worse\n  let rowSum = 0\n  let bestWorst = Infinity\n  let rowEnd = start\n\n  for (let i = start; i < values.length; i++) {\n    const newSum = rowSum + values[i]!\n\n    // Compute row takes up fraction of the short side\n    const rowFraction = newSum\n    const rowThickness = isWide ? w * rowFraction : h * rowFraction\n    const count = i - start + 1\n\n    if (rowThickness <= 0) { rowSum = newSum; rowEnd = i + 1; continue }\n\n    // Worst aspect ratio in this row\n    let worst = 0\n    for (let j = start; j <= i; j++) {\n      const cellFrac = values[j]! / newSum\n      const cellLen = isWide ? h * cellFrac : w * cellFrac\n      const ar = Math.max(rowThickness / cellLen, cellLen / rowThickness)\n      if (ar > worst) worst = ar\n    }\n\n    if (count === 1 || worst <= bestWorst) {\n      bestWorst = worst\n      rowSum = newSum\n      rowEnd = i + 1\n    } else {\n      break\n    }\n  }\n\n  if (rowEnd === start) rowEnd = start + 1\n  const finalSum = values.slice(start, rowEnd).reduce((a, b) => a + b, 0)\n\n  // Lay out this row\n  const rowThickness = isWide ? w * finalSum : h * finalSum\n  let offset = 0\n\n  for (let i = start; i < rowEnd; i++) {\n    const frac = finalSum > 0 ? values[i]! / finalSum : 0\n    const cellLen = isWide ? h * frac : w * frac\n\n    if (isWide) {\n      rects.push({ x, y: y + offset, w: rowThickness, h: cellLen })\n    } else {\n      rects.push({ x: x + offset, y, w: cellLen, h: rowThickness })\n    }\n    offset += cellLen\n  }\n\n  // Recurse for remaining items\n  if (isWide) {\n    layoutRow(values, rowEnd, x + rowThickness, y, w - rowThickness, h, rects)\n  } else {\n    layoutRow(values, rowEnd, x, y + rowThickness, w, h - rowThickness, rects)\n  }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\nimport { roundedSlicePath } from '../../utils/slice-path'\n\n/**\n * Polar / Radial bar chart (Nightingale rose diagram).\n *\n * Each category is a wedge whose radius is proportional to its value.\n * Uses the first series' values as wedge sizes.\n * Wedges have uniform pixel gaps, rounded corners, and a small inner radius.\n */\nexport const polarChartType = defineChartType({\n  type: 'polar',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const values = series.values\n    const count = values.length\n    let maxVal = 0\n    for (const v of values) {\n      if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    }\n    if (maxVal === 0) maxVal = 1\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const maxOuterR = Math.min(area.width, area.height) / 2 - 16\n    const innerR = maxOuterR * 0.08\n    const angleStep = (Math.PI * 2) / count\n    const gapPx = 4\n    const halfGap = gapPx / 2\n    const cornerRadius = 5\n\n    // Draw concentric grid rings\n    const ringCount = 3\n    for (let r = 1; r <= ringCount; r++) {\n      const ringR = (maxOuterR * r) / ringCount\n      const pb = new PathBuilder()\n      pb.moveTo(cx + ringR, cy)\n      pb.arc(ringR, ringR, 0, false, true, cx - ringR, cy)\n      pb.arc(ringR, ringR, 0, false, true, cx + ringR, cy)\n\n      nodes.push(path(pb.build(), {\n        class: 'chartts-polar-grid',\n        stroke: theme.gridColor,\n        strokeWidth: theme.gridWidth,\n        fill: 'none',\n        opacity: 0.3,\n      }))\n    }\n\n    // Draw wedges\n    for (let i = 0; i < count; i++) {\n      const value = Math.abs(values[i]!)\n      const wedgeR = (value / maxVal) * maxOuterR\n      const startAngle = -Math.PI / 2 + i * angleStep\n      const endAngle = -Math.PI / 2 + (i + 1) * angleStep\n      const sliceAngle = endAngle - startAngle\n\n      if (wedgeR < innerR + 2) continue\n\n      // Uniform pixel gap: different angular offsets at different radii\n      const outerPadAngle = halfGap / wedgeR\n      const innerPadAngle = innerR > 0 ? halfGap / innerR : 0\n\n      if (sliceAngle < outerPadAngle * 2 + 0.01) continue\n\n      const colorIndex = i % options.colors.length\n      const color = options.colors[colorIndex]!\n\n      const d = roundedSlicePath(\n        cx, cy, wedgeR, innerR,\n        startAngle + outerPadAngle, endAngle - outerPadAngle,\n        startAngle + innerPadAngle, endAngle - innerPadAngle,\n        cornerRadius,\n      )\n\n      const wedgeNodes: RenderNode[] = [\n        path(d, {\n          class: 'chartts-polar-wedge',\n          fill: color,\n          fillOpacity: 0.75,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? `Item ${i + 1}`}: ${values[i]}`,\n        }),\n      ]\n\n      // Label at the outer edge\n      const midAngle = (startAngle + endAngle) / 2\n      const labelR = maxOuterR + 10\n      const lx = cx + labelR * Math.cos(midAngle)\n      const ly = cy + labelR * Math.sin(midAngle)\n      const anchor = Math.abs(Math.cos(midAngle)) < 0.01 ? 'middle' as const\n        : Math.cos(midAngle) > 0 ? 'start' as const : 'end' as const\n\n      wedgeNodes.push(text(lx, ly, String(data.labels[i] ?? ''), {\n        class: 'chartts-polar-label',\n        fill: theme.textMuted,\n        textAnchor: anchor,\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      nodes.push(group(wedgeNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i] ?? `Item ${i + 1}`),\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const values = series.values\n    const count = values.length\n    let maxVal = 0\n    for (const v of values) {\n      if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    }\n    if (maxVal === 0) return null\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const maxOuterR = Math.min(area.width, area.height) / 2 - 16\n    const innerR = maxOuterR * 0.08\n    const angleStep = (Math.PI * 2) / count\n\n    const dx = mx - cx\n    const dy = my - cy\n    const dist = Math.sqrt(dx * dx + dy * dy)\n    if (dist > maxOuterR || dist < innerR) return null\n\n    let angle = Math.atan2(dy, dx)\n    if (angle < -Math.PI / 2) angle += Math.PI * 2\n\n    const offset = angle + Math.PI / 2\n    const normalizedAngle = offset < 0 ? offset + Math.PI * 2 : offset\n    const idx = Math.floor(normalizedAngle / angleStep)\n\n    if (idx >= 0 && idx < count) {\n      const wedgeR = (Math.abs(values[idx]!) / maxVal) * maxOuterR\n      if (dist <= wedgeR && dist >= innerR) {\n        const midAngle = -Math.PI / 2 + (idx + 0.5) * angleStep\n        const midR = (innerR + wedgeR) / 2\n        return { seriesIndex: 0, pointIndex: idx, distance: dist, x: cx + midR * Math.cos(midAngle), y: cy + midR * Math.sin(midAngle) }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Radial bar chart — concentric arcs radiating from center.\n *\n * Each category gets its own ring. Arc length is proportional to value.\n * Uses the first series' values.\n */\nexport const radialBarChartType = defineChartType({\n  type: 'radial-bar',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const values = series.values\n    const count = values.length\n    let maxVal = 0\n    for (const v of values) {\n      if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    }\n    if (maxVal === 0) maxVal = 1\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 20\n    const innerR = outerR * 0.2\n    const ringGap = 3\n    const ringWidth = (outerR - innerR - ringGap * (count - 1)) / count\n    const startAngle = -Math.PI / 2 // 12 o'clock\n\n    for (let i = 0; i < count; i++) {\n      const value = Math.abs(values[i]!)\n      const fraction = value / maxVal\n      const sweepAngle = fraction * Math.PI * 2 * 0.95 // max 95% of circle\n      const endAngle = startAngle + sweepAngle\n\n      const rOuter = innerR + (count - i) * (ringWidth + ringGap) - ringGap\n      const rInner = rOuter - ringWidth\n\n      const colorIndex = i % options.colors.length\n      const color = options.colors[colorIndex]!\n      const label = String(data.labels[i] ?? `Item ${i + 1}`)\n\n      // Track arc (full background ring) — rounded caps\n      const trackPb = new PathBuilder()\n      const trackEnd = startAngle + Math.PI * 2 * 0.95\n      strokeArc(trackPb, cx, cy, (rOuter + rInner) / 2, startAngle, trackEnd)\n      nodes.push(path(trackPb.build(), {\n        class: 'chartts-radialbar-track',\n        stroke: theme.gridColor,\n        strokeWidth: ringWidth,\n        strokeLinecap: 'round',\n        fill: 'none',\n        opacity: 0.15,\n      }))\n\n      // Value arc — rounded caps for polished look\n      if (sweepAngle > 0.01) {\n        const arcPb = new PathBuilder()\n        strokeArc(arcPb, cx, cy, (rOuter + rInner) / 2, startAngle, endAngle)\n\n        const arcNodes: RenderNode[] = [\n          path(arcPb.build(), {\n            class: 'chartts-radialbar-arc',\n            stroke: color,\n            strokeWidth: ringWidth,\n            strokeLinecap: 'round',\n            fill: 'none',\n            opacity: 0.85,\n            'data-series': 0,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${label}: ${values[i]}`,\n          }),\n        ]\n\n        // Label on the left side of the ring\n        const ringMidR = (rOuter + rInner) / 2\n        arcNodes.push(text(cx - outerR - 6, cy - ringMidR + cy - cy, label, {\n          class: 'chartts-radialbar-label',\n          fill: theme.textMuted,\n          textAnchor: 'end',\n          dominantBaseline: 'central',\n          fontSize: Math.min(theme.fontSizeSmall, ringWidth * 0.9),\n          fontFamily: theme.fontFamily,\n        }))\n\n        nodes.push(group(arcNodes, {\n          class: `chartts-series chartts-series-${i}`,\n          'data-series-name': label,\n        }))\n      }\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const count = series.values.length\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 20\n    const innerR = outerR * 0.2\n    const ringGap = 3\n    const ringWidth = (outerR - innerR - ringGap * (count - 1)) / count\n\n    const dx = mx - cx\n    const dy = my - cy\n    const dist = Math.sqrt(dx * dx + dy * dy)\n\n    for (let i = 0; i < count; i++) {\n      const rOuter = innerR + (count - i) * (ringWidth + ringGap) - ringGap\n      const rInner = rOuter - ringWidth\n\n      if (dist >= rInner && dist <= rOuter) {\n        const midR = (rInner + rOuter) / 2\n        const hitAngle = Math.atan2(dy, dx)\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: cx + midR * Math.cos(hitAngle), y: cy + midR * Math.sin(hitAngle) }\n      }\n    }\n\n    return null\n  },\n})\n\nfunction strokeArc(pb: PathBuilder, cx: number, cy: number, r: number, startAngle: number, endAngle: number): void {\n  const x1 = cx + r * Math.cos(startAngle)\n  const y1 = cy + r * Math.sin(startAngle)\n  const x2 = cx + r * Math.cos(endAngle)\n  const y2 = cy + r * Math.sin(endAngle)\n  const largeArc = (endAngle - startAngle) > Math.PI\n\n  pb.moveTo(x1, y1)\n  pb.arc(r, r, 0, largeArc, true, x2, y2)\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, line, circle } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Lollipop chart — stem line + circle at end.\n *\n * A modern, cleaner alternative to bar charts.\n * Vertical stems from baseline to value with a prominent circle dot.\n */\nexport const lollipopChartType = defineChartType({\n  type: 'lollipop',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return nodes\n\n    const bw = getBandwidth(xScale)\n    const groupWidth = bw * 0.8\n    const stemGap = groupWidth / seriesCount\n    const dotR = Math.min(8, stemGap * 0.4)\n    const baselineY = yScale.map(0)\n\n    for (const series of data.series) {\n      const seriesNodes: RenderNode[] = []\n\n      for (let i = 0; i < series.values.length; i++) {\n        const cx = xScale.map(i) + (series.index - (seriesCount - 1) / 2) * stemGap\n        const vy = yScale.map(series.values[i]!)\n        const color = options.colors[series.index % options.colors.length]!\n\n        // Stem line — rounded cap, slightly thicker\n        seriesNodes.push(line(cx, baselineY, cx, vy, {\n          class: 'chartts-lollipop-stem',\n          stroke: color,\n          strokeWidth: 2.5,\n          strokeLinecap: 'round',\n          strokeOpacity: 0.6,\n        }))\n\n        // Ambient glow behind dot\n        seriesNodes.push(circle(cx, vy, dotR * 2, {\n          class: 'chartts-lollipop-glow',\n          fill: color,\n          fillOpacity: 0.12,\n        }))\n\n        // Dot — bigger, with theme-aware stroke\n        seriesNodes.push(circle(cx, vy, dotR, {\n          class: 'chartts-lollipop-dot',\n          fill: color,\n          stroke: `var(--chartts-bg, #fff)`,\n          strokeWidth: 2.5,\n          'data-series': series.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name}: ${series.values[i]}`,\n        }))\n      }\n\n      nodes.push(group(seriesNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale } = ctx\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return null\n\n    const bw = getBandwidth(xScale)\n    const groupWidth = bw * 0.8\n    const stemGap = groupWidth / seriesCount\n\n    let best: HitResult | null = null\n    let bestDist = 20 // tolerance\n\n    for (const series of data.series) {\n      for (let i = 0; i < series.values.length; i++) {\n        const cx = xScale.map(i) + (series.index - (seriesCount - 1) / 2) * stemGap\n        const vy = yScale.map(series.values[i]!)\n        const dx = mx - cx\n        const dy = my - vy\n        const dist = Math.sqrt(dx * dx + dy * dy)\n\n        if (dist < bestDist) {\n          bestDist = dist\n          best = { seriesIndex: series.index, pointIndex: i, distance: dist, x: cx, y: vy }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, line, text } from '../../render/tree'\n\n/**\n * Bullet chart — compact horizontal gauge.\n *\n * Data format: each label is a metric.\n * - series[0]: actual values\n * - series[1] (optional): target values (shown as a marker line)\n *\n * Qualitative ranges (poor/satisfactory/good) are auto-generated\n * from the max value.\n */\nexport const bulletChartType = defineChartType({\n  type: 'bullet',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const actual = data.series[0]\n    if (!actual || actual.values.length === 0) return nodes\n\n    const target = data.series[1]\n    const count = actual.values.length\n    const labelWidth = Math.min(80, area.width * 0.2)\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n\n    const rowHeight = area.height / count\n    const barHeight = Math.min(rowHeight * 0.4, 20)\n    const rangeHeight = Math.min(rowHeight * 0.7, 32)\n\n    // Find global max for scaling\n    let maxVal = 0\n    for (const v of actual.values) {\n      if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n    }\n    if (target) {\n      for (const v of target.values) {\n        if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n      }\n    }\n    // Extend max to give headroom for ranges\n    maxVal = maxVal * 1.2\n    if (maxVal === 0) maxVal = 1\n\n    for (let i = 0; i < count; i++) {\n      const cy = area.y + rowHeight * (i + 0.5)\n      const val = actual.values[i]!\n      const label = String(data.labels[i] ?? `Item ${i + 1}`)\n      const color = options.colors[i % options.colors.length]!\n      const bulletNodes: RenderNode[] = []\n\n      // Label\n      bulletNodes.push(text(area.x + labelWidth - 8, cy, label, {\n        class: 'chartts-bullet-label',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      // Qualitative ranges (3 bands: poor, satisfactory, good)\n      const bands = [1.0, 0.75, 0.5]\n      const opacities = [0.1, 0.18, 0.28]\n      for (let b = 0; b < bands.length; b++) {\n        const bw = chartW * bands[b]!\n        bulletNodes.push(rect(chartX, cy - rangeHeight / 2, bw, rangeHeight, {\n          rx: 4, ry: 4,\n          class: 'chartts-bullet-range',\n          fill: theme.textColor,\n          opacity: opacities[b],\n        }))\n      }\n\n      // Actual value bar\n      const barW = (Math.abs(val) / maxVal) * chartW\n      bulletNodes.push(rect(chartX, cy - barHeight / 2, barW, barHeight, {\n        rx: 3, ry: 3,\n        class: 'chartts-bullet-bar',\n        fill: color,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${label}: ${val}${target ? `, target: ${target.values[i]}` : ''}`,\n      }))\n\n      // Target marker\n      if (target && target.values[i] != null) {\n        const tx = chartX + (Math.abs(target.values[i]!) / maxVal) * chartW\n        const markerH = rangeHeight * 0.9\n        bulletNodes.push(line(tx, cy - markerH / 2, tx, cy + markerH / 2, {\n          class: 'chartts-bullet-target',\n          stroke: theme.textColor,\n          strokeWidth: 2.5,\n        }))\n      }\n\n      nodes.push(group(bulletNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': label,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const actual = data.series[0]\n    if (!actual || actual.values.length === 0) return null\n\n    const count = actual.values.length\n    const labelWidth = Math.min(80, area.width * 0.2)\n    const rowHeight = area.height / count\n\n    if (mx < area.x + labelWidth) return null\n\n    for (let i = 0; i < count; i++) {\n      const cy = area.y + rowHeight * (i + 0.5)\n      const rangeHeight = Math.min(rowHeight * 0.7, 32)\n\n      if (my >= cy - rangeHeight / 2 && my <= cy + rangeHeight / 2) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: mx, y: cy }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { path } from '../../render/tree'\nimport { buildMonotonePath, type Point } from '../../utils/curves'\nimport { formatNum } from '../../utils/format'\n\n/**\n * Sparkline — tiny inline chart with no axes, no labels, no legend.\n * Just the line/area and optionally a highlight of the last value.\n */\nexport const sparklineChartType = defineChartType({\n  type: 'sparkline',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareData(data, {\n      ...options,\n      xAxis: false,\n      yAxis: false,\n      legend: false,\n      xGrid: false,\n      yGrid: false,\n      padding: [2, 2, 2, 2],\n    })\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const points: Point[] = series.values.map((v, i) => ({\n      x: xScale.map(i),\n      y: yScale.map(v),\n    }))\n\n    const linePath = buildMonotonePath(points)\n\n    // Area fill\n    const baseline = area.y + area.height\n    const first = points[0]!\n    const last = points[points.length - 1]!\n    const areaPath = `${linePath}L${formatNum(last.x)},${formatNum(baseline)}L${formatNum(first.x)},${formatNum(baseline)}Z`\n\n    nodes.push(path(areaPath, {\n      class: 'chartts-sparkline-area',\n      fill: series.color,\n      fillOpacity: 0.15,\n    }))\n\n    nodes.push(path(linePath, {\n      class: 'chartts-sparkline-line',\n      stroke: series.color,\n      strokeWidth: 1.5,\n    }))\n\n    // Last point indicator\n    if (points.length > 0) {\n      const lp = points[points.length - 1]!\n      nodes.push({\n        type: 'circle',\n        cx: lp.x,\n        cy: lp.y,\n        r: 2.5,\n        attrs: {\n          class: 'chartts-sparkline-dot',\n          fill: series.color,\n        },\n      })\n    }\n\n    return nodes\n  },\n\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { lineChartType } from '../line/line-type'\n\n/**\n * Area chart — line chart with fill enabled on all series by default.\n * Delegates entirely to lineChartType after forcing fill:true.\n */\nexport const areaChartType = defineChartType({\n  type: 'area',\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    // Force fill on all series\n    const filled: ChartData = {\n      ...data,\n      series: data.series.map(s => ({\n        ...s,\n        fill: s.fill ?? true,\n        fillOpacity: s.fillOpacity ?? 0.25,\n      })),\n    }\n    return lineChartType.prepareData(filled, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    return lineChartType.render(ctx)\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    return lineChartType.hitTest(ctx, mx, my)\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, circle, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Radar / Spider chart — plots multi-dimensional data on radial axes.\n * Each category becomes an axis radiating from center.\n */\nexport const radarChartType = defineChartType({\n  type: 'radar',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const labelCount = data.labels.length\n    if (labelCount < 3) return nodes\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const radius = Math.min(area.width, area.height) / 2 - 24\n\n    // Find the max value across all series for scaling\n    let maxVal = 0\n    for (const series of data.series) {\n      for (const v of series.values) {\n        if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n      }\n    }\n    if (maxVal === 0) maxVal = 1\n\n    const angleStep = (Math.PI * 2) / labelCount\n    const startAngle = -Math.PI / 2 // start from top\n\n    // Draw grid rings (3 levels)\n    const gridLevels = 3\n    for (let level = 1; level <= gridLevels; level++) {\n      const r = (radius * level) / gridLevels\n      const pb = new PathBuilder()\n      for (let i = 0; i <= labelCount; i++) {\n        const angle = startAngle + (i % labelCount) * angleStep\n        const x = cx + r * Math.cos(angle)\n        const y = cy + r * Math.sin(angle)\n        if (i === 0) pb.moveTo(x, y)\n        else pb.lineTo(x, y)\n      }\n      nodes.push(path(pb.build(), {\n        class: 'chartts-radar-grid',\n        stroke: theme.gridColor,\n        strokeWidth: theme.gridWidth,\n        fillOpacity: 0,\n        fill: 'none',\n      }))\n    }\n\n    // Draw axis lines from center to each vertex\n    for (let i = 0; i < labelCount; i++) {\n      const angle = startAngle + i * angleStep\n      const x = cx + radius * Math.cos(angle)\n      const y = cy + radius * Math.sin(angle)\n\n      nodes.push({\n        type: 'line',\n        x1: cx,\n        y1: cy,\n        x2: x,\n        y2: y,\n        attrs: {\n          class: 'chartts-radar-axis',\n          stroke: theme.gridColor,\n          strokeWidth: theme.gridWidth,\n        },\n      })\n\n      // Label at vertex\n      const labelR = radius + 14\n      const lx = cx + labelR * Math.cos(angle)\n      const ly = cy + labelR * Math.sin(angle)\n      const anchor = Math.abs(Math.cos(angle)) < 0.01 ? 'middle' as const\n        : Math.cos(angle) > 0 ? 'start' as const : 'end' as const\n\n      nodes.push(text(lx, ly, String(data.labels[i]!), {\n        class: 'chartts-radar-label',\n        fill: theme.textMuted,\n        textAnchor: anchor,\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    // Draw series polygons\n    for (const series of data.series) {\n      const pb = new PathBuilder()\n      const points: { x: number; y: number }[] = []\n\n      for (let i = 0; i < labelCount; i++) {\n        const val = series.values[i] ?? 0\n        const r = (Math.abs(val) / maxVal) * radius\n        const angle = startAngle + i * angleStep\n        const x = cx + r * Math.cos(angle)\n        const y = cy + r * Math.sin(angle)\n        points.push({ x, y })\n\n        if (i === 0) pb.moveTo(x, y)\n        else pb.lineTo(x, y)\n      }\n      pb.close()\n\n      const seriesNodes: RenderNode[] = []\n\n      // Fill\n      seriesNodes.push(path(pb.build(), {\n        class: 'chartts-radar-area',\n        fill: series.color,\n        fillOpacity: 0.2,\n        stroke: series.color,\n        strokeWidth: theme.lineWidth,\n        'data-series': series.index,\n      }))\n\n      // Points\n      for (let i = 0; i < points.length; i++) {\n        seriesNodes.push(circle(points[i]!.x, points[i]!.y, theme.pointRadius, {\n          class: 'chartts-radar-point',\n          fill: series.color,\n          'data-series': series.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name} ${data.labels[i]}: ${series.values[i]}`,\n        }))\n      }\n\n      nodes.push(group(seriesNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const labelCount = data.labels.length\n    if (labelCount < 3) return null\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const radius = Math.min(area.width, area.height) / 2 - 24\n    const angleStep = (Math.PI * 2) / labelCount\n    const startAngle = -Math.PI / 2\n\n    let maxVal = 0\n    for (const series of data.series) {\n      for (const v of series.values) {\n        if (Math.abs(v) > maxVal) maxVal = Math.abs(v)\n      }\n    }\n    if (maxVal === 0) return null\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n    const hitRadius = 15\n\n    for (const series of data.series) {\n      for (let i = 0; i < labelCount; i++) {\n        const val = series.values[i] ?? 0\n        const r = (Math.abs(val) / maxVal) * radius\n        const angle = startAngle + i * angleStep\n        const px = cx + r * Math.cos(angle)\n        const py = cy + r * Math.sin(angle)\n        const dist = Math.sqrt((mx - px) ** 2 + (my - py) ** 2)\n        if (dist < bestDist && dist < hitRadius) {\n          bestDist = dist\n          best = { seriesIndex: series.index, pointIndex: i, distance: dist, x: px, y: py }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ResolvedOptions,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { group, circle } from '../../render/tree'\n\nexport interface BubbleOptions extends ResolvedOptions {\n  /** Sizes array per series. Each entry maps 1:1 to values. */\n  sizes?: number[][]\n  /** Min bubble radius in px. Default 4. */\n  minRadius?: number\n  /** Max bubble radius in px. Default 30. */\n  maxRadius?: number\n}\n\n// ---------------------------------------------------------------------------\n// Shared size normalization — used by both render() and hitTest()\n// ---------------------------------------------------------------------------\n\ninterface SizeNorm {\n  sizeMin: number\n  sizeRange: number\n  minR: number\n  maxR: number\n  allSizes: number[][]\n}\n\nfunction resolveSizeNorm(ctx: RenderContext): SizeNorm {\n  const bOpts = ctx.options as BubbleOptions\n  const minR = bOpts.minRadius ?? 4\n  const maxR = bOpts.maxRadius ?? 30\n\n  // Use explicit sizes, or fall back to using series values as sizes\n  let allSizes = bOpts.sizes ?? []\n  if (allSizes.length === 0) {\n    allSizes = ctx.data.series.map(s => s.values.map(v => Math.abs(v)))\n  }\n\n  let sizeMin = Infinity\n  let sizeMax = -Infinity\n  for (const sizes of allSizes) {\n    for (const s of sizes) {\n      if (s < sizeMin) sizeMin = s\n      if (s > sizeMax) sizeMax = s\n    }\n  }\n  if (!isFinite(sizeMin)) { sizeMin = 1; sizeMax = 1 }\n  const sizeRange = sizeMax - sizeMin || 1\n\n  return { sizeMin, sizeRange, minR, maxR, allSizes }\n}\n\nfunction normalizeRadius(rawSize: number, norm: SizeNorm): number {\n  const normalized = (rawSize - norm.sizeMin) / norm.sizeRange\n  return norm.minR + normalized * (norm.maxR - norm.minR)\n}\n\n/**\n * Bubble chart — scatter with variable-radius circles.\n * Pass sizes via options: `{ sizes: [[10, 20, 5, ...], ...] }`\n */\nexport const bubbleChartType = defineChartType({\n  type: 'bubble',\n\n\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n    const norm = resolveSizeNorm(ctx)\n\n    for (const series of data.series) {\n      const sizes = norm.allSizes[series.index] ?? []\n      const dots: RenderNode[] = []\n\n      for (let i = 0; i < series.values.length; i++) {\n        const x = xScale.map(i)\n        const y = yScale.map(series.values[i]!)\n        const rawSize = sizes[i] ?? 1\n        const r = normalizeRadius(rawSize, norm)\n\n        dots.push(circle(x, y, r, {\n          class: 'chartts-bubble',\n          fill: series.color,\n          fillOpacity: 0.5,\n          stroke: series.color,\n          strokeWidth: 1.5,\n          'data-series': series.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name}: ${series.values[i]} (size: ${rawSize})`,\n        }))\n      }\n\n      nodes.push(group(dots, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale } = ctx\n    const norm = resolveSizeNorm(ctx)\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    for (const series of data.series) {\n      const sizes = norm.allSizes[series.index] ?? []\n      for (let i = 0; i < series.values.length; i++) {\n        const x = xScale.map(i)\n        const y = yScale.map(series.values[i]!)\n        const rawSize = sizes[i] ?? 1\n        const r = normalizeRadius(rawSize, norm)\n\n        const dist = Math.sqrt((mx - x) ** 2 + (my - y) ** 2)\n        if (dist < r + 4 && dist < bestDist) {\n          bestDist = dist\n          best = { seriesIndex: series.index, pointIndex: i, distance: dist, x, y }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\nexport interface CandlestickOptions extends ResolvedOptions {\n  /** OHLC data: { open, high, low, close } arrays. */\n  ohlc?: {\n    open: number[]\n    high: number[]\n    low: number[]\n    close: number[]\n  }\n  /** Up candle color. Default green. */\n  upColor?: string\n  /** Down candle color. Default red. */\n  downColor?: string\n  /** Wick width. Default 1.5. */\n  wickWidth?: number\n}\n\n/**\n * Candlestick / OHLC chart for financial data.\n *\n * Pass OHLC data via options:\n * ```ts\n * Candlestick('#el', {\n *   data: { labels: ['Mon','Tue','Wed'], series: [{ name: 'AAPL', values: [150, 152, 148] }] },\n *   ohlc: {\n *     open:  [148, 150, 152],\n *     high:  [153, 155, 154],\n *     low:   [146, 149, 147],\n *     close: [150, 152, 148],\n *   }\n * })\n * ```\n * The series values are used as close prices for scale computation.\n */\nexport const candlestickChartType = defineChartType({\n  type: 'candlestick',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const cOpts = options as CandlestickOptions\n    let ohlc = cOpts.ohlc\n\n    // Auto-detect OHLC from 4 series named Open/High/Low/Close\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n\n    // Expand bounds to include all OHLC values\n    const prepared = prepareData(data, options)\n\n    if (ohlc) {\n      let yMin = prepared.bounds.yMin\n      let yMax = prepared.bounds.yMax\n      for (let i = 0; i < ohlc.high.length; i++) {\n        if (ohlc.high[i]! < yMin) yMin = ohlc.high[i]!\n        if (ohlc.high[i]! > yMax) yMax = ohlc.high[i]!\n        if (ohlc.low[i]! < yMin) yMin = ohlc.low[i]!\n        if (ohlc.low[i]! > yMax) yMax = ohlc.low[i]!\n      }\n      prepared.bounds.yMin = yMin\n      prepared.bounds.yMax = yMax\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const cOpts = options as CandlestickOptions\n    let ohlc = cOpts.ohlc\n\n    // Auto-detect OHLC from 4 series named Open/High/Low/Close\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n\n    if (!ohlc) return nodes\n\n    const series = data.series[0]\n    if (!series) return nodes\n\n    const upColor = cOpts.upColor ?? 'var(--color-emerald-500, #10b981)'\n    const downColor = cOpts.downColor ?? 'var(--color-red-500, #ef4444)'\n    const wickWidth = cOpts.wickWidth ?? 1.5\n\n    // Get bandwidth for candle width\n    const bw = getBandwidth(xScale)\n    const candleWidth = bw * 0.6\n\n    const candleNodes: RenderNode[] = []\n\n    for (let i = 0; i < ohlc.open.length; i++) {\n      const open = ohlc.open[i]!\n      const high = ohlc.high[i]!\n      const low = ohlc.low[i]!\n      const close = ohlc.close[i]!\n\n      const cx = xScale.map(i)\n      const isUp = close >= open\n      const color = isUp ? upColor : downColor\n\n      const yHigh = yScale.map(high)\n      const yLow = yScale.map(low)\n      const yOpen = yScale.map(open)\n      const yClose = yScale.map(close)\n\n      const bodyTop = Math.min(yOpen, yClose)\n      const bodyHeight = Math.max(Math.abs(yOpen - yClose), 1)\n\n      // Wick (high-low line)\n      candleNodes.push({\n        type: 'line',\n        x1: cx,\n        y1: yHigh,\n        x2: cx,\n        y2: yLow,\n        attrs: {\n          class: 'chartts-wick',\n          stroke: color,\n          strokeWidth: wickWidth,\n          'data-series': 0,\n          'data-index': i,\n        },\n      })\n\n      // Body (open-close rect)\n      candleNodes.push(rect(cx - candleWidth / 2, bodyTop, candleWidth, bodyHeight, {\n        rx: 2, ry: 2,\n        class: 'chartts-candle',\n        fill: isUp ? color : color,\n        stroke: color,\n        strokeWidth: 1,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? i}: O${open} H${high} L${low} C${close}`,\n      }))\n    }\n\n    nodes.push(group(candleNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, _my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const cOpts = options as CandlestickOptions\n    let ohlc = cOpts.ohlc\n\n    if (!ohlc && data.series.length >= 4) {\n      const byName: Record<string, number[]> = {}\n      for (const s of data.series) byName[s.name.toLowerCase()] = s.values\n      if (byName.open && byName.high && byName.low && byName.close) {\n        ohlc = { open: byName.open, high: byName.high, low: byName.low, close: byName.close }\n      }\n    }\n\n    if (!ohlc) return null\n\n    const bw = getBandwidth(xScale)\n    const candleWidth = bw * 0.6\n\n    for (let i = 0; i < ohlc.open.length; i++) {\n      const cx = xScale.map(i)\n      if (mx >= cx - candleWidth / 2 - 4 && mx <= cx + candleWidth / 2 + 4) {\n        return { seriesIndex: 0, pointIndex: i, distance: Math.abs(mx - cx), x: cx, y: yScale.map(ohlc.close[i]!) }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { path, circle, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\nexport interface GaugeOptions extends ResolvedOptions {\n  /** Minimum value. Default 0. */\n  gaugeMin?: number\n  /** Maximum value. Default 100. */\n  gaugeMax?: number\n  /** Show value text in center. Default true. */\n  showValue?: boolean\n  /** Value format function. Default: round to int. */\n  valueFormat?: (v: number) => string\n}\n\n/**\n * Gauge / Meter chart — single-value 240° arc with stroke-based rendering.\n *\n * Uses stroke-linecap:round for clean rounded endcaps. No fill-based donut arcs.\n * Looks like a modern dashboard gauge (Grafana, Material style).\n */\nexport const gaugeChartType = defineChartType({\n  type: 'gauge',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const gOpts = options as GaugeOptions\n    const min = gOpts.gaugeMin ?? 0\n    const max = gOpts.gaugeMax ?? 100\n    const showValue = gOpts.showValue ?? true\n    const valueFormat = gOpts.valueFormat ?? ((v: number) => String(Math.round(v)))\n\n    const value = series.values[0]!\n    const pct = Math.max(0, Math.min(1, (value - min) / (max - min || 1)))\n\n    // ----- Layout -----\n    const cx = area.x + area.width / 2\n\n    // Arc angles: 240° sweep, opening at the bottom\n    // Start at 150° (bottom-left), sweep CW to 30° (bottom-right)\n    const toRad = (d: number) => (d * Math.PI) / 180\n    const startRad = toRad(150)\n    const endRad = toRad(390)  // 390° = 30° but keeps sweep direction clear\n\n    // Size the arc to fit within the area with padding for labels\n    // The arc bottom-most points are at 150° and 30° — y = cy + r*sin(30°) = cy + r*0.5\n    // The arc top is at cy - r\n    // Below the arc we need ~50px for value text, label, min/max\n    const labelSpace = Math.min(60, area.height * 0.22)\n    const availH = area.height - labelSpace\n    // Arc top to arc bottom-endpoints: r + r*sin(30°) = r*1.5\n    // So r*1.5 + strokeW <= availH\n    const maxRadiusH = (availH - 8) / 1.55\n    const maxRadiusW = (area.width - 16) / 2\n    const radius = Math.min(maxRadiusH, maxRadiusW)\n    const strokeW = Math.max(12, Math.min(radius * 0.18, 28))\n\n    // Position: the top of the arc (cy - radius - strokeW/2) should be just inside area.y\n    const cy = area.y + radius + strokeW / 2 + 4\n\n    // Arc bottom-left/right y coordinate\n    const arcBottomY = cy + radius * Math.sin(toRad(30))\n\n    // ----- Track arc (background) -----\n    nodes.push(path(strokeArc(cx, cy, radius, startRad, endRad), {\n      class: 'chartts-gauge-track',\n      stroke: theme.gridColor,\n      strokeWidth: strokeW,\n      fill: 'none',\n      opacity: 0.3,\n      style: 'stroke-linecap:round',\n    }))\n\n    // ----- Value arc -----\n    const color = options.colors[0]!\n    if (pct > 0.005) {\n      const valueRad = startRad + (endRad - startRad) * pct\n      nodes.push(path(strokeArc(cx, cy, radius, startRad, valueRad), {\n        class: 'chartts-gauge-fill',\n        stroke: color,\n        strokeWidth: strokeW,\n        fill: 'none',\n        style: 'stroke-linecap:round',\n        'data-series': 0,\n        'data-index': 0,\n      }))\n    }\n\n    // ----- Needle -----\n    const needleAngle = startRad + (endRad - startRad) * pct\n    const needleLen = radius - strokeW / 2 - 2\n    const needleTipX = cx + needleLen * Math.cos(needleAngle)\n    const needleTipY = cy + needleLen * Math.sin(needleAngle)\n\n    // Tapered needle triangle\n    const baseR = 3.5\n    const bAngle1 = needleAngle + Math.PI / 2\n    const bAngle2 = needleAngle - Math.PI / 2\n    const npb = new PathBuilder()\n    npb.moveTo(needleTipX, needleTipY)\n    npb.lineTo(cx + baseR * Math.cos(bAngle1), cy + baseR * Math.sin(bAngle1))\n    npb.lineTo(cx + baseR * Math.cos(bAngle2), cy + baseR * Math.sin(bAngle2))\n    npb.close()\n\n    nodes.push(path(npb.build(), {\n      class: 'chartts-gauge-needle',\n      fill: color,\n      opacity: 0.85,\n    }))\n\n    // Center cap\n    nodes.push(circle(cx, cy, 5, {\n      class: 'chartts-gauge-needle-cap',\n      fill: color,\n    }))\n\n    // ----- Labels -----\n    if (showValue) {\n      // Big value — in the gap below the arc center\n      const valueFontSize = Math.max(16, Math.min(radius * 0.35, 40))\n      const valueY = arcBottomY + labelSpace * 0.28\n      nodes.push(text(cx, valueY, valueFormat(value), {\n        class: 'chartts-gauge-value',\n        fill: theme.textColor,\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize: valueFontSize,\n        fontFamily: theme.fontFamily,\n        fontWeight: 700,\n      }))\n\n      // Series name\n      if (series.name) {\n        nodes.push(text(cx, valueY + valueFontSize * 0.85, series.name, {\n          class: 'chartts-gauge-label',\n          fill: theme.textMuted,\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize: theme.fontSizeSmall,\n          fontFamily: theme.fontFamily,\n        }))\n      }\n\n      // Min / Max at arc endpoints\n      const minX = cx + radius * Math.cos(startRad)\n      const minY = cy + radius * Math.sin(startRad) + strokeW / 2 + 12\n      nodes.push(text(minX, minY, valueFormat(min), {\n        class: 'chartts-gauge-min',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      const maxX = cx + radius * Math.cos(toRad(30))\n      const maxY = cy + radius * Math.sin(toRad(30)) + strokeW / 2 + 12\n      nodes.push(text(maxX, maxY, valueFormat(max), {\n        class: 'chartts-gauge-max',\n        fill: theme.textMuted,\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    return nodes\n  },\n\n})\n\n/**\n * Stroke-based arc path (open, for use with thick stroke + stroke-linecap:round).\n * Angles in radians, CW from positive X axis (SVG convention).\n */\nfunction strokeArc(\n  cx: number, cy: number, r: number,\n  startAngle: number, endAngle: number,\n): string {\n  const pb = new PathBuilder()\n  const x1 = cx + r * Math.cos(startAngle)\n  const y1 = cy + r * Math.sin(startAngle)\n  const x2 = cx + r * Math.cos(endAngle)\n  const y2 = cy + r * Math.sin(endAngle)\n\n  let span = endAngle - startAngle\n  if (span < 0) span += 2 * Math.PI\n  const largeArc = span > Math.PI\n\n  pb.moveTo(x1, y1)\n  pb.arc(r, r, 0, largeArc, true, x2, y2)\n  return pb.build()\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\nexport interface WaterfallOptions extends ResolvedOptions {\n  /** Indices that represent totals (absolute, not cumulative). Default: last index. */\n  totals?: number[]\n  /** Up color. Default emerald. */\n  upColor?: string\n  /** Down color. Default red. */\n  downColor?: string\n  /** Total color. Default blue. */\n  totalColor?: string\n  /** Show connector lines between bars. Default true. */\n  connectors?: boolean\n}\n\n/**\n * Waterfall chart — running totals with floating bars.\n * Each value is a delta from the previous running total.\n * Positive = up (green), negative = down (red), totals = absolute (blue).\n */\nexport const waterfallChartType = defineChartType({\n  type: 'waterfall',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n\n    const wOpts = options as WaterfallOptions\n    const series = data.series[0]\n    if (!series) return prepared\n\n    const totals = new Set(wOpts.totals ?? [series.values.length - 1])\n\n    // Compute running totals to find proper y bounds\n    let running = 0\n    let yMin = 0\n    let yMax = 0\n    for (let i = 0; i < series.values.length; i++) {\n      if (totals.has(i)) {\n        running = series.values[i]!\n      } else {\n        running += series.values[i]!\n      }\n      if (running < yMin) yMin = running\n      if (running > yMax) yMax = running\n    }\n\n    // Include 0 in range\n    prepared.bounds.yMin = Math.min(0, yMin)\n    prepared.bounds.yMax = Math.max(0, yMax)\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, options, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const wOpts = options as WaterfallOptions\n    const totals = new Set(wOpts.totals ?? [series.values.length - 1])\n    const upColor = wOpts.upColor ?? 'var(--color-emerald-500, #10b981)'\n    const downColor = wOpts.downColor ?? 'var(--color-red-500, #ef4444)'\n    const totalColor = wOpts.totalColor ?? 'var(--color-blue-500, #3b82f6)'\n    const showConnectors = wOpts.connectors ?? true\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * 0.6\n    const barNodes: RenderNode[] = []\n    const connectorNodes: RenderNode[] = []\n\n    let running = 0\n    let prevTop = yScale.map(0)\n\n    for (let i = 0; i < series.values.length; i++) {\n      const val = series.values[i]!\n      const cx = xScale.map(i)\n      const isTotal = totals.has(i)\n\n      let barTop: number\n      let barBottom: number\n      let color: string\n\n      if (isTotal) {\n        // Total bar: from 0 to the value\n        running = val\n        barTop = yScale.map(Math.max(0, val))\n        barBottom = yScale.map(Math.min(0, val))\n        color = totalColor\n      } else {\n        // Delta bar: from running to running + val\n        const from = running\n        running += val\n        barTop = yScale.map(Math.max(from, running))\n        barBottom = yScale.map(Math.min(from, running))\n        color = val >= 0 ? upColor : downColor\n      }\n\n      const barH = Math.max(barBottom - barTop, 1)\n\n      barNodes.push(rect(cx - barWidth / 2, barTop, barWidth, barH, {\n        rx: 3, ry: 3,\n        class: 'chartts-waterfall-bar',\n        fill: color,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? i}: ${val}${isTotal ? ' (total)' : ''}`,\n      }))\n\n      // Connector line from previous bar's end to this bar's start\n      if (showConnectors && i > 0 && !isTotal) {\n        connectorNodes.push({\n          type: 'line',\n          x1: xScale.map(i - 1) + barWidth / 2,\n          y1: prevTop,\n          x2: cx - barWidth / 2,\n          y2: prevTop,\n          attrs: {\n            class: 'chartts-waterfall-connector',\n            stroke: theme.gridColor,\n            strokeWidth: 1,\n            strokeDasharray: '3,2',\n          },\n        })\n      }\n\n      prevTop = barTop\n    }\n\n    if (connectorNodes.length > 0) {\n      nodes.push(group(connectorNodes, { class: 'chartts-waterfall-connectors' }))\n    }\n\n    nodes.push(group(barNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': series.name,\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, _my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const series = data.series[0]\n    if (!series) return null\n\n    const wOpts = options as WaterfallOptions\n    const totals = new Set(wOpts.totals ?? [series.values.length - 1])\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * 0.6\n\n    let running = 0\n    for (let i = 0; i < series.values.length; i++) {\n      const val = series.values[i]!\n      const isTotal = totals.has(i)\n      if (isTotal) {\n        running = val\n      } else {\n        running += val\n      }\n\n      const cx = xScale.map(i)\n      if (mx >= cx - barWidth / 2 - 4 && mx <= cx + barWidth / 2 + 4) {\n        return { seriesIndex: 0, pointIndex: i, distance: Math.abs(mx - cx), x: cx, y: yScale.map(running) }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\nexport interface FunnelOptions extends ResolvedOptions {\n  /** Gap between steps in px. Default 2. */\n  stepGap?: number\n  /** Show percentage labels. Default true. */\n  showLabels?: boolean\n  /** Show value labels. Default true. */\n  showValues?: boolean\n}\n\n/**\n * Funnel chart — tapered horizontal bars representing conversion steps.\n * Uses the first series. Values should be descending (largest to smallest).\n */\nexport const funnelChartType = defineChartType({\n  type: 'funnel',\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const fOpts = options as FunnelOptions\n    const stepGap = fOpts.stepGap ?? 4\n    const showLabels = fOpts.showLabels ?? true\n    const showValues = fOpts.showValues ?? true\n\n    const values = series.values\n    const maxVal = Math.max(...values.map(Math.abs))\n    if (maxVal === 0) return nodes\n\n    const stepCount = values.length\n    const totalGap = stepGap * (stepCount - 1)\n    const stepHeight = (area.height - totalGap) / stepCount\n    const centerX = area.x + area.width / 2\n\n    for (let i = 0; i < stepCount; i++) {\n      const val = Math.abs(values[i]!)\n      const nextVal = i < stepCount - 1 ? Math.abs(values[i + 1]!) : val * 0.7\n\n      const topWidth = (val / maxVal) * area.width\n      const bottomWidth = (nextVal / maxVal) * area.width\n      const y = area.y + i * (stepHeight + stepGap)\n\n      const color = options.colors[i % options.colors.length]!\n\n      // Trapezoid path\n      const pb = new PathBuilder()\n      pb.moveTo(centerX - topWidth / 2, y)\n      pb.lineTo(centerX + topWidth / 2, y)\n      pb.lineTo(centerX + bottomWidth / 2, y + stepHeight)\n      pb.lineTo(centerX - bottomWidth / 2, y + stepHeight)\n      pb.close()\n\n      const stepNodes: RenderNode[] = []\n\n      const colorIndex = i % options.colors.length\n      stepNodes.push(path(pb.build(), {\n        class: 'chartts-funnel-step',\n        fill: `url(#chartts-bar-${colorIndex})`,\n        stroke: color,\n        strokeWidth: 0.5,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? `Step ${i + 1}`}: ${values[i]}`,\n      }))\n\n      // Label text\n      const textY = y + stepHeight / 2\n      if (showLabels) {\n        const label = String(data.labels[i] ?? `Step ${i + 1}`)\n        const pct = maxVal > 0 ? Math.round((val / maxVal) * 100) : 0\n\n        const labelStr = showValues\n          ? `${label}: ${values[i]} (${pct}%)`\n          : `${label} (${pct}%)`\n\n        stepNodes.push(text(centerX, textY, labelStr, {\n          class: 'chartts-funnel-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize: theme.fontSize,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n      }\n\n      nodes.push(group(stepNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i] ?? `Step ${i + 1}`),\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, _mx: number, my: number): HitResult | null {\n    const { data, area, options } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const fOpts = options as FunnelOptions\n    const stepGap = fOpts.stepGap ?? 2\n    const stepCount = series.values.length\n    const totalGap = stepGap * (stepCount - 1)\n    const stepHeight = (area.height - totalGap) / stepCount\n\n    for (let i = 0; i < stepCount; i++) {\n      const y = area.y + i * (stepHeight + stepGap)\n      if (my >= y && my <= y + stepHeight) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: area.x + area.width / 2, y: y + stepHeight / 2 }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, path } from '../../render/tree'\nimport { formatNum } from '../../utils/format'\nimport { getBandwidth } from '../../utils/scale'\n\nexport const barChartType = defineChartType({\n  type: 'bar',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n\n    // Bar charts should always include 0 in the y-axis range\n    // unless the user explicitly set yMin/yMax\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n    if (options.yMax === undefined && prepared.bounds.yMax < 0) {\n      prepared.bounds.yMax = 0\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return nodes\n\n    const bw = getBandwidth(xScale)\n    const groupWidth = bw * (1 - options.barGap)\n    const barWidth = groupWidth / seriesCount\n    const groupOffset = -groupWidth / 2\n\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    for (const series of data.series) {\n      const barNodes: RenderNode[] = []\n\n      for (let i = 0; i < series.values.length; i++) {\n        const cx = xScale.map(i)\n        const barX = cx + groupOffset + series.index * barWidth\n        const vy = yScale.map(series.values[i]!)\n\n        // Handle positive and negative values\n        const y = series.values[i]! >= 0 ? vy : baseline\n        const h = Math.abs(vy - baseline)\n\n        const r = Math.min(options.barRadius, barWidth / 2, h / 2)\n        const isPositive = series.values[i]! >= 0\n\n        const barFill = `url(#chartts-bar-${series.index})`\n\n        if (r > 0 && h > r * 2) {\n          const d = isPositive\n            ? `M${formatNum(barX)},${formatNum(y + h)}V${formatNum(y + r)}Q${formatNum(barX)},${formatNum(y)},${formatNum(barX + r)},${formatNum(y)}H${formatNum(barX + barWidth - r)}Q${formatNum(barX + barWidth)},${formatNum(y)},${formatNum(barX + barWidth)},${formatNum(y + r)}V${formatNum(y + h)}Z`\n            : `M${formatNum(barX)},${formatNum(y)}V${formatNum(y + h - r)}Q${formatNum(barX)},${formatNum(y + h)},${formatNum(barX + r)},${formatNum(y + h)}H${formatNum(barX + barWidth - r)}Q${formatNum(barX + barWidth)},${formatNum(y + h)},${formatNum(barX + barWidth)},${formatNum(y + h - r)}V${formatNum(y)}Z`\n\n          barNodes.push(path(d, {\n            class: 'chartts-bar',\n            fill: barFill,\n            'data-series': series.index,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${series.values[i]}`,\n          }))\n        } else {\n          barNodes.push(rect(barX, y, barWidth, h, {\n            class: 'chartts-bar',\n            fill: barFill,\n            'data-series': series.index,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${series.values[i]}`,\n          }))\n        }\n      }\n\n      nodes.push(group(barNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  getHighlightNodes(ctx: RenderContext, hit: HitResult): RenderNode[] {\n    const { data, xScale, yScale, options } = ctx\n    const seriesCount = data.series.length\n    const bw = getBandwidth(xScale)\n    const groupWidth = bw * (1 - options.barGap)\n    const barWidth = groupWidth / seriesCount\n    const groupOffset = -groupWidth / 2\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    const series = data.series[hit.seriesIndex]\n    if (!series) return []\n    const i = hit.pointIndex\n    const cx = xScale.map(i)\n    const barX = cx + groupOffset + series.index * barWidth\n    const vy = yScale.map(series.values[i]!)\n    const y = series.values[i]! >= 0 ? vy : baseline\n    const h = Math.abs(vy - baseline)\n\n    // Bright outline around the hovered bar\n    return [\n      rect(barX - 1, y - 1, barWidth + 2, h + 2, {\n        class: 'chartts-highlight-bar',\n        fill: 'none',\n        stroke: series.color,\n        strokeWidth: 2,\n        strokeOpacity: 0.8,\n      }),\n    ]\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return null\n\n    const bw = getBandwidth(xScale)\n    const groupWidth = bw * (1 - options.barGap)\n    const barWidth = groupWidth / seriesCount\n    const groupOffset = -groupWidth / 2\n    const baseline = yScale.map(Math.max(0, yScale.getDomain()[0] as number))\n\n    let best: HitResult | null = null\n    let bestDist = Infinity\n\n    for (const series of data.series) {\n      for (let i = 0; i < series.values.length; i++) {\n        const cx = xScale.map(i)\n        const barX = cx + groupOffset + series.index * barWidth\n        const vy = yScale.map(series.values[i]!)\n        const y = series.values[i]! >= 0 ? vy : baseline\n        const h = Math.abs(vy - baseline)\n\n        // Check if mouse is inside bar bounds (with small padding)\n        if (mx >= barX - 2 && mx <= barX + barWidth + 2 && my >= y - 2 && my <= y + h + 2) {\n          const dist = 0\n          if (dist < bestDist) {\n            bestDist = dist\n            best = { seriesIndex: series.index, pointIndex: i, distance: dist, x: cx, y: vy }\n          }\n        }\n      }\n    }\n\n    return best\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, path } from '../../render/tree'\nimport { formatNum } from '../../utils/format'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Stacked bar chart — all series at the same x position are stacked vertically.\n */\nexport const stackedBarChartType = defineChartType({\n  type: 'stacked-bar',\n  useBandScale: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, options)\n\n    // y-axis range should cover cumulative totals per x-index\n    const pointCount = prepared.series[0]?.values.length ?? 0\n    let maxTotal = 0\n    let minTotal = 0\n\n    for (let i = 0; i < pointCount; i++) {\n      let posSum = 0\n      let negSum = 0\n      for (const s of prepared.series) {\n        const v = s.values[i] ?? 0\n        if (v >= 0) posSum += v\n        else negSum += v\n      }\n      if (posSum > maxTotal) maxTotal = posSum\n      if (negSum < minTotal) minTotal = negSum\n    }\n\n    if (options.yMin === undefined) prepared.bounds.yMin = Math.min(0, minTotal)\n    if (options.yMax === undefined) prepared.bounds.yMax = Math.max(0, maxTotal)\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale } = ctx\n    const nodes: RenderNode[] = []\n\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return nodes\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const barOffset = -barWidth / 2\n    const baseline = yScale.map(0)\n\n    for (let i = 0; i < pointCount; i++) {\n      let posY = baseline  // tracks current top of positive stack\n      let negY = baseline  // tracks current bottom of negative stack\n\n      for (const series of data.series) {\n        const value = series.values[i] ?? 0\n        if (value === 0) continue\n\n        const cx = xScale.map(i)\n        const barX = cx + barOffset\n        const vy = yScale.map(Math.abs(value))\n        const h = Math.abs(vy - baseline)\n\n        let y: number\n        if (value >= 0) {\n          y = posY - h\n          posY = y\n        } else {\n          y = negY\n          negY = y + h\n        }\n\n        const barFill = `url(#chartts-bar-${series.index})`\n        const r = Math.min(options.barRadius, barWidth / 2, h / 2)\n\n        const barNode = (r > 0 && h > r * 2)\n          ? path(\n              `M${formatNum(barX)},${formatNum(y + h)}V${formatNum(y + r)}Q${formatNum(barX)},${formatNum(y)},${formatNum(barX + r)},${formatNum(y)}H${formatNum(barX + barWidth - r)}Q${formatNum(barX + barWidth)},${formatNum(y)},${formatNum(barX + barWidth)},${formatNum(y + r)}V${formatNum(y + h)}Z`,\n              {\n                class: 'chartts-bar',\n                fill: barFill,\n                'data-series': series.index,\n                'data-index': i,\n                tabindex: 0,\n                role: 'img',\n                ariaLabel: `${series.name}: ${value}`,\n              },\n            )\n          : rect(barX, y, barWidth, h, {\n              class: 'chartts-bar',\n              fill: barFill,\n              'data-series': series.index,\n              'data-index': i,\n              tabindex: 0,\n              role: 'img',\n              ariaLabel: `${series.name}: ${value}`,\n            })\n\n        // Wrap each series segment in its own group for hover isolation\n        nodes.push(group([barNode], {\n          class: `chartts-series chartts-series-${series.index}`,\n          'data-series-name': series.name,\n        }))\n      }\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return null\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const barOffset = -barWidth / 2\n    const baseline = yScale.map(0)\n\n    for (let i = 0; i < pointCount; i++) {\n      const cx = xScale.map(i)\n      const barX = cx + barOffset\n\n      if (mx < barX - 2 || mx > barX + barWidth + 2) continue\n\n      let posY = baseline\n      let negY = baseline\n\n      for (const series of data.series) {\n        const value = series.values[i] ?? 0\n        if (value === 0) continue\n\n        const vy = yScale.map(Math.abs(value))\n        const h = Math.abs(vy - baseline)\n        let y: number\n        if (value >= 0) { y = posY - h; posY = y }\n        else { y = negY; negY = y + h }\n\n        if (my >= y - 2 && my <= y + h + 2) {\n          return { seriesIndex: series.index, pointIndex: i, distance: 0, x: cx, y }\n        }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, path, text } from '../../render/tree'\nimport { formatNum } from '../../utils/format'\nimport { createHorizontalMapper } from '../../utils/scale'\n\n/**\n * Horizontal bar chart — bars grow left-to-right.\n *\n * Uses the xScale for categories (mapped to y positions) and yScale for values\n * (mapped to x positions), but transposes the rendering.\n */\nexport const horizontalBarChartType = defineChartType({\n  type: 'horizontal-bar',\n  useBandScale: true,\n  suppressAxes: true,\n\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    const prepared = prepareData(data, {\n      ...options,\n      xAxis: false,\n      yAxis: false,\n      xGrid: false,\n      yGrid: false,\n      legend: false,\n    })\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n    if (options.yMax === undefined && prepared.bounds.yMax < 0) {\n      prepared.bounds.yMax = 0\n    }\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, options, yScale, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return nodes\n\n    // Reserve space for category labels on the left\n    const labelWidth = Math.min(70, area.width * 0.2)\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n\n    // In horizontal mode:\n    // - Y axis becomes categories\n    // - X axis becomes value axis (use yScale for values mapped to x positions)\n    const categoryHeight = area.height / pointCount\n    const barGap = options.barGap\n    const groupHeight = categoryHeight * (1 - barGap)\n    const barHeight = groupHeight / seriesCount\n    const groupOffset = -groupHeight / 2\n\n    const valueToX = createHorizontalMapper(yScale, area, chartX, chartW)\n    const zeroX = valueToX(0)\n\n    // Category labels on the left\n    for (let i = 0; i < pointCount; i++) {\n      const catCenter = area.y + categoryHeight * (i + 0.5)\n      nodes.push(text(area.x + labelWidth - 6, catCenter, String(data.labels[i] ?? ''), {\n        class: 'chartts-hbar-label',\n        fill: theme.textMuted,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n\n    for (const series of data.series) {\n      const barNodes: RenderNode[] = []\n\n      for (let i = 0; i < series.values.length; i++) {\n        const catCenter = area.y + categoryHeight * (i + 0.5)\n        const barY = catCenter + groupOffset + series.index * barHeight\n        const vx = valueToX(series.values[i]!)\n\n        const x = Math.min(vx, zeroX)\n        const w = Math.abs(vx - zeroX)\n        const isPositive = series.values[i]! >= 0\n\n        const barFill = `url(#chartts-bar-${series.index})`\n        const r = Math.min(options.barRadius, barHeight / 2, w / 2)\n\n        if (r > 0 && w > r * 2) {\n          // Rounded right end for positive, left end for negative\n          const d = isPositive\n            ? `M${formatNum(x)},${formatNum(barY)}H${formatNum(x + w - r)}Q${formatNum(x + w)},${formatNum(barY)},${formatNum(x + w)},${formatNum(barY + r)}V${formatNum(barY + barHeight - r)}Q${formatNum(x + w)},${formatNum(barY + barHeight)},${formatNum(x + w - r)},${formatNum(barY + barHeight)}H${formatNum(x)}Z`\n            : `M${formatNum(x + w)},${formatNum(barY)}H${formatNum(x + r)}Q${formatNum(x)},${formatNum(barY)},${formatNum(x)},${formatNum(barY + r)}V${formatNum(barY + barHeight - r)}Q${formatNum(x)},${formatNum(barY + barHeight)},${formatNum(x + r)},${formatNum(barY + barHeight)}H${formatNum(x + w)}Z`\n\n          barNodes.push(path(d, {\n            class: 'chartts-bar chartts-bar-horizontal',\n            fill: barFill,\n            'data-series': series.index,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${series.values[i]}`,\n          }))\n        } else {\n          barNodes.push(rect(x, barY, w, barHeight, {\n            class: 'chartts-bar chartts-bar-horizontal',\n            fill: barFill,\n            'data-series': series.index,\n            'data-index': i,\n            tabindex: 0,\n            role: 'img',\n            ariaLabel: `${series.name}: ${series.values[i]}`,\n          }))\n        }\n      }\n\n      nodes.push(group(barNodes, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area, options, yScale } = ctx\n    const seriesCount = data.series.length\n    const pointCount = data.series[0]?.values.length ?? 0\n    if (pointCount === 0) return null\n\n    const labelWidth = Math.min(70, area.width * 0.2)\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n    const categoryHeight = area.height / pointCount\n    const groupHeight = categoryHeight * (1 - options.barGap)\n    const barHeight = groupHeight / seriesCount\n    const groupOffset = -groupHeight / 2\n\n    const valueToX = createHorizontalMapper(yScale, area, chartX, chartW)\n    const zeroX = valueToX(0)\n\n    for (const series of data.series) {\n      for (let i = 0; i < series.values.length; i++) {\n        const catCenter = area.y + categoryHeight * (i + 0.5)\n        const barY = catCenter + groupOffset + series.index * barHeight\n        const vx = valueToX(series.values[i]!)\n        const x = Math.min(vx, zeroX)\n        const w = Math.abs(vx - zeroX)\n\n        if (mx >= x - 2 && mx <= x + w + 2 && my >= barY - 2 && my <= barY + barHeight + 2) {\n          return { seriesIndex: series.index, pointIndex: i, distance: 0, x: vx, y: catCenter }\n        }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ResolvedOptions,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, path, text } from '../../render/tree'\nimport { roundedSlicePath } from '../../utils/slice-path'\n\nexport interface PieOptions extends ResolvedOptions {\n  /** Inner radius ratio (0 = pie, 0.5+ = donut). Default 0.08 (small center gap). */\n  innerRadius?: number\n  /** Uniform pixel gap between slices. Default 4. */\n  gap?: number\n  /** Corner radius in px for rounded slice edges. Default 6. */\n  cornerRadius?: number\n  /** Show value labels on slices. Default true. */\n  showLabels?: boolean\n}\n\n// ---------------------------------------------------------------------------\n// Pie chart type\n// ---------------------------------------------------------------------------\n\nexport const pieChartType = defineChartType({\n  type: 'pie',\n  suppressAxes: true,\n  prepareData: (data, options) => prepareNoAxes(data, options),\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const values = series.values\n    const total = values.reduce((sum, v) => sum + Math.abs(v), 0)\n    if (total === 0) return nodes\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 2\n    const opts = ctx.options as PieOptions\n    const innerRatio = opts.innerRadius ?? 0.08\n    const innerR = outerR * Math.max(0, Math.min(0.9, innerRatio))\n    const gapPx = opts.gap ?? 4\n    const halfGap = gapPx / 2\n    const cornerRadius = opts.cornerRadius ?? 6\n    const showLabels = opts.showLabels ?? true\n\n    // Angular gap offsets per radius.\n    // At the outer edge, uniform pixel gap is straightforward.\n    // At the inner edge, clamp the pad angle so it never eats more than 15%\n    // of the smallest slice — otherwise the inner path self-intersects.\n    // When innerR is tiny, use the same angle as outer (gap tapers to center).\n    const outerPadAngle = halfGap / outerR\n    const rawInnerPad = innerR > 0 ? halfGap / innerR : 0\n    const innerPadAngle = Math.min(rawInnerPad, outerPadAngle * 3)\n\n    let startAngle = -Math.PI / 2\n\n    for (let i = 0; i < values.length; i++) {\n      const value = Math.abs(values[i]!)\n      const sliceAngle = (value / total) * Math.PI * 2\n      const endAngle = startAngle + sliceAngle\n\n      // Check if slice is too small to render with gap\n      if (sliceAngle < outerPadAngle * 2 + 0.01) {\n        startAngle = endAngle\n        continue\n      }\n\n      // Per-slice clamp: inner pad must not exceed 15% of the slice angle\n      const sliceInnerPad = Math.min(innerPadAngle, sliceAngle * 0.15)\n\n      const d = roundedSlicePath(\n        cx, cy, outerR, innerR,\n        startAngle + outerPadAngle, endAngle - outerPadAngle,\n        startAngle + sliceInnerPad, endAngle - sliceInnerPad,\n        cornerRadius,\n      )\n\n      const colorIndex = i % ctx.options.colors.length\n      const sliceNodes: RenderNode[] = [\n        path(d, {\n          class: 'chartts-slice',\n          fill: `url(#chartts-pie-${colorIndex})`,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? `Slice ${i + 1}`}: ${values[i]}`,\n        }),\n      ]\n\n      // Label\n      if (showLabels && sliceAngle > 0.3) {\n        const midAngle = (startAngle + endAngle) / 2\n        const labelR = (outerR + innerR) / 2\n        const lx = cx + labelR * Math.cos(midAngle)\n        const ly = cy + labelR * Math.sin(midAngle)\n        const pct = Math.round((value / total) * 100)\n\n        sliceNodes.push(text(lx, ly, `${pct}%`, {\n          class: 'chartts-slice-label',\n          fill: '#fff',\n          textAnchor: 'middle',\n          dominantBaseline: 'central',\n          fontSize: theme.fontSizeSmall,\n          fontFamily: theme.fontFamily,\n          fontWeight: 600,\n        }))\n      }\n\n      nodes.push(group(sliceNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': String(data.labels[i] ?? `Slice ${i + 1}`),\n      }))\n\n      startAngle = endAngle\n    }\n\n    return nodes\n  },\n\n  getHighlightNodes(ctx: RenderContext, hit: HitResult): RenderNode[] {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return []\n\n    const values = series.values\n    const total = values.reduce((sum, v) => sum + Math.abs(v), 0)\n    if (total === 0) return []\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 2\n    const opts = ctx.options as PieOptions\n    const innerRatio = opts.innerRadius ?? 0.08\n    const innerR = outerR * Math.max(0, Math.min(0.9, innerRatio))\n\n    // Find the hit slice angles\n    let startAngle = -Math.PI / 2\n    for (let i = 0; i < values.length; i++) {\n      const sliceAngle = (Math.abs(values[i]!) / total) * Math.PI * 2\n      const endAngle = startAngle + sliceAngle\n      if (i === hit.pointIndex) {\n        // Draw a bright outline around this slice\n        const d = roundedSlicePath(cx, cy, outerR + 3, innerR - 2, startAngle, endAngle, startAngle, endAngle, 0)\n        return [\n          path(d, {\n            class: 'chartts-highlight-slice',\n            fill: 'none',\n            stroke: series.color,\n            strokeWidth: 2,\n            strokeOpacity: 0.8,\n          }),\n        ]\n      }\n      startAngle = endAngle\n    }\n    return []\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const cx = area.x + area.width / 2\n    const cy = area.y + area.height / 2\n    const outerR = Math.min(area.width, area.height) / 2 - 2\n    const innerRatio = (ctx.options as PieOptions).innerRadius ?? 0.08\n    const innerR = outerR * Math.max(0, Math.min(0.9, innerRatio))\n\n    const dx = mx - cx\n    const dy = my - cy\n    const dist = Math.sqrt(dx * dx + dy * dy)\n\n    if (dist > outerR || dist < innerR) return null\n\n    let angle = Math.atan2(dy, dx)\n    if (angle < -Math.PI / 2) angle += Math.PI * 2\n\n    const values = series.values\n    const total = values.reduce((sum, v) => sum + Math.abs(v), 0)\n    if (total === 0) return null\n\n    let startAngle = -Math.PI / 2\n    for (let i = 0; i < values.length; i++) {\n      const sliceAngle = (Math.abs(values[i]!) / total) * Math.PI * 2\n      const endAngle = startAngle + sliceAngle\n\n      if (angle >= startAngle && angle < endAngle) {\n        const midAngle = (startAngle + endAngle) / 2\n        const midR = (innerR + outerR) / 2\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: cx + midR * Math.cos(midAngle), y: cy + midR * Math.sin(midAngle) }\n      }\n\n      startAngle = endAngle\n    }\n\n    return null\n  },\n})\n\n/** Donut chart = pie with innerRadius */\nexport const donutChartType = defineChartType({\n  ...pieChartType,\n  type: 'donut',\n  suppressAxes: true,\n  render(ctx: RenderContext): RenderNode[] {\n    const opts = ctx.options as PieOptions\n    if (!opts.innerRadius || opts.innerRadius < 0.3) {\n      const donutCtx = {\n        ...ctx,\n        options: { ...ctx.options, innerRadius: 0.55 } as typeof ctx.options,\n      }\n      return pieChartType.render(donutCtx)\n    }\n    return pieChartType.render(ctx)\n  },\n})\n","import type {\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { group, circle } from '../../render/tree'\nimport { nearestPointHitTest } from '../../utils/hit-test'\n\nexport const scatterChartType = defineChartType({\n  type: 'scatter',\n\n\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, xScale, yScale, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    for (const series of data.series) {\n      const dots: RenderNode[] = []\n\n      for (let i = 0; i < series.values.length; i++) {\n        const x = xScale.map(i)\n        const y = yScale.map(series.values[i]!)\n\n        // Ambient glow\n        dots.push(circle(x, y, (theme.pointRadius + 1.5) * 2.5, {\n          class: 'chartts-dot-glow',\n          fill: `url(#chartts-pglow-${series.index})`,\n        }))\n\n        dots.push(circle(x, y, theme.pointRadius + 1.5, {\n          class: 'chartts-dot',\n          fill: series.color,\n          fillOpacity: 0.7,\n          stroke: series.color,\n          strokeWidth: 1.5,\n          'data-series': series.index,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${series.name}: ${series.values[i]}`,\n        }))\n      }\n\n      nodes.push(group(dots, {\n        class: `chartts-series chartts-series-${series.index}`,\n        'data-series-name': series.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    return nearestPointHitTest(ctx, mx, my, ctx.theme.pointRadius + 8)\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, text, path, line } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Gantt chart — horizontal task bars on a timeline.\n *\n * Data convention:\n * - labels: task names\n * - series[0].values: start values (day offsets or timestamps)\n * - series[1].values: end values\n * - series[2].values (optional): progress 0-100\n *\n * When start === end, renders a milestone diamond.\n */\n\nexport const ganttChartType = defineChartType({\n  type: 'gantt',\n  suppressAxes: true,\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const startSeries = data.series[0]\n    const endSeries = data.series[1]\n    if (!startSeries || !endSeries) return nodes\n\n    const progressSeries = data.series[2]\n    const taskCount = data.labels.length\n    if (taskCount === 0) return nodes\n\n    // Find time range\n    let tMin = Infinity\n    let tMax = -Infinity\n    for (let i = 0; i < taskCount; i++) {\n      const s = startSeries.values[i] ?? 0\n      const e = endSeries.values[i] ?? 0\n      if (s < tMin) tMin = s\n      if (e > tMax) tMax = e\n    }\n    if (tMin === tMax) tMax = tMin + 1\n\n    const labelWidth = area.width * 0.22\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n    const rowH = area.height / Math.max(taskCount, 1)\n    const barH = Math.min(rowH * 0.55, 28)\n    const tRange = tMax - tMin\n\n    // Grid lines (vertical time ticks)\n    const gridNodes: RenderNode[] = []\n    const tickCount = Math.min(Math.max(Math.floor(chartW / 60), 3), 10)\n    for (let t = 0; t <= tickCount; t++) {\n      const frac = t / tickCount\n      const x = chartX + frac * chartW\n      gridNodes.push(line(x, area.y, x, area.y + area.height, {\n        stroke: theme.gridColor,\n        strokeWidth: 0.5,\n        strokeDasharray: '3,3',\n      }))\n      // Time label at bottom\n      const val = Math.round(tMin + frac * tRange)\n      gridNodes.push(text(x, area.y + area.height + 14, String(val), {\n        fill: theme.textColor,\n        textAnchor: 'middle',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n    }\n    nodes.push(group(gridNodes, { class: 'chartts-gantt-grid' }))\n\n    // Row separators\n    const sepNodes: RenderNode[] = []\n    for (let i = 1; i < taskCount; i++) {\n      const y = area.y + i * rowH\n      sepNodes.push(line(chartX, y, chartX + chartW, y, {\n        stroke: theme.gridColor,\n        strokeWidth: 0.5,\n      }))\n    }\n    if (sepNodes.length > 0) {\n      nodes.push(group(sepNodes, { class: 'chartts-gantt-rows' }))\n    }\n\n    // Task bars\n    const barNodes: RenderNode[] = []\n    for (let i = 0; i < taskCount; i++) {\n      const s = startSeries.values[i] ?? 0\n      const e = endSeries.values[i] ?? 0\n      const progress = progressSeries ? (progressSeries.values[i] ?? 0) : -1\n      const color = options.colors[i % options.colors.length]!\n\n      const cy = area.y + i * rowH + rowH / 2\n\n      // Task label\n      barNodes.push(text(chartX - 8, cy, String(data.labels[i] ?? ''), {\n        fill: theme.textColor,\n        textAnchor: 'end',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      if (s === e) {\n        // Milestone — diamond shape\n        const mx = chartX + ((s - tMin) / tRange) * chartW\n        const sz = barH * 0.45\n        const pb = new PathBuilder()\n        pb.moveTo(mx, cy - sz)\n        pb.lineTo(mx + sz, cy)\n        pb.lineTo(mx, cy + sz)\n        pb.lineTo(mx - sz, cy)\n        pb.close()\n\n        barNodes.push(path(pb.build(), {\n          class: 'chartts-gantt-milestone',\n          fill: color,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? i}: milestone at ${s}`,\n        }))\n      } else {\n        // Bar\n        const x1 = chartX + ((s - tMin) / tRange) * chartW\n        const x2 = chartX + ((e - tMin) / tRange) * chartW\n        const bw = Math.max(x2 - x1, 2)\n        const by = cy - barH / 2\n\n        barNodes.push(rect(x1, by, bw, barH, {\n          rx: 4, ry: 4,\n          class: 'chartts-gantt-bar',\n          fill: color,\n          opacity: 0.75,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `${data.labels[i] ?? i}: ${s} to ${e}`,\n        }))\n\n        // Progress overlay\n        if (progress >= 0 && progress <= 100) {\n          const pw = bw * (progress / 100)\n          barNodes.push(rect(x1, by, pw, barH, {\n            rx: 4, ry: 4,\n            class: 'chartts-gantt-progress',\n            fill: color,\n            opacity: 1,\n          }))\n        }\n      }\n    }\n\n    nodes.push(group(barNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': 'Gantt',\n    }))\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const startSeries = data.series[0]\n    const endSeries = data.series[1]\n    if (!startSeries || !endSeries) return null\n\n    const taskCount = data.labels.length\n    if (taskCount === 0) return null\n\n    let tMin = Infinity\n    let tMax = -Infinity\n    for (let i = 0; i < taskCount; i++) {\n      const s = startSeries.values[i] ?? 0\n      const e = endSeries.values[i] ?? 0\n      if (s < tMin) tMin = s\n      if (e > tMax) tMax = e\n    }\n    if (tMin === tMax) tMax = tMin + 1\n\n    const labelWidth = area.width * 0.22\n    const chartX = area.x + labelWidth\n    const chartW = area.width - labelWidth\n    const rowH = area.height / Math.max(taskCount, 1)\n    const tRange = tMax - tMin\n\n    for (let i = 0; i < taskCount; i++) {\n      const s = startSeries.values[i] ?? 0\n      const e = endSeries.values[i] ?? 0\n      const cy = area.y + i * rowH + rowH / 2\n      const x1 = chartX + ((s - tMin) / tRange) * chartW\n      const x2 = chartX + ((e - tMin) / tRange) * chartW\n\n      if (my >= cy - rowH / 2 && my <= cy + rowH / 2 &&\n          mx >= x1 - 5 && mx <= Math.max(x2, x1 + 10) + 5) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: (x1 + x2) / 2, y: cy }\n      }\n    }\n\n    return null\n  },\n})\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Org chart — hierarchical organization diagram with rectangular cards.\n *\n * Data convention (same as Tree):\n * - labels: node names with \"/\" separators for hierarchy (e.g., \"CEO/CTO/VP Eng\")\n * - series[0].values: node sizing (optional, all 1 by default)\n *\n * Difference from Tree: uses rounded rectangles with text inside (org cards)\n * instead of circles with labels beside them.\n */\n\ninterface OrgNode {\n  name: string\n  value: number\n  children: OrgNode[]\n  depth: number\n  index: number\n  x: number\n  y: number\n  leafCount: number\n}\n\nexport const orgChartType = defineChartType({\n  type: 'org',\n  suppressAxes: true,\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return nodes\n\n    const root = buildOrgTree(data.labels, series.values)\n    if (!root) return nodes\n\n    computeLeafCounts(root)\n    const maxDepth = getMaxDepth(root)\n\n    // Card dimensions\n    const cardW = Math.min(area.width / (root.leafCount + 1) * 0.85, 120)\n    const cardH = Math.min(area.height / (maxDepth + 2) * 0.5, 36)\n\n    // Layout top-down\n    const levelHeight = area.height / Math.max(maxDepth + 1, 1)\n    layoutVertical(root, area.y, area.x, area.x + area.width, levelHeight)\n\n    // Render edges first\n    const edgeNodes: RenderNode[] = []\n    renderEdges(root, edgeNodes, theme, cardH)\n    nodes.push(...edgeNodes)\n\n    // Render cards\n    let nodeIdx = 0\n    const renderOrgNode = (node: OrgNode) => {\n      const color = options.colors[node.depth % options.colors.length]!\n      const cardNodes: RenderNode[] = []\n\n      // Rounded rectangle card\n      cardNodes.push(rect(node.x - cardW / 2, node.y - cardH / 2, cardW, cardH, {\n        rx: 6, ry: 6,\n        class: 'chartts-org-card',\n        fill: color,\n        stroke: theme.background === 'transparent' ? '#fff' : theme.background,\n        strokeWidth: 1.5,\n        'data-series': 0,\n        'data-index': nodeIdx,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: node.name,\n      }))\n\n      // Name label inside card\n      const fontSize = Math.min(theme.fontSizeSmall, cardH * 0.38)\n      const maxChars = Math.floor(cardW / (fontSize * 0.58))\n      const displayName = node.name.length > maxChars\n        ? node.name.slice(0, maxChars - 1) + '\\u2026'\n        : node.name\n\n      cardNodes.push(text(node.x, node.y, displayName, {\n        class: 'chartts-org-label',\n        fill: '#fff',\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize,\n        fontFamily: theme.fontFamily,\n        fontWeight: 600,\n      }))\n\n      nodes.push(group(cardNodes, {\n        class: `chartts-series chartts-series-${nodeIdx}`,\n        'data-series-name': node.name,\n      }))\n\n      nodeIdx++\n      for (const child of node.children) {\n        renderOrgNode(child)\n      }\n    }\n\n    renderOrgNode(root)\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    const series = data.series[0]\n    if (!series || series.values.length === 0) return null\n\n    const root = buildOrgTree(data.labels, series.values)\n    if (!root) return null\n\n    computeLeafCounts(root)\n    const maxDepth = getMaxDepth(root)\n\n    const cardW = Math.min(area.width / (root.leafCount + 1) * 0.85, 120)\n    const cardH = Math.min(area.height / (maxDepth + 2) * 0.5, 36)\n    const levelHeight = area.height / Math.max(maxDepth + 1, 1)\n    layoutVertical(root, area.y, area.x, area.x + area.width, levelHeight)\n\n    let best: HitResult | null = null\n    let idx = 0\n\n    const checkNode = (node: OrgNode) => {\n      if (\n        mx >= node.x - cardW / 2 - 2 && mx <= node.x + cardW / 2 + 2 &&\n        my >= node.y - cardH / 2 - 2 && my <= node.y + cardH / 2 + 2\n      ) {\n        best = { seriesIndex: 0, pointIndex: idx, distance: 0, x: node.x, y: node.y }\n      }\n      idx++\n      for (const child of node.children) {\n        checkNode(child)\n      }\n    }\n\n    checkNode(root)\n    return best\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Tree building (reused from Tree chart pattern)\n// ---------------------------------------------------------------------------\n\nfunction buildOrgTree(labels: (string | number | Date)[], values: number[]): OrgNode | null {\n  const root: OrgNode = {\n    name: 'Root', value: 0, children: [], depth: 0, index: 0,\n    x: 0, y: 0, leafCount: 0,\n  }\n\n  const hasHierarchy = labels.some(l => String(l).includes('/'))\n\n  if (hasHierarchy) {\n    for (let i = 0; i < labels.length; i++) {\n      const parts = String(labels[i] ?? '').split('/')\n      const value = Math.abs(values[i] ?? 1)\n      let current = root\n\n      for (let p = 0; p < parts.length; p++) {\n        const part = parts[p]!.trim()\n        if (!part) continue\n\n        let child = current.children.find(c => c.name === part)\n        if (!child) {\n          child = {\n            name: part, value: 0, children: [], depth: current.depth + 1,\n            index: i, x: 0, y: 0, leafCount: 0,\n          }\n          current.children.push(child)\n        }\n        if (p === parts.length - 1) {\n          child.value = value\n        }\n        current = child\n      }\n    }\n  } else {\n    root.name = String(labels[0] ?? 'Root')\n    root.value = Math.abs(values[0] ?? 1)\n\n    for (let i = 1; i < labels.length; i++) {\n      root.children.push({\n        name: String(labels[i] ?? `Node ${i}`),\n        value: Math.abs(values[i] ?? 1),\n        children: [],\n        depth: 1,\n        index: i,\n        x: 0, y: 0, leafCount: 0,\n      })\n    }\n  }\n\n  if (root.children.length === 0 && labels.length > 0) {\n    root.name = String(labels[0] ?? 'Root')\n    root.value = Math.abs(values[0] ?? 1)\n  }\n\n  return root\n}\n\nfunction computeLeafCounts(node: OrgNode): number {\n  if (node.children.length === 0) {\n    node.leafCount = 1\n    return 1\n  }\n  let count = 0\n  for (const child of node.children) {\n    count += computeLeafCounts(child)\n  }\n  node.leafCount = count\n  return count\n}\n\nfunction getMaxDepth(node: OrgNode): number {\n  if (node.children.length === 0) return node.depth\n  let max = node.depth\n  for (const child of node.children) {\n    max = Math.max(max, getMaxDepth(child))\n  }\n  return max\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\nfunction layoutVertical(\n  node: OrgNode, topY: number, leftX: number, rightX: number, levelHeight: number,\n): void {\n  node.y = topY + node.depth * levelHeight + levelHeight / 2\n  const totalLeaves = node.leafCount || 1\n  const slotWidth = (rightX - leftX) / totalLeaves\n\n  if (node.children.length === 0) {\n    node.x = leftX + slotWidth / 2\n    return\n  }\n\n  let currentX = leftX\n  for (const child of node.children) {\n    const childWidth = (child.leafCount / totalLeaves) * (rightX - leftX)\n    layoutVertical(child, topY, currentX, currentX + childWidth, levelHeight)\n    currentX += childWidth\n  }\n\n  const firstChild = node.children[0]!\n  const lastChild = node.children[node.children.length - 1]!\n  node.x = (firstChild.x + lastChild.x) / 2\n}\n\n// ---------------------------------------------------------------------------\n// Rendering edges with curved connectors\n// ---------------------------------------------------------------------------\n\nfunction renderEdges(\n  node: OrgNode,\n  nodes: RenderNode[],\n  theme: RenderContext['theme'],\n  cardH: number,\n): void {\n  for (const child of node.children) {\n    const pb = new PathBuilder()\n    const startY = node.y + cardH / 2\n    const endY = child.y - cardH / 2\n    const midY = (startY + endY) / 2\n\n    pb.moveTo(node.x, startY)\n    pb.curveTo(node.x, midY, child.x, midY, child.x, endY)\n\n    nodes.push(path(pb.build(), {\n      class: 'chartts-org-edge',\n      stroke: theme.gridColor,\n      strokeWidth: 1.5,\n      fill: 'none',\n    }))\n\n    renderEdges(child, nodes, theme, cardH)\n  }\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareNoAxes } from '../../utils/prepare'\nimport { group, rect, path, text } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\n\n/**\n * Flow chart — process diagram with shaped nodes and directed edges.\n *\n * Data convention:\n * - labels: node names. Shape detected from naming conventions:\n *   - Starting with \"[\" → decision (diamond)\n *   - Starting with \"(\" → terminal (rounded rect / stadium)\n *   - Default → process (rect)\n * - series with \" -> \" in name → edge (from -> to), values[0] = weight\n * - series without \" -> \" → node metadata (ignored for layout)\n *\n * Layout: left-to-right layered (topological sort into columns).\n */\n\ninterface FlowNode {\n  name: string\n  index: number\n  shape: 'rect' | 'diamond' | 'rounded'\n  layer: number\n  layerOrder: number\n  x: number\n  y: number\n}\n\ninterface FlowEdge {\n  from: number\n  to: number\n  weight: number\n}\n\nexport const flowChartType = defineChartType({\n  type: 'flow',\n  suppressAxes: true,\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    // Pad edge series to match label count so validation passes\n    const labelLen = data.labels?.length ?? 0\n    if (labelLen > 0) {\n      const paddedSeries = data.series.map(s => {\n        if (s.values.length < labelLen) {\n          const padded = new Array(labelLen).fill(0)\n          for (let i = 0; i < s.values.length; i++) padded[i] = s.values[i]!\n          return { ...s, values: padded }\n        }\n        return s\n      })\n      return prepareNoAxes({ ...data, series: paddedSeries }, options)\n    }\n    return prepareNoAxes(data, options)\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, area, theme, options } = ctx\n    const nodes: RenderNode[] = []\n\n    if (data.labels.length === 0) return nodes\n\n    const { flowNodes, edges } = parseFlowData(data)\n    if (flowNodes.length === 0) return nodes\n\n    assignLayers(flowNodes, edges)\n    layoutNodes(flowNodes, area)\n\n    // Node dimensions\n    const nodeW = Math.min(area.width / (getMaxLayer(flowNodes) + 2) * 0.65, 110)\n    const nodeH = Math.min(area.height / (getMaxLayerCount(flowNodes) + 1) * 0.55, 36)\n\n    // Render edges first (below nodes)\n    const edgeNodes: RenderNode[] = []\n    for (const edge of edges) {\n      const from = flowNodes[edge.from]\n      const to = flowNodes[edge.to]\n      if (!from || !to) continue\n\n      const pb = new PathBuilder()\n      const startX = from.x + nodeW / 2\n      const endX = to.x - nodeW / 2\n      const midX = (startX + endX) / 2\n\n      pb.moveTo(startX, from.y)\n      pb.curveTo(midX, from.y, midX, to.y, endX, to.y)\n\n      edgeNodes.push(path(pb.build(), {\n        class: 'chartts-flow-edge',\n        stroke: theme.gridColor,\n        strokeWidth: 1.5,\n        fill: 'none',\n      }))\n\n      // Arrowhead\n      const arrowSize = 6\n      const apb = new PathBuilder()\n      apb.moveTo(endX, to.y)\n      apb.lineTo(endX - arrowSize, to.y - arrowSize * 0.6)\n      apb.lineTo(endX - arrowSize, to.y + arrowSize * 0.6)\n      apb.close()\n\n      edgeNodes.push(path(apb.build(), {\n        class: 'chartts-flow-arrow',\n        fill: theme.gridColor,\n      }))\n    }\n    if (edgeNodes.length > 0) {\n      nodes.push(group(edgeNodes, { class: 'chartts-flow-edges' }))\n    }\n\n    // Render nodes\n    for (let i = 0; i < flowNodes.length; i++) {\n      const fNode = flowNodes[i]!\n      const color = options.colors[i % options.colors.length]!\n      const cardNodes: RenderNode[] = []\n\n      if (fNode.shape === 'diamond') {\n        // Diamond (decision)\n        const dw = nodeW * 0.6\n        const dh = nodeH * 0.85\n        const dpb = new PathBuilder()\n        dpb.moveTo(fNode.x, fNode.y - dh)\n        dpb.lineTo(fNode.x + dw, fNode.y)\n        dpb.lineTo(fNode.x, fNode.y + dh)\n        dpb.lineTo(fNode.x - dw, fNode.y)\n        dpb.close()\n\n        cardNodes.push(path(dpb.build(), {\n          class: 'chartts-flow-node chartts-flow-decision',\n          fill: color,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: fNode.name,\n        }))\n      } else if (fNode.shape === 'rounded') {\n        // Stadium / terminal shape (very rounded rect)\n        cardNodes.push(rect(fNode.x - nodeW / 2, fNode.y - nodeH / 2, nodeW, nodeH, {\n          rx: nodeH / 2, ry: nodeH / 2,\n          class: 'chartts-flow-node chartts-flow-terminal',\n          fill: color,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: fNode.name,\n        }))\n      } else {\n        // Rectangle (process)\n        cardNodes.push(rect(fNode.x - nodeW / 2, fNode.y - nodeH / 2, nodeW, nodeH, {\n          rx: 4, ry: 4,\n          class: 'chartts-flow-node chartts-flow-process',\n          fill: color,\n          'data-series': 0,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: fNode.name,\n        }))\n      }\n\n      // Label inside node\n      const displayName = fNode.name.replace(/^\\[|\\]$|^\\(|\\)$/g, '')\n      const fontSize = Math.min(theme.fontSizeSmall, nodeH * 0.38)\n      const maxChars = Math.floor(nodeW / (fontSize * 0.55))\n      const labelText = displayName.length > maxChars\n        ? displayName.slice(0, maxChars - 1) + '\\u2026'\n        : displayName\n\n      cardNodes.push(text(fNode.x, fNode.y, labelText, {\n        class: 'chartts-flow-label',\n        fill: '#fff',\n        textAnchor: 'middle',\n        dominantBaseline: 'central',\n        fontSize,\n        fontFamily: theme.fontFamily,\n        fontWeight: 600,\n      }))\n\n      nodes.push(group(cardNodes, {\n        class: `chartts-series chartts-series-${i}`,\n        'data-series-name': fNode.name,\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, area } = ctx\n    if (data.labels.length === 0) return null\n\n    const { flowNodes, edges } = parseFlowData(data)\n    if (flowNodes.length === 0) return null\n\n    assignLayers(flowNodes, edges)\n    layoutNodes(flowNodes, area)\n\n    const nodeW = Math.min(area.width / (getMaxLayer(flowNodes) + 2) * 0.65, 110)\n    const nodeH = Math.min(area.height / (getMaxLayerCount(flowNodes) + 1) * 0.55, 36)\n\n    for (let i = 0; i < flowNodes.length; i++) {\n      const fNode = flowNodes[i]!\n      if (\n        mx >= fNode.x - nodeW / 2 - 4 && mx <= fNode.x + nodeW / 2 + 4 &&\n        my >= fNode.y - nodeH / 2 - 4 && my <= fNode.y + nodeH / 2 + 4\n      ) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: fNode.x, y: fNode.y }\n      }\n    }\n\n    return null\n  },\n})\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\nfunction parseFlowData(data: PreparedData): { flowNodes: FlowNode[]; edges: FlowEdge[] } {\n  const labels = data.labels ?? []\n  const nameToIndex = new Map<string, number>()\n  const flowNodes: FlowNode[] = []\n\n  for (let i = 0; i < labels.length; i++) {\n    const name = String(labels[i] ?? '')\n    let shape: FlowNode['shape'] = 'rect'\n    if (name.startsWith('[')) shape = 'diamond'\n    else if (name.startsWith('(')) shape = 'rounded'\n\n    flowNodes.push({\n      name,\n      index: i,\n      shape,\n      layer: 0,\n      layerOrder: 0,\n      x: 0,\n      y: 0,\n    })\n    nameToIndex.set(name, i)\n  }\n\n  const edges: FlowEdge[] = []\n  for (const series of data.series) {\n    if (!series.name.includes(' -> ')) continue\n    const [fromName, toName] = series.name.split(' -> ').map(s => s.trim())\n    const fromIdx = nameToIndex.get(fromName!)\n    const toIdx = nameToIndex.get(toName!)\n    if (fromIdx !== undefined && toIdx !== undefined) {\n      edges.push({ from: fromIdx, to: toIdx, weight: series.values[0] ?? 1 })\n    }\n  }\n\n  return { flowNodes, edges }\n}\n\n// ---------------------------------------------------------------------------\n// Layer assignment (topological)\n// ---------------------------------------------------------------------------\n\nfunction assignLayers(flowNodes: FlowNode[], edges: FlowEdge[]): void {\n  // Build adjacency\n  const inDegree = new Array(flowNodes.length).fill(0) as number[]\n  const adj: number[][] = flowNodes.map(() => [])\n\n  for (const edge of edges) {\n    adj[edge.from]!.push(edge.to)\n    inDegree[edge.to]!++\n  }\n\n  // BFS layer assignment\n  const queue: number[] = []\n  for (let i = 0; i < flowNodes.length; i++) {\n    if (inDegree[i] === 0) {\n      queue.push(i)\n      flowNodes[i]!.layer = 0\n    }\n  }\n\n  const visited = new Set<number>()\n  while (queue.length > 0) {\n    const curr = queue.shift()!\n    if (visited.has(curr)) continue\n    visited.add(curr)\n\n    for (const next of adj[curr]!) {\n      flowNodes[next]!.layer = Math.max(flowNodes[next]!.layer, flowNodes[curr]!.layer + 1)\n      inDegree[next]!--\n      if (inDegree[next] === 0) {\n        queue.push(next)\n      }\n    }\n  }\n\n  // Assign nodes that weren't reached (disconnected)\n  for (let i = 0; i < flowNodes.length; i++) {\n    if (!visited.has(i)) {\n      flowNodes[i]!.layer = 0\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Layout\n// ---------------------------------------------------------------------------\n\nfunction layoutNodes(\n  flowNodes: FlowNode[],\n  area: { x: number; y: number; width: number; height: number },\n): void {\n  const maxLayer = getMaxLayer(flowNodes)\n  const layerWidth = area.width / Math.max(maxLayer + 1, 1)\n\n  // Group by layer\n  const layers: FlowNode[][] = []\n  for (const node of flowNodes) {\n    if (!layers[node.layer]) layers[node.layer] = []\n    layers[node.layer]!.push(node)\n  }\n\n  // Position each layer\n  for (let l = 0; l <= maxLayer; l++) {\n    const nodesInLayer = layers[l] ?? []\n    const layerH = area.height / Math.max(nodesInLayer.length, 1)\n\n    for (let j = 0; j < nodesInLayer.length; j++) {\n      const node = nodesInLayer[j]!\n      node.x = area.x + l * layerWidth + layerWidth / 2\n      node.y = area.y + j * layerH + layerH / 2\n      node.layerOrder = j\n    }\n  }\n}\n\nfunction getMaxLayer(flowNodes: FlowNode[]): number {\n  let max = 0\n  for (const n of flowNodes) {\n    if (n.layer > max) max = n.layer\n  }\n  return max\n}\n\nfunction getMaxLayerCount(flowNodes: FlowNode[]): number {\n  const counts = new Map<number, number>()\n  for (const n of flowNodes) {\n    counts.set(n.layer, (counts.get(n.layer) ?? 0) + 1)\n  }\n  let max = 0\n  for (const c of counts.values()) {\n    if (c > max) max = c\n  }\n  return max\n}\n","import type {\n  ChartData, ResolvedOptions, PreparedData,\n  RenderContext, RenderNode, HitResult,\n} from '../../types'\nimport { defineChartType } from '../../api/define'\nimport { prepareData } from '../../data/prepare'\nimport { group, rect, path, circle, text, line } from '../../render/tree'\nimport { PathBuilder } from '../../render/tree'\nimport { getBandwidth } from '../../utils/scale'\n\n/**\n * Pareto chart — bars sorted descending + cumulative percentage line + 80% threshold.\n *\n * Data convention:\n * - Single series — values are auto-sorted descending.\n * - Labels are reordered to match.\n * - Cumulative percentages are computed automatically.\n *\n * Renders: bars (primary color) + cumulative line (secondary) + 80% dashed line.\n */\n\nexport const paretoChartType = defineChartType({\n  type: 'pareto',\n  useBandScale: true,\n\n  prepareData(data: ChartData, options: ResolvedOptions): PreparedData {\n    // Sort data descending and compute cumulative percentages\n    const series = data.series[0]\n    if (!series) return prepareData(data, options)\n\n    const labels = data.labels ?? []\n    const indices = series.values.map((_, i) => i)\n    indices.sort((a, b) => (series.values[b] ?? 0) - (series.values[a] ?? 0))\n\n    const sortedLabels = indices.map(i => String(labels[i] ?? ''))\n    const sortedValues = indices.map(i => series.values[i] ?? 0)\n    const total = sortedValues.reduce((s, v) => s + v, 0)\n\n    // Compute cumulative percentages for y-axis range\n    let cumPct = 0\n    const cumValues: number[] = []\n    for (const v of sortedValues) {\n      cumPct += total > 0 ? (v / total) * 100 : 0\n      cumValues.push(cumPct)\n    }\n\n    const sortedData: ChartData = {\n      labels: sortedLabels,\n      series: [\n        { name: series.name, values: sortedValues },\n        { name: 'Cumulative %', values: cumValues },\n      ],\n    }\n\n    const prepared = prepareData(sortedData, options)\n\n    // Ensure y starts at 0\n    if (options.yMin === undefined && prepared.bounds.yMin > 0) {\n      prepared.bounds.yMin = 0\n    }\n\n    return prepared\n  },\n\n  render(ctx: RenderContext): RenderNode[] {\n    const { data, options, xScale, yScale, area, theme } = ctx\n    const nodes: RenderNode[] = []\n\n    const barSeries = data.series[0]\n    if (!barSeries || barSeries.values.length === 0) return nodes\n\n    const cumSeries = data.series[1]\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const baseline = yScale.map(0)\n\n    const barColor = options.colors[0] ?? '#3b82f6'\n    const lineColor = options.colors[1] ?? '#f59e0b'\n\n    // Bars\n    const barNodes: RenderNode[] = []\n    for (let i = 0; i < barSeries.values.length; i++) {\n      const val = barSeries.values[i]!\n      if (isNaN(val)) continue\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(val)\n      const y = vy\n      const h = Math.abs(baseline - vy)\n\n      barNodes.push(rect(barX, y, barWidth, h, {\n        rx: 3, ry: 3,\n        class: 'chartts-pareto-bar',\n        fill: barColor,\n        'data-series': 0,\n        'data-index': i,\n        tabindex: 0,\n        role: 'img',\n        ariaLabel: `${data.labels[i] ?? i}: ${val}`,\n      }))\n    }\n    nodes.push(group(barNodes, {\n      class: 'chartts-series chartts-series-0',\n      'data-series-name': barSeries.name,\n    }))\n\n    // Cumulative percentage line\n    if (cumSeries && cumSeries.values.length > 0) {\n      const yDomain = yScale.getDomain()\n      const yMax = yDomain[1] as number\n\n      const lineNodes: RenderNode[] = []\n      const pb = new PathBuilder()\n      let started = false\n\n      for (let i = 0; i < cumSeries.values.length; i++) {\n        const cumPct = cumSeries.values[i]!\n        // Map cumulative % (0-100) proportionally onto the y scale\n        // cumPct maps to (cumPct / 100) * yMax on the value scale\n        const mappedVal = (cumPct / 100) * yMax\n        const px = xScale.map(i)\n        const py = yScale.map(mappedVal)\n\n        if (!started) {\n          pb.moveTo(px, py)\n          started = true\n        } else {\n          pb.lineTo(px, py)\n        }\n\n        lineNodes.push(circle(px, py, 3.5, {\n          class: 'chartts-pareto-point',\n          fill: lineColor,\n          stroke: '#fff',\n          strokeWidth: 1.5,\n          'data-series': 1,\n          'data-index': i,\n          tabindex: 0,\n          role: 'img',\n          ariaLabel: `Cumulative: ${cumPct.toFixed(1)}%`,\n        }))\n      }\n\n      lineNodes.unshift(path(pb.build(), {\n        class: 'chartts-pareto-line',\n        stroke: lineColor,\n        strokeWidth: 2,\n        fill: 'none',\n      }))\n\n      // 80% threshold line\n      const threshold80Val = (80 / 100) * yMax\n      const threshold80Y = yScale.map(threshold80Val)\n\n      lineNodes.push(line(area.x, threshold80Y, area.x + area.width, threshold80Y, {\n        class: 'chartts-pareto-threshold',\n        stroke: theme.gridColor,\n        strokeWidth: 1,\n        strokeDasharray: '6,3',\n      }))\n\n      // 80% label on right side\n      lineNodes.push(text(area.x + area.width + 4, threshold80Y, '80%', {\n        fill: theme.textColor,\n        textAnchor: 'start',\n        dominantBaseline: 'central',\n        fontSize: theme.fontSizeSmall,\n        fontFamily: theme.fontFamily,\n      }))\n\n      nodes.push(group(lineNodes, {\n        class: 'chartts-series chartts-series-1',\n        'data-series-name': 'Cumulative %',\n      }))\n    }\n\n    return nodes\n  },\n\n  hitTest(ctx: RenderContext, mx: number, my: number): HitResult | null {\n    const { data, xScale, yScale, options } = ctx\n    const barSeries = data.series[0]\n    if (!barSeries) return null\n\n    const bw = getBandwidth(xScale)\n    const barWidth = bw * (1 - options.barGap)\n    const baseline = yScale.map(0)\n\n    for (let i = 0; i < barSeries.values.length; i++) {\n      const val = barSeries.values[i]!\n      if (isNaN(val)) continue\n      const cx = xScale.map(i)\n      const barX = cx - barWidth / 2\n      const vy = yScale.map(val)\n      const y = Math.min(vy, baseline)\n      const h = Math.abs(baseline - vy)\n\n      if (mx >= barX - 2 && mx <= barX + barWidth + 2 && my >= y - 2 && my <= y + h + 2) {\n        return { seriesIndex: 0, pointIndex: i, distance: 0, x: cx, y: vy }\n      }\n    }\n\n    return null\n  },\n})\n","/**\n * Central registry of all built-in chart types.\n *\n * Adding a new chart type = add ONE entry here.\n * convenience.ts, framework wrappers, and entries all derive from this.\n */\nimport type { ChartTypePlugin } from '../types'\n\nimport { lineChartType } from '../charts/line/line-type'\nimport { barChartType } from '../charts/bar/bar-type'\nimport { stackedBarChartType } from '../charts/bar/stacked-bar-type'\nimport { horizontalBarChartType } from '../charts/bar/horizontal-bar-type'\nimport { pieChartType, donutChartType } from '../charts/pie/pie-type'\nimport { scatterChartType } from '../charts/scatter/scatter-type'\nimport { sparklineChartType } from '../charts/sparkline/sparkline-type'\nimport { areaChartType } from '../charts/area/area-type'\nimport { radarChartType } from '../charts/radar/radar-type'\nimport { bubbleChartType } from '../charts/bubble/bubble-type'\nimport { candlestickChartType } from '../charts/candlestick/candlestick-type'\nimport { gaugeChartType } from '../charts/gauge/gauge-type'\nimport { waterfallChartType } from '../charts/waterfall/waterfall-type'\nimport { funnelChartType } from '../charts/funnel/funnel-type'\nimport { heatmapChartType } from '../charts/heatmap/heatmap-type'\nimport { boxplotChartType } from '../charts/boxplot/boxplot-type'\nimport { histogramChartType } from '../charts/histogram/histogram-type'\nimport { treemapChartType } from '../charts/treemap/treemap-type'\nimport { polarChartType } from '../charts/polar/polar-type'\nimport { radialBarChartType } from '../charts/radialbar/radialbar-type'\nimport { lollipopChartType } from '../charts/lollipop/lollipop-type'\nimport { bulletChartType } from '../charts/bullet/bullet-type'\nimport { dumbbellChartType } from '../charts/dumbbell/dumbbell-type'\nimport { calendarChartType } from '../charts/calendar/calendar-type'\nimport { comboChartType } from '../charts/combo/combo-type'\nimport { sankeyChartType } from '../charts/sankey/sankey-type'\nimport { sunburstChartType } from '../charts/sunburst/sunburst-type'\nimport { treeChartType } from '../charts/tree/tree-type'\nimport { graphChartType } from '../charts/graph/graph-type'\nimport { parallelChartType } from '../charts/parallel/parallel-type'\nimport { themeRiverChartType } from '../charts/themeriver/themeriver-type'\nimport { pictorialBarChartType } from '../charts/pictorialbar/pictorialbar-type'\nimport { chordChartType } from '../charts/chord/chord-type'\nimport { geoChartType } from '../charts/geo/geo-type'\nimport { linesChartType } from '../charts/lines/lines-type'\nimport { matrixChartType } from '../charts/matrix/matrix-type'\nimport { customChartType } from '../charts/custom/custom-type'\nimport { ohlcChartType } from '../charts/ohlc/ohlc-type'\nimport { stepChartType } from '../charts/step/step-type'\nimport { volumeChartType } from '../charts/volume/volume-type'\nimport { rangeChartType } from '../charts/range/range-type'\nimport { baselineChartType } from '../charts/baseline/baseline-type'\nimport { kagiChartType } from '../charts/kagi/kagi-type'\nimport { renkoChartType } from '../charts/renko/renko-type'\nimport { violinChartType } from '../charts/violin/violin-type'\nimport { packChartType } from '../charts/pack/pack-type'\nimport { voronoiChartType } from '../charts/voronoi/voronoi-type'\nimport { wordcloudChartType } from '../charts/wordcloud/wordcloud-type'\nimport { pillarChartType } from '../charts/pillar/pillar-type'\nimport { ganttChartType } from '../charts/gantt/gantt-type'\nimport { orgChartType } from '../charts/org/org-type'\nimport { flowChartType } from '../charts/flow/flow-type'\nimport { paretoChartType } from '../charts/pareto/pareto-type'\n\n/**\n * Map of convenience name -> chart type plugin.\n * Keys are PascalCase names matching the public API (Line, Bar, etc.).\n */\nexport const CHART_TYPES: Record<string, ChartTypePlugin> = {\n  Line: lineChartType,\n  Bar: barChartType,\n  StackedBar: stackedBarChartType,\n  HorizontalBar: horizontalBarChartType,\n  Pie: pieChartType,\n  Donut: donutChartType,\n  Scatter: scatterChartType,\n  Sparkline: sparklineChartType,\n  Area: areaChartType,\n  Radar: radarChartType,\n  Bubble: bubbleChartType,\n  Candlestick: candlestickChartType,\n  Gauge: gaugeChartType,\n  Waterfall: waterfallChartType,\n  Funnel: funnelChartType,\n  Heatmap: heatmapChartType,\n  Boxplot: boxplotChartType,\n  Histogram: histogramChartType,\n  Treemap: treemapChartType,\n  Polar: polarChartType,\n  RadialBar: radialBarChartType,\n  Lollipop: lollipopChartType,\n  Bullet: bulletChartType,\n  Dumbbell: dumbbellChartType,\n  Calendar: calendarChartType,\n  Combo: comboChartType,\n  Sankey: sankeyChartType,\n  Sunburst: sunburstChartType,\n  Tree: treeChartType,\n  Graph: graphChartType,\n  Parallel: parallelChartType,\n  ThemeRiver: themeRiverChartType,\n  PictorialBar: pictorialBarChartType,\n  Chord: chordChartType,\n  Geo: geoChartType,\n  Lines: linesChartType,\n  Matrix: matrixChartType,\n  Custom: customChartType,\n  OHLC: ohlcChartType,\n  Step: stepChartType,\n  Volume: volumeChartType,\n  Range: rangeChartType,\n  Baseline: baselineChartType,\n  Kagi: kagiChartType,\n  Renko: renkoChartType,\n  Violin: violinChartType,\n  Pack: packChartType,\n  Voronoi: voronoiChartType,\n  WordCloud: wordcloudChartType,\n  Pillar: pillarChartType,\n  Gantt: ganttChartType,\n  Org: orgChartType,\n  Flow: flowChartType,\n  Pareto: paretoChartType,\n}\n\n// Re-export individual chart types for direct import\nexport {\n  lineChartType, barChartType, stackedBarChartType, horizontalBarChartType,\n  pieChartType, donutChartType, scatterChartType, sparklineChartType,\n  areaChartType, radarChartType, bubbleChartType, candlestickChartType,\n  gaugeChartType, waterfallChartType, funnelChartType, heatmapChartType,\n  boxplotChartType, histogramChartType, treemapChartType, polarChartType,\n  radialBarChartType, lollipopChartType, bulletChartType, dumbbellChartType,\n  calendarChartType, comboChartType, sankeyChartType,\n  sunburstChartType, treeChartType, graphChartType, parallelChartType,\n  themeRiverChartType, pictorialBarChartType, chordChartType,\n  geoChartType, linesChartType, matrixChartType, customChartType,\n  ohlcChartType, stepChartType, volumeChartType, rangeChartType,\n  baselineChartType, kagiChartType, renkoChartType, violinChartType,\n  packChartType, voronoiChartType, wordcloudChartType, pillarChartType,\n  ganttChartType, orgChartType, flowChartType, paretoChartType,\n}\n","import type { ChartData, ChartOptions, ChartInstance } from '../types'\nimport { createChart } from './create'\nimport { CHART_TYPES } from './chart-types'\n\ninterface ChartConfig extends ChartOptions {\n  data: ChartData\n  debug?: boolean\n}\n\ntype ConvenienceFunction = (target: string | HTMLElement, config: ChartConfig) => ChartInstance\n\n/**\n * Generate all convenience functions from the CHART_TYPES map.\n * Each function is: (target, { data, ...options }) => createChart(target, plugin, data, options)\n */\nfunction generateConvenienceFunctions(): Record<string, ConvenienceFunction> {\n  const fns: Record<string, ConvenienceFunction> = {}\n  for (const [name, chartType] of Object.entries(CHART_TYPES)) {\n    fns[name] = (target: string | HTMLElement, config: ChartConfig): ChartInstance => {\n      const { data, ...options } = config\n      return createChart(target, chartType, data, options)\n    }\n  }\n  return fns\n}\n\nconst _fns = generateConvenienceFunctions()\n\n// Export named convenience functions for backwards-compatible API\nexport const Line = _fns.Line!\nexport const Bar = _fns.Bar!\nexport const StackedBar = _fns.StackedBar!\nexport const HorizontalBar = _fns.HorizontalBar!\nexport const Pie = _fns.Pie!\nexport const Donut = _fns.Donut!\nexport const Scatter = _fns.Scatter!\nexport const Sparkline = _fns.Sparkline!\nexport const Area = _fns.Area!\nexport const Radar = _fns.Radar!\nexport const Bubble = _fns.Bubble!\nexport const Candlestick = _fns.Candlestick!\nexport const Gauge = _fns.Gauge!\nexport const Waterfall = _fns.Waterfall!\nexport const Funnel = _fns.Funnel!\nexport const Heatmap = _fns.Heatmap!\nexport const Boxplot = _fns.Boxplot!\nexport const Histogram = _fns.Histogram!\nexport const Treemap = _fns.Treemap!\nexport const Polar = _fns.Polar!\nexport const RadialBar = _fns.RadialBar!\nexport const Lollipop = _fns.Lollipop!\nexport const Bullet = _fns.Bullet!\nexport const Dumbbell = _fns.Dumbbell!\nexport const Calendar = _fns.Calendar!\nexport const Combo = _fns.Combo!\nexport const Sankey = _fns.Sankey!\nexport const Sunburst = _fns.Sunburst!\nexport const Tree = _fns.Tree!\nexport const Graph = _fns.Graph!\nexport const Parallel = _fns.Parallel!\nexport const ThemeRiver = _fns.ThemeRiver!\nexport const PictorialBar = _fns.PictorialBar!\nexport const Chord = _fns.Chord!\nexport const Geo = _fns.Geo!\nexport const Lines = _fns.Lines!\nexport const Matrix = _fns.Matrix!\nexport const Custom = _fns.Custom!\nexport const OHLC = _fns.OHLC!\nexport const Step = _fns.Step!\nexport const Volume = _fns.Volume!\nexport const Range = _fns.Range!\nexport const Baseline = _fns.Baseline!\nexport const Kagi = _fns.Kagi!\nexport const Renko = _fns.Renko!\nexport const Violin = _fns.Violin!\nexport const Pack = _fns.Pack!\nexport const Voronoi = _fns.Voronoi!\nexport const WordCloud = _fns.WordCloud!\nexport const Pillar = _fns.Pillar!\nexport const Gantt = _fns.Gantt!\nexport const Org = _fns.Org!\nexport const Flow = _fns.Flow!\nexport const Pareto = _fns.Pareto!\n","/**\n * Linked charts — sync crosshair position across multiple chart instances.\n *\n * Usage:\n * ```ts\n * const unlink = linkCharts(chart1, chart2, chart3)\n * // Later:\n * unlink()\n * ```\n */\n\nimport type { ChartInstance } from '../types'\n\n/**\n * Link multiple chart instances so their crosshair positions stay in sync.\n * When one chart emits a crosshair:move event, all others receive it.\n *\n * Returns an unlink function to disconnect the charts.\n */\nexport function linkCharts(...charts: ChartInstance[]): () => void {\n  if (charts.length < 2) return () => {}\n\n  let broadcasting = false\n  const unsubs: (() => void)[] = []\n\n  for (const chart of charts) {\n    const unsub = chart.on('crosshair:move', (payload: unknown) => {\n      if (broadcasting) return\n      broadcasting = true\n\n      const { x, label } = payload as { x: number; label: string | number | Date }\n\n      // Broadcast to all other charts via public _bus\n      for (const other of charts) {\n        if (other === chart) continue\n        other._bus.emit('crosshair:move' as never, { x, label } as never)\n      }\n\n      broadcasting = false\n    })\n\n    unsubs.push(unsub)\n\n    // Also sync hide events\n    const unsubHide = chart.on('crosshair:hide', () => {\n      if (broadcasting) return\n      broadcasting = true\n      for (const other of charts) {\n        if (other === chart) continue\n        other._bus.emit('crosshair:hide' as never, undefined as never)\n      }\n      broadcasting = false\n    })\n    unsubs.push(unsubHide)\n  }\n\n  return () => {\n    for (const unsub of unsubs) unsub()\n    unsubs.length = 0\n  }\n}\n","/**\n * Realtime streaming data module.\n *\n * Provides a circular buffer + rolling window for live data feeds.\n * Throttled re-render via requestAnimationFrame.\n *\n * Usage:\n * ```ts\n * const stream = createStreamingChart(chart, {\n *   windowSize: 100,     // show last 100 points\n *   seriesCount: 3,      // 3 data series\n *   seriesNames: ['CPU', 'Memory', 'Disk'],\n * })\n *\n * // Push single data point (one value per series)\n * stream.push([45, 72, 30], 'now')\n *\n * // Push batch of data points\n * stream.pushBatch([\n *   { values: [45, 72, 30], label: '10:00' },\n *   { values: [46, 71, 31], label: '10:01' },\n * ])\n *\n * // Pause / resume\n * stream.pause()\n * stream.resume()\n *\n * // Clean up\n * stream.destroy()\n * ```\n */\n\nimport type { ChartInstance, ChartData } from '../types'\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface StreamingConfig {\n  /** Number of data points visible in the rolling window. Default 100. */\n  windowSize?: number\n  /** Number of data series. Default 1. */\n  seriesCount?: number\n  /** Series names. Default ['Series 1', 'Series 2', ...] */\n  seriesNames?: string[]\n  /** Series colors (optional — falls back to chart palette). */\n  seriesColors?: string[]\n  /** Maximum buffer size (oldest data is discarded beyond this). Default 10x windowSize. */\n  maxBufferSize?: number\n  /** Throttle interval in ms (0 = use rAF). Default 0. */\n  throttleMs?: number\n}\n\n// ---------------------------------------------------------------------------\n// Instance\n// ---------------------------------------------------------------------------\n\nexport interface StreamingInstance {\n  /** Push one data point (one value per series). */\n  push(values: number[], label?: string | number | Date): void\n  /** Push a batch of data points at once. */\n  pushBatch(points: Array<{ values: number[]; label?: string | number | Date }>): void\n  /** Pause streaming (stops re-renders but still accepts data). */\n  pause(): void\n  /** Resume streaming re-renders. */\n  resume(): void\n  /** Clear all buffered data. */\n  clear(): void\n  /** Get current buffer size. */\n  getBufferSize(): number\n  /** Destroy the streaming instance and clean up. */\n  destroy(): void\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport function createStreamingChart(\n  chart: ChartInstance,\n  config: StreamingConfig = {},\n): StreamingInstance {\n  const windowSize = config.windowSize ?? 100\n  const seriesCount = config.seriesCount ?? 1\n  const maxBuffer = config.maxBufferSize ?? windowSize * 10\n  const throttleMs = config.throttleMs ?? 0\n\n  const names: string[] = config.seriesNames\n    ?? Array.from({ length: seriesCount }, (_, i) => `Series ${i + 1}`)\n  const colors: (string | undefined)[] = config.seriesColors ?? []\n\n  // Circular buffers: one per series + one for labels\n  const buffers: number[][] = Array.from({ length: seriesCount }, () => [])\n  const labels: (string | number | Date)[] = []\n  let totalPushed = 0\n\n  let paused = false\n  let dirty = false\n  let rafId: number | null = null\n  let throttleTimer: ReturnType<typeof setTimeout> | null = null\n\n  // -----------------------------------------------------------------------\n  // Internal: schedule a chart update\n  // -----------------------------------------------------------------------\n\n  function scheduleUpdate(): void {\n    if (paused) { dirty = true; return }\n\n    if (throttleMs > 0) {\n      if (throttleTimer !== null) return\n      throttleTimer = setTimeout(() => {\n        throttleTimer = null\n        flush()\n      }, throttleMs)\n    } else {\n      if (rafId !== null) return\n      rafId = requestAnimationFrame(() => {\n        rafId = null\n        flush()\n      })\n    }\n  }\n\n  function flush(): void {\n    dirty = false\n\n    // Build ChartData from the rolling window\n    const start = Math.max(0, labels.length - windowSize)\n    const windowLabels = labels.slice(start)\n    const series = buffers.map((buf, i) => ({\n      name: names[i] ?? `Series ${i + 1}`,\n      values: buf.slice(start),\n      ...(colors[i] ? { color: colors[i] } : {}),\n    }))\n\n    const data: ChartData = {\n      labels: windowLabels as string[],\n      series,\n    }\n\n    chart.setData(data)\n  }\n\n  // -----------------------------------------------------------------------\n  // Trim buffer if it exceeds maxBuffer\n  // -----------------------------------------------------------------------\n\n  function trimBuffer(): void {\n    if (labels.length <= maxBuffer) return\n    const excess = labels.length - maxBuffer\n    labels.splice(0, excess)\n    for (const buf of buffers) {\n      buf.splice(0, excess)\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Public API\n  // -----------------------------------------------------------------------\n\n  return {\n    push(values: number[], label?: string | number | Date): void {\n      totalPushed++\n      const lbl = label ?? totalPushed\n      labels.push(lbl)\n\n      for (let i = 0; i < seriesCount; i++) {\n        buffers[i]!.push(values[i] ?? 0)\n      }\n\n      trimBuffer()\n      scheduleUpdate()\n    },\n\n    pushBatch(points): void {\n      for (const pt of points) {\n        totalPushed++\n        const lbl = pt.label ?? totalPushed\n        labels.push(lbl)\n\n        for (let i = 0; i < seriesCount; i++) {\n          buffers[i]!.push(pt.values[i] ?? 0)\n        }\n      }\n\n      trimBuffer()\n      scheduleUpdate()\n    },\n\n    pause(): void {\n      paused = true\n    },\n\n    resume(): void {\n      paused = false\n      if (dirty) scheduleUpdate()\n    },\n\n    clear(): void {\n      labels.length = 0\n      for (const buf of buffers) buf.length = 0\n      totalPushed = 0\n      dirty = false\n    },\n\n    getBufferSize(): number {\n      return labels.length\n    },\n\n    destroy(): void {\n      if (rafId !== null) cancelAnimationFrame(rafId)\n      if (throttleTimer !== null) clearTimeout(throttleTimer)\n      labels.length = 0\n      for (const buf of buffers) buf.length = 0\n    },\n  }\n}\n","import type { ChartData, Series } from '../types'\n\n/**\n * Dataset — data transformation utilities for filtering, sorting, and\n * aggregating chart data before rendering.\n */\n\ntype Labels = ChartData['labels']\n\nfunction getLabels(data: ChartData): NonNullable<Labels> {\n  return data.labels ?? []\n}\n\n// ---------------------------------------------------------------------------\n// Filter\n// ---------------------------------------------------------------------------\n\n/** Filter series by a predicate on values. */\nexport function filterData(\n  data: ChartData,\n  predicate: (value: number, index: number, seriesIndex: number) => boolean,\n): ChartData {\n  const labels = getLabels(data)\n  const keepIndices = labels\n    .map((_: unknown, i: number) =>\n      data.series.some((s, si) => predicate(s.values[i] ?? 0, i, si)) ? i : -1,\n    )\n    .filter((i: number) => i >= 0)\n\n  return {\n    ...data,\n    series: data.series.map((s, si) => ({\n      ...s,\n      values: s.values.filter((v, i) => predicate(v, i, si)),\n    })),\n    labels: keepIndices.map((i: number) => (labels as unknown[])[i]) as Labels,\n  }\n}\n\n/** Filter to keep only specific series by name or index. */\nexport function filterSeries(\n  data: ChartData,\n  keep: (string | number)[],\n): ChartData {\n  return {\n    ...data,\n    series: data.series.filter((s, i) =>\n      keep.includes(s.name) || keep.includes(i),\n    ),\n  }\n}\n\n/** Filter to keep only specific labels/categories. */\nexport function filterLabels(\n  data: ChartData,\n  keep: (string | number | Date)[],\n): ChartData {\n  const labels = getLabels(data)\n  const keepSet = new Set(keep.map(String))\n  const indices = (labels as unknown[])\n    .map((l, i) => keepSet.has(String(l)) ? i : -1)\n    .filter(i => i >= 0)\n\n  return {\n    ...data,\n    labels: indices.map(i => (labels as unknown[])[i]) as Labels,\n    series: data.series.map(s => ({\n      ...s,\n      values: indices.map(i => s.values[i] ?? 0),\n    })),\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/** Sort data by label or by a specific series' values. */\nexport function sortData(\n  data: ChartData,\n  by: 'label' | number,\n  direction: 'asc' | 'desc' = 'asc',\n): ChartData {\n  const labels = getLabels(data)\n  const indices = (labels as unknown[]).map((_: unknown, i: number) => i)\n  const dir = direction === 'asc' ? 1 : -1\n\n  if (by === 'label') {\n    indices.sort((a, b) => dir * String((labels as unknown[])[a]).localeCompare(String((labels as unknown[])[b])))\n  } else {\n    const series = data.series[by]\n    if (series) {\n      indices.sort((a, b) => dir * ((series.values[a] ?? 0) - (series.values[b] ?? 0)))\n    }\n  }\n\n  return {\n    ...data,\n    labels: indices.map(i => (labels as unknown[])[i]) as Labels,\n    series: data.series.map(s => ({\n      ...s,\n      values: indices.map(i => s.values[i] ?? 0),\n    })),\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Aggregate\n// ---------------------------------------------------------------------------\n\ntype AggFn = 'sum' | 'avg' | 'min' | 'max' | 'count'\n\n/** Aggregate all series values per label into a single series. */\nexport function aggregateData(\n  data: ChartData,\n  fn: AggFn = 'sum',\n): ChartData {\n  const labels = getLabels(data)\n  const agg = getAggFn(fn)\n  const values = (labels as unknown[]).map((_: unknown, i: number) => {\n    const vals = data.series.map(s => s.values[i] ?? 0)\n    return agg(vals)\n  })\n\n  return {\n    ...data,\n    series: [{ name: fn, values }],\n  }\n}\n\nfunction getAggFn(fn: AggFn): (vals: number[]) => number {\n  switch (fn) {\n    case 'sum': return vals => vals.reduce((a, b) => a + b, 0)\n    case 'avg': return vals => vals.length > 0 ? vals.reduce((a, b) => a + b, 0) / vals.length : 0\n    case 'min': return vals => Math.min(...vals)\n    case 'max': return vals => Math.max(...vals)\n    case 'count': return vals => vals.filter(v => v !== 0).length\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Transform pipeline\n// ---------------------------------------------------------------------------\n\ntype TransformFn = (data: ChartData) => ChartData\n\n/** Apply a chain of transforms to chart data. */\nexport function transformData(data: ChartData, ...transforms: TransformFn[]): ChartData {\n  return transforms.reduce((d, fn) => fn(d), data)\n}\n\n// ---------------------------------------------------------------------------\n// Pivot / transpose\n// ---------------------------------------------------------------------------\n\n/** Transpose rows and columns — series become labels and vice versa. */\nexport function pivotData(data: ChartData): ChartData {\n  const labels = getLabels(data)\n  const newLabels = data.series.map(s => s.name) as string[]\n  const newSeries: Series[] = (labels as unknown[]).map((label: unknown, i: number) => ({\n    name: String(label),\n    values: data.series.map(s => s.values[i] ?? 0),\n  }))\n\n  return { labels: newLabels, series: newSeries }\n}\n\n// ---------------------------------------------------------------------------\n// Slice / window\n// ---------------------------------------------------------------------------\n\n/** Take a slice of the data (for pagination or windowing). */\nexport function sliceData(data: ChartData, start: number, end?: number): ChartData {\n  const labels = getLabels(data)\n  return {\n    ...data,\n    labels: (labels as unknown[]).slice(start, end) as Labels,\n    series: data.series.map(s => ({\n      ...s,\n      values: s.values.slice(start, end),\n    })),\n  }\n}\n","import type { ChartData, RenderNode } from '../types'\nimport { rect, path, text } from '../render/tree'\nimport { PathBuilder } from '../render/tree'\n\n/**\n * DataZoom — interactive data range selection and filtering.\n *\n * Provides utilities to:\n * 1. Filter chart data to a visible window (applyDataZoom)\n * 2. Render a zoom slider control (renderDataZoomSlider)\n * 3. Manage zoom state (createDataZoomState)\n */\n\nexport interface DataZoomRange {\n  /** Start percentage 0..1 */\n  start: number\n  /** End percentage 0..1 */\n  end: number\n}\n\nexport interface DataZoomState {\n  range: DataZoomRange\n  setRange(start: number, end: number): void\n  reset(): void\n  zoomIn(factor?: number): void\n  zoomOut(factor?: number): void\n  panLeft(amount?: number): void\n  panRight(amount?: number): void\n}\n\nexport interface DataZoomSliderOptions {\n  x: number\n  y: number\n  width: number\n  height?: number\n  trackColor?: string\n  handleColor?: string\n  selectedColor?: string\n  showMinimap?: boolean\n}\n\n/** Create a DataZoom state manager. */\nexport function createDataZoomState(\n  initial?: Partial<DataZoomRange>,\n  onChange?: (range: DataZoomRange) => void,\n): DataZoomState {\n  const range: DataZoomRange = {\n    start: initial?.start ?? 0,\n    end: initial?.end ?? 1,\n  }\n\n  function clamp() {\n    range.start = Math.max(0, Math.min(range.start, 1))\n    range.end = Math.max(range.start + 0.01, Math.min(range.end, 1))\n    onChange?.(range)\n  }\n\n  return {\n    range,\n    setRange(start: number, end: number) {\n      range.start = start\n      range.end = end\n      clamp()\n    },\n    reset() {\n      range.start = 0\n      range.end = 1\n      onChange?.(range)\n    },\n    zoomIn(factor = 0.1) {\n      const center = (range.start + range.end) / 2\n      const halfSpan = (range.end - range.start) / 2 * (1 - factor)\n      range.start = center - halfSpan\n      range.end = center + halfSpan\n      clamp()\n    },\n    zoomOut(factor = 0.1) {\n      const center = (range.start + range.end) / 2\n      const halfSpan = (range.end - range.start) / 2 * (1 + factor)\n      range.start = center - halfSpan\n      range.end = center + halfSpan\n      clamp()\n    },\n    panLeft(amount = 0.05) {\n      const span = range.end - range.start\n      range.start = Math.max(0, range.start - amount)\n      range.end = range.start + span\n      clamp()\n    },\n    panRight(amount = 0.05) {\n      const span = range.end - range.start\n      range.end = Math.min(1, range.end + amount)\n      range.start = range.end - span\n      clamp()\n    },\n  }\n}\n\n/** Apply DataZoom range to filter chart data. */\nexport function applyDataZoom(data: ChartData, range: DataZoomRange): ChartData {\n  const labels = data.labels ?? []\n  const total = labels.length\n  if (total === 0) return data\n\n  const startIdx = Math.floor(range.start * total)\n  const endIdx = Math.ceil(range.end * total)\n\n  return {\n    ...data,\n    labels: (labels as unknown[]).slice(startIdx, endIdx) as ChartData['labels'],\n    series: data.series.map(s => ({\n      ...s,\n      values: s.values.slice(startIdx, endIdx),\n    })),\n  }\n}\n\n/** Render a DataZoom slider as RenderNode[]. */\nexport function renderDataZoomSlider(\n  data: ChartData,\n  range: DataZoomRange,\n  opts: DataZoomSliderOptions,\n): RenderNode[] {\n  const nodes: RenderNode[] = []\n  const h = opts.height ?? 30\n  const trackColor = opts.trackColor ?? '#e5e7eb'\n  const handleColor = opts.handleColor ?? '#6b7280'\n  const selectedColor = opts.selectedColor ?? 'rgba(59,130,246,0.2)'\n\n  // Track background\n  nodes.push(rect(opts.x, opts.y, opts.width, h, {\n    class: 'chartts-datazoom-track',\n    fill: trackColor,\n    rx: 4,\n    ry: 4,\n  }))\n\n  // Minimap sparkline\n  if (opts.showMinimap !== false && data.series[0]) {\n    const values = data.series[0].values\n    const max = Math.max(...values.map(Math.abs), 1)\n    const pb = new PathBuilder()\n\n    for (let i = 0; i < values.length; i++) {\n      const x = opts.x + (i / Math.max(values.length - 1, 1)) * opts.width\n      const y = opts.y + h - (Math.abs(values[i]!) / max) * (h - 4) - 2\n      if (i === 0) pb.moveTo(x, y)\n      else pb.lineTo(x, y)\n    }\n\n    nodes.push(path(pb.build(), {\n      class: 'chartts-datazoom-minimap',\n      fill: 'none',\n      stroke: handleColor,\n      strokeWidth: 1,\n      strokeOpacity: 0.4,\n    }))\n  }\n\n  // Selected region\n  const selX = opts.x + range.start * opts.width\n  const selW = (range.end - range.start) * opts.width\n\n  nodes.push(rect(selX, opts.y, selW, h, {\n    class: 'chartts-datazoom-selected',\n    fill: selectedColor,\n    rx: 2,\n    ry: 2,\n  }))\n\n  // Left handle\n  nodes.push(rect(selX - 3, opts.y + 4, 6, h - 8, {\n    class: 'chartts-datazoom-handle chartts-datazoom-handle-left',\n    fill: handleColor,\n    rx: 3,\n    ry: 3,\n    cursor: 'ew-resize',\n  }))\n\n  // Right handle\n  nodes.push(rect(selX + selW - 3, opts.y + 4, 6, h - 8, {\n    class: 'chartts-datazoom-handle chartts-datazoom-handle-right',\n    fill: handleColor,\n    rx: 3,\n    ry: 3,\n    cursor: 'ew-resize',\n  }))\n\n  // Range labels\n  const dlabels = data.labels ?? []\n  const total = dlabels.length\n  const startIdx = Math.floor(range.start * total)\n  const endIdx = Math.min(Math.ceil(range.end * total) - 1, total - 1)\n\n  if (total > 0) {\n    nodes.push(text(selX, opts.y + h + 12, String((dlabels as unknown[])[startIdx] ?? ''), {\n      class: 'chartts-datazoom-label',\n      fill: handleColor,\n      textAnchor: 'start',\n      fontSize: 9,\n    }))\n\n    nodes.push(text(selX + selW, opts.y + h + 12, String((dlabels as unknown[])[endIdx] ?? ''), {\n      class: 'chartts-datazoom-label',\n      fill: handleColor,\n      textAnchor: 'end',\n      fontSize: 9,\n    }))\n  }\n\n  return nodes\n}\n","/**\n * Interactive DataZoom slider widget.\n *\n * A real DOM element with draggable handles and minimap sparkline.\n * Lives outside the chart render loop — manages its own pointer events.\n *\n * Usage:\n * ```ts\n * const widget = createDataZoomWidget({\n *   data: fullData,\n *   onChange: (range) => {\n *     chart.setData(applyDataZoom(fullData, range))\n *   },\n * })\n * container.appendChild(widget.element)\n * ```\n */\n\nimport type { ChartData } from '../types'\nimport { createDataZoomState, type DataZoomState, type DataZoomRange } from './datazoom'\n\nexport interface DataZoomWidgetOptions {\n  /** Chart data (first series used for minimap sparkline). */\n  data: ChartData\n  /** Height of the slider in pixels. Default 40. */\n  height?: number\n  /** Initial visible range. Default { start: 0, end: 1 }. */\n  initialRange?: Partial<DataZoomRange>\n  /** Called when range changes via user interaction. */\n  onChange?: (range: DataZoomRange) => void\n  /** Track background color. */\n  trackColor?: string\n  /** Handle color. */\n  handleColor?: string\n  /** Selected region color. */\n  selectedColor?: string\n  /** Minimap line color. */\n  minimapColor?: string\n}\n\nexport interface DataZoomWidget {\n  /** The DOM element to insert into the page. */\n  element: HTMLElement\n  /** The state manager (setRange, reset, zoomIn, zoomOut, panLeft, panRight). */\n  state: DataZoomState\n  /** Update minimap sparkline data. */\n  setData(data: ChartData): void\n  /** Destroy and clean up. */\n  destroy(): void\n}\n\nexport function createDataZoomWidget(options: DataZoomWidgetOptions): DataZoomWidget {\n  const h = options.height ?? 40\n  const trackColor = options.trackColor ?? '#e5e7eb'\n  const handleColor = options.handleColor ?? '#6b7280'\n  const selectedColor = options.selectedColor ?? 'rgba(59,130,246,0.25)'\n  const minimapColor = options.minimapColor ?? '#9ca3af'\n\n  let currentData = options.data\n\n  // State\n  const state = createDataZoomState(\n    options.initialRange,\n    (range) => {\n      updateLayout()\n      options.onChange?.(range)\n    },\n  )\n\n  // -----------------------------------------------------------------------\n  // DOM construction\n  // -----------------------------------------------------------------------\n\n  const root = document.createElement('div')\n  root.className = 'chartts-datazoom-widget'\n  root.style.cssText = `position:relative;height:${h}px;width:100%;user-select:none;touch-action:none;`\n\n  // Track background\n  const track = document.createElement('div')\n  track.className = 'chartts-datazoom-track'\n  track.style.cssText = `position:absolute;inset:0;background:${trackColor};border-radius:4px;overflow:hidden;`\n  root.appendChild(track)\n\n  // Minimap canvas\n  const minimap = document.createElement('canvas')\n  minimap.className = 'chartts-datazoom-minimap'\n  minimap.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;'\n  track.appendChild(minimap)\n\n  // Left mask (dimmed area)\n  const maskLeft = document.createElement('div')\n  maskLeft.style.cssText = `position:absolute;top:0;left:0;height:100%;background:rgba(0,0,0,0.15);border-radius:4px 0 0 4px;pointer-events:none;`\n  root.appendChild(maskLeft)\n\n  // Right mask (dimmed area)\n  const maskRight = document.createElement('div')\n  maskRight.style.cssText = `position:absolute;top:0;right:0;height:100%;background:rgba(0,0,0,0.15);border-radius:0 4px 4px 0;pointer-events:none;`\n  root.appendChild(maskRight)\n\n  // Selected region (draggable for pan)\n  const selected = document.createElement('div')\n  selected.className = 'chartts-datazoom-selected'\n  selected.style.cssText = `position:absolute;top:0;height:100%;background:${selectedColor};cursor:grab;border-top:2px solid ${handleColor};border-bottom:2px solid ${handleColor};`\n  root.appendChild(selected)\n\n  // Left handle\n  const handleLeft = document.createElement('div')\n  handleLeft.className = 'chartts-datazoom-handle-left'\n  handleLeft.style.cssText = `position:absolute;top:2px;width:8px;height:${h - 4}px;background:${handleColor};border-radius:4px;cursor:ew-resize;z-index:2;transform:translateX(-50%);`\n  root.appendChild(handleLeft)\n\n  // Right handle\n  const handleRight = document.createElement('div')\n  handleRight.className = 'chartts-datazoom-handle-right'\n  handleRight.style.cssText = `position:absolute;top:2px;width:8px;height:${h - 4}px;background:${handleColor};border-radius:4px;cursor:ew-resize;z-index:2;transform:translateX(-50%);`\n  root.appendChild(handleRight)\n\n  // -----------------------------------------------------------------------\n  // Layout update\n  // -----------------------------------------------------------------------\n\n  function updateLayout(): void {\n    const w = root.clientWidth || root.offsetWidth || 300\n    const { start, end } = state.range\n\n    const leftPx = start * w\n    const rightPx = end * w\n    const selWidth = rightPx - leftPx\n\n    maskLeft.style.width = `${leftPx}px`\n    maskRight.style.width = `${w - rightPx}px`\n\n    selected.style.left = `${leftPx}px`\n    selected.style.width = `${selWidth}px`\n\n    handleLeft.style.left = `${leftPx}px`\n    handleRight.style.left = `${rightPx}px`\n  }\n\n  // -----------------------------------------------------------------------\n  // Minimap rendering\n  // -----------------------------------------------------------------------\n\n  function drawMinimap(): void {\n    const w = root.clientWidth || root.offsetWidth || 300\n    const dpr = window.devicePixelRatio || 1\n    minimap.width = Math.round(w * dpr)\n    minimap.height = Math.round(h * dpr)\n    minimap.style.width = `${w}px`\n    minimap.style.height = `${h}px`\n\n    const ctx = minimap.getContext('2d')\n    if (!ctx) return\n    ctx.setTransform(dpr, 0, 0, dpr, 0, 0)\n    ctx.clearRect(0, 0, w, h)\n\n    const series = currentData.series[0]\n    if (!series || series.values.length === 0) return\n\n    const values = series.values.filter(v => !isNaN(v))\n    if (values.length === 0) return\n\n    const max = Math.max(...values)\n    const min = Math.min(...values)\n    const range = max - min || 1\n    const pad = 4\n\n    ctx.beginPath()\n    ctx.strokeStyle = minimapColor\n    ctx.lineWidth = 1\n    ctx.globalAlpha = 0.5\n\n    let started = false\n    for (let i = 0; i < series.values.length; i++) {\n      const v = series.values[i]!\n      if (isNaN(v)) continue\n      const x = (i / Math.max(series.values.length - 1, 1)) * w\n      const y = h - pad - ((v - min) / range) * (h - pad * 2)\n      if (!started) { ctx.moveTo(x, y); started = true }\n      else ctx.lineTo(x, y)\n    }\n    ctx.stroke()\n\n    // Fill area below the line\n    if (started) {\n      ctx.lineTo(w, h)\n      ctx.lineTo(0, h)\n      ctx.closePath()\n      ctx.fillStyle = minimapColor\n      ctx.globalAlpha = 0.08\n      ctx.fill()\n    }\n  }\n\n  // -----------------------------------------------------------------------\n  // Pointer interaction\n  // -----------------------------------------------------------------------\n\n  type DragMode = 'left' | 'right' | 'pan' | null\n  let dragMode: DragMode = null\n  let dragStartX = 0\n  let dragStartRange: DataZoomRange = { start: 0, end: 1 }\n\n  function toNormalized(clientX: number): number {\n    const r = root.getBoundingClientRect()\n    return Math.max(0, Math.min(1, (clientX - r.left) / r.width))\n  }\n\n  function onPointerDown(e: PointerEvent): void {\n    const target = e.target as HTMLElement\n    if (target === handleLeft || target.closest('.chartts-datazoom-handle-left')) {\n      dragMode = 'left'\n    } else if (target === handleRight || target.closest('.chartts-datazoom-handle-right')) {\n      dragMode = 'right'\n    } else if (target === selected || target.closest('.chartts-datazoom-selected')) {\n      dragMode = 'pan'\n      selected.style.cursor = 'grabbing'\n    } else {\n      // Click on track — jump to position\n      const pos = toNormalized(e.clientX)\n      const span = state.range.end - state.range.start\n      state.setRange(pos - span / 2, pos + span / 2)\n      return\n    }\n\n    dragStartX = e.clientX\n    dragStartRange = { ...state.range }\n    root.setPointerCapture(e.pointerId)\n    e.preventDefault()\n  }\n\n  function onPointerMove(e: PointerEvent): void {\n    if (!dragMode) return\n\n    const dx = e.clientX - dragStartX\n    const w = root.clientWidth || root.offsetWidth || 300\n    const delta = dx / w\n\n    if (dragMode === 'left') {\n      state.setRange(\n        Math.min(dragStartRange.start + delta, state.range.end - 0.02),\n        state.range.end,\n      )\n    } else if (dragMode === 'right') {\n      state.setRange(\n        state.range.start,\n        Math.max(dragStartRange.end + delta, state.range.start + 0.02),\n      )\n    } else if (dragMode === 'pan') {\n      const span = dragStartRange.end - dragStartRange.start\n      let newStart = dragStartRange.start + delta\n      let newEnd = dragStartRange.end + delta\n      // Clamp to bounds\n      if (newStart < 0) { newStart = 0; newEnd = span }\n      if (newEnd > 1) { newEnd = 1; newStart = 1 - span }\n      state.setRange(newStart, newEnd)\n    }\n  }\n\n  function onPointerUp(_e: PointerEvent): void {\n    dragMode = null\n    selected.style.cursor = 'grab'\n  }\n\n  function onDblClick(): void {\n    state.reset()\n  }\n\n  root.addEventListener('pointerdown', onPointerDown)\n  root.addEventListener('pointermove', onPointerMove)\n  root.addEventListener('pointerup', onPointerUp)\n  root.addEventListener('dblclick', onDblClick)\n\n  // -----------------------------------------------------------------------\n  // Resize observer\n  // -----------------------------------------------------------------------\n\n  let resizeObserver: ResizeObserver | null = null\n  if (typeof ResizeObserver !== 'undefined') {\n    resizeObserver = new ResizeObserver(() => {\n      updateLayout()\n      drawMinimap()\n    })\n    resizeObserver.observe(root)\n  }\n\n  // Initial draw (deferred to next frame so root has dimensions)\n  requestAnimationFrame(() => {\n    updateLayout()\n    drawMinimap()\n  })\n\n  // -----------------------------------------------------------------------\n  // Public API\n  // -----------------------------------------------------------------------\n\n  return {\n    element: root,\n    state,\n\n    setData(data: ChartData): void {\n      currentData = data\n      drawMinimap()\n    },\n\n    destroy(): void {\n      resizeObserver?.disconnect()\n      root.removeEventListener('pointerdown', onPointerDown)\n      root.removeEventListener('pointermove', onPointerMove)\n      root.removeEventListener('pointerup', onPointerUp)\n      root.removeEventListener('dblclick', onDblClick)\n      root.remove()\n    },\n  }\n}\n","import type { RenderNode, RenderAttrs } from '../types'\nimport { rect, circle, path, text, line, group } from '../render/tree'\n\n/**\n * Graphic — create custom SVG overlay elements for charts.\n *\n * Provides a declarative API to define arbitrary shapes, text, and groups\n * that can be overlaid on any chart. Positions can be absolute (px)\n * or relative (0..1 proportion of chart area).\n */\n\nexport interface GraphicElement {\n  type: 'rect' | 'circle' | 'path' | 'text' | 'line' | 'group' | 'image'\n  // Position (absolute px or relative 0..1 with position: 'relative')\n  x?: number\n  y?: number\n  // Sizing\n  width?: number\n  height?: number\n  r?: number\n  // Content\n  d?: string            // path data\n  content?: string      // text content\n  x2?: number           // line end x\n  y2?: number           // line end y\n  src?: string          // image source\n  // Children (for groups)\n  children?: GraphicElement[]\n  // Positioning mode\n  position?: 'absolute' | 'relative'\n  // Any SVG attributes\n  attrs?: Record<string, unknown>\n}\n\nexport interface GraphicArea {\n  x: number\n  y: number\n  width: number\n  height: number\n}\n\n/**\n * Convert an array of GraphicElement definitions into RenderNode[].\n * Use `area` to resolve relative positions.\n */\nexport function createGraphicElements(\n  elements: GraphicElement[],\n  area?: GraphicArea,\n): RenderNode[] {\n  return elements.map(el => resolveElement(el, area)).filter(Boolean) as RenderNode[]\n}\n\nfunction resolveElement(el: GraphicElement, area?: GraphicArea): RenderNode | null {\n  const resolve = (v: number | undefined, dim: 'x' | 'y'): number => {\n    if (v === undefined) return 0\n    if (el.position === 'relative' && area) {\n      return dim === 'x'\n        ? area.x + v * area.width\n        : area.y + v * area.height\n    }\n    return v\n  }\n\n  const resolveSize = (v: number | undefined, dim: 'w' | 'h'): number => {\n    if (v === undefined) return 0\n    if (el.position === 'relative' && area) {\n      return dim === 'w' ? v * area.width : v * area.height\n    }\n    return v\n  }\n\n  const attrs: RenderAttrs = {\n    class: 'chartts-graphic',\n    ...(el.attrs as RenderAttrs),\n  }\n\n  switch (el.type) {\n    case 'rect':\n      return rect(\n        resolve(el.x, 'x'),\n        resolve(el.y, 'y'),\n        resolveSize(el.width, 'w'),\n        resolveSize(el.height, 'h'),\n        attrs,\n      )\n\n    case 'circle':\n      return circle(\n        resolve(el.x, 'x'),\n        resolve(el.y, 'y'),\n        el.r ?? 10,\n        attrs,\n      )\n\n    case 'path':\n      return el.d ? path(el.d, attrs) : null\n\n    case 'text':\n      return text(\n        resolve(el.x, 'x'),\n        resolve(el.y, 'y'),\n        el.content ?? '',\n        attrs,\n      )\n\n    case 'line':\n      return line(\n        resolve(el.x, 'x'),\n        resolve(el.y, 'y'),\n        resolve(el.x2, 'x'),\n        resolve(el.y2, 'y'),\n        attrs,\n      )\n\n    case 'group': {\n      const children = (el.children ?? [])\n        .map(c => resolveElement(c, area))\n        .filter(Boolean) as RenderNode[]\n      return group(children, attrs)\n    }\n\n    case 'image':\n      return {\n        type: 'image' as unknown as RenderNode['type'],\n        attrs: {\n          ...attrs,\n          href: el.src ?? '',\n          x: resolve(el.x, 'x'),\n          y: resolve(el.y, 'y'),\n          width: resolveSize(el.width, 'w'),\n          height: resolveSize(el.height, 'h'),\n        },\n      } as unknown as RenderNode\n\n    default:\n      return null\n  }\n}\n\n/**\n * Convenience: create a horizontal guideline.\n */\nexport function horizontalLine(\n  y: number,\n  area: GraphicArea,\n  attrs?: RenderAttrs,\n): RenderNode {\n  return line(area.x, y, area.x + area.width, y, {\n    class: 'chartts-graphic-guideline',\n    stroke: '#6b7280',\n    strokeWidth: 1,\n    strokeDasharray: '4,3',\n    ...attrs,\n  })\n}\n\n/**\n * Convenience: create a vertical guideline.\n */\nexport function verticalLine(\n  x: number,\n  area: GraphicArea,\n  attrs?: RenderAttrs,\n): RenderNode {\n  return line(x, area.y, x, area.y + area.height, {\n    class: 'chartts-graphic-guideline',\n    stroke: '#6b7280',\n    strokeWidth: 1,\n    strokeDasharray: '4,3',\n    ...attrs,\n  })\n}\n\n/**\n * Convenience: create a text annotation at a position.\n */\nexport function annotation(\n  x: number, y: number,\n  content: string,\n  attrs?: RenderAttrs,\n): RenderNode {\n  return text(x, y, content, {\n    class: 'chartts-graphic-annotation',\n    fill: '#374151',\n    fontSize: 11,\n    textAnchor: 'middle',\n    dominantBaseline: 'auto',\n    ...attrs,\n  })\n}\n","import type { RenderNode, RenderAttrs } from '../types'\n\n/**\n * Rich Text — parse simple markup into multi-styled text elements.\n *\n * Supports a simple markup syntax:\n * - {b}bold{/b} or **bold**\n * - {i}italic{/i} or *italic*\n * - {color:red}colored{/color}\n * - {size:16}sized{/size}\n * - {style:name}custom{/style} — uses named styles\n *\n * Returns a RenderNode (text element with tspan children).\n */\n\nexport interface RichTextStyle {\n  fontWeight?: number | string\n  fontStyle?: string\n  fill?: string\n  fontSize?: number | string\n  fontFamily?: string\n  textDecoration?: string\n}\n\nexport interface RichTextOptions {\n  /** Default text attributes */\n  defaults?: RichTextStyle\n  /** Named styles for {style:name} syntax */\n  styles?: Record<string, RichTextStyle>\n  /** X position */\n  x?: number\n  /** Y position */\n  y?: number\n  /** Additional attributes for the parent text element */\n  attrs?: RenderAttrs\n}\n\ninterface TextSpan {\n  text: string\n  style: RichTextStyle\n}\n\n/**\n * Parse rich text markup and return a RenderNode with tspan children.\n */\nexport function parseRichText(\n  input: string,\n  options: RichTextOptions = {},\n): RenderNode {\n  const spans = parse(input, options.defaults ?? {}, options.styles ?? {})\n\n  // Build tspan children\n  const tspans: RenderNode[] = spans.map(span => ({\n    type: 'tspan' as unknown as RenderNode['type'],\n    attrs: {\n      ...(span.style.fontWeight ? { fontWeight: span.style.fontWeight } : {}),\n      ...(span.style.fontStyle ? { fontStyle: span.style.fontStyle } : {}),\n      ...(span.style.fill ? { fill: span.style.fill } : {}),\n      ...(span.style.fontSize ? { fontSize: span.style.fontSize } : {}),\n      ...(span.style.fontFamily ? { fontFamily: span.style.fontFamily } : {}),\n      ...(span.style.textDecoration ? { textDecoration: span.style.textDecoration } : {}),\n    },\n    children: [],\n    text: span.text,\n  } as unknown as RenderNode))\n\n  return {\n    type: 'text',\n    x: options.x ?? 0,\n    y: options.y ?? 0,\n    text: '',\n    attrs: {\n      class: 'chartts-richtext',\n      ...options.attrs,\n    },\n    children: tspans,\n  } as unknown as RenderNode\n}\n\n/**\n * Format a value with rich text markup.\n * E.g., richLabel(\"Revenue\", 1234, { valueColor: \"#3b82f6\" })\n * → \"{b}Revenue{/b}: {color:#3b82f6}1,234{/color}\"\n */\nexport function richLabel(\n  label: string,\n  value: number | string,\n  opts?: { valueColor?: string; valueWeight?: string },\n): string {\n  const color = opts?.valueColor ?? '#3b82f6'\n  const weight = opts?.valueWeight ?? ''\n  const valueStr = typeof value === 'number' ? formatNum(value) : value\n  const weightTag = weight ? `{b}${valueStr}{/b}` : valueStr\n  return `{b}${label}{/b}: {color:${color}}${weightTag}{/color}`\n}\n\n// ---------------------------------------------------------------------------\n// Parser\n// ---------------------------------------------------------------------------\n\nfunction parse(\n  input: string,\n  defaults: RichTextStyle,\n  namedStyles: Record<string, RichTextStyle>,\n): TextSpan[] {\n  const spans: TextSpan[] = []\n  const styleStack: RichTextStyle[] = [{ ...defaults }]\n\n  // Pattern matches: {b}, {/b}, {i}, {/i}, {color:X}, {/color}, {size:X}, {/size}, {style:X}, {/style}, **X**, *X*\n  const regex = /\\{(b|\\/b|i|\\/i|color:([^}]+)|\\/color|size:([^}]+)|\\/size|style:([^}]+)|\\/style)\\}|\\*\\*(.+?)\\*\\*|\\*(.+?)\\*/g\n\n  let lastIndex = 0\n  let match: RegExpExecArray | null\n\n  while ((match = regex.exec(input)) !== null) {\n    // Text before this match\n    if (match.index > lastIndex) {\n      spans.push({ text: input.slice(lastIndex, match.index), style: currentStyle(styleStack) })\n    }\n\n    const tag = match[1]\n    const boldShorthand = match[5]\n    const italicShorthand = match[6]\n\n    if (boldShorthand) {\n      spans.push({ text: boldShorthand, style: { ...currentStyle(styleStack), fontWeight: 700 } })\n    } else if (italicShorthand) {\n      spans.push({ text: italicShorthand, style: { ...currentStyle(styleStack), fontStyle: 'italic' } })\n    } else if (tag === 'b') {\n      styleStack.push({ ...currentStyle(styleStack), fontWeight: 700 })\n    } else if (tag === '/b') {\n      popStyle(styleStack)\n    } else if (tag === 'i') {\n      styleStack.push({ ...currentStyle(styleStack), fontStyle: 'italic' })\n    } else if (tag === '/i') {\n      popStyle(styleStack)\n    } else if (tag?.startsWith('color:')) {\n      styleStack.push({ ...currentStyle(styleStack), fill: match[2] })\n    } else if (tag === '/color') {\n      popStyle(styleStack)\n    } else if (tag?.startsWith('size:')) {\n      styleStack.push({ ...currentStyle(styleStack), fontSize: parseFloat(match[3]!) || 12 })\n    } else if (tag === '/size') {\n      popStyle(styleStack)\n    } else if (tag?.startsWith('style:')) {\n      const named = namedStyles[match[4]!]\n      if (named) {\n        styleStack.push({ ...currentStyle(styleStack), ...named })\n      }\n    } else if (tag === '/style') {\n      popStyle(styleStack)\n    }\n\n    lastIndex = match.index + match[0].length\n  }\n\n  // Remaining text\n  if (lastIndex < input.length) {\n    spans.push({ text: input.slice(lastIndex), style: currentStyle(styleStack) })\n  }\n\n  return spans\n}\n\nfunction currentStyle(stack: RichTextStyle[]): RichTextStyle {\n  return { ...stack[stack.length - 1]! }\n}\n\nfunction popStyle(stack: RichTextStyle[]): void {\n  if (stack.length > 1) stack.pop()\n}\n\nfunction formatNum(n: number): string {\n  return n.toLocaleString()\n}\n","import type { ChartTypePlugin, ScaleFactory, ScaleType } from '../types'\n\n/**\n * @deprecated Use the `CHART_TYPES` map from `@chartts/core` instead.\n * This registry is unused internally and will be removed in a future version.\n */\n\nconst charts = new Map<string, ChartTypePlugin>()\nconst scales = new Map<ScaleType, ScaleFactory>()\n\n/** @deprecated Use `CHART_TYPES` map instead. */\nexport function registerChart(plugin: ChartTypePlugin): void {\n  if (charts.has(plugin.type)) {\n    throw new Error(`[chartts] Chart type \"${plugin.type}\" already registered.`)\n  }\n  charts.set(plugin.type, plugin)\n}\n\n/** @deprecated Use `CHART_TYPES` map instead. */\nexport function getChart(type: string): ChartTypePlugin {\n  const plugin = charts.get(type)\n  if (!plugin) {\n    const available = Array.from(charts.keys()).join(', ') || 'none'\n    throw new Error(`[chartts] Unknown chart type \"${type}\". Registered: ${available}`)\n  }\n  return plugin\n}\n\n/** @deprecated */\nexport function registerScale(type: ScaleType, factory: ScaleFactory): void {\n  scales.set(type, factory)\n}\n\n/** @deprecated */\nexport function getScaleFactory(type: ScaleType): ScaleFactory {\n  const factory = scales.get(type)\n  if (!factory) {\n    throw new Error(`[chartts] Unknown scale type \"${type}\".`)\n  }\n  return factory\n}\n\n/** @deprecated */\nexport function clearRegistry(): void {\n  charts.clear()\n  scales.clear()\n}\n","import type { Scale, Tick } from '../types'\n\nexport interface TimeScaleOpts {\n  domain?: [number | Date, number | Date]\n  range?: [number, number]\n  format?: (value: Date) => string\n}\n\nconst S = 1000, M = 60 * S, H = 60 * M, D = 24 * H, W = 7 * D, MO = 30 * D, Y = 365 * D\n\nconst INTERVALS: { ms: number; fmt: (d: Date) => string }[] = [\n  { ms: S,      fmt: fmtTime },\n  { ms: 5 * S,  fmt: fmtTime },\n  { ms: 15 * S, fmt: fmtTime },\n  { ms: 30 * S, fmt: fmtTime },\n  { ms: M,      fmt: fmtTime },\n  { ms: 5 * M,  fmt: fmtTime },\n  { ms: 15 * M, fmt: fmtTime },\n  { ms: H,      fmt: fmtTime },\n  { ms: 3 * H,  fmt: fmtTime },\n  { ms: 6 * H,  fmt: fmtTime },\n  { ms: 12 * H, fmt: fmtTime },\n  { ms: D,      fmt: fmtDate },\n  { ms: W,      fmt: fmtDate },\n  { ms: MO,     fmt: fmtMonthYear },\n  { ms: 3 * MO, fmt: fmtMonthYear },\n  { ms: 6 * MO, fmt: fmtMonthYear },\n  { ms: Y,      fmt: fmtYear },\n  { ms: 5 * Y,  fmt: fmtYear },\n  { ms: 10 * Y, fmt: fmtYear },\n]\n\nexport function createTimeScale(opts?: TimeScaleOpts): Scale {\n  let dMin = ts(opts?.domain?.[0] ?? 0)\n  let dMax = ts(opts?.domain?.[1] ?? Date.now())\n  let rMin = opts?.range?.[0] ?? 0\n  let rMax = opts?.range?.[1] ?? 1\n  const customFmt = opts?.format\n\n  function map(value: number | string | Date): number {\n    const v = ts(value)\n    const span = dMax - dMin\n    if (span === 0) return (rMin + rMax) / 2\n    return rMin + ((v - dMin) / span) * (rMax - rMin)\n  }\n\n  function invert(px: number): number {\n    const span = rMax - rMin\n    if (span === 0) return (dMin + dMax) / 2\n    return dMin + ((px - rMin) / span) * (dMax - dMin)\n  }\n\n  function ticks(count = 6): Tick[] {\n    const span = dMax - dMin\n    if (span <= 0) return []\n\n    const target = span / count\n    const interval = INTERVALS.find((i) => i.ms >= target) ?? INTERVALS[INTERVALS.length - 1]!\n    const fmt = customFmt ?? interval.fmt\n    const result: Tick[] = []\n    const start = Math.ceil(dMin / interval.ms) * interval.ms\n\n    for (let t = start; t <= dMax; t += interval.ms) {\n      const d = new Date(t)\n      result.push({ value: d, position: map(t), label: fmt(d) })\n    }\n    return result\n  }\n\n  return {\n    map,\n    invert,\n    ticks,\n    setDomain(min, max) { dMin = ts(min); dMax = ts(max) },\n    setRange(min, max) { rMin = min; rMax = max },\n    getDomain() { return [new Date(dMin), new Date(dMax)] },\n    getRange() { return [rMin, rMax] },\n    bandwidth() { return 0 },\n  }\n}\n\nfunction ts(v: number | string | Date): number {\n  return v instanceof Date ? v.getTime() : typeof v === 'string' ? new Date(v).getTime() : v\n}\n\nconst MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] as const\n\nfunction pad(n: number): string { return n < 10 ? `0${n}` : String(n) }\nfunction fmtTime(d: Date): string { return `${pad(d.getHours())}:${pad(d.getMinutes())}` }\nfunction fmtDate(d: Date): string { return `${MONTHS[d.getMonth()]} ${d.getDate()}` }\nfunction fmtMonthYear(d: Date): string { return `${MONTHS[d.getMonth()]} ${d.getFullYear()}` }\nfunction fmtYear(d: Date): string { return String(d.getFullYear()) }\n"]}