{"version":3,"file":"fcharts.umd.cjs","sources":["../src/core/downsample.ts","../src/core/model.ts","../src/core/scales.ts","../src/core/ticks.ts","../src/core/scheduler.ts","../src/renderers/renderer.ts","../src/renderers/canvas2d.ts","../src/renderers/detect.ts","../src/renderers/html-in-canvas.ts","../src/renderers/svg-theme.ts","../src/renderers/svg-util.ts","../src/renderers/svg-export.ts","../src/a11y/styles.ts","../src/a11y/readout.ts","../src/a11y/live-region.ts","../src/a11y/ticks.ts","../src/a11y/legend.ts","../src/a11y/pagers.ts","../src/a11y/sonify.ts","../src/a11y/strings.ts","../src/a11y/table-alt.ts","../src/a11y/summary.ts","../src/a11y/cursor.ts","../src/fchart.ts","../src/sync.ts","../src/hydrate.ts","../src/element.ts","../src/a11y/locales.ts","../src/renderers/render-svg.ts","../src/renderers/donut.ts","../src/renderers/scatter.ts","../src/renderers/sparkline.ts","../src/renderers/bars.ts","../src/renderers/progress.ts","../src/renderers/heatmap.ts","../src/a11y/svg-readout.ts"],"sourcesContent":["/**\n * Min/max downsampling — the core trick that decouples frame cost from point count.\n *\n * A naive renderer iterates every visible sample each frame, so cost grows with N.\n * Instead we precompute a multi-resolution min/max pyramid once (O(N), in `setData`),\n * then each frame pick the pyramid level whose buckets are ~1 per pixel column and\n * iterate only those. Per-frame work is therefore O(viewport width), independent of N\n * and of zoom level — see `planDownsample`, which is unit-tested to prove this.\n *\n * This module is renderer-agnostic: it returns per-column min/max envelopes in *data*\n * units. Mapping those to pixels is the renderer's job.\n *\n * Pyramid buckets are Float32 over Float64 source data — a deliberate memory/bandwidth\n * tradeoff (~7 significant digits), invisible at pixel resolution where envelopes are drawn.\n */\n\n/** A pre-aggregated level of the pyramid. `bucketSize` source samples per bucket. */\nexport interface PyramidLevel {\n  readonly bucketSize: number;\n  readonly min: Float32Array;\n  readonly max: Float32Array;\n}\n\n/** Multi-resolution min/max aggregate over one series' y-values, indexed 0..n-1. */\nexport interface MinMaxPyramid {\n  readonly n: number;\n  /** levels[k].bucketSize === 2^(k+1); level 0 aggregates pairs. */\n  readonly levels: readonly PyramidLevel[];\n}\n\n/** Per-column envelope. Columns with no samples carry the sentinels (min=+Inf, max=-Inf). */\nexport interface ColumnEnvelope {\n  readonly min: Float32Array;\n  readonly max: Float32Array;\n  /** Pixel column of the leftmost / rightmost filled sample, or -1 if empty. */\n  readonly first: number;\n  readonly last: number;\n}\n\n/**\n * Build the min/max pyramid for a series. O(n) time and ~2n extra Float32 storage.\n *\n * @param y - Series y-values, length n.\n * @returns A pyramid whose coarsest level has at most one bucket.\n */\nexport function buildPyramid(y: Float64Array): MinMaxPyramid {\n  const n = y.length;\n  const levels: PyramidLevel[] = [];\n  if (n === 0) return { n, levels };\n\n  let prev = buildLevel0(y);\n  levels.push(prev);\n  while (prev.min.length > 1) {\n    prev = combineLevel(prev);\n    levels.push(prev);\n  }\n  return { n, levels };\n}\n\nfunction buildLevel0(y: Float64Array): PyramidLevel {\n  const n = y.length;\n  const count = Math.ceil(n / 2);\n  const min = new Float32Array(count);\n  const max = new Float32Array(count);\n  for (let b = 0; b < count; b++) {\n    const i = b * 2;\n    const a = y[i];\n    const c = i + 1 < n ? y[i + 1] : a;\n    min[b] = a < c ? a : c;\n    max[b] = a > c ? a : c;\n  }\n  return { bucketSize: 2, min, max };\n}\n\nfunction combineLevel(prev: PyramidLevel): PyramidLevel {\n  const len = prev.min.length;\n  const count = Math.ceil(len / 2);\n  const min = new Float32Array(count);\n  const max = new Float32Array(count);\n  for (let b = 0; b < count; b++) {\n    const i = b * 2;\n    const j = i + 1 < len ? i + 1 : i;\n    min[b] = Math.min(prev.min[i], prev.min[j]);\n    max[b] = Math.max(prev.max[i], prev.max[j]);\n  }\n  return { bucketSize: prev.bucketSize * 2, min, max };\n}\n\n/**\n * A min/max pyramid that supports O(log n) incremental `push` for streaming/real-time data,\n * instead of an O(n) rebuild per appended sample. Built once from a batch (O(n)); each `push`\n * updates only the single tail bucket at each level. Storage grows by doubling per level.\n *\n * Structurally a {@link MinMaxPyramid} (so the read path treats it identically) — but its level\n * arrays may carry spare capacity, so readers must derive the bucket count from `n`, not from\n * `level.min.length` (see {@link planDownsample}/`accumulateLevel`).\n */\nexport class StreamingPyramid {\n  n: number;\n  readonly levels: { bucketSize: number; min: Float32Array; max: Float32Array }[];\n\n  constructor(y: Float64Array) {\n    const batch = buildPyramid(y);\n    this.n = batch.n;\n    // Copy each level into a buffer with headroom so the first appends don't reallocate.\n    this.levels = batch.levels.map((l) => ({\n      bucketSize: l.bucketSize,\n      min: withHeadroom(l.min),\n      max: withHeadroom(l.max),\n    }));\n    if (this.levels.length === 0) {\n      this.levels.push({ bucketSize: 2, min: new Float32Array(4), max: new Float32Array(4) });\n    }\n  }\n\n  /** Append one raw value (at index === current n) and fix up the affected bucket per level. */\n  push(v: number): void {\n    const idx = this.n;\n    this.n = idx + 1;\n\n    // Level 0 aggregates raw pairs.\n    const b0 = idx >> 1;\n    this.ensureCap(0, b0 + 1);\n    const L0 = this.levels[0];\n    if ((idx & 1) === 0) {\n      L0.min[b0] = v;\n      L0.max[b0] = v;\n    } else {\n      // Match buildLevel0's `a < c ? a : c` semantics exactly (incl. NaN propagation) so a\n      // streamed pyramid is byte-identical to a batch rebuild.\n      L0.min[b0] = L0.min[b0] < v ? L0.min[b0] : v;\n      L0.max[b0] = L0.max[b0] > v ? L0.max[b0] : v;\n    }\n\n    this.propagateUp(idx);\n  }\n\n  /**\n   * Replace the LAST raw value (index n-1) and fix up its bucket per level — O(log n), for\n   * in-flight samples that keep changing (a forming candle, a ticking last price). When n-1 is\n   * odd its level-0 bucket pairs it with the previous raw value, so the caller passes that\n   * `sibling` (the pyramid stores no raw values).\n   */\n  amendLast(v: number, sibling: number): void {\n    const idx = this.n - 1;\n    const b0 = idx >> 1;\n    const L0 = this.levels[0];\n    if ((idx & 1) === 0) {\n      L0.min[b0] = v;\n      L0.max[b0] = v;\n    } else {\n      // Rebuild the pair bucket from scratch with buildLevel0's exact `a < c ? a : c` semantics.\n      L0.min[b0] = sibling < v ? sibling : v;\n      L0.max[b0] = sibling > v ? sibling : v;\n    }\n    this.propagateUp(idx);\n  }\n\n  /** Recompute every ancestor bucket of raw index `idx` from its two children below. */\n  private propagateUp(idx: number): void {\n    for (let k = 1; ; k++) {\n      const prevCount = Math.ceil(this.n / (1 << k)); // bucket count of level k-1\n      if (prevCount <= 1) break; // level k-1 is the apex; no parent needed\n      if (k >= this.levels.length) {\n        this.levels.push({ bucketSize: 1 << (k + 1), min: new Float32Array(4), max: new Float32Array(4) });\n      }\n      const prev = this.levels[k - 1];\n      const cur = this.levels[k];\n      const bk = idx >> (k + 1);\n      this.ensureCap(k, bk + 1);\n      const c0 = bk << 1;\n      const c1 = c0 + 1;\n      if (c1 < prevCount) {\n        cur.min[bk] = Math.min(prev.min[c0], prev.min[c1]);\n        cur.max[bk] = Math.max(prev.max[c0], prev.max[c1]);\n      } else {\n        cur.min[bk] = prev.min[c0];\n        cur.max[bk] = prev.max[c0];\n      }\n    }\n  }\n\n  private ensureCap(level: number, need: number): void {\n    const l = this.levels[level];\n    if (l.min.length >= need) return;\n    const cap = Math.max(need, l.min.length * 2, 4);\n    const min = new Float32Array(cap);\n    const max = new Float32Array(cap);\n    min.set(l.min);\n    max.set(l.max);\n    l.min = min;\n    l.max = max;\n  }\n}\n\nfunction withHeadroom(arr: Float32Array): Float32Array {\n  const out = new Float32Array(Math.max(arr.length * 2, 4));\n  out.set(arr);\n  return out;\n}\n\n/** First index i with x[i] >= target (binary search; x must be non-decreasing). */\nexport function lowerBound(x: Float64Array, target: number): number {\n  let lo = 0;\n  let hi = x.length;\n  while (lo < hi) {\n    const mid = (lo + hi) >>> 1;\n    if (x[mid] < target) lo = mid + 1;\n    else hi = mid;\n  }\n  return lo;\n}\n\n/** Index of the sample closest to `target` (x non-decreasing); 0 on empty input. */\nexport function nearestIndex(x: Float64Array, target: number): number {\n  const n = x.length;\n  if (n === 0) return 0;\n  const hi = lowerBound(x, target);\n  if (hi <= 0) return 0;\n  if (hi >= n) return n - 1;\n  return target - x[hi - 1] <= x[hi] - target ? hi - 1 : hi;\n}\n\nfunction pickLevel(pyramid: MinMaxPyramid, pointsPerCol: number): PyramidLevel {\n  // Largest bucketSize <= pointsPerCol → buckets-per-column >= 1 (no gaps),\n  // and within a factor of 2 of pointsPerCol → iterations <= ~2w.\n  const idx = Math.floor(Math.log2(pointsPerCol)) - 1;\n  const last = pyramid.levels.length - 1;\n  const clamped = idx < 0 ? 0 : idx > last ? last : idx;\n  return pyramid.levels[clamped];\n}\n\n/** How `downsampleColumns` will traverse the data for a given domain + width. */\nexport interface DownsamplePlan {\n  readonly mode: 'empty' | 'raw' | 'level';\n  /** Inclusive visible index range (raw samples), expanded one sample past each edge. */\n  readonly i0: number;\n  readonly i1: number;\n  /** Chosen pyramid level for `level` mode, else null. */\n  readonly level: PyramidLevel | null;\n  /** Source units (raw samples or buckets) iterated this frame. The O(width) witness. */\n  readonly iterations: number;\n}\n\n/**\n * Decide how to traverse the data without touching y-values. Exposed so tests can assert\n * the central invariant: `iterations` stays ~O(width) no matter how large n is.\n */\nexport function planDownsample(\n  x: Float64Array,\n  pyramid: MinMaxPyramid,\n  domain: readonly [number, number],\n  cols: number,\n): DownsamplePlan {\n  const w = Math.max(1, Math.floor(cols));\n  const span = domain[1] - domain[0];\n  const empty: DownsamplePlan = { mode: 'empty', i0: 0, i1: -1, level: null, iterations: 0 };\n  if (span <= 0 || x.length === 0) return empty;\n\n  const i0 = Math.max(0, lowerBound(x, domain[0]) - 1);\n  const i1 = Math.min(x.length - 1, lowerBound(x, domain[1]));\n  if (i1 < i0) return { ...empty, i0, i1 };\n\n  const visible = i1 - i0 + 1;\n  const pointsPerCol = visible / w;\n  if (pointsPerCol < 2) return { mode: 'raw', i0, i1, level: null, iterations: visible };\n\n  const level = pickLevel(pyramid, pointsPerCol);\n  const b0 = Math.floor(i0 / level.bucketSize);\n  // Bucket count from n (= x.length), not level.min.length, so a streaming pyramid's spare\n  // capacity isn't read as real buckets. Equal to level.min.length for a batch pyramid.\n  const lastBucket = Math.ceil(x.length / level.bucketSize) - 1;\n  const b1 = Math.min(lastBucket, Math.floor(i1 / level.bucketSize));\n  return { mode: 'level', i0, i1, level, iterations: Math.max(0, b1 - b0 + 1) };\n}\n\n/**\n * Compute the per-pixel-column min/max envelope for the visible x-domain.\n *\n * @param x - Shared x-values (non-decreasing), length n.\n * @param rawY - Series y-values, length n.\n * @param pyramid - Pyramid for `rawY`.\n * @param domain - Visible x-range [d0, d1], d0 < d1.\n * @param cols - Number of pixel columns (plot width in CSS px, >= 1).\n * @param out - Optional reusable buffers (length === cols) to avoid per-frame allocation.\n */\nexport function downsampleColumns(\n  x: Float64Array,\n  rawY: Float64Array,\n  pyramid: MinMaxPyramid,\n  domain: readonly [number, number],\n  cols: number,\n  out?: { min: Float32Array; max: Float32Array },\n): ColumnEnvelope {\n  const w = Math.max(1, Math.floor(cols));\n  const min = out && out.min.length === w ? out.min : new Float32Array(w);\n  const max = out && out.max.length === w ? out.max : new Float32Array(w);\n  min.fill(Infinity);\n  max.fill(-Infinity);\n\n  const plan = planDownsample(x, pyramid, domain, w);\n  if (plan.mode === 'empty') return { min, max, first: -1, last: -1 };\n\n  // Column mapping is inlined in both loops (not a shared closure): the call overhead is\n  // measurable at this loop's grain (~25% of the per-frame downsample cost).\n  const d0 = domain[0];\n  const invSpan = w / (domain[1] - domain[0]);\n\n  if (plan.mode === 'raw') {\n    for (let i = plan.i0; i <= plan.i1; i++) {\n      const cf = (x[i] - d0) * invSpan;\n      const c = cf < 0 ? 0 : cf >= w ? w - 1 : cf | 0;\n      const v = rawY[i];\n      if (v < min[c]) min[c] = v;\n      if (v > max[c]) max[c] = v;\n    }\n    return finalize(min, max, w);\n  }\n\n  // Level mode. Each bucket is written across the full column span its x-range covers (from\n  // the x of its first sample to its last), not just its center column. With uniform x a\n  // bucket spans one column (same as a center map); with non-uniform x a sparse bucket spans\n  // many columns and fills them — so there are no gaps regardless of x distribution. Buckets\n  // tile the index space contiguously, so total writes stay O(width + buckets) ≈ O(width).\n  const level = plan.level!;\n  const bs = level.bucketSize;\n  const n = x.length;\n  const b0 = Math.floor(plan.i0 / bs);\n  const b1 = Math.min(Math.ceil(n / bs) - 1, Math.floor(plan.i1 / bs));\n  for (let b = b0; b <= b1; b++) {\n    const start = b * bs;\n    const end = start + bs - 1 < n ? start + bs - 1 : n - 1;\n    const fL = (x[start] - d0) * invSpan;\n    const fR = (x[end] - d0) * invSpan;\n    const cL = fL < 0 ? 0 : fL >= w ? w - 1 : fL | 0;\n    const cR = fR < 0 ? 0 : fR >= w ? w - 1 : fR | 0;\n    const bmin = level.min[b];\n    const bmax = level.max[b];\n    for (let c = cL; c <= cR; c++) {\n      if (bmin < min[c]) min[c] = bmin;\n      if (bmax > max[c]) max[c] = bmax;\n    }\n  }\n  return finalize(min, max, w);\n}\n\nfunction finalize(min: Float32Array, max: Float32Array, w: number): ColumnEnvelope {\n  let first = -1;\n  let last = -1;\n  for (let c = 0; c < w; c++) {\n    if (min[c] !== Infinity) {\n      if (first === -1) first = c;\n      last = c;\n    }\n  }\n  return { min, max, first, last };\n}\n","/**\n * Data model — normalizes user input and precomputes everything the render loop needs:\n * typed-array copies, per-series y extents, and a min/max pyramid per series.\n *\n * All of this is computed once per `setData`, never per frame.\n */\nimport { nearestIndex, StreamingPyramid } from './downsample.ts';\n\nexport type NumberArray = Float64Array | readonly number[];\n\n/** Declarative description of one plotted series. */\nexport interface SeriesConfig {\n  /** Human-readable name (announced to screen readers, shown in legend/tooltip). */\n  name: string;\n  /** CSS color for the line/area (wick/outline for `candle`). Optional — falls back to the\n   *  contrast-checked {@link DEFAULT_PALETTE} by series index. */\n  color?: string;\n  /** `line` (stroked envelope), `area` (filled to baseline), or `candle` (OHLC candlesticks —\n   *  consumes four y arrays: open, high, low, close). Default `line`. */\n  type?: 'line' | 'area' | 'candle';\n  /** Whether the series starts visible. Default true. */\n  visible?: boolean;\n  /** Stroke width in CSS px. Default 1.25. */\n  width?: number;\n  /** Fill opacity for `area` series, 0..1. Default 0.15. */\n  fillAlpha?: number;\n  /** Dash pattern for the stroke (canvas `setLineDash`). Omit to auto-assign a distinct pattern\n   *  per series so colour is not the only differentiator (WCAG 1.4.1). `[]` forces solid. */\n  dash?: number[];\n  /** Candle body color when close >= open. Default green from the contrast-checked palette.\n   *  Up candles are drawn hollow (outline only) so direction never relies on colour alone. */\n  upColor?: string;\n  /** Candle body color when close < open. Default red from the contrast-checked palette.\n   *  Down candles are drawn filled. */\n  downColor?: string;\n}\n\n/**\n * Columnar dataset: one shared, non-decreasing x array and one y array per series *slot*.\n * `line`/`area` series consume one slot; a `candle` series consumes four consecutive slots\n * in the order open, high, low, close. Slots follow series declaration order.\n */\nexport interface FChartData {\n  x: NumberArray;\n  y: NumberArray[];\n}\n\n/** Y-array slots a series consumes: 4 for `candle` (open/high/low/close), 1 otherwise. */\nexport function seriesSlots(type: 'line' | 'area' | 'candle' | undefined): number {\n  return type === 'candle' ? 4 : 1;\n}\n\n/**\n * An event marker on the time series — a dot on the nearest sample of a series, or a vertical\n * rule, at an x position, with a label (e.g. \"GSR +$2.0M\"). Events are half the story on a\n * portfolio chart: a climbing line without the allocation markers hides that a jump was new\n * capital, not yield.\n */\nexport interface AnnotationSpec {\n  /** x position (data units) the annotation marks. */\n  x: number;\n  /** Short description of the event (announced, shown in the readout, listed in the summary). */\n  label: string;\n  /** Mark color; defaults to the target series' color, else a neutral. Shape + label carry the\n   *  meaning too, so the mark is never color-only (WCAG 1.4.1). */\n  color?: string;\n  /** `point` = a diamond on the nearest sample of `seriesIndex`; `rule` = a vertical line. Default `point`. */\n  kind?: 'point' | 'rule';\n  /** Which series' nearest sample a `point` marker sits on. Default 0. */\n  seriesIndex?: number;\n  /** Draw the always-on text label beside the marker. Default `true`. Set `false` for dense event\n   *  sets (many markers on one chart): the marker still renders and the cursor readout +\n   *  screen-reader announcement still surface the label on hover or keyboard select, but the static\n   *  label is suppressed so a cluster of events doesn't collapse into overlapping text. */\n  showLabel?: boolean;\n}\n\n/** An {@link AnnotationSpec} with defaults resolved. */\nexport interface ResolvedAnnotation {\n  x: number;\n  label: string;\n  color: string;\n  kind: 'point' | 'rule';\n  seriesIndex: number;\n  showLabel: boolean;\n}\n\n/** Apply defaults to annotation specs; color falls back to the target series' color. Pure. */\nexport function resolveAnnotations(\n  specs: readonly AnnotationSpec[],\n  series: readonly ResolvedSeries[],\n): ResolvedAnnotation[] {\n  return specs.map((a) => {\n    const seriesIndex = a.seriesIndex ?? 0;\n    return {\n      x: a.x,\n      label: a.label,\n      kind: a.kind ?? 'point',\n      seriesIndex,\n      color: a.color || series[seriesIndex]?.color || '#64748b',\n      showLabel: a.showLabel ?? true,\n    };\n  });\n}\n\n/**\n * The on-line data coordinates a `point` annotation snaps to: the nearest sample of its target\n * series (the close, for a candle), so the marker lands exactly on the drawn line. Returns the\n * sample index too, so callers can attach the annotation to the keyboard cursor. Null when there's\n * no data or the target series doesn't exist.\n */\nexport function annotationSample(\n  data: ChartData,\n  series: readonly ResolvedSeries[],\n  a: ResolvedAnnotation,\n): { index: number; x: number; y: number } | null {\n  if (data.n === 0) return null;\n  const s = series[a.seriesIndex];\n  if (!s) return null;\n  const index = nearestIndex(data.x, a.x);\n  const slot = s.type === 'candle' ? s.index + 3 : s.index;\n  return { index, x: data.x[index], y: data.y[slot][index] };\n}\n\n/** Per-series summary statistics over the full dataset (computed once at setData). */\nexport interface SeriesStats {\n  min: number;\n  max: number;\n  first: number;\n  last: number;\n  mean: number;\n}\n\n/** A series with all optional fields resolved to concrete defaults. */\nexport interface ResolvedSeries {\n  /** First y-slot in `ChartData.y` / `.pyramids` (candles span `index..index+3`: OHLC). */\n  index: number;\n  /** Y-slots consumed: 4 for `candle`, 1 otherwise. */\n  slots: number;\n  name: string;\n  color: string;\n  type: 'line' | 'area' | 'candle';\n  visible: boolean;\n  width: number;\n  fillAlpha: number;\n  /** Resolved dash pattern; `[]` = solid. */\n  dash: number[];\n  /** Candle body colors (unused for line/area). */\n  upColor: string;\n  downColor: string;\n}\n\n/**\n * Default series palette — 8 hues each verified at >= 3:1 non-text contrast (WCAG 1.4.11)\n * against BOTH a white (#ffffff) and a dark (#0c1016 / #1f2937) chart background, so the marks\n * are distinguishable on either theme without the integrator choosing colors. Assigned by\n * series index when `SeriesConfig.color` is omitted. (Color alone is never the sole channel —\n * see the per-series dash/marker option.)\n */\nexport const DEFAULT_PALETTE = [\n  '#0284c7', // blue\n  '#ea580c', // orange\n  '#16a34a', // green\n  '#dc2626', // red\n  '#c026d3', // magenta\n  '#0d9488', // teal\n  '#db2777', // pink\n  '#65a30d', // lime\n] as const;\n\n/**\n * Distinct dash patterns auto-assigned by series index when no explicit dash is given and there\n * is more than one series, so colour is never the only channel (WCAG 1.4.1). Index 0 stays solid.\n */\nconst AUTO_DASH: readonly (readonly number[])[] = [\n  [], [6, 4], [2, 3], [9, 4, 2, 4], [4, 4], [1, 3], [7, 3, 1, 3], [3, 7],\n];\n\n/** Apply defaults to user series configs. Pure; safe to call per update. */\nexport function resolveSeries(configs: readonly SeriesConfig[]): ResolvedSeries[] {\n  // All-or-nothing: auto-assign dashes only when the integrator specified none (an explicit dash\n  // on any series opts out of the auto-cycle).\n  const auto = configs.length > 1 && !configs.some((c) => c.dash !== undefined);\n  let slot = 0;\n  return configs.map((c, i) => {\n    const index = slot;\n    const slots = seriesSlots(c.type);\n    slot += slots;\n    return {\n      index,\n      slots,\n      name: c.name,\n      color: c.color || DEFAULT_PALETTE[i % DEFAULT_PALETTE.length],\n      type: c.type ?? 'line',\n      visible: c.visible ?? true,\n      width: c.width ?? 1.25,\n      fillAlpha: c.fillAlpha ?? 0.15,\n      dash: c.dash ?? (auto ? [...AUTO_DASH[i % AUTO_DASH.length]] : []),\n      upColor: c.upColor ?? '#16a34a', // palette green/red — both contrast-checked (1.4.11)\n      downColor: c.downColor ?? '#dc2626',\n    };\n  });\n}\n\n/** Which sample the keyboard/hover cursor currently points at. */\nexport interface CursorState {\n  /** Resolved series index. */\n  series: number;\n  /** Sample index within the series. */\n  index: number;\n}\n\n/** Plot insets in CSS px (space reserved for axes/ticks around the plotting area). */\nexport interface Margins {\n  left: number;\n  right: number;\n  top: number;\n  bottom: number;\n}\n\nexport const DEFAULT_MARGINS: Margins = { left: 56, right: 16, top: 20, bottom: 32 };\n\nfunction toF64(a: NumberArray): Float64Array {\n  return a instanceof Float64Array ? a : Float64Array.from(a);\n}\n\n/** Copy `src` into a fresh buffer of length `cap` (cap >= src.length). Never aliases caller\n *  data. NOTE (measured): this two-step convert-then-memcpy ctor pipeline, with stats and\n *  pyramids reading the flat exact-length arrays, beats every \"single-copy\" restructure tried\n *  — reading subarray views in the O(n) passes costs ~15% on plain-array input. */\nfunction toCapacity(src: Float64Array, cap: number): Float64Array {\n  const out = new Float64Array(cap);\n  out.set(src);\n  return out;\n}\n\n/**\n * Per-series stats over the finite samples, plus the running sum/count needed to keep the mean\n * correct under incremental `push`. Non-finite values (NaN/±Infinity) are skipped so the stats —\n * and the machine-readable JSON built from them — are always real numbers, not the `null` that\n * `JSON.stringify` emits for NaN/Infinity.\n */\nfunction initStats(y: Float64Array): { stats: SeriesStats; sum: number; count: number } {\n  let min = Infinity;\n  let max = -Infinity;\n  let sum = 0;\n  let count = 0;\n  let first = 0;\n  let last = 0;\n  for (let i = 0; i < y.length; i++) {\n    const v = y[i];\n    if (!Number.isFinite(v)) continue;\n    if (count === 0) first = v;\n    last = v;\n    if (v < min) min = v;\n    if (v > max) max = v;\n    sum += v;\n    count++;\n  }\n  if (count === 0) return { stats: { min: 0, max: 0, first: 0, last: 0, mean: 0 }, sum: 0, count: 0 };\n  return { stats: { min, max, first, last, mean: sum / count }, sum, count };\n}\n\n/**\n * Render-ready view of a dataset, with O(log n) `push` for streaming/real-time appends.\n *\n * `x`/`y[i]` are exact-length (`=== n`) views over doubling-capacity backing buffers, so\n * `x.length === n` holds for the binary search while appends stay amortized O(1). `x` must be\n * non-decreasing; `push` enforces it, the batch constructor trusts the caller (perf).\n */\nexport class ChartData {\n  x: Float64Array;\n  y: Float64Array[];\n  n: number;\n  readonly pyramids: StreamingPyramid[];\n  readonly stats: SeriesStats[];\n\n  private xBuf: Float64Array;\n  private yBuf: Float64Array[];\n  private cap: number;\n  private readonly sums: Float64Array; // per-series running sum of finite values\n  private readonly counts: Int32Array; // per-series finite-value count\n\n  constructor(data: FChartData) {\n    const x = toF64(data.x);\n    const n = x.length;\n    const yArrs = data.y.map((series, i) => {\n      const arr = toF64(series);\n      if (arr.length !== n) {\n        throw new Error(\n          `fcharts: series ${i} has ${arr.length} points but x has ${n}. ` +\n            'Every y array must match the length of x.',\n        );\n      }\n      return arr;\n    });\n    this.cap = Math.max(n, 1);\n    this.xBuf = toCapacity(x, this.cap);\n    this.yBuf = yArrs.map((a) => toCapacity(a, this.cap));\n    this.n = n;\n    this.x = this.xBuf.subarray(0, n);\n    this.y = this.yBuf.map((b) => b.subarray(0, n));\n    this.sums = new Float64Array(yArrs.length);\n    this.counts = new Int32Array(yArrs.length);\n    this.stats = yArrs.map((a, i) => {\n      const r = initStats(a);\n      this.sums[i] = r.sum;\n      this.counts[i] = r.count;\n      return r.stats;\n    });\n    this.pyramids = yArrs.map((a) => new StreamingPyramid(a));\n  }\n\n  /**\n   * Append one sample. `x` must be >= the current last x (non-decreasing). Updates the data,\n   * the per-series min/max pyramids (O(log n) each), and the stats — never an O(n) rebuild.\n   */\n  push(xv: number, ys: readonly number[]): void {\n    if (ys.length !== this.yBuf.length) {\n      throw new Error(\n        `fcharts: append got ${ys.length} y-values but the chart has ${this.yBuf.length} series slots.`,\n      );\n    }\n    // Reject non-finite x explicitly: NaN passes every `<` ordering check, so it would land in\n    // the array silently and corrupt the binary searches that assume x is non-decreasing.\n    if (!Number.isFinite(xv)) {\n      throw new Error(`fcharts: append x must be a finite number (got ${xv}).`);\n    }\n    if (this.n > 0 && xv < this.xBuf[this.n - 1]) {\n      throw new Error('fcharts: append x must be >= the current last x (x is non-decreasing).');\n    }\n    if (this.n === this.cap) this.grow();\n    const i = this.n;\n    this.xBuf[i] = xv;\n    for (let s = 0; s < this.yBuf.length; s++) {\n      const v = ys[s];\n      this.yBuf[s][i] = v;\n      this.pyramids[s].push(v);\n      this.accumStat(s, v);\n    }\n    this.n = i + 1;\n    this.x = this.xBuf.subarray(0, this.n);\n    for (let s = 0; s < this.yBuf.length; s++) this.y[s] = this.yBuf[s].subarray(0, this.n);\n  }\n\n  /**\n   * Replace the y-values of the LAST sample (x unchanged) — O(log n), for in-flight samples\n   * that keep changing, e.g. a forming candle or a ticking last price. Values must be finite.\n   *\n   * Stats caveat: `min`/`max` only widen under amends. If the amended value was the sole\n   * extreme and retreats, the recorded extreme stays until the next `setData`. For the\n   * intended use this never happens (a forming candle's high/low only extend), and a\n   * one-amend-wide extreme is the conservative direction for axis fitting.\n   */\n  amendLast(ys: readonly number[]): void {\n    if (this.n === 0) {\n      throw new Error('fcharts: amendLast called on an empty chart — append a sample first.');\n    }\n    if (ys.length !== this.yBuf.length) {\n      throw new Error(\n        `fcharts: amendLast got ${ys.length} y-values but the chart has ${this.yBuf.length} series slots.`,\n      );\n    }\n    const i = this.n - 1;\n    for (let s = 0; s < this.yBuf.length; s++) {\n      const v = ys[s];\n      if (!Number.isFinite(v)) {\n        throw new Error(`fcharts: amendLast values must be finite numbers (slot ${s} got ${v}).`);\n      }\n      const old = this.yBuf[s][i];\n      this.yBuf[s][i] = v;\n      this.pyramids[s].amendLast(v, i > 0 ? this.yBuf[s][i - 1] : v);\n      this.amendStat(s, old, v);\n    }\n  }\n\n  private amendStat(s: number, old: number, v: number): void {\n    const st = this.stats[s];\n    if (Number.isFinite(old)) {\n      this.sums[s] += v - old;\n    } else {\n      // The previous last value was a gap (appended as NaN) now becoming real data.\n      this.sums[s] += v;\n      this.counts[s] += 1;\n      if (this.counts[s] === 1) {\n        // First finite value ever: seed the extremes rather than widening the empty-state zeros.\n        st.first = v;\n        st.min = v;\n        st.max = v;\n      }\n    }\n    if (v < st.min) st.min = v;\n    if (v > st.max) st.max = v;\n    st.last = v;\n    st.mean = this.sums[s] / this.counts[s];\n  }\n\n  private grow(): void {\n    this.cap = Math.max(this.cap * 2, 8);\n    this.xBuf = toCapacity(this.xBuf.subarray(0, this.n), this.cap);\n    this.yBuf = this.yBuf.map((b) => toCapacity(b.subarray(0, this.n), this.cap));\n  }\n\n  private accumStat(s: number, v: number): void {\n    if (!Number.isFinite(v)) return;\n    const st = this.stats[s];\n    if (this.counts[s] === 0) {\n      st.first = v;\n      st.min = v;\n      st.max = v;\n    } else {\n      if (v < st.min) st.min = v;\n      if (v > st.max) st.max = v;\n    }\n    st.last = v;\n    this.sums[s] += v;\n    this.counts[s] += 1;\n    st.mean = this.sums[s] / this.counts[s];\n  }\n\n  /** Full x-domain [first, last]; falls back to [0, 1] when empty. */\n  xExtent(): [number, number] {\n    if (this.n === 0) return [0, 1];\n    return [this.x[0], this.x[this.n - 1]];\n  }\n\n  /**\n   * Combined y-extent across the series flagged visible.\n   *\n   * @param visible - Per-series visibility (index-aligned with the series). Missing or\n   *   `true` entries count as visible.\n   * @returns [min, max], widened to a unit span when degenerate so scales never collapse.\n   */\n  yExtent(visible: readonly boolean[]): [number, number] {\n    if (this.n === 0) return [0, 1];\n    let min = Infinity;\n    let max = -Infinity;\n    for (let s = 0; s < this.stats.length; s++) {\n      if (visible[s] === false) continue;\n      const e = this.stats[s];\n      if (e.min < min) min = e.min;\n      if (e.max > max) max = e.max;\n    }\n    if (min === Infinity) return [0, 1];\n    if (min === max) return [min - 1, max + 1];\n    return [min, max];\n  }\n}\n","/**\n * Linear scales — map a data domain onto a pixel range and back.\n *\n * Renderer-agnostic: a scale is plain arithmetic over numbers. The y-scale's range is\n * inverted (top pixel = max value) because canvas/DOM y grows downward.\n */\n\n/** Maps values from `domain` (data units) to `range` (pixels) and back. */\nexport interface LinearScale {\n  /** data value → pixel. */\n  (value: number): number;\n  /** pixel → data value. */\n  invert(px: number): number;\n  readonly domain: readonly [number, number];\n  readonly range: readonly [number, number];\n}\n\n/**\n * Build a linear scale. A zero-width domain is treated as spanning [d0, d0+1] so the\n * scale never divides by zero (it collapses to the range start).\n *\n * @param domain - [d0, d1] in data units.\n * @param range - [r0, r1] in pixels.\n */\nexport function linearScale(\n  domain: readonly [number, number],\n  range: readonly [number, number],\n): LinearScale {\n  const [d0, d1] = domain;\n  const [r0, r1] = range;\n  const dspan = d1 - d0 || 1;\n  const rspan = r1 - r0;\n  const m = rspan / dspan;\n\n  const scale = ((value: number): number => r0 + (value - d0) * m) as LinearScale;\n  Object.defineProperties(scale, {\n    invert: { value: (px: number): number => d0 + (px - r0) / m },\n    domain: { value: domain },\n    range: { value: range },\n  });\n  return scale;\n}\n\n/**\n * Build a base-10 log scale (same {@link LinearScale} shape, so renderers are agnostic).\n * The domain must be positive — the caller derives it from positive data (see `rescaleY`).\n * Non-positive values can still reach the scale at render time (a gap sample's neighbors,\n * an area baseline of 0); they clamp to the range start instead of producing NaN, which\n * would break an entire canvas path.\n */\nexport function logScale(\n  domain: readonly [number, number],\n  range: readonly [number, number],\n): LinearScale {\n  const [d0, d1] = domain;\n  const [r0, r1] = range;\n  const l0 = Math.log10(d0);\n  const lspan = Math.log10(d1) - l0 || 1;\n  const m = (r1 - r0) / lspan;\n\n  const scale = ((value: number): number =>\n    value > 0 ? r0 + (Math.log10(value) - l0) * m : r0) as LinearScale;\n  Object.defineProperties(scale, {\n    invert: { value: (px: number): number => Math.pow(10, l0 + (px - r0) / m) },\n    domain: { value: domain },\n    range: { value: range },\n  });\n  return scale;\n}\n","/**\n * \"Nice\" axis ticks — round numbers (1/2/5 × 10^k) covering a domain.\n *\n * Ported and generalized from the POC. Renderer-agnostic: returns tick *values*; the\n * a11y layer turns them into positioned DOM text.\n */\n\n/** The nice step size that yields roughly `target` ticks across [min, max]. */\nexport function tickStep(min: number, max: number, target: number): number {\n  const span = max - min;\n  if (span <= 0 || !Number.isFinite(span)) return 1;\n  const rough = span / Math.max(1, target);\n  const mag = Math.pow(10, Math.floor(Math.log10(rough)));\n  const norm = rough / mag;\n  const factor = norm < 1.5 ? 1 : norm < 3 ? 2 : norm < 7 ? 5 : 10;\n  return factor * mag;\n}\n\n/**\n * Nice tick values within [min, max].\n *\n * @param min - Domain lower bound.\n * @param max - Domain upper bound.\n * @param target - Desired tick count (a hint; the actual count varies with rounding).\n * @param minStep - Optional floor on the step (e.g. 1 for integer index axes).\n */\nexport function niceTicks(min: number, max: number, target: number, minStep = 0): number[] {\n  if (!(max > min)) return [min];\n  const step = Math.max(minStep, tickStep(min, max, target));\n  const start = Math.ceil(min / step) * step;\n  const out: number[] = [];\n  // Index-based loop avoids floating-point drift from repeated += step.\n  for (let k = 0; ; k++) {\n    const v = start + k * step;\n    if (v > max + step * 1e-9) break;\n    // Snap away -0 and tiny FP residue near zero.\n    out.push(Math.abs(v) < step * 1e-9 ? 0 : v);\n    if (out.length > 1000) break; // safety valve\n  }\n  return out;\n}\n\nconst SEC = 1000;\nconst MIN = 60 * SEC;\nconst HOUR = 60 * MIN;\nconst DAY = 24 * HOUR;\n/** Sub-day steps use epoch-aligned multiples (deterministic, DST-immune); day+ steps use the\n *  local calendar below so tick boundaries land on real midnights/month starts. */\nconst TIME_STEPS = [\n  SEC, 2 * SEC, 5 * SEC, 10 * SEC, 15 * SEC, 30 * SEC,\n  MIN, 2 * MIN, 5 * MIN, 10 * MIN, 15 * MIN, 30 * MIN,\n  HOUR, 2 * HOUR, 3 * HOUR, 6 * HOUR, 12 * HOUR,\n];\n\n/** Local-midnight ticks every `days` days (7/14-day steps align to Monday). */\nfunction dayTicks(min: number, max: number, days: number): number[] {\n  const start = new Date(min);\n  start.setHours(0, 0, 0, 0);\n  if (days % 7 === 0) {\n    start.setDate(start.getDate() - ((start.getDay() + 6) % 7)); // back to Monday\n  }\n  const out: number[] = [];\n  for (const d = start; d.getTime() <= max; d.setDate(d.getDate() + days)) {\n    const t = d.getTime();\n    if (t >= min) out.push(t);\n    if (out.length > 1000) break;\n  }\n  return out;\n}\n\n/** First-of-month ticks every `months` months, aligned to month-number multiples (Jan/Apr/Jul…). */\nfunction monthTicks(min: number, max: number, months: number): number[] {\n  const start = new Date(min);\n  start.setDate(1);\n  start.setHours(0, 0, 0, 0);\n  start.setMonth(Math.floor(start.getMonth() / months) * months);\n  const out: number[] = [];\n  for (const d = start; d.getTime() <= max; d.setMonth(d.getMonth() + months)) {\n    const t = d.getTime();\n    if (t >= min) out.push(t);\n    if (out.length > 1000) break;\n  }\n  return out;\n}\n\n/**\n * Calendar-aware \"nice\" ticks for a time x-axis (values = epoch milliseconds, local time).\n * Picks the smallest step from a seconds→minutes→hours→days→months→years ladder that yields\n * at most ~`target` ticks; sub-second spans fall back to plain numeric ticks.\n */\nexport function niceTimeTicks(min: number, max: number, target: number): number[] {\n  const span = max - min;\n  if (!(span > 0)) return [min];\n  const per = span / Math.max(1, target);\n  if (per < SEC) return niceTicks(min, max, target);\n  const step = TIME_STEPS.find((s) => s >= per);\n  if (step !== undefined) {\n    const out: number[] = [];\n    for (let t = Math.ceil(min / step) * step; t <= max; t += step) out.push(t);\n    return out;\n  }\n  const days = [1, 2, 7, 14].find((d) => d * DAY >= per);\n  if (days !== undefined) return dayTicks(min, max, days);\n  const months = [1, 2, 3, 6].find((m) => m * 30 * DAY >= per);\n  if (months !== undefined) return monthTicks(min, max, months);\n  // Years: reuse the 1/2/5 ladder on year counts (>= 1).\n  const years = Math.max(1, Math.round(tickStep(0, span / (365 * DAY), target)));\n  return monthTicks(min, max, years * 12);\n}\n\nconst MONTH_NAMES = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\nconst two = (v: number): string => String(v).padStart(2, '0');\n\n/**\n * Label a time tick by the finest local-calendar boundary it does NOT sit on — midnight ticks\n * read as dates, hour/minute ticks as clock times, month starts as month names, Jan 1 as the\n * year. Pairs with {@link niceTimeTicks}, whose boundary-aligned ticks make this deterministic.\n * English month abbreviations; pass an explicit `formatX` to localize.\n */\nexport function formatTimeTick(value: number): string {\n  const d = new Date(value);\n  if (d.getMilliseconds()) {\n    return `${two(d.getHours())}:${two(d.getMinutes())}:${two(d.getSeconds())}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n  }\n  if (d.getSeconds()) return `${two(d.getHours())}:${two(d.getMinutes())}:${two(d.getSeconds())}`;\n  if (d.getMinutes() || d.getHours()) return `${two(d.getHours())}:${two(d.getMinutes())}`;\n  if (d.getDate() !== 1) return `${MONTH_NAMES[d.getMonth()]} ${d.getDate()}`;\n  if (d.getMonth() !== 0) return MONTH_NAMES[d.getMonth()];\n  return String(d.getFullYear());\n}\n\n/**\n * Ticks for a log y-axis: decade boundaries (powers of 10), thinned to every k-th decade when\n * the domain spans more than `target` of them, densified with 2× and 5× mantissas when it spans\n * fewer than two. Sub-decade domains (e.g. [3, 7]) fall back to linear nice ticks.\n */\nexport function logTicks(min: number, max: number, target: number): number[] {\n  if (!(min > 0) || !(max > min)) return [min];\n  const lo = Math.ceil(Math.log10(min) - 1e-9);\n  const hi = Math.floor(Math.log10(max) + 1e-9);\n  if (hi < lo) return niceTicks(min, max, target);\n  const decades = hi - lo + 1;\n  const stride = Math.max(1, Math.ceil(decades / Math.max(1, target)));\n  const out: number[] = [];\n  for (let e = lo; e <= hi; e += stride) out.push(Math.pow(10, e));\n  if (out.length >= 3 || stride > 1) return out;\n  // Few decades: add 2/5 mantissa ticks so a narrow log axis still has structure.\n  const dense: number[] = [];\n  for (let e = lo - 1; e <= hi; e++) {\n    for (const m of [1, 2, 5]) {\n      const v = m * Math.pow(10, e);\n      if (v >= min - 1e-12 && v <= max + 1e-12) dense.push(v);\n    }\n  }\n  return dense.length >= 2 ? dense : out;\n}\n\n/**\n * Reduce the desired tick count so labels don't overlap at narrow sizes (WCAG 1.4.10 reflow).\n * Reduction-only: never returns more than `base` (so wide plots keep their requested density),\n * clamped to >= 2. `available` is the plot extent in px, `minPx` the minimum spacing per label.\n */\nexport function effectiveTickCount(base: number, available: number, minPx: number): number {\n  const fit = Math.floor(Math.max(0, available) / Math.max(1, minPx));\n  return Math.max(2, Math.min(base, fit));\n}\n\n/**\n * Default tick label formatter: compact thousands (`12.5k`), otherwise trimmed decimals.\n * The a11y layer can override this for time/category axes.\n */\nexport function formatTick(value: number): string {\n  const abs = Math.abs(value);\n  if (abs >= 1000) {\n    const k = value / 1000;\n    return `${Number.isInteger(k) ? k : k.toFixed(1)}k`;\n  }\n  if (abs !== 0 && abs < 1) return value.toFixed(2);\n  return Number.isInteger(value) ? value.toString() : value.toFixed(1);\n}\n\n/**\n * Locale-aware {@link formatTick}: the same three branches (compact thousands, two-decimal\n * sub-unit values, trimmed decimals) rendered by `Intl.NumberFormat`. An invalid BCP-47 tag\n * throws a RangeError here, at construction — fail fast, not once per tick.\n */\nexport function localeNumberFormatter(locale: string): (value: number) => string {\n  const compact = new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: 1 });\n  const small = new Intl.NumberFormat(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });\n  const plain = new Intl.NumberFormat(locale, { maximumFractionDigits: 1 });\n  return (value) => {\n    const abs = Math.abs(value);\n    if (abs >= 1000) return compact.format(value);\n    if (abs !== 0 && abs < 1) return small.format(value);\n    return plain.format(value);\n  };\n}\n\n/**\n * Locale-aware {@link formatTimeTick}: the identical finest-boundary cascade, labeled by\n * `Intl.DateTimeFormat` (local time, matching {@link niceTimeTicks}). Formatters are built\n * once here, so per-tick formatting stays allocation-free.\n */\nexport function localeTimeFormatter(locale: string): (value: number) => string {\n  const dtf = (opts: Intl.DateTimeFormatOptions): Intl.DateTimeFormat =>\n    new Intl.DateTimeFormat(locale, opts);\n  const clock = { hour: '2-digit', minute: '2-digit' } as const;\n  const millisecond = dtf({ ...clock, second: '2-digit', fractionalSecondDigits: 3 });\n  const second = dtf({ ...clock, second: '2-digit' });\n  const minute = dtf(clock);\n  const day = dtf({ month: 'short', day: 'numeric' });\n  const month = dtf({ month: 'short' });\n  const year = dtf({ year: 'numeric' });\n  return (value) => {\n    const d = new Date(value);\n    if (d.getMilliseconds()) return millisecond.format(d);\n    if (d.getSeconds()) return second.format(d);\n    if (d.getMinutes() || d.getHours()) return minute.format(d);\n    if (d.getDate() !== 1) return day.format(d);\n    if (d.getMonth() !== 0) return month.format(d);\n    return year.format(d);\n  };\n}\n\n/**\n * The default x/y tick formatters for an axis pair. Without a `locale` these are the exact\n * hand-rolled English defaults ({@link formatTick} / {@link formatTimeTick}) — same function\n * references, so existing output is untouched byte-for-byte. With a `locale` they become the\n * Intl-based equivalents.\n */\nexport function defaultFormatters(\n  xType: 'linear' | 'time' | undefined,\n  locale: string | undefined,\n): { x: (v: number) => string; y: (v: number) => string } {\n  const num = locale ? localeNumberFormatter(locale) : formatTick;\n  const time = locale ? localeTimeFormatter(locale) : formatTimeTick;\n  return { x: xType === 'time' ? time : num, y: num };\n}\n","/**\n * Render scheduler — coalesces many state changes into a single animation frame.\n *\n * Interaction handlers (zoom, pan, cursor moves) and data updates all call `request()`.\n * No matter how many fire before the next frame, `onFrame` runs exactly once per frame,\n * and only when something is dirty (render-on-demand — idle charts cost nothing).\n */\n\nexport type FrameCallback = (now: number) => void;\n\n/** Injected animation-frame primitives (overridable for tests / non-DOM environments). */\nexport interface FrameClock {\n  request(cb: (now: number) => void): number;\n  cancel(handle: number): void;\n}\n\nfunction fallbackNow(): number {\n  return typeof performance !== 'undefined' ? performance.now() : 0;\n}\n\nfunction defaultClock(): FrameClock {\n  const raf = typeof globalThis.requestAnimationFrame === 'function';\n  if (raf) {\n    return {\n      request: (cb) => globalThis.requestAnimationFrame(cb),\n      cancel: (h) => globalThis.cancelAnimationFrame(h),\n    };\n  }\n  return {\n    request: (cb) => setTimeout(() => cb(fallbackNow()), 16) as unknown as number,\n    cancel: (h) => clearTimeout(h),\n  };\n}\n\nexport class RenderScheduler {\n  private dirty = false;\n  private handle = 0;\n  private disposed = false;\n  private readonly onFrame: FrameCallback;\n  private readonly clock: FrameClock;\n\n  constructor(onFrame: FrameCallback, clock?: FrameClock) {\n    this.onFrame = onFrame;\n    this.clock = clock ?? defaultClock();\n  }\n\n  /** Mark the chart dirty and ensure a frame is scheduled. Idempotent within a frame. */\n  request(): void {\n    if (this.disposed || this.dirty) return;\n    this.dirty = true;\n    this.handle = this.clock.request(this.tick);\n  }\n\n  /** True while a frame is pending — useful for tests and instrumentation. */\n  get pending(): boolean {\n    return this.dirty;\n  }\n\n  /** Drop any pending frame without disposing the scheduler (e.g. before a sync render). */\n  cancel(): void {\n    if (this.handle) this.clock.cancel(this.handle);\n    this.handle = 0;\n    this.dirty = false;\n  }\n\n  private readonly tick = (now: number): void => {\n    this.handle = 0;\n    this.dirty = false;\n    if (this.disposed) return;\n    this.onFrame(now);\n  };\n\n  destroy(): void {\n    this.disposed = true;\n    if (this.handle) this.clock.cancel(this.handle);\n    this.handle = 0;\n    this.dirty = false;\n  }\n}\n","/**\n * Renderer abstraction — the seam between the renderer-agnostic core and a concrete\n * drawing backend (Canvas2D today; WebGL/HTML-in-Canvas can implement the same\n * interface without changing the core or the public API).\n *\n * A `RenderScene` is a plain-data snapshot of everything needed to draw one frame. The\n * core/`FChart` builds it; the renderer only reads it.\n */\nimport type { LinearScale } from '../core/scales.ts';\nimport type {\n  ChartData,\n  CursorState,\n  Margins,\n  ResolvedAnnotation,\n  ResolvedSeries,\n} from '../core/model.ts';\n\nexport interface RenderScene {\n  /** Plot size in CSS px. */\n  width: number;\n  height: number;\n  /** Device pixel ratio the backing store should use (capped by the caller). */\n  dpr: number;\n  margins: Margins;\n  data: ChartData;\n  series: readonly ResolvedSeries[];\n  /** value → px (range inverted: top pixel = max value). */\n  yScale: LinearScale;\n  /** x-value → px. */\n  xScale: LinearScale;\n  /** Visible x-domain [d0, d1] used for downsampling. */\n  domain: readonly [number, number];\n  /** Tick *values* (single source of truth shared with the DOM tick layer). */\n  xTicks: readonly number[];\n  yTicks: readonly number[];\n  /** Active cursor sample, or null when the cursor is inactive. */\n  cursor: CursorState | null;\n  /** Event markers on the series (dots / vertical rules). */\n  annotations: readonly ResolvedAnnotation[];\n  /** Index (into `annotations`) of the marker under pointer/keyboard focus — drawn emphasized\n   *  with its label forced on — or null. */\n  hoveredAnnotation: number | null;\n  /** Index (into `annotations`) of the pinned/selected marker — emphasized and persistent — or\n   *  null. */\n  selectedAnnotation: number | null;\n  reducedMotion: boolean;\n  highContrast: boolean;\n  /** Windows High Contrast / forced-colors active — repaint marks in system colors. */\n  forcedColors: boolean;\n}\n\n/** Minimum px per candle to draw individual bodies; below this, renderers fall back to the\n *  per-column high/low envelope. Shared by the canvas renderer and the SVG export so both\n *  modes switch at the same density. */\nexport const MIN_CANDLE_PX = 3;\n\nexport interface Renderer {\n  /** Draw a single frame. Must be cheap to call every animation frame. */\n  render(scene: RenderScene): void;\n  /** Release GPU/canvas resources. */\n  destroy(): void;\n}\n","/**\n * Canvas2D renderer — draws the data marks (the fast part). It reads a `RenderScene` and\n * paints grid, plot border, per-series min/max envelopes, and the cursor crosshair.\n *\n * It never iterates raw points directly: it asks the core downsampler for a per-column\n * envelope, so its cost tracks plot width, not N. Envelope buffers are reused across\n * series and frames (zero per-frame allocation in the hot path).\n *\n * Theme colors for grid/axis/cursor come from CSS custom properties on the canvas\n * (`--fc-grid`, `--fc-axis`, `--fc-cursor`, `--fc-ring`) with neutral gray fallbacks that\n * read acceptably on both light and dark backgrounds. Series colors come from config.\n */\nimport { downsampleColumns, lowerBound, type ColumnEnvelope } from '../core/downsample.ts';\nimport { annotationSample, type Margins, type ResolvedSeries } from '../core/model.ts';\nimport { MIN_CANDLE_PX, type Renderer, type RenderScene } from './renderer.ts';\n\ninterface ThemeColors {\n  grid: string;\n  axis: string;\n  cursor: string;\n  ring: string;\n}\n\n/** System colors for Windows High Contrast / forced-colors mode (the bitmap can't auto-adapt). */\ninterface SystemColors {\n  text: string;\n  grid: string;\n  accent: string;\n  bg: string;\n}\n\n/**\n * Read forced-colors system colors via a connected probe, or null when forced-colors is inactive.\n * A `<canvas>` bitmap does not participate in forced-colors, so we repaint the marks with these\n * (all series in the system text color, distinguished by their dash patterns — see R5).\n */\nfunction readForcedColors(canvas: HTMLCanvasElement): SystemColors | null {\n  const view = canvas.ownerDocument.defaultView;\n  if (!view?.matchMedia('(forced-colors: active)').matches) return null;\n  const probe = canvas.ownerDocument.createElement('span');\n  probe.style.cssText =\n    'position:absolute;width:0;height:0;color:CanvasText;' +\n    'background-color:Canvas;border-color:GrayText;outline-color:Highlight';\n  (canvas.parentElement ?? canvas.ownerDocument.body).append(probe);\n  const cs = getComputedStyle(probe);\n  const sys: SystemColors = {\n    text: cs.color,\n    grid: cs.borderColor,\n    bg: cs.backgroundColor,\n    accent: cs.outlineColor,\n  };\n  probe.remove();\n  return sys;\n}\n\nfunction readTheme(canvas: HTMLCanvasElement): ThemeColors {\n  const cs = getComputedStyle(canvas);\n  const v = (name: string, fallback: string): string =>\n    cs.getPropertyValue(name).trim() || fallback;\n  return {\n    // Grid/axis are decorative aids (not the \"graphical object required to understand\" that\n    // 1.4.11 governs — that's the series marks, see DEFAULT_PALETTE). Raised from 0.13/0.30 for\n    // legible defaults; a translucent gray line can't reach 3:1 on white and isn't required to.\n    grid: v('--fc-grid', 'rgba(128,128,128,0.20)'),\n    axis: v('--fc-axis', 'rgba(128,128,128,0.40)'),\n    cursor: v('--fc-cursor', 'rgba(128,128,128,0.55)'),\n    ring: v('--fc-ring', 'rgba(255,255,255,0.85)'),\n  };\n}\n\nexport function createCanvas2DRenderer(canvas: HTMLCanvasElement): Renderer {\n  const context = canvas.getContext('2d');\n  if (!context) throw new Error('fcharts: could not acquire a 2D canvas context.');\n  const ctx: CanvasRenderingContext2D = context;\n\n  let cssW = 0;\n  let cssH = 0;\n  let dpr = 0;\n  let theme = readTheme(canvas);\n  // System colors, read only when forced-colors *toggles* (reading forces layout, so not per-frame).\n  let forced: SystemColors | null = null;\n  let forcedActive = false;\n  let forcedRead = false; // whether we've already probed for the current forcedActive value\n  const buf = { min: new Float32Array(0), max: new Float32Array(0) };\n\n  function syncSize(scene: RenderScene): void {\n    if (scene.width === cssW && scene.height === cssH && scene.dpr === dpr) return;\n    cssW = scene.width;\n    cssH = scene.height;\n    dpr = scene.dpr;\n    canvas.width = Math.max(1, Math.round(cssW * dpr));\n    canvas.height = Math.max(1, Math.round(cssH * dpr));\n    canvas.style.width = `${cssW}px`;\n    canvas.style.height = `${cssH}px`;\n    theme = readTheme(canvas);\n  }\n\n  function render(scene: RenderScene): void {\n    syncSize(scene);\n    // Probe only on a genuine toggle. Keying off `!forced` would re-probe every frame when the\n    // option is pinned true but the OS media query is inactive (readForcedColors returns null),\n    // forcing a layout reflow in the render hot path.\n    if (scene.forcedColors !== forcedActive || !forcedRead) {\n      forced = scene.forcedColors ? readForcedColors(canvas) : null;\n      forcedActive = scene.forcedColors;\n      forcedRead = true;\n    }\n    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n    ctx.clearRect(0, 0, cssW, cssH);\n\n    const m = scene.margins;\n    const plotW = Math.max(1, cssW - m.left - m.right);\n    const plotH = Math.max(1, cssH - m.top - m.bottom);\n\n    drawGrid(scene, plotW, plotH);\n\n    const cols = Math.max(1, Math.floor(plotW));\n    if (buf.min.length !== cols) {\n      buf.min = new Float32Array(cols);\n      buf.max = new Float32Array(cols);\n    }\n    for (const s of scene.series) {\n      if (!s.visible) continue;\n      if (s.type === 'candle') {\n        drawCandleSeries(scene, s, m, cols);\n        continue;\n      }\n      const env = downsampleColumns(\n        scene.data.x,\n        scene.data.y[s.index],\n        scene.data.pyramids[s.index],\n        scene.domain,\n        cols,\n        buf,\n      );\n      if (env.first < 0) continue;\n      if (s.type === 'area') drawArea(scene, s, env, m, plotH);\n      drawEnvelope(scene, s, env, m);\n    }\n\n    if (scene.annotations.length) drawAnnotations(scene, m, plotW, plotH);\n    if (scene.cursor) drawCursor(scene, m, plotH);\n  }\n\n  /**\n   * Event markers: a vertical rule, or a diamond on the nearest sample of a series. The diamond\n   * shape (distinct from the round cursor dot) plus the label carry the meaning, so the mark is\n   * never color-only (WCAG 1.4.1). Markers outside the visible x-window are skipped.\n   */\n  function drawDiamond(px: number, py: number, r: number, color: string, emphasized: boolean): void {\n    ctx.beginPath();\n    ctx.moveTo(px, py - r);\n    ctx.lineTo(px + r, py);\n    ctx.lineTo(px, py + r);\n    ctx.lineTo(px - r, py);\n    ctx.closePath();\n    ctx.fillStyle = color;\n    ctx.fill();\n    ctx.lineWidth = emphasized ? 2.5 : 1.5;\n    ctx.strokeStyle = forced ? forced.bg : theme.ring;\n    ctx.stroke();\n  }\n\n  /** A hollow ring around a pinned marker, so the selected event reads as \"held\" not just hovered. */\n  function drawPinRing(px: number, py: number, r: number, color: string): void {\n    ctx.beginPath();\n    ctx.arc(px, py, r + 4, 0, Math.PI * 2);\n    ctx.strokeStyle = color;\n    ctx.lineWidth = 1.5;\n    ctx.stroke();\n  }\n\n  function drawAnnotations(scene: RenderScene, m: Margins, plotW: number, plotH: number): void {\n    const left = m.left;\n    const right = left + plotW;\n    const top = m.top;\n    const bottom = top + plotH;\n    ctx.save();\n    ctx.beginPath();\n    ctx.rect(left, top, plotW, plotH);\n    ctx.clip();\n    ctx.font = '10px system-ui, sans-serif';\n    ctx.textAlign = 'center';\n    for (let i = 0; i < scene.annotations.length; i++) {\n      const a = scene.annotations[i];\n      const px = scene.xScale(a.x);\n      if (px < left - 1 || px > right + 1) continue;\n      const emphasized = i === scene.hoveredAnnotation || i === scene.selectedAnnotation;\n      const pinned = i === scene.selectedAnnotation;\n      const color = forced ? forced.text : a.color;\n      // The focused/selected marker always shows its label (even when showLabel is false), so the\n      // hovered or keyboard-selected event is named on the chart itself, not only in the readout.\n      const label = a.showLabel || emphasized;\n      if (a.kind === 'rule') {\n        ctx.strokeStyle = color;\n        ctx.lineWidth = emphasized ? 2 : 1;\n        ctx.setLineDash([4, 3]);\n        ctx.beginPath();\n        ctx.moveTo(px, top);\n        ctx.lineTo(px, bottom);\n        ctx.stroke();\n        ctx.setLineDash([]);\n        if (label) {\n          ctx.fillStyle = color;\n          ctx.fillText(a.label, px, top + 9);\n        }\n        continue;\n      }\n      // A point marker sits on its series' line, so it hides when that series is toggled off\n      // (consistent with the announce path, which skips hidden series).\n      const target = scene.series[a.seriesIndex];\n      if (target && !target.visible) continue;\n      const pt = annotationSample(scene.data, scene.series, a);\n      if (!pt) continue;\n      const py = scene.yScale(pt.y);\n      const r = emphasized ? 7 : 5;\n      if (pinned) drawPinRing(px, py, r, color);\n      drawDiamond(px, py, r, color, emphasized);\n      if (label) {\n        ctx.fillStyle = color;\n        ctx.fillText(a.label, px, py - r - 4);\n      }\n    }\n    ctx.restore();\n  }\n\n  function drawGrid(scene: RenderScene, plotW: number, plotH: number): void {\n    const m = scene.margins;\n    const left = m.left;\n    const right = m.left + plotW;\n    const top = m.top;\n    const bottom = m.top + plotH;\n\n    ctx.lineWidth = 1;\n    ctx.strokeStyle = forced ? forced.grid : scene.highContrast ? theme.axis : theme.grid;\n    ctx.beginPath();\n    for (const value of scene.yTicks) {\n      const py = Math.round(scene.yScale(value)) + 0.5;\n      if (py < top - 1 || py > bottom + 1) continue;\n      ctx.moveTo(left, py);\n      ctx.lineTo(right, py);\n    }\n    for (const tick of scene.xTicks) {\n      const px = Math.round(scene.xScale(tick)) + 0.5;\n      if (px < left - 1 || px > right + 1) continue;\n      ctx.moveTo(px, top);\n      ctx.lineTo(px, bottom);\n    }\n    ctx.stroke();\n\n    ctx.strokeStyle = forced ? forced.text : theme.axis;\n    ctx.strokeRect(left + 0.5, top + 0.5, plotW - 1, plotH - 1);\n  }\n\n  function drawEnvelope(\n    scene: RenderScene,\n    s: ResolvedSeries,\n    env: ColumnEnvelope,\n    m: Margins,\n  ): void {\n    const y = scene.yScale;\n    ctx.beginPath();\n    let started = false;\n    for (let c = env.first; c <= env.last; c++) {\n      if (env.min[c] === Infinity) continue;\n      const x = m.left + c + 0.5;\n      const pMax = y(env.max[c]);\n      const pMin = y(env.min[c]);\n      if (!started) {\n        ctx.moveTo(x, pMax);\n        started = true;\n      } else {\n        ctx.lineTo(x, pMax);\n      }\n      ctx.lineTo(x, pMin);\n    }\n    // Under forced-colors every series uses the system text color; the dash distinguishes them.\n    ctx.strokeStyle = forced ? forced.text : s.color;\n    ctx.lineWidth = scene.highContrast ? s.width + 0.75 : s.width;\n    ctx.lineJoin = 'round';\n    // Per-series dash so colour isn't the only channel (WCAG 1.4.1). [] = solid.\n    ctx.setLineDash(s.dash);\n    ctx.globalAlpha = 0.95;\n    ctx.stroke();\n    ctx.setLineDash([]);\n    ctx.globalAlpha = 1;\n  }\n\n  function drawArea(\n    scene: RenderScene,\n    s: ResolvedSeries,\n    env: ColumnEnvelope,\n    m: Margins,\n    plotH: number,\n  ): void {\n    const y = scene.yScale;\n    const top = m.top;\n    const bottom = m.top + plotH;\n    const zero = y(0);\n    const baseline = zero < top ? top : zero > bottom ? bottom : zero;\n\n    ctx.beginPath();\n    let started = false;\n    let lastX = m.left;\n    for (let c = env.first; c <= env.last; c++) {\n      if (env.min[c] === Infinity) continue;\n      const x = m.left + c + 0.5;\n      const pMax = y(env.max[c]);\n      if (!started) {\n        ctx.moveTo(x, baseline);\n        ctx.lineTo(x, pMax);\n        started = true;\n      } else {\n        ctx.lineTo(x, pMax);\n      }\n      lastX = x;\n    }\n    ctx.lineTo(lastX, baseline);\n    ctx.closePath();\n    ctx.fillStyle = forced ? forced.text : s.color;\n    ctx.globalAlpha = s.fillAlpha;\n    ctx.fill();\n    ctx.globalAlpha = 1;\n  }\n\n  /**\n   * Candle series: individual candlesticks while each candle has >= MIN_CANDLE_PX of width;\n   * denser than that, the per-column high/low envelope (from the existing pyramids) so cost\n   * stays O(width). Direction is encoded by fill AND colour: up = hollow body, down = filled\n   * (WCAG 1.4.1 — colour is never the only channel).\n   */\n  function drawCandleSeries(scene: RenderScene, s: ResolvedSeries, m: Margins, cols: number): void {\n    const x = scene.data.x;\n    const i0 = Math.max(0, lowerBound(x, scene.domain[0]) - 1);\n    const i1 = Math.min(x.length - 1, lowerBound(x, scene.domain[1]));\n    if (i1 < i0) return;\n    const count = i1 - i0 + 1;\n    if (cols / count < MIN_CANDLE_PX) {\n      drawCandleEnvelope(scene, s, m, cols);\n      return;\n    }\n\n    const [yo, yh, yl, yc] = [\n      scene.data.y[s.index],\n      scene.data.y[s.index + 1],\n      scene.data.y[s.index + 2],\n      scene.data.y[s.index + 3],\n    ];\n    const yS = scene.yScale;\n    const xS = scene.xScale;\n    // Body width from the median candle spacing, capped for readability at deep zoom.\n    const spacing = count > 1 ? (xS(x[i1]) - xS(x[i0])) / (count - 1) : cols;\n    const bodyW = Math.max(1, Math.min(spacing * 0.7, 13));\n    const lineW = scene.highContrast ? 1.75 : 1;\n\n    // The visible range extends one sample past each edge; keep those inside the plot box.\n    ctx.save();\n    ctx.beginPath();\n    ctx.rect(m.left, m.top, scene.width - m.left - m.right, scene.height - m.top - m.bottom);\n    ctx.clip();\n\n    for (let i = i0; i <= i1; i++) {\n      const o = yo[i];\n      const c = yc[i];\n      if (!Number.isFinite(o) || !Number.isFinite(c)) continue; // gap candle\n      const up = c >= o;\n      const color = forced ? forced.text : up ? s.upColor : s.downColor;\n      const px = Math.round(xS(x[i]));\n      const pTop = yS(Math.max(o, c));\n      const pBot = yS(Math.min(o, c));\n\n      // Wick: high → low through the body.\n      ctx.strokeStyle = color;\n      ctx.lineWidth = lineW;\n      ctx.beginPath();\n      ctx.moveTo(px + 0.5, yS(yh[i]));\n      ctx.lineTo(px + 0.5, yS(yl[i]));\n      ctx.stroke();\n\n      // Body: hollow when up, filled when down. Sub-pixel bodies still get a 1px bar.\n      const h = Math.max(1, pBot - pTop);\n      const bx = px - bodyW / 2 + 0.5;\n      if (up) {\n        // Knock the wick out of the hollow body (forced-colors keeps the hollow/filled\n        // channel by filling with the system background).\n        ctx.fillStyle = forced ? forced.bg : theme.ring;\n        ctx.fillRect(bx, pTop, bodyW, h);\n        ctx.strokeStyle = color;\n        ctx.strokeRect(bx, pTop, bodyW, h);\n      } else {\n        ctx.fillStyle = color;\n        ctx.fillRect(bx, pTop, bodyW, h);\n      }\n    }\n    ctx.restore();\n  }\n\n  /** Dense fallback: per-column bars spanning the candle highs/lows (exact via the pyramids). */\n  function drawCandleEnvelope(scene: RenderScene, s: ResolvedSeries, m: Margins, cols: number): void {\n    const hi = downsampleColumns(\n      scene.data.x, scene.data.y[s.index + 1], scene.data.pyramids[s.index + 1],\n      scene.domain, cols, buf,\n    );\n    // `buf` is reused per call: copy the highs out before computing the lows over the same buffer.\n    const hiMax = hi.max.slice();\n    const first = hi.first;\n    const last = hi.last;\n    const lo = downsampleColumns(\n      scene.data.x, scene.data.y[s.index + 2], scene.data.pyramids[s.index + 2],\n      scene.domain, cols, buf,\n    );\n    if (first < 0) return;\n    const y = scene.yScale;\n    ctx.strokeStyle = forced ? forced.text : s.color;\n    ctx.lineWidth = 1;\n    ctx.beginPath();\n    for (let c = first; c <= last; c++) {\n      if (hiMax[c] === -Infinity || lo.min[c] === Infinity) continue;\n      const px = m.left + c + 0.5;\n      ctx.moveTo(px, y(hiMax[c]));\n      ctx.lineTo(px, y(lo.min[c]));\n    }\n    ctx.globalAlpha = 0.95;\n    ctx.stroke();\n    ctx.globalAlpha = 1;\n  }\n\n  function drawCursor(scene: RenderScene, m: Margins, plotH: number): void {\n    const cur = scene.cursor!;\n    const s = scene.series[cur.series];\n    if (!s || !s.visible) return;\n    const xv = scene.data.x[cur.index];\n    // Candle series: pin the cursor dot to the close (the value the readout leads with).\n    const v = scene.data.y[s.type === 'candle' ? s.index + 3 : s.index][cur.index];\n    const px = scene.xScale(xv);\n    const py = scene.yScale(v);\n    const left = m.left;\n    const right = scene.width - m.right;\n    if (px < left - 2 || px > right + 2) return;\n\n    ctx.save();\n    ctx.strokeStyle = forced ? forced.text : theme.cursor;\n    ctx.lineWidth = 1;\n    ctx.setLineDash([3, 3]);\n    ctx.beginPath();\n    ctx.moveTo(px, m.top);\n    ctx.lineTo(px, m.top + plotH);\n    ctx.moveTo(left, py);\n    ctx.lineTo(right, py);\n    ctx.stroke();\n    ctx.setLineDash([]);\n\n    ctx.beginPath();\n    ctx.arc(px, py, 4.5, 0, Math.PI * 2);\n    ctx.fillStyle = forced ? forced.accent : s.color;\n    ctx.fill();\n    ctx.lineWidth = 2;\n    ctx.strokeStyle = forced ? forced.bg : theme.ring;\n    ctx.stroke();\n    ctx.restore();\n  }\n\n  return {\n    render,\n    destroy(): void {\n      ctx.setTransform(1, 0, 0, 1, 0, 0);\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\n      buf.min = new Float32Array(0);\n      buf.max = new Float32Array(0);\n    },\n  };\n}\n","/**\n * HTML-in-Canvas feature detection.\n *\n * The experimental \"HTML-in-Canvas\" API (Chrome dev-trial; Origin Trial M148–M150, behind\n * `chrome://flags/#canvas-draw-element`) lets a `<canvas>` draw its own element children into\n * the bitmap while they stay the live, accessible, hit-testable source of truth. We feature-\n * detect the shipped 2D entry point and fall back to the DOM-overlay path everywhere else —\n * the library is fully functional and fully accessible via the overlay regardless.\n *\n * The 2D method was renamed `drawElement` → `drawHTMLElement` → `drawHTML` → `drawElementImage`,\n * and the older aliases were removed at Chrome M145. We detect the current name only; detecting\n * a removed alias (or the incidental WebGL `texElementImage2D`) would falsely report support.\n */\n\nexport type RenderPath = 'dom-overlay' | 'html-in-canvas';\n\nexport interface HtmlInCanvasSupport {\n  supported: boolean;\n  /** Which specific API surfaced the capability (for diagnostics). */\n  via: string | null;\n}\n\n/**\n * Detect the HTML-in-Canvas 2D drawing entry point. Pure detection — touches no global state\n * and never throws.\n */\nexport function detectHtmlInCanvas(): HtmlInCanvasSupport {\n  try {\n    const ctxProto =\n      typeof CanvasRenderingContext2D !== 'undefined' ? CanvasRenderingContext2D.prototype : null;\n    if (ctxProto && 'drawElementImage' in ctxProto) return { supported: true, via: 'drawElementImage' };\n  } catch {\n    // Any detection error → treat as unsupported and fall back to the DOM overlay.\n  }\n  return { supported: false, via: null };\n}\n\n/**\n * The render path the library will use given current support. The HTML-in-Canvas path is used\n * when available, but it self-verifies at runtime: if a composite reports success yet paints no\n * tick pixels into the bitmap (observed on some Chrome dev builds), the chart automatically falls\n * back to the DOM overlay so the axes can never silently vanish (see `fcharts`' `compositeTicks`).\n */\nexport function resolveRenderPath(support: HtmlInCanvasSupport): RenderPath {\n  return support.supported ? 'html-in-canvas' : 'dom-overlay';\n}\n","/**\n * HTML-in-Canvas compositor — progressive enhancement (Chrome dev-trial only).\n *\n * When the browser exposes the HTML-in-Canvas API (`ctx.drawElementImage`), fcharts can draw\n * its real-DOM text layer *into* the canvas so the chart is one composited surface, while the\n * element stays the live, accessible, hit-testable, find-in-page-able source of truth.\n *\n * Contract (per the WICG explainer, verified empirically in Chrome 148 and 149):\n *  - the layer MUST be an *immediate child* of the `<canvas>`;\n *  - the canvas must carry the boolean `layoutsubtree` attribute (which opts its children into\n *    layout + hit-testing — note they are NOT painted to screen on their own, only via a draw);\n *  - the layer cannot size itself against the canvas box: `inset:0` resolves to 0×0 in\n *    Chrome 149, silently snapshotting nothing — the caller must give it an explicit size;\n *  - a paint snapshot of the children must already exist. Before one does, Chrome 148 throws\n *    \"no cached paint record\" on every draw, Chrome 149 throws InvalidStateError on the first\n *    frame and then \"succeeds\" while painting nothing — callers must verify pixels landed and\n *    treat all of these as warm-up misses (see `fcharts`' `compositeTicks`);\n *  - `drawElementImage(el, dx, dy)` returns the `DOMMatrix` mapping the live element onto the\n *    drawn pixels; assigning it to `el.style.transform` keeps hit-testing/focus aligned with\n *    what's painted.\n *\n * No browser ships this un-flagged, so `composite()` is a no-op in production today. Because a\n * `layoutsubtree` child only becomes visible via `drawElementImage`, the caller MUST keep a\n * fallback (re-show the layer as a normal overlay) if `composite()` never succeeds — see\n * `fcharts`' html-in-canvas handling.\n */\n\ninterface HtmlInCanvasContext extends CanvasRenderingContext2D {\n  drawElementImage(element: Element, dx: number, dy: number): DOMMatrix;\n}\n\nfunction hasDrawElementImage(ctx: CanvasRenderingContext2D): ctx is HtmlInCanvasContext {\n  return typeof (ctx as { drawElementImage?: unknown }).drawElementImage === 'function';\n}\n\nexport interface Compositor {\n  /** Whether this browser actually exposes the API (so callers can branch DOM structure). */\n  readonly supported: boolean;\n  /** Opt the canvas into laying out its element children. Idempotent; no-op if unsupported. */\n  enable(): void;\n  /**\n   * Draw a canvas-child `layer` into the bitmap at (dx, dy) — device pixels — and sync its\n   * transform.\n   * @returns true if it composited this frame; false if unsupported or no snapshot yet.\n   */\n  composite(layer: HTMLElement, dx?: number, dy?: number): boolean;\n}\n\nexport function createCompositor(canvas: HTMLCanvasElement): Compositor {\n  const ctx = canvas.getContext('2d');\n  const supported = !!ctx && hasDrawElementImage(ctx);\n  return {\n    supported,\n    enable(): void {\n      if (supported && !canvas.hasAttribute('layoutsubtree')) canvas.setAttribute('layoutsubtree', '');\n    },\n    composite(layer: HTMLElement, dx = 0, dy = 0): boolean {\n      if (!supported || !ctx) return false;\n      // The element snapshot is already at device-pixel resolution (verified at dpr 2 on\n      // Chrome 149), so it must be drawn under an identity transform. The renderer leaves a\n      // scale(dpr) on the context — drawing under it compounds to dpr²: labels twice their\n      // size and the bottom of the layer pushed off the bitmap.\n      ctx.save();\n      ctx.setTransform(1, 0, 0, 1, 0, 0);\n      try {\n        const matrix = (ctx as HtmlInCanvasContext).drawElementImage(layer, dx, dy);\n        // Keep the live (canvas-placed) element aligned with the drawn pixels so focus and\n        // hit-testing land where the text appears.\n        layer.style.transform = matrix.toString();\n        return true;\n      } catch {\n        // No paint snapshot yet (first frame) or a transient failure — retry next frame.\n        return false;\n      } finally {\n        ctx.restore();\n      }\n    },\n  };\n}\n","/**\n * SVG render themes — the color palette a server-side SVG is painted with.\n *\n * The canvas renderer reads CSS custom properties off the live `<canvas>`, but a pure\n * server-side SVG string has no document to inherit from, so its colors must be passed in.\n * `lightTheme` reproduces the values `buildSVG` hardcoded before themes existed, so it stays\n * the default and nothing rendered today changes. `darkTheme` is the dashboard preset (dark\n * panels, brighter ink) for SSR apps like the Hecate desk.\n */\nimport { DEFAULT_PALETTE } from '../core/model.ts';\n\nexport interface SvgTheme {\n  /** Page/background rect fill. */\n  bg: string;\n  /** Gridlines. */\n  grid: string;\n  /** Plot border + axis lines. */\n  axis: string;\n  /** Tick-label text. */\n  tick: string;\n  /** Axis-title text. */\n  label: string;\n  /** Series palette for series that don't set an explicit color. Index-aligned, cycled.\n   *  Both presets reuse {@link DEFAULT_PALETTE} (verified >= 3:1 on light AND dark, R6). */\n  series: readonly string[];\n}\n\n/** The original hardcoded light values — the default, so existing exports are unchanged. */\nexport const lightTheme: SvgTheme = {\n  bg: '#ffffff',\n  grid: '#e5e7eb',\n  axis: '#9ca3af',\n  tick: '#4b5563',\n  label: '#6b7280',\n  series: DEFAULT_PALETTE,\n};\n\n/** Dark dashboard preset (SSR panels). Ink/grid verified >= 3:1 on the `bg`. */\nexport const darkTheme: SvgTheme = {\n  bg: '#0a0d12',\n  grid: 'rgba(148,163,184,0.16)',\n  axis: 'rgba(148,163,184,0.45)',\n  tick: '#94a3b8',\n  label: '#64748b',\n  series: DEFAULT_PALETTE,\n};\n\n/**\n * Status palette for progress/threshold marks (bars, scatter dots) — `ok`/`near`/`over`.\n * Reuses the contrast-checked green/amber/red verified >= 3:1 on both light and dark\n * backgrounds (R6), so status reads without relying on a legend.\n */\nexport type Status = 'ok' | 'near' | 'over';\n\nexport const STATUS_COLORS: Record<Status, string> = {\n  ok: '#16a34a',\n  near: '#d97706',\n  over: '#dc2626',\n};\n\n/** Resolve an optional partial theme onto a base preset (light by default). */\nexport function resolveTheme(theme?: Partial<SvgTheme>, base: SvgTheme = lightTheme): SvgTheme {\n  return theme ? { ...base, ...theme } : base;\n}\n\n/**\n * A mark's paint: explicit color wins, then its status color, then the palette default —\n * the shared fallback chain for status-bearing marks (bar rows, scatter dots).\n */\nexport function markColor(color: string | undefined, status: Status | undefined): string {\n  return color || (status ? STATUS_COLORS[status] : DEFAULT_PALETTE[0]);\n}\n","/**\n * Shared SVG-building primitives — escaping, number formatting, the document envelope, and the\n * machine-readable JSON embed. Used by every pure-SVG renderer (`svg-export` time-series plus the\n * donut / scatter / sparkline / bars primitives) so escaping and the agent-readable contract are\n * defined once, not re-derived per chart type.\n */\n\n/** Escape a string for inclusion in SVG text / attribute values. */\nexport const esc = (s: string): string =>\n  s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n/** Round to 0.1px — small, stable SVG numbers (sub-pixel precision is noise at render time). */\nexport const n = (v: number): string => (Math.round(v * 10) / 10).toString();\n\n/**\n * An embedded `<script type=\"application/json\" data-fcharts>` block carrying a structured summary.\n * This is the same agent-readable contract the live DOM chart exposes, so a static server-rendered\n * SVG stays machine-readable to crawlers and AI agents with no JS running. Returns '' when omitted.\n */\nexport function embedSummary(summary: unknown): string {\n  return (\n    `<script type=\"application/json\" data-fcharts=\"summary\">` +\n    // `]]>`/`</` can't appear in JSON.stringify output except inside strings; escape `<` so the\n    // script element can never be closed early by hostile label text.\n    `${JSON.stringify(summary).replace(/</g, '\\\\u003c')}</script>`\n  );\n}\n\n/**\n * Wrap inner SVG markup in a focusable hyperlink when `href` is set, else return it unchanged.\n *\n * Uses the SVG2 plain `href` attribute (not the legacy `xlink:href`), so the document needs no\n * extra `xmlns:xlink` declaration to stay well-formed standalone, and the `<a>` is keyboard-\n * focusable — the drill-down affordance a donut slice / bar row needs. Presentation only: the\n * embedded JSON summary and `<desc>` are unaffected by links.\n */\nexport function anchor(href: string | undefined, inner: string): string {\n  return href ? `<a href=\"${esc(href)}\">${inner}</a>` : inner;\n}\n\n/**\n * A `<text>` element in the shared chart font. `content` is raw markup — callers `esc()` their\n * strings (and may include `<tspan>`s), keeping escaping explicit and grep-able at each site.\n */\nexport function text(\n  x: number,\n  y: number,\n  content: string,\n  o: { fill: string; size?: number; anchor?: 'middle' | 'end'; weight?: 600 },\n): string {\n  return (\n    `<text x=\"${n(x)}\" y=\"${n(y)}\"` +\n    (o.anchor ? ` text-anchor=\"${o.anchor}\"` : '') +\n    ` font-family=\"system-ui,sans-serif\" font-size=\"${n(o.size ?? 11)}\"` +\n    (o.weight ? ` font-weight=\"${o.weight}\"` : '') +\n    ` fill=\"${esc(o.fill)}\">${content}</text>`\n  );\n}\n\n/** The full-document background rect every axed chart starts with. */\nexport function bgRect(width: number, height: number, fill: string): string {\n  return `<rect width=\"${n(width)}\" height=\"${n(height)}\" fill=\"${esc(fill)}\"/>`;\n}\n\n/**\n * The minimal accessible SVG envelope — `role=\"img\"` + `aria-label` + a mirroring `<title>`\n * (older AT ignores aria-label on inline SVG). Used directly by the micro-elements (sparkline,\n * progress) that carry no `<desc>`/summary; {@link svgDocument} builds on it for full charts.\n */\nexport function svgRoot(opts: { width: number; height: number; label: string; body: string }): string {\n  return (\n    `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${n(opts.width)} ${n(opts.height)}\" ` +\n    `width=\"${n(opts.width)}\" height=\"${n(opts.height)}\" role=\"img\" aria-label=\"${esc(opts.label)}\">` +\n    `<title>${esc(opts.label)}</title>${opts.body}</svg>`\n  );\n}\n\n/**\n * Wrap body parts in a complete, standalone SVG document with an accessible name + description.\n * `extra` is appended after `<desc>` (e.g. the embedded JSON summary).\n */\nexport function svgDocument(opts: {\n  width: number;\n  height: number;\n  title: string;\n  desc: string;\n  body: string;\n  extra?: string;\n}): string {\n  return svgRoot({\n    width: opts.width,\n    height: opts.height,\n    label: opts.title,\n    body: `<desc>${esc(opts.desc)}</desc>${opts.extra ?? ''}${opts.body}`,\n  });\n}\n","/**\n * SVG export — a standalone `<svg>` string mirroring the current view (the EU data-viz guide\n * lists \"export an SVG that can be turned into a tactile graphic\" as a non-visual technique;\n * it's also handy for print/embedding and zero-client-JS server rendering). Pure: string in,\n * string out, no DOM — unit-testable and Node-safe.\n *\n * It draws the same downsampled min/max envelope the canvas does (so cost tracks plot width,\n * not N), reproduces per-series dash patterns, themes via {@link SvgTheme} (light by default),\n * and embeds the axis ticks as real `<text>` plus a `<title>`/`<desc>` — and optionally the\n * machine-readable `ChartSummary` JSON — so the SVG itself stays accessible and agent-readable.\n */\nimport { downsampleColumns, lowerBound } from '../core/downsample.ts';\nimport {\n  annotationSample,\n  type ChartData,\n  type Margins,\n  type ResolvedAnnotation,\n  type ResolvedSeries,\n} from '../core/model.ts';\nimport type { LinearScale } from '../core/scales.ts';\nimport { MIN_CANDLE_PX } from './renderer.ts';\nimport { lightTheme, type SvgTheme } from './svg-theme.ts';\nimport { bgRect, embedSummary, esc, n, svgDocument, text } from './svg-util.ts';\n\nexport interface SvgScene {\n  width: number;\n  height: number;\n  margins: Margins;\n  series: readonly ResolvedSeries[];\n  data: ChartData;\n  xScale: LinearScale;\n  yScale: LinearScale;\n  domain: readonly [number, number];\n  xTicks: readonly number[];\n  yTicks: readonly number[];\n  formatX: (v: number) => string;\n  formatY: (v: number) => string;\n  title: string;\n  /** One-line natural-language summary (for <desc>). */\n  desc: string;\n  xLabel?: string;\n  yLabel?: string;\n  /** Event markers on the series (dots / vertical rules). */\n  annotations?: readonly ResolvedAnnotation[];\n  /** Render colors. Defaults to {@link lightTheme} so existing exports are byte-unchanged. */\n  theme?: SvgTheme;\n  /** When set, embedded as `<script type=\"application/json\" data-fcharts>` so a static SVG\n   *  stays machine-readable with no JS running. Pass the `ChartSummary`. */\n  summary?: unknown;\n}\n\ninterface Envelope {\n  min: Float32Array;\n  max: Float32Array;\n  first: number;\n  last: number;\n}\n\n/** The min/max envelope as a zigzag stroke path — matches the canvas line drawing. */\nfunction strokePath(env: Envelope, left: number, yScale: LinearScale): string {\n  let d = '';\n  let started = false;\n  for (let c = env.first; c <= env.last; c++) {\n    if (env.min[c] === Infinity) continue;\n    const x = n(left + c + 0.5);\n    d += `${started ? 'L' : 'M'}${x},${n(yScale(env.max[c]))}L${x},${n(yScale(env.min[c]))}`;\n    started = true;\n  }\n  return d;\n}\n\n/** A closed polygon: the max edge left→right, then back along the baseline — for area fills. */\nfunction areaPath(env: Envelope, left: number, yScale: LinearScale, baseY: number): string {\n  let top = '';\n  let firstX = 0;\n  let lastX = 0;\n  let started = false;\n  for (let c = env.first; c <= env.last; c++) {\n    if (env.min[c] === Infinity) continue;\n    const px = left + c + 0.5;\n    top += `${started ? 'L' : 'M'}${n(px)},${n(yScale(env.max[c]))}`;\n    if (!started) firstX = px;\n    lastX = px;\n    started = true;\n  }\n  if (!started) return '';\n  return `${top}L${n(lastX)},${n(baseY)}L${n(firstX)},${n(baseY)}Z`;\n}\n\n/**\n * Candle series → SVG elements, mirroring the canvas: individual wick lines + body rects\n * (up = hollow against the theme background, down = filled) while each candle has >=\n * MIN_CANDLE_PX of width, else the per-column high/low envelope as a single bar path.\n */\nfunction candleParts(\n  scene: SvgScene,\n  s: ResolvedSeries,\n  cols: number,\n  buf: { min: Float32Array; max: Float32Array },\n  theme: SvgTheme,\n): string[] {\n  const { data, xScale, yScale, domain } = scene;\n  const x = data.x;\n  const i0 = Math.max(0, lowerBound(x, domain[0]) - 1);\n  const i1 = Math.min(x.length - 1, lowerBound(x, domain[1]));\n  if (i1 < i0) return [];\n  const count = i1 - i0 + 1;\n  const left = scene.margins.left;\n\n  if (cols / count < MIN_CANDLE_PX) {\n    const hi = downsampleColumns(x, data.y[s.index + 1], data.pyramids[s.index + 1], domain, cols, buf);\n    const hiMax = hi.max.slice();\n    const first = hi.first;\n    const last = hi.last;\n    const lo = downsampleColumns(x, data.y[s.index + 2], data.pyramids[s.index + 2], domain, cols, buf);\n    if (first < 0) return [];\n    let d = '';\n    for (let c = first; c <= last; c++) {\n      if (hiMax[c] === -Infinity || lo.min[c] === Infinity) continue;\n      const px = n(left + c + 0.5);\n      d += `M${px},${n(yScale(hiMax[c]))}L${px},${n(yScale(lo.min[c]))}`;\n    }\n    return d ? [`<path d=\"${d}\" stroke=\"${esc(s.color)}\" stroke-width=\"1\" fill=\"none\"/>`] : [];\n  }\n\n  const [yo, yh, yl, yc] = [data.y[s.index], data.y[s.index + 1], data.y[s.index + 2], data.y[s.index + 3]];\n  const spacing = count > 1 ? (xScale(x[i1]) - xScale(x[i0])) / (count - 1) : cols;\n  const bodyW = Math.max(1, Math.min(spacing * 0.7, 13));\n  const out: string[] = [];\n  for (let i = i0; i <= i1; i++) {\n    const o = yo[i];\n    const c = yc[i];\n    if (!Number.isFinite(o) || !Number.isFinite(c)) continue; // gap candle\n    const up = c >= o;\n    const color = esc(up ? s.upColor : s.downColor);\n    const px = xScale(x[i]);\n    const pTop = yScale(Math.max(o, c));\n    const h = Math.max(1, yScale(Math.min(o, c)) - pTop);\n    out.push(\n      `<line x1=\"${n(px)}\" y1=\"${n(yScale(yh[i]))}\" x2=\"${n(px)}\" y2=\"${n(yScale(yl[i]))}\" ` +\n        `stroke=\"${color}\" stroke-width=\"1\"/>`,\n      `<rect x=\"${n(px - bodyW / 2)}\" y=\"${n(pTop)}\" width=\"${n(bodyW)}\" height=\"${n(h)}\" ` +\n        `fill=\"${up ? esc(theme.bg) : color}\" stroke=\"${color}\" stroke-width=\"1\"/>`,\n    );\n  }\n  return out;\n}\n\n/** Build a complete, standalone SVG document string for the scene. */\nexport function buildSVG(scene: SvgScene): string {\n  const { width: w, height: h, margins: m, xScale, yScale } = scene;\n  const theme = scene.theme ?? lightTheme;\n  const left = m.left;\n  const right = w - m.right;\n  const top = m.top;\n  const bottom = h - m.bottom;\n  const cols = Math.max(1, Math.floor(right - left));\n  const buf = { min: new Float32Array(cols), max: new Float32Array(cols) };\n  const parts: string[] = [];\n\n  parts.push(bgRect(w, h, theme.bg));\n\n  // Grid.\n  let grid = '';\n  for (const v of scene.yTicks) {\n    const py = yScale(v);\n    if (py >= top - 1 && py <= bottom + 1) grid += `M${n(left)},${n(py)}H${n(right)}`;\n  }\n  for (const t of scene.xTicks) {\n    const px = xScale(t);\n    if (px >= left - 1 && px <= right + 1) grid += `M${n(px)},${n(top)}V${n(bottom)}`;\n  }\n  if (grid) parts.push(`<path d=\"${grid}\" stroke=\"${esc(theme.grid)}\" stroke-width=\"1\" fill=\"none\"/>`);\n  parts.push(\n    `<rect x=\"${n(left)}\" y=\"${n(top)}\" width=\"${n(right - left)}\" height=\"${n(bottom - top)}\" ` +\n      `fill=\"none\" stroke=\"${esc(theme.axis)}\" stroke-width=\"1\"/>`,\n  );\n\n  // Series envelopes (+ area fill); candles as marks or their dense envelope.\n  for (const s of scene.series) {\n    if (!s.visible) continue;\n    if (s.type === 'candle') {\n      parts.push(...candleParts(scene, s, cols, buf, theme));\n      continue;\n    }\n    const env = downsampleColumns(\n      scene.data.x, scene.data.y[s.index], scene.data.pyramids[s.index], scene.domain, cols, buf,\n    );\n    if (env.first < 0) continue;\n    if (s.type === 'area') {\n      const baseY = Math.max(top, Math.min(bottom, yScale(0)));\n      const a = areaPath(env, left, yScale, baseY);\n      if (a) parts.push(`<path d=\"${a}\" fill=\"${esc(s.color)}\" fill-opacity=\"${s.fillAlpha}\" stroke=\"none\"/>`);\n    }\n    const d = strokePath(env, left, yScale);\n    if (!d) continue;\n    const dash = s.dash.length ? ` stroke-dasharray=\"${s.dash.join(' ')}\"` : '';\n    parts.push(`<path d=\"${d}\" fill=\"none\" stroke=\"${esc(s.color)}\" stroke-width=\"${s.width}\"${dash}/>`);\n  }\n\n  // Tick labels + axis titles.\n  for (const v of scene.yTicks) {\n    const py = yScale(v);\n    if (py < top - 1 || py > bottom + 1) continue;\n    parts.push(text(left - 6, py + 3, esc(scene.formatY(v)), { fill: theme.tick, anchor: 'end' }));\n  }\n  for (const t of scene.xTicks) {\n    const px = xScale(t);\n    if (px < left - 1 || px > right + 1) continue;\n    parts.push(text(px, bottom + 16, esc(scene.formatX(t)), { fill: theme.tick, anchor: 'middle' }));\n  }\n  if (scene.yLabel) {\n    parts.push(text(left, top - 6, esc(scene.yLabel), { fill: theme.label, size: 10 }));\n  }\n  if (scene.xLabel) {\n    parts.push(text(right, bottom + 16, esc(scene.xLabel), { fill: theme.label, size: 10, anchor: 'end' }));\n  }\n\n  // Event markers (dots / rules), clipped to the plot, drawn over the series.\n  if (scene.annotations?.length) {\n    parts.push(...annotationParts(scene, theme));\n  }\n\n  return svgDocument({\n    width: w,\n    height: h,\n    title: scene.title,\n    desc: scene.desc,\n    body: parts.join(''),\n    extra: scene.summary === undefined ? undefined : embedSummary(scene.summary),\n  });\n}\n\n/** Event markers → SVG: a diamond on the nearest sample of a series, or a vertical rule. The\n *  diamond shape + label carry meaning beyond color (WCAG 1.4.1). */\nfunction annotationParts(scene: SvgScene, theme: SvgTheme): string[] {\n  const { margins: m, width: w, height: h, xScale } = scene;\n  const left = m.left;\n  const right = w - m.right;\n  const top = m.top;\n  const bottom = h - m.bottom;\n  const out: string[] = [];\n  for (const a of scene.annotations ?? []) {\n    const px = xScale(a.x);\n    if (px < left - 1 || px > right + 1) continue;\n    const color = esc(a.color);\n    if (a.kind === 'rule') {\n      out.push(\n        `<line x1=\"${n(px)}\" y1=\"${n(top)}\" x2=\"${n(px)}\" y2=\"${n(bottom)}\" stroke=\"${color}\" ` +\n          `stroke-width=\"1\" stroke-dasharray=\"4 3\"/>`,\n      );\n      if (a.showLabel) {\n        out.push(text(px, top + 9, esc(a.label), { fill: a.color, size: 10, anchor: 'middle' }));\n      }\n      continue;\n    }\n    // A point marker hides when its series is toggled off (parity with the live chart + announce).\n    const target = scene.series[a.seriesIndex];\n    if (target && !target.visible) continue;\n    const pt = annotationSample(scene.data, scene.series, a);\n    if (!pt) continue;\n    const py = scene.yScale(pt.y);\n    out.push(\n      `<path d=\"M${n(px)},${n(py - 5)}L${n(px + 5)},${n(py)}L${n(px)},${n(py + 5)}L${n(px - 5)},${n(py)}Z\" ` +\n        `fill=\"${color}\" stroke=\"${esc(theme.bg)}\" stroke-width=\"1.5\"/>`,\n    );\n    if (a.showLabel) {\n      out.push(text(px, py - 9, esc(a.label), { fill: a.color, size: 10, anchor: 'middle' }));\n    }\n  }\n  return out;\n}\n","/**\n * Base styles, injected once per document on first chart construction. Kept tiny and\n * self-contained so consumers don't need a separate CSS import. Theming is via a handful\n * of CSS custom properties (`--fc-*`); everything else is layout and the screen-reader\n * visually-hidden pattern.\n */\n\nconst CSS = `\n.fc-root{position:relative;display:flex;flex-direction:column;width:100%;height:100%;\n  font-family:var(--fc-font,system-ui,-apple-system,sans-serif);color:var(--fc-ink,#374151);\n  box-sizing:border-box}\n.fc-root *{box-sizing:border-box}\n.fc-plot{position:relative;flex:1 1 auto;min-height:0}\n.fc-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}\n.fc-ticks{position:absolute;inset:0;pointer-events:none}\n.fc-tick{position:absolute;font-size:.6875rem;color:var(--fc-tick-color,#4b5563);white-space:nowrap;\n  font-variant-numeric:tabular-nums}\n.fc-tick-x{transform:translateX(-50%);bottom:8px}\n.fc-tick-y{transform:translateY(-50%);left:8px}\n.fc-axis-title{position:absolute;font-size:.625rem;letter-spacing:.12em;text-transform:uppercase;\n  color:var(--fc-axis-title,#6b7280)}\n.fc-axis-title-x{bottom:8px;right:12px}\n.fc-axis-title-y{top:8px;left:8px}\n.fc-surface{position:absolute;outline:none;border-radius:6px;background:transparent}\n.fc-surface:focus-visible{box-shadow:0 0 0 2px var(--fc-focus,#2563eb)}\n.fc-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;\n  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}\n.fc-readout{position:absolute;z-index:5;pointer-events:none;transform:translate(-50%,-120%);\n  background:var(--fc-readout-bg,#111827);color:var(--fc-readout-ink,#f9fafb);\n  border:1px solid var(--fc-readout-border,rgba(255,255,255,.15));border-radius:8px;padding:6px 9px;\n  font-size:.75rem;min-width:118px;box-shadow:0 8px 24px rgba(0,0,0,.35);opacity:0;\n  transition:opacity .08s}\n.fc-readout.fc-show{opacity:1}\n/* attachReadout() variant for static-SVG charts: fixed to the viewport and positioned by JS\n   (left/top are the top-left corner, so no centering transform), clamped + edge-flipped there. */\n.fc-readout-fixed{position:fixed;transform:none}\n.fc-readout-series{display:flex;align-items:center;gap:6px;font-weight:600;margin-bottom:2px}\n.fc-readout-swatch{width:9px;height:9px;border-radius:2px;flex:none}\n.fc-readout-val{opacity:.85;font-variant-numeric:tabular-nums}\n.fc-legend{padding:8px 4px}\n.fc-legend ul{display:flex;flex-wrap:wrap;gap:6px;list-style:none;margin:0;padding:0}\n.fc-legend li{margin:0}\n.fc-legend button{display:inline-flex;align-items:center;gap:7px;cursor:pointer;padding:5px 10px;\n  min-height:24px;min-width:24px;line-height:1.1;\n  border-radius:7px;border:1px solid var(--fc-legend-border,rgba(0,0,0,.15));\n  background:var(--fc-legend-bg,transparent);color:inherit;font:inherit;font-size:.78rem;\n  font-weight:600}\n.fc-legend button:hover{border-color:var(--fc-legend-border-hover,rgba(0,0,0,.4))}\n/* \"Hidden\" state is conveyed by aria-pressed (to AT), a strikethrough name and a dimmed\n   swatch (to sighted users) — never by reducing text opacity, which would drop the label\n   below the 4.5:1 contrast minimum (WCAG 1.4.3). */\n.fc-legend button[aria-pressed=\"false\"] .fc-swatch{opacity:.35}\n.fc-legend button[aria-pressed=\"false\"] .fc-legend-name{text-decoration:line-through}\n.fc-swatch{width:18px;height:10px;flex:none;overflow:visible}\n.fc-legend-name{white-space:nowrap}\n.fc-legend-state{font-size:.625rem;font-weight:500}\n/* Single-pointer pan affordance (WCAG 2.5.7) — real buttons, >=24x24 target (2.5.8). */\n.fc-pagers{position:absolute;right:10px;bottom:8px;display:flex;gap:6px;z-index:6}\n.fc-pager{min-width:28px;min-height:28px;display:inline-flex;align-items:center;justify-content:center;\n  cursor:pointer;border:1px solid var(--fc-legend-border,rgba(0,0,0,.15));border-radius:7px;\n  background:var(--fc-legend-bg,rgba(127,127,127,.10));color:inherit;font:inherit;font-size:1rem;\n  line-height:1;opacity:.55;transition:opacity .1s}\n.fc-pager:hover,.fc-pager:focus-visible{opacity:1}\n.fc-pager:disabled{opacity:.2;cursor:default}\n/* Opt-in CSV download (an always-available alternative format; pairs with the hidden table). */\n.fc-export{position:absolute;left:10px;bottom:8px;z-index:6;min-height:28px;display:inline-flex;\n  align-items:center;cursor:pointer;padding:0 9px;\n  border:1px solid var(--fc-legend-border,rgba(0,0,0,.15));border-radius:7px;\n  background:var(--fc-legend-bg,rgba(127,127,127,.10));color:inherit;font:inherit;font-size:.72rem;\n  font-weight:600;line-height:1;opacity:.55;transition:opacity .1s}\n.fc-export:hover,.fc-export:focus-visible{opacity:1}\n@media (prefers-reduced-motion:reduce){.fc-readout{transition:none}}\n@media (prefers-contrast:more){\n  .fc-tick{color:var(--fc-tick-color,#1f2937)}\n  .fc-legend button{border-color:var(--fc-legend-border-hover,#000)}\n  .fc-surface:focus-visible{outline:2px solid var(--fc-focus,#2563eb);outline-offset:1px}\n}\n/* Windows High Contrast / forced-colors ignores box-shadow, so the box-shadow focus ring\n   vanishes there. Provide a real outline (which forced-colors honors) using a system color. */\n@media (forced-colors:active){\n  .fc-surface:focus-visible{outline:2px solid Highlight;outline-offset:1px}\n}\n`;\n\n/** Inject the stylesheet once per document. Idempotent. */\nexport function injectStyles(doc: Document = document): void {\n  if (doc.getElementById('fc-styles')) return;\n  const style = doc.createElement('style');\n  style.id = 'fc-styles';\n  style.textContent = CSS;\n  (doc.head ?? doc.documentElement).append(style);\n}\n","/**\n * The hover readout box — the dark, rounded tooltip with a color swatch and a tabular value.\n *\n * Factored out of `fchart.ts` so the interactive canvas chart and the static-SVG {@link\n * attachReadout} helper build the SAME markup and share the `.fc-readout*` CSS (`a11y/styles.ts`):\n * one look, styled by the same `--fc-readout-*` custom properties, instead of every static-SVG\n * consumer re-rolling its own tooltip.\n */\n\nexport interface ReadoutEls {\n  el: HTMLElement;\n  swatch: HTMLElement;\n  name: HTMLElement;\n  value: HTMLElement;\n}\n\n/** Build the readout DOM (detached). The caller appends it and toggles the `.fc-show` class. */\nexport function buildReadout(doc: Document): ReadoutEls {\n  const el = doc.createElement('div');\n  el.className = 'fc-readout';\n  el.setAttribute('aria-hidden', 'true');\n  const series = doc.createElement('div');\n  series.className = 'fc-readout-series';\n  const swatch = doc.createElement('span');\n  swatch.className = 'fc-readout-swatch';\n  const name = doc.createElement('span');\n  series.append(swatch, name);\n  const value = doc.createElement('div');\n  value.className = 'fc-readout-val';\n  el.append(series, value);\n  return { el, swatch, name, value };\n}\n","/**\n * Polite ARIA live region — the channel through which cursor moves and hover are\n * announced to screen readers. Visually hidden, but present in the accessibility tree.\n */\n\nexport class LiveRegion {\n  readonly el: HTMLElement;\n  private last = '';\n\n  constructor(doc: Document = document) {\n    this.el = doc.createElement('span');\n    this.el.className = 'fc-sr-only';\n    this.el.setAttribute('aria-live', 'polite');\n    this.el.setAttribute('aria-atomic', 'true');\n  }\n\n  /** Announce `text`. Re-announces even when unchanged by nudging the content. */\n  announce(text: string): void {\n    // Screen readers ignore identical successive text; toggle a trailing space to force it.\n    this.el.textContent = text === this.last ? `${text} ` : text;\n    this.last = text;\n  }\n\n  clear(): void {\n    this.el.textContent = '';\n    this.last = '';\n  }\n\n  destroy(): void {\n    this.el.remove();\n  }\n}\n","/**\n * DOM axis ticks — real positioned text over the canvas.\n *\n * Because these are real text nodes (not canvas pixels), they are in the accessibility\n * tree, findable with Ctrl+F, selectable, and translatable. They are rebuilt only when the\n * domain or size changes (coalesced), never every frame.\n */\nimport type { LinearScale } from '../core/scales.ts';\nimport type { Margins } from '../core/model.ts';\n\nexport interface TickUpdate {\n  xTicks: readonly number[];\n  yTicks: readonly number[];\n  xScale: LinearScale;\n  yScale: LinearScale;\n  formatX: (v: number) => string;\n  formatY: (v: number) => string;\n  margins: Margins;\n  width: number;\n  height: number;\n}\n\nexport class AxisTicks {\n  readonly el: HTMLElement;\n  private readonly xLayer: HTMLElement;\n  private readonly yLayer: HTMLElement;\n  private readonly doc: Document;\n  private xTitle: HTMLElement | null = null;\n  private yTitle: HTMLElement | null = null;\n\n  constructor(doc: Document = document, xLabel?: string, yLabel?: string) {\n    this.doc = doc;\n    this.el = doc.createElement('div');\n    this.el.className = 'fc-ticks';\n    this.el.setAttribute('aria-hidden', 'false');\n\n    this.yLayer = doc.createElement('div');\n    this.yLayer.className = 'fc-ticks-y';\n    this.xLayer = doc.createElement('div');\n    this.xLayer.className = 'fc-ticks-x';\n    this.el.append(this.yLayer, this.xLayer);\n\n    this.setLabels(xLabel, yLabel);\n  }\n\n  /** Replace the axis titles (FChart.update() calls this when xLabel/yLabel change). */\n  setLabels(xLabel?: string, yLabel?: string): void {\n    for (const title of this.el.querySelectorAll('.fc-axis-title')) title.remove();\n    this.yTitle = yLabel ? this.axisTitle('y', yLabel) : null;\n    this.xTitle = xLabel ? this.axisTitle('x', xLabel) : null;\n    if (this.yTitle) this.el.append(this.yTitle);\n    if (this.xTitle) this.el.append(this.xTitle);\n  }\n\n  private axisTitle(axis: 'x' | 'y', text: string): HTMLElement {\n    const span = this.doc.createElement('span');\n    span.className = `fc-axis-title fc-axis-title-${axis}`;\n    span.textContent = text;\n    return span;\n  }\n\n  private tick(axis: 'x' | 'y', text: string, pos: number): HTMLElement {\n    const span = this.doc.createElement('span');\n    span.className = `fc-tick fc-tick-${axis}`;\n    span.textContent = text;\n    if (axis === 'x') span.style.left = `${pos}px`;\n    else span.style.top = `${pos}px`;\n    return span;\n  }\n\n  /** Rebuild tick labels. Cheap (a dozen nodes); call only on domain/size change. */\n  update(u: TickUpdate): void {\n    const m = u.margins;\n    const left = m.left;\n    const right = u.width - m.right;\n    const top = m.top;\n    const bottom = u.height - m.bottom;\n\n    this.yLayer.replaceChildren(\n      ...u.yTicks\n        .filter((v) => {\n          const py = u.yScale(v);\n          return py >= top - 1 && py <= bottom + 1;\n        })\n        .map((v) => this.tick('y', u.formatY(v), u.yScale(v))),\n    );\n    this.xLayer.replaceChildren(\n      ...u.xTicks\n        .filter((t) => {\n          const px = u.xScale(t);\n          return px >= left - 1 && px <= right + 1;\n        })\n        .map((t) => this.tick('x', u.formatX(t), u.xScale(t))),\n    );\n    this.pruneTitleCollisions();\n  }\n\n  /**\n   * Drop tick labels that would run into an axis title — the x title shares the bottom row\n   * with the x labels (and the y title the left gutter), so a tick landing at the plot edge\n   * would otherwise overlap it. Measured, not estimated, so it holds for localized titles.\n   * Runs only on tick rebuilds (domain/size change), never per frame.\n   */\n  private pruneTitleCollisions(): void {\n    const xTitle = this.xTitle?.isConnected ? this.xTitle : null;\n    const yTitle = this.yTitle?.isConnected ? this.yTitle : null;\n    if (!xTitle && !yTitle) return;\n    // Make titles measurable first (they may be hidden from a previous cramped layout), then\n    // do all layout reads before any removal: interleaving a removal between offset reads\n    // would force one reflow per pruned label, and this runs every streamed frame while the\n    // view follows the live tail. One write phase + one read pass + one write phase.\n    if (xTitle) xTitle.style.display = '';\n    if (yTitle) yTitle.style.display = '';\n    const doomed: HTMLElement[] = [];\n    if (xTitle) this.collectCollisions(xTitle, 'x', doomed);\n    if (yTitle) this.collectCollisions(yTitle, 'y', doomed);\n    for (const span of doomed) span.remove();\n  }\n\n  /**\n   * Collect tick labels colliding with `title` into `doomed` — unless that would leave fewer\n   * than two labels on the axis. In that cramped case the data labels win: hide the title\n   * instead (values are what 1.4.10 reflow must keep usable; the axis name stays available\n   * programmatically via the chart's accessible description and table headers).\n   */\n  private collectCollisions(title: HTMLElement, axis: 'x' | 'y', doomed: HTMLElement[]): void {\n    const layer = axis === 'x' ? this.xLayer : this.yLayer;\n    // Tick spans are centered via translate(-50%): offsetLeft/offsetTop is the center.\n    const limit =\n      axis === 'x' ? title.offsetLeft - 6 : title.offsetTop + title.offsetHeight + 4;\n    const colliding: HTMLElement[] = [];\n    for (const span of layer.children as HTMLCollectionOf<HTMLElement>) {\n      const hits =\n        axis === 'x'\n          ? span.offsetLeft + span.offsetWidth / 2 > limit\n          : span.offsetTop - span.offsetHeight / 2 < limit;\n      if (hits) colliding.push(span);\n    }\n    if (layer.children.length - colliding.length >= 2) doomed.push(...colliding);\n    else title.style.display = 'none';\n  }\n\n  destroy(): void {\n    this.el.remove();\n  }\n}\n","/**\n * Accessible legend — one real `<button aria-pressed>` per series. Toggling a button\n * shows/hides its series. Real buttons mean keyboard focus, Enter/Space activation, and\n * correct screen-reader state come for free.\n */\nimport type { ResolvedSeries } from '../core/model.ts';\nimport type { FChartStrings } from './strings.ts';\n\ntype LegendStrings = Pick<FChartStrings, 'legendGroup' | 'shown' | 'hidden'>;\n\nexport class Legend {\n  readonly el: HTMLElement;\n  private readonly list: HTMLUListElement;\n  private readonly doc: Document;\n  private readonly onToggle: (index: number) => void;\n  private readonly strings: LegendStrings;\n  private buttons: HTMLButtonElement[] = [];\n\n  constructor(\n    series: readonly ResolvedSeries[],\n    onToggle: (index: number) => void,\n    strings: LegendStrings,\n    doc: Document = document,\n  ) {\n    this.doc = doc;\n    this.onToggle = onToggle;\n    this.strings = strings;\n    this.el = doc.createElement('div');\n    this.el.className = 'fc-legend';\n    this.el.setAttribute('role', 'group');\n    this.el.setAttribute('aria-label', strings.legendGroup);\n    this.list = doc.createElement('ul');\n    this.el.append(this.list);\n    this.build(series);\n  }\n\n  private build(series: readonly ResolvedSeries[]): void {\n    this.list.replaceChildren();\n    this.buttons = series.map((s, i) => {\n      const li = this.doc.createElement('li');\n      const button = this.doc.createElement('button');\n      button.type = 'button';\n      // Positional, not s.index: a candle series spans 4 y-slots, so slot offsets diverge\n      // from positions in `series` — and toggleSeries addresses by position.\n      button.dataset.series = String(i);\n      button.addEventListener('click', () => this.onToggle(i));\n\n      const swatch = this.swatch(s);\n\n      const name = this.doc.createElement('span');\n      name.className = 'fc-legend-name';\n      name.textContent = s.name;\n\n      const state = this.doc.createElement('span');\n      state.className = 'fc-legend-state';\n      // Visible-only state cue: aria-pressed already conveys shown/hidden to AT, so keeping\n      // this out of the accessible name leaves the button's name as the stable series name.\n      state.setAttribute('aria-hidden', 'true');\n\n      button.append(swatch, name, state);\n      li.append(button);\n      this.list.append(li);\n      return button;\n    });\n    this.sync(series);\n  }\n\n  /**\n   * Inline-SVG swatch that mirrors the mark: a line with the series' dash pattern (or a filled\n   * rect for area). This makes the legend a colour-free mapping too — series differ by dash, not\n   * only hue (WCAG 1.4.1) — and exactly matches what the canvas draws.\n   */\n  private swatch(s: ResolvedSeries): SVGElement {\n    const NS = 'http://www.w3.org/2000/svg';\n    const svg = this.doc.createElementNS(NS, 'svg');\n    svg.setAttribute('class', 'fc-swatch');\n    svg.setAttribute('viewBox', '0 0 18 10');\n    svg.setAttribute('aria-hidden', 'true');\n    if (s.type === 'candle') {\n      // Two mini candles — hollow up, filled down — mirroring the on-canvas encoding, where\n      // fill (not only hue) carries direction (WCAG 1.4.1).\n      const candle = (cx: number, color: string, filled: boolean): void => {\n        const wick = this.doc.createElementNS(NS, 'line');\n        for (const [k, v] of [['x1', String(cx)], ['y1', '0'], ['x2', String(cx)], ['y2', '10']]) {\n          wick.setAttribute(k, v);\n        }\n        wick.setAttribute('stroke', color);\n        const body = this.doc.createElementNS(NS, 'rect');\n        for (const [k, v] of [['x', String(cx - 2.5)], ['y', '2.5'], ['width', '5'], ['height', '5']]) {\n          body.setAttribute(k, v);\n        }\n        body.setAttribute('fill', filled ? color : 'none');\n        body.setAttribute('stroke', color);\n        body.setAttribute('stroke-width', '1.5');\n        svg.append(wick, body);\n      };\n      candle(5, s.upColor, false);\n      candle(13, s.downColor, true);\n    } else if (s.type === 'area') {\n      const rect = this.doc.createElementNS(NS, 'rect');\n      for (const [k, v] of [['x', '1'], ['y', '2'], ['width', '16'], ['height', '7'], ['rx', '1']]) {\n        rect.setAttribute(k, v);\n      }\n      rect.setAttribute('fill', s.color);\n      rect.setAttribute('fill-opacity', String(Math.max(0.35, s.fillAlpha)));\n      rect.setAttribute('stroke', s.color);\n      rect.setAttribute('stroke-width', '1.5');\n      // Dash the border too, so area series carry the non-colour channel just like lines —\n      // otherwise two area series would be distinguishable by colour alone (WCAG 1.4.1).\n      if (s.dash.length) rect.setAttribute('stroke-dasharray', s.dash.join(' '));\n      svg.append(rect);\n    } else {\n      const line = this.doc.createElementNS(NS, 'line');\n      for (const [k, v] of [['x1', '1'], ['y1', '5'], ['x2', '17'], ['y2', '5']]) line.setAttribute(k, v);\n      line.setAttribute('stroke', s.color);\n      line.setAttribute('stroke-width', '2');\n      if (s.dash.length) line.setAttribute('stroke-dasharray', s.dash.join(' '));\n      svg.append(line);\n    }\n    return svg;\n  }\n\n  /** Reflect current visibility into aria-pressed and the visible state label. */\n  update(series: readonly ResolvedSeries[]): void {\n    if (series.length !== this.buttons.length) {\n      this.build(series);\n      return;\n    }\n    this.sync(series);\n  }\n\n  private sync(series: readonly ResolvedSeries[]): void {\n    series.forEach((s, i) => {\n      const button = this.buttons[i];\n      button.setAttribute('aria-pressed', String(s.visible));\n      const state = button.querySelector('.fc-legend-state');\n      if (state) state.textContent = s.visible ? this.strings.shown : this.strings.hidden;\n    });\n  }\n\n  destroy(): void {\n    this.el.remove();\n  }\n}\n","/**\n * Pan pagers — two real `<button>`s that step the visible window earlier/later with a single\n * pointer click (no dragging). This is the single-pointer, non-dragging alternative to drag-pan\n * that WCAG 2.5.7 requires; being real buttons, they are keyboard- and screen-reader-operable\n * too. Shown only when the view is zoomed in (panning has an effect).\n */\nimport type { FChartStrings } from './strings.ts';\n\ntype PagerStrings = Pick<FChartStrings, 'pagerPrev' | 'pagerNext'>;\n\nexport class Pagers {\n  readonly el: HTMLElement;\n  private readonly prev: HTMLButtonElement;\n  private readonly next: HTMLButtonElement;\n\n  constructor(onPan: (dir: -1 | 1) => void, strings: PagerStrings, doc: Document = document) {\n    this.el = doc.createElement('div');\n    this.el.className = 'fc-pagers';\n    this.el.style.display = 'none'; // hidden until there's something to pan to\n    const mk = (glyph: string, label: string, dir: -1 | 1): HTMLButtonElement => {\n      const b = doc.createElement('button');\n      b.type = 'button';\n      b.className = 'fc-pager';\n      b.textContent = glyph;\n      b.setAttribute('aria-label', label);\n      b.addEventListener('click', () => onPan(dir));\n      return b;\n    };\n    this.prev = mk('‹', strings.pagerPrev, -1); // ‹\n    this.next = mk('›', strings.pagerNext, 1); // ›\n    this.el.append(this.prev, this.next);\n  }\n\n  /** Reflect pannability: hide when the full domain is shown; disable the end you're already at. */\n  update(atStart: boolean, atEnd: boolean): void {\n    this.el.style.display = atStart && atEnd ? 'none' : 'flex';\n    this.prev.disabled = atStart;\n    this.next.disabled = atEnd;\n  }\n\n  destroy(): void {\n    this.el.remove();\n  }\n}\n","/**\n * Sonification — an audible channel for the focused data point (the EU data-visualisation guide\n * lists \"sonification\" as a non-visual technique). As the keyboard cursor moves, a short tone\n * sounds whose pitch maps the value within its series' range, so a blind user can *hear* the\n * shape of the data, not only read it. Opt-in (`options.sonify`); zero dependencies (Web Audio).\n *\n * The AudioContext is created lazily on first use — browsers require a user gesture (the keypress\n * that moves the cursor qualifies) — and closed on destroy.\n */\n\ntype AudioCtor = typeof AudioContext;\n\nexport class Sonifier {\n  private ctx: AudioContext | null = null;\n  private readonly Ctor: AudioCtor | undefined;\n\n  constructor(view: Window) {\n    const w = view as unknown as { AudioContext?: AudioCtor; webkitAudioContext?: AudioCtor };\n    this.Ctor = w.AudioContext ?? w.webkitAudioContext;\n  }\n\n  /**\n   * Play a short tone for `value` within [min, max] — pitch rises with the value across ~2\n   * octaves (220–880 Hz). No-op if Web Audio is unavailable or the range is degenerate.\n   */\n  play(value: number, min: number, max: number): void {\n    if (!this.Ctor) return;\n    if (!this.ctx) {\n      try {\n        this.ctx = new this.Ctor();\n      } catch {\n        return;\n      }\n    }\n    const ctx = this.ctx;\n    if (ctx.state === 'suspended') void ctx.resume();\n    const span = max - min;\n    const norm = span > 0 ? Math.min(1, Math.max(0, (value - min) / span)) : 0.5;\n    const freq = 220 * 2 ** (norm * 2); // 220 Hz (min) → 880 Hz (max)\n    const now = ctx.currentTime;\n    const osc = ctx.createOscillator();\n    const gain = ctx.createGain();\n    osc.type = 'sine';\n    osc.frequency.setValueAtTime(freq, now);\n    // Short pluck envelope so rapid cursor movement doesn't blur into a drone.\n    gain.gain.setValueAtTime(0.0001, now);\n    gain.gain.exponentialRampToValueAtTime(0.14, now + 0.012);\n    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.16);\n    osc.connect(gain).connect(ctx.destination);\n    osc.start(now);\n    osc.stop(now + 0.18);\n  }\n\n  destroy(): void {\n    void this.ctx?.close();\n    this.ctx = null;\n  }\n}\n","/**\n * Localizable UI strings — every fixed phrase the accessibility layer emits.\n *\n * The library's own prose (keyboard help, legend label, data-summary sentence, table caption)\n * is English by default. In a non-English host document those would be untagged\n * different-language passages (WCAG 3.1.2 Language of Parts). Because each phrase interleaves\n * author content (series names, axis labels, formatted numbers) with connective prose, the\n * correct fix is to let the integrator supply translations that match their page — not to wrap\n * mixed subtrees in a `lang` attribute. Strings are `{token}` templates filled by `format`.\n */\n\nexport interface FChartStrings {\n  /** Accessible name for the legend button group. No tokens. */\n  legendGroup: string;\n  /** Per-series visibility state words (visible-only; aria-pressed carries state for AT). */\n  shown: string;\n  hidden: string;\n  /** Keyboard operating instructions woven into the chart's accessible name. No tokens. */\n  keyboardHelp: string;\n  /** Event-marker key instructions, appended to the accessible name only when the chart has\n   *  annotations. No tokens. */\n  eventKeysHelp: string;\n  /** Word appended to an event-marker announcement when it becomes pinned/selected. No tokens. */\n  selected: string;\n  /** Chart accessible name. Tokens: `{name}` `{series}` `{points}` `{help}`. */\n  chartName: string;\n  /** Data-table caption. Tokens: `{caption}` `{series}` `{rows}`. */\n  tableCaption: string;\n  /** One-line summary, empty dataset. Tokens: `{label}`. */\n  summaryNoData: string;\n  /** One-line summary, all series hidden. Tokens: `{label}` `{points}`. */\n  summaryAllHidden: string;\n  /** One-line summary sentence. Tokens: `{label}` `{points}` `{span}` `{parts}`. */\n  summaryLine: string;\n  /** Per-series clause within the summary. Tokens: `{name}` `{min}` `{max}` `{last}` `{dir}`. */\n  summaryPart: string;\n  /** Event-annotations clause appended to the summary. Tokens: `{count}` `{labels}`. */\n  summaryEvents: string;\n  /** x-range phrase within the summary. Tokens: `{start}` `{end}`. */\n  summarySpan: string;\n  /** Direction phrases. `{pct}` for up/down; flat has no token. */\n  trendUp: string;\n  trendDown: string;\n  trendFlat: string;\n  /** Accessible labels for the single-pointer pan buttons. No tokens. */\n  pagerPrev: string;\n  pagerNext: string;\n  /** OHLC value words for candle series (announcements, table headers). No tokens. */\n  open: string;\n  high: string;\n  low: string;\n  close: string;\n  /** Accessible label for the opt-in CSV download control. No tokens. */\n  exportCsv: string;\n}\n\nexport const DEFAULT_STRINGS: FChartStrings = {\n  legendGroup: 'Series — activate to show or hide',\n  shown: 'shown',\n  hidden: 'hidden',\n  keyboardHelp:\n    'Left and right arrows move between samples; up and down switch series; ' +\n    'Home and End jump to the ends; hold Shift for fine steps. ' +\n    'Plus and minus zoom; Escape clears the cursor. ' +\n    'A sampled data table follows for screen-reader review.',\n  eventKeysHelp:\n    'Right and left bracket keys step between event markers; Enter selects the focused marker.',\n  selected: 'selected',\n  chartName: '{name}. {series} series, {points} points each. {help}',\n  tableCaption: '{caption} — {series} series, {rows} sampled rows across the visible range.',\n  summaryNoData: '{label}: no data.',\n  summaryAllHidden: '{label}: {points} points per series, all series hidden.',\n  summaryLine: '{label}: {points} points per series from {span}. {parts}.',\n  summaryPart: '{name} ranges {min} to {max}, now {last} ({dir})',\n  summaryEvents: '{count} events: {labels}',\n  summarySpan: '{start} to {end}',\n  trendUp: 'up {pct}%',\n  trendDown: 'down {pct}%',\n  trendFlat: 'flat',\n  pagerPrev: 'Pan to earlier data',\n  pagerNext: 'Pan to later data',\n  open: 'open',\n  high: 'high',\n  low: 'low',\n  close: 'close',\n  exportCsv: 'Download data (CSV)',\n};\n\n/** Fill `{token}` placeholders from `vars`. Unknown tokens are left intact (so typos are visible). */\nexport function format(template: string, vars: Record<string, string | number>): string {\n  return template.replace(/\\{(\\w+)\\}/g, (whole, key: string) =>\n    key in vars ? String(vars[key]) : whole,\n  );\n}\n\n/** Merge user overrides onto the English defaults. */\nexport function resolveStrings(overrides?: Partial<FChartStrings>): FChartStrings {\n  return overrides ? { ...DEFAULT_STRINGS, ...overrides } : DEFAULT_STRINGS;\n}\n","/**\n * Visually-hidden data table — the text alternative for the chart.\n *\n * A `<canvas>` is opaque to assistive tech, so we mirror the (downsampled) visible data as\n * a real `<table>` in the accessibility tree: caption, column headers, row headers. This\n * gives screen-reader users a structured read of the data and satisfies \"non-text content\n * has a text alternative\". Rebuilt on data/visibility/domain change, never per frame.\n */\nimport { lowerBound } from '../core/downsample.ts';\nimport type { ChartData, ResolvedSeries } from '../core/model.ts';\nimport { DEFAULT_STRINGS, format } from './strings.ts';\n\nexport interface TableUpdate {\n  data: ChartData;\n  series: readonly ResolvedSeries[];\n  domain: readonly [number, number];\n  formatX: (v: number) => string;\n  formatY: (v: number) => string;\n  caption: string;\n  /** Caption template with `{caption}` `{series}` `{rows}` tokens. Defaults to the English string. */\n  captionTemplate?: string;\n  /** Header for the x (independent-variable) column. Defaults to 'x' when unset. */\n  xLabel?: string;\n  /** Max sampled rows (the table summarizes, it does not dump all N). Default 40. */\n  maxRows?: number;\n  /** Localized OHLC words for candle column headers. Defaults to the English strings. */\n  ohlc?: Pick<typeof DEFAULT_STRINGS, 'open' | 'high' | 'low' | 'close'>;\n}\n\n/** Evenly spaced sample indices spanning the visible range [i0, i1] inclusive. */\nfunction sampleIndices(i0: number, i1: number, maxRows: number): number[] {\n  const count = i1 - i0 + 1;\n  if (count <= 0) return [];\n  if (count <= maxRows) {\n    const out: number[] = [];\n    for (let i = i0; i <= i1; i++) out.push(i);\n    return out;\n  }\n  const out: number[] = [];\n  for (let r = 0; r < maxRows; r++) {\n    out.push(i0 + Math.round((r / (maxRows - 1)) * (count - 1)));\n  }\n  return out;\n}\n\nexport class TableAlt {\n  readonly el: HTMLElement;\n  private readonly table: HTMLTableElement;\n  private readonly doc: Document;\n\n  constructor(doc: Document = document) {\n    this.doc = doc;\n    this.el = doc.createElement('div');\n    this.el.className = 'fc-sr-only fc-table-alt';\n    this.table = doc.createElement('table');\n    this.el.append(this.table);\n  }\n\n  update(u: TableUpdate): void {\n    const maxRows = u.maxRows ?? 40;\n    const visible = u.series.filter((s) => s.visible);\n    const [d0, d1] = u.domain;\n    const i0 = u.data.n === 0 ? 0 : Math.max(0, lowerBound(u.data.x, d0) - 1);\n    const i1 = u.data.n === 0 ? -1 : Math.min(u.data.n - 1, lowerBound(u.data.x, d1));\n    const rows = sampleIndices(i0, i1, maxRows);\n\n    const frag = this.doc.createDocumentFragment();\n    frag.append(this.buildCaption(u, visible.length, rows.length));\n    frag.append(this.buildHead(u, visible, u.xLabel ?? 'x'));\n    frag.append(this.buildBody(u, visible, rows));\n\n    this.table.replaceChildren(frag);\n  }\n\n  private buildCaption(u: TableUpdate, seriesCount: number, rowCount: number): HTMLElement {\n    const caption = this.doc.createElement('caption');\n    caption.textContent = format(u.captionTemplate ?? DEFAULT_STRINGS.tableCaption, {\n      caption: u.caption,\n      series: seriesCount,\n      rows: rowCount,\n    });\n    return caption;\n  }\n\n  private buildHead(u: TableUpdate, visible: readonly ResolvedSeries[], xHeader: string): HTMLElement {\n    const ohlc = u.ohlc ?? DEFAULT_STRINGS;\n    const thead = this.doc.createElement('thead');\n    const tr = this.doc.createElement('tr');\n    tr.append(this.th(xHeader));\n    for (const s of visible) {\n      if (s.type === 'candle') {\n        // One column per OHLC component so the table stays a faithful text alternative.\n        for (const part of [ohlc.open, ohlc.high, ohlc.low, ohlc.close]) {\n          tr.append(this.th(`${s.name} ${part}`));\n        }\n      } else {\n        tr.append(this.th(s.name));\n      }\n    }\n    thead.append(tr);\n    return thead;\n  }\n\n  private buildBody(\n    u: TableUpdate,\n    visible: readonly ResolvedSeries[],\n    rows: readonly number[],\n  ): HTMLElement {\n    const tbody = this.doc.createElement('tbody');\n    for (const i of rows) {\n      const tr = this.doc.createElement('tr');\n      const rowHeader = this.th(u.formatX(u.data.x[i]));\n      rowHeader.scope = 'row';\n      tr.append(rowHeader);\n      for (const s of visible) {\n        for (let slot = s.index; slot < s.index + s.slots; slot++) {\n          const td = this.doc.createElement('td');\n          td.textContent = u.formatY(u.data.y[slot][i]);\n          tr.append(td);\n        }\n      }\n      tbody.append(tr);\n    }\n    return tbody;\n  }\n\n  private th(text: string): HTMLTableCellElement {\n    const th = this.doc.createElement('th');\n    th.scope = 'col';\n    th.textContent = text;\n    return th;\n  }\n\n  destroy(): void {\n    this.el.remove();\n  }\n}\n","/**\n * Machine-readable chart summary — the bridge from \"accessible\" to \"agent-readable\".\n *\n * The same data that powers the screen-reader layer is distilled into a structured\n * `ChartSummary` (exposed via the public API and embedded as JSON in the DOM) and a\n * one-line natural-language `describeSummary` (used for `aria-describedby`). Where a canvas\n * chart is opaque pixels, this gives assistive tech, AI agents, and crawlers the actual\n * values and trend — pure functions, no DOM, unit-tested.\n */\nimport type { ChartData, ResolvedAnnotation, ResolvedSeries } from '../core/model.ts';\nimport { DEFAULT_STRINGS, format, type FChartStrings } from './strings.ts';\n\nexport type Trend = 'up' | 'down' | 'flat';\n\nexport interface SeriesSummary {\n  name: string;\n  visible: boolean;\n  min: number;\n  max: number;\n  first: number;\n  last: number;\n  mean: number;\n  /** last − first. */\n  changeAbs: number;\n  /** Percent change of last vs first (range-relative when first is 0). */\n  changePct: number;\n  trend: Trend;\n}\n\n/** One event marker, in the machine-readable summary. */\nexport interface AnnotationSummary {\n  x: number;\n  label: string;\n  kind: 'point' | 'rule';\n}\n\nexport interface ChartSummary {\n  label: string;\n  /** Points per series. */\n  points: number;\n  xStart: number;\n  xEnd: number;\n  series: SeriesSummary[];\n  /** Event markers on the series, when any are configured. */\n  annotations?: AnnotationSummary[];\n}\n\nconst EMPTY_STAT = { min: 0, max: 0, first: 0, last: 0, mean: 0 };\n\n/**\n * Direction of travel, derived from the SAME percentage that `changePct` reports (a <1%\n * move counts as flat) so the structured `trend` field and the reported `changePct` can\n * never contradict each other. Exported so other renderers (e.g. the sparkline) classify\n * direction identically.\n */\nexport function trendOf(changePct: number): Trend {\n  if (changePct > 1) return 'up';\n  if (changePct < -1) return 'down';\n  return 'flat';\n}\n\n/** Distill a dataset + its resolved series into a structured summary. Pure. */\nexport function buildSummary(\n  data: ChartData,\n  series: readonly ResolvedSeries[],\n  label: string,\n  annotations: readonly ResolvedAnnotation[] = [],\n): ChartSummary {\n  const [xStart, xEnd] = data.xExtent();\n  return {\n    label,\n    points: data.n,\n    xStart,\n    xEnd,\n    annotations:\n      annotations.length > 0\n        ? annotations.map((a) => ({ x: a.x, label: a.label, kind: a.kind }))\n        : undefined,\n    series: series.map((s) => {\n      // A candle series spans 4 stat slots (OHLC): range comes from the true traded extremes\n      // (low.min / high.max); first/last/mean/trend follow the close.\n      const st =\n        s.type === 'candle'\n          ? {\n              ...(data.stats[s.index + 3] ?? EMPTY_STAT),\n              min: (data.stats[s.index + 2] ?? EMPTY_STAT).min,\n              max: (data.stats[s.index + 1] ?? EMPTY_STAT).max,\n            }\n          : (data.stats[s.index] ?? EMPTY_STAT);\n      const range = st.max - st.min;\n      const changeAbs = st.last - st.first;\n      // Percent change vs the starting value; fall back to range-relative when first is 0.\n      let changePct = 0;\n      if (st.first !== 0) changePct = (changeAbs / Math.abs(st.first)) * 100;\n      else if (range > 0) changePct = (changeAbs / range) * 100;\n      return {\n        name: s.name,\n        visible: s.visible,\n        min: st.min,\n        max: st.max,\n        first: st.first,\n        last: st.last,\n        mean: st.mean,\n        changeAbs,\n        changePct,\n        trend: trendOf(changePct),\n      };\n    }),\n  };\n}\n\n/** One-line natural-language summary for `aria-describedby` and \"what the agent reads\" UIs. */\nexport function describeSummary(\n  summary: ChartSummary,\n  fmtX: (v: number) => string,\n  fmtY: (v: number) => string,\n  strings: FChartStrings = DEFAULT_STRINGS,\n): string {\n  const label = summary.label;\n  if (summary.points === 0 || summary.series.length === 0) {\n    return format(strings.summaryNoData, { label });\n  }\n  const shown = summary.series.filter((s) => s.visible);\n  const points = summary.points.toLocaleString();\n  if (shown.length === 0) return format(strings.summaryAllHidden, { label, points });\n  const parts = shown.map((s) => {\n    const dir =\n      s.trend === 'flat'\n        ? strings.trendFlat\n        : format(s.trend === 'up' ? strings.trendUp : strings.trendDown, {\n            pct: Math.abs(s.changePct).toFixed(1),\n          });\n    return format(strings.summaryPart, {\n      name: s.name,\n      min: fmtY(s.min),\n      max: fmtY(s.max),\n      last: fmtY(s.last),\n      dir,\n    });\n  });\n  const span = format(strings.summarySpan, { start: fmtX(summary.xStart), end: fmtX(summary.xEnd) });\n  const line = format(strings.summaryLine, { label, points, span, parts: parts.join('; ') });\n  if (!summary.annotations || summary.annotations.length === 0) return line;\n  const events = format(strings.summaryEvents, {\n    count: summary.annotations.length,\n    labels: summary.annotations.map((a) => a.label).join('; '),\n  });\n  return `${line} ${events}.`;\n}\n","/**\n * Keyboard-cursor logic — pure, framework-free, and unit-tested.\n *\n * The data surface is keyboard-navigable: arrows move between samples and switch series,\n * Home/End jump to the edges. This module computes the *next* cursor position from a key\n * press; `FChart` owns the events, the live-region announcement, and the panning.\n */\nimport type { CursorState } from '../core/model.ts';\n\nexport interface CursorStepOptions {\n  /** Number of samples in the series. */\n  n: number;\n  /** Samples currently visible in the viewport (drives the coarse step size). */\n  visibleCount: number;\n  /** Per-series visibility (index-aligned with the resolved series). */\n  seriesVisible: readonly boolean[];\n  /** Shift held → fine (single-sample) movement instead of the coarse jump. */\n  fine: boolean;\n}\n\nconst KEYS = new Set(['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown', 'Home', 'End']);\n\n// Keyboard zoom so a pointer-free user can change magnification, not just pan (WCAG 2.1.1):\n// '+'/'=' zoom in, '-'/'_' zoom out.\nconst ZOOM_IN = new Set(['+', '=']);\nconst ZOOM_OUT = new Set(['-', '_']);\n\n// Step between event markers (annotations) without walking every sample: ']' next, '[' prev,\n// Enter selects/pins the focused marker. Lets keyboard users reach a specific event directly.\nconst ANN_NEXT = ']';\nconst ANN_PREV = '[';\nconst ANN_SELECT = 'Enter';\n\n/**\n * True if this key is one the data surface handles (navigation, zoom, event-marker stepping, or\n * Escape-to-dismiss), so callers know to call preventDefault.\n */\nexport function handlesKey(key: string): boolean {\n  return (\n    KEYS.has(key) ||\n    ZOOM_IN.has(key) ||\n    ZOOM_OUT.has(key) ||\n    key === ANN_NEXT ||\n    key === ANN_PREV ||\n    key === ANN_SELECT ||\n    key === 'Escape'\n  );\n}\n\n/** Step direction for an event-marker key: +1 next (']'), -1 previous ('['), else null. */\nexport function annotationStep(key: string): 1 | -1 | null {\n  if (key === ANN_NEXT) return 1;\n  if (key === ANN_PREV) return -1;\n  return null;\n}\n\n/** True if the key selects/pins the focused event marker (Enter). */\nexport function selectsAnnotation(key: string): boolean {\n  return key === ANN_SELECT;\n}\n\n/**\n * Index (into `xs`) of the next/previous event marker by x-position, stepping from `fromX` in\n * `dir`. A null `fromX` starts at the first marker (dir +1) or the last (dir -1). Does not wrap:\n * stepping past the last/first marker returns that edge marker. Null only when there are no\n * markers. Markers sharing an x with `fromX` are skipped (strict ordering), so a step always\n * advances to a different x.\n */\nexport function annotationIndexByX(\n  xs: readonly number[],\n  fromX: number | null,\n  dir: 1 | -1,\n): number | null {\n  if (xs.length === 0) return null;\n  // Edge fallbacks: the marker with the smallest / largest x (where a non-wrapping step lands\n  // when there's nothing further in the step direction).\n  let minI = 0;\n  let maxI = 0;\n  for (let i = 1; i < xs.length; i++) {\n    if (xs[i]! < xs[minI]!) minI = i;\n    if (xs[i]! > xs[maxI]!) maxI = i;\n  }\n  if (fromX === null) return dir === 1 ? minI : maxI;\n  // The closest marker strictly past `fromX` in the step direction (smallest x above it going\n  // forward, largest x below it going back).\n  let bestI = -1;\n  for (let i = 0; i < xs.length; i++) {\n    const x = xs[i]!;\n    if (dir === 1 ? x <= fromX : x >= fromX) continue;\n    if (bestI === -1 || (dir === 1 ? x < xs[bestI]! : x > xs[bestI]!)) bestI = i;\n  }\n  if (bestI !== -1) return bestI;\n  return dir === 1 ? maxI : minI;\n}\n\n/**\n * Domain-scaling factor for a zoom key: `<1` zooms in (narrows the view), `>1` zooms out, or\n * `null` if the key is not a zoom key. Mirrors the wheel step (1.15×) so keyboard and pointer\n * zoom behave identically.\n */\nexport function zoomFactor(key: string): number | null {\n  if (ZOOM_IN.has(key)) return 1 / 1.15;\n  if (ZOOM_OUT.has(key)) return 1.15;\n  return null;\n}\n\nfunction findVisible(start: number, dir: 1 | -1, visible: readonly boolean[]): number {\n  const len = visible.length;\n  if (len === 0) return start;\n  for (let step = 1; step <= len; step++) {\n    const idx = (start + dir * step + len * step) % len;\n    if (visible[idx]) return idx;\n  }\n  return start; // none visible — stay put\n}\n\n/**\n * Compute the cursor position after a key press.\n *\n * @returns The next cursor state, or `null` if the key is not a navigation key.\n */\nexport function stepCursor(\n  cur: CursorState,\n  key: string,\n  opts: CursorStepOptions,\n): CursorState | null {\n  if (!KEYS.has(key)) return null;\n  const max = Math.max(0, opts.n - 1);\n  const coarse = Math.max(1, Math.round(opts.visibleCount / 120));\n  const step = opts.fine ? 1 : coarse;\n\n  let { index, series } = cur;\n  switch (key) {\n    case 'ArrowRight':\n      index = Math.min(max, index + step);\n      break;\n    case 'ArrowLeft':\n      index = Math.max(0, index - step);\n      break;\n    case 'ArrowUp':\n      series = findVisible(series, -1, opts.seriesVisible);\n      break;\n    case 'ArrowDown':\n      series = findVisible(series, 1, opts.seriesVisible);\n      break;\n    case 'Home':\n      index = 0;\n      break;\n    case 'End':\n      index = max;\n      break;\n  }\n  return { index, series };\n}\n\n/**\n * Pan a domain so it contains the given x-value, preserving its width. Pure: always\n * returns a fresh tuple (equal in value to the input when `x` is already inside).\n */\nexport function panToInclude(\n  domain: readonly [number, number],\n  x: number,\n): [number, number] {\n  const [d0, d1] = domain;\n  const span = d1 - d0;\n  if (x < d0) return [x, x + span];\n  if (x > d1) return [x - span, x];\n  return [d0, d1];\n}\n","/**\n * fcharts — the public chart class. Wires the renderer-agnostic core, the Canvas2D\n * renderer, the render scheduler, the interaction handlers (wheel-zoom, drag-pan,\n * keyboard cursor, hover), and the always-on accessibility layer into one component.\n *\n * Accessibility is load-bearing, not a flag: the DOM tick text, accessible legend,\n * keyboard-navigable data surface with live-region announcements, and the hidden data\n * table are all constructed by default and updated as part of the render lifecycle.\n */\nimport {\n  ChartData,\n  annotationSample,\n  resolveAnnotations,\n  resolveSeries,\n  DEFAULT_MARGINS,\n  type AnnotationSpec,\n  type CursorState,\n  type Margins,\n  type ResolvedAnnotation,\n  type ResolvedSeries,\n  type SeriesConfig,\n  type FChartData,\n} from './core/model.ts';\nimport { linearScale, logScale, type LinearScale } from './core/scales.ts';\nimport {\n  defaultFormatters,\n  effectiveTickCount,\n  logTicks,\n  niceTicks,\n  niceTimeTicks,\n} from './core/ticks.ts';\nimport { lowerBound, nearestIndex } from './core/downsample.ts';\nimport { RenderScheduler } from './core/scheduler.ts';\nimport { createCanvas2DRenderer } from './renderers/canvas2d.ts';\nimport {\n  detectHtmlInCanvas,\n  resolveRenderPath,\n  type HtmlInCanvasSupport,\n  type RenderPath,\n} from './renderers/detect.ts';\nimport { createCompositor, type Compositor } from './renderers/html-in-canvas.ts';\nimport type { Renderer, RenderScene } from './renderers/renderer.ts';\nimport { buildSVG } from './renderers/svg-export.ts';\nimport { injectStyles } from './a11y/styles.ts';\nimport { buildReadout, type ReadoutEls } from './a11y/readout.ts';\nimport { LiveRegion } from './a11y/live-region.ts';\nimport { AxisTicks } from './a11y/ticks.ts';\nimport { Legend } from './a11y/legend.ts';\nimport { Pagers } from './a11y/pagers.ts';\nimport { Sonifier } from './a11y/sonify.ts';\nimport { TableAlt } from './a11y/table-alt.ts';\nimport { buildSummary, describeSummary, type ChartSummary } from './a11y/summary.ts';\nimport {\n  annotationIndexByX,\n  annotationStep,\n  handlesKey,\n  panToInclude,\n  selectsAnnotation,\n  stepCursor,\n  zoomFactor,\n} from './a11y/cursor.ts';\nimport { format, resolveStrings, type FChartStrings } from './a11y/strings.ts';\n\ntype Formatter = (value: number) => string;\n\nexport interface FChartOptions {\n  /** Accessible name for the whole chart. */\n  ariaLabel?: string;\n  xLabel?: string;\n  yLabel?: string;\n  /** Render the accessible legend. Default true. */\n  legend?: boolean;\n  /** Cap on device pixel ratio (perf). Default 2. */\n  maxDpr?: number;\n  /** Fractional y-extent padding. Default 0.06. */\n  yPadding?: number;\n  /** X-domain padding in x data units beyond the first/last sample (it widens the view's hard\n   *  bounds). Candle bodies have width in x, so charts with a visible candle series default to\n   *  half the average sample step — edge candles render whole instead of clipping to slivers at\n   *  the plot border. Other charts default to 0. Set it explicitly to keep multi-panel layouts\n   *  (e.g. price + volume) on identical domains. */\n  xPad?: number;\n  /** Treat x as integer indices (ticks step >= 1). Default false. */\n  xInteger?: boolean;\n  /** X-axis flavor. `'time'` treats x as epoch milliseconds: ticks land on calendar boundaries\n   *  (midnights, month starts) and `formatX` defaults to an adaptive date/clock formatter.\n   *  Default `'linear'`. The `formatX` default is resolved at construction — patch `formatX`\n   *  explicitly if you change `xType` via `update()`. */\n  xType?: 'linear' | 'time';\n  /** Y-axis scale. `'log'` (base 10) needs positive data: the domain is fitted to the positive\n   *  values and non-positive samples clamp to the plot bottom. Default `'linear'`. */\n  yScale?: 'linear' | 'log';\n  xTickCount?: number;\n  yTickCount?: number;\n  /** BCP-47 tag (e.g. `'de'`, `'fr-CH'`) localizing the DEFAULT tick/value formatters via\n   *  `Intl.NumberFormat`/`Intl.DateTimeFormat`. Only the defaults: an explicit `formatX`/\n   *  `formatY` always wins, and without `locale` the deterministic English defaults are\n   *  unchanged. Pairs with `strings` (e.g. `stringsDE`), which localizes the UI prose.\n   *  An invalid tag throws at construction. */\n  locale?: string;\n  formatX?: Formatter;\n  formatY?: Formatter;\n  /** Force reduced-motion behavior (otherwise auto-detected). */\n  reducedMotion?: boolean;\n  /** Force high-contrast behavior (otherwise auto-detected). */\n  highContrast?: boolean;\n  /** Force forced-colors (Windows High Contrast) behavior (otherwise auto-detected + live). */\n  forcedColors?: boolean;\n  /** Play an audible tone for the focused value as the keyboard cursor moves (audio charts).\n   *  Off by default. */\n  sonify?: boolean;\n  /** Render a small \"Download data (CSV)\" button (localizable via `strings.exportCsv`) in the\n   *  plot's lower-left — a visible alternative-format affordance backing the hidden data table.\n   *  Off by default; fixed at construction. The data is always available via `toCSV()`. */\n  exportControl?: boolean;\n  /** Notified when the live render path changes after construction — e.g. when the\n   *  HTML-in-Canvas path self-heals to the DOM overlay because the experimental composite painted\n   *  nothing. Read `chart.renderPath` for the initial value; this fires only on a change.\n   *  Lets a host reflect the live path (a status badge, diagnostics). */\n  onRenderPath?: (path: RenderPath) => void;\n  /** Localize the library's fixed UI strings (legend, keyboard help, summary, caption). */\n  strings?: Partial<FChartStrings>;\n}\n\nexport interface FChartConfig {\n  series: SeriesConfig[];\n  data?: FChartData;\n  options?: FChartOptions;\n  /** Event markers on the series (allocation/closure dots, vertical rules). */\n  annotations?: AnnotationSpec[];\n}\n\n/** Throttle for the DOM-heavy derived updates (hidden table, summary, pagers, label). */\nconst DERIVED_THROTTLE_MS = 150;\n// Coalesce live-region announcements: holding an arrow key fires keydowns at the OS repeat\n// rate, which would flood a polite live region. Announce only the settled position.\nconst ANNOUNCE_DEBOUNCE_MS = 100;\n// Pointer pick radius (px) for grabbing an individual event marker: the diamond's ~5px half-width\n// plus slack, so a near-miss still selects the intended marker.\nconst ANNOTATION_HIT_PX = 11;\n\nlet instanceSeq = 0;\n\n/** Constructor options resolved onto their defaults (media-query autodetects included). */\ntype ResolvedOptions = Required<\n  Omit<\n    FChartOptions,\n    'ariaLabel' | 'xLabel' | 'yLabel' | 'strings' | 'onRenderPath' | 'xPad' | 'locale'\n  >\n> &\n  Pick<FChartOptions, 'ariaLabel' | 'xLabel' | 'yLabel' | 'onRenderPath' | 'xPad' | 'locale'>;\n\nfunction resolveOptions(config: FChartConfig, doc: Document): ResolvedOptions {\n  const fmt = defaultFormatters(config.options?.xType, config.options?.locale);\n  return {\n    legend: config.options?.legend ?? true,\n    maxDpr: config.options?.maxDpr ?? 2,\n    yPadding: config.options?.yPadding ?? 0.06,\n    xInteger: config.options?.xInteger ?? false,\n    xType: config.options?.xType ?? 'linear',\n    yScale: config.options?.yScale ?? 'linear',\n    xTickCount: config.options?.xTickCount ?? 8,\n    yTickCount: config.options?.yTickCount ?? 6,\n    locale: config.options?.locale,\n    formatX: config.options?.formatX ?? fmt.x,\n    formatY: config.options?.formatY ?? fmt.y,\n    reducedMotion:\n      config.options?.reducedMotion ?? prefers(doc, '(prefers-reduced-motion: reduce)'),\n    highContrast: config.options?.highContrast ?? prefers(doc, '(prefers-contrast: more)'),\n    forcedColors: config.options?.forcedColors ?? prefers(doc, '(forced-colors: active)'),\n    sonify: config.options?.sonify ?? false,\n    exportControl: config.options?.exportControl ?? false,\n    onRenderPath: config.options?.onRenderPath,\n    ariaLabel: config.options?.ariaLabel,\n    xLabel: config.options?.xLabel,\n    yLabel: config.options?.yLabel,\n    xPad: config.options?.xPad,\n  };\n}\n\n/**\n * Machine-readable layer: a one-line natural-language summary (aria-describedby, so it is\n * announced and agent-readable), the focused sample as a programmatically-determinable value\n * (an aria-describedby target updated in lockstep with the cursor — vs. the live region, which\n * is a transient announcement; lets AT/automation *query* the current point, not just hear it),\n * and a structured JSON block for DOM scrapers.\n */\nfunction buildA11yEls(\n  doc: Document,\n  summaryId: string,\n  activeId: string,\n): { summaryEl: HTMLElement; activeSample: HTMLElement; dataScript: HTMLElement } {\n  const summaryEl = doc.createElement('p');\n  summaryEl.className = 'fc-sr-only';\n  summaryEl.id = summaryId;\n  const activeSample = doc.createElement('span');\n  activeSample.className = 'fc-sr-only';\n  activeSample.id = activeId;\n  const dataScript = doc.createElement('script');\n  dataScript.setAttribute('type', 'application/json');\n  dataScript.setAttribute('data-fcharts', 'summary');\n  return { summaryEl, activeSample, dataScript };\n}\n\nfunction buildSurface(\n  doc: Document,\n  ids: { tableId: string; summaryId: string; activeId: string },\n): HTMLElement {\n  const surface = doc.createElement('div');\n  surface.className = 'fc-surface';\n  surface.tabIndex = 0;\n  surface.setAttribute('role', 'application');\n  surface.setAttribute('aria-roledescription', 'interactive chart');\n  // Point the focused widget at its data table so screen-reader users can reach it\n  // without leaving application mode and blindly browsing.\n  surface.setAttribute('aria-details', ids.tableId);\n  // Describe the data (values + trend) plus the focused sample (updated live) so SR users\n  // and AI agents get the overview on focus and can query the current point.\n  surface.setAttribute('aria-describedby', `${ids.summaryId} ${ids.activeId}`);\n  return surface;\n}\n\nexport class FChart {\n  private readonly root: HTMLElement;\n  private readonly doc: Document;\n  private readonly options: ResolvedOptions;\n  private readonly strings: FChartStrings;\n\n  private series: ResolvedSeries[];\n  /** Raw annotation specs, kept so a series change can re-resolve their default colors. */\n  private annotationSpecs: AnnotationSpec[] = [];\n  private annotations: ResolvedAnnotation[] = [];\n  private data: ChartData;\n  private domain: [number, number] = [0, 1];\n  private yDomain: [number, number] = [0, 1];\n  private cursor: CursorState = { series: 0, index: 0 };\n  private cursorActive = false;\n  /** Event marker under the pointer or keyboard focus (transient highlight), or null. */\n  private hoveredAnn: number | null = null;\n  /** Pinned/selected event marker (persists until cleared or re-clicked), or null. */\n  private selectedAnn: number | null = null;\n\n  private width = 0;\n  private height = 0;\n  private dpr = 1;\n  private readonly margins: Margins = { ...DEFAULT_MARGINS };\n\n  private ticksDirty = true;\n  private tableTimer = 0;\n  private a11yTimer = 0;\n  private announceTimer = 0;\n  /** One-shot guard so the zero-height diagnostic warns at most once per chart. */\n  private warnedZeroHeight = false;\n  /** Consecutive HTML-in-Canvas composite misses before falling back to the visible overlay. */\n  private hicMisses = 0;\n  /** Whether we've verified a composite actually painted tick pixels into the bitmap. */\n  private hicVerified = false;\n  /** Last render path handed to `options.onRenderPath` (only re-notify on a real change). */\n  private reportedPath: RenderPath;\n\n  private readonly renderer: Renderer;\n  private readonly scheduler: RenderScheduler;\n  private readonly compositor: Compositor;\n  private readonly support: HtmlInCanvasSupport;\n  /** Mutable: the html-in-canvas path can fall back to 'dom-overlay' if compositing fails. */\n  private path: RenderPath;\n\n  private readonly canvas: HTMLCanvasElement;\n  private readonly plot: HTMLElement;\n  private readonly surface: HTMLElement;\n  private readonly liveRegion: LiveRegion;\n  private readonly axisTicks: AxisTicks;\n  private readonly legend: Legend | null;\n  private readonly pagers: Pagers;\n  private readonly sonifier: Sonifier | null;\n  private readonly tableAlt: TableAlt;\n  private readonly summaryEl: HTMLElement;\n  private readonly exportBtn: HTMLButtonElement | null;\n  private readonly activeSample: HTMLElement;\n  private readonly dataScript: HTMLElement;\n  private readonly readout: ReadoutEls;\n  private readonly resizeObserver: ResizeObserver;\n  private readonly listeners = new AbortController();\n  private readonly domainListeners = new Set<(domain: readonly [number, number]) => void>();\n\n  private dragging = false;\n  private dragStartX = 0;\n  private dragStartDomain: [number, number] = [0, 1];\n\n  constructor(el: HTMLElement, config: FChartConfig) {\n    this.root = el;\n    this.doc = el.ownerDocument;\n    this.options = resolveOptions(config, this.doc);\n    this.strings = resolveStrings(config.options?.strings);\n\n    injectStyles(this.doc);\n    this.series = resolveSeries(config.series);\n    this.annotationSpecs = config.annotations ?? [];\n    this.annotations = resolveAnnotations(this.annotationSpecs, this.series);\n    if (config.data) this.assertSlotCount(config.data.y.length);\n    this.data = new ChartData(\n      config.data ?? { x: [], y: Array.from({ length: this.totalSlots() }, () => []) },\n    );\n\n    // --- DOM ---\n    const seq = ++instanceSeq;\n    const tableId = `fc-data-${seq}`;\n    const summaryId = `fc-summary-${seq}`;\n    const activeId = `fc-active-${seq}`;\n    this.root.classList.add('fc-root');\n    this.liveRegion = new LiveRegion(this.doc);\n    this.axisTicks = new AxisTicks(this.doc, this.options.xLabel, this.options.yLabel);\n    this.tableAlt = new TableAlt(this.doc);\n    this.tableAlt.el.id = tableId;\n\n    const a11y = buildA11yEls(this.doc, summaryId, activeId);\n    this.summaryEl = a11y.summaryEl;\n    this.activeSample = a11y.activeSample;\n    this.dataScript = a11y.dataScript;\n    this.legend = this.options.legend\n      ? new Legend(this.series, (i) => this.toggleSeries(i), this.strings, this.doc)\n      : null;\n    this.pagers = new Pagers((dir) => this.panPage(dir), this.strings, this.doc);\n    this.exportBtn = this.options.exportControl ? this.buildExportButton() : null;\n    const view = this.doc.defaultView;\n    this.sonifier = this.options.sonify && view ? new Sonifier(view) : null;\n\n    this.canvas = this.doc.createElement('canvas');\n    this.canvas.className = 'fc-canvas';\n    this.canvas.setAttribute('aria-hidden', 'true');\n\n    this.plot = this.doc.createElement('div');\n    this.plot.className = 'fc-plot';\n    this.surface = buildSurface(this.doc, { tableId, summaryId, activeId });\n    this.readout = buildReadout(this.doc);\n\n    this.renderer = createCanvas2DRenderer(this.canvas);\n    this.compositor = createCompositor(this.canvas);\n    this.support = detectHtmlInCanvas();\n    this.path = resolveRenderPath(this.support);\n    this.reportedPath = this.path;\n\n    this.assembleDom();\n\n    this.scheduler = new RenderScheduler(() => this.frame());\n\n    this.attachEvents();\n    this.trackForcedColors(config.options?.forcedColors !== undefined);\n    this.resizeObserver = new ResizeObserver(() => this.measure());\n    this.resizeObserver.observe(this.plot);\n\n    this.measure();\n    this.resetView();\n    // Always run, even without initial data, so the surface has an accessible name and a\n    // populated (non-empty) aria-describedby target before any setData().\n    this.refreshDerived();\n    this.requestRender();\n  }\n\n  /** Attach the built pieces to the document (legend, plot stack, a11y layer). */\n  private assembleDom(): void {\n    if (this.legend) this.root.append(this.legend.el);\n    this.surface.append(this.liveRegion.el, this.activeSample);\n    // The axis-tick text layer is a plot sibling (a visible CSS overlay) on the DOM-overlay\n    // path; on the HTML-in-Canvas path it becomes an immediate <canvas> child that is drawn\n    // into the bitmap each frame (frame() → compositeTicks) while staying accessible.\n    const ticksAsCanvasChild = this.path === 'html-in-canvas';\n    if (ticksAsCanvasChild) {\n      this.compositor.enable();\n      this.canvas.append(this.axisTicks.el);\n    }\n    this.plot.append(\n      this.canvas,\n      ...(ticksAsCanvasChild ? [] : [this.axisTicks.el]),\n      this.surface,\n      this.pagers.el,\n      this.readout.el,\n      this.tableAlt.el,\n      this.summaryEl,\n      this.dataScript,\n    );\n    if (this.exportBtn) this.plot.append(this.exportBtn);\n    this.root.append(this.plot);\n  }\n\n  /** Live forced-colors (Windows High Contrast) tracking, unless the integrator pinned it. */\n  private trackForcedColors(pinned: boolean): void {\n    if (pinned) return;\n    this.doc.defaultView?.matchMedia?.('(forced-colors: active)').addEventListener?.(\n      'change',\n      (e) => {\n        this.options.forcedColors = e.matches;\n        this.requestRender();\n      },\n      { signal: this.listeners.signal },\n    );\n  }\n\n  /** The render path actually in use. The DOM-overlay path is fully accessible on its own. */\n  get renderPath(): RenderPath {\n    return this.path;\n  }\n\n  /** HTML-in-Canvas support details (for diagnostics/badges). */\n  get htmlInCanvas(): HtmlInCanvasSupport {\n    return this.support;\n  }\n\n  /**\n   * Structured, machine-readable summary of the current data — per-series min/max/first/\n   * last/mean, change, and trend. The same object is embedded as JSON in the DOM and\n   * distilled into the chart's accessible description, so screen readers and AI agents get\n   * the values a bare `<canvas>` chart hides.\n   */\n  summary(): ChartSummary {\n    return buildSummary(this.data, this.series, this.options.ariaLabel ?? 'Chart', this.annotations);\n  }\n\n  /**\n   * Serialize the current view to a standalone, accessible `<svg>` string — the same\n   * downsampled envelope the canvas draws, plus real `<text>` ticks and a `<title>`/`<desc>`.\n   * Useful for print, embedding, or feeding a tactile-graphics pipeline (a non-visual export\n   * the EU data-viz guide recommends). Falls back to the configured size if not yet measured.\n   */\n  toSVG(): string {\n    const width = this.width || 640;\n    const height = this.height || 360;\n    const m = this.margins;\n    const xScale = linearScale(this.domain, [m.left, width - m.right]);\n    const makeY = this.options.yScale === 'log' ? logScale : linearScale;\n    const yScale = makeY(this.yDomain, [height - m.bottom, m.top]);\n    const xCount = effectiveTickCount(this.options.xTickCount, width - m.left - m.right, 64);\n    const yCount = effectiveTickCount(this.options.yTickCount, height - m.top - m.bottom, 28);\n    return buildSVG({\n      width,\n      height,\n      margins: m,\n      series: this.series,\n      data: this.data,\n      xScale,\n      yScale,\n      domain: this.domain,\n      xTicks: this.xAxisTicks(xCount),\n      yTicks: this.yAxisTicks(yCount),\n      formatX: this.options.formatX,\n      formatY: this.options.formatY,\n      title: this.options.ariaLabel ?? 'Chart',\n      desc: describeSummary(this.summary(), this.options.formatX, this.options.formatY, this.strings),\n      xLabel: this.options.xLabel,\n      yLabel: this.options.yLabel,\n      annotations: this.annotations,\n    });\n  }\n\n  /**\n   * The full current dataset as CSV (RFC 4180 quoting): an x column (named after `xLabel`),\n   * then one column per line/area series and four (`open`/`high`/`low`/`close`, localized via\n   * `strings`) per candle series. Values are raw — not run through `formatX`/`formatY` — so the\n   * export round-trips; hidden series are included. The same data the hidden table samples,\n   * but complete.\n   */\n  toCSV(): string {\n    const header = [this.options.xLabel ?? 'x'];\n    for (const s of this.series) {\n      if (s.type === 'candle') {\n        const words = [this.strings.open, this.strings.high, this.strings.low, this.strings.close];\n        header.push(...words.map((w) => `${s.name} ${w}`));\n      } else {\n        header.push(s.name);\n      }\n    }\n    const lines = [header.map(csvQuote).join(',')];\n    for (let i = 0; i < this.data.n; i++) {\n      const row = [String(this.data.x[i])];\n      for (const s of this.series) {\n        for (let k = 0; k < s.slots; k++) row.push(String(this.data.y[s.index + k][i]));\n      }\n      lines.push(row.join(','));\n    }\n    return lines.join('\\n');\n  }\n\n  private buildExportButton(): HTMLButtonElement {\n    const b = this.doc.createElement('button');\n    b.type = 'button';\n    b.className = 'fc-export';\n    b.textContent = this.strings.exportCsv;\n    b.addEventListener('click', () => this.downloadCsv(), { signal: this.listeners.signal });\n    return b;\n  }\n\n  private downloadCsv(): void {\n    const url = URL.createObjectURL(new Blob([this.toCSV()], { type: 'text/csv' }));\n    const a = this.doc.createElement('a');\n    a.href = url;\n    a.download = `${(this.options.ariaLabel ?? 'chart').replace(/[^\\w-]+/g, '-').toLowerCase()}.csv`;\n    a.click();\n    URL.revokeObjectURL(url);\n  }\n\n  /** Replace the dataset. Resets the view to the full x-domain. */\n  setData(data: FChartData): FChart {\n    this.assertSlotCount(data.y.length);\n    this.data = new ChartData(data);\n    this.resetView();\n    this.refreshDerived();\n    this.requestRender();\n    return this;\n  }\n\n  /** Total y-array slots the configured series consume (candles take 4: open/high/low/close). */\n  private totalSlots(): number {\n    const last = this.series[this.series.length - 1];\n    return last ? last.index + last.slots : 0;\n  }\n\n  /** Fail fast when the y-array count doesn't match the series' slot layout. */\n  private assertSlotCount(got: number): void {\n    const want = this.totalSlots();\n    if (got === want) return;\n    const candles = this.series.filter((s) => s.type === 'candle').length;\n    const hint = candles\n      ? ` (${candles} candle series × 4 arrays each — open, high, low, close — plus 1 per line/area series)`\n      : '';\n    throw new Error(`fcharts: ${this.series.length} series need ${want} y arrays${hint}, got ${got}.`);\n  }\n\n  /**\n   * Append one sample for real-time/streaming data — amortized O(1) (only the tail pyramid\n   * buckets update), never an O(n) rebuild. `x` must be >= the current last x; `ys` must have one\n   * value per series.\n   *\n   * When the view is following the live tail, the y-domain auto-fits the new data and the view\n   * tracks it — a zoomed window slides (keeping its width), a full-history view expands. If you've\n   * panned back into history it stays put — same view, same axis — so you can keep reading the past.\n   *\n   * Accessibility: `append` updates content on its own, so if you drive it on a timer you are\n   * creating auto-updating content — provide a Pause/Stop control (WCAG 2.2.2). The library never\n   * auto-updates by itself, so the cadence and its controls are yours.\n   */\n  append(xv: number, ys: readonly number[]): FChart {\n    const prevN = this.data.n;\n    const prevLast = prevN > 0 ? this.data.x[prevN - 1] : xv;\n    const prevLo = prevN > 0 ? this.viewExtent()[0] : xv;\n    const following = prevN === 0 || this.domain[1] >= prevLast - 1e-9;\n    const atLeftEdge = this.domain[0] <= prevLo + 1e-9;\n\n    this.data.push(xv, ys);\n\n    if (following) {\n      // Rescale the y-axis only when following the tail; a paused historical view keeps its axis.\n      this.rescaleY();\n      this.ticksDirty = true;\n      const [vlo, vhi] = this.viewExtent(); // padded bounds, so an edge candle stays whole\n      if (atLeftEdge) {\n        this.applyDomain([vlo, vhi]); // a full-history view → grow the right edge\n      } else {\n        const w = this.domain[1] - this.domain[0]; // a zoomed window → slide, keep its width\n        this.applyDomain([vhi - w, vhi]);\n        this.keepCursorInView();\n      }\n    }\n    // The DOM-facing derived state (summary JSON, accessible name, pagers, table) coalesces at\n    // streaming rates instead of rebuilding per sample — measured at ~99% of append cost.\n    this.scheduleA11yRefresh();\n    this.scheduleTableUpdate();\n    this.requestRender();\n    return this;\n  }\n\n  /**\n   * Replace the y-values of the LAST sample in place (x unchanged) — O(log n). The streaming\n   * companion to `append` for samples that keep changing while they form: amend the forming\n   * candle (or ticking last price) on every update, then `append` the next one when its bucket\n   * opens. Values must be finite; throws on an empty chart.\n   *\n   * The y-axis refits when the view is following the live tail, exactly like `append`.\n   */\n  amendLast(ys: readonly number[]): FChart {\n    const following = this.data.n > 0 && this.domain[1] >= this.data.x[this.data.n - 1] - 1e-9;\n    this.data.amendLast(ys);\n    if (following) {\n      this.rescaleY();\n      this.ticksDirty = true;\n    }\n    this.scheduleA11yRefresh();\n    this.scheduleTableUpdate();\n    this.requestRender();\n    return this;\n  }\n\n  /** If the cursor scrolled out of view (follow-slide, page-pan), snap it back + announce. */\n  private keepCursorInView(): void {\n    if (!this.cursorActive || this.data.n === 0) return;\n    const cx = this.data.x[this.cursor.index];\n    if (cx < this.domain[0] || cx > this.domain[1]) {\n      const mid = (this.domain[0] + this.domain[1]) / 2;\n      this.cursor = { series: this.cursor.series, index: nearestIndex(this.data.x, mid) };\n      this.updateActiveSample();\n      this.queueAnnounce();\n      this.requestRender();\n    }\n  }\n\n  /**\n   * Render immediately and synchronously, optionally to a given x-domain. Bypasses the\n   * rAF scheduler — useful for programmatic zoom, print/offscreen capture, and\n   * deterministic benchmarking.\n   */\n  renderSync(domain?: readonly [number, number]): FChart {\n    if (domain) this.applyDomain(domain);\n    this.scheduler.cancel(); // honor \"bypasses the scheduler\": drop any frame already queued\n    this.frame();\n    return this;\n  }\n\n  /**\n   * Subscribe to x-domain changes — wheel/keyboard zoom, drag pan, pager pans, cursor\n   * follow-pans, and programmatic `renderSync(domain)` all notify (after clamping, only when\n   * the domain actually changed). `setData`'s full-extent reset does not. Returns an\n   * unsubscribe function. See {@link syncCharts} for the linked multi-pane helper built on it.\n   */\n  onDomainChange(cb: (domain: readonly [number, number]) => void): () => void {\n    this.domainListeners.add(cb);\n    return () => this.domainListeners.delete(cb);\n  }\n\n  private emitDomain(): void {\n    for (const cb of this.domainListeners) cb([this.domain[0], this.domain[1]]);\n  }\n\n  /**\n   * Patch series, options, and/or data in place. Updatable options take effect immediately\n   * (labels, formatters, tick counts, modes, callbacks). `legend`, `sonify`, `exportControl`,\n   * and `strings` wire subsystems at construction and cannot change here: a patch that would *change* one throws\n   * (passing the current value is a no-op). Recreate the chart to change them — the React\n   * adapter remounts automatically.\n   */\n  update(patch: Partial<FChartConfig>): FChart {\n    if (patch.series) this.series = resolveSeries(patch.series);\n    if (patch.options) {\n      this.assertUpdatable(patch.options);\n      // `strings` was already resolved at construction; don't let the raw partial shadow it.\n      const { strings: _fixed, ...updatable } = patch.options;\n      Object.assign(this.options, updatable);\n      this.dpr = Math.min(this.options.maxDpr, this.doc.defaultView?.devicePixelRatio ?? 1);\n      if ('xLabel' in patch.options || 'yLabel' in patch.options) {\n        this.axisTicks.setLabels(this.options.xLabel, this.options.yLabel);\n      }\n    }\n    if (patch.data) {\n      this.assertSlotCount(patch.data.y.length);\n      this.data = new ChartData(patch.data);\n      this.resetView();\n    } else if (patch.series) {\n      this.assertSlotCount(this.data.y.length); // new series layout must fit the existing data\n    }\n    if (patch.annotations !== undefined) this.annotationSpecs = patch.annotations;\n    // Re-resolve when the specs change or when series change (annotation colors default off series).\n    if (patch.annotations !== undefined || patch.series) {\n      this.annotations = resolveAnnotations(this.annotationSpecs, this.series);\n      // Drop focus/selection: the indices referred to the old annotation set.\n      this.hoveredAnn = null;\n      this.selectedAnn = null;\n    }\n    this.legend?.update(this.series);\n    this.refreshDerived();\n    this.requestRender();\n    return this;\n  }\n\n  /** Fail fast when a patch tries to change an option only the constructor can wire. */\n  private assertUpdatable(patch: FChartOptions): void {\n    if (patch.legend !== undefined && patch.legend !== this.options.legend) failFixed('legend');\n    if (patch.sonify !== undefined && patch.sonify !== this.options.sonify) failFixed('sonify');\n    if (patch.exportControl !== undefined && patch.exportControl !== this.options.exportControl) {\n      failFixed('exportControl');\n    }\n    for (const [key, value] of Object.entries(patch.strings ?? {})) {\n      if (value !== undefined && value !== this.strings[key as keyof FChartStrings]) {\n        failFixed('strings');\n      }\n    }\n  }\n\n  destroy(): void {\n    this.listeners.abort();\n    this.resizeObserver.disconnect();\n    this.scheduler.destroy();\n    this.renderer.destroy();\n    const view = this.doc.defaultView;\n    if (this.tableTimer) view?.clearTimeout(this.tableTimer);\n    if (this.a11yTimer) view?.clearTimeout(this.a11yTimer);\n    if (this.announceTimer) view?.clearTimeout(this.announceTimer);\n    this.axisTicks.destroy();\n    this.tableAlt.destroy();\n    this.legend?.destroy();\n    this.pagers.destroy();\n    this.sonifier?.destroy();\n    this.liveRegion.destroy();\n    this.plot.remove();\n    this.root.classList.remove('fc-root');\n  }\n\n  // --- internals ---\n\n  private requestRender(): void {\n    this.scheduler.request();\n  }\n\n  private resetView(): void {\n    this.domain = this.viewExtent();\n    this.cursor = { series: this.firstVisibleSeries(), index: Math.floor(this.data.n / 2) };\n    this.ticksDirty = true;\n  }\n\n  /**\n   * The view's hard x-bounds: the data extent widened by `options.xPad` — which defaults to\n   * half the average sample step when a candle series is visible (candle bodies have width in\n   * x; without the pad the first and last candles clip to slivers at the plot border).\n   */\n  private viewExtent(): [number, number] {\n    const [lo, hi] = this.data.xExtent();\n    const pad = this.options.xPad ?? this.autoXPad(lo, hi);\n    return [lo - pad, hi + pad];\n  }\n\n  private autoXPad(lo: number, hi: number): number {\n    if (this.data.n < 2 || !this.series.some((s) => s.type === 'candle' && s.visible)) return 0;\n    return (hi - lo) / (this.data.n - 1) / 2;\n  }\n\n  private firstVisibleSeries(): number {\n    const i = this.series.findIndex((s) => s.visible);\n    return i < 0 ? 0 : i;\n  }\n\n  /**\n   * Recompute the y-domain and refresh the surface label, ticks, and table — synchronously.\n   * Used by the single-event paths (construction, setData, update, toggleSeries); `append`\n   * instead pairs `rescaleY()` with the throttled `scheduleA11yRefresh()`.\n   */\n  private refreshDerived(rescaleY = true): void {\n    if (rescaleY) this.rescaleY();\n    this.refreshA11y();\n    this.ticksDirty = true;\n    this.scheduleTableUpdate();\n  }\n\n  /** Fit the y-domain (plus padding) to the visible series. */\n  private rescaleY(): void {\n    // Per-slot visibility mask (a candle series spans 4 y slots, all sharing its visibility).\n    const visible: boolean[] = [];\n    for (const s of this.series) for (let k = 0; k < s.slots; k++) visible.push(s.visible);\n    const [yMin, yMax] = this.data.yExtent(visible);\n    if (this.options.yScale === 'log') {\n      // Log needs a positive domain; pad in log space so the visual margin matches linear's.\n      // Non-positive extents fall back to a decade below the max (samples <= 0 clamp to the\n      // plot bottom at render time — see logScale).\n      const hi = yMax > 0 ? yMax : 1;\n      const lo = yMin > 0 ? yMin : hi / 10;\n      const pad = (Math.log10(hi) - Math.log10(lo) || 1) * this.options.yPadding;\n      this.yDomain = [Math.pow(10, Math.log10(lo) - pad), Math.pow(10, Math.log10(hi) + pad)];\n      return;\n    }\n    const pad = (yMax - yMin) * this.options.yPadding;\n    this.yDomain = [yMin - pad, yMax + pad];\n  }\n\n  /** The DOM-facing derived state: accessible name, summary, current value, pagers. */\n  private refreshA11y(): void {\n    this.surface.setAttribute('aria-label', this.describeChart());\n    this.updateSummary();\n    this.updateActiveSample();\n    this.updatePagers();\n  }\n\n  /**\n   * Throttled `refreshA11y` for streaming appends. Fires at the throttle interval rather than\n   * debouncing: a continuous feed must not starve the refresh forever, just coalesce it.\n   */\n  private scheduleA11yRefresh(): void {\n    if (this.a11yTimer) return;\n    const view = this.doc.defaultView;\n    const run = (): void => {\n      this.a11yTimer = 0;\n      this.refreshA11y();\n    };\n    this.a11yTimer = view ? view.setTimeout(run, DERIVED_THROTTLE_MS) : (run(), 0);\n  }\n\n  /** Refresh the natural-language description and embedded JSON. Off the frame path. */\n  private updateSummary(): void {\n    const s = this.summary();\n    this.summaryEl.textContent = describeSummary(\n      s,\n      this.options.formatX,\n      this.options.formatY,\n      this.strings,\n    );\n    this.dataScript.textContent = JSON.stringify(s);\n  }\n\n  private describeChart(): string {\n    const help = this.annotations.length\n      ? `${this.strings.keyboardHelp} ${this.strings.eventKeysHelp}`\n      : this.strings.keyboardHelp;\n    return format(this.strings.chartName, {\n      name: this.options.ariaLabel ?? 'Chart',\n      series: this.series.length,\n      points: this.data.n.toLocaleString(),\n      help,\n    });\n  }\n\n  private measure(): void {\n    const rect = this.plot.getBoundingClientRect();\n    const w = Math.max(0, Math.round(rect.width));\n    const h = Math.max(0, Math.round(rect.height));\n    if (w === this.width && h === this.height) return;\n    // A laid-out-but-zero-height container (a real width, no height) renders nothing — the\n    // commonest mount mistake (`.fc-root` is height:100%, so an auto-height ancestor collapses\n    // it to 0). `frame()` already declines to paint at height <= 0 — no flash-then-collapse —\n    // but the integrator gets no signal, so warn once with the fix. See README \"Sizing\".\n    if (w > 0 && h <= 0 && !this.warnedZeroHeight) {\n      this.warnedZeroHeight = true;\n      console.warn(\n        'fcharts: chart container has 0 height — nothing will render. Set an explicit height on ' +\n          'the container or a definite-height ancestor (the root is height:100%), e.g. ' +\n          'style=\"height:320px\", or wrap it in position:relative;height:Npx + the mount at ' +\n          'position:absolute;inset:0. See the README \"Sizing\" note.',\n      );\n    }\n    this.width = w;\n    this.height = h;\n    this.dpr = Math.min(this.options.maxDpr, this.doc.defaultView?.devicePixelRatio ?? 1);\n    this.ticksDirty = true;\n    this.positionSurface();\n    if (this.path === 'html-in-canvas') this.sizeCanvasChildTicks();\n    this.requestRender();\n  }\n\n  /**\n   * Give the canvas-child tick layer an explicit size. A `layoutsubtree` child cannot size\n   * itself against the canvas box — `position:absolute; inset:0` resolves to 0×0 (Chrome 149),\n   * so every composite would snapshot an empty layer and the path would self-heal away even\n   * though the API works. Explicit px sizing keeps its geometry identical to the overlay case.\n   */\n  private sizeCanvasChildTicks(): void {\n    this.axisTicks.el.style.width = `${this.width}px`;\n    this.axisTicks.el.style.height = `${this.height}px`;\n  }\n\n  private positionSurface(): void {\n    const m = this.margins;\n    this.surface.style.inset = `${m.top}px ${m.right}px ${m.bottom}px ${m.left}px`;\n  }\n\n  private scales(): { xScale: LinearScale; yScale: LinearScale } {\n    const m = this.margins;\n    const xScale = linearScale(this.domain, [m.left, this.width - m.right]);\n    const makeY = this.options.yScale === 'log' ? logScale : linearScale;\n    const yScale = makeY(this.yDomain, [this.height - m.bottom, m.top]);\n    return { xScale, yScale };\n  }\n\n  /** Axis tick values for the current domains, honoring `xType`/`xInteger` and `yScale`. */\n  private xAxisTicks(count: number): number[] {\n    const [d0, d1] = this.domain;\n    if (this.options.xType === 'time') return niceTimeTicks(d0, d1, count);\n    return niceTicks(d0, d1, count, this.options.xInteger ? 1 : 0);\n  }\n\n  private yAxisTicks(count: number): number[] {\n    const [d0, d1] = this.yDomain;\n    return this.options.yScale === 'log' ? logTicks(d0, d1, count) : niceTicks(d0, d1, count);\n  }\n\n  private frame(): void {\n    if (this.width <= 0 || this.height <= 0) return;\n    const { xScale, yScale } = this.scales();\n    const m = this.margins;\n    // Thin tick density at narrow sizes so fixed-size labels don't overlap (1.4.10 reflow).\n    const xCount = effectiveTickCount(this.options.xTickCount, this.width - m.left - m.right, 64);\n    const yCount = effectiveTickCount(this.options.yTickCount, this.height - m.top - m.bottom, 28);\n    const xTicks = this.xAxisTicks(xCount);\n    const yTicks = this.yAxisTicks(yCount);\n\n    if (this.ticksDirty) {\n      this.axisTicks.update({\n        xTicks,\n        yTicks,\n        xScale,\n        yScale,\n        formatX: this.options.formatX,\n        formatY: this.options.formatY,\n        margins: this.margins,\n        width: this.width,\n        height: this.height,\n      });\n      this.ticksDirty = false;\n    }\n\n    const scene: RenderScene = {\n      width: this.width,\n      height: this.height,\n      dpr: this.dpr,\n      margins: this.margins,\n      data: this.data,\n      series: this.series,\n      xScale,\n      yScale,\n      domain: this.domain,\n      xTicks,\n      yTicks,\n      // Suppress the sample crosshair while a marker is focused, so hovering a diamond reads as\n      // \"this event\" rather than \"this sample\" — the highlighted marker carries the position.\n      cursor: this.cursorActive && this.hoveredAnn === null ? this.cursor : null,\n      annotations: this.annotations,\n      hoveredAnnotation: this.hoveredAnn,\n      selectedAnnotation: this.selectedAnn,\n      reducedMotion: this.options.reducedMotion,\n      highContrast: this.options.highContrast,\n      forcedColors: this.options.forcedColors,\n    };\n    this.renderer.render(scene);\n    if (this.path === 'html-in-canvas') this.compositeTicks();\n\n    if (this.cursorActive || this.hoveredAnn !== null || this.selectedAnn !== null) {\n      this.updateReadout(xScale, yScale);\n    }\n  }\n\n  /**\n   * Draw the canvas-placed tick layer into the bitmap via HTML-in-Canvas. The first frames\n   * legitimately miss (no paint snapshot exists yet); if compositing never succeeds we fall\n   * back to a visible DOM overlay so the ticks can never vanish on an unexpected API change.\n   */\n  private compositeTicks(): void {\n    // The paint snapshot for the canvas-placed children isn't ready until the browser has\n    // painted them at least once. How that surfaces changed across Chrome: M148 throws (\"no\n    // cached paint record\" → composite() returns false), M149+ \"succeeds\" but paints no pixels.\n    // Treat both as the same warm-up miss: nudge another frame (render-on-demand would otherwise\n    // stop before the snapshot exists) and retry. If the gutter never gains pixels within the\n    // miss budget the API is lying (observed on some dev builds) — self-heal to the visible DOM\n    // overlay so the axes can never vanish. Once verified, skip the per-frame readback.\n    const painted =\n      this.compositor.composite(this.axisTicks.el) &&\n      (this.hicVerified || this.compositePaintedTicks());\n    if (!painted) {\n      if (++this.hicMisses > 8) this.fallbackToOverlay();\n      else this.requestRender();\n      return;\n    }\n    this.hicMisses = 0;\n    this.hicVerified = true;\n  }\n\n  /**\n   * Read back the left y-axis gutter and report whether the composite actually painted there. The\n   * canvas renderer draws no text and keeps grid + axis lines inside `margins.left`, so the gutter\n   * is transparent unless the composited tick layer (labels + axis titles) painted into it.\n   */\n  private compositePaintedTicks(): boolean {\n    const ctx = this.canvas.getContext('2d');\n    const gutter = Math.round((this.margins.left - 3) * this.dpr);\n    const h = Math.round(this.height * this.dpr);\n    if (!ctx || gutter < 1 || h < 1) return false;\n    try {\n      const { data } = ctx.getImageData(0, 0, gutter, h);\n      for (let i = 3; i < data.length; i += 4) if (data[i] > 8) return true; // any opaque pixel\n      return false;\n    } catch {\n      return false; // an unreadable bitmap (tainted/unsupported) → fall back; axes stay visible\n    }\n  }\n\n  /** Re-show the tick layer as a normal CSS overlay and stop using the HTML-in-Canvas path. */\n  private fallbackToOverlay(): void {\n    this.path = 'dom-overlay';\n    this.canvas.removeAttribute('layoutsubtree');\n    this.axisTicks.el.style.transform = '';\n    // Back to the stylesheet's inset:0 sizing — the overlay tracks the plot on resize by itself.\n    this.axisTicks.el.style.width = '';\n    this.axisTicks.el.style.height = '';\n    this.plot.insertBefore(this.axisTicks.el, this.surface);\n    this.ticksDirty = true;\n    this.reportPath();\n    this.requestRender();\n  }\n\n  /** Notify `options.onRenderPath` when the live render path changes (e.g. on self-heal). */\n  private reportPath(): void {\n    if (this.path === this.reportedPath) return;\n    this.reportedPath = this.path;\n    this.options.onRenderPath?.(this.path);\n  }\n\n  // --- accessibility-driven updates ---\n\n  private scheduleTableUpdate(): void {\n    // Throttle, don't debounce: resetting the timer per call would postpone the table forever\n    // under a continuous append stream — it must go at most one interval stale.\n    if (this.tableTimer) return;\n    const view = this.doc.defaultView;\n    const run = (): void => {\n      this.tableTimer = 0;\n      this.tableAlt.update({\n        data: this.data,\n        series: this.series,\n        domain: this.domain,\n        formatX: this.options.formatX,\n        formatY: this.options.formatY,\n        caption: this.options.ariaLabel ?? 'Chart data',\n        captionTemplate: this.strings.tableCaption,\n        xLabel: this.options.xLabel,\n        ohlc: this.strings,\n      });\n    };\n    this.tableTimer = view ? view.setTimeout(run, DERIVED_THROTTLE_MS) : (run(), 0);\n  }\n\n  private toggleSeries(index: number): void {\n    const s = this.series[index];\n    if (!s) return;\n    s.visible = !s.visible;\n    this.legend?.update(this.series);\n    if (!this.series[this.cursor.series]?.visible) this.cursor.series = this.firstVisibleSeries();\n    this.refreshDerived();\n    this.requestRender();\n  }\n\n  /** Natural-language text for the focused sample, or null when there's nothing to describe. */\n  private currentSampleText(): string | null {\n    const s = this.series[this.cursor.series];\n    // Guard visibility too: when every series is hidden, the cursor falls back to series 0\n    // (which is hidden), and neither the announcement nor the value target should leak it.\n    if (!s || !s.visible || this.data.n === 0) return null;\n    const x = this.data.x[this.cursor.index];\n    const lx = this.options.xLabel ?? 'x';\n    let base: string;\n    if (s.type === 'candle') {\n      const [o, h, l, c] = this.candleAt(s, this.cursor.index);\n      const fy = this.options.formatY;\n      const w = this.strings;\n      base =\n        `${s.name} — ${lx} ${this.options.formatX(x)}, ${w.open} ${fy(o)}, ` +\n        `${w.high} ${fy(h)}, ${w.low} ${fy(l)}, ${w.close} ${fy(c)}`;\n    } else {\n      const v = this.data.y[s.index][this.cursor.index];\n      const ly = this.options.yLabel ?? 'value';\n      base = `${s.name} — ${lx} ${this.options.formatX(x)}, ${ly} ${this.options.formatY(v)}`;\n    }\n    // Surface any event markers on this sample so they're reachable in the keyboard walk.\n    const labels = this.annotationLabelsAt(this.cursor.series, this.cursor.index);\n    return labels.length ? `${base} · ${labels.join('; ')}` : base;\n  }\n\n  /** Labels of annotations attached to the sample at (series position, sample index): point\n   *  markers on that series whose nearest sample is `idx`, plus any rule nearest to `idx`. */\n  private annotationLabelsAt(seriesPos: number, idx: number): string[] {\n    if (this.annotations.length === 0) return [];\n    const out: string[] = [];\n    for (const a of this.annotations) {\n      if (a.kind === 'rule') {\n        if (nearestIndex(this.data.x, a.x) === idx) out.push(a.label);\n      } else if (a.seriesIndex === seriesPos) {\n        const pt = annotationSample(this.data, this.series, a);\n        if (pt && pt.index === idx) out.push(a.label);\n      }\n    }\n    return out;\n  }\n\n  /** The [open, high, low, close] of a candle series at a sample index. */\n  private candleAt(s: ResolvedSeries, i: number): [number, number, number, number] {\n    const y = this.data.y;\n    return [y[s.index][i], y[s.index + 1][i], y[s.index + 2][i], y[s.index + 3][i]];\n  }\n\n  /** Announce the current cursor position immediately (used on focus — a single event). */\n  private announceNow(): void {\n    const text = this.currentSampleText();\n    if (text) this.liveRegion.announce(text);\n  }\n\n  /**\n   * Mirror the focused sample into the aria-describedby target so it is a programmatically\n   * queryable value (4.1.2), not only a transient live announcement. Updated synchronously\n   * with the cursor (unlike the debounced live region); cleared when the cursor is inactive.\n   */\n  private updateActiveSample(): void {\n    this.activeSample.textContent = this.cursorActive ? (this.currentSampleText() ?? '') : '';\n  }\n\n  /** Sound the focused value (pitch maps the value within its series range), if sonify is on. */\n  private sonifyCursor(): void {\n    const s = this.series[this.cursor.series];\n    if (!this.sonifier || !s || !s.visible || this.data.n === 0) return;\n    if (s.type === 'candle') {\n      // Pitch the close within the full traded range (low stats → high stats).\n      const lo = this.data.stats[s.index + 2].min;\n      const hi = this.data.stats[s.index + 1].max;\n      this.sonifier.play(this.data.y[s.index + 3][this.cursor.index], lo, hi);\n      return;\n    }\n    const st = this.data.stats[s.index];\n    this.sonifier.play(this.data.y[s.index][this.cursor.index], st.min, st.max);\n  }\n\n  /** Coalesce announcements during rapid movement (key-repeat, hover) to the settled point. */\n  private queueAnnounce(): void {\n    const view = this.doc.defaultView;\n    if (this.announceTimer) view?.clearTimeout(this.announceTimer);\n    const run = (): void => this.announceNow();\n    this.announceTimer = view ? view.setTimeout(run, ANNOUNCE_DEBOUNCE_MS) : (run(), 0);\n  }\n\n  /** The marker that owns the readout/highlight: a live hover wins over a standing selection. */\n  private focusAnn(): number | null {\n    return this.hoveredAnn ?? this.selectedAnn;\n  }\n\n  /** Position the readout on a focused event marker and show its label. Hides if the marker is\n   *  off-screen or its series is toggled off. */\n  private annotationReadout(i: number, xScale: LinearScale, yScale: LinearScale): void {\n    const a = this.annotations[i];\n    const hide = (): void => this.readout.el.classList.remove('fc-show');\n    if (!a) return hide();\n    const px = xScale(a.x);\n    if (px < this.margins.left - 2 || px > this.width - this.margins.right + 2) return hide();\n    let py = this.margins.top + 14;\n    if (a.kind !== 'rule') {\n      const s = this.series[a.seriesIndex];\n      if (s && !s.visible) return hide();\n      const pt = annotationSample(this.data, this.series, a);\n      if (!pt) return hide();\n      py = yScale(pt.y);\n    }\n    this.readout.swatch.style.background = a.color;\n    this.readout.name.textContent = a.label;\n    this.readout.value.textContent = this.options.formatX(a.x);\n    this.readout.el.style.left = `${px}px`;\n    this.readout.el.style.top = `${py - 8}px`;\n    this.readout.el.classList.add('fc-show');\n  }\n\n  private updateReadout(xScale: LinearScale, yScale: LinearScale): void {\n    const fa = this.focusAnn();\n    if (fa !== null) {\n      this.annotationReadout(fa, xScale, yScale);\n      return;\n    }\n    const s = this.series[this.cursor.series];\n    if (!s || !s.visible || this.data.n === 0) {\n      this.readout.el.classList.remove('fc-show');\n      return;\n    }\n    const x = this.data.x[this.cursor.index];\n    const candle = s.type === 'candle' ? this.candleAt(s, this.cursor.index) : null;\n    const v = candle ? candle[3] : this.data.y[s.index][this.cursor.index];\n    const px = xScale(x);\n    const py = yScale(v);\n    if (px < this.margins.left - 2 || px > this.width - this.margins.right + 2) {\n      this.readout.el.classList.remove('fc-show');\n      return;\n    }\n    this.readout.swatch.style.background = candle\n      ? (candle[3] >= candle[0] ? s.upColor : s.downColor)\n      : s.color;\n    this.readout.name.textContent = s.name;\n    const fy = this.options.formatY;\n    // The readout is aria-hidden (the live region speaks full words); abbreviations are visual-only.\n    const valueText = candle\n      ? `${this.options.formatX(x)} · O ${fy(candle[0])} H ${fy(candle[1])} L ${fy(candle[2])} C ${fy(candle[3])}`\n      : `${this.options.formatX(x)} · ${fy(v)}`;\n    const labels = this.annotationLabelsAt(this.cursor.series, this.cursor.index);\n    this.readout.value.textContent = labels.length ? `${valueText} · ${labels.join('; ')}` : valueText;\n    this.readout.el.style.left = `${px}px`;\n    this.readout.el.style.top = `${py - 8}px`;\n    this.readout.el.classList.add('fc-show');\n  }\n\n  // --- interaction ---\n\n  /**\n   * Index of the event marker within {@link ANNOTATION_HIT_PX} of the pointer, or null. Point\n   * markers use 2-D distance to their diamond; rules use horizontal distance to the line. The\n   * nearest qualifying marker wins, so clustered events stay individually selectable.\n   */\n  private annotationAt(clientX: number, clientY: number): number | null {\n    if (this.annotations.length === 0) return null;\n    const rect = this.plot.getBoundingClientRect();\n    const lx = clientX - rect.left;\n    const ly = clientY - rect.top;\n    const { xScale, yScale } = this.scales();\n    const r2 = ANNOTATION_HIT_PX * ANNOTATION_HIT_PX;\n    let best: number | null = null;\n    let bestD = r2;\n    for (let i = 0; i < this.annotations.length; i++) {\n      const a = this.annotations[i];\n      const dx = lx - xScale(a.x);\n      let d = dx * dx;\n      if (a.kind !== 'rule') {\n        const s = this.series[a.seriesIndex];\n        if (s && !s.visible) continue;\n        const pt = annotationSample(this.data, this.series, a);\n        if (!pt) continue;\n        const dy = ly - yScale(pt.y);\n        d += dy * dy;\n      }\n      if (d <= r2 && d < bestD) {\n        best = i;\n        bestD = d;\n      }\n    }\n    return best;\n  }\n\n  /** Move keyboard focus to an event marker: align the sample cursor (for the SR announcement),\n   *  bring it into view, and announce it. */\n  private focusAnnotation(i: number): void {\n    const a = this.annotations[i];\n    if (!a) return;\n    this.hoveredAnn = i;\n    this.cursorActive = true;\n    const pt = a.kind === 'rule' ? null : annotationSample(this.data, this.series, a);\n    this.cursor = {\n      series: a.kind === 'rule' ? this.cursor.series : a.seriesIndex,\n      index: pt ? pt.index : nearestIndex(this.data.x, a.x),\n    };\n    const [b0, b1] = this.domain;\n    this.domain = panToInclude(this.domain, a.x);\n    if (this.domain[0] !== b0 || this.domain[1] !== b1) this.emitDomain();\n    this.ticksDirty = true;\n    this.scheduleTableUpdate();\n    this.updateActiveSample();\n    this.announceAnnotation(i);\n    this.requestRender();\n  }\n\n  /** Step keyboard focus to the next/previous event marker by date. */\n  private stepAnnotation(dir: 1 | -1): void {\n    const fromX = this.hoveredAnn !== null ? this.annotations[this.hoveredAnn]?.x ?? null : null;\n    const idx = annotationIndexByX(this.annotations.map((a) => a.x), fromX, dir);\n    if (idx !== null) this.focusAnnotation(idx);\n  }\n\n  /** Toggle the pinned selection on the currently focused marker (Enter, or a marker click). */\n  private toggleSelectAnnotation(i: number): void {\n    this.selectedAnn = this.selectedAnn === i ? null : i;\n    this.hoveredAnn = i;\n    this.announceAnnotation(i);\n    this.requestRender();\n  }\n\n  private announceAnnotation(i: number): void {\n    const a = this.annotations[i];\n    if (!a) return;\n    const suffix = this.selectedAnn === i ? `, ${this.strings.selected}` : '';\n    this.liveRegion.announce(`${a.label}, ${this.options.formatX(a.x)}${suffix}`);\n  }\n\n  private attachEvents(): void {\n    const signal = this.listeners.signal;\n    const s = this.surface;\n    s.addEventListener('focus', () => this.onFocus(), { signal });\n    s.addEventListener('blur', () => this.onBlur(), { signal });\n    s.addEventListener('keydown', (e) => this.onKeyDown(e), { signal });\n    s.addEventListener('wheel', (e) => this.onWheel(e), { signal, passive: false });\n    s.addEventListener('pointerdown', (e) => this.onPointerDown(e), { signal });\n    s.addEventListener('pointermove', (e) => this.onPointerMove(e), { signal });\n    s.addEventListener('pointerup', (e) => this.onPointerUp(e), { signal });\n    s.addEventListener('pointercancel', (e) => this.onPointerUp(e), { signal });\n    s.addEventListener('pointerleave', () => this.onPointerLeave(), { signal });\n  }\n\n  private onFocus(): void {\n    this.cursorActive = true;\n    this.updateActiveSample();\n    this.announceNow();\n    this.sonifyCursor();\n    this.requestRender();\n  }\n\n  private onBlur(): void {\n    if (this.dragging) return;\n    this.cursorActive = false;\n    this.updateActiveSample();\n    this.readout.el.classList.remove('fc-show');\n    this.requestRender();\n  }\n\n  private onKeyDown(e: KeyboardEvent): void {\n    if (!handlesKey(e.key)) return;\n    e.preventDefault();\n    if (e.key === 'Escape') {\n      this.selectedAnn = null;\n      this.hoveredAnn = null;\n      this.dismissCursor();\n      return;\n    }\n    const annDir = annotationStep(e.key);\n    if (annDir !== null) {\n      this.stepAnnotation(annDir);\n      return;\n    }\n    if (selectsAnnotation(e.key)) {\n      if (this.hoveredAnn !== null) this.toggleSelectAnnotation(this.hoveredAnn);\n      return;\n    }\n    const factor = zoomFactor(e.key);\n    if (factor !== null) {\n      this.zoomAroundCursor(factor);\n      return;\n    }\n    const next = stepCursor(this.cursor, e.key, {\n      n: this.data.n,\n      visibleCount: this.visibleCount(),\n      seriesVisible: this.series.map((sr) => sr.visible),\n      fine: e.shiftKey,\n    });\n    if (!next) return;\n    this.cursor = next;\n    this.hoveredAnn = null; // an arrow press returns to sample navigation\n    this.cursorActive = true;\n    this.updateActiveSample();\n    this.sonifyCursor();\n    const [b0, b1] = this.domain;\n    this.domain = panToInclude(this.domain, this.data.x[this.cursor.index]);\n    if (this.domain[0] !== b0 || this.domain[1] !== b1) {\n      this.ticksDirty = true;\n      this.scheduleTableUpdate();\n      this.emitDomain();\n    }\n    this.queueAnnounce();\n    this.requestRender();\n  }\n\n  /** Dismiss the cursor/readout (Escape) without moving focus, so a later arrow re-activates it. */\n  private dismissCursor(): void {\n    this.cursorActive = false;\n    this.updateActiveSample();\n    this.readout.el.classList.remove('fc-show');\n    this.requestRender();\n  }\n\n  /** Zoom the x-domain around the current cursor sample (keyboard equivalent of wheel-zoom). */\n  private zoomAroundCursor(factor: number): void {\n    const [d0, d1] = this.domain;\n    const cx = this.data.n > 0 ? this.data.x[this.cursor.index] : (d0 + d1) / 2;\n    this.cursorActive = true;\n    this.updateActiveSample();\n    this.setDomain([cx - (cx - d0) * factor, cx + (d1 - cx) * factor]);\n  }\n\n  /** Single-pointer pan: shift the visible window ~one page earlier/later (WCAG 2.5.7). */\n  private panPage(dir: -1 | 1): void {\n    const [d0, d1] = this.domain;\n    const shift = dir * (d1 - d0) * 0.9;\n    this.setDomain([d0 + shift, d1 + shift]);\n    this.keepCursorInView();\n  }\n\n  /** Show/disable the pan pagers based on whether (and which way) the view can pan. */\n  private updatePagers(): void {\n    const [lo, hi] = this.viewExtent();\n    this.pagers.update(this.domain[0] <= lo, this.domain[1] >= hi);\n  }\n\n  private onWheel(e: WheelEvent): void {\n    e.preventDefault();\n    const px = e.clientX - this.plot.getBoundingClientRect().left;\n    const { xScale } = this.scales();\n    const cx = xScale.invert(px);\n    const factor = e.deltaY > 0 ? 1.15 : 1 / 1.15;\n    const [d0, d1] = this.domain;\n    this.setDomain([cx - (cx - d0) * factor, cx + (d1 - cx) * factor]);\n  }\n\n  private onPointerDown(e: PointerEvent): void {\n    if (e.button !== 0) return;\n    const hit = this.annotationAt(e.clientX, e.clientY);\n    if (hit !== null) {\n      this.toggleSelectAnnotation(hit); // click a marker to pin/unpin it, not to start a pan\n      return;\n    }\n    if (this.selectedAnn !== null) {\n      this.selectedAnn = null; // a click on empty space clears the pinned selection\n      this.requestRender();\n    }\n    this.dragging = true;\n    this.dragStartX = e.clientX;\n    this.dragStartDomain = [...this.domain];\n    this.surface.setPointerCapture(e.pointerId);\n  }\n\n  private onPointerMove(e: PointerEvent): void {\n    if (this.dragging) {\n      const plotW = Math.max(1, this.width - this.margins.left - this.margins.right);\n      const span = this.dragStartDomain[1] - this.dragStartDomain[0];\n      const shift = ((e.clientX - this.dragStartX) / plotW) * span;\n      this.setDomain([this.dragStartDomain[0] - shift, this.dragStartDomain[1] - shift]);\n      return;\n    }\n    const hit = this.annotationAt(e.clientX, e.clientY);\n    if (hit !== null) {\n      if (hit !== this.hoveredAnn) {\n        this.hoveredAnn = hit;\n        this.requestRender();\n      }\n      return;\n    }\n    if (this.hoveredAnn !== null) {\n      this.hoveredAnn = null;\n      this.requestRender();\n    }\n    this.hoverAt(e.clientX);\n  }\n\n  private onPointerUp(e: PointerEvent): void {\n    if (!this.dragging) return;\n    this.dragging = false;\n    if (this.surface.hasPointerCapture(e.pointerId)) {\n      this.surface.releasePointerCapture(e.pointerId);\n    }\n  }\n\n  private onPointerLeave(): void {\n    if (this.dragging || this.doc.activeElement === this.surface) return;\n    this.hoveredAnn = null;\n    this.cursorActive = false;\n    this.updateActiveSample();\n    // Keep a pinned selection's readout up; the next frame repaints it from selectedAnn.\n    if (this.selectedAnn === null) this.readout.el.classList.remove('fc-show');\n    this.requestRender();\n  }\n\n  private hoverAt(clientX: number): void {\n    if (this.data.n === 0) return;\n    const px = clientX - this.plot.getBoundingClientRect().left;\n    const { xScale } = this.scales();\n    const xv = xScale.invert(px);\n    const idx = nearestIndex(this.data.x, xv);\n    this.cursor = { series: this.cursor.series, index: idx };\n    if (!this.series[this.cursor.series]?.visible) this.cursor.series = this.firstVisibleSeries();\n    this.cursorActive = true;\n    this.updateActiveSample();\n    this.queueAnnounce();\n    this.requestRender();\n  }\n\n  private visibleCount(): number {\n    if (this.data.n === 0) return 1;\n    const i0 = Math.max(0, lowerBound(this.data.x, this.domain[0]) - 1);\n    const i1 = Math.min(this.data.n - 1, lowerBound(this.data.x, this.domain[1]));\n    return Math.max(1, i1 - i0 + 1);\n  }\n\n  /** Clamp + apply a new x-domain (no render). Returns whether the domain changed. */\n  private applyDomain(next: readonly [number, number]): boolean {\n    const [lo, hi] = this.viewExtent();\n    const minSpan = ((hi - lo) / Math.max(1, this.data.n - 1)) * 4 || 1e-9;\n    let a = next[0];\n    let b = next[1];\n    if (b - a < minSpan) {\n      const mid = (a + b) / 2;\n      a = mid - minSpan / 2;\n      b = mid + minSpan / 2;\n    }\n    if (a < lo) {\n      b += lo - a;\n      a = lo;\n    }\n    if (b > hi) {\n      a -= b - hi;\n      b = hi;\n    }\n    a = Math.max(lo, a);\n    b = Math.min(hi, b);\n    if (a === this.domain[0] && b === this.domain[1]) return false;\n    this.domain = [a, b];\n    this.ticksDirty = true;\n    this.scheduleTableUpdate();\n    this.updatePagers();\n    this.emitDomain();\n    return true;\n  }\n\n  /** Apply a new x-domain with clamping and request an async render. */\n  private setDomain(next: readonly [number, number]): void {\n    if (this.applyDomain(next)) this.requestRender();\n  }\n}\n\n/**\n * True when two option objects agree on every construction-time option (`legend`, `sonify`,\n * `strings`) — i.e. an existing chart built with `a` can absorb `b` via `update()`. Adapters\n * use this to decide between updating in place and remounting (see the React wrapper).\n */\nexport function sameConstructionOptions(a: FChartOptions = {}, b: FChartOptions = {}): boolean {\n  if ((a.legend ?? true) !== (b.legend ?? true)) return false;\n  if ((a.sonify ?? false) !== (b.sonify ?? false)) return false;\n  if ((a.exportControl ?? false) !== (b.exportControl ?? false)) return false;\n  const sa = a.strings ?? {};\n  const sb = b.strings ?? {};\n  const keys = Object.keys({ ...sa, ...sb }) as (keyof FChartStrings)[];\n  return keys.every((k) => sa[k] === sb[k]);\n}\n\nfunction failFixed(name: string): never {\n  throw new Error(\n    `fcharts: option \"${name}\" is fixed at construction; update() cannot rewire it. ` +\n      'Recreate the chart to change it (the React adapter remounts automatically).',\n  );\n}\n\nfunction prefers(doc: Document, query: string): boolean {\n  return doc.defaultView?.matchMedia?.(query).matches ?? false;\n}\n\n/** RFC 4180 field quoting (only header cells can need it; data cells are numbers). */\nfunction csvQuote(s: string): string {\n  return /[\",\\n]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n}\n\n","/**\n * Linked multi-pane charts — one x-domain across panes (price + volume, sensor stacks).\n *\n * Built on {@link FChart.onDomainChange}: when the user zooms/pans any pane, every other pane\n * follows synchronously via `renderSync(domain)`. The follower's own change notification is\n * suppressed while the group is applying, so panes can't feed back. Panes keep their own\n * y-domains, cursors, and a11y layers — only the x-window is shared. For identical hard\n * bounds across panes, construct them with the same explicit `options.xPad`.\n */\nimport type { FChart } from './fchart.ts';\n\n/** Link the charts' x-domains. Returns an unlink function (charts themselves are untouched). */\nexport function syncCharts(charts: readonly FChart[]): () => void {\n  let applying = false;\n  const unsubs = charts.map((chart) =>\n    chart.onDomainChange((domain) => {\n      if (applying) return;\n      applying = true;\n      try {\n        for (const other of charts) {\n          if (other !== chart) other.renderSync(domain);\n        }\n      } finally {\n        applying = false;\n      }\n    }),\n  );\n  return () => {\n    for (const u of unsubs) u();\n  };\n}\n","/**\n * SSR → live upgrade: swap a server-rendered fcharts SVG (from `renderSVG`) for the\n * interactive `FChart`, with no layout shift and no blank frame.\n *\n * Progressive enhancement in the a11y sense: the static SVG is real content (titled,\n * described, agent-readable) before any JS runs; hydration only *adds* interactivity.\n * The swap is synchronous — the container's box is pinned to its current height, the SVG is\n * lifted out of flow, the chart renders its first frame via `renderSync()`, and only then is\n * the SVG removed — all inside one task, so nothing ever paints half-swapped.\n */\nimport { FChart, type FChartConfig } from './fchart.ts';\n\n/**\n * Mount a live `FChart` over the static SVG inside `container` and return it.\n * `config` is the same `{ series, data, options, annotations }` the server rendered from —\n * pass the same data so the first live frame matches the static image.\n * Works on a container with no SVG too (it simply mounts the chart).\n */\nexport function hydrate(container: HTMLElement, config: FChartConfig): FChart {\n  const svg = container.querySelector(':scope > svg');\n  // The static SVG's box is the only thing giving the container its height; pin it before the\n  // SVG leaves the flow, or the chart would measure a zero-height mount (and warn).\n  if (!container.style.height) {\n    const h = container.getBoundingClientRect().height;\n    if (h > 0) container.style.height = `${h}px`;\n  }\n  if (svg instanceof Element) {\n    const s = (svg as SVGElement).style;\n    s.position = 'absolute';\n    s.inset = '0';\n    if (getComputedStyle(container).position === 'static') container.style.position = 'relative';\n  }\n  const chart = new FChart(container, config);\n  chart.renderSync();\n  svg?.remove();\n  return chart;\n}\n","/**\n * Web-component wrapper — `<f-chart>` for zero-framework embeds (CMS blocks, dashboards).\n *\n * Registration is explicit (`defineFChart()`), and the element class is created lazily inside\n * it, so importing the barrel stays Node-safe (no `HTMLElement` at module scope) and\n * tree-shakeable. Light DOM, deliberately: the accessibility layer (live region, hidden table,\n * find-in-page ticks) must sit in the page's accessibility tree, not behind a shadow root.\n * Configuration is a property, not an attribute — configs carry functions (formatters), which\n * JSON attributes can't: `document.querySelector('f-chart').config = { series, data }`.\n */\nimport { FChart, sameConstructionOptions, type FChartConfig } from './fchart.ts';\n\n/** The `<f-chart>` element's public surface (the class itself is created in `defineFChart`). */\nexport interface FChartElement extends HTMLElement {\n  /** Assigning (re)configures the chart: in-place `update()` when construction options allow,\n   *  else a clean remount. Reading returns the last assigned config. */\n  config: FChartConfig | null;\n  /** The live chart instance while connected and configured, else null. */\n  readonly chart: FChart | null;\n}\n\n/**\n * Register the element (idempotent; default tag `f-chart`) and return its class.\n * Give the element a height (`f-chart { display:block; height:320px }`) like any chart mount.\n */\nexport function defineFChart(tag = 'f-chart'): CustomElementConstructor {\n  const existing = customElements.get(tag);\n  if (existing) return existing;\n\n  class FChartHTMLElement extends HTMLElement implements FChartElement {\n    private liveChart: FChart | null = null;\n    private current: FChartConfig | null = null;\n\n    get chart(): FChart | null {\n      return this.liveChart;\n    }\n\n    get config(): FChartConfig | null {\n      return this.current;\n    }\n\n    set config(next: FChartConfig | null) {\n      const prev = this.current;\n      this.current = next;\n      if (!this.isConnected || !next) {\n        this.teardown();\n        return;\n      }\n      if (this.liveChart && prev && sameConstructionOptions(prev.options, next.options)) {\n        this.liveChart.update(next);\n        return;\n      }\n      this.teardown();\n      this.mount();\n    }\n\n    connectedCallback(): void {\n      if (!this.style.display) this.style.display = 'block';\n      if (this.current) this.mount();\n    }\n\n    disconnectedCallback(): void {\n      this.teardown();\n    }\n\n    private mount(): void {\n      if (this.current) this.liveChart = new FChart(this, this.current);\n    }\n\n    private teardown(): void {\n      this.liveChart?.destroy();\n      this.liveChart = null;\n    }\n  }\n\n  customElements.define(tag, FChartHTMLElement);\n  return FChartHTMLElement;\n}\n","/**\n * Ready-made translations of the accessibility layer's fixed UI text — the EU/EAA audience's\n * most common locales. Each pack is a complete {@link FChartStrings}, typed so a missing key is\n * a compile error, and passed whole to `options.strings` (or spread + overridden per key).\n * Author content (series names, labels, formatted numbers) is the integrator's to localize;\n * these cover only the library's own connective prose (WCAG 3.1.2 Language of Parts).\n */\nimport type { FChartStrings } from './strings.ts';\n\nexport const stringsDE: FChartStrings = {\n  legendGroup: 'Datenreihen — aktivieren zum Ein- oder Ausblenden',\n  shown: 'eingeblendet',\n  hidden: 'ausgeblendet',\n  keyboardHelp:\n    'Pfeil links und rechts wechseln zwischen Datenpunkten; Pfeil auf und ab wechseln die ' +\n    'Datenreihe; Pos1 und Ende springen an die Enden; Umschalttaste für feine Schritte. ' +\n    'Plus und Minus zoomen; Escape blendet den Cursor aus. ' +\n    'Zur Prüfung mit dem Screenreader folgt eine Datentabelle.',\n  eventKeysHelp:\n    'Eckige Klammern springen zwischen Ereignismarkern; Enter wählt den fokussierten Marker aus.',\n  selected: 'ausgewählt',\n  chartName: '{name}. {series} Datenreihen mit je {points} Punkten. {help}',\n  tableCaption: '{caption} — {series} Datenreihen, {rows} Stichprobenzeilen im sichtbaren Bereich.',\n  summaryNoData: '{label}: keine Daten.',\n  summaryAllHidden: '{label}: {points} Punkte pro Datenreihe, alle Datenreihen ausgeblendet.',\n  summaryLine: '{label}: {points} Punkte pro Datenreihe von {span}. {parts}.',\n  summaryPart: '{name} reicht von {min} bis {max}, aktuell {last} ({dir})',\n  summaryEvents: '{count} Ereignisse: {labels}',\n  summarySpan: '{start} bis {end}',\n  trendUp: 'plus {pct} %',\n  trendDown: 'minus {pct} %',\n  trendFlat: 'unverändert',\n  pagerPrev: 'Zu früheren Daten schwenken',\n  pagerNext: 'Zu späteren Daten schwenken',\n  open: 'Eröffnung',\n  high: 'Hoch',\n  low: 'Tief',\n  close: 'Schluss',\n  exportCsv: 'Daten herunterladen (CSV)',\n};\n\nexport const stringsFR: FChartStrings = {\n  legendGroup: 'Séries — activer pour afficher ou masquer',\n  shown: 'affichée',\n  hidden: 'masquée',\n  keyboardHelp:\n    \"Les flèches gauche et droite passent d'un point à l'autre ; haut et bas changent de \" +\n    'série ; Début et Fin sautent aux extrémités ; maintenez Maj pour un pas fin. ' +\n    'Plus et moins zooment ; Échap efface le curseur. ' +\n    \"Un tableau de données échantillonné suit pour la lecture par lecteur d'écran.\",\n  eventKeysHelp:\n    \"Les touches crochets passent d'un marqueur d'événement à l'autre ; Entrée sélectionne le \" +\n    'marqueur en focus.',\n  selected: 'sélectionné',\n  chartName: '{name}. {series} séries de {points} points chacune. {help}',\n  tableCaption: '{caption} — {series} séries, {rows} lignes échantillonnées sur la plage visible.',\n  summaryNoData: '{label} : aucune donnée.',\n  summaryAllHidden: '{label} : {points} points par série, toutes les séries masquées.',\n  summaryLine: '{label} : {points} points par série de {span}. {parts}.',\n  summaryPart: '{name} varie de {min} à {max}, actuellement {last} ({dir})',\n  summaryEvents: '{count} événements : {labels}',\n  summarySpan: '{start} à {end}',\n  trendUp: 'en hausse de {pct} %',\n  trendDown: 'en baisse de {pct} %',\n  trendFlat: 'stable',\n  pagerPrev: 'Voir les données précédentes',\n  pagerNext: 'Voir les données suivantes',\n  open: 'ouverture',\n  high: 'plus haut',\n  low: 'plus bas',\n  close: 'clôture',\n  exportCsv: 'Télécharger les données (CSV)',\n};\n\nexport const stringsES: FChartStrings = {\n  legendGroup: 'Series — activar para mostrar u ocultar',\n  shown: 'visible',\n  hidden: 'oculta',\n  keyboardHelp:\n    'Las flechas izquierda y derecha se mueven entre muestras; arriba y abajo cambian de ' +\n    'serie; Inicio y Fin saltan a los extremos; mantenga Mayús para pasos finos. ' +\n    'Más y menos hacen zoom; Escape borra el cursor. ' +\n    'A continuación hay una tabla de datos muestreada para revisión con lector de pantalla.',\n  eventKeysHelp:\n    'Las teclas de corchete saltan entre marcadores de eventos; Intro selecciona el marcador ' +\n    'enfocado.',\n  selected: 'seleccionado',\n  chartName: '{name}. {series} series de {points} puntos cada una. {help}',\n  tableCaption: '{caption} — {series} series, {rows} filas muestreadas del rango visible.',\n  summaryNoData: '{label}: sin datos.',\n  summaryAllHidden: '{label}: {points} puntos por serie, todas las series ocultas.',\n  summaryLine: '{label}: {points} puntos por serie de {span}. {parts}.',\n  summaryPart: '{name} va de {min} a {max}, ahora {last} ({dir})',\n  summaryEvents: '{count} eventos: {labels}',\n  summarySpan: '{start} a {end}',\n  trendUp: 'sube {pct} %',\n  trendDown: 'baja {pct} %',\n  trendFlat: 'estable',\n  pagerPrev: 'Desplazar a datos anteriores',\n  pagerNext: 'Desplazar a datos posteriores',\n  open: 'apertura',\n  high: 'máximo',\n  low: 'mínimo',\n  close: 'cierre',\n  exportCsv: 'Descargar datos (CSV)',\n};\n","/**\n * Public server-side SVG render — `config + data → <svg>` in one call, no DOM, no canvas.\n *\n * `buildSVG` is the low-level primitive (the caller hand-assembles scales, ticks, pyramids, and\n * resolved series). `renderSVG` is the high-level entry an SSR app actually wants: hand it the\n * same `{ series, options }` config and `{ x, y }` data the live `FChart` takes, plus a size and\n * optional theme, and it assembles the scene and returns a standalone, themed, agent-readable SVG\n * string. Pure and Node-safe — it mirrors what `FChart.toSVG()` does, without constructing a chart.\n */\nimport {\n  ChartData,\n  DEFAULT_MARGINS,\n  resolveAnnotations,\n  resolveSeries,\n  type AnnotationSpec,\n  type FChartData,\n  type Margins,\n  type SeriesConfig,\n} from '../core/model.ts';\nimport { linearScale, logScale } from '../core/scales.ts';\nimport {\n  defaultFormatters,\n  effectiveTickCount,\n  logTicks,\n  niceTicks,\n  niceTimeTicks,\n} from '../core/ticks.ts';\nimport { buildSummary, describeSummary } from '../a11y/summary.ts';\nimport { buildSVG } from './svg-export.ts';\nimport { resolveTheme, type SvgTheme } from './svg-theme.ts';\n\n/** Chart-level options that affect a static SVG (the SVG-relevant subset of `FChartOptions`). */\nexport interface RenderSVGChartOptions {\n  ariaLabel?: string;\n  xLabel?: string;\n  yLabel?: string;\n  formatX?: (v: number) => string;\n  formatY?: (v: number) => string;\n  xTickCount?: number;\n  yTickCount?: number;\n  /** BCP-47 tag localizing the DEFAULT tick/value formatters via Intl (matches the live\n   *  chart's `locale` option). Explicit `formatX`/`formatY` always win; without a locale the\n   *  deterministic English defaults are unchanged. An invalid tag throws. */\n  locale?: string;\n  /** Treat x as integer indices (ticks step >= 1). Default false. */\n  xInteger?: boolean;\n  /** X-axis flavor. `'time'` treats x as epoch ms: calendar-boundary ticks + a date/clock\n   *  `formatX` default. Default `'linear'` (matches the live chart). */\n  xType?: 'linear' | 'time';\n  /** Y-axis scale. `'log'` (base 10) needs positive data; non-positive samples clamp to the\n   *  plot bottom. Default `'linear'` (matches the live chart). */\n  yScale?: 'linear' | 'log';\n  /** Fractional y-extent padding. Default 0.06 (matches the live chart). */\n  yPadding?: number;\n}\n\nexport interface RenderSVGOptions {\n  width: number;\n  height: number;\n  /** Color overrides merged onto {@link lightTheme}. Pass `darkTheme` for dark dashboards. */\n  theme?: Partial<SvgTheme>;\n  /** Embed the `ChartSummary` JSON so the static SVG stays machine-readable. Default true. */\n  embedData?: boolean;\n  /** Plot insets in px. Defaults to {@link DEFAULT_MARGINS}. */\n  margins?: Partial<Margins>;\n}\n\n/** Total y-array slots the resolved series consume (a candle takes 4: open/high/low/close). */\nfunction totalSlots(series: readonly { index: number; slots: number }[]): number {\n  const last = series[series.length - 1];\n  return last ? last.index + last.slots : 0;\n}\n\n/**\n * Render a line/area/candle chart to a standalone SVG string.\n *\n * @throws if `data.y` does not provide one array per series slot (candles need four).\n */\nexport function renderSVG(\n  config: { series: SeriesConfig[]; options?: RenderSVGChartOptions; annotations?: AnnotationSpec[] },\n  data: FChartData,\n  opts: RenderSVGOptions,\n): string {\n  const o = config.options ?? {};\n  const series = resolveSeries(config.series);\n  const annotations = resolveAnnotations(config.annotations ?? [], series);\n\n  const want = totalSlots(series);\n  if (data.y.length !== want) {\n    const candles = series.filter((s) => s.type === 'candle').length;\n    const hint = candles ? ` (${candles} candle series need 4 arrays each: open, high, low, close)` : '';\n    throw new Error(`fcharts: renderSVG — ${series.length} series need ${want} y arrays${hint}, got ${data.y.length}.`);\n  }\n\n  const cd = new ChartData(data);\n  const m: Margins = { ...DEFAULT_MARGINS, ...opts.margins };\n  const { width, height } = opts;\n\n  // X-domain: full extent, padded half a step when a candle is shown so edge candles render\n  // whole (parity with the live chart's auto xPad).\n  const [lo, hi] = cd.xExtent();\n  const hasCandle = series.some((s) => s.type === 'candle' && s.visible);\n  const xPad = hasCandle && cd.n >= 2 ? (hi - lo) / (cd.n - 1) / 2 : 0;\n  const domain: [number, number] = [lo - xPad, hi + xPad];\n\n  // Y-domain: slot-aware visibility mask (a candle spans 4 slots that share its visibility).\n  const visible: boolean[] = [];\n  for (const s of series) for (let k = 0; k < s.slots; k++) visible.push(s.visible);\n  const [yMin, yMax] = cd.yExtent(visible);\n  const log = o.yScale === 'log';\n  let yDomain: [number, number];\n  if (log) {\n    // Same positive-domain fitting as the live chart's rescaleY (log-space padding).\n    const yhi = yMax > 0 ? yMax : 1;\n    const ylo = yMin > 0 ? yMin : yhi / 10;\n    const lpad = (Math.log10(yhi) - Math.log10(ylo) || 1) * (o.yPadding ?? 0.06);\n    yDomain = [Math.pow(10, Math.log10(ylo) - lpad), Math.pow(10, Math.log10(yhi) + lpad)];\n  } else {\n    const yPad = (yMax - yMin) * (o.yPadding ?? 0.06);\n    yDomain = [yMin - yPad, yMax + yPad];\n  }\n\n  const xScale = linearScale(domain, [m.left, width - m.right]);\n  const yScale = (log ? logScale : linearScale)(yDomain, [height - m.bottom, m.top]);\n  const xCount = effectiveTickCount(o.xTickCount ?? 8, width - m.left - m.right, 64);\n  const yCount = effectiveTickCount(o.yTickCount ?? 6, height - m.top - m.bottom, 28);\n  const format = defaultFormatters(o.xType, o.locale);\n  const formatX = o.formatX ?? format.x;\n  const formatY = o.formatY ?? format.y;\n  const title = o.ariaLabel ?? 'Chart';\n  const summary = buildSummary(cd, series, title, annotations);\n\n  return buildSVG({\n    width,\n    height,\n    margins: m,\n    series,\n    data: cd,\n    xScale,\n    yScale,\n    domain,\n    xTicks:\n      o.xType === 'time'\n        ? niceTimeTicks(domain[0], domain[1], xCount)\n        : niceTicks(domain[0], domain[1], xCount, o.xInteger ? 1 : 0),\n    yTicks: log ? logTicks(yDomain[0], yDomain[1], yCount) : niceTicks(yDomain[0], yDomain[1], yCount),\n    formatX,\n    formatY,\n    title,\n    desc: describeSummary(summary, formatX, formatY),\n    xLabel: o.xLabel,\n    yLabel: o.yLabel,\n    annotations,\n    theme: resolveTheme(opts.theme),\n    summary: opts.embedData === false ? undefined : summary,\n  });\n}\n","/**\n * Donut / pie — categorical share-of-total as a pure SVG string (no DOM, Node-safe).\n *\n * Arcs are drawn the cheap way: concentric `<circle>` strokes sharing a center, each given a\n * `stroke-dasharray` of (arc, gap) and a `stroke-dashoffset` to place it — O(slices), fine for the\n * N <= ~30 a donut is legible at. Like every fcharts renderer it stays agent-readable: a sorted\n * shares table + a one-line `<desc>` (largest slice, headroom to an optional per-slice cap, HHI\n * concentration) and an embedded `ChartSummary`-shaped JSON block.\n */\nimport { DEFAULT_PALETTE } from '../core/model.ts';\nimport { resolveTheme, STATUS_COLORS, type SvgTheme } from './svg-theme.ts';\nimport { anchor, embedSummary, esc, n, svgDocument, text } from './svg-util.ts';\n\nexport interface DonutSlice {\n  label: string;\n  value: number;\n  /** Slice color; falls back to the contrast-checked {@link DEFAULT_PALETTE} by order. */\n  color?: string;\n  /**\n   * Drill-down target. When set, the slice arc and its legend row become a focusable `<a href>`\n   * (e.g. a `?protocol=…` filter link) — presentation only, the summary/`<desc>` are unchanged.\n   */\n  href?: string;\n}\n\nexport interface DonutOptions {\n  /** Square diameter of the donut, in px. The legend extends to its right. */\n  size: number;\n  theme?: Partial<SvgTheme>;\n  /** Accessible name / title. Default 'Share'. */\n  title?: string;\n  /** Big text in the hole (e.g. a count). */\n  centerLabel?: string;\n  /** Smaller text under `centerLabel`. */\n  centerSub?: string;\n  /** Per-slice cap as a percentage (e.g. 25 = 25%); over-cap slices are flagged. */\n  capPct?: number;\n  /** Render the legend column. Default true. */\n  legend?: boolean;\n  /** Embed the machine-readable JSON summary. Default true. */\n  embedData?: boolean;\n}\n\ninterface ResolvedSlice {\n  label: string;\n  value: number;\n  color: string;\n  pct: number;\n  overCap: boolean;\n  href?: string;\n}\n\nconst LEGEND_W = 184;\nconst ROW_H = 18;\nconst PAD = 8;\n\n/** Build a donut/pie chart as a standalone SVG string. */\nexport function buildDonutSVG(spec: { slices: readonly DonutSlice[] }, opts: DonutOptions): string {\n  const theme = resolveTheme(opts.theme);\n  const size = opts.size;\n  const title = opts.title ?? 'Share';\n  const total = spec.slices.reduce((sum, s) => sum + Math.max(0, s.value), 0);\n\n  const resolved: ResolvedSlice[] = spec.slices.map((s, i) => {\n    const pct = total > 0 ? (Math.max(0, s.value) / total) * 100 : 0;\n    return {\n      label: s.label,\n      value: s.value,\n      color: s.color || DEFAULT_PALETTE[i % DEFAULT_PALETTE.length],\n      pct,\n      overCap: opts.capPct !== undefined && pct > opts.capPct + 1e-9,\n      href: s.href,\n    };\n  });\n\n  const cx = size / 2;\n  const cy = size / 2;\n  const ring = size * 0.18;\n  const r = size / 2 - PAD - ring / 2;\n  const circ = 2 * Math.PI * r;\n\n  const parts: string[] = [];\n  // Faint full-ring track so an empty/partial donut still reads as a ring.\n  parts.push(\n    `<circle cx=\"${n(cx)}\" cy=\"${n(cy)}\" r=\"${n(r)}\" fill=\"none\" ` +\n      `stroke=\"${esc(theme.grid)}\" stroke-width=\"${n(ring)}\"/>`,\n  );\n\n  // Arc segments, clockwise from 12 o'clock (rotate the group -90°). The dash length and the\n  // running offset are accumulated from the SAME rounded arc value, so consecutive slices abut\n  // exactly instead of drifting into a sub-pixel seam after many slices.\n  let acc = 0;\n  const arcs: string[] = [];\n  for (const s of resolved) {\n    if (s.pct <= 0) continue;\n    const arc = Math.round((s.pct / 100) * circ * 10) / 10;\n    arcs.push(\n      anchor(\n        s.href,\n        `<circle cx=\"${n(cx)}\" cy=\"${n(cy)}\" r=\"${n(r)}\" fill=\"none\" stroke=\"${esc(s.color)}\" ` +\n          `stroke-width=\"${n(ring)}\" stroke-dasharray=\"${n(arc)} ${n(circ - arc)}\" ` +\n          `stroke-dashoffset=\"${n(-acc)}\"><title>${esc(s.label)}: ${s.pct.toFixed(1)}%</title></circle>`,\n      ),\n    );\n    acc += arc;\n  }\n  if (arcs.length) parts.push(`<g transform=\"rotate(-90 ${n(cx)} ${n(cy)})\">${arcs.join('')}</g>`);\n\n  if (opts.centerLabel) {\n    parts.push(\n      text(cx, cy + (opts.centerSub ? -2 : 4), esc(opts.centerLabel), {\n        fill: theme.tick, size: size * 0.13, anchor: 'middle', weight: 600,\n      }),\n    );\n  }\n  if (opts.centerSub) {\n    parts.push(\n      text(cx, cy + size * 0.085, esc(opts.centerSub), {\n        fill: theme.label, size: size * 0.055, anchor: 'middle',\n      }),\n    );\n  }\n\n  const legend = opts.legend !== false;\n  if (legend) parts.push(...legendRows(resolved, size, theme));\n\n  const width = legend ? size + LEGEND_W : size;\n  const height = legend ? Math.max(size, resolved.length * ROW_H + 2 * PAD) : size;\n\n  // toSorted() isn't in the ES2020 lib target; this sorts a fresh copy, so nothing is mutated.\n  // oxlint-disable-next-line unicorn/no-array-sort\n  const ordered = [...resolved].sort((a, b) => b.value - a.value);\n  const summary = donutSummary(title, total, ordered, opts.capPct);\n\n  return svgDocument({\n    width,\n    height,\n    title,\n    desc: donutDesc(title, ordered, opts.capPct),\n    body: parts.join(''),\n    extra: opts.embedData === false ? undefined : embedSummary(summary),\n  });\n}\n\nfunction legendRows(slices: readonly ResolvedSlice[], size: number, theme: SvgTheme): string[] {\n  const x = size + PAD;\n  return slices.map((s, i) => {\n    const y = PAD + i * ROW_H + 12;\n    const flag = s.overCap ? `<tspan fill=\"${esc(STATUS_COLORS.over)}\"> ⚑</tspan>` : '';\n    const row =\n      `<rect x=\"${n(x)}\" y=\"${n(y - 9)}\" width=\"10\" height=\"10\" rx=\"2\" fill=\"${esc(s.color)}\"/>` +\n      text(x + 16, y, `${esc(s.label)} — ${s.pct.toFixed(1)}%${flag}`, { fill: theme.tick });\n    return anchor(s.href, row);\n  });\n}\n\nfunction donutSummary(\n  label: string,\n  total: number,\n  ordered: readonly ResolvedSlice[],\n  capPct?: number,\n): object {\n  // Herfindahl–Hirschman concentration index over percentage shares (0–10000).\n  const hhi = ordered.reduce((sum, s) => sum + s.pct * s.pct, 0);\n  return {\n    type: 'donut',\n    label,\n    total,\n    capPct,\n    hhi: Math.round(hhi),\n    slices: ordered.map((s) => ({\n      label: s.label,\n      value: s.value,\n      pct: s.pct,\n      overCap: s.overCap,\n    })),\n  };\n}\n\nfunction donutDesc(label: string, ordered: readonly ResolvedSlice[], capPct?: number): string {\n  if (ordered.length === 0) return `${label}: no slices.`;\n  const top = ordered[0];\n  const headroom =\n    capPct !== undefined ? `; headroom to cap ${(capPct - top.pct).toFixed(1)} pts` : '';\n  const over = ordered.filter((s) => s.overCap).length;\n  const overNote = over > 0 ? `; ${over} over cap` : '';\n  return `${label}: ${ordered.length} slices; largest ${top.label} ${top.pct.toFixed(1)}%${headroom}${overNote}.`;\n}\n","/**\n * Scatter / dot-strip — numeric x against categorical rows, as a pure SVG string (no DOM).\n *\n * One dot per position (e.g. realized APY per book position), grouped into labelled rows (tiers),\n * with optional vertical reference lines (a benchmark, per-row minimums). Dots carry a status color\n * (ok / near / over) so the encoding isn't position-only. Agent-readable: per-row counts plus, for\n * each reference line, how many points fall below it — the outliers a reviewer actually wants.\n */\nimport { formatTick, niceTicks } from '../core/ticks.ts';\nimport { linearScale, type LinearScale } from '../core/scales.ts';\nimport { markColor, resolveTheme, type Status, type SvgTheme } from './svg-theme.ts';\nimport { bgRect, embedSummary, esc, n, svgDocument, text } from './svg-util.ts';\n\nexport interface ScatterPoint {\n  x: number;\n  /** Row (category) this point belongs to; must match one of `rows`. */\n  row: string;\n  status?: Status;\n  /** Explicit dot color (overrides `status`). */\n  color?: string;\n  /** Tooltip / accessible label for the point. */\n  label?: string;\n}\n\nexport interface ScatterRefLine {\n  x: number;\n  label: string;\n  color?: string;\n}\n\nexport interface ScatterOptions {\n  width: number;\n  theme?: Partial<SvgTheme>;\n  title?: string;\n  xLabel?: string;\n  formatX?: (v: number) => string;\n  /** Height of each row band, px. Default 34. */\n  rowHeight?: number;\n  /** Radius (px) of a transparent hover target placed over each dot so the `<title>` tooltip is\n   *  easy to trigger (the visible dot is only ~4px). Off by default; set e.g. 11 for fat fingers /\n   *  dense dot-strips. The visible dot is unchanged. */\n  hoverRadius?: number;\n  embedData?: boolean;\n}\n\nconst M = { left: 96, right: 16, top: 22, bottom: 28 };\n\n/** Geometry + paint shared by the part builders below. */\ninterface ScatterCtx {\n  theme: SvgTheme;\n  xScale: LinearScale;\n  width: number;\n  height: number;\n  rowH: number;\n}\n\nconst rowCenter = (ctx: ScatterCtx, i: number): number => M.top + i * ctx.rowH + ctx.rowH / 2;\n\n/** Build a scatter / dot-strip chart as a standalone SVG string. */\nexport function buildScatterSVG(\n  spec: { points: readonly ScatterPoint[]; rows: readonly string[]; refLines?: readonly ScatterRefLine[] },\n  opts: ScatterOptions,\n): string {\n  const theme = resolveTheme(opts.theme);\n  const title = opts.title ?? 'Scatter';\n  const rowH = opts.rowHeight ?? 34;\n  const refLines = spec.refLines ?? [];\n  const width = opts.width;\n  const height = M.top + Math.max(1, spec.rows.length) * rowH + M.bottom;\n\n  // X-domain across points + reference lines, padded 6%.\n  const xs = [...spec.points.map((p) => p.x), ...refLines.map((r) => r.x)];\n  let lo = xs.length ? Math.min(...xs) : 0;\n  let hi = xs.length ? Math.max(...xs) : 1;\n  if (lo === hi) { lo -= 1; hi += 1; }\n  const pad = (hi - lo) * 0.06;\n  const domain: [number, number] = [lo - pad, hi + pad];\n  const xScale = linearScale(domain, [M.left, width - M.right]);\n  const ctx: ScatterCtx = { theme, xScale, width, height, rowH };\n  const rowIndex = new Map(spec.rows.map((r, i) => [r, i]));\n\n  // Points for an undeclared row are dropped (fail-soft); `valid` is the single rendered set the\n  // summary also accounts over, so total / per-row counts / below-ref counts stay consistent.\n  const valid = spec.points.filter((p) => rowIndex.has(p.row));\n\n  const parts: string[] = [\n    bgRect(width, height, theme.bg),\n    ...axisParts(ctx, domain, opts.formatX ?? formatTick, opts.xLabel),\n    ...rowParts(ctx, spec.rows),\n    ...refLineParts(ctx, refLines),\n    ...dotParts(ctx, valid, rowIndex, opts.hoverRadius),\n  ];\n\n  const summary = scatterSummary(title, valid, spec.rows, refLines);\n  return svgDocument({\n    width,\n    height,\n    title,\n    desc: scatterDesc(title, summary.total, spec.rows.length, summary.refLines),\n    body: parts.join(''),\n    extra: opts.embedData === false ? undefined : embedSummary(summary),\n  });\n}\n\n/** Vertical gridlines at the x ticks, tick labels, and the optional x-axis title. */\nfunction axisParts(\n  ctx: ScatterCtx,\n  domain: [number, number],\n  formatX: (v: number) => string,\n  xLabel?: string,\n): string[] {\n  const { theme, xScale, width, height } = ctx;\n  const out: string[] = [];\n  const ticks = niceTicks(domain[0], domain[1], 6);\n  let grid = '';\n  for (const t of ticks) {\n    grid += `M${n(xScale(t))},${n(M.top)}V${n(height - M.bottom)}`;\n  }\n  out.push(`<path d=\"${grid}\" stroke=\"${esc(theme.grid)}\" stroke-width=\"1\" fill=\"none\"/>`);\n  for (const t of ticks) {\n    out.push(text(xScale(t), height - M.bottom + 16, esc(formatX(t)), { fill: theme.tick, anchor: 'middle' }));\n  }\n  if (xLabel) {\n    out.push(text(width - M.right, height - M.bottom + 16, esc(xLabel), { fill: theme.label, size: 10, anchor: 'end' }));\n  }\n  return out;\n}\n\n/** Row labels (left gutter) + faint separators between row bands. */\nfunction rowParts(ctx: ScatterCtx, rows: readonly string[]): string[] {\n  const { theme, width } = ctx;\n  const out: string[] = [];\n  rows.forEach((row, i) => {\n    out.push(text(M.left - 8, rowCenter(ctx, i) + 4, esc(row), { fill: theme.tick, anchor: 'end' }));\n    if (i > 0) {\n      const y = M.top + i * ctx.rowH;\n      out.push(\n        `<line x1=\"${n(M.left)}\" y1=\"${n(y)}\" x2=\"${n(width - M.right)}\" ` +\n          `y2=\"${n(y)}\" stroke=\"${esc(theme.grid)}\" stroke-width=\"1\"/>`,\n      );\n    }\n  });\n  return out;\n}\n\n/** Vertical reference lines + their labels above the plot. */\nfunction refLineParts(ctx: ScatterCtx, refLines: readonly ScatterRefLine[]): string[] {\n  const { theme, xScale, height } = ctx;\n  const out: string[] = [];\n  for (const ref of refLines) {\n    const px = xScale(ref.x);\n    const color = ref.color || theme.label;\n    out.push(\n      `<line x1=\"${n(px)}\" y1=\"${n(M.top)}\" x2=\"${n(px)}\" y2=\"${n(height - M.bottom)}\" ` +\n        `stroke=\"${esc(color)}\" stroke-width=\"1\" stroke-dasharray=\"4 3\"/>`,\n      text(px, M.top - 6, esc(ref.label), { fill: color, size: 10, anchor: 'middle' }),\n    );\n  }\n  return out;\n}\n\n/** Dots, with small deterministic vertical jitter so co-located points in a row don't fully stack. */\nfunction dotParts(\n  ctx: ScatterCtx,\n  points: readonly ScatterPoint[],\n  rowIndex: Map<string, number>,\n  hoverRadius?: number,\n): string[] {\n  const { theme, xScale } = ctx;\n  const out: string[] = [];\n  const perRow = new Map<string, number>();\n  for (const p of points) {\n    const ri = rowIndex.get(p.row) ?? 0;\n    const seen = perRow.get(p.row) ?? 0;\n    perRow.set(p.row, seen + 1);\n    const jitter = ((seen % 5) - 2) * 4;\n    const cx = xScale(p.x);\n    const cy = rowCenter(ctx, ri) + jitter;\n    const color = markColor(p.color, p.status);\n    const tip = p.label ? `<title>${esc(p.label)}</title>` : '';\n    const hoverR = hoverRadius && hoverRadius > 4 ? hoverRadius : 0;\n    // With a hover target: the visible dot keeps its size; a transparent circle on top carries the\n    // <title> over a larger, easy-to-hit area. Without one: the dot itself holds the <title> (default).\n    out.push(\n      `<circle cx=\"${n(cx)}\" cy=\"${n(cy)}\" r=\"4\" fill=\"${esc(color)}\" ` +\n        `fill-opacity=\"0.85\" stroke=\"${esc(theme.bg)}\" stroke-width=\"0.75\">${hoverR ? '' : tip}</circle>`,\n    );\n    if (hoverR) {\n      // `fc-hit` + `data-fc-swatch` are the contract `attachReadout()` reads to show a styled DOM\n      // tooltip (the dot's color + the `<title>` text); the `<title>` stays as the no-JS fallback.\n      out.push(\n        `<circle class=\"fc-hit\" data-fc-swatch=\"${esc(color)}\" cx=\"${n(cx)}\" cy=\"${n(cy)}\" ` +\n          `r=\"${n(hoverR)}\" fill=\"${esc(theme.bg)}\" fill-opacity=\"0\" pointer-events=\"all\">${tip}</circle>`,\n      );\n    }\n  }\n  return out;\n}\n\ninterface RefSummary {\n  label: string;\n  x: number;\n  below: number;\n}\n\nfunction scatterSummary(\n  label: string,\n  points: readonly ScatterPoint[],\n  rows: readonly string[],\n  refLines: readonly ScatterRefLine[],\n): { type: 'scatter'; label: string; total: number; rows: { row: string; count: number }[]; refLines: RefSummary[] } {\n  // `points` is already filtered to declared rows, so every count below is over the same set.\n  const counts = new Map<string, number>();\n  for (const p of points) counts.set(p.row, (counts.get(p.row) ?? 0) + 1);\n  return {\n    type: 'scatter',\n    label,\n    total: points.length,\n    rows: rows.map((row) => ({ row, count: counts.get(row) ?? 0 })),\n    refLines: refLines.map((ref) => ({\n      label: ref.label,\n      x: ref.x,\n      below: points.filter((p) => p.x < ref.x).length,\n    })),\n  };\n}\n\nfunction scatterDesc(\n  label: string,\n  total: number,\n  rowCount: number,\n  refs: readonly RefSummary[],\n): string {\n  const base = `${label}: ${total} points across ${rowCount} rows`;\n  if (refs.length === 0) return `${base}.`;\n  // toSorted() isn't in the ES2020 lib target; this sorts a fresh copy, so nothing is mutated.\n  // oxlint-disable-next-line unicorn/no-array-sort\n  const worst = [...refs].sort((a, b) => b.below - a.below)[0];\n  return `${base}; ${worst.below} below ${worst.label}.`;\n}\n","/**\n * Sparkline — an inline micro-trend as a pure SVG string (no DOM, transparent background).\n *\n * Deliberately minimal: no axes, legend, or interactive a11y chrome (the full `FChart` is the\n * wrong tool for a 56×18 thumbnail). It keeps just enough to not be invisible to assistive tech —\n * a `role=\"img\"` with an `aria-label` stating the direction and delta — and colors the optional\n * delta label by the SAME up/down/flat classifier the chart summary uses, so a wall of KPI\n * sparklines reads consistently.\n */\nimport { trendOf } from '../a11y/summary.ts';\nimport { STATUS_COLORS, resolveTheme, type SvgTheme } from './svg-theme.ts';\nimport { esc, n, svgRoot, text } from './svg-util.ts';\n\nexport interface SparklineOptions {\n  width: number;\n  height: number;\n  /** Line color. Default: a neutral blue (use `colorByTrend` to color by direction instead). */\n  color?: string;\n  /** Color the line green/red/gray by overall direction (last vs first). Default false. */\n  colorByTrend?: boolean;\n  /** Fill the area under the line. Default false. */\n  area?: boolean;\n  /** Draw a horizontal reference rule at this value. */\n  baseline?: number;\n  /** Append the last-vs-first delta as a colored label to the right. Default false. */\n  showDelta?: boolean;\n  /** Format the delta label value. Default: signed, 1 decimal. */\n  formatDelta?: (deltaPct: number) => string;\n  theme?: Partial<SvgTheme>;\n  /** Accessible-label prefix. Default 'Trend'. */\n  label?: string;\n}\n\nconst INSET = 2;\nconst TREND_COLOR = { up: STATUS_COLORS.ok, down: STATUS_COLORS.over, flat: '#64748b' } as const;\n\n/** Build an inline sparkline as a standalone SVG string. */\nexport function buildSparklineSVG(values: readonly number[], opts: SparklineOptions): string {\n  const theme = resolveTheme(opts.theme);\n  const { width, height } = opts;\n  const finite = values.filter((v) => Number.isFinite(v));\n  const first = finite[0] ?? 0;\n  const last = finite[finite.length - 1] ?? 0;\n  const deltaPct = first !== 0 ? ((last - first) / Math.abs(first)) * 100 : 0;\n  const trend = trendOf(deltaPct);\n  const lineColor = opts.color ?? (opts.colorByTrend ? TREND_COLOR[trend] : '#0284c7');\n\n  // Reserve room on the right for the delta label when shown.\n  const deltaText = opts.showDelta\n    ? (opts.formatDelta ?? defaultDelta)(deltaPct)\n    : '';\n  const labelW = deltaText ? deltaText.length * 6.5 + 6 : 0;\n  // Keep a usable drawing region even if the delta label is wide relative to the SVG.\n  const plotW = Math.max(8, width - labelW);\n\n  const parts: string[] = [];\n  if (values.length >= 1) {\n    let min = Infinity;\n    let max = -Infinity;\n    for (const v of values) {\n      if (!Number.isFinite(v)) continue;\n      if (v < min) min = v;\n      if (v > max) max = v;\n    }\n    if (min === Infinity) { min = 0; max = 1; }\n    if (min === max) { min -= 1; max += 1; }\n    const span = max - min;\n    const xAt = (i: number): number =>\n      values.length === 1 ? plotW / 2 : INSET + (i / (values.length - 1)) * (plotW - 2 * INSET);\n    const yAt = (v: number): number => INSET + (1 - (v - min) / span) * (height - 2 * INSET);\n\n    if (opts.baseline !== undefined && opts.baseline >= min && opts.baseline <= max) {\n      const by = yAt(opts.baseline);\n      parts.push(\n        `<line x1=\"${n(INSET)}\" y1=\"${n(by)}\" x2=\"${n(plotW - INSET)}\" y2=\"${n(by)}\" ` +\n          `stroke=\"${esc(theme.grid)}\" stroke-width=\"1\" stroke-dasharray=\"2 2\"/>`,\n      );\n    }\n\n    let d = '';\n    let firstFinite = -1;\n    let lastFinite = -1;\n    values.forEach((v, i) => {\n      if (!Number.isFinite(v)) return;\n      if (firstFinite < 0) firstFinite = i;\n      lastFinite = i;\n      d += `${d ? 'L' : 'M'}${n(xAt(i))},${n(yAt(v))}`;\n    });\n    if (opts.area && d) {\n      // Close under the drawn line (first/last FINITE vertex), not index 0/last, so a non-finite\n      // endpoint doesn't stretch the fill baseline past the actual data.\n      const base = yAt(min);\n      parts.push(\n        `<path d=\"${d}L${n(xAt(lastFinite))},${n(base)}L${n(xAt(firstFinite))},${n(base)}Z\" ` +\n          `fill=\"${esc(lineColor)}\" fill-opacity=\"0.15\" stroke=\"none\"/>`,\n      );\n    }\n    if (d) {\n      parts.push(`<path d=\"${d}\" fill=\"none\" stroke=\"${esc(lineColor)}\" stroke-width=\"1.5\" stroke-linejoin=\"round\"/>`);\n    }\n  }\n\n  if (deltaText) {\n    parts.push(\n      text(width - 2, height / 2 + 4, esc(deltaText), {\n        fill: TREND_COLOR[trend], anchor: 'end', weight: 600,\n      }),\n    );\n  }\n\n  // svgRoot mirrors the aria-label into a <title> so older AT that ignores aria-label on inline\n  // SVG still gets the trend (matches the title/desc contract of the other primitives).\n  const ariaLabel = `${opts.label ?? 'Trend'}: ${trend} ${Math.abs(deltaPct).toFixed(1)}%`;\n  return svgRoot({ width, height, label: ariaLabel, body: parts.join('') });\n}\n\nfunction defaultDelta(deltaPct: number): string {\n  return `${deltaPct >= 0 ? '+' : ''}${deltaPct.toFixed(1)}%`;\n}\n","/**\n * Horizontal bars / progress-with-target — a pure SVG string (no DOM).\n *\n * One primitive covers the three dashboard flavors the Hecate desk hand-rolls: allocation\n * breakdown bars (value + cap/target marker + over/near/ok status), P&L attribution bars (signed\n * magnitude about a zero baseline, via `signed`), and a KPI cap bar (value vs a limit marker).\n * Status color comes from the contrast-checked ok/near/over palette and, when omitted, is derived\n * from the value's position against its `limit`, so the bar reads without a legend. Agent-readable:\n * a rows table (value, limit, % of limit, status) + a one-line `<desc>`.\n */\nimport { markColor, resolveTheme, type Status, type SvgTheme } from './svg-theme.ts';\nimport { anchor, bgRect, embedSummary, esc, n, svgDocument, text } from './svg-util.ts';\n\nexport interface BarRow {\n  label: string;\n  value: number;\n  /** Cap / target marker, drawn as a vertical tick on the bar. */\n  limit?: number;\n  /** Explicit status; when omitted and `limit` is set, derived from value vs limit. */\n  status?: Status;\n  /** Explicit bar color (overrides status). */\n  color?: string;\n  /**\n   * Drill-down target. When set, the row label becomes a focusable `<a href>` (e.g. a `?chain=…`\n   * filter link) — presentation only, the summary/`<desc>` are unchanged.\n   */\n  href?: string;\n}\n\nexport interface BarsOptions {\n  width: number;\n  theme?: Partial<SvgTheme>;\n  title?: string;\n  /** Format bar values for the right-hand label. Default: `String`. */\n  formatValue?: (v: number) => string;\n  /** Bars extend left/right from a zero baseline (P&L attribution). Default false. */\n  signed?: boolean;\n  /** Row band height, px. Default 28. */\n  rowHeight?: number;\n  embedData?: boolean;\n}\n\nconst M = { left: 132, right: 60, top: 8, bottom: 8 };\n\n/** Status from a value's position against its limit (>=100% over, >=90% near, else ok). */\nfunction deriveStatus(value: number, limit: number): Status {\n  if (limit <= 0) return 'ok';\n  const ratio = value / limit;\n  if (ratio > 1) return 'over';\n  if (ratio >= 0.9) return 'near';\n  return 'ok';\n}\n\n/** Build a horizontal bar / progress chart as a standalone SVG string. */\nexport function buildBarsSVG(spec: { rows: readonly BarRow[] }, opts: BarsOptions): string {\n  const theme = resolveTheme(opts.theme);\n  const title = opts.title ?? 'Bars';\n  const fmt = opts.formatValue ?? ((v: number) => String(v));\n  const rowH = opts.rowHeight ?? 28;\n  const width = opts.width;\n  const height = M.top + Math.max(1, spec.rows.length) * rowH + M.bottom;\n\n  // Domain across values + limits.\n  const all: number[] = [];\n  for (const r of spec.rows) {\n    all.push(r.value);\n    if (r.limit !== undefined) all.push(r.limit);\n  }\n  const dataMax = all.length ? Math.max(...all) : 1;\n  const dataMin = all.length ? Math.min(...all) : 0;\n  const domMax = opts.signed ? Math.max(0, dataMax) : Math.max(dataMax, 0);\n  const domMin = opts.signed ? Math.min(0, dataMin) : 0;\n  const span = domMax - domMin || 1;\n  const plotL = M.left;\n  const plotR = width - M.right;\n  const xAt = (v: number): number => plotL + ((v - domMin) / span) * (plotR - plotL);\n  const xZero = xAt(0);\n\n  const parts: string[] = [bgRect(width, height, theme.bg)];\n\n  // Zero baseline for signed mode.\n  if (opts.signed) {\n    parts.push(\n      `<line x1=\"${n(xZero)}\" y1=\"${n(M.top)}\" x2=\"${n(xZero)}\" y2=\"${n(height - M.bottom)}\" ` +\n        `stroke=\"${esc(theme.axis)}\" stroke-width=\"1\"/>`,\n    );\n  }\n\n  spec.rows.forEach((row, i) => {\n    const cy = M.top + i * rowH + rowH / 2;\n    const bh = rowH * 0.55;\n    const status = row.status ?? (row.limit !== undefined ? deriveStatus(row.value, row.limit) : undefined);\n    const color = markColor(row.color, status);\n\n    // Track.\n    parts.push(\n      `<rect x=\"${n(plotL)}\" y=\"${n(cy - bh / 2)}\" width=\"${n(plotR - plotL)}\" height=\"${n(bh)}\" ` +\n        `rx=\"2\" fill=\"${esc(theme.grid)}\" fill-opacity=\"0.5\"/>`,\n    );\n    // Bar (from zero to value; handles negatives in signed mode). Clamp to the track so an\n    // out-of-domain value — e.g. a negative in unsigned mode, where domMin is 0 — never paints\n    // into the label gutter; it just renders as an empty/full bar.\n    const x0 = Math.max(plotL, Math.min(xZero, xAt(row.value)));\n    const x1 = Math.min(plotR, Math.max(xZero, xAt(row.value)));\n    parts.push(\n      `<rect x=\"${n(x0)}\" y=\"${n(cy - bh / 2)}\" width=\"${n(Math.max(0, x1 - x0))}\" height=\"${n(bh)}\" ` +\n        `rx=\"2\" fill=\"${esc(color)}\"/>`,\n    );\n    // Limit / target marker.\n    if (row.limit !== undefined) {\n      const lx = xAt(row.limit);\n      parts.push(\n        `<line x1=\"${n(lx)}\" y1=\"${n(cy - bh / 2 - 2)}\" x2=\"${n(lx)}\" y2=\"${n(cy + bh / 2 + 2)}\" ` +\n          `stroke=\"${esc(theme.tick)}\" stroke-width=\"2\"/>`,\n      );\n    }\n    // Row label (left, drill-down link when href set) + value (right margin).\n    parts.push(\n      anchor(row.href, text(4, cy + 4, esc(row.label), { fill: theme.tick })),\n      text(width - 4, cy + 4, esc(fmt(row.value)), { fill: theme.tick, anchor: 'end', weight: 600 }),\n    );\n  });\n\n  const summary = barsSummary(title, spec.rows, opts.signed ?? false);\n  return svgDocument({\n    width,\n    height,\n    title,\n    desc: barsDesc(title, summary.rows),\n    body: parts.join(''),\n    extra: opts.embedData === false ? undefined : embedSummary(summary),\n  });\n}\n\ninterface BarSummaryRow {\n  label: string;\n  value: number;\n  limit?: number;\n  pctOfLimit?: number;\n  status?: Status;\n}\n\nfunction barsSummary(\n  label: string,\n  rows: readonly BarRow[],\n  signed: boolean,\n): { type: 'bars'; label: string; signed: boolean; rows: BarSummaryRow[] } {\n  return {\n    type: 'bars',\n    label,\n    signed,\n    rows: rows.map((r) => {\n      const status = r.status ?? (r.limit !== undefined ? deriveStatus(r.value, r.limit) : undefined);\n      return {\n        label: r.label,\n        value: r.value,\n        limit: r.limit,\n        // Keyed on the same `limit !== undefined` guard as `status`, but skip the degenerate\n        // zero limit (a 0% target) to avoid a divide-by-zero Infinity in the agent-readable JSON.\n        pctOfLimit: r.limit !== undefined && r.limit !== 0 ? (r.value / r.limit) * 100 : undefined,\n        status,\n      };\n    }),\n  };\n}\n\nfunction barsDesc(label: string, rows: readonly BarSummaryRow[]): string {\n  if (rows.length === 0) return `${label}: no rows.`;\n  const over = rows.filter((r) => r.status === 'over').length;\n  const overNote = over > 0 ? `; ${over} over target` : '';\n  return `${label}: ${rows.length} bars${overNote}.`;\n}\n","/**\n * Thin inline progress / gauge bar — a pure SVG string (no DOM), the single-row cousin of\n * `buildBarsSVG` for a KPI card's 4px \"% of cap\" / \"coverage %\" meter.\n *\n * Deliberately minimal: one track, one fill, an optional cap/target tick — no labels, legend, or\n * axis (those belong on `buildBarsSVG`, a multi-row bar *chart*). Like the sparkline it keeps just\n * enough to not be invisible to assistive tech: a `role=\"img\"` + `aria-label` + `<title>` stating\n * the percentage (and the cap, when set). It does not embed the JSON summary — at 4px tall it's a\n * micro-element, not a queryable chart.\n */\nimport { resolveTheme, type SvgTheme } from './svg-theme.ts';\nimport { esc, n, svgRoot } from './svg-util.ts';\n\nexport interface ProgressOptions {\n  width: number;\n  /** Track height in px. Default 4 (the thin inline KPI bar). */\n  height?: number;\n  /** The full-track value (the 100% denominator). Default 100. */\n  max?: number;\n  /** Optional cap/target, drawn as a vertical tick at this value (same units as `value`/`max`). */\n  limit?: number;\n  /**\n   * Fill color. Default a neutral blue. Pass a `STATUS_COLORS` value (or your own) for over/near/ok\n   * semantics — this primitive stays minimal and does not derive status itself.\n   */\n  color?: string;\n  theme?: Partial<SvgTheme>;\n  /** Accessible-label prefix. Default 'Progress'. */\n  label?: string;\n}\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\n\n/** Round a percentage to at most 1 decimal (a trailing `.0` is dropped by `Number`). */\nconst pctStr = (p: number): string => String(Math.round(p * 10) / 10);\n\n/** Build a thin inline progress / gauge bar as a standalone SVG string. */\nexport function buildProgressSVG(value: number, opts: ProgressOptions): string {\n  const theme = resolveTheme(opts.theme);\n  const width = opts.width;\n  const height = opts.height ?? 4;\n  const max = opts.max ?? 100;\n  const color = opts.color ?? '#0284c7';\n  const frac = max > 0 ? clamp01(value / max) : 0;\n  const rx = Math.min(height / 2, width / 2);\n\n  const parts: string[] = [\n    // Track (the unfilled remainder).\n    `<rect x=\"0\" y=\"0\" width=\"${n(width)}\" height=\"${n(height)}\" rx=\"${n(rx)}\" ` +\n      `fill=\"${esc(theme.grid)}\" fill-opacity=\"0.5\"/>`,\n  ];\n  // Fill from the left, true width (no min-cap inflation — a 0 value draws nothing, a tiny value a\n  // tiny sliver, so the bar never over-reports). The renderer clamps `rx` to half the fill width,\n  // so a partial fill reads as a rounded pill.\n  if (frac > 0) {\n    parts.push(\n      `<rect x=\"0\" y=\"0\" width=\"${n(frac * width)}\" height=\"${n(height)}\" rx=\"${n(rx)}\" ` +\n        `fill=\"${esc(color)}\"/>`,\n    );\n  }\n  // Cap / target tick.\n  if (opts.limit !== undefined) {\n    const lx = clamp01(max > 0 ? opts.limit / max : 0) * width;\n    parts.push(\n      `<line x1=\"${n(lx)}\" y1=\"0\" x2=\"${n(lx)}\" y2=\"${n(height)}\" ` +\n        `stroke=\"${esc(theme.tick)}\" stroke-width=\"1.5\"/>`,\n    );\n  }\n\n  // aria-label reports the TRUE percentage (may exceed 100% even though the fill is clamped), so an\n  // over-cap meter is announced as over.\n  const pct = max > 0 ? (value / max) * 100 : 0;\n  const cap =\n    opts.limit !== undefined && max > 0 ? ` (cap ${pctStr((opts.limit / max) * 100)}%)` : '';\n  // svgRoot mirrors the aria-label into a <title> so older AT that ignores aria-label on inline\n  // SVG still reads the value (matches the title contract of the sparkline).\n  const ariaLabel = `${opts.label ?? 'Progress'}: ${pctStr(pct)}%${cap}`;\n  return svgRoot({ width, height, label: ariaLabel, body: parts.join('') });\n}\n","/**\n * Matrix heatmap — a rows × cols grid of value-colored cells, as a pure SVG string (no DOM).\n *\n * One cell per (row, col); the fill is a linear-interpolated point on a two-stop sequential ramp\n * spanning the min/max of the cell values, so magnitude reads as color intensity. A cell absent\n * from the data is drawn as a faint outlined slot, not a zero — missing data and a low value stay\n * distinct. Every cell keeps its outline so a pale low cell still reads on either theme, and the\n * value lives in the cell `<title>` + the embedded JSON, so nothing is color-only. Agent-readable:\n * the full cell table with the domain min/max + a one-line `<desc>` naming the peak cell.\n */\nimport { resolveTheme, type SvgTheme } from './svg-theme.ts';\nimport { anchor, bgRect, embedSummary, esc, n, svgDocument, text } from './svg-util.ts';\n\nexport interface HeatmapCell {\n  row: string;\n  col: string;\n  value: number;\n  /** Overrides the default \"row × col: value\" cell tooltip. */\n  label?: string;\n  /** Drill-down target; wraps the cell in a focusable `<a href>` (presentation only). */\n  href?: string;\n}\n\nexport interface HeatmapOptions {\n  width: number;\n  theme?: Partial<SvgTheme>;\n  /** Accessible name / title. Default 'Heatmap'. */\n  title?: string;\n  /** Height of each cell row, px. Default 22. */\n  cellHeight?: number;\n  /** Format cell values for the cell `<title>` + the legend. Default `String`. */\n  formatValue?: (v: number) => string;\n  /** Two-stop sequential ramp [lowColor, highColor]; cells interpolate linearly in sRGB.\n   *  Default a light-blue → dark-blue pair readable on both themes (paired with the cell outline). */\n  colors?: readonly [string, string];\n  embedData?: boolean;\n}\n\n/** Default sequential ramp: pale blue → dark blue. The per-cell grid outline keeps a faint low\n *  cell legible on a white background; the saturated high end reads on the dark theme. */\nconst DEFAULT_COLORS: readonly [string, string] = ['#dbeafe', '#1d4ed8'];\n\nconst M = { left: 120, right: 16, top: 30, bottom: 10 };\nconst LEGEND = { gap: 18, barW: 160, barH: 10, labelH: 16, steps: 24 };\n\n/** Map key for the (row, col) cell lookup; NUL-separated so no label pair can collide. */\nconst cellKey = (row: string, col: string): string => `${row}\\u0000${col}`;\n\ninterface Domain {\n  min: number;\n  max: number;\n  peak: HeatmapCell | null;\n  hasData: boolean;\n}\n\n/** Geometry + paint shared by the part builders. */\ninterface HeatCtx {\n  theme: SvgTheme;\n  plotL: number;\n  plotR: number;\n  cellW: number;\n  cellH: number;\n  colors: readonly [string, string];\n}\n\n/** The declared axes + the rendered-cell lookup + the value domain — the one set every part reads. */\ninterface Grid {\n  rows: readonly string[];\n  cols: readonly string[];\n  lookup: Map<string, HeatmapCell>;\n  dom: Domain;\n}\n\n/** Parse an `#rgb` / `#rrggbb` color to [r,g,b] 0–255, or null when it isn't a hex literal. */\nfunction parseHex(c: string): [number, number, number] | null {\n  const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(c.trim());\n  if (!m) return null;\n  const h = m[1].length === 3 ? m[1].replace(/./g, (d) => d + d) : m[1];\n  return [\n    Number.parseInt(h.slice(0, 2), 16),\n    Number.parseInt(h.slice(2, 4), 16),\n    Number.parseInt(h.slice(4, 6), 16),\n  ];\n}\n\n/** Linear sRGB interpolation between two hex colors. Falls back to the nearer endpoint for a\n *  non-hex ramp (interpolation needs channel values a plain color string can't provide). */\nfunction lerpColor(a: string, b: string, t: number): string {\n  const ca = parseHex(a);\n  const cb = parseHex(b);\n  if (!ca || !cb) return t < 0.5 ? a : b;\n  const hex = (i: number): string =>\n    Math.round(ca[i] + (cb[i] - ca[i]) * t).toString(16).padStart(2, '0');\n  return `#${hex(0)}${hex(1)}${hex(2)}`;\n}\n\n/** A value's fill on the ramp. The endpoints return the exact ramp colors (so the min cell is\n *  colors[0], the max colors[1]); a degenerate single-value domain maps to the ramp midpoint. */\nfunction cellFill(value: number, dom: Domain, colors: readonly [string, string]): string {\n  if (dom.min === dom.max) return lerpColor(colors[0], colors[1], 0.5);\n  const t = (value - dom.min) / (dom.max - dom.min);\n  if (t <= 0) return colors[0];\n  if (t >= 1) return colors[1];\n  return lerpColor(colors[0], colors[1], t);\n}\n\n/** Min/max/peak over the rendered cells (empty → a zero domain flagged `hasData: false`). */\nfunction domainOf(valid: readonly HeatmapCell[]): Domain {\n  if (valid.length === 0) return { min: 0, max: 0, peak: null, hasData: false };\n  let min = Infinity;\n  let max = -Infinity;\n  let peak = valid[0];\n  for (const c of valid) {\n    if (c.value < min) min = c.value;\n    if (c.value > max) max = c.value;\n    if (c.value > peak.value) peak = c;\n  }\n  return { min, max, peak, hasData: true };\n}\n\n/** Cell width, document height, and the legend's top edge for the given axes counts. */\nfunction layout(width: number, rows: number, cols: number, cellH: number, hasData: boolean): {\n  cellW: number;\n  height: number;\n  legendTop: number;\n} {\n  const cellW = cols > 0 ? Math.max(0, width - M.left - M.right) / cols : 0;\n  const gridBottom = M.top + rows * cellH;\n  const legendTop = gridBottom + LEGEND.gap;\n  const height = hasData ? legendTop + LEGEND.barH + LEGEND.labelH : gridBottom + M.bottom;\n  return { cellW, height, legendTop };\n}\n\n/** Grid cells: a filled, outlined rect where a value exists, else a faint outline-only slot. */\nfunction gridParts(ctx: HeatCtx, grid: Grid, fmt: (v: number) => string): string[] {\n  const { theme, plotL, cellW, cellH, colors } = ctx;\n  const out: string[] = [];\n  grid.rows.forEach((row, ri) => {\n    const y = M.top + ri * cellH;\n    grid.cols.forEach((col, ci) => {\n      const geom = `x=\"${n(plotL + ci * cellW)}\" y=\"${n(y)}\" width=\"${n(cellW)}\" height=\"${n(cellH)}\"`;\n      const cell = grid.lookup.get(cellKey(row, col));\n      if (!cell) {\n        // Missing data is not zero — an unfilled, faintly outlined slot.\n        out.push(`<rect ${geom} fill=\"none\" stroke=\"${esc(theme.grid)}\" stroke-width=\"1\"/>`);\n        return;\n      }\n      const tip = cell.label ?? `${row} × ${col}: ${fmt(cell.value)}`;\n      const rect =\n        `<rect ${geom} fill=\"${esc(cellFill(cell.value, grid.dom, colors))}\" ` +\n        `stroke=\"${esc(theme.grid)}\" stroke-width=\"1\"><title>${esc(tip)}</title></rect>`;\n      out.push(anchor(cell.href, rect));\n    });\n  });\n  return out;\n}\n\n/** Column labels along the top (centered, may overlap for many columns) + row labels in the gutter. */\nfunction labelParts(ctx: HeatCtx, grid: Grid): string[] {\n  const { theme, plotL, cellW, cellH } = ctx;\n  const out: string[] = [];\n  grid.cols.forEach((col, ci) => {\n    out.push(text(plotL + (ci + 0.5) * cellW, M.top - 8, esc(col), { fill: theme.tick, anchor: 'middle' }));\n  });\n  grid.rows.forEach((row, ri) => {\n    out.push(text(M.left - 8, M.top + (ri + 0.5) * cellH + 4, esc(row), { fill: theme.tick, anchor: 'end' }));\n  });\n  return out;\n}\n\n/** A stepped color ramp (same interpolation as the cells) with min/max value labels beneath it. */\nfunction legendParts(ctx: HeatCtx, top: number, dom: Domain, fmt: (v: number) => string): string[] {\n  const { theme, plotL, plotR, colors } = ctx;\n  const barW = Math.min(LEGEND.barW, Math.max(0, plotR - plotL));\n  const step = barW / LEGEND.steps;\n  const out: string[] = [];\n  for (let i = 0; i < LEGEND.steps; i++) {\n    const t = LEGEND.steps > 1 ? i / (LEGEND.steps - 1) : 0;\n    // Overlap each step by 0.5px so the ramp reads seamless instead of hairline-gapped.\n    out.push(\n      `<rect x=\"${n(plotL + i * step)}\" y=\"${n(top)}\" width=\"${n(step + 0.5)}\" ` +\n        `height=\"${n(LEGEND.barH)}\" fill=\"${esc(lerpColor(colors[0], colors[1], t))}\"/>`,\n    );\n  }\n  const labelY = top + LEGEND.barH + 12;\n  out.push(\n    text(plotL, labelY, esc(fmt(dom.min)), { fill: theme.tick }),\n    text(plotL + barW, labelY, esc(fmt(dom.max)), { fill: theme.tick, anchor: 'end' }),\n  );\n  return out;\n}\n\ninterface HeatSummary {\n  type: 'heatmap';\n  label: string;\n  rows: string[];\n  cols: string[];\n  min: number | null;\n  max: number | null;\n  cells: { row: string; col: string; value: number }[];\n}\n\nfunction heatmapSummary(\n  label: string,\n  rows: readonly string[],\n  cols: readonly string[],\n  valid: readonly HeatmapCell[],\n): HeatSummary {\n  return {\n    type: 'heatmap',\n    label,\n    rows: [...rows],\n    cols: [...cols],\n    min: valid.length ? Math.min(...valid.map((c) => c.value)) : null,\n    max: valid.length ? Math.max(...valid.map((c) => c.value)) : null,\n    cells: valid.map((c) => ({ row: c.row, col: c.col, value: c.value })),\n  };\n}\n\nfunction heatmapDesc(\n  label: string,\n  rows: readonly string[],\n  cols: readonly string[],\n  peak: HeatmapCell | null,\n  fmt: (v: number) => string,\n): string {\n  const grid = `${rows.length}×${cols.length} grid`;\n  if (!peak) return `${label}: ${grid}; no data.`;\n  return `${label}: ${grid}; peak ${peak.row}/${peak.col} ${fmt(peak.value)}.`;\n}\n\n/** Build a matrix heatmap as a standalone SVG string. */\nexport function buildHeatmapSVG(\n  spec: { rows: readonly string[]; cols: readonly string[]; cells: readonly HeatmapCell[] },\n  opts: HeatmapOptions,\n): string {\n  const theme = resolveTheme(opts.theme);\n  const title = opts.title ?? 'Heatmap';\n  const fmt = opts.formatValue ?? ((v: number) => String(v));\n  const colors = opts.colors ?? DEFAULT_COLORS;\n  const cellH = opts.cellHeight ?? 22;\n\n  // Cells for an undeclared row/col are dropped (fail-soft); `valid` is the single set the grid,\n  // domain, summary, and desc all read, so cell counts / min / max / peak stay consistent.\n  const rowSet = new Set(spec.rows);\n  const colSet = new Set(spec.cols);\n  const valid = spec.cells.filter((c) => rowSet.has(c.row) && colSet.has(c.col));\n  const grid: Grid = {\n    rows: spec.rows,\n    cols: spec.cols,\n    lookup: new Map(valid.map((c) => [cellKey(c.row, c.col), c])),\n    dom: domainOf(valid),\n  };\n\n  const { cellW, height, legendTop } =\n    layout(opts.width, spec.rows.length, spec.cols.length, cellH, grid.dom.hasData);\n  const ctx: HeatCtx = { theme, plotL: M.left, plotR: opts.width - M.right, cellW, cellH, colors };\n\n  const parts: string[] = [\n    bgRect(opts.width, height, theme.bg),\n    ...gridParts(ctx, grid, fmt),\n    ...labelParts(ctx, grid),\n  ];\n  if (grid.dom.hasData) parts.push(...legendParts(ctx, legendTop, grid.dom, fmt));\n\n  const extra = opts.embedData === false\n    ? undefined\n    : embedSummary(heatmapSummary(title, spec.rows, spec.cols, valid));\n  return svgDocument({\n    width: opts.width,\n    height,\n    title,\n    desc: heatmapDesc(title, spec.rows, spec.cols, grid.dom.peak, fmt),\n    body: parts.join(''),\n    extra,\n  });\n}\n","/**\n * attachReadout — a styled DOM hover tooltip for STATIC-SVG charts (the donut / scatter / bars\n * primitives), giving them the same instant `.fc-readout` box the interactive `FChart` shows.\n *\n * The pure-SVG builders stay string-in / string-out; this is an opt-in progressive enhancement\n * attached client-side (the same shape as `injectStyles()` / `FChart` upgrading an SSR fallback).\n * A native `<svg><title>` yields only the slow, unstyled OS tooltip; this finds the labelled\n * hit-targets (`.fc-hit`, e.g. `buildScatterSVG`'s hover halo), lifts their `<title>` text so the\n * native tooltip can't also fire, and shows a viewport-fixed, edge-clamped box that reuses the\n * shared `buildReadout` markup + CSS — so static and interactive tooltips look identical.\n *\n * Accessibility is unchanged: the box is decorative (`aria-hidden`); the SVG keeps `role=\"img\"` +\n * `<title>`/`<desc>` + the embedded `data-fcharts` summary as the real text alternative. With JS\n * off, the `<title>` survives and the (delayed) native tooltip is the graceful fallback.\n */\nimport { injectStyles } from './styles.ts';\nimport { buildReadout } from './readout.ts';\n\nexport interface AttachReadoutOptions {\n  /** CSS selector for hit-targets inside `root`. Default `.fc-hit`. */\n  hitSelector?: string;\n}\n\nconst NOOP = (): void => {};\n\n/**\n * Attach a styled hover readout to every `.fc-hit` target inside `root`.\n *\n * @param root Element containing one or more static-SVG charts.\n * @param opts.hitSelector Override the hit-target selector (default `.fc-hit`).\n * @returns A disposer that removes the listeners + box and restores the lifted `<title>` nodes.\n */\nexport function attachReadout(root: Element, opts: AttachReadoutOptions = {}): () => void {\n  const doc = root.ownerDocument;\n  const win = doc?.defaultView;\n  if (!doc || !win) return NOOP;\n  injectStyles(doc);\n\n  const hitSelector = opts.hitSelector ?? '.fc-hit';\n  const readout = buildReadout(doc);\n  readout.el.classList.add('fc-readout-fixed');\n  (doc.body ?? doc.documentElement).append(readout.el);\n\n  // Lift each target's <title> into a data attribute and drop the node, so the slow native OS\n  // tooltip never also appears (the disposer restores it; JS-off keeps it as the fallback).\n  const lifted: { target: Element; title: Element }[] = [];\n  root.querySelectorAll(hitSelector).forEach((target) => {\n    const title = target.querySelector('title');\n    if (!title) return;\n    target.setAttribute('data-fc-label', title.textContent ?? '');\n    title.remove();\n    lifted.push({ target, title });\n  });\n\n  const hide = (): void => readout.el.classList.remove('fc-show');\n  const showAt = (target: Element, clientX: number, clientY: number): void => {\n    readout.name.textContent = target.getAttribute('data-fc-label') ?? '';\n    readout.value.textContent = '';\n    readout.value.style.display = 'none';\n    // Swatch color: an explicit data attribute wins; else the visible dot is the previous sibling.\n    const swatch =\n      target.getAttribute('data-fc-swatch') ?? target.previousElementSibling?.getAttribute('fill') ?? '';\n    readout.swatch.style.background = swatch;\n    readout.swatch.style.visibility = swatch ? 'visible' : 'hidden';\n    place(readout.el, clientX, clientY, win);\n    readout.el.classList.add('fc-show');\n  };\n\n  const onMove = (e: Event): void => {\n    const pe = e as PointerEvent;\n    const from = pe.target;\n    const target = from instanceof Element ? from.closest(hitSelector) : null;\n    if (target && root.contains(target)) showAt(target, pe.clientX, pe.clientY);\n    else hide();\n  };\n\n  root.addEventListener('pointermove', onMove);\n  root.addEventListener('pointerleave', hide);\n\n  return () => {\n    root.removeEventListener('pointermove', onMove);\n    root.removeEventListener('pointerleave', hide);\n    readout.el.remove();\n    for (const { target, title } of lifted) {\n      target.append(title);\n      target.removeAttribute('data-fc-label');\n    }\n  };\n}\n\n/**\n * Place `el` (a viewport-fixed box) near the cursor: above by default, flipped below when it would\n * clip the top, and clamped into the viewport so a narrow panel never cuts it off.\n */\nfunction place(el: HTMLElement, clientX: number, clientY: number, win: Window): void {\n  const rect = el.getBoundingClientRect();\n  const margin = 8;\n  const gap = 14;\n  let top = clientY - rect.height - gap;\n  if (top < margin) top = clientY + gap;\n  const maxLeft = Math.max(margin, win.innerWidth - rect.width - margin);\n  const maxTop = Math.max(margin, win.innerHeight - rect.height - margin);\n  const left = Math.min(Math.max(clientX - rect.width / 2, margin), maxLeft);\n  top = Math.min(Math.max(top, margin), maxTop);\n  el.style.left = `${left}px`;\n  el.style.top = `${top}px`;\n}\n"],"names":["buildPyramid","y","n","levels","prev","buildLevel0","combineLevel","count","min","max","b","i","c","len","j","StreamingPyramid","batch","l","withHeadroom","v","idx","b0","L0","sibling","k","prevCount","cur","bk","c0","c1","level","need","cap","arr","out","lowerBound","x","target","lo","hi","mid","nearestIndex","pickLevel","pyramid","pointsPerCol","last","clamped","planDownsample","domain","cols","w","span","empty","i0","i1","visible","lastBucket","b1","downsampleColumns","rawY","plan","d0","invSpan","cf","finalize","bs","start","end","fL","fR","cL","cR","bmin","bmax","first","seriesSlots","type","resolveAnnotations","specs","series","a","seriesIndex","_a","annotationSample","data","s","index","slot","DEFAULT_PALETTE","AUTO_DASH","resolveSeries","configs","auto","slots","DEFAULT_MARGINS","toF64","toCapacity","src","initStats","sum","ChartData","yArrs","r","xv","ys","old","st","e","linearScale","range","d1","r0","r1","dspan","m","scale","value","px","logScale","l0","lspan","tickStep","rough","mag","norm","niceTicks","minStep","step","SEC","MIN","HOUR","DAY","TIME_STEPS","dayTicks","days","d","t","monthTicks","months","niceTimeTicks","per","years","MONTH_NAMES","two","formatTimeTick","logTicks","decades","stride","dense","effectiveTickCount","base","available","minPx","fit","formatTick","abs","localeNumberFormatter","locale","compact","small","plain","localeTimeFormatter","dtf","opts","clock","millisecond","second","minute","day","month","year","defaultFormatters","xType","num","time","fallbackNow","defaultClock","cb","h","RenderScheduler","onFrame","now","MIN_CANDLE_PX","readForcedColors","canvas","view","probe","cs","sys","readTheme","name","fallback","createCanvas2DRenderer","context","ctx","cssW","cssH","dpr","theme","forced","forcedActive","forcedRead","buf","syncSize","scene","render","plotW","plotH","drawGrid","drawCandleSeries","env","drawArea","drawEnvelope","drawCursor","drawDiamond","py","color","emphasized","drawPinRing","drawAnnotations","left","right","top","bottom","pinned","label","pt","tick","started","pMax","pMin","zero","baseline","lastX","drawCandleEnvelope","yo","yh","yl","yc","yS","xS","spacing","bodyW","lineW","o","up","pTop","pBot","bx","hiMax","detectHtmlInCanvas","ctxProto","resolveRenderPath","support","hasDrawElementImage","createCompositor","supported","layer","dx","dy","matrix","lightTheme","darkTheme","STATUS_COLORS","resolveTheme","markColor","status","esc","embedSummary","summary","anchor","href","inner","text","content","bgRect","width","height","fill","svgRoot","svgDocument","strokePath","yScale","areaPath","baseY","firstX","candleParts","xScale","buildSVG","parts","grid","dash","annotationParts","CSS","injectStyles","doc","style","buildReadout","el","swatch","LiveRegion","AxisTicks","xLabel","yLabel","title","axis","pos","u","xTitle","yTitle","_b","doomed","limit","colliding","Legend","onToggle","strings","li","button","state","NS","svg","candle","cx","filled","wick","body","rect","line","Pagers","onPan","mk","glyph","dir","atStart","atEnd","Sonifier","freq","osc","gain","DEFAULT_STRINGS","format","template","vars","whole","key","resolveStrings","overrides","sampleIndices","maxRows","TableAlt","rows","frag","seriesCount","rowCount","caption","xHeader","ohlc","thead","tr","part","tbody","rowHeader","td","th","EMPTY_STAT","trendOf","changePct","buildSummary","annotations","xStart","xEnd","changeAbs","describeSummary","fmtX","fmtY","shown","points","events","KEYS","ZOOM_IN","ZOOM_OUT","ANN_NEXT","ANN_PREV","ANN_SELECT","handlesKey","annotationStep","selectsAnnotation","annotationIndexByX","xs","fromX","minI","maxI","bestI","zoomFactor","findVisible","stepCursor","coarse","panToInclude","DERIVED_THROTTLE_MS","ANNOUNCE_DEBOUNCE_MS","ANNOTATION_HIT_PX","instanceSeq","resolveOptions","config","fmt","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","prefers","_o","_p","_q","_r","_s","_t","_u","_v","_w","buildA11yEls","summaryId","activeId","summaryEl","activeSample","dataScript","buildSurface","ids","surface","FChart","seq","tableId","a11y","ticksAsCanvasChild","xCount","yCount","header","words","lines","csvQuote","row","url","got","want","candles","hint","prevN","prevLast","prevLo","following","atLeftEdge","vlo","vhi","patch","_fixed","updatable","failFixed","pad","rescaleY","yMin","yMax","run","help","xTicks","yTicks","gutter","lx","fy","ly","labels","seriesPos","hide","fa","valueText","clientX","clientY","r2","best","bestD","suffix","signal","annDir","factor","next","sr","shift","hit","minSpan","sameConstructionOptions","sa","sb","query","syncCharts","charts","applying","unsubs","chart","other","hydrate","container","defineFChart","tag","existing","FChartHTMLElement","stringsDE","stringsFR","stringsES","totalSlots","renderSVG","cd","xPad","log","yDomain","yhi","ylo","lpad","yPad","formatX","formatY","LEGEND_W","ROW_H","PAD","buildDonutSVG","spec","size","total","resolved","pct","cy","ring","circ","acc","arcs","arc","legend","legendRows","ordered","donutSummary","donutDesc","slices","flag","capPct","hhi","headroom","over","overNote","M","rowCenter","buildScatterSVG","rowH","refLines","p","rowIndex","valid","axisParts","rowParts","refLineParts","dotParts","scatterSummary","scatterDesc","ticks","ref","hoverRadius","perRow","ri","seen","jitter","tip","hoverR","counts","refs","worst","INSET","TREND_COLOR","buildSparklineSVG","values","finite","deltaPct","trend","lineColor","deltaText","defaultDelta","labelW","xAt","yAt","by","firstFinite","lastFinite","ariaLabel","deriveStatus","ratio","buildBarsSVG","all","dataMax","dataMin","domMax","domMin","plotL","plotR","xZero","bh","x0","x1","barsSummary","barsDesc","signed","clamp01","pctStr","buildProgressSVG","frac","rx","DEFAULT_COLORS","LEGEND","cellKey","col","parseHex","lerpColor","ca","hex","cellFill","dom","colors","domainOf","peak","layout","cellH","hasData","cellW","gridBottom","legendTop","gridParts","ci","geom","cell","labelParts","legendParts","barW","labelY","heatmapSummary","heatmapDesc","buildHeatmapSVG","rowSet","colSet","extra","NOOP","attachReadout","root","win","hitSelector","readout","lifted","showAt","place","onMove","pe","from","margin","gap","maxLeft","maxTop"],"mappings":"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"}