<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- ============================================================
       Simple Types
  ============================================================ -->

  <xs:simpleType name="TokenScale">
    <xs:restriction base="xs:string">
      <xs:enumeration value="xs"/>
      <xs:enumeration value="s"/>
      <xs:enumeration value="m"/>
      <xs:enumeration value="l"/>
      <xs:enumeration value="xl"/>
      <xs:enumeration value="xxl"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- e.g. "10pt", "25.4mm", or "1in" (non-negative) -->
  <xs:simpleType name="PtValue">
    <xs:restriction base="xs:string">
      <xs:pattern value="\d+(\.\d+)?(pt|mm|in)"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Same as PtValue but allows a leading minus for coordinates and offsets -->
  <xs:simpleType name="SignedPtValue">
    <xs:restriction base="xs:string">
      <xs:pattern value="-?\d+(\.\d+)?(pt|mm|in)"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- token name or explicit pt value, e.g. "m" or "14pt" -->
  <xs:simpleType name="TokenScaleOrPt">
    <xs:union memberTypes="TokenScale PtValue"/>
  </xs:simpleType>

  <!-- e.g. "10pt" | "10pt 12pt" | "10pt 12pt 8pt" | "10pt 12pt 8pt 6pt" -->
  <xs:simpleType name="SpacingValue">
    <xs:restriction base="xs:string">
      <xs:pattern value="\d+(\.\d+)?pt( \d+(\.\d+)?pt){0,3}"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- spacing: explicit multi-pt shorthand OR a single token name -->
  <xs:simpleType name="SpacingOrToken">
    <xs:union memberTypes="SpacingValue TokenScale"/>
  </xs:simpleType>

  <xs:simpleType name="PageSizeNamed">
    <xs:restriction base="xs:string">
      <xs:enumeration value="a4"/>
      <xs:enumeration value="a3"/>
      <xs:enumeration value="a5"/>
      <xs:enumeration value="letter"/>
      <xs:enumeration value="legal"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- e.g. "100pt 200pt" -->
  <xs:simpleType name="PageSizeCustom">
    <xs:restriction base="xs:string">
      <xs:pattern value="\d+(\.\d+)?pt \d+(\.\d+)?pt"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="PageSize">
    <xs:union memberTypes="PageSizeNamed PageSizeCustom"/>
  </xs:simpleType>

  <xs:simpleType name="Orientation">
    <xs:restriction base="xs:string">
      <xs:enumeration value="portrait"/>
      <xs:enumeration value="landscape"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- e.g. "#1763cf" or "#fff" -->
  <xs:simpleType name="ColorHex">
    <xs:restriction base="xs:string">
      <xs:pattern value="#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- hex or a named color token e.g. "primary", "surface-alt" -->
  <xs:simpleType name="Color">
    <xs:restriction base="xs:string">
      <xs:pattern value="#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?|[a-z][a-z0-9-]*"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- e.g. "s #ccc", "m primary", or "1.5pt #ccc" -->
  <xs:simpleType name="BorderValue">
    <xs:restriction base="xs:string">
      <xs:pattern value="(\d+(\.\d+)?pt|xs|s|m|l|xl|2xl) .+"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- cross-axis alignment (stack cross-axis supports stretch) -->
  <xs:simpleType name="AlignFull">
    <xs:restriction base="xs:string">
      <xs:enumeration value="start"/>
      <xs:enumeration value="center"/>
      <xs:enumeration value="end"/>
      <xs:enumeration value="stretch"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="Align">
    <xs:restriction base="xs:string">
      <xs:enumeration value="start"/>
      <xs:enumeration value="center"/>
      <xs:enumeration value="end"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="Justify">
    <xs:restriction base="xs:string">
      <xs:enumeration value="start"/>
      <xs:enumeration value="center"/>
      <xs:enumeration value="end"/>
      <xs:enumeration value="between"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="TextAlignH">
    <xs:restriction base="xs:string">
      <xs:enumeration value="left"/>
      <xs:enumeration value="center"/>
      <xs:enumeration value="right"/>
      <xs:enumeration value="justify"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- "full", "fill", or an explicit pt value e.g. "48pt" -->
  <xs:simpleType name="HeightValue">
    <xs:union memberTypes="HeightMode PtValue"/>
  </xs:simpleType>

  <xs:simpleType name="HeightMode">
    <xs:restriction base="xs:string">
      <xs:enumeration value="full"/>
      <xs:enumeration value="fill"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Nine reference points on the page (vertical-first naming) -->
  <xs:simpleType name="Anchor">
    <xs:restriction base="xs:string">
      <xs:enumeration value="top-left"/>
      <xs:enumeration value="top-center"/>
      <xs:enumeration value="top-right"/>
      <xs:enumeration value="center-left"/>
      <xs:enumeration value="center"/>
      <xs:enumeration value="center-right"/>
      <xs:enumeration value="bottom-left"/>
      <xs:enumeration value="bottom-center"/>
      <xs:enumeration value="bottom-right"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Keyword or numeric page range (section-relative) -->
  <xs:simpleType name="PageScope">
    <xs:union>
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="each"/>
          <xs:enumeration value="first"/>
          <xs:enumeration value="last"/>
          <xs:enumeration value="odd"/>
          <xs:enumeration value="even"/>
        </xs:restriction>
      </xs:simpleType>
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <!-- matches: 1  |  1-3  |  1-last  |  1,3  |  1,3-5,7-last -->
          <xs:pattern value="[1-9]\d*(-([1-9]\d*|last))?(,[1-9]\d*(-([1-9]\d*|last))?)*"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:union>
  </xs:simpleType>

  <xs:simpleType name="LineCap">
    <xs:restriction base="xs:string">
      <xs:enumeration value="butt"/>
      <xs:enumeration value="round"/>
      <xs:enumeration value="square"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="FillRule">
    <xs:restriction base="xs:string">
      <xs:enumeration value="nonzero"/>
      <xs:enumeration value="evenodd"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Pin positions for layout regions; top/bottom implemented in Phase 2;
       left/right schema-valid but implementation deferred. -->
  <xs:simpleType name="RegionPin">
    <xs:restriction base="xs:string">
      <xs:enumeration value="top"/>
      <xs:enumeration value="bottom"/>
      <xs:enumeration value="left"/>
      <xs:enumeration value="right"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="BuiltinFont">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Courier"/>
      <xs:enumeration value="Courier-Bold"/>
      <xs:enumeration value="Courier-Oblique"/>
      <xs:enumeration value="Courier-BoldOblique"/>
      <xs:enumeration value="Helvetica"/>
      <xs:enumeration value="Helvetica-Bold"/>
      <xs:enumeration value="Helvetica-Oblique"/>
      <xs:enumeration value="Helvetica-BoldOblique"/>
      <xs:enumeration value="Times-Roman"/>
      <xs:enumeration value="Times-Bold"/>
      <xs:enumeration value="Times-Italic"/>
      <xs:enumeration value="Times-BoldItalic"/>
      <xs:enumeration value="Symbol"/>
      <xs:enumeration value="ZapfDingbats"/>
    </xs:restriction>
  </xs:simpleType>


  <!-- ============================================================
       Reusable complex types
  ============================================================ -->

  <!-- All six scale slots with pt values — used by every token row -->
  <xs:complexType name="TokenScaleRow">
    <xs:attribute name="xs"  type="PtValue" use="required"/>
    <xs:attribute name="s"   type="PtValue" use="required"/>
    <xs:attribute name="m"   type="PtValue" use="required"/>
    <xs:attribute name="l"   type="PtValue" use="required"/>
    <xs:attribute name="xl"  type="PtValue" use="required"/>
    <xs:attribute name="xxl" type="PtValue" use="required"/>
  </xs:complexType>


  <!-- ============================================================
       Shared attribute groups
  ============================================================ -->

  <!-- Data-binding attrs valid on any layout element.
       data-value  : dot-path to a scalar; replaces the element's text content.
       data-source : dot-path to an array; repeats this element once per item.
       data-if     : dot-path to a value; element is rendered only when truthy.
       data-if-not : dot-path to a value; element is rendered only when falsy. -->
  <xs:attributeGroup name="DataBindingAttrs">
    <xs:attribute name="data-value"  type="xs:string"/>
    <xs:attribute name="data-source" type="xs:string"/>
    <xs:attribute name="data-if"     type="xs:string"/>
    <xs:attribute name="data-if-not" type="xs:string"/>
  </xs:attributeGroup>

  <!-- Box attrs shared by all layout elements -->
  <xs:attributeGroup name="BoxAttrs">
    <xs:attribute name="font"       type="xs:string"/>
    <xs:attribute name="font-size"  type="TokenScaleOrPt"/>
    <xs:attribute name="gap"        type="TokenScaleOrPt"/>
    <xs:attribute name="padding"    type="SpacingOrToken"/>
    <xs:attribute name="height"     type="HeightValue"/>
    <xs:attribute name="background" type="Color"/>
    <xs:attribute name="border"     type="BorderValue"/>
    <xs:attribute name="radius"     type="TokenScaleOrPt"/>
    <xs:attribute name="debug"      type="xs:boolean"/>
    <xs:attributeGroup ref="DataBindingAttrs"/>
  </xs:attributeGroup>

  <!-- Box attrs for frame — no gap (frame always centers its single child) -->
  <xs:attributeGroup name="FrameBoxAttrs">
    <xs:attribute name="font"       type="xs:string"/>
    <xs:attribute name="font-size"  type="TokenScaleOrPt"/>
    <xs:attribute name="padding"    type="SpacingOrToken"/>
    <xs:attribute name="height"     type="HeightValue"/>
    <xs:attribute name="background" type="Color"/>
    <xs:attribute name="border"     type="BorderValue"/>
    <xs:attribute name="radius"     type="TokenScaleOrPt"/>
    <xs:attribute name="debug"      type="xs:boolean"/>
    <xs:attributeGroup ref="DataBindingAttrs"/>
  </xs:attributeGroup>

  <!-- ============================================================
       Canvas primitives — named group of flat drawing elements.
       <layer> is not in this group; nesting is not permitted.
  ============================================================ -->

  <!-- Shared fill/stroke attributes for canvas primitives -->
  <xs:attributeGroup name="CanvasFillStrokeAttrs">
    <xs:attribute name="fill"         type="Color"/>
    <xs:attribute name="stroke"       type="Color"/>
    <xs:attribute name="stroke-width" type="PtValue"/>
    <xs:attribute name="stroke-dash"  type="xs:string"/>
    <xs:attribute name="opacity">
      <xs:simpleType>
        <xs:restriction base="xs:decimal">
          <xs:minInclusive value="0"/>
          <xs:maxInclusive value="1"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
  </xs:attributeGroup>

  <!-- Positioning rule (enforced by parser, not XSD 1.0):
       anchor OR (x AND y) must be present.
       When anchor is present, x/y are signed offsets from that reference point. -->
  <xs:group name="CanvasPrimitives">
    <xs:choice>

      <!-- rect -->
      <xs:element name="rect">
        <xs:complexType>
          <xs:attribute name="x"      type="SignedPtValue"/>
          <xs:attribute name="y"      type="SignedPtValue"/>
          <xs:attribute name="w"      type="PtValue" use="required"/>
          <xs:attribute name="h"      type="PtValue" use="required"/>
          <xs:attribute name="anchor" type="Anchor"/>
          <xs:attribute name="radius" type="PtValue"/>
          <xs:attributeGroup ref="CanvasFillStrokeAttrs"/>
        </xs:complexType>
      </xs:element>

      <!-- circle -->
      <xs:element name="circle">
        <xs:complexType>
          <xs:attribute name="cx"     type="SignedPtValue"/>
          <xs:attribute name="cy"     type="SignedPtValue"/>
          <xs:attribute name="r"      type="PtValue" use="required"/>
          <xs:attribute name="anchor" type="Anchor"/>
          <xs:attributeGroup ref="CanvasFillStrokeAttrs"/>
        </xs:complexType>
      </xs:element>

      <!-- ellipse -->
      <xs:element name="ellipse">
        <xs:complexType>
          <xs:attribute name="cx"     type="SignedPtValue"/>
          <xs:attribute name="cy"     type="SignedPtValue"/>
          <xs:attribute name="rx"     type="PtValue" use="required"/>
          <xs:attribute name="ry"     type="PtValue" use="required"/>
          <xs:attribute name="anchor" type="Anchor"/>
          <xs:attributeGroup ref="CanvasFillStrokeAttrs"/>
        </xs:complexType>
      </xs:element>

      <!-- line (no anchor — x1/y1/x2/y2 always required) -->
      <xs:element name="line">
        <xs:complexType>
          <xs:attribute name="x1"          type="SignedPtValue" use="required"/>
          <xs:attribute name="y1"          type="SignedPtValue" use="required"/>
          <xs:attribute name="x2"          type="SignedPtValue" use="required"/>
          <xs:attribute name="y2"          type="SignedPtValue" use="required"/>
          <xs:attribute name="stroke"       type="Color"/>
          <xs:attribute name="stroke-width" type="PtValue"/>
          <xs:attribute name="stroke-dash"  type="xs:string"/>
          <xs:attribute name="line-cap"     type="LineCap"/>
        </xs:complexType>
      </xs:element>

      <!-- path (no anchor — SVG-compatible d attribute) -->
      <xs:element name="path">
        <xs:complexType>
          <xs:attribute name="d"            type="xs:string" use="required"/>
          <xs:attribute name="fill"         type="Color"/>
          <xs:attribute name="stroke"       type="Color"/>
          <xs:attribute name="fill-rule"    type="FillRule"/>
          <xs:attribute name="stroke-width" type="PtValue"/>
          <xs:attribute name="stroke-dash"  type="xs:string"/>
          <xs:attribute name="line-cap"     type="LineCap"/>
          <xs:attribute name="opacity">
            <xs:simpleType>
              <xs:restriction base="xs:decimal">
                <xs:minInclusive value="0"/>
                <xs:maxInclusive value="1"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:complexType>
      </xs:element>

      <!-- text — absolutely positioned; <span> children for mixed runs -->
      <xs:element name="text">
        <xs:complexType mixed="true">
          <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element ref="span"/>
          </xs:choice>
          <xs:attribute name="x"           type="SignedPtValue"/>
          <xs:attribute name="y"           type="SignedPtValue"/>
          <xs:attribute name="anchor"      type="Anchor"/>
          <xs:attribute name="font"        type="xs:string"/>
          <xs:attribute name="font-size"   type="TokenScaleOrPt"/>
          <xs:attribute name="color"       type="Color"/>
          <xs:attribute name="align"       type="TextAlignH"/>
          <xs:attribute name="w"           type="PtValue"/>
          <xs:attribute name="line-height">
            <xs:simpleType>
              <xs:restriction base="xs:decimal">
                <xs:minInclusive value="0"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attribute name="opacity">
            <xs:simpleType>
              <xs:restriction base="xs:decimal">
                <xs:minInclusive value="0"/>
                <xs:maxInclusive value="1"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attributeGroup ref="DataBindingAttrs"/>
        </xs:complexType>
      </xs:element>

      <!-- img — absolutely positioned; w and h required (no auto-sizing) -->
      <xs:element name="img">
        <xs:complexType>
          <xs:attribute name="name"   type="xs:string" use="required"/>
          <xs:attribute name="x"      type="SignedPtValue"/>
          <xs:attribute name="y"      type="SignedPtValue"/>
          <xs:attribute name="w"      type="PtValue" use="required"/>
          <xs:attribute name="h"      type="PtValue" use="required"/>
          <xs:attribute name="anchor" type="Anchor"/>
          <xs:attributeGroup ref="DataBindingAttrs"/>
        </xs:complexType>
      </xs:element>

    </xs:choice>
  </xs:group>

  <!-- Canvas wrapper: contains absolute-coordinate content.
       Coordinates are top-left origin, y-down, relative to the full page.
       Page targeting is via <layer page="…">; bare primitives are not permitted. -->
  <xs:element name="canvas">
    <xs:complexType>
      <xs:sequence>
        <!-- layer: graphics state scope (page, opacity, transform, clip).
             All primitives must be inside a <layer>. Cannot nest. -->
        <xs:element name="layer" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:group ref="CanvasPrimitives" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="page"      type="PageScope"/>
            <xs:attribute name="opacity">
              <xs:simpleType>
                <xs:restriction base="xs:decimal">
                  <xs:minInclusive value="0"/>
                  <xs:maxInclusive value="1"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="transform" type="xs:string"/>
            <xs:attribute name="clip"      type="xs:string"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>


  <!-- ============================================================
       Layout content group — any layout element can nest any other
  ============================================================ -->

  <xs:group name="LayoutContent">
    <xs:choice>
      <xs:element ref="stack"/>
      <xs:element ref="flank"/>
      <xs:element ref="split"/>
      <xs:element ref="cluster"/>
      <xs:element ref="grid"/>
      <xs:element ref="frame"/>
      <xs:element ref="link"/>
      <xs:element ref="text"/>
      <xs:element ref="img"/>
      <xs:element ref="divider"/>
      <xs:element ref="table"/>
      <xs:element ref="barcode"/>
      <xs:element ref="field"/>
    </xs:choice>
  </xs:group>


  <!-- ============================================================
       Token elements
  ============================================================ -->

  <!-- Font asset: either a built-in PDF core font (core=) or a registry key (ref=) -->
  <xs:element name="font">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string"  use="required"/>
      <xs:attribute name="core" type="BuiltinFont"/>
      <xs:attribute name="ref"  type="xs:string"/>
      <xs:attribute name="src"  type="xs:anyURI"/>
    </xs:complexType>
  </xs:element>

  <!-- Image asset declared in <assets> -->
  <xs:element name="image">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string" use="required"/>
      <xs:attribute name="ref"  type="xs:string"/>
      <xs:attribute name="src"  type="xs:anyURI"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="color">
    <xs:complexType>
      <xs:attribute name="name"  type="xs:string" use="required"/>
      <xs:attribute name="value" type="ColorHex"  use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="tokens">
    <xs:complexType>
      <xs:all>
        <xs:element name="space"  type="TokenScaleRow" minOccurs="0"/>
        <xs:element name="border" type="TokenScaleRow" minOccurs="0"/>
        <xs:element name="radius" type="TokenScaleRow" minOccurs="0"/>
        <xs:element name="width"  type="TokenScaleRow" minOccurs="0"/>
        <xs:element name="text"   type="TokenScaleRow" minOccurs="0"/>
        <!-- "grid" and "space" share the same shape -->
        <xs:element name="grid"   type="TokenScaleRow" minOccurs="0"/>
        <xs:element name="colors" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element ref="color" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:all>
    </xs:complexType>
  </xs:element>

  <!-- Asset declarations: fonts and images used by layout elements -->
  <xs:element name="assets">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="font"/>
        <xs:element ref="image"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>


  <!-- ============================================================
       Document structure
  ============================================================ -->

  <xs:element name="meta">
    <xs:complexType>
      <xs:attribute name="title"    type="xs:string"/>
      <xs:attribute name="author"   type="xs:string"/>
      <xs:attribute name="subject"  type="xs:string"/>
      <xs:attribute name="keywords" type="xs:string"/>
      <xs:attribute name="creator"  type="xs:string"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="layout">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:group ref="LayoutContent"/>
        <!-- Pinned region: reserves a slot at the specified edge of the content area.
             pin="top|bottom" implemented in this phase.
             pin="left|right" schema-valid but deferred (requires w attribute).
             Only valid as a direct child of <layout>, not inside containers.
             At most one region per pin per physical page (parser-enforced). -->
        <xs:element name="region">
          <xs:complexType>
            <xs:sequence>
              <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="pin"   type="RegionPin" use="required"/>
            <xs:attribute name="page"  type="PageScope"/>
            <!-- w required for pin="left|right"; ignored for pin="top|bottom" (parser-enforced) -->
            <xs:attribute name="w"     type="PtValue"/>
            <xs:attribute name="debug" type="xs:boolean"/>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <!-- document: holds default page settings; contains one or more sections.
       Single-section shorthand: if <document> contains <layout> or <canvas>
       directly (no <section> children), treated as an implicit single section.
       Mixing direct <layout>/<canvas> with explicit <section> children is a parse error. -->
  <xs:element name="document">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="meta" minOccurs="0"/>
        <xs:choice>
          <!-- Explicit multi-section form -->
          <xs:sequence>
            <xs:element ref="section" maxOccurs="unbounded"/>
          </xs:sequence>
          <!-- Single-section shorthand: layout and/or canvas directly in document -->
          <xs:sequence>
            <xs:choice minOccurs="0">
              <xs:sequence>
                <xs:element ref="layout"/>
                <xs:element ref="canvas" minOccurs="0"/>
              </xs:sequence>
              <xs:sequence>
                <xs:element ref="canvas"/>
                <xs:element ref="layout" minOccurs="0"/>
              </xs:sequence>
            </xs:choice>
          </xs:sequence>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="font"        type="xs:string"/>
      <xs:attribute name="size"        type="PageSize"/>
      <xs:attribute name="orientation" type="Orientation"/>
      <xs:attribute name="margin"      type="SpacingValue"/>
      <xs:attribute name="background"  type="Color"/>
      <xs:attribute name="debug"       type="xs:boolean"/>
    </xs:complexType>
  </xs:element>

  <!-- section: a content boundary with its own auto-pagination.
       Attributes override document-level defaults for this section only.
       title becomes a PDF outline entry (bookmark).
       Four valid content combinations; document order = paint order. -->
  <xs:element name="section">
    <xs:complexType>
      <xs:choice minOccurs="0">
        <!-- layout only, or layout + canvas overlay (layout painted first) -->
        <xs:sequence>
          <xs:element ref="layout"/>
          <xs:element ref="canvas" minOccurs="0"/>
        </xs:sequence>
        <!-- canvas only, or canvas underlay + layout (canvas painted first) -->
        <xs:sequence>
          <xs:element ref="canvas"/>
          <xs:element ref="layout" minOccurs="0"/>
        </xs:sequence>
      </xs:choice>
      <xs:attribute name="size"        type="PageSize"/>
      <xs:attribute name="orientation" type="Orientation"/>
      <xs:attribute name="margin"      type="SpacingValue"/>
      <xs:attribute name="background"  type="Color"/>
      <xs:attribute name="title"       type="xs:string"/>
      <xs:attribute name="debug"       type="xs:boolean"/>
    </xs:complexType>
  </xs:element>

  <!-- Root element -->
  <xs:element name="lpdf">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="assets"   minOccurs="0"/>
        <xs:element ref="tokens"   minOccurs="0"/>
        <xs:element ref="document"/>
      </xs:sequence>
      <xs:attribute name="version" type="xs:positiveInteger" use="required"/>
    </xs:complexType>
  </xs:element>


  <!-- ============================================================
       Layout elements
  ============================================================ -->

  <xs:element name="stack">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="align"   type="AlignFull"/>
      <xs:attribute name="justify" type="Justify"/>
      <xs:attribute name="width"   type="TokenScaleOrPt"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="flank">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="align" type="Align"/>
      <xs:attribute name="end"   type="xs:boolean"/>
      <xs:attribute name="width" type="TokenScaleOrPt"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="split">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="align" type="Align"/>
      <xs:attribute name="equal" type="xs:boolean"/>
      <xs:attribute name="width" type="TokenScaleOrPt"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="cluster">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="align"   type="AlignFull"/>
      <xs:attribute name="justify" type="Justify"/>
      <xs:attribute name="width"   type="TokenScaleOrPt"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="grid">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="width" type="TokenScaleOrPt"/>
      <xs:attribute name="col-width" type="TokenScaleOrPt"/>
      <xs:attribute name="cols">
        <xs:simpleType>
          <xs:restriction base="xs:positiveInteger">
            <xs:minInclusive value="1"/>
            <xs:maxInclusive value="12"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <xs:element name="frame">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="1"/>
      </xs:sequence>
      <xs:attributeGroup ref="FrameBoxAttrs"/>
      <xs:attribute name="width" type="TokenScaleOrPt"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="link">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="href"   type="xs:anyURI" use="required"/>
      <xs:attribute name="gap"    type="SpacingOrToken"/>
      <xs:attribute name="debug"  type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="divider">
    <xs:complexType>
      <xs:attribute name="direction">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="horizontal"/>
            <xs:enumeration value="vertical"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="color"     type="Color"/>
      <xs:attribute name="thickness" type="TokenScaleOrPt"/>
      <xs:attribute name="debug"     type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="span">
    <xs:complexType mixed="true">
      <xs:attribute name="font"      type="xs:string"/>
      <xs:attribute name="color"     type="Color"/>
      <xs:attribute name="href"      type="xs:anyURI"/>
      <xs:attribute name="underline" type="xs:boolean"/>
      <xs:attribute name="strike"    type="xs:boolean"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="img">
    <xs:complexType>
      <!-- <img> uses a pt-only height constraint, not HeightMode (fill/full) -->
      <xs:attribute name="name"       type="xs:string"     use="required"/>
      <xs:attribute name="height"     type="PtValue"/>
      <xs:attribute name="width"      type="TokenScaleOrPt"/>
      <xs:attribute name="font"       type="xs:string"/>
      <xs:attribute name="font-size"  type="TokenScaleOrPt"/>
      <xs:attribute name="gap"        type="TokenScaleOrPt"/>
      <xs:attribute name="padding"    type="SpacingOrToken"/>
      <xs:attribute name="background" type="Color"/>
      <xs:attribute name="border"     type="BorderValue"/>
      <xs:attribute name="radius"     type="TokenScaleOrPt"/>
      <xs:attribute name="debug"      type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="barcode">
    <xs:complexType>
      <xs:attribute name="type" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="qr"/>
            <xs:enumeration value="code128"/>
            <xs:enumeration value="ean13"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="data"       type="xs:string"       use="required"/>
      <xs:attribute name="size"       type="TokenScaleOrPt"/>
      <xs:attribute name="width"      type="TokenScaleOrPt"/>
      <xs:attribute name="height"     type="PtValue"/>
      <xs:attribute name="ec">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="L"/>
            <xs:enumeration value="M"/>
            <xs:enumeration value="Q"/>
            <xs:enumeration value="H"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="hrt"        type="xs:boolean"/>
      <xs:attribute name="color"      type="Color"/>
      <xs:attribute name="background" type="Color"/>
      <xs:attribute name="debug"      type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="text">
    <xs:complexType mixed="true">
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="span"/>
      </xs:choice>
      <xs:attribute name="font-size" type="TokenScaleOrPt"/>
      <xs:attribute name="font"      type="xs:string"/>
      <xs:attribute name="color"     type="Color"/>
      <xs:attribute name="align"     type="TextAlignH"/>
      <xs:attribute name="width"     type="TokenScaleOrPt"/>
      <xs:attribute name="debug"     type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <!-- ============================================================
       Table elements
  ============================================================ -->

  <!-- <td>: a table cell — container equivalent to stack -->
  <xs:element name="td">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="LayoutContent" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attributeGroup ref="BoxAttrs"/>
      <xs:attribute name="align"  type="Align"/>
      <xs:attribute name="valign">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="top"/>
            <xs:enumeration value="middle"/>
            <xs:enumeration value="bottom"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>

  <!-- <thead>: header row — repeated at the top of each new page -->
  <xs:element name="thead">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="td" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="background" type="Color"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <!-- <tr>: a data row -->
  <xs:element name="tr">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="td" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="background" type="Color"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <!-- <table>: tabular layout with explicit column widths -->
  <xs:element name="table">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="thead" minOccurs="0" maxOccurs="1"/>
        <xs:element ref="tr"    minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <!-- cols: space-separated column widths — fr, pt, % units.
           Example: "2fr 1fr 120pt 20%" -->
      <xs:attribute name="cols"       type="xs:string" use="required"/>
      <xs:attribute name="border"     type="BorderValue"/>
      <xs:attribute name="stripe"     type="Color"/>
      <xs:attribute name="gap"        type="TokenScaleOrPt"/>
      <xs:attribute name="padding"    type="SpacingOrToken"/>
      <xs:attribute name="background" type="Color"/>
      <xs:attribute name="width"      type="TokenScaleOrPt"/>
      <xs:attribute name="height"     type="HeightValue"/>
      <xs:attribute name="debug"      type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

  <!-- ============================================================
       Form field element
  ============================================================ -->

  <xs:element name="field">
    <xs:complexType>
      <xs:attribute name="type" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="text"/>
            <xs:enumeration value="checkbox"/>
            <xs:enumeration value="dropdown"/>
            <xs:enumeration value="radio"/>
            <xs:enumeration value="button"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
      <xs:attribute name="name"       type="xs:string" use="required"/>
      <xs:attribute name="value"      type="xs:string"/>
      <xs:attribute name="label"      type="xs:string"/>
      <xs:attribute name="options"    type="xs:string"/>
      <xs:attribute name="group"      type="xs:string"/>
      <xs:attribute name="checked"    type="xs:boolean"/>
      <xs:attribute name="required"   type="xs:boolean"/>
      <xs:attribute name="readonly"   type="xs:boolean"/>
      <xs:attribute name="max-len"    type="xs:positiveInteger"/>
      <xs:attribute name="action-url" type="xs:anyURI"/>
      <xs:attribute name="width"      type="TokenScaleOrPt"/>
      <xs:attribute name="height"     type="PtValue"/>
      <xs:attribute name="debug"      type="xs:boolean"/>
      <xs:attributeGroup ref="DataBindingAttrs"/>
    </xs:complexType>
  </xs:element>

</xs:schema>
