{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cta-surface",
  "title": "CTA Surface",
  "author": "Visant Labs <visantsupply@gmail.com>",
  "description": "A superfície de conversão em três proporções (barra, painel, card). O botão herda o contraste do tom em vez de receber cor.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/visant/ui/cta-surface.tsx",
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * CtaSurface — a superfície de conversão no fim da dobra.\n *\n * Cinco referências de site de agência entraram aqui: a barra lime de uma linha,\n * o painel escuro com a marca em cima, o banner com avatares, o card estreito de\n * \"ainda tem dúvida?\" e o card de agendar call. **São a mesma peça.** O que muda\n * é a proporção (`variant`) e quem paga o contraste (`tone`) — não o desenho.\n *\n * Colher os cinco separados teria criado cinco CTAs quase iguais no registry, e\n * a correção de um deixaria os outros quatro para trás.\n *\n * Decisões que custam caro quando se erra:\n *\n * - **O tom decide a cor do botão, não o consumidor.** Numa superfície `brand` o\n *   botão precisa ser o fundo da página; numa `ink`, a cor da marca. Deixar isso\n *   a cargo de quem usa é como o CTA sai invisível em metade dos clientes. Por\n *   isso `CtaAction` lê `data-tone` do ancestral em vez de receber cor.\n * - **`backdrop` é conteúdo, não estilo.** Gradiente e foto das referências são\n *   da marca de cada um; entram por slot, atrás de uma camada de isolamento, e o\n *   componente continua sem cor própria.\n * - **`variant=\"bar\"` empilha no celular.** A barra de uma linha só existe\n *   enquanto cabe; abaixo de `sm` ela vira duas linhas, senão o botão encolhe\n *   até virar alvo de toque impossível.\n */\n\ntype Tone = \"brand\" | \"ink\" | \"surface\";\ntype Variant = \"bar\" | \"panel\" | \"card\";\n\nconst TONE: Record<Tone, string> = {\n  brand: \"bg-[var(--brand)] text-[var(--brand-foreground)]\",\n  ink: \"bg-[var(--foreground)] text-[var(--background)]\",\n  surface: \"bg-[var(--muted)] text-[var(--foreground)]\",\n};\n\nexport interface CtaSurfaceProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n  variant?: Variant;\n  tone?: Tone;\n  title: React.ReactNode;\n  /** Linha de contexto. A barra ignora — de propósito: barra é uma frase só. */\n  lead?: React.ReactNode;\n  /** Botões. Use `CtaAction` para herdar o contraste do tom. */\n  actions?: React.ReactNode;\n  /** Marca, ícone ou pilha de avatares acima do título. */\n  mark?: React.ReactNode;\n  /** A linha miúda embaixo: prazo de resposta, \"sem cartão\", e afins. */\n  footnote?: React.ReactNode;\n  /** Camada decorativa atrás do conteúdo (gradiente, foto, ruído). */\n  backdrop?: React.ReactNode;\n}\n\nexport function CtaSurface({\n  variant = \"panel\",\n  tone = \"brand\",\n  title,\n  lead,\n  actions,\n  mark,\n  footnote,\n  backdrop,\n  className,\n  children,\n  ...props\n}: CtaSurfaceProps) {\n  const bar = variant === \"bar\";\n  const card = variant === \"card\";\n\n  return (\n    <section\n      data-tone={tone}\n      className={cn(\n        \"relative isolate overflow-hidden rounded-[var(--r-surface,1rem)]\",\n        TONE[tone],\n        bar && \"px-6 py-6 sm:px-9\",\n        variant === \"panel\" && \"px-6 py-14 text-center sm:px-12 sm:py-20\",\n        card && \"px-6 py-7\",\n        className,\n      )}\n      {...props}\n    >\n      {backdrop ? (\n        <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-0 -z-10\">\n          {backdrop}\n        </div>\n      ) : null}\n\n      <div\n        className={cn(\n          bar && \"flex flex-col gap-5 sm:flex-row sm:items-center sm:justify-between\",\n          variant === \"panel\" && \"mx-auto flex max-w-[46rem] flex-col items-center gap-5\",\n          card && \"flex flex-col items-start gap-4\",\n        )}\n      >\n        {/* A barra não tem altura para uma marca: ela é uma linha e um botão. */}\n        {mark && !bar ? <div>{mark}</div> : null}\n\n        <div className={cn(bar && \"flex min-w-0 flex-col gap-1.5\", variant === \"panel\" && \"contents\")}>\n          <h2\n            className={cn(\n              \"text-balance [font-family:var(--font-display,inherit)] font-medium tracking-[-0.02em]\",\n              bar && \"text-[clamp(1.0625rem,0.95rem+0.5vw,1.375rem)] leading-[1.3]\",\n              variant === \"panel\" &&\n                \"text-[clamp(1.75rem,1.2rem+2.6vw,3rem)] leading-[1.08]\",\n              card && \"text-[clamp(1.5rem,1.2rem+1.2vw,2rem)] leading-[1.12]\",\n            )}\n          >\n            {title}\n          </h2>\n\n          {/* Barra é uma frase só: um lead ali empurra o botão para fora da linha. */}\n          {lead && !bar ? (\n            <p className=\"max-w-[62ch] text-pretty text-[15px] leading-[1.6] opacity-80\">{lead}</p>\n          ) : null}\n\n          {/* Na barra o rodapé fica junto do texto — some seria perder informação. */}\n          {footnote && bar ? (\n            <p className=\"text-[13px] leading-[1.5] opacity-70\">{footnote}</p>\n          ) : null}\n        </div>\n\n        {children}\n\n        {actions ? (\n          <div\n            className={cn(\n              \"flex flex-wrap items-center gap-3\",\n              bar && \"shrink-0\",\n              variant === \"panel\" && \"justify-center pt-3\",\n              card && \"w-full [&>*]:w-full\",\n            )}\n          >\n            {actions}\n          </div>\n        ) : null}\n\n        {footnote && !bar ? (\n          <p className=\"text-[13px] leading-[1.5] opacity-70\">{footnote}</p>\n        ) : null}\n      </div>\n    </section>\n  );\n}\n\n/**\n * O botão da superfície. `variant=\"solid\"` é o primário — e a cor dele é o\n * NEGATIVO do tom, resolvido por seletor de atributo, não por prop.\n */\nexport interface CtaActionProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n  variant?: \"solid\" | \"outline\";\n  /** Vira `<a>` quando presente. Um CTA que navega precisa ser link. */\n  href?: string;\n}\n\nexport function CtaAction({\n  variant = \"solid\",\n  href,\n  className,\n  children,\n  ...props\n}: CtaActionProps) {\n  const Tag = (href ? \"a\" : \"button\") as \"button\";\n\n  return (\n    <Tag\n      {...(href ? { href } : { type: \"button\" })}\n      className={cn(\n        \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--r-pill,9999px)]\",\n        \"px-6 text-[15px] font-semibold no-underline\",\n        \"min-h-[var(--control-h,2.75rem)] py-2.5\",\n        // Só transform, sombra e cor — nada de `transition-all`, que arrasta\n        // layout junto e engasga.\n        \"transition-[transform,box-shadow,background-color,border-color,color]\",\n        \"[transition-duration:var(--dur-fast,160ms)]\",\n        \"[transition-timing-function:var(--ease-out)]\",\n        \"focus-visible:outline-none focus-visible:[box-shadow:var(--focus)]\",\n        // O toque responde antes da cor: `--dur-press` é mais curto que o hover\n        // de propósito, porque afundar tem de parecer instantâneo.\n        \"active:scale-[0.98] active:[transition-duration:var(--dur-press,120ms)]\",\n        \"motion-reduce:hover:translate-y-0 motion-reduce:active:scale-100\",\n        variant === \"solid\" && [\n          // Em fundo de marca ou tinta, o sólido é o fundo da página.\n          \"bg-[var(--background)] text-[var(--foreground)]\",\n          // Em superfície neutra não há contraste a tomar emprestado: usa a marca.\n          \"[[data-tone=surface]_&]:bg-[var(--brand)] [[data-tone=surface]_&]:text-[var(--brand-foreground)]\",\n          // Levanta em vez de desbotar. `hover:opacity` num botão sólido lava o\n          // texto e faz a peça parecer desabilitada bem na hora do convite.\n          \"hover:-translate-y-px hover:[box-shadow:var(--e-raised)]\",\n        ],\n        variant === \"outline\" && [\n          \"border border-current bg-transparent\",\n          \"hover:bg-current/10 hover:-translate-y-px\",\n        ],\n        className,\n      )}\n      {...props}\n    >\n      {children}\n    </Tag>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "meta": {
    "uso": {
      "quando": "Bloco de conversão no fim de dobra ou página: barra, painel ou card com a ação principal",
      "evite": "Só o botão ganhar presença: magnetic-cta; abertura de seção sem ação, section-intro"
    }
  },
  "categories": [
    "conteudo",
    "cta",
    "conversao",
    "dobra"
  ],
  "type": "registry:ui"
}