{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "timeline-01",
  "title": "Timeline · 01",
  "description": "Timeline · 01 section.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/talizen/timeline/timeline-01/timeline-01.tsx",
      "content": "import { useLayoutEffect, useRef } from \"react\"\nimport { ArrowRight } from \"lucide-react\"\n\ntype TimelinePoint = {\n  percentage: number\n  label: string\n  subtitle: string\n  details: string[]\n  variant: \"left\" | \"right\"\n  mobileLabel?: string\n  mobileSubtitle: string\n  mobileDetails: string[]\n}\n\ntype PointPosition = {\n  x: number\n  y: number\n}\n\nexport type Timeline01Props = {\n  className?: string\n}\n\nconst PATH_D =\n  \"M1 2C299.481 2 593.937 49.2507 835.5 142.213 1143.67 260.81 1365.77 453.804 1400.3 718 1403.41 741.749 1405 766.074 1405 790.972C1405 1015.35 1206.5 1177.61 971 1343.12 752.77 1496.48 502.766 1652.64 349.5 1863.6 261.584 1984.61 205.499 2123.65 205.499 2290.54C205.499 2453.35 257.153 2581.89 336.864 2690.5 493.17 2903.47 757.359 3039.79 951.5 3207.49 1091.79 3328.68 1195.5 3466.25 1195.5 3660.98C1195.5 3836.03 1099.14 3925.77 980.477 4006.5 790.36 4135.85 542.999 4242.07 542.999 4639\"\n\nconst VIEWBOX_WIDTH = 1459\nconst VIEWBOX_HEIGHT = 4694\nconst INITIAL_PATH_LENGTH = 6785.34814453125\n\nconst points: TimelinePoint[] = [\n  {\n    percentage: 0.0001,\n    label: \"BORN\",\n    subtitle: \"C-Section\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"right\",\n    mobileSubtitle: \"C-Section\",\n    mobileDetails: [\"Microbiome optimization\", \"Genetic test\"],\n  },\n  {\n    percentage: 0.12,\n    label: \"Age 22\",\n    subtitle: \"Annual Superpower Baselin\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"right\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n  {\n    percentage: 0.25,\n    label: \"Age 26\",\n    subtitle: \"Gut health protocol\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"left\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n  {\n    percentage: 0.38,\n    label: \"Age 31\",\n    subtitle: \"Fertility protocol\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"left\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\"Prevent Alzheimer’s, heart disease, cancer\", \"Genetic test\"],\n  },\n  {\n    percentage: 0.48,\n    label: \"Age 41\",\n    subtitle: \"Hormone optimization protocol\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"left\",\n    mobileLabel: \"AGE 41\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n  {\n    percentage: 0.63,\n    label: \"Age 45\",\n    subtitle: \"Disease prevention program\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"right\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n  {\n    percentage: 0.73,\n    label: \"Age 60\",\n    subtitle: \"Longevity protocol\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"right\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n  {\n    percentage: 0.9,\n    label: \"Age 120\",\n    subtitle: \"Aging goal\",\n    details: [\"60 biomarker blood test\", \"60 biomarker blood test\"],\n    variant: \"left\",\n    mobileSubtitle: \"Longevity protocol\",\n    mobileDetails: [\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n      \"Prevent Alzheimer’s, heart disease, cancer\",\n    ],\n  },\n]\n\nfunction clamp(value: number, min = 0, max = 1) {\n  return Math.min(Math.max(value, min), max)\n}\n\nfunction getActiveIndex(progress: number) {\n  const nextIndex = points.findIndex((point) => progress < point.percentage)\n  return nextIndex === -1 ? points.length - 1 : Math.max(nextIndex - 1, 0)\n}\n\nfunction LifeGridIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      strokeWidth=\"1.5\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      aria-hidden\n      className={className}\n    >\n      <path d=\"M10 12V6h1\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M10 12h1V6\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M10 18v-3h1\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M11 15v3h-1\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M7 6v6\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M7 15v3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M14 6v6\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M14 15v3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M17 6v6\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M17 15v3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M6 3H3v3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M2 12h20\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M18 3h3v3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M6 21H3v-3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      <path d=\"M18 21h3v-3\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n    </svg>\n  )\n}\n\nfunction TimelineNode({\n  point,\n  setRef,\n}: {\n  point: TimelinePoint\n  setRef: (node: HTMLDivElement | null) => void\n}) {\n  const alignLeft = point.variant === \"left\"\n\n  return (\n    <div\n      ref={setRef}\n      data-active=\"false\"\n      className=\"absolute z-20 size-0 [transform:translate3d(0,0,2px)] [backface-visibility:hidden]\"\n    >\n      <div\n        data-timeline-default\n        className={[\n          \"absolute bottom-0 flex h-9 items-start gap-1 whitespace-nowrap text-white opacity-100\",\n          alignLeft ? \"right-0 flex-row\" : \"left-0 flex-row\",\n        ].join(\" \")}\n      >\n        {alignLeft ? (\n          <span className=\"[font-family:Roboto] text-[16px] font-semibold leading-[1.2] tracking-[-0.575px]\">\n            {point.label}\n          </span>\n        ) : (\n          <div className=\"-ml-3 flex h-9 flex-col items-center gap-3\">\n            <LifeGridIcon className=\"size-6 shrink-0\" />\n            <div className=\"w-px flex-1\" />\n          </div>\n        )}\n\n        {alignLeft ? (\n          <div className=\"-mr-3 flex h-9 flex-col items-center gap-3\">\n            <LifeGridIcon className=\"size-6 shrink-0\" />\n            <div className=\"w-px flex-1\" />\n          </div>\n        ) : (\n          <span className=\"[font-family:Roboto] text-[16px] font-semibold leading-[1.2] tracking-[-0.575px]\">\n            {point.label}\n          </span>\n        )}\n      </div>\n\n      <div\n        data-timeline-dot\n        className=\"absolute left-0 top-0 z-10 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#fe8000] shadow-[0_0_20px_rgba(255,133,0,0.7)] transition-shadow duration-300\"\n      />\n      <div className=\"absolute left-0 top-0 h-[180px] w-px -translate-x-1/2 bg-gradient-to-b from-white/50 to-black/40\" />\n    </div>\n  )\n}\n\nfunction ExpandedTimelineNode({\n  point,\n  setRef,\n}: {\n  point: TimelinePoint\n  setRef: (node: HTMLDivElement | null) => void\n}) {\n  const alignLeft = point.variant === \"left\"\n\n  return (\n    <div ref={setRef} data-active=\"false\" className=\"absolute size-0\">\n      <div\n        data-timeline-expanded\n        className={[\n          \"absolute bottom-0 flex items-start gap-1 whitespace-nowrap opacity-0\",\n          alignLeft ? \"right-0 flex-row\" : \"left-0 flex-row\",\n        ].join(\" \")}\n      >\n        {alignLeft ? (\n          <div className=\"flex flex-col items-end gap-1 overflow-hidden pb-5 pt-[5px] text-right\">\n            <p className=\"[font-family:Roboto] text-[16px] font-semibold leading-[1.2] tracking-[-0.575px] text-[#fe8000]\">{point.label}</p>\n            <div className=\"hidden flex-col items-end justify-center gap-1 md:flex\">\n              <p className=\"text-[16px] font-normal leading-[1.2] text-white\">{point.subtitle}</p>\n              {point.details.map((detail, detailIndex) => (\n                <p\n                  key={`${detail}-${detailIndex}`}\n                  className=\"flex h-[16.8px] items-center justify-end text-[14px] font-normal leading-[1.2] text-white\"\n                >\n                  <ArrowRight className=\"size-4 shrink-0 text-[#fe8000]\" />\n                  <span>{detail}</span>\n                </p>\n              ))}\n            </div>\n          </div>\n        ) : (\n          <div className=\"-ml-3 flex h-20 flex-col items-center justify-center gap-3 md:h-auto md:self-stretch\">\n            <LifeGridIcon className=\"size-6 shrink-0 text-[#fe8000]\" />\n            <div className=\"w-px flex-1 bg-gradient-to-b from-[#fb5100] to-transparent\" />\n          </div>\n        )}\n\n        {alignLeft ? (\n          <div className=\"-mr-3 flex h-20 flex-col items-center justify-center gap-3 md:h-auto md:self-stretch\">\n            <LifeGridIcon className=\"size-6 shrink-0 text-[#fe8000]\" />\n            <div className=\"w-px flex-1 bg-gradient-to-b from-[#fb5100] to-transparent\" />\n          </div>\n        ) : (\n          <div className=\"flex flex-col items-start gap-1 overflow-hidden pb-5 pt-[5px] text-left\">\n            <p className=\"[font-family:Roboto] text-[16px] font-semibold leading-[1.2] tracking-[-0.575px] text-[#fe8000]\">{point.label}</p>\n            <div className=\"hidden flex-col items-start justify-center gap-1 md:flex\">\n              <p className=\"text-[16px] font-normal leading-[1.2] text-white\">{point.subtitle}</p>\n              {point.details.map((detail, detailIndex) => (\n                <p\n                  key={`${detail}-${detailIndex}`}\n                  className=\"flex h-[16.8px] items-center text-[14px] font-normal leading-[1.2] text-white\"\n                >\n                  <ArrowRight className=\"size-4 shrink-0 text-[#fe8000]\" />\n                  <span>{detail}</span>\n                </p>\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  )\n}\n\nfunction MobilePoint({\n  point,\n  setRef,\n}: {\n  point: TimelinePoint\n  setRef: (node: HTMLDivElement | null) => void\n}) {\n  return (\n    <div\n      ref={setRef}\n      data-active=\"false\"\n      className=\"pointer-events-none absolute inset-x-0 bottom-0 flex flex-col gap-3 px-4 py-6 opacity-0\"\n    >\n      <p className=\"w-fit [font-family:Roboto] text-[16px] font-semibold leading-[1.2] tracking-[-0.575px] text-[#ff8500]\">\n        {point.mobileLabel ?? point.label}\n      </p>\n      <p className=\"w-fit [font-family:Roboto] text-[16px] font-normal leading-[1.2] tracking-[-0.39px] text-white\">\n        {point.mobileSubtitle}\n      </p>\n      <div className=\"flex flex-col\">\n        {point.mobileDetails.map((detail, detailIndex) => (\n          <p\n            key={`${detail}-${detailIndex}`}\n            className=\"w-fit [font-family:Roboto] text-[14px] font-normal leading-[1.2] tracking-[-0.374px] text-white\"\n          >\n            <span>{detail}</span>\n          </p>\n        ))}\n      </div>\n    </div>\n  )\n}\n\nexport function Timeline01({ className = \"\" }: Timeline01Props) {\n  const trackRef = useRef<HTMLDivElement | null>(null)\n  const stageRef = useRef<HTMLDivElement | null>(null)\n  const expandedStageRef = useRef<HTMLDivElement | null>(null)\n  const svgWrapperRef = useRef<HTMLDivElement | null>(null)\n  const pathRef = useRef<SVGPathElement | null>(null)\n  const progressPathRefs = useRef<Array<SVGPathElement | null>>([])\n  const nodeRefs = useRef<Array<HTMLDivElement | null>>([])\n  const expandedNodeRefs = useRef<Array<HTMLDivElement | null>>([])\n  const mobilePanelRef = useRef<HTMLDivElement | null>(null)\n  const mobilePointRefs = useRef<Array<HTMLDivElement | null>>([])\n\n  useLayoutEffect(() => {\n    const track = trackRef.current\n    const stage = stageRef.current\n    const expandedStage = expandedStageRef.current\n    const svgWrapper = svgWrapperRef.current\n    const path = pathRef.current\n    if (!track || !stage || !expandedStage || !svgWrapper || !path) return\n\n    let frame = 0\n    let pathLength = INITIAL_PATH_LENGTH\n    let positions: PointPosition[] = []\n    let layoutWidth = 0\n    let isMobile = false\n    let lastActiveIndex = -1\n\n    const syncActivePoint = (activeIndex: number) => {\n      if (activeIndex === lastActiveIndex) return\n\n      nodeRefs.current.forEach((node, index) => {\n        if (!node) return\n        const isActive = index === activeIndex\n        const defaultLabel = node.querySelector<HTMLElement>(\"[data-timeline-default]\")\n        const dot = node.querySelector<HTMLElement>(\"[data-timeline-dot]\")\n\n        node.dataset.active = String(isActive)\n        node.style.zIndex = isActive ? \"40\" : \"20\"\n        if (defaultLabel) {\n          defaultLabel.style.opacity = isActive ? \"0\" : \"1\"\n        }\n        if (dot) {\n          dot.style.boxShadow = isActive\n            ? \"0 0 42px rgba(255, 133, 0, 0.95)\"\n            : \"0 0 20px rgba(255, 133, 0, 0.7)\"\n        }\n      })\n      expandedNodeRefs.current.forEach((node, index) => {\n        if (!node) return\n        const isActive = index === activeIndex\n        const expanded = node.querySelector<HTMLElement>(\"[data-timeline-expanded]\")\n\n        node.dataset.active = String(isActive)\n        node.style.zIndex = isActive ? \"40\" : \"20\"\n        if (expanded) {\n          expanded.style.opacity = isActive ? \"1\" : \"0\"\n          expanded.style.transform = isActive ? \"translateY(0)\" : \"translateY(-0.5rem)\"\n        }\n      })\n      mobilePointRefs.current.forEach((node, index) => {\n        if (!node) return\n        const isActive = index === activeIndex\n        node.dataset.active = String(isActive)\n        node.style.opacity = isActive ? \"1\" : \"0\"\n      })\n      lastActiveIndex = activeIndex\n    }\n\n    const update = () => {\n      frame = 0\n      const rect = track.getBoundingClientRect()\n      const progress = clamp((window.innerHeight - rect.top) / Math.max(rect.height, 1))\n      const scale = isMobile ? 1 : Math.max(1 - progress, 0.5)\n      const scaleY = isMobile ? 0.9 : 0.4\n      const svgScale = layoutWidth / VIEWBOX_WIDTH\n      const currentPoint = path.getPointAtLength(pathLength * progress)\n      const verticalShift = currentPoint.y * svgScale * scaleY * scale * 0.5\n      const mobilePanelVisible = isMobile && rect.bottom > 0 && rect.top < window.innerHeight\n\n      stage.style.transform = `translate3d(0, -${verticalShift.toFixed(3)}px, 0)`\n      expandedStage.style.transform = `translate3d(0, -${verticalShift.toFixed(3)}px, 0)`\n      svgWrapper.style.transform = `translate3d(0, 0, 1px) scale(${scale.toFixed(5)}) scaleY(${scaleY})`\n      if (mobilePanelRef.current) {\n        mobilePanelRef.current.style.opacity = mobilePanelVisible ? \"1\" : \"0\"\n      }\n\n      const dashOffset = (pathLength * (1 - progress)).toFixed(3)\n      progressPathRefs.current.forEach((progressPath) => {\n        progressPath?.setAttribute(\"stroke-dashoffset\", dashOffset)\n      })\n\n      positions.forEach((position, index) => {\n        const node = nodeRefs.current[index]\n        if (!node) return\n        const left = (position.x * svgScale - layoutWidth / 2) * scale + layoutWidth / 2\n        const top = position.y * svgScale * scaleY * scale\n        node.style.left = `${left.toFixed(3)}px`\n        node.style.top = `${top.toFixed(3)}px`\n\n        const expandedNode = expandedNodeRefs.current[index]\n        if (expandedNode) {\n          expandedNode.style.left = `${left.toFixed(3)}px`\n          expandedNode.style.top = `${top.toFixed(3)}px`\n        }\n      })\n\n      syncActivePoint(getActiveIndex(progress))\n    }\n\n    const requestUpdate = () => {\n      if (frame) return\n      frame = window.requestAnimationFrame(update)\n    }\n\n    const measure = () => {\n      layoutWidth = stage.clientWidth\n      isMobile = layoutWidth < 810\n      pathLength = path.getTotalLength()\n      positions = points.map((point) => path.getPointAtLength(pathLength * point.percentage))\n\n      const dashArray = `${pathLength} ${pathLength}`\n      progressPathRefs.current.forEach((progressPath) => {\n        progressPath?.setAttribute(\"stroke-dasharray\", dashArray)\n      })\n      update()\n    }\n\n    measure()\n    window.addEventListener(\"scroll\", requestUpdate, { passive: true })\n    window.addEventListener(\"resize\", measure)\n\n    return () => {\n      if (frame) window.cancelAnimationFrame(frame)\n      window.removeEventListener(\"scroll\", requestUpdate)\n      window.removeEventListener(\"resize\", measure)\n    }\n  }, [])\n\n  return (\n    <section className={`relative bg-black text-white ${className}`}>\n      <div className=\"pointer-events-none sticky top-0 z-30 flex h-[50vh] items-start\">\n        <div className=\"w-full bg-[linear-gradient(180deg,rgba(0,0,0,0.84)_0%,rgba(0,0,0,0.8)_65.91%,rgba(0,0,0,0.12)_100%)] px-6 pb-px pt-[60px] md:pb-0 md:pt-[120px]\">\n          <h2 className=\"mx-auto w-full max-w-[1050px] text-center text-[32px] font-normal leading-[1.2] text-white md:text-[64px]\">\n            <span className=\"md:hidden\">\n              <span\n                data-timeline-title-mobile-line\n                className=\"mx-auto block w-fit whitespace-nowrap tracking-[-0.635px]\"\n              >\n                Unlock all the potential\n              </span>\n              <span className=\"mx-auto block w-fit whitespace-nowrap\">your life holds</span>\n            </span>\n            <span data-timeline-title-text className=\"hidden tracking-[1.45px] md:inline\">\n              Unlock all the potential your life holds\n            </span>\n          </h2>\n        </div>\n      </div>\n\n      <div\n        ref={trackRef}\n        className=\"relative mt-4 h-[3000px] bg-black md:h-[312vw] md:min-h-[460vh]\"\n      >\n        <div className=\"pointer-events-none absolute inset-y-0 left-4 right-4 z-20 md:inset-0\">\n          <div className=\"sticky top-[200px] h-screen overflow-visible md:h-px\">\n            <div\n              ref={stageRef}\n              className=\"relative w-full will-change-transform [backface-visibility:hidden] [transform-style:preserve-3d]\"\n            >\n              <div\n                ref={svgWrapperRef}\n                className=\"relative w-full origin-top will-change-transform [backface-visibility:hidden] [transform-style:preserve-3d]\"\n                style={{ aspectRatio: `${VIEWBOX_WIDTH} / ${VIEWBOX_HEIGHT}` }}\n              >\n                <svg\n                  viewBox={`0 0 ${VIEWBOX_WIDTH} ${VIEWBOX_HEIGHT}`}\n                  fill=\"none\"\n                  xmlns=\"http://www.w3.org/2000/svg\"\n                  className=\"absolute inset-0 overflow-visible [backface-visibility:hidden]\"\n                  aria-hidden\n                >\n                  <path ref={pathRef} d={PATH_D} stroke=\"white\" strokeWidth=\"5\" className=\"opacity-95\" />\n                  <path\n                    ref={(node) => {\n                      progressPathRefs.current[0] = node\n                    }}\n                    d={PATH_D}\n                    stroke=\"#FE8000\"\n                    strokeWidth=\"5\"\n                    strokeDasharray={`${INITIAL_PATH_LENGTH} ${INITIAL_PATH_LENGTH}`}\n                    strokeDashoffset={INITIAL_PATH_LENGTH}\n                  />\n                  <path\n                    ref={(node) => {\n                      progressPathRefs.current[1] = node\n                    }}\n                    d={PATH_D}\n                    stroke=\"#FE8000\"\n                    strokeWidth=\"24\"\n                    strokeDasharray={`${INITIAL_PATH_LENGTH} ${INITIAL_PATH_LENGTH}`}\n                    strokeDashoffset={INITIAL_PATH_LENGTH}\n                    className=\"blur-[48px]\"\n                  />\n                </svg>\n              </div>\n\n              {points.map((point, index) => (\n                <TimelineNode\n                  key={point.label}\n                  point={point}\n                  setRef={(node) => {\n                    nodeRefs.current[index] = node\n                  }}\n                />\n              ))}\n            </div>\n          </div>\n        </div>\n\n        <div className=\"pointer-events-none absolute inset-y-0 left-4 right-4 z-20 md:inset-0\">\n          <div className=\"sticky top-[200px] h-screen overflow-visible md:h-px\">\n            <div\n              ref={expandedStageRef}\n              className=\"relative w-full will-change-transform [backface-visibility:hidden] [transform-style:preserve-3d]\"\n            >\n              {points.map((point, index) => (\n                <ExpandedTimelineNode\n                  key={point.label}\n                  point={point}\n                  setRef={(node) => {\n                    expandedNodeRefs.current[index] = node\n                  }}\n                />\n              ))}\n            </div>\n          </div>\n        </div>\n\n        <div\n          ref={mobilePanelRef}\n          className=\"pointer-events-none fixed inset-x-0 bottom-0 z-20 h-[320px] overflow-hidden opacity-0 transition-opacity duration-300 md:hidden\"\n        >\n          {points.map((point, index) => (\n            <MobilePoint\n              key={point.label}\n              point={point}\n              setRef={(node) => {\n                mobilePointRefs.current[index] = node\n              }}\n            />\n          ))}\n        </div>\n      </div>\n    </section>\n  )\n}\n\nexport default Timeline01\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "timeline"
  ],
  "type": "registry:block"
}