← Biblioteca componentes/conversao/planos-honorarios/ficha.md CódigoTela cheia
conversao/planos-honorarios

Planos de honorários com alternância

🟢 estavel complexidade média prefixo plan- planos honorarios precos colunas comparacao alternancia subgrid radio compliance acessibilidade aria-live sem-lib escuro

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

<link rel="stylesheet" href="componentes/conversao/planos-honorarios/estilo.css">
<script src="componentes/conversao/planos-honorarios/script.js"></script>

markup.html · 261 linhas · 15,5 KB

<!-- ==========================================================================
     PLANOS DE HONORÁRIOS — três modelos de relacionamento, lado a lado
     Prefixo: plan-
     Requer: core (tokens, base, motion.css, motion.js) + estilo.css + script.js

     A IDEIA. Não é tabela de preços de SaaS: é a explicação de como a casa
     cobra e do que entra em cada faixa. Três colunas por conjunto, uma
     alternância entre "Pessoa física e família" e "Empresa e holding", e as
     linhas equivalentes das três colunas ALINHADAS na horizontal — é o
     alinhamento que permite ler de lado e comparar, e ele é feito com
     `subgrid` (ver estilo.css), nunca com altura fixa.

     O IRMÃO. dados/comparador-cenarios responde outra pergunta com números:
     "quanto custa cada MODELO de remuneração ao longo do tempo". Este aqui
     responde "qual modelo é o meu". Um é aritmética de custo; o outro é
     escolha de relacionamento. Não se substituem.

     COMPLIANCE — É ISSO QUE DÁ FORMA À PEÇA, e não preferência de desenho:
       · FAIXA, nunca número cravado. "A partir de", "entre X e Y".
       · A PREMISSA que gera a faixa fica visível NA peça (.plan-premissa,
         logo acima das colunas), não em letra miúda de rodapé.
       · O que se compara é SERVIÇO e REMUNERAÇÃO, nunca resultado. Nenhuma
         coluna promete performance, e nenhuma insinua.
       · O modelo é explícito e repetido nas seis colunas, como último item
         da lista: taxa previamente acordada sobre o patrimônio sob
         assessoria, SEM COMISSÃO POR PRODUTO. É o argumento da
         independência, e ele vale mais que qualquer superlativo.
       · NADA de "melhor plano" nem de "mais popular" solto. O destaque de
         uma coluna é editorial e qualificado ("mais procurado por famílias
         em sucessão"), nunca um juízo de valor.
     Ver ficha.md, seção Compliance, para o que a área técnica do cliente
     tem de revisar antes de publicar.

     OS NÚMEROS, E ONDE ELES MORAM. Todos são ILUSTRATIVOS. São doze, e
     vivem em dois lugares por coluna, sempre dentro de <span class="plan-num">:
     a faixa de patrimônio de entrada (.plan-entrada) e a faixa de honorário
     (.plan-fee). Nenhum outro ponto do markup tem número — quem for publicar
     troca doze spans e acabou. Recalibrar com a área técnica e com o
     compliance do cliente.

     ORDEM DOS BLOCOS, E POR QUÊ. O que está escrito aqui é o estado SEM
     JavaScript: os DOIS conjuntos empilhados, cada um com o seu subtítulo,
     tudo legível. Quem esconde um deles é o script — nunca o CSS —, e é por
     isso que o segundo conjunto não nasce com [hidden]. O que nasce com
     [hidden] é só o que não faz sentido sem script: a alternância. Mesmo
     critério do conversao/diagnostico-perfil.

     A ALTERNÂNCIA É UM GRUPO DE RADIO DE VERDADE, e não um tablist. Motivo:
     é uma escolha entre dois conjuntos mutuamente exclusivos, que é
     exatamente o que um grupo de radio é — e as setas do teclado vêm de
     graça, com o foco andando e marcando junto. Um role="tablist" pediria
     roving tabindex escrito à mão para chegar no mesmo lugar, e ainda
     prometeria painéis de aba que estes conjuntos não são. O `name` dos
     radios é reescrito pelo script com um sufixo por instância, para dois
     componentes na mesma página não caírem no mesmo grupo.

     SEM data-rv DENTRO DOS CONJUNTOS, e isso é armadilha medida: o reveal do
     core é IntersectionObserver, e um bloco que nasce [hidden] nunca
     intersecta — ele ficaria em opacity 0 para sempre ao ser revelado pela
     alternância. O data-rv vive no invólucro .plan-quadro, que está sempre
     visível; a entrada escalonada das colunas na troca é do próprio
     componente (.is-in / --plan-i).
     ========================================================================== -->

<section class="sec-deep sec-pad plan" data-plan>
  <div class="wrap">

    <div class="sec-head plan-head">
      <p class="eyebrow" data-rv>Honorários</p>
      <h2 class="sec-title ttl">Como cobramos, e o que <em>entra</em> em cada modelo.</h2>
      <p class="sec-lead plan-apoio" data-rv data-d="1">Três formas de trabalhar com a casa. A diferença entre elas não é o acesso a um produto melhor — é a profundidade do acompanhamento e a estrutura que ele exige.</p>
    </div>

    <!-- A alternância nasce [hidden]: sem script ela não trocaria nada, e um
         controle que se mexe sem efeito é pior que controle ausente. -->
    <div class="plan-switch" role="group" aria-label="Escolha o conjunto de modelos" hidden>
      <label class="plan-switch-op">
        <input class="plan-switch-radio" type="radio" name="plan-grupo" value="pessoa" checked>
        <span class="plan-switch-txt">Pessoa física e família</span>
      </label>
      <label class="plan-switch-op">
        <input class="plan-switch-radio" type="radio" name="plan-grupo" value="empresa">
        <span class="plan-switch-txt">Empresa e holding</span>
      </label>
    </div>

    <p class="plan-anuncio visually-hidden" role="status" aria-live="polite"></p>

    <!-- A premissa que gera as faixas, ANTES dos números e no corpo da peça. -->
    <p class="plan-premissa" data-rv data-d="1">O honorário é anual, cobrado sobre o patrimônio sob assessoria e regressivo por faixa: quanto maior o patrimônio, menor o percentual. É a única remuneração da casa — não há comissão por produto, e o valor é acordado em contrato antes de qualquer aplicação.</p>

    <div class="plan-quadro" data-rv data-d="2">

      <!-- ================================================ pessoa física -->
      <div class="plan-grupo" data-plan-grupo="pessoa">
        <p class="plan-grupo-tit">Pessoa física e família</p>

        <div class="plan-set" role="group" aria-label="Modelos para pessoa física e família">

          <div class="plan-col" style="--plan-i:0">
            <h3 class="plan-nome">Acompanhamento</h3>
            <p class="plan-quem">Para quem está organizando fora do banco a primeira carteira relevante e quer alguém para chamar antes de decidir.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">A partir de R$ 1 milhão</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">A partir de 1,0% ao ano</span>
              <span class="plan-fee-nota">taxa previamente acordada, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor dedicado, com reunião trimestral</li>
              <li class="plan-item">Carteira desenhada a partir de um diagnóstico</li>
              <li class="plan-item">Relatório consolidado mensal</li>
              <li class="plan-item">Portal do cliente com a posição consolidada</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-ghost plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

          <!-- Coluna de destaque. O destaque é EDITORIAL e qualificado: diz
               para quem este modelo é mais procurado, não que ele é melhor. -->
          <div class="plan-col is-destaque" style="--plan-i:1">
            <p class="plan-tag pill pill-accent">Mais procurado por famílias em sucessão</p>
            <h3 class="plan-nome">Assessoria dedicada</h3>
            <p class="plan-quem">Para famílias que já dividem o patrimônio entre instituições e querem uma política de investimentos escrita, com o tema da sucessão na mesa.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">De R$ 5 a R$ 20 milhões</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">Entre 0,6% e 0,9% ao ano</span>
              <span class="plan-fee-nota">taxa previamente acordada, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor dedicado, com reunião mensal</li>
              <li class="plan-item">Política de investimentos escrita e revisada em comitê</li>
              <li class="plan-item">Relatório consolidado mensal, por titular</li>
              <li class="plan-item">Portal do cliente e mesa de renda fixa e exterior</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-primary plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

          <div class="plan-col" style="--plan-i:2">
            <h3 class="plan-nome">Patrimônio e legado</h3>
            <p class="plan-quem">Para famílias com holding, imóveis e participações, em que a estrutura vem antes da alocação e o horizonte é de geração.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">Acima de R$ 20 milhões</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">Entre 0,3% e 0,6% ao ano</span>
              <span class="plan-fee-nota">taxa previamente acordada, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor e especialista de patrimônio, com reunião mensal</li>
              <li class="plan-item">Política de investimentos escrita, com plano de sucessão</li>
              <li class="plan-item">Relatório consolidado mensal, por titular e por veículo</li>
              <li class="plan-item">Portal do cliente, mesa dedicada e custódia no exterior</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-ghost plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

        </div>
      </div>

      <!-- ============================================ empresa e holding -->
      <div class="plan-grupo" data-plan-grupo="empresa">
        <p class="plan-grupo-tit">Empresa e holding</p>

        <div class="plan-set" role="group" aria-label="Modelos para empresa e holding">

          <div class="plan-col" style="--plan-i:0">
            <h3 class="plan-nome">Caixa da operação</h3>
            <p class="plan-quem">Para a tesouraria da empresa: liquidez com data marcada, previsibilidade e prestação de contas à contabilidade.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">A partir de R$ 2 milhões</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">A partir de 0,8% ao ano</span>
              <span class="plan-fee-nota">taxa previamente acordada, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor dedicado, com reunião trimestral</li>
              <li class="plan-item">Política de caixa escrita com a tesouraria</li>
              <li class="plan-item">Relatório consolidado mensal para a contabilidade</li>
              <li class="plan-item">Portal do cliente com a posição da empresa</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-ghost plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

          <div class="plan-col is-destaque" style="--plan-i:1">
            <p class="plan-tag pill pill-accent">Mais procurado depois da venda de um negócio</p>
            <h3 class="plan-nome">Holding patrimonial</h3>
            <p class="plan-quem">Para o patrimônio já separado da operação, em holding constituída, com mais de um titular olhando o mesmo relatório.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">De R$ 10 a R$ 50 milhões</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">Entre 0,4% e 0,7% ao ano</span>
              <span class="plan-fee-nota">taxa previamente acordada, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor dedicado, com reunião mensal</li>
              <li class="plan-item">Política de investimentos da holding, escrita</li>
              <li class="plan-item">Relatório consolidado mensal, por veículo</li>
              <li class="plan-item">Portal do cliente e mesa de renda fixa e exterior</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-primary plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

          <div class="plan-col" style="--plan-i:2">
            <h3 class="plan-nome">Comitê e política escrita</h3>
            <p class="plan-quem">Para grupos com mais de um sócio, comitê formal e prestação de contas periódica a quem não acompanha o dia a dia.</p>
            <div class="plan-entrada">
              <span class="plan-rotulo">Patrimônio de entrada</span>
              <span class="plan-num">Acima de R$ 50 milhões</span>
            </div>
            <div class="plan-fee">
              <span class="plan-rotulo">Honorário</span>
              <span class="plan-num">A partir de 0,25% ao ano</span>
              <span class="plan-fee-nota">sob proposta, sobre o patrimônio sob assessoria</span>
            </div>
            <p class="plan-inclui-tit">O que está incluído</p>
            <ul class="plan-inclui">
              <li class="plan-item">Assessor e especialista, com reunião mensal</li>
              <li class="plan-item">Política escrita e comitê trimestral com os sócios</li>
              <li class="plan-item">Relatório consolidado mensal, por sócio e por veículo</li>
              <li class="plan-item">Portal do cliente, mesa dedicada e custódia no exterior</li>
              <li class="plan-item plan-item-chave">Sem comissão por produto</li>
            </ul>
            <a class="btn btn-ghost plan-cta" href="#conversa">Conversar sobre este modelo</a>
          </div>

        </div>
      </div>

    </div>

    <!-- A ressalva fica onde a pessoa lê o número: no fim da própria peça,
         no mesmo bloco de leitura, e não no rodapé da página. -->
    <p class="nota plan-nota" data-rv>Faixas ilustrativas, para orientar a conversa. O honorário final entra em proposta, depende da complexidade do patrimônio e da estrutura envolvida, e é acordado em contrato antes de qualquer aplicação. Nada nesta página é oferta, recomendação de investimento ou promessa de resultado.</p>

  </div>
</section>

estilo.css · 466 linhas · 18,4 KB

/* ==========================================================================
   PLANOS DE HONORÁRIOS — prefixo plan-
   Três modelos de relacionamento lado a lado, com alternância entre dois
   conjuntos (pessoa física e família / empresa e holding).

   Tokens usados:
     --accent           filete da coluna de destaque, pílula, botão primário
     --dark             tinta do texto sobre a pílula acesa e sombra da coluna
     --dark-rgb         a mesma sombra, em rgba() lendo token
     --display          face dos nomes, dos valores e da alternância
     --sans             face do texto corrido e dos rótulos
     --ease             curva única do projeto
     --fg --fg-2        tinta do nome e do texto de apoio
     --fg-muted         rótulos, ressalva, premissa
     --rule --rule-2    filete entre colunas e divisórias internas
     --radius-media     canto da superfície da coluna (0 em projeto flat)
     --radius-pill      só via .btn e .pill do core
     --sec-gap          respiro derivado, nunca clamp solto

   O ALINHAMENTO É A PEÇA. Os itens equivalentes das três colunas ficam na
   MESMA linha — é isso que permite ler na horizontal e comparar. O mecanismo
   é `subgrid`: o conjunto (.plan-set) declara doze linhas, cada coluna
   (.plan-col) ocupa todas elas com `grid-template-rows:subgrid`, e a lista
   "o que inclui" (.plan-inclui) é um segundo subgrid encaixado nas linhas 7
   a 11. Altura fixa NÃO resolveria: a altura de cada linha depende de quantas
   linhas o texto quebra, o que muda com o tema, com a largura e com a
   tradução.

   O QUE ISSO COBRA, e é a armadilha do subgrid: padding, borda e margem no
   EIXO SUBGRIDADO deslocam as faixas e desalinham as colunas. Por isso a
   coluna só tem padding-inline; o respiro vertical vem das margens dos
   próprios itens de linha, e a superfície visual da coluna é um ::before
   posicionado, que pode transbordar para fora da área de grade sem mexer em
   linha nenhuma.

   AS DOZE LINHAS, e mexer numa pede mexer nas três:
     1 pílula · 2 nome · 3 para quem · 4 patrimônio de entrada · 5 honorário
     6 rótulo da lista · 7–11 os cinco itens · 12 botão
   Trocar o número de itens da lista pede acertar `repeat(12,auto)` aqui, o
   `grid-row` da lista e o `grid-row` do botão. Não dá para derivar de uma
   variável: `repeat()` exige inteiro literal, e nenhum navegador aceita
   var() na contagem de faixas.

   O QUE ESTE ARQUIVO NÃO FAZ: esconder conjunto. Quem esconde é o script,
   com [hidden], e é por isso que sem JavaScript os dois conjuntos aparecem
   empilhados. Toda regra de troca vive sob .plan.is-live — classe que só o
   script põe.
   ========================================================================== */

.plan{
  /* Respiro interno da coluna. O horizontal é padding de verdade; o vertical
     NÃO pode ser (ver o cabeçalho), então vira o transbordo do ::before. */
  --plan-pad-x:clamp(16px,1.7vw,28px);
  --plan-pad-y:clamp(24px,2.6vw,36px);

  /* Vão entre colunas. */
  --plan-gap:clamp(16px,2.2vw,34px);

  /* Saída do conjunto que sai. O script lê o MESMO número (SAIDA em
     script.js): mudar aqui pede mudar lá, senão o conjunto some antes ou
     depois da hora. */
  --plan-saida:.26s;

  /* Atraso entre colunas na entrada. 3 colunas x 90ms = .18s de
     escalonamento — o bastante para o olho ver a fileira montar, curto o
     bastante para não virar espera. */
  --plan-escala:90ms;

  /* Largura de leitura da premissa e da ressalva. */
  --plan-prosa:76ch;
}

/* O [hidden] do navegador é display:none na folha do agente do usuário, e
   QUALQUER regra de autor com display vence essa — inclusive o display:flex
   da alternância aqui embaixo. Uma linha, no topo, cobre o componente
   inteiro. */
.plan [hidden]{display:none}

/* ==========================================================================
   CABEÇALHO
   ========================================================================== */

/* O .sec-title centra pela primitiva .sec-head do core. O apoio daqui não é
   .sec-lead, então a primitiva não o alcança: dentro de um cabeçalho
   centralizado, sem margin-inline a CAIXA dele fica à esquerda e só o texto
   centraliza — o bloco sai torto. */
.plan-head .plan-apoio{margin-inline:auto}

/* ==========================================================================
   A ALTERNÂNCIA
   Grupo de radio de verdade (ver o cabeçalho do markup): as setas do teclado
   andam e marcam junto, que é o comportamento nativo do grupo, e o `change`
   é o único evento que o script escuta.
   ========================================================================== */

.plan-switch{
  /* flex e não inline-flex: é o par width:fit-content + margin-inline:auto
     que centra a pílula. Em inline-flex a margem automática não centra
     nada. */
  display:flex;flex-wrap:wrap;justify-content:center;gap:4px;
  width:fit-content;max-width:100%;
  margin:clamp(26px,3.4vh,42px) auto 0;
  padding:4px;
  border:1px solid var(--rule);
  border-radius:var(--radius-pill);
}

/* O <label> é só a caixa de posicionamento; quem desenha a pílula é o
   <span>. Assim o estado marcado sai de `:checked ~ .plan-switch-txt`, sem
   depender de :has() para pintar o rótulo. */
.plan-switch-op{position:relative;display:inline-flex}

/* O RADIO É DE VERDADE e cobre o rótulo inteiro, em vez de ficar escondido
   num canto de 1px. Duas coisas dependem disso: o :focus-visible do core cai
   em volta da pílula, e o clique em qualquer ponto dela chega ao input sem
   precisar de for/id (que se repetiria se o componente aparecesse duas vezes
   na página). appearance:none, e não opacity:0 — com opacity:0 o anel de
   foco some junto com o widget. */
.plan-switch-radio{
  -webkit-appearance:none;appearance:none;
  position:absolute;inset:0;width:100%;height:100%;
  margin:0;padding:0;border:0;background:none;
  border-radius:var(--radius-pill);
  cursor:pointer;
}

.plan-switch-txt{
  display:inline-flex;align-items:center;justify-content:center;
  padding:11px 22px;border-radius:var(--radius-pill);
  font-family:var(--display);font-weight:700;font-size:11.5px;
  letter-spacing:.12em;text-transform:uppercase;
  color:var(--fg-muted);
  transition:background .35s var(--ease),color .35s var(--ease);
}
.plan-switch-op:hover .plan-switch-txt{color:var(--fg-2)}
.plan-switch-radio:checked ~ .plan-switch-txt{background:var(--accent);color:var(--dark)}
.plan-switch-radio:checked ~ .plan-switch-txt,
.plan-switch-op:hover .plan-switch-radio:checked ~ .plan-switch-txt{color:var(--dark)}

/* ==========================================================================
   PREMISSA E RESSALVA
   As duas ficam NO corpo da peça, e não em letra miúda de rodapé: a premissa
   antes dos números, porque é ela que os gera; a ressalva no fim do mesmo
   bloco de leitura, onde a pessoa acabou de ler a faixa.
   ========================================================================== */

.plan-premissa{
  max-width:var(--plan-prosa);
  margin:clamp(24px,3vh,34px) auto 0;
  text-align:center;
  font-size:14px;line-height:1.62;color:var(--fg-muted);
}

/* A tipografia é a da primitiva .nota do core. Fica a posição — e a medida
   pelo parafuso, porque a ressalva divide a largura de prosa com a premissa
   logo acima e as duas têm de quebrar no mesmo lugar. */
.plan-nota{
  --nota-max:var(--plan-prosa);
  margin:clamp(28px,3.6vh,42px) auto 0;
  text-align:center;
}

/* ==========================================================================
   OS CONJUNTOS
   ========================================================================== */

.plan-quadro{margin-top:clamp(26px,3.4vh,40px)}

/* Só vale sem script: com script um conjunto está sempre [hidden], e o vão
   entre eles viraria um vão morto acima do que ficou visível. */
.plan-grupo + .plan-grupo{margin-top:calc(var(--sec-gap) * .42)}
.plan.is-live .plan-grupo{margin-top:0}

/* O subtítulo do conjunto. Existe para o estado SEM script, onde os dois
   conjuntos estão empilhados e precisam de nome; com script o script o
   esconde, porque a alternância acesa já diz a mesma coisa dois centímetros
   acima. O nome acessível do conjunto não depende dele: mora no aria-label
   do próprio .plan-set, que não some. */
.plan-grupo-tit{
  text-align:center;
  font-family:var(--sans);font-size:11.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent);
  margin-top:clamp(20px,2.6vh,30px);
}

