← Biblioteca componentes/conteudo/lista-beneficios-palco/ficha.md CódigoTela cheia
conteudo/lista-beneficios-palco

Lista de benefícios com palco ilustrado

🟢 estavel complexidade média prefixo benf- beneficios duas-colunas palco cards-flutuantes interface-simulada lista-com-icone movimento-continuo cta porque-nos sem-javascript sem javascript

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

<link rel="stylesheet" href="componentes/conteudo/lista-beneficios-palco/estilo.css">

markup.html · 251 linhas · 13,9 KB

<!-- ==========================================================================
     LISTA DE BENEFÍCIOS COM PALCO ILUSTRADO
     Prefixo: benf-
     Requer: core (tokens.css, base.css, motion.css, motion.js) + estilo.css
     SEM script.js e SEM lib — a dobra inteira é HTML e CSS.

     A DOBRA. Duas colunas, ~7/5. À esquerda um PALCO: uma foto e quatro
     peças soltas boiando em volta dela (um cartão com um dado, uma
     confirmação, um arco e uma linha pontilhada que liga as duas). À
     direita quatro benefícios em lista — ícone, título, uma frase, um link
     opcional — separados por um filete de 2px, e um botão fechando a coluna.

     A IDEIA. É a dobra "por que trabalhar com a gente" nos dois registros ao
     mesmo tempo: a coluna da direita ARGUMENTA e o palco da esquerda MOSTRA.
     Uma foto sozinha não diz o que a assessoria entrega; quatro parágrafos
     sozinhos não têm imagem nenhuma. O palco resolve isso sem virar um
     segundo componente: as peças flutuantes são um retrato do produto — o
     relatório consolidado existe, o mês fecha, alguém confirma.

     data-rv NO INVÓLUCRO, PEÇA POR DENTRO — e isto é medido, não estilo.
     Cada peça boia continuamente com um `transform` próprio. O core termina
     o reveal com `[data-rv].in{transform:none}`, que vale (0,2,0) contra a
     (0,1,0) de `.benf-piece`: com os dois no MESMO nó, a boiada seria apagada
     em silêncio no instante em que a dobra entra — o keyframe continuaria
     rodando e o computado voltaria a `none`. Por isso o data-rv mora em
     .benf-slot (que só posiciona) e o .benf-piece de dentro fica livre.
     Mesma separação de efeitos/inclinacao-3d com .tilt-card-slot.
     Quem juntar os dois numa "simplificação" apaga a boiada e não vê erro
     nenhum no console.

     A ENTRADA É ESCALONADA E NADA ENTRA SECO: a foto primeiro (sem data-d),
     depois cartão e arco (data-d="1"), a confirmação (2) e por último a
     linha que liga as duas (3) — uma linha só faz sentido depois das duas
     pontas existirem. Todas com blur indo a zero, pelo core.

     PEÇA CLARA EM DOBRA ESCURA. O cartão e a confirmação declaram .sec-light
     neles mesmos. Sem isso o texto de dentro leria o --fg da seção (claro) e
     sumiria no papel claro da peça — e a .pill de "ilustrativo", que lê
     --fg-muted e --rule-2, ficaria invisível. Escopo de tom no markup NÃO é
     override de token: o componente entra num escopo que o core já define e
     segue lendo os mesmos nomes (MANUAL §3). Nenhuma regra daqui escreve cor
     de texto.

     COMPLIANCE. O cartão mostra PATRIMÔNIO CONSOLIDADO e DISTRIBUIÇÃO POR
     CLASSE — estoque e composição, nunca resultado. A confirmação é uma AÇÃO
     CONCLUÍDA ("relatório do mês enviado"), nunca um ganho. A ressalva
     "ilustrativo" fica DENTRO do cartão, onde a pessoa lê o número, e não num
     rodapé legal que ninguém desce para ver. Trocar isso por "sua carteira
     rendeu X" quebra a peça no sentido que importa, e o CSS não vai reclamar.

     AS PEÇAS SÃO ORNAMENTO, E POR ISSO SÃO aria-hidden. Quem usa leitor de
     tela recebe a foto (com alt de verdade) e a lista da direita, que é onde
     o argumento mora. Ler "R$ 12 mi" fora de contexto transformaria uma
     ilustração numa afirmação. É a mesma decisão de conteudo/trio-cards-ui-simulada
     e de dados/painel-patrimonio para interface simulada — e é o que torna
     legítimo escondê-las inteiras no celular: ali não se perde conteúdo.
     ========================================================================== -->

