← Biblioteca componentes/hero/centrado-prova-social/ficha.md CódigoTela cheia
hero/centrado-prova-social

Hero centrado com prova social

🟢 estavel complexidade média prefixo pitch- hero above-the-fold centrado sem-imagem prova-social avatares coreografia palavra-a-palavra painel-recuado cta-unico saas produto-digital escuro

Incluir · as linhas que se colam num site novo, depois do core (CLAUDE.md §10)

<link rel="stylesheet" href="componentes/hero/centrado-prova-social/estilo.css">
<script src="componentes/hero/centrado-prova-social/script.js"></script>

markup.html · 89 linhas · 4,5 KB

<!-- ==========================================================================
     HERO CENTRADO COM PROVA SOCIAL — painel recuado, uma promessa, um botão
     Prefixo: pitch-
     Requer: core (tokens, base, motion.css) + estilo.css e script.js

     O QUE É. Um hero sem foto. Em vez de mídia, um painel escuro recuado das
     bordas da página, com canto arredondado e um fio de borda, e dentro dele
     quatro coisas empilhadas no centro: a prova social, a promessa, o apoio e
     um botão. Nada mais. É o hero de produto — o que convence não é a imagem,
     é a frase.

     PAINEL, NÃO SANGRIA. A seção é full-bleed e o painel vive 16px para dentro
     dela. Esse fio de fundo aparecendo em volta é o que faz a página parecer
     um aplicativo e não um site — e é a diferença entre esta dobra e o
     hero/full-bleed-media, que sangra a foto até a borda.

     A COREOGRAFIA É O COMPONENTE. Quatro tempos, e a ordem importa: a prova
     social entra primeiro (por que confiar), a promessa vem palavra a palavra
     (o que é), o apoio a segue (como funciona) e o botão estoura por último
     (o que fazer). Os tempos estão no estilo.css e são os da referência.

     PALAVRA A PALAVRA, aqui, de propósito. O hero/full-bleed-media diz no CSS
     dele que não se quebra headline por palavra, e está certo NAQUELE caso: lá
     são três palavras com um itálico de destaque, e cortar isso desmonta a
     frase. Aqui são sete palavras em duas linhas, e a onda de 54ms é a
     assinatura da dobra — quem tirar, tira o efeito.

     Não usa data-split do core: o gancho quebra o texto em .w, e .w é classe do
     core que componente não pode estilizar. Sem poder estilizar, não há como
     escalonar por palavra. Os spans vêm do markup, com o índice no style.
     ========================================================================== -->

<section class="sec-dark pitch" data-pitch>
  <div class="pitch-panel">

    <span class="pitch-beams" aria-hidden="true"></span>
    <span class="grain"></span>

    <div class="wrap pitch-body">

      <p class="pitch-social">
        <span class="pitch-faces" aria-hidden="true">
          <img class="pitch-face" src="../../../showroom/demo/ph-4.webp" alt="" style="--pitch-face-pos:52% 26%" decoding="async">
          <img class="pitch-face" src="../../../showroom/demo/ph-7.webp" alt="" style="--pitch-face-pos:62% 40%" decoding="async">
          <img class="pitch-face" src="../../../showroom/demo/ph-5.webp" alt="" style="--pitch-face-pos:44% 30%" decoding="async">
        </span>
        <span class="pitch-social-txt">
          <strong class="pitch-social-n">R$ 2,4 bilhões</strong> sob assessoria de famílias e empresários
        </span>
      </p>

      <h1 class="pitch-title">
        <span class="pitch-w" style="--pitch-i:0">Proteja,</span>
        <span class="pitch-w" style="--pitch-i:1">multiplique</span>
        <span class="pitch-w" style="--pitch-i:2">e</span>
        <span class="pitch-w" style="--pitch-i:3">transmita</span>
        <span class="pitch-w" style="--pitch-i:4">o</span>
        <span class="pitch-w" style="--pitch-i:5">seu</span>
        <span class="pitch-w" style="--pitch-i:6">patrimônio</span>
      </h1>

      <p class="pitch-desc">
        <span class="pitch-w" style="--pitch-i:0">Do</span>
        <span class="pitch-w" style="--pitch-i:1">diagnóstico</span>
        <span class="pitch-w" style="--pitch-i:2">à</span>
        <span class="pitch-w" style="--pitch-i:3">sucessão,</span>
        <span class="pitch-w" style="--pitch-i:4">a</span>
        <span class="pitch-w" style="--pitch-i:5">Liberta</span>
        <span class="pitch-w" style="--pitch-i:6">cuida</span>
        <span class="pitch-w" style="--pitch-i:7">da</span>
        <span class="pitch-w" style="--pitch-i:8">estrutura</span>
        <span class="pitch-w" style="--pitch-i:9">técnica</span>
        <span class="pitch-w" style="--pitch-i:10">do</span>
        <span class="pitch-w" style="--pitch-i:11">seu</span>
        <span class="pitch-w" style="--pitch-i:12">patrimônio</span>
        <span class="pitch-w" style="--pitch-i:13">para</span>
        <span class="pitch-w" style="--pitch-i:14">você</span>
        <span class="pitch-w" style="--pitch-i:15">decidir</span>
        <span class="pitch-w" style="--pitch-i:16">com</span>
        <span class="pitch-w" style="--pitch-i:17">clareza.</span>
      </p>

      <div class="pitch-act">
        <a class="btn btn-primary pitch-cta" href="#diagnostico">Agende seu diagnóstico</a>
      </div>

    </div>
  </div>
