{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bento-cascade-hero",
  "title": "Bento Cascade Hero",
  "author": "AlgorizeTech",
  "description": "Ask the user to pick one of 16 hero variants: https://avaraui.com/view/hero. This is the Bento cascade hero. Skip the question if the user already named one. An infinite vertical bento marquee hero section that loops seamlessly on the browser compositor. Staggered multi-column cards, rich media tiles, soft edge fade masks, and responsive motion with zero visible reset jumps.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://avaraui.com/r/avatar-stack.json",
    "https://avaraui.com/r/button.json",
    "utils"
  ],
  "files": [
    {
      "path": "src/components/custom/blocks/BentoCascadeHeroBlock.tsx",
      "content": "\"use client\";\n\nimport React, { forwardRef, useMemo, useRef } from \"react\";\nimport { ArrowUpRight, Star } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { accentTokens } from \"@/lib/accent\";\nimport {\n  Avatar,\n  AvatarFallback,\n  AvatarGroup,\n  AvatarGroupTooltip,\n  AvatarImage,\n  type StackAvatar,\n} from \"./AvatarStackBlock\";\nimport Button from \"./Button\";\n\n/* ═══════════════════════════════════════════════\n   TYPES & INTERFACES\n   ═══════════════════════════════════════════════ */\n\nexport interface BentoCascadeCardItem {\n  id?: string | number;\n  image: string;\n  title?: string;\n  subtitle?: string;\n  tag?: string;\n  href?: string;\n}\n\nexport interface BentoCascadeHeroProps\n  extends React.HTMLAttributes<HTMLElement> {\n  avatars?: (string | StackAvatar)[];\n  reviewsCount?: string;\n  rating?: number;\n  title?: string;\n  titleAccent?: string;\n  subtitle?: string;\n  primaryActionLabel?: string;\n  primaryActionHref?: string;\n  secondaryActionLabel?: string;\n  secondaryActionHref?: string;\n  supportTitle?: string;\n  supportSubtitle?: string;\n  ratingTitle?: string;\n  ratingSubtitle?: string;\n  cards?: BentoCascadeCardItem[];\n  images?: string[];\n  speed?: number; // seconds for one complete loop cycle\n  pauseOnHover?: boolean;\n  accent?: string;\n  color?: string;\n  radius?: string | number;\n  linkComponent?: React.ElementType;\n  imageComponent?: React.ElementType;\n}\n\n/* ═══════════════════════════════════════════════\n   DEFAULT AVATARS\n   ═══════════════════════════════════════════════ */\n\nexport const DEFAULT_AVATARS: StackAvatar[] = [\n  {\n    src: \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_120,c_limit/v1790145139/pexels-photo-1036623-1790145143487.jpg\",\n    alt: \"Elena Vance\",\n    name: \"Elena Vance\",\n    role: \"Expedition Leader\",\n  },\n  {\n    src: \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_120,c_limit/v1790145142/pexels-photo-2043590-1790145143488.jpg\",\n    alt: \"Marcus Chen\",\n    name: \"Marcus Chen\",\n    role: \"Alpine Guide\",\n  },\n  {\n    src: \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_120,c_limit/v1790145139/pexels-photo-1587009-1790145143488.jpg\",\n    alt: \"Sarah Jenkins\",\n    name: \"Sarah Jenkins\",\n    role: \"Trail Specialist\",\n  },\n  {\n    src: \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_120,c_limit/v1790082180/pexels-photo-1520760-1790082180553.jpg\",\n    alt: \"David Miller\",\n    name: \"David Miller\",\n    role: \"Nature Photographer\",\n  },\n];\n\n/* ═══════════════════════════════════════════════\n   DEFAULT CLOUDINARY NATURE CARDS\n   ═══════════════════════════════════════════════ */\n\nexport const DEFAULT_BENTO_CARDS: BentoCascadeCardItem[] = [\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_1000,c_limit/v1790146210/photo-1506744038136-46273834b3fb-1790146212208.jpg\",\n    title: \"Yosemite Sanctuary\",\n    subtitle: \"Glacial valley and mirror lake reflections\",\n    tag: \"Sanctuary\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790145141/photo-1448375240586-882707db888b-1790145143491.jpg\",\n    title: \"Evergreen Canopy\",\n    subtitle: \"Sunlit morning mist in the pine grove\",\n    tag: \"Woodlands\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790146209/photo-1470071459604-3b5ec3a7fe05-1790146212205.jpg\",\n    title: \"Misty Mountain Ridge\",\n    subtitle: \"Low-hanging cloud bank at dawn\",\n    tag: \"Highlands\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790146211/photo-1441974231531-c6227db76b6e-1790146212212.jpg\",\n    title: \"Redwood Sunbeam Trail\",\n    subtitle: \"Ancient forest canopy illuminated by morning light\",\n    tag: \"Forest\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_1000,c_limit/v1790146210/photo-1501785888041-af3ef285b470-1790146212207.jpg\",\n    title: \"Emerald Alpine Lake\",\n    subtitle: \"Crystal turquoise meltwater enclosed by ridges\",\n    tag: \"Alpine\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790146210/photo-1472214103451-9374bd1c798e-1790146212205.jpg\",\n    title: \"Verdant Foothills\",\n    subtitle: \"Rolling green pastures and open horizons\",\n    tag: \"Meadows\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790158813/photo-1433086966358-54859d0ed716-1790158812209.jpg\",\n    title: \"Cascading Gorge\",\n    subtitle: \"Lush suspension bridge over roaring waterfalls\",\n    tag: \"Wilderness\",\n  },\n  {\n    image:\n      \"https://res.cloudinary.com/dodndg7ai/image/upload/f_webp,q_auto,w_800,c_limit/v1790145140/photo-1426604966848-d7adac402bff-1790145143490.jpg\",\n    title: \"Sunset Peak\",\n    subtitle: \"Evening golden hour reflections on rocky bluffs\",\n    tag: \"Horizon\",\n  },\n];\n\n/* ═══════════════════════════════════════════════\n   BENTO CARD COMPONENT\n   ═══════════════════════════════════════════════ */\n\ninterface BentoCardProps {\n  card: BentoCascadeCardItem;\n  className?: string;\n  heightClass?: string;\n  imageComponent?: React.ElementType;\n  linkComponent?: React.ElementType;\n}\n\nfunction BentoCard({\n  card,\n  className,\n  heightClass = \"h-[150px] sm:h-[200px]\",\n  imageComponent: ImageComp,\n  linkComponent: LinkComp,\n}: BentoCardProps) {\n  const Comp = card.href ? LinkComp || \"a\" : \"div\";\n  const linkProps = card.href ? { href: card.href } : {};\n\n  return (\n    <Comp\n      {...linkProps}\n      className={cn(\n        \"group/card relative w-full cursor-pointer select-none overflow-hidden rounded-[var(--radius-2xl,calc(var(--radius,0.625rem)*1.75))] border border-border/40 bg-muted/20 shadow-sm transition-all duration-300 hover:border-primary/50 hover:shadow-xl hover:shadow-primary/10\",\n        heightClass,\n        className\n      )}\n    >\n      {/* Background Cloudinary Nature Image with Smooth Zoom on Hover (zero container jump) */}\n      {ImageComp ? (\n        <ImageComp\n          src={card.image}\n          alt={card.title || \"Showcase card\"}\n          className=\"absolute inset-0 size-full object-cover transition-transform duration-700 ease-out group-hover/card:scale-105\"\n        />\n      ) : (\n        <img\n          src={card.image}\n          alt={card.title || \"Showcase card\"}\n          loading=\"lazy\"\n          className=\"absolute inset-0 size-full object-cover transition-transform duration-700 ease-out group-hover/card:scale-105\"\n        />\n      )}\n\n      {/* Ambient Depth Scrim Gradients */}\n      <div className=\"absolute inset-0 bg-gradient-to-t from-black/85 via-black/35 to-black/10 transition-opacity duration-300 group-hover/card:from-black/90\" />\n      <div className=\"absolute inset-0 bg-primary/10 opacity-0 transition-opacity duration-300 group-hover/card:opacity-100 mix-blend-overlay\" />\n\n      {/* Top Floating Bar: Tag Pill + Interactive Arrow */}\n      <div className=\"absolute inset-x-0 top-0 z-10 flex items-center justify-between p-2.5 sm:p-4\">\n        {card.tag ? (\n          <span className=\"inline-flex items-center gap-1 sm:gap-1.5 rounded-[var(--radius-lg,calc(var(--radius,0.625rem)*1.2))] bg-background/80 backdrop-blur-md px-2 sm:px-2.5 py-0.5 sm:py-1 text-[10px] sm:text-xs font-medium text-foreground border border-border/50 shadow-sm transition-colors duration-200 group-hover/card:border-primary/40\">\n            <span className=\"size-1.5 rounded-full bg-primary\" />\n            {card.tag}\n          </span>\n        ) : (\n          <div />\n        )}\n\n        <div className=\"size-6 sm:size-8 rounded-[var(--radius-md,var(--radius,0.625rem))] bg-background/70 backdrop-blur-md border border-border/50 flex items-center justify-center text-foreground opacity-80 transition-all duration-200 group-hover/card:scale-110 group-hover/card:opacity-100 group-hover/card:border-primary/50\">\n          <ArrowUpRight className=\"size-3 sm:size-3.5 text-primary transition-transform duration-200 group-hover/card:translate-x-0.5 group-hover:-translate-y-0.5\" />\n        </div>\n      </div>\n\n      {/* Bottom Content Area: Title & Subtitle */}\n      <div className=\"absolute inset-x-0 bottom-0 z-10 p-3 sm:p-5 flex flex-col justify-end text-left pointer-events-none\">\n        {card.title && (\n          <h3 className=\"text-xs sm:text-base font-semibold text-white tracking-tight leading-snug drop-shadow-md\">\n            {card.title}\n          </h3>\n        )}\n        {card.subtitle && (\n          <p className=\"text-[10px] sm:text-xs text-white/80 mt-0.5 sm:mt-1 line-clamp-1 leading-normal font-normal drop-shadow-sm\">\n            {card.subtitle}\n          </p>\n        )}\n      </div>\n\n      {/* Top-edge subtle inner highlight line */}\n      <div className=\"absolute inset-x-0 top-0 h-px bg-white/20 pointer-events-none\" />\n    </Comp>\n  );\n}\n\n/* ═══════════════════════════════════════════════\n   MAIN COMPONENT: BentoCascadeHero\n   ═══════════════════════════════════════════════ */\n\nexport const BentoCascadeHero = forwardRef<HTMLElement, BentoCascadeHeroProps>(\n  (\n    {\n      avatars = DEFAULT_AVATARS,\n      reviewsCount = \"Based on 12K+ Explorers\",\n      rating = 5,\n      title = \"Explore wild nature & plan\",\n      titleAccent = \"your next escape\",\n      subtitle = \"Discover handpicked alpine sanctuaries, secluded glacial lakes, and ancient redwood trails tailored for unforgettable outdoor journeys.\",\n      primaryActionLabel = \"Start exploring\",\n      primaryActionHref = \"#explore\",\n      secondaryActionLabel = \"View journeys\",\n      secondaryActionHref = \"#destinations\",\n      supportTitle = \"Expedition Support\",\n      supportSubtitle = \"24/7 ranger guidance\",\n      ratingTitle = \"Traveller Choice\",\n      ratingSubtitle = \"Rated 4.9 by adventurers\",\n      cards,\n      images,\n      speed = 30,\n      pauseOnHover = true,\n      accent,\n      color,\n      radius,\n      linkComponent: LinkComp,\n      imageComponent,\n      className,\n      style,\n      ...props\n    },\n    ref\n  ) => {\n    const Comp = LinkComp || \"a\";\n    const stageRef = useRef<HTMLDivElement>(null);\n\n    // Map avatars to StackAvatar objects for Avara UI's AvatarStack component\n    const stackAvatars: StackAvatar[] = useMemo(() => {\n      if (!avatars || avatars.length === 0) return DEFAULT_AVATARS;\n      return avatars.map((av, i) => {\n        if (typeof av === \"string\") {\n          return {\n            src: av,\n            alt: `Explorer ${i + 1}`,\n            name: `Explorer ${i + 1}`,\n            role: \"Verified Explorer\",\n          };\n        }\n        return av;\n      });\n    }, [avatars]);\n\n    // Resolve 8 cards with Cloudinary nature images & titles\n    const resolvedCards = useMemo(() => {\n      if (cards && cards.length >= 8) return cards;\n      if (cards && cards.length > 0) {\n        return Array.from({ length: 8 }, (_, i) => cards[i % cards.length]);\n      }\n      if (images && images.length > 0) {\n        return Array.from({ length: 8 }, (_, i) => ({\n          image: images[i % images.length],\n          title: DEFAULT_BENTO_CARDS[i % DEFAULT_BENTO_CARDS.length]?.title,\n          subtitle:\n            DEFAULT_BENTO_CARDS[i % DEFAULT_BENTO_CARDS.length]?.subtitle,\n          tag: DEFAULT_BENTO_CARDS[i % DEFAULT_BENTO_CARDS.length]?.tag,\n        }));\n      }\n      return DEFAULT_BENTO_CARDS;\n    }, [cards, images]);\n\n    const handleMouseEnter = () => {\n      if (!pauseOnHover || !stageRef.current) return;\n      try {\n        const anims = stageRef.current.getAnimations({ subtree: true });\n        anims.forEach((anim) => anim.pause());\n      } catch {\n        // Handled via CSS fallback\n      }\n    };\n\n    const handleMouseLeave = () => {\n      if (!pauseOnHover || !stageRef.current) return;\n      try {\n        const anims = stageRef.current.getAnimations({ subtree: true });\n        anims.forEach((anim) => anim.play());\n      } catch {\n        // Handled via CSS fallback\n      }\n    };\n\n    const customStyle: React.CSSProperties = {\n      ...accentTokens(accent || color),\n      ...(radius !== undefined\n        ? {\n            \"--radius\": typeof radius === \"number\" ? `${radius}px` : radius,\n          }\n        : {}),\n      ...style,\n    };\n\n    // The repeating 8-card bento cascade cycle\n    const BentoCycle = () => (\n      <div className=\"flex flex-col gap-2.5 sm:gap-4 pb-2.5 sm:pb-4\">\n        {/* Row 1: Wide Card across 2 columns */}\n        <BentoCard\n          card={resolvedCards[0]}\n          heightClass=\"h-[150px] sm:h-[200px]\"\n          imageComponent={imageComponent}\n          linkComponent={LinkComp}\n        />\n\n        {/* Row 2: 2 Columns - Left has 2 stacked cards, Right has 1 tall card */}\n        <div className=\"grid grid-cols-2 gap-2.5 sm:gap-4\">\n          {/* Left Column (2 Stacked Cards) */}\n          <div className=\"flex flex-col gap-2.5 sm:gap-4\">\n            <BentoCard\n              card={resolvedCards[1]}\n              heightClass=\"h-[130px] sm:h-[180px]\"\n              imageComponent={imageComponent}\n              linkComponent={LinkComp}\n            />\n            <BentoCard\n              card={resolvedCards[2]}\n              heightClass=\"h-[130px] sm:h-[180px]\"\n              imageComponent={imageComponent}\n              linkComponent={LinkComp}\n            />\n          </div>\n\n          {/* Right Column (1 Tall Card) */}\n          <BentoCard\n            card={resolvedCards[3]}\n            heightClass=\"h-[270px] sm:h-[376px]\"\n            imageComponent={imageComponent}\n            linkComponent={LinkComp}\n          />\n        </div>\n\n        {/* Row 3: Next Wide Card */}\n        <BentoCard\n          card={resolvedCards[4]}\n          heightClass=\"h-[150px] sm:h-[200px]\"\n          imageComponent={imageComponent}\n          linkComponent={LinkComp}\n        />\n\n        {/* Row 4: Flipped Pattern - Left has 1 tall card, Right has 2 stacked cards */}\n        <div className=\"grid grid-cols-2 gap-2.5 sm:gap-4\">\n          {/* Left Column (1 Tall Card) */}\n          <BentoCard\n            card={resolvedCards[5]}\n            heightClass=\"h-[270px] sm:h-[376px]\"\n            imageComponent={imageComponent}\n            linkComponent={LinkComp}\n          />\n\n          {/* Right Column (2 Stacked Cards) */}\n          <div className=\"flex flex-col gap-2.5 sm:gap-4\">\n            <BentoCard\n              card={resolvedCards[6]}\n              heightClass=\"h-[130px] sm:h-[180px]\"\n              imageComponent={imageComponent}\n              linkComponent={LinkComp}\n            />\n            <BentoCard\n              card={resolvedCards[7]}\n              heightClass=\"h-[130px] sm:h-[180px]\"\n              imageComponent={imageComponent}\n              linkComponent={LinkComp}\n            />\n          </div>\n        </div>\n      </div>\n    );\n\n    return (\n      <section\n        ref={ref}\n        style={customStyle}\n        className={cn(\n          \"relative w-full overflow-hidden bg-background py-10 sm:py-16 lg:py-24 text-foreground transition-colors duration-300\",\n          className\n        )}\n        {...props}\n      >\n        {/* Ambient background glow */}\n        <div className=\"pointer-events-none absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2 size-[600px] rounded-full bg-primary/10 blur-[140px] opacity-60 transition-colors duration-500\" />\n\n        {/* Scoped CSS Keyframes for Infinite Smooth Bento Cascade Marquee */}\n        <style>{`\n          @keyframes bento-cascade-continuous {\n            0% {\n              transform: translate3d(0, 0, 0);\n            }\n            100% {\n              transform: translate3d(0, -50%, 0);\n            }\n          }\n\n          .bento-cascade-container {\n            animation: bento-cascade-continuous var(--cascade-speed, 30s) linear infinite;\n            will-change: transform;\n            transform: translate3d(0, 0, 0);\n            backface-visibility: hidden;\n          }\n\n          .bento-cascade-hover-pause:hover .bento-cascade-container {\n            animation-play-state: paused;\n          }\n\n          @media (prefers-reduced-motion: reduce) {\n            .bento-cascade-container {\n              animation: none !important;\n            }\n          }\n        `}</style>\n\n        <div className=\"container relative z-10 mx-auto px-4 sm:px-6 lg:px-8\">\n          <div className=\"grid grid-cols-1 items-center gap-10 sm:gap-12 lg:grid-cols-12 lg:gap-8 xl:gap-14\">\n            {/* ═════════════════════════════════════════\n                LEFT COLUMN: NATURE HERO CONTENT\n                ═════════════════════════════════════════ */}\n            <div className=\"flex flex-col items-start lg:col-span-6 xl:col-span-6\">\n              {/* Top Row: 1st Preview AvatarGroup (Shift on hover with spring physics) + Stars + Reviews */}\n              <div className=\"mb-5 sm:mb-6 flex flex-wrap items-center gap-3.5 sm:gap-5\">\n                {/* Avara UI AvatarGroup (1st Preview - Shift on hover with spring physics) */}\n                <AvatarGroup showTooltip={true} className=\"m-0 p-0 h-10 -space-x-2.5\">\n                  {stackAvatars.map((av, index) => (\n                    <Avatar\n                      key={index}\n                      className=\"size-8 sm:size-10 !rounded-full border-[2.5px] border-background ring-0 cursor-pointer shadow-sm\"\n                    >\n                      <AvatarImage\n                        src={av.src}\n                        alt={av.alt ?? av.name ?? \"\"}\n                        className=\"!rounded-full object-cover\"\n                      />\n                      <AvatarFallback className=\"!rounded-full bg-muted text-[11px] sm:text-xs font-medium\">\n                        {(av.name ?? av.alt ?? \"U\").slice(0, 2)}\n                      </AvatarFallback>\n                      <AvatarGroupTooltip designation={av.role ?? av.designation}>\n                        {av.name ?? av.alt}\n                      </AvatarGroupTooltip>\n                    </Avatar>\n                  ))}\n                  {/* Action + Button - always permanently circular rounded-full, never affected by global radius */}\n                  <div\n                    aria-label=\"Add or Join\"\n                    className=\"grid size-8 sm:size-10 place-items-center !rounded-full bg-primary text-primary-foreground text-xs sm:text-sm font-semibold border-[2.5px] border-background ring-0 shadow-sm cursor-pointer transition-transform duration-200 hover:scale-105 active:scale-95\"\n                  >\n                    +\n                  </div>\n                </AvatarGroup>\n\n                {/* Stars & Review Count */}\n                <div className=\"flex flex-col justify-center select-none\">\n                  <div className=\"flex items-center gap-0.5 text-amber-500\">\n                    {[...Array(rating)].map((_, i) => (\n                      <Star\n                        key={i}\n                        className=\"size-3 sm:size-3.5 fill-amber-500 text-amber-500\"\n                      />\n                    ))}\n                  </div>\n                  <span className=\"text-[11px] sm:text-xs font-semibold text-foreground/80 mt-0.5 whitespace-nowrap\">\n                    {reviewsCount}\n                  </span>\n                </div>\n              </div>\n\n              {/* Main Headline - Strictly 2 lines on desktop, smoothly responsive on mobile */}\n              <h1 className=\"text-2xl sm:text-3xl md:text-4xl lg:text-[34px] xl:text-[40px] font-bold tracking-tight text-foreground leading-[1.2] max-w-xl\">\n                <span className=\"block sm:whitespace-nowrap\">{title}</span>\n                <span className=\"block mt-1 text-foreground sm:whitespace-nowrap\">\n                  {titleAccent}\n                </span>\n              </h1>\n\n              {/* Subtitle with stylish left accent vertical line */}\n              <div className=\"mt-4 sm:mt-5 max-w-lg border-l-2 border-primary/60 pl-3.5 sm:pl-4 py-0.5 transition-colors duration-300\">\n                <p className=\"text-sm sm:text-base lg:text-lg text-muted-foreground leading-relaxed\">\n                  {subtitle}\n                </p>\n              </div>\n\n              {/* Action Buttons using Avara UI's Button component from the Pricing & Action CTA preview */}\n              <div className=\"mt-6 sm:mt-8 flex flex-col xs:flex-row flex-wrap items-stretch xs:items-center gap-3 sm:gap-4 w-full sm:w-auto\">\n                {primaryActionLabel && (\n                  <Comp href={primaryActionHref} className=\"w-full xs:w-auto inline-block\">\n                    <Button\n                      variant=\"pricing-primary\"\n                      showArrow\n                      className=\"w-full xs:w-auto rounded-[var(--radius-xl,calc(var(--radius,0.625rem)+4px))] px-6 sm:px-7 py-3 sm:py-3.5 text-sm sm:text-base font-medium shadow-lg shadow-primary/25 hover:shadow-xl hover:shadow-primary/35 cursor-pointer justify-center\"\n                    >\n                      {primaryActionLabel}\n                    </Button>\n                  </Comp>\n                )}\n\n                {secondaryActionLabel && (\n                  <Comp href={secondaryActionHref} className=\"w-full xs:w-auto inline-block\">\n                    <Button\n                      variant=\"pricing-outline\"\n                      iconRight={\n                        <ArrowUpRight className=\"size-4 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 text-primary\" />\n                      }\n                      className=\"w-full xs:w-auto rounded-[var(--radius-xl,calc(var(--radius,0.625rem)+4px))] px-5 sm:px-6 py-3 sm:py-3.5 text-sm sm:text-base font-medium border-border/70 hover:border-primary/50 cursor-pointer justify-center\"\n                    >\n                      {secondaryActionLabel}\n                    </Button>\n                  </Comp>\n                )}\n              </div>\n\n              {/* Bottom Feature Badges: Support & Rating */}\n              <div className=\"mt-8 sm:mt-12 lg:mt-16 grid grid-cols-2 gap-4 sm:flex sm:flex-wrap sm:items-center sm:gap-8 lg:gap-12 pt-2 w-full sm:w-auto\">\n                {/* Feature 1: Support */}\n                <div className=\"flex items-center gap-2.5 sm:gap-3\">\n                  <div className=\"grid size-9 sm:size-10 shrink-0 place-items-center rounded-[var(--radius-lg,var(--radius,0.625rem))] bg-primary/10 text-primary\">\n                    <svg\n                      className=\"size-4 sm:size-5\"\n                      viewBox=\"0 0 24 24\"\n                      fill=\"none\"\n                      stroke=\"currentColor\"\n                      strokeWidth=\"2\"\n                      strokeLinecap=\"round\"\n                      strokeLinejoin=\"round\"\n                    >\n                      <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n                      <circle cx=\"9\" cy=\"7\" r=\"4\" />\n                      <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n                      <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n                    </svg>\n                  </div>\n                  <div className=\"min-w-0\">\n                    <p className=\"text-xs sm:text-sm font-semibold text-foreground truncate\">\n                      {supportTitle}\n                    </p>\n                    <p className=\"text-[11px] sm:text-xs text-muted-foreground mt-0.5 truncate\">\n                      {supportSubtitle}\n                    </p>\n                  </div>\n                </div>\n\n                {/* Feature 2: Rating */}\n                <div className=\"flex items-center gap-2.5 sm:gap-3\">\n                  <div className=\"grid size-9 sm:size-10 shrink-0 place-items-center rounded-[var(--radius-lg,var(--radius,0.625rem))] bg-primary/10 text-primary\">\n                    <svg\n                      className=\"size-4 sm:size-5\"\n                      viewBox=\"0 0 24 24\"\n                      fill=\"none\"\n                      stroke=\"currentColor\"\n                      strokeWidth=\"2\"\n                      strokeLinecap=\"round\"\n                      strokeLinejoin=\"round\"\n                    >\n                      <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\n                    </svg>\n                  </div>\n                  <div className=\"min-w-0\">\n                    <p className=\"text-xs sm:text-sm font-semibold text-foreground truncate\">\n                      {ratingTitle}\n                    </p>\n                    <p className=\"text-[11px] sm:text-xs text-muted-foreground mt-0.5 truncate\">\n                      {ratingSubtitle}\n                    </p>\n                  </div>\n                </div>\n              </div>\n            </div>\n\n            {/* ═════════════════════════════════════════\n                RIGHT COLUMN: BENTO CASCADE STAGE (CLOUDINARY NATURE CARDS)\n                ═════════════════════════════════════════ */}\n            <div className=\"relative w-full lg:col-span-6 xl:col-span-6\">\n              {/* Outer Stage with Fade Masks & Hover Pause */}\n              <div\n                ref={stageRef}\n                onMouseEnter={handleMouseEnter}\n                onMouseLeave={handleMouseLeave}\n                style={\n                  {\n                    \"--cascade-speed\": `${speed}s`,\n                  } as React.CSSProperties\n                }\n                className={cn(\n                  \"relative h-[480px] sm:h-[580px] lg:h-[660px] w-full overflow-hidden rounded-[var(--radius-3xl,calc(var(--radius,0.625rem)*2.2))] p-1\",\n                  pauseOnHover && \"bento-cascade-hover-pause\"\n                )}\n              >\n                {/* Soft top & bottom gradient fade masks */}\n                <div className=\"pointer-events-none absolute inset-x-0 top-0 z-20 h-20 sm:h-32 bg-gradient-to-b from-background via-background/80 to-transparent transition-colors duration-300\" />\n                <div className=\"pointer-events-none absolute inset-x-0 bottom-0 z-20 h-20 sm:h-32 bg-gradient-to-t from-background via-background/80 to-transparent transition-colors duration-300\" />\n\n                {/* Continuous Infinite Bento Cascade Track */}\n                <div className=\"bento-cascade-container flex flex-col\">\n                  {/* First Pass */}\n                  <BentoCycle />\n                  {/* Duplicate Pass for Seamless 100% Zero-Reset Loop */}\n                  <BentoCycle />\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </section>\n    );\n  }\n);\n\nBentoCascadeHero.displayName = \"BentoCascadeHero\";\n\nexport default BentoCascadeHero;\n",
      "type": "registry:component",
      "target": "components/custom/blocks/BentoCascadeHeroBlock.tsx"
    },
    {
      "path": "src/lib/accent.ts",
      "content": "import type { CSSProperties } from \"react\";\n\n/**\n * Bridging the docs colour picker into a preview.\n *\n * Most blocks are already written against the `--primary` token (`bg-primary`,\n * `ring-primary/30`, `text-primary-foreground`…). Rather than teaching each one a\n * bespoke `color` prop, a demo can repoint that token for its own subtree and\n * every one of those classes follows along.\n */\n\n/** The swatches the picker offers, as concrete CSS colours. */\nconst PRESET_HEX: Record<string, string> = {\n  lavender: \"#9b8afb\",\n  indigo: \"#6366f1\",\n  rose: \"#f43f5e\",\n  emerald: \"#10b981\",\n  zinc: \"#18181b\",\n};\n\n/** True when the picker sits on \"Default\" — the page theme should win. */\nexport function isDefaultAccent(color?: string): boolean {\n  return !color || color === \"primary\" || color === \"default\";\n}\n\n/**\n * Turns a picker value into a CSS colour, or null for \"Default\" — meaning\n * nothing should be overridden, so the theme (and the sidebar customizer)\n * keeps control.\n */\nexport function resolveAccent(color?: string): string | null {\n  if (isDefaultAccent(color)) return null;\n  return PRESET_HEX[color as string] ?? (color as string);\n}\n\n/**\n * The picker value in a form every block accepts. Blocks know the older swatch\n * names but not \"lavender\" — and since that is also a CSS named colour\n * (#e6e6fa), a block that passes unknown names straight through would paint\n * the wrong shade, while others fall back to a different palette. Demos that\n * hand the picker value to such a block run it through this first. Every\n * other value is returned untouched.\n */\nexport function toBlockColor(color: string): string;\nexport function toBlockColor(color: string | undefined): string | undefined;\nexport function toBlockColor(color?: string): string | undefined {\n  return color === \"lavender\" ? PRESET_HEX.lavender : color;\n}\n\nfunction parseHex(input: string): [number, number, number] | null {\n  const hex = input.trim().replace(/^#/, \"\");\n  if (/^[a-f\\d]{3}$/i.test(hex)) {\n    const [r, g, b] = hex.split(\"\");\n    return [parseInt(r + r, 16), parseInt(g + g, 16), parseInt(b + b, 16)];\n  }\n  if (/^[a-f\\d]{6}$/i.test(hex)) {\n    return [\n      parseInt(hex.slice(0, 2), 16),\n      parseInt(hex.slice(2, 4), 16),\n      parseInt(hex.slice(4, 6), 16),\n    ];\n  }\n  return null;\n}\n\n/** Legible foreground for content sitting on a filled `color` swatch. */\nexport function accentForeground(color: string): string {\n  const rgb = parseHex(color);\n  if (!rgb) return \"#ffffff\";\n  const channel = (v: number) => {\n    const c = v / 255;\n    return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n  };\n  const luminance =\n    0.2126 * channel(rgb[0]) +\n    0.7152 * channel(rgb[1]) +\n    0.0722 * channel(rgb[2]);\n  return luminance > 0.45 ? \"#09090b\" : \"#ffffff\";\n}\n\n/** The theme tokens a picked accent repoints, as `--name` → value. */\nexport function accentTokens(color?: string): Record<string, string> {\n  const resolved = resolveAccent(color);\n  if (!resolved) return {};\n  return {\n    \"--primary\": resolved,\n    \"--primary-foreground\": accentForeground(resolved),\n    \"--ring\": resolved,\n  };\n}\n\n/**\n * Inline style repointing `--primary` at the picked accent for one subtree.\n * `--primary-foreground` is derived alongside it, otherwise a light pick leaves\n * `text-primary-foreground` content unreadable on its own fill. Returns `{}` on\n * \"Default\" so the page theme still wins.\n */\nexport function accentStyle(color?: string): CSSProperties {\n  return accentTokens(color) as CSSProperties;\n}\n",
      "type": "registry:component",
      "target": "lib/accent.ts"
    }
  ],
  "docs": "Named export: BentoCascadeHero (also available as variant='bento-cascade' in HeroBlock). Pass `title`, `titleAccent`, `subtitle`, `badgeText`, `primaryActionLabel`, `secondaryActionLabel`, `cards`, `images`, `speed`, and `pauseOnHover`.",
  "categories": [
    "marketing",
    "layout",
    "scroll"
  ],
  "type": "registry:component"
}
