{
  "$schema": "https://www.digitaltableteur.com/schemas/contract-spec/1.0/contract.schema.json",
  "specVersion": "1.0",
  "name": "PixelLoop",
  "status": "beta",
  "description": "Decorative constellation loop with rounded-dot and 45-degree vector-stroke variants; the glyph pool includes the studio D and T initials.",
  "package": {
    "name": "@digitaltableteur/react",
    "import": "import { PixelLoop } from \"@digitaltableteur/react\";"
  },
  "props": {
    "size": {
      "type": "union",
      "values": [
        "sm",
        "md",
        "lg"
      ],
      "optional": true,
      "description": "Scales the glyphs and the equal space between them."
    },
    "variant": {
      "type": "union",
      "values": [
        "dots",
        "strokes"
      ],
      "optional": true,
      "description": "Rounded dots or short, round-capped 45-degree strokes."
    },
    "rows": {
      "type": "PixelLoopRows",
      "optional": true,
      "description": "Number of three-cell rows in the field."
    },
    "animate": {
      "type": "boolean",
      "optional": true,
      "description": "Runs the cross-fade cycle. Disable for a deliberate static composition."
    },
    "cycle": {
      "type": "boolean",
      "optional": true,
      "description": "Renders a single glyph cell (one row, one column) that steps through the\nwhole glyph pool one formation at a time. Ignores `rows`."
    },
    "collapsed": {
      "type": "boolean",
      "optional": true,
      "description": "One row only (`rows={1}`): shows just the first cell, and the loop is one\ncell wide. Turning it false grows the other cells open left to right, so\na title that follows the loop slides along with it; instant when the\nvisitor prefers reduced motion. Ignored with `cycle` and more rows."
    }
  },
  "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/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.139Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:26.478Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:27.746Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.632Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:27.013Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:28.236Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.871Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:27.291Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:28.472Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.387Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:26.755Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:27.997Z",
            "passed": true,
            "runner": "local-audit-fixes"
          }
        ]
      },
      {
        "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/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.139Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.160Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:26.478Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:27.746Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.632Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.644Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:27.013Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:28.236Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.871Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.890Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:27.291Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:28.472Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.dark.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:26:10.387Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.400Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:12:26.755Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.light.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:19:27.997Z",
            "passed": true,
            "runner": "local-audit-fixes"
          }
        ]
      },
      {
        "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/components/PixelLoop/__a11y-evidence__/display-pixelloop-default.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.160Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-example.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.644Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-forced-colors.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.890Z",
            "passed": true,
            "runner": "local-audit-fixes"
          },
          {
            "artifact": "../../../nextjs-app/shared/components/PixelLoop/__a11y-evidence__/display-pixelloop-playground.forced-colors.json",
            "sourceCommit": "ffbeeeec52e120b19494e2ac7b4dbab8ff13ceb3",
            "capturedAt": "2026-11-07T09:33:13.400Z",
            "passed": true,
            "runner": "local-audit-fixes"
          }
        ]
      },
      {
        "id": "reduced-motion",
        "statement": "Positional, scale, and opacity motion is suppressed under prefers-reduced-motion.",
        "verification": "manual",
        "wcag": [
          "2.2.2",
          "2.3.3"
        ],
        "reviewedAt": "2026-10-31"
      },
      {
        "id": "keyboard-contract",
        "statement": "Every documented keyboard interaction works as specified.",
        "verification": "unverified",
        "wcag": [
          "2.1.1",
          "2.1.2"
        ],
        "note": "No exportable evidence record for this check; re-run the check to capture one."
      },
      {
        "id": "aria-requirements",
        "statement": "Documented ARIA roles, states, and properties are present on the rendered output.",
        "verification": "unverified",
        "wcag": [
          "4.1.2"
        ],
        "note": "No exportable evidence record for this check; re-run the check to capture one."
      },
      {
        "id": "human-a11y-review",
        "statement": "A human completed an end-to-end accessibility review of this component.",
        "verification": "manual",
        "note": "2026-10-31: reviewed live in Storybook (Default, Example, ForcedColors). The root is aria-hidden with no role, every SVG has focusable=\"false\", there are no focusable descendants and no text reaches the accessibility tree. Under prefers-reduced-motion the cross-fade stops and each cell keeps its first glyph, so the composition stays static rather than blank; animate={false} gives the same still frame. Cells swap at most every 0.6 s over a small area, well below the WCAG 2.3.1 flash threshold. Marks inherit the text colour and switch to CanvasText in forced colors. Because the loop runs indefinitely with no on-page pause, use it as a small accent beside content, not as a large hero behind reading text (WCAG 2.2.2).",
        "reviewedAt": "2026-10-31"
      }
    ]
  },
  "governance": {
    "owner": "design-system",
    "lastReviewed": "2026-10-31",
    "note": "The Primary Studio reference informed the compact modular format, while original 5x5 vector cell-grid artwork, round marks, row-aware choreography, and timing establish a distinct implementation. Supports one, two, or three rows of three glyph grids."
  },
  "source": [
    "../../../nextjs-app/shared/components/PixelLoop/PixelLoop.module.css",
    "../../../nextjs-app/shared/components/PixelLoop/PixelLoop.tsx"
  ]
}