.plan-set{
  /* Os seis parafusos da forma. O bloco EMPILHADO no fim do arquivo troca só
     estes valores — é o mesmo conjunto de regras servindo as duas formas, em
     vez de duas listas de layout concorrentes. */
  --plan-cols:repeat(3,minmax(0,1fr));
  --plan-rows:repeat(12,auto);
  --plan-span:1 / -1;
  --plan-sub:subgrid;
  --plan-col-pb:0px;
  --plan-surf:calc(var(--plan-pad-y) * -1) 0;

  display:grid;
  grid-template-columns:var(--plan-cols);
  grid-template-rows:var(--plan-rows);
  column-gap:var(--plan-gap);
  /* Zero, e de propósito: com subgrid, faixa vazia + row-gap abriria vão
     morto em toda coluna que não usa aquela linha (a pílula, por exemplo, só
     existe numa das três). O respiro vertical vem das margens dos itens. */
  row-gap:0;
  /* Cria contexto de empilhamento no conjunto, para o ::before de superfície
     (z-index:-1) parar aqui em vez de mergulhar atrás do fundo da seção. */
  isolation:isolate;
  margin-top:clamp(20px,2.6vh,32px);
}

/* ==========================================================================
   A COLUNA
   ========================================================================== */

.plan-col{
  /* Filete separador (à esquerda) e filete de topo. Ficam em variável, e não
     em regra direta, porque a forma empilhada troca um pelo outro e o
     destaque troca a cor do de cima — resolver isso por variável evita três
     regras concorrentes brigando por ordem no fim do arquivo. */
  --plan-sep:0px;
  --plan-top-w:0px;
  --plan-top-c:var(--rule);

  position:relative;
  display:grid;
  grid-row:var(--plan-span);
  grid-template-rows:var(--plan-sub);
  /* Uma coluna explícita com minmax(0,…): sem ela a faixa implícita é `auto`
     e uma palavra longa (um número, uma URL) estoura a coluna em vez de
     quebrar. */
  grid-template-columns:minmax(0,1fr);
  padding-inline:var(--plan-pad-x);
  padding-block:var(--plan-col-pb);
}
.plan-col:not(:first-child){--plan-sep:1px}

