{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cta-newsletter",
  "title": "Newsletter sign-up",
  "description": "Newsletter card over a glowing dot grid with a labelled email field, subscriber avatars and a privacy note.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "button",
    "input",
    "label",
    "https://velora.colorlib.com/r/avatar-circles.json",
    "https://velora.colorlib.com/r/dotted-glow-background.json"
  ],
  "files": [
    {
      "path": "src/components/blocks/cta-newsletter.tsx",
      "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\nimport { ArrowRightIcon, CheckCircle2Icon, MailIcon } from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { AvatarCircles } from \"@/components/velora/avatar-circles\";\nimport { DottedGlowBackground } from \"@/components/velora/dotted-glow-background\";\n\nconst TITLE = \"The Friday changelog\";\nconst COPY =\n  \"One short email a week: what we shipped, what we learned and the best reads on building calm software.\";\nconst SUBSCRIBERS = [\"Maya Chen\", \"Jonas Berg\", \"Priya Nair\", \"Leo Martins\"];\nconst SUBSCRIBER_COUNT = \"12,400\";\nconst PRIVACY_NOTE = \"We only use your email to send the newsletter. Unsubscribe in one click.\";\nconst PRIVACY_HREF = \"#\";\n\n/**\n * Newsletter sign-up card over a dot grid whose glows drift and brighten\n * the dots they pass. The form only shows a thank-you state — wire\n * `handleSubmit` to your email provider.\n */\nexport function CtaNewsletter() {\n  const id = useId();\n  const [email, setEmail] = useState(\"\");\n  const [subscribed, setSubscribed] = useState<string | null>(null);\n\n  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n    event.preventDefault();\n    setSubscribed(email);\n    setEmail(\"\");\n  }\n\n  return (\n    <section className=\"px-6 py-24 sm:py-32 lg:px-8\">\n      <div className=\"relative isolate mx-auto max-w-5xl overflow-hidden rounded-3xl border bg-card px-6 py-14 shadow-sm sm:px-12 sm:py-16 lg:px-16\">\n        {/* Fades the dots out behind the copy so the text stays easy to read. */}\n        <DottedGlowBackground\n          gap={16}\n          opacity={0.22}\n          glows={3}\n          className=\"-z-10 [mask-image:linear-gradient(to_bottom,transparent_20%,black_70%)] lg:[mask-image:linear-gradient(to_right,transparent_30%,black_75%)]\"\n        />\n        <div\n          aria-hidden\n          className=\"pointer-events-none absolute -top-32 left-1/2 -z-10 h-64 w-xl -translate-x-1/2 rounded-full bg-brand/15 blur-3xl\"\n        />\n\n        <div className=\"grid items-center gap-10 lg:grid-cols-[1.1fr_1fr] lg:gap-16\">\n          <div>\n            <span className=\"grid size-11 place-items-center rounded-xl border bg-background/80 text-primary shadow-sm backdrop-blur\">\n              <MailIcon aria-hidden className=\"size-5\" />\n            </span>\n            <h2 className=\"mt-6 text-3xl font-semibold tracking-tight text-balance sm:text-4xl\">\n              {TITLE}\n            </h2>\n            <p className=\"mt-4 text-base text-pretty text-muted-foreground sm:text-lg\">{COPY}</p>\n            <div className=\"mt-8 flex items-center gap-4\">\n              <AvatarCircles aria-hidden people={SUBSCRIBERS} />\n              <p className=\"text-sm text-muted-foreground\">\n                Join <span className=\"font-medium text-foreground\">{SUBSCRIBER_COUNT}+</span> product\n                builders\n              </p>\n            </div>\n          </div>\n\n          <div className=\"rounded-2xl border bg-background/80 p-5 shadow-lg shadow-brand/5 backdrop-blur sm:p-6\">\n            <form onSubmit={handleSubmit} className=\"space-y-3\">\n              <Label htmlFor={`${id}-email`}>Email address</Label>\n              <div className=\"flex flex-col gap-2 sm:flex-row\">\n                <Input\n                  id={`${id}-email`}\n                  type=\"email\"\n                  name=\"email\"\n                  required\n                  autoComplete=\"email\"\n                  placeholder=\"you@company.com\"\n                  value={email}\n                  onChange={(event) => setEmail(event.target.value)}\n                  aria-describedby={`${id}-privacy`}\n                  className=\"h-11 rounded-full bg-background px-4\"\n                />\n                <Button type=\"submit\" size=\"lg\" className=\"h-11 rounded-full px-5\">\n                  Subscribe\n                  <ArrowRightIcon aria-hidden />\n                </Button>\n              </div>\n            </form>\n\n            {/* Always rendered so screen readers announce the message when it appears. */}\n            <p role=\"status\" className=\"text-sm font-medium text-primary\">\n              {subscribed ? (\n                <span className=\"mt-3 flex items-center gap-2\">\n                  <CheckCircle2Icon aria-hidden className=\"size-4 shrink-0\" />\n                  <span className=\"min-w-0 wrap-break-word\">Thanks! Check {subscribed} to confirm.</span>\n                </span>\n              ) : null}\n            </p>\n\n            <p id={`${id}-privacy`} className=\"mt-4 text-xs leading-relaxed text-muted-foreground\">\n              {PRIVACY_NOTE}{\" \"}\n              <a\n                href={PRIVACY_HREF}\n                className=\"rounded-sm font-medium text-foreground underline underline-offset-4 hover:text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\"\n              >\n                Privacy policy\n              </a>\n            </p>\n          </div>\n        </div>\n      </div>\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/blocks/cta-newsletter.tsx"
    }
  ],
  "categories": [
    "cta-sections"
  ],
  "type": "registry:block"
}