{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "grid-frame-hero",
  "type": "registry:ui",
  "title": "Grid Frame Hero",
  "description": "A bento-style hero with a framed grid layout and dual feature cards with illustrations.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/ruixenui/grid-frame-hero.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport { ArrowUp, Blocks, Palette, Paperclip } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\n/* ── types ───────────────────────────────────────────────────── */\n\ntype Action = { href: string; label: string };\n\nexport interface GridFrameFeature {\n  icon?: React.ReactNode;\n  title: string;\n  highlight: string;\n  description: string;\n  illustration?: React.ReactNode;\n}\n\nexport interface GridFrameHeroProps {\n  title: React.ReactNode;\n  description?: string;\n  primaryAction?: Action;\n  microcopy?: string;\n  features?: [GridFrameFeature, GridFrameFeature];\n  className?: string;\n}\n\n/* ── helpers ─────────────────────────────────────────────────── */\n\nfunction OuterRail() {\n  return (\n    <div aria-hidden className=\"p-px\">\n      <div className=\"h-full w-2 md:w-6 lg:w-full rounded-sm bg-card\" />\n    </div>\n  );\n}\n\n/* ── default illustrations ───────────────────────────────────── */\n\nfunction ChatMessage({\n  avatar,\n  alt,\n  reversed = false,\n  children,\n}: {\n  avatar: string;\n  alt: string;\n  reversed?: boolean;\n  children: React.ReactNode;\n}) {\n  return (\n    <div\n      className={cn(\"flex items-start gap-3\", reversed && \"flex-row-reverse\")}\n    >\n      {/* eslint-disable-next-line @next/next/no-img-element */}\n      <img\n        src={avatar}\n        alt={alt}\n        className=\"size-8 shrink-0 rounded-full object-cover\"\n      />\n      <div className=\"rounded-xl bg-white px-3 py-2 text-sm text-neutral-700 shadow-sm shadow-black/5 ring-1 ring-black/5 dark:bg-neutral-800 dark:text-neutral-200\">\n        {children}\n      </div>\n    </div>\n  );\n}\n\nfunction ChatComposer() {\n  return (\n    <div className=\"w-full shrink-0 pb-1 pt-2 px-2 sm:px-3\">\n      <div className=\"mx-auto w-full rounded-2xl bg-white p-1.5 shadow-sm shadow-black/5 ring-1 ring-black/5 dark:bg-neutral-800\">\n        <div className=\"flex items-center gap-2 px-1.5 py-1\">\n          <span className=\"flex-1 truncate text-sm text-neutral-400 dark:text-neutral-500\">\n            Message your agent...\n          </span>\n        </div>\n        <div className=\"mt-1 flex items-center justify-between border-t border-neutral-100 px-1 pt-1.5 dark:border-neutral-700/60\">\n          <div className=\"flex items-center gap-1 text-neutral-400 dark:text-neutral-500\">\n            <span className=\"flex size-6 items-center justify-center rounded-md hover:bg-neutral-100 dark:hover:bg-neutral-700\">\n              <Paperclip className=\"size-3.5\" />\n            </span>\n            <span className=\"rounded-md px-1.5 py-0.5 text-[11px] font-medium text-neutral-500 ring-1 ring-inset ring-neutral-200 dark:text-neutral-400 dark:ring-neutral-700\">\n              Agents\n            </span>\n          </div>\n          <span className=\"flex size-7 shrink-0 items-center justify-center rounded-full bg-blue-500 text-white shadow-sm shadow-blue-500/30\">\n            <ArrowUp className=\"size-3.5\" strokeWidth={2.5} />\n          </span>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nfunction AgentWorkflowIllustration() {\n  return (\n    <div\n      aria-hidden\n      className=\"mt-auto flex w-full flex-1 flex-col items-stretch justify-between gap-2 overflow-hidden pt-4\"\n    >\n      <div className=\"flex min-h-0 shrink items-center justify-center p-2\">\n        <div className=\"flex flex-col justify-center gap-3\">\n          <ChatMessage avatar=\"/avatar-images/avatar-01.jpg\" alt=\"AI Agent\">\n            Workflow completed. 847 tasks processed.\n          </ChatMessage>\n          <ChatMessage avatar=\"/avatar-images/avatar-02.jpg\" alt=\"You\" reversed>\n            Deploy to production\n          </ChatMessage>\n          <ChatMessage avatar=\"/avatar-images/avatar-03.jpg\" alt=\"AI Agent\">\n            Deployed. All systems operational.\n          </ChatMessage>\n        </div>\n      </div>\n\n      <ChatComposer />\n    </div>\n  );\n}\n\nfunction ClipboardDataIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2\" />\n      <path d=\"M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z\" />\n      <path d=\"M9 17v-4\" />\n      <path d=\"M12 17v-1\" />\n      <path d=\"M15 17v-2\" />\n      <path d=\"M12 17v-1\" />\n    </svg>\n  );\n}\n\nfunction FileDotsIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 24 24\"\n      fill=\"currentColor\"\n      stroke=\"none\"\n      className={className}\n    >\n      <path d=\"M12 2l.117 .007a1 1 0 0 1 .876 .876l.007 .117v4l.005 .15a2 2 0 0 0 1.838 1.844l.157 .006h4l.117 .007a1 1 0 0 1 .876 .876l.007 .117v9a3 3 0 0 1 -2.824 2.995l-.176 .005h-10a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-14a3 3 0 0 1 2.824 -2.995l.176 -.005zm-3 12a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1m3 0a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1m3 0a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1\" />\n      <path d=\"M19 7h-4l-.001 -4.001z\" />\n    </svg>\n  );\n}\n\nfunction FeatherIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 24 24\"\n      fill=\"currentColor\"\n      stroke=\"none\"\n      className={className}\n    >\n      <path d=\"M8 9.585v6.415h6.414l-2.707 2.707a1 1 0 0 1 -.112 .097l-.11 .071l-.114 .054l-.105 .035l-.149 .03l-.117 .006h-4.586l-1.707 1.707a1 1 0 1 1 -1.414 -1.414l1.707 -1.709v-4.584l.003 -.075l.017 -.126l.03 -.111l.044 -.111l.052 -.098l.067 -.096l.08 -.09z\" />\n      <path d=\"M19.414 11l-3 3h-4.914l2.914 -3z\" />\n      <path d=\"M13 4.586v4.998l-3 3v-4.999z\" />\n      <path d=\"M16.482 3a4.515 4.515 0 0 1 4.518 4.514a4.7 4.7 0 0 1 -.239 1.487l-5.761 -.001v-5.76c.469 -.158 .968 -.24 1.482 -.24\" />\n    </svg>\n  );\n}\n\nfunction PointerUpIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M15.984 13.428l-1.206 -1.206l3.113 -2.09a1.2 1.2 0 0 0 -.309 -2.228l-13.582 -3.904l3.904 13.563a1.2 1.2 0 0 0 2.228 .308l2.09 -3.093l1.217 1.217\" />\n      <path d=\"M19 22v-6\" />\n      <path d=\"M22 19l-3 -3l-3 3\" />\n    </svg>\n  );\n}\n\nfunction FilterSearchIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M4 6h16\" />\n      <path d=\"M6 12h8.5\" />\n      <path d=\"M9 18h2\" />\n      <path d=\"M15 18c0 .796 .316 1.559 .879 2.121c.563 .563 1.326 .879 2.121 .879c.796 0 1.559 -.316 2.121 -.879c.563 -.563 .879 -1.326 .879 -2.121c0 -.796 -.316 -1.559 -.879 -2.121c-.563 -.563 -1.326 -.879 -2.121 -.879c-.796 0 -1.559 .316 -2.121 .879c-.563 .563 -.879 1.326 -.879 2.121z\" />\n      <path d=\"M20.2 20.2l1.8 1.8\" />\n    </svg>\n  );\n}\n\nfunction SalesforceLogo() {\n  return (\n    <svg\n      width=\"15\"\n      height=\"10\"\n      viewBox=\"0 0 15 10\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className=\"size-3\"\n    >\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.94348 1.08897C6.40431 0.609254 7.04568 0.312185 7.75424 0.312185C8.69899 0.312185 9.51776 0.837042 9.95864 1.61908C10.35 1.44413 10.7739 1.35381 11.2026 1.35403C12.9031 1.35403 14.2835 2.7449 14.2835 4.46118C14.2835 6.17746 12.9031 7.56834 11.2026 7.56834C10.9947 7.56834 10.7921 7.54745 10.5937 7.50798C10.2079 8.19554 9.47052 8.66266 8.63075 8.66266C8.28885 8.66334 7.95133 8.58578 7.64402 8.43593C7.253 9.35443 6.34238 10 5.28216 10C4.17471 10 3.23522 9.30194 2.87307 8.32046C2.71188 8.35447 2.54759 8.37157 2.38285 8.37147C1.06546 8.37147 0 7.29027 0 5.96238C0 5.07012 0.479719 4.29333 1.19143 3.87345C1.04044 3.52562 0.962718 3.15043 0.963113 2.77125C0.963113 1.23866 2.20702 0 3.73961 0C4.63711 0 5.44015 0.427759 5.94401 1.0917\"\n        fill=\"#00A1E0\"\n      />\n    </svg>\n  );\n}\n\nfunction HubspotLogo() {\n  return (\n    <svg\n      width=\"10\"\n      height=\"10\"\n      viewBox=\"0 0 10 10\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className=\"size-3\"\n    >\n      <path\n        d=\"M7.61726 3.29259V2.10176C7.77462 2.02822 7.90786 1.91149 8.00146 1.76516C8.09507 1.61884 8.14519 1.44894 8.14599 1.27524V1.24789C8.14599 0.741441 7.73543 0.330879 7.22898 0.330879H7.20163C6.95842 0.330879 6.72518 0.427493 6.55321 0.599465C6.38123 0.771438 6.28462 1.00468 6.28462 1.24789V1.27524C6.28542 1.44894 6.33554 1.61884 6.42915 1.76516C6.52275 1.91149 6.65599 2.02822 6.81335 2.10176V3.29259C6.36108 3.36184 5.93513 3.54937 5.57863 3.83618L2.31271 1.29246C2.33601 1.20839 2.34816 1.12195 2.34951 1.03518C2.34991 0.830814 2.28969 0.630919 2.17647 0.46078C2.06325 0.290642 1.90212 0.157904 1.71345 0.0793569C1.52478 0.000809612 1.31705 -0.0200182 1.11654 0.0195079C0.91603 0.059034 0.731748 0.157138 0.587002 0.301412C0.442257 0.445685 0.343551 0.629645 0.303369 0.830024C0.263188 1.0304 0.283338 1.2382 0.361268 1.42712C0.439198 1.61605 0.571407 1.77762 0.741174 1.89139C0.910942 2.00517 1.11064 2.06604 1.31501 2.06631C1.4938 2.06547 1.66924 2.01774 1.82382 1.92788L5.03977 4.43041C4.75087 4.86686 4.60015 5.38022 4.60725 5.90357C4.61436 6.42692 4.77896 6.936 5.07961 7.36444L4.10149 8.3429C4.02242 8.31761 3.94004 8.30419 3.85704 8.30306C3.68929 8.30319 3.52534 8.35305 3.38591 8.44633C3.24648 8.53962 3.13784 8.67214 3.0737 8.82715C3.00957 8.98215 2.99282 9.1527 3.02558 9.31722C3.05834 9.48175 3.13914 9.63287 3.25776 9.75149C3.37638 9.87011 3.5275 9.9509 3.69202 9.98366C3.85655 10.0164 4.02709 9.99968 4.1821 9.93554C4.33711 9.87141 4.46963 9.76276 4.56291 9.62333C4.6562 9.48391 4.70605 9.31996 4.70619 9.1522C4.7051 9.0692 4.69167 8.98681 4.66635 8.90776L5.634 7.93977C5.94955 8.18269 6.31651 8.35017 6.70678 8.42937C7.09705 8.50857 7.50027 8.49739 7.88555 8.39668C8.27083 8.29597 8.62795 8.10841 8.92955 7.84837C9.23114 7.58832 9.46921 7.2627 9.62552 6.89643C9.78183 6.53016 9.85223 6.13298 9.83133 5.7353C9.81042 5.33763 9.69877 4.95001 9.50492 4.60215C9.31108 4.25429 9.04018 3.95542 8.71298 3.72843C8.38579 3.50144 8.01097 3.35235 7.61726 3.29259ZM7.21615 7.20913C7.03731 7.21405 6.85931 7.18308 6.69265 7.11804C6.52599 7.053 6.37405 6.95522 6.24582 6.83047C6.11759 6.70571 6.01567 6.55653 5.94607 6.39172C5.87647 6.22691 5.84062 6.04982 5.84062 5.87092C5.84062 5.69202 5.87647 5.51493 5.94607 5.35013C6.01567 5.18532 6.11759 5.03613 6.24582 4.91138C6.37405 4.78663 6.52599 4.68885 6.69265 4.62381C6.85931 4.55877 7.03731 4.5278 7.21615 4.53272C7.56275 4.54485 7.89113 4.69103 8.1321 4.94046C8.37307 5.1899 8.50784 5.52311 8.50801 5.86993C8.50819 6.21675 8.37375 6.55011 8.13303 6.79978C7.89231 7.04946 7.56409 7.19597 7.2175 7.20845\"\n        fill=\"#FF7A59\"\n      />\n    </svg>\n  );\n}\n\nfunction SheetsLogo() {\n  return (\n    <svg\n      width=\"9\"\n      height=\"10\"\n      viewBox=\"0 0 9 10\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className=\"size-3\"\n    >\n      <path\n        d=\"M5.38222 0.147949H1.62911C1.26484 0.147949 0.966797 0.44599 0.966797 0.810263V9.19957C0.966797 9.56384 1.26484 9.86188 1.62911 9.86188H7.36916C7.73343 9.86188 8.03147 9.56384 8.03147 9.19957V2.7972L6.48608 1.69335L5.38222 0.147949Z\"\n        fill=\"#0F9D58\"\n      />\n      <path\n        d=\"M2.7334 4.89478V8.09596H6.26574V4.89478H2.7334ZM4.2788 7.65441H3.17494V7.10249H4.2788V7.65441ZM4.2788 6.77133H3.17494V6.2194H4.2788V6.77133ZM4.2788 5.88825H3.17494V5.33632H4.2788V5.88825ZM5.82419 7.65441H4.72034V7.10249H5.82419V7.65441ZM5.82419 6.77133H4.72034V6.2194H5.82419V6.77133ZM5.82419 5.88825H4.72034V5.33632H5.82419V5.88825Z\"\n        fill=\"#F1F1F1\"\n      />\n      <path\n        d=\"M5.38281 0.14917V2.13611C5.38281 2.50204 5.6792 2.79842 6.04513 2.79842H8.03207L5.38281 0.14917Z\"\n        fill=\"#87CEAC\"\n      />\n    </svg>\n  );\n}\n\nconst filterCategories: ReadonlyArray<{\n  label: string;\n  active?: boolean;\n  classes: string;\n  icon: React.ReactNode;\n}> = [\n  {\n    label: \"Buttons\",\n    active: true,\n    classes:\n      \"bg-blue-100 border-blue-200 dark:bg-blue-100/10 dark:border-blue-200/10\",\n    icon: <ClipboardDataIcon className=\"size-4 text-blue-500\" />,\n  },\n  {\n    label: \"Cards\",\n    classes:\n      \"bg-green-100 border-green-200 dark:bg-green-100/10 dark:border-green-200/10\",\n    icon: <FileDotsIcon className=\"size-4 text-green-500\" />,\n  },\n  {\n    label: \"Inputs\",\n    classes:\n      \"bg-indigo-100 border-indigo-200 dark:bg-indigo-100/10 dark:border-indigo-200/10\",\n    icon: <FeatherIcon className=\"size-4 text-indigo-500\" />,\n  },\n  {\n    label: \"Hero Sections\",\n    classes:\n      \"bg-neutral-100 border-neutral-200 dark:bg-neutral-100/10 dark:border-neutral-200/10\",\n    icon: <PointerUpIcon className=\"size-4 text-neutral-500\" />,\n  },\n  {\n    label: \"Navbars\",\n    classes:\n      \"bg-purple-100 border-purple-200 dark:bg-purple-100/10 dark:border-purple-200/10\",\n    icon: <FilterSearchIcon className=\"size-4 text-purple-500\" />,\n  },\n];\n\nfunction CategoryPanelIllustration() {\n  return (\n    <div aria-hidden className=\"w-full\">\n      <div className=\"mx-auto mb-4 flex max-w-lg flex-wrap items-center justify-center gap-2\">\n        {filterCategories.map((cat) => (\n          <div\n            key={cat.label}\n            className={cn(\n              \"relative flex items-center justify-center gap-1 rounded-sm border px-2 py-1 text-xs transition duration-200\",\n              cat.active ? \"opacity-100\" : \"opacity-50\",\n              cat.classes,\n            )}\n          >\n            {cat.active && (\n              <div className=\"pointer-events-none absolute inset-0 rounded-[5px] shadow-inner\" />\n            )}\n            {cat.icon}\n            {cat.label}\n          </div>\n        ))}\n      </div>\n\n      <div\n        className=\"mx-auto flex w-full max-w-[20rem] flex-col gap-2 rounded-t-3xl border-x border-t border-neutral-200 bg-neutral-100 p-2 pb-8 dark:border-neutral-700 dark:bg-neutral-800 lg:max-w-sm\"\n        style={{\n          maskImage:\n            \"linear-gradient(to bottom, black calc(100% - 1.5rem), rgba(0,0,0,0.4))\",\n          WebkitMaskImage:\n            \"linear-gradient(to bottom, black calc(100% - 1.5rem), rgba(0,0,0,0.4))\",\n        }}\n      >\n        <div\n          className=\"flex flex-col items-start gap-4 rounded-2xl border border-transparent bg-white p-4 shadow-black/10 ring-1 ring-black/10 dark:bg-neutral-900\"\n          style={{\n            maskImage:\n              \"linear-gradient(to bottom, black calc(100% - 1.5rem), rgba(0,0,0,0.4))\",\n            WebkitMaskImage:\n              \"linear-gradient(to bottom, black calc(100% - 1.5rem), rgba(0,0,0,0.4))\",\n          }}\n        >\n          <div className=\"flex items-center gap-2\">\n            <div className=\"mt-1 flex size-6 shrink-0 items-center justify-center rounded-full border border-blue-200 bg-blue-100 dark:border-blue-200/10 dark:bg-blue-100/10\">\n              <ClipboardDataIcon className=\"size-4 text-blue-500\" />\n            </div>\n            <p className=\"text-lg font-bold text-neutral-800 dark:text-neutral-200\">\n              Buttons\n            </p>\n          </div>\n          <div>\n            <p className=\"text-base text-neutral-600 dark:text-neutral-400\">\n              Primary Variant\n            </p>\n            <p className=\"mb-4 mt-2 rounded-sm border border-dashed border-neutral-200 px-2 py-1 text-sm text-neutral-600 dark:border-neutral-200/10 dark:text-neutral-400\">\n              Install any component with a single shadcn CLI command — themed by\n              your tokens, no configuration required.\n            </p>\n            <div className=\"mt-2 flex flex-row flex-wrap gap-2\">\n              <span className=\"flex w-fit items-center gap-1 rounded-sm border border-neutral-200 px-1 py-0.5 text-sm dark:border-neutral-200/10\">\n                <SalesforceLogo />\n                <span className=\"text-xs text-neutral-500\">Salesforce</span>\n              </span>\n              <span className=\"flex w-fit items-center gap-1 rounded-sm border border-neutral-200 px-1 py-0.5 text-sm dark:border-neutral-200/10\">\n                <HubspotLogo />\n                <span className=\"text-xs text-neutral-500\">Hubspot</span>\n              </span>\n              <span className=\"flex w-fit items-center gap-1 rounded-sm border border-neutral-200 px-1 py-0.5 text-sm dark:border-neutral-200/10\">\n                <SheetsLogo />\n                <span className=\"text-xs text-neutral-500\">Sheets</span>\n              </span>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nconst defaultFeatures: [GridFrameFeature, GridFrameFeature] = [\n  {\n    icon: <Blocks className=\"size-4\" />,\n    title: \"Component Registry\",\n    highlight: \"200+ components ready for production.\",\n    description:\n      \"Add any block to your project with a single shadcn CLI command.\",\n    illustration: <CategoryPanelIllustration />,\n  },\n  {\n    icon: <Palette className=\"size-4\" />,\n    title: \"Themeable by Design\",\n    highlight: \"Adapt instantly to your brand.\",\n    description:\n      \"Semantic tokens drive every component, so light and dark just work.\",\n    illustration: <AgentWorkflowIllustration />,\n  },\n];\n\n/* ── building blocks ─────────────────────────────────────────── */\n\nfunction HeroBlock({\n  title,\n  description,\n  primaryAction,\n  microcopy,\n}: Pick<\n  GridFrameHeroProps,\n  \"title\" | \"description\" | \"primaryAction\" | \"microcopy\"\n>) {\n  return (\n    <div className=\"grid grid-cols-[auto_minmax(0,1fr)_auto] lg:grid-cols-[minmax(0,1fr)_minmax(0,69rem)_minmax(0,1fr)]\">\n      <OuterRail />\n      <div className=\"mx-auto w-full max-w-[69rem]\">\n        <div className=\"rounded-sm bg-card px-4 py-12 text-center sm:px-6 sm:py-14 md:py-20\">\n          <div className=\"mx-auto max-w-3xl\">\n            <h1 className=\"text-balance text-3xl font-semibold tracking-tight text-foreground sm:text-4xl md:text-5xl lg:text-6xl\">\n              {title}\n            </h1>\n            {description && (\n              <p className=\"mt-5 text-balance text-base text-muted-foreground sm:text-lg\">\n                {description}\n              </p>\n            )}\n            {primaryAction && (\n              <div className=\"mt-9\">\n                <Link\n                  href={primaryAction.href}\n                  className={cn(\n                    \"inline-flex h-10 items-center justify-center gap-2 whitespace-nowrap rounded-md px-4 text-sm font-medium\",\n                    \"bg-primary text-primary-foreground shadow-lg shadow-primary/20\",\n                    \"ring-1 ring-foreground/10\",\n                    \"transition-colors hover:bg-primary/90\",\n                    \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n                  )}\n                >\n                  {primaryAction.label}\n                </Link>\n              </div>\n            )}\n            {microcopy && (\n              <span className=\"mt-3 block text-center text-sm text-muted-foreground\">\n                {microcopy}\n              </span>\n            )}\n          </div>\n        </div>\n      </div>\n      <OuterRail />\n    </div>\n  );\n}\n\nfunction FeaturesBlock({\n  features,\n}: {\n  features: [GridFrameFeature, GridFrameFeature];\n}) {\n  return (\n    <div className=\"mx-auto grid w-full max-w-[75rem] grid-cols-[auto_minmax(0,1fr)_auto] border border-border/60 lg:grid-cols-[minmax(0,1fr)_minmax(0,69rem)_minmax(0,1fr)]\">\n      <OuterRail />\n      <div className=\"mx-auto w-full max-w-[69rem]\">\n        <h2 className=\"sr-only\">Features</h2>\n        <div className=\"grid gap-px bg-border/60 sm:grid-cols-2 lg:grid-cols-10\">\n          <div aria-hidden className=\"hidden lg:col-span-1 lg:block\">\n            <div className=\"h-full w-full bg-card\" />\n          </div>\n          {features.map((feature, idx) => (\n            <FeatureCard key={idx} feature={feature} />\n          ))}\n          <div aria-hidden className=\"hidden lg:col-span-1 lg:block\">\n            <div className=\"h-full w-full bg-card\" />\n          </div>\n        </div>\n      </div>\n      <OuterRail />\n    </div>\n  );\n}\n\nfunction FeatureCard({ feature }: { feature: GridFrameFeature }) {\n  return (\n    <div className=\"grid h-full min-w-0 grid-rows-[auto_1fr] gap-px bg-border/60 sm:col-span-1 lg:col-span-4\">\n      <div className=\"space-y-4 bg-card p-5 sm:p-6 md:p-7 lg:p-10\">\n        <h3 className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n          {feature.icon}\n          {feature.title}\n        </h3>\n        <p className=\"text-base font-medium text-muted-foreground lg:text-xl\">\n          <span className=\"text-foreground\">{feature.highlight}</span>{\" \"}\n          {feature.description}\n        </p>\n      </div>\n      <div className=\"flex min-w-0 flex-col items-center justify-center overflow-hidden bg-card p-5 sm:p-6 md:p-7 lg:p-10\">\n        {feature.illustration}\n      </div>\n    </div>\n  );\n}\n\n/* ── component ───────────────────────────────────────────────── */\n\nexport function GridFrameHero({\n  title,\n  description,\n  primaryAction,\n  microcopy,\n  features = defaultFeatures,\n  className,\n}: GridFrameHeroProps) {\n  return (\n    <section className={cn(\"relative overflow-hidden bg-card\", className)}>\n      <HeroBlock\n        title={title}\n        description={description}\n        primaryAction={primaryAction}\n        microcopy={microcopy}\n      />\n      {features && <FeaturesBlock features={features} />}\n    </section>\n  );\n}\n\nexport default GridFrameHero;\n",
      "type": "registry:ui",
      "target": "components/ruixen/grid-frame-hero.tsx"
    }
  ]
}