/* A SUPERFÍCIE. Fica num ::before posicionado, e não no fundo da própria
   coluna, por uma razão de subgrid: a coluna não pode ter padding vertical
   sem desalinhar as faixas, e a superfície precisa transbordar para cima e
   para baixo do conteúdo. Um elemento posicionado transborda sem participar
   da grade. */
.plan-col::before{
  content:"";
  position:absolute;inset:var(--plan-surf);
  z-index:-1;
  border-radius:var(--radius-media);
  border-left:var(--plan-sep) solid var(--rule);
  border-top:var(--plan-top-w) solid var(--plan-top-c);
}

/* O DESTAQUE É DISCRETO, e isso é decisão de compliance, não de gosto: um
   filete na cor de marca, a pílula do core e um véu de elevação. Sem escala
   maior, que quebraria o alinhamento das linhas — que é justamente o que a
   peça tem de entregar —, e sem caixa berrante, que leria como "melhor
   plano". O que o destaque diz está escrito na pílula, em texto qualificado. */
.plan-col.is-destaque{
  --plan-sep:0px;
  --plan-top-w:2px;
  --plan-top-c:var(--accent);
}
.plan-col.is-destaque::before{
  background:
    linear-gradient(180deg,color-mix(in srgb,var(--accent) 8%,transparent),transparent 58%),
    color-mix(in srgb,var(--fg) 4%,transparent);
  box-shadow:0 30px 70px -34px rgba(var(--dark-rgb),.9);
}

