{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hand-matrix",
  "title": "Hand matrix",
  "description": "The 13×13 range grid. Each cell is a stacked bar of action frequencies for one hand class.",
  "files": [
    {
      "path": "src/components/pokerstudy/hand-matrix.tsx",
      "content": "/** One 13×13 cell: the class label and its per-action frequency split. */\nexport interface MatrixCell {\n  label: string;\n  /** Frequency per action, parallel to the `colors` array. */\n  freqs: number[];\n}\n\n/**\n * The 13×13 hand matrix and its legend. Each cell is a stacked bar of action\n * frequencies for one hand class; a `null` cell (class not in range) is the\n * empty dark square. Pass `onSelect` to make cells clickable.\n */\nexport function HandMatrix({\n  cells,\n  colors,\n  legend,\n  selected,\n  onSelect,\n}: {\n  /** 169 cells, row-major A→2 by A→2 (suited above the diagonal). */\n  cells: (MatrixCell | null)[];\n  /** Per-action colors, parallel to each cell's `freqs`. */\n  colors: string[];\n  /** Legend entries under the grid, one per action. */\n  legend: { label: string; color: string }[];\n  /** Label of the highlighted cell, e.g. \"AKs\". */\n  selected?: string | null;\n  onSelect?: (label: string) => void;\n}) {\n  return (\n    <div className=\"flex w-full max-w-[560px] flex-col gap-4\">\n      <div className=\"grid aspect-square w-full grid-cols-[repeat(13,minmax(0,1fr))] grid-rows-[repeat(13,minmax(0,1fr))] gap-px overflow-hidden rounded-md\">\n        {cells.map((cell, i) => {\n          if (!cell) {\n            return (\n              <div key={i} className=\"relative overflow-hidden rounded-[1px]\">\n                <div className=\"size-full bg-white/[0.04]\" />\n              </div>\n            );\n          }\n          const body = (\n            <>\n              <div className=\"absolute inset-0 flex\">\n                {cell.freqs.map((f, a) =>\n                  f <= 0.001 ? null : (\n                    <div key={a} style={{ flexGrow: f, backgroundColor: colors[a] }} />\n                  ),\n                )}\n              </div>\n              <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n                <span className=\"text-[9px] font-bold leading-[11px] text-white [text-shadow:0_0_2px_rgba(0,0,0,0.85)]\">\n                  {cell.label}\n                </span>\n              </div>\n              {selected === cell.label ? (\n                <div aria-hidden className=\"pointer-events-none absolute inset-0 ring-2 ring-inset ring-white\" />\n              ) : null}\n            </>\n          );\n          return onSelect ? (\n            <button\n              key={i}\n              type=\"button\"\n              aria-label={cell.label}\n              aria-pressed={selected === cell.label}\n              onClick={() => onSelect(cell.label)}\n              className=\"relative overflow-hidden rounded-[1px] focus-visible:outline-2 focus-visible:outline-white\"\n            >\n              {body}\n            </button>\n          ) : (\n            <div key={i} className=\"relative overflow-hidden rounded-[1px]\">\n              {body}\n            </div>\n          );\n        })}\n      </div>\n\n      <div className=\"flex flex-wrap justify-center gap-4\">\n        {legend.map((it, i) => (\n          <div key={i} className=\"flex items-center gap-1.5\">\n            <span className=\"size-3 rounded-[3px]\" style={{ backgroundColor: it.color }} />\n            <span className=\"text-xs text-muted-foreground\">{it.label}</span>\n          </div>\n        ))}\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/pokerstudy/hand-matrix.tsx"
    }
  ],
  "type": "registry:component"
}