{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://insightcharts.dev/schema/insight-spec.json",
  "title": "InsightCharts spec",
  "description": "A component described as JSON: { type, ...props }. Render with <Insight spec={...} />. Generated from the component manifest.",
  "oneOf": [
    {
      "$ref": "#/definitions/components/arc-diagram"
    },
    {
      "$ref": "#/definitions/components/area-chart"
    },
    {
      "$ref": "#/definitions/components/arrow-chart"
    },
    {
      "$ref": "#/definitions/components/bar-chart"
    },
    {
      "$ref": "#/definitions/components/beeswarm-chart"
    },
    {
      "$ref": "#/definitions/components/big-number"
    },
    {
      "$ref": "#/definitions/components/block-bar"
    },
    {
      "$ref": "#/definitions/components/box-plot"
    },
    {
      "$ref": "#/definitions/components/bubble-network"
    },
    {
      "$ref": "#/definitions/components/bubble-scale"
    },
    {
      "$ref": "#/definitions/components/bullet-chart"
    },
    {
      "$ref": "#/definitions/components/bump-chart"
    },
    {
      "$ref": "#/definitions/components/calendar-heatmap"
    },
    {
      "$ref": "#/definitions/components/callout"
    },
    {
      "$ref": "#/definitions/components/choropleth-map"
    },
    {
      "$ref": "#/definitions/components/circle-pack"
    },
    {
      "$ref": "#/definitions/components/curve-rank"
    },
    {
      "$ref": "#/definitions/components/data-table"
    },
    {
      "$ref": "#/definitions/components/delta"
    },
    {
      "$ref": "#/definitions/components/diverging-bar-chart"
    },
    {
      "$ref": "#/definitions/components/donut-chart"
    },
    {
      "$ref": "#/definitions/components/dumbbell-chart"
    },
    {
      "$ref": "#/definitions/components/fan-flow"
    },
    {
      "$ref": "#/definitions/components/funnel-chart"
    },
    {
      "$ref": "#/definitions/components/glyph-table"
    },
    {
      "$ref": "#/definitions/components/headline"
    },
    {
      "$ref": "#/definitions/components/heatmap"
    },
    {
      "$ref": "#/definitions/components/histogram"
    },
    {
      "$ref": "#/definitions/components/icon-array-grid"
    },
    {
      "$ref": "#/definitions/components/icon-stat"
    },
    {
      "$ref": "#/definitions/components/legend-key"
    },
    {
      "$ref": "#/definitions/components/line-chart"
    },
    {
      "$ref": "#/definitions/components/lollipop-chart"
    },
    {
      "$ref": "#/definitions/components/nested-shares"
    },
    {
      "$ref": "#/definitions/components/orbit-chart"
    },
    {
      "$ref": "#/definitions/components/pictogram-chart"
    },
    {
      "$ref": "#/definitions/components/pill-rank"
    },
    {
      "$ref": "#/definitions/components/progress-meter"
    },
    {
      "$ref": "#/definitions/components/proportional-area"
    },
    {
      "$ref": "#/definitions/components/prose"
    },
    {
      "$ref": "#/definitions/components/pull-quote"
    },
    {
      "$ref": "#/definitions/components/radial-bar-chart"
    },
    {
      "$ref": "#/definitions/components/radial-spokes"
    },
    {
      "$ref": "#/definitions/components/ribbon-chart"
    },
    {
      "$ref": "#/definitions/components/sankey-chart"
    },
    {
      "$ref": "#/definitions/components/scale-ladder"
    },
    {
      "$ref": "#/definitions/components/scatter-chart"
    },
    {
      "$ref": "#/definitions/components/segmented-bar"
    },
    {
      "$ref": "#/definitions/components/shape-fill"
    },
    {
      "$ref": "#/definitions/components/slope-chart"
    },
    {
      "$ref": "#/definitions/components/small-multiples"
    },
    {
      "$ref": "#/definitions/components/source-note"
    },
    {
      "$ref": "#/definitions/components/sparkline"
    },
    {
      "$ref": "#/definitions/components/stat-circles"
    },
    {
      "$ref": "#/definitions/components/stat-tile"
    },
    {
      "$ref": "#/definitions/components/step-marker"
    },
    {
      "$ref": "#/definitions/components/strip-plot"
    },
    {
      "$ref": "#/definitions/components/timeline-chart"
    },
    {
      "$ref": "#/definitions/components/treemap"
    },
    {
      "$ref": "#/definitions/components/unit-blocks"
    },
    {
      "$ref": "#/definitions/components/waffle-chart"
    },
    {
      "$ref": "#/definitions/components/annotated-timeline"
    },
    {
      "$ref": "#/definitions/components/before-after"
    },
    {
      "$ref": "#/definitions/components/chart-callout"
    },
    {
      "$ref": "#/definitions/components/chart-tabs"
    },
    {
      "$ref": "#/definitions/components/comparison-table"
    },
    {
      "$ref": "#/definitions/components/filter-chips"
    },
    {
      "$ref": "#/definitions/components/hero-figure"
    },
    {
      "$ref": "#/definitions/components/kpi-grid"
    },
    {
      "$ref": "#/definitions/components/linked-charts"
    },
    {
      "$ref": "#/definitions/components/metric-breakdown"
    },
    {
      "$ref": "#/definitions/components/poster"
    },
    {
      "$ref": "#/definitions/components/proportion-statement"
    },
    {
      "$ref": "#/definitions/components/quote-figure"
    },
    {
      "$ref": "#/definitions/components/ranked-list"
    },
    {
      "$ref": "#/definitions/components/scrolly-chart"
    },
    {
      "$ref": "#/definitions/components/section"
    },
    {
      "$ref": "#/definitions/components/small-multiple-grid"
    },
    {
      "$ref": "#/definitions/components/stat-row"
    },
    {
      "$ref": "#/definitions/components/trend-card"
    },
    {
      "$ref": "#/definitions/components/atlas-poster"
    },
    {
      "$ref": "#/definitions/components/comparison-brief"
    },
    {
      "$ref": "#/definitions/components/count-poster"
    },
    {
      "$ref": "#/definitions/components/data-explorer"
    },
    {
      "$ref": "#/definitions/components/executive-brief"
    },
    {
      "$ref": "#/definitions/components/explainer"
    },
    {
      "$ref": "#/definitions/components/flow-poster"
    },
    {
      "$ref": "#/definitions/components/matrix-poster"
    },
    {
      "$ref": "#/definitions/components/network-poster"
    },
    {
      "$ref": "#/definitions/components/profile-poster"
    },
    {
      "$ref": "#/definitions/components/radial-poster"
    },
    {
      "$ref": "#/definitions/components/ranking-poster"
    },
    {
      "$ref": "#/definitions/components/report-page"
    },
    {
      "$ref": "#/definitions/components/scale-poster"
    },
    {
      "$ref": "#/definitions/components/scorecard"
    },
    {
      "$ref": "#/definitions/components/social-card"
    },
    {
      "$ref": "#/definitions/components/story-deck"
    },
    {
      "$ref": "#/definitions/components/timeline-poster"
    },
    {
      "$ref": "#/definitions/components/timeline-story"
    },
    {
      "$ref": "#/definitions/components/visual-essay"
    }
  ],
  "definitions": {
    "components": {
      "arc-diagram": {
        "title": "Arc diagram",
        "description": "Places entities in order on a line and joins each related pair with a semicircular arc whose thickness is the value of the connection; dots are sized by each entity's total. Use: Connections among up to about 20 entities that have a meaningful order (stops on a line, chapters, age groups, teams by size): trips between stations, trade between neighbours, characters sharing scenes. Avoid: Flows with a direction through stages (use sankey-chart); one source splitting into parts (use fan-flow); a full matrix of every pair where exact values matter (use heatmap); more than about 20 entities or 60 connections (use heatmap).",
        "type": "object",
        "properties": {
          "type": {
            "const": "arc-diagram"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "from": {
            "type": "string",
            "description": "Field naming one end of each connection. With `select: true` a click selects the entity under this field name, so inside `<InsightData>` other charts are filtered on `from`; pass `select: \"<field>\"` to link on the field that holds the entity in the shared rows."
          },
          "to": {
            "type": "string",
            "description": "Field naming the other end."
          },
          "value": {
            "type": "string",
            "description": "Value field: arc thickness. Omit to count rows. Rows joining the same pair are summed, in either direction."
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Entity names in the order they sit on the line. Entities not listed follow in data order."
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Line along the bottom with arcs above, or down the left with arcs to the right. Auto turns vertical on narrow screens.",
            "$comment": "default: \"auto\""
          },
          "colorBy": {
            "enum": [
              "series",
              "none"
            ],
            "description": "`series`: each arc in the colour of its first entity; past the size of the theme's palette the extra colours are derived from the theme's own. `none`: every arc in the accent. Default: series while the entities fit the palette (at most 8), none beyond."
          },
          "arcLabels": {
            "type": "boolean",
            "description": "Print values at the top of the arcs, largest first, wherever they do not collide. The values that do not fit are printed while their entity is hovered or selected, and every value is in the tooltip.",
            "$comment": "default: true"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for entity keys."
          }
        },
        "required": [
          "type",
          "from",
          "to"
        ],
        "additionalProperties": false
      },
      "area-chart": {
        "title": "Area chart",
        "description": "Shows a quantity over time as a filled area from zero: one series, stacked series, shares of 100%, or a streamgraph. Use: A volume or cumulative quantity over time where the filled magnitude matters; stacked when the total and its composition both matter; percent when only the mix matters; stream for the changing mix of many series over a long period. Avoid: Comparing the trajectories of several series against each other (use line-chart: only the bottom band of a stack has a flat baseline); a few time points (use bar-chart with stack); more than about 6 bands.",
        "type": "object",
        "properties": {
          "type": {
            "const": "area-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Time or ordered category field. ISO dates are placed on a true time axis."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or several (one area each)."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into areas (long data)."
          },
          "stack": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "const": "percent"
              }
            ],
            "description": "Stack the areas; `percent` normalises every x position to 100%.",
            "$comment": "default: false"
          },
          "stream": {
            "type": "boolean",
            "description": "Streamgraph: stack around a centred baseline. The value axis is dropped because only band thickness is readable.",
            "$comment": "default: false"
          },
          "curve": {
            "enum": [
              "linear",
              "smooth",
              "step"
            ],
            "description": "Edge shape. A streamgraph defaults to smooth.",
            "$comment": "default: \"linear\""
          },
          "labels": {
            "type": "boolean",
            "description": "Name each band inside itself where it fits; the rest go to the legend. Default: on when stacked."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "arrow-chart": {
        "title": "Arrow chart",
        "description": "Draws an arrow per category from a start value to an end value, showing the direction and size of each shift. Use: Shifts between two moments across up to about 25 categories when some rise and some fall: swings between elections, before / after a policy. Avoid: When both levels matter more than the direction (use dumbbell-chart); more than two points in time (use slope-chart or line-chart); a single value per category (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "arrow-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "category": {
            "type": "string",
            "description": "Category field: one arrow each."
          },
          "from": {
            "type": "string",
            "description": "Field with the start value, or (long data) the `series` value that marks it."
          },
          "to": {
            "type": "string",
            "description": "Field with the end value, or (long data) the `series` value that marks it."
          },
          "series": {
            "type": "string",
            "description": "Long data: the field whose values are `from` and `to`."
          },
          "value": {
            "type": "string",
            "description": "Long data: the measure field.",
            "$comment": "default: \"value\""
          },
          "good": {
            "enum": [
              "up",
              "down",
              "none"
            ],
            "description": "Direction drawn in the positive colour. `none` uses the accent for every arrow.",
            "$comment": "default: \"up\""
          },
          "sort": {
            "enum": [
              "change",
              "from",
              "to",
              "none"
            ],
            "description": "Row order.",
            "$comment": "default: \"change\""
          },
          "order": {
            "enum": [
              "desc",
              "asc"
            ],
            "description": "Sort direction.",
            "$comment": "default: \"desc\""
          },
          "labels": {
            "type": "boolean",
            "description": "Start and end values at the tail and head. Default: on for up to 14 rows; otherwise a value axis is drawn."
          },
          "changeLabel": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Print the signed change in a right-hand column; a string sets the column header.",
            "$comment": "default: false"
          },
          "zero": {
            "type": "boolean",
            "description": "Start the value axis at zero.",
            "$comment": "default: false"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for the `from` and `to` keys."
          }
        },
        "required": [
          "type",
          "category",
          "from",
          "to"
        ],
        "additionalProperties": false
      },
      "bar-chart": {
        "title": "Bar chart",
        "description": "Compares a value across categories with bars from a zero baseline. Use: Ranking or comparing up to about 20 categories; grouped for a few series, stacked when the total and its composition both matter. Avoid: Change over many time points (use line-chart); two values per category (use dumbbell-chart); more than about 5 stacked segments.",
        "type": "object",
        "properties": {
          "type": {
            "const": "bar-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Category field."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or several for grouped / stacked bars."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into series (long data)."
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Horizontal for rankings and long labels, vertical for time.",
            "$comment": "default: \"auto\""
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Bar order. Default: descending for rankings, data order for time."
          },
          "stack": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "const": "percent"
              }
            ],
            "description": "Stack series; `percent` normalises to 100%.",
            "$comment": "default: false"
          },
          "labels": {
            "type": "boolean",
            "description": "Value labels at bar ends. Default: on for one series of up to 12 bars."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "beeswarm-chart": {
        "title": "Beeswarm chart",
        "description": "Shows a distribution as one dot per row along a value axis, with dots stacked sideways where they would collide. Use: Showing a distribution while keeping every individual visible: 30 to about 2,000 named things (countries, players, schools), optionally in a few rows by group, with one or two highlighted. Avoid: More than about 2,000 rows or when only the summary matters (use histogram or box-plot); many groups with few rows each (use strip-plot); two numeric measures (use scatter-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "beeswarm-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Field that splits the dots into rows, one swarm per group."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "value": {
            "type": "string",
            "description": "Numeric field that positions each dot along the axis."
          },
          "series": {
            "type": "string",
            "description": "Field that colours dots by category. Beyond 6 categories the rest turn grey."
          },
          "label": {
            "type": "string",
            "description": "Field naming each dot, for tooltips, `highlight` and labels on highlighted dots."
          },
          "radius": {
            "type": "number",
            "description": "Dot radius in px. Default 5 down to 3 by row count; shrinks if a swarm would overflow its row."
          },
          "median": {
            "type": "boolean",
            "description": "Mark each row's median with a vertical tick.",
            "$comment": "default: false"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "value"
        ],
        "additionalProperties": false
      },
      "big-number": {
        "title": "Big number",
        "description": "A featured statistic with its label, change and the context that gives it meaning. Use: A single headline figure, or a row of three or four key numbers. Always give it context: a comparison, a denominator or a period. Avoid: Showing a number with no comparison; using a gauge or a one-slice donut for the same job.",
        "type": "object",
        "properties": {
          "type": {
            "const": "big-number"
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The figure. Numbers are formatted with `format`."
          },
          "label": {
            "type": "string",
            "description": "What it measures, sentence case."
          },
          "context": {
            "type": "string",
            "description": "The comparison, denominator or period that gives it meaning."
          },
          "delta": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Change against a baseline. Numbers render as signed percentages (0.12 is +12%)."
          },
          "deltaLabel": {
            "type": "string",
            "description": "What the delta is against, e.g. \"vs last quarter\"."
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is good news; decides the delta colour.",
            "$comment": "default: true"
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format.",
            "$comment": "default: \"auto\""
          },
          "size": {
            "enum": [
              "hero",
              "stat"
            ],
            "description": "`hero` for the one number a piece leads with.",
            "$comment": "default: \"stat\""
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Text alignment.",
            "$comment": "default: \"left\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "value",
          "label"
        ],
        "additionalProperties": false
      },
      "block-bar": {
        "title": "Block bars",
        "description": "Compares 3 to 12 values as thick rounded bars from a zero baseline, with each value printed inside the end of its bar and the category beneath. Use: A short series or ranking that should read as a bold graphic with no axis: ticket sales in each of six years, two paired measures in five regions. Add `detail` for a second small figure above each bar and `marker` for an event between two bars. Avoid: More than 12 bars, more than two series or stacked parts (use bar-chart); negative values (use diverging-bar-chart); a long time series (use line-chart); values that differ by more than about 50 times, where the short bars vanish (use proportional-area).",
        "type": "object",
        "properties": {
          "type": {
            "const": "block-bar"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one bar (or one pair of bars) per value."
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or two fields for paired bars."
          },
          "series": {
            "type": "string",
            "description": "Field that splits long-format rows into paired series."
          },
          "detail": {
            "type": "string",
            "description": "Field holding a short secondary label printed above each bar, e.g. \"3.5% of GDP\"."
          },
          "marker": {
            "type": "object",
            "description": "A dotted line after the named category, marking an event, with an optional label."
          },
          "orientation": {
            "enum": [
              "auto",
              "vertical",
              "horizontal"
            ],
            "description": "`auto` draws columns and switches to horizontal bars on narrow widths.",
            "$comment": "default: \"auto\""
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "box-plot": {
        "title": "Box plot",
        "description": "Summarises a numeric field per group as median, quartile box, whiskers and outlier dots, computed from raw rows. Use: Comparing the centre and spread of a numeric value across several groups, especially with many rows per group and an audience comfortable with quartiles. Avoid: A general audience or fewer than about 20 rows per group (use strip-plot or beeswarm-chart, which show the observations themselves); one group whose shape matters, such as two peaks, which a box hides (use histogram).",
        "type": "object",
        "properties": {
          "type": {
            "const": "box-plot"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Category field: one box per distinct value. Omit for a single box."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "value": {
            "type": "string",
            "description": "Numeric field to summarise. Pass raw rows; quartiles are computed in the chart."
          },
          "label": {
            "type": "string",
            "description": "Field naming each row, shown when hovering an outlier."
          },
          "orientation": {
            "enum": [
              "horizontal",
              "vertical"
            ],
            "description": "Horizontal leaves room for long names; vertical suits ordered categories.",
            "$comment": "default: \"horizontal\""
          },
          "whiskers": {
            "enum": [
              "tukey",
              "minmax"
            ],
            "description": "`tukey`: furthest point within 1.5 × IQR, the rest drawn as outliers. `minmax`: the extremes.",
            "$comment": "default: \"tukey\""
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order boxes by median.",
            "$comment": "default: \"none\""
          }
        },
        "required": [
          "type",
          "value"
        ],
        "additionalProperties": false
      },
      "bubble-network": {
        "title": "Bubble network",
        "description": "Draws a small set of circles sized by value and joined by thin lines, with one circle highlighted and tagged. Use: Showing which of up to about 12 named things are connected, and how big each is: trade blocs, route maps between hubs, partnerships, shared ownership. Give `x` and `y` to place the circles by hand, for example roughly geographically. Avoid: Flows with magnitudes between stages (use sankey-chart); more than about 12 circles or a dense web of links (use heatmap as a matrix, or data-table); comparison of the sizes alone (use bar-chart or circle-pack).",
        "type": "object",
        "properties": {
          "type": {
            "const": "bubble-network"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one circle per row."
          },
          "value": {
            "type": "string",
            "description": "Value field: circle area."
          },
          "x": {
            "type": "string",
            "description": "Horizontal position field, 0 (left) to 100 (right). With `y`, places the circles by hand."
          },
          "y": {
            "type": "string",
            "description": "Vertical position field, 0 (top) to 100 (bottom)."
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Lines between circles, by name. `value` sets the line width and is printed on the line."
          },
          "tag": {
            "type": "string",
            "description": "Short tag attached to the highlighted circle, e.g. \"Joined 2024\"."
          },
          "linkFormat": {
            "$ref": "#/definitions/format",
            "description": "How to print link values."
          },
          "linkLabels": {
            "type": "boolean",
            "description": "Print link values on the lines. Default: on when any link has a value."
          },
          "layout": {
            "enum": [
              "ring",
              "hub"
            ],
            "description": "Without `x` and `y`: \"ring\" spaces the circles round an ellipse in data order, \"hub\" also moves the most-connected circle to the middle. Default: \"hub\" when one circle links to most of the others."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "bubble-scale": {
        "title": "Bubble scale",
        "description": "Places circles sized by one measure along a single value scale set by another, spread sideways so none overlap, with boxed scale marks instead of an axis. Use: A poster answer to \"where does each one sit on this scale, and how big is it\": 5 to about 40 named things with a rate or score (the scale) and a magnitude (the area), such as import dependency against share of demand. Avoid: Two measures that should be read against each other on two axes (use scatter-chart); one measure only (use beeswarm-chart or strip-plot); precise comparison of the sizes (use bar-chart); more than about 60 rows (use beeswarm-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "bubble-scale"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one circle per row."
          },
          "value": {
            "type": "string",
            "description": "Numeric field that positions each circle along the scale. Printed with `format`."
          },
          "size": {
            "type": "string",
            "description": "Numeric field for circle area. Printed inside or beside each circle with `sizeFormat`."
          },
          "series": {
            "type": "string",
            "description": "Field that colours circles by category. Default: circles are shaded along the scale with the sequential ramp."
          },
          "orientation": {
            "enum": [
              "vertical",
              "horizontal"
            ],
            "description": "Direction of the scale. Narrow containers always use vertical.",
            "$comment": "default: \"vertical\""
          },
          "domain": {
            "type": "array",
            "description": "Scale range. Default: the data extent rounded out to the tick step."
          },
          "ticks": {
            "type": "array",
            "items": {
              "type": "number"
            },
            "description": "Values to mark on the scale. Default: about five round values."
          },
          "scaleLabel": {
            "type": "string",
            "description": "Short name of the scale measure, printed at the head of the scale."
          },
          "sizeFormat": {
            "$ref": "#/definitions/format",
            "description": "How to print the size measure."
          },
          "guides": {
            "type": "boolean",
            "description": "Thin dotted guide line at each scale mark.",
            "$comment": "default: true"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "name",
          "value",
          "size"
        ],
        "additionalProperties": false
      },
      "bullet-chart": {
        "title": "Bullet chart",
        "description": "Compares one measure per row with its target, optionally against qualitative bands such as poor / fair / good. Use: Progress against a target or budget for one to about 10 measures, including measures in different units (`scale: \"independent\"`); a compact scorecard instead of a row of gauges. Avoid: No target or thresholds to compare with (use bar-chart); a single share of a whole (use progress-meter); change over time (use line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "bullet-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "category": {
            "type": "string",
            "description": "Field naming each row."
          },
          "value": {
            "type": "string",
            "description": "Field with the measured value. Values below zero are not supported."
          },
          "target": {
            "type": "string",
            "description": "Field with the target, drawn as a tick across the bar."
          },
          "bands": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Ascending upper bounds of qualitative bands, or the fields holding them per row. Omit unless the thresholds are real."
          },
          "bandNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Band names, lowest first, for the legend and tooltip."
          },
          "max": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "End of the scale: a number or a per-row field. Default: just past the largest value, target or band."
          },
          "scale": {
            "enum": [
              "shared",
              "independent"
            ],
            "description": "One axis for all rows, or each row on its own scale (different units).",
            "$comment": "default: \"shared\""
          },
          "formatField": {
            "type": "string",
            "description": "Field holding a format spec per row, for mixed units."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for the value and target fields."
          }
        },
        "required": [
          "type",
          "category",
          "value"
        ],
        "additionalProperties": false
      },
      "bump-chart": {
        "title": "Bump chart",
        "description": "Shows how the ranking of entities changes over time, with rank 1 at the top and each line named at its end. Use: League tables over 3 to about 15 periods for up to about 12 entities, when the order and the changes in rank are what matter and the underlying values differ too much (or too little) to share an axis. Avoid: When the size of the values matters (use line-chart); only two periods (use slope-chart); a single ranking (use bar-chart or lollipop-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "bump-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Time or ordered category field."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field to rank by, or several (one line each)."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into entities (long data)."
          },
          "ranked": {
            "type": "boolean",
            "description": "The values are already ranks (1 = best) and are plotted as given.",
            "$comment": "default: false"
          },
          "order": {
            "enum": [
              "desc",
              "asc"
            ],
            "description": "Which values rank first when ranks are computed: largest (`desc`) or smallest (`asc`).",
            "$comment": "default: \"desc\""
          },
          "startLabels": {
            "type": "boolean",
            "description": "Name lines at the start as well as the end. Default: on when the chart is wide enough."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "calendar-heatmap": {
        "title": "Calendar heatmap",
        "description": "Colours every day of one or more years by a value, laid out as a grid of weeks. Use: Daily data over months or years where weekly rhythm, seasonality, streaks and gaps matter: activity, sales, incidents, habits. Avoid: Reading the trend or exact values (use line-chart); fewer than about three months of days (use bar-chart); a non-daily grain such as hour by weekday (use heatmap).",
        "type": "object",
        "properties": {
          "type": {
            "const": "calendar-heatmap"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Common prop, but note the default: when omitted the height follows the cell size, which follows the width, so cells stay square."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "date": {
            "type": "string",
            "description": "Date field: ISO strings, Dates or epoch milliseconds. One cell per calendar day."
          },
          "value": {
            "type": "string",
            "description": "Numeric field that colours each day. Rows sharing a day are summed."
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Weeks left to right, or top to bottom. `auto` goes vertical under 480px.",
            "$comment": "default: \"auto\""
          },
          "weekStart": {
            "enum": [
              "monday",
              "sunday"
            ],
            "description": "First day of the week.",
            "$comment": "default: \"monday\""
          },
          "domain": {
            "type": "array",
            "description": "Fix the ends of the colour scale. Default: 0 to the maximum."
          }
        },
        "required": [
          "type",
          "date",
          "value"
        ],
        "additionalProperties": false
      },
      "callout": {
        "title": "Callout",
        "description": "A boxed statement of fact with a short bold lead and a sentence of explanation. The tone is marked by icon and tint. Use: Beside or under a chart, to state its main fact in words, with the number. Also for a caveat the reader must not miss (`negative`). Avoid: Long narration (use `prose`), a featured number (use `big-number` or `stat-tile`), or more than one callout per chart.",
        "type": "object",
        "properties": {
          "type": {
            "const": "callout"
          },
          "lead": {
            "type": "string",
            "description": "The fact in a few bold words. State it with its number."
          },
          "text": {
            "type": "string",
            "description": "One sentence of explanation or evidence."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `text`."
          },
          "tone": {
            "enum": [
              "neutral",
              "positive",
              "negative",
              "accent"
            ],
            "description": "Sets the icon shape and the tint together.",
            "$comment": "default: \"neutral\""
          },
          "label": {
            "type": "string",
            "description": "Small label above the lead, e.g. \"Summary\"."
          },
          "variant": {
            "enum": [
              "soft",
              "outline",
              "plain"
            ],
            "description": "Tinted box, bordered box, or no box.",
            "$comment": "default: \"soft\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "choropleth-map": {
        "title": "Choropleth map",
        "description": "Colours the regions of a map by a normalised value, from GeoJSON you supply. Use: A rate, share or per-capita figure that varies by place, where the geographic pattern (a north-south divide, a cluster) is what the reader needs to see. Use a diverging scale for change or for values either side of a meaningful midpoint. Avoid: Raw counts, which mostly map population (normalise first, or use bar-chart); ranking regions precisely (use bar-chart); a handful of regions with no spatial pattern (use bar-chart); regions so different in size that small ones vanish (use a tile-grid GeoJSON).",
        "type": "object",
        "properties": {
          "type": {
            "const": "choropleth-map"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "geo": {
            "anyOf": [
              {},
              {
                "type": "string"
              }
            ],
            "description": "The map: a GeoJSON object, or a URL to fetch one from. Registered with ECharts automatically."
          },
          "region": {
            "type": "string",
            "description": "Row field holding the region name that joins to the GeoJSON."
          },
          "value": {
            "type": "string",
            "description": "Row field holding the value. Use a rate or share, not a raw count."
          },
          "nameProperty": {
            "type": "string",
            "description": "GeoJSON feature property holding each region's name.",
            "$comment": "default: \"name\""
          },
          "scale": {
            "enum": [
              "sequential",
              "diverging"
            ],
            "description": "Sequential for magnitude; diverging for values either side of a midpoint.",
            "$comment": "default: \"sequential\""
          },
          "midpoint": {
            "type": "number",
            "description": "Centre of the diverging scale.",
            "$comment": "default: 0"
          },
          "domain": {
            "type": "array",
            "description": "Fix the colour scale instead of using the data's range."
          },
          "labels": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "const": "value"
              }
            ],
            "description": "Print region names on the map; `\"value\"` adds the value on a second line.",
            "$comment": "default: false"
          },
          "labelProperty": {
            "type": "string",
            "description": "GeoJSON feature property to print instead of the full name, e.g. a postal or ISO code."
          },
          "missingLabel": {
            "type": "string",
            "description": "Legend text for regions without a value.",
            "$comment": "default: \"No data\""
          },
          "aspectScale": {
            "type": "number",
            "description": "Horizontal stretch for longitude; 1 for tile maps and projected coordinates.",
            "$comment": "default: 0.75"
          }
        },
        "required": [
          "type",
          "geo",
          "region",
          "value"
        ],
        "additionalProperties": false
      },
      "circle-pack": {
        "title": "Circle pack",
        "description": "Shows parts as tightly packed circles sized by value, optionally clustered into groups, with the value and name printed inside each circle. Use: A poster view of 5 to about 60 parts of very different sizes where the reader should see the largest ones and their rough proportions at once: budgets by programme, emissions by source, users by product. One level of grouping is supported. Avoid: Values that need precise comparison (use bar-chart, where bars share a baseline); parts that must visibly add up to a whole (use treemap or waffle-chart); more than about 80 parts (use treemap); negative values (use diverging-bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "circle-pack"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Parent field. Circles sharing a group sit together and share a colour."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one circle per row."
          },
          "value": {
            "type": "string",
            "description": "Value field: circle area. Non-positive values are dropped."
          },
          "ring": {
            "enum": [
              "none",
              "group",
              "all"
            ],
            "description": "Thin dotted enclosing ring: one per group with its name and total, or one around the whole pack. Default \"group\" when `group` is set, else \"none\"."
          },
          "colorBy": {
            "enum": [
              "group",
              "value",
              "single"
            ],
            "description": "Colour by group, shade by value along the sequential ramp, or use the accent for every circle. Default \"group\" when `group` is set, else \"single\"."
          },
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            ],
            "description": "Icon drawn above the number in large circles: one for all, or a map from circle or group name to icon. Built-in name or `path://`."
          },
          "sizeLegend": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "type": "number"
                }
              }
            ],
            "description": "Size key of nested reference circles. `true` picks round values; an array sets them.",
            "$comment": "default: false"
          },
          "labels": {
            "type": "boolean",
            "description": "Print names and values inside circles, and beside the ones too small to hold them.",
            "$comment": "default: true"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for group keys."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "curve-rank": {
        "title": "Curve rank",
        "description": "Places each entity on two parallel scales, one per measure, and joins its two positions with a smooth S-curve labelled with the name and both values. Use: Two different measures of the same 4 to about 15 entities, when the point is how standing on one relates to standing on the other: price against sales, staff against output, cost against usage. Each side has its own scale, stated in its heading. Avoid: The same measure at two moments (use slope-chart); ranks across many periods (use bump-chart); more than about 15 entities or a statistical relationship (use scatter-chart); exact comparison on one measure (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "curve-rank"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Entity field: one curve per row."
          },
          "left": {
            "type": "string",
            "description": "Field for the left-hand measure."
          },
          "right": {
            "type": "string",
            "description": "Field for the right-hand measure."
          },
          "leftLabel": {
            "type": "string",
            "description": "Heading over the left rule: the measure and its unit. Defaults to the field name."
          },
          "rightLabel": {
            "type": "string",
            "description": "Heading over the right rule. Defaults to the field name."
          },
          "leftScale": {
            "enum": [
              "linear",
              "log"
            ],
            "description": "Scale of the left measure. A log scale is stated in the heading.",
            "$comment": "default: \"linear\""
          },
          "rightScale": {
            "enum": [
              "linear",
              "log"
            ],
            "description": "Scale of the right measure.",
            "$comment": "default: \"linear\""
          },
          "leftTop": {
            "enum": [
              "high",
              "low"
            ],
            "description": "Which end of the left measure sits at the top.",
            "$comment": "default: \"high\""
          },
          "rightTop": {
            "enum": [
              "high",
              "low"
            ],
            "description": "Which end of the right measure sits at the top.",
            "$comment": "default: \"high\""
          },
          "leftFormat": {
            "$ref": "#/definitions/format",
            "description": "How to print left values. Defaults to `format`."
          },
          "rightFormat": {
            "$ref": "#/definitions/format",
            "description": "How to print right values. Defaults to `format`."
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Entity names in the order that assigns colours. Pass the same list to glyph-table to match its row colours."
          },
          "colorBy": {
            "enum": [
              "series",
              "none"
            ],
            "description": "`series`: one colour per entity; past the size of the theme's palette the extra colours are derived from the theme's own (glyph-table derives the same ones). `none`: every curve in the accent. Default: series while the entities fit the palette (at most 8), none beyond."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for entity keys."
          }
        },
        "required": [
          "type",
          "name",
          "left",
          "right"
        ],
        "additionalProperties": false
      },
      "data-table": {
        "title": "Data table",
        "description": "A restrained editorial table from rows and a column config: aligned tabular numbers, an optional in-cell bar, row highlight and click-to-sort headers. Use: When readers need to look up exact values, or compare a handful of entities across several measures with different units. Sort it by the column the caption refers to and highlight the row it names. Avoid: Showing a trend or a single comparison (use `line-chart` or `bar-chart`); more than about 7 columns or 30 rows without `maxHeight`.",
        "type": "object",
        "properties": {
          "type": {
            "const": "data-table"
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One object per row."
          },
          "columns": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "Columns in order. Defaults to every key of the first row. Numeric columns are right-aligned."
          },
          "caption": {
            "type": "string",
            "description": "The table's title, as a real `<caption>`."
          },
          "subtitle": {
            "type": "string",
            "description": "Units and period, under the caption."
          },
          "source": {
            "type": "string",
            "description": "Shown under the table as \"Source: ...\"."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "number"
                    }
                  ]
                }
              }
            ],
            "description": "Rows to emphasise, matched on the first column (or `highlightKey`)."
          },
          "highlightKey": {
            "type": "string",
            "description": "Field `highlight` matches against."
          },
          "sort": {
            "type": "object",
            "description": "Initial sort."
          },
          "sortable": {
            "type": "boolean",
            "description": "Click or press Enter on a header to sort; a third press restores the original order.",
            "$comment": "default: true"
          },
          "maxHeight": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Height before the body scrolls under the sticky header."
          },
          "density": {
            "enum": [
              "comfortable",
              "compact"
            ],
            "description": "Row padding.",
            "$comment": "default: \"comfortable\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "rows"
        ],
        "additionalProperties": false
      },
      "delta": {
        "title": "Delta",
        "description": "An inline change indicator: direction arrow, signed value and an optional baseline label. Use: Next to a figure, in a sentence, a table cell or a tile, to say how much it changed and against what. Set `upIsGood: false` for measures where a fall is the good news (churn, emissions, wait times). Avoid: Standing alone as the main figure (use `big-number` or `stat-tile`, which include a delta). Do not omit the baseline label unless the surrounding text names it.",
        "type": "object",
        "properties": {
          "type": {
            "const": "delta"
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The change. Numbers format as signed percentages by default (0.12 is +12%)."
          },
          "label": {
            "type": "string",
            "description": "The baseline, e.g. \"vs last quarter\"."
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is good news; decides the colour only.",
            "$comment": "default: true"
          },
          "direction": {
            "enum": [
              "up",
              "down",
              "flat"
            ],
            "description": "Override the direction inferred from the sign."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format, e.g. `\"signed\"` for absolute changes or `\"{value} pts\"`.",
            "$comment": "default: signed percent"
          },
          "size": {
            "enum": [
              "sm",
              "md",
              "lg"
            ],
            "description": "12, 14 or 16px. Inherits the surrounding size when omitted."
          },
          "variant": {
            "enum": [
              "text",
              "pill"
            ],
            "description": "`pill` adds a tinted capsule behind the value.",
            "$comment": "default: \"text\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "value"
        ],
        "additionalProperties": false
      },
      "diverging-bar-chart": {
        "title": "Diverging bar chart",
        "description": "Draws bars either side of a centre line: positive against negative values, or stacked agree / disagree responses around a neutral midpoint. Use: Values that can be above or below zero (net change, balance, deviation from average); survey scales where the split between the two sides matters; two opposed groups back to back. Avoid: Values that are all positive (use bar-chart); parts that do not have a natural two-sided order (use a stacked bar-chart); change between two dates (use arrow-chart or dumbbell-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "diverging-bar-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Category field."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "One signed value field, or several fields ordered from most negative to most positive."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into ordered series (long data)."
          },
          "neutral": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "const": false
              }
            ],
            "description": "Series centred on the midline. Default: the middle one of an odd number of series."
          },
          "percent": {
            "type": "boolean",
            "description": "Normalise each row to 100% (stacked series).",
            "$comment": "default: false"
          },
          "colors": {
            "enum": [
              "polarity",
              "sentiment"
            ],
            "description": "Single series: diverging poles, or the positive / negative colours when one side is good and the other bad.",
            "$comment": "default: \"polarity\""
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Row order. Default: descending by value or by the positive side; data order for dates."
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Horizontal, except vertical for a single series over dates.",
            "$comment": "default: \"auto\""
          },
          "labels": {
            "type": "boolean",
            "description": "Values at bar ends (single) or inside segments (stacked). Default: on when there is room."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "donut-chart": {
        "title": "Donut chart",
        "description": "Shows how 2 to 5 parts make up one whole, with each slice labelled by name and share. Use: A simple composition with one dominant part, or one part the title is about, where the total itself is worth printing in the centre. Avoid: More than 5 categories or parts of similar size that must be ranked (use bar-chart); a single figure (use big-number); composition compared across groups or time (use bar-chart with stack \"percent\"); a compact card (use segmented-bar).",
        "type": "object",
        "properties": {
          "type": {
            "const": "donut-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one slice per distinct value."
          },
          "value": {
            "type": "string",
            "description": "Value field."
          },
          "maxSlices": {
            "type": "number",
            "description": "Most slices drawn, including \"Other\"; smaller categories are folded.",
            "$comment": "default: 5"
          },
          "centerLabel": {
            "type": "string",
            "description": "Small label in the hole, e.g. \"Total\". Turns the centre text on."
          },
          "centerValue": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "description": "Big text in the hole. Default: the formatted total when `centerLabel` is set."
          },
          "otherLabel": {
            "type": "string",
            "description": "Name of the folded slice.",
            "$comment": "default: \"Other\""
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for category keys."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "dumbbell-chart": {
        "title": "Dumbbell chart",
        "description": "Shows two values per category as dots joined by a line, so the length of the line shows the difference. Use: Before / after or group A / group B across up to about 20 categories, when the size of the difference is what the reader needs. Avoid: A single value per category (use lollipop-chart or bar-chart); when the direction of change matters more than the two levels (use arrow-chart); more than two points in time (use slope-chart or line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "dumbbell-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "category": {
            "type": "string",
            "description": "Category field: one row of the chart each."
          },
          "from": {
            "type": "string",
            "description": "Field with the first value, or (long data) the `series` value that marks it."
          },
          "to": {
            "type": "string",
            "description": "Field with the second value, or (long data) the `series` value that marks it."
          },
          "series": {
            "type": "string",
            "description": "Long data: the field whose values are `from` and `to`."
          },
          "value": {
            "type": "string",
            "description": "Long data: the measure field.",
            "$comment": "default: \"value\""
          },
          "kind": {
            "enum": [
              "change",
              "groups"
            ],
            "description": "`change` draws a tint then the accent (before / after); `groups` uses two hues (two peers).",
            "$comment": "default: \"change\""
          },
          "sort": {
            "enum": [
              "gap",
              "from",
              "to",
              "none"
            ],
            "description": "Row order.",
            "$comment": "default: \"gap\""
          },
          "order": {
            "enum": [
              "desc",
              "asc"
            ],
            "description": "Sort direction.",
            "$comment": "default: \"desc\""
          },
          "labels": {
            "type": "boolean",
            "description": "Value labels beside both dots. Default: on for up to 14 rows; otherwise a value axis is drawn."
          },
          "gapLabel": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Print the gap in a right-hand column; a string sets the column header.",
            "$comment": "default: false"
          },
          "zero": {
            "type": "boolean",
            "description": "Start the value axis at zero.",
            "$comment": "default: false"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for the `from` and `to` keys."
          }
        },
        "required": [
          "type",
          "category",
          "from",
          "to"
        ],
        "additionalProperties": false
      },
      "fan-flow": {
        "title": "Fan flow",
        "description": "One solid block that splits into curved ribbons, each as thick as its value, ending at an aligned column of names, values and shares. Use: One total divided among 4 to about 14 destinations (or collected from that many origins, with `direction: \"in\"`) when the picture of the split is the point: where a budget goes, what a day's water is used for, which sources feed one total. Avoid: Flows with more than one stage or several sources (use sankey-chart); precise comparison of the parts (use bar-chart); 2 to 4 parts (use segmented-bar or donut-chart); values that can be negative (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "fan-flow"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Destination field: one ribbon per distinct value."
          },
          "value": {
            "type": "string",
            "description": "Value field: ribbon thickness. Rows sharing a name are summed; non-positive values are dropped."
          },
          "trunk": {
            "type": "string",
            "description": "Label printed in the single block, with the total."
          },
          "direction": {
            "enum": [
              "out",
              "in"
            ],
            "description": "`out`: one block fans out to many labels on the right. `in`: many labels on the left flow into one block.",
            "$comment": "default: \"out\""
          },
          "maxItems": {
            "type": "number",
            "description": "Ribbons to keep; the rest are summed into the remainder ribbon.",
            "$comment": "default: 12"
          },
          "otherLabel": {
            "type": "string",
            "description": "Name of the remainder ribbon, drawn in the context colour. A row with this name is treated as the remainder.",
            "$comment": "default: \"Other\""
          },
          "tagged": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Destinations marked with a dotted outline around the name."
          },
          "tagLabel": {
            "type": "string",
            "description": "What the dotted outline means, printed in the key. Needed for `tagged` to be drawn."
          },
          "share": {
            "type": "boolean",
            "description": "Print each ribbon's share of the total. Dropped on narrow screens.",
            "$comment": "default: true"
          },
          "colorBy": {
            "enum": [
              "series",
              "none"
            ],
            "description": "`series`: one colour per destination; past the size of the theme's palette the extra colours are derived from the theme's own. `none`: every ribbon in the accent. Default: series while the destinations fit the palette (at most 8), none beyond."
          },
          "sort": {
            "enum": [
              "value",
              "none"
            ],
            "description": "Largest first, or the data order.",
            "$comment": "default: \"value\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "funnel-chart": {
        "title": "Funnel chart",
        "description": "Shows how many remain at each step of a sequence, with conversion and drop-off between steps. Use: A strict sequence where each stage is a subset of the one before: sign-up flows, hiring pipelines, sales stages, applications to admissions. 3 to 7 stages. Avoid: Stages that are not sequential subsets, or categories with no order (use bar-chart); flows that split to several destinations (use sankey-chart); conversion tracked over time (use line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "funnel-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "stage": {
            "type": "string",
            "description": "Stage field. Rows are read in data order; the first row is the top of the funnel."
          },
          "value": {
            "type": "string",
            "description": "Count field."
          },
          "dropoff": {
            "type": "boolean",
            "description": "State the drop-off between consecutive stages.",
            "$comment": "default: true"
          },
          "dropoffLabel": {
            "type": "string",
            "description": "Word for what is lost between stages.",
            "$comment": "default: \"dropped off\""
          }
        },
        "required": [
          "type",
          "stage",
          "value"
        ],
        "additionalProperties": false
      },
      "glyph-table": {
        "title": "Glyph table",
        "description": "A table with one row per entity in which every number is drawn as a small form chosen per column (counted dots, squares or icons, a ring, a sized circle, a bar) with the value printed beside it. Use: Comparing 3 to about 12 entities across 2 to 5 measures with different units, when the table should read as a graphic: profiles of products, cities, teams or species. Pair it with curve-rank by passing both the same `order`. Avoid: Looking up many exact values, sorting, or more than about 12 rows (use data-table); one measure across entities (use bar-chart or pictogram-chart); a trend over time (use line-chart or small-multiples).",
        "type": "object",
        "properties": {
          "type": {
            "const": "glyph-table"
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One object per entity."
          },
          "name": {
            "type": "string",
            "description": "Field holding the entity name. Defaults to the first key of the first row."
          },
          "nameLabel": {
            "type": "string",
            "description": "Heading of the name column."
          },
          "columns": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Glyph columns in order. `dots`, `blocks` and `icons` draw one mark per `unit` (default 1, raised to a round number when the largest value would not fit, and stated in the heading). `ring` fills to `max` (default 100, or 1 for fractions). `circle` is sized by area and `bar` by length against `max` (default: the column's largest value). `text` prints the value alone."
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Entity names in display order; also assigns colours. Pass the same list to curve-rank to match its curve colours."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Entities drawn in colour; every other row turns grey."
          },
          "colorBy": {
            "enum": [
              "series",
              "none"
            ],
            "description": "`series`: one colour per entity; past the size of the theme's palette the extra colours are derived from the theme's own (curve-rank derives the same ones). `none`: every row in the accent. Default: series while the rows fit the palette (at most 8), none beyond."
          },
          "caption": {
            "type": "string",
            "description": "The table's title, as a real `<caption>`."
          },
          "subtitle": {
            "type": "string",
            "description": "Measures, units and period, under the caption."
          },
          "source": {
            "type": "string",
            "description": "Shown under the table as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats, shown under the table."
          },
          "select": {
            "type": "boolean",
            "description": "Let readers click a row (or press Enter on it) to select it; the other rows fade."
          },
          "selected": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Controlled selection: the entity names currently selected. When given, the table shows exactly this list and a click only calls `onSelect`. Omit it and the table keeps its own selection."
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "rows",
          "columns"
        ],
        "additionalProperties": false
      },
      "headline": {
        "title": "Headline",
        "description": "The opening block of a piece or section: kicker, title, one-sentence deck and a byline/date line. Use: At the top of a data story (`page`), at the start of each chapter (`section`), or as the heading of a tile (`card`). Write the title as one plain fact with its number. Write the deck as a second plain sentence. Avoid: Titling a single chart: charts carry their own `title` and `subtitle`. For numbered chapters use `step-marker`.",
        "type": "object",
        "properties": {
          "type": {
            "const": "headline"
          },
          "title": {
            "type": "string",
            "description": "One fact with its number, as a plain sentence. Wraps balanced."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: section, series or topic. Sentence case."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line, shown as written, e.g. \"By Ana Ruiz\"."
          },
          "date": {
            "type": "string",
            "description": "ISO dates are formatted for the locale and wrapped in `<time>`; other strings are shown as written."
          },
          "size": {
            "enum": [
              "page",
              "section",
              "card"
            ],
            "description": "Type scale. Titles step down automatically in narrow containers.",
            "$comment": "default: \"section\""
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level. Defaults to 1 (page), 2 (section), 3 (card)."
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Text alignment.",
            "$comment": "default: \"left\""
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "Extra content under the byline."
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "heatmap": {
        "title": "Heatmap",
        "description": "Colours a category-by-category (or time-by-category) grid by a numeric value, using a sequential or diverging scale. Use: Finding patterns across two dimensions at once: hour by weekday, cohort by month, product by region. Good when there are too many series for lines or bars and the overall pattern matters more than exact values. Avoid: Precise comparison of a few values (use bar-chart); a single series over time (use line-chart); a daily value across a year (use calendar-heatmap).",
        "type": "object",
        "properties": {
          "type": {
            "const": "heatmap"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Column field: a category or a date."
          },
          "y": {
            "type": "string",
            "description": "Row field."
          },
          "value": {
            "type": "string",
            "description": "Numeric field that colours each cell. One data row per cell."
          },
          "diverging": {
            "type": "boolean",
            "description": "Diverging palette centred on `midpoint`, for values with a meaningful middle.",
            "$comment": "default: false"
          },
          "midpoint": {
            "type": "number",
            "description": "Centre of the diverging scale.",
            "$comment": "default: 0"
          },
          "labels": {
            "type": "boolean",
            "description": "Print the value in each cell. Default: on when cells are large enough."
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order rows by their total.",
            "$comment": "default: \"none\""
          },
          "domain": {
            "type": "array",
            "description": "Fix the ends of the colour scale."
          }
        },
        "required": [
          "type",
          "x",
          "y",
          "value"
        ],
        "additionalProperties": false
      },
      "histogram": {
        "title": "Histogram",
        "description": "Bins a numeric field and shows how many rows fall in each bin, as touching bars on a continuous axis. Use: Showing the shape of a distribution for one numeric variable with roughly 50 rows or more: its centre, spread, skew, gaps and multiple peaks. Avoid: Comparing distributions across several groups (use box-plot or beeswarm-chart); under about 50 rows, where every observation can be shown (use strip-plot or beeswarm-chart); counts by category (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "histogram"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "value": {
            "type": "string",
            "description": "Numeric field to bin."
          },
          "bins": {
            "type": "number",
            "description": "Approximate number of bins; the width is rounded to a tidy step. Default: from the row count."
          },
          "step": {
            "type": "number",
            "description": "Exact bin width in value units. Overrides `bins`."
          },
          "median": {
            "type": "boolean",
            "description": "Vertical marker at the median.",
            "$comment": "default: false"
          },
          "mean": {
            "type": "boolean",
            "description": "Vertical marker at the mean.",
            "$comment": "default: false"
          },
          "normalize": {
            "type": "boolean",
            "description": "Share of rows per bin instead of a count.",
            "$comment": "default: false"
          },
          "countLabel": {
            "type": "string",
            "description": "Title for the count axis, e.g. \"Runners\"."
          }
        },
        "required": [
          "type",
          "value"
        ],
        "additionalProperties": false
      },
      "icon-array-grid": {
        "title": "Icon array grid",
        "description": "Compares many counts as a grid of labelled tiles, each holding an array of N icons with its name and number. Use: Counts of up to about 150 in 4 to 24 categories, especially rates per 100 or per 1,000: cars per 100 households in 12 districts. Set `total` so every tile shows the same full array with the uncounted icons as ghosts. Avoid: Counts in the thousands (use unit-blocks); two to six categories where one row of icons each is enough (use pictogram-chart); values that need precise comparison or ranking (use block-bar or bar-chart); one share of one whole (use waffle-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "icon-array-grid"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one tile per row."
          },
          "value": {
            "type": "string",
            "description": "Value field: the count each tile shows."
          },
          "unit": {
            "type": "number",
            "description": "Units per icon.",
            "$comment": "default: 1"
          },
          "unitLabel": {
            "type": "string",
            "description": "What one icon stands for, for the key line, e.g. \"1 car\"."
          },
          "total": {
            "type": "number",
            "description": "Draw every tile out of this many units, with uncounted icons as ghosts: 100 for a rate per 100."
          },
          "icon": {
            "anyOf": [
              {},
              {
                "const": "path://..."
              }
            ],
            "description": "Built-in icon name or a custom single SVG path.",
            "$comment": "default: \"circle\""
          },
          "perRow": {
            "type": "number",
            "description": "Icons per line inside a tile.",
            "$comment": "default: 10"
          },
          "columns": {
            "type": "number",
            "description": "Most tiles per line. Default: as many as fit at a readable size. Narrow containers use fewer."
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order of the tiles.",
            "$comment": "default: \"none\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "icon-stat": {
        "title": "Icon stat",
        "description": "A \"1 in 4\"-style statement: a row or grid of simple glyphs with some filled, and the sentence they illustrate. Use: A single proportion that is easier to read as people or units than as a percentage: 1 in 4, 3 in 10, 37 of 100. Round to a small denominator first. Avoid: Comparing several proportions (use `bar-chart`), precise percentages (use `big-number`), or fractions that need more than 100 units.",
        "type": "object",
        "properties": {
          "type": {
            "const": "icon-stat"
          },
          "count": {
            "type": "number",
            "description": "How many glyphs are filled."
          },
          "total": {
            "type": "number",
            "description": "How many glyphs are drawn. Capped at 100.",
            "$comment": "default: 10"
          },
          "text": {
            "type": "string",
            "description": "The sentence completing the figure."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `text`."
          },
          "value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "const": false
              }
            ],
            "description": "The figure as words. Defaults to \"{count} in {total}\"; `false` hides it."
          },
          "icon": {
            "anyOf": [
              {
                "const": "circle"
              },
              {
                "const": "person"
              },
              {
                "const": "square"
              },
              {}
            ],
            "description": "Glyph per unit. Filled units are solid, the rest outlined. Any other icon name from `core/icons.ts` also works; its unfilled units are faded instead of outlined.",
            "$comment": "default: \"circle\""
          },
          "columns": {
            "type": "number",
            "description": "Glyphs per row. Defaults to `total`, at most 10."
          },
          "size": {
            "type": "number",
            "description": "Glyph height in px; shrinks to fit narrow containers."
          },
          "tone": {
            "enum": [
              "accent",
              "positive",
              "negative",
              "neutral"
            ],
            "description": "Fill colour by meaning.",
            "$comment": "default: \"accent\""
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Alignment.",
            "$comment": "default: \"left\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "count"
        ],
        "additionalProperties": false
      },
      "legend-key": {
        "title": "Legend key",
        "description": "A standalone colour key: categorical swatches, or a sequential/diverging ramp with end labels. Use: When several charts (small multiples, a map and a bar chart, a dashboard row) share one colour encoding, show the key once above them and turn their own legends off. Avoid: A single chart: its built-in legend or, better, direct labels already do this. Do not list more than eight categories.",
        "type": "object",
        "properties": {
          "type": {
            "const": "legend-key"
          },
          "scale": {
            "enum": [
              "categorical",
              "sequential",
              "diverging"
            ],
            "description": "Defaults to `categorical` when `items` is given, otherwise `sequential`."
          },
          "items": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "Categorical entries. Colours come from the theme's categorical order by position (or `index`) unless given."
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ramp end labels: `[low, high]` or `[low, middle, high]`."
          },
          "colors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ramp colours, low to high. Defaults to the theme's sequential or diverging ramp."
          },
          "stepped": {
            "type": "boolean",
            "description": "Discrete steps instead of a continuous gradient, for binned scales.",
            "$comment": "default: false"
          },
          "title": {
            "type": "string",
            "description": "What the key encodes."
          },
          "shape": {
            "enum": [
              "square",
              "line",
              "dot"
            ],
            "description": "Default swatch shape: match the marks.",
            "$comment": "default: \"square\""
          },
          "orientation": {
            "enum": [
              "horizontal",
              "vertical"
            ],
            "description": "Categorical layout.",
            "$comment": "default: \"horizontal\""
          },
          "width": {
            "type": "number",
            "description": "Ramp width in px, capped at the container.",
            "$comment": "default: 240"
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Alignment within the container.",
            "$comment": "default: \"left\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "line-chart": {
        "title": "Line chart",
        "description": "Shows how one or more values change over time or another ordered dimension. Use: Trends over time with roughly 5 or more points; comparing the trajectories of a few series; one highlighted series against many context series. Avoid: Unordered categories (use bar-chart); only two time points (use slope-chart); more than about 6 equally important lines (use small-multiples).",
        "type": "object",
        "properties": {
          "type": {
            "const": "line-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Time or ordered category field. ISO dates are placed on a true time axis."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or several (one line each)."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into lines (long data)."
          },
          "curve": {
            "enum": [
              "linear",
              "smooth",
              "step"
            ],
            "description": "Line shape.",
            "$comment": "default: \"linear\""
          },
          "area": {
            "type": "boolean",
            "description": "Light fill under the line; forces a zero baseline.",
            "$comment": "default: false"
          },
          "endLabels": {
            "type": "boolean",
            "description": "Name each line at its end. Default: on for up to 6 lines."
          },
          "points": {
            "type": "boolean",
            "description": "Marker on every point. Default: on for 12 points or fewer."
          },
          "zero": {
            "type": "boolean",
            "description": "Start the value axis at zero.",
            "$comment": "default: false"
          },
          "log": {
            "type": "boolean",
            "description": "Logarithmic value axis.",
            "$comment": "default: false"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          },
          "contextLabels": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "With `highlight`: name the grey context lines. `true` adds a muted end label to each when they all fit; a string such as `\"Other cities\"` adds one muted legend entry instead. On narrow charts the legend already lists every line.",
            "$comment": "default: false"
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "lollipop-chart": {
        "title": "Lollipop chart",
        "description": "Ranks categories with a dot on a thin stem from zero, or as a stemless dot plot on a free scale. Use: Rankings of 8 to 30 categories where bars would be too heavy; dot plot mode when the values sit far from zero and the differences between them matter, or to compare a few series per row. Avoid: Fewer than about 6 categories or part-to-whole stacks (use bar-chart); exactly two values per row where the difference between them matters (use dumbbell-chart); change over time (use line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "lollipop-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Category field."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field. Several fields draw several dots per row (dot plot)."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into series (long data). Forces the dot plot."
          },
          "stem": {
            "type": "boolean",
            "description": "Stem from zero. `false` draws a dot plot whose scale need not start at zero.",
            "$comment": "default: true"
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Horizontal for rankings, vertical for dates.",
            "$comment": "default: \"auto\""
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Row order. Default: descending for rankings, data order for dates."
          },
          "labels": {
            "type": "boolean",
            "description": "Value beside each dot. Default: on for one series of up to 16 rows."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "nested-shares": {
        "title": "Nested shares",
        "description": "Shows several shares of the same whole, such as one share at five dates, as outlines nested from one corner of a square, each enclosing an area equal to its share. Use: How much of one whole something was at 2 to 8 dates or in 2 to 8 categories, when the growth of a share is the point: bicycles made 4% of trips in 2005 and 27% in 2025. Avoid: Shares that are parts of each other and should add up (use waffle-chart or treemap); more than 8 items or precise reading of a trend (use line-chart); shares within a point or two of each other, where outlines coincide (use block-bar).",
        "type": "object",
        "properties": {
          "type": {
            "const": "nested-shares"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Field naming each share: a period (\"2025\") or a category."
          },
          "value": {
            "type": "string",
            "description": "Value field: each row's share of the whole."
          },
          "total": {
            "type": "number",
            "description": "The whole. Default: 1 when every value is at most 1, otherwise 100."
          },
          "wholeLabel": {
            "type": "string",
            "description": "What the outer square stands for, printed under it, e.g. \"All trips\"."
          },
          "corner": {
            "enum": [
              "bottom-left",
              "top-left"
            ],
            "description": "The corner every outline grows from.",
            "$comment": "default: \"bottom-left\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "orbit-chart": {
        "title": "Orbit chart",
        "description": "Places items as dots on concentric rings round a centre, one ring per category, level or period, with a key that explains rings, angle and dot area. Use: A designed alternative to a table for 6 to about 40 named things grouped by distance, level or era from one centre: suppliers by tier, moons by planet-distance band, releases by decade, stakeholders by closeness. One item can be highlighted. Avoid: A numeric distance that must be read exactly (use strip-plot or scatter-chart); comparison of the dot values (use bar-chart); more than about 6 rings or 40 items (use data-table); hierarchy with sizes that add up (use treemap or circle-pack).",
        "type": "object",
        "properties": {
          "type": {
            "const": "orbit-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one dot per row."
          },
          "ring": {
            "type": "string",
            "description": "Field naming the ring each dot sits on: a category, level or period."
          },
          "rings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ring order from the centre outward. Default: first appearance in the data."
          },
          "value": {
            "type": "string",
            "description": "Value field: dot area. Without it every dot is the same size."
          },
          "angle": {
            "type": "string",
            "description": "Numeric field that sets the angle round the ring. Without it dots are spaced evenly."
          },
          "angleDomain": {
            "type": "array",
            "description": "Values of `angle` that map to a full turn, clockwise from 12 o'clock.",
            "$comment": "default: [0, 360]"
          },
          "ringLabel": {
            "type": "string",
            "description": "What the rings mean, for the key. Default: the `ring` field name."
          },
          "angleLabel": {
            "type": "string",
            "description": "What the angle means, for the key, e.g. \"Clockwise from the top: month of launch\"."
          },
          "sizeLabel": {
            "type": "string",
            "description": "What dot area means, for the key. Default: the `value` field name."
          },
          "icon": {
            "type": "string",
            "description": "Icon in the centre disc: a built-in name or `path://`."
          },
          "centerLabel": {
            "type": "string",
            "description": "Short text in the centre disc, used when there is no `icon`."
          },
          "colorBy": {
            "enum": [
              "ring",
              "single"
            ],
            "description": "A colour per ring, or the accent for every dot.",
            "$comment": "default: \"ring\""
          },
          "showKey": {
            "type": "boolean",
            "description": "Show the key that explains rings, angle and dot area.",
            "$comment": "default: true"
          }
        },
        "required": [
          "type",
          "name",
          "ring"
        ],
        "additionalProperties": false
      },
      "pictogram-chart": {
        "title": "Pictogram chart",
        "description": "Compares quantities with rows of repeated icons, each icon standing for a fixed number of units. Use: A few categories (2 to 6) of countable things, people, homes, vehicles, where making the quantity concrete matters more than reading precise values. Avoid: More than about 8 categories or values that need precise comparison (use bar-chart); a share of one whole (use waffle-chart); values that would need more than about 60 icons in a row (raise `unit`, or use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "pictogram-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one row of icons per category."
          },
          "value": {
            "type": "string",
            "description": "Value field."
          },
          "unit": {
            "type": "number",
            "description": "Units per icon. Default: a round number giving the largest row about ten icons."
          },
          "unitLabel": {
            "type": "string",
            "description": "What one icon stands for, for the key line, e.g. \"1 million people\"."
          },
          "icon": {
            "anyOf": [
              {},
              {
                "const": "path://..."
              }
            ],
            "description": "Built-in icon name from `core/icons.ts` (\"person\", \"house\", \"car\", \"tree\", \"coin\", \"drop\", \"bolt\", \"wind-turbine\", \"wheat\" and about 60 more) or a custom single SVG path.",
            "$comment": "default: \"person\""
          },
          "icons": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Icon per category key; falls back to `icon`."
          },
          "perRow": {
            "type": "number",
            "description": "Wrap rows after this many icons. Default: as many as fit."
          },
          "labels": {
            "type": "boolean",
            "description": "Print the value after each row.",
            "$comment": "default: true"
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Row order.",
            "$comment": "default: \"none\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "pill-rank": {
        "title": "Pill rank",
        "description": "Shows a ranked list as horizontally centred rounded bars, with each name in capitals on its pill, the value at the left edge and the rank at the right. Use: A poster ranking of 4 to about 20 named things where the order and the overall silhouette matter more than fine differences: top cities, largest employers, league tables, with one row highlighted and optional reference rows set apart below. Avoid: Precise comparison of values (use bar-chart, where bars share a baseline); negative values (use diverging-bar-chart); change in rank over time (use bump-chart); more than about 25 rows (use data-table).",
        "type": "object",
        "properties": {
          "type": {
            "const": "pill-rank"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one row per data row."
          },
          "value": {
            "type": "string",
            "description": "Value field: pill width. Non-positive values are dropped."
          },
          "sort": {
            "type": "boolean",
            "description": "Sort rows largest first. Set false to keep the data order.",
            "$comment": "default: true"
          },
          "compare": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Names of rows that are not ranked: drawn below a dotted rule, without a rank number."
          },
          "compareLabel": {
            "type": "string",
            "description": "Short heading over the comparison rows, e.g. \"For comparison\"."
          },
          "max": {
            "type": "number",
            "description": "Value that fills the full pill width. Default: the largest value."
          },
          "ranks": {
            "type": "boolean",
            "description": "Show the rank number at the right edge.",
            "$comment": "default: true"
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "progress-meter": {
        "title": "Progress meter",
        "description": "A labelled horizontal meter of one value against a maximum or target, with the target marked and the value printed. Use: Progress toward a goal, a quota or a capacity: funds raised, budget spent, share of a target reached. Stack several with `size: \"sm\"` to compare progress across a few items. Avoid: Comparing more than a handful of items (use `bar-chart`), anything without a meaningful end point (use `big-number`), or a gauge dial.",
        "type": "object",
        "properties": {
          "type": {
            "const": "progress-meter"
          },
          "value": {
            "type": "number",
            "description": "The current value."
          },
          "label": {
            "type": "string",
            "description": "What is measured, sentence case."
          },
          "max": {
            "type": "number",
            "description": "End of the track. Defaults to the target, or 1 with no target."
          },
          "min": {
            "type": "number",
            "description": "Start of the track.",
            "$comment": "default: 0"
          },
          "target": {
            "type": "number",
            "description": "A goal or threshold, drawn as a tick and labelled."
          },
          "targetLabel": {
            "type": "string",
            "description": "Name for the target tick.",
            "$comment": "default: \"Target\""
          },
          "showMax": {
            "type": "boolean",
            "description": "Print \"of {max}\" after the value. Default: only when `max` is given."
          },
          "context": {
            "type": "string",
            "description": "A line under the meter that gives the number meaning."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format. Defaults to `\"percent\"` when the track ends at 1 or less, otherwise `\"auto\"`."
          },
          "tone": {
            "enum": [
              "accent",
              "positive",
              "negative",
              "neutral"
            ],
            "description": "Fill colour by meaning.",
            "$comment": "default: \"accent\""
          },
          "size": {
            "enum": [
              "sm",
              "md"
            ],
            "description": "`sm` for dense stacks.",
            "$comment": "default: \"md\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "value",
          "label"
        ],
        "additionalProperties": false
      },
      "proportional-area": {
        "title": "Proportional area",
        "description": "Compares two to eight values as squares or circles whose areas are proportional to the values, each printed with its name and number. Use: A few quantities that differ a lot (2 times to 100 times), where the reader should feel the difference in size: lake areas, budgets, market sizes. Nest them to show one quantity inside another. Avoid: Values within about 30% of each other, where areas look the same (use block-bar or bar-chart); more than 8 values (use treemap or bar-chart); parts of one whole (use treemap or waffle-chart); negative values.",
        "type": "object",
        "properties": {
          "type": {
            "const": "proportional-area"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one shape per row."
          },
          "value": {
            "type": "string",
            "description": "Value field. Each shape's area is proportional to it."
          },
          "shape": {
            "enum": [
              "square",
              "circle"
            ],
            "description": "Squares or circles.",
            "$comment": "default: \"square\""
          },
          "layout": {
            "enum": [
              "row",
              "nested",
              "packed"
            ],
            "description": "`row`: side by side on a common baseline. `nested`: inside one another from a shared corner (squares) or lowest point (circles). `packed`: clustered together.",
            "$comment": "default: \"row\""
          },
          "ratio": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Print how many times the largest value is the smallest. `true` for \"{largest} is {ratio} times {smallest}\", or a template with those placeholders."
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order of the shapes in the row layout. Nested and packed always draw largest first.",
            "$comment": "default: \"none\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "prose": {
        "title": "Prose",
        "description": "A readable block of narration at a 45-75 character measure, for the text between charts. Use: To say what a chart showed and introduce the next one. Use two or three short paragraphs at a time. Avoid: A single statement of fact (use `callout`), a quotation (use `pull-quote`), or sourcing and method notes (use `source-note`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "prose"
          },
          "text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Narration. Blank lines separate paragraphs. Supports `**bold**`, `*italic*` and `[link](url)`."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `text`."
          },
          "size": {
            "enum": [
              "sm",
              "md",
              "lg"
            ],
            "description": "Body size: 14, 16 or 18px.",
            "$comment": "default: \"md\""
          },
          "measure": {
            "type": "number",
            "description": "Line length in characters, clamped to 45-75.",
            "$comment": "default: 65"
          },
          "lead": {
            "type": "boolean",
            "description": "Set the first paragraph a step larger.",
            "$comment": "default: false"
          },
          "tone": {
            "enum": [
              "default",
              "muted"
            ],
            "description": "`muted` for secondary narration.",
            "$comment": "default: \"default\""
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Centres the block (text stays left-aligned).",
            "$comment": "default: \"left\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "pull-quote": {
        "title": "Pull quote",
        "description": "A large quotation with its attribution. Use: To quote a person on a finding the charts have already shown, or to break up a long run of charts. One per section at most. Avoid: Restating a number (use `big-number`) or the main fact of a chart (use `callout`). Never quote without attribution.",
        "type": "object",
        "properties": {
          "type": {
            "const": "pull-quote"
          },
          "quote": {
            "type": "string",
            "description": "The words quoted, without quotation marks."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `quote`."
          },
          "attribution": {
            "type": "string",
            "description": "Who said it."
          },
          "role": {
            "type": "string",
            "description": "Their role, or where it was said."
          },
          "cite": {
            "type": "string",
            "description": "Source URL: set as the blockquote `cite` and linked from the attribution."
          },
          "size": {
            "enum": [
              "md",
              "lg"
            ],
            "description": "`lg` anchors a section; `md` sits inside a column.",
            "$comment": "default: \"lg\""
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Left-aligned quotes carry a side rule; centred ones do not.",
            "$comment": "default: \"left\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "radial-bar-chart": {
        "title": "Radial bar chart",
        "description": "Draws bars around a circle for data that repeats in a cycle, such as hours of the day or months of the year. Use: Only when the dimension is cyclical and the wrap-around matters: activity by hour of day, seasonality by month, wind by compass direction. The first category is placed at 12 o'clock. Avoid: Any dimension that does not wrap around: categories, rankings, years (use bar-chart); precise comparison of values, since bars further out look bigger (use bar-chart or line-chart); more than about 3 stacked series.",
        "type": "object",
        "properties": {
          "type": {
            "const": "radial-bar-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "The cyclical category field, in cycle order."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or several to stack."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into stacked series (long data)."
          },
          "labelEvery": {
            "type": "number",
            "description": "Label every nth category around the rim. Default: chosen to avoid crowding."
          },
          "labels": {
            "type": "boolean",
            "description": "Print the value on the tallest bar. Default: on for a single series."
          },
          "centerFirst": {
            "type": "boolean",
            "description": "Centre the first category on 12 o'clock (compass directions) instead of starting its band there (hours).",
            "$comment": "default: false"
          },
          "centerLabel": {
            "type": "string",
            "description": "Text in the centre of the ring, e.g. \"24 hours\"."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "radial-spokes": {
        "title": "Radial spokes",
        "description": "Draws one spoke per row radiating from a centre disc, each as long as its value, with the name and value set on an outer ring. Use: A poster of 4 to 12 effects, causes or attributes of one subject, which sits in the centre as an icon or a short label: what a household's energy goes on, the side effects of one drug, the scores of one product. Avoid: Precise comparison or a ranking (use bar-chart or pill-rank); a dimension that is a cycle, such as hours or months (use radial-bar-chart); more than 12 rows (use bar-chart); several subjects compared on the same attributes (use small-multiples or heatmap).",
        "type": "object",
        "properties": {
          "type": {
            "const": "radial-spokes"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Name field: one spoke per row, in data order, clockwise."
          },
          "value": {
            "type": "string",
            "description": "Value field: spoke length from the centre disc."
          },
          "shape": {
            "enum": [
              "bar",
              "line"
            ],
            "description": "A thick tapered bar with a round head, or a thin line ending in a dot.",
            "$comment": "default: \"bar\""
          },
          "icon": {
            "type": "string",
            "description": "Icon in the centre disc: a built-in name or `path://`."
          },
          "centerLabel": {
            "type": "string",
            "description": "Short text in the centre disc, used when there is no `icon`."
          },
          "ring": {
            "type": "boolean",
            "description": "Dotted outer ring at the scale maximum, where the labels sit.",
            "$comment": "default: true"
          },
          "max": {
            "type": "number",
            "description": "Value that reaches the outer ring. Default: the largest value."
          },
          "startAngle": {
            "type": "number",
            "description": "Angle of the first spoke in degrees clockwise from 12 o'clock.",
            "$comment": "default: 0"
          },
          "sweep": {
            "type": "number",
            "description": "Arc the spokes are spread over, in degrees. 180 makes a fan.",
            "$comment": "default: 360"
          },
          "colorBy": {
            "enum": [
              "single",
              "value"
            ],
            "description": "The accent for every spoke, or a shade by value along the sequential ramp.",
            "$comment": "default: \"single\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "ribbon-chart": {
        "title": "Ribbon chart",
        "description": "One filled band per entity across periods: its thickness is its value in each period and its vertical position is its rank, so bands cross as the order changes. Use: 4 to 8 entities over 4 to 10 periods when both the size of each and the changing order matter, and the graphic should read as one flowing form: market shares, harvests, medal tables, budget lines. Avoid: Totals that matter more than order, or a smooth centred stream of many periods (use area-chart, which has stacked and stream modes); rank alone (use bump-chart); more than 8 entities or 10 periods (use line-chart or small-multiples); values that can be negative (use line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "ribbon-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Period field: one column of the ribbon per distinct value, in data order."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field (long data), or one column per entity (wide data). Band thickness; negative values are drawn as zero."
          },
          "series": {
            "type": "string",
            "description": "Entity field, for long data."
          },
          "values": {
            "type": "boolean",
            "description": "Print each value inside its band at every period where it fits.",
            "$comment": "default: true"
          },
          "labels": {
            "enum": [
              "both",
              "end"
            ],
            "description": "Entity names at both ends, or only at the end. Default: both, end only on narrow screens."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for entity keys."
          },
          "colorBy": {
            "enum": [
              "auto",
              "series",
              "none"
            ],
            "description": "`auto`: the largest entities take the theme's colours and any past the palette size (at most 8) are grey. `series`: every band gets its own colour, the extra ones derived from the theme's own. `none`: every band in the accent.",
            "$comment": "default: \"auto\""
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "sankey-chart": {
        "title": "Sankey chart",
        "description": "Shows how a quantity flows from sources through stages to destinations, with link width proportional to the flow. Use: Where things come from and where they go: energy from fuel to end use, budget from revenue to spending, users from channel to outcome. Works best with 2 to 4 stages and up to about 20 nodes. Avoid: A single sequence of steps with drop-off (use funnel-chart); comparing a few totals (use bar-chart); flows that loop back (cycles cannot be drawn and are dropped); more than about 40 links.",
        "type": "object",
        "properties": {
          "type": {
            "const": "sankey-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "from": {
            "type": "string",
            "description": "Field naming where each flow starts. Not called `source` because that is the figure's source line.",
            "$comment": "default: \"source\""
          },
          "to": {
            "type": "string",
            "description": "Field naming where each flow ends.",
            "$comment": "default: \"target\""
          },
          "value": {
            "type": "string",
            "description": "Flow size field. Non-positive flows are dropped.",
            "$comment": "default: \"value\""
          },
          "orientation": {
            "enum": [
              "auto",
              "horizontal",
              "vertical"
            ],
            "description": "Left to right, or top to bottom for narrow columns with short names.",
            "$comment": "default: \"auto\""
          },
          "labels": {
            "type": "boolean",
            "description": "Print each node's total after its name.",
            "$comment": "default: true"
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for node keys."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "scale-ladder": {
        "title": "Scale ladder",
        "description": "A tall vertical band graded along one scale (linear or log, running up or down) with each item placed at its true position and labelled with an icon, its name and its value on alternating sides. Use: Answering how deep, how high, how hot, how old or how far each of 4 to about 20 things is on one shared scale, when the reader needs the positions themselves: depths, altitudes, temperatures, ages, distances. Use `zones` to name ranges along the scale. Avoid: Comparing sizes rather than positions (use bar-chart or lollipop-chart); events with start and end dates (use timeline-chart); a distribution of many unnamed values (use strip-plot or histogram).",
        "type": "object",
        "properties": {
          "type": {
            "const": "scale-ladder"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Field holding each item's name."
          },
          "value": {
            "type": "string",
            "description": "Field holding each item's position on the scale."
          },
          "icon": {
            "description": "One icon for every item: a built-in name or a `path://` string. Items without an icon get a dot."
          },
          "iconField": {
            "type": "string",
            "description": "Field holding a per-item icon name or `path://` string. Overrides `icon`."
          },
          "scale": {
            "enum": [
              "linear",
              "log"
            ],
            "description": "Log spaces the scale by powers of ten; the heading over the band says so.",
            "$comment": "default: \"linear\""
          },
          "direction": {
            "enum": [
              "up",
              "down"
            ],
            "description": "`up`: larger values higher (height, temperature). `down`: larger values lower (depth, age).",
            "$comment": "default: \"up\""
          },
          "min": {
            "type": "number",
            "description": "Start of the scale. Default: a round number at or below the smallest value."
          },
          "max": {
            "type": "number",
            "description": "End of the scale. Default: a round number at or above the largest value."
          },
          "ticks": {
            "type": "array",
            "items": {
              "type": "number"
            },
            "description": "Values that get a boxed label on the band. Default: round steps, or powers of ten on a log scale."
          },
          "zones": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Named ranges along the scale, shaded across the graphic and named along its outer edge."
          },
          "scaleLabel": {
            "type": "string",
            "description": "Heading over the band: the measure and its unit, e.g. \"Depth, metres\"."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for item keys."
          },
          "bandWidth": {
            "type": "number",
            "description": "Width of the band in px, at most 40% of the plot width. Default 60, or 46 on narrow screens."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "scatter-chart": {
        "title": "Scatter chart",
        "description": "Plots two numeric measures against each other, one dot per row, with optional bubble size, group colour, selective labels and a trend line. Use: Showing whether and how two measures move together, spotting clusters and outliers, and placing named entities in a two-dimensional space (with quadrant lines via `annotations`). Avoid: A measure over time (use line-chart); one numeric measure by category (use beeswarm-chart or strip-plot); fewer than about 8 points (use bar-chart or a table); more than 4 colour groups (facet with small-multiples).",
        "type": "object",
        "properties": {
          "type": {
            "const": "scatter-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "x": {
            "type": "string",
            "description": "Numeric field on the horizontal axis."
          },
          "y": {
            "type": "string",
            "description": "Numeric field on the vertical axis."
          },
          "size": {
            "type": "string",
            "description": "Numeric field for bubble size; area is proportional to the value."
          },
          "series": {
            "type": "string",
            "description": "Field that colours points by group. Beyond 4 groups the smallest fold into a grey Other."
          },
          "label": {
            "type": "string",
            "description": "Field naming each point, for tooltips, direct labels and `highlight`."
          },
          "labels": {
            "anyOf": [
              {
                "const": "auto"
              },
              {
                "const": "all"
              },
              {
                "const": "none"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Which points are labelled. `auto`: highlighted points, or the outliers when nothing is highlighted. Overlapping labels are hidden.",
            "$comment": "default: \"auto\""
          },
          "trend": {
            "type": "boolean",
            "description": "Least-squares line of best fit through all points.",
            "$comment": "default: false"
          },
          "logX": {
            "type": "boolean",
            "description": "Logarithmic x axis.",
            "$comment": "default: false"
          },
          "logY": {
            "type": "boolean",
            "description": "Logarithmic y axis.",
            "$comment": "default: false"
          },
          "xLabel": {
            "type": "string",
            "description": "x axis title. Defaults to the field name."
          },
          "yLabel": {
            "type": "string",
            "description": "y axis title. Defaults to the field name."
          },
          "xFormat": {
            "$ref": "#/definitions/format",
            "description": "Format for x values; `format` applies to y."
          },
          "opacity": {
            "type": "number",
            "description": "Point opacity. Default falls as the point count rises."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for series keys."
          }
        },
        "required": [
          "type",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "segmented-bar": {
        "title": "Segmented bar",
        "description": "Splits one whole into proportional segments along a single horizontal bar. Use: A compact part-to-whole for cards, table cells and stat rows: budget split, device mix, vote share. The legend carries names in block order. Avoid: Comparing compositions across several groups (use bar-chart with stack \"percent\"); more than about 6 parts or many slivers (use bar-chart); when the reader should count units (use waffle-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "segmented-bar"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Category field: one segment per distinct value."
          },
          "value": {
            "type": "string",
            "description": "Value field."
          },
          "size": {
            "enum": [
              "tall",
              "thin"
            ],
            "description": "28px with shares printed inside where they fit, or 8px unlabelled.",
            "$comment": "default: \"tall\""
          },
          "sort": {
            "enum": [
              "none",
              "desc"
            ],
            "description": "Segment order; the legend follows it.",
            "$comment": "default: \"none\""
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for category keys."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "shape-fill": {
        "title": "Shape fill",
        "description": "Shows one or more percentages as icon silhouettes filled from the bottom to that level, with the number printed large beside each. Use: One to six shares of a full amount where the object itself says what is measured: how full a reservoir is, how charged a fleet is, what share of homes have a heat pump. Avoid: The fill height only approximates the share, because an irregular silhouette holds less area at its narrow end, so the number must always stay printed; for values to be compared precisely use block-bar or bar-chart, for a counted share use waffle-chart, for a compact inline meter use progress-meter.",
        "type": "object",
        "properties": {
          "type": {
            "const": "shape-fill"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Label field: one silhouette per row."
          },
          "value": {
            "type": "string",
            "description": "Value field: how full each silhouette is, against `max`."
          },
          "max": {
            "type": "number",
            "description": "The value that fills a silhouette completely. Default: 1 when every value is at most 1, otherwise 100."
          },
          "icon": {
            "anyOf": [
              {},
              {
                "const": "path://..."
              }
            ],
            "description": "Built-in icon name or a custom single SVG path.",
            "$comment": "default: \"drop\""
          },
          "icons": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Icon per label; falls back to `icon`."
          },
          "columns": {
            "type": "number",
            "description": "Silhouettes per line. Default: up to four, two on a phone."
          },
          "colorBy": {
            "enum": [
              "single",
              "item"
            ],
            "description": "`single`: every silhouette in the accent colour. `item`: one colour per row.",
            "$comment": "default: \"single\""
          },
          "iconSize": {
            "type": "number",
            "description": "Silhouette height in px. Default: sized to the width, or grown to fill the box when the `height` prop or `aspect` is given, so one silhouette can be the main figure of a poster."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "slope-chart": {
        "title": "Slope chart",
        "description": "Connects each entity's value at two (or a few) points with a straight line, labelled with name and value at both ends. Use: Before / after for 3 to about 15 entities when the change in level and in ordering both matter; pair with `highlight` to emphasise one line. Avoid: Five or more time points (use line-chart); when only the ordering matters (use bump-chart); when only the size of each gap matters (use dumbbell-chart or arrow-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "slope-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "series": {
            "type": "string",
            "description": "Entity field: one line each."
          },
          "x": {
            "type": "string",
            "description": "Period field for long data. Omit when each row is an entity with one column per period."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field (long data), or the period columns in order (one row per entity)."
          },
          "colorBy": {
            "enum": [
              "none",
              "direction",
              "series"
            ],
            "description": "Accent for all lines, positive / negative by direction, or one hue per entity (up to 8).",
            "$comment": "default: \"none\""
          },
          "good": {
            "enum": [
              "up",
              "down"
            ],
            "description": "Direction that takes the positive colour when colouring by direction.",
            "$comment": "default: \"up\""
          },
          "labels": {
            "enum": [
              "both",
              "end"
            ],
            "description": "Entity names at both ends or only the end. Default: both; end only on narrow screens."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for entity keys and period columns."
          }
        },
        "required": [
          "type",
          "series",
          "y"
        ],
        "additionalProperties": false
      },
      "small-multiples": {
        "title": "Small multiples",
        "description": "Repeats one small line, area or bar chart per value of a facet field on a shared scale, each panel titled. Use: The same measure for 4 to about 24 entities when one chart would have too many overlapping lines; pair with `highlight` to pick out one panel, or `context` to show every other line faintly behind each. Avoid: Three or fewer series (use line-chart with direct labels); when exact comparison between two entities matters most (use line-chart with `highlight`); a single value per entity (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "small-multiples"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "facet": {
            "type": "string",
            "description": "Field whose values each get a panel."
          },
          "x": {
            "type": "string",
            "description": "Time or ordered category field, shared by every panel."
          },
          "y": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Value field, or several (one series each in every panel)."
          },
          "series": {
            "type": "string",
            "description": "Field that splits rows into series inside each panel (long data)."
          },
          "kind": {
            "enum": [
              "line",
              "area",
              "bar"
            ],
            "description": "What each panel draws. Area and bar panels start at zero.",
            "$comment": "default: \"line\""
          },
          "columns": {
            "type": "number",
            "description": "Preferred number of columns; reduced automatically on narrow containers."
          },
          "scales": {
            "enum": [
              "shared",
              "free"
            ],
            "description": "Shared value scale across panels, or each panel on its own (say so in the subtitle).",
            "$comment": "default: \"shared\""
          },
          "context": {
            "type": "boolean",
            "description": "Draw every other panel's line faintly behind each panel's own.",
            "$comment": "default: false"
          },
          "latest": {
            "type": "boolean",
            "description": "Print the latest value beside each panel title. Default: on for a single series."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for facet values and series keys."
          }
        },
        "required": [
          "type",
          "facet",
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "source-note": {
        "title": "Source note",
        "description": "A sourcing footer for a whole piece: sources with optional links, the period covered, method, caveats and credit. Use: Once, at the end of a story or dashboard, to say where every number came from and how it was produced. Avoid: Sourcing a single chart: use that chart's own `source` and `note` props so the citation travels with its export.",
        "type": "object",
        "properties": {
          "type": {
            "const": "source-note"
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers, e.g. \"2015 to 2024\". Shown as \"Data\"."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "layout": {
            "enum": [
              "list",
              "inline"
            ],
            "description": "Labelled list, or one running paragraph.",
            "$comment": "default: \"list\""
          },
          "rule": {
            "type": "boolean",
            "description": "Hairline above the note.",
            "$comment": "default: true"
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "Extra content after the rows."
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "sparkline": {
        "title": "Sparkline",
        "description": "A word-sized line or bar series without axes, with the latest point marked. Use: Showing the recent history of a number inside a stat tile, a table cell or a sentence, where the shape of the trend matters and exact values do not. Avoid: Anything the reader must read values from or compare across series (use line-chart); fewer than about 5 points (state the change in words or use big-number with a delta).",
        "type": "object",
        "properties": {
          "type": {
            "const": "sparkline"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "y": {
            "type": "string",
            "description": "Value field."
          },
          "x": {
            "type": "string",
            "description": "Time or label field, used in the tooltip and alt text. Rows are drawn in data order."
          },
          "mark": {
            "enum": [
              "line",
              "bar"
            ],
            "description": "Line for a trend, bars for discrete counts or gains and losses (negative bars take the negative colour).",
            "$comment": "default: \"line\""
          },
          "extremes": {
            "type": "boolean",
            "description": "Mark the lowest and highest points with small dots.",
            "$comment": "default: false"
          },
          "band": {
            "type": "array",
            "description": "Shaded reference range in value units, e.g. a normal range."
          },
          "area": {
            "type": "boolean",
            "description": "Light fill under the line; forces a zero baseline.",
            "$comment": "default: false"
          },
          "showValue": {
            "type": "boolean",
            "description": "Print the last value after the line.",
            "$comment": "default: false"
          },
          "zero": {
            "type": "boolean",
            "description": "Include zero in the scale. Default: off for lines, always on for bars."
          }
        },
        "required": [
          "type",
          "y"
        ],
        "additionalProperties": false
      },
      "stat-circles": {
        "title": "Stat circles",
        "description": "Shows a few related magnitudes as plain circles sized by area, each with its number set large and a short label. Use: The poster way to show two to six related magnitudes whose rough proportion is the point: kilograms per person in three countries, the same quantity in three years, a total and its parts set side by side. Avoid: More than six values or values that need precise comparison (use bar-chart); a single number (use big-number); many circles of one whole (use circle-pack); values close together, where areas look the same (use bar-chart or dumbbell-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "stat-circles"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Label field: the short text under or beside each circle."
          },
          "value": {
            "type": "string",
            "description": "Value field: circle area, and the number printed large. Non-positive values are dropped."
          },
          "unit": {
            "type": "string",
            "description": "Unit printed small after each number, e.g. \"kg\". Leave out when `format` already includes it."
          },
          "layout": {
            "enum": [
              "row",
              "steps",
              "nested"
            ],
            "description": "Circles centred on one line, standing on a shared baseline, or drawn inside each other from a shared lowest point. Narrow containers stack a row or steps into a column.",
            "$comment": "default: \"row\""
          },
          "colorBy": {
            "enum": [
              "item",
              "value",
              "single"
            ],
            "description": "A colour per circle, a shade by value along the sequential ramp, or the accent for all.",
            "$comment": "default: \"item\""
          },
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            ],
            "description": "Icon above the number in large circles: one for all, or a map from label to icon. Built-in name or `path://`."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "stat-tile": {
        "title": "Stat tile",
        "description": "A compact, bordered KPI tile: label, value, change against a baseline and an optional trend graphic. Use: Dashboard grids and KPI rows of three to six figures, each needing its own change indicator or sparkline. Give every tile a delta or a context line. Avoid: The single number a story leads with (use `big-number` with `size: \"hero\"`). Do not put a full chart with axes in the trend slot.",
        "type": "object",
        "properties": {
          "type": {
            "const": "stat-tile"
          },
          "label": {
            "type": "string",
            "description": "What it measures, sentence case."
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The figure. Numbers are formatted with `format`."
          },
          "delta": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Change against a baseline. Numbers render as signed percentages (0.12 is +12%)."
          },
          "deltaLabel": {
            "type": "string",
            "description": "What the delta is against, e.g. \"vs last month\"."
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is an improvement. Sets the delta colour.",
            "$comment": "default: true"
          },
          "context": {
            "type": "string",
            "description": "A line that states a comparison or reference for the number."
          },
          "trend": {
            "anyOf": [
              {
                "$ref": "#/definitions/slot"
              },
              {
                "type": "array",
                "items": {
                  "type": "number"
                }
              }
            ],
            "description": "A chart spec, a React element, or an array of numbers drawn as a sparkline."
          },
          "trendPosition": {
            "enum": [
              "bottom",
              "right"
            ],
            "description": "Where the trend sits; `right` falls back to `bottom` under 280px.",
            "$comment": "default: \"bottom\""
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format for `value`.",
            "$comment": "default: \"auto\""
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "Extra content at the bottom of the tile."
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "label",
          "value"
        ],
        "additionalProperties": false
      },
      "step-marker": {
        "title": "Step marker",
        "description": "A numbered chapter or step heading (\"01 — Electricity sources in 2015\") for sequencing the sections of a story. Use: When a piece has three to seven ordered chapters or steps. Open each one with a marker so the reader can see the position in the sequence. Avoid: Unordered sections (use `headline` with `size: \"section\"`), or numbering a list of items inside a paragraph.",
        "type": "object",
        "properties": {
          "type": {
            "const": "step-marker"
          },
          "step": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Step number, zero-padded to two digits. Strings are shown as written."
          },
          "title": {
            "type": "string",
            "description": "The chapter or step title."
          },
          "total": {
            "type": "number",
            "description": "Total steps; the marker then reads \"02 / 05\"."
          },
          "text": {
            "type": "string",
            "description": "A sentence under the title."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `text`."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level.",
            "$comment": "default: 2"
          },
          "size": {
            "enum": [
              "md",
              "lg"
            ],
            "description": "`lg` for chapter openers.",
            "$comment": "default: \"md\""
          },
          "layout": {
            "enum": [
              "inline",
              "stacked"
            ],
            "description": "Number beside or above the title. Narrow containers always stack.",
            "$comment": "default: \"inline\""
          },
          "rule": {
            "type": "boolean",
            "description": "Hairline above the marker.",
            "$comment": "default: false"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          },
          "theme": {
            "type": "object",
            "description": "Theme override: partial tokens, or { light, dark }."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode."
          }
        },
        "required": [
          "type",
          "step",
          "title"
        ],
        "additionalProperties": false
      },
      "strip-plot": {
        "title": "Strip plot",
        "description": "Shows every observation as a tick or dot along a value axis, one row per category. Use: Comparing the spread and clustering of a numeric value across 2 to about 15 categories when there are few enough observations to show each one; many rows with few to a few hundred observations each. Avoid: A single group where the shape matters (use histogram or beeswarm-chart); when individual points must be identifiable or coloured (use beeswarm-chart); when only quartiles matter (use box-plot).",
        "type": "object",
        "properties": {
          "type": {
            "const": "strip-plot"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Category field: one row per distinct value."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "value": {
            "type": "string",
            "description": "Numeric field positioning each mark."
          },
          "label": {
            "type": "string",
            "description": "Field naming each observation, for the tooltip."
          },
          "mark": {
            "enum": [
              "tick",
              "dot"
            ],
            "description": "Thin vertical ticks (a barcode) or translucent dots.",
            "$comment": "default: \"tick\""
          },
          "median": {
            "type": "boolean",
            "description": "Heavier tick at each row's median, with its value printed.",
            "$comment": "default: false"
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order rows by median.",
            "$comment": "default: \"none\""
          },
          "jitter": {
            "type": "boolean",
            "description": "Deterministic vertical spread for dots, to relieve overplotting.",
            "$comment": "default: false"
          }
        },
        "required": [
          "type",
          "value",
          "group"
        ],
        "additionalProperties": false
      },
      "timeline-chart": {
        "title": "Timeline chart",
        "description": "Places events and spans on a time axis in labelled lanes, with each item named directly. Use: When things happened and how long they lasted: project phases, terms of office, product launches, the sequence of events in a story. Mix spans (start and end) with point milestones (start only). Avoid: A measured value changing over time (use line-chart, with annotations for the events); more than about 40 items (filter, or split into several timelines); durations to be compared precisely with no interest in when (use bar-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "timeline-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Label field: what the event or span is."
          },
          "start": {
            "type": "string",
            "description": "Start field: ISO date, year or timestamp."
          },
          "end": {
            "type": "string",
            "description": "End field. Rows without an end are point milestones."
          },
          "lane": {
            "type": "string",
            "description": "Field that groups rows into labelled lanes."
          },
          "precision": {
            "enum": [
              "year",
              "month",
              "day"
            ],
            "description": "Date precision in tooltips. Default: chosen from the span of the data."
          }
        },
        "required": [
          "type",
          "name",
          "start"
        ],
        "additionalProperties": false
      },
      "treemap": {
        "title": "Treemap",
        "description": "Shows parts of a whole as nested rectangles sized by value, optionally grouped into categories. Use: Many parts (10 to 100) of very different sizes, or a two-level hierarchy, where the reader needs the largest parts rather than exact comparison: budgets, market capitalisation, export baskets. Avoid: Fewer than about 6 parts or values that need precise comparison (use bar-chart); 2 to 5 parts (use donut-chart or segmented-bar); values that can be negative (use bar-chart); change over time (use line-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "treemap"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Parent field. Rows sharing a group are drawn together and share a colour."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Leaf name field: one tile per row."
          },
          "value": {
            "type": "string",
            "description": "Value field: tile area. Non-positive values are dropped."
          },
          "labels": {
            "type": "boolean",
            "description": "Print the value under the name where the tile is big enough.",
            "$comment": "default: true"
          },
          "groupLabels": {
            "type": "boolean",
            "description": "Heading strip above each group. Default: on when `group` is set and not compact."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for group keys."
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "unit-blocks": {
        "title": "Unit blocks",
        "description": "Shows the size of each group as a solid block of small icons, one icon per fixed number of units. Use: Large counts of people or things in 2 to 12 groups, where the reader should see the crowd itself: 20,350 marathon finishers by age group, one figure per 10 runners. Avoid: Precise comparison of close values (use block-bar or bar-chart); fewer than about 30 icons per group (use pictogram-chart or icon-array-grid); shares of one whole (use waffle-chart).",
        "type": "object",
        "properties": {
          "type": {
            "const": "unit-blocks"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "name": {
            "type": "string",
            "description": "Group field: one block of icons per row of data."
          },
          "value": {
            "type": "string",
            "description": "Value field: the quantity each block counts out."
          },
          "unit": {
            "type": "number",
            "description": "Units per icon. Default: a round number that gives about 2,000 icons in total."
          },
          "unitLabel": {
            "type": "string",
            "description": "What one icon stands for, for the key line, e.g. \"10 finishers\"."
          },
          "icon": {
            "anyOf": [
              {},
              {
                "const": "path://..."
              }
            ],
            "description": "Built-in icon name or a custom single SVG path.",
            "$comment": "default: \"person\""
          },
          "series": {
            "type": "string",
            "description": "Field that colours the blocks. Default: one colour per group, up to eight groups."
          },
          "layout": {
            "enum": [
              "packed",
              "columns"
            ],
            "description": "`packed`: equal block heights, widths follow the counts. `columns`: equal widths, blocks grow upwards from a baseline.",
            "$comment": "default: \"packed\""
          },
          "columns": {
            "type": "number",
            "description": "Blocks per line in the `columns` layout. Default: all, two on a phone."
          },
          "iconSize": {
            "type": "number",
            "description": "Icon height in px. Default: the largest that fits, chosen per chart. To put two charts on one scale, give both the same `unit` and `iconSize`: the icon size, the gaps and the worth of an icon are then identical and the chart takes the height it needs."
          },
          "sort": {
            "enum": [
              "none",
              "asc",
              "desc"
            ],
            "description": "Order of the blocks.",
            "$comment": "default: \"none\""
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "waffle-chart": {
        "title": "Waffle chart",
        "description": "Shows shares of a whole as counted cells in a grid, such as 37 in every 100. Use: One share (\"37 in every 100\") or a handful of categories that add up to a whole, where the reader should be able to count the units. Avoid: Comparing shares across several groups (use bar-chart with stack \"percent\"); more than about 6 categories or shares under 1% (use bar-chart); a compact inline part-to-whole (use segmented-bar).",
        "type": "object",
        "properties": {
          "type": {
            "const": "waffle-chart"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows, CSV text, a URL, `{ url, path }`, an async function, or an Arrow-style table. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "A pipeline of transforms applied before drawing."
          },
          "title": {
            "type": "string",
            "description": "The title. One plain statement of what the data shows, with the number and the period (\"Monthly churn fell from 4.2% to 2.1% in 2024\"), or a plain label (\"Monthly churn, 2024\"). One clause, no figures of speech."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, unit, population, period."
          },
          "source": {
            "type": "string",
            "description": "Data source, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method notes or caveats."
          },
          "height": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "CSS height of the plot. Default 360."
          },
          "aspect": {
            "type": "number",
            "description": "Width / height. Overrides `height`."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "The entity (or entities) the title is about. Every other series is drawn in grey."
          },
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/annotation"
            },
            "description": "Reference lines, shaded bands and callouts, in data coordinates."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values: `\"compact\"`, `\"percent\"`, `\"currency:USD\"`, `\"{value} kg\"`, Intl options, or a function."
          },
          "legend": {
            "type": "boolean",
            "description": "Show the legend. Default: shown when there are two or more series."
          },
          "select": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string"
              }
            ],
            "description": "Make marks clickable to filter. Inside `<InsightData>` the selection filters every other chart. Pass a field name, or `true` to use the chart's category field."
          },
          "option": {
            "type": "object",
            "description": "Deep-merged over the generated ECharts option, or a function that receives and returns it. Use it for ECharts settings no prop covers."
          },
          "theme": {
            "type": "object",
            "description": "A full theme, `{ light, dark }` partial tokens, or flat tokens applied to both modes. Merged over the surrounding `InsightProvider` theme."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "`\"auto\"` (default) follows the page, `\"system\"` follows the OS, or force `\"light\"` / `\"dark\"`."
          },
          "renderer": {
            "enum": [
              "auto",
              "svg",
              "canvas"
            ],
            "description": "`\"auto\"` (default) uses SVG for light charts and canvas for heavy ones."
          },
          "animate": {
            "type": "boolean",
            "description": "Set false to disable animation for this chart. Reduced-motion preferences are always respected."
          },
          "lazy": {
            "type": "boolean",
            "description": "Mount the chart only when it scrolls within 200px of the viewport. Default true (from `InsightProvider`)."
          },
          "group": {
            "type": "string",
            "description": "Link tooltips with other charts sharing this group id."
          },
          "exportable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "array",
                "items": {
                  "enum": [
                    "png",
                    "jpeg",
                    "svg",
                    "pdf",
                    "csv",
                    "json"
                  ]
                }
              }
            ],
            "description": "Show an export menu: `true` or a list of formats from png, jpeg, svg, pdf, csv, json."
          },
          "table": {
            "type": "boolean",
            "description": "Show a collapsible \"View data\" table under the chart."
          },
          "alt": {
            "type": "string",
            "description": "Accessible description: the chart type and measures, then the main pattern and the notable values."
          },
          "id": {
            "type": "string",
            "description": "Stable id for this chart's selection in the shared store."
          },
          "className": {
            "type": "string",
            "description": "Class on the figure element."
          },
          "style": {
            "type": "object",
            "description": "Inline style on the figure element."
          },
          "value": {
            "type": "string",
            "description": "Value field. Each category's cells are its share of the whole."
          },
          "name": {
            "type": "string",
            "description": "Category field. Omit for a single share."
          },
          "total": {
            "type": "number",
            "description": "The whole. Default: the sum of the values. Set to 100 with one value to show a single share against an empty remainder."
          },
          "rows": {
            "type": "number",
            "description": "Grid rows.",
            "$comment": "default: 10"
          },
          "columns": {
            "type": "number",
            "description": "Grid columns.",
            "$comment": "default: 10"
          },
          "shape": {
            "enum": [
              "square",
              "circle"
            ],
            "description": "Cell shape.",
            "$comment": "default: \"square\""
          },
          "restLabel": {
            "type": "string",
            "description": "Label for the unfilled remainder when `total` exceeds the sum."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for category keys."
          }
        },
        "required": [
          "type",
          "value"
        ],
        "additionalProperties": false
      },
      "annotated-timeline": {
        "title": "Annotated timeline",
        "description": "A vertical sequence of dated events along a rail, each with a short explanation and, optionally, a small chart or figure. Use: Telling how something unfolded when the events matter more than a continuous measure: a policy history, an incident, a product's milestones. Four to eight events; give a figure only to the ones where a number changed. Avoid: Events that should be read against a time scale, with gaps and overlaps to scale (use `timeline-chart`); a continuous series with a few annotated moments (use `line-chart` with `annotations`); ordered steps that are not dated (use `section` with `step`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "annotated-timeline"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The events in reading order. `date` is shown as written; `figure` is a chart spec or element; `emphasis` fills the marker to mark the most important events."
          },
          "figurePosition": {
            "enum": [
              "below",
              "side"
            ],
            "description": "Where an event's figure sits; `side` falls back to `below` under 640px.",
            "$comment": "default: \"below\""
          },
          "level": {
            "enum": [
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the event titles.",
            "$comment": "default: 3"
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label."
          },
          "subtitle": {
            "type": "string",
            "description": "Scope and period."
          },
          "source": {
            "type": "string",
            "description": "Shown under the timeline as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to every event."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "events"
        ],
        "additionalProperties": false
      },
      "before-after": {
        "title": "Before and after",
        "description": "Two states of one measure side by side, as figures or small charts, with the change between them stated in the middle. Use: A single measure at two moments or under two conditions: before and after a policy, control and treatment, last year and this. The change is computed from the two values unless you state it. Avoid: More than two states (use `line-chart` or `slope-chart`); many entities each with a before and after (use `dumbbell-chart` or `arrow-chart`); two unrelated figures (use `stat-row`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "before-after"
          },
          "before": {
            "type": "object",
            "description": "The first state: a figure, a chart slot, or both."
          },
          "after": {
            "type": "object",
            "description": "The second state."
          },
          "delta": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The change stated between the two. Default: the relative change when both values are numbers."
          },
          "deltaLabel": {
            "type": "string",
            "description": "Words under the change, e.g. \"in five years\"."
          },
          "deltaFormat": {
            "$ref": "#/definitions/format",
            "description": "Number format for a numeric `delta`.",
            "$comment": "default: signed percent"
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is good news; decides the colour of the change.",
            "$comment": "default: true"
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format shared by both values.",
            "$comment": "default: \"auto\""
          },
          "title": {
            "type": "string",
            "description": "The change stated plainly, with both values and the period."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure and population."
          },
          "source": {
            "type": "string",
            "description": "Shown underneath as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to both states."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "before",
          "after"
        ],
        "additionalProperties": false
      },
      "chart-callout": {
        "title": "Chart with callout",
        "description": "A chart with a callout beside it that states the main fact. In narrow containers the callout goes underneath. Use: Whenever a chart needs its meaning stated in words next to it: the standard chart-plus-interpretation unit of a report. The chart's title states the main fact with its number. The callout adds a second fact, a cause or a caveat in plain words. Avoid: Repeating the chart title in the callout; long narration (put `prose` before the chart instead); a chart that is already a small tile (the callout would outweigh it).",
        "type": "object",
        "properties": {
          "type": {
            "const": "chart-callout"
          },
          "chart": {
            "$ref": "#/definitions/slot",
            "description": "The chart: a spec or a React element."
          },
          "lead": {
            "type": "string",
            "description": "The main fact in a few words, with its number. Shown in bold."
          },
          "body": {
            "type": "string",
            "description": "One or two plain sentences that say what the fact means."
          },
          "tone": {
            "enum": [
              "neutral",
              "positive",
              "negative",
              "accent"
            ],
            "description": "Sets the callout's icon and tint together.",
            "$comment": "default: \"accent\""
          },
          "label": {
            "type": "string",
            "description": "Small label above the lead, e.g. \"Takeaway\" or \"Caveat\"."
          },
          "side": {
            "enum": [
              "left",
              "right"
            ],
            "description": "Side of the chart the callout sits on. Under 640px it always goes underneath.",
            "$comment": "default: \"right\""
          },
          "variant": {
            "enum": [
              "plain",
              "soft",
              "outline"
            ],
            "description": "`plain` separates the callout with a hairline; the others box it.",
            "$comment": "default: \"plain\""
          },
          "align": {
            "enum": [
              "start",
              "center",
              "end"
            ],
            "description": "Vertical position of the callout beside the chart.",
            "$comment": "default: \"center\""
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `chart`."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the chart and callout."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "chart"
        ],
        "additionalProperties": false
      },
      "chart-tabs": {
        "title": "Chart tabs",
        "description": "One chart frame with a segmented control that switches between several views of the same data, morphing between views that share a chart type. Use: The same entities under two to five measures or scalings where each view changes the reading: total / per capita / change, absolute / share, linear / log. Give the frame a plain label as its title. Each view's `subtitle` names its measure. Avoid: Hiding the most important view behind a tab (show it first, or show both with `small-multiple-grid`); unrelated charts (give each its own figure); more than five views.",
        "type": "object",
        "properties": {
          "type": {
            "const": "chart-tabs"
          },
          "chart": {
            "$ref": "#",
            "description": "The base chart spec every view starts from: `{ type, data, ... }`."
          },
          "views": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to five views. `props` are merged over `chart`; or give a view its own complete `chart` slot."
          },
          "defaultView": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "description": "The view shown first: an id, a label or an index."
          },
          "view": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "description": "Controlled active view."
          },
          "tabsLabel": {
            "type": "string",
            "description": "Accessible name of the tab list.",
            "$comment": "default: \"Chart view\""
          },
          "tabsPosition": {
            "enum": [
              "right",
              "below"
            ],
            "description": "Tabs beside the title or under it. Under 560px they always go underneath.",
            "$comment": "default: \"right\""
          },
          "title": {
            "type": "string",
            "description": "A plain label or fact that is true of every view."
          },
          "subtitle": {
            "type": "string",
            "description": "What the views share; each view's own `subtitle` names its measure."
          },
          "source": {
            "type": "string",
            "description": "Shown under the chart as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "Extra content under the chart."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the chart."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "views"
        ],
        "additionalProperties": false
      },
      "comparison-table": {
        "title": "Comparison table",
        "description": "A table whose rows carry inline sparklines, deltas and in-cell bars beside their exact values, from rows and a column config. Use: Comparing five to twenty entities on a level, a trend and a change at once: countries, products, teams. Readers look up their row. The sparkline and delta show how the value changed. Avoid: Plain lookups with no series (use `data-table`); one measure ranked (use `ranked-list` or `bar-chart`); trends the reader must compare precisely (use `small-multiples`). Each sparkline has its own scale, so it shows the direction of change and cannot be used to compare levels between rows.",
        "type": "object",
        "properties": {
          "type": {
            "const": "comparison-table"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Wide data: one row per entity. Long data: one row per entity and period, with `groupBy`. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied before rows are grouped."
          },
          "columns": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "Columns in order; the first is the row header. `kind` is `text`, `number`, `sparkline`, `delta` or `bar`. For wide data give a sparkline or computed delta its series with `fields`; for long data they use the group's rows."
          },
          "groupBy": {
            "type": "string",
            "description": "Long data: the entity field. Rows sharing a value become one table row, in data order."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Entities to emphasise, matched on the first column."
          },
          "sort": {
            "type": "object",
            "description": "Order rows by a column's value. Default direction: descending. With `sortable` this is the opening order."
          },
          "sortable": {
            "type": "boolean",
            "description": "Click or press Enter on a column header to sort by it (numbers largest first, text A to Z); a second press reverses and a third restores the original order. Sparkline columns do not sort; set `sortable: false` on a column to exclude it.",
            "$comment": "default: true"
          },
          "limit": {
            "type": "number",
            "description": "Show only the first N rows."
          },
          "density": {
            "enum": [
              "comfortable",
              "compact"
            ],
            "description": "Row padding.",
            "$comment": "default: \"comfortable\""
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label. Set as the table's `<caption>`."
          },
          "subtitle": {
            "type": "string",
            "description": "Units and period."
          },
          "source": {
            "type": "string",
            "description": "Shown under the table as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the sparklines and deltas."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "columns"
        ],
        "additionalProperties": false
      },
      "filter-chips": {
        "title": "Filter chips",
        "description": "The active crossfilter selections of the surrounding `InsightData`, shown as removable chips with a reset control. Use: Inside any `<InsightData>` whose charts use `select`: put it above the charts so readers can see what is filtered, drop one value, or clear everything. `linked-charts` already includes it. Avoid: Outside `<InsightData>` it renders nothing unless you pass `selections` yourself. It is not a filter builder: selections are made by clicking marks in the charts.",
        "type": "object",
        "properties": {
          "type": {
            "const": "filter-chips"
          },
          "selections": {
            "type": "object",
            "additionalProperties": {
              "type": "object"
            },
            "description": "Selections to show when there is no surrounding `<InsightData>` (or to override it), keyed by owner. Uncontrolled unless `onSelectionsChange` is given."
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for field names, e.g. `{ region: \"Region\" }`."
          },
          "hint": {
            "type": "string",
            "description": "Shown while nothing is selected, e.g. \"Click a bar to filter\"."
          },
          "resetLabel": {
            "type": "string",
            "description": "Text of the clear-all control.",
            "$comment": "default: \"Reset\""
          },
          "count": {
            "type": "boolean",
            "description": "Show \"1,204 of 5,000 rows\" at the end of the line.",
            "$comment": "default: false"
          },
          "unit": {
            "type": "string",
            "description": "Noun for the count, e.g. \"orders\".",
            "$comment": "default: \"rows\""
          },
          "theme": {
            "type": "object",
            "description": "Theme override."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "hero-figure": {
        "title": "Hero figure",
        "description": "The opening exhibit of a piece: kicker, headline and deck above one large chart, with a source line underneath. Use: At the very top of a data story or a one-page report. The headline states the main fact with its number. The chart shows that fact. Avoid: Giving the chart its own `title` (the headline is the title; use the chart's `subtitle` for the measure). A second hero on the same page: later sections use `section` or `chart-callout`.",
        "type": "object",
        "properties": {
          "type": {
            "const": "hero-figure"
          },
          "title": {
            "type": "string",
            "description": "The main fact, as one plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the series or topic."
          },
          "deck": {
            "type": "string",
            "description": "One plain sentence under the title that adds a second fact."
          },
          "byline": {
            "type": "string",
            "description": "Author line, e.g. \"By Ana Ruiz\"."
          },
          "date": {
            "type": "string",
            "description": "Publication date. ISO dates are formatted for the locale."
          },
          "chart": {
            "$ref": "#/definitions/slot",
            "description": "The hero chart: a spec or a React element, without its own title."
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know."
          },
          "align": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Headline alignment.",
            "$comment": "default: \"left\""
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title.",
            "$comment": "default: 1"
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `chart`."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the headline, chart and source note."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "chart"
        ],
        "additionalProperties": false
      },
      "kpi-grid": {
        "title": "KPI grid",
        "description": "A responsive grid of trend cards drawn from one dataset: each metric shows its latest value, its change and a sparkline. Use: The top of a dashboard or a monthly report: three to eight metrics tracked over the same periods. Pass one table with a column per metric. Avoid: Figures without a series behind them (use `stat-row`); comparing the metrics with each other on one scale (use `line-chart` or `small-multiples`); more than eight cards.",
        "type": "object",
        "properties": {
          "type": {
            "const": "kpi-grid"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "One dataset in time order: a row per period, a column per metric. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied once, before the cards read the rows."
          },
          "x": {
            "type": "string",
            "description": "Period field shared by every metric."
          },
          "metrics": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One card per metric; each takes the props of `trend-card`."
          },
          "compare": {
            "anyOf": [
              {
                "const": "first"
              },
              {
                "const": "previous"
              },
              {
                "type": "number"
              }
            ],
            "description": "Baseline for every card's change; a metric can override it.",
            "$comment": "default: \"first\""
          },
          "change": {
            "enum": [
              "percent",
              "absolute"
            ],
            "description": "Relative change, or the difference between the two values; a metric can override it. An absolute change of a percentage metric is shown in percentage points (\"−2.1 pts\").",
            "$comment": "default: \"percent\""
          },
          "deltaFormat": {
            "$ref": "#/definitions/format",
            "description": "Format for absolute changes, e.g. `\"{value} pp\"` or `\"signed\"`; a metric can override it. Default: points for percentage formats, otherwise the metric's own `format`."
          },
          "columns": {
            "type": "number",
            "description": "Preferred columns. Default: up to four, reduced to fit cards of at least 200px."
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label."
          },
          "subtitle": {
            "type": "string",
            "description": "Population and period."
          },
          "source": {
            "type": "string",
            "description": "Shown under the grid as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to every card."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "metrics"
        ],
        "additionalProperties": false
      },
      "linked-charts": {
        "title": "Linked charts",
        "description": "Two to four charts over one shared dataset in a responsive grid: clicking a mark in one filters the others, with the active filters shown as removable chips. Use: Exploration of one table along several dimensions: by region, by category and over time. Pass row-level data once; each chart aggregates it with its own `transform`, sets `select: true` and omits `data`. Avoid: A report that states one fixed fact (use `chart-callout` or `scrolly-chart`); charts over unrelated datasets (they cannot filter each other); more than four charts.",
        "type": "object",
        "properties": {
          "type": {
            "const": "linked-charts"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "The shared, row-level dataset."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied once to the shared data."
          },
          "charts": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/slot"
            },
            "description": "Two to four chart specs or elements. Give each `select: true` (or a field name) and a stable `id`, and leave out `data`."
          },
          "columns": {
            "type": "number",
            "description": "Preferred columns. Default two; fewer when charts would be narrower than `minChartWidth`."
          },
          "minChartWidth": {
            "type": "number",
            "description": "Narrowest a chart may get before the grid drops a column.",
            "$comment": "default: 260"
          },
          "filters": {
            "type": "boolean",
            "description": "Show the filter line (`filter-chips`).",
            "$comment": "default: true"
          },
          "hint": {
            "type": "string",
            "description": "Shown in the filter line while nothing is selected.",
            "$comment": "default: \"Click a mark to filter the other charts\""
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for the fields in the chips."
          },
          "count": {
            "type": "boolean",
            "description": "Show the filtered row count at the end of the filter line.",
            "$comment": "default: false"
          },
          "unit": {
            "type": "string",
            "description": "Noun for the count.",
            "$comment": "default: \"rows\""
          },
          "selections": {
            "type": "object",
            "additionalProperties": {},
            "description": "Controlled selections, keyed by chart id."
          },
          "title": {
            "type": "string",
            "description": "Heading for the group."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, population and period shared by the charts."
          },
          "source": {
            "type": "string",
            "description": "Shown under the grid as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `charts`."
          },
          "before": {
            "anyOf": [
              {
                "$ref": "#/definitions/slot"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/slot"
                }
              }
            ],
            "description": "Content rendered inside the shared store above the grid: figures, text, a custom component that calls `useInsightData()`, or a spec that omits `data` (e.g. `stat-row`, `data-table`). It sees the same filtered rows as the charts."
          },
          "after": {
            "anyOf": [
              {
                "$ref": "#/definitions/slot"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/slot"
                }
              }
            ],
            "description": "Content rendered inside the shared store below the grid, e.g. a detail table of the filtered rows."
          },
          "gap": {
            "type": "number",
            "description": "Space in px between the `before` slot, the grid and the `after` slot.",
            "$comment": "default: 24"
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to every chart."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "data"
        ],
        "additionalProperties": false
      },
      "metric-breakdown": {
        "title": "Metric breakdown",
        "description": "A headline number with its composition underneath: one segmented bar and a key giving each part's value and share. Use: A total that the reader will immediately want split: a budget by department, revenue by product line, emissions by sector. Two to six parts that add up to the number above them. Avoid: Parts that do not sum to the headline; more than about six parts (use `bar-chart`); composition compared across groups or over time (use `bar-chart` with `stack: \"percent\"` or `area-chart`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "metric-breakdown"
          },
          "label": {
            "type": "string",
            "description": "What the headline number measures."
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "One row per part. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied before the parts are summed."
          },
          "name": {
            "type": "string",
            "description": "Field naming each part."
          },
          "value": {
            "type": "string",
            "description": "Field with each part's value."
          },
          "total": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The headline number. Default: the sum of the parts."
          },
          "context": {
            "type": "string",
            "description": "The line under the headline number."
          },
          "delta": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Change in the headline number. Numbers render as signed percentages."
          },
          "deltaLabel": {
            "type": "string",
            "description": "What the delta is against."
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is good news.",
            "$comment": "default: true"
          },
          "size": {
            "enum": [
              "hero",
              "stat"
            ],
            "description": "`hero` when this opens a piece.",
            "$comment": "default: \"stat\""
          },
          "show": {
            "enum": [
              "both",
              "value",
              "share"
            ],
            "description": "What the key prints beside each part.",
            "$comment": "default: \"both\""
          },
          "sort": {
            "enum": [
              "none",
              "desc"
            ],
            "description": "Order parts by size; the bar and the key follow.",
            "$comment": "default: \"none\""
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for part keys."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format for the headline and the parts.",
            "$comment": "default: \"auto\""
          },
          "source": {
            "type": "string",
            "description": "Shown underneath as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the number and the bar."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "label",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "poster": {
        "title": "Poster",
        "description": "The sheet an infographic is composed on. It paints a full-bleed ground from a poster theme, forces one theme and colour mode on everything inside, and lays out a masthead, a grid of panels and a footer. It can save the whole sheet as one PNG. Use: Use it as the outer frame of any infographic: one dominant graphic with a few supporting panels, on a painted ground. Give it a poster theme (`noir`, `magenta`, `dusk`, `paper`, `ocean`, `forest`, `blueprint`, `sunrise`) and put a chart or figure spec in each panel. Put the one fact in `title` and keep panel headings short. It reflows to one column under 600px. Avoid: Long reading text or more than about six panels (use `report-page` or `visual-essay`). A single fact at a fixed social size (use `social-card`). Charts that need axes, gridlines and dense labels to be read, because a poster ground suits large flat marks with their values printed on them.",
        "type": "object",
        "properties": {
          "type": {
            "const": "poster"
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number. Set large and light in the theme's display face."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic or series."
          },
          "subtitle": {
            "type": "string",
            "description": "One or two lines under the title: the measure, population and period."
          },
          "panels": {
            "type": "array",
            "items": {},
            "description": "The blocks, in reading order. Each is `{ content, title?, subtitle?, span?, rowSpan?, source?, note?, align?, valign?, bleed?, id? }`. `content` is a component spec or rendered content. `span` is in units of `columns` (default: full width). `bleed` runs the content to the poster's left and right edges."
          },
          "columns": {
            "type": "number",
            "description": "Columns of the layout grid: a 12-unit grid, or a simple count such as 2 or 3. Under 600px every panel is full width; from 600 to 760px the grid has two columns.",
            "$comment": "default: 12"
          },
          "gap": {
            "type": "number",
            "description": "Space between panels in px. Default 40 (28 under 600px)."
          },
          "padding": {
            "type": "number",
            "description": "Space between the poster's edge and its content in px. Default 56 (36 under 900px, 20 under 600px)."
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1200"
          },
          "aspect": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Fixed shape as width / height: `0.75`, `\"3:4\"`, `\"16:9\"`. The poster still grows when its content needs more height, and the ratio is dropped under 600px."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "A poster theme name, any other theme name, or a theme object. It is passed on to everything inside.",
            "$comment": "default: \"noir\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "background": {
            "type": "string",
            "description": "CSS background of the sheet, a colour or a gradient. Default: the poster theme's ground. Keep it close to the theme's `surface`, which charts use for the gaps between marks."
          },
          "rules": {
            "enum": [
              "none",
              "solid",
              "dotted"
            ],
            "description": "Lines under the masthead, between rows of panels and above the footer.",
            "$comment": "default: \"dotted\""
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "titleAlign": {
            "enum": [
              "left",
              "center"
            ],
            "description": "Alignment of the masthead.",
            "$comment": "default: \"left\""
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster. The image is the whole sheet, drawn from the DOM onto a canvas, without the control.",
            "$comment": "default: false"
          },
          "exportWidth": {
            "type": "number",
            "description": "Width of the downloaded PNG in pixels.",
            "$comment": "default: 2400"
          },
          "filename": {
            "type": "string",
            "description": "File name without extension. Defaults to a slug of the title."
          },
          "downloadLabel": {
            "type": "string",
            "description": "Label of the download control.",
            "$comment": "default: \"Download PNG\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "panels"
        ],
        "additionalProperties": false
      },
      "proportion-statement": {
        "title": "Proportion statement",
        "description": "A share stated as a countable sentence (\"37 in every 100…\"): a waffle grid or a row of icons beside the statement in large type, with the number emphasised. Use: One proportion that is easier to read as a count of people or units than as a percentage. Round to a small whole first: 1 in 4 with icons, 37 in every 100 with a waffle. Avoid: Several shares side by side (use `bar-chart`, or `waffle-chart` with categories); a precise percentage where the decimals matter (use `big-number`); totals above 100.",
        "type": "object",
        "properties": {
          "type": {
            "const": "proportion-statement"
          },
          "value": {
            "type": "number",
            "description": "How many of the whole are counted."
          },
          "total": {
            "type": "number",
            "description": "The whole.",
            "$comment": "default: 100"
          },
          "figure": {
            "type": "string",
            "description": "The emphasised words. Default: \"{value} in every {total}\", or \"{value} in {total}\" up to 20."
          },
          "text": {
            "type": "string",
            "description": "The rest of the sentence, read straight after the figure."
          },
          "visual": {
            "enum": [
              "waffle",
              "icons"
            ],
            "description": "Grid of cells or row of glyphs. Default: icons up to a total of 20, waffle above."
          },
          "icon": {
            "enum": [
              "circle",
              "person",
              "square"
            ],
            "description": "Glyph for the `icons` visual.",
            "$comment": "default: \"person\""
          },
          "shape": {
            "enum": [
              "square",
              "circle"
            ],
            "description": "Cell shape for the `waffle` visual.",
            "$comment": "default: \"square\""
          },
          "side": {
            "enum": [
              "left",
              "right"
            ],
            "description": "Side the visual sits on; under 520px it goes on top.",
            "$comment": "default: \"left\""
          },
          "detail": {
            "type": "string",
            "description": "A second, quieter sentence under the statement."
          },
          "source": {
            "type": "string",
            "description": "Shown under the statement as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the visual."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "value",
          "text"
        ],
        "additionalProperties": false
      },
      "quote-figure": {
        "title": "Quote with figure",
        "description": "A pull-quote paired with the statistic or small chart that backs it up, side by side and stacking in narrow containers. Use: A quotation shown next to the number it refers to: an interview finding with its survey figure, an executive's statement with the metric. One per section. Avoid: A quote with no evidence (use `pull-quote`); a figure that needs axes to read (use `chart-callout` and put the quote in prose); unattributed quotations.",
        "type": "object",
        "properties": {
          "type": {
            "const": "quote-figure"
          },
          "quote": {
            "type": "string",
            "description": "The words quoted, without quotation marks."
          },
          "attribution": {
            "type": "string",
            "description": "Who said it."
          },
          "role": {
            "type": "string",
            "description": "Their role, or where it was said."
          },
          "cite": {
            "type": "string",
            "description": "Source URL, linked from the attribution."
          },
          "stat": {
            "type": "object",
            "description": "The statistic that backs the quote up; takes the props of `big-number`."
          },
          "figure": {
            "$ref": "#/definitions/slot",
            "description": "A small chart or figure instead of, or under, the statistic: a spec or a React element."
          },
          "side": {
            "enum": [
              "left",
              "right"
            ],
            "description": "Side the evidence sits on; under 640px it goes underneath.",
            "$comment": "default: \"right\""
          },
          "source": {
            "type": "string",
            "description": "Shown underneath as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the quote and the figure."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "quote"
        ],
        "additionalProperties": false
      },
      "ranked-list": {
        "title": "Ranked list",
        "description": "A ranking as a list: position, name, value and a thin in-row bar, with an optional change indicator and highlighted rows. Use: A top-N list where the names matter as much as the values: league tables, best and worst performers, leaderboards with a movement column. It keeps long names readable and works in a narrow column. Avoid: Precise visual comparison of many values or more than about 15 rows (use `bar-chart`); several measures per entity (use `data-table` or `comparison-table`); rank changing over time (use `bump-chart`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "ranked-list"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "One row per entity. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied before ranking."
          },
          "name": {
            "type": "string",
            "description": "Field naming each entity."
          },
          "value": {
            "type": "string",
            "description": "Field with the value that ranks them. Bars start at zero."
          },
          "change": {
            "type": "string",
            "description": "Field with a change shown at the end of each row: a number (0.12 is +12%) or a string."
          },
          "changeFormat": {
            "$ref": "#/definitions/format",
            "description": "Format for numeric changes, e.g. `\"signed\"` for places moved.",
            "$comment": "default: signed percent"
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether a positive change is good news.",
            "$comment": "default: true"
          },
          "detail": {
            "type": "string",
            "description": "Field with a short secondary line under each name."
          },
          "sort": {
            "enum": [
              "desc",
              "asc",
              "none"
            ],
            "description": "Order by value; `none` keeps the data order.",
            "$comment": "default: \"desc\""
          },
          "limit": {
            "type": "number",
            "description": "Show only the first N rows after sorting."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Entity names to emphasise. The other bars are drawn in grey."
          },
          "bar": {
            "type": "boolean",
            "description": "Draw the in-row bar.",
            "$comment": "default: true"
          },
          "max": {
            "type": "number",
            "description": "Value at which a bar is full. Default: the largest value shown."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format for the values.",
            "$comment": "default: \"auto\""
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, population and period."
          },
          "source": {
            "type": "string",
            "description": "Shown under the list as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "name",
          "value"
        ],
        "additionalProperties": false
      },
      "scrolly-chart": {
        "title": "Scrolly chart",
        "description": "A scroll-driven story from JSON: one base chart spec and a list of steps, each with narration and a patch of chart props applied while that step is active. Use: Walking a reader through one chart in stages: show everything, highlight the subject, change the measure, add the annotation. Make ONE change per step (the highlight, the data or the encoding) so the reader can see what changed. Avoid: Steps that change several things at once, or that swap to an unrelated chart (start a new `section` instead). More than about seven steps. A fact that one view can show (use `chart-callout`). In documents that will be printed or embedded in a short frame, set `scrollMode: \"steps\"`.",
        "type": "object",
        "properties": {
          "type": {
            "const": "scrolly-chart"
          },
          "chart": {
            "$ref": "#",
            "description": "The base chart spec: `{ type, data, x, y, ... }`. Give it a `title`; steps may replace it."
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The steps in order. `content` is a short paragraph that says plainly what the chart now shows (`**bold**` works). Every other key is a chart prop merged over `chart` for that step: `highlight`, `transform`, `annotations`, `x`, `y`, `title`… Use `null` to remove a base prop. Change one thing per step."
          },
          "cumulative": {
            "type": "boolean",
            "description": "Each step's patch builds on the previous steps instead of on the base spec alone.",
            "$comment": "default: false"
          },
          "scrollMode": {
            "enum": [
              "auto",
              "scroll",
              "swipe",
              "steps"
            ],
            "description": "`scroll` pins the chart while steps scroll past; `swipe` makes steps swipeable cards; `steps` shows previous/next buttons; `auto` uses scroll, or swipe on narrow touch screens. (Named `scrollMode` because `mode` is the colour mode.)",
            "$comment": "default: \"auto\""
          },
          "side": {
            "enum": [
              "left",
              "right"
            ],
            "description": "Side of the text column in scroll mode. Narrow containers overlay the text on the chart.",
            "$comment": "default: \"left\""
          },
          "stickyTop": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Offset from the top of the viewport at which the chart pins; set it to the height of a fixed header.",
            "$comment": "default: 0"
          },
          "stepHeight": {
            "type": "string",
            "description": "Scroll distance per step, as a CSS length.",
            "$comment": "default: \"80vh\""
          },
          "title": {
            "type": "string",
            "description": "Heading above the whole story."
          },
          "subtitle": {
            "type": "string",
            "description": "Line under the heading."
          },
          "source": {
            "type": "string",
            "description": "Shown after the last step as \"Source: ...\". Prefer the chart's own `source`, which stays visible."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the chart and the step cards."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "chart",
          "steps"
        ],
        "additionalProperties": false
      },
      "section": {
        "title": "Section",
        "description": "A story section: a numbered step marker or a headline, introductory prose, then one or more exhibits in a responsive one- to three-column grid. Use: The building block of a longer piece. Each section states one fact with its number in the title, explains it in a paragraph and shows it in one to three exhibits. Use `step` when the sections are read in order. Avoid: The opening of a piece (use `hero-figure`); a single chart with one callout (use `chart-callout` directly); more than three exhibits in one section (split it).",
        "type": "object",
        "properties": {
          "type": {
            "const": "section"
          },
          "title": {
            "type": "string",
            "description": "The section's main fact, as one plain sentence with its number."
          },
          "step": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Step number: turns the heading into a numbered chapter marker (\"02 — ...\")."
          },
          "total": {
            "type": "number",
            "description": "Total steps, shown as \"02 / 05\"."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above an unnumbered heading."
          },
          "deck": {
            "type": "string",
            "description": "One plain sentence under the heading that adds a second fact."
          },
          "intro": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Introductory narration. Supports `**bold**`, `*italic*` and links."
          },
          "body": {
            "anyOf": [
              {
                "$ref": "#/definitions/slot"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/slot"
                }
              }
            ],
            "description": "The exhibits: one slot or several, each a spec or a React element."
          },
          "columns": {
            "enum": [
              1,
              2,
              3
            ],
            "description": "Columns for the body at full width; reduced under 720px and 520px.",
            "$comment": "default: 1"
          },
          "outro": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Closing narration under the body."
          },
          "rule": {
            "type": "boolean",
            "description": "Hairline above the section.",
            "$comment": "default: false"
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level.",
            "$comment": "default: 2"
          },
          "id": {
            "type": "string",
            "description": "Anchor id for deep links."
          },
          "spacing": {
            "enum": [
              "compact",
              "comfortable"
            ],
            "description": "Vertical rhythm between heading, intro and body.",
            "$comment": "default: \"comfortable\""
          },
          "children": {
            "$ref": "#/definitions/slot",
            "description": "JSX alternative to `body`; each child becomes a grid item."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "small-multiple-grid": {
        "title": "Small multiple grid",
        "description": "Repeats any chart spec once per value of a facet field, each panel with its own filtered rows and a title, in a grid that follows the container width. Use: Faceting a chart form the `small-multiples` atom does not draw: stacked bars, scatter plots, donuts, waffles, dumbbells, histograms. Also when each panel should be a full chart with its own tooltip and axis. Avoid: Line, area or bar facets that must share one value scale: use the `small-multiples` atom, which draws every panel in one chart on a common axis. Here each panel scales to its own rows unless the spec fixes the axis (for example `option: { xAxis: { max: 70 } }`), so say so in the subtitle or fix it. More than about twelve panels.",
        "type": "object",
        "properties": {
          "type": {
            "const": "small-multiple-grid"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows for every panel together. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied before the rows are split by `facet`."
          },
          "facet": {
            "type": "string",
            "description": "Field whose values each get a panel."
          },
          "chart": {
            "$ref": "#",
            "description": "The chart repeated in every panel: a spec without `data` and without a `title`, or a render function from JSX."
          },
          "columns": {
            "type": "number",
            "description": "Preferred columns. Default: up to four, reduced to fit `minPanelWidth`."
          },
          "minPanelWidth": {
            "type": "number",
            "description": "Narrowest a panel may get before the grid drops a column.",
            "$comment": "default: 200"
          },
          "order": {
            "anyOf": [
              {
                "const": "data"
              },
              {
                "const": "asc"
              },
              {
                "const": "desc"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Panel order: data order, alphabetical, or an explicit list of facet values.",
            "$comment": "default: \"data\""
          },
          "panelHeight": {
            "type": "number",
            "description": "Plot height of each panel when the spec sets none.",
            "$comment": "default: 160"
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Passed to every panel as its `highlight`, so the same entity is emphasised everywhere."
          },
          "emphasis": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Facet values whose panel titles are emphasised."
          },
          "legend": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "One shared colour key above the panels (`legend-key` items, in series order). Set `legend: false` in the chart spec so panels do not repeat it."
          },
          "names": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for facet values."
          },
          "level": {
            "enum": [
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the panel titles.",
            "$comment": "default: 4"
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label."
          },
          "subtitle": {
            "type": "string",
            "description": "Measure, population, period, and whether the panels share a scale."
          },
          "source": {
            "type": "string",
            "description": "Shown under the grid as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to every panel."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "facet",
          "chart"
        ],
        "additionalProperties": false
      },
      "stat-row": {
        "title": "Stat row",
        "description": "Two to five key figures in one row separated by hairlines, collapsing to two columns and then one as the container narrows. Use: The opening summary of a report or dashboard: the two to five most important numbers. Give every figure a delta or a context line, and order them by importance. Avoid: More than five figures (use `kpi-grid`), a single lead number (use `big-number` with `size: \"hero\"`), or figures that need their history shown (use `kpi-grid`, or `variant: \"tiles\"` with a `trend`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "stat-row"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to five figures, most important first. Each takes the props of `big-number` (or `stat-tile` when `variant` is `tiles`)."
          },
          "variant": {
            "enum": [
              "plain",
              "tiles"
            ],
            "description": "Open figures divided by hairlines, or bordered tiles that can carry a `trend`.",
            "$comment": "default: \"plain\""
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format for every figure that does not set its own.",
            "$comment": "default: \"auto\""
          },
          "title": {
            "type": "string",
            "description": "The main fact with its number, or a plain label."
          },
          "subtitle": {
            "type": "string",
            "description": "Population and period the figures share."
          },
          "source": {
            "type": "string",
            "description": "Shown under the row as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Method note or caveat."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to every figure."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to every figure.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "items"
        ],
        "additionalProperties": false
      },
      "trend-card": {
        "title": "Trend card",
        "description": "A KPI card computed from a series: the latest value, its change against a baseline in the same data, and a sparkline of the series. Use: A metric whose recent history matters as much as its level: users, revenue, response time. Pass the series and field names; the figure, the change and the sparkline all come from the same rows, so they cannot disagree. Avoid: A number with no history (use `big-number` or `stat-tile`); several metrics from one dataset (use `kpi-grid`); a series the reader must read values from (use `line-chart`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "trend-card"
          },
          "label": {
            "type": "string",
            "description": "What the figure measures, sentence case."
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows in time order, one per period. Omit inside `<InsightData>`."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied to the rows before anything is computed."
          },
          "y": {
            "type": "string",
            "description": "Value field: the series drawn and the source of the figure and its change."
          },
          "x": {
            "type": "string",
            "description": "Period field, used to name the baseline and in the sparkline tooltip."
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The figure shown. Default: the last row's `y`."
          },
          "delta": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "The change shown. Default: computed from the series according to `compare`."
          },
          "compare": {
            "anyOf": [
              {
                "const": "first"
              },
              {
                "const": "previous"
              },
              {
                "type": "number"
              }
            ],
            "description": "Baseline for the computed change: first row, previous row, or a number of rows back (12 for year-on-year in monthly data).",
            "$comment": "default: \"first\""
          },
          "change": {
            "enum": [
              "percent",
              "absolute"
            ],
            "description": "Relative change, or the difference between the two values (use for rates and shares). An absolute change of a percentage is shown in percentage points.",
            "$comment": "default: \"percent\""
          },
          "deltaFormat": {
            "$ref": "#/definitions/format",
            "description": "Format for a computed absolute change, e.g. `\"{value} pp\"` or `\"signed\"`. Default: points (\"+1.9 pts\") when `format` is a percentage, otherwise `format`."
          },
          "deltaLabel": {
            "type": "string",
            "description": "What the change is against. Default: \"since {first period}\" when `x` is given."
          },
          "upIsGood": {
            "type": "boolean",
            "description": "Whether an increase is good news; decides the delta colour.",
            "$comment": "default: true"
          },
          "context": {
            "type": "string",
            "description": "A line under the figure that gives it meaning."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "Number format for the figure and the sparkline tooltip.",
            "$comment": "default: \"auto\""
          },
          "kind": {
            "enum": [
              "line",
              "bar"
            ],
            "description": "Sparkline form: a line for a trend, bars for discrete counts.",
            "$comment": "default: \"line\""
          },
          "area": {
            "type": "boolean",
            "description": "Light fill under the line; the scale then includes zero.",
            "$comment": "default: false"
          },
          "trendPosition": {
            "enum": [
              "bottom",
              "right"
            ],
            "description": "Where the sparkline sits; `right` falls back to `bottom` in narrow cards.",
            "$comment": "default: \"bottom\""
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the tile and sparkline."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "label",
          "y"
        ],
        "additionalProperties": false
      },
      "atlas-poster": {
        "title": "Atlas poster",
        "description": "A landscape spread of up to eleven small illustrations of one subject, each a different graphic form, in three bands of unequal panels: a statement in large type, spokes round an icon and a network of circles; a smooth trend with its peak labelled, nested squares and a slope chart; a pill ranking, a treemap, a tile map and sized circles; and a closing row of icon statements. Use: Use it when one subject has many small facts of different kinds (shares, places, a trend, a change, a ranking, a map) and none of them should dominate: a crop, an industry, a service, a country's internet. Fill at least eight regions. Give every panel a short heading that states its one number. Every region is optional, and each band shares its width among the panels that are present. Avoid: One dominant fact or graphic (use `count-poster`, `flow-poster` or `ranking-poster`). The same measures across several entities (use `matrix-poster`). Fewer than six panels (use `poster` and place them yourself). A phone-first piece: the spread becomes one long column under 600px.",
        "type": "object",
        "properties": {
          "type": {
            "const": "atlas-poster"
          },
          "statement": {
            "type": "object",
            "description": "Band 1, left: the subject's main number in large light type, in the accent colour."
          },
          "spokes": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 1, middle: 4 to 12 attributes as spokes round a centre icon (`radial-spokes`)."
          },
          "network": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 1, right: named places or things as circles sized by value and joined by lines (`bubble-network`)."
          },
          "trend": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 2, wide: one measure over an ordered dimension as a smooth filled curve (`area-chart`). The highest point is labelled with its value and position; `peak` replaces that label, and `peak: false` removes it."
          },
          "area": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 2: two or three quantities as squares nested from one corner, with a bracket stating the ratio (`proportional-area`, `layout: \"nested\"`)."
          },
          "slope": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 2: each entity at two dates, joined by a line and labelled at the end (`slope-chart`)."
          },
          "rank": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 3: a ranking of 4 to 6 rows as centred pills (`pill-rank`). Pass a `bar-chart` spec for bars instead."
          },
          "parts": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 3: the parts of one whole as tiles (`treemap`)."
          },
          "map": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 3: a tile map shaded by value (`choropleth-map`). Give every row `col` and `row`, the tile's place in the grid, and the template builds the squares; `code` names the field printed on each tile. Pass `geo` to use your own GeoJSON."
          },
          "circles": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Band 3: two to four magnitudes as sized circles (`stat-circles`)."
          },
          "stats": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Closing row: up to three \"3 in 10\" statements, each a row of icons with some filled (`icon-stat`)."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"forest\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1440"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "comparison-brief": {
        "title": "Comparison brief",
        "description": "A compared with B on one page. It has a headline that states the result, the headline figures mirrored either side of their labels, one hero exhibit that shows both sides, paired exhibits on a shared scale, a verdict callout and a source note. Use: Use it for two things a reader has to choose between or compare, such as two countries, two products or a before and an after. Write the result with its number in the headline. Put the four or five most important measures in `figures`. Use a two-series line, dumbbell, slope or `before-after` as the hero. In each pair, use the same chart form and the same scale for both sides. The `subject` side takes the accent colour everywhere and the other side stays grey. Avoid: Three or more things (use a `comparison-table` or `small-multiple-grid` inside a `report-page`). One thing over time with nothing to compare it with (use `timeline-story`). Paired charts on different scales, because readers compare bar lengths across the pair.",
        "type": "object",
        "properties": {
          "type": {
            "const": "comparison-brief"
          },
          "title": {
            "type": "string",
            "description": "The result of the comparison, as one plain sentence with the number in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "a": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Side A, shown on the left."
          },
          "b": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Side B, shown on the right."
          },
          "subject": {
            "enum": [
              "a",
              "b",
              "none"
            ],
            "description": "The side the piece is about. It takes the accent colour; the other stays grey. Match it with `highlight` in the charts.",
            "$comment": "default: \"a\""
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Headline measures. Numeric values get mirrored bars scaled within each row; `better` sets the stronger value bolder."
          },
          "hero": {
            "$ref": "#/definitions/slot",
            "description": "The exhibit that shows both sides at once. Default height 360px."
          },
          "heroText": {
            "type": "string",
            "description": "One or two sentences under the hero."
          },
          "pairs": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Paired exhibits under one heading. A is on the left and B on the right; they stack in narrow containers. Use the same form and scale for both."
          },
          "verdict": {
            "type": "object",
            "description": "The closing recommendation, shown as a callout."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "a",
          "b"
        ],
        "additionalProperties": false
      },
      "count-poster": {
        "title": "Count poster",
        "description": "A poster that counts at scale. Blocks of thousands of unit icons fill most of the sheet, a second band counts reference groups with the same icon at the same size in a muted colour, and a bottom row holds three small graphics: squares sized by area with a ratio bracket, thick bars with the numbers inside, and shares as nested outlines or filled silhouettes. Use: Use it when the subject is a large count of people or things in 2 to 6 groups and the reader should see the crowd: pupils by stage, trees planted by species, vehicles built by model. Give `hero` the groups and `reference` one to three quantities to compare them with. Both bands use the same `unit`, `icon` and icon size, so their areas compare. State the total in the title. Avoid: Counts under a few hundred (use `pictogram-chart` in a `poster`). Shares of one whole as the main point (use `waffle-chart` or `treemap`). A ranking of many named things (use `ranking-poster`). A flow from sources to destinations (use `flow-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "count-poster"
          },
          "hero": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The hero band: one block of unit icons per row, drawn by `unit-blocks`. A full spec or element replaces it."
          },
          "unit": {
            "type": "number",
            "description": "Units one icon stands for, in both bands. Default: a round number that gives the hero about 2,000 icons."
          },
          "unitLabel": {
            "type": "string",
            "description": "What one icon stands for, e.g. \"1,000 pupils\". Printed as the key of both bands."
          },
          "icon": {
            "anyOf": [
              {},
              {
                "const": "path://..."
              }
            ],
            "description": "Icon of both bands.",
            "$comment": "default: \"person\""
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print the counts.",
            "$comment": "default: \"integer\""
          },
          "reference": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The second band: reference groups counted with the same icon at the same size, painted in the theme's context grey (`unit-blocks`)."
          },
          "area": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom left: two to four values as squares sized by area, with a bracket stating how many times the largest is the smallest (`proportional-area`). `ratio` defaults to `\"{ratio}x larger\"`."
          },
          "bars": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom middle: 3 to 8 values as thick rounded bars with the numbers inside (`block-bar`)."
          },
          "shares": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom right: shares of one whole. With `icon` each share is a silhouette filled to its level (`shape-fill`); without, the shares are outlines nested in one square (`nested-shares`)."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"noir\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "hero",
          "title"
        ],
        "additionalProperties": false
      },
      "data-explorer": {
        "title": "Data explorer",
        "description": "A set of linked charts over one shared dataset that filter each other. It has a headline, a sentence of instructions with filter chips, a row of figures that recompute from the filtered rows, two to four charts and an optional detail table. It opens on selections the author chooses. Use: Use it when readers will want to filter the data themselves after seeing the main finding. State the finding with its number in the headline. Set `initialSelections` so the piece opens on the view the headline describes. Use the figures and the `finding` callout to give the numbers for that view. Keep to one dataset and two to four small, plain charts. Readers click the charts to filter, so keep them all the same size. Avoid: A fixed message that needs no exploration (use `executive-brief` or `visual-essay`). Charts over unrelated datasets, which cannot filter each other. More than four charts or five figures.",
        "type": "object",
        "properties": {
          "type": {
            "const": "data-explorer"
          },
          "title": {
            "type": "string",
            "description": "What the starting view shows, as one plain sentence with the number in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "instructions": {
            "type": "string",
            "description": "One sentence saying what can be clicked and what happens. Shown in the filter line."
          },
          "finding": {
            "type": "object",
            "description": "A callout saying what to look for in the starting view."
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "The shared, row-level dataset: rows, CSV text, a URL or a loader."
          },
          "transform": {
            "anyOf": [
              {
                "$ref": "#/definitions/transform"
              },
              {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/transform"
                }
              }
            ],
            "description": "Applied once to the shared data."
          },
          "charts": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/slot"
            },
            "description": "Two to four chart specs. Give each a stable `id`, `select: true` (or a field name) and its own aggregating `transform`; leave out `data`."
          },
          "initialSelections": {
            "type": "object",
            "additionalProperties": {
              "type": "object"
            },
            "description": "Selections the piece opens with, keyed by chart `id`. A button restores them after the reader changes the filter."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Figures recomputed from the filtered rows: `op` over `field` (default sum; count without a field), optionally restricted by `where` and divided by the sum of `per` for a rate or share. While a filter is active each shows the all-rows value as context."
          },
          "table": {
            "type": "object",
            "description": "A detail table of the filtered rows: the props of `data-table` without `rows`, plus a `transform` applied first."
          },
          "labels": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Display names for fields in the filter chips."
          },
          "unit": {
            "type": "string",
            "description": "Noun for what the figures total, used in figure context (\"3,650 across all trips\").",
            "$comment": "default: \"rows\""
          },
          "count": {
            "type": "boolean",
            "description": "Show the filtered row count beside the chips.",
            "$comment": "default: false"
          },
          "rowUnit": {
            "type": "string",
            "description": "Noun for one row of `data` in that count.",
            "$comment": "default: \"rows\""
          },
          "columns": {
            "type": "number",
            "description": "Preferred chart columns."
          },
          "restoreLabel": {
            "type": "string",
            "description": "Label of the button that restores `initialSelections`.",
            "$comment": "default: \"Back to the starting view\""
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "data",
          "charts"
        ],
        "additionalProperties": false
      },
      "executive-brief": {
        "title": "Executive brief",
        "description": "A one-page summary. It has a headline that states the main finding with its number, a deck, a row of three or four key figures, one hero chart with a takeaway callout, two smaller supporting exhibits, a short list of actions and a source note. Use: Use it when a decision-maker will spend about a minute on the page. State the main finding with its number and period in the headline. The headline and the hero chart should be enough for a reader who stops there. The figures, supporting exhibits and actions add detail. Use one accent colour for the subject (`highlight`) and leave everything else grey. Mark the cause on the hero as an annotation. The proportions suit a printed page. Avoid: More than one hero or more than three supporting exhibits (use `report-page`). A recurring set of numbers with no single finding (use `scorecard`). A story told in several steps (use `visual-essay`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "executive-brief"
          },
          "title": {
            "type": "string",
            "description": "The main finding, as one plain sentence with the number and the period in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the report series or team."
          },
          "deck": {
            "type": "string",
            "description": "One to three short sentences. Each states one more fact."
          },
          "byline": {
            "type": "string",
            "description": "Author line, shown as written."
          },
          "date": {
            "type": "string",
            "description": "Publication date. ISO dates are formatted for the locale."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Three or four key figures, most important first. Rendered with `stat-row`."
          },
          "hero": {
            "$ref": "#/definitions/slot",
            "description": "The hero exhibit: a chart spec or element whose `title` states one fact with its number. Gets a height of 340px (260px on phones) unless it sets one."
          },
          "takeaway": {
            "type": "object",
            "description": "The callout beside the hero. `lead` is one short sentence stating the main fact. `body` gives the supporting numbers."
          },
          "supporting": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/slot"
            },
            "description": "Two (at most three) smaller exhibits shown side by side; they stack in narrow containers. Default height 220px."
          },
          "actions": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "Recommended actions, numbered. Two to four."
          },
          "actionsTitle": {
            "type": "string",
            "description": "Heading of the actions list.",
            "$comment": "default: \"What to do\""
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "hero"
        ],
        "additionalProperties": false
      },
      "explainer": {
        "title": "Explainer",
        "description": "A vertical infographic in one narrow column. It opens with a big number or a proportion statement (`hook`), then the hero exhibit, then numbered sections with one exhibit each, a conclusion with an optional link, and sources. Use: Use it to explain one subject to a general audience in a single narrow column. The column also works as a tall image or on a phone screen. State the main finding with its number in the headline and repeat the main number in `hook`. Make the hero exhibit the largest thing on the page. Give each numbered section one heading, one exhibit and one sentence with its main number. Write each section so it can be read without the others. Keep one accent colour on the subject (`highlight`) throughout. Avoid: Findings that need caveats and separate interpretation (use `report-page`). A chart that has to change step by step (use `visual-essay` with a scrolly block). More than five sections, because readers stop before the end.",
        "type": "object",
        "properties": {
          "type": {
            "const": "explainer"
          },
          "title": {
            "type": "string",
            "description": "The main finding, as one plain sentence with the number and the period in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "hook": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The opening number. With `text` it renders a `proportion-statement` (\"19 in every 100 ...\"); with `label` a hero `big-number`. A spec or element is rendered as given."
          },
          "hero": {
            "$ref": "#/definitions/slot",
            "description": "The main exhibit. Its `title` states one fact with its number. Default height 360px."
          },
          "heroText": {
            "type": "string",
            "description": "One or two sentences under the hero. Each states one more fact."
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Numbered sections. Each has a heading, one exhibit and a `takeaway` sentence with its main number."
          },
          "screenful": {
            "type": "boolean",
            "description": "Give every section at least the height of the viewport and centre its content, so each fills a screen.",
            "$comment": "default: false"
          },
          "conclusion": {
            "type": "object",
            "description": "The closing block: a heading, text, a list of actions and an optional link."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "flow-poster": {
        "title": "Flow poster",
        "description": "A portrait poster of where something comes from and where it goes, in three stacked bands painted in one colour: the producers as large labelled tiles, the leading producer's output fanning out as ribbons to an aligned column of destinations, and the destinations as bubbles on a scale of how much each depends on that producer. Use: Use it when one producer leads and the reader should follow its output: ports and the buyers of one port's catch, regions and the users of one region's electricity, terminals and the routes out of the largest. Give `producers` 4 to 10 rows, `flow` 4 to 12 destinations of the leading producer, and `scale` the same destinations with a share (position) and a size. Keep the destination names identical in `flow` and `scale` so `linked` can join them. Avoid: Flows through more than one stage or between many sources and many destinations (use `sankey-chart` in a `poster`). A count of people or things (use `count-poster`). Many measures of the same entities (use `matrix-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "flow-poster"
          },
          "producers": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Top band: the producers as tiles sized by output (`treemap`). The leading one is painted in the accent."
          },
          "lead": {
            "type": "string",
            "description": "The producer the flow starts from. Default: the largest row of `producers`. It names the block the ribbons leave."
          },
          "flow": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Middle band: one ribbon per destination, as thick as its value, ending at a column of names, values and shares (`fan-flow`)."
          },
          "scale": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom band: one bubble per destination, placed by `value` on a 0 to 100 scale and sized by `size` (`bubble-scale`). Set `domain` and `ticks` for a scale that is not a percentage."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print the quantities of the top and middle bands, e.g. `\"{value} kt\"`."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"magenta\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 920"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "producers",
          "flow",
          "title"
        ],
        "additionalProperties": false
      },
      "matrix-poster": {
        "title": "Matrix poster",
        "description": "One wide landscape graphic that compares 4 to 12 entities on five to seven measures: two measures as S-curves between parallel scales on the left, joined to a table on the right in which every other number is drawn as dots, squares, icons, a ring, a circle or a bar. Both halves share one row order and one colour per entity. Use: Use it for profiles of a handful of comparable things with measures in different units: cities, species, products, stations, teams. Pass one row per entity with every measure in it. Put the two measures whose relationship matters in `curve` and the rest in `columns`, choosing a counted glyph (`dots`, `blocks`, `icons`) for small whole numbers, `ring` for shares, `bar` or `circle` for magnitudes. Leave `highlight` out to give every entity its own colour, derived from the theme when its palette is smaller than the number of entities; set it to draw one or two entities in colour and the rest in grey. Avoid: One measure across entities (use `pill-rank` or `bar-chart`). More than 12 entities (use `data-table` or `heatmap`). A subject with a total and its parts (use `ranking-poster` or `flow-poster`). A phone-first piece: the table stacks into cards under 600px and the poster becomes long.",
        "type": "object",
        "properties": {
          "type": {
            "const": "matrix-poster"
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One object per entity, holding the name and every measure."
          },
          "name": {
            "type": "string",
            "description": "Field holding the entity name. Default: the first key of the first row."
          },
          "nameLabel": {
            "type": "string",
            "description": "Heading of the table's name column."
          },
          "curve": {
            "type": "object",
            "description": "Left graphic: the two measures joined by one S-curve per entity (`curve-rank`). The poster's rows are ordered by `left`, largest first."
          },
          "columns": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Right graphic: the glyph columns of the table, in order (`glyph-table`). Three to five read well beside the curves."
          },
          "table": {
            "type": "object",
            "description": "Short heading and source line over and under the table."
          },
          "order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Entity names in display order, for both graphics. Default: largest first on the curve's left measure."
          },
          "highlight": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Entities drawn in colour while every other one turns grey. Without it each entity has its own colour in both graphics."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"paper\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1400"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "rows",
          "curve",
          "columns",
          "title"
        ],
        "additionalProperties": false
      },
      "network-poster": {
        "title": "Network poster",
        "description": "A poster of who is connected to whom: a full-width arc diagram with one arc per connection, as thick as its value (`arc-diagram`), a strip of two to four large figures, and a bottom row where the same entities return as circles joined by lines (`bubble-network`) and as a ranking of centred pills (`pill-rank`). Use: Use it when the connections between 5 to about 20 named things are the subject: ferry crossings between harbours, joint papers between institutes, freight between rail yards. Give `hero` one row per connection and the `order` the entities sit in, `map` the entities with a size and optional hand-placed `x` and `y`, and `rank` one measure of each entity. With `linked`, a click on an entity in any of the three highlights it in the other two. Avoid: A flow from sources to destinations in one direction (use `flow-poster` or `sankey-chart`). More than about 20 entities or 40 connections, because the arcs cover each other. Entities with no meaningful order and few links (use `bubble-network` in a `poster`). Parts of one subject (use `radial-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "network-poster"
          },
          "hero": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The hero: one arc per pair of connected entities, drawn by `arc-diagram`. Rows joining the same pair are summed. A full spec or element replaces it."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to four large figures in a strip under the hero."
          },
          "map": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom left: the entities as circles sized by `value` and joined by `links: { from, to, value? }[]` (`bubble-network`). `x` and `y` (0 to 100) place the circles by hand."
          },
          "rank": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom right: the entities ranked by one measure as centred pills (`pill-rank`). With only one of `map` and `rank`, that one takes the full width."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"dusk\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "hero",
          "title"
        ],
        "additionalProperties": false
      },
      "profile-poster": {
        "title": "Profile poster",
        "description": "A poster that describes one subject from four sides: the subject as one large silhouette filled to a share (`shape-fill`), two to four large figures, its place among other things on one scale (`scale-ladder`), and a table that sets it beside its peers with every number drawn as a small form (`glyph-table`). Use: Use it for a fact sheet about one named thing: a vehicle, a reservoir, a building, a machine, a species. Give `portrait` one row with the share that defines the subject and the `icon` that stands for it, `figures` the numbers a reader should take away, `scale` the subject among 4 to 10 reference points, and `table` the subject beside 2 to 6 peers. Highlight the subject in `scale` and `table`. On a sheet at least 960px wide the silhouette, the figures and the scale stand in three columns. Avoid: Several subjects of equal weight (use `glyph-table` in a `poster`, or `ranking-poster`). A subject whose parts are the point (use `radial-poster`). A subject with no defining share: leave `portrait` to a full spec such as `stat-circles`, or use `scale-poster` when the scale is the whole subject. Change over time (use `timeline-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "profile-poster"
          },
          "portrait": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The portrait: one silhouette filled from the bottom to the share in its row, with the number beside it, drawn by `shape-fill`. `format` defaults to `\"{value}%\"`. A full spec or element replaces it."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to four large figures about the subject. In the three-column layout they stand between the silhouette and the scale; otherwise they run in a strip."
          },
          "scale": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The subject among 4 to 10 other things on one scale (`scale-ladder`). It is drawn as tall as the silhouette."
          },
          "table": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The subject beside its peers, one row each, with a glyph per measure (`glyph-table`). `columns` is `{ field, label?, glyph?, unit?, format?, max?, icon? }[]`."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"blueprint\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "portrait",
          "title"
        ],
        "additionalProperties": false
      },
      "radial-poster": {
        "title": "Radial poster",
        "description": "A poster with one subject in the middle of the sheet: a wheel of spokes round an icon (`radial-spokes`), two to four large figures standing either side of it, and a bottom row with the same subject's surroundings on concentric rings (`orbit-chart`) and a ranking as centred pills (`pill-rank`). Use: Use it when the poster is about the 4 to 12 parts, causes, effects or scores of one thing: what a household's water goes on, the species one tree supports, where one home's energy goes. Give `hero` the spokes and an `icon` for the centre, state the total in the title, and use `figures` for the two to four numbers a reader should take away. Avoid: Parts of a whole that must be compared precisely (use `bar-chart` in a `poster`). Positions on one scale (use `scale-poster`). Change over time (use `timeline-poster`). Connections between many things (use `network-poster`). Large counts shown as crowds (use `count-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "radial-poster"
          },
          "hero": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The hero: one spoke per row round a centre disc, drawn by `radial-spokes`. A full spec or element replaces it."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to four large figures. On a sheet at least 960px wide they stand in two columns either side of the hero; on a narrower one they run in a row under it."
          },
          "rings": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom left: named things on concentric rings, one ring per category, level or period (`orbit-chart`)."
          },
          "rank": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom right: a ranking as centred pills (`pill-rank`). With only one of `rings` and `rank`, that one takes the full width."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"magenta\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "hero",
          "title"
        ],
        "additionalProperties": false
      },
      "ranking-poster": {
        "title": "Ranking poster",
        "description": "A poster of one subject by the numbers, in four rows: two figures in large type or as filled silhouettes, two treemaps side by side, a full-width ranking of centred pills with one row highlighted, and packed circles with icons beside a column of sized circles and a closing figure. Use: Use it for a profile of one event, place or organisation that has a headline total, two ways to split it, a ranking of 6 to 12 named things and a few supporting magnitudes: a festival, a race, a nature reserve, a library service. Put the total in the title and repeat it as the first figure. Highlight the ranking row the heading is about. Avoid: A subject whose point is a count of people or things (use `count-poster`). Several entities compared on the same measures (use `matrix-poster`). Eight or more small graphics on one subject (use `atlas-poster`). A ranking alone (use `pill-rank` in a `poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "ranking-poster"
          },
          "figures": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object"
                },
                {
                  "type": "object"
                },
                {
                  "$ref": "#/definitions/slot"
                }
              ]
            },
            "description": "Top row, up to two. A statement `{ value, label }` is set in large light type (the first in the accent colour); a config with `data` draws silhouettes filled to their level (`shape-fill`)."
          },
          "breakdowns": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object"
                },
                {
                  "$ref": "#/definitions/slot"
                }
              ]
            },
            "description": "Second row, up to two: the subject's total split two ways, as treemaps side by side."
          },
          "ranking": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Third row, full width: a ranking as centred pills with the value at the left and the rank at the right (`pill-rank`). `highlight` names the row drawn in the accent."
          },
          "pack": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom left: parts as packed circles (`circle-pack`). `icon` is one icon name or a map from circle name to icon."
          },
          "circles": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom right: two to four related magnitudes as circles standing on one baseline (`stat-circles`)."
          },
          "figure": {
            "type": "object",
            "description": "Bottom right, under the circles: one closing figure in large type."
          },
          "format": {
            "$ref": "#/definitions/format",
            "description": "How to print values in the regions that set no `format` of their own."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"dusk\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "ranking",
          "title"
        ],
        "additionalProperties": false
      },
      "report-page": {
        "title": "Report page",
        "description": "A section of an analytical report laid out as a document. It has a title block, a summary, numbered findings, then method, limitations and sources. Each finding has one exhibit, an observation and a separately labelled interpretation with a confidence rating and a caveat. Use: Use it for readers who will check the reasoning, as in evaluations, research notes, audits and experiment write-ups. State the main finding with its number in the title. Put all the main findings and the recommendation in the summary. Write each finding title as one fact with its number, and give it an exhibit that shows that fact. Put what the data shows in `observation` and what you infer from it in `interpretation`. End with method, limitations and sources. Avoid: A decision-maker who wants only the result (use `executive-brief`). A general audience (use `explainer` or `visual-essay`). Findings without an exhibit. Put those in the summary.",
        "type": "object",
        "properties": {
          "type": {
            "const": "report-page"
          },
          "title": {
            "type": "string",
            "description": "The report's main finding, as one plain sentence with the number in it."
          },
          "kicker": {
            "type": "string",
            "description": "The report series or section, e.g. \"Evaluation report · Section 3\"."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "One paragraph with the main findings, their numbers and the recommendation. Supports `**bold**`."
          },
          "summaryTitle": {
            "type": "string",
            "description": "Heading of the summary.",
            "$comment": "default: \"Summary\""
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Numbered findings. `observation` is what the data shows; `interpretation` is what the authors infer, with an optional confidence rating and caveat."
          },
          "observationLabel": {
            "type": "string",
            "description": "Label over each observation.",
            "$comment": "default: \"What the data shows\""
          },
          "interpretationLabel": {
            "type": "string",
            "description": "Label over each interpretation.",
            "$comment": "default: \"What we think it means\""
          },
          "method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "How the analysis was done, as its own section."
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the analysis cannot show."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "scale-poster": {
        "title": "Scale poster",
        "description": "A tall poster that is one illustrated scale: a full-height `scale-ladder` with icons, leader-labelled items and named zones, and a narrow side column of large figures and one small graphic, each set level with the part of the scale it describes. Use: Use it when the positions of 6 to about 16 named things on one scale are the whole subject: depths, altitudes, temperatures, distances, ages. Give the scale's rows and zones in `scale`, up to five `figures` with the scale position each belongs to, and optionally a `side` graphic of two to four magnitudes. Beside the scale the figures line up with their positions; under 760px they move below it. Avoid: Comparing sizes rather than positions (use `ranking-poster` or `count-poster`); change over time (use `timeline-poster`); more than about 16 items, because the labels run together; several unrelated graphics (use `poster` and lay the panels out yourself).",
        "type": "object",
        "properties": {
          "type": {
            "const": "scale-poster"
          },
          "scale": {
            "anyOf": [
              {},
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The scale. A compact `scale-ladder` config: `{ data, name, value, iconField?, icon?, direction?, scale?, min?, max?, ticks?, zones?, scaleLabel?, format?, highlight? }`. Or a full spec, which replaces the ladder."
          },
          "figures": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Large figures for the side column. `at` is the position on the scale the figure belongs to; beside the scale the figure is set level with it under a dotted rule."
          },
          "side": {
            "anyOf": [
              {},
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "One small graphic in the side column. A compact `stat-circles` config: `{ data, name, value, unit?, format?, title?, subtitle? }`. Or a full spec."
          },
          "sideAt": {
            "type": "number",
            "description": "Position on the scale where the `side` graphic starts. Default: under the last figure."
          },
          "height": {
            "type": "number",
            "description": "Height of the scale in px. Default: 68px per item, at least 920 (760 when stacked)."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"ocean\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 980"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "scale",
          "title"
        ],
        "additionalProperties": false
      },
      "scorecard": {
        "title": "Scorecard",
        "description": "A recurring report. It has a masthead with the report name and period, a headline that states the main change, a KPI grid with changes and sparklines, a ranked list beside one or two trend charts, an optional comparison table, short notes and a source note. Use: Use it for weekly or monthly numbers. Keep the layout the same in every edition so readers know where each number is. Change the headline each edition to state the main change with its number. The headline and the KPI row should be enough for a reader who stops there. The ranking, trends and notes add detail. Highlight the one row or series the headline is about and leave the rest grey. Avoid: A one-off finding (use `executive-brief`). Readers who need to filter the data themselves (use `data-explorer`). More than six KPIs.",
        "type": "object",
        "properties": {
          "type": {
            "const": "scorecard"
          },
          "title": {
            "type": "string",
            "description": "The main change this period, as one plain sentence with the number in it."
          },
          "kicker": {
            "type": "string",
            "description": "The name of the report, e.g. \"Store scorecard\". Shown in the masthead."
          },
          "reportPeriod": {
            "type": "string",
            "description": "The period reported, e.g. \"October 2024\". Shown opposite the report name."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "kpis": {
            "type": "object",
            "description": "The headline metrics: the props of `kpi-grid`. One time-ordered dataset, one card per metric."
          },
          "ranking": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "A ranking: the props of `ranked-list`, or any spec or element."
          },
          "trends": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/slot"
            },
            "description": "One or two trend exhibits, shown beside the ranking in wide containers."
          },
          "table": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "A comparison across entities: the props of `comparison-table`, or any spec or element."
          },
          "notes": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object"
                }
              ]
            },
            "description": "Short notes on what changed in the period. Each states one fact with its number."
          },
          "notesTitle": {
            "type": "string",
            "description": "Heading of the notes.",
            "$comment": "default: \"Notes\""
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "social-card": {
        "title": "Social card",
        "description": "A graphic that states one fact, at a fixed aspect ratio (1:1, 4:5, 16:9 or 9:16). It has a kicker, a headline, one exhibit, a source and a credit, painted on the theme surface. A button downloads the whole card as a PNG. Use: Use it for one finding that will be shared in a feed, a slide or a chat thread with no text around it. State the fact with its number in the headline. Use one simple exhibit, such as one highlighted bar, one line or one number. Put the source and your name on the card, because it will be shared without the page. Use 1:1 or 4:5 for feeds, 16:9 for slides and link previews, 9:16 for stories. Avoid: More than one fact or more than one exhibit (use `story-deck` for a sequence, `executive-brief` for a page). Charts that need a legend, small labels or hovering to read, because a shared image is not interactive. An exhibit with its own `title`, because the card's headline is the title.",
        "type": "object",
        "properties": {
          "type": {
            "const": "social-card"
          },
          "title": {
            "type": "string",
            "description": "The card's one fact, as a plain sentence with the number in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One short line under the title: the measure, or the number in words."
          },
          "exhibit": {
            "$ref": "#/definitions/slot",
            "description": "The one exhibit. A chart spec is given the height left in the card (any `height` you set wins); leave out its `title`."
          },
          "source": {
            "type": "string",
            "description": "Where the data comes from, shown as \"Source: ...\"."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown after the source, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made it: a name, handle or publication."
          },
          "aspect": {
            "enum": [
              "1:1",
              "4:5",
              "16:9",
              "9:16"
            ],
            "description": "Shape of the card.",
            "$comment": "default: \"1:1\""
          },
          "tone": {
            "enum": [
              "surface",
              "inverse"
            ],
            "description": "`inverse` paints the card in the opposite colour mode.",
            "$comment": "default: \"surface\""
          },
          "downloadable": {
            "type": "boolean",
            "description": "Show the download button under the card. The image is the whole card, drawn from the DOM onto a canvas.",
            "$comment": "default: true"
          },
          "exportWidth": {
            "type": "number",
            "description": "Width of the downloaded PNG in pixels (1920 for 16:9).",
            "$comment": "default: 1080"
          },
          "filename": {
            "type": "string",
            "description": "File name without extension. Defaults to a slug of the title."
          },
          "downloadLabel": {
            "type": "string",
            "description": "Label of the download button.",
            "$comment": "default: \"Download PNG\""
          },
          "maxWidth": {
            "type": "number",
            "description": "Widest the card is drawn on screen, in px. Default 540 (520 for 4:5, 720 for 16:9, 400 for 9:16). In narrower containers the whole card is scaled down, like an image, so its composition never changes."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title.",
            "$comment": "default: 2"
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to the exhibit."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ],
        "additionalProperties": false
      },
      "story-deck": {
        "title": "Story deck",
        "description": "A sequence of full-frame cards (title, stat, chart, quote, closing) that the reader swipes or steps through. Each card states one fact. It has an optional fixed aspect ratio, a keyboard-accessible pager and a stacked layout for print. Use: Use it for a short sequence read on a phone, such as a “year in review”. Each card should be readable in a couple of seconds. State the main fact with its number on the title card. Put one fact on each later card, as a number or as one chart with one highlighted mark under a headline that states the fact. Use five to ten cards. End with a closing card and the sources. Charts in cards should have few data points and direct labels, with no legend. Avoid: Findings that need two exhibits in view at once (use `executive-brief`). A single shareable image (use `social-card`). Dense charts or long paragraphs, because a card has little room. One chart that changes step by step (use `scrolly-chart` in `steps` mode).",
        "type": "object",
        "properties": {
          "type": {
            "const": "story-deck"
          },
          "cards": {
            "type": "array",
            "items": {},
            "description": "The cards in order. Each has a `kind`: `title` `{ title, deck?, byline? }`; `stat` `{ value, label, context?, delta?, deltaLabel?, upIsGood?, format?, text? }`; `chart` `{ title, chart, text? }`; `quote` `{ quote, attribution?, role? }`; `closing` `{ title, text?, points?, action?: { label, href } }`. Any card takes `kicker`, `tone: \"surface\" | \"inverse\" | \"accent\"` and `id`."
          },
          "label": {
            "type": "string",
            "description": "Accessible name of the deck. Defaults to the first card's title."
          },
          "aspect": {
            "enum": [
              "auto",
              "9:16",
              "4:5",
              "1:1",
              "16:9"
            ],
            "description": "Shape of every card. `auto` lets cards take the height their content needs. `16:9` falls back to `4:5` in containers under 520px.",
            "$comment": "default: \"4:5\""
          },
          "layout": {
            "enum": [
              "pager",
              "stack"
            ],
            "description": "`pager` shows one card at a time (swipe, buttons, dots, arrow keys, Home/End). `stack` lists every card in a column.",
            "$comment": "default: \"pager\""
          },
          "startAt": {
            "type": "number",
            "description": "Card shown first (zero-based).",
            "$comment": "default: 0"
          },
          "maxWidth": {
            "type": "number",
            "description": "Widest a card is drawn, in px. Default 440 (400 for 9:16, 520 for 1:1, 840 for 16:9). Type and spacing scale with the card."
          },
          "previousLabel": {
            "type": "string",
            "description": "Label of the previous button.",
            "$comment": "default: \"Previous\""
          },
          "nextLabel": {
            "type": "string",
            "description": "Label of the next button.",
            "$comment": "default: \"Next\""
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "cards"
        ],
        "additionalProperties": false
      },
      "timeline-poster": {
        "title": "Timeline poster",
        "description": "A poster of change over a run of periods: a full-width ribbon of bands whose thickness is each entity's value and whose order is its rank (`ribbon-chart`), a strip of two to four dated figures under it, and a bottom row with one measure per period as thick bars (`block-bar`) and one share at several dates as nested outlines (`nested-shares`). Use: Use it when the subject is how 4 to 8 named things grew, shrank and changed places over 4 to 10 periods: electricity by source, library loans by format, commuters by mode. Give `hero` the periods and entities, `milestones` the dated numbers a reader should take away, `bars` one measure of the whole at each period and `shares` one share at a few dates. State the latest value in the title. Avoid: A single series over time (use `line-chart` or `area-chart` in a `poster`). Events with start and end dates (use `timeline-chart` or the `timeline-story` template). More than 8 entities or 10 periods, because the bands get too thin to label. Positions on one scale (use `scale-poster`). Parts of one subject at one date (use `radial-poster`).",
        "type": "object",
        "properties": {
          "type": {
            "const": "timeline-poster"
          },
          "hero": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "The hero: one band per entity across the periods, drawn by `ribbon-chart`. Wide rows take `y` as a list of columns; long rows take `y` and `series`. A full spec or element replaces it."
          },
          "milestones": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Two to four dated figures in a strip under the hero, in time order. `at` is the period, printed in small capitals over the figure."
          },
          "bars": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom left: one measure at each period as thick bars with the numbers inside (`block-bar`). `marker: { after, label }` draws a dotted line after one period to mark an event."
          },
          "shares": {
            "anyOf": [
              {
                "type": "object"
              },
              {
                "$ref": "#/definitions/slot"
              }
            ],
            "description": "Bottom right: one share at 2 to 8 dates as outlines nested in one square (`nested-shares`). `format` defaults to `\"{value}%\"`. With only one of `bars` and `shares`, that one takes the full width."
          },
          "title": {
            "type": "string",
            "description": "The poster's one fact, as a plain sentence with its number."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title: the topic."
          },
          "subtitle": {
            "type": "string",
            "description": "One line under the title: the measure, population and period."
          },
          "theme": {
            "anyOf": [
              {},
              {
                "type": "string"
              },
              {
                "type": "object"
              }
            ],
            "description": "Poster theme: `noir`, `magenta`, `dusk`, `ocean`, `forest`, `blueprint`, `sunrise`, `paper`, any other theme name, or a theme object.",
            "$comment": "default: \"sunrise\""
          },
          "mode": {
            "enum": [
              "light",
              "dark",
              "auto",
              "system"
            ],
            "description": "Colour mode of the poster and everything in it. A poster paints its own ground and does not follow the page unless you set `auto`. Only `paper` has a different dark variant.",
            "$comment": "default: \"light\""
          },
          "download": {
            "type": "boolean",
            "description": "Show a \"Download PNG\" control under the poster that saves the whole poster as one image.",
            "$comment": "default: false"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the poster is drawn. It is centred in wider containers.",
            "$comment": "default: 1100"
          },
          "linked": {
            "type": "boolean",
            "description": "Make the marks clickable. Clicking a mark in one graphic highlights the same name in every other graphic that has it, and filters the graphics that read the shared `data`. Click it again, or the empty ground of that graphic, to clear.",
            "$comment": "default: false"
          },
          "data": {
            "$ref": "#/definitions/data",
            "description": "Rows shared by every region whose config leaves out its own `data`. With `linked`, a click filters those regions."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "Where the data comes from, shown in the footer."
          },
          "note": {
            "type": "string",
            "description": "Caveat shown in the footer, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the poster, shown at the right of the footer."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5
            ],
            "description": "Heading level of the title. Panel headings are one level down.",
            "$comment": "default: 2"
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "hero",
          "title"
        ],
        "additionalProperties": false
      },
      "timeline-story": {
        "title": "Timeline story",
        "description": "A story told in date order. It has a headline, one overview exhibit of the whole period (a timeline chart or an annotated line), dated chapters along a rail, a closing paragraph and a source note. Each chapter has a short text and an optional small exhibit. Use: Use it when the reader needs the events in date order to understand a change. State the change over the whole period in the headline, with the numbers and dates. Mark the main events on the overview exhibit as annotations. Give each chapter one event. Add a small figure to a chapter only when it has a number to show. Mark the two or three most important events with `emphasis`. Avoid: Events with no measure that runs through the period (use a plain `annotated-timeline`). A comparison of two states with nothing in between (use `comparison-brief`). More than eight chapters. Merge minor events into the text of the chapter before or after.",
        "type": "object",
        "properties": {
          "type": {
            "const": "timeline-story"
          },
          "title": {
            "type": "string",
            "description": "The change over the whole period, as one plain sentence with the numbers and dates in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date."
          },
          "timeline": {
            "$ref": "#/definitions/slot",
            "description": "The overview exhibit: a `timeline-chart` spec, or a `line-chart` with the events as `annotations`. Default height 360px for line charts."
          },
          "intro": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "A paragraph between the overview and the chapters."
          },
          "chaptersTitle": {
            "type": "string",
            "description": "Heading over the chapters."
          },
          "chapters": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The dated chapters, oldest first. `date` is shown as written; `exhibit` is a small chart or figure; `emphasis` fills the marker for a major event."
          },
          "exhibitPosition": {
            "enum": [
              "below",
              "side"
            ],
            "description": "Where a chapter's exhibit sits; `side` falls back to `below` under 640px.",
            "$comment": "default: \"side\""
          },
          "closing": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ],
            "description": "A closing paragraph that states the latest figures."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "chapters"
        ],
        "additionalProperties": false
      },
      "visual-essay": {
        "title": "Visual essay",
        "description": "A long article read by scrolling. It has a headline, then an ordered list of blocks in a reading column, then a source note. The blocks are prose, figures, charts with a callout, scrolly sequences, pull quotes, stat rows, small multiples and chapter breaks. Exhibits can be wider than the column. Use: Use it for a finding that takes several charts and some text to explain. State the main finding with its number in the headline. Put the main figure within the first screen. Alternate text and charts, with two or three short paragraphs before each exhibit. In a scrolly block change one thing per step, such as the highlight, the year or an annotation. Use one accent colour for the subject in every chart. Avoid: A summary for someone who will not scroll (use `executive-brief`). Reference material read out of order (use `report-page`). More than one or two scrolly blocks. Use one only where the chart changes between steps.",
        "type": "object",
        "properties": {
          "type": {
            "const": "visual-essay"
          },
          "title": {
            "type": "string",
            "description": "The essay's main finding, as one plain sentence with the number and the period in it."
          },
          "kicker": {
            "type": "string",
            "description": "Small label above the title."
          },
          "deck": {
            "type": "string",
            "description": "One-sentence standfirst."
          },
          "byline": {
            "type": "string",
            "description": "Author line."
          },
          "date": {
            "type": "string",
            "description": "Publication date. ISO dates are formatted for the locale."
          },
          "blocks": {
            "type": "array",
            "items": {
              "anyOf": [
                {},
                {
                  "$ref": "#/definitions/slot"
                }
              ]
            },
            "description": "The story in reading order. Each block has a `kind`: `prose` `{ text, lead? }`; `figure` `{ chart, caption? }`; `callout` `{ chart, lead, body, label?, tone?, side? }`; `scrolly` `{ chart, steps, cumulative?, scrollMode?, side?, stepHeight? }` (the props of `scrolly-chart`); `quote` `{ quote, attribution?, role? }`; `stats` `{ items, title? }`; `multiples` `{ facet, ... }` (props of `small-multiples`, or of `small-multiple-grid` when it has a `chart`); `break` `{ title, step?, total?, text? }`. Any block takes `width: \"text\" | \"wide\" | \"full\"` and an `id`. A bare chart spec is treated as a wide figure."
          },
          "measure": {
            "type": "number",
            "description": "Width of the reading column in px.",
            "$comment": "default: 680"
          },
          "textSize": {
            "enum": [
              "md",
              "lg"
            ],
            "description": "Body text size. Default 18px, 16px in narrow containers."
          },
          "sources": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object"
              },
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object"
                    }
                  ]
                }
              }
            ],
            "description": "Where the data comes from, shown in the closing source note. Entries with a `url` are linked."
          },
          "period": {
            "type": "string",
            "description": "The period the data covers."
          },
          "method": {
            "type": "string",
            "description": "How the numbers were produced: definitions, adjustments, exclusions."
          },
          "note": {
            "type": "string",
            "description": "Caveats the reader should know, e.g. \"Illustrative data\"."
          },
          "credit": {
            "type": "string",
            "description": "Who made the piece."
          },
          "level": {
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6
            ],
            "description": "Heading level of the title; section headings follow one level down.",
            "$comment": "default: 1"
          },
          "maxWidth": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ],
            "description": "Widest the piece may get. It is centred in wider containers."
          },
          "theme": {
            "type": "object",
            "description": "Theme override, passed on to everything inside."
          },
          "mode": {
            "enum": [
              "auto",
              "system",
              "light",
              "dark"
            ],
            "description": "Colour mode, passed on to everything inside.",
            "$comment": "default: \"auto\""
          },
          "className": {
            "type": "string"
          },
          "style": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title",
          "blocks"
        ],
        "additionalProperties": false
      }
    },
    "slot": {
      "description": "Content for a slot: text, a nested spec, or a list of either.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "number"
        },
        {
          "type": "null"
        },
        {
          "$ref": "#"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/definitions/slot"
          }
        }
      ]
    },
    "data": {
      "description": "Rows, column arrays, CSV text, a URL, { url, format, path }, { csv } or { json, path }.",
      "anyOf": [
        {
          "type": "array"
        },
        {
          "type": "string"
        },
        {
          "type": "object",
          "required": [
            "url"
          ],
          "properties": {
            "url": {
              "type": "string"
            },
            "format": {
              "enum": [
                "csv",
                "tsv",
                "json",
                "ndjson"
              ]
            },
            "path": {
              "type": "string"
            },
            "init": {
              "type": "object"
            },
            "refresh": {
              "type": "number"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "csv"
          ],
          "properties": {
            "csv": {
              "type": "string"
            },
            "delimiter": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "json"
          ],
          "properties": {
            "path": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "description": "Columnar: { field: [values...] }",
          "additionalProperties": {
            "type": "array"
          }
        }
      ]
    },
    "transform": {
      "type": "object",
      "required": [
        "type"
      ],
      "properties": {
        "type": {
          "enum": [
            "filter",
            "aggregate",
            "sort",
            "limit",
            "top",
            "fold",
            "pivot",
            "bin",
            "derive",
            "rename",
            "select",
            "parse"
          ]
        }
      }
    },
    "annotation": {
      "oneOf": [
        {
          "type": "object",
          "required": [
            "type",
            "axis",
            "value"
          ],
          "additionalProperties": false,
          "properties": {
            "type": {
              "const": "line"
            },
            "axis": {
              "enum": [
                "x",
                "y"
              ]
            },
            "value": {
              "type": [
                "string",
                "number"
              ]
            },
            "label": {
              "type": "string"
            },
            "dashed": {
              "type": "boolean"
            },
            "emphasis": {
              "type": "boolean"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "axis",
            "from",
            "to"
          ],
          "additionalProperties": false,
          "properties": {
            "type": {
              "const": "band"
            },
            "axis": {
              "enum": [
                "x",
                "y"
              ]
            },
            "from": {
              "type": [
                "string",
                "number"
              ]
            },
            "to": {
              "type": [
                "string",
                "number"
              ]
            },
            "label": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "type",
            "x",
            "y",
            "label"
          ],
          "additionalProperties": false,
          "properties": {
            "type": {
              "const": "point"
            },
            "x": {
              "type": [
                "string",
                "number"
              ]
            },
            "y": {
              "type": "number"
            },
            "label": {
              "type": "string"
            },
            "position": {
              "enum": [
                "top",
                "bottom",
                "left",
                "right"
              ]
            },
            "dot": {
              "type": "boolean"
            }
          }
        }
      ]
    },
    "format": {
      "description": "\"auto\", \"compact\", \"percent\", \"percent-raw\", \"integer\", \"signed\", \"year\", \"currency:USD\", \"decimal:2\", a \"{value} unit\" template, or Intl.NumberFormat options.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "object"
        }
      ]
    }
  }
}