/* -------------------------------------------------------------- as linhas */

.plan-tag{
  grid-row:1;
  justify-self:start;align-self:start;
  margin-bottom:14px;
  /* A pílula do core é caixa alta com tracking largo: numa frase inteira ela
     precisa de entrelinha, senão as duas linhas colam. */
  line-height:1.5;
}

.plan-nome{
  grid-row:2;
  font-family:var(--display);font-weight:700;
  font-size:clamp(20px,2vw,26px);letter-spacing:-.02em;line-height:1.16;
  color:var(--fg);
}

.plan-quem{
  grid-row:3;
  margin-top:12px;
  font-size:15px;line-height:1.6;color:var(--fg-2);
}

.plan-entrada{
  grid-row:4;
  margin-top:clamp(18px,2.2vw,26px);
  padding-top:16px;
  border-top:1px solid var(--rule);
}
.plan-fee{
  grid-row:5;
  margin-top:14px;
}

.plan-rotulo{
  display:block;
  font-family:var(--sans);font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--fg-muted);
}

/* A FAIXA. É aqui que mora todo número da peça — dois por coluna, doze no
   total. Em display peso 700 porque é o dado que a pessoa veio buscar; na
   cor do texto, e não na de marca, porque cor de marca em número lê como
   oferta. */
.plan-num{
  display:block;
  margin-top:7px;
  font-family:var(--display);font-weight:700;
  font-size:clamp(17px,1.5vw,21px);letter-spacing:-.015em;line-height:1.24;
  color:var(--fg);
}

