{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cta69",
  "title": "Worth Keeping CTA",
  "description": "Full-bleed monochrome closing CTA with a giant scrolling marquee behind a single centered seal button.",
  "dependencies": [
    "clsx",
    "tailwind-merge",
    "lucide-react"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/cta69/cta69.tsx",
      "content": "\"use client\";\n\nimport { Badge7 } from \"@/components/beste/component/badge7\";\nimport { Button12 } from \"@/components/beste/component/button12\";\nimport { cn } from \"@/lib/utils\";\nimport Link from \"next/link\";\n\ninterface Badge {\n  label: string;\n}\n\ninterface ActionButton {\n  label: string;\n  href: string;\n}\n\ninterface Cta69Labels {\n  /** Repeated phrase scrolling across the backdrop */\n  marqueePhrase?: string;\n  /** Short supporting line beneath the heading */\n  note?: string;\n  /** Fine print sitting under the button */\n  footnote?: string;\n}\n\ninterface Cta69Props {\n  badge?: Badge;\n  heading?: string;\n  button?: ActionButton;\n  labels?: Cta69Labels;\n  className?: string;\n}\n\nexport const cta69Demo: Cta69Props = {\n  badge: { label: \"Last word\" },\n  heading: \"Let's make something worth keeping.\",\n  button: {\n    label: \"Start the conversation\",\n    href: \"https://beste.co\",\n  },\n  labels: {\n    marqueePhrase: \"Worth keeping\",\n    note: \"No decks, no detours: one room, your problem, and a studio that ships.\",\n    footnote: \"Booking two new partners for the autumn cycle.\",\n  },\n};\n\n/**\n * How many times the phrase is written into one half of the marquee.\n *\n * The loop is two identical halves slid by exactly half their width, so it only\n * reads as endless while a single half is wider than the screen. A short phrase\n * written once is not: it reaches the right edge and then drags a hole across\n * the section until the animation restarts. Repeating it is what closes that\n * hole, and eight is enough for a one-word phrase at this size.\n */\nconst REPEATS = 8;\n\nexport function Cta69({ badge, heading, button, labels = {}, className }: Cta69Props) {\n  const marqueePhrase = labels.marqueePhrase;\n  // The separator lives inside the phrase rather than in padding between spans:\n  // padding is only applied between elements, so it left one wide gap per copy\n  // instead of the same small gap between every repeat.\n  const marqueeLine = marqueePhrase ? `${marqueePhrase} · `.repeat(REPEATS) : \"\";\n\n  return (\n    <section className={cn(\"relative overflow-hidden bg-background py-16 md:py-24 w-full\", className)}>\n      <style jsx>{`\n        @keyframes cta69-marquee {\n          from {\n            transform: translateX(0);\n          }\n          to {\n            transform: translateX(-50%);\n          }\n        }\n      `}</style>\n\n      {/* Giant scrolling backdrop */}\n      {marqueePhrase && (\n        <div\n          aria-hidden=\"true\"\n          className=\"pointer-events-none absolute inset-0 flex items-center overflow-hidden select-none\"\n        >\n          <div className=\"flex w-max shrink-0 animate-[cta69-marquee_40s_linear_infinite] whitespace-nowrap text-foreground/[0.06]\">\n            {[0, 1].map((copy) => (\n              <span\n                key={copy}\n                className=\"text-[22vw] font-bold leading-none tracking-tighter md:text-[16vw]\"\n              >\n                {marqueeLine}\n              </span>\n            ))}\n          </div>\n        </div>\n      )}\n\n      {/* Centered statement */}\n      <div className=\"relative mx-auto flex max-w-3xl flex-col items-center px-4 text-center md:px-6\">\n        {badge && <Badge7 label={badge.label} />}\n\n        {heading && (\n          <h2 className=\"mt-8 text-balance text-4xl font-bold leading-[1.05] tracking-tight text-foreground md:text-6xl lg:text-7xl\">\n            {heading}\n          </h2>\n        )}\n\n        {labels.note && (\n          <p className=\"mt-6 max-w-xl text-balance text-lg text-muted-foreground md:text-xl\">\n            {labels.note}\n          </p>\n        )}\n\n        {button && (\n          <div className=\"mt-12\">\n            <Button12 asChild label={button.label}>\n              <Link href={button.href} />\n            </Button12>\n          </div>\n        )}\n\n        {labels.footnote && (\n          <p className=\"mt-8 text-base text-muted-foreground\">{labels.footnote}</p>\n        )}\n      </div>\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/beste/block/cta69.tsx"
    },
    {
      "path": "registry-components/badge7/badge7.tsx",
      "content": "import { cn } from \"@/lib/utils\";\n\n/** Allowed wrapper styles, a fixed set, not arbitrary characters. */\ntype Badge7Bracket = \"round\" | \"square\" | \"curly\" | \"angle\" | \"none\";\n\nconst BRACKETS: Record<Badge7Bracket, [open: string, close: string]> = {\n  round: [\"(\", \")\"],\n  square: [\"[\", \"]\"],\n  curly: [\"{\", \"}\"],\n  angle: [\"<\", \">\"],\n  none: [\"\", \"\"],\n};\n\ntype Tone = \"muted\" | \"foreground\" | \"primary\";\n\ninterface Badge7Props {\n  /** Eyebrow label (rendered uppercase) */\n  label: string;\n  /** Which characters wrap the label. Limited to the BRACKETS set. */\n  bracket?: Badge7Bracket;\n  /** Label color */\n  tone?: Tone;\n  /** Render rotated for vertical edge placement (e.g. along a hero side) */\n  vertical?: boolean;\n  /** Additional classes merged onto the root */\n  className?: string;\n}\n\nconst toneStyles: Record<Tone, string> = {\n  muted: \"text-muted-foreground\",\n  foreground: \"text-foreground\",\n  primary: \"text-primary\",\n};\n\nexport const badge7Demo: Badge7Props = {\n  label: \"About\",\n};\n\nexport function Badge7({\n  label,\n  bracket = \"round\",\n  tone = \"muted\",\n  vertical = false,\n  className,\n}: Badge7Props) {\n  const [open, close] = BRACKETS[bracket];\n\n  return (\n    <span\n      className={cn(\n        \"font-mono text-base uppercase tracking-[0.25em]\",\n        toneStyles[tone],\n        vertical ? \"rotate-180 [writing-mode:vertical-rl]\" : \"inline-block\",\n        className\n      )}\n    >\n      {`${open}${label}${close}`}\n    </span>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/beste/component/badge7.tsx"
    },
    {
      "path": "registry-components/button12/button12.tsx",
      "content": "\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { ArrowUpRight, type LucideIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ntype Tone = \"dark\" | \"primary\" | \"outline\";\n\ninterface Button12Props {\n  /** Button label (rendered uppercase) */\n  label: string;\n  /**\n   * Compose the rendered element shadcn-style (radix asChild): your element\n   * (e.g. a router Link) becomes the root and the button content is injected\n   * as its children. Pass the element without children of its own.\n   */\n  asChild?: boolean;\n  /** The element to render when `asChild` is set (e.g. your framework's Link) */\n  children?: React.ReactElement;\n  /**\n   * Fallback link: renders a plain `<a>`. Prefer `asChild` with your\n   * framework's Link component for client-side navigation.\n   */\n  href?: string;\n  /** Seal icon (defaults to ArrowUpRight) */\n  icon?: LucideIcon;\n  /** Surface tone: solid dark (default), solid primary, or bordered outline */\n  tone?: Tone;\n  /** Click handler (used when there is no href and no asChild) */\n  onClick?: React.MouseEventHandler<HTMLButtonElement>;\n  /** Additional classes merged onto the button */\n  className?: string;\n}\n\nconst toneStyles: Record<Tone, { pill: string; seal: string }> = {\n  dark: {\n    pill: \"bg-foreground text-background hover:bg-foreground/90\",\n    seal: \"bg-background text-foreground\",\n  },\n  primary: {\n    pill: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n    seal: \"bg-primary-foreground text-primary\",\n  },\n  outline: {\n    pill: \"border bg-background text-foreground hover:bg-muted\",\n    seal: \"bg-foreground text-background\",\n  },\n};\n\nexport const button12Demo: Button12Props = {\n  label: \"Book an intro call\",\n};\n\nexport function Button12({\n  label,\n  asChild = false,\n  children,\n  href,\n  icon: Icon = ArrowUpRight,\n  tone = \"dark\",\n  onClick,\n  className,\n}: Button12Props) {\n  const styles = toneStyles[tone];\n\n  const classes = cn(\n    \"group/button12 inline-flex w-fit cursor-pointer items-center gap-3 rounded-full py-2 pl-8 pr-2 text-base font-bold uppercase tracking-wider transition-colors\",\n    styles.pill,\n    className\n  );\n\n  const inner = (\n    <>\n      {/* Label slides out the bottom while a copy drops in from the top */}\n      <span className=\"relative block overflow-hidden\">\n        <span className=\"block transition-transform duration-300 ease-out motion-safe:group-hover/button12:translate-y-full\">\n          {label}\n        </span>\n        <span\n          aria-hidden=\"true\"\n          className=\"absolute inset-0 block -translate-y-full transition-transform duration-300 ease-out motion-safe:group-hover/button12:translate-y-0\"\n        >\n          {label}\n        </span>\n      </span>\n\n      {/* Seal: icon exits the top-right corner as a copy enters from bottom-left */}\n      <span\n        className={cn(\n          \"relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-full\",\n          styles.seal\n        )}\n      >\n        <Icon className=\"size-4 transition-transform duration-300 ease-out motion-safe:group-hover/button12:translate-x-[160%] motion-safe:group-hover/button12:-translate-y-[160%]\" />\n        <Icon\n          aria-hidden=\"true\"\n          className=\"absolute size-4 -translate-x-[160%] translate-y-[160%] transition-transform duration-300 ease-out motion-safe:group-hover/button12:translate-x-0 motion-safe:group-hover/button12:translate-y-0\"\n        />\n      </span>\n    </>\n  );\n\n  if (asChild && React.isValidElement(children)) {\n    return (\n      <Slot className={classes}>\n        {React.cloneElement(children, undefined, inner)}\n      </Slot>\n    );\n  }\n\n  if (href) {\n    return (\n      <a href={href} className={classes}>\n        {inner}\n      </a>\n    );\n  }\n\n  return (\n    <button type=\"button\" onClick={onClick} className={classes}>\n      {inner}\n    </button>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/beste/component/button12.tsx"
    }
  ],
  "type": "registry:block"
}