{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://www.obviouspdf.com/downloads/obviouspdfjson-schema.json",
  "title": "ObviousPDF JSON Document",
  "description": "Schema for the ObviousPDF JSON renderer (ObviousPDF.Json). Pass a document conforming to this schema to PdfJsonRenderer.Render(), PdfJsonRenderer.RenderFromFile(), or PdfJsonRenderer.BuildDocument() to produce a tagged, accessible PDF.",
  "type": "object",
  "required": ["pages"],
  "properties": {
    "coordinateOrigin": {
      "type": "string",
      "enum": ["topLeft", "bottomLeft"],
      "default": "bottomLeft",
      "description": "Default coordinate origin for all pages. 'bottomLeft' is native PDF space (Y increases upward). 'topLeft' flips Y so (0,0) is the top-left corner and Y increases downward. Can be overridden per page."
    },
    "tagged": {
      "type": "boolean",
      "default": false,
      "description": "Enable tagged PDF. Required for PDF/UA accessibility compliance. Use structureTree to declare the logical structure and link content elements via structureId."
    },
    "accessible": {
      "type": "boolean",
      "default": false,
      "description": "Shorthand to enable full PDF/UA accessibility. When true, tagged mode is implicitly enabled, document language and title are set if not provided, DisplayDocTitle is enabled, PDF/UA-1 conformance is declared, and all content elements are automatically tagged. Standard fonts are auto-upgraded to embedded substitutes."
    },
    "generateAccessibilityReport": {
      "type": "boolean",
      "default": false,
      "description": "When true, an internal accessibility report is generated after building the PDF. The report is returned via PdfJsonRenderResult.AccessibilityReport. Disclaimer: This automated report is provided solely to assist in the assessment of document accessibility. It is not a comprehensive accessibility audit. To confirm that WCAG or PDF/UA standards are fully met, human assessment by an accessibility specialist is recommended."
    },
    "document": { "$ref": "#/definitions/documentSettings" },
    "fonts": {
      "type": "array",
      "items": { "$ref": "#/definitions/fontEntry" },
      "description": "Font library. Declare fonts here and reference them by id via fontRef in text options."
    },
    "images": {
      "type": "array",
      "items": { "$ref": "#/definitions/imageEntry" },
      "description": "Image library. Declare images here and reference them by id via imageRef in image elements."
    },
    "formXObjects": {
      "type": "array",
      "items": { "$ref": "#/definitions/formXObjectEntry" },
      "description": "Reusable FormXObject templates. Declare here and place on pages via formXObject elements."
    },
    "layers": {
      "type": "array",
      "items": { "$ref": "#/definitions/layerEntry" },
      "description": "Optional Content Group (OCG) layer declarations. Reference by id via layerRef in layer elements."
    },
    "shadings": {
      "type": "array",
      "items": { "$ref": "#/definitions/shadingEntry" },
      "description": "Gradient shading declarations (axial or radial). Reference by id via shadingId in shading elements."
    },
    "patterns": {
      "type": "array",
      "items": { "$ref": "#/definitions/tilingPatternEntry" },
      "description": "Tiling pattern declarations. Reference by id via patternId in tilingPattern elements."
    },
    "attachments": {
      "type": "array",
      "items": { "$ref": "#/definitions/attachmentEntry" },
      "description": "Files to embed in the PDF (for PDF/A-3 or general use)."
    },
    "outlines": {
      "type": "array",
      "items": { "$ref": "#/definitions/outlineEntry" },
      "description": "Bookmark/outline tree. Entries can be nested via children."
    },
    "pageLabels": {
      "type": "array",
      "items": { "$ref": "#/definitions/pageLabelEntry" },
      "description": "Page label ranges (e.g. i, ii, iii for front matter, then 1, 2, 3 for body)."
    },
    "structureTree": {
      "$ref": "#/definitions/structureElement",
      "description": "Root of the logical structure tree for tagged PDF. Typically a 'Document' type element containing all other structure elements."
    },
    "roleMappings": {
      "type": "array",
      "items": { "$ref": "#/definitions/roleMappingEntry" },
      "description": "Maps custom structure type names to standard PDF structure types for role mapping."
    },
    "pages": {
      "type": "array",
      "items": { "$ref": "#/definitions/page" },
      "minItems": 1,
      "description": "Page definitions. At least one page is required."
    }
  },
  "definitions": {

    "documentSettings": {
      "type": "object",
      "description": "Document-level metadata and settings.",
      "properties": {
        "info": { "$ref": "#/definitions/documentInfo" },
        "language": {
          "type": "string",
          "description": "BCP 47 language tag (e.g. 'en-US', 'fr-FR'). Required for PDF/UA conformance.",
          "examples": ["en-US", "en-GB", "fr-FR", "de-DE", "ja-JP"]
        },
        "displayDocTitle": {
          "type": "boolean",
          "default": false,
          "description": "Show document title in viewer title bar. Required for PDF/UA conformance."
        },
        "pdfVersion": {
          "type": "string",
          "description": "Explicit PDF version string. Auto-inferred when omitted.",
          "examples": ["1.7", "2.0"]
        },
        "conformance": { "$ref": "#/definitions/conformanceSettings" },
        "linearize": {
          "type": "boolean",
          "default": false,
          "description": "Enable fast web view (linearized PDF, also called 'web optimized')."
        },
        "useCrossReferenceStreams": {
          "type": "boolean",
          "default": false,
          "description": "Use compact cross-reference streams instead of cross-reference table (requires PDF 1.5+)."
        },
        "useObjectStreams": {
          "type": "boolean",
          "default": false,
          "description": "Pack indirect objects into compressed object streams (requires PDF 1.5+). Significantly reduces file size."
        },
        "encryption": { "$ref": "#/definitions/encryptionSettings" },
        "signature": { "$ref": "#/definitions/signatureSettings" }
      }
    },

    "documentInfo": {
      "type": "object",
      "description": "PDF document information dictionary (/Info).",
      "properties": {
        "title":    { "type": "string", "description": "Document title." },
        "author":   { "type": "string", "description": "Document author." },
        "subject":  { "type": "string", "description": "Document subject." },
        "keywords": { "type": "string", "description": "Document keywords (space or comma-separated)." },
        "creator":  { "type": "string", "description": "Application that created the content." }
      }
    },

    "conformanceSettings": {
      "type": "object",
      "description": "PDF/A archival and PDF/UA accessibility conformance levels.",
      "properties": {
        "pdfA": {
          "type": "string",
          "enum": ["pdfA1B", "pdfA2B", "pdfA3B"],
          "description": "PDF/A conformance level. 'pdfA1B' = ISO 19005-1 Level B. 'pdfA2B' = ISO 19005-2 Level B. 'pdfA3B' = ISO 19005-3 Level B (allows embedded files)."
        },
        "pdfUa": {
          "type": "string",
          "enum": ["PdfUA1", "PdfUA2"],
          "description": "PDF/UA accessibility conformance. 'PdfUA1' = ISO 14289-1 (based on PDF 1.7). 'PdfUA2' = ISO 14289-2 (based on PDF 2.0)."
        }
      }
    },

    "encryptionSettings": {
      "type": "object",
      "description": "PDF encryption using AES. Encrypt with a user password (to open) and/or an owner password (for full permissions).",
      "properties": {
        "userPassword":    { "type": "string", "description": "Password required to open the document." },
        "ownerPassword":   { "type": "string", "description": "Owner password granting full permissions." },
        "algorithm": {
          "type": "string",
          "enum": ["Aes128", "Aes256"],
          "default": "Aes256",
          "description": "Encryption algorithm. 'Aes256' (PDF 2.0) is recommended."
        },
        "allowPrinting":   { "type": "boolean", "default": true, "description": "Allow printing the document." },
        "allowCopying":    { "type": "boolean", "default": true, "description": "Allow copying text and graphics." },
        "allowModifying":  { "type": "boolean", "default": true, "description": "Allow modifying document content." },
        "allowAnnotating": { "type": "boolean", "default": true, "description": "Allow adding or modifying annotations." }
      }
    },

    "signatureSettings": {
      "type": "object",
      "description": "Digital signature settings. Uses a PKCS#12 (.pfx/.p12) certificate.",
      "properties": {
        "certificatePath":     { "type": "string", "description": "File system path to the .pfx or .p12 certificate file." },
        "certificatePassword": { "type": "string", "description": "Password for the certificate file." },
        "reason":              { "type": "string", "description": "Reason for signing (e.g. 'Approved', 'Reviewed')." },
        "location":            { "type": "string", "description": "Location of signing (e.g. 'New York, NY')." },
        "contactInfo":         { "type": "string", "description": "Contact information of the signer." },
        "signerName":          { "type": "string", "description": "Display name of the signer." },
        "fieldName":           { "type": "string", "description": "Name of the signature field on the page." },
        "pageIndex":           { "type": "integer", "default": 0, "description": "Zero-based page index for the signature appearance." },
        "x":      { "type": "number", "description": "X position of the signature appearance box." },
        "y":      { "type": "number", "description": "Y position of the signature appearance box." },
        "width":  { "type": "number", "default": 200, "description": "Width of the signature appearance box in points." },
        "height": { "type": "number", "default": 50,  "description": "Height of the signature appearance box in points." }
      }
    },

    "fontEntry": {
      "type": "object",
      "required": ["id", "mode"],
      "description": "Font library entry. Declare fonts here and reference them by id in text options via fontRef.",
      "properties": {
        "id":          { "type": "string", "description": "Unique identifier for this font, referenced by fontRef in text options." },
        "description": { "type": "string", "description": "Optional human-readable description." },
        "mode": {
          "type": "string",
          "enum": ["standard", "bundled", "file", "base64"],
          "description": "'standard' = one of the 14 standard PDF fonts (not embedded, avoid for PDF/UA). 'bundled' = a font built into ObviousPDF. 'file' = font loaded from a file path. 'base64' = font data as a base64 string."
        },
        "standardFont": {
          "type": "string",
          "enum": ["Helvetica","HelveticaBold","HelveticaOblique","HelveticaBoldOblique","Times","TimesBold","TimesItalic","TimesBoldItalic","Courier","CourierBold","CourierOblique","CourierBoldOblique","Symbol","ZapfDingbats"],
          "description": "Standard font name. Required when mode = 'standard'. WARNING: Standard fonts are not embedded and fail PDF/UA font-embedding requirements."
        },
        "bundledFont": {
          "type": "string",
          "description": "Bundled font name. Required when mode = 'bundled'. Bundled fonts are embedded and have full Unicode coverage."
        },
        "path": { "type": "string", "description": "Absolute or relative file path to a .ttf or .otf font file. Required when mode = 'file'." },
        "data": { "type": "string", "description": "Base64-encoded font file data. Required when mode = 'base64'." }
      }
    },

    "imageEntry": {
      "type": "object",
      "required": ["id", "mode"],
      "description": "Image library entry. Declare images here and reference them by id via imageRef in image elements.",
      "properties": {
        "id":          { "type": "string", "description": "Unique identifier referenced by imageRef in image elements." },
        "description": { "type": "string" },
        "mode": {
          "type": "string",
          "enum": ["file", "base64", "url"],
          "description": "'file' = load from file path. 'base64' = inline base64-encoded image data. 'url' = load from a URL."
        },
        "path":     { "type": "string", "description": "File system path. Required when mode = 'file'." },
        "data":     { "type": "string", "description": "Base64-encoded image data. Required when mode = 'base64'." },
        "mimeType": { "type": "string", "description": "MIME type (e.g. 'image/jpeg', 'image/png'). Required when mode = 'base64'.", "examples": ["image/jpeg","image/png","image/gif","image/tiff"] },
        "url":      { "type": "string", "format": "uri", "description": "Image URL. Required when mode = 'url'." }
      }
    },

    "inlineImageSource": {
      "type": "object",
      "required": ["mode"],
      "description": "Inline image source for an image element (alternative to imageRef).",
      "properties": {
        "mode":     { "type": "string", "enum": ["file", "base64", "url"] },
        "path":     { "type": "string" },
        "data":     { "type": "string" },
        "mimeType": { "type": "string" },
        "url":      { "type": "string", "format": "uri" }
      }
    },

    "formXObjectEntry": {
      "type": "object",
      "required": ["id", "width", "height", "content"],
      "description": "Reusable FormXObject (PDF Form XObject). Define once, place multiple times.",
      "properties": {
        "id":      { "type": "string", "description": "Unique identifier referenced by ref in formXObject elements." },
        "width":   { "type": "number", "description": "Width of the FormXObject bounding box in points." },
        "height":  { "type": "number", "description": "Height of the FormXObject bounding box in points." },
        "content": { "type": "array", "items": { "$ref": "#/definitions/contentElement" }, "description": "Content elements drawn inside this FormXObject." }
      }
    },

    "layerEntry": {
      "type": "object",
      "required": ["id", "name"],
      "description": "Optional Content Group (OCG) layer declaration.",
      "properties": {
        "id":      { "type": "string", "description": "Unique identifier referenced by layerRef in layer elements." },
        "name":    { "type": "string", "description": "Human-readable layer name displayed in PDF viewer layer panel." },
        "visible": { "type": "boolean", "default": true, "description": "Initial visibility of the layer." }
      }
    },

    "shadingEntry": {
      "type": "object",
      "required": ["id", "type"],
      "description": "Gradient shading declaration. Use axial for linear gradients, radial for circular gradients.",
      "properties": {
        "id":   { "type": "string", "description": "Unique identifier referenced by shadingId in shading elements." },
        "type": { "type": "string", "enum": ["axial", "radial"], "description": "'axial' = linear gradient between two points. 'radial' = gradient between two circles (inner and outer)." },
        "x0": { "type": "number", "description": "Start X (axial) or center X of inner circle (radial)." },
        "y0": { "type": "number", "description": "Start Y (axial) or center Y of inner circle (radial)." },
        "x1": { "type": "number", "description": "End X (axial) or center X of outer circle (radial)." },
        "y1": { "type": "number", "description": "End Y (axial) or center Y of outer circle (radial)." },
        "r0": { "type": "number", "description": "Radius of the inner circle. Radial gradients only." },
        "r1": { "type": "number", "description": "Radius of the outer circle. Radial gradients only." },
        "colorStops": {
          "type": "array",
          "items": { "$ref": "#/definitions/colorStop" },
          "description": "Color stops along the gradient. Typically at minimum a start (offset 0) and end (offset 1) stop."
        }
      }
    },

    "colorStop": {
      "type": "object",
      "required": ["offset", "color"],
      "description": "A color stop in a gradient shading.",
      "properties": {
        "offset": { "type": "number", "minimum": 0, "maximum": 1, "description": "Position along the gradient (0.0 = start, 1.0 = end)." },
        "color":  { "$ref": "#/definitions/color" }
      }
    },

    "tilingPatternEntry": {
      "type": "object",
      "required": ["id", "width", "height", "content"],
      "description": "Tiling pattern declaration. The content is tiled repeatedly when the pattern is applied.",
      "properties": {
        "id":      { "type": "string", "description": "Unique identifier referenced by patternId in tilingPattern elements." },
        "width":   { "type": "number", "description": "Width of a single tile in points." },
        "height":  { "type": "number", "description": "Height of a single tile in points." },
        "content": { "type": "array", "items": { "$ref": "#/definitions/contentElement" } }
      }
    },

    "attachmentEntry": {
      "type": "object",
      "required": ["id", "fileName", "mode"],
      "description": "Embedded file attachment. For PDF/A-3, set relationship to specify the file's role.",
      "properties": {
        "id":           { "type": "string" },
        "fileName":     { "type": "string", "description": "File name as it will appear in the PDF attachment panel." },
        "mimeType":     { "type": "string", "description": "MIME type of the attached file (e.g. 'application/xml')." },
        "relationship": { "type": "string", "description": "PDF/A-3 relationship type.", "examples": ["Data", "Source", "Alternative", "Supplement", "Unspecified"] },
        "mode":         { "type": "string", "enum": ["file", "base64"] },
        "path":         { "type": "string" },
        "data":         { "type": "string" }
      }
    },

    "outlineEntry": {
      "type": "object",
      "required": ["title"],
      "description": "Bookmark/outline entry. Use children for nested bookmarks.",
      "properties": {
        "title":    { "type": "string", "description": "Bookmark title displayed in viewer." },
        "page":     { "type": "integer", "description": "Zero-based page index to navigate to when clicked." },
        "children": { "type": "array", "items": { "$ref": "#/definitions/outlineEntry" }, "description": "Nested child bookmarks." }
      }
    },

    "pageLabelEntry": {
      "type": "object",
      "required": ["startPage"],
      "description": "Page label range. Define ranges to produce custom page numbering (e.g. i, ii, iii then 1, 2, 3).",
      "properties": {
        "startPage":    { "type": "integer", "description": "Zero-based physical page index where this label range begins." },
        "style": {
          "type": "string",
          "enum": ["Decimal", "LowerRoman", "UpperRoman", "LowerAlpha", "UpperAlpha", "None"],
          "default": "Decimal"
        },
        "prefix":       { "type": "string", "description": "Label prefix (e.g. 'A-' produces 'A-1', 'A-2', ...)." },
        "logicalStart": { "type": "integer", "default": 1, "description": "Logical page number of the first page in this range." }
      }
    },

    "roleMappingEntry": {
      "type": "object",
      "required": ["customType", "standardType"],
      "description": "Maps a custom structure element type name to a standard PDF structure type.",
      "properties": {
        "customType":   { "type": "string", "description": "The custom type name used in structureTree elements." },
        "standardType": { "type": "string", "description": "The standard PDF structure type it maps to (e.g. 'P', 'H1', 'Sect')." }
      }
    },

    "structureElement": {
      "type": "object",
      "required": ["type"],
      "description": "A node in the tagged PDF logical structure tree. Link to page content via the id property and structureId on content elements.",
      "properties": {
        "type": {
          "type": "string",
          "description": "Standard PDF structure type. Common values: Document, Part, Sect, Div, P, H, H1, H2, H3, H4, H5, H6, BlockQuote, Caption, Index, TOC, TOCI, L, LI, Lbl, LBody, Table, TR, TH, TD, THead, TBody, TFoot, Span, Quote, Note, Reference, BibEntry, Code, Link, Annot, Ruby, Warichu, Figure, Formula, Form, MC.",
          "examples": ["Document", "Sect", "P", "H1", "H2", "Table", "TR", "TH", "TD", "L", "LI", "Lbl", "LBody", "Figure", "Form"]
        },
        "customType":  { "type": "string", "description": "Custom type name (must be registered in roleMappings)." },
        "id":          { "type": "string", "description": "Unique ID. Content elements reference this via their structureId property to be included in this structure element." },
        "altText":     { "type": "string", "description": "Alternative text. REQUIRED for Figure elements (PDF/UA §7.3, Matterhorn 13-004)." },
        "actualText":  { "type": "string", "description": "Actual text replacement for non-textual content." },
        "language":    { "type": "string", "description": "BCP 47 language tag override for this element subtree." },
        "title":       { "type": "string", "description": "Human-readable element title." },
        "phoneme":     { "type": "string", "description": "Phonemic transcription of the element's text content (PDF 2.0)." },
        "phonemeAlphabet": { "type": "string", "enum": ["ipa", "xSampa"], "description": "Phonetic alphabet used in the phoneme property." },
        "children": {
          "type": "array",
          "items": { "$ref": "#/definitions/structureElement" },
          "description": "Child structure elements."
        }
      }
    },

    "page": {
      "type": "object",
      "required": ["content"],
      "description": "A PDF page. Specify size by name or by width+height in points.",
      "properties": {
        "size": {
          "type": "string",
          "enum": ["Letter", "Legal", "A4", "A3", "A5", "Tabloid"],
          "description": "Named page size. Letter = 612×792pt, Legal = 612×1008pt, A4 = 595×842pt, A3 = 842×1191pt, A5 = 420×595pt, Tabloid = 792×1224pt."
        },
        "width":  { "type": "number", "description": "Page width in points (1 pt = 1/72 inch). Use with height for custom sizes." },
        "height": { "type": "number", "description": "Page height in points." },
        "coordinateOrigin": {
          "type": "string",
          "enum": ["topLeft", "bottomLeft"],
          "description": "Page-level coordinate origin override. Overrides the document-level coordinateOrigin."
        },
        "content": {
          "type": "array",
          "items": { "$ref": "#/definitions/contentElement" },
          "description": "Content elements drawn on this page."
        }
      }
    },

    "color": {
      "description": "A color value. Can be a named string, an RGB object, a grayscale object, or a CMYK object. All component values are in the 0.0–1.0 range.",
      "oneOf": [
        {
          "type": "string",
          "enum": ["black", "white", "red", "green", "blue"],
          "description": "Named color shorthand."
        },
        {
          "type": "object",
          "required": ["r", "g", "b"],
          "description": "RGB color (DeviceRGB color space). Components are 0.0–1.0.",
          "properties": {
            "r": { "type": "number", "minimum": 0, "maximum": 1 },
            "g": { "type": "number", "minimum": 0, "maximum": 1 },
            "b": { "type": "number", "minimum": 0, "maximum": 1 }
          },
          "additionalProperties": false
        },
        {
          "type": "object",
          "required": ["gray"],
          "description": "Grayscale color (DeviceGray color space). 0.0 = black, 1.0 = white.",
          "properties": {
            "gray": { "type": "number", "minimum": 0, "maximum": 1 }
          },
          "additionalProperties": false
        },
        {
          "type": "object",
          "required": ["c", "m", "y", "k"],
          "description": "CMYK color (DeviceCMYK color space). Components are 0.0–1.0.",
          "properties": {
            "c": { "type": "number", "minimum": 0, "maximum": 1 },
            "m": { "type": "number", "minimum": 0, "maximum": 1 },
            "y": { "type": "number", "minimum": 0, "maximum": 1 },
            "k": { "type": "number", "minimum": 0, "maximum": 1 }
          },
          "additionalProperties": false
        }
      ]
    },

    "textOptions": {
      "type": "object",
      "description": "Text rendering options. All properties are optional.",
      "properties": {
        "fontRef":    { "type": "string", "description": "ID of a font declared in the fonts library." },
        "fontSize":   { "type": "number", "default": 12, "description": "Font size in points." },
        "color":      { "$ref": "#/definitions/color", "description": "Text fill color." },
        "leading":    { "type": "number", "description": "Line spacing in points (distance from one baseline to the next). Default is fontSize × 1.2." },
        "renderingMode": {
          "type": "string",
          "enum": ["fill", "stroke", "fillAndStroke", "invisible"],
          "default": "fill",
          "description": "Text rendering mode. 'fill' = solid fill. 'stroke' = outline only. 'fillAndStroke' = filled with outline. 'invisible' = invisible but present in the PDF stream."
        },
        "alignment": {
          "type": "string",
          "enum": ["left", "center", "right", "justify"],
          "default": "left",
          "description": "Text alignment. Requires width to be set for center/right/justify."
        },
        "width":  { "type": "number", "description": "Maximum text width in points for wrapping and alignment." },
        "decoration": {
          "type": "array",
          "items": { "type": "string", "enum": ["underline", "strikeOut", "overline"] },
          "description": "Text decoration(s). Multiple values can be combined."
        },
        "decorationColor":     { "$ref": "#/definitions/color" },
        "decorationThickness": { "type": "number", "description": "Decoration line thickness in points." },
        "superscript":  { "type": "boolean", "default": false, "description": "Render text as superscript." },
        "subscript":    { "type": "boolean", "default": false, "description": "Render text as subscript." },
        "outlineColor": { "$ref": "#/definitions/color", "description": "Stroke color for text outline. Use with renderingMode 'stroke' or 'fillAndStroke'." },
        "outlineWidth": { "type": "number", "description": "Stroke width for text outline in points." },
        "backgroundColor": { "$ref": "#/definitions/color", "description": "Highlight color drawn behind the text." },
        "shadowColor":     { "$ref": "#/definitions/color", "description": "Drop shadow color." },
        "shadowOffsetX":   { "type": "number", "default": 1.0, "description": "Horizontal shadow offset in points." },
        "shadowOffsetY":   { "type": "number", "default": -1.0, "description": "Vertical shadow offset in points." },
        "rotation":        { "type": "number", "default": 0, "description": "Text rotation in degrees (counter-clockwise)." }
      }
    },

    "drawOptions": {
      "type": "object",
      "description": "Shape stroke and fill options.",
      "properties": {
        "strokeColor": { "$ref": "#/definitions/color", "description": "Stroke (outline) color." },
        "fillColor":   { "$ref": "#/definitions/color", "description": "Fill color." },
        "lineWidth":   { "type": "number", "default": 1.0, "description": "Stroke line width in points." },
        "lineCap": {
          "type": "string",
          "enum": ["butt", "round", "projecting"],
          "default": "butt",
          "description": "Line cap style for open path endpoints."
        },
        "lineJoin": {
          "type": "string",
          "enum": ["miter", "round", "bevel"],
          "default": "miter",
          "description": "Line join style for corners."
        },
        "miterLimit":   { "type": "number", "default": 10.0, "description": "Miter limit for miter line joins." },
        "dashPattern":  { "type": "array", "items": { "type": "number" }, "description": "Dash pattern as an array of on/off lengths in points. E.g. [5, 3] = 5pt dash, 3pt gap." },
        "dashPhase":    { "type": "number", "default": 0, "description": "Phase offset into the dash pattern in points." },
        "strokeAlpha":  { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "Stroke opacity (0.0 = transparent, 1.0 = opaque)." },
        "fillAlpha":    { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "Fill opacity." }
      }
    },

    "contentElement": {
      "description": "A page content element, discriminated by the required 'type' field.",
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "text", "textBlock", "image", "line", "rectangle", "circle", "ellipse",
            "polygon", "path", "link", "textAnnotation", "freeTextAnnotation",
            "markupAnnotation", "stampAnnotation", "formXObject",
            "textField", "checkboxField", "dropdownField", "listBoxField",
            "pushButtonField", "signatureField",
            "transform", "clip", "layer", "shading", "tilingPattern", "alpha"
          ]
        },
        "structureId":    { "type": "string", "description": "Links this element to a structureTree node by its id, making this content part of that structure element." },
        "artifact":       { "type": "boolean", "default": false, "description": "Mark as a PDF artifact. Artifacts are ignored by assistive technology." },
        "artifactType":   { "type": "string", "enum": ["pagination", "layout", "page", "background"], "description": "Artifact subtype." },
        "artifactSubtype":{ "type": "string", "enum": ["Header", "Footer"], "description": "Sub-subtype for pagination artifacts." },
        "structureTag":   { "type": "string", "enum": ["P","H1","H2","H3","H4","H5","H6","H","Span","BlockQuote","Caption","Div","Sect","Art","Part","Code","Quote","Note","Reference","Link","L","LI","Lbl","LBody","Table","TR","TH","TD","THead","TBody","TFoot","Figure","Formula","Form"], "description": "Overrides the default structure type in accessible (auto-tag) mode. E.g. set to 'H2' to tag text as a heading instead of the default P." },
        "text":       { "type": "string" },
        "lines":      { "type": "array", "items": { "type": "string" } },
        "imageRef":   { "type": "string", "description": "ID of an image in the images library." },
        "source":     { "$ref": "#/definitions/inlineImageSource" },
        "scaleMode":  { "type": "string", "enum": ["exact", "fit", "stretch"], "default": "exact" },
        "x":    { "type": "number" },
        "y":    { "type": "number" },
        "x1":   { "type": "number" },
        "y1":   { "type": "number" },
        "x2":   { "type": "number" },
        "y2":   { "type": "number" },
        "cx":   { "type": "number" },
        "cy":   { "type": "number" },
        "r":    { "type": "number" },
        "rx":   { "type": "number" },
        "ry":   { "type": "number" },
        "width":  { "type": "number" },
        "height": { "type": "number" },
        "mode":   { "type": "string", "enum": ["draw", "fill", "drawAndFill", "stroke", "fill+stroke"], "description": "Render mode for shapes." },
        "points": { "type": "array", "items": { "type": "array", "items": { "type": "number" } }, "description": "Array of [x, y] point pairs for polygon." },
        "render": { "type": "string", "enum": ["stroke", "fill", "fillAndStroke"], "description": "Render mode for path elements." },
        "operations": { "type": "array", "items": { "$ref": "#/definitions/pathOperation" } },
        "uri":        { "type": "string", "format": "uri", "description": "URI for link elements." },
        "contents":   { "type": "string", "description": "Annotation text content." },
        "color":      { "$ref": "#/definitions/color" },
        "open":       { "type": "boolean", "description": "Initial open state for text annotations." },
        "markupType": { "type": "string", "enum": ["highlight", "underline", "squiggly", "strikeOut"], "description": "Markup annotation type." },
        "icon":       { "type": "string", "description": "Stamp annotation icon name." },
        "ref":        { "type": "string", "description": "FormXObject id reference." },
        "name":       { "type": "string", "description": "Form field name (acroform field name)." },
        "anchor":     { "type": "string", "enum": ["top", "bottom", "center"], "default": "top", "description": "Y coordinate anchor for form fields." },
        "tooltip":    { "type": "string", "description": "Form field tooltip/alternate name (/TU). Required for PDF/UA." },
        "defaultValue": { "type": "string" },
        "multiline":  { "type": "boolean", "default": false },
        "password":   { "type": "boolean", "default": false, "description": "Render as password field (text obscured)." },
        "maxLength":  { "type": "integer", "description": "Maximum character count. 0 = unlimited." },
        "fontSize":   { "type": "number", "default": 12, "description": "Font size for form field text." },
        "readonly":   { "type": "boolean", "default": false },
        "required":   { "type": "boolean", "default": false },
        "checked":    { "type": "boolean", "default": false, "description": "Initial checked state for checkbox fields." },
        "options":    {
          "oneOf": [
            { "$ref": "#/definitions/textOptions" },
            { "type": "array", "items": { "type": "string" } }
          ],
          "description": "Text rendering options (for text/textBlock/freeTextAnnotation) OR list of option strings (for dropdownField/listBoxField)."
        },
        "selectedIndex": { "type": "integer", "default": -1, "description": "Zero-based selected index for dropdown/listbox. -1 = no selection." },
        "label":     { "type": "string", "description": "Button label for pushButtonField." },
        "drawOptions": { "$ref": "#/definitions/drawOptions" },
        "operation": { "type": "string", "enum": ["translate", "scale", "rotate", "skew", "matrix"], "description": "Transform operation type." },
        "tx": { "type": "number", "description": "X translation (translate operation)." },
        "ty": { "type": "number", "description": "Y translation (translate operation)." },
        "sx": { "type": "number", "default": 1, "description": "X scale factor (scale operation)." },
        "sy": { "type": "number", "default": 1, "description": "Y scale factor (scale operation)." },
        "angle":  { "type": "number", "description": "Rotation angle in degrees (rotate operation)." },
        "angleX": { "type": "number", "description": "X skew angle in degrees (skew operation)." },
        "angleY": { "type": "number", "description": "Y skew angle in degrees (skew operation)." },
        "matrix": { "type": "array", "items": { "type": "number" }, "minItems": 6, "maxItems": 6, "description": "6-element CTM matrix [a, b, c, d, e, f] (matrix operation)." },
        "content": { "type": "array", "items": { "$ref": "#/definitions/contentElement" }, "description": "Nested content elements (transform, clip, layer, alpha)." },
        "shape":  { "type": "string", "enum": ["rectangle", "circle", "ellipse"], "description": "Clipping shape type." },
        "layerRef":   { "type": "string", "description": "ID of a layer declared in the layers library." },
        "shadingId":  { "type": "string", "description": "ID of a shading declared in the shadings library." },
        "patternId":  { "type": "string", "description": "ID of a pattern declared in the patterns library." },
        "strokeAlpha": { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "Stroke opacity for alpha elements." },
        "fillAlpha":   { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "Fill opacity for alpha elements." }
      }
    },

    "pathOperation": {
      "type": "object",
      "required": ["op"],
      "description": "A single operation in a PDF path.",
      "properties": {
        "op": { "type": "string", "enum": ["moveTo", "lineTo", "curveTo", "closePath"], "description": "'moveTo' = move to (x,y). 'lineTo' = straight line to (x,y). 'curveTo' = cubic Bézier curve to (x3,y3) with control points (x1,y1) and (x2,y2). 'closePath' = close the current subpath." },
        "x":  { "type": "number" },
        "y":  { "type": "number" },
        "x1": { "type": "number", "description": "First Bézier control point X." },
        "y1": { "type": "number", "description": "First Bézier control point Y." },
        "x2": { "type": "number", "description": "Second Bézier control point X." },
        "y2": { "type": "number", "description": "Second Bézier control point Y." },
        "x3": { "type": "number", "description": "Bézier endpoint X." },
        "y3": { "type": "number", "description": "Bézier endpoint Y." }
      }
    }
  }
}