<section class="benf sec-dark sec-pad" id="beneficios">
  <div class="wrap benf-grid">

    <!-- =================================================================
         COLUNA ESQUERDA — argumento e palco
         ================================================================= -->
    <div class="benf-side">

      <span class="eyebrow" data-rv>Por que uma assessoria independente</span>
      <h2 class="sec-title ttl">O patrimônio inteiro num lugar só, e um assessor que <em>responde por ele</em></h2>

      <!-- O palco é a caixa de referência de TUDO que flutua: as quatro
           peças são absolute em PORCENTAGEM dele, nunca em px cravado. É o
           que faz a composição sobreviver a qualquer largura de coluna —
           em px a primeira tela estreita joga o cartão para fora da foto.
           A foto é recuada à esquerda (--benf-photo-inset) justamente para
           abrir a calha onde o cartão e o arco pousam. -->
      <div class="benf-stage">

        <img class="benf-photo" data-rv
             src="../../../showroom/demo/ph-wide-1.webp"
             alt="Casal caminhando por um vinhedo ao entardecer"
             loading="lazy" decoding="async">

        <!-- ---- ARCO ----
             Primeiro no DOM porque tem de ficar ATRÁS do cartão: quatro
             irmãos absolutos empilham na ordem do markup, e resolver isso
             por z-index seria inventar uma camada que ninguém pediu. -->
        <div class="benf-slot" data-rv data-d="1"
             style="--benf-x:1%;--benf-y:63%;--benf-w:50%">
          <span class="benf-piece benf-piece-arc" aria-hidden="true">
            <svg class="benf-glyph" viewBox="0 0 190 74" fill="none" focusable="false">
              <path d="M5 65 A130 130 0 0 1 185 65" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
            </svg>
          </span>
        </div>

        <!-- ---- CARTÃO ----
             CONTEÚDO ILUSTRATIVO: número redondo de exemplo, sem cliente e
             sem instituição real. Estoque e composição — nunca resultado.
             Ao usar num site, troque pelo dado do cliente (mantendo a pílula
             "ilustrativo" enquanto o dado for de exemplo) ou apague a peça:
             nada mais na dobra depende dela. -->
        <div class="benf-slot" data-rv data-d="1"
             style="--benf-x:0%;--benf-y:51%;--benf-w:36%">
          <div class="benf-piece benf-piece-card sec-light" aria-hidden="true">
            <span class="pill benf-badge-illu">ilustrativo</span>
            <span class="benf-card-label">Patrimônio consolidado</span>
            <b class="benf-card-fig">R$ 12 mi</b>
            <!-- A barra É a distribuição por classe: quatro faixas em quatro
                 intensidades do acento. Sem legenda de propósito — nomear as
                 classes num cartão de 36% do palco produz três linhas de 9px
                 que ninguém lê e que o celular teria de esconder de novo. -->
            <span class="benf-bar">
              <span class="benf-seg" style="--benf-seg:45%"></span>
              <span class="benf-seg" style="--benf-seg:25%"></span>
              <span class="benf-seg" style="--benf-seg:20%"></span>
              <span class="benf-seg" style="--benf-seg:10%"></span>
            </span>
          </div>
        </div>

        <!-- ---- LINHA PONTILHADA ----
             Depois do cartão no DOM: o ponto da ponta encosta na borda
             direita do cartão, e atrás dele a ligação se perderia.
             A geometria é combinada com as duas peças que ela liga — mexer
             em --benf-x/--benf-y de qualquer uma das três solta a linha no
             ar. Os três valores andam juntos. -->
        <div class="benf-slot" data-rv data-d="3"
             style="--benf-x:34%;--benf-y:30%;--benf-w:34%">
          <span class="benf-piece benf-piece-link" aria-hidden="true">
            <!-- O MESMO CAMINHO, DUAS VEZES. A de baixo é um halo escuro mais
                 largo: um pontilhado de 3px em cor de marca some sobre a metade
                 clara de qualquer foto, e a peça é justamente a que atravessa a
                 imagem inteira. Apagar o halo devolve a linha invisível.

                 A CURVA SOBE ANTES DE DESCER, e não é gosto: em sag suave ela
                 passava por cima das cabeças de quem está na foto — medido no
                 preview, o traço cortava o rosto do casal. Assim ela corre pelo
                 alto do quadro e só mergulha no último terço, onde a foto já é
                 fundo. Foto com o assunto em outra posição pede outra curva. -->
            <svg class="benf-glyph" viewBox="0 0 168 96" fill="none" focusable="false">
              <path class="benf-link-halo" d="M162 6C140 14 118 26 96 44 74 62 46 76 16 84"
                    stroke-width="6" stroke-linecap="round" stroke-dasharray="0.1 9"/>
              <circle class="benf-link-halo" cx="10" cy="86" r="8.4" stroke-width="0"/>
              <path d="M162 6C140 14 118 26 96 44 74 62 46 76 16 84"
                    stroke="currentColor" stroke-width="3.2" stroke-linecap="round"
                    stroke-dasharray="0.1 9"/>
              <circle cx="10" cy="86" r="6" fill="currentColor"/>
            </svg>
          </span>
        </div>

        <!-- ---- CONFIRMAÇÃO ----
             Ação concluída, não ganho. "Relatório do mês enviado" é o que a
             assessoria faz; "sua carteira subiu" é o que ela não promete. -->
        <div class="benf-slot" data-rv data-d="2"
             style="--benf-x:69%;--benf-y:8%;--benf-w:18%">
          <div class="benf-piece benf-piece-check sec-light" aria-hidden="true">
            <span class="benf-check-mark">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M4.5 12.5L9.5 17.5L19.5 7"/></svg>
            </span>
            <span class="benf-check-text">Relatório do mês enviado</span>
          </div>
        </div>

      </div>
    </div>

    <!-- =================================================================
         COLUNA DIREITA — os quatro benefícios
         O filete de 2px vive no .benf-body, e não no <li>, porque ele tem de
         começar depois do ícone: uma borda no item atravessaria a coluna
         inteira e o ritmo da lista se perderia. O último item não leva
         filete — filete no fim fecha a lista como se houvesse um quinto.

         O BOTÃO FICA FORA DO <ul>, e não é detalhe de semântica: dentro da
         lista ele seria o último <li>, e aí `.benf-item:last-child` deixaria
         de casar com o quarto benefício — o filete voltaria justamente onde
         ele não pode existir. Fora, uma regra simples resolve, sem :has()
         nem :nth-last-child a contar irmãos.
         ================================================================= -->
    <div class="benf-col">
    <ul class="benf-list">

      <li class="benf-item" data-rv>
        <span class="benf-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" focusable="false">
            <path d="M14 3H6.5A1.5 1.5 0 0 0 5 4.5v15A1.5 1.5 0 0 0 6.5 21h11a1.5 1.5 0 0 0 1.5-1.5V8z"/>
            <path d="M14 3v5h5M8.6 12.5h6.8M8.6 16.5h4"/>
          </svg>
        </span>
        <div class="benf-body">
          <h3 class="benf-title">Relatório consolidado <span class="pill pill-accent benf-badge">Novo</span></h3>
          <p>Todas as instituições num relatório mensal só, com a posição de cada ativo e o custo de cada produto.</p>
          <a class="benf-link" href="#relatorio">
            Ver o modelo de relatório
            <svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 7h10M8 3l4 4-4 4"/></svg>
          </a>
        </div>
      </li>

      <li class="benf-item" data-rv data-d="1">
        <span class="benf-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" focusable="false">
            <path d="M20.5 12a8.5 8.5 0 1 1-2.9-6.4"/>
            <path d="M20.6 4v4.2h-4.2"/>
            <circle cx="12" cy="12" r="2.2"/>
          </svg>
        </span>
        <div class="benf-body">
          <h3 class="benf-title">Carteira acompanhada</h3>
          <p>Comitê trimestral, rebalanceamento registrado e uma política de investimentos assinada pelos dois lados.</p>
        </div>
      </li>

      <li class="benf-item" data-rv data-d="2">
        <span class="benf-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" focusable="false">
            <circle cx="12" cy="8.2" r="3.8"/>
            <path d="M4.8 20.4a7.4 7.4 0 0 1 14.4 0"/>
          </svg>
        </span>
        <div class="benf-body">
          <h3 class="benf-title">Acesso ao assessor</h3>
          <p>A mesma pessoa que conduziu o diagnóstico atende no dia a dia — sem central e sem troca de time.</p>
        </div>
      </li>

      <li class="benf-item" data-rv data-d="3">
        <span class="benf-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" focusable="false">
            <path d="M12 4.6v15M7.6 19.6h8.8M4 8.6h16"/>
            <path d="M4 8.6 1.8 13.4a2.5 2.5 0 0 0 4.4 0zM20 8.6l-2.2 4.8a2.5 2.5 0 0 0 4.4 0z"/>
          </svg>
        </span>
        <div class="benf-body">
          <h3 class="benf-title">Independência de remuneração</h3>
          <p>Taxa previamente acordada sobre o patrimônio assessorado. Nenhuma comissão de produto na conversa.</p>
          <a class="benf-link" href="#remuneracao">
            Como cobramos
            <svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M2 7h10M8 3l4 4-4 4"/></svg>
          </a>
        </div>
      </li>

    </ul>

      <a class="btn btn-primary benf-cta" href="#diagnostico" data-rv data-d="3">Agende seu diagnóstico</a>
    </div>

  </div>
