{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "saas-landing-2",
  "title": "SaaS Landing 2",
  "description": "Product-tour SaaS landing page template: hero section with announcement pill, browser-framed gallery, tabbed features, how it works stepper, integrations, comparison, stats, testimonial, pricing, and FAQ.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "accordion",
    "avatar",
    "badge",
    "button",
    "card",
    "dialog",
    "field",
    "input",
    "label",
    "separator",
    "sheet",
    "skeleton",
    "sonner",
    "tabs",
    "textarea",
    "utils"
  ],
  "files": [
    {
      "path": "registry/templates/saas-landing-2/install-page.tsx",
      "content": "import { Toaster } from \"@/components/ui/sonner\"\nimport Comparison from \"@/components/saas-landing-2/comparison\"\nimport Cta from \"@/components/saas-landing-2/cta\"\nimport Faqs from \"@/components/saas-landing-2/faqs\"\nimport Features from \"@/components/saas-landing-2/features\"\nimport Footer from \"@/components/saas-landing-2/footer\"\nimport Gallery from \"@/components/saas-landing-2/gallery\"\nimport Header from \"@/components/saas-landing-2/header\"\nimport Hero from \"@/components/saas-landing-2/hero\"\nimport HowItWorks from \"@/components/saas-landing-2/how-it-works\"\nimport Integrations from \"@/components/saas-landing-2/integrations\"\nimport Pricing from \"@/components/saas-landing-2/pricing\"\nimport Stats from \"@/components/saas-landing-2/stats\"\nimport Testimonials from \"@/components/saas-landing-2/testimonials\"\n\n/**\n * Page wash. A background paints only inside its own box, so the fixed-height\n * band this replaces sliced every pool whose falloff reached past its edge into\n * a straight line mid-page, and left the rest of the scroll flat. `inset-0`\n * removes both problems at once. Each pool also eases through a half-alpha stop\n * on its way to zero: a two-stop fade ramps linearly, which the eye reads as the\n * flat edge of a disc rather than as light.\n *\n * Inline `backgroundImage` rather than `bg-[…]` — Tailwind only sees class\n * names it can read literally, and at this length one string per theme is\n * unreadable anyway. The layers swap on `dark:`.\n */\nconst pool = (size: string, color: string, mid: string, out: string) =>\n  `radial-gradient(${size}, ${color}, ${mid} 38%, ${out} 78%)`\n\nconst wash = (base: string, a: number, b: number) => {\n  const at = (v: number) => `rgba(${base},${v})`\n  return [\n    pool(\"38% 13% at 84% 9%\", at(a), at(a / 2), at(0)),\n    pool(\"42% 13% at 12% 28%\", at(b), at(b / 2), at(0)),\n    pool(\"40% 12% at 70% 47%\", at(a), at(a / 2), at(0)),\n    pool(\"42% 12% at 14% 66%\", at(b), at(b / 2), at(0)),\n    pool(\"40% 13% at 74% 87%\", at(a), at(a / 2), at(0)),\n  ].join(\",\")\n}\n\nconst WASH_LIGHT = wash(\"0,0,0\", 0.04, 0.034)\nconst WASH_DARK = wash(\"255,255,255\", 0.06, 0.051)\n\nexport default function SaasLanding2Template() {\n  return (\n    <div className=\"relative isolate flex min-h-svh w-full flex-col bg-background text-foreground\">\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-x-0 top-0 -z-10 h-[720px] bg-[radial-gradient(65%_60%_at_50%_-8%,rgba(0,0,0,0.06),transparent_72%)] dark:bg-[radial-gradient(65%_60%_at_50%_-8%,rgba(255,255,255,0.13),transparent_72%)]\"\n      />\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-0 -z-10 dark:hidden\"\n        style={{ backgroundImage: WASH_LIGHT }}\n      />\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-0 -z-10 hidden dark:block\"\n        style={{ backgroundImage: WASH_DARK }}\n      />\n      <div\n        aria-hidden=\"true\"\n        className=\"pointer-events-none absolute inset-x-0 bottom-0 -z-10 h-[560px] bg-[radial-gradient(55%_50%_at_50%_100%,rgba(0,0,0,0.05),transparent_70%)] dark:bg-[radial-gradient(55%_50%_at_50%_100%,rgba(255,255,255,0.08),transparent_70%)]\"\n      />\n      <Toaster />\n      <Header />\n      <main className=\"flex w-full flex-col\">\n        <Hero />\n        <Gallery />\n        <Features />\n        <HowItWorks />\n        <Integrations />\n        <Comparison />\n        <Stats />\n        <Testimonials />\n        <Pricing />\n        <Faqs />\n        <Cta />\n      </main>\n      <div className=\"border-t border-border/50\">\n        <Footer />\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:page",
      "target": "app/saas-landing-2/page.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/comparison.tsx",
      "content": "import { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst acmePoints = [\n  \"Onboarding completed in under 10 minutes\",\n  \"Real-time sync across all devices and team members\",\n  \"Granular role-based access control included\",\n  \"99.99 % uptime SLA with status page\",\n  \"Dedicated Slack channel for Pro customers\",\n  \"SOC 2 Type II certified infrastructure\",\n  \"One-click data export in any format\",\n  \"No per-seat fees, unlimited collaborators\",\n]\n\nconst othersPoints = [\n  \"Complex setup requires engineering resources\",\n  \"Sync delays of up to 15 minutes on free tiers\",\n  \"Permissions locked behind enterprise plan\",\n  \"SLA only available on custom contracts\",\n  \"Email-only support with 48 h response time\",\n  \"Compliance docs behind sales call\",\n  \"Data export limited to CSV on lower plans\",\n  \"Per-seat pricing adds up fast at scale\",\n]\n\nfunction CheckRow({ text }: { text: string }) {\n  return (\n    <li className=\"flex items-start gap-3\">\n      <span className=\"mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-md bg-primary\">\n        <IconPlaceholder\n          lucide=\"Check\"\n          tabler=\"IconCheck\"\n          hugeicons=\"Tick02Icon\"\n          phosphor=\"Check\"\n          remixicon=\"RiCheckLine\"\n          className=\"size-3 text-primary-foreground\"\n          aria-hidden\n        />\n      </span>\n      <span className=\"text-sm text-foreground\">{text}</span>\n    </li>\n  )\n}\n\nfunction CrossRow({ text }: { text: string }) {\n  return (\n    <li className=\"flex items-start gap-3\">\n      <span className=\"mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-md bg-muted\">\n        <IconPlaceholder\n          lucide=\"X\"\n          tabler=\"IconX\"\n          hugeicons=\"Cancel01Icon\"\n          phosphor=\"X\"\n          remixicon=\"RiCloseLine\"\n          className=\"size-3 text-muted-foreground\"\n          aria-hidden\n        />\n      </span>\n      <span className=\"text-sm text-muted-foreground\">{text}</span>\n    </li>\n  )\n}\n\nexport default function Comparison() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-4xl\">\n        <div className=\"mb-10 text-center\">\n          <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            Why Acme\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            Built differently, on purpose\n          </h2>\n          <p className=\"mt-4 text-sm text-muted-foreground\">\n            We obsessed over the details others skip. Here is what that means\n            for your team every single day.\n          </p>\n        </div>\n\n        <div className=\"grid gap-4 sm:grid-cols-2\">\n          <Card className=\"border-primary/30 ring-primary/20\">\n            <CardHeader>\n              <div className=\"flex items-center gap-2\">\n                <CardTitle className=\"text-base font-semibold\">Acme</CardTitle>\n                <Badge variant=\"default\">Recommended</Badge>\n              </div>\n              {/* min-h keeps both headers the same height, so the rows below\n                  stay in register across the two columns */}\n              <CardDescription className=\"sm:min-h-10\">\n                Everything your team needs, without the enterprise runaround.\n              </CardDescription>\n            </CardHeader>\n\n            <Separator />\n\n            <CardContent className=\"pt-4\">\n              <ul className=\"flex flex-col gap-3\">\n                {acmePoints.map((point) => (\n                  <CheckRow key={point} text={point} />\n                ))}\n              </ul>\n            </CardContent>\n\n            <CardFooter className=\"border-t\">\n              <Button\n                nativeButton={false}\n                className=\"w-full\"\n                render={<a href=\"#\" />}\n              >\n                Start For Free\n                <IconPlaceholder\n                  lucide=\"ArrowRight\"\n                  tabler=\"IconArrowRight\"\n                  hugeicons=\"ArrowRightIcon\"\n                  phosphor=\"ArrowRight\"\n                  remixicon=\"RiArrowRightLine\"\n                  data-icon=\"inline-end\"\n                />\n              </Button>\n            </CardFooter>\n          </Card>\n\n          <Card className=\"bg-muted/30\">\n            <CardHeader>\n              <CardTitle className=\"text-base font-semibold text-muted-foreground\">\n                The others\n              </CardTitle>\n              <CardDescription className=\"sm:min-h-10\">\n                Common friction points teams encounter with legacy platforms.\n              </CardDescription>\n            </CardHeader>\n\n            <Separator />\n\n            <CardContent className=\"pt-4\">\n              <ul className=\"flex flex-col gap-3\">\n                {othersPoints.map((point) => (\n                  <CrossRow key={point} text={point} />\n                ))}\n              </ul>\n            </CardContent>\n\n            <CardFooter className=\"border-t\">\n              <Button\n                variant=\"secondary\"\n                nativeButton={false}\n                className=\"w-full\"\n                render={<a href=\"#\" />}\n              >\n                See Why Teams Switch\n                <IconPlaceholder\n                  lucide=\"ArrowRight\"\n                  tabler=\"IconArrowRight\"\n                  hugeicons=\"ArrowRightIcon\"\n                  phosphor=\"ArrowRight\"\n                  remixicon=\"RiArrowRightLine\"\n                  data-icon=\"inline-end\"\n                />\n              </Button>\n            </CardFooter>\n          </Card>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/comparison.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/cta.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nexport default function Cta() {\n  const [email, setEmail] = useState(\"\")\n  const [submitted, setSubmitted] = useState(false)\n\n  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n    event.preventDefault()\n    if (!email) return\n    setSubmitted(true)\n  }\n\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-2xl rounded-lg border border-border bg-muted/30 px-6 py-12 text-center sm:px-12 sm:py-16\">\n        <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n          Get Started\n        </span>\n        <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n          Start building with Acme today\n        </h2>\n        <p className=\"mx-auto mt-4 max-w-lg text-base text-pretty text-muted-foreground\">\n          Join thousands of teams shipping faster. Get a 14-day free trial, no\n          credit card required.\n        </p>\n\n        <form\n          onSubmit={handleSubmit}\n          className=\"mx-auto mt-8 flex w-full max-w-md flex-col gap-3 sm:flex-row\"\n        >\n          <div className=\"flex-1 text-left\">\n            <Label htmlFor=\"cta-email\" className=\"sr-only\">\n              Email address\n            </Label>\n            <Input\n              id=\"cta-email\"\n              type=\"email\"\n              required\n              placeholder=\"you@acme.com\"\n              value={email}\n              onChange={(event) => setEmail(event.target.value)}\n              className=\"h-11 w-full\"\n            />\n          </div>\n          <Button type=\"submit\" className=\"h-11 shrink-0\">\n            Start Free Trial\n            <IconPlaceholder\n              lucide=\"ArrowRight\"\n              tabler=\"IconArrowRight\"\n              hugeicons=\"ArrowRightIcon\"\n              phosphor=\"ArrowRight\"\n              remixicon=\"RiArrowRightLine\"\n              data-icon=\"inline-end\"\n              aria-hidden=\"true\"\n            />\n          </Button>\n        </form>\n\n        <p\n          className={cn(\n            \"mt-3 text-sm text-primary transition-opacity\",\n            submitted ? \"opacity-100\" : \"opacity-0\"\n          )}\n          aria-live=\"polite\"\n        >\n          Thanks! Check your inbox to confirm your trial.\n        </p>\n\n        <p className=\"mt-4 flex items-center justify-center gap-1.5 text-xs text-muted-foreground\">\n          <IconPlaceholder\n            lucide=\"ShieldCheck\"\n            tabler=\"IconShieldCheck\"\n            hugeicons=\"Shield01Icon\"\n            phosphor=\"ShieldCheck\"\n            remixicon=\"RiShieldCheckLine\"\n            className=\"size-3.5\"\n            data-icon=\"inline-start\"\n            aria-hidden=\"true\"\n          />\n          We respect your privacy. No spam, unsubscribe anytime.\n        </p>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/cta.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/faqs.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { toast } from \"sonner\"\n\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from \"@/components/ui/accordion\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/components/ui/card\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\"\nimport { Field, FieldGroup, FieldLabel } from \"@/components/ui/field\"\nimport { Input } from \"@/components/ui/input\"\nimport { Textarea } from \"@/components/ui/textarea\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst faqs = [\n  {\n    q: \"How do I install a block from the registry?\",\n    a: \"Copy the install command from any block page and run it with the shadcn CLI. The block, its dependencies, and required primitives are added straight to your project.\",\n  },\n  {\n    q: \"Do the blocks work with my existing theme?\",\n    a: \"Yes. Every block is built on shadcn theme tokens, so it inherits your colors, radius, and typography automatically and renders correctly in both light and dark mode.\",\n  },\n  {\n    q: \"Can I customize a block after installing it?\",\n    a: \"Absolutely. Blocks are copied directly into your codebase as plain, editable source, so you own the code and can change markup, styles, and logic however you like.\",\n  },\n  {\n    q: \"What is the difference between free and Pro blocks?\",\n    a: \"Free blocks are open and installable by anyone. Pro blocks unlock advanced layouts, dashboards, and full-page templates, served through your authenticated Acme account.\",\n  },\n  {\n    q: \"Will updates to a block overwrite my changes?\",\n    a: \"No. Because blocks live in your repository, reinstalling a newer version is opt-in. You decide when to pull updates and how to merge them with your edits.\",\n  },\n  {\n    q: \"Which frameworks are supported?\",\n    a: \"Blocks target React 19 and Next.js with the App Router, styled using Tailwind CSS. Most are framework-agnostic enough to drop into any modern React setup.\",\n  },\n]\n\nexport default function Faqs() {\n  const [open, setOpen] = useState(false)\n\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto grid w-full max-w-5xl gap-12 md:grid-cols-[1.4fr_1fr] md:gap-16\">\n        <div>\n          <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            FAQ\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            Frequently asked questions\n          </h2>\n          <p className=\"mt-4 text-muted-foreground\">\n            Everything you need to know about installing and using Acme blocks.\n          </p>\n\n          <Accordion defaultValue={[faqs[0].q]} className=\"mt-8\">\n            {faqs.map(({ q, a }) => (\n              <AccordionItem key={q} value={q}>\n                <AccordionTrigger className=\"py-4 text-base font-medium\">\n                  {q}\n                </AccordionTrigger>\n                <AccordionContent className=\"pb-4 text-base text-muted-foreground\">\n                  {a}\n                </AccordionContent>\n              </AccordionItem>\n            ))}\n          </Accordion>\n        </div>\n\n        <div className=\"md:pt-16\">\n          <Card className=\"md:sticky md:top-8\">\n            <CardHeader>\n              <span className=\"flex size-10 items-center justify-center rounded-full bg-primary/10 text-primary\">\n                <IconPlaceholder\n                  lucide=\"Headset\"\n                  tabler=\"IconHeadset\"\n                  hugeicons=\"CustomerSupportIcon\"\n                  phosphor=\"Headset\"\n                  remixicon=\"RiCustomerService2Line\"\n                  className=\"size-5\"\n                />\n              </span>\n              <CardTitle className=\"mt-4 text-xl\">\n                Still have questions?\n              </CardTitle>\n              <CardDescription className=\"text-base\">\n                Can&apos;t find the answer you&apos;re looking for? Our support\n                team usually replies within a few hours.\n              </CardDescription>\n            </CardHeader>\n            <CardContent className=\"flex flex-col gap-3\">\n              <Dialog open={open} onOpenChange={setOpen}>\n                <DialogTrigger\n                  render={\n                    <Button className=\"w-full\">\n                      <IconPlaceholder\n                        lucide=\"Mail\"\n                        tabler=\"IconMail\"\n                        hugeicons=\"MailIcon\"\n                        phosphor=\"Envelope\"\n                        remixicon=\"RiMailLine\"\n                        data-icon=\"inline-start\"\n                      />\n                      Contact Support\n                      <IconPlaceholder\n                        lucide=\"ArrowRight\"\n                        tabler=\"IconArrowRight\"\n                        hugeicons=\"ArrowRightIcon\"\n                        phosphor=\"ArrowRight\"\n                        remixicon=\"RiArrowRightLine\"\n                        data-icon=\"inline-end\"\n                      />\n                    </Button>\n                  }\n                />\n                <DialogContent>\n                  <form\n                    onSubmit={(event) => {\n                      event.preventDefault()\n                      setOpen(false)\n                      toast.success(\n                        \"Message sent. Our support team will reply shortly.\"\n                      )\n                    }}\n                  >\n                    <DialogHeader>\n                      <DialogTitle>Contact support</DialogTitle>\n                      <DialogDescription>\n                        Send us a message and we&apos;ll get back to you within\n                        a few hours.\n                      </DialogDescription>\n                    </DialogHeader>\n                    <FieldGroup className=\"my-4\">\n                      <Field>\n                        <FieldLabel htmlFor=\"support-email\">\n                          Work email\n                        </FieldLabel>\n                        <Input\n                          id=\"support-email\"\n                          type=\"email\"\n                          placeholder=\"jane@company.com\"\n                          required\n                        />\n                      </Field>\n                      <Field>\n                        <FieldLabel htmlFor=\"support-message\">\n                          How can we help?\n                        </FieldLabel>\n                        <Textarea\n                          id=\"support-message\"\n                          rows={4}\n                          className=\"resize-none\"\n                          placeholder=\"Describe your question…\"\n                          required\n                        />\n                      </Field>\n                    </FieldGroup>\n                    <DialogFooter showCloseButton>\n                      <Button type=\"submit\">\n                        <IconPlaceholder\n                          lucide=\"Mail\"\n                          tabler=\"IconMail\"\n                          hugeicons=\"MailIcon\"\n                          phosphor=\"Envelope\"\n                          remixicon=\"RiMailLine\"\n                          data-icon=\"inline-start\"\n                        />\n                        Send Message\n                      </Button>\n                    </DialogFooter>\n                  </form>\n                </DialogContent>\n              </Dialog>\n              <Button\n                variant=\"outline\"\n                render={<a href=\"#\" />}\n                nativeButton={false}\n                className=\"w-full\"\n              >\n                Browse Documentation\n              </Button>\n            </CardContent>\n          </Card>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/faqs.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/features.tsx",
      "content": "import { Card } from \"@/components/ui/card\"\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\"\nimport { cn } from \"@/lib/utils\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\n/** Props a call site may pass through to an icon. */\ntype IconProps = { className?: string; size?: number | string }\n\ntype Feature = {\n  icon: React.ComponentType<{ className?: string }>\n  title: string\n  description: string\n}\n\ntype FeatureTab = {\n  value: string\n  label: string\n  features: Feature[]\n}\n\nconst TABS: FeatureTab[] = [\n  {\n    value: \"collaboration\",\n    label: \"Collaboration\",\n    features: [\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Group\"\n            tabler=\"IconUsers\"\n            hugeicons=\"GroupIcon\"\n            phosphor=\"Users\"\n            remixicon=\"RiGroupLine\"\n            {...p}\n          />\n        ),\n        title: \"Shared workspaces\",\n        description:\n          \"Bring every team into one workspace with granular roles and instant invites.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"MessageCircle\"\n            tabler=\"IconMessageCircle\"\n            hugeicons=\"Message01Icon\"\n            phosphor=\"ChatCircle\"\n            remixicon=\"RiChat3Line\"\n            {...p}\n          />\n        ),\n        title: \"Inline comments\",\n        description:\n          \"Discuss changes in context with threaded comments, mentions, and reactions.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"History\"\n            tabler=\"IconHistory\"\n            hugeicons=\"HistoryIcon\"\n            phosphor=\"ClockCounterClockwise\"\n            remixicon=\"RiHistoryLine\"\n            {...p}\n          />\n        ),\n        title: \"Version history\",\n        description:\n          \"Track every edit and restore any previous state with a single click.\",\n      },\n    ],\n  },\n  {\n    value: \"automation\",\n    label: \"Automation\",\n    features: [\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Flashlight\"\n            tabler=\"IconBulb\"\n            hugeicons=\"FlashlightIcon\"\n            phosphor=\"Flashlight\"\n            remixicon=\"RiFlashlightLine\"\n            {...p}\n          />\n        ),\n        title: \"Visual workflows\",\n        description:\n          \"Chain triggers and actions on a drag-and-drop canvas, no code required.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Bot\"\n            tabler=\"IconRobot\"\n            hugeicons=\"RobotIcon\"\n            phosphor=\"Robot\"\n            remixicon=\"RiRobot2Line\"\n            {...p}\n          />\n        ),\n        title: \"Smart agents\",\n        description:\n          \"Let Acme agents triage requests, draft replies, and route work for you.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Timer\"\n            tabler=\"IconClockBolt\"\n            hugeicons=\"TimerIcon\"\n            phosphor=\"Timer\"\n            remixicon=\"RiTimerFlashLine\"\n            {...p}\n          />\n        ),\n        title: \"Scheduled runs\",\n        description:\n          \"Queue recurring jobs down to the minute with built-in retries and alerts.\",\n      },\n    ],\n  },\n  {\n    value: \"security\",\n    label: \"Security\",\n    features: [\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"ShieldCheck\"\n            tabler=\"IconShieldCheck\"\n            hugeicons=\"Shield01Icon\"\n            phosphor=\"ShieldCheck\"\n            remixicon=\"RiShieldCheckLine\"\n            {...p}\n          />\n        ),\n        title: \"SOC 2 Type II\",\n        description:\n          \"Independently audited controls keep your data compliant and protected.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Key\"\n            tabler=\"IconKey\"\n            hugeicons=\"KeyIcon\"\n            phosphor=\"Key\"\n            remixicon=\"RiKeyLine\"\n            {...p}\n          />\n        ),\n        title: \"SSO & SCIM\",\n        description:\n          \"Provision users through SAML, OIDC, and automated directory sync.\",\n      },\n      {\n        icon: (p: IconProps) => (\n          <IconPlaceholder\n            lucide=\"Fingerprint\"\n            tabler=\"IconFingerprint\"\n            hugeicons=\"FingerPrintIcon\"\n            phosphor=\"Fingerprint\"\n            remixicon=\"RiFingerprintLine\"\n            {...p}\n          />\n        ),\n        title: \"Audit logging\",\n        description:\n          \"Every action is timestamped, immutable, and exportable to your SIEM.\",\n      },\n    ],\n  },\n]\n\nexport default function Features() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-5xl\">\n        <div className=\"flex flex-col items-center text-center\">\n          <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            Built For Teams\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            Everything you need to ship faster\n          </h2>\n          <p className=\"mt-4 max-w-xl text-pretty text-muted-foreground\">\n            Acme brings collaboration, automation, and enterprise-grade security\n            together in one connected platform.\n          </p>\n        </div>\n\n        <Tabs\n          defaultValue=\"collaboration\"\n          className=\"mt-10 w-full items-center\"\n        >\n          <TabsList className=\"h-auto flex-wrap gap-1 rounded-lg p-1\">\n            {TABS.map((tab) => (\n              <TabsTrigger\n                key={tab.value}\n                value={tab.value}\n                className=\"rounded-md px-4 py-1.5 text-sm\"\n              >\n                {tab.label}\n              </TabsTrigger>\n            ))}\n          </TabsList>\n\n          {TABS.map((tab) => (\n            <TabsContent key={tab.value} value={tab.value} className=\"mt-8\">\n              <div className=\"grid gap-4 sm:grid-cols-2 md:grid-cols-3\">\n                {tab.features.map((feature) => {\n                  const Icon = feature.icon\n                  return (\n                    <Card\n                      key={feature.title}\n                      className=\"group h-full gap-4 p-6 transition-colors hover:border-primary/40\"\n                    >\n                      <div\n                        className={cn(\n                          \"flex size-11 items-center justify-center rounded-md\",\n                          \"bg-primary/10 text-primary transition-colors\",\n                          \"group-hover:bg-primary group-hover:text-primary-foreground\"\n                        )}\n                      >\n                        <Icon className=\"size-5\" />\n                      </div>\n                      <div className=\"space-y-1.5\">\n                        <h3 className=\"font-heading text-base font-medium\">\n                          {feature.title}\n                        </h3>\n                        <p className=\"text-sm/relaxed text-muted-foreground\">\n                          {feature.description}\n                        </p>\n                      </div>\n                      <div className=\"mt-auto flex items-center gap-2 text-xs font-medium text-muted-foreground\">\n                        <IconPlaceholder\n                          lucide=\"GitBranch\"\n                          tabler=\"IconGitBranch\"\n                          hugeicons=\"GitBranchIcon\"\n                          phosphor=\"GitBranch\"\n                          remixicon=\"RiGitBranchLine\"\n                          className=\"size-3.5\"\n                        />\n                        Included on every plan\n                      </div>\n                    </Card>\n                  )\n                })}\n              </div>\n            </TabsContent>\n          ))}\n        </Tabs>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/features.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/footer.tsx",
      "content": "import { Button } from \"@/components/ui/button\"\nimport { Separator } from \"@/components/ui/separator\"\n\nconst columns = [\n  { title: \"Product\", links: [\"Blocks\", \"Templates\", \"Pricing\", \"Changelog\"] },\n  { title: \"Resources\", links: [\"Docs\", \"Guides\", \"Support\", \"API\"] },\n  { title: \"Company\", links: [\"About\", \"Blog\", \"Careers\", \"Contact\"] },\n]\n\nconst socials = [\n  { label: \"GitHub\", icon: GithubMark },\n  { label: \"X\", icon: XMark },\n  { label: \"Discord\", icon: DiscordMark },\n]\n\nexport default function Footer() {\n  return (\n    <section className=\"flex w-full flex-col\">\n      <footer className=\"w-full px-4 py-10 sm:px-6\">\n        <div className=\"grid gap-8 md:grid-cols-2\">\n          <div className=\"max-w-sm\">\n            <a href=\"#\" className=\"flex items-center gap-2\">\n              <svg\n                viewBox=\"0 0 24 24\"\n                fill=\"currentColor\"\n                aria-hidden=\"true\"\n                className=\"size-6 shrink-0 text-primary\"\n              >\n                <rect\n                  x=\"3\"\n                  y=\"3\"\n                  width=\"8\"\n                  height=\"8\"\n                  transform=\"rotate(-6 7 7)\"\n                />\n                <rect\n                  x=\"3\"\n                  y=\"13\"\n                  width=\"8\"\n                  height=\"8\"\n                  transform=\"rotate(5 7 17)\"\n                />\n                <rect\n                  x=\"13\"\n                  y=\"13\"\n                  width=\"8\"\n                  height=\"8\"\n                  transform=\"rotate(-4 17 17)\"\n                />\n                <rect\n                  x=\"13\"\n                  y=\"3\"\n                  width=\"8\"\n                  height=\"8\"\n                  transform=\"rotate(15 17 7)\"\n                />\n              </svg>\n              <span className=\"text-lg font-bold tracking-tight\">Acme</span>\n            </a>\n            <p className=\"mt-3 text-sm text-muted-foreground\">\n              Everything your team needs to build, ship, and scale.\n            </p>\n          </div>\n          <div className=\"grid grid-cols-2 gap-8 sm:grid-cols-3\">\n            {columns.map((col) => (\n              <div key={col.title}>\n                <h3 className=\"font-heading text-sm font-bold tracking-tight\">\n                  {col.title}\n                </h3>\n                <ul className=\"mt-3 flex flex-col gap-2\">\n                  {col.links.map((link) => (\n                    <li key={link}>\n                      <a\n                        href=\"#\"\n                        className=\"text-sm text-muted-foreground transition-colors hover:text-foreground\"\n                      >\n                        {link}\n                      </a>\n                    </li>\n                  ))}\n                </ul>\n              </div>\n            ))}\n          </div>\n        </div>\n        <Separator className=\"mt-10\" />\n        <div className=\"flex flex-col items-start gap-4 pt-6 sm:flex-row sm:items-center sm:justify-between\">\n          <p className=\"text-sm text-muted-foreground\">\n            &copy; 2026 Acme. All rights reserved.\n          </p>\n          <div className=\"flex items-center gap-2\">\n            {socials.map((social) => (\n              <Button\n                key={social.label}\n                variant=\"outline\"\n                size=\"icon-sm\"\n                aria-label={social.label}\n                render={<a href=\"#\" />}\n                nativeButton={false}\n                className=\"rounded-lg text-muted-foreground hover:text-foreground\"\n              >\n                <social.icon className=\"size-4\" aria-hidden=\"true\" />\n              </Button>\n            ))}\n          </div>\n        </div>\n      </footer>\n    </section>\n  )\n}\n\n// Brand marks are inlined rather than imported from an icon library, which\n// would drag a whole extra package into the consumer's install for a handful\n// of glyphs.\ntype MarkProps = React.ComponentProps<\"svg\"> & { size?: number | string }\n\nfunction DiscordMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M19.3034 5.33716C17.9344 4.71103 16.4805 4.2547 14.9629 4C14.7719 4.32899 14.5596 4.77471 14.411 5.12492C12.7969 4.89144 11.1944 4.89144 9.60255 5.12492C9.45397 4.77471 9.2311 4.32899 9.05068 4C7.52251 4.2547 6.06861 4.71103 4.70915 5.33716C1.96053 9.39111 1.21766 13.3495 1.5891 17.2549C3.41443 18.5815 5.17612 19.388 6.90701 19.9187C7.33151 19.3456 7.71356 18.73 8.04255 18.0827C7.41641 17.8492 6.82211 17.5627 6.24904 17.2231C6.39762 17.117 6.5462 17.0003 6.68416 16.8835C10.1438 18.4648 13.8911 18.4648 17.3082 16.8835C17.4568 17.0003 17.5948 17.117 17.7434 17.2231C17.1703 17.5627 16.576 17.8492 15.9499 18.0827C16.2789 18.73 16.6609 19.3456 17.0854 19.9187C18.8152 19.388 20.5875 18.5815 22.4033 17.2549C22.8596 12.7341 21.6806 8.80747 19.3034 5.33716ZM8.5201 14.8459C7.48007 14.8459 6.63107 13.9014 6.63107 12.7447C6.63107 11.5879 7.45884 10.6434 8.5201 10.6434C9.57071 10.6434 10.4303 11.5879 10.4091 12.7447C10.4091 13.9014 9.57071 14.8459 8.5201 14.8459ZM15.4936 14.8459C14.4535 14.8459 13.6034 13.9014 13.6034 12.7447C13.6034 11.5879 14.4323 10.6434 15.4936 10.6434C16.5442 10.6434 17.4038 11.5879 17.3825 12.7447C17.3825 13.9014 16.5548 14.8459 15.4936 14.8459Z\" />\n    </svg>\n  )\n}\n\nfunction GithubMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M12.001 2C6.47598 2 2.00098 6.475 2.00098 12C2.00098 16.425 4.86348 20.1625 8.83848 21.4875C9.33848 21.575 9.52598 21.275 9.52598 21.0125C9.52598 20.775 9.51348 19.9875 9.51348 19.15C7.00098 19.6125 6.35098 18.5375 6.15098 17.975C6.03848 17.6875 5.55098 16.8 5.12598 16.5625C4.77598 16.375 4.27598 15.9125 5.11348 15.9C5.90098 15.8875 6.46348 16.625 6.65098 16.925C7.55098 18.4375 8.98848 18.0125 9.56348 17.75C9.65098 17.1 9.91348 16.6625 10.201 16.4125C7.97598 16.1625 5.65098 15.3 5.65098 11.475C5.65098 10.3875 6.03848 9.4875 6.67598 8.7875C6.57598 8.5375 6.22598 7.5125 6.77598 6.1375C6.77598 6.1375 7.61348 5.875 9.52598 7.1625C10.326 6.9375 11.176 6.825 12.026 6.825C12.876 6.825 13.726 6.9375 14.526 7.1625C16.4385 5.8625 17.276 6.1375 17.276 6.1375C17.826 7.5125 17.476 8.5375 17.376 8.7875C18.0135 9.4875 18.401 10.375 18.401 11.475C18.401 15.3125 16.0635 16.1625 13.8385 16.4125C14.201 16.725 14.5135 17.325 14.5135 18.2625C14.5135 19.6 14.501 20.675 14.501 21.0125C14.501 21.275 14.6885 21.5875 15.1885 21.4875C19.259 20.1133 21.9999 16.2963 22.001 12C22.001 6.475 17.526 2 12.001 2Z\" />\n    </svg>\n  )\n}\n\nfunction XMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M17.6874 3.0625L12.6907 8.77425L8.37045 3.0625H2.11328L9.58961 12.8387L2.50378 20.9375H5.53795L11.0068 14.6886L15.7863 20.9375H21.8885L14.095 10.6342L20.7198 3.0625H17.6874ZM16.6232 19.1225L5.65436 4.78217H7.45745L18.3034 19.1225H16.6232Z\" />\n    </svg>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/footer.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/gallery.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst screens = [\n  {\n    id: 1,\n    label: \"Acme Dashboard: Overview\",\n    url: \"app.acme.io/dashboard\",\n    version: \"v2.4\",\n    description:\n      \"A unified command center for monitoring pipeline health, active deployments, and real-time system metrics across all environments.\",\n    src: \"https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=1200&q=80\",\n    alt: \"Acme dashboard overview showing pipeline metrics\",\n  },\n  {\n    id: 2,\n    label: \"Analytics\",\n    url: \"app.acme.io/analytics\",\n    description:\n      \"Deep-dive into usage trends, funnel conversion, and retention cohorts.\",\n    src: \"https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&q=75\",\n    alt: \"Analytics charts and metrics\",\n  },\n  {\n    id: 3,\n    label: \"Deployments\",\n    url: \"app.acme.io/deployments\",\n    description:\n      \"Track every release: status, rollback controls, and canary traffic splits.\",\n    src: \"https://images.unsplash.com/photo-1667372393119-3d4c48d07fc9?w=800&q=75\",\n    alt: \"Deployment pipeline and release status\",\n  },\n  {\n    id: 4,\n    label: \"Team Settings\",\n    url: \"app.acme.io/team\",\n    description:\n      \"Manage members, roles, SSO configuration, and access policies.\",\n    src: \"https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=800&q=75\",\n    alt: \"Team settings and member management\",\n  },\n  {\n    id: 5,\n    label: \"Audit Logs\",\n    url: \"app.acme.io/audit\",\n    description:\n      \"Immutable event history with filtering, export, and alert rules.\",\n    src: \"https://images.unsplash.com/photo-1555949963-ff9fe0c870eb?w=800&q=75\",\n    alt: \"Audit log event timeline\",\n  },\n  {\n    id: 6,\n    label: \"API Keys\",\n    url: \"app.acme.io/api-keys\",\n    description:\n      \"Generate, rotate, and scope API credentials with fine-grained permissions.\",\n    src: \"https://images.unsplash.com/photo-1558494949-ef010cbdcc31?w=800&q=75\",\n    alt: \"API key management interface\",\n  },\n]\n\nexport default function Gallery() {\n  const [activeId, setActiveId] = useState(screens[0].id)\n  const active = screens.find((screen) => screen.id === activeId) ?? screens[0]\n  const thumbnails = screens.slice(1)\n\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto flex w-full max-w-5xl flex-col gap-8\">\n        <div className=\"flex flex-col gap-4\">\n          <span className=\"block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            Product Screenshots\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            See Acme in action\n          </h2>\n        </div>\n\n        <div className=\"rounded-xl border border-border bg-card shadow-sm\">\n          <div className=\"flex items-center gap-2.5 rounded-t-xl border-b border-border bg-muted px-4 py-2.5\">\n            <div className=\"flex items-center gap-1.5\">\n              <span className=\"size-2.5 border border-border bg-background\" />\n              <span className=\"size-2.5 border border-border bg-background\" />\n              <span className=\"size-2.5 border border-border bg-background\" />\n            </div>\n            <div className=\"mx-2 flex flex-1 items-center gap-2 rounded-md border border-border bg-background px-3 py-1\">\n              <span className=\"size-1.5 bg-muted-foreground/30\" />\n              <span className=\"flex-1 truncate text-xs text-muted-foreground\">\n                {active.url}\n              </span>\n            </div>\n            <IconPlaceholder\n              lucide=\"ZoomIn\"\n              tabler=\"IconZoomIn\"\n              hugeicons=\"SearchAddIcon\"\n              phosphor=\"MagnifyingGlassPlus\"\n              remixicon=\"RiZoomInLine\"\n              className=\"size-4 shrink-0 text-muted-foreground/40\"\n              aria-hidden=\"true\"\n            />\n          </div>\n\n          <Dialog>\n            <DialogTrigger\n              render={\n                <button\n                  type=\"button\"\n                  aria-label={`Enlarge ${active.label}`}\n                  className=\"group relative block aspect-video w-full cursor-zoom-in overflow-hidden rounded-b-xl bg-muted text-left focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none\"\n                />\n              }\n            >\n              <img\n                key={active.id}\n                src={active.src}\n                alt={active.alt}\n                className=\"size-full object-cover grayscale transition-[transform,filter] duration-300 group-hover:scale-[1.02] group-hover:grayscale-0\"\n              />\n              <span className=\"pointer-events-none absolute right-3 bottom-3 flex items-center gap-1.5 rounded-md bg-foreground/70 px-2 py-1 text-[10px] font-medium tracking-wide text-background opacity-0 backdrop-blur-sm transition-opacity duration-200 group-hover:opacity-100\">\n                <IconPlaceholder\n                  lucide=\"ZoomIn\"\n                  tabler=\"IconZoomIn\"\n                  hugeicons=\"SearchAddIcon\"\n                  phosphor=\"MagnifyingGlassPlus\"\n                  remixicon=\"RiZoomInLine\"\n                  className=\"size-3.5\"\n                  aria-hidden=\"true\"\n                />\n                Enlarge\n              </span>\n            </DialogTrigger>\n\n            <DialogContent showCloseButton className=\"gap-0 p-0 sm:max-w-3xl\">\n              <DialogTitle className=\"sr-only\">{active.label}</DialogTitle>\n              <DialogDescription className=\"sr-only\">\n                {active.description}\n              </DialogDescription>\n              <div className=\"aspect-video w-full overflow-hidden rounded-t-xl bg-muted\">\n                <img\n                  src={active.src}\n                  alt={active.alt}\n                  className=\"size-full object-contain\"\n                />\n              </div>\n              <div className=\"flex items-center justify-between gap-3 border-t border-border px-4 py-3\">\n                <span className=\"text-sm font-semibold tracking-tight text-foreground\">\n                  {active.label}\n                </span>\n                <span className=\"truncate text-xs text-muted-foreground\">\n                  {active.url}\n                </span>\n              </div>\n            </DialogContent>\n          </Dialog>\n        </div>\n\n        <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between sm:gap-6\">\n          <div className=\"flex flex-col gap-1.5\">\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-base font-semibold tracking-tight\">\n                {active.label}\n              </span>\n              {active.version && (\n                <Badge\n                  variant=\"secondary\"\n                  className=\"text-[10px] font-medium tracking-wide\"\n                >\n                  {active.version}\n                </Badge>\n              )}\n            </div>\n            <p className=\"max-w-lg text-sm leading-relaxed text-muted-foreground\">\n              {active.description}\n            </p>\n          </div>\n          <Button\n            render={<a href=\"#\" />}\n            nativeButton={false}\n            variant=\"outline\"\n            className=\"shrink-0 gap-2 text-xs font-medium\"\n          >\n            <IconPlaceholder\n              lucide=\"ExternalLink\"\n              tabler=\"IconExternalLink\"\n              hugeicons=\"ExternalLinkIcon\"\n              phosphor=\"ArrowSquareOut\"\n              remixicon=\"RiExternalLinkLine\"\n              className=\"size-3.5\"\n              aria-hidden=\"true\"\n            />\n            View Live Demo\n          </Button>\n        </div>\n\n        <div className=\"border-t border-border\" />\n\n        <div className=\"flex flex-col gap-3\">\n          <span className=\"text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            More Screens\n          </span>\n          <div className=\"grid grid-cols-3 gap-3 sm:grid-cols-5\">\n            {thumbnails.map((thumb) => {\n              const isActive = thumb.id === activeId\n              return (\n                <button\n                  key={thumb.id}\n                  type=\"button\"\n                  onClick={() => setActiveId(thumb.id)}\n                  className=\"group flex cursor-pointer flex-col gap-1.5 text-left focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none\"\n                >\n                  <div\n                    className={[\n                      \"relative aspect-video w-full overflow-hidden rounded-md border transition-all duration-200\",\n                      isActive\n                        ? \"border-foreground/60 ring-1 ring-foreground/20\"\n                        : \"border-border group-hover:border-foreground/30\",\n                    ].join(\" \")}\n                  >\n                    <img\n                      src={thumb.src}\n                      alt={thumb.alt}\n                      className=\"size-full object-cover grayscale transition-[transform,filter] duration-300 group-hover:scale-[1.04] group-hover:grayscale-0\"\n                    />\n                    {!isActive && (\n                      <div className=\"absolute inset-0 bg-foreground/0 transition-colors duration-200 group-hover:bg-foreground/5\" />\n                    )}\n                  </div>\n                  <span\n                    className={[\n                      \"truncate text-xs font-medium transition-colors\",\n                      isActive\n                        ? \"text-foreground\"\n                        : \"text-muted-foreground group-hover:text-foreground/70\",\n                    ].join(\" \")}\n                  >\n                    {thumb.label}\n                  </span>\n                </button>\n              )\n            })}\n          </div>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/gallery.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/header.tsx",
      "content": "\"use client\"\nimport { Button } from \"@/components/ui/button\"\nimport { Separator } from \"@/components/ui/separator\"\nimport {\n  Sheet,\n  SheetClose,\n  SheetContent,\n  SheetFooter,\n  SheetHeader,\n  SheetTitle,\n  SheetTrigger,\n} from \"@/components/ui/sheet\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst navLinks = [\n  { label: \"Products\", href: \"#\" },\n  { label: \"Solutions\", href: \"#\" },\n  { label: \"Pricing\", href: \"#\" },\n  { label: \"Docs\", href: \"#\" },\n  { label: \"Blog\", href: \"#\" },\n]\n\nexport default function Header() {\n  return (\n    <header className=\"sticky top-0 z-30 flex h-16 w-full items-center border-b border-border bg-background/80 px-6 backdrop-blur\">\n      <a href=\"#\" className=\"flex shrink-0 items-center gap-2.5\">\n        <svg\n          viewBox=\"0 0 24 24\"\n          fill=\"currentColor\"\n          aria-hidden=\"true\"\n          className=\"size-6 shrink-0 text-primary\"\n        >\n          <rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" transform=\"rotate(-6 7 7)\" />\n          <rect x=\"3\" y=\"13\" width=\"8\" height=\"8\" transform=\"rotate(5 7 17)\" />\n          <rect\n            x=\"13\"\n            y=\"13\"\n            width=\"8\"\n            height=\"8\"\n            transform=\"rotate(-4 17 17)\"\n          />\n          <rect x=\"13\" y=\"3\" width=\"8\" height=\"8\" transform=\"rotate(15 17 7)\" />\n        </svg>\n        <span className=\"text-base font-bold tracking-tight\">Acme</span>\n      </a>\n\n      <nav className=\"absolute left-1/2 hidden -translate-x-1/2 items-center gap-1 md:flex\">\n        {navLinks.map((link) => (\n          <Button\n            key={link.label}\n            render={<a href={link.href} />}\n            nativeButton={false}\n            variant=\"ghost\"\n            className=\"text-muted-foreground hover:text-foreground\"\n          >\n            {link.label}\n          </Button>\n        ))}\n      </nav>\n\n      <div className=\"ml-auto flex shrink-0 items-center gap-3\">\n        <Button\n          render={<a href=\"#\" />}\n          nativeButton={false}\n          variant=\"ghost\"\n          className=\"hidden text-muted-foreground hover:text-foreground sm:inline-flex\"\n        >\n          Sign In\n        </Button>\n        <Separator orientation=\"vertical\" className=\"hidden h-5 sm:block\" />\n        <Button\n          render={<a href=\"#\" />}\n          nativeButton={false}\n          className=\"hidden sm:inline-flex\"\n        >\n          Start Free Trial\n          <IconPlaceholder\n            lucide=\"ArrowRight\"\n            tabler=\"IconArrowRight\"\n            hugeicons=\"ArrowRightIcon\"\n            phosphor=\"ArrowRight\"\n            remixicon=\"RiArrowRightLine\"\n            data-icon=\"inline-end\"\n            aria-hidden=\"true\"\n          />\n        </Button>\n\n        <Sheet>\n          <SheetTrigger\n            render={\n              <Button variant=\"outline\" size=\"icon\" className=\"md:hidden\" />\n            }\n            aria-label=\"Open menu\"\n          >\n            <IconPlaceholder\n              lucide=\"Menu\"\n              tabler=\"IconMenu\"\n              hugeicons=\"MenuIcon\"\n              phosphor=\"List\"\n              remixicon=\"RiMenuLine\"\n              aria-hidden=\"true\"\n            />\n          </SheetTrigger>\n          <SheetContent side=\"right\" className=\"w-full sm:max-w-xs\">\n            <SheetHeader>\n              <SheetTitle className=\"flex items-center gap-2.5\">\n                <svg\n                  viewBox=\"0 0 24 24\"\n                  fill=\"currentColor\"\n                  aria-hidden=\"true\"\n                  className=\"size-5 shrink-0 text-primary\"\n                >\n                  <rect\n                    x=\"3\"\n                    y=\"3\"\n                    width=\"8\"\n                    height=\"8\"\n                    transform=\"rotate(-6 7 7)\"\n                  />\n                  <rect\n                    x=\"3\"\n                    y=\"13\"\n                    width=\"8\"\n                    height=\"8\"\n                    transform=\"rotate(5 7 17)\"\n                  />\n                  <rect\n                    x=\"13\"\n                    y=\"13\"\n                    width=\"8\"\n                    height=\"8\"\n                    transform=\"rotate(-4 17 17)\"\n                  />\n                  <rect\n                    x=\"13\"\n                    y=\"3\"\n                    width=\"8\"\n                    height=\"8\"\n                    transform=\"rotate(15 17 7)\"\n                  />\n                </svg>\n                Acme\n              </SheetTitle>\n            </SheetHeader>\n            <nav className=\"flex flex-col px-2\">\n              {navLinks.map((link) => (\n                <SheetClose\n                  key={link.label}\n                  render={<a href={link.href} />}\n                  nativeButton={false}\n                  className=\"rounded-md px-2 py-2.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n                >\n                  {link.label}\n                </SheetClose>\n              ))}\n            </nav>\n            <SheetFooter>\n              <Button\n                render={<a href=\"#\" />}\n                nativeButton={false}\n                variant=\"ghost\"\n                className=\"w-full\"\n              >\n                Sign In\n              </Button>\n              <Button\n                render={<a href=\"#\" />}\n                nativeButton={false}\n                className=\"w-full\"\n              >\n                Start Free Trial\n                <IconPlaceholder\n                  lucide=\"ArrowRight\"\n                  tabler=\"IconArrowRight\"\n                  hugeicons=\"ArrowRightIcon\"\n                  phosphor=\"ArrowRight\"\n                  remixicon=\"RiArrowRightLine\"\n                  data-icon=\"inline-end\"\n                  aria-hidden=\"true\"\n                />\n              </Button>\n            </SheetFooter>\n          </SheetContent>\n        </Sheet>\n      </div>\n    </header>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/header.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/hero.tsx",
      "content": "import { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Button } from \"@/components/ui/button\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst avatars = [\n  { src: \"https://i.pravatar.cc/80?img=45\", name: \"Elena\", initials: \"E\" },\n  { src: \"https://i.pravatar.cc/80?img=13\", name: \"Marcus\", initials: \"M\" },\n  { src: \"https://i.pravatar.cc/80?img=32\", name: \"Priya\", initials: \"P\" },\n  { src: \"https://i.pravatar.cc/80?img=52\", name: \"Tomás\", initials: \"T\" },\n  { src: \"https://i.pravatar.cc/80?img=27\", name: \"Hannah\", initials: \"H\" },\n]\n\nexport default function Hero() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto flex max-w-2xl flex-col items-center text-center\">\n        <a\n          href=\"#\"\n          className=\"group inline-flex items-center gap-2 rounded-4xl border border-border bg-muted/40 py-1 pr-2 pl-2.5 text-xs font-medium text-foreground transition-colors hover:bg-muted\"\n        >\n          <IconPlaceholder\n            lucide=\"Sparkles\"\n            tabler=\"IconSparkles\"\n            hugeicons=\"SparklesIcon\"\n            phosphor=\"Sparkle\"\n            remixicon=\"RiSparkling2Line\"\n            className=\"size-3.5 text-foreground\"\n            aria-hidden=\"true\"\n          />\n          <span>Introducing real-time collaboration</span>\n          <IconPlaceholder\n            lucide=\"ChevronRight\"\n            tabler=\"IconChevronRight\"\n            hugeicons=\"ArrowRight01Icon\"\n            phosphor=\"CaretRight\"\n            remixicon=\"RiArrowRightSLine\"\n            className=\"size-3.5 transition-transform group-hover:translate-x-0.5\"\n            aria-hidden=\"true\"\n          />\n        </a>\n\n        <h1 className=\"mt-6 font-heading text-4xl font-bold tracking-tight text-balance sm:text-5xl\">\n          Ship your product faster than ever\n        </h1>\n        <p className=\"mt-5 max-w-xl text-base text-pretty text-muted-foreground\">\n          The all-in-one platform that helps teams design, build, and launch\n          without the busywork. Free to start, no credit card required.\n        </p>\n\n        <div className=\"mt-8 flex flex-col items-center gap-3 sm:flex-row\">\n          <Button\n            render={<a href=\"#\" />}\n            nativeButton={false}\n            variant=\"outline\"\n            size=\"lg\"\n          >\n            Book a demo\n          </Button>\n          <Button render={<a href=\"#\" />} nativeButton={false} size=\"lg\">\n            Get started free\n            <IconPlaceholder\n              lucide=\"ChevronRight\"\n              tabler=\"IconChevronRight\"\n              hugeicons=\"ArrowRight01Icon\"\n              phosphor=\"CaretRight\"\n              remixicon=\"RiArrowRightSLine\"\n              data-icon=\"inline-end\"\n              aria-hidden=\"true\"\n            />\n          </Button>\n        </div>\n\n        <div className=\"mt-10 flex flex-col items-center gap-3 sm:flex-row sm:gap-4\">\n          <div className=\"flex -space-x-2\">\n            {avatars.map((avatar) => (\n              <Avatar\n                key={avatar.name}\n                className=\"size-8 border-2 border-background\"\n              >\n                <AvatarImage\n                  src={avatar.src}\n                  alt={avatar.name}\n                  className=\"grayscale\"\n                />\n                <AvatarFallback className=\"text-[10px]\">\n                  {avatar.initials}\n                </AvatarFallback>\n              </Avatar>\n            ))}\n          </div>\n          <div className=\"flex flex-col items-center gap-0.5 sm:items-start\">\n            <div className=\"flex items-center gap-0.5\" aria-label=\"5 out of 5\">\n              {Array.from({ length: 5 }).map((_, index) => (\n                <IconPlaceholder\n                  lucide=\"Star\"\n                  tabler=\"IconStar\"\n                  hugeicons=\"StarIcon\"\n                  phosphor=\"Star\"\n                  remixicon=\"RiStarFill\"\n                  key={index}\n                  className=\"size-4 text-foreground\"\n                  aria-hidden=\"true\"\n                />\n              ))}\n            </div>\n            <span className=\"text-xs text-muted-foreground\">\n              Trusted by 2,000+ teams worldwide\n            </span>\n          </div>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/hero.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/how-it-works.tsx",
      "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\n/** Props a call site may pass through to an icon. */\ntype IconProps = { className?: string; size?: number | string }\n\nconst steps = [\n  {\n    icon: (p: IconProps) => (\n      <IconPlaceholder\n        lucide=\"UserPlus\"\n        tabler=\"IconUserPlus\"\n        hugeicons=\"UserAddIcon\"\n        phosphor=\"UserPlus\"\n        remixicon=\"RiUserAddLine\"\n        {...p}\n      />\n    ),\n    title: \"Create your account\",\n    copy: \"Sign up in under two minutes, no card required to get started.\",\n  },\n  {\n    icon: (p: IconProps) => (\n      <IconPlaceholder\n        lucide=\"Palette\"\n        tabler=\"IconPalette\"\n        hugeicons=\"PaintBoardIcon\"\n        phosphor=\"Palette\"\n        remixicon=\"RiPaletteLine\"\n        {...p}\n      />\n    ),\n    title: \"Customize your space\",\n    copy: \"Pick a template and tune Acme to match how your team already works.\",\n  },\n  {\n    icon: (p: IconProps) => (\n      <IconPlaceholder\n        lucide=\"Users\"\n        tabler=\"IconUsersGroup\"\n        hugeicons=\"UserGroupIcon\"\n        phosphor=\"UsersThree\"\n        remixicon=\"RiTeamLine\"\n        {...p}\n      />\n    ),\n    title: \"Invite your team\",\n    copy: \"Send role-based invites in bulk and let colleagues join in one click.\",\n  },\n  {\n    icon: (p: IconProps) => (\n      <IconPlaceholder\n        lucide=\"Rocket\"\n        tabler=\"IconRocket\"\n        hugeicons=\"RocketIcon\"\n        phosphor=\"Rocket\"\n        remixicon=\"RiRocketLine\"\n        {...p}\n      />\n    ),\n    title: \"Ship with confidence\",\n    copy: \"Run automated checks and deploy knowing Acme has your back.\",\n  },\n]\n\nexport default function HowItWorks() {\n  const [active, setActive] = useState(0)\n  // Fill the connector up to the centre of the active circle so the segment\n  // from the left edge is already drawn once the first step is active.\n  const progress = ((active + 0.5) / steps.length) * 100\n\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-4xl\">\n        <div className=\"mb-12 text-center\">\n          <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            How It Works\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            Up and running in four steps\n          </h2>\n          <p className=\"mx-auto mt-4 max-w-xl text-muted-foreground\">\n            Go from sign-up to full team collaboration without a single support\n            ticket.\n          </p>\n        </div>\n\n        <ol\n          className={cn(\"relative flex flex-col gap-8\", \"md:flex-row md:gap-0\")}\n        >\n          <div\n            className=\"absolute top-0 left-[1.25rem] hidden h-full w-px bg-border md:top-5 md:left-0 md:h-px md:w-full\"\n            aria-hidden=\"true\"\n          />\n          <div\n            className=\"absolute top-0 left-[1.25rem] hidden w-px bg-primary transition-all duration-500 md:top-5 md:left-0 md:h-px md:w-auto\"\n            style={{ height: `${progress}%` }}\n            aria-hidden=\"true\"\n          />\n          <div\n            className=\"absolute top-5 left-0 hidden h-px bg-primary transition-all duration-500 md:block\"\n            style={{ width: `${progress}%` }}\n            aria-hidden=\"true\"\n          />\n\n          {steps.map(({ icon: Icon, title, copy }, index) => {\n            const isDone = index <= active\n            const isCurrent = index === active\n            return (\n              <li\n                key={title}\n                className=\"relative flex flex-1 gap-4 md:flex-col md:items-center md:gap-0 md:px-3 md:text-center\"\n              >\n                <button\n                  type=\"button\"\n                  onClick={() => setActive(index)}\n                  aria-current={isCurrent ? \"step\" : undefined}\n                  className={cn(\n                    \"z-10 flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-full border p-0 transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none\",\n                    isDone\n                      ? \"border-primary bg-primary text-primary-foreground\"\n                      : \"border-border bg-background text-muted-foreground hover:bg-muted\",\n                    isCurrent &&\n                      \"ring-2 ring-primary ring-offset-2 ring-offset-background\"\n                  )}\n                >\n                  {isDone ? (\n                    <IconPlaceholder\n                      lucide=\"Check\"\n                      tabler=\"IconCheck\"\n                      hugeicons=\"Tick02Icon\"\n                      phosphor=\"Check\"\n                      remixicon=\"RiCheckLine\"\n                      className=\"size-4\"\n                      aria-hidden=\"true\"\n                    />\n                  ) : (\n                    <Icon className=\"size-4\" aria-hidden=\"true\" />\n                  )}\n                  <span className=\"sr-only\">{title}</span>\n                </button>\n\n                <div className=\"md:mt-4\">\n                  <h3\n                    className={cn(\n                      \"mt-0.5 font-heading text-sm font-semibold transition-colors\",\n                      isCurrent || isDone\n                        ? \"text-foreground\"\n                        : \"text-muted-foreground\"\n                    )}\n                  >\n                    {title}\n                  </h3>\n                  <p className=\"mt-1.5 text-sm text-muted-foreground md:mx-auto md:max-w-[16rem]\">\n                    {copy}\n                  </p>\n                </div>\n              </li>\n            )\n          })}\n        </ol>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/how-it-works.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/integrations.tsx",
      "content": "import { Button } from \"@/components/ui/button\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\n/** Props a call site may pass through to an icon. */\ntype IconProps = { className?: string; size?: number | string }\n\nconst integrations = [\n  { name: \"Slack\", Icon: (p: IconProps) => <SlackMark {...p} /> },\n  { name: \"Figma\", Icon: (p: IconProps) => <FigmaMark {...p} /> },\n  { name: \"Notion\", Icon: (p: IconProps) => <NotionMark {...p} /> },\n  { name: \"Vercel\", Icon: (p: IconProps) => <VercelMark {...p} /> },\n  { name: \"GitHub\", Icon: (p: IconProps) => <GithubMark {...p} /> },\n  { name: \"Google\", Icon: (p: IconProps) => <GoogleMark {...p} /> },\n]\n\nexport default function Integrations() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto grid w-full max-w-5xl grid-cols-1 items-center gap-12 lg:grid-cols-2\">\n        <div className=\"flex flex-col items-start gap-4\">\n          <span className=\"block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n            Integrations\n          </span>\n          <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n            Works with the tools you already use\n          </h2>\n          <p className=\"text-base text-muted-foreground\">\n            Connect Acme to your favorite apps in a couple of clicks. No brittle\n            scripts, no maintenance — just data flowing where you need it.\n          </p>\n          <Button render={<a href=\"#\" />} nativeButton={false}>\n            Browse all integrations\n            <IconPlaceholder\n              lucide=\"ChevronRight\"\n              tabler=\"IconChevronRight\"\n              hugeicons=\"ArrowRight01Icon\"\n              phosphor=\"CaretRight\"\n              remixicon=\"RiArrowRightSLine\"\n              data-icon=\"inline-end\"\n              aria-hidden=\"true\"\n            />\n          </Button>\n        </div>\n\n        <div className=\"grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-3\">\n          {integrations.map(({ name, Icon }) => (\n            <div\n              key={name}\n              className=\"group flex aspect-[4/3] flex-col items-center justify-center gap-2.5 bg-background p-4 text-muted-foreground transition-colors hover:bg-muted/40 hover:text-foreground\"\n            >\n              <Icon className=\"size-8 shrink-0\" aria-hidden=\"true\" />\n              <span className=\"text-xs font-medium\">{name}</span>\n            </div>\n          ))}\n        </div>\n      </div>\n    </section>\n  )\n}\n\n// Brand marks are inlined rather than imported from an icon library: the rest\n// of this file uses IconPlaceholder, which resolves to whichever icon set the\n// consumer already has, and one brand import would drag a whole extra package\n// into their install for a handful of glyphs.\ntype MarkProps = React.ComponentProps<\"svg\"> & { size?: number | string }\n\nfunction FigmaMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M5.33317 5.33333C5.33317 3.49238 6.82556 2 8.6665 2H11.9997H11.9998H15.333C17.174 2 18.6663 3.49238 18.6663 5.33333C18.6663 7.17428 17.174 8.66667 15.333 8.66667H11.9998H11.9997L11.9997 12L11.9997 15.3333V18.6667C11.9997 20.5076 10.5073 22 8.66634 22C6.82539 22 5.33301 20.5076 5.33301 18.6667C5.33301 16.8257 6.82539 15.3333 8.66634 15.3333C6.82539 15.3333 5.33301 13.841 5.33301 12C5.33301 10.1591 6.82539 8.66667 8.66634 8.66667H8.6665C6.82555 8.66667 5.33317 7.17428 5.33317 5.33333ZM11.9997 12C11.9997 13.841 13.4921 15.3333 15.333 15.3333C17.174 15.3333 18.6663 13.841 18.6663 12C18.6663 10.1591 17.174 8.66667 15.333 8.66667C13.4921 8.66667 11.9997 10.1591 11.9997 12Z\" />\n    </svg>\n  )\n}\n\nfunction GithubMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M12.001 2C6.47598 2 2.00098 6.475 2.00098 12C2.00098 16.425 4.86348 20.1625 8.83848 21.4875C9.33848 21.575 9.52598 21.275 9.52598 21.0125C9.52598 20.775 9.51348 19.9875 9.51348 19.15C7.00098 19.6125 6.35098 18.5375 6.15098 17.975C6.03848 17.6875 5.55098 16.8 5.12598 16.5625C4.77598 16.375 4.27598 15.9125 5.11348 15.9C5.90098 15.8875 6.46348 16.625 6.65098 16.925C7.55098 18.4375 8.98848 18.0125 9.56348 17.75C9.65098 17.1 9.91348 16.6625 10.201 16.4125C7.97598 16.1625 5.65098 15.3 5.65098 11.475C5.65098 10.3875 6.03848 9.4875 6.67598 8.7875C6.57598 8.5375 6.22598 7.5125 6.77598 6.1375C6.77598 6.1375 7.61348 5.875 9.52598 7.1625C10.326 6.9375 11.176 6.825 12.026 6.825C12.876 6.825 13.726 6.9375 14.526 7.1625C16.4385 5.8625 17.276 6.1375 17.276 6.1375C17.826 7.5125 17.476 8.5375 17.376 8.7875C18.0135 9.4875 18.401 10.375 18.401 11.475C18.401 15.3125 16.0635 16.1625 13.8385 16.4125C14.201 16.725 14.5135 17.325 14.5135 18.2625C14.5135 19.6 14.501 20.675 14.501 21.0125C14.501 21.275 14.6885 21.5875 15.1885 21.4875C19.259 20.1133 21.9999 16.2963 22.001 12C22.001 6.475 17.526 2 12.001 2Z\" />\n    </svg>\n  )\n}\n\nfunction GoogleMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M3.06364 7.50914C4.70909 4.24092 8.09084 2 12 2C14.6954 2 16.959 2.99095 18.6909 4.60455L15.8227 7.47274C14.7864 6.48185 13.4681 5.97727 12 5.97727C9.39542 5.97727 7.19084 7.73637 6.40455 10.1C6.2045 10.7 6.09086 11.3409 6.09086 12C6.09086 12.6591 6.2045 13.3 6.40455 13.9C7.19084 16.2636 9.39542 18.0227 12 18.0227C13.3454 18.0227 14.4909 17.6682 15.3864 17.0682C16.4454 16.3591 17.15 15.3 17.3818 14.05H12V10.1818H21.4181C21.5364 10.8363 21.6 11.5182 21.6 12.2273C21.6 15.2727 20.5091 17.8363 18.6181 19.5773C16.9636 21.1046 14.7 22 12 22C8.09084 22 4.70909 19.7591 3.06364 16.4909C2.38638 15.1409 2 13.6136 2 12C2 10.3864 2.38638 8.85911 3.06364 7.50914Z\" />\n    </svg>\n  )\n}\n\nfunction NotionMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M6.1039 5.90972C6.68754 6.38386 6.90648 6.34768 8.00238 6.27457L18.3342 5.65418C18.5533 5.65418 18.3711 5.43557 18.2981 5.39924L16.5822 4.15879C16.2534 3.90354 15.8153 3.61122 14.9758 3.68434L4.9715 4.41403C4.60665 4.45021 4.53377 4.63262 4.67909 4.77886L6.1039 5.90972ZM6.72422 8.31752L6.72422 19.1884C6.72422 19.7726 7.01618 19.9912 7.6733 19.955L19.028 19.298C19.6854 19.2619 19.7586 18.86 19.7586 18.3854V7.58753C19.7586 7.1137 19.5764 6.85816 19.1739 6.89464L7.30815 7.58753C6.87027 7.62433 6.72422 7.84337 6.72422 8.31752ZM17.9335 8.90066C18.0063 9.22933 17.9335 9.55767 17.6043 9.5946L17.0571 9.70361V17.7292C16.5822 17.9845 16.1441 18.1304 15.7791 18.1304C15.1947 18.1304 15.0484 17.9479 14.6107 17.401L11.0321 11.783V17.2186L12.1645 17.4741C12.1645 17.4741 12.1645 18.1304 11.2509 18.1304L8.73222 18.2765C8.65905 18.1304 8.73222 17.7659 8.98769 17.6929L9.64494 17.5108V10.324L8.73237 10.2509C8.6592 9.92222 8.84146 9.44837 9.35298 9.41159L12.0549 9.22946L15.7791 14.9205V9.88603L14.8296 9.77704C14.7567 9.37526 15.0484 9.08353 15.4135 9.04735L17.9335 8.90066ZM4.13151 3.4291L14.5376 2.66279C15.8155 2.55318 16.1443 2.6266 16.9475 3.21005L20.2692 5.54473C20.8173 5.9462 21 6.05551 21 6.49316V19.298C21 20.1005 20.7077 20.5751 19.6856 20.6477L7.60101 21.3775C6.83376 21.4141 6.4686 21.3047 6.0668 20.7937L3.6206 17.6199C3.18227 17.0357 3 16.5986 3 16.0873L3 4.70545C3 4.04918 3.29242 3.50177 4.13151 3.4291Z\" />\n    </svg>\n  )\n}\n\nfunction SlackMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M6.52739 14.5136C6.52739 15.5966 5.64264 16.4814 4.55959 16.4814C3.47654 16.4814 2.5918 15.5966 2.5918 14.5136C2.5918 13.4305 3.47654 12.5458 4.55959 12.5458H6.52739V14.5136ZM7.51892 14.5136C7.51892 13.4305 8.40366 12.5458 9.48671 12.5458C10.5698 12.5458 11.4545 13.4305 11.4545 14.5136V19.4407C11.4545 20.5238 10.5698 21.4085 9.48671 21.4085C8.40366 21.4085 7.51892 20.5238 7.51892 19.4407V14.5136ZM9.48671 6.52715C8.40366 6.52715 7.51892 5.6424 7.51892 4.55935C7.51892 3.4763 8.40366 2.59155 9.48671 2.59155C10.5698 2.59155 11.4545 3.4763 11.4545 4.55935V6.52715H9.48671ZM9.48671 7.51867C10.5698 7.51867 11.4545 8.40342 11.4545 9.48647C11.4545 10.5695 10.5698 11.4543 9.48671 11.4543H4.55959C3.47654 11.4543 2.5918 10.5695 2.5918 9.48647C2.5918 8.40342 3.47654 7.51867 4.55959 7.51867H9.48671ZM17.4732 9.48647C17.4732 8.40342 18.3579 7.51867 19.4409 7.51867C20.524 7.51867 21.4087 8.40342 21.4087 9.48647C21.4087 10.5695 20.524 11.4543 19.4409 11.4543H17.4732V9.48647ZM16.4816 9.48647C16.4816 10.5695 15.5969 11.4543 14.5138 11.4543C13.4308 11.4543 12.546 10.5695 12.546 9.48647V4.55935C12.546 3.4763 13.4308 2.59155 14.5138 2.59155C15.5969 2.59155 16.4816 3.4763 16.4816 4.55935V9.48647ZM14.5138 17.4729C15.5969 17.4729 16.4816 18.3577 16.4816 19.4407C16.4816 20.5238 15.5969 21.4085 14.5138 21.4085C13.4308 21.4085 12.546 20.5238 12.546 19.4407V17.4729H14.5138ZM14.5138 16.4814C13.4308 16.4814 12.546 15.5966 12.546 14.5136C12.546 13.4305 13.4308 12.5458 14.5138 12.5458H19.4409C20.524 12.5458 21.4087 13.4305 21.4087 14.5136C21.4087 15.5966 20.524 16.4814 19.4409 16.4814H14.5138Z\" />\n    </svg>\n  )\n}\n\nfunction VercelMark({ size = 24, ...props }: MarkProps) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      width={size}\n      height={size}\n      fill=\"currentColor\"\n      aria-hidden=\"true\"\n      {...props}\n    >\n      <path d=\"M23 21.6479H1L12 2.35205L23 21.6479Z\" />\n    </svg>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/integrations.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/pricing.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst STARTER_FEATURES = [\n  \"1 workspace\",\n  \"Up to 3 members\",\n  \"5 GB storage\",\n  \"Community support\",\n  \"Basic analytics\",\n]\n\nconst PRO_FEATURES = [\n  \"Unlimited workspaces\",\n  \"Up to 50 members\",\n  \"100 GB storage\",\n  \"Priority email support\",\n  \"Advanced analytics\",\n  \"Custom domain\",\n  \"Audit logs\",\n]\n\ntype Billing = \"monthly\" | \"annual\"\n\nexport default function Pricing() {\n  const [billing, setBilling] = React.useState<Billing>(\"monthly\")\n  const proPrice = billing === \"annual\" ? 23 : 29\n\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-3xl\">\n        <div className=\"flex flex-col gap-4 pb-8 sm:flex-row sm:items-end sm:justify-between\">\n          <div className=\"flex flex-col gap-4\">\n            <span className=\"block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n              Pricing\n            </span>\n            <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n              Two plans. No surprises.\n            </h2>\n          </div>\n          <div\n            role=\"group\"\n            aria-label=\"Billing period\"\n            className=\"inline-flex items-center gap-1 self-start rounded-lg border border-border bg-muted/50 p-1 sm:self-auto\"\n          >\n            <button\n              type=\"button\"\n              onClick={() => setBilling(\"monthly\")}\n              aria-pressed={billing === \"monthly\"}\n              className={cn(\n                \"rounded-md px-4 py-1.5 text-sm font-medium transition-colors\",\n                billing === \"monthly\"\n                  ? \"bg-background text-foreground shadow-sm\"\n                  : \"text-muted-foreground hover:text-foreground\"\n              )}\n            >\n              Monthly\n            </button>\n            <button\n              type=\"button\"\n              onClick={() => setBilling(\"annual\")}\n              aria-pressed={billing === \"annual\"}\n              className={cn(\n                \"flex items-center gap-2 rounded-md px-4 py-1.5 text-sm font-medium transition-colors\",\n                billing === \"annual\"\n                  ? \"bg-background text-foreground shadow-sm\"\n                  : \"text-muted-foreground hover:text-foreground\"\n              )}\n            >\n              Annual\n              <Badge className=\"px-1.5 text-[10px] font-semibold\">-20%</Badge>\n            </button>\n          </div>\n        </div>\n\n        <div className=\"flex flex-col overflow-hidden rounded-xl ring-1 ring-border sm:flex-row\">\n          <div className=\"flex flex-1 flex-col gap-6 bg-primary p-8 text-primary-foreground\">\n            <div className=\"flex flex-col gap-3\">\n              <div className=\"flex items-center gap-3\">\n                <span className=\"text-base font-semibold\">Pro</span>\n                <Badge className=\"border-transparent bg-primary-foreground/20 text-primary-foreground\">\n                  Most Popular\n                </Badge>\n              </div>\n              <div className=\"flex items-baseline gap-1\">\n                <span className=\"text-5xl font-bold tracking-tight\">\n                  ${proPrice}\n                </span>\n                <span className=\"text-sm opacity-70\">/Month</span>\n              </div>\n              <p className=\"text-sm opacity-75\">\n                For growing teams that ship daily and need more room to scale.\n              </p>\n            </div>\n\n            <Separator className=\"bg-primary-foreground/20\" />\n\n            <ul className=\"flex flex-1 flex-col gap-3\">\n              {PRO_FEATURES.map((feature) => (\n                <li key={feature} className=\"flex items-center gap-2 text-sm\">\n                  <IconPlaceholder\n                    lucide=\"Check\"\n                    tabler=\"IconCheck\"\n                    hugeicons=\"Tick02Icon\"\n                    phosphor=\"Check\"\n                    remixicon=\"RiCheckLine\"\n                    data-icon=\"inline-start\"\n                    className=\"size-4 shrink-0 opacity-80\"\n                    aria-hidden=\"true\"\n                  />\n                  {feature}\n                </li>\n              ))}\n            </ul>\n\n            <Button\n              nativeButton={false}\n              variant=\"secondary\"\n              size=\"lg\"\n              className=\"w-full\"\n              render={<a href=\"#\" />}\n            >\n              Start Free Trial\n              <IconPlaceholder\n                lucide=\"ArrowRight\"\n                tabler=\"IconArrowRight\"\n                hugeicons=\"ArrowRightIcon\"\n                phosphor=\"ArrowRight\"\n                remixicon=\"RiArrowRightLine\"\n                data-icon=\"inline-end\"\n                aria-hidden=\"true\"\n              />\n            </Button>\n          </div>\n\n          <div className=\"flex flex-1 flex-col gap-6 bg-card p-8\">\n            <div className=\"flex flex-col gap-3\">\n              <span className=\"text-base font-semibold\">Starter</span>\n              <div className=\"flex items-baseline gap-1\">\n                <span className=\"text-5xl font-bold tracking-tight\">$0</span>\n                <span className=\"text-sm text-muted-foreground\">/Month</span>\n              </div>\n              <p className=\"text-sm text-muted-foreground\">\n                For individuals and side projects just getting off the ground.\n              </p>\n            </div>\n\n            <Separator />\n\n            <ul className=\"flex flex-1 flex-col gap-3\">\n              {STARTER_FEATURES.map((feature) => (\n                <li\n                  key={feature}\n                  className=\"flex items-center gap-2 text-sm text-foreground\"\n                >\n                  <IconPlaceholder\n                    lucide=\"Check\"\n                    tabler=\"IconCheck\"\n                    hugeicons=\"Tick02Icon\"\n                    phosphor=\"Check\"\n                    remixicon=\"RiCheckLine\"\n                    data-icon=\"inline-start\"\n                    className=\"size-4 shrink-0 text-muted-foreground\"\n                    aria-hidden=\"true\"\n                  />\n                  {feature}\n                </li>\n              ))}\n            </ul>\n\n            <Button\n              nativeButton={false}\n              variant=\"outline\"\n              size=\"lg\"\n              className=\"w-full\"\n              render={<a href=\"#\" />}\n            >\n              Get Started Free\n            </Button>\n          </div>\n        </div>\n\n        <p className=\"mt-4 text-center text-xs text-muted-foreground\">\n          No credit card required. Upgrade or cancel anytime.\n        </p>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/pricing.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/stats.tsx",
      "content": "const stats = [\n  { value: \"99.99%\", label: \"Uptime across all regions\" },\n  { value: \"12M+\", label: \"Requests handled every day\" },\n  { value: \"180ms\", label: \"Median global response time\" },\n  { value: \"40+\", label: \"Countries with edge presence\" },\n]\n\nexport default function Stats() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-5xl\">\n        <div className=\"rounded-xl bg-primary px-6 py-14 text-primary-foreground sm:px-12\">\n          <div className=\"mx-auto max-w-xl text-center\">\n            <span className=\"mb-4 block text-xs font-semibold tracking-widest text-primary-foreground/70 uppercase\">\n              By The Numbers\n            </span>\n            <h2 className=\"font-heading text-3xl font-bold tracking-tight text-balance sm:text-4xl\">\n              Built for scale from day one\n            </h2>\n            <p className=\"mt-4 text-sm text-primary-foreground/70\">\n              The numbers behind a platform teams rely on in production.\n            </p>\n          </div>\n\n          <dl className=\"mt-12 grid grid-cols-2 gap-y-10 lg:grid-cols-4\">\n            {stats.map(({ value, label }) => (\n              <div\n                key={label}\n                className=\"flex flex-col items-center gap-2 text-center\"\n              >\n                <dt className=\"text-4xl font-bold tracking-tight tabular-nums sm:text-5xl\">\n                  {value}\n                </dt>\n                <dd className=\"max-w-[12rem] text-xs text-primary-foreground/70\">\n                  {label}\n                </dd>\n              </div>\n            ))}\n          </dl>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/stats.tsx"
    },
    {
      "path": "registry/templates/saas-landing-2/components/testimonials.tsx",
      "content": "import { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\nconst testimonial = {\n  quote:\n    \"Acme's platform compressed what used to be a six-week integration cycle down to a single sprint. Our engineers finally have breathing room to work on things that matter, and our customers felt the difference immediately.\",\n  name: \"Isabelle Fontaine\",\n  role: \"Chief Product Officer\",\n  company: \"Meridian Labs\",\n  initials: \"IF\",\n  avatar: \"https://i.pravatar.cc/150?img=45\",\n}\n\nconst metrics = [\n  { value: \"6×\", label: \"faster integrations\" },\n  { value: \"40%\", label: \"less engineer toil\" },\n  { value: \"1 sprint\", label: \"to full deployment\" },\n]\n\nexport default function Testimonials() {\n  return (\n    <section className=\"flex w-full items-center justify-center px-6 py-16 sm:py-24\">\n      <div className=\"mx-auto w-full max-w-2xl\">\n        <span className=\"mb-4 block text-xs font-semibold tracking-widest text-muted-foreground uppercase\">\n          Customer Story\n        </span>\n        <div className=\"relative rounded-xl border border-border bg-card p-10 sm:p-14\">\n          <div\n            className=\"absolute top-10 left-0 h-16 w-[3px] bg-foreground\"\n            aria-hidden=\"true\"\n          />\n\n          <IconPlaceholder\n            lucide=\"Quote\"\n            tabler=\"IconQuotes\"\n            hugeicons=\"QuotesIcon\"\n            phosphor=\"Quotes\"\n            remixicon=\"RiDoubleQuotesR\"\n            className=\"mb-8 size-8 text-muted-foreground\"\n            aria-hidden=\"true\"\n          />\n\n          <blockquote className=\"text-xl leading-[1.65] font-medium tracking-tight text-foreground sm:text-2xl\">\n            &ldquo;{testimonial.quote}&rdquo;\n          </blockquote>\n\n          <Separator className=\"my-10\" />\n\n          <div className=\"flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between\">\n            <div className=\"flex items-center gap-4\">\n              <Avatar className=\"size-14 border border-border\">\n                <AvatarImage\n                  src={testimonial.avatar}\n                  alt={testimonial.name}\n                  className=\"grayscale\"\n                />\n                <AvatarFallback className=\"text-sm font-semibold\">\n                  {testimonial.initials}\n                </AvatarFallback>\n              </Avatar>\n\n              <div className=\"flex flex-col gap-1\">\n                <span className=\"text-sm leading-tight font-semibold text-foreground\">\n                  {testimonial.name}\n                </span>\n                <span className=\"text-xs leading-tight text-muted-foreground\">\n                  {testimonial.role},{\" \"}\n                  <span className=\"font-medium text-foreground\">\n                    {testimonial.company}\n                  </span>\n                </span>\n              </div>\n            </div>\n\n            <div className=\"flex items-center gap-6 sm:gap-8\">\n              {metrics.map((m, i) => (\n                <div\n                  key={i}\n                  className=\"flex flex-col items-center gap-0.5 text-center\"\n                >\n                  <span className=\"text-lg leading-none font-bold tracking-tight text-foreground\">\n                    {m.value}\n                  </span>\n                  <span className=\"text-[11px] leading-tight text-muted-foreground\">\n                    {m.label}\n                  </span>\n                </div>\n              ))}\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/saas-landing-2/testimonials.tsx"
    }
  ],
  "meta": {
    "kind": "template",
    "tier": "free"
  },
  "docs": "Requires a `base-*` style in components.json (the `shadcn init` default). Legacy `new-york`/`radix-*` styles install Radix primitives, which reject the `render` prop this block uses.",
  "categories": [
    "comparison",
    "cta",
    "faqs",
    "features",
    "footer",
    "gallery",
    "header",
    "hero",
    "how-it-works",
    "integrations",
    "pricing",
    "stats",
    "testimonials"
  ],
  "type": "registry:block"
}