{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "modern-scroll-stack",
  "title": "Modern Scroll Stack",
  "author": "AlgorizeTech",
  "description": "Ask the user to pick one of 2 modern scroll stack variants: https://avaraui.com/view/modern-scroll-stack. This item holds 2 of them as looks of one component (fan, stacked). Skip the question if the user already named one. A sticky scroll-driven service cards stack where cards slide up from below with horizontal fan offsets and smoothly tilt into resting angles as they lock into place.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/custom/blocks/ModernScrollStackBlock.tsx",
      "content": "\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ModernScrollStackItem {\n  id: string;\n  title: string;\n  description: string;\n  /** Optional prominent metric/stat callout (used in the \"stacked\" variant, e.g. \"48h\", \"99.9%\"). */\n  stat?: string;\n  /** Optional category/step pill label (used in the \"stacked\" variant, e.g. \"01 · VELOCITY\"). */\n  badge?: string;\n  /** Card background color (CSS color value, e.g. \"#F6F3EE\"). */\n  bgColor?: string;\n  /** Card text and icon color (CSS color value, e.g. \"#3E2718\"). */\n  textColor?: string;\n  /** Custom icon node rendered in the top-left corner. */\n  icon?: React.ReactNode;\n  /** Optional image URL rendered in the top-left corner if provided. */\n  image?: string;\n  /** Target resting tilt in degrees when the card locks into the stack. */\n  rotation?: number;\n}\n\nexport interface ModernScrollStackProps {\n  /** Layout variant: \"fan\" spreads cards horizontally; \"stacked\" piles cards directly on top of one another in the center. */\n  variant?: \"fan\" | \"stacked\";\n  /** Array of cards to stack on scroll. Defaults to the 4 Demo 1 service cards. */\n  items?: ModernScrollStackItem[];\n  /** Small uppercase eyebrow label above the section heading. */\n  eyebrow?: string;\n  /** Main section heading. */\n  heading?: string;\n  /** Section description text below the heading. */\n  subheading?: string;\n  /** Show or hide the section header block. */\n  showHeader?: boolean;\n  /** Horizontal offset step (in px) between consecutive stacked cards on desktop. */\n  cardOffsetX?: number;\n  /** Vertical spacing (in px) between cards before they stack. */\n  cardGap?: number;\n  /** Sticky top position (in px) where cards lock into the stack. */\n  stickyTop?: number;\n  /** Card width (in px) on desktop screens. */\n  cardWidth?: number;\n  /** Card height (in px) on desktop screens. */\n  cardHeight?: number;\n  /** Optional scroll container ref when embedded inside a scrollable box. */\n  scrollerRef?: React.RefObject<HTMLElement | null>;\n  /** Additional classes for the root section. */\n  className?: string;\n}\n\n// ==========================================\n// CUSTOM VECTOR CARD ICONS\n// ==========================================\n\nfunction AiAutomationIcon() {\n  return (\n    <svg\n      width=\"46\"\n      height=\"46\"\n      viewBox=\"0 0 46 46\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.75\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      {/* Central AI processor core */}\n      <rect x=\"14\" y=\"14\" width=\"18\" height=\"18\" rx=\"4\" />\n      <path d=\"M23 19l1.4 2.6L27 23l-2.6 1.4L23 27l-1.4-2.6L19 23l2.6-1.4L23 19z\" />\n      {/* Neural connector nodes */}\n      <line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"14\" />\n      <circle cx=\"18\" cy=\"5\" r=\"2\" />\n      <line x1=\"28\" y1=\"6\" x2=\"28\" y2=\"14\" />\n      <circle cx=\"28\" cy=\"5\" r=\"2\" />\n      <line x1=\"18\" y1=\"32\" x2=\"18\" y2=\"40\" />\n      <circle cx=\"18\" cy=\"41\" r=\"2\" />\n      <line x1=\"28\" y1=\"32\" x2=\"28\" y2=\"40\" />\n      <circle cx=\"28\" cy=\"41\" r=\"2\" />\n      <line x1=\"6\" y1=\"18\" x2=\"14\" y2=\"18\" />\n      <circle cx=\"5\" cy=\"18\" r=\"2\" />\n      <line x1=\"6\" y1=\"28\" x2=\"14\" y2=\"28\" />\n      <circle cx=\"5\" cy=\"28\" r=\"2\" />\n      <line x1=\"32\" y1=\"18\" x2=\"40\" y2=\"18\" />\n      <circle cx=\"41\" cy=\"18\" r=\"2\" />\n      <line x1=\"32\" y1=\"28\" x2=\"40\" y2=\"28\" />\n      <circle cx=\"41\" cy=\"28\" r=\"2\" />\n    </svg>\n  );\n}\n\nfunction ProductStrategyIcon() {\n  return (\n    <svg\n      width=\"46\"\n      height=\"46\"\n      viewBox=\"0 0 46 46\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.75\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      {/* Outer compass ring */}\n      <circle cx=\"23\" cy=\"23\" r=\"17\" />\n      {/* Cardinal tick marks */}\n      <line x1=\"23\" y1=\"6\" x2=\"23\" y2=\"10\" />\n      <line x1=\"23\" y1=\"36\" x2=\"23\" y2=\"40\" />\n      <line x1=\"6\" y1=\"23\" x2=\"10\" y2=\"23\" />\n      <line x1=\"36\" y1=\"23\" x2=\"40\" y2=\"23\" />\n      {/* Precision navigation needle */}\n      <polygon points=\"29,17 25,25 17,29 21,21\" />\n      <circle cx=\"23\" cy=\"23\" r=\"1.5\" fill=\"currentColor\" />\n    </svg>\n  );\n}\n\nfunction CloudArchitectureIcon() {\n  return (\n    <svg\n      width=\"46\"\n      height=\"46\"\n      viewBox=\"0 0 46 46\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.75\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      {/* Top isometric layer */}\n      <polygon points=\"23,6 39,14.5 23,23 7,14.5\" />\n      {/* Middle isometric layer */}\n      <polyline points=\"7,23 23,31.5 39,23\" />\n      {/* Bottom isometric layer */}\n      <polyline points=\"7,31.5 23,40 39,31.5\" />\n      {/* Center vertical spine */}\n      <line x1=\"23\" y1=\"23\" x2=\"23\" y2=\"40\" />\n    </svg>\n  );\n}\n\nfunction InteractiveMotionIcon() {\n  return (\n    <svg\n      width=\"46\"\n      height=\"46\"\n      viewBox=\"0 0 46 46\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.75\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      {/* Smooth bezier motion curve */}\n      <path d=\"M8 36C14 36 16 10 23 23C30 36 32 10 38 10\" />\n      {/* Keyframe control handles */}\n      <line x1=\"8\" y1=\"36\" x2=\"18\" y2=\"36\" strokeDasharray=\"2.5 2.5\" />\n      <line x1=\"38\" y1=\"10\" x2=\"28\" y2=\"10\" strokeDasharray=\"2.5 2.5\" />\n      {/* Anchor nodes */}\n      <rect x=\"5\" y=\"33\" width=\"6\" height=\"6\" rx=\"1.5\" />\n      <rect x=\"35\" y=\"7\" width=\"6\" height=\"6\" rx=\"1.5\" />\n      <circle cx=\"23\" cy=\"23\" r=\"3.5\" />\n    </svg>\n  );\n}\n\nexport const DEFAULT_MODERN_SCROLL_STACK_ITEMS: ModernScrollStackItem[] = [\n  {\n    id: \"ai-automation\",\n    title: \"AI Automation\",\n    description:\n      \"Autonomous workflows that eliminate repetitive tasks and scale operations effortlessly\",\n    bgColor: \"#F7C844\",\n    textColor: \"#2B1C06\",\n    icon: <AiAutomationIcon />,\n    rotation: 0,\n  },\n  {\n    id: \"product-strategy\",\n    title: \"Product Strategy\",\n    description:\n      \"Data-backed roadmaps engineered to turn ambitious ideas into market-leading products\",\n    bgColor: \"#EB5E30\",\n    textColor: \"#FFFDF9\",\n    icon: <ProductStrategyIcon />,\n    rotation: 3.5,\n  },\n  {\n    id: \"cloud-architecture\",\n    title: \"Cloud Architecture\",\n    description:\n      \"Resilient, low-latency infrastructure built for global scale and zero-downtime deploys\",\n    bgColor: \"#98E3AD\",\n    textColor: \"#1A4325\",\n    icon: <CloudArchitectureIcon />,\n    rotation: -4.5,\n  },\n  {\n    id: \"interactive-motion\",\n    title: \"Interactive Motion\",\n    description:\n      \"Physics-driven micro-interactions and fluid transitions that make interfaces feel alive.\",\n    bgColor: \"#4086D6\",\n    textColor: \"#FFFFFF\",\n    icon: <InteractiveMotionIcon />,\n    rotation: 3.5,\n  },\n];\n\nexport const DEFAULT_STACKED_SCROLL_STACK_ITEMS: ModernScrollStackItem[] = [\n  {\n    id: \"velocity\",\n    badge: \"01 · VELOCITY\",\n    stat: \"10x\",\n    title: \"Faster Execution\",\n    description: \"Automated workflows from initial brief to production deploy\",\n    bgColor: \"#1E1B4B\",\n    textColor: \"#EEF2FF\",\n    icon: <AiAutomationIcon />,\n    rotation: 0,\n  },\n  {\n    id: \"uptime\",\n    badge: \"02 · RELIABILITY\",\n    stat: \"99.9%\",\n    title: \"Uptime SLA\",\n    description: \"Multi-region edge clusters with zero-downtime failover\",\n    bgColor: \"#065F46\",\n    textColor: \"#ECFDF5\",\n    icon: <CloudArchitectureIcon />,\n    rotation: -6.5,\n  },\n  {\n    id: \"turnaround\",\n    badge: \"03 · DELIVERY\",\n    stat: \"48h\",\n    title: \"Turnaround Time\",\n    description: \"From brief to first interactive concept and prototype\",\n    bgColor: \"#C2410C\",\n    textColor: \"#FFF7ED\",\n    icon: <ProductStrategyIcon />,\n    rotation: -2.5,\n  },\n  {\n    id: \"satisfaction\",\n    badge: \"04 · IMPACT\",\n    stat: \"4.9★\",\n    title: \"Partner Rating\",\n    description: \"Trusted by high-velocity product teams worldwide\",\n    bgColor: \"#581C87\",\n    textColor: \"#FAF5FF\",\n    icon: <InteractiveMotionIcon />,\n    rotation: 6.5,\n  },\n];\n\nconst DEFAULT_ROTATIONS = [0, 3.5, -4.5, 3.5];\nconst STACKED_ROTATIONS = [0, -6.5, -2.5, 6.5];\n\nexport function ModernScrollStack({\n  variant = \"fan\",\n  items,\n  eyebrow,\n  heading,\n  subheading,\n  showHeader = false,\n  cardOffsetX = 78,\n  cardGap = 48,\n  stickyTop = 72,\n  cardWidth,\n  cardHeight,\n  scrollerRef,\n  className,\n}: ModernScrollStackProps) {\n  const resolvedItems =\n    items ??\n    (variant === \"stacked\"\n      ? DEFAULT_STACKED_SCROLL_STACK_ITEMS\n      : DEFAULT_MODERN_SCROLL_STACK_ITEMS);\n  const resolvedCardWidth = cardWidth ?? (variant === \"stacked\" ? 430 : 316);\n  const resolvedCardHeight = cardHeight ?? (variant === \"stacked\" ? 308 : 376);\n\n  const sectionRef = useRef<HTMLDivElement>(null);\n  const cardRefs = useRef<(HTMLDivElement | null)[]>([]);\n  const innerCardRefs = useRef<(HTMLDivElement | null)[]>([]);\n  const currentAnglesRef = useRef<number[]>([]);\n  const currentXRef = useRef<number[]>([]);\n  const [containerWidth, setContainerWidth] = useState<number>(1024);\n  const [viewportHeight, setViewportHeight] = useState<number>(640);\n\n  const count = resolvedItems.length;\n\n  // Measure available container width & viewport height so horizontal fan offset,\n  // card size, and exact scroll termination adapt smoothly on all screens.\n  useEffect(() => {\n    const el = sectionRef.current;\n    if (!el) return;\n    const scroller = scrollerRef?.current ?? null;\n    const updateSize = () => {\n      setContainerWidth(el.clientWidth || 1024);\n      const vh = scroller\n        ? scroller.clientHeight\n        : typeof window !== \"undefined\"\n          ? window.innerHeight\n          : 640;\n      setViewportHeight(vh || 640);\n    };\n    updateSize();\n    const ro = new ResizeObserver(updateSize);\n    ro.observe(el);\n    if (scroller) ro.observe(scroller);\n    window.addEventListener(\"resize\", updateSize, { passive: true });\n    return () => {\n      ro.disconnect();\n      window.removeEventListener(\"resize\", updateSize);\n    };\n  }, [scrollerRef]);\n\n  const isMobile = containerWidth < 480;\n  const isSmallScreen = containerWidth < 640;\n\n  const effectiveCardWidth =\n    variant === \"fan\"\n      ? isMobile\n        ? Math.min(resolvedCardWidth, Math.max(176, Math.round(containerWidth * 0.6)))\n        : isSmallScreen\n          ? Math.min(resolvedCardWidth, Math.max(210, Math.round(containerWidth * 0.58)))\n          : Math.min(resolvedCardWidth, Math.max(240, containerWidth - 64))\n      : isMobile\n        ? Math.min(resolvedCardWidth, Math.max(216, containerWidth - 44))\n        : isSmallScreen\n          ? Math.min(resolvedCardWidth, Math.max(260, containerWidth - 56))\n          : Math.min(resolvedCardWidth, Math.max(240, containerWidth - 64));\n\n  const effectiveCardHeight =\n    effectiveCardWidth < resolvedCardWidth\n      ? Math.max(\n          variant === \"stacked\" ? 216 : 228,\n          Math.round(resolvedCardHeight * (effectiveCardWidth / resolvedCardWidth)),\n        )\n      : resolvedCardHeight;\n\n  const horizontalMargin = isMobile ? 24 : 32;\n  const maxTotalSpread = Math.max(\n    0,\n    containerWidth - effectiveCardWidth - horizontalMargin,\n  );\n  const effectiveOffsetX =\n    variant === \"stacked\"\n      ? 0\n      : count > 1\n        ? Math.min(cardOffsetX, Math.floor(maxTotalSpread / (count - 1)))\n        : 0;\n\n  const effectiveStickyTop = isMobile\n    ? Math.min(stickyTop, 44)\n    : isSmallScreen\n      ? Math.min(stickyTop, 56)\n      : stickyTop;\n\n  const effectiveCardGap = isMobile\n    ? Math.min(cardGap, 32)\n    : isSmallScreen\n      ? Math.min(cardGap, 40)\n      : cardGap;\n\n  // Distance Card 0 travels from the bottom of the viewport up to `effectiveStickyTop`\n  const card0TravelDistance = Math.min(\n    effectiveCardHeight + effectiveCardGap,\n    Math.max(\n      isMobile ? 160 : 220,\n      viewportHeight - effectiveStickyTop - (isMobile ? 110 : 160),\n    ),\n  );\n  const topSpacerHeight = effectiveStickyTop + card0TravelDistance;\n\n  // Exact spacer inside the sticky content box so scrolling ends the exact\n  // moment the last card reaches `effectiveStickyTop`, preventing cards from scrolling up.\n  const endSpacerHeight = Math.max(\n    0,\n    viewportHeight - effectiveStickyTop - effectiveCardHeight,\n  );\n\n  // Smooth inertial scroll & damped rotation interpolation:\n  // 1. Smooths discrete mousewheel steps on `scrollerRef` into a fluid glide.\n  // 2. Smoothly interpolates each card's rotation angle via a damped RAF loop\n  //    so cards tilt organically as they lock into `stickyTop`.\n  useEffect(() => {\n    const scroller = scrollerRef?.current ?? null;\n    let transformRafId = 0;\n    let wheelRafId = 0;\n    let isWheelAnimating = false;\n    let targetScrollTop = scroller ? scroller.scrollTop : 0;\n    let currentScrollTop = targetScrollTop;\n\n    if (currentAnglesRef.current.length !== count) {\n      currentAnglesRef.current = new Array(count).fill(0);\n    }\n    if (currentXRef.current.length !== count) {\n      currentXRef.current = new Array(count).fill(0);\n    }\n\n    const getCardProgress = (index: number, scrollerTop: number, startDistance: number) => {\n      const wrapperEl = cardRefs.current[index];\n      if (!wrapperEl) return 0;\n      const rect = wrapperEl.getBoundingClientRect();\n      const distanceFromSticky = rect.top - scrollerTop - effectiveStickyTop;\n      const raw =\n        startDistance > 0\n          ? 1 - Math.min(1, Math.max(0, distanceFromSticky / startDistance))\n          : 1;\n      return raw < 0.5\n        ? 4 * raw * raw * raw\n        : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n    };\n\n    const computeAndApplyTransforms = () => {\n      const scrollerTop = scroller\n        ? scroller.getBoundingClientRect().top\n        : 0;\n      const startDistance = effectiveCardHeight + effectiveCardGap;\n      let needsMoreFrames = false;\n\n      for (let i = 0; i < count; i++) {\n        const innerEl = innerCardRefs.current[i];\n        if (!innerEl) continue;\n\n        const targetRotation =\n          resolvedItems[i]?.rotation ??\n          (variant === \"stacked\"\n            ? STACKED_ROTATIONS[i % STACKED_ROTATIONS.length]\n            : DEFAULT_ROTATIONS[i % DEFAULT_ROTATIONS.length]) ??\n          0;\n\n        const finalXOffset = (i - (count - 1) / 2) * effectiveOffsetX;\n\n        // Every card (including Card 0) starts at the bottom in the center (x = 0, rotate = 0)\n        // and glides into its target horizontal slot & tilt as it rises to `stickyTop`.\n        const travelDist = i === 0 ? card0TravelDistance : startDistance;\n        const eased = getCardProgress(i, scrollerTop, travelDist);\n\n        const desiredX = eased * finalXOffset;\n        const desiredAngle = eased * targetRotation;\n\n        const prevX = currentXRef.current[i] ?? 0;\n        const nextX = prevX + (desiredX - prevX) * 0.16;\n        if (Math.abs(desiredX - nextX) > 0.05) {\n          currentXRef.current[i] = nextX;\n          needsMoreFrames = true;\n        } else {\n          currentXRef.current[i] = desiredX;\n        }\n\n        const prevAngle = currentAnglesRef.current[i] ?? 0;\n        const nextAngle = prevAngle + (desiredAngle - prevAngle) * 0.16;\n        if (Math.abs(desiredAngle - nextAngle) > 0.01) {\n          currentAnglesRef.current[i] = nextAngle;\n          needsMoreFrames = true;\n        } else {\n          currentAnglesRef.current[i] = desiredAngle;\n        }\n\n        innerEl.style.transform = `translate3d(${currentXRef.current[i].toFixed(2)}px, 0px, 0px) rotate(${currentAnglesRef.current[i].toFixed(3)}deg)`;\n      }\n\n      if (needsMoreFrames) {\n        transformRafId = requestAnimationFrame(computeAndApplyTransforms);\n      } else {\n        transformRafId = 0;\n      }\n    };\n\n    const scheduleTransformUpdate = () => {\n      if (!transformRafId) {\n        transformRafId = requestAnimationFrame(computeAndApplyTransforms);\n      }\n    };\n\n    const stepWheelScroll = () => {\n      if (!scroller) return;\n      const diff = targetScrollTop - currentScrollTop;\n      if (Math.abs(diff) > 0.4) {\n        currentScrollTop += diff * 0.11;\n        scroller.scrollTop = currentScrollTop;\n        scheduleTransformUpdate();\n        wheelRafId = requestAnimationFrame(stepWheelScroll);\n      } else {\n        currentScrollTop = targetScrollTop;\n        scroller.scrollTop = targetScrollTop;\n        isWheelAnimating = false;\n        wheelRafId = 0;\n        scheduleTransformUpdate();\n      }\n    };\n\n    const onWheel = (e: WheelEvent) => {\n      if (!scroller) return;\n      const maxScroll = scroller.scrollHeight - scroller.clientHeight;\n      if (maxScroll <= 0) return;\n\n      const delta =\n        e.deltaMode === 1\n          ? e.deltaY * 32\n          : e.deltaMode === 2\n            ? e.deltaY * scroller.clientHeight\n            : e.deltaY;\n\n      const atTop = scroller.scrollTop <= 0 && delta < 0;\n      const atBottom = scroller.scrollTop >= maxScroll - 1 && delta > 0;\n      if (atTop || atBottom) return;\n\n      e.preventDefault();\n      if (!isWheelAnimating) {\n        currentScrollTop = scroller.scrollTop;\n        targetScrollTop = currentScrollTop;\n      }\n\n      targetScrollTop = Math.max(\n        0,\n        Math.min(maxScroll, targetScrollTop + delta * 0.8),\n      );\n\n      if (!isWheelAnimating) {\n        isWheelAnimating = true;\n        wheelRafId = requestAnimationFrame(stepWheelScroll);\n      }\n    };\n\n    const onScroll = () => {\n      if (scroller && !isWheelAnimating) {\n        currentScrollTop = scroller.scrollTop;\n        targetScrollTop = currentScrollTop;\n      }\n      scheduleTransformUpdate();\n    };\n\n    computeAndApplyTransforms();\n\n    const target: EventTarget = scroller ?? window;\n    target.addEventListener(\"scroll\", onScroll, { passive: true });\n    if (scroller) {\n      scroller.addEventListener(\"wheel\", onWheel, { passive: false });\n    }\n    window.addEventListener(\"resize\", onScroll, { passive: true });\n\n    return () => {\n      if (transformRafId) cancelAnimationFrame(transformRafId);\n      if (wheelRafId) cancelAnimationFrame(wheelRafId);\n      target.removeEventListener(\"scroll\", onScroll);\n      if (scroller) {\n        scroller.removeEventListener(\"wheel\", onWheel);\n      }\n      window.removeEventListener(\"resize\", onScroll);\n    };\n  }, [\n    card0TravelDistance,\n    count,\n    effectiveCardGap,\n    effectiveCardHeight,\n    effectiveOffsetX,\n    effectiveStickyTop,\n    resolvedItems,\n    scrollerRef,\n    variant,\n  ]);\n\n  return (\n    <section\n      ref={sectionRef}\n      className={cn(\n        \"relative w-full pt-0 pb-0 px-3 sm:px-8 select-none\",\n        className,\n      )}\n    >\n      {showHeader && (\n        <div className=\"max-w-2xl mx-auto text-center flex flex-col items-center gap-2 pt-8 sm:pt-12 mb-6 sm:mb-10\">\n          {eyebrow && (\n            <span className=\"text-[10px] sm:text-[11px] font-bold uppercase tracking-[0.12em] text-[#E85A34]\">\n              {eyebrow}\n            </span>\n          )}\n          {heading && (\n            <h2 className=\"text-xl sm:text-[28px] font-bold tracking-[-0.02em] text-foreground leading-tight\">\n              {heading}\n            </h2>\n          )}\n          {subheading && (\n            <p className=\"text-[12.5px] sm:text-sm text-muted-foreground leading-relaxed max-w-xl mt-0.5\">\n              {subheading}\n            </p>\n          )}\n        </div>\n      )}\n\n      {/* Tall sticky stacking track */}\n      <div className=\"relative mx-auto flex flex-col items-center\">\n        <div\n          aria-hidden=\"true\"\n          className=\"w-full shrink-0 pointer-events-none\"\n          style={{ height: `${topSpacerHeight}px` }}\n        />\n        {resolvedItems.map((item, index) => {\n          const bgColor = item.bgColor ?? \"#F7C844\";\n          const textColor = item.textColor ?? \"#2B1C06\";\n\n          return (\n            <div\n              key={item.id}\n              ref={(el) => {\n                cardRefs.current[index] = el;\n              }}\n              className=\"sticky flex justify-center w-full pointer-events-none\"\n              style={{\n                top: `${effectiveStickyTop}px`,\n                marginTop: index === 0 ? \"0px\" : `${effectiveCardGap}px`,\n                zIndex: index + 1,\n              }}\n            >\n              <div\n                ref={(el) => {\n                  innerCardRefs.current[index] = el;\n                }}\n                className={cn(\n                  \"pointer-events-auto relative overflow-hidden flex flex-col justify-between will-change-transform origin-center\",\n                  variant === \"stacked\"\n                    ? \"rounded-[16px] sm:rounded-[20px] p-4 sm:p-8 border border-white/15\"\n                    : \"rounded-[14px] sm:rounded-[16px] p-4 sm:p-9\",\n                )}\n                style={{\n                  width: `${effectiveCardWidth}px`,\n                  height: `${effectiveCardHeight}px`,\n                  backgroundColor: bgColor,\n                  color: textColor,\n                  transform: \"translate3d(0px, 0px, 0px) rotate(0deg)\",\n                }}\n              >\n                {variant === \"stacked\" ? (\n                  <>\n                    {/* Decorative soft corner glow */}\n                    <div\n                      aria-hidden=\"true\"\n                      className=\"pointer-events-none absolute -top-20 -right-20 w-48 h-48 rounded-full opacity-20 blur-2xl\"\n                      style={{ backgroundColor: textColor }}\n                    />\n\n                    {/* Top bar: pill badge + icon circle */}\n                    <div className=\"relative z-10 flex items-center justify-between gap-2 sm:gap-3\">\n                      <span\n                        className=\"inline-flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-3 py-0.5 sm:py-1 rounded-full text-[9px] sm:text-[11px] font-bold uppercase tracking-[0.11em] sm:tracking-[0.14em]\"\n                        style={{\n                          backgroundColor: \"rgba(255,255,255,0.12)\",\n                          border: \"1px solid rgba(255,255,255,0.18)\",\n                        }}\n                      >\n                        <span\n                          className=\"w-1.5 h-1.5 rounded-full shrink-0\"\n                          style={{ backgroundColor: textColor }}\n                        />\n                        {item.badge ?? `0${index + 1} · HIGHLIGHT`}\n                      </span>\n\n                      <div\n                        className=\"w-7 h-7 sm:w-9 sm:h-9 rounded-full flex items-center justify-center shrink-0\"\n                        style={{\n                          backgroundColor: \"rgba(255,255,255,0.1)\",\n                          border: \"1px solid rgba(255,255,255,0.16)\",\n                        }}\n                      >\n                        <div className=\"scale-[0.42] sm:scale-[0.52] flex items-center justify-center\">\n                          {item.icon}\n                        </div>\n                      </div>\n                    </div>\n\n                    {/* Center hero stat + title */}\n                    <div className=\"relative z-10 flex flex-col items-center justify-center text-center my-auto py-1 sm:py-2\">\n                      {item.stat && (\n                        <span className=\"text-[36px] sm:text-[62px] font-extrabold tracking-[-0.04em] leading-none\">\n                          {item.stat}\n                        </span>\n                      )}\n                      <h3 className=\"text-[16px] sm:text-[22px] font-semibold tracking-[-0.02em] leading-tight mt-1 sm:mt-2\">\n                        {item.title}\n                      </h3>\n                    </div>\n\n                    {/* Bottom footer row */}\n                    <div\n                      className=\"relative z-10 flex items-center justify-between gap-3 sm:gap-4 pt-2.5 sm:pt-3.5 text-center\"\n                      style={{\n                        borderTop: \"1px solid rgba(255,255,255,0.15)\",\n                      }}\n                    >\n                      <p className=\"text-[11px] sm:text-[13.5px] leading-snug opacity-85 mx-auto font-normal line-clamp-2\">\n                        {item.description}\n                      </p>\n                    </div>\n                  </>\n                ) : (\n                  <>\n                    {/* Top-left icon or image */}\n                    <div className=\"flex items-start justify-start\">\n                      {item.image ? (\n                        <img\n                          src={item.image}\n                          alt={item.title}\n                          className=\"w-8 h-8 sm:w-12 sm:h-12 object-contain\"\n                          loading=\"lazy\"\n                        />\n                      ) : (\n                        <div className=\"w-8 h-8 sm:w-12 sm:h-12 flex items-center justify-start [&>svg]:w-full [&>svg]:h-full\">\n                          {item.icon}\n                        </div>\n                      )}\n                    </div>\n\n                    {/* Bottom-left title & description */}\n                    <div className=\"flex flex-col gap-1.5 sm:gap-2.5 text-left\">\n                      <h3 className=\"text-[17px] sm:text-[25px] font-bold tracking-[-0.02em] leading-[1.15]\">\n                        {item.title}\n                      </h3>\n                      <p className=\"text-[11.5px] sm:text-[13.5px] leading-[1.38] sm:leading-[1.45] opacity-90 max-w-[235px] font-normal\">\n                        {item.description}\n                      </p>\n                    </div>\n                  </>\n                )}\n              </div>\n            </div>\n          );\n        })}\n        <div\n          aria-hidden=\"true\"\n          className=\"w-full shrink-0 pointer-events-none\"\n          style={{ height: `${endSpacerHeight}px` }}\n        />\n      </div>\n    </section>\n  );\n}\n\nexport default ModernScrollStack;\n",
      "type": "registry:component",
      "target": "components/custom/blocks/ModernScrollStackBlock.tsx"
    }
  ],
  "docs": "Named export: ModernScrollStack (also default export), DEFAULT_MODERN_SCROLL_STACK_ITEMS, ModernScrollStackItem, and ModernScrollStackProps.",
  "categories": [
    "scroll",
    "marketing",
    "data-display"
  ],
  "type": "registry:component"
}