</section>

estilo.css · 357 linhas · 14,6 KB

/* ==========================================================================
   LISTA DE BENEFÍCIOS COM PALCO ILUSTRADO — prefixo benf-
   Duas colunas: um palco de foto com quatro peças flutuando em volta, e uma
   lista de quatro benefícios com ícone, filete e um botão fechando a coluna.

   Tokens usados:
     --display --sans        tipografia de título e de texto
     --fg --fg-2 --fg-muted  tinta, herdada do escopo de tom
     --rule                  o filete de 2px que dá ritmo à lista
     --rule-2                borda da pílula de ressalva (via .pill do core)
     --bg                    papel das peças claras (vem do .sec-light delas)
     --accent                ícones, arco, linha pontilhada, barra do cartão
     --dark-rgb              sombra das peças, em canal separado
     --ease                  curva única — boiada, hover do link
     --radius-media          canto das peças e da foto
     --radius-pill           ícone em círculo, pílula, barra
     --sec-gap               respiro vertical, via .sec-pad do core

   SEM script.js. A entrada é o [data-rv] do core, a boiada é uma animação
   CSS e o resto é layout. Não há um só listener nesta dobra.

   POR QUE A BOIADA É @keyframes E NÃO UM LAÇO EM rAF. O §5 pede animação
   por TEMPO, com dt limitado — a regra existe porque um laço de JS que anda
   por QUADRO acelera em 120Hz e salta ao voltar de uma aba em segundo plano.
   Animação CSS já é por tempo na origem: o navegador interpola pelo relógio
   do documento, pausa junto com a aba e não tem dt nenhum a limitar. O laço
   equivalente em JS seria mais código para chegar ao mesmo lugar com mais
   jeitos de errar. Precedente na casa: o stageBob do hero/duas-colunas-produto.
   ========================================================================== */

.benf-grid{
  display:grid;
  /* ~7/5, medido na referência (696 e 488 numa coluna de 1264). minmax(0,…)
     e não 7fr/5fr puro: sem o minmax, uma linha longa dentro de um item da
     lista estica a coluna e a proporção some. */
  grid-template-columns:minmax(0,7fr) minmax(0,5fr);
  gap:clamp(34px,4.6vw,64px);
  align-items:start;
}


/* ==========================================================================
   O PALCO
   Caixa de referência de tudo que flutua. As quatro peças são absolute em
   PORCENTAGEM daqui — nunca em px —, e é só por isso que a composição
   sobrevive a qualquer largura de coluna.
   ========================================================================== */

