{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "section-intro",
  "title": "Section Intro",
  "author": "Visant Labs <visantsupply@gmail.com>",
  "description": "Abertura de dobra: rótulo, título grande e linha de contexto, com duas medidas de linha em vez de uma.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/visant/ui/section-intro.tsx",
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * SectionIntro — a abertura de dobra: rótulo, título e uma linha de contexto.\n *\n * Colhida de quatro referências de site de agência que repetiam o mesmo arranjo\n * com medidas diferentes. O que sempre saía torto quando cada dobra escrevia o\n * seu:\n *\n * 1. **Medida de linha.** Título e subtítulo pedem larguras DIFERENTES. Título\n *    grande quebra bonito em ~14 palavras; o subtítulo em ~65 caracteres. Uma\n *    `max-w` só para os dois deixa o subtítulo comprido demais ou o título\n *    apertado. Aqui são duas medidas, expostas em `titleWidth`/`leadWidth`.\n * 2. **`text-balance` no título, `text-pretty` no lead.** O título é curto e\n *    quer linhas de peso igual; o parágrafo só quer evitar órfã.\n * 3. **O rótulo é decoração.** Ele repete a navegação (\"Serviços\", \"Benefícios\")\n *    e não acrescenta nada para quem ouve a página — vai com `aria-hidden`.\n * 4. **Quatro composições por `layout`.** Centrada, dividida (título de um lado,\n *    contexto do outro), com índice de seção e editorial. A mesma anatomia de\n *    rótulo, título e contexto, arrumada dos jeitos que as referências\n *    repetiam. `align` continua valendo para quem já usava.\n *\n * As composições novas quebram pela largura do CONTAINER (`flex-wrap` com base\n * mínima), não da janela: abertura de dobra mora em coluna de qualquer largura,\n * e media query de viewport mente dentro de uma coluna de 700px.\n *\n * O nível do heading é `h2` por padrão porque isto é dobra, não topo de página.\n * Trocar por prop, nunca por CSS.\n */\n\nexport type SectionIntroLayout = \"center\" | \"start\" | \"split\" | \"index\" | \"editorial\";\n\nexport interface SectionIntroProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n  /** O texto do rótulo. Some quando ausente. */\n  eyebrow?: React.ReactNode;\n  title: React.ReactNode;\n  /** A linha de contexto abaixo do título. */\n  lead?: React.ReactNode;\n  /** Atalho antigo para `layout=\"center\"` ou `layout=\"start\"`. */\n  align?: \"center\" | \"start\";\n  /**\n   * A composição da abertura:\n   * · `center`: tudo no eixo, rótulo em pílula. O padrão.\n   * · `start`: a mesma pilha, alinhada à esquerda.\n   * · `split`: título à esquerda, contexto e ações à direita. Empilha sozinho\n   *   quando o container aperta.\n   * · `index`: o número da seção em corpo grande ao lado do título.\n   * · `editorial`: fio de ponta a ponta com o rótulo em cima, título largo e o\n   *   contexto recuado à direita, como abertura de capítulo.\n   * Ausente, vale o `align`.\n   */\n  layout?: SectionIntroLayout;\n  /** O número da seção (\"01\"), usado em `index` e `editorial`. */\n  index?: React.ReactNode;\n  as?: \"h1\" | \"h2\" | \"h3\";\n  /** Medida do título, em ch. Título mais longo pede mais. */\n  titleWidth?: number;\n  /** Medida do parágrafo, em ch. Acima de ~70 o olho perde a volta da linha. */\n  leadWidth?: number;\n  /** Ações abaixo do lead — botão, link, o que o projeto quiser. */\n  actions?: React.ReactNode;\n}\n\nconst TITULO = cn(\n  \"text-balance [font-family:var(--font-display,inherit)] font-medium tracking-[-0.02em]\",\n  \"text-[clamp(2rem,1.35rem+3.1vw,3.75rem)] leading-[1.06] text-[var(--foreground)]\",\n);\nconst LEAD = \"text-pretty text-[15px] leading-[1.65] text-[var(--muted-foreground)]\";\nconst ROTULO = \"text-[13px] font-medium text-[var(--muted-foreground)]\";\n\nexport function SectionIntro({\n  eyebrow,\n  title,\n  lead,\n  align = \"center\",\n  layout,\n  index,\n  as: Heading = \"h2\",\n  titleWidth = 20,\n  leadWidth = 62,\n  actions,\n  className,\n  ...props\n}: SectionIntroProps) {\n  const modo: SectionIntroLayout = layout ?? align;\n\n  const contexto = lead ? (\n    <p className={LEAD} style={{ maxWidth: `${leadWidth}ch` }}>\n      {lead}\n    </p>\n  ) : null;\n  const acoes = actions ? (\n    <div className={cn(\"flex flex-wrap gap-3\", modo === \"center\" && \"justify-center\")}>{actions}</div>\n  ) : null;\n  // Fora da pilha centrada o rótulo é texto, não pílula: ao lado de um fio ou\n  // de um número grande, a pílula vira um terceiro elemento disputando o olho.\n  const rotulo = eyebrow ? (\n    <span aria-hidden=\"true\" className={ROTULO}>\n      {eyebrow}\n    </span>\n  ) : null;\n\n  if (modo === \"split\") {\n    return (\n      <div\n        className={cn(\"flex flex-wrap items-end justify-between gap-x-10 gap-y-6\", className)}\n        {...props}\n      >\n        <div className=\"flex min-w-0 flex-[1_1_19rem] flex-col gap-4\">\n          {rotulo}\n          <Heading className={TITULO} style={{ maxWidth: `${titleWidth}ch` }}>\n            {title}\n          </Heading>\n        </div>\n        {contexto || acoes ? (\n          <div className=\"flex min-w-0 flex-[0_1_19rem] flex-col gap-5\">\n            {contexto}\n            {acoes}\n          </div>\n        ) : null}\n      </div>\n    );\n  }\n\n  if (modo === \"index\") {\n    return (\n      <div className={cn(\"flex flex-wrap items-start gap-x-10 gap-y-4\", className)} {...props}>\n        {index != null ? (\n          <span\n            aria-hidden=\"true\"\n            className={cn(\n              \"shrink-0 [font-family:var(--font-display,inherit)] font-medium tabular-nums leading-[0.9]\",\n              \"text-[clamp(3rem,2.2rem+3.6vw,5.5rem)] tracking-[-0.04em] text-[var(--muted-foreground)]\",\n            )}\n          >\n            {index}\n          </span>\n        ) : null}\n        <div className=\"flex min-w-0 flex-[1_1_20rem] flex-col gap-4\">\n          {rotulo}\n          <Heading className={TITULO} style={{ maxWidth: `${titleWidth}ch` }}>\n            {title}\n          </Heading>\n          {contexto}\n          {acoes}\n        </div>\n      </div>\n    );\n  }\n\n  if (modo === \"editorial\") {\n    return (\n      <div className={cn(\"flex flex-col gap-6\", className)} {...props}>\n        {/* O fio é a moldura inteira da abertura: uma linha, sem caixa. */}\n        <div className=\"flex items-baseline justify-between gap-4 border-t border-[var(--border)] pt-3\">\n          {rotulo ?? <span />}\n          {index != null ? (\n            <span aria-hidden=\"true\" className={cn(ROTULO, \"tabular-nums\")}>\n              {index}\n            </span>\n          ) : null}\n        </div>\n        <Heading className={TITULO} style={{ maxWidth: `${Math.max(titleWidth, 24)}ch` }}>\n          {title}\n        </Heading>\n        {contexto || acoes ? (\n          <div\n            className=\"flex flex-col gap-5 self-end\"\n            style={{ maxWidth: `min(100%, ${Math.min(leadWidth, 46)}ch)` }}\n          >\n            {contexto}\n            {acoes}\n          </div>\n        ) : null}\n      </div>\n    );\n  }\n\n  const centered = modo === \"center\";\n\n  return (\n    <div\n      className={cn(\n        \"flex flex-col gap-5\",\n        centered ? \"items-center text-center\" : \"items-start text-left\",\n        className,\n      )}\n      {...props}\n    >\n      {eyebrow ? (\n        <span\n          aria-hidden=\"true\"\n          className={cn(\n            \"inline-flex items-center rounded-[var(--r-pill,9999px)] border border-[var(--border)]\",\n            \"px-3.5 py-1.5 text-[13px] font-medium text-[var(--muted-foreground)]\",\n          )}\n        >\n          {eyebrow}\n        </span>\n      ) : null}\n\n      <Heading className={TITULO} style={{ maxWidth: `${titleWidth}ch` }}>\n        {title}\n      </Heading>\n      {contexto}\n      {acoes}\n    </div>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "meta": {
    "uso": {
      "quando": "Abrir uma dobra de landing com rótulo, título grande e linha de contexto",
      "evite": "Título de hero animado: line-reveal ou mist-text; chamada com ação de conversão, cta-surface"
    }
  },
  "categories": [
    "conteudo",
    "dobra",
    "titulo",
    "landing"
  ],
  "type": "registry:ui"
}