018 / RECHARTS / AREA

Interactive Area

Recharts

Inspection-first area visualization with nearest-X selection, observation-aligned crosshair, keyboard navigation, and a persistent lockable tooltip.

SPEC
#018
ENGINE
Recharts
FAMILY
Area
RENDERER
svg
STATUS
preview

Installation

PLOTCN/REGISTRY/AREA-INTERACTIVE/SOURCE
pnpm dlx shadcn@latest add @plotcn/area-interactive

Checking public registry…

View local registry JSON
REGISTRY direct URL·ENGINE Recharts·FILES 1·DEPENDENCIES 7

Copied as source into your project (requires recharts, @hugeicons/react, @hugeicons/core-free-icons).

× 340Container width
Measuring preview...
RECHARTS · SVG · 0 × 340pxMotion enabled · ResizeObserver

Overview

Interactive Area is the inspection-specialized instrument of the Plotcn Area family. While other area components prioritize continuous visual magnitude or semantic fills, Interactive Area focuses on exact observation inspection: nearest-X pointer scrubbing, an observation-aligned neutral crosshair, keyboard navigation, touch-friendly exploration, and a persistent lockable tooltip.

The primary analytical question answered by Interactive Area is:

"What exact observed value belongs to this position on the ordered domain?"

The defining interaction question is:

"Can I inspect that observation, keep it selected, move through neighboring observations, and compare context without the tooltip disappearing?"
TSX
import { InteractiveArea } from "@/components/charts/recharts/area-interactive"const apiTrafficData = [  { date: "May 01", requests: 12400 },  { date: "May 04", requests: 14200 },  { date: "May 08", requests: 11900 },  { date: "May 12", requests: 16800 },  { date: "May 16", requests: 18500 },  { date: "May 20", requests: 15300 },  { date: "May 24", requests: 19800 },  { date: "May 28", requests: 23400 },  { date: "May 31", requests: 26100 },]export function RequestVolumeTracker() {  return (    <InteractiveArea      data={apiTrafficData}      xKey="date"      series={{        key: "requests",        label: "API Requests",        valueFormatter: (v) => `${v.toLocaleString()} req/s`,      }}      color="var(--chart-1)"      selectionColor="var(--chart-selection)"      fillOpacity={0.22}      curve="monotone"      showGrid    />  )}

Area-Family Positioning

The Plotcn Area family provides specialized analytical instruments across quantitative domains:

Consideration Prism Area (011) Focus Line (008) Comparison Area (015) Baseline Area (017) Interactive Area (018)
ConsiderationPrism Area (011)Focus Line (008)Comparison Area (015)Baseline Area (017)Interactive Area (018)
Primary Question"How much magnitude relative to baseline?""What is the exact value along the signal curve?""How does primary compare to reference series?""How far above or below the baseline?""What exact observed value belongs to this domain position?"
Defining FeatureRestrained translucent fill magnitudeHigh-precision line inspectionOverlapping dual-series fillDual-color deviation fillNearest-X scrubbing + observation crosshair + persistent lock
Geometry1 filled area polygon1 continuous stroke (no fill)2 overlapping areasDual-region baseline partitioned area1 filled area polygon + 1 observation crosshair + 0–1 marker dot
Inspection ModelStandard pointer hoverNearest-X line focus & lockMulti-series hover inspectionSigned deviation inspectionInspection-first nearest-X scrubbing, crosshair snap, persistent lock
Interaction SurfaceStandard plot containerPlot-wide Cartesian surfaceStandard plot containerStandard plot containerUnified touch-action: pan-y hit region with O(logN)O(\log N) resolver

Interactive Area vs. Focus Line (008)

  • Focus Line: Best when lower visual mass is desired and the line trajectory alone provides sufficient analytical context.
  • Interactive Area: Best when the occupied space between trend and baseline communicates essential volume context, while high-precision nearest-X inspection remains the primary user task.

Interactive Area vs. Prism Area (011)

  • Prism Area: The visual area itself is the primary experience, using conventional hover tooltips.
  • Interactive Area: The filled area provides ambient context, while exact observation inspection, keyboard traversal, and persistent locking are the primary experience.

Inspection Model

Governing Principle: Interaction may help users reach data more easily, but it must never manufacture data that was not observed.

If the user points between observations:

x1 ——— pointer ——— x2x_1 \quad \bullet \text{ --------- } \uparrow_{\text{pointer}} \text{ --------- } \bullet \quad x_2

The component resolves the nearest real observation (x1x_1 or x2x_2). It never calculates synthetic midpoints, interpolated Y values, or fictional timestamps.

INSPECTION PIPELINEInput to Resolution

Input Coordinate to Persistent Observation Lock

Observed Datum
Locked State

Inspection flow diagram showing input events mapped to nearest domain X coordinates, resolving real observations without interpolation, and driving crosshair, marker, and persistent lockable tooltip.

1. Input EventPointer scrubKeyboard ← → / Tap2. Nearest-X MathHorizontal plot XIgnore vertical Y3. Real Datumdata[activeIndex]Zero interpolationNeutral CrosshairSnaps to observation X--chart-crosshairTooltip & MarkerExact observed valueNo marker if null/missingPersistent Lock (◎)Survives mouse leaveEnter / Click / Space
Truthful Principle: Pointer coordinates guide navigation; only real observations produce tooltips and crosshairs.
Inspection Model Architecture

The inspection lifecycle follows a deterministic pipeline:

  1. Input Event: Dispatched via pointer move, keyboard arrow navigation, or mobile tap.
  2. Coordinate Normalization: Normalizes viewport coordinates against chart plot margins.
  3. Nearest-X Resolution: Maps horizontal plot position to the nearest ordered domain observation index.
  4. Real Observation Binding: Pulls the authentic datum from caller data. No curve interpolation is presented as observed data.
  5. Observation-Aligned Crosshair: Snaps the structural crosshair to the exact observation X coordinate.
  6. Persistent Lock: Prevents incidental pointer drift from changing the selected observation.

Nearest-X Model

In Cartesian time-series analysis, inspection is strictly horizontal:

Pointer Y does not choose the observation. Only horizontal plot position resolves the nearest ordered domain observation.
NEAREST-X RESOLUTIONSnapping & Midpoint Partitioning

Midpoint Boundary Zones and Observation-Aligned Snapping

Midpoint Bound
Crosshair Snapped

Conceptual diagram showing ordered domain observations, midpoint boundaries dividing screen zones, a pointer in zone 2, and the resulting snapped crosshair at the real observation coordinate.

x₀ (Jan 1)m₀₁x₁ (Jan 2)m₁₂x₂ (Jan 3)Selected Datumm₂₃x₃ (Jan 4)m₃₄x₄ (Jan 5)Raw Pointer: (328, 55)Vertical Y ignoredSnaps
Observation-Centric Invariant: The crosshair always snaps to x₂ (360px). It never follows raw cursor X (328px) continuously.
Nearest-X Mathematical Model

Midpoint boundaries conceptually partition the domain:

mi,i+1=xi+xi+12m_{i, i+1} = \frac{x_i + x_{i+1}}{2}

Tie-Break Rule

When the pointer coordinate lands at the exact mathematical midpoint between two observations:

dist(x,xi)=dist(x,xi+1)\text{dist}(x, x_i) = \text{dist}(x, x_{i+1})

The resolver deterministically chooses the earlier index (ii). This prevents visual flickering and floating-point oscillations.

Algorithmic Complexity

Because domain coordinates are ordered, nearest-X resolution runs via binary search in O(logN)O(\log N) time, avoiding expensive linear scans or per-point DOM hit rectangles.

Interaction States

Interactive Area decouples three distinct states that are often conflated in lesser charting libraries:

STATE MACHINEFocus vs Active vs Locked

Interaction State Transitions & Input Decoupling

Focus Shell
Active Point
Locked Pin

State machine diagram illustrating transitions between IDLE, FOCUSED, ACTIVE, and LOCKED states. Shows keyboard focus, arrow navigation, click-to-lock, and escape-to-unlock flows.

IDLE STATENo active cursorTooltip closedAwaiting user actionpointerenter / Tab / tapACTIVE INSPECTIONNearest-X resolvedTransient crosshair & dot← → navigates domainpointerleave / blurClick / Enter / SpaceLOCKED SELECTION (◎)Persistent double ringPointer drift ignored← → moves locked pinEscape / click again← → advances lock
Lock Invariant: When locked, incidental pointer movement never alters the selected observation until explicitly unlocked or clicked elsewhere.
Interaction State Machine

1. FOCUSED State

The chart interaction surface currently holds keyboard focus. It is visually framed by the standard focus ring:

CSS
outline: none;box-shadow: 0 0 0 2px var(--chart-focus, #38bdf8);

Focus does not require a point to be locked.

2. ACTIVE State

A real observation is actively inspected through transient pointer scrubbing, initial keyboard focus, or tap. The observation is indicated by:

  • A solid marker dot in series color
  • An observation-aligned crosshair in neutral --chart-crosshair
  • A synchronized inspection tooltip

3. LOCKED State

The user has intentionally pinned the observation. It gains:

  • A concentric double-ring marker (───◎───) using selectionColor
  • A persistent crosshair using selectionColor
  • A persistent tooltip with a Locked badge and lock icon
  • Pointer Immunity: Incidental pointer movement across the plot does not move or dismiss the locked observation.

Locking Behavior

Locking turns fleeting inspection into stable analysis:

  • Locking on Desktop: Click any observation or press Enter or Space while focused.
  • Moving Locked Observation:
    • Click any other observation to move the lock directly to that coordinate.
    • Press ArrowLeft or ArrowRight while locked to advance the locked selection step-by-step.
  • Unlocking:
    • Press Escape.
    • Click the currently locked observation again to release the lock.
  • Touch Behavior: Tap any observation to inspect and pin. Tapping elsewhere moves the lock.
  • Resize & Theme Immunity: Resizing the window, toggling dark mode, or updating series colors does not clear the locked observation.

Missing Observations

An observation can exist along an ordered domain even when its quantitative value was not recorded:

Observation(x)Domain,Value(x)=null\text{Observation}(x) \in \text{Domain}, \quad \text{Value}(x) = \text{null}

Interactive Area treats missingness truthfully:

  • Domain Preservation: Missing observations remain in the domain and are navigable via keyboard arrows and pointer scrub.
  • Truthful Tooltip: The tooltip reports "Unavailable" or "—". It never fabricates zero.
  • Crosshair Continuity: The crosshair snaps to the missing observation's horizontal X coordinate.
  • No Fake Dot: No marker dot is rendered on the canvas because there is no observed Y coordinate.
  • Zero is Valid: A recorded value of 0 is rendered at zero; it is never treated as missing.
  • Non-Finite Sanitization: NaN, Infinity, and -Infinity are safely treated as missing to protect SVG path geometry.

Keyboard Navigation

Interactive Area provides a single accessible tab stop on its root <figure> element. Observations are not individually tabbable:

Key Action Description
KeyActionDescription
TabFocus ChartMoves focus to the chart container; displays --chart-focus ring.
ArrowRightNext ObservationSteps forward to the next domain coordinate (including missing observations).
ArrowLeftPrevious ObservationSteps backward to the previous domain coordinate.
HomeFirst ObservationJumps immediately to observation index 0.
EndLast ObservationJumps immediately to the final observation in the dataset.
Enter / SpaceToggle LockLocks or unlocks the currently active observation. Page scroll is prevented.
EscapeRelease LockUnlocks the persistent selection without clearing active focus.

Touch Exploration

Touch interactions are engineered to respect page scrolling:

  • Scroll Preservation: The container uses touch-action: pan-y. Vertical swipes scroll the page naturally without being hijacked by chart gestures.
  • Tap Inspection: Tapping anywhere within the plot region resolves the nearest observation X and pins the tooltip.
  • Zero Gesture Dependencies: Implemented purely using native Pointer Events; no Hammer.js or external gesture frameworks required.

Color Customization

The component enforces a clean, multi-token color hierarchy:

TSX
<InteractiveArea  data={data}  xKey="date"  series={{ key: "requests", label: "Requests" }}  color="var(--chart-1)"  selectionColor="var(--chart-selection)"/>
  • Series Color (color): Controls the area fill, boundary stroke, active marker point, and tooltip dot. Defaults to var(--chart-1).
  • Selection Color (selectionColor): Controls the locked concentric double-ring marker, locked crosshair, and locked tooltip badge. Defaults to var(--chart-selection).
  • Crosshair Token (--chart-crosshair): Structural neutral line (rgba(255, 255, 255, 0.28)). Not modified by series colors.
  • Focus Token (--chart-focus): Structural keyboard focus ring (#38bdf8).

Rendering Architecture

Interactive Area is built purely on top of Recharts and native SVG primitives:

SYSTEM ARCHITECTURERendering & Event Topology

Recharts Area Chart and Synchronized Inspection Layers

Pure SVG Pipeline
Accessible DOM

System architecture diagram detailing raw data ingestion, normalizer, domain and scale computation, Recharts Area rendering, nearest-X resolution, and synchronized crosshair and HTML tooltip overlays.

1. Caller Input & ValidationReadonly TData[] + xKeyNon-finite values sanitized2. Scale & Domain EnginecalculateInteractiveAreaDomain()Encloses data & baseValue3. Recharts Area Chart<Area baseValue={baseline} />Restrained 22% fill + stroke4. Unified Hit Surfacetouch-action: pan-y (scroll-safe)One plot surface (no 100 hit rects)5. Nearest-X Index EngineresolveNearestIndex()Equidistant midpoint tie-break6. Observation OutputsCrosshair + Concentric RingLockable HTML Tooltip + A11yPerformance & Accessibility Invariant:Only 1 Area geometry is generated. Tooltip values strictly map to real observations without synthetic continuous interpolation.
SVG Pipeline: Zero external gesture or state machine libraries. Clean source portability.
Registry Component: area-interactive
  1. Single Interaction Surface: The entire plot region acts as one unified hit area. There are no per-datum invisible DOM rectangles.
  2. Deterministic O(logN)O(\log N) Resolver: Binary search calculates the active observation index without querying or parsing SVG path geometry.
  3. Observation-Aligned Crosshair: Crosshair rendered via <ReferenceLine x={activeX} />, strictly locked to the observation's scaled coordinate.
  4. Active / Locked Dot Callback: Exactly 0 or 1 marker is rendered by the Area component, preventing DOM bloat on dense datasets.
03 / Component API & Styling

Props Reference & Interactive Prop Explorer

Inspect every component property, customize semantic color roles live with instant visual feedback, and copy production-ready code with active prop configurations.

Colors & Appearance Configuration

Customize primary, reference, or annotation series colors. Defaults derive from Plotcn theme tokens.

Generated Usage Code (Live Props):
<InteractiveArea
  data={data}
  xKey="date"
  seriesKey="value"
/>
Interactive Prop Preview Lab
colorstring

Primary stroke color, area fill, active marker point, and tooltip dot.

Active: color="function"Default: "var(--chart-1, #3b82f6)"
selectionColorstring

Accent color for persistent locked marker ring, locked tooltip badge, and locked crosshair.

Active: selectionColor="function"Default: "var(--chart-selection, #f59e0b)"
fillOpacitynumber

Fill opacity for the occupied area polygon below the signal curve.

Select value to preview live:
Active: fillOpacity={0.22}Default: 0.22
curve"monotone" | "linear" | "step"

Curve interpolation algorithm for the continuous area boundary stroke.

Select value to preview live:
Active: curve="monotone"Default: "monotone"
baselinenumber | "zero" | "domain-min"

Baseline anchor for the area polygon baseValue.

Select value to preview live:
Active: baseline="zero"Default: "zero"
heightnumber | string

Visual container height in pixels or CSS dimension string.

Select value to preview live:
Active: height={320}Default: 320
lockableboolean

Whether clicking or pressing Enter/Space locks the currently inspected observation.

Select value to preview live:
Active: lockable={true}Default: true
missingValuePolicy"gap" | "carry" | "connect"

Truthful handling of null/undefined observations. Under gap, missing points remain inspectable without area fill.

Select value to preview live:
Active: missingValuePolicy="gap"Default: "gap"
showGridboolean

Whether to render subtle horizontal background reference gridlines.

Select value to preview live:
Active: showGrid={true}Default: true
showXAxisboolean

Whether to render the horizontal category scale ticks and domain labels.

Select value to preview live:
Active: showXAxis={true}Default: true
showYAxisboolean

Whether to render the vertical numeric scale ticks and metric values.

Select value to preview live:
Active: showYAxis={true}Default: true
showLegendboolean

Whether to render the single-series identity legend.

Select value to preview live:
Active: showLegend={false}Default: false
All Properties (22)
Component properties
PropertyTypeDefaultRequiredDescription
dataReq
readonly TData[][]Yes

Readonly array of observation records. Caller data is never mutated or reordered.

xKeyReq
keyof TData & stringYes

Property name on data records representing the horizontal domain coordinate.

InteractiveAreaSeries<TData>Yes

Single quantitative series configuration defining metric key, label, and valueFormatter.

string"var(--chart-1, #3b82f6)"No

Primary stroke color, area fill, active marker point, and tooltip dot.

string"var(--chart-selection, #f59e0b)"No

Accent color for persistent locked marker ring, locked tooltip badge, and locked crosshair.

number0.22No

Fill opacity for the occupied area polygon below the signal curve.

"monotone" | "linear" | "step""monotone"No

Curve interpolation algorithm for the continuous area boundary stroke.

number | "zero" | "domain-min""zero"No

Baseline anchor for the area polygon baseValue.

[number, number] | "auto""auto"No

Explicit vertical Y-axis scale bounds, or automatic padding computation.

number | string320No

Visual container height in pixels or CSS dimension string.

booleantrueNo

Whether clicking or pressing Enter/Space locks the currently inspected observation.

number | nullnullNo

Initial observation index to pin/lock on mount.

"none" | "first" | "last""none"No

Initial inspection position upon keyboard focus entry into the chart.

"gap" | "carry" | "connect""gap"No

Truthful handling of null/undefined observations. Under gap, missing points remain inspectable without area fill.

booleantrueNo

Whether to render subtle horizontal background reference gridlines.

booleantrueNo

Whether to render the horizontal category scale ticks and domain labels.

booleantrueNo

Whether to render the vertical numeric scale ticks and metric values.

booleanfalseNo

Whether to render the single-series identity legend.

(active: ActiveDatum | null, index: number | null) => voidNo

Callback fired whenever the active inspected observation changes.

(locked: ActiveDatum | null, index: number | null) => voidNo

Callback fired whenever the persistent locked observation changes.

stringNo

Accessible name announced to assistive technologies.

stringNo

Detailed descriptive summary announced to assistive technologies.

04 / Cookbook & States

Component Variants & Edge States

Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.

Basic Inspection

Pointer scrub along the timeline, snapping crosshair to observations with synchronized tooltips.

<InteractiveArea
  data={data}
  xKey="date"
  series={{
    key: "requests",
    label: "API Requests",
  }}
/>

Persistent Locked Tooltip

Click or press Enter to pin the observation. Pointer movement no longer drifts the tooltip.

<InteractiveArea
  data={data}
  xKey="date"
  series={{
    key: "requests",
    label: "API Requests",
  }}
  defaultLockedIndex={4}
  selectionColor="var(--chart-selection)"
/>

Missing Observation Handling

Unrecorded observations exist in the domain and report as unavailable without synthetic values.

<InteractiveArea
  data={[
    { date: "May 01", requests: 120 },
    { date: "May 02", requests: null },
    { date: "May 03", requests: 180 },
  ]}
  xKey="date"
  series={{ key: "requests", label: "Requests" }}
  missingValuePolicy="gap"
/>

Custom Series and Selection Theming

Independent series color for the area fill and selectionColor for the locked double ring.

<InteractiveArea
  data={data}
  xKey="date"
  series={{ key: "requests", label: "Requests" }}
  color="#3b82f6"
  selectionColor="#f59e0b"
/>
Lifecycle & Exception States
01. Loading State

Skeletons indicate runtime fetch or pending data queries.

02. Empty Data State

Handles empty collections ([]) gracefully without crashing.

03. Error State

Graceful failure banner when data source or script fails.

05 / Responsive Lab

Container-Driven Breakpoints

Interactive Area preserves the full inspection hit surface, nearest-X resolution, observation-aligned crosshair, and persistent lock state across all viewport dimensions down to 320px.

Desktop
>= 1024px

Spacious Cartesian grid, full domain tick density, observation-aligned crosshair, anchored inspection card, and complete keyboard shortcuts.

Tablet
640px - 1023px

Adaptive domain tick thinning, preserved hit region, and compact inspection gutters.

Mobile
< 640px

Compact gutters, touch-forgiving tap inspection, pan-y scroll preservation, and persistent locked inspection card.

Tablet Preview (768px Container Constraint)
Mobile Preview (390px Container Constraint)

Accessibility & Data Safety

  • One Tab Stop: Chart shell receives keyboard focus without trapping the user or creating dozens of SVG tab stops.
  • Screen Reader Announcements: An off-screen live region provides concise, factual orientation:
> "Interactive time-series area chart depicting 30 observations for API Requests. Currently locked on observation 8 of 30 at May 08 with value 11,900."
  • Structured Data Table: A complete HTML <table> is provided in an off-screen container for non-visual exploration.
  • No Live-Region Spam: Rapid pointer scrubbing does not flood screen readers with aria-live announcements.
  • Reduced Motion: Respects prefers-reduced-motion by disabling path animations while keeping pointer and keyboard inspection immediate.
06 / Assistive Technology

Accessibility & Navigation Standards

Single keyboard tab stop on root figure with ArrowLeft, ArrowRight, Home, End, Enter/Space, and Escape shortcuts. Complete structured data table provided for screen readers.

Semantic Role & Landmark

Container mounts as region with explicit assistive label.

Color-Independent Legibility

Concentric double-ring marker (◎), observation-aligned vertical crosshair, textual lock badge, and offscreen structured HTML table ensure non-color accessibility.

Screen Reader Summary

Embeds visually hidden summary (.sr-only) declaring: “Announces domain coordinate, observed value, observation index and count, and locked status factually without editorial commentary.

Reduced Motion Support

All entrance animations immediately bypass when prefers-reduced-motion is detected in user system preferences.

Keyboard Interaction Model
Keyboard interaction model
KeyAction
ArrowRightInspect next chronological observation across the domain.
ArrowLeftInspect previous chronological observation across the domain.
HomeJump inspection directly to the first observation.
EndJump inspection directly to the final observation.
Enter / SpaceLock or unlock persistent inspection at the active coordinate.
EscapeRelease locked selection without losing active keyboard focus.

Data Safety Guarantees

  • ✓ Active values always correspond to real observations
  • ✓ Pointer position never manufactures an interpolated value
  • ✓ Crosshair snaps to the selected observation X, not raw cursor X
  • ✓ Pointer Y does not alter horizontal nearest-X selection
  • ✓ Missing observations remain inspectable as unavailable
  • ✓ Missing values are never silently coerced to zero
  • ✓ Zero remains a valid quantitative observation
  • ✓ Non-finite values (NaN, Infinity) never reach SVG path strings
  • ✓ Locking alters interaction state only; underlying caller data is never mutated
  • ✓ Resizing the viewport preserves active and locked observations
  • ✓ Theme switches and color changes preserve lock state without remounting
  • ✓ Single plot-level interaction surface with zero per-point DOM overhead
  • ✓ Caller data array is treated as strictly readonly
07 / Source Anatomy

Internal Architecture & File Dependencies

Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.

Component Architecture Call Tree
InteractiveArea(Root figure element with keyboard navigation and ARIA accessibility shell)
├──ResponsiveContainer[Responsive container wrapper]

Handles container dimension measurement and SVG viewBox sizing

└──AreaChart[Recharts Cartesian SVG coordinator]

Coordinates scales, Cartesian grid, Area geometry, ReferenceLine crosshair, and Tooltip

Involved Source Files & Registry Assets
registry/recharts/area-interactive.tsx
Complete Interactive Area component with nearest-X inspection, observation-aligned crosshair, and persistent lockable tooltip
registry/recharts/area-interactive.tsx
"use client"import * as React from "react"import {  ResponsiveContainer,  AreaChart,  Area,  XAxis,  YAxis,  Tooltip,  CartesianGrid,  Legend,  ReferenceLine,} from "recharts"import { HugeiconsIcon } from "@hugeicons/react"import { LockKeyIcon } from "@hugeicons/core-free-icons"import { useChartReducedMotion } from "../shared/use-chart-reduced-motion"import { ChartContainer } from "../shared/chart-container"import {  ChartLoadingState,  ChartEmptyState,  ChartErrorState,  ChartUnavailableState,} from "../shared/chart-state"import { cn } from "@/lib/utils"/* -------------------------------------------------------------------------- *//*  Type Definitions                                                          *//* -------------------------------------------------------------------------- */export type NumericKeyOf<TData> = [keyof TData] extends [never]  ? string  : {      [K in keyof TData]: TData[K] extends number | null | undefined ? K : never    }[keyof TData] extends never  ? string  : {      [K in keyof TData]: TData[K] extends number | null | undefined ? K : never    }[keyof TData] & string/** * Single quantitative series descriptor for Interactive Area. */export interface InteractiveAreaSeries<TData extends Record<string, unknown> = Record<string, unknown>> {  /** Property key on observation records containing quantitative numeric values */  key: NumericKeyOf<TData>  /** Human-readable display label for tooltips, legend, and screen readers */  label: string  /** Optional custom numeric formatter for tooltip and scale values */  valueFormatter?: (value: number) => string}/** * Semantic representation of an actively inspected or locked observation. */export interface ActiveDatum<  TData extends Record<string, unknown> = Record<string, unknown>,  XVal extends string | number = string | number> {  /** 0-based index within the normalized observation dataset */  index: number  /** Domain coordinate along the horizontal axis */  x: XVal  /** Numeric quantitative metric value (null if missing/unrecorded) */  value: number | null  /** Original raw observation record from caller */  raw: TData  /** Alias for raw observation record */  datum?: TData  /** Whether this observation is actively pinned/locked */  isLocked: boolean  /** Whether this observation has a missing or unrecorded value */  isMissing: boolean}export interface InteractiveAreaProps<  TData extends Record<string, unknown> = Record<string, unknown>,  XVal extends string | number = string | number> {  /** Readonly array of observation records. Caller data is never mutated. */  data: readonly TData[]  /** Key for the horizontal axis domain (e.g. date, month, time, timestamp). */  xKey: keyof TData & string  /** Single quantitative series specification. */  series: InteractiveAreaSeries<TData>  /** Primary stroke and fill color for the area. (default: "var(--chart-1, #3b82f6)") */  color?: string  /** Accent color for locked selection marker, persistent ring, and lock badge. (default: "var(--chart-selection, #f59e0b)") */  selectionColor?: string  /** Fill opacity for the occupied area polygon. (default: 0.22) */  fillOpacity?: number  /** Container height in pixels or CSS dimension string. (default: 320) */  height?: number | string  /** Curve interpolation: "monotone" | "linear" | "step". (default: "monotone") */  curve?: "monotone" | "linear" | "step"  /** Explicit Y-axis numeric domain, or "auto" calculation. (default: "auto") */  domain?: [number, number] | ["auto", "auto"] | "auto"  /** Baseline reference: quantitative number, "zero", or "domain-min". (default: "zero") */  baseline?: number | "zero" | "domain-min"  /** Whether clicking or pressing Enter/Space pins the currently inspected datum. (default: true) */  lockable?: boolean  /** Alias for lockable. (default: true) */  lockableTooltip?: boolean  /** Default observation index to pin/lock on initial mount. (default: null) */  defaultLockedIndex?: number | null  /** Initial inspection position upon keyboard focus entry: "none" | "first" | "last". (default: "none") */  initialFocus?: "none" | "first" | "last"  /** Handling of null or undefined values: "gap" (truthful break) | "carry" (last known) | "connect". (default: "gap") */  missingValuePolicy?: "gap" | "carry" | "connect"  /** Animation mode: "draw" | "fade" | "none". (default: "draw") */  animation?: "draw" | "fade" | "none"  /** Animation configuration or boolean toggle. Respects prefers-reduced-motion. */  motion?: boolean | { duration?: number }  /** Whether to render subtle horizontal background reference gridlines. (default: true) */  showGrid?: boolean  /** Whether to render the horizontal category scale. (default: true) */  showXAxis?: boolean  /** Whether to render the vertical numeric scale. (default: true) */  showYAxis?: boolean  /** Whether to render the chart legend. (default: false) */  showLegend?: boolean  /** Custom formatter for Y-axis scale numbers and tooltip metric values. */  valueFormatter?: (value: number) => string  /** Custom formatter for X-axis coordinate labels. */  xFormatter?: (value: string | number) => string  /** Callback fired whenever the active inspected observation changes. */  onActiveChange?: (active: ActiveDatum<TData, XVal> | null, index: number | null) => void  /** Callback fired whenever the persistent locked observation changes. */  onLockChange?: (locked: ActiveDatum<TData, XVal> | null, index: number | null) => void  /** Optional heading announced to assistive technologies. */  title?: string  /** Optional descriptive explanation announced to assistive technologies. */  description?: string  /** Optional CSS class name passed to the root figure element. */  className?: string  /** Display neutral skeleton loading state. */  loading?: boolean  /** Display truthful empty state. */  empty?: boolean  /** Display actionable error banner. */  error?: Error | string | null  /** Display metric unavailability notice. */  unavailable?: boolean | string | null}/* -------------------------------------------------------------------------- *//*  Pure Algorithmic Helpers                                                  *//* -------------------------------------------------------------------------- */export function isFiniteNumber(val: unknown): val is number {  return typeof val === "number" && Number.isFinite(val)}export interface NormalizedInteractiveDatum {  __x: string | number  __value: number | null  __raw: Record<string, unknown>  __index: number}/** * Safely normalizes input observation records: * 1. Missing values are preserved as null under "gap" policy (no null-to-zero coercion). * 2. Non-finite values (NaN, Infinity) are treated as missing. * 3. Never mutates caller array or objects. */export function normalizeInteractiveData<TData extends Record<string, unknown>>(  data: readonly TData[],  xKey: keyof TData & string,  seriesKey: string,  missingValuePolicy: "gap" | "carry" | "connect" = "gap"): NormalizedInteractiveDatum[] {  if (!Array.isArray(data) || data.length === 0) return []  let lastKnownValid: number | null = null  return data.map((d, idx) => {    const rawX = d[xKey]    const xVal = typeof rawX === "string" || typeof rawX === "number" ? rawX : String(rawX ?? "")    const rawV = d[seriesKey]    const isDirectFinite = isFiniteNumber(rawV)    let finalVal: number | null = null    if (isDirectFinite) {      finalVal = rawV      lastKnownValid = rawV    } else if (missingValuePolicy === "carry" && lastKnownValid !== null) {      finalVal = lastKnownValid    } else {      finalVal = null      if (missingValuePolicy === "gap") {        lastKnownValid = null      }    }    return {      __x: xVal,      __value: finalVal,      __raw: d,      __index: idx,    }  })}/** * Calculates a safe Cartesian Y-domain covering observation extrema and baseline. */export function calculateInteractiveAreaDomain(  normalized: readonly NormalizedInteractiveDatum[],  explicitDomain?: [number, number] | ["auto", "auto"] | "auto",  baseline: number | "zero" | "domain-min" = "zero"): [number, number] {  if (    Array.isArray(explicitDomain) &&    typeof explicitDomain[0] === "number" &&    typeof explicitDomain[1] === "number" &&    Number.isFinite(explicitDomain[0]) &&    Number.isFinite(explicitDomain[1])  ) {    return explicitDomain  }  const values: number[] = []  for (const item of normalized) {    if (item.__value !== null && Number.isFinite(item.__value)) {      values.push(item.__value)    }  }  if (values.length === 0) {    return [0, 100]  }  if (typeof baseline === "number" && Number.isFinite(baseline)) {    values.push(baseline)  } else if (baseline === "zero") {    values.push(0)  }  const min = Math.min(...values)  const max = Math.max(...values)  if (min === max) {    if (min === 0) return [-10, 10]    const delta = Math.abs(min) * 0.15 || 10    return [Math.floor(min - delta), Math.ceil(max + delta)]  }  const span = max - min  const pad = span * 0.08  return [Math.floor(min - pad), Math.ceil(max + pad)]}/** * Deterministic Nearest-X resolution along an ordered array of screen coordinates. * Invariant: At exact midpoint (equidistant), tie breaks deterministically to the earlier index. */export function resolveNearestIndex(targetX: number, xPositions: readonly number[]): number {  if (xPositions.length === 0) return -1  if (xPositions.length === 1) return 0  let low = 0  let high = xPositions.length - 1  if (targetX <= xPositions[low]) return low  if (targetX >= xPositions[high]) return high  while (low <= high) {    const mid = Math.floor((low + high) / 2)    const midVal = xPositions[mid]    if (midVal === targetX) return mid    if (midVal < targetX) {      if (mid + 1 < xPositions.length && targetX < xPositions[mid + 1]) {        const dLeft = targetX - midVal        const dRight = xPositions[mid + 1] - targetX        // Equidistant tie-break: pick earlier index        return dLeft <= dRight ? mid : mid + 1      }      low = mid + 1    } else {      if (mid - 1 >= 0 && targetX > xPositions[mid - 1]) {        const dLeft = targetX - xPositions[mid - 1]        const dRight = midVal - targetX        return dLeft <= dRight ? mid - 1 : mid      }      high = mid - 1    }  }  return low}/* -------------------------------------------------------------------------- *//*  Synchronized Custom Tooltip Content                                       *//* -------------------------------------------------------------------------- */interface InteractiveAreaTooltipContentProps {  active?: boolean  payload?: readonly { dataKey?: string | number; value?: any; payload?: any; [key: string]: any }[]  activeDatum: ActiveDatum | null  seriesLabel: string  primaryColor: string  selectionColor: string  valueFormatter?: (value: number) => string  xFormatter?: (value: string | number) => string  lockable: boolean  isLocked?: boolean}function InteractiveAreaTooltipContent({  active,  payload,  activeDatum,  seriesLabel,  primaryColor,  selectionColor,  valueFormatter,  xFormatter,  lockable,  isLocked = false,}: InteractiveAreaTooltipContentProps) {  const payloadItem = payload?.[0]?.payload as NormalizedInteractiveDatum | undefined  const hasPayload = Boolean(payloadItem)  if (!activeDatum && (!active || !hasPayload)) {    return null  }  const fmt = valueFormatter ?? ((n: number) => n.toLocaleString())  const rawX = activeDatum ? activeDatum.x : (payloadItem?.__x ?? "")  const xDisplay = xFormatter ? xFormatter(rawX) : String(rawX)  const val = activeDatum ? activeDatum.value : (payloadItem?.__value ?? null)  const isMissing = val === null  const lockedState = activeDatum ? activeDatum.isLocked : isLocked  const isCustomHex = typeof selectionColor === "string" && selectionColor.startsWith("#")  return (    <div      className={cn(        "rounded-xl border bg-zinc-950/95 p-3.5 shadow-2xl backdrop-blur-md min-w-[180px] max-w-[260px] text-left transition-all duration-150 pointer-events-none select-none z-50",        lockedState          ? "border-amber-500/40 shadow-[0_12px_32px_-4px_rgba(0,0,0,0.6),0_0_16px_rgba(245,158,11,0.15)] ring-1 ring-amber-500/25"          : "border-white/[0.12] ring-1 ring-white/[0.04]"      )}      style={        lockedState && isCustomHex          ? {              borderColor: `${selectionColor}66`,              boxShadow: `0 12px 32px -4px rgba(0,0,0,0.6), 0 0 16px ${selectionColor}26, 0 0 0 1px ${selectionColor}40`,            }          : undefined      }    >      {/* Header: Coordinate + Lock Badge */}      <div className="flex items-center justify-between gap-2 border-b border-white/[0.08] pb-2 mb-2.5">        <span className="font-mono text-xs font-semibold text-zinc-200 tracking-wide truncate">          {xDisplay}        </span>        {lockedState && (          <span            className="inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] font-mono font-semibold tracking-tight border bg-amber-500/15 border-amber-500/40 text-amber-300 dark:bg-amber-400/15 dark:border-amber-400/40 dark:text-amber-200 shadow-2xs"            style={              isCustomHex                ? {                    backgroundColor: `${selectionColor}20`,                    borderColor: `${selectionColor}55`,                    color: selectionColor,                  }                : undefined            }          >            <HugeiconsIcon icon={LockKeyIcon} size={11} strokeWidth={2.2} className="shrink-0" />            Locked          </span>        )}      </div>      {/* Series Metric Row */}      <div className="flex items-center justify-between gap-3">        <div className="flex items-center gap-2 min-w-0">          <span            className="size-2 rounded-full ring-1 ring-white/20 shadow-xs shrink-0"            style={{ backgroundColor: primaryColor }}          />          <span className="text-xs font-medium text-zinc-300 font-sans truncate">            {seriesLabel}          </span>        </div>        <span className="font-mono text-xs font-bold text-white shrink-0 tabular-nums">          {isMissing ? "—" : fmt(val)}        </span>      </div>      {/* Interaction Hint Footer */}      {lockable && (        <div className="mt-2.5 pt-2 border-t border-white/[0.08] flex items-center justify-between text-[10px] font-mono text-zinc-400">          {lockedState ? (            <span className="flex items-center gap-1.5">              <kbd className="inline-flex items-center justify-center px-1.5 py-0.5 rounded bg-zinc-800/90 border border-white/15 text-[9px] font-mono font-semibold text-zinc-200 shadow-2xs">                Esc              </kbd>              <span className="text-zinc-400">or click to release</span>            </span>          ) : (            <span className="flex items-center gap-1.5 text-zinc-500">              <kbd className="inline-flex items-center justify-center px-1.5 py-0.5 rounded bg-zinc-800/60 border border-white/10 text-[9px] font-mono font-medium text-zinc-400">                Click              </kbd>              <span>to lock</span>            </span>          )}        </div>      )}    </div>  )}/* -------------------------------------------------------------------------- *//*  Main InteractiveArea Component                                            *//* -------------------------------------------------------------------------- */export function InteractiveArea<  TData extends Record<string, unknown> = Record<string, unknown>,  XVal extends string | number = string | number>({  data = [],  xKey,  series,  color: propColor,  selectionColor: propSelectionColor,  fillOpacity = 0.22,  height = 320,  curve = "monotone",  domain = "auto",  baseline = "zero",  lockable = true,  lockableTooltip,  defaultLockedIndex = null,  initialFocus = "none",  missingValuePolicy = "gap",  animation = "draw",  motion = true,  showGrid = true,  showXAxis = true,  showYAxis = true,  showLegend = false,  valueFormatter,  xFormatter,  onActiveChange,  onLockChange,  title,  description,  className,  loading = false,  empty = false,  error = null,  unavailable = false,}: InteractiveAreaProps<TData, XVal>) {  const isLockable = lockableTooltip !== undefined ? lockableTooltip : lockable  const reducedMotion = useChartReducedMotion()  const uid = React.useId()  const titleId = `plotcn-area-interactive-title-${uid}`  const descId = `plotcn-area-interactive-desc-${uid}`  // Resolved series metadata & colors  const activeSeriesKey = series?.key ?? "value"  const seriesLabel = series?.label ?? "Requests"  const primaryColor = propColor ?? "var(--chart-1, #3b82f6)"  const selectionColor = propSelectionColor ?? "var(--chart-selection, #f59e0b)"  // Normalized observation dataset  const normalizedData = React.useMemo(    () => normalizeInteractiveData(data, xKey, activeSeriesKey, missingValuePolicy),    [data, xKey, activeSeriesKey, missingValuePolicy]  )  // Safe Y-axis domain  const safeDomain = React.useMemo(    () => calculateInteractiveAreaDomain(normalizedData, domain, baseline),    [normalizedData, domain, baseline]  )  // Resolved baseline value for Area baseValue  const resolvedBaseValue = React.useMemo(() => {    if (typeof baseline === "number" && Number.isFinite(baseline)) return baseline    if (baseline === "domain-min") return safeDomain[0]    return 0  }, [baseline, safeDomain])  // Explicit interaction state model  const [lockedIndex, setLockedIndex] = React.useState<number | null>(() => {    if (      typeof defaultLockedIndex === "number" &&      defaultLockedIndex >= 0 &&      defaultLockedIndex < normalizedData.length    ) {      return defaultLockedIndex    }    return null  })  const [activeIndex, setActiveIndex] = React.useState<number | null>(() => {    if (      typeof defaultLockedIndex === "number" &&      defaultLockedIndex >= 0 &&      defaultLockedIndex < normalizedData.length    ) {      return defaultLockedIndex    }    if (normalizedData.length === 0) return null    if (initialFocus === "first") return 0    if (initialFocus === "last") return normalizedData.length - 1    return null  })  const [isChartFocused, setIsChartFocused] = React.useState(false)  // Ensure lockedIndex is safely cleared if underlying datum disappears after data update  React.useEffect(() => {    if (lockedIndex !== null && (lockedIndex >= normalizedData.length || normalizedData.length === 0)) {      setLockedIndex(null)      if (onLockChange) onLockChange(null, null)    }  }, [normalizedData.length, lockedIndex, onLockChange])  // Effective visible index: lockedIndex takes priority over transient activeIndex  const effectiveIndex = lockedIndex !== null ? lockedIndex : activeIndex  // Construct active datum object for callbacks and tooltip  const activeDatum = React.useMemo<ActiveDatum<TData, XVal> | null>(() => {    if (effectiveIndex === null || effectiveIndex < 0 || effectiveIndex >= normalizedData.length) {      return null    }    const item = normalizedData[effectiveIndex]    return {      index: effectiveIndex,      x: item.__x as XVal,      value: item.__value,      raw: item.__raw as TData,      datum: item.__raw as TData,      isLocked: lockedIndex !== null && lockedIndex === effectiveIndex,      isMissing: item.__value === null,    }  }, [effectiveIndex, lockedIndex, normalizedData])  // Notify consumer callbacks when state changes  React.useEffect(() => {    if (onActiveChange) {      onActiveChange(activeDatum, effectiveIndex)    }  }, [activeDatum, effectiveIndex, onActiveChange])  React.useEffect(() => {    if (onLockChange) {      if (lockedIndex !== null && activeDatum && activeDatum.isLocked) {        onLockChange(activeDatum, lockedIndex)      } else {        onLockChange(null, null)      }    }  }, [lockedIndex, activeDatum, onLockChange])  /* -------------------------------------------------------------------------- */  /*  Keyboard Navigation Handlers                                              */  /* -------------------------------------------------------------------------- */  const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {    if (normalizedData.length === 0) return    const currentIndex = activeIndex !== null ? activeIndex : 0    switch (e.key) {      case "ArrowRight": {        e.preventDefault()        const nextIdx = Math.min(currentIndex + 1, normalizedData.length - 1)        setActiveIndex(nextIdx)        if (lockedIndex !== null) setLockedIndex(nextIdx)        break      }      case "ArrowLeft": {        e.preventDefault()        const prevIdx = Math.max(currentIndex - 1, 0)        setActiveIndex(prevIdx)        if (lockedIndex !== null) setLockedIndex(prevIdx)        break      }      case "Home": {        e.preventDefault()        setActiveIndex(0)        if (lockedIndex !== null) setLockedIndex(0)        break      }      case "End": {        e.preventDefault()        const lastIdx = normalizedData.length - 1        setActiveIndex(lastIdx)        if (lockedIndex !== null) setLockedIndex(lastIdx)        break      }      case "Enter":      case " ": {        if (!isLockable) return        e.preventDefault()        const targetIndex = activeIndex !== null ? activeIndex : 0        if (lockedIndex === targetIndex) {          setLockedIndex(null)        } else {          setLockedIndex(targetIndex)          setActiveIndex(targetIndex)        }        break      }      case "Escape": {        e.preventDefault()        setLockedIndex(null)        break      }    }  }  /* -------------------------------------------------------------------------- */  /*  Pointer / Mouse Scrubbing Handlers                                        */  /* -------------------------------------------------------------------------- */  const handleChartMouseMove = (state: any) => {    if (!state || typeof state.activeTooltipIndex !== "number") return    const idx = state.activeTooltipIndex    if (idx < 0 || idx >= normalizedData.length) return    // If locked, incidental pointer movement does not override locked datum    if (lockedIndex === null) {      if (activeIndex !== idx) {        setActiveIndex(idx)      }    }  }  const handleChartMouseLeave = () => {    // When unlocked, pointer leave clears transient active inspection    if (lockedIndex === null) {      setActiveIndex(null)    }  }  const handleChartClick = (state: any) => {    if (!isLockable || normalizedData.length === 0) return    const clickedIdx = typeof state?.activeTooltipIndex === "number" ? state.activeTooltipIndex : activeIndex    if (clickedIdx === null || clickedIdx < 0 || clickedIdx >= normalizedData.length) return    if (lockedIndex === clickedIdx) {      // Clicking locked datum again releases lock      setLockedIndex(null)    } else {      // Move lock directly to clicked observation      setLockedIndex(clickedIdx)      setActiveIndex(clickedIdx)    }  }  // Animation settings  const isAnimated = animation !== "none" && motion !== false && !reducedMotion  const animationDuration =    typeof motion === "object" && motion?.duration !== undefined ? motion.duration * 1000 : 350  // Screen reader factual summary  const factualSummary = React.useMemo(() => {    if (normalizedData.length === 0) return "No observations recorded."    const count = normalizedData.length    const activeInfo = activeDatum      ? ` Currently ${activeDatum.isLocked ? "locked on" : "inspecting"} observation ${activeDatum.index + 1} of ${count} at ${String(activeDatum.x)}${activeDatum.isMissing ? " (value unavailable)" : ` with value ${activeDatum.value}`}.`      : " Use Left and Right Arrow keys to inspect observations along the domain."    return `Interactive time-series area chart depicting ${count} observations for ${seriesLabel}.${activeInfo}`  }, [normalizedData.length, activeDatum, seriesLabel])  /* -------------------------------------------------------------------------- */  /*  Early Return Exception States                                             */  /* -------------------------------------------------------------------------- */  if (error) {    return (      <figure        role="region"        aria-label={title || `${seriesLabel} chart error state`}        className={cn("plotcn-area-interactive relative w-full overflow-hidden rounded-xl border border-white/10 bg-zinc-950 p-4", className)}        style={{ height }}      >        <ChartErrorState          title="Unable to load interactive area visualization"          description={            typeof error === "string"              ? error              : error?.message || "An unexpected error occurred while loading inspection data."          }        />      </figure>    )  }  if (loading) {    return (      <figure        role="region"        aria-label={title || `${seriesLabel} chart loading state`}        className={cn("plotcn-area-interactive relative w-full overflow-hidden rounded-xl border border-white/10 bg-zinc-950 p-4", className)}        style={{ height }}      >        <ChartLoadingState          title="Loading interactive area…"          description="Preparing domain observations for nearest-X inspection"        />      </figure>    )  }  if (unavailable) {    return (      <figure        role="region"        aria-label={title || `${seriesLabel} chart unavailable state`}        className={cn("plotcn-area-interactive relative w-full overflow-hidden rounded-xl border border-white/10 bg-zinc-950 p-4", className)}        style={{ height }}      >        <ChartUnavailableState          title="Inspection metrics unavailable"          description={            typeof unavailable === "string"              ? unavailable              : "Timeline observation metrics are unavailable for this view."          }        />      </figure>    )  }  if (empty || normalizedData.length === 0) {    return (      <figure        role="region"        aria-label={title || `${seriesLabel} chart empty state`}        className={cn("plotcn-area-interactive relative w-full overflow-hidden rounded-xl border border-white/10 bg-zinc-950 p-4", className)}        style={{ height }}      >        <ChartEmptyState          title="No data available"          description="Provide ordered observations to inspect metrics across the timeline."        />      </figure>    )  }  /* -------------------------------------------------------------------------- */  /*  Active Coordinate Crosshair & Point Calculation                           */  /* -------------------------------------------------------------------------- */  const activeXCoordinate = effectiveIndex !== null ? normalizedData[effectiveIndex].__x : null  const isCurrentlyLocked = lockedIndex !== null  return (    <figure      role="region"      aria-labelledby={titleId}      aria-describedby={descId}      tabIndex={0}      onKeyDown={handleKeyDown}      onFocus={() => setIsChartFocused(true)}      onBlur={() => setIsChartFocused(false)}      className={cn(        "plotcn-area-interactive relative w-full outline-none select-none transition-all duration-150 rounded-xl",        "focus-visible:ring-2 focus-visible:ring-[var(--chart-focus,#38bdf8)] focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950",        className      )}      style={{        height,        minHeight: typeof height === "number" ? height : 320,        touchAction: "pan-y", // Strictly preserves vertical page scroll while allowing horizontal inspection      }}    >      {/* Accessible Name & Screen Reader Description */}      <div className="sr-only">        <h3 id={titleId}>{title || `${seriesLabel} Interactive Area Chart`}</h3>        <p id={descId}>{description ? `${description} ${factualSummary}` : factualSummary}</p>      </div>      <ChartContainer className="w-full h-full min-w-0 max-w-full overflow-hidden">        <ResponsiveContainer          width="100%"          height="100%"          minWidth={0}          minHeight={0}          initialDimension={{ width: 320, height: typeof height === "number" ? height : 320 }}        >          <AreaChart            data={normalizedData as any}            margin={{ top: 12, right: 16, bottom: 8, left: 8 }}            onMouseMove={handleChartMouseMove}            onMouseLeave={handleChartMouseLeave}            onClick={handleChartClick}          >            {/* 1. Subtle Reference Grid */}            {showGrid && (              <CartesianGrid                stroke="var(--chart-grid, rgba(255, 255, 255, 0.08))"                strokeDasharray="3 3"                vertical={false}              />            )}            {/* 2. Horizontal Category Scale */}            <XAxis              hide={!showXAxis}              dataKey="__x"              tickLine={false}              axisLine={false}              tick={{ fontSize: 11, fill: "var(--chart-axis, #71717a)" }}              tickFormatter={xFormatter as any}              dy={6}            />            {/* 3. Vertical Numeric Scale */}            <YAxis              hide={!showYAxis}              domain={safeDomain as any}              tickLine={false}              axisLine={false}              tick={{ fontSize: 11, fill: "var(--chart-axis, #71717a)" }}              tickFormatter={valueFormatter ? (v) => valueFormatter(Number(v)) : undefined}              dx={-4}            />            {/* 4. Observation-Aligned Structural Crosshair (Snaps to selected datum X, never raw pointer) */}            {activeXCoordinate !== null && (              <ReferenceLine                x={activeXCoordinate}                stroke={isCurrentlyLocked ? selectionColor : "var(--chart-crosshair, rgba(255, 255, 255, 0.28))"}                strokeDasharray="3 3"                strokeWidth={isCurrentlyLocked ? 1.5 : 1}              />            )}            {/* 5. Synchronized Tooltip */}            <Tooltip              active={isCurrentlyLocked || (isChartFocused && activeIndex !== null) ? true : undefined}              defaultIndex={typeof defaultLockedIndex === "number" ? defaultLockedIndex : undefined}              cursor={false} // Disabled so only observation-aligned ReferenceLine crosshair renders              content={                <InteractiveAreaTooltipContent                  activeDatum={activeDatum}                  seriesLabel={seriesLabel}                  primaryColor={primaryColor}                  selectionColor={selectionColor}                  valueFormatter={valueFormatter}                  xFormatter={xFormatter}                  lockable={isLockable}                  isLocked={isCurrentlyLocked}                />              }            />            {/* 6. Optional Legend */}            {showLegend && (              <Legend                content={() => (                  <div className="flex items-center justify-center gap-2 pt-2 text-xs font-mono text-zinc-400">                    <span className="size-2.5 rounded-xs" style={{ backgroundColor: primaryColor }} />                    <span>{seriesLabel}</span>                  </div>                )}              />            )}            {/* 7. Area Geometry with Active / Locked Point Marker */}            <Area              type={curve === "step" ? "stepAfter" : curve}              dataKey="__value"              name={seriesLabel}              baseValue={resolvedBaseValue}              stroke={primaryColor}              strokeWidth={2}              fill={primaryColor}              fillOpacity={fillOpacity}              connectNulls={missingValuePolicy === "connect"}              isAnimationActive={isAnimated}              animationDuration={animationDuration}              activeDot={false} // Managed deterministically through dot callback below              dot={(dotProps: any) => {                const { cx, cy, index, payload } = dotProps                if (typeof cx !== "number" || typeof cy !== "number" || payload?.__value === null) {                  return <React.Fragment key={`dot-frag-${index}`} />                }                // Exactly 0 or 1 marker is rendered: only at effectiveIndex                if (index === effectiveIndex) {                  if (index === lockedIndex) {                    // Concentric Double-Ring Marker for Locked Selection (───◎───)                    return (                      <g key={`locked-marker-${index}`} className="pointer-events-none">                        <circle                          cx={cx}                          cy={cy}                          r={8}                          fill="none"                          stroke={selectionColor}                          strokeWidth={2.5}                        />                        <circle                          cx={cx}                          cy={cy}                          r={4}                          fill={selectionColor}                          stroke="var(--chart-background, #09090b)"                          strokeWidth={1.5}                        />                      </g>                    )                  }                  // Active Dot for transient inspection (───●───)                  return (                    <circle                      key={`active-dot-${index}`}                      cx={cx}                      cy={cy}                      r={5.5}                      fill={primaryColor}                      stroke="var(--chart-background, #09090b)"                      strokeWidth={2}                      className="pointer-events-none"                    />                  )                }                // No permanent dots across the plot                return <React.Fragment key={`dot-empty-${index}`} />              }}            />          </AreaChart>        </ResponsiveContainer>      </ChartContainer>      {/* 8. Off-Screen Structured HTML Data Table for Screen Readers */}      <div className="sr-only">        <table>          <caption>{title || `${seriesLabel} Data Table`}</caption>          <thead>            <tr>              <th scope="col">{xKey}</th>              <th scope="col">{seriesLabel}</th>              <th scope="col">Status</th>            </tr>          </thead>          <tbody>            {normalizedData.map((row, idx) => (              <tr key={idx}>                <td>{String(row.__x)}</td>                <td>{row.__value !== null ? row.__value : "Unavailable"}</td>                <td>                  {idx === lockedIndex                    ? "Locked"                    : idx === activeIndex                      ? "Inspecting"                      : "Unselected"}                </td>              </tr>            ))}          </tbody>        </table>      </div>    </figure>  )}