.benf-stage{
  /* 696x530 da referência. É o único lugar onde a proporção do palco mora:
     mudar aqui reposiciona as quatro peças junto, porque todas leem % desta
     mesma caixa. */
  --benf-stage-ratio:696/530;

  /* A calha à esquerda. A foto não encosta na borda do palco: os 6,3% que
     sobram (44 de 696 na referência) são onde o cartão e o arco pousam
     meio para dentro, meio para fora da imagem. Zerar isto cola o cartão
     na foto e a composição perde a profundidade inteira. */
  --benf-photo-inset:6.3%;

  position:relative;
  aspect-ratio:var(--benf-stage-ratio);
  margin-top:clamp(32px,3.4vw,48px);
}

/* LARGURA E ALTURA EXPLÍCITAS, e isto é medido: `left/right/top/bottom` mais
   `width:auto` NÃO dimensiona uma <img>. Elemento SUBSTITUÍDO com dimensão
   automática resolve pelo tamanho intrínseco do arquivo, o `right`/`bottom`
   viram excesso e são descartados. Medido no Chrome com uma foto 1600x900
   num palco de 602x458: a imagem saiu 602x339 — a largura toda (pelo
   max-width:100% do core) e só 74% da altura, com as peças de baixo boiando
   sobre fundo vazio. A conta abaixo é o que devolve os 458. */
.benf-photo{
  position:absolute;
  top:0;left:var(--benf-photo-inset);
  width:calc(100% - var(--benf-photo-inset));
  height:100%;
  object-fit:cover;
  /* O assunto vive no terço central e alto do quadro: embaixo à esquerda
     entram o cartão e o arco, e em cima à direita a confirmação. */
  object-position:50% 40%;
  border-radius:var(--radius-media);
}

/* ---- o invólucro que posiciona ----
   ELE leva o data-rv; a peça de dentro é que se move. Não junte os dois no
   mesmo nó: `[data-rv].in{transform:none}` vale (0,2,0) contra a (0,1,0) de
   `.benf-piece` e apagaria a boiada em silêncio assim que a dobra entrasse
   (ver o cabeçalho do markup.html). Aqui não há transform NENHUM de repouso,
   de propósito — a única coisa que este nó faz é posicionar. */
.benf-slot{
  position:absolute;
  left:var(--benf-x);
  top:var(--benf-y);
  width:var(--benf-w);
}

/* ---- a peça, e a boiada ----
   Amplitude pequena e tempos primos entre si. Em fase igual as quatro peças
   sobem e descem juntas, a foto inteira parece respirar e o truque aparece;
   dessincronizar é o que as faz ler como objetos soltos. O delay NEGATIVO
   começa cada uma no meio do próprio balanço, para nenhuma nascer parada. */
.benf-piece{
  --benf-bob:7px;
  --benf-bob-dur:6.4s;
  --benf-bob-delay:0s;
  animation:benfBob var(--benf-bob-dur) var(--ease) var(--benf-bob-delay) infinite alternate;
}
@keyframes benfBob{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(0,calc(var(--benf-bob) * -1),0)}
}
/* Colada à regra que ela desliga (§6.5): o que anda sozinho para. */
@media(prefers-reduced-motion:reduce){
  .benf-piece{animation:none}
}

.benf-piece-card{--benf-bob:6px;--benf-bob-dur:7.4s;--benf-bob-delay:-2.6s}
.benf-piece-check{--benf-bob:9px;--benf-bob-dur:5.8s;--benf-bob-delay:-1.2s}
.benf-piece-link{--benf-bob:5px;--benf-bob-dur:8.2s;--benf-bob-delay:-3.4s}
.benf-piece-arc{--benf-bob:4px;--benf-bob-dur:9s;--benf-bob-delay:-.8s}

/* ---- as duas peças de papel ----
   Superfície clara sobre foto escura. A cor vem do --bg do .sec-light que
   cada uma declara no markup: nenhuma regra daqui escreve cor de papel nem
   cor de texto, e o tema segue mandando nas duas.

   O CANTO É DO TEMA, e isso é decisão, não esquecimento: a referência mede
   12px, mas projeto flat (--radius-media:0) tem de devolver peça de canto
   vivo, senão o componente passa a decidir a forma do cliente — que é
   exatamente o que o §10 proíbe. Quem quiser o arredondado da referência num
   tema flat troca --benf-piece-radius no consumidor, sem tocar em regra. */
.benf-piece-card,
.benf-piece-check{
  --benf-piece-radius:var(--radius-media);
  --benf-piece-pad:clamp(11px,1.15vw,15px);

  display:flex;
  flex-direction:column;
  align-items:flex-start;
  padding:var(--benf-piece-pad);
  background:var(--bg);
  border-radius:var(--benf-piece-radius);
  box-shadow:0 10px 24px rgba(var(--dark-rgb),.32);
}

.benf-piece-card{gap:clamp(5px,.55vw,8px)}
.benf-piece-check{gap:clamp(6px,.7vw,9px)}

/* ---- o cartão ---- */

/* A ressalva onde a pessoa lê o número, e não num rodapé legal. Herda a
   .pill do core (contorno, caixa alta, --fg-muted já virado escuro pelo
   .sec-light da peça) e só encolhe: 11px ao lado de um rótulo de 10px
   inverteria a hierarquia — a ressalva gritaria mais que o dado. */