</section>

estilo.css · 240 linhas · 9,5 KB

/* ==========================================================================
   HERO CENTRADO COM PROVA SOCIAL — prefixo pitch-
   Painel escuro recuado, conteúdo centrado, quatro tempos de entrada.

   Tokens usados:
     --dark --dark-rgb     fundo do painel e das faixas de luz
     --fg --fg-2           promessa e apoio
     --accent              o botão, pela primitiva .btn-primary
     --display --sans      tipografia
     --radius-media        canto do painel e do botão
     --nav-h               folga do menu fixo no topo
     --ease                curva do projeto

   O botão é a primitiva .btn do core. A única coisa que este componente
   sobrescreve nele é a ESCALA da tipografia e o canto — ver o bloco do CTA
   lá embaixo, onde está escrito por quê.
   ========================================================================== */

.pitch{
  /* Corpo da promessa. Calibrado pela LARGURA da linha, não pelo número: a
     referência roda 58px numa grotesca de largura normal e a headline ocupa
     59% da coluna. É essa fração que se persegue quando a display do tema
     muda. */
  --pitch-title:clamp(32px,4vw,58px);

  /* Recuo do painel em relação à borda da página. É o fio de fundo que
     aparece em volta e faz a dobra parecer um aplicativo. */
  --pitch-inset:clamp(10px,1.1vw,16px);

  position:relative;
  /* O respiro lateral aqui NÃO é a coluna: é a moldura do painel. Quem
     continua controlando a coluna de texto é o .wrap, lá dentro (§4). */
  padding:var(--pitch-inset) var(--pitch-inset) 0;
}

.pitch-panel{
  position:relative;
  overflow:hidden;
  border:1px solid color-mix(in srgb,var(--fg) 10%,transparent);
  border-radius:calc(var(--radius-media) + 0px);
  background:var(--dark);
  min-height:calc(100vh - var(--pitch-inset));
}

/* FAIXAS DE LUZ.
   A referência resolve isso com uma imagem de fundo. Imagem de terceiro não
   atravessa (§11), e uma foto de 200KB para desenhar duas diagonais de 5% de
   opacidade seria caro de qualquer forma. Dois gradientes inclinados fazem o
   mesmo, escalam em qualquer tela e leem token.

   color-mix e não rgba com número: o §3 proíbe cor crua, e color-mix é a
   forma de tirar uma opacidade de um token sem inventar um canal. */
.pitch-beams{
  position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(126deg,
      color-mix(in srgb,var(--fg) 6%,transparent) 0%,
      transparent 28%),
    linear-gradient(306deg,
      color-mix(in srgb,var(--fg) 5%,transparent) 0%,
      transparent 24%);
}

/* ---------------------------------------------------------------- corpo */
/* Centrado nos dois eixos. É o que separa esta dobra do hero/full-bleed-media,
   que ancora o texto embaixo para a foto respirar. Aqui não há foto: o centro
   é o lugar da frase. */
.pitch-body{
  position:relative;z-index:2;
  min-height:calc(100vh - var(--pitch-inset));
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  text-align:center;
  /* O menu fixo do projeto passa por cima do topo do painel. */
  padding-top:calc(var(--nav-h) + clamp(32px,6vh,72px));
  padding-bottom:clamp(48px,8vh,96px);
}

/* ---------------------------------------------------------------- prova social */
.pitch-social{
  display:flex;align-items:center;justify-content:center;
  gap:12px;flex-wrap:wrap;
  font-size:14px;line-height:1.45;
  color:var(--fg-muted);
}
.pitch-social-n{font-weight:500;color:var(--fg-2)}

.pitch-faces{display:flex;flex:0 0 auto}

