{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://docs.maplibre-yaml.org/schema/latest/scrollytelling.schema.json",
  "title": "maplibre-yaml scrollytelling block",
  "description": "A single `type: scrollytelling` block with chapters — the unit consumed by <ml-map src> and by `mlym validate`.",
  "$ref": "#/$defs/scrollytelling",
  "$defs": {
    "scrollytelling": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "const": "scrollytelling",
          "description": "Block type"
        },
        "id": {
          "type": "string",
          "description": "Unique block identifier"
        },
        "className": {
          "type": "string",
          "description": "CSS class name for container"
        },
        "style": {
          "type": "string",
          "description": "Inline CSS styles for container"
        },
        "config": {
          "type": "object",
          "properties": {
            "center": {
              "type": "array",
              "minItems": 2,
              "maxItems": 2,
              "items": [
                {
                  "type": "number",
                  "minimum": -180,
                  "maximum": 180,
                  "description": "Longitude in degrees (-180 to 180)"
                },
                {
                  "type": "number",
                  "minimum": -90,
                  "maximum": 90,
                  "description": "Latitude in degrees (-90 to 90)"
                }
              ],
              "description": "Initial map center [longitude, latitude]"
            },
            "zoom": {
              "type": "number",
              "minimum": 0,
              "maximum": 24,
              "description": "Initial zoom level (0-24)"
            },
            "mapStyle": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uri"
                },
                {}
              ],
              "description": "MapLibre style URL or style object. Optional when global config.defaultMapStyle is set."
            },
            "pitch": {
              "type": "number",
              "minimum": 0,
              "maximum": 85,
              "default": 0,
              "description": "Camera pitch angle in degrees (0-85)"
            },
            "bearing": {
              "type": "number",
              "minimum": -180,
              "maximum": 180,
              "default": 0,
              "description": "Camera bearing (rotation) in degrees (-180 to 180)"
            },
            "bounds": {
              "anyOf": [
                {
                  "type": "array",
                  "minItems": 4,
                  "maxItems": 4,
                  "items": [
                    {
                      "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/0"
                    },
                    {
                      "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/1"
                    },
                    {
                      "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/0"
                    },
                    {
                      "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/1"
                    }
                  ],
                  "description": "Bounding box as [west, south, east, north]"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              ],
              "description": "Fit map to bounds"
            },
            "fitTo": {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Name of a GeoJSON entry in `sources:` whose data the camera frames"
                },
                "padding": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Padding in pixels around the fitted bounds"
                },
                "maxZoom": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 24,
                  "description": "Upper zoom limit for the fit (a single point would otherwise zoom all the way in)"
                }
              },
              "required": [
                "source"
              ],
              "additionalProperties": false,
              "description": "Fit the initial camera to a GeoJSON source's data (wins over `bounds`)",
              "patternProperties": {
                "^x-": {}
              }
            },
            "minZoom": {
              "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
              "description": "Minimum zoom level"
            },
            "maxZoom": {
              "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
              "description": "Maximum zoom level"
            },
            "minPitch": {
              "type": "number",
              "minimum": 0,
              "maximum": 85,
              "description": "Minimum pitch"
            },
            "maxPitch": {
              "type": "number",
              "minimum": 0,
              "maximum": 85,
              "description": "Maximum pitch"
            },
            "maxBounds": {
              "$ref": "#/$defs/scrollytelling/properties/config/properties/bounds/anyOf/0",
              "description": "Maximum geographic bounds"
            },
            "interactive": {
              "type": "boolean",
              "default": true,
              "description": "Enable map interaction"
            },
            "scrollZoom": {
              "type": "boolean",
              "description": "Enable scroll to zoom"
            },
            "boxZoom": {
              "type": "boolean",
              "description": "Enable box zoom (shift+drag)"
            },
            "dragRotate": {
              "type": "boolean",
              "description": "Enable drag to rotate"
            },
            "dragPan": {
              "type": "boolean",
              "description": "Enable drag to pan"
            },
            "keyboard": {
              "type": "boolean",
              "description": "Enable keyboard shortcuts"
            },
            "doubleClickZoom": {
              "type": "boolean",
              "description": "Enable double-click zoom"
            },
            "touchZoomRotate": {
              "type": "boolean",
              "description": "Enable touch zoom/rotate"
            },
            "touchPitch": {
              "type": "boolean",
              "description": "Enable touch pitch"
            },
            "hash": {
              "type": "boolean",
              "description": "Sync map state with URL hash"
            },
            "attributionControl": {
              "type": "boolean",
              "description": "Show attribution control"
            },
            "logoPosition": {
              "type": "string",
              "enum": [
                "top-left",
                "top-right",
                "bottom-left",
                "bottom-right"
              ],
              "description": "MapLibre logo position"
            },
            "fadeDuration": {
              "type": "number",
              "description": "Fade duration in milliseconds"
            },
            "crossSourceCollisions": {
              "type": "boolean",
              "description": "Check for cross-source collisions"
            },
            "antialias": {
              "type": "boolean",
              "description": "Enable antialiasing"
            },
            "refreshExpiredTiles": {
              "type": "boolean",
              "description": "Refresh expired tiles"
            },
            "renderWorldCopies": {
              "type": "boolean",
              "description": "Render multiple world copies"
            },
            "locale": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              },
              "description": "Localization strings"
            },
            "maxTileCacheSize": {
              "type": "number",
              "description": "Maximum tiles to cache"
            },
            "localIdeographFontFamily": {
              "type": "string",
              "description": "Font for CJK characters"
            },
            "trackResize": {
              "type": "boolean",
              "description": "Track container resize"
            },
            "preserveDrawingBuffer": {
              "type": "boolean",
              "description": "Preserve drawing buffer"
            },
            "failIfMajorPerformanceCaveat": {
              "type": "boolean",
              "description": "Fail if major performance caveat"
            }
          },
          "required": [
            "center",
            "zoom"
          ],
          "additionalProperties": true,
          "description": "Map configuration with MapLibre options"
        },
        "theme": {
          "type": "string",
          "enum": [
            "light",
            "dark"
          ],
          "default": "light",
          "description": "Visual theme"
        },
        "showMarkers": {
          "type": "boolean",
          "default": false,
          "description": "Show chapter markers on map"
        },
        "markerColor": {
          "type": "string",
          "default": "#3FB1CE",
          "description": "Chapter marker color"
        },
        "layers": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Unique layer identifier"
                      },
                      "label": {
                        "type": "string",
                        "description": "Human-readable layer label"
                      },
                      "source": {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "geojson",
                                    "description": "Source type"
                                  },
                                  "url": {
                                    "type": "string",
                                    "pattern": "^(?:[a-zA-Z][a-zA-Z\\d+\\-.]*:|\\/|\\.\\.?\\/)",
                                    "description": "URL to fetch GeoJSON data"
                                  },
                                  "data": {
                                    "description": "Inline GeoJSON object"
                                  },
                                  "prefetchedData": {
                                    "description": "Pre-fetched data from build time"
                                  },
                                  "fetchStrategy": {
                                    "type": "string",
                                    "enum": [
                                      "runtime",
                                      "build",
                                      "hybrid"
                                    ],
                                    "default": "runtime",
                                    "description": "When to fetch data: runtime (default), build, or hybrid"
                                  },
                                  "stream": {
                                    "type": "object",
                                    "properties": {
                                      "type": {
                                        "type": "string",
                                        "enum": [
                                          "websocket",
                                          "sse"
                                        ],
                                        "description": "Streaming connection type"
                                      },
                                      "url": {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/0/properties/url",
                                        "description": "WebSocket or SSE endpoint URL"
                                      },
                                      "reconnect": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "Automatically reconnect on disconnect"
                                      },
                                      "reconnectMaxAttempts": {
                                        "type": "number",
                                        "minimum": 0,
                                        "default": 10,
                                        "description": "Maximum number of reconnection attempts"
                                      },
                                      "reconnectDelay": {
                                        "type": "number",
                                        "minimum": 100,
                                        "default": 1000,
                                        "description": "Initial delay in milliseconds before reconnecting"
                                      },
                                      "reconnectMaxDelay": {
                                        "type": "number",
                                        "minimum": 1000,
                                        "default": 30000,
                                        "description": "Maximum delay in milliseconds for exponential backoff"
                                      },
                                      "eventTypes": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        },
                                        "description": "Event types to listen for (SSE only)"
                                      },
                                      "protocols": {
                                        "anyOf": [
                                          {
                                            "type": "string"
                                          },
                                          {
                                            "type": "array",
                                            "items": {
                                              "type": "string"
                                            }
                                          }
                                        ],
                                        "description": "WebSocket sub-protocols (WebSocket only)"
                                      }
                                    },
                                    "required": [
                                      "type"
                                    ],
                                    "additionalProperties": false,
                                    "description": "WebSocket/SSE streaming configuration",
                                    "patternProperties": {
                                      "^x-": {}
                                    }
                                  },
                                  "refresh": {
                                    "type": "object",
                                    "properties": {
                                      "refreshInterval": {
                                        "type": "number",
                                        "minimum": 1000,
                                        "description": "Polling interval in milliseconds (minimum 1000ms)"
                                      },
                                      "updateStrategy": {
                                        "type": "string",
                                        "enum": [
                                          "replace",
                                          "merge",
                                          "append-window"
                                        ],
                                        "default": "replace",
                                        "description": "How to merge incoming data with existing data"
                                      },
                                      "updateKey": {
                                        "type": "string",
                                        "description": "Property key for merge strategy (required for merge)"
                                      },
                                      "windowSize": {
                                        "type": "number",
                                        "exclusiveMinimum": 0,
                                        "description": "Maximum features to keep (append-window)"
                                      },
                                      "windowDuration": {
                                        "type": "number",
                                        "exclusiveMinimum": 0,
                                        "description": "Maximum age in milliseconds (append-window)"
                                      },
                                      "timestampField": {
                                        "type": "string",
                                        "description": "Property field containing timestamp (append-window)"
                                      }
                                    },
                                    "additionalProperties": false,
                                    "description": "Polling refresh configuration",
                                    "patternProperties": {
                                      "^x-": {}
                                    }
                                  },
                                  "refreshInterval": {
                                    "type": "number",
                                    "minimum": 1000,
                                    "description": "Polling interval in milliseconds (legacy, use refresh.refreshInterval)",
                                    "deprecated": true
                                  },
                                  "updateStrategy": {
                                    "type": "string",
                                    "enum": [
                                      "replace",
                                      "merge",
                                      "append-window"
                                    ],
                                    "description": "Update strategy (legacy, use refresh.updateStrategy)",
                                    "deprecated": true
                                  },
                                  "updateKey": {
                                    "type": "string",
                                    "description": "Update key (legacy, use refresh.updateKey)",
                                    "deprecated": true
                                  },
                                  "loading": {
                                    "type": "object",
                                    "properties": {
                                      "enabled": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Enable loading UI overlays"
                                      },
                                      "message": {
                                        "type": "string",
                                        "description": "Custom loading message to display"
                                      },
                                      "showErrorOverlay": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "Show error overlay on fetch failure"
                                      }
                                    },
                                    "additionalProperties": false,
                                    "description": "Loading UI configuration",
                                    "patternProperties": {
                                      "^x-": {}
                                    }
                                  },
                                  "cache": {
                                    "type": "object",
                                    "properties": {
                                      "enabled": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "Enable HTTP caching"
                                      },
                                      "ttl": {
                                        "type": "number",
                                        "exclusiveMinimum": 0,
                                        "description": "Cache TTL in milliseconds (overrides default)"
                                      }
                                    },
                                    "additionalProperties": false,
                                    "description": "Cache configuration",
                                    "patternProperties": {
                                      "^x-": {}
                                    }
                                  },
                                  "cluster": {
                                    "type": "boolean",
                                    "description": "Enable point clustering"
                                  },
                                  "clusterRadius": {
                                    "type": "integer",
                                    "minimum": 0,
                                    "description": "Cluster radius in pixels (default: 50)"
                                  },
                                  "clusterMaxZoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Maximum zoom level to cluster points"
                                  },
                                  "clusterMinPoints": {
                                    "type": "integer",
                                    "minimum": 2,
                                    "description": "Minimum points to form a cluster"
                                  },
                                  "clusterProperties": {
                                    "type": "object",
                                    "additionalProperties": {},
                                    "description": "Aggregate cluster properties"
                                  },
                                  "tolerance": {
                                    "type": "number",
                                    "description": "Douglas-Peucker simplification tolerance (higher = simpler geometry)"
                                  },
                                  "buffer": {
                                    "type": "number",
                                    "description": "Tile buffer size on each side, in pixels at tile scale"
                                  },
                                  "lineMetrics": {
                                    "type": "boolean",
                                    "description": "Calculate line distance metrics (required for `line-gradient`)"
                                  },
                                  "generateId": {
                                    "type": "boolean",
                                    "description": "Assign feature ids from each feature's index (enables feature-state)"
                                  },
                                  "promoteId": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "object",
                                        "additionalProperties": {
                                          "type": "string"
                                        }
                                      }
                                    ],
                                    "description": "Feature property to use as the feature id (for feature-state), or a map of source-layer name to property name"
                                  },
                                  "attribution": {
                                    "type": "string",
                                    "description": "Attribution text"
                                  }
                                },
                                "required": [
                                  "type"
                                ],
                                "additionalProperties": true
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "vector",
                                    "description": "Source type"
                                  },
                                  "url": {
                                    "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/0/properties/url",
                                    "description": "TileJSON URL"
                                  },
                                  "tiles": {
                                    "type": "array",
                                    "items": {
                                      "type": "string",
                                      "description": "Tile URL template"
                                    },
                                    "description": "Tile URL template array"
                                  },
                                  "minzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Minimum zoom level"
                                  },
                                  "maxzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Maximum zoom level"
                                  },
                                  "bounds": {
                                    "type": "array",
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "items": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      }
                                    ],
                                    "description": "Bounding box [west, south, east, north]"
                                  },
                                  "scheme": {
                                    "type": "string",
                                    "enum": [
                                      "xyz",
                                      "tms"
                                    ],
                                    "description": "Tile coordinate scheme"
                                  },
                                  "attribution": {
                                    "type": "string",
                                    "description": "Attribution text"
                                  },
                                  "promoteId": {
                                    "anyOf": [
                                      {
                                        "type": "string"
                                      },
                                      {
                                        "type": "object",
                                        "additionalProperties": {
                                          "type": "string"
                                        }
                                      }
                                    ],
                                    "description": "Feature property to use as the feature id (for feature-state), or a map of source-layer name to property name"
                                  },
                                  "volatile": {
                                    "type": "boolean",
                                    "description": "Skip the tile cache (MapLibre `volatile`); for frequently changing tiles"
                                  }
                                },
                                "required": [
                                  "type"
                                ],
                                "additionalProperties": true
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "raster",
                                    "description": "Source type"
                                  },
                                  "url": {
                                    "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/0/properties/url",
                                    "description": "TileJSON URL"
                                  },
                                  "tiles": {
                                    "type": "array",
                                    "items": {
                                      "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/1/properties/tiles/items"
                                    },
                                    "description": "Tile URL template array"
                                  },
                                  "tileSize": {
                                    "type": "integer",
                                    "minimum": 1,
                                    "default": 512,
                                    "description": "Tile size in pixels"
                                  },
                                  "minzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Minimum zoom level"
                                  },
                                  "maxzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Maximum zoom level"
                                  },
                                  "bounds": {
                                    "type": "array",
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "items": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      }
                                    ],
                                    "description": "Bounding box [west, south, east, north]"
                                  },
                                  "scheme": {
                                    "type": "string",
                                    "enum": [
                                      "xyz",
                                      "tms"
                                    ],
                                    "description": "Tile coordinate scheme"
                                  },
                                  "attribution": {
                                    "type": "string",
                                    "description": "Attribution text"
                                  },
                                  "volatile": {
                                    "type": "boolean",
                                    "description": "Skip the tile cache (MapLibre `volatile`); for frequently changing tiles"
                                  }
                                },
                                "required": [
                                  "type"
                                ],
                                "additionalProperties": true
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "raster-dem",
                                    "description": "Source type"
                                  },
                                  "url": {
                                    "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/0/properties/url",
                                    "description": "TileJSON URL"
                                  },
                                  "tiles": {
                                    "type": "array",
                                    "items": {
                                      "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/1/properties/tiles/items"
                                    },
                                    "description": "Tile URL template array"
                                  },
                                  "tileSize": {
                                    "type": "integer",
                                    "minimum": 1,
                                    "default": 512,
                                    "description": "Tile size in pixels"
                                  },
                                  "encoding": {
                                    "type": "string",
                                    "enum": [
                                      "terrarium",
                                      "mapbox",
                                      "custom"
                                    ],
                                    "default": "mapbox",
                                    "description": "How elevation is encoded in the tile's RGB channels"
                                  },
                                  "minzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Minimum zoom level"
                                  },
                                  "maxzoom": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 24,
                                    "description": "Maximum zoom level"
                                  },
                                  "bounds": {
                                    "type": "array",
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "items": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      }
                                    ],
                                    "description": "Bounding box [west, south, east, north]"
                                  },
                                  "attribution": {
                                    "type": "string",
                                    "description": "Attribution text"
                                  },
                                  "volatile": {
                                    "type": "boolean",
                                    "description": "Skip the tile cache (MapLibre `volatile`); for frequently changing tiles"
                                  }
                                },
                                "required": [
                                  "type"
                                ],
                                "additionalProperties": true
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "image",
                                    "description": "Source type"
                                  },
                                  "url": {
                                    "type": "string",
                                    "pattern": "^(?:[a-zA-Z][a-zA-Z\\d+\\-.]*:|\\/|\\.\\.?\\/)",
                                    "description": "Image URL"
                                  },
                                  "coordinates": {
                                    "type": "array",
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "items": [
                                      {
                                        "type": "array",
                                        "minItems": 2,
                                        "maxItems": 2,
                                        "items": [
                                          {
                                            "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/0"
                                          },
                                          {
                                            "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/1"
                                          }
                                        ],
                                        "description": "Geographic coordinates as [longitude, latitude]"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      }
                                    ],
                                    "description": "Four corner coordinates [topLeft, topRight, bottomRight, bottomLeft]"
                                  }
                                },
                                "required": [
                                  "type",
                                  "url",
                                  "coordinates"
                                ],
                                "additionalProperties": true
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "const": "video",
                                    "description": "Source type"
                                  },
                                  "urls": {
                                    "type": "array",
                                    "items": {
                                      "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/0/properties/url"
                                    },
                                    "minItems": 1,
                                    "description": "Array of video URLs for browser compatibility"
                                  },
                                  "coordinates": {
                                    "type": "array",
                                    "minItems": 4,
                                    "maxItems": 4,
                                    "items": [
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      },
                                      {
                                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source/anyOf/0/anyOf/4/properties/coordinates/items/0"
                                      }
                                    ],
                                    "description": "Four corner coordinates [topLeft, topRight, bottomRight, bottomLeft]"
                                  }
                                },
                                "required": [
                                  "type",
                                  "urls",
                                  "coordinates"
                                ],
                                "additionalProperties": true
                              }
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "$ref": {
                                "type": "string",
                                "description": "Reference to a root-level source (e.g., \"#/sources/name\")"
                              }
                            },
                            "required": [
                              "$ref"
                            ],
                            "additionalProperties": false,
                            "description": "Source reference",
                            "patternProperties": {
                              "^x-": {}
                            }
                          },
                          {
                            "type": "string"
                          }
                        ],
                        "description": "Layer source: inline definition, { $ref: '#/sources/name' } reference, or named-source string"
                      },
                      "source-layer": {
                        "type": "string",
                        "description": "Source layer name (for vector sources)"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
                        "description": "Minimum zoom level to show layer"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
                        "description": "Maximum zoom level to show layer"
                      },
                      "filter": {
                        "type": "array",
                        "description": "MapLibre filter expression"
                      },
                      "visible": {
                        "type": "boolean",
                        "default": true,
                        "description": "Initial visibility state"
                      },
                      "toggleable": {
                        "type": "boolean",
                        "default": true,
                        "description": "Allow users to toggle visibility"
                      },
                      "before": {
                        "type": "string",
                        "description": "Layer ID to insert this layer before"
                      },
                      "interactive": {
                        "type": "object",
                        "properties": {
                          "hover": {
                            "type": "object",
                            "properties": {
                              "cursor": {
                                "type": "string",
                                "description": "CSS cursor style (e.g., \"pointer\")"
                              },
                              "highlight": {
                                "type": "boolean",
                                "description": "Highlight feature on hover"
                              },
                              "emit": {
                                "type": "object",
                                "properties": {
                                  "event": {
                                    "type": "string",
                                    "description": "Named event dispatched to the host handler map"
                                  },
                                  "payload": {
                                    "type": "object",
                                    "additionalProperties": {
                                      "type": "object",
                                      "properties": {
                                        "property": {
                                          "type": "string",
                                          "description": "Feature property name to project"
                                        },
                                        "else": {
                                          "type": "string",
                                          "description": "Fallback value when the property is missing"
                                        },
                                        "str": {
                                          "type": "string",
                                          "description": "Static literal value"
                                        }
                                      },
                                      "additionalProperties": false,
                                      "description": "Declarative payload projection item",
                                      "patternProperties": {
                                        "^x-": {}
                                      }
                                    },
                                    "description": "Declarative payload: named keys projected from feature properties"
                                  }
                                },
                                "required": [
                                  "event"
                                ],
                                "additionalProperties": false,
                                "description": "Dispatch a named host event with a declarative payload once per feature entered on hover (per-feature dedupe, not per mousemove)",
                                "patternProperties": {
                                  "^x-": {}
                                }
                              },
                              "popup": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "str": {
                                          "anyOf": [
                                            {
                                              "type": "string"
                                            },
                                            {
                                              "type": "object",
                                              "properties": {
                                                "$html": {
                                                  "type": "string"
                                                }
                                              },
                                              "required": [
                                                "$html"
                                              ],
                                              "additionalProperties": true
                                            }
                                          ],
                                          "description": "Static text; an `!html`-tagged value carries raw markup"
                                        },
                                        "property": {
                                          "type": "string",
                                          "description": "Feature property name"
                                        },
                                        "else": {
                                          "type": "string",
                                          "description": "Fallback value if property missing"
                                        },
                                        "format": {
                                          "type": "string",
                                          "description": "Number format string (e.g., \",.0f\")"
                                        },
                                        "href": {
                                          "type": "string",
                                          "format": "uri",
                                          "description": "Link URL"
                                        },
                                        "text": {
                                          "type": "string",
                                          "description": "Link text"
                                        },
                                        "src": {
                                          "type": "string",
                                          "format": "uri",
                                          "description": "Image/iframe source"
                                        },
                                        "alt": {
                                          "type": "string",
                                          "description": "Image alt text"
                                        }
                                      },
                                      "additionalProperties": true,
                                      "description": "Popup content item with static or dynamic values"
                                    }
                                  }
                                },
                                "description": "Popup shown while hovering a feature (no close button; dismissed on leave). A pinned click popup suppresses hover popups until it is dismissed. Touch has no hover: tap uses `click.popup`."
                              }
                            },
                            "additionalProperties": false,
                            "description": "Hover behavior",
                            "patternProperties": {
                              "^x-": {}
                            }
                          },
                          "click": {
                            "type": "object",
                            "properties": {
                              "popup": {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive/properties/hover/properties/popup",
                                "description": "Popup content to display"
                              },
                              "action": {
                                "type": "string",
                                "description": "Custom action name to trigger",
                                "deprecated": true
                              },
                              "flyTo": {
                                "type": "object",
                                "properties": {
                                  "center": {
                                    "type": "array",
                                    "minItems": 2,
                                    "maxItems": 2,
                                    "items": [
                                      {
                                        "type": "number"
                                      },
                                      {
                                        "type": "number"
                                      }
                                    ],
                                    "description": "Target center [longitude, latitude]; defaults to the clicked point"
                                  },
                                  "zoom": {
                                    "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
                                    "description": "Target zoom level; MapLibre keeps the current zoom when unset"
                                  },
                                  "duration": {
                                    "type": "number",
                                    "description": "Animation duration in milliseconds; MapLibre's default when unset"
                                  }
                                },
                                "additionalProperties": false,
                                "description": "Fly to location on click",
                                "patternProperties": {
                                  "^x-": {}
                                }
                              },
                              "zoomToFeature": {
                                "type": "object",
                                "properties": {
                                  "padding": {
                                    "type": "number",
                                    "description": "Padding in pixels around the fitted bounds"
                                  },
                                  "maxZoom": {
                                    "$ref": "#/$defs/scrollytelling/properties/config/properties/fitTo/properties/maxZoom",
                                    "description": "Maximum zoom level when fitting the feature's bounds"
                                  },
                                  "duration": {
                                    "type": "number",
                                    "description": "Animation duration in milliseconds"
                                  }
                                },
                                "additionalProperties": false,
                                "description": "Fit the camera to the clicked feature's own bounds on click",
                                "patternProperties": {
                                  "^x-": {}
                                }
                              },
                              "emit": {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive/properties/hover/properties/emit",
                                "description": "Dispatch a named host event with a declarative payload on click"
                              }
                            },
                            "additionalProperties": false,
                            "description": "Click behavior",
                            "patternProperties": {
                              "^x-": {}
                            }
                          },
                          "mouseenter": {
                            "type": "object",
                            "properties": {
                              "action": {
                                "type": "string",
                                "description": "Custom action on mouse enter",
                                "deprecated": true
                              }
                            },
                            "additionalProperties": false,
                            "description": "Legacy mouse-enter trigger. Its only key, `action`, is deprecated and never dispatched; use `hover` or listen for `ml-map:layer-hover`",
                            "patternProperties": {
                              "^x-": {}
                            }
                          },
                          "mouseleave": {
                            "type": "object",
                            "properties": {
                              "action": {
                                "type": "string",
                                "description": "Custom action on mouse leave",
                                "deprecated": true
                              }
                            },
                            "additionalProperties": false,
                            "description": "Legacy mouse-leave trigger. Its only key, `action`, is deprecated and never dispatched; use `hover` or listen for `ml-map:layer-hover`",
                            "patternProperties": {
                              "^x-": {}
                            }
                          }
                        },
                        "additionalProperties": false,
                        "description": "Interactive event configuration",
                        "patternProperties": {
                          "^x-": {}
                        }
                      },
                      "legend": {
                        "type": "object",
                        "properties": {
                          "color": {
                            "type": "string",
                            "description": "CSS color value"
                          },
                          "label": {
                            "type": "string",
                            "description": "Legend label text"
                          },
                          "shape": {
                            "type": "string",
                            "enum": [
                              "circle",
                              "square",
                              "line",
                              "icon"
                            ],
                            "default": "square",
                            "description": "Symbol shape"
                          },
                          "icon": {
                            "type": "string",
                            "description": "Icon name or URL (for shape: icon)"
                          }
                        },
                        "required": [
                          "color",
                          "label"
                        ],
                        "additionalProperties": false,
                        "description": "Legend configuration",
                        "patternProperties": {
                          "^x-": {}
                        }
                      },
                      "effect": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "minLength": 1,
                            "description": "A registered effect type, e.g. tonal-hatch or blueprint"
                          }
                        },
                        "required": [
                          "type"
                        ],
                        "additionalProperties": true,
                        "description": "Experimental: a registered shader effect (`type` + flat params) that enhances this layer; the layer itself is the static fallback"
                      },
                      "metadata": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Custom metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "circle",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "circle-radius": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ],
                            "description": "Number value or MapLibre expression"
                          },
                          "circle-color": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "CSS color value"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ],
                            "description": "Color value or MapLibre expression"
                          },
                          "circle-blur": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "circle-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "circle-stroke-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "circle-stroke-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "circle-stroke-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "circle-pitch-scale": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "circle-pitch-alignment": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "circle-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "circle-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          }
                        },
                        "additionalProperties": true,
                        "description": "Circle paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Circle layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "line",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "line-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "line-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "line-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "line-gap-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "line-offset": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "line-blur": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "line-dasharray": {
                            "type": "array",
                            "items": {
                              "type": "number"
                            }
                          },
                          "line-pattern": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          },
                          "line-gradient": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "line-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "line-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          }
                        },
                        "additionalProperties": true,
                        "description": "Line paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {
                          "line-cap": {
                            "type": "string",
                            "enum": [
                              "butt",
                              "round",
                              "square"
                            ]
                          },
                          "line-join": {
                            "type": "string",
                            "enum": [
                              "bevel",
                              "round",
                              "miter"
                            ]
                          },
                          "line-miter-limit": {
                            "type": "number"
                          },
                          "line-round-limit": {
                            "type": "number"
                          },
                          "line-sort-key": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Line layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "fill",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "fill-antialias": {
                            "type": "boolean"
                          },
                          "fill-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "fill-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "fill-outline-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "fill-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "fill-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "fill-pattern": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          }
                        },
                        "additionalProperties": true,
                        "description": "Fill paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {
                          "fill-sort-key": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Fill layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "symbol",
                        "description": "Layer type"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {
                          "symbol-placement": {
                            "type": "string",
                            "enum": [
                              "point",
                              "line",
                              "line-center"
                            ]
                          },
                          "symbol-spacing": {
                            "type": "number"
                          },
                          "symbol-avoid-edges": {
                            "type": "boolean"
                          },
                          "symbol-sort-key": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "symbol-z-order": {
                            "type": "string",
                            "enum": [
                              "auto",
                              "viewport-y",
                              "source"
                            ]
                          },
                          "icon-allow-overlap": {
                            "type": "boolean"
                          },
                          "icon-ignore-placement": {
                            "type": "boolean"
                          },
                          "icon-optional": {
                            "type": "boolean"
                          },
                          "icon-rotation-alignment": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport",
                              "auto"
                            ]
                          },
                          "icon-size": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "icon-text-fit": {
                            "type": "string",
                            "enum": [
                              "none",
                              "width",
                              "height",
                              "both"
                            ]
                          },
                          "icon-text-fit-padding": {
                            "type": "array",
                            "minItems": 4,
                            "maxItems": 4,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "icon-image": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          },
                          "icon-rotate": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "icon-padding": {
                            "type": "number"
                          },
                          "icon-keep-upright": {
                            "type": "boolean"
                          },
                          "icon-offset": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "icon-anchor": {
                            "type": "string",
                            "enum": [
                              "center",
                              "left",
                              "right",
                              "top",
                              "bottom",
                              "top-left",
                              "top-right",
                              "bottom-left",
                              "bottom-right"
                            ]
                          },
                          "icon-pitch-alignment": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport",
                              "auto"
                            ]
                          },
                          "text-pitch-alignment": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport",
                              "auto"
                            ]
                          },
                          "text-rotation-alignment": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport",
                              "auto"
                            ]
                          },
                          "text-field": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          },
                          "text-font": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "text-size": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-max-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-line-height": {
                            "type": "number"
                          },
                          "text-letter-spacing": {
                            "type": "number"
                          },
                          "text-justify": {
                            "type": "string",
                            "enum": [
                              "auto",
                              "left",
                              "center",
                              "right"
                            ]
                          },
                          "text-radial-offset": {
                            "type": "number"
                          },
                          "text-variable-anchor": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "center",
                                "left",
                                "right",
                                "top",
                                "bottom",
                                "top-left",
                                "top-right",
                                "bottom-left",
                                "bottom-right"
                              ]
                            }
                          },
                          "text-anchor": {
                            "type": "string",
                            "enum": [
                              "center",
                              "left",
                              "right",
                              "top",
                              "bottom",
                              "top-left",
                              "top-right",
                              "bottom-left",
                              "bottom-right"
                            ]
                          },
                          "text-max-angle": {
                            "type": "number"
                          },
                          "text-rotate": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-padding": {
                            "type": "number"
                          },
                          "text-keep-upright": {
                            "type": "boolean"
                          },
                          "text-transform": {
                            "type": "string",
                            "enum": [
                              "none",
                              "uppercase",
                              "lowercase"
                            ]
                          },
                          "text-offset": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "text-allow-overlap": {
                            "type": "boolean"
                          },
                          "text-ignore-placement": {
                            "type": "boolean"
                          },
                          "text-optional": {
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Symbol layout properties"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "icon-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "icon-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "icon-halo-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "icon-halo-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "icon-halo-blur": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "icon-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "icon-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "text-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "text-halo-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "text-halo-width": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-halo-blur": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "text-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "text-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          }
                        },
                        "additionalProperties": true,
                        "description": "Symbol paint properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "raster",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "raster-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-hue-rotate": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-brightness-min": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-brightness-max": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-saturation": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-contrast": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "raster-resampling": {
                            "type": "string",
                            "enum": [
                              "linear",
                              "nearest"
                            ]
                          },
                          "raster-fade-duration": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Raster paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Raster layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "fill-extrusion",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "fill-extrusion-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "fill-extrusion-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "fill-extrusion-translate": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "number"
                              }
                            ]
                          },
                          "fill-extrusion-translate-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "fill-extrusion-pattern": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          },
                          "fill-extrusion-height": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "fill-extrusion-base": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "fill-extrusion-vertical-gradient": {
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Fill extrusion paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Fill extrusion layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "heatmap",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "heatmap-radius": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "heatmap-weight": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "heatmap-intensity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "heatmap-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "heatmap-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Heatmap paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Heatmap layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "hillshade",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "hillshade-illumination-direction": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "array",
                                "items": {
                                  "type": "number"
                                },
                                "minItems": 1
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ],
                            "description": "A number, one number per light (multidirectional), or an expression"
                          },
                          "hillshade-illumination-altitude": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/7/properties/paint/properties/hillshade-illumination-direction",
                            "description": "A number, one number per light (multidirectional), or an expression"
                          },
                          "hillshade-illumination-anchor": {
                            "type": "string",
                            "enum": [
                              "map",
                              "viewport"
                            ]
                          },
                          "hillshade-method": {
                            "type": "string",
                            "enum": [
                              "standard",
                              "basic",
                              "combined",
                              "igor",
                              "multidirectional"
                            ]
                          },
                          "hillshade-exaggeration": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          },
                          "hillshade-shadow-color": {
                            "anyOf": [
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color/anyOf/0"
                              },
                              {
                                "type": "array",
                                "items": {
                                  "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color/anyOf/0"
                                },
                                "minItems": 1
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ],
                            "description": "A color, one color per light (multidirectional), or an expression"
                          },
                          "hillshade-highlight-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/7/properties/paint/properties/hillshade-shadow-color",
                            "description": "A color, one color per light (multidirectional), or an expression"
                          },
                          "hillshade-accent-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Hillshade paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Hillshade layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/id"
                      },
                      "label": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/label"
                      },
                      "source": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source"
                      },
                      "source-layer": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/source-layer"
                      },
                      "minzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/minzoom"
                      },
                      "maxzoom": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/maxzoom"
                      },
                      "filter": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                      },
                      "visible": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/visible"
                      },
                      "toggleable": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/toggleable"
                      },
                      "before": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/before"
                      },
                      "interactive": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/interactive"
                      },
                      "legend": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/legend"
                      },
                      "effect": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/effect"
                      },
                      "metadata": {
                        "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/metadata"
                      },
                      "type": {
                        "type": "string",
                        "const": "color-relief",
                        "description": "Layer type (maplibre-gl >= 5.6)"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "color-relief-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color ramp over [\"elevation\"] — an interpolate/step expression"
                          },
                          "color-relief-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Layer opacity (0-1)"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Color-relief paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Color-relief layout properties"
                      }
                    },
                    "required": [
                      "id",
                      "source",
                      "type"
                    ],
                    "additionalProperties": true
                  },
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Unique layer identifier"
                      },
                      "type": {
                        "type": "string",
                        "const": "background",
                        "description": "Layer type"
                      },
                      "paint": {
                        "type": "object",
                        "properties": {
                          "background-color": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-color",
                            "description": "Color value or MapLibre expression"
                          },
                          "background-pattern": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                              }
                            ]
                          },
                          "background-opacity": {
                            "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/paint/properties/circle-radius",
                            "description": "Number value or MapLibre expression"
                          }
                        },
                        "additionalProperties": true,
                        "description": "Background paint properties"
                      },
                      "layout": {
                        "type": "object",
                        "properties": {},
                        "additionalProperties": true,
                        "description": "Background layout properties"
                      },
                      "metadata": {
                        "type": "object",
                        "additionalProperties": {},
                        "description": "Custom metadata"
                      }
                    },
                    "required": [
                      "id",
                      "type"
                    ],
                    "additionalProperties": true
                  }
                ]
              },
              {
                "type": "object",
                "properties": {
                  "$ref": {
                    "type": "string",
                    "description": "Reference to global layer (e.g., \"#/layers/bikeLayer\")"
                  }
                },
                "required": [
                  "$ref"
                ],
                "additionalProperties": false,
                "description": "Layer reference",
                "patternProperties": {
                  "^x-": {}
                }
              }
            ]
          },
          "default": [],
          "description": "Persistent layers (visible throughout story)"
        },
        "chapters": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "Unique chapter identifier"
              },
              "title": {
                "type": "string",
                "description": "Chapter title"
              },
              "center": {
                "type": "array",
                "minItems": 2,
                "maxItems": 2,
                "items": [
                  {
                    "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/0"
                  },
                  {
                    "$ref": "#/$defs/scrollytelling/properties/config/properties/center/items/1"
                  }
                ],
                "description": "Map center [longitude, latitude]"
              },
              "zoom": {
                "type": "number",
                "description": "Zoom level"
              },
              "description": {
                "type": "string",
                "description": "Chapter description (HTML/markdown supported)"
              },
              "image": {
                "type": "string",
                "format": "uri",
                "description": "Hero image URL"
              },
              "video": {
                "type": "string",
                "format": "uri",
                "description": "Video URL"
              },
              "pitch": {
                "type": "number",
                "minimum": 0,
                "maximum": 85,
                "default": 0,
                "description": "Camera pitch angle (0-85)"
              },
              "bearing": {
                "type": "number",
                "minimum": -180,
                "maximum": 180,
                "default": 0,
                "description": "Camera bearing (-180 to 180)"
              },
              "speed": {
                "type": "number",
                "minimum": 0,
                "maximum": 2,
                "default": 0.6,
                "description": "Animation speed multiplier (0-2)"
              },
              "curve": {
                "type": "number",
                "minimum": 0,
                "maximum": 2,
                "default": 1,
                "description": "Animation curve (0=linear, 1=default, 2=steep)"
              },
              "animation": {
                "type": "string",
                "enum": [
                  "flyTo",
                  "easeTo",
                  "jumpTo"
                ],
                "default": "flyTo",
                "description": "Animation type"
              },
              "rotateAnimation": {
                "type": "boolean",
                "description": "Enable continuous rotation animation"
              },
              "spinGlobe": {
                "type": "boolean",
                "description": "Not implemented (warns, no effect). Globe projection itself is the map-level `projection: { type: globe }`"
              },
              "alignment": {
                "type": "string",
                "enum": [
                  "left",
                  "right",
                  "center",
                  "full"
                ],
                "default": "center",
                "description": "Content alignment"
              },
              "hidden": {
                "type": "boolean",
                "default": false,
                "description": "Hide chapter content (map-only)"
              },
              "layers": {
                "type": "object",
                "properties": {
                  "show": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Layer IDs to show"
                  },
                  "hide": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Layer IDs to hide"
                  }
                },
                "additionalProperties": false,
                "description": "Layer visibility control",
                "patternProperties": {
                  "^x-": {}
                }
              },
              "onChapterEnter": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "action": {
                      "type": "string",
                      "enum": [
                        "setFilter",
                        "setPaintProperty",
                        "setLayoutProperty",
                        "flyTo",
                        "easeTo",
                        "fitBounds",
                        "custom"
                      ],
                      "description": "Action type"
                    },
                    "layer": {
                      "type": "string",
                      "description": "Target layer ID"
                    },
                    "property": {
                      "type": "string",
                      "description": "Property name (for setPaintProperty/setLayoutProperty)"
                    },
                    "value": {
                      "description": "Property value"
                    },
                    "filter": {
                      "anyOf": [
                        {
                          "$ref": "#/$defs/scrollytelling/properties/layers/items/anyOf/0/anyOf/0/properties/filter"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Filter expression (for setFilter, null to clear)"
                    },
                    "bounds": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      },
                      "description": "Bounds array (for fitBounds)"
                    },
                    "options": {
                      "type": "object",
                      "additionalProperties": {},
                      "description": "Additional options"
                    }
                  },
                  "required": [
                    "action"
                  ],
                  "additionalProperties": false,
                  "description": "Chapter action for map state changes",
                  "patternProperties": {
                    "^x-": {}
                  }
                },
                "default": [],
                "description": "Actions when entering chapter"
              },
              "onChapterExit": {
                "type": "array",
                "items": {
                  "$ref": "#/$defs/scrollytelling/properties/chapters/items/properties/onChapterEnter/items"
                },
                "default": [],
                "description": "Actions when exiting chapter"
              },
              "callback": {
                "type": "string",
                "description": "Custom callback function name"
              }
            },
            "required": [
              "id",
              "title",
              "center",
              "zoom"
            ],
            "additionalProperties": false,
            "description": "Scrollytelling chapter",
            "patternProperties": {
              "^x-": {}
            }
          },
          "minItems": 1,
          "description": "Story chapters"
        },
        "footer": {
          "type": "string",
          "description": "Footer content (HTML)"
        }
      },
      "required": [
        "type",
        "id",
        "config",
        "chapters"
      ],
      "additionalProperties": false,
      "description": "Scrollytelling block for narrative map stories",
      "patternProperties": {
        "^x-": {}
      }
    }
  }
}