.benf-badge-illu{
  font-size:9.5px;
  letter-spacing:.12em;
  padding:3px 9px;
}
.benf-card-label{
  font-family:var(--sans);font-weight:500;
  font-size:clamp(9.5px,.82vw,11px);line-height:1.3;letter-spacing:.02em;
  color:var(--fg-muted);
}
.benf-card-fig{
  font-family:var(--display);font-weight:700;
  font-size:clamp(17px,1.65vw,22px);line-height:1.1;letter-spacing:-.02em;
  color:var(--fg);
}
/* A barra É a distribuição por classe. Quatro faixas do mesmo acento em
   quatro intensidades: uma paleta de quatro cores exigiria quatro tokens
   novos e faria um cartão de 36% do palco competir com a dobra inteira. */
.benf-bar{
  display:flex;
  width:100%;
  gap:3px;
  height:6px;
  margin-top:3px;
}
.benf-seg{
  flex:0 0 var(--benf-seg);
  background:var(--accent);
  border-radius:var(--radius-pill);
}
/* O piso é .38 e não zero: abaixo disso a última classe some no papel da
   peça, e uma distribuição com uma fatia invisível deixa de ser distribuição. */
.benf-seg:nth-child(2){opacity:.8}
.benf-seg:nth-child(3){opacity:.58}
.benf-seg:nth-child(4){opacity:.38}

/* ---- a confirmação ---- */
.benf-check-mark{
  --benf-check-size:clamp(22px,2.2vw,28px);
  flex:0 0 auto;
  width:var(--benf-check-size);height:var(--benf-check-size);
  display:grid;place-items:center;
  border-radius:var(--radius-pill);
  /* Disco CHEIO com o sinal no papel da peça, e não o inverso: acento sobre
     papel claro é o par de menor contraste do tema (sage sobre creme, na
     Liberta), e um "concluído" que só se adivinha não confirma nada. */
  background:var(--accent);
  color:var(--bg);
}
.benf-check-mark svg{width:58%;height:58%;display:block}
.benf-check-text{
  font-family:var(--sans);font-weight:600;
  font-size:clamp(9.5px,.82vw,11px);line-height:1.35;
  color:var(--fg-2);
}

/* ---- arco e linha pontilhada ----
   Traço puro, sem caixa. Os dois são só um SVG que estica na largura do
   invólucro; a altura sai do viewBox, e é isso que mantém a geometria da
   linha casada com o cartão e a confirmação em qualquer largura. */
.benf-piece-arc,
.benf-piece-link{
  display:block;
  color:var(--accent);
}
.benf-glyph{display:block;width:100%;height:auto}
/* O halo do pontilhado: mesma curva, mais larga, no escuro do projeto. Ele
   existe porque a linha é a única peça que atravessa a foto de ponta a ponta
   e vai encontrar céu, terra e sombra no mesmo caminho. Sem ele, medido sobre
   uma foto de fim de tarde, o pontilhado em --accent simplesmente sumia na
   metade clara. Lê --dark-rgb, não cor crua. */
.benf-link-halo{stroke:rgba(var(--dark-rgb),.5);fill:rgba(var(--dark-rgb),.5)}
/* O arco tem de ficar ATRÁS do cartão, e quem resolve isso é a ordem do
   markup — quatro absolutos irmãos empilham na ordem em que aparecem.
   A opacidade recua um passo só — o bastante para ele ficar atrás da linha
   pontilhada na hierarquia, não o bastante para virar borrão. Em .55 ele
   lia como sombra suja do cartão em vez de gráfico; medido na foto do
   preview. */
.benf-piece-arc{opacity:.85}


/* ==========================================================================
   A LISTA
   ========================================================================== */

.benf-col{display:flex;flex-direction:column;align-items:flex-start}

.benf-list{
  display:flex;
  flex-direction:column;
  /* 40 na referência. 34 aqui: o título desta dobra corre uma linha a mais
     que o dela, e o ritmo mais fechado é o que aproxima o pé das duas colunas
     — com gap 40 a lista terminava 139px abaixo da foto, e o botão ficava
     pendurado no vazio. Medido. */
  gap:clamp(26px,2.4vw,34px);
  width:100%;
}

.benf-item{
  --benf-icon:clamp(44px,3.6vw,52px);
  display:grid;
  grid-template-columns:var(--benf-icon) 1fr;
  gap:clamp(14px,1.4vw,20px);
  align-items:start;
}

.benf-icon{
  width:var(--benf-icon);height:var(--benf-icon);
  display:grid;place-items:center;
  border-radius:var(--radius-pill);
  /* A referência põe um disco ESCURO aqui. Numa dobra escura isso
     desapareceria: o disco vira um véu do próprio acento, que separa o
     ícone do fundo sem inventar uma superfície nova. */
  background:color-mix(in srgb,var(--accent) 12%,transparent);
  border:1px solid var(--rule);
  color:var(--accent);
}
.benf-icon svg{width:52%;height:52%;display:block}

/* O filete começa DEPOIS do ícone, e é por isso que ele vive aqui e não no
   <li>: atravessando a coluna inteira, ele viraria uma régua de tabela e o
   ícone deixaria de ancorar o item. 2px e não 1px — em 1px o filete some no
   --rule de uma dobra escura, e a lista perde o ritmo que a referência tem. */
.benf-body{
  padding-bottom:clamp(16px,1.5vw,21px);
  border-bottom:2px solid var(--rule);
}
/* Filete no fim fecharia a lista como se houvesse um quinto item. O botão
   mora fora do <ul> exatamente para esta regra poder ser esta linha. */
.benf-item:last-child .benf-body{border-bottom:0}

