{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-with-media",
  "type": "registry:block",
  "title": "Hero — with media",
  "description": "A landing page hero with centred text over a full-width background image, or above a framed screenshot. Over a background, a dark layer keeps the text readable.",
  "categories": [
    "section"
  ],
  "registryDependencies": [
    "https://facadeui.dev/r/container.json",
    "https://facadeui.dev/r/cta-group.json",
    "https://facadeui.dev/r/eyebrow.json",
    "https://facadeui.dev/r/heading.json",
    "https://facadeui.dev/r/section.json",
    "https://facadeui.dev/r/types.json",
    "https://facadeui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/sections/hero-with-media.tsx",
      "type": "registry:component",
      "target": "components/sections/hero-with-media.tsx",
      "content": "/**\n * HeroWithMedia — centred copy over a full-bleed background, or above a wide\n * framed screenshot.\n *\n * Two shapes, one component, because they differ only in where the media sits:\n * `overlay` puts it behind the copy, `below` puts it under.\n *\n * a11y: `overlay` is the easiest hero to get wrong. Text over an arbitrary image\n * has no predictable contrast ratio, so the overlay variant always paints a\n * scrim between the media and the copy, and the copy switches to a fixed\n * light-on-dark pair rather than inheriting theme colours that might be dark on\n * dark. The scrim is opinionated on purpose — `overlayClassName` can tune it,\n * but it cannot be removed by accident.\n *\n * Background media is decorative by definition here: it carries no information\n * the copy does not, so pass it with `alt=\"\"`.\n *\n * Dependencies: react, @/lib/types, @/lib/utils,\n * @/components/ui/container, @/components/ui/cta-group, @/components/ui/eyebrow,\n * @/components/ui/heading, @/components/ui/section.\n */\n\nimport type { ElementType, ReactNode } from \"react\"\n\nimport type {\n  CtaItem,\n  HeadingLevel,\n  LinkComponent,\n  StackSlotProps,\n} from \"@/lib/types\"\nimport { cn, slugId } from \"@/lib/utils\"\nimport { Container } from \"@/components/ui/container\"\nimport { CtaGroup } from \"@/components/ui/cta-group\"\nimport { Eyebrow } from \"@/components/ui/eyebrow\"\nimport { Heading } from \"@/components/ui/heading\"\nimport { Section } from \"@/components/ui/section\"\n\nexport interface HeroWithMediaProps extends StackSlotProps {\n  title: string\n  description?: string\n  eyebrow?: ReactNode\n  actions?: CtaItem[]\n  link?: LinkComponent\n  note?: ReactNode\n  /** The media. In `overlay` mode it is decorative, so give it `alt=\"\"`. */\n  media: ReactNode\n  /** `overlay` puts media behind the copy; `below` puts it underneath. */\n  placement?: \"overlay\" | \"below\"\n  /** Classes for the dark layer between the media and the text. */\n  overlayClassName?: string\n  headingLevel?: HeadingLevel\n  size?: \"md\" | \"lg\" | \"xl\"\n  as?: \"section\" | \"div\"\n  spacing?: \"sm\" | \"md\" | \"lg\" | \"none\"\n  className?: string\n  id?: string\n}\n\nconst titleSizes = {\n  md: \"text-display-md\",\n  lg: \"text-display-lg\",\n  xl: \"text-display-xl\",\n} as const\n\nexport function HeroWithMedia({\n  title,\n  description,\n  eyebrow,\n  actions,\n  link,\n  note,\n  media,\n  placement = \"overlay\",\n  overlayClassName,\n  stackAs,\n  blockAs,\n  headingLevel = 1,\n  size = \"lg\",\n  as = \"div\",\n  spacing = \"lg\",\n  className,\n  id,\n}: HeroWithMediaProps) {\n  const Stack = (stackAs ?? \"div\") as ElementType\n  const Block = (blockAs ?? \"div\") as ElementType\n  const titleId = id ? `${id}-title` : slugId(title)\n  const overlay = placement === \"overlay\"\n\n  const copy = (\n    <Stack\n      className={cn(\n        \"flex max-w-3xl flex-col items-center gap-6 text-center\",\n        // Over media, contrast cannot be inherited from the theme — it has to be\n        // guaranteed against the scrim.\n        overlay && \"text-white\",\n      )}\n    >\n      {eyebrow ? (\n        <Block>\n          <Eyebrow\n            tone={overlay ? \"foreground\" : \"primary\"}\n            className={overlay ? \"text-white/85\" : undefined}\n          >\n            {eyebrow}\n          </Eyebrow>\n        </Block>\n      ) : null}\n\n      <Block>\n        <Heading\n          level={headingLevel}\n          id={titleId}\n          className={cn(\"text-balance font-semibold\", titleSizes[size])}\n        >\n          {title}\n        </Heading>\n      </Block>\n\n      {description ? (\n        <Block>\n          <p\n            className={cn(\n              \"max-w-2xl text-pretty text-lg sm:text-xl\",\n              overlay ? \"text-white/90\" : \"text-muted-foreground\",\n            )}\n          >\n            {description}\n          </p>\n        </Block>\n      ) : null}\n\n      {actions?.length ? (\n        <Block className=\"w-full sm:w-auto\">\n          <CtaGroup items={actions} link={link} size=\"lg\" align=\"center\" stackOnMobile />\n        </Block>\n      ) : null}\n\n      {note ? (\n        <Block>\n          <p\n            className={cn(\n              \"text-pretty text-sm\",\n              overlay ? \"text-white/80\" : \"text-muted-foreground\",\n            )}\n          >\n            {note}\n          </p>\n        </Block>\n      ) : null}\n    </Stack>\n  )\n\n  if (!overlay) {\n    return (\n      <Section\n        as={as}\n        spacing={spacing}\n        labelledBy={as === \"section\" ? titleId : undefined}\n        id={id}\n        className={className}\n      >\n        <Container className=\"flex flex-col items-center gap-14\">\n          {copy}\n          <div className=\"w-full overflow-hidden rounded-2xl border shadow-sm\">\n            {media}\n          </div>\n        </Container>\n      </Section>\n    )\n  }\n\n  return (\n    <Section\n      as={as}\n      spacing={spacing}\n      labelledBy={as === \"section\" ? titleId : undefined}\n      id={id}\n      className={cn(\"isolate overflow-hidden\", className)}\n    >\n      <div\n        aria-hidden\n        className=\"absolute inset-0 -z-20 [&_img]:size-full [&_img]:object-cover [&_video]:size-full [&_video]:object-cover\"\n      >\n        {media}\n      </div>\n      {/* Always present: text over arbitrary media has no guaranteed ratio. */}\n      <div\n        aria-hidden\n        className={cn(\"absolute inset-0 -z-10 bg-black/65\", overlayClassName)}\n      />\n      <Container className=\"flex flex-col items-center py-10\">{copy}</Container>\n    </Section>\n  )\n}\n"
    }
  ],
  "docs": "Import styles/facade-tokens.css in your global stylesheet, after @import \"tailwindcss\". Set headingLevel to fit the page outline (sections default to h2). Pass next/link and next/image through the link and image props. Docs: https://facadeui.dev/components/hero-with-media"
}
