{
  "name": "utils",
  "type": "registry:lib",
  "title": "utils (cn)",
  "description": "The class combiner every component leans on: clsx + tailwind-merge with proper precedence. Ships automatically as a registry dependency of every component.",
  "dependencies": [
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "path": "lib/utils.ts",
      "type": "registry:lib",
      "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\n/**\n * ⚠️ TRAP (shipped once — do not re-learn). Candlelight WIPES Tailwind's\n * default text scale and names its own steps (§2.6). tailwind-merge\n * cannot tell a custom font-size (`text-marquee`) from a text color\n * (`text-ink`) — both wear the `text-` prefix — so an unconfigured\n * twMerge treats them as conflicting and silently DROPS the earlier one:\n * cn('text-marquee', 'text-ink') would lose the marquee. The named type\n * steps are registered here so sizes and colors merge independently.\n */\nconst twMerge = extendTailwindMerge({\n  extend: {\n    classGroups: {\n      \"font-size\": [\n        {\n          text: [\n            \"nano\",\n            \"micro\",\n            \"eyebrow\",\n            \"tooltip\",\n            \"meta\",\n            \"body\",\n            \"body-lg\",\n            \"title\",\n            \"overlay-title\",\n            \"heading\",\n            \"heading-lg\",\n            \"marquee\",\n          ],\n        },\n      ],\n    },\n  },\n});\n\n/** Merge Tailwind classes with proper precedence. */\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n",
      "target": "lib/utils.ts"
    }
  ],
  "meta": {
    "candlelight": {
      "category": "hook",
      "gRules": [],
      "useWhen": "Composing conditional Tailwind classes in any registry component.",
      "dontUseWhen": "Anywhere else — it is plumbing, not a pattern.",
      "states": [],
      "keyboard": [],
      "acceptanceTests": [
        "Later classes win conflicts (twMerge precedence), so a consumer's className prop can override a component default."
      ],
      "traps": [
        "tailwind-merge cannot tell a renamed font-size (text-marquee) from a text color (text-ink) — both wear text-. The shipped cn registers the named type steps via extendTailwindMerge; replace it with a bare twMerge and cn('text-marquee', 'text-ink') silently drops the size."
      ]
    }
  }
}