{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cta-photo-headline",
  "type": "registry:block",
  "title": "CTA Photo Headline",
  "description": "A call-to-action where avatars pop in above a heading with two photos tucked into the copy — a pill that grows from the left, then a tilted square that drops into place.",
  "dependencies": [
    "gsap",
    "@gsap/react"
  ],
  "registryDependencies": [
    "https://tween-ui.vercel.app/r/slide-arrow-button.json"
  ],
  "cssVars": {
    "theme": {}
  },
  "files": [
    {
      "path": "components/tweenui/cta-photo-headline.tsx",
      "type": "registry:component",
      "target": "components/tweenui/cta-photo-headline.tsx",
      "content": "'use client';\n\nimport { useRef, type ComponentPropsWithoutRef } from 'react';\nimport { useGSAP } from '@gsap/react';\nimport gsap from 'gsap';\nimport { cn } from '@/lib/utils';\nimport SlideArrowButton from './slide-arrow-button';\n\ngsap.registerPlugin(useGSAP);\n\nconst prefersReducedMotion = () =>\n  typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\nexport interface CtaPhotoHeadlineAvatar {\n  src: string;\n  alt: string;\n}\n\nexport interface CtaPhotoHeadlineImage {\n  src: string;\n  alt?: string;\n}\n\nexport interface CtaPhotoHeadlineProps extends ComponentPropsWithoutRef<'section'> {\n  /** Faces in the row above the heading. */\n  avatars?: CtaPhotoHeadlineAvatar[];\n  /** Landscape photo tucked into the first headline line. */\n  inlineImage?: CtaPhotoHeadlineImage;\n  /** Tilted photo on the second headline line. */\n  accentImage?: CtaPhotoHeadlineImage;\n  /** First headline fragment, before the pill photo. */\n  lead?: string;\n  /** Headline fragment after the pill photo. */\n  mid?: string;\n  /** Second-line headline, after the tilted photo. */\n  end?: string;\n  /** Supporting line under the heading. */\n  description?: string;\n  /** Label for the slide-arrow CTA. */\n  ctaLabel?: string;\n  /** Click handler for the CTA button. */\n  onCtaClick?: () => void;\n}\n\nconst DEFAULT_AVATARS: CtaPhotoHeadlineAvatar[] = [\n  {\n    src: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=112&h=112&fit=crop&crop=faces',\n    alt: 'Motion designer',\n  },\n  {\n    src: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=112&h=112&fit=crop&crop=faces',\n    alt: 'Frontend engineer',\n  },\n  {\n    src: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=112&h=112&fit=crop&crop=faces',\n    alt: 'Product designer',\n  },\n  {\n    src: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=112&h=112&fit=crop&crop=faces',\n    alt: 'AI engineer',\n  },\n];\n\nconst DEFAULT_INLINE_IMAGE: CtaPhotoHeadlineImage = {\n  src: 'https://images.unsplash.com/photo-1677442136019-21780ecad995?w=264&h=156&fit=crop',\n  alt: 'AI interface collage',\n};\n\nconst DEFAULT_ACCENT_IMAGE: CtaPhotoHeadlineImage = {\n  src: 'https://images.unsplash.com/photo-1617791160505-6f00504e3519?w=144&h=144&fit=crop',\n  alt: 'Abstract 3D motion form',\n};\n\nexport default function CtaPhotoHeadline({\n  avatars = DEFAULT_AVATARS,\n  inlineImage = DEFAULT_INLINE_IMAGE,\n  accentImage = DEFAULT_ACCENT_IMAGE,\n  lead = 'Turn static',\n  mid = 'into motion',\n  end = 'with Tween UI',\n  description = 'Copy-paste GSAP blocks for React. Themed, reduced-motion ready, and built to drop into any stack.',\n  ctaLabel = 'Browse the blocks',\n  onCtaClick,\n  className,\n  ...props\n}: CtaPhotoHeadlineProps) {\n  const rootRef = useRef<HTMLElement>(null);\n\n  useGSAP(\n    () => {\n      const root = rootRef.current;\n      if (!root) return;\n\n      const faces = gsap.utils.toArray<HTMLElement>('[data-cta-avatar]', root);\n      const inlineEl = root.querySelector<HTMLElement>('[data-cta-inline-image]');\n      const accentEl = root.querySelector<HTMLElement>('[data-cta-accent-image]');\n      const targets = [...faces, inlineEl, accentEl].filter(Boolean);\n\n      if (prefersReducedMotion()) {\n        gsap.set(targets, {\n          opacity: 1,\n          x: 0,\n          y: 0,\n          scale: 1,\n          scaleX: 1,\n          rotation: 0,\n          filter: 'none',\n        });\n        if (accentEl) gsap.set(accentEl, { rotation: -20 });\n        return;\n      }\n\n      gsap.fromTo(\n        faces,\n        { opacity: 0, scale: 0, x: -40, filter: 'blur(5px)' },\n        {\n          opacity: 1,\n          scale: 1,\n          x: 0,\n          filter: 'blur(0px)',\n          duration: 1.5,\n          stagger: 0.1,\n          ease: 'elastic.out(1, 0.7)',\n        }\n      );\n\n      if (inlineEl) {\n        gsap.fromTo(\n          inlineEl,\n          { scaleX: 0, autoAlpha: 0, transformOrigin: 'left center' },\n          {\n            scaleX: 1,\n            autoAlpha: 1,\n            duration: 1.7,\n            delay: 0.3,\n            ease: 'power3.out',\n          }\n        );\n      }\n\n      if (accentEl) {\n        gsap.fromTo(\n          accentEl,\n          { y: 80, scale: 0, autoAlpha: 0, rotation: 40, transformOrigin: 'center center' },\n          {\n            y: 0,\n            scale: 1,\n            autoAlpha: 1,\n            rotation: -20,\n            duration: 1.3,\n            delay: 0.2,\n            ease: 'power2.out',\n          }\n        );\n      }\n    },\n    { scope: rootRef }\n  );\n\n  return (\n    <section\n      {...props}\n      ref={rootRef}\n      data-cta-photo-headline\n      className={cn('w-full overflow-hidden py-16 md:py-20', className)}\n    >\n      <div className=\"mx-auto flex w-full max-w-[720px] flex-col items-center gap-10 px-4\">\n        <div className=\"flex items-center justify-center gap-2\">\n          {avatars.map((avatar) => (\n            <figure\n              key={avatar.src}\n              data-cta-avatar\n              className=\"size-14 shrink-0 overflow-hidden rounded-full opacity-0 motion-reduce:opacity-100\"\n            >\n              <img src={avatar.src} alt={avatar.alt} className=\"size-full object-cover\" />\n            </figure>\n          ))}\n        </div>\n\n        <div className=\"space-y-6 text-center\">\n          <h2 className=\"text-2xl leading-[1.15] font-medium tracking-tight text-[#12161F] md:text-3xl lg:text-4xl dark:text-white\">\n            <span className=\"inline-flex flex-wrap items-center justify-center gap-x-2 gap-y-2\">\n              <span>{lead}</span>\n              <span\n                data-cta-inline-image\n                className=\"inline-block h-[52px] w-[88px] origin-left overflow-hidden rounded-full align-middle opacity-0 motion-reduce:opacity-100\"\n              >\n                <img\n                  src={inlineImage.src}\n                  alt={inlineImage.alt ?? ''}\n                  aria-hidden={!inlineImage.alt}\n                  className=\"size-full object-cover\"\n                />\n              </span>\n              <span>{mid}</span>\n            </span>\n            <span className=\"mt-2 flex items-center justify-center gap-x-4\">\n              <span\n                data-cta-accent-image\n                className=\"inline-block size-12 overflow-hidden rounded-lg align-middle opacity-0 motion-reduce:-rotate-[20deg] motion-reduce:opacity-100\"\n              >\n                <img\n                  src={accentImage.src}\n                  alt={accentImage.alt ?? ''}\n                  aria-hidden={!accentImage.alt}\n                  className=\"size-full object-cover\"\n                />\n              </span>\n              <span>{end}</span>\n            </span>\n          </h2>\n          <p className=\"mx-auto max-w-[320px] text-sm leading-relaxed text-[#045f64]/70 dark:text-[#9fd4d6]/80\">\n            {description}\n          </p>\n        </div>\n\n        <SlideArrowButton onClick={onCtaClick}>{ctaLabel}</SlideArrowButton>\n      </div>\n    </section>\n  );\n}\n"
    }
  ],
  "docs": "Docs, props and examples: https://tween-ui.vercel.app/block/cta-photo-headline\nThe sample content loads images from images.unsplash.com. Replace them with your own before shipping."
}