.benf-title{
  font-family:var(--display);font-weight:700;
  font-size:clamp(17px,1.45vw,20px);line-height:1.3;letter-spacing:-.018em;
  color:var(--fg);
}
/* A pílula acompanha o título na mesma linha e não vira uma segunda linha
   de metadado. vertical-align porque ela é inline-block dentro de texto. */
.benf-badge{margin-left:10px;vertical-align:middle}

.benf-body p{
  font-size:clamp(14.5px,1.1vw,16px);line-height:1.6;
  color:var(--fg-2);
  margin-top:9px;
  max-width:48ch;
}

.benf-link{
  display:inline-flex;align-items:center;gap:9px;
  margin-top:13px;
  font-family:var(--sans);font-weight:600;font-size:13.5px;letter-spacing:.01em;
  color:var(--accent);
  border-bottom:1px solid transparent;
  padding-bottom:2px;
  transition:border-color .3s var(--ease);
}
.benf-link svg{width:13px;height:13px;display:block;transition:transform .3s var(--ease)}
/* Só o sublinhado e o deslocamento da seta dependem de hover — a seta já
   NASCE visível, então em toque não falta nada (§ "toque não tem hover"). */
.benf-link:hover{border-bottom-color:var(--accent)}
.benf-link:hover svg{transform:translateX(4px)}
@media(prefers-reduced-motion:reduce){
  .benf-link:hover svg{transform:none}
}

.benf-cta{margin-top:clamp(24px,2.4vw,34px)}


/* ==========================================================================
   MOBILE
   ========================================================================== */

/* Uma coluna. O palco NÃO ganha a largura inteira: as peças flutuantes são
   dimensionadas em vw e a caixa em %, então um palco de 900px de largura
   produziria um cartão de 320px com tipografia de 17px — sparso e errado.
   O teto devolve ao palco mais ou menos o tamanho que ele tem no desktop, e
   a composição centraliza. */
@media(max-width:980px){
  .benf-grid{grid-template-columns:1fr;gap:clamp(38px,6vw,56px)}
  .benf-stage{max-width:560px;margin-inline:auto}
  .benf-col{width:100%}
}

/* A COMPOSIÇÃO SAI, A FOTO FICA — e esta é a decisão de forma da peça.
   A referência esconde o palco inteiro no celular, e esconder as PEÇAS é
   inegociável: quatro objetos absolutos sobre 350px viram sopa, e o cartão
   ficaria mais largo que a foto. Mas levar a foto junto seria jogar fora a
   única metade da composição que atravessa intacta — e a dobra "por que
   trabalhar com a gente" sem nenhuma imagem vira uma lista comum, que a
   biblioteca já tem em conteudo/imagem-lista-numerada.
   O que se perde é ornamento, não conteúdo: as quatro peças são aria-hidden
   justamente porque o argumento inteiro mora na lista ao lado. */
@media(max-width:640px){
  .benf-slot{display:none}
  .benf-stage{
    --benf-stage-ratio:16/11;
    --benf-photo-inset:0%;   /* sem cartão, a calha não tem mais função */
    max-width:none;
  }
  .benf-item{--benf-icon:44px;gap:14px}
  .benf-body p{max-width:none}
}

Duas colunas, aproximadamente 7/5. À esquerda um palco: uma foto com quatro peças soltas boiando em volta dela — um cartão de patrimônio consolidado meio dentro e meio fora da imagem, uma confirmação de ação concluída no alto, um arco que sai por baixo do cartão e uma linha pontilhada que atravessa a foto ligando a confirmação ao cartão. À direita, quatro benefícios em lista: ícone em círculo, título com pílula opcional, uma frase, um link opcional com seta e um filete de 2px separando um do outro, mais um botão fechando a coluna.

O que ela resolve: a dobra "por que trabalhar com a gente" nos dois registros ao mesmo tempo. A coluna da direita argumenta; o palco da esquerda mostra. Uma foto sozinha não diz o que a assessoria entrega — vira banco de imagem com legenda. Quatro parágrafos sozinhos não têm imagem nenhuma e a dobra fica seca no meio de uma página que tem foto em todas as outras. O palco fecha esse vão sem pedir um segundo componente: as peças flutuantes são um retrato do produto — o relatório consolidado existe, o mês fecha, alguém confirma.

Zero JavaScript. A entrada é o [data-rv] do core, a boiada é uma animação CSS e o resto é layout.


Quando usar

Quando não usar

Os irmãos, e o que cada um resolve que este não

Irmão A diferença que decide
conteudo/imagem-lista-numerada O irmão mais próximo, e a distinção é de função. Lá a foto é apoio: estica na altura da linha, desloca em parallax e ilustra. O texto ao lado é numerado (01, 02, 03) porque o que importa é a ordem. Aqui a foto é palco: ela existe para receber quatro objetos que dizem o que o serviço entrega, e a lista é de atributos paralelos, não de sequência — ícone e não número, com link e botão porque cada item pode ser uma porta. Escolha o duo- quando o material for uma foto e três frases; escolha este quando houver produto para mostrar e ação para pedir.
hero/duas-colunas-produto Também tem palco à esquerda com cards em posição percentual, e é dele que vem o padrão da boiada. Mas é hero: acima da dobra, com headline, slider de fotos, setas e narrativa em passos. Aqui não há carrossel nem passo — o palco é uma composição parada, e a dobra é de meio de página.
conteudo/trio-cards-ui-simulada Também simula interface, em três cards lado a lado que se mexem sozinhos. Não tem foto de pessoa e não tem lista de argumento: os cards são os argumentos. Use aquele quando forem três recursos de produto; use este quando forem quatro razões para contratar alguém.
conversao/cta-formulario-lead Também casa lista de benefícios com uma ação, mas a ação é um formulário e a dobra é de conversão. Este termina em botão e vive no meio da página.

