{
  "manifest": {
    "meta": {
      "name": "HibouPay Design System",
      "version": "0.4.0",
      "motto": "Papel para decidir. Vidro para navegar.",
      "lead": "A fonte de cor, espaço, vidro e comportamento do checkout, do backoffice e dos produtos que vierem depois. Cada peça tem uma razão escrita."
    },
    "principles": [
      {
        "title": "Papel e vidro",
        "body": "Papel guarda dado e decisão. Vidro só no que navega por cima: barras, busca, compositor, toast."
      },
      {
        "title": "A coruja é o agente",
        "body": "Nenhum ícone genérico de IA. A coruja pisca quando vigia e ganha órbita quando trabalha."
      },
      {
        "title": "Mono é máquina",
        "body": "Índices, IDs, rótulos e estados em mono. O que a pessoa lê fica em Inter; o que decide, em Sora."
      },
      {
        "title": "Raios concêntricos",
        "body": "Raio interno = externo − padding. Cartão 16 com 4 de respiro abriga controle 12."
      },
      {
        "title": "Uma margem só",
        "body": "16 · 24 · 40 por largura. Nenhuma tela inventa o próprio padding lateral."
      },
      {
        "title": "Luz, não faixa",
        "body": "Tom aparece como ponto e brilho. Nada de barra colorida no topo do cartão."
      }
    ],
    "brand": {
      "palette": [
        {
          "name": "Black",
          "hex": "#000000",
          "rgb": "0 · 0 · 0",
          "role": "Robustez. Fim da escala corporativa, fundo da superfície escura."
        },
        {
          "name": "Graffiti",
          "hex": "#2E3440",
          "rgb": "46 · 52 · 64",
          "role": "Credibilidade. Tinta de texto, sidebar, dock e toda sombra."
        },
        {
          "name": "Vivid Blue",
          "hex": "#0061F1",
          "rgb": "0 · 97 · 241",
          "role": "Confiança e tecnologia. Ação principal, foco e luz."
        },
        {
          "name": "White",
          "hex": "#FFFFFF",
          "rgb": "255 · 255 · 255",
          "role": "Transparência. Papel onde o dado mora.",
          "light": true
        }
      ],
      "toneScale": {
        "from": "Tom corporativo",
        "to": "Tom popular",
        "body": "Cada tela escolhe onde pousa. Relatório e dinheiro puxam para o corporativo; convite e ação puxam para o popular."
      },
      "owl": {
        "gradient": [
          "#0162F7",
          "#0C53DA",
          "#312782"
        ],
        "states": [
          {
            "id": "parado",
            "body": "Sem estado: a marca como assinatura, sem movimento."
          },
          {
            "id": "idle",
            "body": "Vigiando. Pisca a cada 6 s. Use onde o agente está disponível mas não age."
          },
          {
            "id": "working",
            "body": "Trabalhando. Ganha órbita azul. Use enquanto o agente lê, busca ou escreve."
          }
        ]
      }
    },
    "neutrals": [
      {
        "name": "canvas",
        "token": "color.bg",
        "use": "Fundo da aplicação. Nunca recebe dado direto; o dado mora no papel."
      },
      {
        "name": "paper",
        "token": "color.card",
        "use": "Cartão, tabela, formulário, diálogo."
      },
      {
        "name": "wash",
        "token": "color.wash",
        "use": "Skeleton e áreas rebaixadas."
      },
      {
        "name": "muted",
        "token": "color.muted",
        "use": "Texto de apoio, rótulo de máquina, ícone inativo."
      },
      {
        "name": "success",
        "token": "color.success",
        "use": "Concluído, aplicado, liquidado. Texto usa success-ink."
      },
      {
        "name": "warning",
        "token": "color.warning",
        "use": "Aguardando decisão, variação ruim. Texto usa warning-ink."
      },
      {
        "name": "danger",
        "token": "color.danger",
        "use": "Falha, ação destrutiva. Texto usa danger-ink."
      },
      {
        "name": "secondary",
        "token": "color.secondary",
        "use": "Rascunho, experimento. Nunca como ação principal."
      }
    ],
    "glass": {
      "rule": "Mesmo fundo, mesmo desenho, três níveis de transparência. Escolha um e ele vale para barra, busca, popover, toast, sidebar e dock no produto inteiro.",
      "levels": [
        {
          "id": "base",
          "name": "Base",
          "spec": "branco 56→40% · blur 32 · sat 200%",
          "note": "Lê a cor de trás, não a forma. Mais sóbrio, mais corporativo."
        },
        {
          "id": "medio",
          "name": "Mediano",
          "spec": "branco 40→24% · blur 24 · sat 220%",
          "note": "A forma de trás aparece borrada. Brilho na quina superior."
        },
        {
          "id": "intenso",
          "name": "Intenso",
          "spec": "branco 20→8% · blur 14 · sat 250%",
          "note": "Quase líquido: vê-se o que está atrás. Borda e brilho seguram a leitura."
        }
      ],
      "where": [
        "Barra de topo e cabeçalho móvel",
        "Busca global e paleta de comandos",
        "Popover de filtro e menu",
        "Toast",
        "Sidebar e dock (vidro noturno)"
      ],
      "never": [
        "Tabela, formulário ou qualquer dado que precise ser lido com atenção",
        "Diálogo de decisão (é papel sobre scrim)",
        "Sobre foto sem scrim",
        "Empilhado sobre outro vidro"
      ]
    },
    "typeRoles": [
      {
        "name": "Display",
        "spec": "Sora 600 · clamp(32→44px) · −0.035em",
        "className": "text-hb-display",
        "use": "Título de página e herói. Um por tela."
      },
      {
        "name": "Título",
        "spec": "Sora 600 · 16 · −0.015em",
        "className": "font-sora text-hb-title font-semibold",
        "use": "Cabeçalho de cartão, diálogo e seção."
      },
      {
        "name": "Subtítulo",
        "spec": "Sora 600 · 14",
        "className": "font-sora text-hb-body font-semibold",
        "use": "Linha de apoio sob o título. O código já usava; agora tem nome."
      },
      {
        "name": "Métrica",
        "spec": "Sora tabular · 26/30",
        "className": "font-sora text-hb-metric tabular-nums",
        "use": "Número grande de cartão. 30 quando é o herói da área."
      },
      {
        "name": "Número",
        "spec": "Sora tabular · −0.02em",
        "className": "hb-num",
        "use": "Valor, contagem, dinheiro. Alinha em coluna."
      },
      {
        "name": "Corpo",
        "spec": "Inter 15 · 1.55",
        "className": "text-hb-lead leading-relaxed",
        "use": "Texto corrido, descrição, ajuda."
      },
      {
        "name": "Máquina",
        "spec": "JetBrains Mono 12",
        "className": "font-mono text-hb-small",
        "use": "ID, código, hash, modelo, custo."
      },
      {
        "name": "Rótulo",
        "spec": "JetBrains Mono 500 · 11 · +0.12em · caixa alta",
        "className": "hb-label",
        "use": "Cabeçalho de tabela, rótulo de campo, índice de seção."
      }
    ],
    "motion": [
      {
        "name": "instant",
        "value": "120ms",
        "use": "Fecha a pálpebra. Hover, troca de cor."
      },
      {
        "name": "strike",
        "value": "150ms",
        "use": "O corpo do controle viaja antes da luz. Thumb do Switch."
      },
      {
        "name": "quick",
        "value": "200ms",
        "use": "Botão, chip, toast, drawer."
      },
      {
        "name": "calm",
        "value": "280ms",
        "use": "Abre a pálpebra. Diálogo que assenta. Aba que desliza."
      },
      {
        "name": "slow",
        "value": "420ms",
        "use": "Bloco que entra na tela, tile ativo da navegação."
      },
      {
        "name": "pupil",
        "value": "80ms",
        "use": "Atraso da luz. Entra depois que o corpo chegou."
      },
      {
        "name": "ease",
        "value": "cubic-bezier(0.16, 1, 0.3, 1)",
        "use": "Curva padrão: sai rápido, pousa devagar."
      },
      {
        "name": "spring",
        "value": "cubic-bezier(0.34, 1.36, 0.64, 1)",
        "use": "Só para confirmação alegre: passa um pouco e volta."
      }
    ],
    "patterns": [
      {
        "slug": "decision-gate",
        "title": "Gate de decisão",
        "summary": "Toda ação irreversível passa por um gate legível: o que acontece, o que não volta e por quê.",
        "rules": [
          "Dinheiro, permissão, exclusão e execução de agente sempre abrem ConfirmGate.",
          "Se a ação entra no histórico, peça motivo (requireReason). Mínimo de 3 caracteres.",
          "Para exclusão em massa ou irreversível, peça a palavra exata (requireTypedConfirm).",
          "O botão de confirmação repete o verbo da ação: \"Estornar R$ 1.200\", não \"OK\".",
          "Cancelar é sempre ghost e fica à esquerda; no celular fica por baixo."
        ],
        "antiPatterns": [
          "Confirmar com \"Tem certeza?\" sem dizer a consequência.",
          "Gate que libera o botão sem motivo quando o motivo vai para auditoria.",
          "Toast de desfazer no lugar de gate para dinheiro."
        ]
      },
      {
        "slug": "agent-proposal",
        "title": "Agente propõe, humano decide",
        "summary": "A coruja mostra o que encontrou, com fonte. A pessoa decide. O agente não inventa campo, estado nem componente.",
        "rules": [
          "Enquanto trabalha, a coruja ganha órbita (HibouMark state=\"working\"). Espera de tela é StatusView working, não um spinner de página.",
          "A proposta é papel: o que muda, de onde veio, e a confiança em faixa — não um número falso-preciso.",
          "Faltou componente, token ou campo no contrato: diga o que falta. Não invente.",
          "Decisão ainda aberta não vira código. A pessoa registra a escolha antes.",
          "Consultar margem, enviar ou cobrar passa também pelo Gate de decisão. Consentimento de dado pessoal nunca vem pré-marcado.",
          "A decisão fica registrada com autor humano."
        ],
        "antiPatterns": [
          "Ícone de brilho ou robô no lugar da coruja.",
          "Aceitar a proposta sozinho porque a confiança é alta.",
          "Esconder a fonte da sugestão.",
          "Inventar estado, campo ou componente que não está no contrato."
        ]
      },
      {
        "slug": "empty-error-loading",
        "title": "Vazio, erro e carregando",
        "summary": "Nenhuma tela termina num beco. Vazio diz o próximo passo, erro diz o que fazer, carregando mostra a forma do que vem.",
        "rules": [
          "Vazio usa EmptyState com a coruja vigiando e uma ação quando houver.",
          "Erro recuperável usa ErrorBanner com \"Tentar de novo\". A mensagem diz a causa em linguagem da pessoa.",
          "Carregando lista ou cartão usa Skeleton com a forma final; ação curta usa Button loading.",
          "Espera que a pessoa não controla ocupa a tela com StatusView working: diga quanto demora e o que não fazer.",
          "Aviso que fica enquanto durar a condição é Notice, preso ao conteúdo. Toast é só para o que passa.",
          "Célula sem dado fica vazia. Nunca invente valor, nunca escreva \"N/A\" em dado financeiro."
        ],
        "antiPatterns": [
          "Ilustração genérica de caixa vazia.",
          "Mensagem técnica (\"Error 500\") sem próxima ação.",
          "Spinner de página inteira para uma lista.",
          "Tela de espera sem saída nenhuma."
        ]
      },
      {
        "slug": "money-and-numbers",
        "title": "Dinheiro e números",
        "summary": "Número é Sora tabular, alinhado à direita, com unidade. Variação ruim é aviso, não erro.",
        "rules": [
          "Use hb-num (Sora, algarismos tabulares) para valor, contagem e percentual.",
          "Em tabela, coluna numérica usa align=\"right\".",
          "Sempre com unidade: R$, %, pp, tokens. Valor em real usa formatBRL / formatCents do Core — o formato não é escolha de cada app.",
          "Guarde dinheiro em centavos e formate só na borda, com formatCents. Float em valor de contrato é bug.",
          "Delta bom usa success; delta ruim usa warning. Danger é só para falha.",
          "Célula vazia segue vazia."
        ],
        "antiPatterns": [
          "Valor monetário em Inter proporcional.",
          "Número centralizado em coluna.",
          "Arredondar sem indicar (\"1,2k\" sem contexto de milhar)."
        ]
      },
      {
        "slug": "filters",
        "title": "Filtros",
        "summary": "Filtros são chips no canvas. Ativo vira papel com anel azul; as opções abrem em popover de vidro.",
        "rules": [
          "Um FilterChip por dimensão. O rótulo diz a dimensão; o valor aparece ao lado quando ativo.",
          "Mais de 8 opções: searchable.",
          "Dimensão exclusiva (período, ordenação): single.",
          "Chip ativo tem X para limpar sem abrir o popover.",
          "Resultado vazio por filtro mostra EmptyState com \"Limpar filtros\"."
        ],
        "antiPatterns": [
          "Select nativo numa barra de filtros.",
          "Filtro que some quando não há resultado.",
          "Cor de estado no chip (o chip não é status)."
        ]
      },
      {
        "slug": "navigation",
        "title": "Navegação em vidro",
        "summary": "Sidebar de vidro noturno que recolhe para trilho, espia no hover e marca a página com o tile de orelhas.",
        "rules": [
          "Desktop: painel 256 aberto, trilho 84 recolhido. \"[\" alterna; preferência em cookie.",
          "No trilho, hover por 380 ms espia o painel sem mudar o layout.",
          "Item ativo: tile branco com orelhas (hb-ears) que desliza até o item.",
          "Celular: barra de vidro no topo e dock noturno flutuante com até 4 destinos + Mais.",
          "Busca global em ⌘K / Ctrl K, sempre."
        ],
        "antiPatterns": [
          "Barra lateral branca opaca.",
          "Mais de 4 itens no dock.",
          "Destacar ativo com faixa colorida na borda."
        ]
      },
      {
        "slug": "forms",
        "title": "Formulários",
        "summary": "Rótulo de máquina em cima, controle com a mesma altura do botão, dica embaixo. Erro diz o que fazer.",
        "rules": [
          "Rótulo sempre visível (hb-label). Placeholder é exemplo, não rótulo.",
          "Tamanho do campo acompanha o botão ao lado: sm 32, md 40, lg 48.",
          "Erro liga aria-invalid e aria-describedby, com ícone e instrução: \"Falta o domínio. Ex.: nome@empresa.com\".",
          "Campos relacionados em grade de 2 colunas a partir de md; texto longo ocupa a linha.",
          "Ação principal à direita no rodapé; no celular, empilhada com a principal por baixo."
        ],
        "antiPatterns": [
          "Erro só em cor.",
          "Validar a cada tecla antes de a pessoa terminar.",
          "Rótulo flutuante dentro do campo."
        ]
      },
      {
        "slug": "checkout-lending",
        "title": "Checkout com crédito",
        "summary": "Contratar crédito dentro de uma compra. A pessoa precisa saber, em toda etapa, quanto vai pagar, o que autorizou e o que ainda falta.",
        "rules": [
          "Stepper no topo com o fim conhecido. O título repete a etapa em texto: \"Etapa 2 de 4\".",
          "Consentimento é Notice info com Checkbox dentro, citando a norma. Autorizar consulta de dado pessoal nunca vem pré-marcado.",
          "Condição de pagamento é ChoiceCard: parcela e total no mesmo cartão. A opção padrão é a mais barata, não a mais lucrativa.",
          "Adicional com preço (seguro, garantia) é ChoiceCard multiple, desmarcado, com o custo mensal explícito.",
          "Antes de assinar, SummaryList repete valor solicitado, parcela, primeiro desconto e total. O total é a única linha em ênfase.",
          "Assinatura e aprovação são gate: o botão repete o verbo e o valor (\"Confirmar e assinar\"), e só libera com o aceite marcado.",
          "Espera de análise ou de assinatura usa StatusView working com o aviso de não fechar a janela no rodapé.",
          "O fim tem documento e caminho de volta: contrato (CCB) e retorno à loja, aprovado ou recusado.",
          "Sair da compra é sempre possível: Button link \"Cancelar e voltar à loja\", em todas as etapas."
        ],
        "antiPatterns": [
          "Pré-marcar consentimento de consulta de margem ou adicional pago.",
          "Mostrar parcela sem o total, ou total sem o custo efetivo.",
          "Barra de progresso falsa para uma análise de duração desconhecida.",
          "Tela de espera sem cancelar e sem suporte.",
          "Recusa sem motivo nem próximo passo."
        ]
      }
    ],
    "accessibility": [
      {
        "title": "Contraste",
        "rules": [
          "Texto AA (4.5:1). Texto de estado usa a variante -ink (success-ink, warning-ink, danger-ink).",
          "Muted #686D75 sobre papel e canvas passa AA para texto de apoio.",
          "Vidro revalida contraste nos três níveis; texto sobre vidro é ink, nunca muted claro."
        ]
      },
      {
        "title": "Foco",
        "rules": [
          "Todo interativo tem o mesmo foco: anel de 2px Vivid Blue com offset de 2px, imediato; halo de 4px entra 80ms depois (pupil). Utilitária hb-focus; campos usam hb-pupil com a mesma geometria.",
          "Foco nunca é removido sem substituto.",
          "Diálogo prende o foco e devolve ao gatilho ao fechar."
        ]
      },
      {
        "title": "Teclado",
        "rules": [
          "Tab / Shift+Tab percorrem; Enter e Espaço ativam.",
          "Esc fecha diálogo, popover e busca.",
          "Setas navegam dentro de Tabs e listas.",
          "Enter no cabeçalho da tabela ordena; Tab foca o link da linha."
        ]
      },
      {
        "title": "Leitor de tela",
        "rules": [
          "Botão só com ícone exige aria-label.",
          "Spinner sozinho exige label (vira role=status).",
          "Erro de campo é anunciado via aria-describedby.",
          "A coruja é decorativa sem title; com title vira img nomeada."
        ]
      },
      {
        "title": "Movimento",
        "rules": [
          "prefers-reduced-motion zera animação e transição (órbita, piscar, shimmer, deslizes).",
          "Nenhuma informação depende só de movimento."
        ]
      },
      {
        "title": "Alvo",
        "rules": [
          "Alvo mínimo de 28 px (control xs); 40 px no celular para ação principal.",
          "Espaço entre alvos de no mínimo 4 px."
        ]
      }
    ],
    "voice": {
      "summary": "Direto, humano, sem jargão. Diga o que aconteceu e o que fazer agora.",
      "rules": [
        {
          "do": "Tentar de novo",
          "dont": "Ocorreu um erro inesperado. Por favor, tente novamente mais tarde!"
        },
        {
          "do": "Falta o domínio. Ex.: nome@empresa.com",
          "dont": "E-mail inválido"
        },
        {
          "do": "Estornar R$ 1.200",
          "dont": "Confirmar"
        },
        {
          "do": "Nada por aqui ainda. A primeira cobrança aparece aqui.",
          "dont": "Nenhum registro encontrado."
        },
        {
          "do": "A chave foi recusada pelo provedor.",
          "dont": "Erro 401: Unauthorized"
        }
      ],
      "principles": [
        "Verbo no botão. O rótulo diz o que acontece ao clicar.",
        "Sem ponto de exclamação e sem \"por favor\" em erro.",
        "Número sempre com unidade.",
        "IDs e códigos em mono, nunca traduzidos.",
        "Português do Brasil; termos técnicos consagrados ficam em inglês (token, deploy)."
      ]
    },
    "governance": {
      "lifecycle": [
        "Proposta: o problema real e onde aparece",
        "Contrato no registry ou no manifesto, revisado por uma pessoa",
        "Implementação no Core, sem funil nem copy de um app",
        "Documentação e story no mesmo verbo",
        "Release SemVer com changelog",
        "Sensor: pnpm ds:check e pnpm verify"
      ],
      "maturity": [
        {
          "id": "experimental",
          "body": "Pode mudar sem aviso. Não use em fluxo crítico."
        },
        {
          "id": "beta",
          "body": "API estável na intenção; pode ganhar props. Breaking só em minor com nota."
        },
        {
          "id": "stable",
          "body": "Breaking só em major, com guia de migração."
        },
        {
          "id": "deprecated",
          "body": "Tem substituto documentado. Sai na próxima major."
        }
      ],
      "rules": [
        "Tokens são a fonte da verdade. Derivados (CSS, JS, JSON, MD) são gerados; editar derivado é bug e o check de drift bloqueia.",
        "O Core não conhece funil, estágio nem copy de um app. Consentimento, margem e sessão ficam no produto.",
        "Componente, token ou padrão que não está no registry não se inventa. Diga o que falta.",
        "Componente novo entra como experimental e só sobe com documentação completa e uso real.",
        "Mudança de contrato começa no manifesto ou no registry, com revisão humana, antes do código. pnpm verify é o sensor: typecheck, drift, lint de valor solto, axe por story e uma story por slug.",
        "Tamanho de texto só com a escala text-hb-*. Foco só com a utilitária hb-focus; campo usa hb-pupil.",
        "Overlay no celular é folha (hb-sheet); toast nasce no topo."
      ]
    }
  },
  "registry": [
    {
      "slug": "button",
      "name": "Button",
      "category": "action",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Button",
        "buttonVariants",
        "buttonSizes",
        "ButtonProps",
        "ButtonVariant",
        "ButtonSize"
      ],
      "summary": "Ação. Uma altura por tamanho, compartilhada com input e chip. Toque afunda 2%. No foco, o anel de 2px chega agora e o halo azul entra depois.",
      "whenToUse": [
        "Disparar uma ação na tela atual: salvar, confirmar, abrir diálogo.",
        "Confirmar ou cancelar dentro de diálogo e gate.",
        "Ação de ícone em barra densa (size icon / icon-sm) com aria-label."
      ],
      "whenNotToUse": [
        "Navegar para outra página: use link.",
        "Alternar entre vistas: use Tabs.",
        "Filtrar lista: use FilterChip."
      ],
      "anatomy": [
        "Contêiner com altura de controle (28 · 32 · 40 · 48)",
        "Ícone opcional à esquerda ou direita (lucide, tamanho automático)",
        "Rótulo com verbo",
        "Spinner sobreposto quando loading (a largura não muda)"
      ],
      "variants": [
        {
          "name": "primary",
          "description": "Vivid Blue em degradê. Uma por área. A ação que a pessoa veio fazer."
        },
        {
          "name": "night",
          "description": "Graffiti. Ação forte que não é a principal, ou principal sobre fundo azul."
        },
        {
          "name": "outline",
          "description": "Papel com anel. Ação alternativa ao lado da primária."
        },
        {
          "name": "secondary",
          "description": "Violeta suave. Rascunho, experimento."
        },
        {
          "name": "ghost",
          "description": "Sem fundo. Cancelar, ação terciária."
        },
        {
          "name": "glass",
          "description": "Sobre vidro ou canvas com aurora."
        },
        {
          "name": "success",
          "description": "Concluir de forma positiva (liquidar, aprovar)."
        },
        {
          "name": "danger",
          "description": "Destrutiva. Quase sempre abre ConfirmGate."
        },
        {
          "name": "link",
          "description": "Saída discreta, sem caixa. Voltar, cancelar navegação."
        }
      ],
      "states": [
        "default",
        "hover",
        "active (scale 0.98)",
        "focus-visible (anel 2px + offset 2px)",
        "loading (aria-busy, largura mantida)",
        "disabled (opacidade 55%)"
      ],
      "props": [
        {
          "name": "variant",
          "type": "\"primary\" | \"night\" | \"secondary\" | \"outline\" | \"ghost\" | \"glass\" | \"link\" | \"danger\" | \"success\"",
          "default": "\"primary\"",
          "description": "Peso visual e intenção."
        },
        {
          "name": "size",
          "type": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"icon\" | \"icon-sm\"",
          "default": "\"md\"",
          "description": "xs 28 · sm 32 · md 40 · lg 48. icon é quadrado de 40; icon-sm de 32."
        },
        {
          "name": "loading",
          "type": "boolean",
          "default": "false",
          "description": "Troca o conteúdo por spinner mantendo a largura. Também desabilita e liga aria-busy."
        },
        {
          "name": "type",
          "type": "\"button\" | \"submit\" | \"reset\"",
          "default": "\"button\"",
          "description": "Padrão button para não submeter formulário por acidente."
        },
        {
          "name": "...props",
          "type": "ButtonHTMLAttributes",
          "description": "Qualquer atributo nativo de <button>. ref é encaminhado."
        }
      ],
      "tokens": [
        "color.primary",
        "color.primaryLight",
        "color.primaryDeep",
        "color.secondaryInk",
        "color.graffiti",
        "color.graffitiDeep",
        "color.graffitiLight",
        "type.small",
        "type.compact",
        "type.body",
        "type.lead",
        "control.xs",
        "control.sm",
        "control.md",
        "control.lg",
        "radius.sm",
        "radius.md",
        "radius.lg",
        "motion.ease",
        "motion.quick",
        "motion.pupil"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Move o foco para o botão."
        },
        {
          "keys": "Enter / Espaço",
          "action": "Ativa."
        }
      ],
      "screenReader": [
        "Anunciado como botão com o rótulo.",
        "size icon / icon-sm exige aria-label.",
        "loading anuncia ocupado (aria-busy)."
      ],
      "dos": [
        "Uma primária por área de decisão.",
        "Rótulo com verbo: \"Confirmar e assinar\", \"Estornar R$ 1.200\".",
        "Mesma altura do input ao lado."
      ],
      "donts": [
        "Duas primárias lado a lado.",
        "Botão para navegar.",
        "Rótulo genérico (\"OK\", \"Clique aqui\")."
      ],
      "content": [
        "Verbo no infinitivo ou imperativo curto, até 3 palavras.",
        "Inclua o objeto quando houver dinheiro: \"Pagar R$ 90\"."
      ],
      "related": [
        "confirm-gate",
        "modal",
        "spinner",
        "dropdown-menu"
      ]
    },
    {
      "slug": "card",
      "name": "Card",
      "category": "surface",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Card",
        "CardHeader",
        "CardFooter",
        "SectionTitle",
        "Kicker",
        "CardProps",
        "CardHeaderProps",
        "CardMaterial",
        "CardPadding"
      ],
      "summary": "Superfície. Quatro materiais: papel guarda dado e decisão, rebaixado abriga prévia, vidro só no que flutua, noite é a superfície da marca.",
      "whenToUse": [
        "Agrupar dado relacionado com título e ações.",
        "Item clicável em grade (interactive).",
        "Bloco de métrica, formulário ou prévia."
      ],
      "whenNotToUse": [
        "Envolver a página inteira.",
        "Card dentro de card com o mesmo material.",
        "Vidro sobre dado que precisa de leitura atenta."
      ],
      "anatomy": [
        "Contêiner raio 16 com material",
        "CardHeader: índice mono, rótulo (kicker), título Sora, descrição, ações",
        "Corpo livre",
        "CardFooter: divisor e ações à direita"
      ],
      "variants": [
        {
          "name": "paper · e1",
          "description": "O padrão. Dado, formulário, decisão."
        },
        {
          "name": "sunken · e0",
          "description": "Trilho de segmento, área de teste, prévia."
        },
        {
          "name": "glass · e2",
          "description": "Só no que flutua. Combine com hb-lens para a borda de luz."
        },
        {
          "name": "night · e2",
          "description": "Graffiti. Cabeçalho do agente, destaque de marca."
        }
      ],
      "states": [
        "default",
        "interactive: fica no lugar, sombra e2, borda de luz nasce depois"
      ],
      "props": [
        {
          "name": "material",
          "type": "\"paper\" | \"sunken\" | \"glass\" | \"night\"",
          "default": "\"paper\"",
          "description": "Material da superfície."
        },
        {
          "name": "padding",
          "type": "\"none\" | \"sm\" | \"md\" | \"lg\"",
          "default": "\"md\"",
          "description": "Cresce com a tela. O raio interno de quem está dentro é 16 − padding."
        },
        {
          "name": "interactive",
          "type": "boolean",
          "default": "false",
          "description": "Acende a borda de luz no hover, sem levantar o cartão."
        },
        {
          "name": "hover",
          "type": "boolean",
          "description": "Obsoleto. Use interactive."
        },
        {
          "name": "CardHeader.index",
          "type": "string | number",
          "description": "Número vira dois dígitos (1 → 01)."
        },
        {
          "name": "CardHeader.kicker",
          "type": "ReactNode",
          "description": "Rótulo de máquina acima do título."
        },
        {
          "name": "CardHeader.title",
          "type": "ReactNode",
          "description": "Título em Sora 16."
        },
        {
          "name": "CardHeader.description",
          "type": "ReactNode",
          "description": "Texto de apoio."
        },
        {
          "name": "CardHeader.actions",
          "type": "ReactNode",
          "description": "Botões. Quebram para baixo no celular."
        },
        {
          "name": "CardHeader.divider",
          "type": "boolean",
          "description": "Linha abaixo do cabeçalho."
        }
      ],
      "tokens": [
        "color.card",
        "radius.lg",
        "elevation.0",
        "elevation.1",
        "elevation.2",
        "motion.ease"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Card não é focável. Se for clicável, envolva um link ou botão real."
        }
      ],
      "screenReader": [
        "CardHeader.title é h3; ajuste a hierarquia da página em volta.",
        "Não coloque role=button no Card; use link ou botão dentro."
      ],
      "dos": [
        "Um assunto por cartão.",
        "Ações no cabeçalho ou no rodapé, não nos dois.",
        "Raio concêntrico para o que está dentro."
      ],
      "donts": [
        "Faixa colorida no topo para indicar estado.",
        "Sombra preta.",
        "Card com padding lg dentro de card."
      ],
      "content": [
        "Título diz o assunto, não a ação.",
        "Kicker em mono, curto: \"paper · e1\", \"Etapa 2\"."
      ],
      "related": [
        "metric-widget",
        "empty-state",
        "grid"
      ]
    },
    {
      "slug": "badge",
      "name": "Badge",
      "category": "feedback",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Badge",
        "badgeTones",
        "BadgeProps",
        "BadgeTone"
      ],
      "summary": "Etiqueta de estado com raio 6, nunca pílula. O ponto diz que o estado está vivo. O app mapeia o domínio para um tom do Core.",
      "whenToUse": [
        "Estado de um item: aplicado, aguardando, falhou.",
        "Código curto (P0, L2, v1) com code.",
        "Categoria discreta em tabela ou cartão."
      ],
      "whenNotToUse": [
        "Ação clicável: use Button.",
        "Filtro: use FilterChip.",
        "Texto longo."
      ],
      "anatomy": [
        "Contêiner 20px, raio 6, anel interno",
        "Ponto opcional em currentColor",
        "Rótulo 11px (ou mono 11 com code)"
      ],
      "variants": [
        {
          "name": "default",
          "description": "Neutro."
        },
        {
          "name": "muted",
          "description": "Expirado, inativo."
        },
        {
          "name": "primary",
          "description": "Em andamento, agente."
        },
        {
          "name": "secondary",
          "description": "Rascunho."
        },
        {
          "name": "success",
          "description": "Concluído, aplicado."
        },
        {
          "name": "warning",
          "description": "Aguardando decisão."
        },
        {
          "name": "danger",
          "description": "Falhou."
        },
        {
          "name": "night",
          "description": "Nível, código de destaque."
        }
      ],
      "states": [
        "estático",
        "com ponto (estado vivo)"
      ],
      "props": [
        {
          "name": "tone",
          "type": "\"default\" | \"muted\" | \"primary\" | \"secondary\" | \"success\" | \"warning\" | \"danger\" | \"night\"",
          "default": "\"default\"",
          "description": "Tom do Core."
        },
        {
          "name": "dot",
          "type": "boolean",
          "default": "false",
          "description": "Ponto que indica estado vivo."
        },
        {
          "name": "code",
          "type": "boolean",
          "default": "false",
          "description": "Mono em caixa, para códigos curtos (P0, L2, v1)."
        },
        {
          "name": "...props",
          "type": "HTMLAttributes<HTMLSpanElement>",
          "description": "Atributos de <span>."
        }
      ],
      "tokens": [
        "radius.xs",
        "color.successInk",
        "color.warningInk",
        "color.dangerInk",
        "color.primaryDeep"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "Lido como texto. Se o estado for só cor, o rótulo precisa dizer o estado.",
        "O ponto é aria-hidden."
      ],
      "dos": [
        "Rótulo de uma ou duas palavras, minúsculas.",
        "Mapear domínio → tom no app."
      ],
      "donts": [
        "Criar tom novo no Core para um domínio.",
        "Pílula totalmente arredondada.",
        "Badge clicável."
      ],
      "content": [
        "Minúsculas, particípio ou substantivo: \"aplicado\", \"rascunho\"."
      ],
      "related": [
        "avatar",
        "data-table"
      ]
    },
    {
      "slug": "input",
      "name": "Input",
      "category": "input",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Input",
        "Label",
        "Field",
        "fieldFrame",
        "InputProps",
        "FieldSize"
      ],
      "summary": "Papel com anel fino. Foco vira azul com halo de 4px. Erro diz o que fazer, com ícone e aria.",
      "whenToUse": [
        "Texto curto de uma linha: nome, e-mail, valor, busca.",
        "Busca em barra com leading de ícone."
      ],
      "whenNotToUse": [
        "Texto longo: Textarea.",
        "Escolha de lista fechada: Select ou FilterChip."
      ],
      "anatomy": [
        "Label (hb-label) opcional acima",
        "Campo com anel interno",
        "leading / trailing opcionais",
        "Mensagem: dica ou erro com ícone"
      ],
      "variants": [
        {
          "name": "sm · 32",
          "description": "Barras densas."
        },
        {
          "name": "md · 40",
          "description": "Padrão."
        },
        {
          "name": "lg · 48",
          "description": "Formulário de destaque, celular."
        }
      ],
      "states": [
        "default",
        "hover (anel mais escuro)",
        "focus (anel azul + halo 4px)",
        "error (anel e halo danger, aria-invalid)",
        "disabled"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "description": "Rótulo visível, ligado por htmlFor."
        },
        {
          "name": "hint",
          "type": "string",
          "description": "Dica abaixo, ligada por aria-describedby."
        },
        {
          "name": "error",
          "type": "string",
          "description": "Mensagem de erro. Liga aria-invalid e substitui a dica."
        },
        {
          "name": "size",
          "type": "\"sm\" | \"md\" | \"lg\"",
          "default": "\"md\"",
          "description": "32 · 40 · 48. Acompanhe o botão ao lado."
        },
        {
          "name": "leading",
          "type": "ReactNode",
          "description": "Ícone à esquerda (decorativo)."
        },
        {
          "name": "trailing",
          "type": "ReactNode",
          "description": "Ícone ou ação à direita."
        },
        {
          "name": "...props",
          "type": "InputHTMLAttributes",
          "description": "Atributos nativos. ref é encaminhado; id é gerado se ausente."
        }
      ],
      "tokens": [
        "control.sm",
        "control.md",
        "control.lg",
        "radius.md",
        "color.primary",
        "color.danger",
        "color.dangerInk",
        "motion.quick"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca o campo."
        }
      ],
      "screenReader": [
        "Label associado por id.",
        "Erro e dica anunciados por aria-describedby.",
        "aria-invalid quando há erro."
      ],
      "dos": [
        "Rótulo sempre visível.",
        "Erro com instrução e exemplo."
      ],
      "donts": [
        "Placeholder como rótulo.",
        "Erro só em cor."
      ],
      "content": [
        "Rótulo substantivo curto: \"E-mail do decisor\".",
        "Placeholder é exemplo: \"nome@empresa.com\"."
      ],
      "related": [
        "select",
        "textarea",
        "filter-chip",
        "checkbox",
        "file-upload"
      ]
    },
    {
      "slug": "select",
      "name": "Select",
      "category": "input",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Select",
        "SelectProps"
      ],
      "summary": "Campo nativo. Mesmo anel e a mesma altura do Input, com a seta Graffiti do campo. O menu aberto é o do sistema.",
      "whenToUse": [
        "Escolher um valor de lista curta dentro de formulário.",
        "Quando o picker nativo do celular é desejável."
      ],
      "whenNotToUse": [
        "Filtro em barra: FilterChip.",
        "Mais de ~15 opções com busca: FilterChip searchable."
      ],
      "anatomy": [
        "Label",
        "Campo com seta à direita",
        "Mensagem: dica ou erro"
      ],
      "states": [
        "default",
        "hover",
        "focus",
        "error",
        "disabled"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "description": "Rótulo visível."
        },
        {
          "name": "hint",
          "type": "string",
          "description": "Dica abaixo."
        },
        {
          "name": "error",
          "type": "string",
          "description": "Erro; liga aria-invalid."
        },
        {
          "name": "size",
          "type": "\"sm\" | \"md\" | \"lg\"",
          "default": "\"md\"",
          "description": "32 · 40 · 48."
        },
        {
          "name": "children",
          "type": "<option> | <optgroup>",
          "required": true,
          "description": "Opções nativas."
        }
      ],
      "tokens": [
        "control.md",
        "radius.md",
        "color.muted"
      ],
      "keyboard": [
        {
          "keys": "Espaço / Alt+↓",
          "action": "Abre as opções."
        },
        {
          "keys": "↑ ↓",
          "action": "Troca a opção."
        }
      ],
      "screenReader": [
        "Combobox nativo, anunciado pelo sistema."
      ],
      "dos": [
        "Opção padrão sensata ou placeholder desabilitado."
      ],
      "donts": [
        "Select para duas opções: use Tabs segment."
      ],
      "content": [
        "Opções em ordem lógica (fluxo), não alfabética, quando houver fluxo."
      ],
      "related": [
        "input",
        "filter-chip",
        "radio"
      ]
    },
    {
      "slug": "textarea",
      "name": "Textarea",
      "category": "input",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Textarea",
        "TextareaProps"
      ],
      "summary": "Campo de várias linhas. Mesmo anel do Input. Mínimo de 96px, cresce na vertical.",
      "whenToUse": [
        "Motivo, nota, descrição.",
        "Motivo obrigatório do ConfirmGate."
      ],
      "whenNotToUse": [
        "Uma linha: Input."
      ],
      "anatomy": [
        "Label",
        "Área de texto",
        "Mensagem"
      ],
      "states": [
        "default",
        "hover",
        "focus",
        "error",
        "disabled"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "description": "Rótulo visível."
        },
        {
          "name": "hint",
          "type": "string",
          "description": "Dica abaixo."
        },
        {
          "name": "error",
          "type": "string",
          "description": "Erro; liga aria-invalid."
        },
        {
          "name": "...props",
          "type": "TextareaHTMLAttributes",
          "description": "Atributos nativos."
        }
      ],
      "tokens": [
        "radius.md",
        "color.primary"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca. Enter quebra linha."
        }
      ],
      "screenReader": [
        "Igual ao Input."
      ],
      "dos": [
        "Dica dizendo para onde o texto vai: \"Vai para o histórico.\""
      ],
      "donts": [
        "Limite de caracteres escondido."
      ],
      "content": [
        "Placeholder com exemplos reais separados por ponto e vírgula."
      ],
      "related": [
        "input",
        "confirm-gate"
      ]
    },
    {
      "slug": "tabs",
      "name": "Tabs",
      "category": "input",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Tabs",
        "TabsList",
        "TabsTrigger",
        "TabsContent",
        "TabsListProps",
        "TabsTriggerProps",
        "TabsVariant"
      ],
      "summary": "Segmento: trilho rebaixado com um papel que desliza até a aba ativa. Linha: sublinhado azul para conteúdo longo. Base Radix.",
      "whenToUse": [
        "Alternar vistas do mesmo conjunto (Todos, Aguardando, Decididos).",
        "Seções de um detalhe (line)."
      ],
      "whenNotToUse": [
        "Navegação entre páginas.",
        "Mais de 6 abas."
      ],
      "anatomy": [
        "TabsList (trilho)",
        "Indicador deslizante (papel ou linha)",
        "TabsTrigger com contagem opcional",
        "TabsContent (entra só por opacidade)"
      ],
      "variants": [
        {
          "name": "segment",
          "description": "Padrão. Filtro de vista compacto."
        },
        {
          "name": "line",
          "description": "Abas de conteúdo longo, largura total."
        }
      ],
      "states": [
        "inativa",
        "hover",
        "ativa",
        "focus-visible"
      ],
      "props": [
        {
          "name": "Tabs.defaultValue / value",
          "type": "string",
          "description": "Aba inicial (não controlado) ou atual (controlado)."
        },
        {
          "name": "Tabs.onValueChange",
          "type": "(value: string) => void",
          "description": "Troca de aba."
        },
        {
          "name": "TabsList.variant",
          "type": "\"segment\" | \"line\"",
          "default": "\"segment\"",
          "description": "Desenho do trilho."
        },
        {
          "name": "TabsTrigger.value",
          "type": "string",
          "required": true,
          "description": "Identificador da aba."
        },
        {
          "name": "TabsTrigger.count",
          "type": "number",
          "description": "Contagem em Sora tabular ao lado do rótulo."
        }
      ],
      "tokens": [
        "radius.md",
        "radius.sm",
        "color.primary",
        "motion.ease"
      ],
      "keyboard": [
        {
          "keys": "← →",
          "action": "Move entre abas."
        },
        {
          "keys": "Home / End",
          "action": "Primeira / última."
        },
        {
          "keys": "Tab",
          "action": "Sai para o conteúdo."
        }
      ],
      "screenReader": [
        "tablist / tab / tabpanel com aria-selected (Radix)."
      ],
      "dos": [
        "Rótulos curtos e paralelos.",
        "count para o que pede atenção."
      ],
      "donts": [
        "Aba que dispara ação."
      ],
      "content": [
        "Substantivo ou particípio no plural: \"Decididos\"."
      ],
      "related": [
        "filter-chip"
      ]
    },
    {
      "slug": "filter-chip",
      "name": "FilterChip",
      "category": "input",
      "status": "beta",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "FilterChip",
        "FilterChipProps",
        "ChipOption"
      ],
      "summary": "Chip de filtro: rótulo + valor, popover de vidro. Ativo vira papel com anel azul e ganha X para limpar.",
      "whenToUse": [
        "Barra de filtros sobre lista ou quadro.",
        "Seleção múltipla (padrão) ou única (single)."
      ],
      "whenNotToUse": [
        "Campo de formulário: Select.",
        "Alternar vista: Tabs."
      ],
      "anatomy": [
        "Gatilho: rótulo, valor resumido, seta",
        "Botão limpar (quando ativo)",
        "Popover de vidro com lente",
        "Busca opcional",
        "Opções com caixa ou rádio, ponto de acento e dica mono",
        "Limpar seleção"
      ],
      "states": [
        "inativo",
        "hover",
        "aberto",
        "ativo (anel azul)",
        "vazio na busca"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "required": true,
          "description": "Dimensão filtrada."
        },
        {
          "name": "options",
          "type": "ChipOption[]",
          "required": true,
          "description": "{ value, label, hint?, accent? }."
        },
        {
          "name": "value",
          "type": "string[]",
          "required": true,
          "description": "Valores selecionados."
        },
        {
          "name": "onChange",
          "type": "(next: string[]) => void",
          "required": true,
          "description": "Nova seleção."
        },
        {
          "name": "single",
          "type": "boolean",
          "default": "false",
          "description": "Uma opção por vez (rádio)."
        },
        {
          "name": "searchable",
          "type": "boolean",
          "default": "false",
          "description": "Busca no topo do popover."
        },
        {
          "name": "renderOption",
          "type": "(option, selected) => ReactNode",
          "description": "Conteúdo customizado da opção."
        },
        {
          "name": "emptyLabel",
          "type": "string",
          "default": "\"Nada encontrado\"",
          "description": "Texto quando a busca não acha."
        },
        {
          "name": "clearLabel",
          "type": "string",
          "default": "\"Limpar seleção\"",
          "description": "Rótulo do limpar no rodapé."
        }
      ],
      "tokens": [
        "control.sm",
        "radius.lg",
        "color.primary",
        "color.primaryDeep",
        "glass.base.blur",
        "motion.calm"
      ],
      "keyboard": [
        {
          "keys": "Enter / Espaço",
          "action": "Abre o popover."
        },
        {
          "keys": "↑ / ↓",
          "action": "Percorre as opções."
        },
        {
          "keys": "Home / End",
          "action": "Primeira e última opção."
        },
        {
          "keys": "Tab",
          "action": "Percorre as opções."
        },
        {
          "keys": "Esc",
          "action": "Fecha e devolve o foco."
        }
      ],
      "screenReader": [
        "Grupo de opções. Múltipla: role=checkbox com aria-checked. Única: role=radio com aria-checked.",
        "Limpar tem aria-label \"Limpar {label}\"."
      ],
      "dos": [
        "Uma dimensão por chip.",
        "searchable acima de 8 opções."
      ],
      "donts": [
        "Cor de estado no chip.",
        "Chip que some quando não há resultado."
      ],
      "content": [
        "Rótulo substantivo singular: \"Status\", \"Período\"."
      ],
      "related": [
        "tabs",
        "empty-state",
        "checkbox",
        "dropdown-menu"
      ]
    },
    {
      "slug": "modal",
      "name": "Modal",
      "category": "overlay",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Modal",
        "ModalProps"
      ],
      "summary": "Papel sobre scrim de Graffiti. No celular vira folha que sobe; no desktop pousa e a borda de luz acende depois. O rodapé é a faixa da decisão; o corpo rola.",
      "whenToUse": [
        "Tarefa curta que precisa de foco: atribuir, editar um campo, revisar.",
        "Detalhe que não merece página."
      ],
      "whenNotToUse": [
        "Confirmação de ação irreversível: ConfirmGate.",
        "Fluxo longo com várias etapas: página."
      ],
      "anatomy": [
        "Scrim (hb-scrim)",
        "Alça (só no celular)",
        "Título Sora 18 e descrição",
        "Fechar (X)",
        "Corpo com rolagem",
        "Rodapé com ações"
      ],
      "variants": [
        {
          "name": "sm · 420",
          "description": "Gate, confirmação."
        },
        {
          "name": "md · 520",
          "description": "Padrão."
        },
        {
          "name": "lg · 720",
          "description": "Formulário com duas colunas."
        },
        {
          "name": "xl · 960",
          "description": "Revisão com tabela."
        }
      ],
      "states": [
        "fechado",
        "abrindo (folha no celular, assenta no desktop)",
        "aberto"
      ],
      "props": [
        {
          "name": "open",
          "type": "boolean",
          "required": true,
          "description": "Controlado."
        },
        {
          "name": "onOpenChange",
          "type": "(open: boolean) => void",
          "required": true,
          "description": "Fechar por X, Esc ou clique no scrim."
        },
        {
          "name": "title",
          "type": "ReactNode",
          "required": true,
          "description": "Título acessível."
        },
        {
          "name": "description",
          "type": "ReactNode",
          "description": "Descrição acessível."
        },
        {
          "name": "footer",
          "type": "ReactNode",
          "description": "Ações. Empilham no celular com a principal por baixo."
        },
        {
          "name": "size",
          "type": "\"sm\" | \"md\" | \"lg\" | \"xl\"",
          "default": "\"md\"",
          "description": "Largura máxima no desktop."
        },
        {
          "name": "children",
          "type": "ReactNode",
          "description": "Corpo."
        }
      ],
      "tokens": [
        "radius.xl",
        "elevation.3",
        "motion.ease"
      ],
      "keyboard": [
        {
          "keys": "Esc",
          "action": "Fecha."
        },
        {
          "keys": "Tab",
          "action": "Circula dentro do diálogo (foco preso)."
        }
      ],
      "screenReader": [
        "role=dialog com aria-labelledby (title) e aria-describedby (description).",
        "Foco volta ao gatilho ao fechar."
      ],
      "dos": [
        "Título diz a tarefa.",
        "Ação principal repete o verbo do título."
      ],
      "donts": [
        "Modal sobre modal.",
        "Modal para aviso que não pede decisão."
      ],
      "content": [
        "Título: verbo + objeto (\"Atribuir responsável\")."
      ],
      "related": [
        "confirm-gate",
        "button"
      ]
    },
    {
      "slug": "confirm-gate",
      "name": "ConfirmGate",
      "category": "overlay",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "ConfirmGate",
        "ConfirmGateProps"
      ],
      "summary": "Gate para ações irreversíveis: dinheiro, permissão, exclusão, execução de agente. Pode exigir motivo e palavra digitada.",
      "whenToUse": [
        "Qualquer ação que não volta.",
        "Ação cujo motivo precisa ir para auditoria."
      ],
      "whenNotToUse": [
        "Ação desfazível: execute e ofereça desfazer."
      ],
      "anatomy": [
        "Ícone de escudo com tom",
        "Título e consequência",
        "Conteúdo extra opcional",
        "Motivo (Textarea) opcional",
        "Palavra de confirmação (Input mono) opcional",
        "Cancelar (ghost) + Confirmar (tom)"
      ],
      "variants": [
        {
          "name": "danger",
          "description": "Destrutiva (padrão)."
        },
        {
          "name": "warning",
          "description": "Arriscada, mas não destrutiva."
        },
        {
          "name": "primary",
          "description": "Execução que precisa de consentimento."
        },
        {
          "name": "success",
          "description": "Conclusão positiva irreversível."
        }
      ],
      "states": [
        "bloqueado (motivo ou palavra faltando)",
        "liberado",
        "loading"
      ],
      "props": [
        {
          "name": "open / onOpenChange",
          "type": "boolean / (open) => void",
          "required": true,
          "description": "Controlado."
        },
        {
          "name": "title",
          "type": "ReactNode",
          "required": true,
          "description": "O que vai acontecer."
        },
        {
          "name": "description",
          "type": "ReactNode",
          "description": "Consequência."
        },
        {
          "name": "tone",
          "type": "\"danger\" | \"primary\" | \"success\" | \"warning\"",
          "default": "\"danger\"",
          "description": "Cor do ícone e do botão."
        },
        {
          "name": "confirmLabel",
          "type": "string",
          "default": "\"Confirmar\"",
          "description": "Repita o verbo da ação."
        },
        {
          "name": "cancelLabel",
          "type": "string",
          "default": "\"Cancelar\"",
          "description": "Rótulo do cancelar."
        },
        {
          "name": "requireReason",
          "type": "boolean",
          "default": "false",
          "description": "Exige motivo de ao menos 3 caracteres."
        },
        {
          "name": "reasonLabel",
          "type": "string",
          "default": "\"Motivo (obrigatório)\"",
          "description": "Rótulo do motivo."
        },
        {
          "name": "reasonPlaceholder",
          "type": "string",
          "description": "Exemplo de motivo."
        },
        {
          "name": "requireTypedConfirm",
          "type": "string",
          "description": "Palavra exata a digitar (ex.: EXCLUIR)."
        },
        {
          "name": "onConfirm",
          "type": "({ reason?: string }) => void | Promise<void>",
          "required": true,
          "description": "Recebe o motivo."
        },
        {
          "name": "loading",
          "type": "boolean",
          "description": "Botão de confirmar em loading."
        }
      ],
      "tokens": [
        "color.danger",
        "color.dangerInk",
        "color.warningInk",
        "radius.xl"
      ],
      "keyboard": [
        {
          "keys": "Esc",
          "action": "Cancela."
        },
        {
          "keys": "Tab",
          "action": "Motivo → Cancelar → Confirmar."
        }
      ],
      "screenReader": [
        "Herdado do Modal.",
        "Botão desabilitado até cumprir as exigências."
      ],
      "dos": [
        "Diga a consequência em uma frase.",
        "Motivo quando a ação entra no histórico."
      ],
      "donts": [
        "\"Tem certeza?\" sem consequência.",
        "Confirmar com rótulo genérico."
      ],
      "content": [
        "Título: \"Estornar pagamento\". Descrição: \"O valor volta ao cliente em até 2 dias. Não dá para desfazer.\""
      ],
      "related": [
        "modal",
        "textarea"
      ]
    },
    {
      "slug": "data-table",
      "name": "DataTable",
      "category": "data",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "DataTable",
        "DataTableProps",
        "Column"
      ],
      "summary": "Tabela de trabalho em papel. Linha de 48 (36 no denso), cabeçalho de máquina que ordena, número à direita em Sora tabular. O link da linha é o alvo do teclado.",
      "whenToUse": [
        "Lista de registros com colunas comparáveis.",
        "Dado financeiro que precisa alinhar."
      ],
      "whenNotToUse": [
        "Poucos itens ricos: cartões.",
        "Layout de página."
      ],
      "anatomy": [
        "Contêiner papel e1 com rolagem horizontal",
        "Cabeçalho hb-label, opaco, que gruda quando pedido",
        "Botão de ordenação com seta Graffiti",
        "Linhas com divisor 5%",
        "Link ou botão na primeira célula quando a linha abre",
        "Célula numérica hb-num à direita",
        "Vazio com EmptyState compacto",
        "Carregando com esqueleto na altura da linha"
      ],
      "variants": [
        {
          "name": "padrão · 48",
          "description": "Leitura confortável."
        },
        {
          "name": "dense · 36",
          "description": "Muitas linhas, painel operacional."
        }
      ],
      "states": [
        "vazio",
        "carregando",
        "com linhas",
        "linha hover",
        "coluna ordenada"
      ],
      "props": [
        {
          "name": "columns",
          "type": "Column<T>[]",
          "required": true,
          "description": "{ key, header, cell(row), align?, width?, sortable?, sortValue?, className? }."
        },
        {
          "name": "rows",
          "type": "T[]",
          "required": true,
          "description": "Dados."
        },
        {
          "name": "rowKey",
          "type": "(row: T) => string",
          "required": true,
          "description": "Chave estável."
        },
        {
          "name": "onRowClick",
          "type": "(row: T) => void",
          "description": "Ação de mouse. O teclado usa um botão na primeira célula."
        },
        {
          "name": "rowHref",
          "type": "(row: T) => string",
          "description": "Link real na primeira célula. O ::after cobre a linha."
        },
        {
          "name": "sort",
          "type": "SortState | null",
          "description": "Ordem controlada. Sem isto, a tabela guarda."
        },
        {
          "name": "onSortChange",
          "type": "(sort: SortState) => void",
          "description": "Nova ordem ao clicar no cabeçalho."
        },
        {
          "name": "loading",
          "type": "boolean",
          "description": "Corpo vira esqueleto. aria-busy na tabela."
        },
        {
          "name": "stickyHeader",
          "type": "boolean",
          "description": "Cabeçalho gruda no topo do scroll."
        },
        {
          "name": "empty",
          "type": "ReactNode | string",
          "default": "\"Nada por aqui.\"",
          "description": "Conteúdo quando não há linhas."
        },
        {
          "name": "dense",
          "type": "boolean",
          "default": "false",
          "description": "Linha de 36px."
        },
        {
          "name": "caption",
          "type": "string",
          "description": "Legenda acessível (sr-only)."
        }
      ],
      "tokens": [
        "radius.lg",
        "elevation.1",
        "font.mono",
        "font.heading",
        "type.body",
        "type.caption"
      ],
      "keyboard": [
        {
          "keys": "Enter / Espaço",
          "action": "Ordena o cabeçalho."
        },
        {
          "keys": "Tab",
          "action": "Foca o link ou o botão da linha."
        },
        {
          "keys": "Enter",
          "action": "Abre a linha."
        }
      ],
      "screenReader": [
        "Tabela semântica com th scope=col.",
        "Use caption para nomear a tabela."
      ],
      "dos": [
        "Números à direita.",
        "ID em mono.",
        "Célula vazia fica vazia."
      ],
      "donts": [
        "Zebra.",
        "Centralizar números."
      ],
      "content": [
        "Cabeçalho curto, substantivo."
      ],
      "related": [
        "badge",
        "avatar",
        "empty-state",
        "pagination"
      ]
    },
    {
      "slug": "avatar",
      "name": "Avatar",
      "category": "data",
      "status": "beta",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Avatar",
        "AvatarPlaceholder",
        "avatarPalette",
        "avatarHue",
        "initials",
        "AvatarProps",
        "AvatarPlaceholderProps",
        "AvatarSize"
      ],
      "summary": "Iniciais em Sora sobre uma cor de token: Vivid Blue, Graffiti, success-ink, warning-ink ou danger-ink. A cor vem do e-mail, então a mesma pessoa tem sempre a mesma cor. Ninguém atribuído é tracejado.",
      "whenToUse": [
        "Pessoa responsável em lista, cartão, conta."
      ],
      "whenNotToUse": [
        "Empresa ou marca: use logo."
      ],
      "anatomy": [
        "Círculo na cor do token",
        "Iniciais Sora",
        "Brilho interno"
      ],
      "variants": [
        {
          "name": "xs · 20",
          "description": "Tabela densa."
        },
        {
          "name": "sm · 24",
          "description": "Padrão em lista."
        },
        {
          "name": "md · 32",
          "description": "Menu de conta."
        },
        {
          "name": "lg · 40",
          "description": "Perfil."
        }
      ],
      "states": [
        "com pessoa",
        "AvatarPlaceholder (ninguém)"
      ],
      "props": [
        {
          "name": "name",
          "type": "string | null",
          "description": "Nome para as iniciais."
        },
        {
          "name": "email",
          "type": "string | null",
          "description": "Chave da cor; fallback das iniciais."
        },
        {
          "name": "size",
          "type": "\"xs\" | \"sm\" | \"md\" | \"lg\"",
          "default": "\"sm\"",
          "description": "20 · 24 · 32 · 40."
        },
        {
          "name": "title",
          "type": "string",
          "description": "Tooltip; padrão é o nome ou e-mail."
        },
        {
          "name": "AvatarPlaceholder.title",
          "type": "string",
          "default": "\"Ninguém atribuído\"",
          "description": "Explica a ausência."
        }
      ],
      "tokens": [
        "font.heading",
        "color.primary",
        "color.graffiti",
        "color.successInk",
        "color.warningInk",
        "color.dangerInk",
        "color.muted"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "Avatar expõe o nome por title; ponha o nome em texto ao lado quando for essencial.",
        "AvatarPlaceholder é role=img com aria-label."
      ],
      "dos": [
        "Mesmo tamanho numa lista."
      ],
      "donts": [
        "Inventar pessoa quando não há.",
        "Cor manual."
      ],
      "content": [
        "title do placeholder diz o que fazer: \"Sem responsável — atribua alguém\"."
      ],
      "related": [
        "data-table"
      ]
    },
    {
      "slug": "metric-widget",
      "name": "MetricWidget",
      "category": "data",
      "status": "beta",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "MetricWidget",
        "Bar",
        "MetricWidgetProps",
        "BarProps",
        "MetricTone"
      ],
      "summary": "Métrica: rótulo de máquina, número em Sora tabular, contexto embaixo. O tom é luz, não faixa. Bar mostra proporção.",
      "whenToUse": [
        "Número-chave de painel com contexto.",
        "Progresso contra meta (Bar no footer)."
      ],
      "whenNotToUse": [
        "Série temporal: gráfico.",
        "Mais de 4 por linha."
      ],
      "anatomy": [
        "Ponto do tom + rótulo hb-label",
        "Valor 26–30 hb-num",
        "Delta mono",
        "Sub",
        "Rodapé opcional (Bar)"
      ],
      "states": [
        "sem tom",
        "com tom",
        "delta ok",
        "delta aviso"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "required": true,
          "description": "O que é medido."
        },
        {
          "name": "value",
          "type": "ReactNode",
          "required": true,
          "description": "Valor formatado pelo app."
        },
        {
          "name": "sub",
          "type": "ReactNode",
          "description": "Contexto."
        },
        {
          "name": "delta",
          "type": "{ label: string; ok: boolean } | null",
          "description": "Variação. ok=false pinta aviso, não perigo."
        },
        {
          "name": "tone",
          "type": "\"primary\" | \"secondary\" | \"success\" | \"warning\" | \"danger\"",
          "description": "Luz do cartão."
        },
        {
          "name": "footer",
          "type": "ReactNode",
          "description": "Área abaixo com divisor."
        },
        {
          "name": "Bar.value / Bar.max",
          "type": "number",
          "required": true,
          "description": "Proporção (limitada a 100%)."
        },
        {
          "name": "Bar.tone",
          "type": "MetricTone | \"muted\"",
          "default": "\"primary\"",
          "description": "Primário usa degradê Graffiti → Vivid Blue."
        },
        {
          "name": "Bar.label",
          "type": "ReactNode",
          "description": "Linha acima da barra."
        }
      ],
      "tokens": [
        "font.heading",
        "radius.xs",
        "color.successInk",
        "color.warningInk"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "Bar é role=meter com aria-valuenow em %.",
        "Leia rótulo e valor juntos; evite abreviações sem contexto."
      ],
      "dos": [
        "Valor com unidade.",
        "Delta curto: \"+4 pp\"."
      ],
      "donts": [
        "Delta ruim em danger.",
        "Faixa colorida no topo."
      ],
      "content": [
        "Rótulo curto, substantivo: \"Liquidado\", \"Custo\"."
      ],
      "related": [
        "card",
        "progress",
        "grid"
      ]
    },
    {
      "slug": "empty-state",
      "name": "EmptyState",
      "category": "feedback",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "EmptyState",
        "EmptyStateProps"
      ],
      "summary": "Vazio: a coruja vigia até ter o que mostrar. Sem ilustração genérica. Sempre que puder, um próximo passo. É o StatusView no tom neutro.",
      "whenToUse": [
        "Lista ou área sem dados.",
        "Resultado de filtro vazio.",
        "Primeiro uso."
      ],
      "whenNotToUse": [
        "Erro recuperável numa área: ErrorBanner.",
        "Esperando, aprovado ou recusado: StatusView com o tom certo."
      ],
      "anatomy": [
        "Halo azul radial",
        "Tile de papel com a coruja (ou ícone)",
        "Título Sora 15",
        "Descrição",
        "Ação"
      ],
      "variants": [
        {
          "name": "padrão",
          "description": "Área principal."
        },
        {
          "name": "compact",
          "description": "Dentro de tabela ou cartão."
        }
      ],
      "states": [
        "estático"
      ],
      "props": [
        {
          "name": "title",
          "type": "string",
          "required": true,
          "description": "O que está vazio."
        },
        {
          "name": "description",
          "type": "string",
          "description": "Por quê, ou o que fazer."
        },
        {
          "name": "action",
          "type": "ReactNode",
          "description": "Próximo passo."
        },
        {
          "name": "icon",
          "type": "ReactNode",
          "description": "Troca a coruja por um ícone."
        },
        {
          "name": "compact",
          "type": "boolean",
          "default": "false",
          "description": "Menos respiro."
        }
      ],
      "tokens": [
        "elevation.1",
        "font.heading",
        "color.muted"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Só a ação é focável."
        }
      ],
      "screenReader": [
        "role=status: anunciado quando aparece."
      ],
      "dos": [
        "Diga o próximo passo."
      ],
      "donts": [
        "\"Nenhum registro encontrado.\" sem saída."
      ],
      "content": [
        "Título: \"Nada por aqui ainda.\" Descrição: o que traz dado para cá."
      ],
      "related": [
        "status-view",
        "error-banner",
        "skeleton",
        "file-upload"
      ]
    },
    {
      "slug": "error-banner",
      "name": "ErrorBanner",
      "category": "feedback",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "ErrorBanner",
        "ErrorBannerProps"
      ],
      "summary": "Erro recuperável com a saída já montada: causa em linguagem humana e \"Tentar de novo\". É o Notice de perigo com o botão pronto.",
      "whenToUse": [
        "Falha ao carregar ou salvar uma área."
      ],
      "whenNotToUse": [
        "Erro de campo: use error no Input.",
        "Página inteira quebrada: StatusView danger.",
        "Aviso que não é falha: Notice."
      ],
      "anatomy": [
        "Ícone de alerta em tile danger",
        "Mensagem",
        "Tentar de novo (opcional)"
      ],
      "states": [
        "sem ação",
        "com ação"
      ],
      "props": [
        {
          "name": "message",
          "type": "string",
          "required": true,
          "description": "Causa, na língua da pessoa."
        },
        {
          "name": "onRetry",
          "type": "() => void",
          "description": "Mostra o botão de tentar de novo."
        },
        {
          "name": "retryLabel",
          "type": "string",
          "default": "\"Tentar de novo\"",
          "description": "Rótulo do botão."
        }
      ],
      "tokens": [
        "color.danger",
        "color.dangerInk",
        "radius.lg"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca Tentar de novo."
        }
      ],
      "screenReader": [
        "role=alert: anunciado na hora."
      ],
      "dos": [
        "Diga a causa."
      ],
      "donts": [
        "Código técnico sem tradução."
      ],
      "content": [
        "\"A chave foi recusada pelo provedor.\""
      ],
      "related": [
        "notice",
        "status-view",
        "toast"
      ]
    },
    {
      "slug": "spinner",
      "name": "Spinner",
      "category": "feedback",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Spinner",
        "SpinnerProps"
      ],
      "summary": "Arco curto em currentColor, para dentro de um botão ou ao lado de um texto.",
      "whenToUse": [
        "Ação curta dentro de botão (automático com loading).",
        "Indicador pequeno ao lado de texto."
      ],
      "whenNotToUse": [
        "Carregando lista: Skeleton.",
        "Agente trabalhando: HibouMark working.",
        "Espera de tela: StatusView working."
      ],
      "anatomy": [
        "Trilho 20% de opacidade",
        "Arco de 90°"
      ],
      "states": [
        "girando"
      ],
      "props": [
        {
          "name": "label",
          "type": "string",
          "description": "Nome acessível quando está sozinho (vira role=status)."
        },
        {
          "name": "className",
          "type": "string",
          "description": "Tamanho e cor (text-*)."
        }
      ],
      "tokens": [
        "color.primary"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "Sem label: aria-hidden.",
        "Com label: role=status."
      ],
      "dos": [
        "label quando sozinho."
      ],
      "donts": [
        "Spinner de página inteira."
      ],
      "content": [
        "label: \"Carregando pagamentos\"."
      ],
      "related": [
        "button",
        "skeleton",
        "hibou-mark",
        "progress",
        "status-view"
      ]
    },
    {
      "slug": "skeleton",
      "name": "Skeleton",
      "category": "feedback",
      "status": "beta",
      "since": "0.1.0",
      "package": "@hiboupay/react",
      "exports": [
        "Skeleton",
        "SkeletonCard",
        "SkeletonRows",
        "SkeletonMetric"
      ],
      "summary": "A forma da peça que ainda não chegou. Raio, altura e etiqueta iguais aos da peça real. Sempre aria-hidden; quem carrega anuncia.",
      "whenToUse": [
        "Lista, tabela ou cartão carregando."
      ],
      "whenNotToUse": [
        "Ação curta: Button loading."
      ],
      "anatomy": [
        "Espelha a peça que anuncia: linha 48 da tabela, cartão 16, etiqueta raio 6",
        "Bloco wash com shimmer",
        "Nunca pílula"
      ],
      "variants": [
        {
          "name": "Skeleton",
          "description": "Bloco livre (dê altura e largura)."
        },
        {
          "name": "SkeletonCard",
          "description": "Cartão com título Sora 16 e etiqueta raio 6."
        },
        {
          "name": "SkeletonRows",
          "description": "Linhas de 48 (36 no denso), a altura da tabela."
        },
        {
          "name": "SkeletonMetric",
          "description": "Métrica com barra."
        }
      ],
      "states": [
        "shimmer (desliga com reduced-motion)"
      ],
      "props": [
        {
          "name": "className",
          "type": "string",
          "description": "Tamanho e raio do bloco."
        },
        {
          "name": "SkeletonRows.rows",
          "type": "number",
          "default": "6",
          "description": "Quantidade de linhas."
        }
      ],
      "tokens": [
        "color.wash",
        "motion.ease",
        "radius.xs",
        "radius.lg",
        "type.title",
        "type.body"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "aria-hidden. Marque o contêiner com aria-busy ou use Spinner com label."
      ],
      "dos": [
        "Mesma forma do conteúdo final."
      ],
      "donts": [
        "Skeleton genérico que não lembra o conteúdo."
      ],
      "content": [
        "—"
      ],
      "related": [
        "spinner",
        "empty-state"
      ]
    },
    {
      "slug": "hibou-mark",
      "name": "HibouMark",
      "category": "brand",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/icons",
      "exports": [
        "HibouMark",
        "HibouMarkProps",
        "OWL",
        "OWL_STOPS"
      ],
      "summary": "O símbolo oficial, com o traço exato do imagotipo. Ocioso ele pisca a cada 6 s; trabalhando ganha órbita. É o ícone do agente.",
      "whenToUse": [
        "Representar o agente.",
        "Vazio (EmptyState).",
        "Marca compacta no trilho da navegação."
      ],
      "whenNotToUse": [
        "Decoração repetida.",
        "Ícone genérico de IA."
      ],
      "anatomy": [
        "Contêiner",
        "SVG da coruja (degradê ou currentColor)",
        "Órbita (working)"
      ],
      "variants": [
        {
          "name": "tone brand",
          "description": "Degradê oficial sobre papel."
        },
        {
          "name": "tone current",
          "description": "Herda a cor do texto: noite, botão, ícone."
        }
      ],
      "states": [
        "parado",
        "idle (pisca)",
        "working (órbita)"
      ],
      "props": [
        {
          "name": "tone",
          "type": "\"brand\" | \"current\"",
          "default": "\"brand\"",
          "description": "Degradê oficial ou cor do texto."
        },
        {
          "name": "state",
          "type": "\"idle\" | \"working\"",
          "description": "Sem estado fica parado."
        },
        {
          "name": "title",
          "type": "string",
          "description": "Nome acessível. Sem title é decorativa."
        },
        {
          "name": "className",
          "type": "string",
          "description": "Tamanho (h-* w-*)."
        }
      ],
      "tokens": [
        "color.primary"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "Sem title: aria-hidden.",
        "Com title: role=img nomeada."
      ],
      "dos": [
        "working enquanto o agente age."
      ],
      "donts": [
        "Redesenhar, esticar ou recolorir fora do degradê.",
        "Usar Sparkle ou robô no lugar."
      ],
      "content": [
        "title: \"Agente trabalhando\"."
      ],
      "related": [
        "wordmark",
        "empty-state"
      ]
    },
    {
      "slug": "wordmark",
      "name": "Wordmark",
      "category": "brand",
      "status": "stable",
      "since": "0.1.0",
      "package": "@hiboupay/icons",
      "exports": [
        "Wordmark",
        "WordmarkProps",
        "HIBOU",
        "PAY"
      ],
      "summary": "Imagotipo oficial: coruja + \"hibou\" + \"pay\". \"pay\" é sempre Vivid Blue; \"hibou\" é preto no claro e branco no escuro.",
      "whenToUse": [
        "Topo da navegação.",
        "Login, e-mail, documento."
      ],
      "whenNotToUse": [
        "Espaço menor que 96px de largura: HibouMark."
      ],
      "anatomy": [
        "Coruja em degradê",
        "\"hibou\" em tinta",
        "\"pay\" em Vivid Blue"
      ],
      "variants": [
        {
          "name": "onLight",
          "description": "\"hibou\" preto."
        },
        {
          "name": "onDark",
          "description": "\"hibou\" branco."
        }
      ],
      "states": [
        "estático"
      ],
      "props": [
        {
          "name": "onDark",
          "type": "boolean",
          "default": "false",
          "description": "Fundo escuro."
        },
        {
          "name": "title",
          "type": "string",
          "default": "\"HibouPay\"",
          "description": "Nome acessível."
        },
        {
          "name": "className",
          "type": "string",
          "description": "Altura (h-*); largura segue a proporção."
        }
      ],
      "tokens": [
        "brand.vividBlue",
        "brand.black",
        "brand.white"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Se for link, o link recebe o foco."
        }
      ],
      "screenReader": [
        "role=img com aria-label \"HibouPay\"."
      ],
      "dos": [
        "Respiro mínimo da altura da coruja em volta."
      ],
      "donts": [
        "Trocar a cor de \"pay\".",
        "Aplicar sobre foto sem scrim."
      ],
      "content": [
        "—"
      ],
      "related": [
        "hibou-mark"
      ]
    },
    {
      "slug": "checkbox",
      "name": "Checkbox",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Checkbox",
        "CheckboxProps"
      ],
      "summary": "A mesma marca do FilterChip: papel com anel fino, azul preenchido com check branco. Independente ou em lote. Traço quando só alguns filhos estão marcados.",
      "whenToUse": [
        "Aceitar um termo no formulário.",
        "Marcar linhas ou filhos de um grupo.",
        "Preferência que não é ligar/desligar um sistema (isso é Switch)."
      ],
      "whenNotToUse": [
        "Uma entre poucas opções exclusivas: Radio.",
        "Ligar uma configuração: Switch.",
        "Filtrar lista: FilterChip."
      ],
      "anatomy": [
        "Caixa 16px, raio 5",
        "Check branco ou traço (indeterminate)",
        "Rótulo Inter 14 à direita"
      ],
      "states": [
        "off",
        "on",
        "indeterminate",
        "focus-visible (anel azul)",
        "disabled"
      ],
      "props": [
        {
          "name": "label",
          "type": "ReactNode",
          "description": "Texto clicável à direita da marca."
        },
        {
          "name": "indeterminate",
          "type": "boolean",
          "default": "false",
          "description": "Traço. Use quando alguns filhos estão marcados."
        },
        {
          "name": "checked",
          "type": "boolean",
          "description": "Controlado."
        },
        {
          "name": "onChange",
          "type": "ChangeEventHandler",
          "description": "Nativo. Para controlado, leia e.target.checked."
        }
      ],
      "tokens": [
        "color.primary",
        "radius.sm",
        "motion.quick"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca a caixa."
        },
        {
          "keys": "Espaço",
          "action": "Liga ou desliga."
        }
      ],
      "screenReader": [
        "input checkbox nativo. Rótulo associado por id.",
        "indeterminate é anunciado pelo sistema."
      ],
      "dos": [
        "Rótulo que afirma o que fica marcado: \"Enviar comprovante por e-mail\"."
      ],
      "donts": [
        "Checkbox sozinho sem rótulo visível.",
        "Usar para on/off de produto (Switch)."
      ],
      "content": [
        "Frase curta, sem ponto. Evite \"Clique aqui\"."
      ],
      "related": [
        "radio",
        "switch",
        "filter-chip"
      ]
    },
    {
      "slug": "radio",
      "name": "Radio",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "RadioGroup",
        "Radio",
        "RadioGroupProps",
        "RadioProps"
      ],
      "summary": "Uma entre poucas. Círculo da mesma família do FilterChip single. fieldset + legend em rótulo de máquina.",
      "whenToUse": [
        "2 a 5 opções exclusivas no formulário: método, prazo, tom.",
        "Quando todas as opções precisam aparecer ao mesmo tempo."
      ],
      "whenNotToUse": [
        "Lista longa: Select ou FilterChip.",
        "Ligar/desligar: Switch.",
        "Duas vistas: Tabs."
      ],
      "anatomy": [
        "fieldset com legend (hb-label)",
        "Círculo 16px",
        "Ponto branco interno quando ativo",
        "Rótulo Inter 14"
      ],
      "states": [
        "off",
        "on",
        "focus-visible",
        "disabled"
      ],
      "props": [
        {
          "name": "RadioGroup.name",
          "type": "string",
          "required": true,
          "description": "name nativo compartilhado."
        },
        {
          "name": "RadioGroup.value",
          "type": "string",
          "description": "Controlado."
        },
        {
          "name": "RadioGroup.onValueChange",
          "type": "(value: string) => void",
          "description": "Nova escolha."
        },
        {
          "name": "RadioGroup.label",
          "type": "ReactNode",
          "description": "Legend visível."
        },
        {
          "name": "Radio.value",
          "type": "string",
          "required": true,
          "description": "Valor desta opção."
        },
        {
          "name": "Radio.children",
          "type": "ReactNode",
          "description": "Rótulo da opção."
        }
      ],
      "tokens": [
        "color.primary",
        "radius.pill",
        "motion.quick"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Entra no grupo."
        },
        {
          "keys": "↑ ↓",
          "action": "Troca a opção."
        }
      ],
      "screenReader": [
        "radiogroup nativo via fieldset. Cada Radio é input radio."
      ],
      "dos": [
        "Mostre 2–5. A opção padrão deve ser a mais segura, não a mais lucrativa."
      ],
      "donts": [
        "Radio para aceitar termo (Checkbox).",
        "Esconder opções atrás de \"ver mais\"."
      ],
      "content": [
        "Rótulos paralelos: \"PIX\", \"Boleto\", \"Cartão\"."
      ],
      "related": [
        "checkbox",
        "select",
        "switch"
      ]
    },
    {
      "slug": "switch",
      "name": "Switch",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Switch",
        "SwitchProps"
      ],
      "summary": "Liga ou desliga uma configuração. Trilho com raio da escala: apagado em papel com anel Graffiti, aceso em Vivid Blue com luz interna. Thumb de papel.",
      "whenToUse": [
        "Preferência persistente: aviso por e-mail, modo compacto.",
        "Um bit. O efeito é imediato."
      ],
      "whenNotToUse": [
        "Escolher entre A e B: Radio.",
        "Filtrar lista: FilterChip.",
        "Ação com efeito irreversível: ConfirmGate."
      ],
      "anatomy": [
        "Trilho 44×24, raio 8",
        "Thumb 16 de papel, raio 5",
        "kicker mono opcional",
        "Rótulo Inter 14"
      ],
      "states": [
        "off",
        "on",
        "focus-visible",
        "disabled"
      ],
      "props": [
        {
          "name": "checked",
          "type": "boolean",
          "description": "Controlado."
        },
        {
          "name": "onCheckedChange",
          "type": "(checked: boolean) => void",
          "description": "Novo valor."
        },
        {
          "name": "label",
          "type": "ReactNode",
          "description": "O que muda quando liga."
        },
        {
          "name": "kicker",
          "type": "string",
          "description": "Rótulo de máquina acima do texto."
        },
        {
          "name": "disabled",
          "type": "boolean",
          "default": "false",
          "description": "Não muda."
        }
      ],
      "tokens": [
        "color.primary",
        "color.graffiti",
        "radius.sm",
        "motion.strike",
        "motion.pupil"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca."
        },
        {
          "keys": "Espaço / Enter",
          "action": "Liga ou desliga."
        }
      ],
      "screenReader": [
        "role=switch com aria-checked. label associado por id."
      ],
      "dos": [
        "Rótulo descreve o estado ligado: \"Receber aviso de liquidação\"."
      ],
      "donts": [
        "Switch que pede confirmação depois. Se precisa de gate, é botão + ConfirmGate."
      ],
      "content": [
        "Afirmação, não pergunta. Sem \"Ativar…\" genérico."
      ],
      "related": [
        "checkbox",
        "radio"
      ]
    },
    {
      "slug": "dropdown-menu",
      "name": "DropdownMenu",
      "category": "overlay",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "DropdownMenu",
        "DropdownMenuTrigger",
        "DropdownMenuContent",
        "DropdownMenuItem",
        "DropdownMenuLabel",
        "DropdownMenuSeparator",
        "DropdownMenuCheckboxItem",
        "DropdownMenuRadioGroup",
        "DropdownMenuRadioItem",
        "DropdownMenuItemProps"
      ],
      "summary": "Menu de vidro no desktop; folha de papel no celular. Item 34 (40 no toque), perigo em tinta rosa. Nunca é navegação e nunca é filtro.",
      "whenToUse": [
        "Ações secundárias de uma linha ou de um botão ícone.",
        "Exportar, atribuir, abrir detalhe, excluir (este último abre ConfirmGate)."
      ],
      "whenNotToUse": [
        "Filtrar lista: FilterChip.",
        "Navegar entre páginas: links.",
        "Formulário: Select."
      ],
      "anatomy": [
        "Trigger (quase sempre Button)",
        "Popover hb-glass + hb-lens a partir de md",
        "Folha hb-sheet com scrim abaixo de md",
        "Label mono",
        "Item com ícone opcional e hint mono",
        "Separador",
        "Item com marca (check ou rádio)"
      ],
      "variants": [
        {
          "name": "popover (md+)",
          "description": "Vidro com pálpebra, alinhado ao gatilho."
        },
        {
          "name": "folha (< md)",
          "description": "Papel que sobe, a mesma gramática do Modal. Itens com altura de controle."
        }
      ],
      "states": [
        "fechado (120ms)",
        "aberto (pálpebra, 280ms)",
        "folha aberta",
        "highlighted (papel 80%)",
        "disabled",
        "danger"
      ],
      "props": [
        {
          "name": "DropdownMenu.open / onOpenChange",
          "type": "boolean / (open) => void",
          "description": "Controlado. Base Radix."
        },
        {
          "name": "DropdownMenuContent.align",
          "type": "\"start\" | \"center\" | \"end\"",
          "default": "\"end\"",
          "description": "Alinhamento do popover. A folha ignora e ocupa a largura."
        },
        {
          "name": "DropdownMenuItem.icon",
          "type": "ReactNode",
          "description": "Ícone de 16 em muted, à esquerda. Não decore todo item."
        },
        {
          "name": "DropdownMenuItem.tone",
          "type": "\"default\" | \"danger\"",
          "default": "\"default\"",
          "description": "Perigo em danger-ink. Quase sempre abre ConfirmGate."
        },
        {
          "name": "DropdownMenuItem.hint",
          "type": "string",
          "description": "Atalho ou metadado em mono à direita."
        },
        {
          "name": "DropdownMenuCheckboxItem.checked",
          "type": "boolean",
          "description": "Marca da família ChoiceMark."
        }
      ],
      "tokens": [
        "radius.lg",
        "radius.xl",
        "glass.base.blur",
        "color.dangerInk",
        "control.md",
        "motion.calm"
      ],
      "keyboard": [
        {
          "keys": "Enter / Espaço",
          "action": "Abre."
        },
        {
          "keys": "↑ ↓",
          "action": "Percorre itens."
        },
        {
          "keys": "Home / End",
          "action": "Primeiro e último item."
        },
        {
          "keys": "Enter",
          "action": "Ativa o item."
        },
        {
          "keys": "Esc",
          "action": "Fecha."
        }
      ],
      "screenReader": [
        "menu / menuitem (Radix). Item perigoso precisa de rótulo que diga a ação."
      ],
      "dos": [
        "Uma ação por item, verbo no infinitivo.",
        "Excluir no fim, separado, tone danger."
      ],
      "donts": [
        "Menu com 15 itens. Quebre ou use Command no app.",
        "Ícones decorativos em todo item."
      ],
      "content": [
        "\"Exportar CSV\", \"Atribuir responsável\", \"Excluir cobrança\"."
      ],
      "related": [
        "button",
        "filter-chip",
        "tooltip",
        "confirm-gate"
      ]
    },
    {
      "slug": "pagination",
      "name": "Pagination",
      "category": "data",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Pagination",
        "PaginationProps"
      ],
      "summary": "Intervalo em Sora tabular e duas setas no rodapé da lista. No estreito o texto sai da vista e fica no leitor.",
      "whenToUse": [
        "Rodapé de DataTable ou lista longa.",
        "Quando a pessoa precisa saber onde está (1–20 de 240)."
      ],
      "whenNotToUse": [
        "Poucos itens: mostre tudo.",
        "Carregar mais no scroll (isso é do app, não do Core)."
      ],
      "anatomy": [
        "Texto hb-num: intervalo e total",
        "Select de tamanho quando há opções",
        "Campo mono para saltar de página",
        "Botão ícone anterior",
        "Botão ícone próximo"
      ],
      "variants": [
        {
          "name": "compacta",
          "description": "Abaixo de md o intervalo fica só para o leitor. As setas continuam."
        },
        {
          "name": "com salto",
          "description": "Input mono \"Ir para a página\" quando a lista é longa."
        }
      ],
      "states": [
        "meio",
        "primeira (anterior disabled)",
        "última (próxima disabled)",
        "vazia (\"Nenhum\")",
        "carregando (setas desabilitadas, aria-busy)"
      ],
      "props": [
        {
          "name": "page",
          "type": "number",
          "required": true,
          "description": "Página atual, 1-based."
        },
        {
          "name": "pageSize",
          "type": "number",
          "required": true,
          "description": "Itens por página."
        },
        {
          "name": "total",
          "type": "number",
          "required": true,
          "description": "Total de itens."
        },
        {
          "name": "onPageChange",
          "type": "(page: number) => void",
          "required": true,
          "description": "Nova página."
        },
        {
          "name": "noun",
          "type": "{ one: string; many: string }",
          "required": true,
          "description": "one: \"pagamento\". many: \"pagamentos\"."
        },
        {
          "name": "pageSizeOptions",
          "type": "number[]",
          "description": "Quando passa, um Select troca o tamanho."
        },
        {
          "name": "onPageSizeChange",
          "type": "(pageSize: number) => void",
          "description": "Novo tamanho. Volte a página para 1 no app."
        },
        {
          "name": "jump",
          "type": "boolean",
          "default": "false",
          "description": "Mostra o campo para ir a uma página."
        },
        {
          "name": "loading",
          "type": "boolean",
          "default": "false",
          "description": "Desabilita as setas e marca aria-busy."
        }
      ],
      "tokens": [
        "control.sm",
        "font.heading",
        "font.mono",
        "type.compact"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca as setas."
        },
        {
          "keys": "Enter / Espaço",
          "action": "Vai."
        }
      ],
      "screenReader": [
        "nav aria-label Paginação. O intervalo tem aria-live, mesmo quando some no estreito.",
        "Setas com aria-label Página anterior / Próxima página."
      ],
      "dos": [
        "pageSize estável (20 ou 50).",
        "Vazio é EmptyState na tabela; a paginação diz \"Nenhum\"."
      ],
      "donts": [
        "Pílulas 1 2 3 4 … 99.",
        "Escrever \"N/A\" quando total é 0."
      ],
      "content": [
        "one no singular e many no plural, minúsculos: \"pagamento\" / \"pagamentos\"."
      ],
      "related": [
        "data-table",
        "empty-state"
      ]
    },
    {
      "slug": "progress",
      "name": "Progress",
      "category": "feedback",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Progress",
        "ProgressProps",
        "ProgressTone"
      ],
      "summary": "Trilha wash. Com número, o corpo é Graffiti e a ponta é Vivid Blue. Indeterminado: a coruja trabalha e a barra desliza.",
      "whenToUse": [
        "Upload, importação, job do agente com progresso conhecido.",
        "Espera longa sem número: indeterminate + label."
      ],
      "whenNotToUse": [
        "Ação curta: Button loading / Spinner.",
        "Proporção numa métrica: Bar do MetricWidget.",
        "Lista carregando: Skeleton."
      ],
      "anatomy": [
        "Label + coruja (indeterminate)",
        "% em hb-num (determinado)",
        "Trilha 6px wash, ou n trilhos quando há etapas",
        "Preenchimento em degradê da marca",
        "Ponta Vivid Blue, apagada quando concluído"
      ],
      "variants": [
        {
          "name": "linear",
          "description": "Uma trilha. O padrão."
        },
        {
          "name": "com etapas",
          "description": "N trilhos com gap 4, para importação em lotes. O valor 0–100 preenche em ordem."
        }
      ],
      "states": [
        "0%",
        "parcial",
        "100%",
        "concluído (barra em success-ink, ponta apagada)",
        "indeterminate (órbita + slide)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "default": "0",
          "description": "0–100. Ignorado se indeterminate."
        },
        {
          "name": "indeterminate",
          "type": "boolean",
          "default": "false",
          "description": "Sem número. A coruja entra em working."
        },
        {
          "name": "label",
          "type": "ReactNode",
          "description": "O que está acontecendo."
        },
        {
          "name": "segments",
          "type": "number",
          "description": "Quantidade de trilhos. Ausente = um."
        },
        {
          "name": "tone",
          "type": "\"primary\" | \"success\"",
          "default": "\"primary\"",
          "description": "success só pinta a barra concluída (100%). Antes disso segue o degradê."
        }
      ],
      "tokens": [
        "color.primary",
        "color.graffiti",
        "color.successInk",
        "radius.pill",
        "motion.slow"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Não é interativo."
        }
      ],
      "screenReader": [
        "role=progressbar. indeterminate liga aria-busy e omite aria-valuenow.",
        "Coruja com title \"Agente trabalhando\"."
      ],
      "dos": [
        "Label concreto: \"Lendo 1.204 linhas\"."
      ],
      "donts": [
        "Progresso circular. Isso é Spinner.",
        "Animação se a pessoa pediu reduced-motion no app (respeite)."
      ],
      "content": [
        "Verbo no gerúndio: \"Lendo\", \"Enviando\", \"Aplicando\"."
      ],
      "related": [
        "spinner",
        "file-upload",
        "metric-widget",
        "hibou-mark"
      ]
    },
    {
      "slug": "file-upload",
      "name": "FileUpload",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "FileUpload",
        "FileUploadProps"
      ],
      "summary": "Zona rebaixada, anel tracejado, coruja vigiando. No arraste ela trabalha. Arquivo vira linha de papel com tamanho mono e X. Sem nuvem genérica.",
      "whenToUse": [
        "Importar planilha, comprovante, anexo único ou poucos arquivos."
      ],
      "whenNotToUse": [
        "Galeria de mídia. Campo de texto. Arrastar para mudar ordem (não é este componente)."
      ],
      "anatomy": [
        "Label",
        "Zona sunken com coruja idle/working",
        "Título Sora + dica",
        "Lista de arquivos em papel",
        "Linha de arquivo com Progress",
        "Mensagem de erro ou hint"
      ],
      "states": [
        "vazia",
        "arraste (anel azul, coruja working)",
        "com arquivos",
        "enviando",
        "erro (anel danger)",
        "disabled"
      ],
      "props": [
        {
          "name": "files",
          "type": "File[]",
          "required": true,
          "description": "Arquivos aceitos."
        },
        {
          "name": "onChange",
          "type": "(files: File[]) => void",
          "required": true,
          "description": "Nova lista."
        },
        {
          "name": "accept",
          "type": "string",
          "description": "accept nativo. Ex.: .csv,.xlsx."
        },
        {
          "name": "multiple",
          "type": "boolean",
          "default": "false",
          "description": "Vários arquivos."
        },
        {
          "name": "maxSize",
          "type": "number",
          "description": "Limite em bytes. O que passa não entra e vira erro."
        },
        {
          "name": "progress",
          "type": "Record<string, number>",
          "description": "0–100 por arquivo. A chave é nome-tamanho."
        },
        {
          "name": "renderFile",
          "type": "(file: File) => ReactNode",
          "description": "Substitui o miolo da linha. O remover continua."
        },
        {
          "name": "emptyTitle",
          "type": "string",
          "default": "\"Solte o arquivo aqui\"",
          "description": "Título da zona vazia."
        },
        {
          "name": "emptyDescription",
          "type": "string",
          "default": "\"ou clique para escolher\"",
          "description": "Apoio."
        },
        {
          "name": "error",
          "type": "string",
          "description": "Erro externo. Substitui o hint."
        }
      ],
      "tokens": [
        "radius.lg",
        "color.primary",
        "color.danger",
        "elevation.0"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca o botão da zona."
        },
        {
          "keys": "Enter / Espaço",
          "action": "Abre o seletor."
        }
      ],
      "screenReader": [
        "input file sr-only ligado ao label.",
        "Remover tem aria-label \"Remover {nome}\"."
      ],
      "dos": [
        "accept e maxSize explícitos no hint.",
        "Enquanto sobe, progress na linha do arquivo.",
        "disabled esmaece só a zona, não o texto da lista."
      ],
      "donts": [
        "Ícone de nuvem.",
        "Aceitar qualquer tipo e recusar depois sem dizer o porquê."
      ],
      "content": [
        "hint: \"CSV ou XLSX até 10 MB\". emptyTitle fala o objeto: \"Solte a planilha\"."
      ],
      "related": [
        "progress",
        "empty-state",
        "error-banner"
      ]
    },
    {
      "slug": "toast",
      "name": "Toast",
      "category": "feedback",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "ToastProvider",
        "useToast",
        "ToastTone",
        "ToastInput",
        "ToastPosition"
      ],
      "summary": "Aviso de vidro. Na mesa, canto inferior direito. No celular, topo, sob a barra. Tom é um ponto de luz, não uma faixa. Some sozinho. Não decide por ninguém.",
      "whenToUse": [
        "Confirmar que algo já aconteceu: \"Planilha importada\".",
        "Oferecer um desfazer leve (action)."
      ],
      "whenNotToUse": [
        "Erro que bloqueia a tarefa: ErrorBanner no lugar.",
        "Ação irreversível: ConfirmGate antes, não toast depois como se fosse pergunta.",
        "Validação de campo: Input error."
      ],
      "anatomy": [
        "Viewport no canto ou no topo",
        "Cartão hb-glass + hb-lens",
        "Ponto de tom",
        "Título Sora",
        "Descrição",
        "Ação opcional",
        "Fechar"
      ],
      "variants": [
        {
          "name": "mesa (canto inferior direito)",
          "description": "Entra pela direita. Não cobre o dock porque o dock é do celular."
        },
        {
          "name": "celular (topo, sob a barra)",
          "description": "Entra de cima, com safe-area. O polegar continua livre embaixo."
        },
        {
          "name": "default",
          "description": "Ponto Vivid Blue. Aviso neutro."
        },
        {
          "name": "success",
          "description": "Ponto verde. Concluído."
        },
        {
          "name": "warning",
          "description": "Ponto âmbar. Delta ruim, a tela segue."
        },
        {
          "name": "danger",
          "description": "Ponto rosa. Falhou, mas a tela segue."
        }
      ],
      "states": [
        "entrando (opacidade, depois o deslocamento)",
        "visível",
        "pausado (hover ou foco)",
        "fechado"
      ],
      "props": [
        {
          "name": "ToastProvider.position",
          "type": "\"bottom-right\" | \"top\"",
          "description": "Força o lugar. Sem isto, o celular usa o topo."
        },
        {
          "name": "useToast().push",
          "type": "(t: ToastInput) => id",
          "description": "Empilha. Máximo 3. Some em 5s se duration omitido."
        },
        {
          "name": "ToastInput.title",
          "type": "string",
          "required": true,
          "description": "O que aconteceu."
        },
        {
          "name": "ToastInput.description",
          "type": "string",
          "description": "Apoio curto."
        },
        {
          "name": "ToastInput.tone",
          "type": "\"default\" | \"success\" | \"warning\" | \"danger\"",
          "default": "\"default\"",
          "description": "Cor do ponto. warning é aviso; danger é falha."
        },
        {
          "name": "ToastInput.action",
          "type": "{ label, onClick }",
          "description": "Desfazer ou abrir. Pausa o timer enquanto o foco está no cartão."
        },
        {
          "name": "ToastInput.duration",
          "type": "number",
          "default": "5000",
          "description": "ms. 0 = não some sozinho. Hover e foco pausam a contagem."
        }
      ],
      "tokens": [
        "radius.lg",
        "glass.base.blur",
        "color.success",
        "color.warning",
        "color.danger",
        "motion.quick"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Ação e fechar são focáveis."
        }
      ],
      "screenReader": [
        "role=status. Não use alert — toast não interrompe."
      ],
      "dos": [
        "Frase no passado: \"Cobrança atribuída\".",
        "Uma ação no máximo."
      ],
      "donts": [
        "Toast de erro no lugar de ErrorBanner.",
        "Empilhar 8 toasts.",
        "Faixa colorida no topo do cartão."
      ],
      "content": [
        "Título sem ponto. Descrição só se o título não baste."
      ],
      "related": [
        "error-banner",
        "tooltip"
      ]
    },
    {
      "slug": "tooltip",
      "name": "Tooltip",
      "category": "overlay",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Tooltip",
        "TooltipProvider",
        "TooltipProps"
      ],
      "summary": "Chip Graffiti com seta, 12px, atraso de 400ms. Entra só por opacidade. Explica o que já está na tela. Nunca carrega a regra.",
      "whenToUse": [
        "Ícone sem texto (aria-label no gatilho + tooltip de apoio).",
        "Expandir um ID ou um atalho."
      ],
      "whenNotToUse": [
        "Informação essencial: coloque na tela.",
        "Erro: Input error ou ErrorBanner.",
        "Menu de ações: DropdownMenu."
      ],
      "anatomy": [
        "Gatilho (asChild)",
        "Chip graffiti com seta, texto branco e atalho mono"
      ],
      "states": [
        "oculto",
        "visível após 400ms",
        "visível no foco",
        "no toque: não aparece"
      ],
      "props": [
        {
          "name": "content",
          "type": "ReactNode",
          "required": true,
          "description": "Texto curto."
        },
        {
          "name": "children",
          "type": "ReactNode",
          "required": true,
          "description": "Gatilho. Precisa aceitar ref (asChild)."
        },
        {
          "name": "side",
          "type": "\"top\" | \"right\" | \"bottom\" | \"left\"",
          "default": "\"top\"",
          "description": "Lado preferido."
        },
        {
          "name": "shortcut",
          "type": "string",
          "description": "Atalho em mono, à direita do texto."
        },
        {
          "name": "delay",
          "type": "number",
          "default": "400",
          "description": "ms até abrir. O Provider também usa 400."
        }
      ],
      "tokens": [
        "color.graffiti",
        "radius.sm",
        "elevation.2"
      ],
      "keyboard": [
        {
          "keys": "Tab / foco",
          "action": "Mostra."
        },
        {
          "keys": "Esc",
          "action": "Esconde."
        }
      ],
      "screenReader": [
        "O gatilho precisa de nome (aria-label ou texto). No toque o tooltip não abre: o nome do gatilho é o contrato."
      ],
      "dos": [
        "Uma linha, até ~12 palavras.",
        "Botão ícone sempre com aria-label, tooltip é extra."
      ],
      "donts": [
        "Tooltip em texto corrido.",
        "Tooltip com botão dentro."
      ],
      "content": [
        "Sem ponto final. \"ID da cobrança\", \"Atalho ⌘K\"."
      ],
      "related": [
        "dropdown-menu",
        "button"
      ]
    },
    {
      "slug": "grid",
      "name": "Grid",
      "category": "surface",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Grid",
        "GridItem",
        "GridProps",
        "GridItemProps",
        "GridColumns",
        "GridCols",
        "GridGap"
      ],
      "summary": "1 a 6 colunas. Gap da escala (8 · 12 · 16 · 24 · 32) e os cortes da margem (md 768, xl 1280).",
      "whenToUse": [
        "Fila de MetricWidget.",
        "Cartões lado a lado.",
        "Dois campos no mesmo andar de um formulário."
      ],
      "whenNotToUse": [
        "Tabela: DataTable.",
        "Empilhar Grid dentro de Grid mais de uma vez.",
        "Inventar gap fora da escala."
      ],
      "anatomy": [
        "Contêiner display:grid",
        "Colunas base / md / xl",
        "Gap da escala",
        "Alinhamento dos itens",
        "GridItem com span, mdSpan e xlSpan"
      ],
      "variants": [
        {
          "name": "1",
          "description": "Pilha. Celular, formulário estreito."
        },
        {
          "name": "2 / 3 / 4",
          "description": "Métricas e cartões."
        },
        {
          "name": "6",
          "description": "Só para peças miúdas (avatares, chips). Quase nunca."
        }
      ],
      "states": [
        "estático"
      ],
      "props": [
        {
          "name": "columns",
          "type": "1|2|3|4|6 | { base, md?, xl? }",
          "default": "1",
          "description": "md = 768, xl = 1280 — os mesmos da gutter."
        },
        {
          "name": "gap",
          "type": "2 | 3 | 4 | 6 | 8",
          "default": "4",
          "description": "8 · 12 · 16 · 24 · 32 px."
        },
        {
          "name": "align",
          "type": "\"start\" | \"center\" | \"stretch\"",
          "default": "\"stretch\"",
          "description": "Alinhamento vertical dos itens."
        },
        {
          "name": "GridItem.span",
          "type": "1 | 2 | 3 | 4 | 6",
          "description": "Largura em colunas na base."
        },
        {
          "name": "GridItem.mdSpan / xlSpan",
          "type": "1 | 2 | 3 | 4 | 6",
          "description": "Largura nos cortes."
        }
      ],
      "tokens": [
        "space.2",
        "space.3",
        "space.4",
        "space.6",
        "space.8",
        "gutter.md",
        "gutter.xl"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Layout. O foco mora nos filhos."
        }
      ],
      "screenReader": [
        "É um div. Não anuncie a grade; anuncie o conteúdo."
      ],
      "dos": [
        "No celular, base: 1. Métricas: { base: 1, md: 2, xl: 3 }.",
        "gap 4 (16) entre cartões, gap 6 (24) entre seções."
      ],
      "donts": [
        "12 colunas, offset, pull/push.",
        "gap-5 (20) ou gap arbitrário em px."
      ],
      "content": [
        "—"
      ],
      "related": [
        "card",
        "metric-widget"
      ]
    },
    {
      "slug": "choice-card",
      "name": "ChoiceCard",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "ChoiceCardGroup",
        "ChoiceCard",
        "ChoiceCardGroupProps",
        "ChoiceCardProps"
      ],
      "summary": "Escolha que precisa mostrar o preço da decisão. É o Radio quando a opção não cabe numa linha: ícone, título, explicação e o total no pé. Marca no canto, luz azul quando ativo.",
      "whenToUse": [
        "Forma de pagamento no checkout.",
        "Condição de parcelamento com valor e total.",
        "Adicional opcional com preço (seguro, garantia)."
      ],
      "whenNotToUse": [
        "Opção que cabe numa linha: Radio.",
        "Aceitar um termo: Checkbox.",
        "Lista longa: Select.",
        "Filtrar uma tabela: FilterChip."
      ],
      "anatomy": [
        "fieldset com legend (hb-label)",
        "Cartão de papel, raio 16",
        "Ícone opcional em tile",
        "Título type.lead",
        "Etiqueta Badge opcional",
        "Descrição",
        "Rodapé separado por linha fina",
        "ChoiceMark no canto superior direito"
      ],
      "variants": [
        {
          "name": "radio",
          "description": "Uma entre poucas. Padrão."
        },
        {
          "name": "multiple",
          "description": "Vários adicionais ao mesmo tempo. A marca vira check."
        }
      ],
      "states": [
        "off",
        "on (papel azul + anel)",
        "hover",
        "focus-visible",
        "disabled",
        "invalid"
      ],
      "props": [
        {
          "name": "ChoiceCardGroup.name",
          "type": "string",
          "required": true,
          "description": "name nativo compartilhado."
        },
        {
          "name": "ChoiceCardGroup.multiple",
          "type": "boolean",
          "default": "false",
          "description": "Troca radio por checkbox; value vira string[]."
        },
        {
          "name": "ChoiceCardGroup.value",
          "type": "string | string[]",
          "description": "Controlado. Array quando multiple."
        },
        {
          "name": "ChoiceCardGroup.onValueChange",
          "type": "(value: string | string[]) => void",
          "description": "Nova escolha."
        },
        {
          "name": "ChoiceCardGroup.columns",
          "type": "1 | 2 | { base, md }",
          "default": "1",
          "description": "Uma ou duas colunas. Objeto troca no corte md do contêiner."
        },
        {
          "name": "ChoiceCardGroup.invalid",
          "type": "boolean",
          "default": "false",
          "description": "Grupo obrigatório sem escolha. aria-invalid no fieldset."
        },
        {
          "name": "ChoiceCardGroup.message",
          "type": "string",
          "description": "Mensagem em danger-ink, ligada por aria-describedby."
        },
        {
          "name": "ChoiceCard.value",
          "type": "string",
          "required": true,
          "description": "Valor desta opção."
        },
        {
          "name": "ChoiceCard.title",
          "type": "ReactNode",
          "required": true,
          "description": "A decisão, em uma linha."
        },
        {
          "name": "ChoiceCard.badge",
          "type": "ReactNode",
          "description": "Etiqueta \"Mais barata\" ou \"Recomendada\" com Badge. Nunca pílula."
        },
        {
          "name": "ChoiceCard.description",
          "type": "ReactNode",
          "description": "O que muda se escolher."
        },
        {
          "name": "ChoiceCard.footer",
          "type": "ReactNode",
          "description": "Total, prazo ou condição, separado por linha fina."
        },
        {
          "name": "ChoiceCard.icon",
          "type": "ReactNode",
          "description": "Marca do meio de pagamento ou do adicional."
        }
      ],
      "tokens": [
        "color.primary",
        "color.dangerInk",
        "radius.lg",
        "elevation.1",
        "motion.quick",
        "type.lead"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Entra no grupo."
        },
        {
          "keys": "↑ ↓",
          "action": "Troca a opção (radio)."
        },
        {
          "keys": "Espaço",
          "action": "Marca (radio e multiple) ou desmarca (multiple)."
        }
      ],
      "screenReader": [
        "input radio ou checkbox nativo dentro de label. O cartão inteiro é o alvo.",
        "Grupo inválido: aria-invalid e aria-describedby na mensagem."
      ],
      "dos": [
        "Mostre o total junto da parcela — a pessoa decide com os dois números.",
        "Ordene da condição mais barata para a mais longa."
      ],
      "donts": [
        "Pré-selecionar a opção mais cara.",
        "Esconder taxa no rodapé em corpo menor que 12."
      ],
      "content": [
        "Título com o número que decide: \"12x R$ 223,04\". Rodapé com o total: \"Total R$ 2.676,48\"."
      ],
      "related": [
        "radio",
        "checkbox",
        "summary-list",
        "grid"
      ]
    },
    {
      "slug": "stepper",
      "name": "Stepper",
      "category": "feedback",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Stepper",
        "StepperProps",
        "Step",
        "StepStatus",
        "StepperOrientation"
      ],
      "summary": "Onde a pessoa está numa jornada de poucos passos. Concluído vira check e nunca volta a ser número. No horizontal estreito cabe só o número; no vertical a descrição fica.",
      "whenToUse": [
        "Checkout em etapas.",
        "Onboarding, cadastro ou KYC em mais de duas telas.",
        "Qualquer fluxo em que voltar é possível e o fim é conhecido."
      ],
      "whenNotToUse": [
        "Processo de duração desconhecida: Progress.",
        "Duas vistas do mesmo dado: Tabs.",
        "Mais de seis passos — quebre o fluxo."
      ],
      "anatomy": [
        "nav com ol",
        "Disco 32px por passo",
        "Conector que acende até o passo atual",
        "Rótulo opcional",
        "Descrição no vertical",
        "Resumo \"N de M\" só no horizontal estreito"
      ],
      "variants": [
        {
          "name": "horizontal",
          "description": "Discos em linha. Abaixo de md vira \"N de M · rótulo\"."
        },
        {
          "name": "vertical",
          "description": "Lista com descrição por passo. Serve onboarding e KYC."
        }
      ],
      "states": [
        "concluído (check azul)",
        "atual (azul com halo)",
        "pendente (wash)",
        "erro no passo (disco em danger)"
      ],
      "props": [
        {
          "name": "steps",
          "type": "Step[]",
          "required": true,
          "description": "{ id, label?, description?, status? }. Sem label vira só o número."
        },
        {
          "name": "current",
          "type": "number",
          "required": true,
          "description": "Índice base 0. Tudo antes está concluído, salvo status error."
        },
        {
          "name": "orientation",
          "type": "\"horizontal\" | \"vertical\"",
          "default": "\"horizontal\"",
          "description": "Vertical mostra a descrição e não some no celular."
        },
        {
          "name": "onStepClick",
          "type": "(index: number) => void",
          "description": "Só o passo concluído vira botão. Pendente nunca é botão."
        },
        {
          "name": "label",
          "type": "string",
          "default": "\"Progresso\"",
          "description": "Nome da jornada para o leitor de tela."
        },
        {
          "name": "Step.status",
          "type": "\"complete\" | \"current\" | \"upcoming\" | \"error\"",
          "description": "error pinta o disco em danger-ink. KYC recusado."
        },
        {
          "name": "Step.description",
          "type": "string",
          "description": "Uma linha sob o rótulo, no vertical."
        }
      ],
      "tokens": [
        "color.primary",
        "color.dangerInk",
        "radius.pill",
        "control.md",
        "motion.calm"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Só chega no passo concluído, quando há onStepClick."
        },
        {
          "keys": "Enter / Espaço",
          "action": "Volta ao passo concluído."
        }
      ],
      "screenReader": [
        "nav nomeada, ol de passos. O passo atual tem aria-current=\"step\".",
        "Cada passo declara concluído, atual, pendente ou com erro em texto oculto."
      ],
      "dos": [
        "Rótulo com substantivo: \"Endereço\", \"Pagamento\".",
        "No celular horizontal, só o resumo. Vertical quando cada passo precisa de descrição."
      ],
      "donts": [
        "Deixar o passo pendente clicável.",
        "Contar passos que a pessoa não controla (processamento)."
      ],
      "content": [
        "\"Etapa 2 de 4\" no título da página; o Stepper mostra, não repete."
      ],
      "related": [
        "progress",
        "tabs",
        "status-view"
      ]
    },
    {
      "slug": "notice",
      "name": "Notice",
      "category": "feedback",
      "status": "stable",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Notice",
        "NoticeProps",
        "NoticeTone"
      ],
      "summary": "Aviso preso ao conteúdo, nos quatro tons. Tom aparece como preenchimento e tinta — nunca como faixa colorida no topo do cartão.",
      "whenToUse": [
        "Consentimento e termo legal antes de uma ação.",
        "Garantia ao lado de dado sensível: \"seus dados estão protegidos\".",
        "Alerta que precisa ficar na tela enquanto durar a condição."
      ],
      "whenNotToUse": [
        "Confirmação efêmera de algo que deu certo: Toast.",
        "Falha com \"tentar de novo\": ErrorBanner.",
        "Bloquear uma ação com dinheiro: ConfirmGate."
      ],
      "anatomy": [
        "Superfície tingida com anel fino",
        "Ícone do tom em tile",
        "Título opcional",
        "Corpo",
        "Ação opcional à direita"
      ],
      "variants": [
        {
          "name": "info",
          "description": "Contexto, consentimento, regra. Azul."
        },
        {
          "name": "success",
          "description": "Garantia e proteção. Verde."
        },
        {
          "name": "warning",
          "description": "Condição que exige atenção agora. Âmbar."
        },
        {
          "name": "danger",
          "description": "Risco ou perda. Rosa. Vira role=alert."
        }
      ],
      "states": [
        "estático"
      ],
      "props": [
        {
          "name": "tone",
          "type": "\"info\" | \"success\" | \"warning\" | \"danger\"",
          "default": "\"info\"",
          "description": "danger é anunciado como alert."
        },
        {
          "name": "title",
          "type": "ReactNode",
          "description": "Uma linha em Sora."
        },
        {
          "name": "icon",
          "type": "ReactNode",
          "description": "Troca o ícone do tom. null remove."
        },
        {
          "name": "action",
          "type": "ReactNode",
          "description": "Um botão ou link à direita."
        }
      ],
      "tokens": [
        "color.primary",
        "color.successInk",
        "color.warningInk",
        "color.dangerInk",
        "radius.lg"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca a ação, se houver."
        }
      ],
      "screenReader": [
        "danger é role=alert. Os outros tons não interrompem a leitura."
      ],
      "dos": [
        "Diga a condição e o que fazer com ela.",
        "Consentimento com Checkbox dentro do Notice info."
      ],
      "donts": [
        "Três Notice empilhados na mesma tela.",
        "Notice para elogiar o produto."
      ],
      "content": [
        "\"Autorizo a consulta da minha margem consignável no eSocial.\" Cite a norma, não o processo interno."
      ],
      "related": [
        "error-banner",
        "toast",
        "confirm-gate",
        "checkbox"
      ]
    },
    {
      "slug": "summary-list",
      "name": "SummaryList",
      "category": "data",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "SummaryList",
        "SummaryListProps",
        "SummaryRow",
        "SummaryMaterial",
        "SummaryTone"
      ],
      "summary": "Resumo de uma decisão: rótulo à esquerda, valor tabular à direita, linha fina entre as duas. O total é a única linha que grita. Papel sozinho; flush dentro de outro cartão.",
      "whenToUse": [
        "Resumo do pedido antes de pagar.",
        "Condições da proposta: valor, parcela, primeiro desconto.",
        "Painel de detalhe de um registro."
      ],
      "whenNotToUse": [
        "Muitas linhas comparáveis com ordenação: DataTable.",
        "Um número em destaque: MetricWidget.",
        "Formulário editável: Field."
      ],
      "anatomy": [
        "Papel com raio 16, ou flush sem cartão",
        "Rótulo mono opcional no topo",
        "dl com linhas divididas",
        "Valor em hb-num alinhado à direita",
        "Tom success ou warning no valor",
        "hintValue na segunda linha à direita",
        "Linha de ênfase para o total"
      ],
      "variants": [
        {
          "name": "papel",
          "description": "Cartão próprio. O padrão."
        },
        {
          "name": "flush",
          "description": "Sem raio, sombra nem padding. Para dentro de Card ou Modal."
        }
      ],
      "states": [
        "estático",
        "carregando (Skeleton na coluna do valor)"
      ],
      "props": [
        {
          "name": "rows",
          "type": "SummaryRow[]",
          "required": true,
          "description": "{ label, value?, hint?, hintValue?, emphasis?, tone? }."
        },
        {
          "name": "title",
          "type": "ReactNode",
          "description": "Rótulo de máquina acima da lista."
        },
        {
          "name": "material",
          "type": "\"paper\" | \"flush\"",
          "default": "\"paper\"",
          "description": "flush tira o cartão."
        },
        {
          "name": "loading",
          "type": "boolean",
          "default": "false",
          "description": "Skeleton no lugar de cada valor."
        },
        {
          "name": "SummaryRow.hint",
          "type": "ReactNode",
          "description": "Segunda linha à esquerda: quantidade, prazo, identificador."
        },
        {
          "name": "SummaryRow.hintValue",
          "type": "ReactNode",
          "description": "Segunda linha à direita: \"12x\"."
        },
        {
          "name": "SummaryRow.tone",
          "type": "\"success\" | \"warning\"",
          "description": "Desconto é success. Taxa é warning. Sem danger."
        },
        {
          "name": "SummaryRow.emphasis",
          "type": "boolean",
          "default": "false",
          "description": "Fecha a conta. Use em uma linha só."
        }
      ],
      "tokens": [
        "elevation.1",
        "radius.lg",
        "font.heading",
        "color.muted",
        "color.successInk",
        "color.warningInk"
      ],
      "keyboard": [
        {
          "keys": "—",
          "action": "Texto. O foco mora nas ações em volta."
        }
      ],
      "screenReader": [
        "dl com dt e dd: o leitor lê rótulo e valor em par.",
        "Carregando: aria-busy na lista."
      ],
      "dos": [
        "Valor sempre com moeda e em pt-BR — use formatBRL.",
        "Uma linha de ênfase por lista."
      ],
      "donts": [
        "Célula vazia com \"—\" ou \"N/A\": deixe vazia.",
        "Três totais competindo pela mesma atenção."
      ],
      "content": [
        "Rótulo curto e substantivo: \"Valor solicitado\", \"Total a pagar\"."
      ],
      "related": [
        "data-table",
        "metric-widget",
        "choice-card"
      ]
    },
    {
      "slug": "slider",
      "name": "Slider",
      "category": "input",
      "status": "beta",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "Slider",
        "SliderProps"
      ],
      "summary": "Faixa contínua de valor. Trilho wash preenchido pelo degradê Graffiti → Vivid Blue, polegar de papel. O número atual fica visível o tempo todo.",
      "whenToUse": [
        "Quanto usar de um saldo: pontos, crédito, limite.",
        "Ajuste aproximado em que a pessoa reage ao resultado."
      ],
      "whenNotToUse": [
        "Valor exato que a pessoa já sabe: Input.",
        "Poucas opções discretas: Radio ou ChoiceCard.",
        "Ligar e desligar: Switch."
      ],
      "anatomy": [
        "Rótulo à esquerda e valor em azul à direita",
        "input range nativo com alvo de 40",
        "Trilho 6px com preenchimento até o valor",
        "Marcas de referência",
        "Polegar 16px de papel",
        "Input numérico opcional",
        "Legendas das pontas"
      ],
      "states": [
        "padrão",
        "arrastando",
        "focus-visible (anel azul no polegar)",
        "no limite (polegar com anel graffiti)",
        "disabled"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Controlado."
        },
        {
          "name": "onValueChange",
          "type": "(value: number) => void",
          "description": "Novo valor a cada passo."
        },
        {
          "name": "min / max / step",
          "type": "number",
          "default": "0 / 100 / 1",
          "description": "Faixa e granularidade."
        },
        {
          "name": "format",
          "type": "(value: number) => string",
          "description": "Como o número aparece. Padrão: pt-BR sem casas."
        },
        {
          "name": "minLabel / maxLabel",
          "type": "ReactNode",
          "description": "Legendas das pontas."
        },
        {
          "name": "marks",
          "type": "number[]",
          "description": "Traços de referência no trilho."
        },
        {
          "name": "input",
          "type": "boolean",
          "default": "false",
          "description": "Input numérico ao lado, mesma faixa e o mesmo valor."
        }
      ],
      "tokens": [
        "color.primary",
        "color.graffiti",
        "color.wash",
        "radius.pill",
        "control.md"
      ],
      "keyboard": [
        {
          "keys": "← →",
          "action": "Um passo."
        },
        {
          "keys": "Home / End",
          "action": "Mínimo e máximo."
        },
        {
          "keys": "PageUp / PageDown",
          "action": "Salto maior."
        }
      ],
      "screenReader": [
        "input range nativo: valor, mínimo e máximo anunciados. Rótulo associado por id."
      ],
      "dos": [
        "Mostre o valor formatado ao lado do rótulo.",
        "Deixe uma entrada exata por perto quando o valor importa no contrato."
      ],
      "donts": [
        "Slider como única forma de escolher valor de dinheiro.",
        "Faixa sem legenda de mínimo e máximo."
      ],
      "content": [
        "Rótulo diz o que o valor faz: \"Usar pontos\", não \"Selecione\"."
      ],
      "related": [
        "input",
        "progress",
        "switch"
      ]
    },
    {
      "slug": "status-view",
      "name": "StatusView",
      "category": "feedback",
      "status": "stable",
      "since": "0.2.0",
      "package": "@hiboupay/react",
      "exports": [
        "StatusView",
        "StatusViewProps",
        "StatusTone"
      ],
      "summary": "Tela inteira que só tem um estado para contar: vazio, esperando, aprovado ou falhou. Um desenho para os quatro; o tom troca o ícone no tile branco. EmptyState é o preset neutro.",
      "whenToUse": [
        "Espera de resultado que a pessoa não controla: análise, assinatura, liquidação.",
        "Fim de fluxo: aprovado ou recusado.",
        "Área sem dado (via EmptyState)."
      ],
      "whenNotToUse": [
        "Aviso dentro de uma tela cheia: Notice.",
        "Confirmação efêmera: Toast.",
        "Carregar um pedaço da tela: Skeleton."
      ],
      "anatomy": [
        "Tile de papel com a coruja ou ícone de tom",
        "Título Sora 15",
        "Descrição",
        "Ação",
        "Rodapé: barra de progresso, aviso, link de contrato"
      ],
      "variants": [
        {
          "name": "neutral",
          "description": "Vazio. A coruja vigia. É o EmptyState."
        },
        {
          "name": "working",
          "description": "Esperando. A coruja trabalha e a tela vira aria-busy."
        },
        {
          "name": "success",
          "description": "Aprovado."
        },
        {
          "name": "danger",
          "description": "Recusado ou falhou."
        }
      ],
      "states": [
        "neutral",
        "working",
        "success",
        "danger"
      ],
      "props": [
        {
          "name": "tone",
          "type": "\"neutral\" | \"working\" | \"success\" | \"danger\"",
          "default": "\"neutral\"",
          "description": "Troca halo e ícone; working marca aria-busy."
        },
        {
          "name": "title",
          "type": "string",
          "required": true,
          "description": "O que está acontecendo, em uma frase."
        },
        {
          "name": "description",
          "type": "string",
          "description": "Por quê, ou o que fazer agora."
        },
        {
          "name": "action",
          "type": "ReactNode",
          "description": "Próximo passo. Tela sem saída é bug."
        },
        {
          "name": "footer",
          "type": "ReactNode",
          "description": "Progress, aviso de não fechar a janela, link do contrato."
        },
        {
          "name": "compact",
          "type": "boolean",
          "default": "false",
          "description": "Menos respiro, para dentro de cartão ou tabela."
        }
      ],
      "tokens": [
        "elevation.1",
        "font.heading",
        "color.muted",
        "color.success",
        "color.dangerInk"
      ],
      "keyboard": [
        {
          "keys": "Tab",
          "action": "Foca a ação e o que estiver no rodapé."
        }
      ],
      "screenReader": [
        "role=status. working adiciona aria-busy para a espera ser anunciada."
      ],
      "dos": [
        "Na espera, diga quanto tempo leva e o que não fazer.",
        "No fim, ofereça o documento e o caminho de volta."
      ],
      "donts": [
        "Espera sem saída nenhuma.",
        "\"Erro inesperado\" sem causa nem próximo passo."
      ],
      "content": [
        "\"Confirmando sua autorização. Isso leva só um instante.\" Aviso de não fechar a janela vai no rodapé."
      ],
      "related": [
        "empty-state",
        "progress",
        "notice",
        "stepper"
      ]
    }
  ]
}