/* O modelo de remuneração, colado no número. Não é rodapé nem asterisco: a
   pessoa lê "0,6% a 0,9% ao ano" e na linha seguinte lê sobre o que incide. */
.plan-fee-nota{
  display:block;
  margin-top:7px;
  font-size:12.5px;line-height:1.5;color:var(--fg-muted);
}

.plan-inclui-tit{
  grid-row:6;
  margin-top:clamp(18px,2.2vw,26px);
  padding-top:16px;
  margin-bottom:10px;
  border-top:1px solid var(--rule);
  font-family:var(--sans);font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--fg-muted);
}

/* A LISTA É UM SEGUNDO SUBGRID, encaixado nas linhas 7 a 11 do conjunto. É
   isso que alinha o terceiro item de uma coluna com o terceiro das outras
   duas, mesmo quando um deles quebra em duas linhas e os outros não.
   Sem margin e sem padding: no eixo subgridado eles deslocariam as faixas. */
.plan-inclui{
  grid-row:7 / 12;
  display:grid;
  grid-template-rows:var(--plan-sub);
  grid-template-columns:minmax(0,1fr);
}

.plan-item{
  padding-block:10px;
  border-bottom:1px solid var(--rule);
  font-size:14.5px;line-height:1.5;color:var(--fg-2);
}

/* "Sem comissão por produto" é o último item das seis colunas, sempre com o
   mesmo texto. Alinhado na mesma faixa nas três, ele lê na horizontal como
   uma linha só — que é o argumento da independência, e ele vale mais que
   qualquer superlativo. */
.plan-item-chave{color:var(--fg);border-bottom-color:var(--rule-2)}

.plan-cta{
  grid-row:12;
  align-self:end;
  margin-top:clamp(20px,2.4vw,30px);
  width:100%;
}

/* ==========================================================================
   A TROCA DE CONJUNTO — o movimento da peça
   Tudo sob .plan.is-live: sem script nenhuma destas regras existe, e os dois
   conjuntos ficam empilhados e opacos.
   ========================================================================== */

/* Estado de repouso das colunas com script: invisíveis, esperando o .is-in
   do conjunto. O escalonamento vem de --plan-i, escrito no style de cada
   coluna no markup — o que varia por item mora no item, não numa cadeia de
   :nth-child que se desalinha quando alguém troca a ordem das colunas. */
.plan.is-live .plan-col{
  opacity:0;filter:blur(12px);transform:translateY(16px);
  transition:opacity .6s var(--ease),
             filter .6s var(--ease),
             transform .6s var(--ease);
  transition-delay:calc(var(--plan-i,0) * var(--plan-escala));
}
.plan.is-live .plan-grupo.is-in .plan-col{opacity:1;filter:blur(0);transform:none}

/* Sai junto, sem escalonar: quem sai não precisa ser lido. */
.plan.is-live .plan-grupo.is-out .plan-col{
  opacity:0;filter:blur(12px);transform:translateY(-16px);
  transition-duration:var(--plan-saida);
  transition-delay:0s;
}

/* Movimento reduzido: o conjunto TROCA — a pessoa pediu a troca —, mas não
   anda. Sem esta regra o estado de repouso acima deixaria as colunas
   invisíveis para sempre. Colada à regra que desliga, como manda o §6.5. */
@media(prefers-reduced-motion:reduce){
  .plan.is-live .plan-col,
  .plan.is-live .plan-grupo.is-out .plan-col{
    opacity:1;filter:none;transform:none;transition:none;
  }
}

/* ==========================================================================
   MOBILE
   As colunas empilham. A de destaque continua reconhecível: perde o filete
   lateral e ganha o de topo na cor de marca, mais a mesma superfície.
   ========================================================================== */

@media(max-width:900px){
  .plan-set{
    /* Os mesmos seis parafusos do topo, com os valores da forma empilhada.
       Com --plan-sub:none a coluna vira uma grade comum de faixas
       implícitas e os filhos caem em ordem; os grid-row fixos (a lista em
       7/12, o botão em 12) continuam válidos, e as faixas vazias custam
       zero porque o row-gap da coluna é zero. */
    --plan-cols:minmax(0,1fr);
    --plan-rows:auto;
    --plan-span:auto;
    --plan-sub:none;
    --plan-col-pb:var(--plan-pad-y);
    --plan-surf:0;
    row-gap:clamp(26px,5vw,40px);
  }
  /* O separador vira filete de topo. As duas regras estão aqui embaixo, e
     não em variável no topo, porque só a forma empilhada as usa. */
  .plan-col:not(:first-child){--plan-sep:0px}
  .plan-col:not(:first-child):not(.is-destaque){--plan-top-w:1px}

  .plan-switch-txt{padding:10px 16px;font-size:11px;letter-spacing:.1em}
}