Padrão editorial

Slot Regra
Olho A categoria da dobra, não um slogan. Três a cinco palavras.
Título Uma frase, com o realce em <em> na metade que carrega a promessa. Três linhas é o alvo: em duas a coluna esquerda fica baixa demais para o palco, em cinco o palco desce para fora da tela.
Ícone Forma simples de traço, 24×24, um conceito só. Ícone com cena dentro some em 27px de desenho útil.
Título do item Duas a três palavras, substantivo. Relatório consolidado, não Nós entregamos um relatório. Paralelismo entre os quatro é o que faz a lista ler como lista.
Pílula No máximo uma na dobra inteira. Duas deixam de sinalizar novidade e viram decoração.
Frase Uma ou duas linhas, entre 90 e 105 caracteres. Acima disso a coluna direita ultrapassa o pé da foto e o botão fica pendurado no vazio — medido.
Link Opcional, e só onde existe página de verdade do outro lado. Dois em quatro é o equilíbrio: quatro links transformam a lista num menu.
Botão Um só, e é a ação principal da página.
Cartão flutuante Um rótulo, um número redondo, e a distribuição. Ver Compliance.
Confirmação flutuante Uma ação concluída, em três a cinco palavras. "Relatório do mês enviado", "Rebalanceamento aprovado", "Política assinada". Nunca um ganho.

O que mantém a peça coesa: os quatro benefícios têm de ser da mesma natureza (todos entregas, ou todos princípios) e de comprimento parecido. Um item de uma linha ao lado de outro de três desmonta o ritmo do filete, que é o que sustenta a coluna inteira.

Especificação dos assets

Uma foto, e ela é a peça que mais escolhe mal.

O preview usa showroom/demo/ph-wide-1.webp, que é placeholder — troque por foto do cliente ao consumir.


Como usar

<link rel="stylesheet" href="componentes/conteudo/lista-beneficios-palco/estilo.css">

Não há script.js. O core (motion.css + motion.js) já entrega a entrada.

Ganchos

Gancho Papel
--benf-x / --benf-y / --benf-w Inline em cada .benf-slot: posição e largura da peça, em % do palco. É o único lugar onde se remonta a composição.
--benf-stage-ratio Proporção do palco. 696/530 da referência. Mudar aqui move as quatro peças junto, porque todas leem % desta mesma caixa.
--benf-photo-inset A calha à esquerda (6,3%) onde o cartão e o arco pousam meio para dentro da foto. Zerar cola o cartão na imagem e a composição perde a profundidade.
--benf-piece-radius Canto das peças de papel. Nasce em var(--radius-media) — o tema decide a forma.
--benf-piece-pad Respiro interno das peças de papel.
--benf-bob / --benf-bob-dur / --benf-bob-delay Amplitude, ciclo e fase da boiada, por peça.
--benf-seg Inline em cada .benf-seg: a fatia da barra de distribuição. As quatro têm de somar 100%.
--benf-icon Lado do círculo de ícone. 52px na referência.
--benf-check-size Lado do disco de confirmação.
[data-rv] no .benf-slot Nunca no .benf-piece. Ver o primeiro gotcha.

Variações


Gotchas


Compliance

A dobra mostra um número. Antes de publicar, o consumidor tem de trocar ou apagar:

Peça O que está lá O que pode entrar no lugar
Cartão — número R$ 12 mi, redondo, marcado ilustrativo na própria peça Patrimônio consolidado real do cliente (com autorização) ou outro número redondo, mantendo a pílula enquanto for exemplo
Cartão — barra Distribuição por classe (45/25/20/10) Outra distribuição. Nunca evolução, rentabilidade ou comparação com índice
Confirmação "Relatório do mês enviado" Outra ação concluída. Nunca um ganho
Pílula "Novo" Um item Só onde houver novidade de verdade

As três regras que decidem a forma, e não só o texto:

  1. Estoque e composição, nunca resultado. Patrimônio consolidado é quanto existe; rentabilidade é quanto rendeu. A peça só pode dizer a primeira coisa. "Sua carteira rendeu X" quebra a dobra no sentido que importa, e nenhum validador vai reclamar.
  2. A ressalva fica onde a pessoa lê o número. A pílula ilustrativo é a primeira linha do cartão, e não uma nota de rodapé que ninguém desce para ver. Precedente: dados/painel-patrimonio.
  3. Nenhum nome real. Sem cliente, sem instituição, sem logo — nem na foto, nem no cartão.

Acessibilidade e compliance se encontram aqui: as quatro peças são aria-hidden="true". São ornamento, e ler "R$ 12 mi" fora de contexto num leitor de tela transformaria uma ilustração numa afirmação. O argumento inteiro mora na lista ao lado, que é conteúdo de verdade. É a mesma decisão de conteudo/trio-cards-ui-simulada e dados/painel-patrimonio para interface simulada — e é o que torna legítimo escondê-las inteiras no celular.

Sem captura de dado e sem localStorage. A dobra não guarda nada de ninguém.


Celular — a decisão de forma, e por que ela é essa

Abaixo de 640px as quatro peças saem e a foto fica.

A referência esconde o palco inteiro (m:hidden no contêiner). Esconder as peças é inegociável e a referência está certa nisso: quatro objetos absolutos sobre 350px de largura viram sopa, e o cartão — 36% do palco — ficaria mais largo que a metade útil da foto. Mas levar a foto junto seria jogar fora a única metade da composição que atravessa intacta, e a dobra "por que trabalhar com a gente" sem imagem nenhuma vira uma lista comum — que a biblioteca já tem, em conteudo/imagem-lista-numerada.

A terceira via só é honesta porque não se perde conteúdo: as peças são aria-hidden justamente por serem ornamento. Se algum dia o cartão carregar informação que não esteja na lista, esconder deixa de ser aceitável e a peça precisa reempilhar.

Ao esconder as peças, duas coisas mudam junto: a calha da esquerda (--benf-photo-inset) vai a zero, porque não há mais o que pousar nela, e o palco fica mais baixo (16/11), porque em largura cheia o 696/530 empurra a lista para fora da primeira tela.

Entre 640 e 980px a dobra já é de uma coluna, mas o palco não ganha a largura inteira: ele tem teto de 560px e centraliza. As peças são dimensionadas em vw e a caixa em %, então um palco de 900px produziria um cartão de 320px com tipografia de 17px — esparso e errado.


Histórico

Projeto Onde Data Diferenças
referência: contasonline.com.br https://www.contasonline.com.br/ — seção .s-itens, "Chega de planilhas" 2026-09-06 Clone reescrito do zero. Ver abaixo.

Origem: clone de referência visual, não origem de código. A URL acima é registro do que foi visto, nunca de onde veio arquivo. Licença de site no ar nunca é clara, e a regra do §11 decide sozinha: não se copia — se reescreve. Da referência vieram a ideia da composição, a proporção das duas colunas, o tamanho relativo das peças e o ritmo da lista. Nenhuma linha de HTML, CSS ou JS atravessou. Registro consolidado em projetos/referencias-externas.md, seção Clones.

Medidas de partida, do mapa da referência: coluna de 1264 em 12 colunas, com .destaque de 696 e .itens de 488 (~7/5); palco .mulher de 696×530 com a foto de 652×530 recuada 44 à esquerda; cartão 248×140 no canto inferior esquerdo (raio 12, sombra 0 10 20), toast 112×97 no alto à direita (raio 12, sombra 0 14 29), arco de 190×95 embaixo à esquerda, linha pontilhada de 61×60 e um ponto de 14 abaixo do toast; à direita ul com gap 40, ícone 52×52, h3 20/26 com badge "Novo", p 16/24, bloco com borda inferior de 2px, e botão 252×56 com mt-40.

O que mudou na tradução:

Normalizações aplicadas na extração: prefixo benf- em toda classe; toda cor por token, sem exceção; entrada pelo [data-rv]/data-d do core em vez de observer próprio; .wrap, .sec-pad, .eyebrow, .sec-title, .pill, .pill-accent, .btn/.btn-primary consumidos do core sem recópia; escopo de tom .sec-light declarado nas peças claras em vez de cor de texto escrita à mão; peças decorativas em aria-hidden e focusable="false" nos SVG; @media(prefers-reduced-motion) colado a cada regra que ele desliga; media queries de largura no fim do arquivo.

Divergências conhecidas vs. a referência: o ritmo da lista fechou de 40 para 34 (gap) e de 24 para 21 (respiro do filete) — o título desta dobra corre uma linha a mais que o dela, e com os valores originais a lista terminava 139px abaixo do pé da foto, com o botão pendurado no vazio. Depois do ajuste a diferença é de 103px numa dobra de 1049, e a coluna esquerda é a mais curta das duas (na referência é a mais longa).

Verificação (Chrome headless, bin/medir.js).

1440×900 — seção 1049px, palco 602×458 (proporção 1,314), foto 564×458 preenchendo o palco, grade 602px 430px (7/5 exato). As quatro peças dentro dos limites do palco, em % dele (posição de repouso, sem a boiada): arco 1–51% × 63–88,6%; cartão 0–36% × 51–78,1%; linha 34–68% × 30–55,5%; confirmação 69–87% × 8–29,1%. Zero overflow horizontal, console limpo, nenhuma imagem sem pintar. Três focáveis, na ordem do DOM (dois links de item, depois o botão), com anel de 2px e offset 3px; nada focável dentro de aria-hidden.

Rolando a dobra (--scroll=0.6) — a prova da armadilha do data-rv: os quatro .benf-slot com classe .in, opacidade 1 e transform: none (a entrada terminou), enquanto os quatro .benf-piece computam matriz viva (matrix(1,0,0,1,0,-3.19), -5.79, -4.87, -8.46) com animation-name: benfBob. Com os dois atributos no mesmo nó, a segunda linha leria none.

--reduce — animation-name: none e transform: none nas quatro peças, todas inteiras, legíveis e na posição de repouso declarada. Nada de movimento contínuo; nada escondido.

390×844 — uma coluna, palco 350×241 com a foto preenchendo, as quatro peças em display:none, zero overflow horizontal, console limpo.

Varredura de largura (1920, 1280, 1100, 1000, 900, 768, 700, 660, 640, 560, 390, 360) — zero overflow horizontal em todas, e em todas as larguras de composição visível (1920 a 660) as quatro peças permanecem dentro do palco. O palco vai de 614×468 (em 1280, onde a coluna é mais larga) a 489×373 (em 1000, o menor da faixa de duas colunas) e fica travado em 560×426 entre 980 e 660. A partir de 640 as peças somem, como previsto.