{"version":3,"file":"google-charts.mjs","sources":["../src/type/grammar.ts","../src/adapters/google-charts/selectors.ts","../src/adapters/google-charts/converters.ts","../src/google-charts-entry.ts"],"sourcesContent":["/**\n * Represents the trend direction for candlestick data points.\n * Used across the application for audio palette selection and data representation.\n */\nexport type CandlestickTrend = 'Bull' | 'Bear' | 'Neutral';\n\n/**\n * Format function signature for axis values.\n * Takes a value (number or string) and returns a formatted string.\n *\n * @example\n * // Currency formatting\n * const currencyFormat: FormatFunction = (v) => `$${Number(v).toFixed(2)}`;\n *\n * @example\n * // Date formatting\n * const dateFormat: FormatFunction = (v) => new Date(v).toLocaleDateString();\n */\nexport type FormatFunction = (value: number | string) => string;\n\n/**\n * Supported format type specifiers for JSON/HTML API.\n */\nexport type FormatType = 'currency' | 'percent' | 'fixed' | 'number' | 'date' | 'scientific';\n\n/**\n * Configuration for formatting values on an axis.\n *\n * Two ways to specify formatting:\n * 1. `function` - Function body string (for custom logic)\n * 2. `type` - Format type specifier (for common patterns)\n *\n * @example\n * // Using function string\n * { \"function\": \"return `$${Number(value).toFixed(2)}`\" }\n *\n * @example\n * // Using type specifier\n * { \"type\": \"currency\", \"decimals\": 2 }\n */\nexport interface AxisFormat {\n  /**\n   * Function body string for custom formatting.\n   * The function receives `value` as parameter and must return a string.\n   *\n   * @example\n   * // Currency formatting\n   * { \"function\": \"return `$${Number(value).toFixed(2)}`\" }\n   *\n   * @example\n   * // Date formatting\n   * { \"function\": \"return new Date(value).toLocaleDateString('en-US')\" }\n   */\n  function?: string;\n\n  /**\n   * Format type specifier for common formatting patterns.\n   * Use with `decimals`, `currency`, `locale`, `dateOptions` for customization.\n   *\n   * @example\n   * { \"type\": \"currency\", \"currency\": \"USD\", \"decimals\": 2 }\n   * { \"type\": \"percent\", \"decimals\": 1 }\n   * { \"type\": \"date\", \"dateOptions\": { \"month\": \"short\", \"day\": \"numeric\" } }\n   */\n  type?: FormatType;\n\n  /**\n   * Number of decimal places for numeric formatters.\n   * Used with: currency, percent, fixed, number, scientific\n   * @default varies by type\n   */\n  decimals?: number;\n\n  /**\n   * ISO 4217 currency code for currency formatter.\n   * @default 'USD'\n   */\n  currency?: string;\n\n  /**\n   * BCP 47 locale string for locale-aware formatters.\n   * Used with: currency, number, date\n   * @default 'en-US'\n   */\n  locale?: string;\n\n  /**\n   * Options for Intl.DateTimeFormat when using date type.\n   *\n   * @example\n   * { \"month\": \"short\", \"day\": \"numeric\" } // \"Jan 15\"\n   * { \"year\": \"numeric\", \"month\": \"long\" } // \"January 2024\"\n   */\n  dateOptions?: Intl.DateTimeFormatOptions;\n}\n\n/**\n * Configuration for formatting values across all axes in a layer.\n */\nexport interface FormatConfig {\n  x?: AxisFormat;\n  y?: AxisFormat;\n  z?: AxisFormat;\n}\n\n/**\n * Configuration options for violin plot display.\n * Controls which summary statistics are shown in the violin box overlay.\n * Sent from the Python backend alongside violin_kde and violin_box layers.\n */\nexport interface ViolinOptions {\n  /** Show median line marker. Default: true */\n  showMedian?: boolean;\n  /** Show mean value marker. Default: false */\n  showMean?: boolean;\n  /** Show extrema (min/max) markers. Default: true */\n  showExtrema?: boolean;\n}\n\n/**\n * Data point for violin KDE (kernel density estimation) curves.\n * Library-agnostic — no SVG coordinates embedded in data.\n * The density field falls back to width if absent.\n */\nexport interface ViolinKdePoint {\n  /** Categorical label for the violin (e.g., \"setosa\") */\n  x: string | number;\n  /** Position along the density axis */\n  y: number;\n  /** KDE density value at this point. Falls back to `width` if absent. */\n  density?: number;\n  /** Half-width of the violin at this Y level (used as density fallback) */\n  width?: number;\n  /** SVG viewport x-coordinate for highlight positioning (provided by backend) */\n  svg_x?: number;\n  /** SVG viewport y-coordinate for highlight positioning (provided by backend) */\n  svg_y?: number;\n}\n\n/**\n * Root MAIDR data structure containing figure metadata and subplot grid.\n * This is the type for the `data` prop passed to the `<Maidr>` React component.\n *\n * @example\n * ```typescript\n * const data: Maidr = {\n *   id: 'my-chart',\n *   title: 'Sales by Quarter',\n *   subplots: [[{\n *     layers: [{\n *       id: '0',\n *       type: 'bar',\n *       axes: { x: 'Quarter', y: 'Revenue' },\n *       data: [{ x: 'Q1', y: 120 }, { x: 'Q2', y: 200 }],\n *     }],\n *   }]],\n * };\n * ```\n */\nexport interface Maidr {\n  /** Unique identifier for the chart. Used for DOM element IDs. */\n  id: string;\n  /** Chart title displayed in text descriptions. */\n  title?: string;\n  /** Chart subtitle. */\n  subtitle?: string;\n  /** Chart caption. */\n  caption?: string;\n  /**\n   * 2D grid of subplots. Each row is an array of subplots.\n   * For a single chart, use `[[{ layers: [...] }]]`.\n   */\n  subplots: MaidrSubplot[][];\n}\n\n/**\n * Subplot data structure containing optional legend and trace layers.\n * A subplot groups one or more layers (traces) that share the same coordinate space.\n *\n * @example\n * ```typescript\n * const subplot: MaidrSubplot = {\n *   layers: [\n *     { id: '0', type: 'bar', axes: { x: 'X', y: 'Y' }, data: [...] },\n *     { id: '1', type: 'line', axes: { x: 'X', y: 'Y' }, data: [...] },\n *   ],\n * };\n * ```\n */\nexport interface MaidrSubplot {\n  /** Legend labels for multi-series plots. */\n  legend?: string[];\n  /** CSS selector for the subplot container element. */\n  selector?: string;\n  /** Array of trace layers in this subplot. */\n  layers: MaidrLayer[];\n}\n\n/**\n * Data point for bar charts with x and y coordinates.\n */\nexport interface BarPoint {\n  x: string | number;\n  y: number | string;\n}\n\n/**\n * Data point for boxplots containing quartiles, min/max, and outliers.\n */\nexport interface BoxPoint {\n  z: string;\n  lowerOutliers: number[];\n  min: number;\n  q1: number;\n  q2: number;\n  q3: number;\n  max: number;\n  upperOutliers: number[];\n  /** Mean value for violin plots when mean display is enabled. */\n  mean?: number;\n}\n\n/**\n * DOM selectors for boxplot visual elements.\n */\nexport interface BoxSelector {\n  lowerOutliers: string[];\n  min: string;\n  iq: string;\n  q2: string;\n  max: string;\n  upperOutliers: string[];\n  /** CSS selector for mean marker element in violin plots. */\n  mean?: string;\n  /** Optional direct CSS selector for Q1 element (bypasses iq edge derivation). */\n  q1?: string;\n  /** Optional direct CSS selector for Q3 element (bypasses iq edge derivation). */\n  q3?: string;\n}\n\n/**\n * Data point for candlestick charts with OHLC values, volume, and trend information.\n */\nexport interface CandlestickPoint {\n  value: string;\n  open: number;\n  high: number;\n  low: number;\n  close: number;\n  /** Optional volume data. May be undefined when source (e.g., Google Charts) doesn't provide it. */\n  volume?: number;\n  trend: CandlestickTrend;\n  volatility: number;\n}\n\n/**\n * Data structure for heatmap charts with x/y labels and 2D point values.\n */\nexport interface HeatmapData {\n  x: string[];\n  y: string[];\n  points: number[][];\n}\n\n/**\n * Data point for histograms extending bar points with bin ranges.\n */\nexport interface HistogramPoint extends BarPoint {\n  xMin: number;\n  xMax: number;\n  yMin: number;\n  yMax: number;\n}\n\n/**\n * Data point for line charts with optional fill color for multi-series plots.\n */\nexport interface LinePoint {\n  x: number | string;\n  y: number;\n  z?: string;\n}\n\n/**\n * Data point for scatter plots with x and y coordinates.\n */\nexport interface ScatterPoint {\n  x: number;\n  y: number;\n}\n\n/**\n * Data point for segmented/grouped bar charts with fill color identifier.\n */\nexport interface SegmentedPoint extends BarPoint {\n  z: string;\n}\n\n/**\n * Data point for smooth/regression plots with data and SVG coordinate pairs.\n */\nexport interface SmoothPoint {\n  x: number;\n  y: number;\n  svg_x: number;\n  svg_y: number;\n}\n\n/**\n * Extended axis configuration that includes an optional label and grid navigation properties.\n * Used when an axis needs both a label and grid config (min, max, tickStep).\n *\n * @example\n * // axes.x as an object with grid config\n * axes: { x: { label: \"Sepal Length\", min: 4.3, max: 7.9, tickStep: 0.7 } }\n */\nexport interface AxisConfig {\n  label?: string;\n  min?: number;\n  max?: number;\n  tickStep?: number;\n}\n\n/**\n * Alternate grid configuration shape where grid properties are grouped by property name.\n * Supports `axes.min.x`, `axes.max.x`, `axes.tickStep.x` etc.\n *\n * @example\n * axes: { x: \"Sepal Length\", min: { x: 4.3, y: 2 }, max: { x: 7.9, y: 4.4 }, tickStep: { x: 0.7, y: 0.5 } }\n */\nexport interface AxisGridProperty {\n  x?: number;\n  y?: number;\n}\n\n/**\n * Chart orientation for bar and box plots.\n */\nexport enum Orientation {\n  VERTICAL = 'vert',\n  HORIZONTAL = 'horz',\n}\n\n/**\n * DOM selectors for candlestick chart visual elements.\n */\nexport interface CandlestickSelector {\n  body: string | string[];\n  wickHigh?: string | string[];\n  wickLow?: string | string[];\n  wick?: string | string[]; // single combined wick (high-to-low) line\n  open?: string | string[];\n  close?: string | string[];\n}\n\n/**\n * Layer/trace definition containing plot type, data, and rendering configuration.\n */\nexport interface MaidrLayer {\n  id: string;\n  type: TraceType;\n  title?: string;\n  selectors?: string | string[] | BoxSelector[] | CandlestickSelector;\n  orientation?: Orientation;\n  /**\n   * Optional DOM mapping hints. When provided, individual traces can opt-in\n   * to use these hints to map DOM elements to the internal row-major data grid\n   * without changing default behavior when omitted.\n   */\n  domMapping?: {\n    /**\n     * Specify DOM flattening order for grid-like traces.\n     * 'row' => row-major, 'column' => column-major.\n     */\n    order?: 'row' | 'column';\n    /**\n     * For segmented/dodged bars, control the per-column group/level iteration.\n     * 'forward' => iterate groups top-to-bottom (as previously domOrder='forward').\n     * 'reverse' => iterate bottom-to-top (default).\n     */\n    groupDirection?: 'forward' | 'reverse';\n    /**\n     * For boxplots, control the Q1/Q3 edge mapping for IQR box.\n     * 'forward' => Q1=bottom, Q3=top (default for vertical)\n     * 'reverse' => Q1=top, Q3=bottom (for Base R vertical boxplots)\n     */\n    iqrDirection?: 'forward' | 'reverse';\n  };\n  /**\n   * Axis configuration including labels, optional formatting, and grid navigation properties.\n   *\n   * Supports two shapes for grid config (both can coexist):\n   *\n   * **Format A** – per-axis objects (`axes.x.min`):\n   * ```json\n   * { \"axes\": { \"x\": { \"label\": \"Sepal Length\", \"min\": 4.3, \"max\": 7.9, \"tickStep\": 0.7 } } }\n   * ```\n   *\n   * **Format B** – grouped by property (`axes.min.x`):\n   * ```json\n   * { \"axes\": { \"x\": \"Sepal Length\", \"min\": { \"x\": 4.3, \"y\": 2 }, \"tickStep\": { \"x\": 0.7, \"y\": 0.5 } } }\n   * ```\n   *\n   * @example\n   * // Basic axis labels (no grid)\n   * axes: { x: \"Date\", y: \"Price\" }\n   *\n   * @example\n   * // With formatting\n   * axes: { x: \"Date\", y: \"Price\", format: { y: { type: \"currency\", decimals: 2 } } }\n   */\n  axes?: {\n    /** Axis label (string) or axis config object with label + grid properties. */\n    x?: string | AxisConfig;\n    /** Axis label (string) or axis config object with label + grid properties. */\n    y?: string | AxisConfig;\n    /** Z-axis label (string) or axis config object. Used for grouping/fill in multi-series plots. */\n    z?: string | AxisConfig;\n    /** Grouped grid property: `min: { x: 4.3, y: 2 }` */\n    min?: AxisGridProperty;\n    /** Grouped grid property: `max: { x: 7.9, y: 4.4 }` */\n    max?: AxisGridProperty;\n    /** Grouped grid property: `tickStep: { x: 0.7, y: 0.5 }` */\n    tickStep?: AxisGridProperty;\n    /**\n     * Optional formatting configuration for axis values.\n     * When provided, values displayed in text descriptions will be formatted.\n     *\n     * @example\n     * format: {\n     *   x: { function: \"return new Date(value).toLocaleDateString()\" },\n     *   y: { type: \"currency\", decimals: 2 }\n     * }\n     */\n    format?: FormatConfig;\n  };\n  /**\n   * Optional display configuration for violin plot layers (VIOLIN_KDE and VIOLIN_BOX).\n   * Controls which summary statistics are shown in the violin box overlay.\n   */\n  violinOptions?: ViolinOptions;\n  data:\n    | BarPoint[]\n    | BoxPoint[]\n    | CandlestickPoint[]\n    | HeatmapData\n    | HistogramPoint[]\n    | LinePoint[][]\n    | ScatterPoint[]\n    | SegmentedPoint[][]\n    | SmoothPoint[][]\n    | ViolinKdePoint[][];\n}\n\n/**\n * Enumeration of supported plot trace types.\n * Use these values for the `type` field in {@link MaidrLayer}.\n *\n * @example\n * ```typescript\n * import { TraceType } from 'maidr/react';\n * const layer = { id: '0', type: TraceType.BAR, ... };\n * // Or use the string value directly:\n * const layer2 = { id: '0', type: 'bar', ... };\n * ```\n */\nexport enum TraceType {\n  BAR = 'bar',\n  BOX = 'box',\n  CANDLESTICK = 'candlestick',\n  DODGED = 'dodged_bar',\n  HEATMAP = 'heat',\n  HISTOGRAM = 'hist',\n  LINE = 'line',\n  NORMALIZED = 'stacked_normalized_bar',\n  SCATTER = 'point',\n  SMOOTH = 'smooth',\n  STACKED = 'stacked_bar',\n  VIOLIN_BOX = 'violin_box',\n  VIOLIN_KDE = 'violin_kde',\n}\n","/**\n * CSS selectors for Google Charts SVG elements.\n *\n * Google Charts renders SVG with specific structure patterns. These selectors\n * target the individual data point elements that MAIDR uses for visual\n * highlighting during keyboard navigation.\n *\n * SVG structure reference:\n *\n * Bar/Column Charts:\n *   The chart-area data elements live inside a `<g>` with a `clip-path`\n *   attribute, which distinguishes them from axes, gridlines, legends,\n *   and background rects.\n *   [target: g[clip-path] > rect]\n *\n * Line Charts:\n *   Line paths typically have `fill=\"none\"` to distinguish from area fills.\n *   [target: path[fill=\"none\"] or path]\n *\n * Scatter Charts:\n *   Data points are rendered as circles.\n *   [target: circle]\n *\n * Selectors are scoped to the container element to avoid matching elements\n * from other charts on the same page.\n */\n\n/**\n * Generates a unique ID with the given prefix using crypto.randomUUID().\n *\n * Uses the browser's cryptographically-secure random UUID generator to ensure\n * truly unique IDs without module-level mutable state.\n *\n * @param prefix - The prefix for the generated ID\n * @returns A unique string ID (e.g., \"maidr-gc-a1b2c3d4-...\")\n */\nexport function nextId(prefix: string): string {\n  // Use first 8 chars of UUID for shorter, readable IDs\n  const uuid = crypto.randomUUID().slice(0, 8);\n  return `${prefix}-${uuid}`;\n}\n\n/**\n * Assigns a stable, unique `id` to the container element if it doesn't\n * already have one. This is called once, up-front, so that the per-layer\n * `buildDataSelector` calls don't mutate the DOM as a side-effect.\n *\n * @param container - The container element to ensure has an ID\n */\nexport function ensureContainerId(container: HTMLElement): void {\n  if (!container.id) {\n    container.id = nextId('maidr-gc-container');\n  }\n}\n\n/**\n * Builds a scoped CSS selector targeting chart data elements inside the\n * container.\n *\n * Google Charts renders its SVG inside the container `<div>`. The chart-area\n * data elements live inside a `<g>` with a `clip-path` attribute, which\n * distinguishes them from axes, gridlines, legends, and background rects.\n * We prefer the narrower `g[clip-path] > <element>` selector; if no\n * clip-path group exists we fall back to the broader `svg <element>`.\n *\n * @param container - The container element holding the chart SVG\n * @param elementSelector - The element type to target (e.g., 'rect', 'circle', 'path')\n * @returns A CSS selector string, or `undefined` when no matching elements\n *          are found.\n */\nexport function buildDataSelector(\n  container: HTMLElement,\n  elementSelector: string,\n): string | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg)\n    return undefined;\n\n  // Prefer elements inside the chart-area clip-path group (excludes axes,\n  // gridlines, legends, background rects).\n  const clippedSelector = `g[clip-path] > ${elementSelector}`;\n  const clippedCandidates = svg.querySelectorAll(clippedSelector);\n  if (clippedCandidates.length > 0)\n    return `#${container.id} svg ${clippedSelector}`;\n\n  // Fallback: any matching element in the SVG.\n  const candidates = svg.querySelectorAll(elementSelector);\n  if (candidates.length > 0)\n    return `#${container.id} svg ${elementSelector}`;\n\n  return undefined;\n}\n","/**\n * Data converters for transforming Google Charts data into MAIDR's schema.\n *\n * Google Charts uses a DataTable structure where:\n *   - Column 0 is typically the domain/label column\n *   - Columns 1..N are data series\n *   - Role columns (tooltip, annotation, style) are interspersed\n *\n * MAIDR uses typed data structures per chart type:\n *   BarPoint[]          = [{ x, y }, ...]\n *   LinePoint[][]       = [[{ x, y, fill? }, ...], ...]\n *   ScatterPoint[]      = [{ x, y }, ...]\n *   SegmentedPoint[][]  = [[{ x, y, fill }, ...], ...]  (stacked/dodged/normalized)\n *   CandlestickPoint[]  = [{ value, open, high, low, close, ... }, ...]\n */\n\nimport type {\n  BarPoint,\n  CandlestickPoint,\n  CandlestickSelector,\n  CandlestickTrend,\n  LinePoint,\n  Maidr,\n  MaidrLayer,\n  MaidrSubplot,\n  ScatterPoint,\n  SegmentedPoint,\n} from '@type/grammar';\nimport type { GoogleBoundingBox, GoogleChart, GoogleChartType, GoogleDataTable } from './types';\nimport { Orientation, TraceType } from '@type/grammar';\nimport { buildDataSelector, ensureContainerId, nextId } from './selectors';\n\n/**\n * Tolerance (in pixels) for matching SVG rect positions to bounding boxes.\n * Google Charts positions may have floating-point imprecision.\n */\nconst POSITION_TOLERANCE = 2;\n\n/**\n * Candlestick element width thresholds (in pixels).\n *\n * Google Charts renders candlesticks as SVG rect elements with varying widths:\n * - Grid lines: width ≤ 1px (horizontal or vertical axis lines)\n * - Wicks: width ≤ 3px (thin rects representing high-low range)\n * - Bodies: width > 10px (wider rects representing open-close range)\n *\n * These thresholds are based on default Google Charts rendering. They may need\n * adjustment for custom chart sizes or high-DPI displays.\n */\nconst CANDLESTICK_GRID_MAX_WIDTH = 1;\nconst CANDLESTICK_WICK_MAX_WIDTH = 3;\nconst CANDLESTICK_BODY_MIN_WIDTH = 10;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Options accepted by {@link createMaidrFromGoogleChart}.\n */\nexport interface GoogleChartAdapterOptions {\n  /** Unique ID for the MAIDR instance. Defaults to the container element's `id`. */\n  id?: string;\n  /** Chart title. Extracted from chart options when omitted. */\n  title?: string;\n  /**\n   * The Google Charts chart type string (e.g. `'BarChart'`, `'LineChart'`).\n   * Must be provided because the chart instance does not expose its own type.\n   *\n   * For stacked, normalized, or grouped (dodged) variants of bar / column\n   * charts, use the explicit adapter type strings such as\n   * `'StackedColumnChart'`, `'NormalizedBarChart'`, or `'DodgedColumnChart'`.\n   */\n  chartType: GoogleChartType;\n}\n\n/**\n * Creates a MAIDR data object from a rendered Google Charts chart.\n *\n * Call this **after** the chart has finished rendering (inside the\n * `google.visualization.events.addListener(chart, 'ready', …)` callback)\n * so that the container DOM already contains the SVG elements.\n *\n * @param chart     - The Google Charts chart instance. Used to access\n *                    `getChartLayoutInterface()` for locating SVG elements.\n * @param dataTable - The `google.visualization.DataTable` (or DataView) used\n *                    to draw the chart.\n * @param container - The DOM element the chart was drawn into.\n * @param options   - Adapter options (chart type is required).\n * @returns A {@link Maidr} object ready to be passed to `<Maidr data={…}>` or\n *          set as the `maidr` / `maidr-data` attribute.\n *\n * @example\n * ```js\n * google.charts.load('current', { packages: ['corechart'] });\n * google.charts.setOnLoadCallback(() => {\n *   const data = google.visualization.arrayToDataTable([\n *     ['City', 'Population'],\n *     ['New York', 8336817],\n *     ['Los Angeles', 3979576],\n *   ]);\n *   const container = document.getElementById('chart');\n *   const chart = new google.visualization.ColumnChart(container);\n *\n *   google.visualization.events.addListener(chart, 'ready', () => {\n *     const maidr = createMaidrFromGoogleChart(chart, data, container, {\n *       chartType: 'ColumnChart',\n *     });\n *     container.setAttribute('maidr', JSON.stringify(maidr));\n *   });\n *\n *   chart.draw(data);\n * });\n * ```\n */\nexport function createMaidrFromGoogleChart(\n  chart: GoogleChart,\n  dataTable: GoogleDataTable,\n  container: HTMLElement,\n  options: GoogleChartAdapterOptions,\n): Maidr {\n  const id = options.id ?? container.id ?? nextId('maidr-gc');\n  const title = options.title ?? '';\n\n  // Assign a stable container id up-front (used for scoped CSS selectors).\n  ensureContainerId(container);\n\n  const layer = buildLayer(chart, dataTable, container, options.chartType);\n\n  const subplot: MaidrSubplot = { layers: [layer] };\n\n  return {\n    id,\n    ...(title ? { title } : {}),\n    subplots: [[subplot]],\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Layer builders — one per supported chart type\n// ---------------------------------------------------------------------------\n\nfunction buildLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n  chartType: GoogleChartType,\n): MaidrLayer {\n  switch (chartType) {\n    case 'ColumnChart':\n      return buildBarOrSegmentedLayer(chart, dt, container, Orientation.VERTICAL);\n    case 'BarChart':\n      return buildBarOrSegmentedLayer(chart, dt, container, Orientation.HORIZONTAL);\n    case 'LineChart':\n      return buildLineLayer(chart, dt, container);\n    case 'ScatterChart':\n      return buildScatterLayer(chart, dt, container);\n    case 'StackedColumnChart':\n      return buildSegmentedLayer(chart, dt, container, Orientation.VERTICAL, TraceType.STACKED);\n    case 'StackedBarChart':\n      return buildSegmentedLayer(chart, dt, container, Orientation.HORIZONTAL, TraceType.STACKED);\n    case 'DodgedColumnChart':\n      return buildSegmentedLayer(chart, dt, container, Orientation.VERTICAL, TraceType.DODGED);\n    case 'DodgedBarChart':\n      return buildSegmentedLayer(chart, dt, container, Orientation.HORIZONTAL, TraceType.DODGED);\n    case 'CandlestickChart':\n      return buildCandlestickLayer(chart, dt, container);\n    default:\n      throw new Error(\n        `Unsupported Google Charts type: ${chartType as string}. `\n        + 'Supported types: BarChart, CandlestickChart, ColumnChart, DodgedBarChart, '\n        + 'DodgedColumnChart, LineChart, ScatterChart, StackedBarChart, StackedColumnChart.',\n      );\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Bar / Column — auto-detects single vs multi-series\n// ---------------------------------------------------------------------------\n\n/**\n * Inspects the DataTable and delegates to {@link buildBarLayer} for a single\n * data column, or to {@link buildSegmentedLayer} when multiple data columns\n * are present (grouped / dodged layout).\n */\nfunction buildBarOrSegmentedLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n  orientation: Orientation,\n): MaidrLayer {\n  const dataColCount = countDataColumns(dt);\n  if (dataColCount > 1) {\n    return buildSegmentedLayer(chart, dt, container, orientation, TraceType.DODGED);\n  }\n  return buildBarLayer(chart, dt, container, orientation);\n}\n\nfunction buildBarLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n  orientation: Orientation,\n): MaidrLayer {\n  const data: BarPoint[] = [];\n  const rows = dt.getNumberOfRows();\n\n  // Find first non-role data column (defensive: don't assume column 1 is data)\n  let dataCol = 1;\n  for (let c = 1; c < dt.getNumberOfColumns(); c++) {\n    if (!isRoleColumn(dt, c)) {\n      dataCol = c;\n      break;\n    }\n  }\n\n  for (let r = 0; r < rows; r++) {\n    const label = formatCellValue(dt, r, 0);\n    const value = numericValue(dt, r, dataCol);\n    data.push({ x: label, y: value });\n  }\n\n  // Use chart API to find and mark the correct SVG rect elements\n  const selector = markBarElements(chart, container, rows, 1);\n\n  return {\n    id: nextId('layer'),\n    type: TraceType.BAR,\n    orientation,\n    ...(selector ? { selectors: selector } : {}),\n    axes: {\n      x: dt.getColumnLabel(0) || undefined,\n      y: dt.getColumnLabel(dataCol) || undefined,\n    },\n    data,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Segmented bars (stacked, dodged / grouped, normalized)\n// ---------------------------------------------------------------------------\n\nfunction buildSegmentedLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n  orientation: Orientation,\n  traceType: TraceType.STACKED | TraceType.DODGED,\n): MaidrLayer {\n  const cols = dt.getNumberOfColumns();\n  const rows = dt.getNumberOfRows();\n\n  // Build standard data array: data[series][category]\n  // - row index = series (the \"Level\" in text output)\n  // - col index = category (x-axis value)\n  //\n  // Navigation:\n  // - Up/Down arrows: move between series (changes row)\n  // - Left/Right arrows: move between categories (changes col)\n  const data: SegmentedPoint[][] = [];\n  let seriesCount = 0;\n\n  for (let c = 1; c < cols; c++) {\n    if (isRoleColumn(dt, c))\n      continue;\n\n    const series: SegmentedPoint[] = [];\n    const fillLabel = dt.getColumnLabel(c) || `Series ${seriesCount + 1}`;\n\n    for (let r = 0; r < rows; r++) {\n      const label = formatCellValue(dt, r, 0);\n      const value = numericValue(dt, r, c);\n      series.push({ x: label, y: value, z: fillLabel });\n    }\n    data.push(series);\n    seriesCount++;\n  }\n\n  // Use chart API to find and mark SVG rect elements.\n  // Google Charts renders DOM in row-major order (all categories for series 0,\n  // then all categories for series 1, etc.), so we set domMapping.order='row'\n  // to tell MAIDR to iterate in row-major order when mapping SVG elements.\n  const selector = markSegmentedBarElements(chart, container, rows, seriesCount);\n\n  return {\n    id: nextId('layer'),\n    type: traceType,\n    orientation,\n    ...(selector ? { selectors: selector } : {}),\n    // 'row' tells MAIDR that DOM elements are in row-major order (series-first)\n    domMapping: { order: 'row' },\n    axes: {\n      x: dt.getColumnLabel(0) || undefined,\n      y: 'Level',\n    },\n    data,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Line / Area\n// ---------------------------------------------------------------------------\n\nfunction buildLineLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n): MaidrLayer {\n  const cols = dt.getNumberOfColumns();\n  const rows = dt.getNumberOfRows();\n\n  // Each data column (1 .. cols-1) is a separate series.\n  const data: LinePoint[][] = [];\n  let seriesCount = 0;\n\n  for (let c = 1; c < cols; c++) {\n    if (isRoleColumn(dt, c))\n      continue;\n    const series: LinePoint[] = [];\n    for (let r = 0; r < rows; r++) {\n      const x = formatCellValue(dt, r, 0);\n      const y = numericValue(dt, r, c);\n      const z = dt.getColumnLabel(c) || `Series ${c}`;\n      series.push({ x, y, z });\n    }\n    data.push(series);\n    seriesCount++;\n  }\n\n  // Use chart API to create synthetic point elements for each series\n  const selectors = markLinePointElements(chart, container, rows, seriesCount);\n\n  return {\n    id: nextId('layer'),\n    type: TraceType.LINE,\n    ...(selectors && selectors.length > 0 ? { selectors } : {}),\n    axes: {\n      x: dt.getColumnLabel(0) || undefined,\n      y: dt.getColumnLabel(1) || undefined,\n    },\n    data,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Scatter\n// ---------------------------------------------------------------------------\n\nfunction buildScatterLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n): MaidrLayer {\n  const rows = dt.getNumberOfRows();\n  const data: ScatterPoint[] = [];\n\n  for (let r = 0; r < rows; r++) {\n    const x = numericValue(dt, r, 0);\n    const y = numericValue(dt, r, 1);\n    data.push({ x, y });\n  }\n\n  // Use chart API to find and mark the correct SVG circle elements\n  const selector = markScatterElements(chart, container, data);\n\n  return {\n    id: nextId('layer'),\n    type: TraceType.SCATTER,\n    ...(selector ? { selectors: selector } : {}),\n    axes: {\n      x: dt.getColumnLabel(0) || undefined,\n      y: dt.getColumnLabel(1) || undefined,\n    },\n    data,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Candlestick\n// ---------------------------------------------------------------------------\n\n/**\n * Builds a candlestick layer from a Google Charts CandlestickChart.\n *\n * Google Charts candlestick DataTable format:\n *   - Column 0: Date/datetime (x-axis)\n *   - Column 1: Low value\n *   - Column 2: Open value\n *   - Column 3: Close value\n *   - Column 4: High value\n *\n * MAIDR CandlestickPoint format:\n *   { value, open, high, low, close, volume, trend, volatility }\n */\nfunction buildCandlestickLayer(\n  chart: GoogleChart,\n  dt: GoogleDataTable,\n  container: HTMLElement,\n): MaidrLayer {\n  const rows = dt.getNumberOfRows();\n  const data: CandlestickPoint[] = [];\n\n  for (let r = 0; r < rows; r++) {\n    const value = formatCellValue(dt, r, 0);\n    // Google Charts order: Low, Open, Close, High (columns 1-4)\n    const low = numericValue(dt, r, 1);\n    const open = numericValue(dt, r, 2);\n    const close = numericValue(dt, r, 3);\n    const high = numericValue(dt, r, 4);\n\n    // Compute trend based on open/close relationship\n    let trend: CandlestickTrend = 'Neutral';\n    if (close > open) {\n      trend = 'Bull';\n    } else if (close < open) {\n      trend = 'Bear';\n    }\n\n    data.push({\n      value,\n      open,\n      high,\n      low,\n      close,\n      volume: undefined, // Google Charts doesn't provide volume data\n      trend,\n      volatility: high - low,\n    });\n  }\n\n  // Mark candlestick SVG elements and get selectors\n  const selectors = markCandlestickElements(chart, container, rows);\n\n  return {\n    id: nextId('layer'),\n    type: TraceType.CANDLESTICK,\n    ...(selectors ? { selectors } : {}),\n    axes: {\n      x: dt.getColumnLabel(0) || 'Date',\n      y: 'Price',\n    },\n    data,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers — cell value extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Returns a human-readable string for a cell value.\n *\n * Prefers the formatted value (which respects locale and date formatting)\n * and only falls back to the raw value when the formatted string is empty.\n */\nfunction formatCellValue(dt: GoogleDataTable, row: number, col: number): string {\n  const formatted = dt.getFormattedValue(row, col);\n  if (formatted)\n    return formatted;\n\n  const raw = dt.getValue(row, col);\n  if (raw instanceof Date)\n    return raw.toLocaleDateString();\n  return String(raw ?? '');\n}\n\n/**\n * Extracts a numeric value from a cell, returning `NaN` for genuinely\n * missing data instead of silently coercing it to `0`.\n */\nfunction numericValue(dt: GoogleDataTable, row: number, col: number): number {\n  const raw = dt.getValue(row, col);\n  if (raw === null || raw === undefined)\n    return Number.NaN;\n  return Number(raw);\n}\n\n// ---------------------------------------------------------------------------\n// Helpers — DataTable inspection\n// ---------------------------------------------------------------------------\n\n/**\n * Returns `true` when column `c` is a \"role\" column (tooltip, annotation,\n * style, etc.) rather than a data column.\n */\nfunction isRoleColumn(dt: GoogleDataTable, c: number): boolean {\n  if (dt.getColumnRole) {\n    const role = dt.getColumnRole(c);\n    return role !== '' && role !== 'data';\n  }\n  return false;\n}\n\n/**\n * Counts non-role data columns (excluding the domain/label column 0).\n */\nfunction countDataColumns(dt: GoogleDataTable): number {\n  let count = 0;\n  for (let c = 1; c < dt.getNumberOfColumns(); c++) {\n    if (!isRoleColumn(dt, c))\n      count++;\n  }\n  return count;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers — SVG element marking via chart layout API\n// ---------------------------------------------------------------------------\n\n/**\n * Uses the Google Charts layout API to find and mark the SVG rect elements\n * that correspond to each bar. Returns a CSS selector for the marked elements.\n *\n * Google Charts renders many overlapping rect elements for visual effects.\n * The layout API provides the exact bounding box for each bar, allowing us\n * to identify the correct elements by matching coordinates.\n *\n * @param chart - The Google Chart instance\n * @param container - The DOM container element\n * @param rowCount - Number of data rows (bars per series)\n * @param seriesCount - Number of data series\n * @returns CSS selector for the marked elements, or undefined if no elements found\n */\nfunction markBarElements(\n  chart: GoogleChart,\n  container: HTMLElement,\n  rowCount: number,\n  seriesCount: number,\n): string | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg)\n    return undefined;\n\n  const layout = chart.getChartLayoutInterface();\n  if (!layout)\n    return buildDataSelector(container, 'rect');\n\n  // Get all rects in the SVG\n  const allRects = svg.querySelectorAll('rect');\n\n  // Clear any existing marks from previous initializations\n  allRects.forEach(rect => rect.removeAttribute('data-maidr-bar'));\n\n  let markedCount = 0;\n\n  // For each series and data point, find the corresponding rect\n  for (let series = 0; series < seriesCount; series++) {\n    for (let dataIndex = 0; dataIndex < rowCount; dataIndex++) {\n      const bbox = layout.getBoundingBox(`bar#${series}#${dataIndex}`);\n      if (!bbox)\n        continue;\n\n      const rect = findRectByBoundingBox(allRects, bbox);\n      if (rect) {\n        // Mark with series and index for ordered selection\n        rect.setAttribute('data-maidr-bar', `${series}-${dataIndex}`);\n        markedCount++;\n      }\n    }\n  }\n\n  if (markedCount === 0)\n    return buildDataSelector(container, 'rect');\n\n  return `#${container.id} svg rect[data-maidr-bar]`;\n}\n\n/**\n * Uses the Google Charts layout API to find and mark the SVG rect elements\n * for segmented bar charts (stacked, dodged, normalized).\n *\n * Unlike simple bar charts, segmented charts have a 2D structure where\n * SegmentedTrace expects elements ordered **category-first**:\n *   Category A: Series 0, Series 1\n *   Category B: Series 0, Series 1\n *   etc.\n *\n * This function marks elements in the correct order for mapToSvgElements().\n *\n * @param chart - The Google Chart instance\n * @param container - The DOM container element\n * @param categoryCount - Number of categories\n * @param seriesCount - Number of data series\n * @returns CSS selector for the marked elements, or undefined if no elements found\n */\nfunction markSegmentedBarElements(\n  chart: GoogleChart,\n  container: HTMLElement,\n  categoryCount: number,\n  seriesCount: number,\n): string | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg)\n    return undefined;\n\n  const layout = chart.getChartLayoutInterface();\n  if (!layout)\n    return buildDataSelector(container, 'rect');\n\n  // Get all rects in the SVG\n  const allRects = svg.querySelectorAll('rect');\n\n  // Clear any existing marks from previous initializations\n  allRects.forEach(rect => rect.removeAttribute('data-maidr-bar'));\n\n  let markedCount = 0;\n\n  // Mark elements in ROW-MAJOR order (series-first, then categories within each series)\n  // This matches Google Charts' DOM rendering order, where all bars for series 0\n  // appear first, followed by all bars for series 1, etc.\n  //\n  // With domMapping.order='row', MAIDR iterates:\n  //   for (r = 0 to numSeries)\n  //     for (c = 0 to numCategories)\n  //       svgElements[r].push(domElements[domIndex++])\n  //\n  // Google Charts' getBoundingBox uses: bar#seriesIndex#categoryIndex\n  for (let series = 0; series < seriesCount; series++) {\n    for (let category = 0; category < categoryCount; category++) {\n      const bbox = layout.getBoundingBox(`bar#${series}#${category}`);\n      if (!bbox) {\n        continue;\n      }\n\n      const rect = findRectByBoundingBox(allRects, bbox);\n      if (rect) {\n        rect.setAttribute('data-maidr-bar', `${markedCount}`);\n        markedCount++;\n      }\n    }\n  }\n\n  const selector = `#${container.id} svg rect[data-maidr-bar]`;\n\n  if (markedCount === 0)\n    return buildDataSelector(container, 'rect');\n\n  return selector;\n}\n\n/**\n * Finds an SVG rect element that matches the given bounding box coordinates.\n *\n * Due to floating-point precision issues in Google Charts rendering,\n * we use a small tolerance when comparing positions.\n *\n * @param rects - NodeList of SVG rect elements to search\n * @param bbox - The target bounding box from the chart layout API\n * @returns The matching rect element, or null if not found\n */\nfunction findRectByBoundingBox(\n  rects: NodeListOf<SVGRectElement>,\n  bbox: GoogleBoundingBox,\n): SVGRectElement | null {\n  for (const rect of rects) {\n    const x = Number.parseFloat(rect.getAttribute('x') || '0');\n    const y = Number.parseFloat(rect.getAttribute('y') || '0');\n    const width = Number.parseFloat(rect.getAttribute('width') || '0');\n    const height = Number.parseFloat(rect.getAttribute('height') || '0');\n\n    // Match by position and size with tolerance\n    const xMatch = Math.abs(x - bbox.left) <= POSITION_TOLERANCE;\n    const yMatch = Math.abs(y - bbox.top) <= POSITION_TOLERANCE;\n    const widthMatch = Math.abs(width - bbox.width) <= POSITION_TOLERANCE;\n    const heightMatch = Math.abs(height - bbox.height) <= POSITION_TOLERANCE;\n\n    if (xMatch && yMatch && widthMatch && heightMatch) {\n      return rect;\n    }\n  }\n  return null;\n}\n\n/**\n * Uses the Google Charts layout API to find and mark the SVG circle elements\n * that correspond to each scatter point. Returns a CSS selector for the marked elements.\n *\n * Google Charts renders multiple overlapping circles per data point for visual effects.\n * This function tries two approaches:\n * 1. Use getBoundingBox('point#0#i') to get exact positions (preferred)\n * 2. Fall back to getXLocation/getYLocation with skip-already-marked logic\n *\n * @param chart - The Google Chart instance\n * @param container - The DOM container element\n * @param data - Array of scatter points with x, y coordinates\n * @returns CSS selector for the marked elements, or undefined if no elements found\n */\nfunction markScatterElements(\n  chart: GoogleChart,\n  container: HTMLElement,\n  data: ScatterPoint[],\n): string | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg)\n    return undefined;\n\n  const layout = chart.getChartLayoutInterface();\n  if (!layout)\n    return buildDataSelector(container, 'circle');\n\n  // Get all circles in the SVG\n  const allCircles = svg.querySelectorAll('circle');\n  if (allCircles.length === 0)\n    return undefined;\n\n  // Clear any existing marks from previous initializations\n  allCircles.forEach(circle => circle.removeAttribute('data-maidr-point'));\n\n  let markedCount = 0;\n\n  // Approach 1: Try getBoundingBox('point#series#row') - similar to bar charts\n  for (let i = 0; i < data.length; i++) {\n    const bbox = layout.getBoundingBox(`point#0#${i}`);\n    if (bbox) {\n      const circle = findCircleByBoundingBox(allCircles, bbox);\n      if (circle && !circle.hasAttribute('data-maidr-point')) {\n        circle.setAttribute('data-maidr-point', `${i}`);\n        markedCount++;\n      }\n    }\n  }\n\n  // Approach 2: Fallback to position-based matching if getBoundingBox didn't work\n  if (markedCount === 0 && layout.getXLocation && layout.getYLocation) {\n    for (let i = 0; i < data.length; i++) {\n      const point = data[i];\n      const expectedX = layout.getXLocation(point.x);\n      const expectedY = layout.getYLocation(point.y);\n\n      // Skip circles that are already marked (handles multiple circles per point)\n      const circle = findUnmarkedCircleByPosition(allCircles, expectedX, expectedY);\n      if (circle) {\n        circle.setAttribute('data-maidr-point', `${i}`);\n        markedCount++;\n      }\n    }\n  }\n\n  if (markedCount === 0) {\n    return buildDataSelector(container, 'circle');\n  }\n\n  return `#${container.id} svg circle[data-maidr-point]`;\n}\n\n/**\n * Finds an SVG circle element that matches the given bounding box.\n *\n * The bounding box center should match the circle's cx/cy position.\n *\n * @param circles - NodeList of SVG circle elements to search\n * @param bbox - The target bounding box from the chart layout API\n * @returns The matching circle element, or null if not found\n */\nfunction findCircleByBoundingBox(\n  circles: NodeListOf<SVGCircleElement>,\n  bbox: GoogleBoundingBox,\n): SVGCircleElement | null {\n  // Calculate center of bounding box\n  const centerX = bbox.left + bbox.width / 2;\n  const centerY = bbox.top + bbox.height / 2;\n\n  for (const circle of circles) {\n    const cx = Number.parseFloat(circle.getAttribute('cx') || '0');\n    const cy = Number.parseFloat(circle.getAttribute('cy') || '0');\n\n    // Match by center position with tolerance\n    const xMatch = Math.abs(cx - centerX) <= POSITION_TOLERANCE;\n    const yMatch = Math.abs(cy - centerY) <= POSITION_TOLERANCE;\n\n    if (xMatch && yMatch) {\n      return circle;\n    }\n  }\n  return null;\n}\n\n/**\n * Finds an unmarked SVG circle element at the specified pixel position.\n *\n * Skips circles that already have the data-maidr-point attribute to handle\n * Google Charts rendering multiple overlapping circles per data point.\n *\n * @param circles - NodeList of SVG circle elements to search\n * @param expectedX - Expected x-coordinate (center)\n * @param expectedY - Expected y-coordinate (center)\n * @returns The matching unmarked circle element, or null if not found\n */\nfunction findUnmarkedCircleByPosition(\n  circles: NodeListOf<SVGCircleElement>,\n  expectedX: number,\n  expectedY: number,\n): SVGCircleElement | null {\n  for (const circle of circles) {\n    // Skip already-marked circles\n    if (circle.hasAttribute('data-maidr-point')) {\n      continue;\n    }\n\n    const cx = Number.parseFloat(circle.getAttribute('cx') || '0');\n    const cy = Number.parseFloat(circle.getAttribute('cy') || '0');\n\n    // Match by center position with tolerance\n    const xMatch = Math.abs(cx - expectedX) <= POSITION_TOLERANCE;\n    const yMatch = Math.abs(cy - expectedY) <= POSITION_TOLERANCE;\n\n    if (xMatch && yMatch) {\n      return circle;\n    }\n  }\n  return null;\n}\n\n/**\n * Marks line chart path elements with series identifiers and returns per-series selectors.\n *\n * Google Charts line charts render `<path>` elements inside a `g[clip-path]` group.\n * This function marks each line path with a `data-maidr-line-series` attribute\n * so MAIDR's `mapViaPathParsing` can parse the path `d` attribute and create\n * synthetic highlight circles at each data point.\n *\n * @param _chart - The Google Chart instance (unused, kept for API consistency)\n * @param container - The DOM container element\n * @param _rowCount - Number of data points per series (unused)\n * @param seriesCount - Number of data series\n * @returns Array of CSS selectors (one per series), or undefined if no paths found\n */\nfunction markLinePointElements(\n  _chart: GoogleChart,\n  container: HTMLElement,\n  _rowCount: number,\n  seriesCount: number,\n): string[] | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg) {\n    return undefined;\n  }\n\n  // Clear any existing marks from previous initializations\n  const existingMarked = svg.querySelectorAll('path[data-maidr-line-series]');\n  existingMarked.forEach(path => path.removeAttribute('data-maidr-line-series'));\n\n  // Find line paths: paths with fill=\"none\" inside clip-path group (actual data lines)\n  // These exclude axis lines, gridlines, etc.\n  const linePaths = svg.querySelectorAll('g[clip-path] path[fill=\"none\"]');\n\n  if (linePaths.length === 0) {\n    return undefined;\n  }\n\n  // Mark each path with its series index\n  // Google Charts renders paths in series order\n  const selectors: string[] = [];\n  const pathsToMark = Math.min(linePaths.length, seriesCount);\n\n  for (let series = 0; series < pathsToMark; series++) {\n    const path = linePaths[series];\n    path.setAttribute('data-maidr-line-series', `${series}`);\n    selectors.push(`#${container.id} svg path[data-maidr-line-series=\"${series}\"]`);\n  }\n\n  return selectors.length > 0 ? selectors : undefined;\n}\n\n/**\n * Marks candlestick SVG elements (bodies and wicks) and returns a CandlestickSelector.\n *\n * Google Charts renders candlesticks as pairs of rect elements:\n *   - Wick: narrow rect (width=2) representing high-low range\n *   - Body: wider rect (width~43) representing open-close range\n *\n * Elements are filtered from grid lines by checking width:\n *   - Grid lines: width=1 (vertical) or height=1 (horizontal)\n *   - Wicks: width=2\n *   - Bodies: width > 10 (typically 43)\n *\n * @param _chart - The Google Chart instance (unused, kept for API consistency)\n * @param container - The DOM container element\n * @param rowCount - Number of candlesticks\n * @returns CandlestickSelector object or undefined if no elements found\n */\nfunction markCandlestickElements(\n  _chart: GoogleChart,\n  container: HTMLElement,\n  rowCount: number,\n): CandlestickSelector | undefined {\n  const svg = container.querySelector('svg');\n  if (!svg) {\n    return undefined;\n  }\n\n  // Clear any existing marks from previous initializations\n  const existingMarked = svg.querySelectorAll('rect[data-maidr-candle-body], rect[data-maidr-candle-wick]');\n  existingMarked.forEach((rect) => {\n    rect.removeAttribute('data-maidr-candle-body');\n    rect.removeAttribute('data-maidr-candle-wick');\n  });\n\n  // Get all rects inside clip-path (data elements, not axis/legend)\n  const allRects = svg.querySelectorAll('g[clip-path] rect');\n  if (allRects.length === 0) {\n    return undefined;\n  }\n\n  // Separate bodies from wicks based on width thresholds\n  const bodies: SVGRectElement[] = [];\n  const wicks: SVGRectElement[] = [];\n\n  for (const rect of allRects) {\n    const width = Number.parseFloat(rect.getAttribute('width') || '0');\n    const height = Number.parseFloat(rect.getAttribute('height') || '0');\n\n    // Skip grid lines (very thin horizontal or vertical lines)\n    if (width <= CANDLESTICK_GRID_MAX_WIDTH || height <= CANDLESTICK_GRID_MAX_WIDTH) {\n      continue;\n    }\n\n    // Classify by width: wicks are narrow, bodies are wider\n    if (width <= CANDLESTICK_WICK_MAX_WIDTH) {\n      wicks.push(rect as SVGRectElement);\n    } else if (width > CANDLESTICK_BODY_MIN_WIDTH) {\n      bodies.push(rect as SVGRectElement);\n    }\n    // Note: Elements with widths between WICK_MAX and BODY_MIN are skipped\n    // (typically chart decorations, not data elements)\n  }\n\n  // We expect equal numbers of bodies and wicks\n  if (bodies.length === 0) {\n    return undefined;\n  }\n\n  // Sort by x-position to ensure correct order\n  bodies.sort((a, b) => {\n    const ax = Number.parseFloat(a.getAttribute('x') || '0');\n    const bx = Number.parseFloat(b.getAttribute('x') || '0');\n    return ax - bx;\n  });\n\n  wicks.sort((a, b) => {\n    const ax = Number.parseFloat(a.getAttribute('x') || '0');\n    const bx = Number.parseFloat(b.getAttribute('x') || '0');\n    return ax - bx;\n  });\n\n  // Warn if element counts don't match expected row count (aids debugging)\n  if (bodies.length !== rowCount) {\n    console.warn(\n      `[MAIDR] Candlestick body count mismatch: expected ${rowCount}, found ${bodies.length}. `\n      + 'This may indicate pixel threshold issues with custom chart sizes or high-DPI displays.',\n    );\n  }\n  if (wicks.length !== rowCount) {\n    console.warn(\n      `[MAIDR] Candlestick wick count mismatch: expected ${rowCount}, found ${wicks.length}.`,\n    );\n  }\n\n  // Mark bodies with index\n  const bodiesToMark = Math.min(bodies.length, rowCount);\n  for (let i = 0; i < bodiesToMark; i++) {\n    bodies[i].setAttribute('data-maidr-candle-body', `${i}`);\n  }\n\n  // Mark wicks with index\n  const wicksToMark = Math.min(wicks.length, rowCount);\n  for (let i = 0; i < wicksToMark; i++) {\n    wicks[i].setAttribute('data-maidr-candle-wick', `${i}`);\n  }\n\n  // Build selector object\n  const selector: CandlestickSelector = {\n    body: `#${container.id} svg rect[data-maidr-candle-body]`,\n  };\n\n  if (wicksToMark > 0) {\n    selector.wick = `#${container.id} svg rect[data-maidr-candle-wick]`;\n  }\n\n  return selector;\n}\n","/**\n * Google Charts adapter entry point for MAIDR.\n *\n * This module re-exports the Google Charts adapter API and exposes it globally\n * for script-tag usage. For detailed documentation and examples, see\n * {@link createMaidrFromGoogleChart} in the converters module.\n *\n * @packageDocumentation\n */\nimport { createMaidrFromGoogleChart } from './adapters/google-charts/converters';\n\nexport {\n  createMaidrFromGoogleChart,\n  type GoogleChartAdapterOptions,\n} from './adapters/google-charts/converters';\n\n// Expose Google Charts adapter globally for script-tag usage (UMD build)\n// Only runs in browser environments (not SSR/Node.js)\ndeclare global {\n  interface Window {\n    maidrGoogleCharts?: {\n      createMaidrFromGoogleChart: typeof createMaidrFromGoogleChart;\n    };\n  }\n}\n\nif (typeof window !== 'undefined') {\n  window.maidrGoogleCharts = {\n    createMaidrFromGoogleChart,\n  };\n}\n\nexport type {\n  GoogleChart,\n  GoogleChartType,\n  GoogleDataTable,\n  GoogleEvents,\n  GoogleSelectionItem,\n} from './adapters/google-charts/types';\n\n// Re-export core types that consumers may need alongside the adapter\nexport type { Maidr as MaidrData, MaidrLayer, MaidrSubplot } from './type/grammar';\nexport { Orientation, TraceType } from './type/grammar';\n"],"names":["Orientation","TraceType","nextId","prefix","uuid","ensureContainerId","container","buildDataSelector","elementSelector","svg","clippedSelector","POSITION_TOLERANCE","CANDLESTICK_GRID_MAX_WIDTH","CANDLESTICK_WICK_MAX_WIDTH","CANDLESTICK_BODY_MIN_WIDTH","createMaidrFromGoogleChart","chart","dataTable","options","id","title","subplot","buildLayer","dt","chartType","buildBarOrSegmentedLayer","buildLineLayer","buildScatterLayer","buildSegmentedLayer","buildCandlestickLayer","orientation","countDataColumns","buildBarLayer","data","rows","dataCol","c","isRoleColumn","r","label","formatCellValue","value","numericValue","selector","markBarElements","traceType","cols","seriesCount","series","fillLabel","markSegmentedBarElements","x","y","z","selectors","markLinePointElements","markScatterElements","low","open","close","high","trend","markCandlestickElements","row","col","formatted","raw","role","count","rowCount","layout","allRects","rect","markedCount","dataIndex","bbox","findRectByBoundingBox","categoryCount","category","rects","width","height","xMatch","yMatch","widthMatch","heightMatch","allCircles","circle","i","findCircleByBoundingBox","point","expectedX","expectedY","findUnmarkedCircleByPosition","circles","centerX","centerY","cx","cy","_chart","_rowCount","path","linePaths","pathsToMark","bodies","wicks","a","b","ax","bx","bodiesToMark","wicksToMark"],"mappings":"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"}