{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://decantr.ai/schemas/pattern.v2.json",
  "title": "Decantr Pattern",
  "type": "object",
  "required": [
    "$schema",
    "id",
    "version",
    "name",
    "description",
    "components",
    "default_preset",
    "presets"
  ],
  "properties": {
    "$schema": {
      "const": "https://decantr.ai/schemas/pattern.v2.json"
    },
    "id": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
    },
    "version": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
    },
    "decantr_compat": {
      "type": "string"
    },
    "name": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
    },
    "description": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
    },
    "tags": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
    },
    "dependencies": {
      "type": "object",
      "additionalProperties": true
    },
    "components": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
    },
    "default_preset": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
    },
    "presets": {
      "type": "object",
      "minProperties": 1,
      "additionalProperties": {
        "type": "object",
        "required": [
          "description",
          "layout"
        ],
        "properties": {
          "description": {
            "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyString"
          },
          "components": {
            "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
          },
          "layout": {
            "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/patternLayoutSpec"
          },
          "code": {
            "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/codeSpec"
          }
        },
        "additionalProperties": true
      }
    },
    "contained": {
      "type": "boolean"
    },
    "io": {
      "type": "object",
      "properties": {
        "produces": {
          "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
        },
        "consumes": {
          "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
        },
        "actions": {
          "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
        }
      },
      "additionalProperties": true
    },
    "code": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/codeSpec"
    },
    "default_layout": {
      "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/patternLayoutSpec"
    },
    "visual_brief": {
      "type": "string"
    },
    "composition": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "motion": {
      "type": "object",
      "additionalProperties": true
    },
    "interactions": {
      "type": "array",
      "description": "Declared runtime interactions that the rendered pattern MUST implement. Surfaced as a checkbox checklist in the per-page execution pack; enforced by decantr check --strict. Each value maps to a canonical implementation: a specific treatment class, handler pattern, or both — see 'Interaction Requirements' table in DECANTR.md for the mapping. Before this field, motion/interactivity lived only as prose philosophy that cold LLMs categorized as 'nice to have'.",
      "items": {
        "type": "string",
        "enum": [
          "animate-on-mount",
          "stagger-children",
          "status-pulse",
          "shimmer-skeleton",
          "float-idle",
          "glow-hover",
          "lift-hover",
          "scale-hover",
          "ripple-click",
          "drag-nodes",
          "drag-reorder",
          "pan-background",
          "zoom-scroll",
          "zoom-pinch",
          "click-select",
          "click-connect",
          "inline-edit",
          "hover-tooltip",
          "hover-reveal",
          "live-simulation",
          "real-time-updates",
          "scroll-reveal",
          "keyboard-navigation",
          "focus-trap"
        ]
      },
      "uniqueItems": true
    },
    "responsive": {
      "type": "object",
      "description": "Per-breakpoint adaptation. Keys are viewport breakpoint tokens (e.g., 'mobile', 'tablet', 'desktop', or '<768px', '>=900px'). Values may be either a legacy prose string OR a structured ResponsiveBreakpointRule object. Prefer structured rules so the LLM can adapt mechanically instead of paraphrasing.",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "description": "Legacy prose form — kept for backward compatibility."
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "layout": {
                "type": "string",
                "enum": ["stack", "grid", "flex-row", "flex-column", "hide", "alternate-pattern"],
                "description": "Top-level layout strategy at this breakpoint. 'hide' removes the pattern entirely; 'alternate-pattern' swaps to the pattern id in alternate_pattern_id."
              },
              "columns": {
                "type": "integer",
                "minimum": 1,
                "maximum": 12,
                "description": "Grid column count when layout=grid."
              },
              "gap": {
                "type": "string",
                "description": "Gap as a CSS length, density-token, or atom (e.g., '1rem', 'var(--d-content-gap)', '_gap4')."
              },
              "hide_components": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Component ids/aliases rendered by this pattern that should be hidden at this breakpoint."
              },
              "stack_order": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Explicit order when layout=stack. Useful when the default DOM order doesn't map to the intended mobile reading order."
              },
              "alternate_pattern_id": {
                "type": "string",
                "description": "Pattern id to substitute when layout=alternate-pattern. Use for desktop-only patterns that need a mobile-specific counterpart."
              },
              "horizontal_scroll": {
                "type": "boolean",
                "description": "If true: permit horizontal scroll at this breakpoint (e.g., data table on mobile). Default false."
              },
              "notes": {
                "type": "string",
                "description": "Prose that doesn't fit the structured fields. Short."
              }
            }
          }
        ]
      }
    },
    "accessibility": {
      "type": "object",
      "properties": {
        "role": {
          "type": "string"
        },
        "aria-label": {
          "type": "string"
        },
        "keyboard": {
          "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
        },
        "announcements": {
          "$ref": "https://decantr.ai/schemas/common.v1.json#/$defs/nonEmptyStringArray"
        },
        "focus_management": {
          "type": "string"
        }
      },
      "additionalProperties": true
    },
    "layout_hints": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "category": {
      "type": "string"
    }
  },
  "additionalProperties": true
}
