{
  "$schema": "https://www.digitaltableteur.com/schemas/contract-spec/1.0/contract.schema.json",
  "specVersion": "1.0",
  "name": "HeroSection",
  "status": "stable",
  "description": "Full-bleed hero shell with min-height, alignment, and background variants.",
  "props": {
    "children": {
      "type": "ReactNode",
      "optional": false,
      "description": "Hero content"
    },
    "background": {
      "type": "union",
      "values": [
        "image",
        "transparent",
        "solid",
        "gradient"
      ],
      "optional": true,
      "description": "Background style variant. Defaults to `transparent`."
    },
    "backgroundImage": {
      "type": "string",
      "optional": true,
      "description": "Background image URL (only used when background=\"image\")"
    },
    "minHeight": {
      "type": "union",
      "values": [
        "auto",
        "hero",
        "screen",
        "half"
      ],
      "optional": true,
      "description": "Minimum height of the hero section. Defaults to `hero` (75vh); `screen` is\n100vh, `half` 50vh, `auto` none."
    },
    "align": {
      "type": "union",
      "values": [
        "center",
        "start",
        "end"
      ],
      "optional": true,
      "description": "Horizontal (cross-axis) alignment of the content. The root is a flex\ncolumn, so this maps to items-*. Defaults to `center`."
    },
    "justify": {
      "type": "union",
      "values": [
        "center",
        "start",
        "end"
      ],
      "optional": true,
      "description": "Vertical (main-axis) alignment of the content within the min-height. The\nroot is a flex column, so this maps to justify-*. Defaults to `center`."
    },
    "className": {
      "type": "string",
      "optional": true,
      "description": "Custom className for styling extensions"
    },
    "as": {
      "type": "union",
      "values": [
        "symbol",
        "object",
        "image",
        "form",
        "slot",
        "style",
        "title",
        "button",
        "search",
        "article",
        "dialog",
        "figure",
        "img",
        "link",
        "main",
        "menu",
        "menuitem",
        "option",
        "switch",
        "table",
        "text",
        "time",
        "div",
        "section",
        "aside",
        "li",
        "a",
        "abbr",
        "address",
        "area",
        "audio",
        "b",
        "base",
        "bdi",
        "bdo",
        "big",
        "blockquote",
        "body",
        "br",
        "canvas",
        "caption",
        "center",
        "cite",
        "code",
        "col",
        "colgroup",
        "data",
        "datalist",
        "dd",
        "del",
        "details",
        "dfn",
        "dl",
        "dt",
        "em",
        "embed",
        "fieldset",
        "figcaption",
        "footer",
        "h1",
        "h2",
        "h3",
        "h4",
        "h5",
        "h6",
        "head",
        "header",
        "hgroup",
        "hr",
        "html",
        "i",
        "iframe",
        "input",
        "ins",
        "kbd",
        "keygen",
        "label",
        "legend",
        "map",
        "mark",
        "meta",
        "meter",
        "nav",
        "noindex",
        "noscript",
        "ol",
        "optgroup",
        "output",
        "p",
        "param",
        "picture",
        "pre",
        "progress",
        "q",
        "rp",
        "rt",
        "ruby",
        "s",
        "samp",
        "script",
        "select",
        "small",
        "source",
        "span",
        "strong",
        "sub",
        "summary",
        "sup",
        "template",
        "tbody",
        "td",
        "textarea",
        "tfoot",
        "th",
        "thead",
        "tr",
        "track",
        "u",
        "ul",
        "var",
        "video",
        "wbr",
        "webview",
        "svg",
        "animate",
        "animateMotion",
        "animateTransform",
        "circle",
        "clipPath",
        "defs",
        "desc",
        "ellipse",
        "feBlend",
        "feColorMatrix",
        "feComponentTransfer",
        "feComposite",
        "feConvolveMatrix",
        "feDiffuseLighting",
        "feDisplacementMap",
        "feDistantLight",
        "feDropShadow",
        "feFlood",
        "feFuncA",
        "feFuncB",
        "feFuncG",
        "feFuncR",
        "feGaussianBlur",
        "feImage",
        "feMerge",
        "feMergeNode",
        "feMorphology",
        "feOffset",
        "fePointLight",
        "feSpecularLighting",
        "feSpotLight",
        "feTile",
        "feTurbulence",
        "filter",
        "foreignObject",
        "g",
        "line",
        "linearGradient",
        "marker",
        "mask",
        "metadata",
        "mpath",
        "path",
        "pattern",
        "polygon",
        "polyline",
        "radialGradient",
        "rect",
        "set",
        "stop",
        "textPath",
        "tspan",
        "use",
        "view"
      ],
      "optional": true,
      "description": "Semantic HTML element to render as. Defaults to `section`. Typed as any\nReact ElementType, so the values list is every JSX intrinsic; only\nsection-level elements (section, header, div) make sense here."
    },
    "ariaLabel": {
      "type": "string",
      "optional": true,
      "description": "ARIA label for accessibility"
    }
  },
  "rules": [
    {
      "id": "hero-background-image-needs-image-mode",
      "when": {
        "backgroundImage": {
          "present": true
        },
        "background": {
          "oneOf": [
            "gradient",
            "solid",
            "transparent"
          ]
        }
      },
      "forbid": [
        "backgroundImage"
      ],
      "reason": "`backgroundImage` only renders when background=\"image\"; with any other background it is silently dropped.",
      "severity": "error",
      "evidence": "HeroSection.tsx: hasBackgroundImage = background === \"image\" && backgroundImage"
    },
    {
      "id": "hero-background-image-default-mode",
      "when": {
        "backgroundImage": {
          "present": true
        },
        "background": {
          "absent": true
        }
      },
      "requireAllOf": [
        "background"
      ],
      "reason": "`background` defaults to \"transparent\", which drops `backgroundImage`. Set background=\"image\".",
      "severity": "error",
      "evidence": "HeroSection.tsx: background defaults to \"transparent\""
    }
  ],
  "accessibility": {
    "criteria": [
      {
        "id": "axe-no-violations",
        "statement": "Required stories produce no axe violations at the configured severity.",
        "verification": "automated",
        "wcag": [
          "2.5.8"
        ],
        "check": "npm run test:stories:matrix:ci",
        "evidence": [
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.227Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:21.591Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.232Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.822Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:22.110Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.897Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:20.107Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:22.372Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:18.240Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.510Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:21.855Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.538Z",
            "passed": true,
            "runner": "local-recapture"
          }
        ]
      },
      {
        "id": "accessibility-tree",
        "statement": "The accessibility tree (role, name, state) matches the committed snapshot for every required story.",
        "verification": "automated",
        "wcag": [
          "1.3.1",
          "4.1.2"
        ],
        "check": "npm run test:stories:matrix:ci",
        "evidence": [
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.227Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:28.509Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:21.591Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.232Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.822Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:29.062Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:22.110Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.897Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:20.107Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:29.341Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:22.372Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:18.240Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.dark.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:38:19.510Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:28.772Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:17:21.855Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.light.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:29:17.538Z",
            "passed": true,
            "runner": "local-recapture"
          }
        ]
      },
      {
        "id": "forced-colors-real-browser",
        "statement": "The component remains legible and operable under a real browser forced-colors: active pass.",
        "verification": "automated",
        "check": "npm run test:stories:hc",
        "evidence": [
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-default.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:28.509Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-example.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:29.062Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-forced-colors.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:29.341Z",
            "passed": true,
            "runner": "local-recapture"
          },
          {
            "artifact": "../../../nextjs-app/shared/patterns/HeroSection/__a11y-evidence__/patterns-herosection-playground.forced-colors.json",
            "sourceCommit": "930c562b591b6d9967e1e8c214899052624d9a2f",
            "capturedAt": "2026-11-03T22:45:28.772Z",
            "passed": true,
            "runner": "local-recapture"
          }
        ]
      },
      {
        "id": "human-a11y-review",
        "statement": "A human completed an end-to-end accessibility review of this component.",
        "verification": "manual",
        "note": "2026-05-28 — Breadth beta port: keyboard/ARIA contract reviewed, ForcedColors story added, Storybook axe gate (parameters.a11y.test: error). 2026-07-09 — Promoted beta→stable: AT snapshots captured for all required stories (base mode, pattern-tier convention), forced-colors re-verified in a real browser, consumers audited.",
        "reviewedAt": "2026-11-04"
      }
    ]
  },
  "governance": {
    "owner": "design-system",
    "lastReviewed": "2026-11-04",
    "note": "Reviewed by Petri Lahdelma; prepared by Claude from a code review on 2026-11-03"
  },
  "source": [
    "../../../nextjs-app/shared/patterns/HeroSection/HeroSection.tsx"
  ]
}
