{
	"$schema": "http://json-schema.org/draft-07/schema#",
	"$id": "https://schema.jiscribe.dev/v1/jiscribe.schema.json",
	"title": "CanvasDoc",
	"description": "Root document format for a .jis.json file used by svg-canvas-2.",
	"type": "object",
	"required": ["version", "root", "connectors"],
	"additionalProperties": false,
	"properties": {
		"version": {
			"description": "Schema version. Must be 1 for this version of the format.",
			"type": "integer",
			"const": 1
		},
		"root": {
			"description": "All objects on the canvas (shapes, polylines, groups). Connectors are separate.",
			"type": "array",
			"items": { "$ref": "#/$defs/AnyObjectDoc" }
		},
		"connectors": {
			"description": "Connector (arrow) objects linking shapes on the canvas.",
			"type": "array",
			"items": { "$ref": "#/$defs/ConnectorDoc" }
		}
	},
	"$defs": {
		"AnyObjectDoc": {
			"description": "Any placeable object on the canvas.",
			"oneOf": [
				{ "$ref": "#/$defs/RectDoc" },
				{ "$ref": "#/$defs/EllipseDoc" },
				{ "$ref": "#/$defs/PolylineDoc" },
				{ "$ref": "#/$defs/PolygonDoc" },
				{ "$ref": "#/$defs/GroupDoc" },
				{ "$ref": "#/$defs/StickyDoc" }
			],
			"discriminator": { "propertyName": "type" }
		},

		"MetaDoc": {
			"description": "Optional metadata attached to any object.",
			"type": "object",
			"properties": {
				"name": {
					"description": "Display name of the object.",
					"type": "string"
				},
				"description": {
					"description": "Arbitrary description.",
					"type": "string"
				}
			},
			"additionalProperties": true
		},

		"Point": {
			"description": "A 2D coordinate.",
			"type": "object",
			"required": ["x", "y"],
			"additionalProperties": false,
			"properties": {
				"x": { "type": "number" },
				"y": { "type": "number" }
			}
		},

		"StrokeDashType": {
			"description": "Dash pattern for stroke/border.",
			"type": "string",
			"enum": ["solid", "dashed", "dotted"]
		},

		"TextType": {
			"description": "How text content is rendered.",
			"type": "string",
			"enum": ["text", "markdown"]
		},

		"TextAlign": {
			"description": "Horizontal text alignment.",
			"type": "string",
			"enum": ["left", "center", "right"]
		},

		"VerticalAlign": {
			"description": "Vertical text alignment.",
			"type": "string",
			"enum": ["top", "middle", "bottom"]
		},

		"ArrowType": {
			"description": "Arrow shape at a connector endpoint.",
			"type": "string",
			"enum": [
				"FilledTriangle",
				"ConcaveTriangle",
				"OpenArrow",
				"HollowTriangle",
				"FilledDiamond",
				"HollowDiamond",
				"Circle",
				"None"
			]
		},

		"ConnectPointId": {
			"description": "Named connection point on a shape.",
			"type": "string",
			"enum": [
				"center",
				"topCenter",
				"rightCenter",
				"bottomCenter",
				"leftCenter"
			]
		},

		"StrokeStyle": {
			"description": "Stroke (outline) style properties.",
			"type": "object",
			"properties": {
				"stroke": {
					"description": "Stroke color as a CSS color string. Default: \"#374151\"",
					"type": "string"
				},
				"strokeWidth": {
					"description": "Stroke width in pixels. Default: 2",
					"type": "number",
					"minimum": 0
				},
				"strokeDashType": {
					"description": "Dash pattern. Default: \"solid\"",
					"$ref": "#/$defs/StrokeDashType"
				}
			}
		},

		"FillStyle": {
			"description": "Fill (background) style properties.",
			"type": "object",
			"properties": {
				"fill": {
					"description": "Fill color as a CSS color string. Default: \"transparent\"",
					"type": "string"
				}
			}
		},

		"TextStyle": {
			"description": "Text content and typography properties.",
			"type": "object",
			"properties": {
				"text": {
					"description": "Text content to display. Default: \"\"",
					"type": "string"
				},
				"textType": {
					"description": "How text is rendered. Default: \"text\"",
					"$ref": "#/$defs/TextType"
				},
				"textAlign": {
					"description": "Horizontal text alignment. Default: \"center\"",
					"$ref": "#/$defs/TextAlign"
				},
				"verticalAlign": {
					"description": "Vertical text alignment. Default: \"center\"",
					"$ref": "#/$defs/VerticalAlign"
				},
				"fontColor": {
					"description": "Font color as a CSS color string. Default: \"#000000\"",
					"type": "string"
				},
				"fontSize": {
					"description": "Font size in pixels. Default: 16",
					"type": "number",
					"minimum": 1
				},
				"fontFamily": {
					"description": "Font family. Default: \"Noto Sans JP\"",
					"type": "string"
				},
				"fontWeight": {
					"description": "Font weight (e.g. \"normal\", \"bold\", \"700\"). Default: \"normal\"",
					"type": "string"
				}
			}
		},

		"TransformStyle": {
			"description": "Transformation properties (rotation, flip).",
			"type": "object",
			"properties": {
				"rotation": {
					"description": "Rotation angle in degrees. Default: 0",
					"type": "number"
				},
				"flipX": {
					"description": "Horizontal flip. Default: false",
					"type": "boolean"
				},
				"flipY": {
					"description": "Vertical flip. Default: false",
					"type": "boolean"
				},
				"lockAspectRatio": {
					"description": "Lock aspect ratio during resize. Default: false",
					"type": "boolean"
				}
			}
		},

		"RectDoc": {
			"description": "Rectangle shape.",
			"type": "object",
			"required": ["id", "type", "x", "y", "width", "height"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"rect\".",
					"type": "string",
					"const": "rect"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"x": { "description": "Left-edge X coordinate.", "type": "number" },
				"y": { "description": "Top-edge Y coordinate.", "type": "number" },
				"width": {
					"description": "Width in pixels.",
					"type": "number",
					"minimum": 0
				},
				"height": {
					"description": "Height in pixels.",
					"type": "number",
					"minimum": 0
				},
				"rx": {
					"description": "Corner radius (SVG rx). Default: 0",
					"type": "number",
					"minimum": 0
				},
				"stroke": { "$ref": "#/$defs/StrokeStyle/properties/stroke" },
				"strokeWidth": { "$ref": "#/$defs/StrokeStyle/properties/strokeWidth" },
				"strokeDashType": {
					"$ref": "#/$defs/StrokeStyle/properties/strokeDashType"
				},
				"fill": { "$ref": "#/$defs/FillStyle/properties/fill" },
				"text": { "$ref": "#/$defs/TextStyle/properties/text" },
				"textType": { "$ref": "#/$defs/TextStyle/properties/textType" },
				"textAlign": { "$ref": "#/$defs/TextStyle/properties/textAlign" },
				"verticalAlign": {
					"$ref": "#/$defs/TextStyle/properties/verticalAlign"
				},
				"fontColor": { "$ref": "#/$defs/TextStyle/properties/fontColor" },
				"fontSize": { "$ref": "#/$defs/TextStyle/properties/fontSize" },
				"fontFamily": { "$ref": "#/$defs/TextStyle/properties/fontFamily" },
				"fontWeight": { "$ref": "#/$defs/TextStyle/properties/fontWeight" },
				"rotation": { "$ref": "#/$defs/TransformStyle/properties/rotation" },
				"flipX": { "$ref": "#/$defs/TransformStyle/properties/flipX" },
				"flipY": { "$ref": "#/$defs/TransformStyle/properties/flipY" },
				"lockAspectRatio": {
					"$ref": "#/$defs/TransformStyle/properties/lockAspectRatio"
				}
			}
		},

		"EllipseDoc": {
			"description": "Ellipse (oval) shape.",
			"type": "object",
			"required": ["id", "type", "cx", "cy", "rx", "ry"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"ellipse\".",
					"type": "string",
					"const": "ellipse"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"cx": { "description": "Center X coordinate.", "type": "number" },
				"cy": { "description": "Center Y coordinate.", "type": "number" },
				"rx": {
					"description": "Horizontal radius in pixels.",
					"type": "number",
					"minimum": 0
				},
				"ry": {
					"description": "Vertical radius in pixels.",
					"type": "number",
					"minimum": 0
				},
				"stroke": { "$ref": "#/$defs/StrokeStyle/properties/stroke" },
				"strokeWidth": { "$ref": "#/$defs/StrokeStyle/properties/strokeWidth" },
				"strokeDashType": {
					"$ref": "#/$defs/StrokeStyle/properties/strokeDashType"
				},
				"fill": { "$ref": "#/$defs/FillStyle/properties/fill" },
				"text": { "$ref": "#/$defs/TextStyle/properties/text" },
				"textType": { "$ref": "#/$defs/TextStyle/properties/textType" },
				"textAlign": { "$ref": "#/$defs/TextStyle/properties/textAlign" },
				"verticalAlign": {
					"$ref": "#/$defs/TextStyle/properties/verticalAlign"
				},
				"fontColor": { "$ref": "#/$defs/TextStyle/properties/fontColor" },
				"fontSize": { "$ref": "#/$defs/TextStyle/properties/fontSize" },
				"fontFamily": { "$ref": "#/$defs/TextStyle/properties/fontFamily" },
				"fontWeight": { "$ref": "#/$defs/TextStyle/properties/fontWeight" },
				"rotation": { "$ref": "#/$defs/TransformStyle/properties/rotation" },
				"flipX": { "$ref": "#/$defs/TransformStyle/properties/flipX" },
				"flipY": { "$ref": "#/$defs/TransformStyle/properties/flipY" },
				"lockAspectRatio": {
					"$ref": "#/$defs/TransformStyle/properties/lockAspectRatio"
				}
			}
		},

		"PolylineDoc": {
			"description": "Open polyline (non-closed path).",
			"type": "object",
			"required": ["id", "type", "points"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"polyline\".",
					"type": "string",
					"const": "polyline"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"points": {
					"description": "Ordered list of vertices.",
					"type": "array",
					"items": { "$ref": "#/$defs/Point" },
					"minItems": 2
				},
				"startArrow": {
					"description": "Arrow at the start point.",
					"$ref": "#/$defs/ArrowType"
				},
				"endArrow": {
					"description": "Arrow at the end point.",
					"$ref": "#/$defs/ArrowType"
				},
				"stroke": { "$ref": "#/$defs/StrokeStyle/properties/stroke" },
				"strokeWidth": { "$ref": "#/$defs/StrokeStyle/properties/strokeWidth" },
				"strokeDashType": {
					"$ref": "#/$defs/StrokeStyle/properties/strokeDashType"
				}
			}
		},

		"PolygonDoc": {
			"description": "Closed polygon shape.",
			"type": "object",
			"required": ["id", "type", "points"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"polygon\".",
					"type": "string",
					"const": "polygon"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"points": {
					"description": "Ordered list of vertices (automatically closed).",
					"type": "array",
					"items": { "$ref": "#/$defs/Point" },
					"minItems": 3
				},
				"stroke": { "$ref": "#/$defs/StrokeStyle/properties/stroke" },
				"strokeWidth": { "$ref": "#/$defs/StrokeStyle/properties/strokeWidth" },
				"strokeDashType": {
					"$ref": "#/$defs/StrokeStyle/properties/strokeDashType"
				},
				"fill": { "$ref": "#/$defs/FillStyle/properties/fill" }
			}
		},

		"GroupDoc": {
			"description": "A group containing child objects.",
			"type": "object",
			"required": ["id", "type", "children"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"group\".",
					"type": "string",
					"const": "group"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"children": {
					"description": "Child objects inside this group.",
					"type": "array",
					"items": { "$ref": "#/$defs/AnyObjectDoc" }
				},
				"rotation": { "$ref": "#/$defs/TransformStyle/properties/rotation" },
				"flipX": { "$ref": "#/$defs/TransformStyle/properties/flipX" },
				"flipY": { "$ref": "#/$defs/TransformStyle/properties/flipY" },
				"lockAspectRatio": {
					"$ref": "#/$defs/TransformStyle/properties/lockAspectRatio"
				}
			}
		},

		"StickyDoc": {
			"description": "Sticky note annotation.",
			"type": "object",
			"required": ["id", "type", "x", "y", "width", "height"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"sticky\".",
					"type": "string",
					"const": "sticky"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"x": { "description": "Left-edge X coordinate.", "type": "number" },
				"y": { "description": "Top-edge Y coordinate.", "type": "number" },
				"width": {
					"description": "Width in pixels.",
					"type": "number",
					"minimum": 0
				},
				"height": {
					"description": "Height in pixels.",
					"type": "number",
					"minimum": 0
				},
				"fill": { "$ref": "#/$defs/FillStyle/properties/fill" },
				"text": { "$ref": "#/$defs/TextStyle/properties/text" },
				"textType": { "$ref": "#/$defs/TextStyle/properties/textType" },
				"textAlign": { "$ref": "#/$defs/TextStyle/properties/textAlign" },
				"verticalAlign": {
					"$ref": "#/$defs/TextStyle/properties/verticalAlign"
				},
				"fontColor": { "$ref": "#/$defs/TextStyle/properties/fontColor" },
				"fontSize": { "$ref": "#/$defs/TextStyle/properties/fontSize" },
				"fontFamily": { "$ref": "#/$defs/TextStyle/properties/fontFamily" },
				"fontWeight": { "$ref": "#/$defs/TextStyle/properties/fontWeight" },
				"rotation": { "$ref": "#/$defs/TransformStyle/properties/rotation" },
				"flipX": { "$ref": "#/$defs/TransformStyle/properties/flipX" },
				"flipY": { "$ref": "#/$defs/TransformStyle/properties/flipY" },
				"lockAspectRatio": {
					"$ref": "#/$defs/TransformStyle/properties/lockAspectRatio"
				}
			}
		},

		"CenterAnchorSpec": {
			"description": "Anchor at the geometric center of an object.",
			"type": "object",
			"required": ["kind"],
			"additionalProperties": false,
			"properties": {
				"kind": { "type": "string", "const": "center" }
			}
		},

		"ConnectPointAnchorSpec": {
			"description": "Anchor at a named connection point on an object.",
			"type": "object",
			"required": ["kind", "id"],
			"additionalProperties": false,
			"properties": {
				"kind": { "type": "string", "const": "connectPoint" },
				"id": { "$ref": "#/$defs/ConnectPointId" }
			}
		},

		"FreeAnchorSpec": {
			"description": "Anchor at an arbitrary point in canvas space.",
			"type": "object",
			"required": ["kind", "point"],
			"additionalProperties": false,
			"properties": {
				"kind": { "type": "string", "const": "free" },
				"point": { "$ref": "#/$defs/Point" }
			}
		},

		"OwnerRef": {
			"description": "Reference to an object on the canvas.",
			"type": "object",
			"required": ["type", "id"],
			"additionalProperties": false,
			"properties": {
				"type": {
					"description": "Type of the target object.",
					"type": "string"
				},
				"id": { "description": "ID of the target object.", "type": "string" }
			}
		},

		"OwnedEndpointRef": {
			"description": "Endpoint attached to a specific object.",
			"type": "object",
			"required": ["owner", "anchor"],
			"additionalProperties": false,
			"properties": {
				"owner": { "$ref": "#/$defs/OwnerRef" },
				"anchor": {
					"oneOf": [
						{ "$ref": "#/$defs/CenterAnchorSpec" },
						{ "$ref": "#/$defs/ConnectPointAnchorSpec" }
					]
				}
			}
		},

		"FreeEndpointRef": {
			"description": "Endpoint floating at a fixed point in canvas space.",
			"type": "object",
			"required": ["anchor"],
			"additionalProperties": false,
			"properties": {
				"anchor": { "$ref": "#/$defs/FreeAnchorSpec" }
			}
		},

		"EndpointRef": {
			"description": "Connector endpoint — either attached to an object or floating.",
			"oneOf": [
				{ "$ref": "#/$defs/OwnedEndpointRef" },
				{ "$ref": "#/$defs/FreeEndpointRef" }
			]
		},

		"ConnectorDoc": {
			"description": "Connector (arrow) linking two endpoints.",
			"type": "object",
			"required": ["id", "type", "points", "source", "target"],
			"additionalProperties": false,
			"properties": {
				"id": { "description": "Unique identifier.", "type": "string" },
				"type": {
					"description": "Must be \"connector\".",
					"type": "string",
					"const": "connector"
				},
				"meta": { "$ref": "#/$defs/MetaDoc" },
				"points": {
					"description": "Ordered list of path vertices.",
					"type": "array",
					"items": { "$ref": "#/$defs/Point" },
					"minItems": 2
				},
				"source": {
					"description": "Where the connector starts.",
					"$ref": "#/$defs/EndpointRef"
				},
				"target": {
					"description": "Where the connector ends.",
					"$ref": "#/$defs/EndpointRef"
				},
				"startArrow": {
					"description": "Arrow at the start point.",
					"$ref": "#/$defs/ArrowType"
				},
				"endArrow": {
					"description": "Arrow at the end point.",
					"$ref": "#/$defs/ArrowType"
				},
				"stroke": { "$ref": "#/$defs/StrokeStyle/properties/stroke" },
				"strokeWidth": { "$ref": "#/$defs/StrokeStyle/properties/strokeWidth" },
				"strokeDashType": {
					"$ref": "#/$defs/StrokeStyle/properties/strokeDashType"
				}
			}
		}
	}
}