@media(max-width:560px){
  .plan{--plan-pad-x:16px}
  .plan-switch{width:100%}
  .plan-switch-op{flex:1 1 100%}
  .plan-switch-txt{width:100%}
}

/* ==========================================================================
   SEM SUBGRID
   Chrome 117, Firefox 71 e Safari 16 em diante têm subgrid; antes disso o
   alinhamento entre colunas não tem como existir sem altura fixa, e altura
   fixa MENTE — ela para de bater na primeira tradução do texto. A degradação
   honesta é empilhar: cada coluna passa a ser lida sozinha, de cima a baixo,
   que é exatamente a forma do celular.

   As declarações repetem as do @media acima de propósito: @media e @supports
   não se combinam num seletor só, e derivar as duas de uma terceira regra
   custaria mais leitura do que a repetição.
   ========================================================================== */

@supports not (grid-template-rows:subgrid){
  .plan-set{
    --plan-cols:minmax(0,1fr);
    --plan-rows:auto;
    --plan-span:auto;
    --plan-sub:none;
    --plan-col-pb:var(--plan-pad-y);
    --plan-surf:0;
    row-gap:clamp(26px,5vw,40px);
  }
  .plan-col:not(:first-child){--plan-sep:0px}
  .plan-col:not(:first-child):not(.is-destaque){--plan-top-w:1px}
}

script.js · 169 linhas · 6,9 KB

/* ==========================================================================
   PLANOS DE HONORÁRIOS — prefixo plan-
   A alternância entre os dois conjuntos de três colunas. Nada mais.

   O QUE ESTE SCRIPT FAZ, EM ORDEM:
     1. dá nomes únicos aos radios da alternância — sem isso, dois
        componentes na mesma página cairiam no mesmo grupo de radio e um
        apagaria a escolha do outro;
     2. põe .is-live na seção — é essa classe que liga, no CSS, o estado de
        repouso das colunas e as regras de troca. Sem script nenhuma delas
        existe;
     3. mostra a alternância (que nasce [hidden], porque sem script ela não
        trocaria nada) e esconde os subtítulos dos conjuntos, que existem
        para o estado sem script e viram repetição do rótulo aceso;
     4. esconde com [hidden] o conjunto que não está escolhido — nunca com
        opacity: bloco invisível e tabulável é armadilha;
     5. troca: saída com blur e subida do conjunto que sai, entrada com blur
        a zero e escalonamento por coluna do que entra, e um anúncio em
        aria-live para quem não vê a troca.

   O ESTADO SEM JAVASCRIPT É O ESTADO DE PARTIDA DO MARKUP: os dois conjuntos
   empilhados, cada um com o seu subtítulo. Este script esconde o que sobra —
   o contrário (CSS escondendo e script revelando) deixaria metade da peça
   invisível para quem tem o script bloqueado.

   NADA É GRAVADO. A escolha entre "pessoa física" e "empresa" vive no
   próprio radio e morre no recarregamento: sem localStorage, sem cookie,
   sem envio. A peça não coleta nada — quem coleta é o
   conversao/cta-formulario-lead, para onde os botões apontam.

   MOVIMENTO REDUZIDO: a troca continua acontecendo — a pessoa pediu por ela
   —, só que sem a fase de saída animada. O CSS zera o estado de repouso das
   colunas na mesma preferência.
   ========================================================================== */

(function () {

  var raizes = document.querySelectorAll('[data-plan]');
  if (!raizes.length) return;                        // guard silencioso

  /* Bate com --plan-saida no estilo.css. Mudar um pede mudar o outro: mais
     curto aqui e o conjunto some antes de terminar de sair; mais longo e
     fica um vão parado no meio da dobra. */
  var SAIDA = 260;

  function reduzido() {
    if (window.LIB && typeof window.LIB.reduce === 'boolean') return window.LIB.reduce;
    return matchMedia('(prefers-reduced-motion: reduce)').matches &&
           location.search.indexOf('motion=on') < 0;
  }

  function iniciar(raiz, indice) {

    var grupos = raiz.querySelectorAll('.plan-grupo');
    var chave  = raiz.querySelector('.plan-switch');
    var radios = raiz.querySelectorAll('.plan-switch-radio');
    var titulos = raiz.querySelectorAll('.plan-grupo-tit');
    var aviso  = raiz.querySelector('.plan-anuncio');

    /* Um conjunto só, ou alternância removida pelo consumidor: não há o que
       alternar, e a peça continua correta como está. Sai sem tocar em nada —
       inclusive sem pôr .is-live, que é o que esconderia as colunas. */
    if (grupos.length < 2 || !chave || radios.length < 2) return;

    var atual = null;        // .plan-grupo visível
    var saindo = null;       // .plan-grupo no meio da saída
    var timer = 0;
    var k;

    function grupoDe(valor) {
      for (var j = 0; j < grupos.length; j++) {
        if (grupos[j].getAttribute('data-plan-grupo') === valor) return grupos[j];
      }
      return null;
    }

    function rotuloDe(radio) {
      var txt = radio.parentNode ? radio.parentNode.querySelector('.plan-switch-txt') : null;
      return txt ? txt.textContent : '';
    }

    function anunciar(texto) { if (aviso) aviso.textContent = texto; }

    function entrar(g) {
      g.hidden = false;
      /* Reflow: sem ele o navegador junta o "deixou de ser display:none" e o
         "ganhou .is-in" no mesmo recálculo, e a transição não roda. */
      void g.offsetWidth;
      g.classList.add('is-in');
    }

    /* Fecha uma saída pendente na hora. Chamada tanto pelo relógio quanto
       por uma segunda troca disparada antes da primeira terminar — segurar
       as setas do teclado faz exatamente isso, e sem este atalho a peça
       ficaria com dois conjuntos no ar ou com nenhum. */
    function concluir() {
      if (timer) { clearTimeout(timer); timer = 0; }
      if (!saindo) return;
      saindo.classList.remove('is-out');
      saindo.hidden = true;
      saindo = null;
      entrar(atual);
    }

    function trocar(destino, rotulo) {
      if (!destino || destino === atual) return;
      concluir();
      var sai = atual;
      atual = destino;
      anunciar('Mostrando os modelos para ' + rotulo + '.');

      if (reduzido() || !sai) {
        if (sai) { sai.classList.remove('is-in'); sai.hidden = true; }
        entrar(destino);
        return;
      }

      sai.classList.remove('is-in');
      sai.classList.add('is-out');
      saindo = sai;
      timer = setTimeout(function () { timer = 0; concluir(); }, SAIDA);
    }

    /* ---------------------------------------------------- inicialização */

    /* Nome único por instância: o `name` do markup é o mesmo em toda cópia
       do componente, e dois grupos de radio com o mesmo nome na mesma página
       viram UM grupo — marcar a alternância de baixo apagaria a de cima. */
    for (k = 0; k < radios.length; k++) {
      radios[k].name = radios[k].name + '-' + (indice + 1);
    }

    raiz.classList.add('is-live');
    chave.hidden = false;
    for (k = 0; k < titulos.length; k++) titulos[k].hidden = true;

    /* O conjunto de partida é o do radio marcado no markup; se ninguém
       estiver marcado, é o primeiro — e aí o radio correspondente é marcado,
       para o controle não abrir mentindo sobre o que está na tela. */
    var inicial = null;
    for (k = 0; k < radios.length; k++) {
      if (radios[k].checked) { inicial = grupoDe(radios[k].value); break; }
    }
    if (!inicial) {
      inicial = grupos[0];
      for (k = 0; k < radios.length; k++) {
        if (grupoDe(radios[k].value) === inicial) radios[k].checked = true;
      }
    }
    atual = inicial;
    for (k = 0; k < grupos.length; k++) grupos[k].hidden = (grupos[k] !== inicial);
    inicial.classList.add('is-in');

    /* ---------------------------------------------------------- eventos */

    /* `change` no grupo, e não `click` no rótulo: é ele que cobre também a
       seta do teclado, que no grupo de radio move o foco e marca junto. É
       por isso que a alternância é radio e não um par de botões — as setas
       vêm de graça, sem roving tabindex escrito à mão. */
    raiz.addEventListener('change', function (e) {
      var alvo = e.target;
      if (!alvo || !alvo.classList || !alvo.classList.contains('plan-switch-radio')) return;
      trocar(grupoDe(alvo.value), rotuloDe(alvo));
    });
  }

  for (var n = 0; n < raizes.length; n++) iniciar(raizes[n], n);

})();

