{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "featured-halftone",
  "title": "Halftone Photo Card",
  "description": "Real CMYK halftone shader (via @paper-design/shaders-react) applied to any image. WebGL renders the printing-press look — channel-by-channel ink colors, dot size/softness, grain overlay, three dot styles (dots/ink/sharp). Includes the shared title overlay API (titleText/titlePosition/titleSize/titleColor) for hero copy on top of the shader.",
  "dependencies": [
    "@paper-design/shaders-react"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/featured-halftone/featured-halftone.tsx",
      "content": "\"use client\";\n\nimport { HalftoneCmyk } from \"@paper-design/shaders-react\";\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport type TitlePosition =\n  | \"top-left\"\n  | \"top-center\"\n  | \"top-right\"\n  | \"center-left\"\n  | \"center\"\n  | \"center-right\"\n  | \"bottom-left\"\n  | \"bottom-center\"\n  | \"bottom-right\";\n\nconst POSITION_CLASSES: Record<TitlePosition, string> = {\n  \"top-left\": \"items-start justify-start text-left\",\n  \"top-center\": \"items-start justify-center text-center\",\n  \"top-right\": \"items-start justify-end text-right\",\n  \"center-left\": \"items-center justify-start text-left\",\n  center: \"items-center justify-center text-center\",\n  \"center-right\": \"items-center justify-end text-right\",\n  \"bottom-left\": \"items-end justify-start text-left\",\n  \"bottom-center\": \"items-end justify-center text-center\",\n  \"bottom-right\": \"items-end justify-end text-right\",\n};\n\nexport type FeaturedHalftoneProps = {\n  image: string;\n  imageAlt?: string;\n  /** Title overlay text. */\n  title?: React.ReactNode;\n  /** Small label above the title. */\n  eyebrow?: React.ReactNode;\n  /** Where to anchor the title block. Default \"bottom-left\". */\n  titlePosition?: TitlePosition;\n  /** Title font size in px. Eyebrow scales proportionally. Default 30. */\n  titleSize?: number;\n  /** Inline color for the title + eyebrow. Overrides titleClassName color. */\n  titleColor?: string;\n  /** Class for the title text — color, weight overrides. */\n  titleClassName?: string;\n  /** Dot rendering style. Default \"dots\". */\n  type?: \"dots\" | \"ink\" | \"sharp\";\n  /** Halftone cell size, 0-1. Default 0.18. */\n  size?: number;\n  /** Dot edge softness, 0-1. Default 0.5. */\n  softness?: number;\n  /** Image contrast, 0-2. Default 1. */\n  contrast?: number;\n  /** Paper / background color. */\n  colorBack?: string;\n  /** CMYK ink colors. */\n  colorC?: string;\n  colorM?: string;\n  colorY?: string;\n  colorK?: string;\n  /** Grain overlay strength, 0-1. */\n  grainOverlay?: number;\n  /** Grain mixer strength, 0-1. */\n  grainMixer?: number;\n  /** Aspect ratio. Default \"1/1\". */\n  aspectRatio?: string;\n  className?: string;\n};\n\nexport function FeaturedHalftone({\n  image,\n  imageAlt: _imageAlt,\n  title,\n  eyebrow,\n  titlePosition = \"bottom-left\",\n  titleSize = 30,\n  titleColor,\n  titleClassName = \"text-stone-900\",\n  type = \"dots\",\n  size = 0.18,\n  softness = 0.55,\n  contrast = 1.1,\n  colorBack = \"#f3ead8\",\n  colorC = \"#1f6f97\",\n  colorM = \"#d23a5a\",\n  colorY = \"#e8a334\",\n  colorK = \"#1a1a1a\",\n  grainOverlay = 0.25,\n  grainMixer = 0.15,\n  aspectRatio = \"1/1\",\n  className,\n}: FeaturedHalftoneProps) {\n  const eyebrowSize = Math.max(11, Math.round(titleSize * 0.4));\n\n  return (\n    <figure\n      className={cn(\n        \"relative isolate overflow-hidden rounded-2xl bg-stone-100\",\n        className\n      )}\n      style={{ aspectRatio }}\n    >\n      <HalftoneCmyk\n        colorBack={colorBack}\n        colorC={colorC}\n        colorK={colorK}\n        colorM={colorM}\n        colorY={colorY}\n        contrast={contrast}\n        fit=\"cover\"\n        grainMixer={grainMixer}\n        grainOverlay={grainOverlay}\n        image={image}\n        size={size}\n        softness={softness}\n        style={{\n          position: \"absolute\",\n          inset: 0,\n          width: \"100%\",\n          height: \"100%\",\n        }}\n        type={type}\n      />\n\n      {title || eyebrow ? (\n        <div\n          className={cn(\n            \"pointer-events-none absolute inset-0 flex p-4 sm:p-6\",\n            POSITION_CLASSES[titlePosition]\n          )}\n        >\n          <figcaption className=\"flex max-w-full flex-col gap-1\">\n            {eyebrow ? (\n              <span\n                className={cn(\"font-medium opacity-80\", titleClassName)}\n                style={{ fontSize: `${eyebrowSize}px`, color: titleColor }}\n              >\n                {eyebrow}\n              </span>\n            ) : null}\n            {title ? (\n              <h3\n                className={cn(\n                  \"font-bold leading-tight tracking-tight\",\n                  titleClassName\n                )}\n                style={{ fontSize: `${titleSize}px`, color: titleColor }}\n              >\n                {title}\n              </h3>\n            ) : null}\n          </figcaption>\n        </div>\n      ) : null}\n    </figure>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "featured"
  ],
  "type": "registry:block"
}