{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ingot-grid",
  "type": "registry:ui",
  "title": "Ingot Grid",
  "description": "A responsive bento layout primitive — IngotGrid and IngotCell compose column/row spans into magazine-style tiles with beveled borders that brighten on hover while sibling cells dim.",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/cards/ingot-grid/ingot-grid.tsx",
      "type": "registry:ui",
      "target": "components/crucible/ingot-grid.tsx",
      "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface IngotGridProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  /** IngotCell children (or any content). */\n  children: React.ReactNode;\n  /** Columns at the desktop (`lg`) breakpoint. Mobile is always 1 column, `sm` is 2. @default 4 */\n  columns?: 2 | 3 | 4 | 5 | 6;\n  /** Height of an implicit row in px — controls how tall a `rowSpan` step is. @default 140 */\n  rowHeight?: number;\n  /** Gap between cells, any CSS length or a number of px. @default 16 */\n  gap?: number | string;\n}\n\nconst COLUMN_CLASSES: Record<number, string> = {\n  2: \"lg:grid-cols-2\",\n  3: \"lg:grid-cols-3\",\n  4: \"lg:grid-cols-4\",\n  5: \"lg:grid-cols-5\",\n  6: \"lg:grid-cols-6\",\n};\n\n/**\n * IngotGrid — a responsive bento layout primitive. Compose it with\n * `IngotCell` children that declare `colSpan`/`rowSpan` to build\n * magazine-style tile layouts. Base component for future marketing\n * sections — keep consumers to the `columns`/`gap` knobs and cell spans,\n * nothing structural.\n */\nexport function IngotGrid({\n  children,\n  className,\n  style,\n  columns = 4,\n  rowHeight = 140,\n  gap = 16,\n  ...props\n}: IngotGridProps) {\n  return (\n    <div\n      data-crucible=\"ingot-grid\"\n      className={cn(\n        \"grid grid-cols-1 sm:grid-cols-2\",\n        COLUMN_CLASSES[columns] ?? COLUMN_CLASSES[4],\n        className\n      )}\n      style={{\n        gap: typeof gap === \"number\" ? `${gap}px` : gap,\n        gridAutoRows: typeof rowHeight === \"number\" ? `${rowHeight}px` : rowHeight,\n        ...style,\n      }}\n      {...props}\n    >\n      <style>{`\n        [data-crucible=\"ingot-grid\"]:has(.ingot-cell:hover) .ingot-cell:not(:hover) {\n          opacity: 0.45;\n        }\n        @media (prefers-reduced-motion: reduce) {\n          [data-crucible=\"ingot-grid\"] .ingot-cell {\n            transition: border-color 200ms ease, opacity 200ms ease, box-shadow 200ms ease;\n          }\n          [data-crucible=\"ingot-grid\"] .ingot-cell:hover {\n            transform: none;\n          }\n        }\n      `}</style>\n      {children}\n    </div>\n  );\n}\n\nexport interface IngotCellProps extends React.ComponentPropsWithoutRef<\"div\"> {\n  /** Cell content — any header/icon/title/description markup. */\n  children?: React.ReactNode;\n  /** Columns this cell spans at `lg` (clamped to 1 on mobile and 2 at `sm`). @default 1 */\n  colSpan?: 1 | 2 | 3 | 4;\n  /** Rows this cell spans. @default 1 */\n  rowSpan?: 1 | 2 | 3;\n}\n\n// Spans collapse with the breakpoints so a wide cell never forces implicit\n// overflow columns: 1 column on mobile, at most 2 at `sm`, the full span at `lg`.\nconst COL_SPAN_CLASSES: Record<number, string> = {\n  1: \"col-span-1\",\n  2: \"col-span-1 sm:col-span-2\",\n  3: \"col-span-1 sm:col-span-2 lg:col-span-3\",\n  4: \"col-span-1 sm:col-span-2 lg:col-span-4\",\n};\n\nconst ROW_SPAN_CLASSES: Record<number, string> = {\n  1: \"row-span-1\",\n  2: \"row-span-2\",\n  3: \"row-span-3\",\n};\n\n/**\n * IngotCell — a single tile inside `IngotGrid`. Reads as a stacked slab:\n * a beveled border, a soft vertical sheen, and a faint top-edge highlight.\n * On hover it lifts slightly and blooms — border brightens white and a\n * soft monochrome glow spreads beneath it — while sibling cells dim, so\n * the grid concentrates attention on the tile under the cursor. The lift\n * is skipped under `prefers-reduced-motion`; the border/glow/dim\n * choreography (color and opacity, not motion) still runs.\n */\nexport function IngotCell({\n  children,\n  className,\n  colSpan = 1,\n  rowSpan = 1,\n  ...props\n}: IngotCellProps) {\n  return (\n    <div\n      className={cn(\n        \"ingot-cell\",\n        \"relative overflow-hidden rounded-xl border border-white/10 bg-gradient-to-b from-white/[0.08] via-white/[0.03] to-transparent p-5\",\n        \"shadow-[inset_0_1px_0_rgba(255,255,255,0.07)]\",\n        \"transition-[transform,border-color,opacity,box-shadow] duration-300 ease-out\",\n        \"hover:-translate-y-1 hover:border-white/55\",\n        \"hover:shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_0_0_1px_rgba(255,255,255,0.08),0_12px_36px_-12px_rgba(255,255,255,0.22),0_0_28px_-6px_rgba(255,255,255,0.14)]\",\n        \"before:pointer-events-none before:absolute before:inset-x-0 before:top-0 before:h-px before:bg-gradient-to-r before:from-transparent before:via-white/35 before:to-transparent\",\n        COL_SPAN_CLASSES[colSpan] ?? COL_SPAN_CLASSES[1],\n        ROW_SPAN_CLASSES[rowSpan] ?? ROW_SPAN_CLASSES[1],\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n}\n"
    }
  ]
}