Três colunas lado a lado, cada uma um modelo de relacionamento da casa: nome, para quem é, a faixa de patrimônio de entrada, o honorário em faixa e a lista do que está incluído. Uma delas tem um filete na cor de marca no topo, uma pílula de contorno com um recado editorial e um véu de elevação — destaque discreto, sem escala maior e sem caixa berrante. Acima das colunas, uma alternância em pílula troca o conjunto inteiro entre "Pessoa física e família" e "Empresa e holding": o que sai desaparece com blur e subida curta, o que entra vem com blur a zero, coluna a coluna. As linhas equivalentes das três colunas ficam na mesma altura — o terceiro item de uma lista alinhado com o terceiro das outras duas —, e é isso que permite ler na horizontal e comparar.

O problema editorial é o de explicar como a casa cobra sem virar tabela de preço. Uma assessoria independente não vende plano: vende um modelo de relacionamento, cuja remuneração é uma taxa previamente acordada sobre o patrimônio sob assessoria, sem comissão por produto. Esse argumento — o da independência — só aparece quando as três colunas o repetem na mesma linha, e não quando ele vira um parágrafo solto embaixo. E como honorário de assessoria é terreno regulado, a forma da peça sai daí e não do gosto: faixa e nunca número cravado, premissa visível ao lado dos números, serviço comparado e resultado jamais.


Quando usar

Quando não usar


Padrão editorial

Slot Regra
Olho Uma palavra. "Honorários", "Modelos", "Como cobramos".
Título h2.sec-title de uma linha, com o <em> na palavra que carrega a promessa. Diz o que se vai explicar, não vende.
Apoio Duas linhas. É aqui que se diz qual é a diferença entre as colunas — "não é acesso a um produto melhor, é profundidade de acompanhamento". Sem isso a pessoa lê as três colunas como três preços.
Alternância Dois rótulos curtos, paralelos, sem verbo. "Pessoa física e família" / "Empresa e holding". Três no máximo.
Premissa Uma frase, acima das colunas, dizendo de onde sai a faixa: base de cálculo, periodicidade, regressividade e a ausência de comissão. É a linha que transforma número em informação.
Nome do modelo Uma ou duas palavras, substantivo, sóbrio. Descreve o trabalho ("Acompanhamento", "Holding patrimonial"), nunca o nível ("Essencial", "Premium", "Black").
Para quem é Uma frase, começando por "Para", descrevendo a situação e não o perfil psicológico. Duas linhas no desenho padrão; três já desequilibram a leitura horizontal.
Patrimônio de entrada Sempre faixa ou piso: "A partir de X", "De X a Y", "Acima de Y". Número redondo.
Honorário Sempre faixa: "A partir de 1,0% ao ano", "Entre 0,6% e 0,9% ao ano". Logo abaixo, em corpo menor, sobre o que incide — no mesmo bloco, nunca como asterisco.
O que inclui O mesmo número de itens nas três colunas (cinco no desenho padrão), na mesma ordem temática: quem atende e com que frequência, o que fica escrito, o que se recebe, a que se tem acesso, e como se é cobrado. É o paralelismo que faz a leitura horizontal funcionar.
Último item Idêntico nas três colunas, e é sempre a remuneração: "Sem comissão por produto". Alinhado na mesma faixa, ele lê como uma linha só atravessando a peça.
Pílula do destaque Frase qualificada e verificável ("Mais procurado por famílias em sucessão", "Mais procurado depois da venda de um negócio"). Nunca "O melhor", "Mais popular", "Recomendado".
Botão O mesmo texto nas três colunas. Texto diferente por coluna sugere caminhos diferentes onde há um só.
Ressalva No fim da peça, no mesmo bloco de leitura. Ver Compliance.

