{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "record-card",
  "title": "Record card",
  "description": "A triumph / record card (the in-game Triumphs & Seals grid): a circular record icon + title, a divider, an objective description, a right-aligned reward or completion check, and a thin progress edge — continuous or `steps` segments.",
  "dependencies": [
    "@engram/core"
  ],
  "registryDependencies": [
    "@engram/bungie-image",
    "@engram/cn",
    "@engram/tokens"
  ],
  "files": [
    {
      "path": "src/components/record-card.tsx",
      "content": "import type { ImageRef } from \"@engram/core\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport { BungieImage } from \"./bungie-image.js\";\n\nexport interface RecordCardProps\n  extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n  title: ReactNode;\n  /** The objective summary line. */\n  description?: ReactNode;\n  /** Triumph/record icon (rendered in a circular frame, in-game style). */\n  icon?: ImageRef;\n  /** Completed → gold check + gold-tinted card and a gold (full) progress edge. */\n  complete?: boolean;\n  /**\n   * Progress 0–1 for the bottom edge. Omit for a boolean triumph (no bar).\n   * White-ish while in progress, gold when `complete`.\n   */\n  progress?: number;\n  /**\n   * Discrete part count — when set, the bottom edge renders as `steps` segments\n   * (e.g. \"collect all 7\") instead of a continuous bar.\n   */\n  steps?: number;\n  /** Right-aligned reward / score slot (overrides the completion check). */\n  reward?: ReactNode;\n}\n\nfunction CheckMark() {\n  return (\n    <svg\n      viewBox=\"0 0 14 14\"\n      className=\"size-4 text-engram-gold\"\n      aria-label=\"complete\"\n      role=\"img\"\n    >\n      <path\n        d=\"M3 7.5 6 10.5l5.5-6.5\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"square\"\n      />\n    </svg>\n  );\n}\n\n/**\n * A triumph / record card (the in-game Triumphs & Seals grid): a circular record\n * icon + title, a divider, an objective description, a right-aligned reward or\n * completion check, and a thin progress edge — continuous or `steps` segments.\n * The edge is white-ish in progress and gold when complete; boolean triumphs\n * (no `progress`/`steps`) show no edge. Distinct from the magenta seal progress.\n */\nexport function RecordCard({\n  title,\n  description,\n  icon,\n  complete = false,\n  progress,\n  steps,\n  reward,\n  className,\n  ...props\n}: RecordCardProps) {\n  const hasBar = progress != null || steps != null;\n  const fill = complete ? \"var(--engram-gold)\" : \"var(--engram-bar)\";\n  const pct = complete ? 1 : Math.max(0, Math.min(1, progress ?? 0));\n  const filled = steps ? Math.round(pct * steps) : 0;\n  return (\n    <div\n      className={cn(\n        \"relative flex flex-col overflow-hidden border\",\n        complete\n          ? \"border-engram-gold/45 bg-[color-mix(in_oklch,var(--engram-gold)_7%,var(--engram-raised))]\"\n          : \"border-engram-border bg-engram-raised\",\n        className,\n      )}\n      {...props}\n    >\n      <div className=\"flex flex-1 flex-col px-3 py-2.5\">\n        {/* Title row: record glyph + title, with a reward in the corner. Glyphs\n            are transparent light line-art rendered in place (no circle); a theme\n            backing keeps them visible — transparent on dark, a dark chip on the\n            light canvas. */}\n        <div className=\"flex items-center gap-2.5\">\n          {icon ? (\n            <BungieImage\n              src={icon}\n              alt=\"\"\n              aria-hidden\n              className=\"size-7 shrink-0 rounded-sm object-contain\"\n              style={{\n                background: \"var(--engram-glyph-bg)\",\n                padding: \"var(--engram-glyph-pad)\",\n              }}\n            />\n          ) : (\n            <span\n              aria-hidden\n              className=\"grid size-7 shrink-0 place-items-center rounded-sm\"\n              style={{\n                background: \"var(--engram-glyph-bg)\",\n                padding: \"var(--engram-glyph-pad)\",\n              }}\n            >\n              <span className=\"size-2 rotate-45 bg-engram-muted\" />\n            </span>\n          )}\n          <span className=\"min-w-0 flex-1 truncate font-engram-display font-bold text-[13px] text-engram-fg leading-tight tracking-[0.01em]\">\n            {title}\n          </span>\n          {reward != null ? <span className=\"shrink-0\">{reward}</span> : null}\n        </div>\n\n        {description != null ? (\n          <div className=\"my-2 border-engram-border/60 border-t\" />\n        ) : null}\n\n        {/* Bottom row (below the divider): description + the completion check,\n            matching the in-game placement. */}\n        {description != null || (complete && reward == null) ? (\n          <div className=\"flex items-center gap-2\">\n            {description != null ? (\n              <p className=\"line-clamp-2 min-w-0 flex-1 text-[12px] text-engram-muted leading-snug\">\n                {description}\n              </p>\n            ) : (\n              <span className=\"flex-1\" />\n            )}\n            {complete && reward == null ? <CheckMark /> : null}\n          </div>\n        ) : null}\n      </div>\n\n      {hasBar ? (\n        steps ? (\n          <div className=\"flex h-[3px] w-full gap-px\">\n            {Array.from({ length: steps }, (_, i) => (\n              <span\n                // positional segments — index is the identity\n                // biome-ignore lint/suspicious/noArrayIndexKey: fixed-count positional segments\n                key={i}\n                className=\"h-full flex-1\"\n                style={{\n                  background: i < filled ? fill : \"var(--engram-track)\",\n                }}\n              />\n            ))}\n          </div>\n        ) : (\n          <div className=\"h-[3px] w-full bg-engram-track\">\n            <div\n              className=\"h-full\"\n              style={{ width: `${pct * 100}%`, background: fill }}\n            />\n          </div>\n        )\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/engram/record-card.tsx"
    }
  ],
  "meta": {
    "level": "component"
  },
  "docs": "Extend without forking: edit the copied source, use `asChild` (Radix Slot) to change the rendered element, pass the typed `annotations` prop for curated data (verdict/tags/per-plug), or use slot / render-prop props for arbitrary content. Requires the @engram/tokens theme (--engram-* CSS variables).",
  "categories": [
    "triumph"
  ],
  "type": "registry:component"
}