{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-aurora",
  "title": "Hero Aurora",
  "description": "Motion-first product hero with an animated aurora field, staggered reveal, parallax panel, and metric ticker.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "badge"
  ],
  "files": [
    {
      "path": "payload-components/source/blocks/shared/heroFields.ts",
      "content": "import type { Field } from 'payload'\n\nimport { linkGroup } from '@/fields/linkGroup'\n\n/**\n * Shared field core for the Hero component family.\n *\n * Every hero variant spreads these fields first and then appends its own\n * variant-specific ones. Editing the\n * shared headline/eyebrow/description/CTA shape here updates every installed\n * hero block at once, so the family never drifts field-by-field across a repo.\n *\n * Installed once per repo at `src/blocks/shared/heroFields.ts`; re-running\n * `payload-components add hero-*` never overwrites a copy you have already edited.\n */\nexport const heroFields: Field[] = [\n  {\n    name: 'eyebrow',\n    type: 'text',\n  },\n  {\n    name: 'title',\n    type: 'text',\n    required: true,\n  },\n  {\n    name: 'description',\n    type: 'textarea',\n    required: true,\n  },\n  linkGroup({\n    overrides: {\n      admin: {\n        initCollapsed: true,\n      },\n      maxRows: 2,\n      minRows: 1,\n    },\n  }),\n]\n",
      "type": "registry:file",
      "target": "~/src/blocks/shared/heroFields.ts"
    },
    {
      "path": "payload-components/source/blocks/HeroAurora/config.ts",
      "content": "import type { Block } from 'payload'\n\nimport { heroFields } from '@/blocks/shared/heroFields'\n\nexport const HeroAurora: Block = {\n  slug: 'heroAurora',\n  // Existing apps must migrate stored data before adopting this identifier:\n  // https://www.payload-components.xyz/docs/registry#installed-source-and-migrations\n  dbName: 'pc_hero_aurora',\n  interfaceName: 'HeroAuroraBlock',\n  fields: [\n    // Shared hero core (eyebrow, title, description, CTA links). Variant-specific\n    // fields follow; edit the shared shape in @/blocks/shared/heroFields.\n    ...heroFields,\n    {\n      name: 'metrics',\n      type: 'array',\n      admin: {\n        initCollapsed: true,\n      },\n      fields: [\n        {\n          name: 'value',\n          type: 'text',\n          required: true,\n        },\n        {\n          name: 'label',\n          type: 'text',\n          required: true,\n        },\n      ],\n      maxRows: 3,\n    },\n    {\n      name: 'productImage',\n      type: 'upload',\n      relationTo: 'media',\n    },\n    {\n      name: 'imageCaption',\n      type: 'text',\n    },\n    {\n      name: 'proofItems',\n      type: 'array',\n      admin: {\n        initCollapsed: true,\n      },\n      fields: [\n        {\n          name: 'label',\n          type: 'text',\n          required: true,\n        },\n      ],\n      maxRows: 4,\n    },\n  ],\n  labels: {\n    plural: 'Hero Aurora Blocks',\n    singular: 'Hero Aurora',\n  },\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/HeroAurora/config.ts"
    },
    {
      "path": "payload-components/source/blocks/HeroAurora/Component.tsx",
      "content": "'use client'\n\nimport React, { useEffect, useRef, useState } from 'react'\n\nimport type { Transition } from 'motion/react'\nimport { animate, motion, useMotionValue, useReducedMotion, useSpring, useTransform } from 'motion/react'\n\nimport type { HeroAuroraBlock as HeroAuroraBlockData } from '@/payload-types'\n\nimport { CMSLink } from '@/components/Link'\nimport { Media } from '@/components/Media'\nimport { Badge } from '@/components/ui/badge'\nimport { cn } from '@/utilities/ui'\n\n/* Hero Aurora — a motion-first product hero.\n *\n * Everything luminous is derived from the theme tokens (--brand, --brand-200,\n * --primary, --border, --background) via color-mix, so the same component\n * re-tints itself under any theme scope without a single hardcoded hue.\n * Motion (via the `motion` package) is presentation only: transform/opacity,\n * one spring set for the pointer parallax, and a scoped\n * prefers-reduced-motion net that forces the finished frame — before\n * hydration, without JavaScript, and in screenshot captures. */\n\ntype Props = HeroAuroraBlockData & {\n  id?: string\n  className?: string\n  disableInnerContainer?: boolean\n}\n\nconst EASE_OUT: Transition['ease'] = [0.16, 1, 0.3, 1]\nconst WORD_SPRING: Transition = { damping: 26, mass: 0.8, stiffness: 340, type: 'spring' }\nconst PANEL_SPRING: Transition = { damping: 26, mass: 1.1, stiffness: 150, type: 'spring' }\nconst CHIP_SPRING: Transition = { damping: 22, mass: 0.7, stiffness: 380, type: 'spring' }\nconst POINTER_SPRING = { damping: 20, mass: 0.4, stiffness: 160 }\n\n/* Aurora drift + the reduced-motion net. Scoped to this block's data\n * attributes and shipped inside the component so consumer repos inherit the\n * safety net with the file. Transform-only keyframes on pre-blurred\n * (gradient-falloff) layers — no animated filters, no background repaints. */\nconst auroraCss = `\n@keyframes pc-aurora-drift-a{0%,100%{transform:translate3d(-3%,-2%,0) scale(1)}50%{transform:translate3d(4%,3%,0) scale(1.08)}}\n@keyframes pc-aurora-drift-b{0%,100%{transform:translate3d(3%,3%,0) scale(1.06)}50%{transform:translate3d(-4%,-2%,0) scale(1)}}\n@keyframes pc-aurora-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.045)}}\n@keyframes pc-aurora-rays{0%,100%{transform:translate3d(-1.4%,0,0)}50%{transform:translate3d(1.4%,0,0)}}\n.pc-aurora-drift-a{animation:pc-aurora-drift-a 26s ease-in-out infinite}\n.pc-aurora-drift-b{animation:pc-aurora-drift-b 34s ease-in-out infinite}\n.pc-aurora-breathe{animation:pc-aurora-breathe 30s ease-in-out infinite}\n.pc-aurora-rays{animation:pc-aurora-rays 42s ease-in-out infinite}\n@media (prefers-reduced-motion: reduce){\n.pc-aurora-drift-a,.pc-aurora-drift-b,.pc-aurora-breathe,.pc-aurora-rays{animation:none}\n[data-aurora-root] *{animation-duration:.001s!important;animation-delay:0s!important;animation-iteration-count:1!important;transition-duration:.001s!important}\n[data-aurora-root] [data-aurora-reveal]{opacity:1!important;transform:none!important;stroke-dasharray:none!important}\n}\n`\n\n/* Server and client render identical initial markup (no hydration drift);\n * reduced motion zeroes the transition instead, and the scoped CSS net keeps\n * the frame final even before any JavaScript runs. */\nconst entrance = (reduceMotion: boolean, delay: number, distance = 18) => ({\n  animate: { opacity: 1, y: 0 },\n  initial: { opacity: 0, y: distance },\n  transition: reduceMotion ? { duration: 0 } : { delay, duration: 0.65, ease: EASE_OUT },\n})\n\nconst springEntrance = (\n  reduceMotion: boolean,\n  delay: number,\n  spring: Transition,\n  distance: number,\n  scale?: number,\n) => ({\n  animate: { opacity: 1, scale: 1, y: 0 },\n  initial: { opacity: 0, scale: scale ?? 1, y: distance },\n  transition: reduceMotion ? { duration: 0 } : { ...spring, delay },\n})\n\n/* ------------------------------------------------------------------ */\n/* Metric ticker                                                       */\n/* ------------------------------------------------------------------ */\n\ntype ParsedMetric = {\n  decimals: number\n  grouped: boolean\n  prefix: string\n  suffix: string\n  target: number\n}\n\nconst parseMetricValue = (raw: string): ParsedMetric | null => {\n  const match = /^([^0-9]*)([0-9][0-9,]*(?:\\.[0-9]+)?)([\\s\\S]*)$/.exec(raw.trim())\n  if (!match) return null\n  const [, prefix, numeric, suffix] = match\n  const target = Number.parseFloat(numeric.replace(/,/g, ''))\n  if (!Number.isFinite(target)) return null\n  const decimals = numeric.includes('.') ? numeric.split('.')[1].length : 0\n  return { decimals, grouped: numeric.includes(','), prefix, suffix, target }\n}\n\nconst formatMetricValue = (parsed: ParsedMetric, value: number): string => {\n  const text = parsed.grouped\n    ? value.toLocaleString('en-US', {\n        maximumFractionDigits: parsed.decimals,\n        minimumFractionDigits: parsed.decimals,\n      })\n    : value.toFixed(parsed.decimals)\n  return `${parsed.prefix}${text}${parsed.suffix}`\n}\n\n/* Server-renders the final value (captures and no-JS read the finished\n * number), then counts up through the same rAF motion runs on. The count\n * writes textContent directly — zero re-renders. Unparsable values simply\n * keep the parent fade. A ghost span reserves the final width so the ticker\n * never causes layout shift. */\nfunction MetricTicker({\n  delay,\n  reduceMotion,\n  value,\n}: {\n  delay: number\n  reduceMotion: boolean\n  value: string\n}) {\n  const nodeRef = useRef<HTMLSpanElement>(null)\n\n  useEffect(() => {\n    const node = nodeRef.current\n    const parsed = parseMetricValue(value)\n    if (reduceMotion || !node || !parsed) return\n\n    const controls = animate(0, parsed.target, {\n      delay,\n      duration: 1.3,\n      ease: EASE_OUT,\n      onComplete: () => {\n        node.textContent = value\n      },\n      onUpdate: (latest) => {\n        node.textContent = formatMetricValue(parsed, latest)\n      },\n    })\n\n    return () => {\n      controls.stop()\n      node.textContent = value\n    }\n  }, [delay, reduceMotion, value])\n\n  return (\n    <span className=\"relative inline-flex justify-center\">\n      <span aria-hidden=\"true\" className=\"invisible\">\n        {value}\n      </span>\n      <span className=\"absolute inset-0 text-center\" ref={nodeRef}>\n        {value}\n      </span>\n    </span>\n  )\n}\n\n/* ------------------------------------------------------------------ */\n/* Aurora field — the layered light atmosphere behind the content      */\n/* ------------------------------------------------------------------ */\n\nfunction AuroraField() {\n  return (\n    <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-0 -z-10\" data-aurora-field>\n      {/* Base wash pooling under the headline. */}\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          background:\n            'radial-gradient(100% 54% at 50% -4%, color-mix(in oklab, var(--brand) 8%, transparent), transparent 60%)',\n        }}\n      />\n      {/* Aurora arch — the top rim of a huge ring rising behind the\n          headline, breathing slowly. */}\n      <div className=\"absolute left-1/2 top-0 h-[34rem] w-[165%] -translate-x-1/2 sm:w-full\">\n        <div\n          className=\"pc-aurora-breathe h-full w-full\"\n          style={{\n            background:\n              'radial-gradient(85% 180% at 50% 165%, transparent 71%, color-mix(in oklab, var(--brand) 26%, transparent) 74.5%, color-mix(in oklab, var(--brand-100) 88%, transparent) 77.5%, color-mix(in oklab, var(--brand) 20%, transparent) 80%, transparent 83.5%)',\n            transformOrigin: '50% 165%',\n          }}\n        />\n      </div>\n      {/* Curtain rays hanging from the arch, shimmering sideways. */}\n      <div className=\"absolute left-1/2 top-0 h-[68%] w-[112%] -translate-x-1/2 opacity-70 sm:opacity-100\">\n        <div\n          className=\"pc-aurora-rays h-full w-full\"\n          style={{\n            background:\n              'linear-gradient(96deg, transparent 6%, color-mix(in oklab, var(--brand) 7%, transparent) 11%, transparent 15%, color-mix(in oklab, var(--brand-200) 28%, transparent) 21%, transparent 26%, color-mix(in oklab, var(--brand) 12%, transparent) 33%, transparent 38%, color-mix(in oklab, var(--brand-100) 42%, transparent) 45%, transparent 51%, color-mix(in oklab, var(--brand) 9%, transparent) 58%, transparent 63%, color-mix(in oklab, var(--brand-200) 24%, transparent) 70%, transparent 75%, color-mix(in oklab, var(--brand) 7%, transparent) 82%, transparent 87%)',\n            maskImage: 'linear-gradient(180deg, black 10%, transparent 88%)',\n          }}\n        />\n      </div>\n      {/* Drifting corner glows — soft gradient falloff stands in for blur,\n          so the drift is pure compositor transform. */}\n      <div\n        className=\"pc-aurora-drift-a absolute -left-[14%] -top-[8%] h-[22rem] w-[36rem] max-w-none\"\n        style={{\n          background:\n            'radial-gradient(46% 44% at 50% 50%, color-mix(in oklab, var(--brand-200) 40%, transparent), transparent 70%)',\n        }}\n      />\n      <div\n        className=\"pc-aurora-drift-b absolute -right-[12%] -top-[6%] h-[20rem] w-[34rem] max-w-none\"\n        style={{\n          background:\n            'radial-gradient(46% 42% at 50% 50%, color-mix(in oklab, var(--brand-100) 52%, transparent), transparent 70%)',\n        }}\n      />\n      <div\n        className=\"absolute inset-0 opacity-70\"\n        style={{\n          backgroundImage:\n            'radial-gradient(color-mix(in oklab, var(--foreground) 9%, transparent) 1px, transparent 1.5px)',\n          backgroundSize: '26px 26px',\n          maskImage: 'radial-gradient(105% 72% at 50% 0%, black 36%, transparent 76%)',\n        }}\n      />\n      {/* Ink floor grounds the composition. */}\n      <div\n        className=\"absolute inset-x-0 bottom-0 h-2/3\"\n        style={{\n          background:\n            'radial-gradient(90% 90% at 50% 120%, color-mix(in oklab, var(--primary) 7%, transparent), transparent 62%)',\n        }}\n      />\n      {/* Veil keeps the headline zone airy and AA-clean on any tint. */}\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          background:\n            'radial-gradient(60% 44% at 50% 30%, color-mix(in oklab, var(--background) 68%, transparent), transparent 78%)',\n        }}\n      />\n    </div>\n  )\n}\n\n/* ------------------------------------------------------------------ */\n/* Dashboard glow — the token-derived scene shown without an image     */\n/* ------------------------------------------------------------------ */\n\nconst CHART_LINE =\n  'M0 300 C84 292 128 250 196 246 C258 242 300 210 356 196 C418 180 458 150 516 128 C572 106 634 92 720 72'\nconst CHART_GHOST =\n  'M0 326 C96 320 160 296 232 290 C320 282 380 260 452 246 C540 228 632 210 720 198'\n\nfunction DashboardGlow({ reduceMotion }: { reduceMotion: boolean }) {\n  const gradientId = React.useId()\n\n  return (\n    <div className=\"absolute inset-0\" data-aurora-scene>\n      {/* Tinted glass base. */}\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          background:\n            'linear-gradient(180deg, color-mix(in oklab, var(--brand) 10%, var(--background)), var(--background) 58%)',\n        }}\n      />\n      {/* Graph grid. */}\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          backgroundImage:\n            'linear-gradient(color-mix(in oklab, var(--border) 80%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in oklab, var(--border) 80%, transparent) 1px, transparent 1px)',\n          backgroundSize: '44px 44px',\n          maskImage: 'linear-gradient(180deg, black 26%, transparent 96%)',\n        }}\n      />\n      {/* Bloom behind the chart's climb. */}\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          background:\n            'radial-gradient(42% 52% at 72% 30%, color-mix(in oklab, var(--brand) 13%, transparent), transparent 72%)',\n        }}\n      />\n      {/* Signal line, drawing itself on arrival. */}\n      <svg\n        aria-hidden=\"true\"\n        className=\"absolute inset-x-0 bottom-0 h-[72%] w-full\"\n        fill=\"none\"\n        preserveAspectRatio=\"none\"\n        viewBox=\"0 0 720 360\"\n      >\n        <defs>\n          <linearGradient gradientUnits=\"userSpaceOnUse\" id={gradientId} x1=\"0\" x2=\"0\" y1=\"60\" y2=\"360\">\n            <stop offset=\"0\" stopColor=\"var(--brand)\" stopOpacity=\"0.25\" />\n            <stop offset=\"1\" stopColor=\"var(--brand)\" stopOpacity=\"0\" />\n          </linearGradient>\n        </defs>\n        <path\n          d={CHART_GHOST}\n          stroke=\"color-mix(in oklab, var(--foreground) 16%, transparent)\"\n          strokeDasharray=\"3 7\"\n          strokeWidth=\"1.5\"\n          vectorEffect=\"non-scaling-stroke\"\n        />\n        <motion.path\n          animate={{ opacity: 1 }}\n          d={`${CHART_LINE} L720 360 L0 360 Z`}\n          data-aurora-reveal\n          fill={`url(#${gradientId})`}\n          initial={{ opacity: 0 }}\n          transition={reduceMotion ? { duration: 0 } : { delay: 1.9, duration: 0.9, ease: 'easeOut' }}\n        />\n        <motion.path\n          animate={{ opacity: 1, pathLength: 1 }}\n          d={CHART_LINE}\n          data-aurora-reveal\n          initial={{ opacity: 0, pathLength: 0 }}\n          stroke=\"var(--brand)\"\n          strokeLinecap=\"round\"\n          strokeWidth=\"2.5\"\n          transition={reduceMotion ? { duration: 0 } : { delay: 1.0, duration: 1.5, ease: 'easeInOut' }}\n          vectorEffect=\"non-scaling-stroke\"\n        />\n        <motion.g\n          animate={{ opacity: 1 }}\n          data-aurora-reveal\n          initial={{ opacity: 0 }}\n          transition={reduceMotion ? { duration: 0 } : { delay: 2.3, duration: 0.5, ease: EASE_OUT }}\n        >\n          <circle cx=\"664\" cy=\"80\" fill=\"color-mix(in oklab, var(--brand) 22%, transparent)\" r=\"14\" />\n          <circle cx=\"664\" cy=\"80\" fill=\"var(--brand)\" r=\"4.5\" />\n        </motion.g>\n      </svg>\n    </div>\n  )\n}\n\n/* ------------------------------------------------------------------ */\n/* Block                                                               */\n/* ------------------------------------------------------------------ */\n\nexport const HeroAuroraBlock: React.FC<Props> = ({\n  className,\n  description,\n  disableInnerContainer,\n  eyebrow,\n  id,\n  imageCaption,\n  links,\n  metrics,\n  productImage,\n  proofItems,\n  title,\n}) => {\n  const reduceMotion = useReducedMotion() ?? false\n\n  /* Pointer parallax — one springed value set, active only on hover-capable\n     pointers. Touch and reduced-motion keep the panel perfectly still. */\n  const [pointerFine, setPointerFine] = useState(false)\n  useEffect(() => {\n    const query = window.matchMedia('(hover: hover) and (pointer: fine)')\n    const update = () => setPointerFine(query.matches)\n    update()\n    query.addEventListener('change', update)\n    return () => query.removeEventListener('change', update)\n  }, [])\n  const interactive = pointerFine && !reduceMotion\n\n  const pointerX = useMotionValue(0.5)\n  const pointerY = useMotionValue(0.5)\n  const rotateX = useSpring(useTransform(pointerY, [0, 1], [4.5, -4.5]), POINTER_SPRING)\n  const rotateY = useSpring(useTransform(pointerX, [0, 1], [-6.5, 6.5]), POINTER_SPRING)\n  const panelX = useSpring(useTransform(pointerX, [0, 1], [-6, 6]), POINTER_SPRING)\n  const panelY = useSpring(useTransform(pointerY, [0, 1], [-4, 4]), POINTER_SPRING)\n  const sheenX = useSpring(useTransform(pointerX, [0, 1], [-70, 70]), POINTER_SPRING)\n  const shadowX = useTransform(rotateY, [-6.5, 6.5], [16, -16])\n\n  const handlePointerMove = (event: React.PointerEvent<HTMLElement>) => {\n    if (!interactive || event.pointerType === 'touch') return\n    const rect = event.currentTarget.getBoundingClientRect()\n    pointerX.set((event.clientX - rect.left) / rect.width)\n    pointerY.set((event.clientY - rect.top) / rect.height)\n  }\n  const handlePointerLeave = () => {\n    pointerX.set(0.5)\n    pointerY.set(0.5)\n  }\n\n  const words = (title ?? '').trim().split(/\\s+/).filter(Boolean)\n\n  return (\n    <section className={cn('container', className)} id={id ? `block-${id}` : undefined}>\n      <style>{auroraCss}</style>\n      <div\n        className=\"relative isolate overflow-hidden rounded-frame border border-border/70 bg-background px-6 py-14 sm:px-10 sm:py-16 lg:px-14 lg:py-20\"\n        data-aurora-root\n      >\n        <AuroraField />\n        <div\n          className={cn('relative flex flex-col items-center gap-12 lg:gap-14', {\n            'mx-auto max-w-6xl': !disableInnerContainer,\n          })}\n        >\n          <div className=\"mx-auto flex max-w-3xl flex-col items-center gap-6 text-center\">\n            {eyebrow ? (\n              <motion.div data-aurora-reveal {...entrance(reduceMotion, 0.05, 14)}>\n                <Badge\n                  className=\"gap-2 rounded-full border-border/80 bg-background/80 px-3 py-1 uppercase tracking-eyebrow text-muted-foreground\"\n                  variant=\"outline\"\n                >\n                  <span aria-hidden=\"true\" className=\"size-1.5 rounded-full bg-brand\" />\n                  {eyebrow}\n                </Badge>\n              </motion.div>\n            ) : null}\n\n            <div className=\"flex flex-col gap-5\">\n              <h2 className=\"text-4xl font-medium leading-[1.06] tracking-display text-balance text-foreground sm:text-6xl\">\n                <span className=\"sr-only\">{title}</span>\n                <span aria-hidden=\"true\">\n                  {words.map((word, index) => {\n                    const isLast = index === words.length - 1\n                    return (\n                      <React.Fragment key={`${word}-${index}`}>\n                        <motion.span\n                          className={cn(\n                            'inline-block',\n                            isLast && 'font-serif italic tracking-title text-brand-600',\n                          )}\n                          data-aurora-reveal\n                          {...springEntrance(reduceMotion, 0.16 + index * 0.055, WORD_SPRING, 34)}\n                        >\n                          {word}\n                        </motion.span>\n                        {isLast ? null : ' '}\n                      </React.Fragment>\n                    )\n                  })}\n                </span>\n              </h2>\n              <motion.p\n                className=\"mx-auto max-w-xl text-base leading-7 text-muted-foreground sm:text-lg\"\n                data-aurora-reveal\n                {...entrance(reduceMotion, 0.42, 16)}\n              >\n                {description}\n              </motion.p>\n            </div>\n\n            {links && links.length > 0 ? (\n              <motion.div\n                className=\"flex flex-col justify-center gap-3 pt-1 sm:flex-row\"\n                data-aurora-reveal\n                {...entrance(reduceMotion, 0.54, 16)}\n              >\n                {links.map(({ link }, index) => (\n                  <CMSLink\n                    key={index}\n                    appearance={link.appearance === 'outline' ? 'outline' : 'default'}\n                    {...link}\n                  />\n                ))}\n              </motion.div>\n            ) : null}\n\n            {metrics && metrics.length > 0 ? (\n              <motion.dl\n                className=\"flex flex-wrap items-start justify-center gap-x-10 gap-y-4 pt-2\"\n                data-aurora-reveal\n                {...entrance(reduceMotion, 0.7, 18)}\n              >\n                {metrics.map(({ label, value }, index) => (\n                  <div\n                    key={`${label}-${index}`}\n                    className={cn(\n                      'flex flex-col items-center gap-1',\n                      index > 0 && 'sm:border-s sm:border-border/70 sm:ps-10',\n                    )}\n                  >\n                    <dd className=\"text-3xl font-medium tracking-display tabular-nums text-foreground sm:text-4xl\">\n                      <MetricTicker delay={0.95 + index * 0.12} reduceMotion={reduceMotion} value={value} />\n                    </dd>\n                    <dt className=\"text-xs uppercase tracking-eyebrow text-muted-foreground\">\n                      {label}\n                    </dt>\n                  </div>\n                ))}\n              </motion.dl>\n            ) : null}\n\n            {proofItems && proofItems.length > 0 ? (\n              <div className=\"flex flex-wrap justify-center gap-2.5\">\n                {proofItems.map(({ label }, index) => (\n                  <motion.div\n                    key={`${label}-${index}`}\n                    data-aurora-reveal\n                    {...entrance(reduceMotion, 0.84 + index * 0.05, 12)}\n                  >\n                    <Badge\n                      className=\"gap-1.5 rounded-full border-border/80 bg-background/70 px-3 py-1 text-xs font-normal text-muted-foreground sm:text-sm\"\n                      variant=\"outline\"\n                    >\n                      <span aria-hidden=\"true\" className=\"size-1 rounded-full bg-brand\" />\n                      {label}\n                    </Badge>\n                  </motion.div>\n                ))}\n              </div>\n            ) : null}\n          </div>\n\n          <motion.figure\n            className=\"group/panel relative w-full max-w-4xl\"\n            data-aurora-reveal\n            onPointerLeave={handlePointerLeave}\n            onPointerMove={handlePointerMove}\n            {...springEntrance(reduceMotion, 0.5, PANEL_SPRING, 44, 0.96)}\n          >\n            {/* Ground shadow leans against the tilt. */}\n            <motion.div\n              aria-hidden=\"true\"\n              className=\"absolute -bottom-9 left-[10%] -z-10 h-16 w-[80%] rounded-full opacity-70\"\n              style={{\n                background:\n                  'radial-gradient(50% 50% at 50% 50%, color-mix(in oklab, var(--primary) 24%, transparent), transparent 72%)',\n                x: shadowX,\n              }}\n            />\n            <motion.div\n              className=\"relative aspect-video rounded-panel border border-border/70 bg-card shadow-xl\"\n              style={{\n                rotateX,\n                rotateY,\n                transformPerspective: 1200,\n                transformStyle: 'preserve-3d',\n                x: panelX,\n                y: panelY,\n              }}\n            >\n              {/* Clipped scene layer (image or the token-derived glow). */}\n              <div className=\"absolute inset-0 overflow-hidden rounded-panel\">\n                {productImage ? (\n                  <Media imgClassName=\"h-full w-full object-cover\" resource={productImage} />\n                ) : (\n                  <DashboardGlow reduceMotion={reduceMotion} />\n                )}\n                {/* Pointer sheen, gliding across the glass. */}\n                <motion.div\n                  aria-hidden=\"true\"\n                  className=\"pointer-events-none absolute -inset-x-16 inset-y-0 opacity-0 transition-opacity duration-700 group-hover/panel:opacity-100\"\n                  style={{\n                    background:\n                      'radial-gradient(38% 60% at 50% 28%, color-mix(in oklab, var(--background) 55%, transparent), transparent 72%)',\n                    x: sheenX,\n                  }}\n                />\n              </div>\n\n              {productImage ? null : (\n                <>\n                  {/* KPI chips float above the panel plane — they detach in Z\n                      as the panel tilts toward the pointer. */}\n                  <motion.div\n                    aria-hidden=\"true\"\n                    className=\"absolute left-[5%] top-[10%] w-[24%] min-w-28 rounded-card border border-border/80 bg-background/90 p-3 shadow-lg\"\n                    data-aurora-reveal\n                    style={{ z: 44 }}\n                    {...springEntrance(reduceMotion, 1.1, CHIP_SPRING, 18, 0.94)}\n                  >\n                    <div className=\"h-1.5 w-12 rounded-full bg-muted-foreground/25\" />\n                    <div className=\"mt-3 flex items-end gap-1\">\n                      <div className=\"h-2.5 w-1.5 rounded-full bg-brand/25\" />\n                      <div className=\"h-4 w-1.5 rounded-full bg-brand/30\" />\n                      <div className=\"h-3 w-1.5 rounded-full bg-brand/35\" />\n                      <div className=\"h-5 w-1.5 rounded-full bg-brand/45\" />\n                      <div className=\"h-4 w-1.5 rounded-full bg-brand/55\" />\n                      <div className=\"h-6 w-1.5 rounded-full bg-brand/70\" />\n                      <div className=\"h-7 w-1.5 rounded-full bg-brand\" />\n                    </div>\n                  </motion.div>\n                  <motion.div\n                    aria-hidden=\"true\"\n                    className=\"absolute right-[5%] top-[26%] hidden items-center gap-3 rounded-card border border-border/80 bg-background/90 p-3 shadow-lg sm:flex\"\n                    data-aurora-reveal\n                    style={{ z: 30 }}\n                    {...springEntrance(reduceMotion, 1.25, CHIP_SPRING, 18, 0.94)}\n                  >\n                    <div\n                      className=\"relative size-10 rounded-full\"\n                      style={{\n                        background:\n                          'conic-gradient(var(--brand) 0 74%, color-mix(in oklab, var(--muted-foreground) 24%, transparent) 74% 100%)',\n                      }}\n                    >\n                      <div className=\"absolute inset-1.5 rounded-full bg-background/95\" />\n                    </div>\n                    <div className=\"flex flex-col gap-1.5\">\n                      <div className=\"h-1.5 w-10 rounded-full bg-muted-foreground/25\" />\n                      <div className=\"h-1.5 w-7 rounded-full bg-muted-foreground/15\" />\n                    </div>\n                  </motion.div>\n                  <motion.div\n                    aria-hidden=\"true\"\n                    className=\"absolute bottom-[9%] left-[5%] inline-flex items-center gap-2 rounded-full border border-border/80 bg-background/90 px-3 py-1.5 shadow-md\"\n                    data-aurora-reveal\n                    style={{ z: 36 }}\n                    {...springEntrance(reduceMotion, 1.4, CHIP_SPRING, 14, 0.94)}\n                  >\n                    <span className=\"relative flex size-2\">\n                      <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-60\" />\n                      <span className=\"relative inline-flex size-2 rounded-full bg-brand\" />\n                    </span>\n                    <span className=\"h-1.5 w-12 rounded-full bg-muted-foreground/30\" />\n                  </motion.div>\n                </>\n              )}\n\n              {/* Glass edge highlight. */}\n              <div\n                aria-hidden=\"true\"\n                className=\"pointer-events-none absolute inset-0 rounded-panel\"\n                style={{\n                  boxShadow:\n                    'inset 0 1px 0 color-mix(in oklab, var(--background) 85%, transparent), inset 0 0 0 1px color-mix(in oklab, var(--background) 35%, transparent)',\n                }}\n              />\n            </motion.div>\n            {imageCaption ? (\n              <motion.figcaption\n                className=\"mt-5 text-center text-sm text-muted-foreground\"\n                data-aurora-reveal\n                {...entrance(reduceMotion, 1.15, 10)}\n              >\n                {imageCaption}\n              </motion.figcaption>\n            ) : null}\n          </motion.figure>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:file",
      "target": "~/src/blocks/HeroAurora/Component.tsx"
    }
  ],
  "meta": {
    "payloadComponent": {
      "installCommand": "payload-components add hero-aurora",
      "postInstall": [
        "generate:types",
        "generate:importmap"
      ],
      "requiresPayloadComponentWrapper": true,
      "supportedTargets": [
        "payload-website-starter",
        "payload-blocks-app"
      ]
    }
  },
  "docs": "Payload Components installs this as a Payload CMS block for the Payload website starter shape.\n\nRecommended install:\n\n```bash\npnpm payload-components add hero-aurora\n```\n\nDirect shadcn install URL:\n\n```bash\npnpm dlx shadcn@latest add https://www.payload-components.xyz/r/hero-aurora.json\n```\n\nDirect shadcn installs only copy the block source files and shadcn UI dependencies. Use `payload-components add hero-aurora` when you also want Payload layout registration, `RenderBlocks` wiring, `generate:types`, and `generate:importmap` handled for you.",
  "type": "registry:block"
}