diff --git a/.changeset/add-boxplot-component.md b/.changeset/add-boxplot-component.md
new file mode 100644
index 000000000..c6d436426
--- /dev/null
+++ b/.changeset/add-boxplot-component.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat: Add BoxPlot component for box-and-whisker plots
+
+New composite mark that renders whiskers, caps, IQR box, median line, and outlier dots. Supports both pre-computed statistics (`min`, `q1`, `median`, `q3`, `max`, `outliers` accessors) and automatic computation from raw values via the `values` prop. Orientation-aware via `valueAxis` context.
diff --git a/.changeset/add-dodge-component.md b/.changeset/add-dodge-component.md
new file mode 100644
index 000000000..471bf45bc
--- /dev/null
+++ b/.changeset/add-dodge-component.md
@@ -0,0 +1,19 @@
+---
+'layerchart': minor
+---
+
+feat(Dodge): Add Dodge component for deterministic non-overlapping layout
+
+A new composition component (similar to `ForceSimulation`) that packs items along one axis to avoid overlaps. Modeled after [Observable Plot's `dodge` transform](https://observablehq.com/plot/transforms/dodge):
+
+- `axis`: `'x'` or `'y'` — which axis to dodge along (default `'y'`)
+- `anchor`: `'top'`/`'middle'`/`'bottom'` (for `axis='y'`) or `'left'`/`'middle'`/`'right'` (for `axis='x'`) — controls which edge items grow away from
+- `padding`: minimum px gap between items
+- `r`: collision radius per item (constant or accessor). When omitted, falls back to the chart's `r` accessor / `rScale` (matching `Points`), then to a default of `5`.
+- `position`: override the anchor-axis pixel accessor (defaults to chart's `xGet`/`yGet`)
+
+Yields each item's computed pixel `x`/`y` (and original `index`) via the children snippet, so you can render with any primitive (`Circle`, `Text`, etc.).
+
+Also includes a `rowHeight` mode that switches from circular to row-based rectangular packing — useful for text labels where circular collision would produce unnecessarily large vertical gaps. The pure `dodge()` algorithm is exported from `Dodge.shared.svelte.ts` for direct use.
+
+Algorithm modeled after Observable Plot / SveltePlot: maintains an interval tree of placed items keyed by anchor-axis extent, queries it for items in the new item's collision zone, and builds candidate dodge-axis positions from circle-tangency math. Currently implemented as a linear-scan tracker with the same API; can be swapped for a real interval tree without API changes if profiling demands it.
diff --git a/.changeset/add-geoclippath-component.md b/.changeset/add-geoclippath-component.md
new file mode 100644
index 000000000..947dfeb53
--- /dev/null
+++ b/.changeset/add-geoclippath-component.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat: New `GeoClipPath` component for clipping content to GeoJSON boundaries in both SVG and Canvas modes
diff --git a/.changeset/add-georaster-component.md b/.changeset/add-georaster-component.md
new file mode 100644
index 000000000..024d3c6da
--- /dev/null
+++ b/.changeset/add-georaster-component.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat: New `GeoRaster` component for reprojecting raster imagery (e.g. NASA Blue Marble) onto any d3-geo projection via per-pixel inverse sampling on Canvas
diff --git a/.changeset/add-pattern-rects.md b/.changeset/add-pattern-rects.md
new file mode 100644
index 000000000..a3871c072
--- /dev/null
+++ b/.changeset/add-pattern-rects.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat(Pattern): Add `rects` shape definition for tile patterns for rendering one or more rectangles per pattern tile
diff --git a/.changeset/add-smart-label-placement.md b/.changeset/add-smart-label-placement.md
new file mode 100644
index 000000000..3a45f1c52
--- /dev/null
+++ b/.changeset/add-smart-label-placement.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat(Labels): Add `smart` placement option
+
+New `placement="smart"` mode that dynamically positions labels based on neighboring point values (peak, trough, rising, falling) to reduce overlapping.
diff --git a/.changeset/add-stats-utils.md b/.changeset/add-stats-utils.md
new file mode 100644
index 000000000..f111cfb1d
--- /dev/null
+++ b/.changeset/add-stats-utils.md
@@ -0,0 +1,8 @@
+---
+'layerchart': minor
+---
+
+feat: Add statistical utility functions `computeBoxStats()` and `kde()`
+
+- `computeBoxStats(values, k?)` computes the five-number summary and outliers using the Tukey IQR method
+- `kde(values, options?)` computes kernel density estimation using the Epanechnikov kernel with Silverman's rule-of-thumb bandwidth
diff --git a/.changeset/add-text-segments.md b/.changeset/add-text-segments.md
new file mode 100644
index 000000000..fc777bd5c
--- /dev/null
+++ b/.changeset/add-text-segments.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat(Text): Add `segments` prop for inline mixed-style text
+
+New `segments` prop accepts an array of `{ value, class }` objects to render text with different styles (font size, weight, color) inline. Works across SVG (via tspans), Canvas (via sequential measureText/fillText), and HTML layers. Useful for labels that combine a bold name with a lighter value, such as treemap headers.
diff --git a/.changeset/add-trail-component.md b/.changeset/add-trail-component.md
new file mode 100644
index 000000000..24ff4a244
--- /dev/null
+++ b/.changeset/add-trail-component.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat: New Trail component for variable-width lines
diff --git a/.changeset/add-violin-component.md b/.changeset/add-violin-component.md
new file mode 100644
index 000000000..cddfe4c91
--- /dev/null
+++ b/.changeset/add-violin-component.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat: Add Violin component for violin plots
+
+New composite mark that renders a symmetric density curve (mirrored area) from raw data using kernel density estimation (Epanechnikov kernel). Supports pre-computed density data via `density` prop or automatic KDE from raw values via `values` prop. Optional `box` and `median` overlays. Configurable `bandwidth`, `thresholds`, and `curve`.
diff --git a/.changeset/add-waffle-component.md b/.changeset/add-waffle-component.md
new file mode 100644
index 000000000..c78c7a3e9
--- /dev/null
+++ b/.changeset/add-waffle-component.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat(Waffle): Add Waffle component for countable-cell visualizations
diff --git a/.changeset/afraid-jobs-say.md b/.changeset/afraid-jobs-say.md
new file mode 100644
index 000000000..6a705dae3
--- /dev/null
+++ b/.changeset/afraid-jobs-say.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat(Spline): Support geo projection
diff --git a/.changeset/all-papers-unite.md b/.changeset/all-papers-unite.md
new file mode 100644
index 000000000..f14eded0f
--- /dev/null
+++ b/.changeset/all-papers-unite.md
@@ -0,0 +1,5 @@
+---
+'layerchart': patch
+---
+
+fix: Prevent submitting forms when clicking legend buttons
diff --git a/.changeset/annotation-line-sloped.md b/.changeset/annotation-line-sloped.md
new file mode 100644
index 000000000..75c4e2562
--- /dev/null
+++ b/.changeset/annotation-line-sloped.md
@@ -0,0 +1,8 @@
+---
+'layerchart': minor
+---
+
+feat(AnnotationLine): Add `x1`/`y1`/`x2`/`y2` props for sloped lines
+
+- Pass any combination of `x1`, `y1`, `x2`, `y2` to draw a line between arbitrary points. Missing coordinates fall back to the corresponding axis range (so `x1`/`x2` alone still span the y range, etc.). The existing `x` / `y` shorthand for full-span vertical/horizontal lines is unchanged.
+- Labels on sloped lines automatically rotate to follow the line angle (normalized to stay upright), with `labelPlacement`, `labelXOffset`, and `labelYOffset` applied along and perpendicular to the line.
diff --git a/.changeset/annotation-point-link-callouts.md b/.changeset/annotation-point-link-callouts.md
new file mode 100644
index 000000000..49d9074c6
--- /dev/null
+++ b/.changeset/annotation-point-link-callouts.md
@@ -0,0 +1,8 @@
+---
+'layerchart': minor
+---
+
+feat(AnnotationPoint): Add `link` prop for ring-note style callouts, plus geo projection support
+
+- Pass `link={true}` or `link={{ type: 'beveled', radius: 20, ... }}` etc. to draw a `` from the ring edge to the label. Any `Link` prop (`type`, `curve`, `sweep`, `radius`, `bend`, `class`, ...) can be passed through.
+- Inside a geo ``, `x`/`y` are now interpreted as `[lon, lat]` and projected directly, so `AnnotationPoint` can be used on maps.
diff --git a/.changeset/arclabel-component.md b/.changeset/arclabel-component.md
new file mode 100644
index 000000000..b5475aaaa
--- /dev/null
+++ b/.changeset/arclabel-component.md
@@ -0,0 +1,17 @@
+---
+'layerchart': minor
+---
+
+feat(ArcLabel): New component for positioning text labels on arc segments
+
+`ArcLabel` is a new marking component for placing text (and optional leader lines) relative to an arc. It's used internally by `PieChart` and `ArcChart` when the `labels` prop is set, but can also be rendered directly inside an `Arc` children snippet.
+
+Supported placements:
+
+- `centroid` — at the arc centroid (horizontal text, default)
+- `centroid-rotated` — at the centroid, rotated to follow the arc tangent, flipped where needed so text stays upright
+- `centroid-radial` — at the centroid, rotated to read along the radial direction (center → outer edge)
+- `inner` / `middle` / `outer` — along the inner, medial, or outer arc path (centered via `startOffset: '50%'` by default)
+- `callout` — outside the arc with a leader line that bends horizontally to the label
+
+`ArcLabel` accepts a single `offset` prop that is routed to the placement-appropriate radial padding (centroid offset, `innerPadding`/`outerPadding`, or `calloutLineLength`), plus `calloutLineLength` / `calloutLabelOffset` / `calloutPadding` for fine-grained control of callout leader lines. The leader line renders via the `Path` primitive, so it works in both SVG and Canvas chart layers.
diff --git a/.changeset/arctext-centered-default.md b/.changeset/arctext-centered-default.md
new file mode 100644
index 000000000..573ee385b
--- /dev/null
+++ b/.changeset/arctext-centered-default.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+breaking(Arc): Center arc text along path by default for `inner`/`middle`/`outer` positions
+
+`getArcTextProps('inner' | 'middle' | 'outer')` now defaults to `startOffset: '50%'` with `textAnchor: 'middle'`, centering the text along the arc path rather than anchoring it at the arc start. When an explicit `startOffset` is provided, the anchor falls back to `'start'` so the text begins at that position (matching prior behavior for callers that set a start offset).
diff --git a/.changeset/arctext-inner-padding.md b/.changeset/arctext-inner-padding.md
new file mode 100644
index 000000000..2def49808
--- /dev/null
+++ b/.changeset/arctext-inner-padding.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat(Arc): Add `innerPadding` option to `getArcTextProps` / `getTrackTextProps`
+
+`ArcTextOptions` now supports an `innerPadding` option, symmetric to the existing `outerPadding`. Positive values shrink the inner radius used to build the `inner`/`middle` arc text paths, moving text inward (toward the chart center). Previously, offsetting an `inner`-placed arc label away from the arc edge required overriding the path manually; now it works the same as `outerPadding` does for `outer` text.
diff --git a/.changeset/area-y0-baseline-default.md b/.changeset/area-y0-baseline-default.md
new file mode 100644
index 000000000..7ca9f297a
--- /dev/null
+++ b/.changeset/area-y0-baseline-default.md
@@ -0,0 +1,7 @@
+---
+'layerchart': patch
+---
+
+fix(Area): Default y0 baseline to chart's yBaseline when set
+
+Area's y0 fallback now respects the chart's `yBaseline` prop (e.g. `yBaseline={0}` set by AreaChart) instead of always using `min(yScale.domain())`. This fixes areas filling to the bottom of the chart instead of to the baseline when data goes negative.
diff --git a/.changeset/axis-grid-stroke-fill-props.md b/.changeset/axis-grid-stroke-fill-props.md
new file mode 100644
index 000000000..be3b22a44
--- /dev/null
+++ b/.changeset/axis-grid-stroke-fill-props.md
@@ -0,0 +1,5 @@
+---
+'layerchart': patch
+---
+
+feat: Add `stroke` and `fill` props to `Axis` and `Grid` for explicit color control (useful for SSR where CSS variables are unavailable)
diff --git a/.changeset/band-scale-transform-brush.md b/.changeset/band-scale-transform-brush.md
new file mode 100644
index 000000000..161c67b05
--- /dev/null
+++ b/.changeset/band-scale-transform-brush.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+feat(Chart, BrushState): Add band scale (categorical) support for transform pan/zoom and brush selection. Uses range-rescaling pattern to smoothly zoom and pan categorical bar charts. Automatically constrains panning to data boundaries and prevents zooming out past initial view.
diff --git a/.changeset/band-tick-spacing-default.md b/.changeset/band-tick-spacing-default.md
new file mode 100644
index 000000000..fc01ca555
--- /dev/null
+++ b/.changeset/band-tick-spacing-default.md
@@ -0,0 +1,5 @@
+---
+'layerchart': minor
+---
+
+fix(Axis): Default `tickSpacing` to `null` for categorical band scales, showing all ticks by default instead of reducing them. Use `tickSpacing={80}` to opt-in to tick reducing on categorical band scale axes.
diff --git a/.changeset/band-tick-spacing.md b/.changeset/band-tick-spacing.md
new file mode 100644
index 000000000..a82f1456b
--- /dev/null
+++ b/.changeset/band-tick-spacing.md
@@ -0,0 +1,5 @@
+---
+'layerchart': patch
+---
+
+Support `tickSpacing` for band scales on Axis, thinning tick labels when the domain is larger than the available space. Automatically shows more tick labels when zoomed in on band scale transforms.
diff --git a/.changeset/bar-html-layer-support.md b/.changeset/bar-html-layer-support.md
new file mode 100644
index 000000000..5d32b7dcf
--- /dev/null
+++ b/.changeset/bar-html-layer-support.md
@@ -0,0 +1,7 @@
+---
+'layerchart': minor
+---
+
+feat(Bar, Bars): Support `` layer
+
+Bar/Bars now render in `` layers in addition to `