/* O anel é box-shadow e não border: border entra na conta da largura e
   estragaria a sobreposição de -8px, que é o que faz os três rostos lerem
   como um grupo e não como três ícones enfileirados. */
.pitch-face{
  width:28px;height:28px;flex:0 0 auto;
  border-radius:var(--radius-pill);
  object-fit:cover;
  object-position:var(--pitch-face-pos,50% 30%);
  box-shadow:0 0 0 2px var(--dark);
}
.pitch-face + .pitch-face{margin-inline-start:-8px}

/* ---------------------------------------------------------------- promessa */
/* Não usa .display-xl do core: aquela primitiva tem corpo que enche a coluna
   e entrelinha .95, para título de uma ou duas palavras. Esta headline é sete
   palavras, corpo menor e entrelinha 1.07 — são dois desenhos diferentes, e
   juntá-los numa primitiva só faria as duas piorarem. */
.pitch-title{
  font-family:var(--display);font-weight:600;
  font-size:var(--pitch-title);
  line-height:1.07;letter-spacing:-.025em;
  color:var(--fg);
  /* 18ch é o que faz a promessa cair em DUAS linhas, com a quebra depois de
     "escale" — a mesma da referência. Medida em ch e não em px porque o que
     decide a quebra é o número de caracteres, não a largura da tela: trocar a
     display do tema muda os pixels e mantém a quebra. */
  max-width:18ch;
  margin-top:28px;
}

/* Peso 400 e não o 300 que o corpo da página herda: a 24px o Light fica
   fino demais e o apoio some ao lado da promessa. */
.pitch-desc{
  font-size:clamp(16px,1.6vw,24px);line-height:1.38;
  font-weight:400;
  color:var(--fg-2);
  /* 44ch = duas linhas, como no original. */
  max-width:44ch;
  margin-top:32px;
}

.pitch-act{margin-top:30px}

/* CTA. Herda forma, cor e transição da primitiva .btn/.btn-primary do core e
   sobrescreve DUAS coisas: a escala da tipografia e o canto.

   O .btn da casa é um rótulo — 11.5px, caixa alta, tracking largo, pílula.
   O botão desta referência é uma frase: corpo de leitura, caixa baixa, canto
   de 12px. Não é gosto: um hero cujo único caminho adiante é este botão pede
   um alvo que se leia à distância, e o rótulo pequeno some no meio do painel.

   Seletor duplo (.pitch .pitch-cta) de propósito: .btn e .pitch-cta têm a
   mesma especificidade, e o §6.4 proíbe depender de qual folha carregou
   primeiro. Mesma solução do .hgal-cap .hgal-type. */
.pitch .pitch-cta{
  font-family:var(--sans);
  font-size:16px;font-weight:600;
  letter-spacing:normal;text-transform:none;
  padding:16px 32px;
  border-radius:var(--radius-media);
}

/* ---------------------------------------------------------------- entrada */
/* Quatro tempos, disparados por .in na raiz — a convenção que o
   hero/full-bleed-media abriu (ver o script.js dele). IntersectionObserver
   não serve num hero: a dobra já está na tela quando a página abre.

   Os atrasos são os da referência, medidos no navegador:
     prova social  0.12s
     promessa      0.30s + 54ms por palavra
     apoio         0.90s + 33ms por palavra
     botão         1.62s

   O que a referência NÃO tem e aqui tem é o blur. O §5 do contrato é
   explícito — "nada entra seco" — e o hero/full-bleed-media é anterior a
   essa regra, o que explica (não justifica) ele transicionar só opacidade e
   deslocamento. */
.pitch-social,
.pitch-w,
.pitch-act{
  opacity:0;
  filter:blur(12px);
  transform:translateY(24px);
  transition:opacity .9s var(--ease),
             filter .9s var(--ease),
             transform .9s var(--ease);
}

.pitch-w{display:inline-block}

.pitch-social{transition-delay:.12s;transition-duration:1s}
.pitch-title .pitch-w{transition-delay:calc(.3s + var(--pitch-i,0) * 54ms)}
.pitch-desc .pitch-w{transition-delay:calc(.9s + var(--pitch-i,0) * 33ms)}

/* O botão não sobe: ele estoura. É o único movimento diferente da dobra, e
   é o que faz o olho parar nele depois de a frase inteira ter passado. */
.pitch-act{
  transform:scale(.6);
  transition-duration:.7s;
  transition-delay:1.62s;
}

.pitch.in .pitch-social,
.pitch.in .pitch-w,
.pitch.in .pitch-act{opacity:1;filter:blur(0);transform:none}

