{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://vivi.vora.im/downloads/character.schema.json",
  "title": "VORA VIVI Character Pack v1",
  "type": "object",
  "required": [
    "schemaVersion",
    "packId",
    "packVersion",
    "canvas",
    "clips",
    "eventBindings"
  ],
  "properties": {
    "schemaVersion": {
      "const": 1
    },
    "packId": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._-]+$"
    },
    "packVersion": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._-]+$"
    },
    "minAppVersion": {
      "type": "string"
    },
    "name": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "author": {
      "type": "string"
    },
    "license": {
      "type": "string"
    },
    "canvas": {
      "type": "object",
      "required": [
        "width",
        "height"
      ],
      "properties": {
        "width": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2048
        },
        "height": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2048
        }
      }
    },
    "defaultDisplayHeight": {
      "type": "integer",
      "minimum": 80,
      "maximum": 320
    },
    "anchor": {
      "type": "object",
      "required": [
        "x",
        "y"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "y": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      },
      "additionalProperties": false
    },
    "bubbleAnchor": {
      "type": "object",
      "required": [
        "x",
        "y"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "y": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      },
      "additionalProperties": false
    },
    "hitArea": {
      "type": "object",
      "required": [
        "x",
        "y",
        "width",
        "height"
      ],
      "properties": {
        "x": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "y": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "width": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "height": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      }
    },
    "clips": {
      "type": "object",
      "minProperties": 1,
      "maxProperties": 512,
      "additionalProperties": {
        "type": "object",
        "required": [
          "frameCount",
          "sequence",
          "entryPose",
          "exitPose"
        ],
        "properties": {
          "frameCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 240
          },
          "sequence": {
            "type": "string",
            "minLength": 1
          },
          "entryPose": {
            "type": "string"
          },
          "exitPose": {
            "type": "string"
          },
          "loop": {
            "type": "boolean"
          },
          "propState": {
            "type": "string"
          },
          "interruptMarkers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    },
    "transitions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "from",
          "to",
          "clip"
        ],
        "properties": {
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "clip": {
            "type": "string"
          }
        }
      }
    },
    "eventBindings": {
      "type": "object",
      "required": [
        "idle"
      ],
      "additionalProperties": {
        "type": "array",
        "minItems": 1,
        "items": {
          "type": "string"
        }
      }
    },
    "fallbacks": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "preview": {
      "type": "string"
    }
  },
  "$comment": "The app additionally verifies safe relative paths, image canvas sizes, total expanded bytes, file hashes, matching loop/transition endpoints, event bindings and fallback cycles. This schema does not replace import validation."
}
