{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-studio-01",
  "title": "Hero Studio",
  "description": "A short tagline beside a serif headline and pitch, over a wide landscape photo that fades into the page",
  "dependencies": [
    "class-variance-authority",
    "motion@13"
  ],
  "registryDependencies": [
    "https://ui.cortexcn.dev/r/utils.json",
    "button"
  ],
  "files": [
    {
      "path": "registry/blocks/hero-studio-01/components/hero-studio.tsx",
      "content": "\"use client\";\n\nimport { motion, useReducedMotion, type Variants } from \"motion/react\";\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { Cta, type CtaProps } from \"./hero-cta\";\n\n// Cortexcn item \"hero-studio-01\", revision 6ff401680917, MIT license.\n// https://ui.cortexcn.dev/r/v/hero-studio-01/6ff401680917.json\n\nexport interface HeroStudioProps {\n  /** Short line in the left column, set against the bottom of the copy. */\n  tagline?: string;\n  title?: string;\n  description?: string;\n  /** Wide photo under the copy, faded into the page at its top edge. */\n  landscapeImage?: string;\n  landscapeAlt?: string;\n  animation?: \"none\" | \"subtle\";\n  primaryCTA?: CtaProps;\n  /** Shown as a text link unless it sets its own variant. */\n  secondaryCTA?: CtaProps;\n  variant?: \"standard\" | \"compact\";\n}\n\nconst DEFAULTS = {\n  tagline: \"Brand, product, and story for teams building something new\",\n  title:\n    \"A creative studio for founders who want their work to feel considered.\",\n  description:\n    \"We help early stage companies turn rough ideas into clear identities, thoughtful digital products, and messaging people remember. Strategy, design, and execution in one place.\",\n  // Sample photo from Unsplash (free to use under the Unsplash License).\n  landscapeImage:\n    \"https://images.unsplash.com/photo-1578301978018-3005759f48f7?q=80&w=1600&auto=format&fit=crop\",\n  landscapeAlt: \"A painted landscape of hills and autumn trees\",\n  primaryCTA: {\n    ctaEnabled: false,\n    text: \"Start a project\",\n    link: \"\",\n    variant: \"default\",\n  },\n  secondaryCTA: {\n    ctaEnabled: false,\n    text: \"View work\",\n    link: \"\",\n    variant: \"link\",\n  },\n} satisfies HeroStudioProps;\n\nconst variantStyles = {\n  standard: {\n    copy: \"pt-20 pb-10 sm:pt-28 sm:pb-12 lg:pt-32\",\n    tagline: \"text-sm sm:text-base\",\n    title: \"text-3xl sm:text-4xl md:text-5xl\",\n    description: \"text-sm sm:text-base\",\n    header: \"gap-6 sm:gap-8\",\n    grid: \"gap-10\",\n  },\n  compact: {\n    copy: \"pt-14 pb-8 sm:pt-20 sm:pb-10 lg:pt-24\",\n    tagline: \"text-sm\",\n    title: \"text-2xl sm:text-3xl md:text-4xl\",\n    description: \"text-sm\",\n    header: \"gap-4 sm:gap-5\",\n    grid: \"gap-8\",\n  },\n} as const;\n\nconst container: Variants = {\n  hidden: {},\n  visible: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },\n};\n\nconst item: Variants = {\n  hidden: { opacity: 0, y: 12, filter: \"blur(6px)\" },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: \"blur(0px)\",\n    transition: { duration: 0.28, ease: [0.22, 1, 0.36, 1] },\n  },\n};\n\nconst mediaItem: Variants = {\n  hidden: { opacity: 0, y: 20, filter: \"blur(8px)\" },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: \"blur(0px)\",\n    transition: { duration: 0.32, ease: [0.22, 1, 0.36, 1] },\n  },\n};\n\nfunction Reveal({\n  active,\n  variants,\n  className,\n  children,\n}: Readonly<{\n  active: boolean;\n  variants?: Variants;\n  className?: string;\n  children: ReactNode;\n}>) {\n  if (!active) {\n    return <div className={className}>{children}</div>;\n  }\n\n  return (\n    <motion.div className={className} variants={variants ?? item}>\n      {children}\n    </motion.div>\n  );\n}\n\n/**\n * A short tagline beside a serif headline, a pitch, and up to two calls to\n * action, over a wide landscape photo that fades into the page.\n */\nexport function HeroStudio({\n  tagline = DEFAULTS.tagline,\n  title = DEFAULTS.title,\n  description = DEFAULTS.description,\n  landscapeImage = DEFAULTS.landscapeImage,\n  landscapeAlt = DEFAULTS.landscapeAlt,\n  animation = \"subtle\",\n  primaryCTA = DEFAULTS.primaryCTA,\n  secondaryCTA = DEFAULTS.secondaryCTA,\n  variant = \"standard\",\n}: Readonly<HeroStudioProps>) {\n  const reduce = useReducedMotion();\n  const animate = animation === \"subtle\" && !reduce;\n  const vs = variantStyles[variant];\n  const hasCtas = primaryCTA?.ctaEnabled || secondaryCTA?.ctaEnabled;\n\n  return (\n    <section className=\"relative isolate w-full overflow-hidden bg-background\">\n      <motion.div\n        className={cn(\n          \"relative z-10 mx-auto grid max-w-7xl grid-cols-1 px-6 lg:grid-cols-12\",\n          vs.copy,\n          vs.grid,\n        )}\n        initial={animate ? \"hidden\" : false}\n        variants={animate ? container : undefined}\n        viewport={{ once: true, margin: \"-80px\" }}\n        whileInView={animate ? \"visible\" : undefined}\n      >\n        <Reveal\n          active={animate}\n          className=\"flex lg:col-span-4 lg:col-start-1 lg:items-end lg:self-stretch\"\n        >\n          {tagline && (\n            <p\n              className={cn(\n                \"max-w-xs text-balance text-muted-foreground leading-relaxed tracking-tight\",\n                vs.tagline,\n              )}\n            >\n              {tagline}\n            </p>\n          )}\n        </Reveal>\n\n        <Reveal\n          active={animate}\n          className={cn(\n            \"flex flex-col items-start lg:col-span-6 lg:col-start-7\",\n            vs.header,\n          )}\n        >\n          {title && (\n            <h1\n              className={cn(\n                \"text-balance font-normal font-serif text-foreground tracking-tight\",\n                vs.title,\n              )}\n            >\n              {title}\n            </h1>\n          )}\n          {description && (\n            <p\n              className={cn(\n                \"max-w-xl text-balance text-muted-foreground leading-relaxed\",\n                vs.description,\n              )}\n            >\n              {description}\n            </p>\n          )}\n          {hasCtas && (\n            <div className=\"flex flex-wrap items-center gap-x-4 gap-y-3\">\n              {primaryCTA?.ctaEnabled && <Cta cta={primaryCTA} />}\n              {secondaryCTA?.ctaEnabled && (\n                <Cta\n                  cta={{\n                    ...secondaryCTA,\n                    variant: secondaryCTA.variant ?? \"link\",\n                  }}\n                />\n              )}\n            </div>\n          )}\n        </Reveal>\n      </motion.div>\n\n      {landscapeImage && (\n        <Reveal active={animate} className=\"w-full\" variants={mediaItem}>\n          <div className=\"relative w-full overflow-hidden\">\n            <div className=\"mask-t-from-80% mask-t-to-95% relative overflow-hidden rounded-b-sm\">\n              <div\n                aria-hidden=\"true\"\n                className=\"pointer-events-none absolute inset-0 z-10 bg-background/15 mix-blend-overlay dark:bg-background/30\"\n              />\n              {/* biome-ignore lint/performance/noImgElement: framework-agnostic registry block */}\n              <img\n                alt={landscapeAlt}\n                className=\"aspect-2/1 w-full object-cover object-center outline outline-black/10 sm:aspect-9/4 dark:outline-white/10 dark:brightness-[0.97] dark:saturate-[0.92]\"\n                decoding=\"async\"\n                height={711}\n                src={landscapeImage}\n                width={1600}\n              />\n            </div>\n          </div>\n        </Reveal>\n      )}\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/hero-studio.tsx"
    },
    {
      "path": "registry/blocks/hero-studio-01/components/hero-cta.tsx",
      "content": "import { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { Button, buttonVariants } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\n// Cortexcn item \"hero-studio-01\", revision 6ff401680917, MIT license.\n// https://ui.cortexcn.dev/r/v/hero-studio-01/6ff401680917.json\n\ntype ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonVariant = NonNullable<ButtonVariants[\"variant\"]>;\n\nexport interface CtaProps {\n  ctaEnabled?: boolean;\n  text: string;\n  /** Leave empty to render a button instead of a link. */\n  link: string;\n  variant?: ButtonVariant;\n  size?: \"default\" | \"sm\" | \"lg\";\n}\n\nconst ctaVariants = cva(\"w-fit rounded-full px-4\", {\n  variants: {\n    invert: {\n      true: \"border-transparent! bg-white! text-zinc-900! hover:bg-zinc-100!\",\n      false: \"\",\n    },\n  },\n  defaultVariants: {\n    invert: false,\n  },\n});\n\nexport function Cta({\n  cta,\n  className,\n  invert,\n}: Readonly<{ cta?: CtaProps; className?: string; invert?: boolean }>) {\n  if (!cta?.ctaEnabled) {\n    return null;\n  }\n\n  const variant = cta.variant ?? (invert ? \"secondary\" : \"default\");\n\n  if (!cta.link) {\n    return (\n      <Button\n        aria-label={cta.text}\n        className={cn(ctaVariants({ invert }), className)}\n        size={cta.size ?? \"default\"}\n        type=\"button\"\n        variant={variant}\n      >\n        {cta.text}\n      </Button>\n    );\n  }\n\n  return (\n    // No aria-label here, so screen readers also hear \"(opens in new tab)\".\n    <a\n      className={cn(\n        buttonVariants({\n          variant,\n          size: cta.size ?? \"default\",\n          className: cn(ctaVariants({ invert }), className),\n        }),\n      )}\n      href={cta.link}\n      rel=\"noopener noreferrer\"\n      target=\"_blank\"\n    >\n      {cta.text}\n      <span className=\"sr-only\">{`${cta.text} (opens in new tab)`}</span>\n    </a>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/hero-cta.tsx"
    }
  ],
  "type": "registry:block",
  "author": "Cortexcn (https://ui.cortexcn.dev)",
  "meta": {
    "license": "MIT",
    "revision": "6ff401680917"
  }
}