{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://decks.hedyassist.com/schemas/hedydeck-v2.schema.json",
  "title": "Hedy Deck 2.0 source document",
  "description": "Monolithic editable source. Cross-reference checks, uniqueness, parent bounds, component cycles, asset verification, resource budgets, and visual layout additionally require Hedy validation. ZIP deck.json uses the package envelope documented in /docs/hedydeck-v2.md.",
  "type": "object",
  "properties": {
    "format": {
      "const": "hedydeck"
    },
    "version": {
      "const": "2.0"
    },
    "id": {
      "$ref": "#/$defs/id"
    },
    "revision": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "title": {
      "type": "string",
      "maxLength": 500,
      "minLength": 1,
      "pattern": "\\S"
    },
    "language": {
      "type": "string",
      "maxLength": 35,
      "minLength": 1,
      "pattern": "\\S"
    },
    "stage": {
      "type": "object",
      "properties": {
        "width": {
          "const": 1920
        },
        "height": {
          "const": 1080
        }
      },
      "required": [
        "width",
        "height"
      ],
      "additionalProperties": false
    },
    "theme": {
      "$ref": "#/$defs/theme"
    },
    "slides": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/slide"
      },
      "minItems": 1,
      "maxItems": 500
    },
    "components": {
      "type": "object",
      "propertyNames": {
        "$ref": "#/$defs/id"
      },
      "additionalProperties": {
        "type": "array",
        "items": {
          "$ref": "#/$defs/node"
        }
      }
    },
    "data": {
      "type": "object",
      "propertyNames": {
        "$ref": "#/$defs/id"
      },
      "additionalProperties": {
        "$ref": "#/$defs/json"
      }
    },
    "assets": {
      "type": "object",
      "maxProperties": 1000,
      "propertyNames": {
        "$ref": "#/$defs/id"
      },
      "additionalProperties": {
        "$ref": "#/$defs/asset"
      }
    },
    "metadata": {
      "$ref": "#/$defs/metadata"
    },
    "requires": {
      "type": "array",
      "items": {
        "enum": [
          "core",
          "static",
          "text",
          "shapes",
          "images",
          "svg",
          "html",
          "charts",
          "tables",
          "data-bindings",
          "components",
          "reveal-steps",
          "fonts"
        ]
      }
    },
    "extensions": {
      "type": "object",
      "propertyNames": {
        "not": {
          "enum": [
            "__proto__",
            "prototype",
            "constructor"
          ]
        }
      },
      "additionalProperties": {
        "$ref": "#/$defs/json"
      }
    }
  },
  "required": [
    "format",
    "version",
    "id",
    "revision",
    "title",
    "language",
    "stage",
    "theme",
    "slides",
    "components",
    "data",
    "assets"
  ],
  "additionalProperties": false,
  "$defs": {
    "id": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,95}$",
      "not": {
        "enum": [
          "__proto__",
          "prototype",
          "constructor"
        ]
      }
    },
    "json": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "boolean"
        },
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/json"
          }
        },
        {
          "type": "object",
          "propertyNames": {
            "not": {
              "enum": [
                "__proto__",
                "prototype",
                "constructor"
              ]
            }
          },
          "additionalProperties": {
            "$ref": "#/$defs/json"
          }
        }
      ]
    },
    "theme": {
      "type": "object",
      "properties": {
        "background": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        },
        "foreground": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        },
        "accent": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        },
        "muted": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        },
        "fontFamily": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        },
        "headingFont": {
          "type": "string",
          "maxLength": 200,
          "minLength": 1,
          "pattern": "\\S"
        }
      },
      "required": [
        "background",
        "foreground",
        "accent",
        "muted",
        "fontFamily",
        "headingFont"
      ],
      "additionalProperties": false
    },
    "style": {
      "type": "object",
      "properties": {
        "color": {
          "type": "string",
          "maxLength": 200
        },
        "fill": {
          "type": "string",
          "maxLength": 200
        },
        "stroke": {
          "type": "string",
          "maxLength": 200
        },
        "fontFamily": {
          "type": "string",
          "maxLength": 200
        },
        "strokeWidth": {
          "type": "number",
          "minimum": 0
        },
        "radius": {
          "type": "number",
          "minimum": 0
        },
        "fontSize": {
          "type": "number",
          "minimum": 0
        },
        "fontWeight": {
          "type": "number",
          "minimum": 0
        },
        "lineHeight": {
          "type": "number",
          "minimum": 0
        },
        "padding": {
          "type": "number",
          "minimum": 0
        },
        "align": {
          "enum": [
            "left",
            "center",
            "right"
          ]
        },
        "opacity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "binding": {
      "type": "object",
      "properties": {
        "data": {
          "$ref": "#/$defs/id"
        },
        "path": {
          "type": "string",
          "pattern": "^(?:[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)*)?$",
          "not": {
            "pattern": "(?:^|\\.)(?:__proto__|prototype|constructor)(?:\\.|$)"
          }
        },
        "format": {
          "enum": [
            "text",
            "number",
            "percent",
            "currency"
          ]
        },
        "decimals": {
          "type": "integer",
          "minimum": 0,
          "maximum": 20
        },
        "currency": {
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        "prefix": {
          "type": "string",
          "maxLength": 100
        },
        "suffix": {
          "type": "string",
          "maxLength": 100
        }
      },
      "required": [
        "data",
        "path"
      ],
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "properties": {
              "format": {
                "const": "currency"
              }
            },
            "required": [
              "format"
            ]
          },
          "then": {
            "required": [
              "currency"
            ]
          }
        }
      ]
    },
    "series": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "maxLength": 100000,
          "minLength": 1,
          "pattern": "\\S"
        },
        "values": {
          "type": "array",
          "items": {
            "type": "number"
          },
          "maxItems": 200
        },
        "color": {
          "type": "string",
          "maxLength": 200
        }
      },
      "required": [
        "name",
        "values"
      ],
      "additionalProperties": false
    },
    "chart": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "bar",
            "line",
            "donut"
          ]
        },
        "labels": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 200
        },
        "series": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/series"
          },
          "maxItems": 12
        },
        "data": {
          "$ref": "#/$defs/id"
        },
        "labelKey": {
          "type": "string"
        },
        "valueKey": {
          "type": "string"
        }
      },
      "required": [
        "type",
        "labels",
        "series"
      ],
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "required": [
              "data"
            ]
          },
          "then": {
            "required": [
              "labelKey",
              "valueKey"
            ]
          },
          "else": {
            "properties": {
              "series": {
                "minItems": 1
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "donut"
              }
            }
          },
          "then": {
            "properties": {
              "series": {
                "maxItems": 1,
                "items": {
                  "properties": {
                    "values": {
                      "items": {
                        "minimum": 0
                      }
                    }
                  }
                }
              }
            }
          }
        }
      ]
    },
    "table": {
      "type": "object",
      "properties": {
        "columns": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1,
          "maxItems": 50
        },
        "rows": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/$defs/json"
            }
          },
          "maxItems": 1000
        },
        "data": {
          "$ref": "#/$defs/id"
        },
        "keys": {
          "type": "array",
          "items": {
            "type": "string",
            "not": {
              "enum": [
                "__proto__",
                "prototype",
                "constructor"
              ]
            }
          }
        }
      },
      "required": [
        "columns",
        "rows"
      ],
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "required": [
              "data"
            ]
          },
          "then": {
            "required": [
              "keys"
            ]
          }
        }
      ]
    },
    "node": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/id"
        },
        "type": {
          "enum": [
            "text",
            "image",
            "shape",
            "chart",
            "table",
            "svg",
            "html",
            "group",
            "component"
          ]
        },
        "x": {
          "type": "number",
          "minimum": 0
        },
        "y": {
          "type": "number",
          "minimum": 0
        },
        "w": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "h": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "name": {
          "type": "string",
          "maxLength": 100000
        },
        "role": {
          "enum": [
            "title",
            "body",
            "caption",
            "decoration"
          ]
        },
        "text": {
          "type": "string",
          "maxLength": 100000
        },
        "binding": {
          "$ref": "#/$defs/binding"
        },
        "style": {
          "$ref": "#/$defs/style"
        },
        "asset": {
          "$ref": "#/$defs/id"
        },
        "alt": {
          "type": "string",
          "maxLength": 100000
        },
        "fit": {
          "enum": [
            "contain",
            "cover"
          ]
        },
        "shape": {
          "enum": [
            "rect",
            "ellipse",
            "line"
          ]
        },
        "svg": {
          "type": "string",
          "maxLength": 1000000
        },
        "html": {
          "type": "string",
          "maxLength": 1000000
        },
        "css": {
          "type": "string",
          "maxLength": 1000000
        },
        "children": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/node"
          }
        },
        "component": {
          "$ref": "#/$defs/id"
        },
        "chart": {
          "$ref": "#/$defs/chart"
        },
        "table": {
          "$ref": "#/$defs/table"
        },
        "visibleIn": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/id"
          }
        }
      },
      "required": [
        "id",
        "type",
        "x",
        "y",
        "w",
        "h"
      ],
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "const": "image"
              }
            }
          },
          "then": {
            "required": [
              "asset"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "svg"
              }
            }
          },
          "then": {
            "required": [
              "svg"
            ],
            "properties": {
              "svg": {
                "minLength": 1
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "html"
              }
            }
          },
          "then": {
            "required": [
              "html"
            ],
            "properties": {
              "html": {
                "minLength": 1
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "group"
              }
            }
          },
          "then": {
            "required": [
              "children"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "component"
              }
            }
          },
          "then": {
            "required": [
              "component"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "chart"
              }
            }
          },
          "then": {
            "required": [
              "chart"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "table"
              }
            }
          },
          "then": {
            "required": [
              "table"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "text"
              }
            }
          },
          "then": {
            "anyOf": [
              {
                "required": [
                  "text"
                ]
              },
              {
                "required": [
                  "binding"
                ]
              }
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "not": {
                  "const": "group"
                }
              }
            }
          },
          "then": {
            "not": {
              "required": [
                "children"
              ]
            }
          }
        }
      ]
    },
    "step": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/id"
        },
        "title": {
          "type": "string",
          "maxLength": 500,
          "minLength": 1,
          "pattern": "\\S"
        },
        "notes": {
          "type": "string",
          "maxLength": 100000
        }
      },
      "required": [
        "id",
        "title"
      ],
      "additionalProperties": false
    },
    "slide": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/id"
        },
        "title": {
          "type": "string",
          "maxLength": 500,
          "minLength": 1,
          "pattern": "\\S"
        },
        "notes": {
          "type": "string",
          "maxLength": 100000
        },
        "purpose": {
          "type": "string",
          "maxLength": 100000
        },
        "background": {
          "type": "string",
          "maxLength": 200
        },
        "nodes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/node"
          }
        },
        "steps": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/step"
          },
          "minItems": 1,
          "maxItems": 100
        }
      },
      "required": [
        "id",
        "title",
        "nodes"
      ],
      "additionalProperties": false
    },
    "asset": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "pattern": "^assets/(?!.*(?:^|/)\\.{1,2}(?:/|$))[A-Za-z0-9][A-Za-z0-9_.-]*(?:/[A-Za-z0-9_.-]+)*$",
          "maxLength": 208
        },
        "mime": {
          "enum": [
            "image/png",
            "image/jpeg",
            "image/webp",
            "font/woff2"
          ]
        },
        "sha256": {
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        },
        "alt": {
          "type": "string",
          "maxLength": 2000
        }
      },
      "required": [
        "path",
        "mime",
        "sha256"
      ],
      "additionalProperties": false
    },
    "source": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/id"
        },
        "title": {
          "type": "string",
          "maxLength": 100000,
          "minLength": 1,
          "pattern": "\\S"
        },
        "url": {
          "type": "string",
          "pattern": "^https?://[^\\s]+$"
        }
      },
      "required": [
        "id",
        "title"
      ],
      "additionalProperties": false
    },
    "metadata": {
      "type": "object",
      "properties": {
        "author": {
          "type": "string",
          "maxLength": 5000
        },
        "description": {
          "type": "string",
          "maxLength": 5000
        },
        "audience": {
          "type": "string",
          "maxLength": 5000
        },
        "objective": {
          "type": "string",
          "maxLength": 5000
        },
        "sources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/source"
          },
          "maxItems": 1000
        }
      },
      "required": [],
      "additionalProperties": false
    }
  }
}
