diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Revision history for granite
 
+## 0.7.1.1 -- 2026-05-25
+* `GeomTile` honours a continuous `scaleFill` (`SColorContinuous`) via smooth RGB interpolation, and no longer emits a stray category legend entry.
+
 ## 0.7.1.0 -- 2026-05-25
 
 * Numeric `aesAlpha` mappings are now honoured for points (per-point opacity); previously only the per-layer `defAlpha` was applied.
diff --git a/granite.cabal b/granite.cabal
--- a/granite.cabal
+++ b/granite.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               granite
-version:            0.7.1.0
+version:            0.7.1.1
 synopsis:           Easy terminal plotting.
 description:        A terminal plotting library for quick and easy visualisation.
 license:            MIT
diff --git a/src/Granite/Render/Pipeline.hs b/src/Granite/Render/Pipeline.hs
--- a/src/Granite/Render/Pipeline.hs
+++ b/src/Granite/Render/Pipeline.hs
@@ -67,6 +67,7 @@
     Mapping (..),
     PolarAes (..),
     PolarDir (..),
+    Scale (..),
     Scales (..),
     Size (..),
     Theme (..),
@@ -147,12 +148,15 @@
             Just t -> not (Text.null t)
             Nothing -> False
         colorMaps = map (layerColorMap palette (chartData chart)) (chartLayers chart)
+        fillCols = case scaleFill (chartScales chart) of
+            Just (SColorContinuous cs) -> Just cs
+            _ -> Nothing
         legendEntries = collectLegend (chartLayers chart) palette colorMaps
         hasRightLegend = not (null legendEntries)
         box = computePlotBox (chartSize chart) theme hasTitle hasRightLegend False
 
         panels = layoutPanels theme box chart
-        panelMarks = concatMap (renderPanel theme palette coord colorMaps) panels
+        panelMarks = concatMap (renderPanel theme palette coord colorMaps fillCols) panels
 
         legend = legendMarks theme box legendEntries
         title = titleMarks theme box (chartTitle chart)
@@ -174,14 +178,24 @@
     [ColorSpec] ->
     Coord ->
     [Maybe [(Text, ColorSpec)]] ->
+    Maybe [ColorSpec] ->
     PanelSpec ->
     [Mark]
-renderPanel theme palette coord colorMaps ps =
+renderPanel theme palette coord colorMaps fillCols ps =
     let proj = buildProjector coord (panelBox ps) (panelXScale ps) (panelYScale ps)
         cmap i = if i < length colorMaps then colorMaps !! i else Nothing
         layerMarks =
             concat
-                [ runLayer theme (panelBox ps) proj palette (cmap i) i (panelData ps) layer
+                [ runLayer
+                    theme
+                    (panelBox ps)
+                    proj
+                    palette
+                    (cmap i)
+                    fillCols
+                    i
+                    (panelData ps)
+                    layer
                 | (i, layer) <- zip [0 :: Int ..] (panelLayers ps)
                 ]
         axes = axesMarks theme (panelBox ps) coord (panelXScale ps) (panelYScale ps)
@@ -414,11 +428,12 @@
     Projector ->
     [ColorSpec] ->
     Maybe [(Text, ColorSpec)] ->
+    Maybe [ColorSpec] ->
     Int ->
     DataFrame ->
     Layer ->
     [Mark]
-runLayer theme box proj palette colorMap ix globalFrame layer =
+runLayer theme box proj palette colorMap fillCols ix globalFrame layer =
     let frame0 = fromMaybe globalFrame (layerData layer)
         framePostStat = applyStat (layerStat layer) (layerMapping layer) frame0
         frame = applyPosition (layerPosition layer) (layerMapping layer) framePostStat
@@ -456,7 +471,7 @@
             GeomHistogram -> drawBars proj frame m col
             GeomRibbon -> drawRibbon proj frame m col
             GeomErrorbar -> drawErrorbar proj frame m col
-            GeomTile -> drawTiles proj frame m col
+            GeomTile -> drawTiles proj frame m col fillCols
             GeomBoxplot -> drawBoxplot proj frame m col
             GeomDensity -> drawDensity proj frame m col
             GeomText -> drawText proj frame m col (themeFontSize theme)
@@ -580,8 +595,9 @@
                     ]
         _ -> []
 