/* Quem pediu menos movimento recebe a dobra inteira, pronta, sem espera.
   Colado na regra que ele desliga, como manda o §6.5. */
@media(prefers-reduced-motion:reduce){
  .pitch-social,
  .pitch-w,
  .pitch-act{opacity:1;filter:none;transform:none;transition:none}
}

/* ---------------------------------------------------------------- mobile */
@media(max-width:760px){
  .pitch-body{
    padding-top:calc(var(--nav-h) + 32px);
    padding-bottom:56px;
    /* 100vh em celular conta com a barra do navegador recolhida: a dobra
       fica alta demais e o botão cai abaixo da linha d'água. Deixar a altura
       ser o conteúdo é o que garante o botão à vista. */
    min-height:0;
  }
  .pitch-panel{min-height:0}
  .pitch-title{max-width:none;margin-top:22px}
  .pitch-desc{max-width:38ch;margin-top:20px}
  .pitch-act{margin-top:26px}
  .pitch .pitch-cta{width:100%}
}

/* ==========================================================================
   SEM JAVASCRIPT, O CONTEUDO APARECE. §5 do contrato.

   Estas regras revelam por CLASSE PROPRIA (`.pitch.in`), e nao pelo `[data-rv]` do
   core — por isso o `@media (scripting: none)` do core/motion.css nao as
   alcanca: ele cobre `[data-rv]`, `.w` e `.ttl`, e mais nada.

   Sem esta excecao, com o JavaScript desligado a headline inteira ficava invisivel — sao 25 palavras em nos separados. Medido com
   `node bin/medir.js <preview> --sem-js`: 25 nos com texto proprio em opacidade 0
   ========================================================================== */
/* `.pitch-act`, e não `.pitch-cta`: quem nasce apagado é o INVÓLUCRO do
   botão (ver a entrada acima), e liberar o filho não acende o pai. A versão
   anterior listava `.pitch-cta` e um `.pitch-lead` que nem existe no markup —
   e o único caminho adiante do hero sumia sem JavaScript. Achado pelo
   bin/varredura.js, que procura texto que nunca aparece. */
@media (scripting: none){
  .pitch-w,
  .pitch-social,
  .pitch-act{opacity:1;transform:none;filter:none;transition:none}
}

script.js · 28 linhas · 1,4 KB

/* ==========================================================================
   HERO CENTRADO — dispara a entrada.

   Faz uma coisa só: põe .in na raiz depois que o estado inicial já pintou.
   O resto da coreografia é CSS — os quatro tempos, os atrasos por palavra e
   o desligamento em movimento reduzido moram no estilo.css.

   IntersectionObserver não serve aqui, e não é preguiça: o hero já está na
   tela quando a página abre, então o observador dispararia no mesmo quadro
   em que o CSS pintou o estado inicial, e a transição não teria de onde sair.
   É a mesma convenção do hero/full-bleed-media.
   ========================================================================== */

(function () {
  var raiz = document.querySelector('[data-pitch]');
  if (!raiz) return;                                  // guard

  /* Dois rAF encadeados garantem que o estado inicial (opacidade zero, blur,
     deslocamento) já foi pintado antes de a classe ligar a transição. Com um
     só, o navegador às vezes junta os dois quadros e o texto aparece pronto. */
  requestAnimationFrame(function () {
    requestAnimationFrame(function () { raiz.classList.add('in'); });
  });

  /* Rede de segurança para aba aberta em segundo plano, onde o rAF não roda:
     sem isto o hero fica invisível até a pessoa trocar de aba. */
  setTimeout(function () { raiz.classList.add('in'); }, 450);
})();

Um hero sem foto. No lugar da mídia, um painel escuro recuado das bordas da página — canto arredondado, um fio de borda, duas faixas de luz muito fracas nos cantos — e dentro dele quatro coisas empilhadas no centro dos dois eixos: a linha de prova social com três rostos sobrepostos, a promessa, o apoio e um botão. Nada mais. O olho entra pelos rostos (são a única mancha de cor da dobra), sobe para a frase, desce pela explicação e para no botão, que é o último a aparecer e o único movimento diferente da dobra: os outros três tempos sobem, o botão estoura. Quem controla essa ordem não é o layout, é a coreografia — quatro tempos com atraso cravado, em que a headline vem palavra a palavra numa onda de 54ms.

