{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-aurora",
  "type": "registry:component",
  "title": "Hero Aurora",
  "description": "A complete, layered hero section: drifting aurora gradient wash, faint dot-grid depth layer, a pointer-reactive spotlight, the glass-nav liquid-glass navigation, and a kinetic word-pop headline with a staged entrance choreography (nav -> headline words -> subheadline -> CTAs). Ships as a ready-to-drop section, not a loose primitive.",
  "dependencies": [
    "framer-motion@^12.0.0"
  ],
  "registryDependencies": [
    "@safari/glass-nav",
    "@safari/mouse-reactive-gradient"
  ],
  "files": [
    {
      "path": "hero-aurora.tsx",
      "target": "components/safari/hero-aurora/hero-aurora.tsx",
      "type": "registry:component",
      "content": "\"use client\";\n\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport { motion, useReducedMotion, type Variants } from \"framer-motion\";\n\nimport { GlassNav, type GlassNavCta, type GlassNavLink } from \"../glass-nav/glass-nav\";\nimport { MouseReactiveGradient } from \"../mouse-reactive-gradient/mouse-reactive-gradient\";\n\nimport \"./hero-aurora.css\";\n\nexport interface HeroAuroraProps {\n  navBrand: ReactNode;\n  navLinks: GlassNavLink[];\n  navCta?: GlassNavCta;\n  /** Small label above the headline, e.g. \"Component registry\". */\n  eyebrow?: string;\n  /** Headline, split into lines. Each line staggers its own words. */\n  headline: string[];\n  subheadline: string;\n  primaryCta: GlassNavCta;\n  secondaryCta?: GlassNavCta;\n  className?: string;\n}\n\nconst EASE_OVERSHOOT = [0.34, 1.56, 0.64, 1] as const;\nconst EASE_REVEAL = [0.16, 1, 0.3, 1] as const;\n\n// Entrance choreography, in seconds — nav is already visible (it renders\n// its own state), everything below stages in this order:\n//   background -> headline words -> subheadline -> CTAs\nconst TIMING = {\n  headlineStart: 0.15,\n  wordStagger: 0.045,\n  lineGap: 0.1,\n  subheadlineOffset: 0.15,\n  ctaOffset: 0.15,\n};\n\nfunction splitWords(line: string): string[] {\n  return line.split(\" \").filter(Boolean);\n}\n\nexport function HeroAurora({\n  navBrand,\n  navLinks,\n  navCta,\n  eyebrow,\n  headline,\n  subheadline,\n  primaryCta,\n  secondaryCta,\n  className,\n}: HeroAuroraProps) {\n  const prefersReducedMotion = useReducedMotion();\n  // Avoids a mismatch between the server-rendered (motion-enabled) markup\n  // and a reduced-motion client on first paint.\n  const [mounted, setMounted] = useState(false);\n  useEffect(() => setMounted(true), []);\n  const reduced = mounted && prefersReducedMotion;\n\n  let wordIndex = 0;\n  const lineStartIndices = headline.map((line) => {\n    const start = wordIndex;\n    wordIndex += splitWords(line).length;\n    return start;\n  });\n\n  const wordVariants: Variants = reduced\n    ? {\n        hidden: { opacity: 0 },\n        visible: { opacity: 1, transition: { duration: 0.2 } },\n      }\n    : {\n        hidden: { opacity: 0, y: 46, scale: 0.82, rotate: -3, filter: \"blur(6px)\" },\n        visible: {\n          opacity: 1,\n          y: 0,\n          scale: 1,\n          rotate: 0,\n          filter: \"blur(0px)\",\n          transition: { duration: 0.75, ease: EASE_OVERSHOOT },\n        },\n      };\n\n  const fadeUp = (delay: number): Variants =>\n    reduced\n      ? { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { duration: 0.2, delay } } }\n      : {\n          hidden: { opacity: 0, y: 24 },\n          visible: {\n            opacity: 1,\n            y: 0,\n            transition: { duration: 0.7, ease: EASE_REVEAL, delay },\n          },\n        };\n\n  const totalHeadlineWords = wordIndex;\n  const headlineEnd =\n    TIMING.headlineStart + totalHeadlineWords * TIMING.wordStagger + headline.length * TIMING.lineGap;\n  const subheadlineDelay = headlineEnd + TIMING.subheadlineOffset;\n  const ctaDelay = subheadlineDelay + TIMING.ctaOffset;\n\n  return (\n    <section className={`sm-hero-aurora relative isolate overflow-hidden ${className ?? \"\"}`}>\n      <div className=\"sm-hero-aurora-bg\" aria-hidden=\"true\" />\n      <div className=\"sm-hero-aurora-grid\" aria-hidden=\"true\" />\n\n      <MouseReactiveGradient\n        className=\"relative flex min-h-[100dvh] flex-col\"\n        color=\"var(--sm-hero-aurora-accent, #5b8cff)\"\n        radius={640}\n        intensity={0.14}\n      >\n        <GlassNav brand={navBrand} links={navLinks} cta={navCta} />\n\n        <div className=\"relative mx-auto flex w-full max-w-5xl flex-1 flex-col justify-center px-6 py-24 md:px-10\">\n          {eyebrow ? (\n            <motion.p\n              initial=\"hidden\"\n              animate=\"visible\"\n              variants={fadeUp(0)}\n              className=\"mb-5 text-sm font-medium uppercase tracking-[0.14em] text-sm-accent\"\n            >\n              {eyebrow}\n            </motion.p>\n          ) : null}\n\n          <h1 className=\"sm-hero-aurora-headline text-[clamp(40px,7vw,84px)] font-semibold leading-[0.98] tracking-[-0.03em] text-sm-text\">\n            {headline.map((line, lineIdx) => (\n              <span key={line} className=\"block overflow-hidden py-1\">\n                {splitWords(line).map((word, wordIdx) => {\n                  const globalIndex = lineStartIndices[lineIdx]! + wordIdx;\n                  const delay = TIMING.headlineStart + globalIndex * TIMING.wordStagger;\n                  return (\n                    <motion.span\n                      key={`${lineIdx}-${word}-${wordIdx}`}\n                      initial=\"hidden\"\n                      animate=\"visible\"\n                      variants={wordVariants}\n                      transition={{ delay }}\n                      className=\"mr-[0.28em] inline-block last:mr-0\"\n                    >\n                      {word}\n                    </motion.span>\n                  );\n                })}\n              </span>\n            ))}\n          </h1>\n\n          <motion.p\n            initial=\"hidden\"\n            animate=\"visible\"\n            variants={fadeUp(subheadlineDelay)}\n            className=\"mt-8 max-w-xl text-lg leading-relaxed text-sm-text-muted\"\n          >\n            {subheadline}\n          </motion.p>\n\n          <motion.div\n            initial=\"hidden\"\n            animate=\"visible\"\n            variants={fadeUp(ctaDelay)}\n            className=\"mt-10 flex flex-wrap items-center gap-4\"\n          >\n            <a\n              href={primaryCta.href}\n              className=\"sm-hero-aurora-cta-primary rounded-full bg-sm-text px-6 py-3 text-sm font-medium text-sm-bg transition-transform hover:scale-[1.03] active:scale-[0.98]\"\n            >\n              {primaryCta.label}\n            </a>\n            {secondaryCta ? (\n              <a\n                href={secondaryCta.href}\n                className=\"rounded-full border border-sm-border px-6 py-3 text-sm font-medium text-sm-text transition-colors hover:border-sm-text-muted\"\n              >\n                {secondaryCta.label}\n              </a>\n            ) : null}\n          </motion.div>\n        </div>\n      </MouseReactiveGradient>\n    </section>\n  );\n}\n"
    },
    {
      "path": "hero-aurora.css",
      "target": "components/safari/hero-aurora/hero-aurora.css",
      "type": "registry:file",
      "content": "/*\n * hero-aurora background layers, stacked bottom to top:\n *   1. .sm-hero-aurora-bg    — slow-drifting aurora gradient wash (the\n *      \"signature moment\": a large, soft, animated color field, not a\n *      static gradient).\n *   2. .sm-hero-aurora-grid  — faint dot-grid texture (cinematic landing\n *      pattern), adds depth without competing with the headline.\n *   3. MouseReactiveGradient — pointer-follow spotlight, rendered by the\n *      component itself as the third layer.\n */\n\n.sm-hero-aurora-bg {\n  --sm-hero-aurora-accent: #5b8cff;\n  --sm-hero-aurora-base: #0a0a0b;\n  position: absolute;\n  inset: -20%;\n  z-index: 0;\n  background:\n    radial-gradient(38% 42% at 18% 22%, color-mix(in srgb, var(--sm-hero-aurora-accent) 26%, transparent), transparent 70%),\n    radial-gradient(32% 38% at 82% 14%, color-mix(in srgb, var(--sm-hero-aurora-accent) 14%, transparent), transparent 72%),\n    radial-gradient(46% 50% at 50% 100%, color-mix(in srgb, var(--sm-hero-aurora-accent) 10%, transparent), transparent 75%),\n    var(--sm-hero-aurora-base);\n  filter: blur(60px) saturate(120%);\n  animation: sm-hero-aurora-drift 22s ease-in-out infinite alternate;\n  will-change: transform;\n}\n\n:root.light .sm-hero-aurora-bg {\n  --sm-hero-aurora-base: #fafafa;\n}\n\n@keyframes sm-hero-aurora-drift {\n  0% {\n    transform: translate3d(0, 0, 0) scale(1);\n  }\n  100% {\n    transform: translate3d(-2%, 2%, 0) scale(1.04);\n  }\n}\n\n.sm-hero-aurora-grid {\n  position: absolute;\n  inset: 0;\n  z-index: 0;\n  background-image: radial-gradient(rgba(255, 255, 255, 0.55) 1px, transparent 1px);\n  background-size: 26px 26px;\n  opacity: 0.05;\n  mask-image: radial-gradient(60% 60% at 50% 30%, #000 40%, transparent 90%);\n  -webkit-mask-image: radial-gradient(60% 60% at 50% 30%, #000 40%, transparent 90%);\n}\n\n:root.light .sm-hero-aurora-grid {\n  background-image: radial-gradient(rgba(0, 0, 0, 0.55) 1px, transparent 1px);\n  opacity: 0.06;\n}\n\n.sm-hero-aurora-headline {\n  /* Words render as their own inline-block spans below; the wrapper only\n     needs to keep them from collapsing while off-screen pre-animation. */\n  text-wrap: balance;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .sm-hero-aurora-bg {\n    animation: none;\n  }\n}\n"
    },
    {
      "path": "demo.tsx",
      "target": "components/safari/hero-aurora/demo.tsx",
      "type": "registry:file",
      "content": "\"use client\";\n\nimport { HeroAurora } from \"./hero-aurora\";\n\n/**\n * Isolated demo used by the future component catalog. Full-bleed hero,\n * representative of how the section is meant to be dropped at the top of\n * a page — layered background, nav, and entrance choreography included.\n */\nexport default function HeroAuroraDemo() {\n  return (\n    <HeroAurora\n      navBrand=\"Safari Motion\"\n      navLinks={[\n        { label: \"Components\", href: \"#components\" },\n        { label: \"Docs\", href: \"#docs\" },\n        { label: \"Pricing\", href: \"#pricing\" },\n      ]}\n      navCta={{ label: \"Get started\", href: \"#get-started\" }}\n      eyebrow=\"Component registry\"\n      headline={[\"Motion that ships\", \"with the product.\"]}\n      subheadline=\"Layered, production-grade sections for Apple-inspired web builds — copy-and-own React, no runtime dependency on us. Built for 60fps, dark mode, and reduced motion from day one.\"\n      primaryCta={{ label: \"Browse components\", href: \"#components\" }}\n      secondaryCta={{ label: \"Read the docs\", href: \"#docs\" }}\n    />\n  );\n}\n"
    }
  ],
  "meta": {
    "name": "hero-aurora",
    "title": "Hero Aurora",
    "description": "A complete, layered hero section: drifting aurora gradient wash, faint dot-grid depth layer, a pointer-reactive spotlight, the glass-nav liquid-glass navigation, and a kinetic word-pop headline with a staged entrance choreography (nav -> headline words -> subheadline -> CTAs). Ships as a ready-to-drop section, not a loose primitive.",
    "type": "section",
    "status": "prototype",
    "version": "0.1.0",
    "visibility": "internal",
    "tier": "free",
    "dependencies": {
      "framer-motion": "^12.0.0"
    },
    "registryDependencies": [
      "glass-nav",
      "mouse-reactive-gradient"
    ],
    "files": [
      {
        "path": "hero-aurora.tsx",
        "target": "components/safari/hero-aurora/hero-aurora.tsx",
        "type": "registry:component"
      },
      {
        "path": "hero-aurora.css",
        "target": "components/safari/hero-aurora/hero-aurora.css",
        "type": "registry:file"
      },
      {
        "path": "demo.tsx",
        "target": "components/safari/hero-aurora/demo.tsx",
        "type": "registry:file"
      }
    ],
    "compatibility": {
      "react": ">=19.0.0",
      "motionPackage": "framer-motion",
      "motionRange": "^12.0.0",
      "tailwind": ">=4.0.0",
      "ssr": "client-only",
      "browsers": [
        "chrome >= 100",
        "safari >= 16",
        "firefox >= 100"
      ]
    },
    "mobileStrategy": "simplified",
    "reducedMotion": "Gated via Framer Motion's `useReducedMotion()`, checked after mount to avoid an SSR/client markup mismatch. When active, the headline word-pop collapses to a plain opacity fade (no translate/scale/rotate/blur) and the subheadline/CTA fade-up drops its y-translate — both keep their staggered delays so content still arrives in the same choreographed order, just without motion. The aurora background's CSS drift animation is disabled via the global `prefers-reduced-motion` media query in hero-aurora.css. glass-nav and mouse-reactive-gradient apply their own reduced-motion guards independently as layered dependencies.",
    "performance": {
      "bundleCost": "~4KB gzip for this file; framer-motion itself is a peer dependency most Safari Motion consumers already carry",
      "offscreenBehavior": "All entrance animations run once on mount via `animate=\"visible\"` (not scroll-triggered, this is above-the-fold hero content) and settle to static transforms — no ongoing per-frame work once the choreography completes, aside from the CSS-only aurora drift and the inherited mouse-reactive-gradient pointer listeners.",
      "notes": "Word-pop delays are computed once from the headline word count (no re-render loop). Aurora drift and dot-grid are pure CSS (transform/opacity-safe, GPU-composited). The only layout-affecting cost is the initial word span mounting, which is a fixed, small DOM size proportional to headline word count."
    },
    "a11y": "Renders a single `<section>` containing the real `<h1>` headline (split into `<span>` words purely for animation — the text content and reading order are unaffected, no aria-hidden duplication). Eyebrow, subheadline, and CTAs are plain text/links, fully readable with motion off. Inherits glass-nav's dialog/focus-trap mobile menu and mouse-reactive-gradient's aria-hidden decorative background layer.",
    "knownLimitations": [
      "Designed as an above-the-fold, first-section hero; the sticky nav and min-h-[100dvh] layout assume it opens the page rather than sitting mid-scroll.",
      "The word-pop entrance always plays on mount (not scroll-triggered) — reusing this section lower on a long page would replay unless the consumer wraps it in their own whileInView guard.",
      "Aurora background uses color-mix() and backdrop-filter (via mouse-reactive-gradient), same modern-browser baseline as its dependency."
    ],
    "license": "MIT",
    "origin": "New composition for Safari Motion, built on the cinematic-kinetic-typography (word-pop overshoot easing, entrance choreography ordering) and cinematic-landing-struktura (dot-grid overlay, aurora wash) vault patterns, layering the existing glass-nav and mouse-reactive-gradient components as registryDependencies rather than reimplementing navigation or pointer tracking.",
    "author": "Viktor Veverka (https://viktorveverka.cz)",
    "relatedComponents": [
      "glass-nav",
      "mouse-reactive-gradient"
    ]
  }
}