O que mantém a peça coesa: as três colunas têm de ser comparáveis frase a frase. Se uma tem "Para famílias que já dividem o patrimônio entre instituições" e a outra tem "Simplicidade", a comparação horizontal morre e sobram três cards soltos. Escreva as três listas em coluna, item a item, antes de escrever o markup.

Especificação dos assets

Nenhum. A peça é tipografia, filete e um véu — não há imagem, ícone nem logo, e isso é a forma: ícone em coluna de plano vira decoração de tabela de SaaS, que é exatamente o registro que esta peça evita. O que a seção precisa é de largura (a 1440 cada coluna mede 344px) e de uma âncora de destino para o href="#conversa" dos botões.


Compliance

Honorário de assessoria é terreno regulado, e é o compliance que desenha esta peça — não o contrário. O que o consumidor tem de rever com a área técnica do cliente antes de publicar:

  1. Os doze números. Seis faixas de patrimônio de entrada e seis faixas de honorário, todas ilustrativas. Vivem em dois lugares por coluna e só ali, sempre dentro de <span class="plan-num">: .plan-entrada e .plan-fee. O cabeçalho do markup.html diz isso em voz alta — quem for publicar troca doze spans e acabou.
  2. Faixa, nunca linha única. "A partir de", "Entre X e Y". Um percentual cravado lê como tabela de preço fechada, e honorário de assessoria não é. Se o cliente não puder publicar percentual nenhum, troque o conteúdo de .plan-num por "Sob proposta" e mantenha o resto — a peça continua de pé, e a comparação passa a ser só de serviço.
  3. A premissa fica na peça. O .plan-premissa vive acima das colunas, antes dos números, e diz base de cálculo, periodicidade, regressividade e a ausência de comissão. Não é rodapé, não é asterisco e não é title. Uma peça de honorário que esconde a premissa é propaganda, não informação.
  4. A ressalva fica onde a pessoa lê o número. O .plan-nota fecha o mesmo bloco de leitura: faixas ilustrativas, honorário final em proposta, dependente da complexidade, acordado em contrato antes de qualquer aplicação, e nada ali é oferta, recomendação ou promessa de resultado.
  5. O que se compara é serviço e remuneração — nunca resultado. Nenhuma coluna pode citar rentabilidade, retorno, desempenho passado ou meta. Nem no nome, nem na frase de "para quem é", nem na lista. A tentação aparece na coluna de cima da faixa; ela é onde o texto tem de ser mais seco.
  6. O destaque é editorial e qualificado. "Mais procurado por famílias em sucessão" diz um fato sobre a base de clientes. "O melhor plano" e "Mais popular" são juízo de valor e comparação implícita — fora. Se o compliance do cliente não aceitar nem o qualificado, existe a variação sem destaque nenhum, e ela não perde a comparação: quem compara é o alinhamento das linhas.
  7. A voz. Nenhum superlativo de mercado, nenhum nome de instituição real, nenhum logo. O modelo de remuneração é dito por extenso — taxa previamente acordada sobre o patrimônio sob assessoria, sem comissão por produto — porque é ele o argumento, e ele é verificável.

Dado pessoal. A peça não coleta nada e não grava nada: a escolha entre os dois conjuntos vive no próprio <input type="radio"> e morre no recarregamento. Sem localStorage, sem cookie, sem envio. Quem coleta é o conversao/cta-formulario-lead, para onde os botões apontam.


Como usar

<link rel="stylesheet" href="componentes/conversao/planos-honorarios/estilo.css">
<script src="componentes/conversao/planos-honorarios/script.js" defer></script>

O script lê LIB.reduce do core/motion.js, e a página precisa de uma âncora #conversa.

Ganchos

Gancho Papel
data-plan A seção. Raiz de toda busca do script; sem ela, saída silenciosa.
data-plan-grupo Casa cada .plan-grupo com o value do radio da alternância. Renomear um conjunto é trocar os dois de uma vez.
.plan-col.is-destaque A coluna destacada. Move-se de coluna trocando a classe (e a pílula) de lugar — nada no CSS presume que ela é a do meio.
.plan-tag A pílula do destaque, com o recado editorial. Só existe na coluna destacada; a linha 1 da grade continua reservada nas outras.
--plan-i Índice da coluna, no style de cada .plan-col. Multiplicador do transition-delay da entrada.
--plan-pad-x / --plan-pad-y Respiro interno da coluna. O vertical não é padding — ver gotcha.
--plan-gap Vão entre colunas.
--plan-saida Saída do conjunto, .26s. Bate com SAIDA no script.
--plan-escala Atraso entre colunas na entrada, 90ms.
--plan-prosa Largura de leitura da premissa e da ressalva, 76ch.
--plan-cols --plan-rows --plan-span --plan-sub --plan-col-pb --plan-surf Os seis parafusos da forma. A forma empilhada troca só estes valores.
--plan-sep / --plan-top-w / --plan-top-c Filete separador à esquerda e filete de topo. Em variável porque a forma empilhada troca um pelo outro.
.is-live Script vivo. Sem ela nada é escondido: é o estado sem JavaScript.
.is-in / .is-out O conjunto que está no ar e o que está saindo.
.plan-anuncio role="status" aria-live="polite": "Mostrando os modelos para Empresa e holding." Leva a primitiva .visually-hidden do core, sem regra própria.
.plan-premissa / .plan-nota A premissa antes dos números e a ressalva depois deles.

Variações


Gotchas


Histórico

Projeto Onde Data Diferenças
autoral construído do zero na biblioteca 2026-09-06 —

Origem. Não há referência única e não há uma linha copiada. O padrão — três colunas de oferta lado a lado, uma destacada, e um alternador que troca o conjunto inteiro — aparece em três famílias de site: página de preços de SaaS (o alternador mensal/anual), página de planos de operadora e de banco (pessoa física/pessoa jurídica) e página de serviços de escritório profissional. O que a biblioteca tirou de todas foi a forma da tela, não o código. O registro consolidado vai em projetos/autorais.md.

Decisões da tradução para o contrato e para o ramo:

Divergências conhecidas vs. produção: nunca rodou num site. Espere ajuste no primeiro uso real, principalmente nos textos das listas — é o paralelismo entre elas que sustenta a leitura horizontal, e ele é a primeira coisa que se perde quando o cliente reescreve uma coluna sozinha.