-drawTiles :: Projector -> DataFrame -> Mapping -> Color -> [Mark]
-drawTiles proj frame m col =
+drawTiles ::
+    Projector -> DataFrame -> Mapping -> Color -> Maybe [ColorSpec] -> [Mark]
+drawTiles proj frame m col fillCols =
     case (resolveNumColumn frame (aesX m), resolveNumColumn frame (aesY m)) of
         (Just xs, Just ys) ->
             let wX = barWidth xs / 0.8
@@ -600,7 +616,9 @@
                                     if hi == lo
                                         then 0.5
                                         else (vs !! i - lo) / (hi - lo)
-                             in gradientColor t
+                             in case fillCols of
+                                    Just cs -> continuousColorFor cs t
+                                    Nothing -> gradientColor t
                     _ -> col
              in [ rectFromCorners
                     (proj (x - halfX) (y - halfY))
@@ -625,6 +643,26 @@
         ix = floor (clamped * fromIntegral n) :: Int
      in palette !! ix
 
+{- | Map @t@ in [0,1] to a colour by piecewise-linear RGB interpolation across
+the anchor colours (used to honour a continuous 'scaleFill' on tiles).
+-}
+continuousColorFor :: [ColorSpec] -> Double -> Color
+continuousColorFor specs t =
+    case map specToColor specs of
+        [] -> gradientColor t
+        [c] -> c
+        colors ->
+            let n = length colors
+                clamped = max 0 (min 1 t)
+                pos = clamped * fromIntegral (n - 1)
+                i = min (n - 2) (floor pos)
+                frac = pos - fromIntegral i
+                Color r1 g1 b1 = colors !! i
+                Color r2 g2 b2 = colors !! (i + 1)
+                lerp a b =
+                    round (fromIntegral a + frac * (fromIntegral b - fromIntegral a))
+             in Color (lerp r1 r2) (lerp g1 g2) (lerp b1 b2)
+
 drawBoxplot :: Projector -> DataFrame -> Mapping -> Color -> [Mark]
 drawBoxplot proj frame m col =
     case ( resolveNumColumn frame (aesX m)
@@ -952,6 +990,7 @@
   where
     entriesFor ix layer cmap
         | GeomText <- layerGeom layer = []
+        | GeomTile <- layerGeom layer = []
         | Just levelColors <- cmap = levelColors
         | otherwise =
             [(legendName ix layer, palette !! (ix `mod` max 1 (length palette)))]
diff --git a/test/GoldenSpec.hs b/test/GoldenSpec.hs
--- a/test/GoldenSpec.hs
+++ b/test/GoldenSpec.hs
@@ -24,6 +24,7 @@
 import Granite.Spec (
     BinSpec (..),
     Chart (..),
+    ColorSpec (..),
     ColumnRef (..),
     Coord (..),
     Facet (..),
@@ -266,6 +267,44 @@
             , chartSize = SizeChars 30 16
             }
 
+-- A continuous-fill heatmap: GeomTile coloured by a numeric column through a
+-- 'SColorContinuous' scaleFill (blue -> white -> red). Exercises the continuous
+-- tile colour path + the suppressed tile legend.
+contHeatmap :: Chart
+contHeatmap =
+    let coords =
+            [ (fromIntegral x, fromIntegral y, fromIntegral (x + y) :: Double)
+            | x <- [0 .. 3 :: Int]
+            , y <- [0 .. 3 :: Int]
+            ]
+        df =
+            fromColumns
+                [ ("x", ColNum [x | (x, _, _) <- coords])
+                , ("y", ColNum [y | (_, y, _) <- coords])
+                , ("z", ColNum [z | (_, _, z) <- coords])
+                ]
+        tile =
+            (defLayer GeomTile)
+                { layerMapping =
+                    emptyMapping
+                        { aesX = Just (ColumnRef "x")
+                        , aesY = Just (ColumnRef "y")
+                        , aesFill = Just (ColumnRef "z")
+                        }
+                , layerStat = StatIdentity
+                }
+     in emptyChart
+            { chartData = df
+            , chartLayers = [tile]
+            , chartScales =
+                defScales
+                    { scaleFill =
+                        Just (SColorContinuous [Hex "#2166ac", Hex "#f7f7f7", Hex "#b2182b"])
+                    }
+            , chartTitle = Just "Continuous heatmap"
+            , chartSize = SizeChars 40 14
+            }
+
 -- A four-petal rose in polar coordinates: r = |sin(2θ)| sampled at 33
 -- angular positions. Locks in the polar projector + polar chrome.
 polarRose :: Chart
@@ -377,6 +416,9 @@
 
         it "pie chart renders to expected SVG output" $
             goldenText "pie-basic.svg" (renderChartSvg pieBasic)
+
+        it "continuous-fill heatmap renders to expected SVG output" $
+            goldenText "heatmap-continuous.svg" (renderChartSvg contHeatmap)
 
     describe "Sizing" $ do
         it "responsive scatter renders to expected SVG output" $
diff --git a/test/golden/heatmap-continuous.svg b/test/golden/heatmap-continuous.svg
new file mode 100644
--- /dev/null
+++ b/test/golden/heatmap-continuous.svg
@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 224" width="400" height="224" font-family="system-ui, -apple-system, sans-serif">
+<rect width="100%" height="100%" fill="white"/>
+<line x1="55" y1="196.20" x2="380" y2="196.20" stroke="#ecf0f1" stroke-width="1"/>
+<line x1="55" y1="34" x2="55" y2="196.20" stroke="#ecf0f1" stroke-width="1"/>
+<text x="100.87" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>
+<text x="178.62" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">1.0</text>
+<text x="256.38" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>
+<text x="334.13" y="211.20" text-anchor="middle" fill="#7f8c8d" font-size="11">3.0</text>
+<text x="49" y="176.97" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text>
+<text x="49" y="138.17" text-anchor="end" fill="#7f8c8d" font-size="11">1.0</text>
+<text x="49" y="99.36" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text>
+<text x="49" y="60.56" text-anchor="end" fill="#7f8c8d" font-size="11">3.0</text>
+<rect x="62.00" y="153.90" width="77.75" height="38.80" fill="#2166ac"/>
+<rect x="62.00" y="115.10" width="77.75" height="38.80" fill="#6896c5"/>
+<rect x="62.00" y="76.30" width="77.75" height="38.80" fill="#b0c7de"/>
+<rect x="62.00" y="37.49" width="77.75" height="38.80" fill="#f7f7f7"/>
+<rect x="139.75" y="153.90" width="77.75" height="38.80" fill="#6896c5"/>
+<rect x="139.75" y="115.10" width="77.75" height="38.80" fill="#b0c7de"/>
+<rect x="139.75" y="76.30" width="77.75" height="38.80" fill="#f7f7f7"/>
+<rect x="139.75" y="37.49" width="77.75" height="38.80" fill="#e0adb3"/>
+<rect x="217.50" y="153.90" width="77.75" height="38.80" fill="#b0c7de"/>
+<rect x="217.50" y="115.10" width="77.75" height="38.80" fill="#f7f7f7"/>
+<rect x="217.50" y="76.30" width="77.75" height="38.80" fill="#e0adb3"/>
+<rect x="217.50" y="37.49" width="77.75" height="38.80" fill="#c9626f"/>
+<rect x="295.25" y="153.90" width="77.75" height="38.80" fill="#f7f7f7"/>
+<rect x="295.25" y="115.10" width="77.75" height="38.80" fill="#e0adb3"/>
+<rect x="295.25" y="76.30" width="77.75" height="38.80" fill="#c9626f"/>
+<rect x="295.25" y="37.49" width="77.75" height="38.80" fill="#b2182b"/>
+<text x="217.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Continuous heatmap</text>
+</svg>
diff --git a/test/golden/plotly-heatmap-annotated.svg b/test/golden/plotly-heatmap-annotated.svg
--- a/test/golden/plotly-heatmap-annotated.svg
+++ b/test/golden/plotly-heatmap-annotated.svg
@@ -1,64 +1,62 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 256" width="480" height="256" font-family="system-ui, -apple-system, sans-serif">
 <rect width="100%" height="100%" fill="white"/>
-<line x1="55" y1="228.20" x2="360" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
+<line x1="55" y1="228.20" x2="460" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
 <line x1="55" y1="34" x2="55" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
-<text x="91.97" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>
-<text x="207.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>
-<text x="323.03" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>
+<text x="104.09" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>
+<text x="257.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>
+<text x="410.91" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>
 <text x="49" y="208.33" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text>
 <text x="49" y="134.77" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text>
 <text x="49" y="61.21" text-anchor="end" fill="#7f8c8d" font-size="11">4.0</text>
-<rect x="63.09" y="186.27" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="63.09" y="149.49" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="63.09" y="112.71" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="63.09" y="75.93" width="57.77" height="36.78" fill="#3498db"/>
-<rect x="63.09" y="39.15" width="57.77" height="36.78" fill="#2980b9"/>
-<rect x="120.85" y="186.27" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="120.85" y="149.49" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="120.85" y="112.71" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="120.85" y="75.93" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="120.85" y="39.15" width="57.77" height="36.78" fill="#3498db"/>
-<rect x="178.62" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="178.62" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="178.62" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="178.62" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="178.62" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="236.38" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="236.38" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="236.38" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="236.38" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="236.38" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="294.15" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="294.15" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="294.15" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="294.15" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="294.15" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<text x="91.97" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
-<text x="91.97" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>
-<text x="91.97" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>
-<text x="91.97" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>
-<text x="91.97" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">-0.4</text>
-<text x="149.73" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>
-<text x="149.73" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
-<text x="149.73" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
-<text x="149.73" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>
-<text x="149.73" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>
-<text x="207.50" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>
-<text x="207.50" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.7</text>
-<text x="207.50" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
-<text x="207.50" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>
-<text x="207.50" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.4</text>
-<text x="265.27" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">2.0</text>
-<text x="265.27" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>
-<text x="265.27" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>
-<text x="265.27" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.1</text>
-<text x="265.27" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>
-<text x="323.03" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>
-<text x="323.03" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>
-<text x="323.03" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
-<text x="323.03" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
-<text x="323.03" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>
-<text x="207.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Annotated heatmap</text>
-<rect x="375" y="39" width="12" height="12" fill="#3498db"/>
-<text x="391" y="49" text-anchor="start" fill="#7f8c8d" font-size="11">series 0</text>
+<rect x="65.74" y="186.27" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="65.74" y="149.49" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="65.74" y="112.71" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="65.74" y="75.93" width="76.70" height="36.78" fill="#3498db"/>
+<rect x="65.74" y="39.15" width="76.70" height="36.78" fill="#2980b9"/>
+<rect x="142.44" y="186.27" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="142.44" y="149.49" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="142.44" y="112.71" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="142.44" y="75.93" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="142.44" y="39.15" width="76.70" height="36.78" fill="#3498db"/>
+<rect x="219.15" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="219.15" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="219.15" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="219.15" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="219.15" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="295.85" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="295.85" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="295.85" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="295.85" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="295.85" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="372.56" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="372.56" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="372.56" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="372.56" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="372.56" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<text x="104.09" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
+<text x="104.09" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>
+<text x="104.09" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>
+<text x="104.09" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>
+<text x="104.09" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">-0.4</text>
+<text x="180.80" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>
+<text x="180.80" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
+<text x="180.80" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
+<text x="180.80" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>
+<text x="180.80" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.1</text>
+<text x="257.50" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>
+<text x="257.50" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.7</text>
+<text x="257.50" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
+<text x="257.50" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">0.9</text>
+<text x="257.50" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.4</text>
+<text x="334.20" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">2.0</text>
+<text x="334.20" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>
+<text x="334.20" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.5</text>
+<text x="334.20" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.1</text>
+<text x="334.20" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.6</text>
+<text x="410.91" y="204.66" text-anchor="middle" fill="#9b59b6" font-size="11">1.9</text>
+<text x="410.91" y="167.88" text-anchor="middle" fill="#9b59b6" font-size="11">1.8</text>
+<text x="410.91" y="131.10" text-anchor="middle" fill="#9b59b6" font-size="11">1.4</text>
+<text x="410.91" y="94.32" text-anchor="middle" fill="#9b59b6" font-size="11">1.0</text>
+<text x="410.91" y="57.54" text-anchor="middle" fill="#9b59b6" font-size="11">0.5</text>
+<text x="257.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Annotated heatmap</text>
 </svg>
diff --git a/test/golden/plotly-heatmap-annotated.txt b/test/golden/plotly-heatmap-annotated.txt
--- a/test/golden/plotly-heatmap-annotated.txt
+++ b/test/golden/plotly-heatmap-annotated.txt
@@ -1,16 +1,16 @@
                                                 
-            [90mAnnotated heatmap                   [0m
-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██         [0m
- [90m4.0 [0m[37m│[0m[34m█[0m[95m-0.4[0m[34m█[0m[94m█[0m[95m0.1[0m[94m█[0m[96m██[0m[95m0.4[0m[96m███[0m[95m0.6[0m[96m███[0m[95m0.5[0m[96m██ [0m[94m██[0m[90mseries 0 [0m
-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████            [0m
-     [37m│[0m[94m██[0m[95m0.1[0m[94m█[0m[96m█[0m[95m0.6[0m[96m█[0m[92m██[0m[95m0.9[0m[92m███[0m[95m1.1[0m[92m███[0m[95m1.0[0m[92m██            [0m
-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m
-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m
- [90m2.0 [0m[37m│[0m[96m██[0m[95m0.5[0m[96m█[0m[92m█[0m[95m1.0[0m[92m█[0m[93m██[0m[95m1.4[0m[93m███[0m[95m1.5[0m[93m███[0m[95m1.4[0m[93m██            [0m
-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m
-     [37m│[0m[92m██[0m[95m0.9[0m[92m█[0m[93m█[0m[95m1.4[0m[93m█[0m[91m██[0m[95m1.7[0m[91m███[0m[95m1.9[0m[91m███[0m[95m1.8[0m[91m██            [0m
-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
-     [37m│[0m[92m██[0m[95m1.0[0m[92m█[0m[93m█[0m[95m1.5[0m[93m█[0m[91m██[0m[95m1.8[0m[91m███[0m[95m2.0[0m[91m███[0m[95m1.9[0m[91m██            [0m
- [90m0.0 [0m[37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
-     [37m┼───────────────────────────────           [0m
-        [90m0.0        2.0         4.0              [0m
+                 [90mAnnotated heatmap              [0m
+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m
+ [90m4.0 [0m[37m│[0m[34m██[0m[95m-0.4[0m[34m██[0m[94m███[0m[95m0.1[0m[94m█[0m[96m███[0m[95m0.4[0m[96m█████[0m[95m0.6[0m[96m█████[0m[95m0.5[0m[96m██   [0m
+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m
+     [37m│[0m[94m███[0m[95m0.1[0m[94m██[0m[96m███[0m[95m0.6[0m[96m█[0m[92m███[0m[95m0.9[0m[92m█████[0m[95m1.1[0m[92m█████[0m[95m1.0[0m[92m██   [0m
+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m
+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m
+ [90m2.0 [0m[37m│[0m[96m███[0m[95m0.5[0m[96m██[0m[92m███[0m[95m1.0[0m[92m█[0m[93m███[0m[95m1.4[0m[93m█████[0m[95m1.5[0m[93m█████[0m[95m1.4[0m[93m██   [0m
+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m
+     [37m│[0m[92m███[0m[95m0.9[0m[92m██[0m[93m███[0m[95m1.4[0m[93m█[0m[91m███[0m[95m1.7[0m[91m█████[0m[95m1.9[0m[91m█████[0m[95m1.8[0m[91m██   [0m
+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+     [37m│[0m[92m███[0m[95m1.0[0m[92m██[0m[93m███[0m[95m1.5[0m[93m█[0m[91m███[0m[95m1.8[0m[91m█████[0m[95m2.0[0m[91m█████[0m[95m1.9[0m[91m██   [0m
+ [90m0.0 [0m[37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+     [37m┼───────────────────────────────────────── [0m
+         [90m0.0            2.0             4.0     [0m
diff --git a/test/golden/plotly-heatmap.svg b/test/golden/plotly-heatmap.svg
--- a/test/golden/plotly-heatmap.svg
+++ b/test/golden/plotly-heatmap.svg
@@ -1,39 +1,37 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 256" width="480" height="256" font-family="system-ui, -apple-system, sans-serif">
 <rect width="100%" height="100%" fill="white"/>
-<line x1="55" y1="228.20" x2="360" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
+<line x1="55" y1="228.20" x2="460" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
 <line x1="55" y1="34" x2="55" y2="228.20" stroke="#ecf0f1" stroke-width="1"/>
-<text x="91.97" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>
-<text x="207.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>
-<text x="323.03" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>
+<text x="104.09" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">0.0</text>
+<text x="257.50" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">2.0</text>
+<text x="410.91" y="243.20" text-anchor="middle" fill="#7f8c8d" font-size="11">4.0</text>
 <text x="49" y="208.33" text-anchor="end" fill="#7f8c8d" font-size="11">0.0</text>
 <text x="49" y="134.77" text-anchor="end" fill="#7f8c8d" font-size="11">2.0</text>
 <text x="49" y="61.21" text-anchor="end" fill="#7f8c8d" font-size="11">4.0</text>
-<rect x="63.09" y="186.27" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="63.09" y="149.49" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="63.09" y="112.71" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="63.09" y="75.93" width="57.77" height="36.78" fill="#3498db"/>
-<rect x="63.09" y="39.15" width="57.77" height="36.78" fill="#2980b9"/>
-<rect x="120.85" y="186.27" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="120.85" y="149.49" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="120.85" y="112.71" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="120.85" y="75.93" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="120.85" y="39.15" width="57.77" height="36.78" fill="#3498db"/>
-<rect x="178.62" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="178.62" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="178.62" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="178.62" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="178.62" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="236.38" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="236.38" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="236.38" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="236.38" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="236.38" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<rect x="294.15" y="186.27" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="294.15" y="149.49" width="57.77" height="36.78" fill="#e74c3c"/>
-<rect x="294.15" y="112.71" width="57.77" height="36.78" fill="#f1c40f"/>
-<rect x="294.15" y="75.93" width="57.77" height="36.78" fill="#2ecc71"/>
-<rect x="294.15" y="39.15" width="57.77" height="36.78" fill="#1abc9c"/>
-<text x="207.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Heatmap</text>
-<rect x="375" y="39" width="12" height="12" fill="#3498db"/>
-<text x="391" y="49" text-anchor="start" fill="#7f8c8d" font-size="11">series 0</text>
+<rect x="65.74" y="186.27" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="65.74" y="149.49" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="65.74" y="112.71" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="65.74" y="75.93" width="76.70" height="36.78" fill="#3498db"/>
+<rect x="65.74" y="39.15" width="76.70" height="36.78" fill="#2980b9"/>
+<rect x="142.44" y="186.27" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="142.44" y="149.49" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="142.44" y="112.71" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="142.44" y="75.93" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="142.44" y="39.15" width="76.70" height="36.78" fill="#3498db"/>
+<rect x="219.15" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="219.15" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="219.15" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="219.15" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="219.15" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="295.85" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="295.85" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="295.85" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="295.85" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="295.85" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<rect x="372.56" y="186.27" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="372.56" y="149.49" width="76.70" height="36.78" fill="#e74c3c"/>
+<rect x="372.56" y="112.71" width="76.70" height="36.78" fill="#f1c40f"/>
+<rect x="372.56" y="75.93" width="76.70" height="36.78" fill="#2ecc71"/>
+<rect x="372.56" y="39.15" width="76.70" height="36.78" fill="#1abc9c"/>
+<text x="257.50" y="26" text-anchor="middle" fill="#7f8c8d" font-size="14">Heatmap</text>
 </svg>
diff --git a/test/golden/plotly-heatmap.txt b/test/golden/plotly-heatmap.txt
--- a/test/golden/plotly-heatmap.txt
+++ b/test/golden/plotly-heatmap.txt
@@ -1,16 +1,16 @@
                                                 
-                 [90mHeatmap                        [0m
-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██         [0m
- [90m4.0 [0m[37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████ [0m[94m██[0m[90mseries 0 [0m
-     [37m│[0m[34m██████[0m[94m█████[0m[96m███████████████████            [0m
-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m
-     [37m│[0m[94m██████[0m[96m█████[0m[92m███████████████████            [0m
-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m
- [90m2.0 [0m[37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m
-     [37m│[0m[96m██████[0m[92m█████[0m[93m███████████████████            [0m
-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
-     [37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
- [90m0.0 [0m[37m│[0m[92m██████[0m[93m█████[0m[91m███████████████████            [0m
-     [37m┼───────────────────────────────           [0m
-        [90m0.0        2.0         4.0              [0m
+                      [90mHeatmap                   [0m
+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m
+ [90m4.0 [0m[37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m
+     [37m│[0m[34m████████[0m[94m███████[0m[96m████████████████████████   [0m
+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m
+     [37m│[0m[94m████████[0m[96m███████[0m[92m████████████████████████   [0m
+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m
+ [90m2.0 [0m[37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m
+     [37m│[0m[96m████████[0m[92m███████[0m[93m████████████████████████   [0m
+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+     [37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+ [90m0.0 [0m[37m│[0m[92m████████[0m[93m███████[0m[91m████████████████████████   [0m
+     [37m┼───────────────────────────────────────── [0m
+         [90m0.0            2.0             4.0     [0m
