A primeira dobra não é um botão: é um campo. Olho, pergunta em duas linhas, uma frase de apoio e, logo abaixo, uma caixa de texto grande com um disco de envio ancorado no canto e três chips de intenção embaixo — "Organizar minha carteira", "Planejar a sucessão", "Vender minha empresa". Sob o campo, a ressalva. Quem já sabe o que quer, escreve; quem não sabe, clica num chip e cai na mesma conversa com o assunto já declarado. O formulário longo fica para depois, quando houver motivo para pedir nome e telefone.
O que sustenta a dobra é ela funcionar sem JavaScript. O bloco é um <form method="post"> de verdade: o disco é type="submit" e cada chip é um <button type="submit" name="intencao" value="…"> — o navegador monta o envio com o par nome/valor do botão acionado, e foi assim que se mediu, com o JavaScript desligado. O script.js faz duas melhorias e nada mais: cresce a altura da caixa conforme o texto e anuncia o contador quando falta pouco para o maxlength. Tire o script e a dobra continua inteira; ele não escuta submit, não valida e não trava nada.
Compliance
Três coisas, e as três são forma, não só texto.
1. A ressalva é slot exigido. É o único slot obrigatório desta dobra, e diz três coisas nesta ordem: a conversa não é recomendação de investimento; não substitui a análise de perfil exigida na abertura de conta; e não se escreve dado sensível ali — CPF, número de conta, senha, saldo. Ela veste a primitiva .nota do core, fica ao lado do campo, onde a pessoa escreve, e não no rodapé — e o aria-describedby do <textarea> aponta para ela, de modo que quem usa leitor de tela recebe o aviso ao entrar no campo, não depois de enviar. Medido: a ressalva sai em --fg-muted a 12.5px com 5.74:1 sobre o pior pixel do fundo com foto e 6.05:1 sem foto — acima do mínimo de 4.5:1 para texto normal.
Um campo aberto numa primeira dobra é um convite a escrever o que vier. Sem a ressalva, uma porta de conversa vira captação de dado sensível sem aviso, e a resposta do assessor do outro lado vira, na leitura de quem escreveu, uma recomendação.
2. O anexo fica desligado, e está escrito por quê. O original anexa uma foto; o equivalente aqui seria extrato ou carteira — dado pessoal sensível, de terceiros inclusive (cônjuge, herdeiros, sócios). O <label class="cnv-anexo"> com o <input type="file"> está escrito e comentado no markup.html, com quatro perguntas que precisam de resposta antes de descomentar:
| Pergunta | Por que ela trava o campo |
|---|---|
| O site tem backend para receber arquivo? | Um <input type="file"> num formulário que ninguém processa é um campo que promete e descarta. E exige enctype="multipart/form-data" no <form>, que este markup não declara justamente por isso. |
| Qual a base legal da LGPD? | Consentimento ou legítimo interesse mudam o que a tela precisa dizer, e o aviso vai ao lado do campo, não no rodapé. |
| O canal é seguro do envio ao armazenamento? | TLS, bucket privado, acesso nominal. Anexo de carteira caindo numa caixa de e-mail compartilhada do comercial não é. |
| Qual o prazo de retenção, e quem apaga? | Dado que ninguém sabe apagar é dado guardado para sempre. |
Enquanto as quatro não tiverem dono, a conversa começa por texto: é mais barato pedir o documento depois, por um canal preparado, do que guardar o que não se sabe proteger. Está como variação experimental no componente.json de propósito.
3. method="post", nunca get. Com get, o texto escrito vai para a barra de endereço, para o histórico do navegador, para o Referer do próximo pedido e para o log do servidor. Numa assessoria, a primeira frase costuma trazer o assunto patrimonial inteiro — "vou vender minha empresa em 2027". Isso não pode virar URL. E a copy de exemplo não promete retorno, não cita rentabilidade e não nomeia instituição: os três chips falam de organizar, planejar e vender, que são serviços, não resultados.
Quando usar
- Primeira dobra de assessoria, consultoria ou escritório de planejamento, onde o que se vende é conversa e a objeção real é "será que o meu caso é caso para vocês?". A pergunta na cara e um campo embaixo respondem isso sem pedir nada em troca.
- Quando a casa tem quem leia o que chega. A peça promete leitura humana no apoio ("um assessor lê, responde por e-mail"); se do outro lado houver só um autoresponder, a dobra mente na primeira frase.
- Quando existem duas ou três portas de entrada nomeáveis — os chips. Eles são o atalho de quem não quer escrever, e é por eles que a maioria entra no celular.
- Quando o destino do
actionsabe rotear por intenção. O parintencao=planejar-sucessaosó vale se alguém o lê: uma página de conversa, um CRM, uma fila de atendimento. - Quando o projeto precisa de uma dobra que funcione sem JavaScript — página servida por Elementor, bloco colado dentro de um CMS alheio, ou simplesmente um site que não pode perder contato porque um bundle falhou.
Quando não usar
- Quando o próximo passo é um formulário qualificado, com nome, e-mail, telefone e faixa de capital. É
conversao/cta-formulario-lead— o irmão mais próximo em papel, e ele ganha sempre que o comercial precisa do contato antes da conversa: quatro campos num card de vidro, com a lista de benefícios ao lado sustentando o pedido. Este hero pede uma frase; aquele pede um lead. Os dois convivem bem na mesma página, um abrindo e outro fechando. - Quando a pessoa precisa descobrir algo antes de falar com alguém. É
conversao/diagnostico-perfil, cinco perguntas fechadas que devolvem um perfil — e é o destino natural deste hero, não o concorrente dele. Um campo aberto não devolve nada na hora; se a promessa é "descubra agora", é a ferramenta que ganha. - Quando existe uma foto que carrega a dobra sozinha — imóvel, pessoa, lugar. É
hero/full-bleed-media, que sangra a mídia e ancora o texto embaixo. Aqui a foto é atmosfera a 34% de opacidade e some atrás do scrim: quem tem uma imagem boa está desperdiçando-a. - Quando o argumento é a promessa e a prova, não a pergunta. É
hero/centrado-prova-social: painel recuado, promessa em duas linhas, prova social e um botão. A diferença de fundo é o verbo: lá a dobra afirma, aqui ela pergunta. - Quando o produto precisa aparecer na primeira dobra — é
hero/duas-colunas-produto; ou quando a abertura é atmosfera em movimento, e aí éhero/slideshow-cinematicoouhero/video-fundo. - No meio ou no fim da página. O bloco abre 100vh e assume que nada veio antes. Uma chamada de fecho com campo é outra peça.
Nenhum dos outros cinco heroes da casa é "campo primeiro", e é essa a vaga que este ocupa: os cinco terminam num <a class="btn"> que leva a pessoa para outro lugar. Aqui a ação acontece na própria dobra.
Padrão editorial
| Slot | Regra |
|---|---|
| Olho | 2 a 4 palavras. O que a casa é, não o que promete: "Assessoria de investimentos". A promessa é a pergunta. Opcional. |
Pergunta (h1) |
5 a 9 palavras, uma pergunta aberta terminada em "?", quebrada em duas linhas por <br> no markup. Enunciado que não é pergunta deixa a caixa sem assunto. A linha mais longa tem de caber em ~92% de --cnv-max — medido: 660px dentro de 720 a 1440. |
| Apoio | 14 a 28 palavras. O que acontece depois de enviar: quem lê, em quanto tempo, e quanto custa, mesmo que seja nada. Não repete a pergunta. |
| Rótulo do campo | 1 a 3 palavras. Sai em caixa alta de 10.5px pela primitiva .field. Não é instrução — a instrução é o placeholder. |
Exemplo (placeholder) |
7 a 12 palavras, um caso concreto na voz de quem escreve: "herdei uma carteira e não sei por onde começar". Nunca "digite sua mensagem". O exemplo ensina o tamanho e o tom da resposta esperada. Sem número, sem valor, sem nome de instituição. Teto medido: ~60 caracteres — acima disso a frase não cabe nas duas linhas do campo a 390px e corta no meio. |
Rótulo do disco (aria-label) |
2 a 7 palavras. O disco não tem texto visível: é a única coisa que o leitor de tela anuncia. Diz a ação e o destino. |
| Chips | 2 a 4 palavras cada, três (dois funcionam). Primeira pessoa de quem chega, em paralelismo: verbo no infinitivo + objeto nos três. O value vai em kebab-case, é o que o destino roteia e não é copy. |
| Ressalva | 25 a 45 palavras. Exigida. Ver Compliance. |
| Frases do contador | Duas, em data-cnv-rot-faltam e data-cnv-rot-limite, com {n} no lugar do número. Só o leitor de tela as recebe. |
| Atributos do rodapé | 3 itens de 4 a 7 palavras, do mesmo tamanho — a fileira é centrada e um item longo desequilibra a linha. Fato verificável (registro, modelo de remuneração, público), nunca adjetivo e nunca número de resultado. Opcional. |
O que mantém a dobra coesa é a pergunta e os chips serem a mesma frase em dois níveis de esforço: a pergunta é aberta, os chips são as três respostas mais comuns a ela. Se um chip não responde à pergunta do h1, ele vira um menu, e aí a caixa de texto passa a parecer o campo "outros".
Especificação dos assets
Um só, e opcional: a foto de fundo.
- Formato e dimensão mínima: WebP paisagem, 1600×900 no mínimo. Ela cobre a dobra inteira com
object-fit:cover. - Peso alvo: até 90 KB. Está acima da dobra e compete com a fonte pelo primeiro quadro.
- Composição: enquadramento aberto e vazio no centro — a pergunta e o campo ocupam os 720px centrais. Paisagem, interior amplo, horizonte. O
object-position:50% 38%puxa o interesse para cima da caixa. - O que não pode ter: rosto reconhecível em primeiro plano (a 34% de opacidade vira um borrão que o olho persegue), texto, marca, linha de alto contraste cortando o centro, e qualquer imagem que precise ser vista — aqui ela é atmosfera, não assunto.
- Sem foto, a dobra fica melhor em contraste (17.39:1 contra 14.48:1). A imagem é decisão de tom, não de legibilidade.
Como usar
<link rel="stylesheet" href="componentes/hero/campo-de-conversa/estilo.css">
<script src="componentes/hero/campo-de-conversa/script.js" defer></script>
Do core precisa de tokens.css, base.css (pelas primitivas .wrap, .field, .btn-disc, .nota, .visually-hidden, .display-xl, .sec-lead, .eyebrow, .grain) e do par motion.css/motion.js, que é quem faz a entrada.
Antes de publicar, três linhas do markup:
action="conversa"→ o endpoint real. Ele tem de tratar dois envios: o do disco (mensagempreenchida) e o dos chips (mensagemvazia +intencao).- O
placeholdere os trêsvaluedos chips, que são o vocabulário da casa. - A ressalva, revisada por quem responde por compliance no cliente.
Ganchos
| Gancho | Papel |
|---|---|
[data-cnv] |
A seção. O script parte daqui, nunca do documento, e aceita mais de uma na página. |
[data-cnv-chips="preencher"] |
Na seção. Liga a variação em que o chip preenche o campo em vez de submeter. |
[data-cnv-form] |
No <form>. Marcação de leitura: o script não escuta submit. |
[data-cnv-conta] |
A região viva do contador, com data-cnv-rot-faltam e data-cnv-rot-limite. {n} vira o número. |
.cnv.is-auto |
Estado que o script põe ao assumir a altura da caixa. É o que desliga a alça nativa de redimensionar. |
.cnv-arte / .cnv-arte-img / .cnv-scrim / .cnv-veu |
A arte de fundo, em bloco apagável. |
.cnv-title / .cnv-lead / .cnv-olho |
Pergunta, apoio e olho. |
.cnv-form / .cnv-slot / .cnv-campo / .cnv-linha |
O formulário, o invólucro de data-rv, o .field e a linha caixa + disco. |
.cnv-texto / .cnv-enviar / .cnv-seta |
A caixa, o disco (.btn-disc) e o ícone. |
.cnv-chips / .cnv-chip |
A fileira e cada atalho. |
.cnv-anexo / .cnv-anexo-ico / .cnv-anexo-txt |
Escritos no CSS, comentados no markup. Ver Compliance. |
.cnv-nota / .cnv-atrib |
A ressalva e o rodapé de atributos. |
Parafusos
| Variável | Padrão | O que faz |
|---|---|---|
--display-xl |
clamp(30px,4vw,60px) |
Corpo da pergunta. Parafuso da primitiva .display-xl, alimentado na raiz. Persiga a fração (~92% de --cnv-max na linha mais longa), não o número. |
--display-xl-lh |
1.04 |
Entrelinha da pergunta. O .95 padrão da primitiva serve a título de uma ou duas palavras, sem descendente para colidir. |
--cnv-texto |
clamp(17px,1.6vw,22px) |
Corpo do texto editável. É o maior texto editável da casa de propósito. |
--cnv-teto |
34vh (24vh no mobile) |
Teto de crescimento da caixa. O script lê este valor de volta do CSS — mudar aqui muda o limite real. |
--cnv-max |
720px |
Medida do bloco central: pergunta, apoio, campo e chips. Não é a coluna; a coluna continua sendo o .wrap. |
--disc-size |
clamp(44px,4vw,52px) no .cnv-enviar |
Parafuso da primitiva .btn-disc, que traz 42px. Aqui o disco não é seta de carrossel: é o botão principal da dobra. |
--nota-size / --nota-max |
12.5px / none aqui |
Parafusos da primitiva .nota. A medida é livre porque quem limita a linha é o bloco de 720px. |
Variações
- sem arte de fundo — apague o bloco
.cnv-arteinteiro. O contraste sobe (17.39:1 contra 14.48:1). - chip que preenche em vez de enviar —
data-cnv-chips="preencher"na seção. Medido: o clique escrevePlanejar a sucessão:no campo, põe o cursor no fim e não submete. Exige JavaScript; sem ele o mesmo markup volta a submeter. - sem rodapé de atributos — apague a
<ul class="cnv-atrib">. Nada se desloca. - dois chips — quando a casa só tem duas portas. Um chip só é um botão com nome estranho.
- com anexo — descomente o
.cnv-anexoe acrescenteenctype="multipart/form-data". Leia Compliance antes.
Gotchas
-
O campo é
requirede os chips sãoformnovalidate— sem isso os chips não funcionam. Os dois caminhos saem do mesmo<form>: a validação nativa barraria o chip por causa de um campo de texto vazio que o chip nem usa, e o navegador mostraria "Preencha este campo" apontando para uma caixa que a pessoa deliberadamente não quis preencher. Medido, com um ouvinte desubmite outro deinvalid: disco com campo vazio → 0 envios, 1 eventoinvalid; chip com campo vazio → envio, commensagem=eintencao=organizar-carteira; disco com texto → envio só commensagem. Quem tirar oformnovalidatequebra os três atalhos e não vê nada acusar. -
O script não envia nada, e isso é o oposto do
conversao/cta-formulario-lead. Lá oscript.jsintercepta osubmit, finge sucesso e trava o formulário — e a ficha dele avisa que publicar assim perde todos os leads em silêncio. Aqui não há o que ligar: quem envia é o navegador. Se o endpoint doactionestiver errado, a falha é visível na hora, que é o comportamento certo. -
Sem JavaScript a peça inteira funciona, e foi medido assim. Com
--sem-js: os 6 nós de entrada (data-rve.ttl) ficam em opacidade 1 pelo@media (scripting: none)do core, a raiz não recebe.is-auto, o<textarea>mantém a alça nativa de redimensionar (resize:vertical) — que é a única forma de ver um texto longo inteiro sem o crescimento automático — e cada chip entrega ao navegadormensagem=…mais o própriointencao=…. -
A alça de redimensionar e o crescimento automático não podem conviver. A alça guarda uma altura que o próximo caractere sobrescreveria, e a pessoa veria o campo desfazer o que ela arrastou. Por isso o CSS nasce com
resize:verticale só a regra.cnv.is-auto .cnv-texto{resize:none}— cuja classe o script põe — desliga a alça. A ordem importa: o script põe a classe antes do primeirocrescer(). -
O teto do crescimento mora no CSS e o script o lê de volta.
--cnv-tetoresolve emmax-height, e ocrescer()fazparseFloat(getComputedStyle(campo).maxHeight). Medido a 1440×900: caixa em repouso 64px (duas linhas de 22px/1.45); com 414 caracteres, 255px; com 828, 306px — o teto de 34vh — e o conteúdo (478px descrollHeight) passa a rolar por dentro. Se o número estivesse cravado no JavaScript, a media query do mobile (24vh) o deixaria mentindo. -
maxlengthnão limita o que chega por outro caminho, e o contador dizia "Faltam -228 caracteres". Apareceu na medição, escrevendo o valor por script: o atributo segura a digitação e a colagem, não a restauração de sessão nem o preenchimento automático. Orestam <= 0cai no rótulo de limite. É o tipo de defeito que só aparece medindo, porque digitando é impossível de reproduzir. -
O contador não fala a cada tecla, e isso é o ponto dele. Uma região
aria-liveque muda a cada caractere produz fala contínua sobre o que se está digitando: o leitor de tela passa a disputar com o eco do teclado e a digitação fica impossível. Dois freios: só abaixo de 60 caracteres restantes, e só de 20 em 20. Medido: 100 restantes → silêncio; 55 → "Faltam 55 caracteres."; 51 → nada de novo (mesmo degrau); 35 → "Faltam 35 caracteres."; 0 → "Limite de 600 caracteres atingido."; e apagar o texto limpa a região — sem isso o último aviso fica pendurado e pode ser relido ao reentrar no campo, dizendo "faltam 20" com o campo vazio. -
O
<button>nativo precisa debackground:noneeappearance:none, ou o chip fica cinza-claro.color-scheme:only light(tokens.css) faz o cromo do sistema pintar por baixo em toda parte, e o resultado é fundo#f0f0f0sob texto quase branco. O core registra o mesmo caso na primitiva.btn, medido noconversao/diagnostico-perfil;<a class="btn">nunca sofreu, e é por isso que o defeito passa despercebido — quase todo uso da primitiva é âncora. -
A régua do
.fieldcontinua acesa enquanto o disco tem o foco, e é de propósito. O disco vive dentro do.field, então o:focus-withinda primitiva não se apaga ao tabular da caixa para o botão: o campo continua lendo como uma coisa só. Medido:border-bottom-coloremrgb(198,206,170)— o accent do tema — com o foco na caixa e com o foco no disco. -
O foco visível é do core e não foi tocado. Medido nos três controles (caixa, disco, primeiro chip), tabulando de verdade:
solid 2px rgb(198,206,170)comoutline-offset:3px. A primitiva.fieldnão zera o anel — e a ficha do core registra que ela quase entrou zerando. -
A pergunta e o campo dividem a mesma medida, e o corpo da display foi calibrado por isso. A
--display-xla4.4vwdava uma primeira linha de 726px, 6px mais larga que o bloco de 720 do campo: a pergunta pendia para fora da caixa que ela apresenta. A4vwa mesma linha mede 660px, 91.7% do bloco. Quem trocar a copy ou a display do tema remede — a linha longa é a que manda, e acima de 100% ela quebra sozinha e viram três linhas, desfazendo o<br>. -
O olho saía sozinho na margem esquerda, e a culpa é da bloquificação. A primitiva
.eyebrowédisplay:inline-flex; como filho do.cnv-body, que é flex, ela é bloquificada — viraflexe passa a esticar na largura inteira da coluna (1096px a 1440), com o traço e o rótulo ancorados à esquerda. Otext-align:centerdo corpo não alcança: ele alinha texto, e ali dentro o que existe é uma caixa flex. A linha que resolve éalign-self:centerno.cnv-olho. Vale para qualquer primitivainline-*posta dentro de um contêiner flex. -
O apoio leva
text-wrap:balance, e a pergunta levainitial— os dois de propósito. Em três linhas, sem balance, a última fica órfã ("compromisso." sozinho no meio da dobra). Na pergunta é o contrário: balancear por cima de uma quebra decidida no<br>desfaz a quebra. -
O
text-wrap:initialna pergunta não é redundante. O reset do core dátext-wrap:balancea todoh1..h4, e balancear por cima de uma quebra decidida no<br>reintroduz exatamente a quebra automática que o<br>existe para evitar. A.display-xljá devolveinitial; a declaração fica repetida aqui porque quem trocar a primitiva por uma classe própria perderia a quebra em silêncio. -
O véu sobre a foto é
backdrop-filtercom máscara em gradiente (§6), e a camada inteira vive dentro de um@supports. Caixa reta produziria uma borda dura atravessando a imagem na horizontal, lida como "faixa chapada"; e ondebackdrop-filternão existe, sem o@supportssobraria um retângulo sem efeito nenhum — o scrim já basta sozinho. -
A foto é fundo, e o contraste foi medido pixel a pixel. Screenshot com o conteúdo escondido, decodificado fora do navegador: o pior pixel atrás da pergunta é
rgb(31,31,31), o que dá 14.48:1 com--fg; atrás do campo, 15.92:1; a ressalva em--fg-muted, 5.74:1. Sem a arte, os mesmos números sobem para 17.39:1 e 6.05:1. A pergunta é legível com e sem a imagem, que é o requisito. -
No mobile o
min-height:100vhvira0, e o teto da caixa cai para 24vh.100vhno celular conta com a barra do navegador recolhida, e a dobra fica alta demais; e com o teclado virtual aberto sobra cerca de 45% da tela — um campo de 34vh empurraria o disco de envio para debaixo do teclado. Medido a 390×844: sem estouro horizontal (390/390), seção de 940px, chips empilhados de borda a borda (350px cada) e teto da caixa em 202.56px. -
Os chips empilham no mobile em vez de quebrar a fileira. Três pílulas de 13.5px não cabem lado a lado em 390px, e a fileira centrada vira uma escada de larguras diferentes. Empilhados e esticados, eles viram três alvos de 46px de altura — que é o que se quer numa tela em que a maioria entra pelo atalho.
-
O
data-rvnunca divide nó comtransformpróprio (§5), e aqui isso aparece como o.cnv-slot. O invólucro leva odata-rv; o.fielde a caixa ficam por dentro. Nenhum elemento desta dobra éposition:fixed, então a contenção que oblur(0)do reveal cria não afeta nada — mas é a razão de o rodapé de atributos ser um irmão, e não um filho do formulário. -
No mobile o rodapé de atributos nasce abaixo da linha d'água e só entra com um rolar mínimo. A seção mede 940px numa tela de 844, e o
data-rvdele fica nos 10px finais — abaixo do limiar de 0.16 do observador do core. É o comportamento normal do gancho, não um defeito: quem rola um dedo vê a entrada. Quem quiser os três atributos garantidos na primeira tela apaga a arte e encurta o apoio.
Movimento reduzido / toque
Movimento reduzido desliga tudo pelo core: medido com --reduce, os seis nós de entrada ficam em opacity:1, filter:none, transform:none. Não há o que desligar no script — a caixa cresce sem transição, no mesmo quadro da tecla, porque campo que cresce animado atrasa o cursor em relação ao que se digita. Por isso o script.js não consulta LIB.reduce: não há nada andando sozinho.
Toque. Nada depende de hover: o hover do chip é acabamento (tinta e borda), e os três alvos — caixa, disco e chips — nascem visíveis e clicáveis. No celular os chips ficam com 46px de altura e largura cheia, e o disco com 44px, que é o piso de alvo de toque. O <textarea> abre o teclado nativo, e é por isso que o teto cai para 24vh: o que não pode acontecer é o disco de envio ficar debaixo do teclado.
Teclado. A ordem de tabulação é a ordem da leitura: caixa → disco → chip 1 → chip 2 → chip 3. Cada um é um <button> de verdade, com Enter e Espaço nativos. Dentro da caixa, Enter quebra linha — não envia —, o que é o comportamento certo para um campo em que se escreve uma frase inteira.
Histórico
| Projeto | Onde | Data | Diferenças |
|---|---|---|---|
| referência: skinboost-design-review.vercel.app | dobra #inicio — hero com campo e chips |
2026-09-21 | referência visual, não origem de código |
Origem. Escrito do zero a partir da observação da primeira dobra de skinboost-design-review.vercel.app. O original roda three.js, GSAP/ScrollTrigger, ícones Phosphor e assets de Figma, e nada disso atravessa (§11): a stack da casa é HTML+CSS+JS vanilla, sem lib. O que veio de lá foi a ordem de leitura — pergunta, campo, atalhos — e a proporção entre a headline e a caixa. A referência está registrada em projetos/referencias-externas.md.
O que mudou na tradução:
- O assunto, e com ele o compliance. Skincare virou assessoria de investimentos. Entrou a ressalva que o original não tem nem precisa ter, como slot exigido, vestindo a primitiva
.notae apontada peloaria-describedbydo campo. - O anexo saiu de cena. O original pede uma foto; aqui seria extrato ou carteira. Ficou escrito e comentado, com as quatro perguntas de LGPD no próprio markup. Ver Compliance.
- O envio deixou de depender de JavaScript.
<form method="post">, disco e chips como<button type="submit">,formnovalidatenos chips. Medido com o JS desligado. poste nãoget, para a frase de quem escreve não virar URL, histórico e log.- Lib → nada. As três camadas de fundo são dois gradientes, um
backdrop-filtermascarado e o.graindo core. Sem WebGL, sem imagem de efeito, sem GSAP. - Cor crua → token. Fundo, scrim, bordas e tinta leem
--dark-rgb,--rule,--rule-2,--accente--fg-*. O único#000do arquivo está dentro de umamask-image, onde o valor é opacidade e não cor. - Tipografia própria → primitivas do core. A pergunta é
.display-xl(com os dois parafusos), o apoio é.sec-lead, o campo é.field, o disco é.btn-disc, a ressalva é.notae o contador é.visually-hidden. Este arquivo não reescreve nenhuma delas: alimenta parafusos e escreve margem, medida e alinhamento. - Coreografia por lib → ganchos do core.
.ttlna pergunta edata-rv/data-dnos quatro blocos, com o blur que o §5 exige — nada entra seco. - Acessibilidade que o original não tinha: contador em
aria-live="polite"com dois freios,aria-labelno disco,aria-describedbyligando o campo à ressalva, foco visível medido nos três controles e alvos de 44–46px no toque.
Divergências conhecidas vs. a referência:
- A fonte não atravessa (§11). A dobra sai na
--display/--sansdo tema. - A foto é placeholder. O preview usa
showroom/demo/ph-wide-4.webp(sala de reunião vazia com vista). O asset real é uma paisagem ou interior amplo, vazio no centro — ver Especificação dos assets. - Não há fundo animado. O original tem uma cena WebGL atrás do campo. Aqui o fundo é estático de propósito: movimento contínuo atrás de uma caixa de texto compete com o cursor, e a WCAG 2.2.2 exigiria um botão de pausa para uma decoração que não informa nada.
- Os chips submetem, e no original eles preenchem. As duas rotas existem (ver a variação
data-cnv-chips="preencher"), e a padrão é a que sobrevive sem JavaScript.