Resolve a abertura de produto digital, onde não existe foto que ajude. Um hero institucional pode se apoiar em atmosfera; um hero de plataforma não tem o que fotografar — captura de tela envelhece, ilustração genérica não diz nada, e foto de banco mente sobre o que o produto é. Aqui o que convence é a frase, e a dobra é construída para isso: tudo o que não é a frase (o painel, as faixas, o grão) fica em 5% de opacidade, e a única coisa com peso visual além do texto é a prova social — que existe justamente porque uma promessa sozinha, sem ninguém por trás, é só uma afirmação.


Quando usar

Quando não usar


Padrão editorial

Slot Regra
Rostos Exatamente 3. Dois leem como casal; quatro passam de 100px de fila com a sobreposição de −8px e a linha quebra antes do texto.
Prova social — número Um número redondo dentro do <strong class="pitch-social-n">. Quantidade verificável, nunca adjetivo: "R$ 2,4 bilhões sob assessoria", não "bilhões sob a guarda de famílias satisfeitas".
Prova social — resto da frase Até 6 palavras, completando a oração começada pelo número. A linha inteira tem flex-wrap: quando não cabe, os rostos ficam sozinhos numa linha e o efeito de grupo se perde.
Promessa (h1) 6 a 8 palavras, uma oração só, caixa baixa. O max-width:18ch é o que a joga em duas linhas — conte caracteres, não palavras. Cada palavra em um .pitch-w com --pitch-i sequencial a partir de 0.
Apoio 15 a 22 palavras, duas linhas em 44ch. Diz como funciona; não repete o que a promessa já disse. Mesma numeração --pitch-i, reiniciando em 0.
Botão Um só, duas palavras, verbo no infinitivo ("Criar conta", "Começar agora"). Um segundo botão desmonta a dobra: o pop-in de 1.62s existe porque há um alvo, não dois.

O que mantém a dobra coesa é os quatro tempos dizerem quatro coisas diferentes, nessa ordem: por que confiar (prova), o que é (promessa), como funciona (apoio), o que fazer (botão). Se dois slots dizem a mesma coisa, sobra um tempo vazio na coreografia e a espera de 1.6s até o botão fica sem pagamento. O segundo eixo de coesão é aritmético: --pitch-i sem furo e sem repetição — índice repetido faz duas palavras entrarem juntas e a onda gagueja; índice pulado abre um buraco de 54ms no meio da frase.

Especificação dos assets

São três, e só três: os rostos da linha de prova social.


Como usar

<link rel="stylesheet" href="componentes/hero/centrado-prova-social/estilo.css">
<script src="componentes/hero/centrado-prova-social/script.js"></script>

Este componente não usa core/motion.js — a entrada inteira é dele (ver Gotchas). Do core ele precisa de tokens.css e de base.css, por causa do .wrap, do .grain e da primitiva .btn.

Ganchos

Gancho Papel
[data-pitch] A seção. O script parte daqui, nunca do documento.
.pitch.in Estado que dispara os quatro tempos. Quem põe é o script, e só ele.
--pitch-title Corpo da promessa. clamp(32px,4vw,58px) no padrão.
--pitch-inset Recuo do painel em relação à borda da página. clamp(10px,1.1vw,16px) no padrão. 0 sangra.
--pitch-i Inline em cada .pitch-w. O índice da palavra — é o multiplicador do atraso (54ms no título, 33ms no apoio).
--pitch-face-pos Inline em cada .pitch-face. object-position do recorte. Some ao usar avatar de verdade.
.pitch-panel O painel recuado. Fundo, borda, canto e overflow:hidden.
.pitch-beams As duas faixas de luz. Gradiente, aria-hidden, sem asset.
.pitch-body A caixa centrada. É também o .wrap — a coluna de texto sai dele.
.pitch-social / .pitch-social-txt / .pitch-social-n A linha, o bloco de texto que não pode ser separado dos rostos, e o trecho forte.
.pitch-faces / .pitch-face A fila e cada rosto.
.pitch-title / .pitch-desc / .pitch-w Promessa, apoio e a palavra — a unidade que a coreografia move.
.pitch-act / .pitch-cta O invólucro que estoura e o botão dentro dele.

Variações


Gotchas


Histórico

Projeto Onde Data Diferenças
referência: Kirvano https://www.kirvano.com/ — hero, primeira dobra da home 2026-09-01 referência visual, não origem de código

Origem. Escrito do zero a partir da observação do hero de kirvano.com, medido no navegador a 1440×900. Site em Tailwind, com fonte de terceiro e sem licença declarada: nada foi copiado (§11). O que veio de lá foi a medida e o timing. Status externo — nunca rodou em produção nossa; o primeiro site que usar promove, e esta ficha registra qual foi. A referência está registrada em projetos/referencias-externas.md.

Normalizações aplicadas na tradução:

Divergências conhecidas vs. a referência: