/* ============================================================================
   BORDADOS SMANIOTTO — DESIGN SYSTEM v1 · PADRÕES DE NEGÓCIO
   Ibitinga/SP · Grupo Smaniotto · Smaniotto · Sofisticata · Palácio dos Tapetes

   Os arranjos que só existem neste projeto: medidor de tapete sob medida,
   página de produto, faixa de vídeo, catálogos em PDF, hero e faixa das três
   linhas. No fim, o responsivo (375 / 768 / 1440) e o movimento reduzido —
   nessa ordem de propósito: regra de mesma especificidade só vence se vier por
   último. Depende das três folhas anteriores.
   ========================================================================== */

/* ── 07 PADRÕES DE NEGÓCIO ───────────────────────────────────────────────── */

/* MEDIDOR SOB MEDIDA — o componente-chave dos tapetes cortados por metro.
   O cliente digita largura × altura; o desenho responde na hora e o pedido
   sai para o WhatsApp da loja com a medida já escrita. */
.medidor { display: grid; }
/* O FORMULÁRIO É QUE É A GRADE, e não o `.medidor` em volta. Parece detalhe e
   é a coisa toda: a mesa de medição precisa morar DENTRO do formulário, entre
   os campos de medida e o seletor de cor.

   Por quê. Até 5/8/2026 a mesa era irmã do formulário, e em tela estreita as
   duas viravam uma coluna na ordem do documento: formulário inteiro primeiro,
   mesa depois. Medido num iPhone de 812px de altura: o campo de largura ficava
   em y=673 e o desenho em y=1325 — 652px abaixo, e depois dos DOIS botões de
   ação. Numa página que se chama "Digite a medida. O desenho responde.", o
   desenho respondia fora de vista, e a pega que se arrasta — a razão de a
   página funcionar no celular — ficava embaixo dos botões de fechar, onde
   ninguém ia descobri-la.

   Com a mesa dentro do formulário, a ordem do documento já é a ordem certa no
   celular: linha → medidas → DESENHO → cor → resumo → ações. Nenhuma regra de
   `order` para manter em dia.

   No desktop as duas colunas voltam por posicionamento explícito: os dois
   blocos de controle empilham na coluna 1, a mesa ocupa a coluna 2 inteira. */
.medidor__controles {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--esp-5);
}
/* Os dois blocos que sanduicham a mesa. Cada um mantém o ritmo de antes. */
.medidor__bloco { display: flex; flex-direction: column; gap: var(--esp-5); }

@media (min-width: 1081px) {
  .medidor__controles {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    column-gap: var(--esp-7); align-items: start;
  }
  .medidor__bloco:first-of-type { grid-column: 1; grid-row: 1; }
  .medidor__controles > .mesa      { grid-column: 2; grid-row: 1 / span 2;
    /* A mesa acompanha a rolagem: mexer na cor ou conferir o resumo lá embaixo
       não pode tirar da tela a única coisa que a página promete mostrar.
       `top` é a altura do cabeçalho grudento mais uma folga. */
    position: sticky; top: calc(4.5rem + var(--esp-5)); }
  .medidor__bloco:last-of-type  { grid-column: 1; grid-row: 2; }
}

.medidor__par { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--esp-3); align-items: end; }
.medidor__vezes { padding-bottom: var(--esp-3); font-family: var(--fonte-dado); color: var(--rose); }

.mesa { position: relative; padding: var(--esp-7) var(--esp-5) var(--esp-5) var(--esp-7);
        background: rgb(var(--bruma-rgb) / .05); border: 1px solid var(--borda-inversa); border-radius: var(--rad-2); }
.mesa__palco { position: relative; height: 20rem; display: grid; place-items: start; }
/* Réguas: traço a cada 10 cm, traço alto e rosa a cada metro. Ancoradas no
   canto de origem do palco, que é de onde a peça é medida. */
.mesa__regua { position: absolute; background-repeat: repeat; }
.mesa__regua--topo { top: calc(var(--esp-5) * -1); left: 0; right: 0; height: var(--esp-4);
  background-image: repeating-linear-gradient(90deg, var(--rose) 0 2px, transparent 2px var(--px-metro, 60px)),
                    repeating-linear-gradient(90deg, rgb(var(--bruma-rgb) / .38) 0 1px, transparent 1px calc(var(--px-metro, 60px) / 10));
  background-size: 100% 100%, 100% 42%; background-position: bottom, bottom; }
.mesa__regua--lado { left: calc(var(--esp-5) * -1); top: 0; bottom: 0; width: var(--esp-4);
  background-image: repeating-linear-gradient(0deg, var(--rose) 0 2px, transparent 2px var(--px-metro, 60px)),
                    repeating-linear-gradient(0deg, rgb(var(--bruma-rgb) / .38) 0 1px, transparent 1px calc(var(--px-metro, 60px) / 10));
  background-size: 100% 100%, 42% 100%; background-position: right, right; }
.tapete-previa {
  position: relative; display: grid; place-items: center; text-align: center;
  background: rgb(var(--rose-rgb) / .12);
  outline: var(--fio-espessura) dashed var(--rose); outline-offset: -6px;
  transition: width var(--dur-2) var(--saida), height var(--dur-2) var(--saida);
}
.tapete-previa::after { content: ''; position: absolute; inset: 0;
  background-image: repeating-linear-gradient(45deg, rgb(var(--bruma-rgb) / .07) 0 2px, transparent 2px 7px); }
.tapete-previa__medida { position: relative; z-index: 1; font-family: var(--fonte-dado); font-size: var(--t-auxiliar);
                         color: var(--algodao); background: rgb(var(--tinta-rgb) / .6); padding: var(--esp-1) var(--esp-2); }
.resumo-medida { display: flex; flex-wrap: wrap; gap: var(--esp-5); padding-top: var(--esp-4); border-top: 1px dashed var(--borda-inversa); }
.resumo-medida__valor { font-family: var(--fonte-titulo); font-size: var(--t-h3); font-variation-settings: 'opsz' 72, 'SOFT' 40; color: var(--algodao); }

/* Mesa clara — a mesma mesa de medição sobre fundo claro, para usar dentro do
   modal de medida que abre a partir do card do tapete. */
.mesa--clara { background: rgb(var(--tinta-rgb) / .03); border-color: var(--borda); }
.mesa--clara .mesa__palco { height: 12rem; }
.mesa--clara .mesa__regua--topo {
  background-image: repeating-linear-gradient(90deg, var(--carmim) 0 2px, transparent 2px var(--px-metro, 60px)),
                    repeating-linear-gradient(90deg, rgb(var(--tinta-rgb) / .3) 0 1px, transparent 1px calc(var(--px-metro, 60px) / 10)); }
.mesa--clara .mesa__regua--lado {
  background-image: repeating-linear-gradient(0deg, var(--carmim) 0 2px, transparent 2px var(--px-metro, 60px)),
                    repeating-linear-gradient(0deg, rgb(var(--tinta-rgb) / .3) 0 1px, transparent 1px calc(var(--px-metro, 60px) / 10)); }
.mesa--clara .tapete-previa { background: rgb(var(--carmim-rgb) / .09); outline-color: var(--carmim); }
.mesa--clara .tapete-previa::after {
  background-image: repeating-linear-gradient(45deg, rgb(var(--tinta-rgb) / .06) 0 2px, transparent 2px 7px); }
.mesa--clara .tapete-previa__medida { background: rgb(var(--tinta-rgb) / .78); }
.mesa--clara .resumo-medida { border-top-color: var(--borda); }
.mesa--clara .resumo-medida__valor { color: var(--texto); }

/* Modal de medida — cabeçalho com a foto do tapete que originou o clique. */
.modal { --sob: var(--superficie); }
.medida-peca { display: flex; align-items: center; gap: var(--esp-3); }
.medida-peca img { width: 3.5rem; height: 3.5rem; object-fit: cover; border-radius: var(--rad-1); flex: none; }
.medida-corpo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: var(--esp-5); align-items: start; }
@media (max-width: 640px) { .medida-corpo { grid-template-columns: minmax(0, 1fr); } }

/* PÁGINA DE PRODUTO ---------------------------------------------------------
   Composição de tudo o que já existe no sistema: galeria com lupa, ficha,
   chips de cor, medidor e as duas ações (juntar no orçamento / falar agora). */
/* Duas colunas com papéis distintos: à esquerda o cliente vê e ganha confiança;
   à direita ele decide e pede. A coluna de decisão fica curta de propósito. */
.produto { display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
           gap: var(--esp-5) var(--esp-7); align-items: start; }
.produto .galeria         { grid-column: 1; grid-row: 1; }
.produto .videos          { grid-column: 1; grid-row: 2; }
.produto .produto__extras { grid-column: 1; grid-row: 3; }
.produto .produto__painel { grid-column: 2; grid-row: 1 / 4; }

.migalha { display: flex; flex-wrap: wrap; align-items: center; gap: var(--esp-2);
           font-size: var(--t-auxiliar); color: var(--texto-brando); margin-bottom: var(--esp-5); }
.migalha a:hover { color: var(--carmim); text-decoration: underline; text-underline-offset: var(--desloca-sublinhado); }
.migalha svg { width: .7rem; height: .7rem; opacity: .5; }
.migalha [aria-current] { color: var(--texto); font-weight: var(--peso-medio); }

/* Galeria: miniaturas na lateral, palco com lupa dentro da própria caixa. */
.galeria { display: grid; grid-template-columns: 4.75rem minmax(0, 1fr); gap: var(--esp-3); }
/* Cor com UMA foto não tem fita, e sem fita a coluna dela não pode existir: o
   palco cairia nos 4,75rem reservados para as miniaturas e a foto do produto
   apareceria do tamanho de uma miniatura, com o resto da caixa em branco. Quem
   marca é o PHP, que já sabe quantas fotos a cor tem. */
.galeria--sem-fita { grid-template-columns: minmax(0, 1fr); }
.galeria__fitas { display: flex; flex-direction: column; gap: var(--esp-3); }
.galeria__fita { position: relative; padding: 0; border: 0; background: none; cursor: pointer;
                 border-radius: var(--rad-2); overflow: hidden; aspect-ratio: 4 / 3;
                 box-shadow: inset 0 0 0 1px var(--borda);
                 transition: box-shadow var(--dur-1) var(--suave), transform var(--dur-2) var(--saida); }
.galeria__fita img { width: 100%; height: 100%; object-fit: cover; }
.galeria__fita:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px var(--borda-forte); }
.galeria__fita[aria-current='true'] { box-shadow: inset 0 0 0 2px var(--carmim); }

.galeria__palco { position: relative; margin: 0; aspect-ratio: 4 / 3; overflow: hidden;
                  border-radius: var(--rad-2); background: var(--bruma); cursor: zoom-in; }
.galeria__palco img { width: 100%; height: 100%; object-fit: cover; }
/* A lupa é uma segunda camada com a mesma foto ampliada, posicionada pelo
   ponteiro. Fica dentro da caixa — não abre painel flutuante. */
.galeria__lupa { position: absolute; inset: 0; opacity: 0; pointer-events: none;
                 background-image: var(--foto); background-repeat: no-repeat;
                 background-size: calc(var(--zoom, 2) * 100%);
                 background-position: var(--zx, 50%) var(--zy, 50%);
                 transition: opacity var(--dur-2) var(--suave); }
.galeria__palco:hover .galeria__lupa, .galeria__palco:focus-within .galeria__lupa { opacity: 1; }
/* ⚠️ FECHAR A JANELA NÃO PODE DEIXAR A LUPA ACESA (fase 17C).
   A regra acima acende a lupa com o foco DENTRO do palco, e o botão que abre a
   foto em tela cheia mora ali dentro. Ao fechar a janela o foco volta para ele
   — como deve, e é conquista da fase 17 —, `:focus-within` é satisfeito, e a
   foto fica ampliada sozinha, sem ninguém pedir. Clicar fora "conserta", e é
   justamente isso que parece defeito.

   A distinção que faltava é entre foco de TECLADO e foco herdado de clique:
   `:focus-visible` a faz, `:focus-within` não. Com ela, a lupa acende
   exatamente quando o contorno de foco aparece — as duas coisas passam a dizer
   a mesma frase, "este botão está com o foco do teclado", e nunca se
   contradizem na tela.

   O `:not(:hover)` está aqui porque o ponteiro sobre a foto manda mais do que
   qualquer foco: sem ele, o foco herdado de um clique apagaria a lupa debaixo
   do próprio ponteiro que a pediu.

   ONDE `:has()` NÃO EXISTIR, NADA DISTO ACONTECE: o navegador descarta o
   `@supports` inteiro, a regra de cima continua valendo sozinha e o pior caso
   volta a ser o comportamento de hoje — lupa acesa demais. Nunca "sem lupa no
   teclado", que seria trocar um incômodo visual por uma perda de
   acessibilidade. */
@supports selector(:has(*)) {
  .galeria__palco:focus-within:not(:hover):not(:has(:focus-visible)) .galeria__lupa { opacity: 0; }
}
.galeria__aviso { position: absolute; left: var(--esp-3); bottom: var(--esp-3); z-index: 2;
                  display: inline-flex; align-items: center; gap: var(--esp-2);
                  padding: var(--esp-2) var(--esp-3); border-radius: var(--rad-total);
                  background: rgb(var(--algodao-rgb) / .92); color: var(--texto-brando);
                  transition: opacity var(--dur-1) var(--suave); }
.galeria__aviso svg { width: .85rem; height: .85rem; }
.galeria__palco:hover .galeria__aviso { opacity: 0; }

/* O CLIQUE QUE ABRE A FOTO EM TELA CHEIA (fase 17) — um botão transparente do
   tamanho do palco. Ele nasce `hidden` no HTML e quem o revela é o produto.js,
   porque sem JavaScript não existe janela para abrir.

   Fica ACIMA da lupa (z-index 3 contra os 2 da etiqueta) para receber o clique
   em qualquer ponto da foto, e não pinta nada: a única coisa que ele acrescenta
   à tela é o contorno de foco, que vem da regra de documento do base.css. */
.galeria__ampliar { position: absolute; inset: 0; z-index: 3; padding: 0; border: 0;
                    background: none; cursor: zoom-in; border-radius: inherit; }

/* Duas frases para o mesmo canto: "passe o mouse" onde há ponteiro, "toque"
   onde não há. O padrão é a do ponteiro; a do toque só aparece na consulta
   abaixo. */
.galeria__aviso-toque { display: none; }

@media (hover: none) {
  .galeria__palco { cursor: default; }
  .galeria__lupa { display: none; }
  /* A ETIQUETA CONTINUA ESCONDIDA EM TELA DE TOQUE — a menos que exista o que
     ela promete. `galeria--ampliavel` é escrita pelo produto.js, e só ele:
     sem JavaScript, tocar na foto não faz nada, e uma etiqueta convidando ao
     toque seria promessa que a tela não cumpre. */
  .galeria__aviso { display: none; }
  /* ⚠️ NO CELULAR ELA SOBE PARA O CANTO DE CIMA, E ENCOLHE (fase 17B).
     No lugar de onde ela saiu — a base da foto — é exatamente onde fica a
     barra bordada de uma colcha, que é o que a cliente abriu a página para
     ver. Uma pastilha branca ali é tarja sobre o produto, e vale para ela a
     mesma régua que proíbe mostrar uma aproximação do produto no lugar do
     produto.

     Ela CONTINUA ensinando o gesto: mesma frase, mesma pastilha, mesmo ícone
     — quem dá a descoberta é ela, e sem ela ninguém adivinha que a foto abre.
     O que muda é tamanho e canto. Medido em 375 px na página do Kit Prime:
     228,8 × 30,8 px (8,39% da área da foto) passou a 158,8 × 21,6 px (4,07%)
     — metade da tarja —, e a base da foto ficou limpa.

     A tipografia menor é do sistema (`--t-micro`), e a tracking volta ao
     `--tr-normal`: a caixa alta com os 0,18em do `.rotulo` é o que mais
     alargava a pastilha, e aqui a largura é justamente o que a cobria. */
  .galeria--ampliavel .galeria__aviso {
    display: inline-flex; left: auto; bottom: auto;
    right: var(--esp-2); top: var(--esp-2);
    gap: var(--esp-1); padding: var(--esp-1) var(--esp-2);
    font-size: var(--t-micro); letter-spacing: var(--tr-normal);
  }
  .galeria--ampliavel .galeria__aviso-ponteiro { display: none; }
  .galeria--ampliavel .galeria__aviso-toque { display: inline; }
}

.produto__painel { display: flex; flex-direction: column; gap: var(--esp-5); }
.produto__grupo { display: flex; flex-direction: column; gap: var(--esp-3);
                  padding-top: var(--esp-5); border-top: 1px dashed var(--borda); }
.produto__medida { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--esp-3); align-items: end; }
.produto__vezes { padding-bottom: var(--esp-3); font-family: var(--fonte-dado); color: var(--carmim); }
.produto__acoes { display: flex; flex-direction: column; gap: var(--esp-3); }
.produto__extras { display: flex; flex-direction: column; }
.produto__garantias { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--esp-3);
                      padding-block: var(--esp-4); border-top: 1px dashed var(--borda); }
.produto__garantia { display: flex; flex-direction: column; gap: var(--esp-1); }
.produto__garantia svg { width: 1.15rem; height: 1.15rem; color: var(--carmim); }

/* VÍDEO DA PEÇA ─────────────────────────────────────────────────────────────
   Decisão: o vídeo NÃO entra no carrossel de fotos. Motivo concreto — 106 dos
   108 vídeos do acervo são verticais 9:16 a 478×850, e o palco da galeria é
   4:3 horizontal. Encaixar um no outro exige cortar o vertical (decepa o
   produto) ou deitar a foto (desperdiça a foto). Some-se que só 39% dos
   produtos têm vídeo: se o vídeo morasse na galeria, a galeria teria dois
   comportamentos diferentes dependendo do produto.
   Então o vídeo ganha faixa própria, logo abaixo da galeria, e abre num
   reprodutor vertical em modal — o formato em que ele foi filmado. */
.videos { display: flex; flex-direction: column; gap: var(--esp-3);
          padding-block: var(--esp-4); border-top: 1px dashed var(--borda); }
/* align-items:flex-start é obrigatório: o padrão `stretch` iguala a altura de
   todos os cartões e anula o aspect-ratio do cartão horizontal. */
.videos__fila { display: flex; align-items: flex-start; gap: var(--esp-3);
                overflow-x: auto; padding-bottom: var(--esp-2); }
/* O cartão herda a forma do vídeo: em pé para vertical, deitado para
   horizontal. Assim a pessoa já sabe o formato antes de clicar, e o poster
   nunca é cortado para caber numa moldura que não é a dele. */
.video-cartao {
  position: relative; flex: none; width: 5rem; aspect-ratio: 9 / 16;
  padding: 0; border: 0; background: var(--bruma); border-radius: var(--rad-2);
  overflow: hidden; cursor: pointer; box-shadow: inset 0 0 0 1px var(--borda);
  transition: transform var(--dur-2) var(--saida), box-shadow var(--dur-1) var(--suave);
}
.video-cartao--horizontal { width: 8.9rem; aspect-ratio: 16 / 9; }
/* Selo de origem: quem vê já sabe que abre no YouTube. */
.video-cartao__fonte { position: absolute; top: var(--esp-1); right: var(--esp-1); z-index: 1;
  padding: .1rem var(--esp-1); border-radius: var(--rad-1); background: rgb(var(--tinta-rgb) / .72);
  color: var(--algodao); font-size: var(--t-nano); font-weight: var(--peso-forte);
  letter-spacing: var(--tr-chip); text-transform: uppercase; }
.video-cartao img { width: 100%; height: 100%; object-fit: cover; }
.video-cartao::after { content: ''; position: absolute; inset: 0; background: var(--grad-veu); opacity: .55; }
.video-cartao__play { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; }
.video-cartao__play span { display: grid; place-items: center; width: 1.85rem; height: 1.85rem;
  border-radius: var(--rad-total); background: rgb(var(--algodao-rgb) / .94); color: var(--carmim);
  transition: transform var(--dur-2) var(--saida); }
.video-cartao__play svg { width: .9rem; height: .9rem; margin-left: .1rem; }
.video-cartao__dur { position: absolute; left: var(--esp-1); bottom: var(--esp-1); z-index: 1;
  padding: .1rem var(--esp-1); border-radius: var(--rad-1); background: rgb(var(--tinta-rgb) / .72);
  color: var(--algodao); font-family: var(--fonte-dado); font-size: var(--t-micro); }
.video-cartao:hover { transform: translateY(-3px); box-shadow: inset 0 0 0 2px var(--carmim), var(--elev-2); }
.video-cartao:hover .video-cartao__play span { transform: scale(1.12); }

/* Reprodutor vertical — moldura 9:16 com controles nativos.
   Controles nativos de propósito: teclado, leitor de tela, velocidade e tela
   cheia vêm prontos e são os que qualquer pessoa já conhece. O sistema só
   desenha a moldura em volta. */
.modal--video { width: min(30rem, calc(100% - var(--esp-5) * 2)); }
/* Limitado pela ALTURA, não pela largura: um 9:16 preso à largura estoura a
   tela e empurra a navegação para fora do modal. Como o vídeo é 478 px nativo,
   qualquer largura resultante abaixo disso ainda fica nítida. */
.player { position: relative; margin-inline: auto; height: min(56dvh, 30rem); width: auto;
          max-width: 100%; aspect-ratio: var(--proporcao, 9 / 16); background: var(--tinta);
          border-radius: var(--rad-2); overflow: hidden; }
/* Deitado: manda a largura, não a altura — senão sobra moldura preta em cima
   e embaixo e o vídeo fica minúsculo no meio. */
.player--horizontal { height: auto; width: 100%; max-width: 28rem; }
.player video, .player iframe { display: block; width: 100%; height: 100%; border: 0;
                                object-fit: contain; background: var(--tinta); }
.player__capa { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.player__capa[hidden], .player video[hidden] { display: none; }
/* Alvo grande e explícito sobre o poster. Os controles nativos do navegador
   nem sempre se pintam antes do primeiro toque com preload="none", e este
   site atende tanto representante quanto cliente final — o "assistir" tem
   que estar na cara. Some depois do primeiro play e devolve o comando aos
   controles nativos. */
.player__play { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: var(--esp-3);
  background: rgb(var(--tinta-rgb) / .28); border: 0; cursor: pointer; color: var(--algodao);
  font-size: var(--t-rotulo); font-weight: var(--peso-forte); letter-spacing: var(--tr-rotulo);
  text-transform: uppercase; transition: opacity var(--dur-2) var(--suave); }
.player__play span { display: grid; place-items: center; width: 3.5rem; height: 3.5rem;
  border-radius: var(--rad-total); background: var(--algodao); color: var(--carmim);
  box-shadow: var(--elev-2); transition: transform var(--dur-2) var(--saida); }
.player__play svg { width: 1.4rem; height: 1.4rem; margin-left: .15rem; }
.player__play:hover span { transform: scale(1.08); }
.player__play[hidden] { display: none; }
.player__passo { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-3); }
.player__passo[hidden] { display: none; }
.player__contagem { font-family: var(--fonte-dado); font-size: var(--t-auxiliar); color: var(--texto-brando); }

/* A FOTO EM TELA CHEIA ──────────────────────────────────────────────────────
   A janela que abre ao clicar na foto grande da peça. É o `.modal` do sistema
   com um modificador só, como o `.modal--video` logo acima: véu, abertura, Esc,
   clique fora, foco preso e foco devolvido são do site.js, e não se repetem.

   O modificador é MEDIDA, e nada mais: 66rem contra as 46rem do modal de
   texto, porque aqui o conteúdo é a foto e cada rem a menos é produto que a
   cliente não vê. É o mesmo raciocínio das 58rem do escolhedor de foto do
   painel — e o mesmo do caminho contrário, as 30rem do modal de vídeo, que é
   estreito porque o vídeo é vertical. */
/* ⚠️ AS DUAS MEDIDAS DA JANELA MORAM AQUI, E SÓ AQUI (fase 17B). A altura da
   foto é a da janela menos o recuo do corpo — se os três números fossem
   escritos em três lugares, mudar um deixaria os outros mentindo, que foi
   exatamente o que aconteceu enquanto a foto tinha um teto próprio de 72dvh:
   ele havia sido escolhido para caber DEBAIXO do cabeçalho, e o cabeçalho não
   existe mais desde 25/8/2026. A conta abaixo é a mesma nos dois tamanhos de
   tela, e no celular ela chega sozinha em 100dvh porque lá o recuo é zero. */
.modal--foto { --altura-janela: min(92dvh, 56rem); --recuo-janela: var(--esp-4);
               width: min(66rem, calc(100% - var(--esp-5) * 2));
               max-height: var(--altura-janela); }
.modal--foto .modal__corpo { padding: var(--recuo-janela); }

/* ⚠️ A MOLDURA TEM O TAMANHO DA FOTO, E NÃO O DA JANELA. `align-self: center`
   é o que faz isso: sem ele o `.modal__corpo`, que é uma coluna flex, estica a
   moldura de ponta a ponta e sobra uma faixa de bruma de cada lado da foto —
   116 px por lado em 1440, medido antes da linha existir. A foto aqui não é
   cortada por nada: `max-width` e `max-height` a seguram, e a proporção é a
   dela, seja 4:3 ou não (52 fotos do acervo vieram de original pequeno e não
   são). Cortar seria esconder da cliente justamente a parte que ela clicou
   para ver. */
.foto-cheia { position: relative; margin: 0; align-self: center; max-width: 100%;
              background: var(--bruma); border-radius: var(--rad-2); overflow: hidden;
              /* ⚠️ ESTA LINHA É O QUE IMPEDE O DESLIZE DE BRIGAR COM A ROLAGEM.
                 `pan-y` entrega o eixo vertical ao navegador — a página rola
                 normalmente com o dedo em cima da foto — e reserva o horizontal
                 para o script. Sem ela os dois disputam o mesmo gesto, e o
                 resultado é a tela travando de lado no meio de uma rolagem. */
              touch-action: pan-y; }
.foto-cheia__trilho { position: relative; display: block; }
/* Enquanto o dedo está na tela não há transição nenhuma: a foto acompanha o
   movimento quadro a quadro. A classe abaixo entra só na hora de assentar —
   quando o dedo solta —, e some assim que a troca termina. */
.foto-cheia__trilho--assentando { transition: transform var(--dur-2) var(--saida); }
.foto-cheia__quadro { display: block; max-width: 100%;
                      max-height: calc(var(--altura-janela) - var(--recuo-janela) * 2);
                      width: auto; height: auto; }
/* As vizinhas ocupam exatamente a caixa da foto do meio e ficam encostadas nela,
   uma de cada lado, fora do que a moldura mostra. */
.foto-cheia__vizinha { position: absolute; inset: 0; width: 100%; height: 100%;
                       object-fit: contain; background: var(--bruma); }
.foto-cheia__vizinha--antes  { translate: -100% 0; }
.foto-cheia__vizinha--depois { translate: 100% 0; }

/* AS SETAS E O × ficam SOBRE a foto, que é onde a mão já está — no vídeo as
   setas estão acima da moldura porque disputariam espaço com a barra de
   controle nativa, e aqui não há barra nenhuma. `--alt-controle` é 44px, o
   alvo de toque mínimo, e é o mesmo token que dá altura a todo campo e botão
   do sistema.

   ⚠️ O × ENTROU NESTA REGRA EM 25/8/2026 (fase 17B), quando o cabeçalho da
   janela saiu. Ele é a MESMA pastilha das setas de propósito: os três botões
   flutuam sobre a mesma foto, e um deles com outra roupa — o `.btn--icone`
   quadrado do cabeçalho, desenhado para pousar sobre superfície opaca — seria
   um segundo idioma para a mesma situação. O alvo não encolheu: era 44 × 44 no
   cabeçalho e continua 44 × 44 aqui. */
.foto-cheia__seta, .foto-cheia__fechar {
                    position: absolute; z-index: 2;
                    display: grid; place-items: center;
                    width: var(--alt-controle); height: var(--alt-controle);
                    padding: 0; border: 0; border-radius: var(--rad-total); cursor: pointer;
                    background: rgb(var(--algodao-rgb) / .92); color: var(--texto);
                    box-shadow: var(--elev-2);
                    transition: background var(--dur-1) var(--suave), transform var(--dur-2) var(--saida); }
.foto-cheia__seta { top: 50%; translate: 0 -50%; }
.foto-cheia__seta:hover, .foto-cheia__fechar:hover { background: var(--algodao); transform: scale(1.06); }
.foto-cheia__seta svg, .foto-cheia__fechar svg { width: 1.1rem; height: 1.1rem; }
.foto-cheia__seta--volta { left: var(--esp-3); }
.foto-cheia__seta--segue { right: var(--esp-3); }
.foto-cheia__fechar { top: var(--esp-3); right: var(--esp-3); }

/* O contador é a mesma pastilha da etiqueta da lupa, no canto de baixo: mesmo
   raio, mesmo fundo, mesma tinta. Uma pastilha nova aqui seria um segundo
   idioma para a mesma ideia. */
.foto-cheia__conta { position: absolute; left: 50%; bottom: var(--esp-3); z-index: 2;
                     translate: -50% 0;
                     padding: var(--esp-2) var(--esp-3); border-radius: var(--rad-total);
                     background: rgb(var(--algodao-rgb) / .92); color: var(--texto-brando); }

/* Combinação de variação indisponível — some do caminho sem sumir da tela. */
.opcao--fora { opacity: .55; cursor: not-allowed; }
.opcao--fora .opcao__texto s { text-decoration-color: var(--erro); }

/* Sanfona — especificação longa que não precisa ficar aberta o tempo todo. */
.sanfona { border-top: 1px dashed var(--borda); }
.sanfona__gatilho { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-3);
                    width: 100%; padding: var(--esp-4) 0; background: none; border: 0; cursor: pointer;
                    font-size: var(--t-corpo-sm); font-weight: var(--peso-medio); text-align: left;
                    transition: color var(--dur-1) var(--suave); }
.sanfona__gatilho::-webkit-details-marker { display: none; }
.sanfona__gatilho:hover { color: var(--carmim); }
.sanfona__sinal { display: grid; place-items: center; width: 1.5rem; height: 1.5rem; flex: none;
                  border: 1px solid var(--borda); border-radius: var(--rad-1);
                  transition: transform var(--dur-2) var(--saida), background var(--dur-1) var(--suave); }
.sanfona__sinal svg { width: .75rem; height: .75rem; }
.sanfona[open] .sanfona__sinal { transform: rotate(45deg); background: var(--carmim); color: var(--algodao); border-color: var(--carmim); }
.sanfona__corpo { padding-bottom: var(--esp-4); animation: sanfona-abrir var(--dur-3) var(--saida); }
@keyframes sanfona-abrir { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* CATÁLOGOS PDF */
.card-catalogo { display: grid; grid-template-columns: 7rem 1fr; gap: var(--esp-4); padding: var(--esp-4);
                 background: var(--superficie-alta); border: 1px solid var(--borda); border-radius: var(--rad-2);
                 transition: transform var(--dur-2) var(--saida), box-shadow var(--dur-2) var(--saida); }
.card-catalogo:hover { transform: translateY(-3px); box-shadow: var(--elev-2); }
.card-catalogo img { width: 100%; aspect-ratio: 5 / 7; object-fit: cover; border-radius: var(--rad-1); }
.card-catalogo__corpo { display: flex; flex-direction: column; gap: var(--esp-3); align-items: flex-start; }

/* PÁGINAS INSTITUCIONAIS (fase 11) — revenda, fábrica, contato, privacidade.
   Quatro páginas de texto que dividem o mesmo esqueleto: cabeça de seção,
   títulos de nível dois espaçados, e blocos. Não têm componente próprio quase
   nenhum — o que elas fazem é montar os que já existem numa ordem que responde
   perguntas. Foi a decisão de projeto: `.bloco`, `.grade`, `.card-categoria`,
   `.card-catalogo`, `.badge` e `.aviso` já estavam prontos, e três telas novas
   não justificam três componentes novos. */
.institucional__titulo { margin-top: var(--esp-8); margin-bottom: var(--esp-4); }
.institucional__legenda { margin-top: calc(var(--esp-4) * -1); margin-bottom: var(--esp-5); max-width: var(--largura-texto); }
.institucional__blocos, .institucional__condicoes, .institucional__canais, .institucional__linhas { margin-top: var(--esp-5); }
.institucional__blocos .bloco { display: flex; flex-direction: column; gap: var(--esp-3); }
/* A coluna de saída da página da fábrica: dois botões empilhados, alinhados ao
   topo do bloco vizinho em vez de esticados na altura dele. */
.institucional__saida { display: flex; flex-direction: column;
                        justify-content: flex-start; align-items: stretch; gap: var(--esp-3); }

/* A HERO DAS INSTITUCIONAIS. Metade da altura da home: estas páginas abrem com
   presença, mas o conteúdo delas é o que importa, e uma dobra de tela inteira
   faria a pessoa rolar às cegas antes de chegar nele. */
.hero--institucional { min-height: 62vh; }

/* O FECHO ESCURO. Toda institucional termina oferecendo o passo seguinte —
   página que informa e não aponta para lugar nenhum é um beco com decoração. */
.institucional__fecho { position: relative; overflow: hidden; }
.institucional__brilho { top: calc(var(--esp-9) * -1); right: calc(var(--esp-9) * -1);
                         width: var(--largura-coluna); height: var(--largura-coluna); }
.institucional__fecho .institucional__blocos { margin-top: 0; align-items: center; }
.institucional__fecho-texto { color: rgb(var(--bruma-rgb) / .78); max-width: var(--largura-texto);
                              margin: var(--esp-3) 0 var(--esp-5); }
.institucional__fecho .endereco { color: var(--algodao); }
.institucional__fecho-fixo { color: var(--rose); margin-top: var(--esp-3); }
/* O fecho centrado da fábrica: três linhas e dois botões, o arremate da página. */
.institucional__fecho-grade { display: grid; justify-items: center; text-align: center; gap: var(--esp-3); }
.institucional__fecho-grade .institucional__fecho-texto { margin: 0 0 var(--esp-3); }
.institucional__arabesco { width: 100%; max-width: 16rem; margin-bottom: var(--esp-2); }

/* A página de privacidade é texto corrido, e texto corrido tem largura de
   leitura. Sem isto a linha atravessa 1240px e o olho perde a volta. */
.institucional--texto .institucional__secao { margin-top: var(--esp-7); max-width: var(--largura-texto);
  /* Coluna com respiro entre os filhos: o bloco final da política empilha
     endereço, telefone e botão, e sem isto os três se encostavam. */
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--esp-4); }
.institucional--texto .institucional__secao h2 { margin-bottom: calc(var(--esp-4) * -1 + var(--esp-1)); }
.institucional--texto .aviso { max-width: var(--largura-texto); margin-top: var(--esp-5); }
.privacidade__data { margin-top: var(--esp-3); }
/* A SEÇÃO QUE TEM ENDEREÇO PRÓPRIO — hoje só `#medicao`, para onde o link "Como
   funciona" do aviso de cookies leva (fase 19A). Sem o recuo, o cabeçalho, que
   gruda no alto da tela, cobre o título da seção na chegada. O botão "Mudar
   minha escolha" não precisa de regra: o `gap` da coluna já o afasta do texto. */
.institucional--texto .institucional__secao[id] { scroll-margin-top: calc(var(--alt-cabecalho) + var(--esp-5)); }
/* A costura logo abaixo do título: separa a pergunta ("o que este site guarda")
   da resposta, e é o mesmo divisor que o resto do site usa entre seções. */
.institucional--texto .costura { max-width: var(--largura-texto); margin-top: var(--esp-5); }

/* A CONDIÇÃO — rótulo pequeno em cima, número grande embaixo.
   É a mesma leitura da faixa de números da hero ("35+ anos / de fábrica") e do
   resumo do medidor ("Área / 3,45 m²"), e é de propósito: quem revende compara
   fábrica com fábrica, e o que decide é o número, não o adjetivo em volta dele.
   Por isso o pedido mínimo aparece ANTES dos argumentos de venda, nesta forma. */
.condicao { display: grid; gap: var(--esp-1); padding: var(--esp-4) 0;
            border-top: var(--fio-espessura) solid var(--borda); }
.condicao__valor { font-family: var(--fonte-titulo); font-size: var(--t-h4);
                   font-variation-settings: 'opsz' 48, 'SOFT' 40; color: var(--texto); }

/* LISTA MARCADA — item com visto no lugar do ponto. Serve para o que a fábrica
   oferece e para o que o site não faz; nos dois casos a leitura é "isto está
   garantido", que é o que o visto diz e o ponto não diz. */
.lista-marcada { display: grid; gap: var(--esp-3); list-style: none; padding: 0; }
.lista-marcada li { display: flex; align-items: flex-start; gap: var(--esp-3); font-size: var(--t-corpo); }
.lista-marcada svg { flex: none; width: 1rem; height: 1rem; margin-top: .25rem; color: var(--carmim); }
.secao--tinta .lista-marcada svg { color: var(--rose); }

/* O CANAL DE CONTATO — ícone, para que serve, e o botão. O texto vem ANTES do
   número porque a pergunta de quem chega é "qual desses é o meu?", e não "qual
   é o número". Três canais sem essa frase fazem o lojista cair na fila do
   consumidor. */
.canal { display: flex; flex-direction: column; gap: var(--esp-3); padding: var(--esp-5);
         background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--rad-2); }
.canal__icone { width: var(--esp-6); height: var(--esp-6); color: var(--carmim); }
.canal .btn { margin-top: auto; }

/* O endereço não é citação: o itálico que o navegador põe em <address> por
   padrão o faz parecer um aparte, e ele é dado. */
.endereco { font-style: normal; line-height: var(--lh-corpo); }

/* O convite do fim da revenda: texto à esquerda, botão à direita, e empilhado
   quando não há largura para os dois. */
.institucional__convite { display: flex; flex-wrap: wrap; align-items: center;
                          justify-content: space-between; gap: var(--esp-5); }
.institucional__convite > div { max-width: var(--largura-texto); }

/* ══ LANDING DE REVENDA ═══════════════════════════════════════════════════
   Três componentes nascidos para a página de captação de representantes, todos
   feitos com os tokens e o vocabulário de movimento que já existiam. O que a
   página tem de novo não é paleta nem tipografia: é intensidade. */

/* O CARD DE BENEFÍCIO.
   Uma grade de cards com ícone é o desenho mais previsível que existe, então
   duas coisas o tiram do lugar-comum, e as duas vêm da própria fábrica: o ícone
   sai do conjunto dela — régua, tesoura, agulha, bastidor, caminhão, e não a
   estrelinha de sempre — e o hover NÃO é a sombra que todo card faz. É o fio de
   costura correndo na borda de cima, o mesmo tracejado da assinatura do sistema,
   como se o card estivesse sendo pregado ali. */
.beneficio { position: relative; display: flex; flex-direction: column; gap: var(--esp-3);
             padding: var(--esp-5); background: var(--superficie-alta);
             border: 1px solid var(--borda); border-radius: var(--rad-2);
             transition: border-color var(--dur-2) var(--saida), transform var(--dur-2) var(--saida); }
.beneficio::before {
  content: ''; position: absolute; top: -1px; left: var(--esp-5); right: var(--esp-5);
  border-top: var(--fio-espessura) dashed var(--carmim);
  /* Fechado por padrão; o hover abre o fio da esquerda para a direita. */
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-3) var(--saida);
}
.beneficio:hover, .beneficio:focus-within { border-color: var(--borda-forte); transform: translateY(-2px); }
.beneficio:hover::before, .beneficio:focus-within::before { transform: scaleX(1); }
.beneficio__icone { width: var(--esp-6); height: var(--esp-6); color: var(--carmim); }
.beneficio__titulo { font-family: var(--fonte-titulo); font-size: var(--t-h5);
                     font-variation-settings: 'opsz' 24, 'SOFT' 40; }
/* O NÚMERO, quando o card tem um. É o que transforma "parcelamos em até 6× no
   cartão de crédito, e a gente envia o link pelo WhatsApp" — um parágrafo que
   ninguém lê — em algo que se entende de relance: 6× em corpo de título, e o
   resto virando a legenda que ele é. Mesmo gesto da faixa de números da hero e
   do resumo do medidor, e é por isso que não é um componente novo.

   Vem DEPOIS do título na tela e ANTES dele em importância, então o título
   encolhe para rótulo quando o valor existe. */
.beneficio:has(.beneficio__valor) .beneficio__titulo {
  font-family: var(--fonte-corpo); font-size: var(--t-rotulo); font-weight: var(--peso-forte);
  letter-spacing: var(--tr-rotulo); text-transform: uppercase;
  font-variation-settings: 'wdth' 88; color: var(--texto-brando);
}
.beneficio__valor { font-family: var(--fonte-titulo); font-size: var(--t-h3);
                    font-variation-settings: 'opsz' 72, 'SOFT' 40; line-height: var(--lh-apertada);
                    color: var(--texto); }
/* O card de valor tem menos ar entre título e número: eles são um par, e o
   detalhe embaixo é que se separa. */
.beneficio:has(.beneficio__valor) { gap: var(--esp-2); }
.beneficio:has(.beneficio__valor) .corpo-sm { margin-top: var(--esp-2); }

/* A CONDIÇÃO ganha ícone, e continua sendo faixa de fio fino em vez de caixa.
   É de propósito: a seção alterna texturas — faixa, cards, faixa, cards — e
   quatro caixas aqui em cima fariam onze caixas seguidas numa tela só, que é
   como uma landing vira painel de controle. */
.condicao__icone { width: var(--esp-5); height: var(--esp-5); color: var(--carmim);
                   transition: transform var(--dur-2) var(--saida); }
.condicao:hover .condicao__icone { transform: translateY(-2px); }

/* A REGRA — informação condicional, escrita como condição.
   O frete tem DOIS resultados e o parágrafo escondia isso: era preciso ler até
   o fim para descobrir que existe o caso em que o cliente paga. Em duas linhas,
   com a seta no meio, a pessoa vê os dois de uma vez e sabe em qual ela cai. */
.regra { display: grid; gap: var(--esp-4); padding: var(--esp-5);
         background: var(--superficie-alta); border: 1px solid var(--borda); border-radius: var(--rad-2); }
.regra__linha { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--esp-2) var(--esp-3); }
.regra__caso { flex: none; display: inline-flex; align-items: center; gap: var(--esp-2);
               font-size: var(--t-corpo-sm); color: var(--texto-brando); }
.regra__caso svg { width: 1rem; height: 1rem; }
/* A seta é o operador da condição: "isto ENTÃO aquilo". */
.regra__seta { flex: none; width: 1rem; height: 1rem; color: var(--borda-forte); }
.regra__valor { font-family: var(--fonte-titulo); font-size: var(--t-h4);
                font-variation-settings: 'opsz' 48, 'SOFT' 40; color: var(--texto); }
/* O caso favorável em carmim; o outro em tinta. A cor faz a leitura antes da
   palavra — mas o segundo não é erro, é a outra metade da regra, então ele não
   leva vermelho de alerta. */
.regra__linha--sim .regra__caso svg { color: var(--sucesso); }
.regra__linha--sim .regra__valor { color: var(--carmim); }
.regra__nota { padding-top: var(--esp-4); border-top: 1px dashed var(--borda);
               font-size: var(--t-corpo-sm); color: var(--texto-brando); }

@media (max-width: 640px) {
  /* Em tela estreita a linha quebra e o resultado desce para baixo da condição
     — mas a seta continuava apontando para a direita, para o vazio. Girada, ela
     volta a apontar para onde a leitura vai. */
  .regra__seta { transform: rotate(90deg); }
}

/* O PASSO, pendurado na costura vertical.
   O número não é um círculo colorido: é o nó da linha, na fonte de dado, com o
   mesmo halo do `.costura__no`. Ele fica EM CIMA da linha, e é por isso que o
   passo tem recuo à esquerda. */
.passos { display: grid; gap: var(--esp-7); padding-left: var(--esp-6); }
.passo { position: relative; display: grid; gap: var(--esp-2); }
.passo__numero {
  position: absolute; left: calc(var(--esp-6) * -1); top: 0;
  width: var(--esp-6); height: var(--esp-6); display: grid; place-items: center;
  margin-left: calc(var(--esp-6) / -2);
  font-family: var(--fonte-dado); font-size: var(--t-corpo-sm); letter-spacing: var(--tr-dado);
  color: var(--tinta); background: var(--rose); border-radius: var(--rad-total);
  box-shadow: 0 0 0 4px rgb(var(--rose-rgb) / .18);
}
.passo__titulo { font-family: var(--fonte-titulo); font-size: var(--t-h4);
                 font-variation-settings: 'opsz' 48, 'SOFT' 40; color: var(--algodao); }
.passo__texto { color: rgb(var(--bruma-rgb) / .78); max-width: var(--largura-texto); }

/* A PROVA — os números que ocupam o lugar dos depoimentos que não existem.
   Mesma leitura da faixa da hero e do resumo do medidor: valor grande em
   Fraunces, rótulo pequeno embaixo. */
.prova { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--esp-5); }
.prova__item { display: grid; gap: var(--esp-1); padding-top: var(--esp-4);
               border-top: var(--fio-espessura) solid var(--borda-inversa); }
.prova__valor { font-family: var(--fonte-titulo); font-size: var(--t-h2);
                font-variation-settings: 'opsz' 72, 'SOFT' 40, 'WONK' 1;
                line-height: var(--lh-apertada); color: var(--algodao); }
.prova__rotulo { color: var(--rose); }

/* A hero da revenda reusa `.hero--foto` inteira. Mudam duas coisas.

   A ALTURA: a da home ocupa a tela toda porque é a porta do site; esta abre uma
   página que precisa continuar, então deixa a próxima seção espiar por baixo e
   convidar a rolagem.

   O VÉU: a foto são pilhas de toalhas brancas e palha num ambiente claro, e o
   título atravessa uma toalha branca no meio da frase. O véu calibrado na foto
   da home não segura ali — a razão inteira está no token. */
.hero--revenda { min-height: 82vh; }
/* ⚠️ AS DUAS CLASSES NO SELETOR NÃO SÃO ENFEITE. Escrito `.hero--revenda::after`,
   este véu NUNCA CHEGOU À TELA: ele empata em especificidade com o
   `.hero--foto::after` do bloco geral, que mora ~120 linhas ABAIXO nesta mesma
   folha — e no empate ganha quem vem depois. O token existia, estava
   documentado no ds1.html com o motivo inteiro, e a hero da revenda continuou
   com o véu da home desde o dia em que foi escrito. Achado na fase 15, ao medir
   por que o contraste do selo não melhorava depois de o token ser reforçado.
   O elemento tem as duas classes (`hero hero--foto hero--revenda`), então
   `.hero--foto.hero--revenda` vence por especificidade e não depende mais da
   ordem das linhas. */
.hero--foto.hero--revenda::after { background: var(--grad-veu-hero-forte); }

/* Foto de apoio com a marca do sistema: canto vivo, e o fio tracejado deslocado
   por trás, como um bastidor. Um `outline` deslocado não é sombra — é o mesmo
   gesto do contorno da prévia do medidor. */
.foto-bastidor { position: relative; border-radius: var(--rad-2); overflow: hidden;
                 outline: var(--fio-espessura) dashed var(--borda-forte); outline-offset: var(--esp-3); }
.foto-bastidor img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Os arranjos da página de revenda. Ficam com o prefixo `revenda__` porque são
   posicionamento desta página, e não componentes que outra tela vá reusar. */
.revenda__abertura { align-items: center; gap: var(--esp-8); }
.revenda__abertura > div > .corpo { margin-bottom: var(--esp-4); max-width: var(--largura-texto); }
/* A frase que explica de onde sai a margem da revendedora. É a única do corpo
   da página que ganha peso: sem isso ela vira mais um parágrafo. */
.revenda__destaque { color: var(--texto); font-weight: var(--peso-medio);
                     padding-left: var(--esp-4); border-left: var(--fio-espessura) solid var(--carmim); }
.revenda__condicoes-secao { position: relative; overflow: hidden; }
/* Os cards do "o que você leva" são menores que os do pagamento de propósito:
   duas grades de card seguidas com o mesmo peso viram uma parede: é a diferença
   de ritmo que diz que são duas listas, e não uma de sete. */
.beneficio--compacto { padding: var(--esp-4); gap: var(--esp-2); }
.beneficio--compacto .beneficio__icone { width: var(--esp-5); height: var(--esp-5); }
.beneficio--compacto .beneficio__titulo { font-size: var(--t-h6); }
.beneficio--compacto::before { left: var(--esp-4); right: var(--esp-4); }

.revenda__passos-secao { position: relative; overflow: hidden; }
.revenda__brilho { top: calc(var(--esp-10) * -1); right: calc(var(--esp-9) * -1);
                   width: var(--largura-coluna); height: var(--largura-coluna); }
.revenda__brilho--fim { top: auto; bottom: calc(var(--esp-10) * -1); right: auto; left: calc(var(--esp-9) * -1); }
.revenda__acao-passos { margin-top: var(--esp-8); padding-left: var(--esp-6); }

.revenda__fechamento { position: relative; overflow: hidden; text-align: center; }
.revenda__fechamento-grade { display: grid; justify-items: center; gap: var(--esp-4); }
.revenda__fechamento-texto { max-width: var(--largura-texto); }
.revenda__arabesco { width: 100%; max-width: 20rem; margin-bottom: var(--esp-2); }

@media (max-width: 900px) {
  .prova { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .revenda__abertura { gap: var(--esp-6); }
}
@media (max-width: 640px) {
  .passos { gap: var(--esp-6); padding-left: var(--esp-5); }
  .passo__numero { left: calc(var(--esp-5) * -1); margin-left: calc(var(--esp-5) / -2);
                   width: var(--esp-5); height: var(--esp-5); font-size: var(--t-auxiliar); }
  .revenda__acao-passos { padding-left: var(--esp-5); }
  .hero--revenda { min-height: 0; }
  /* O VÉU ALIVIA NO CELULAR, E A SOMBRA ASSUME O QUE ELE LARGOU.
     Medido a 375px em 12/8/2026: o véu de tela larga cobria a foto em 84% na
     média da altura do título e 94% no pior ponto — a toalha bordada sumia. A
     causa é a segunda camada do véu, a horizontal, que escurece a esquerda
     porque lá é onde o texto mora em tela larga; no telefone o texto ocupa a
     largura toda e ela só cobra o preço sem entregar o benefício.

     São duas linhas e elas andam juntas: o véu do celular é de uma camada só e
     abre o meio da hero, e a sombra funda devolve no TEXTO o recorte que o véu
     deixou de dar na IMAGEM. Trocar uma sem a outra derruba o contraste.

     ⚠️ MESMA ARMADILHA DE ESPECIFICIDADE DA LINHA 510: as duas classes no
     seletor não são enfeite. `@media` não soma especificidade nenhuma, então
     `.hero--revenda::after` aqui dentro empataria com `.hero--foto::after` do
     bloco geral, que mora ADIANTE nesta folha, e perderia no desempate por
     ordem — sem erro, sem aviso, e com o véu de tela larga na tela do celular.

     A sombra é redeclaração do token no escopo da hero, não regra nova: quem
     consome `--sombra-texto-sobre-foto` é o bloco `.hero--foto` mais adiante, e
     todo consumidor dele dentro desta hero passa a receber a versão funda. É o
     mesmo idioma de `--largura-titulo-hero`. */
  .hero--foto.hero--revenda { --sombra-texto-sobre-foto: var(--sombra-texto-sobre-foto-movel); }
  .hero--foto.hero--revenda::after { background: var(--grad-veu-hero-forte-movel); }
}

/* ── 09 RESPONSIVO ───────────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .grade--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Uma coluna só. A regra de duas colunas mora em `min-width: 1081px`, então
     aqui não há o que desfazer — o que sobra é o respiro entre os blocos. */
  .medidor__controles { gap: var(--esp-6); }
}
@media (max-width: 900px) {
  .menu, .barra-topo { display: none; }
  .abre-menu { display: inline-flex; }
  .grade--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .secao { padding-block: var(--esp-8); }
}
@media (max-width: 640px) {
  .grade--2, .grade--3, .grade--4 { grid-template-columns: minmax(0, 1fr); }
  .secao { padding-block: var(--esp-7); }
  .card-catalogo { grid-template-columns: 5rem 1fr; }
  .modal { max-height: 92vh; }
  .medidor__par { grid-template-columns: 1fr; }
  .medidor__vezes { display: none; }
  .mesa { padding: var(--esp-6) var(--esp-4) var(--esp-4) var(--esp-6); }
  .mesa__palco { height: 15rem; }
}

/* ── 10 MOVIMENTO REDUZIDO ─────────────────────────────────────────────────
   ⚠️ A REGRA GERAL — o `*` que encurta toda animação e toda transição — MUDOU
   PARA O base.css em 14/8/2026. Ela é regra de documento, não padrão de
   negócio, e o painel administrativo não carrega esta folha: enquanto ela
   morava aqui, quem pedisse menos movimento no sistema continuava recebendo
   movimento inteiro dentro do painel. O que ficou aqui é o que é daqui — o
   comportamento dos componentes que esta folha desenha. */
@media (prefers-reduced-motion: reduce) {
  .js .surge, .js .surge-lento { opacity: 1 !important; transform: none !important; }
  .js .revela-palavra { transform: none !important; }
  /* Tudo o que se desenha por `--avanco` nasce INTEIRO aqui. A costura vertical
     da landing de revenda entrou nesta lista junto com o componente: sem ela, a
     linha que segura os quatro passos ficaria em 0 e sumiria da tela para quem
     pediu menos movimento — o conteúdo continuaria legível, mas a espinha que
     o organiza desapareceria, que é pior do que não animar. */
  .js .costura:not(.visivel),
  .js .costura-vertical:not(.visivel),
  .js .arabesco-porta:not(.visivel) { --avanco: 1; }
  /* O fio do card de benefício NÃO entra aqui de propósito. Ele é sinal de
     hover, não decoração: a regra geral acima já encurta a transição para
     0,01ms, então ele continua aparecendo ao apontar — instantâneo, em vez de
     correndo. Forçá-lo aberto tiraria o único sinal de que o card responde. */
  #fundo-fios { display: none; }
  .marquise { animation: none; }
  /* O menu móvel perde a transição INTEIRA, não só a duração. A regra geral
     acima encurta a duração, mas basta existir transição em `visibility` para
     o valor calculado ficar `hidden` no primeiro quadro — e aí o teclado não
     entra no menu, porque .focus() é ignorado em elemento invisível. Sem
     movimento o menu já aparece de uma vez, então não há o que animar. */
  .menu-movel, .menu-movel[data-aberto='true'] { transition: none; }
}

/* ── 11 SEÇÕES ESPECÍFICAS ───────────────────────────────────────────────── */
.hero { padding-block: var(--esp-8) var(--esp-9); overflow: hidden; }
.hero__grade { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--esp-8); align-items: center; }

/* ── A hero de foto ──────────────────────────────────────────────────────────
   A peça ocupa a tela e o texto entra por cima, ancorado na base. A altura usa
   `svh` — a unidade que desconta a barra do navegador do celular; com `vh`, a
   primeira dobra ficaria escondida atrás da barra justamente no aparelho em que
   a maior parte das visitas acontece.

   O teto de 46rem existe porque em monitor grande e deitado uma hero de 88% da
   altura empurra o catálogo inteiro para fora da tela — e o catálogo é o que
   esta página existe para abrir. */
.hero--foto { position: relative; isolation: isolate; display: flex; align-items: flex-end;
              min-height: min(88svh, 46rem); padding-block: var(--esp-9) var(--esp-8); }
.hero--foto .hero__grade { grid-template-columns: minmax(0, 1fr); }

.hero__fundo { position: absolute; inset: 0; z-index: -2; display: block; }
.hero__fundo img { width: 100%; height: 100%; object-fit: cover; object-position: center 42%; }

.hero--foto::after { content: ''; position: absolute; inset: 0; z-index: -1; background: var(--grad-veu-hero); }

.hero__conteudo { position: relative; width: 100%; }
/* O título não atravessa a página inteira. Além de ser linha longa demais para
   ler, ele passaria por cima da cama toda — e a cama é o argumento de venda. */
.hero--foto .hero__titulo { max-width: var(--largura-titulo-hero); }

/* A sombra faz o trabalho que o véu faria escurecendo a foto inteira. */
.hero--foto .hero__eixo,
.hero--foto .hero__titulo,
.hero--foto .hero__texto,
.hero--foto .hero__numero b,
.hero--foto .hero__numero .rotulo { text-shadow: var(--sombra-texto-sobre-foto); }

/* O bloco de texto é mais compacto aqui do que na versão sobre fundo liso, e o
   motivo é de legibilidade, não de gosto: quanto mais alto o texto sobe na
   foto, mais claro é o fundo atrás dele. Compactar desce tudo para a faixa
   onde o véu já é forte — o que dá contraste sem precisar escurecer a peça a
   ponto de ela sumir. Medido: o título saiu de 2,28 para acima de 4. */
.hero--foto .hero__eixo { margin-bottom: var(--esp-4); }
.hero--foto .hero__arabesco { margin-bottom: var(--esp-4); max-width: 20rem; }
.hero--foto .hero__texto { margin-bottom: var(--esp-5); }
.hero--foto .hero__acoes { margin-bottom: var(--esp-5); }
.hero--foto .hero__titulo,
.hero--foto .hero__texto { color: var(--texto-inverso); }
.hero--foto .hero__texto { max-width: 38rem; }
.hero--foto .hero__eixo { color: var(--rose); }
.hero--foto .hero__eixo::after { background: var(--borda-inversa); }
.hero--foto .hero__numeros { border-block-color: var(--borda-inversa); }
.hero--foto .hero__numero + .hero__numero { border-left-color: var(--borda-inversa); }
.hero--foto .hero__numero b { color: var(--texto-inverso); }
.hero--foto .hero__numero .rotulo { color: var(--rose); }
/* O fio de bordado sobre foto escura mora com o componente, e não aqui: a mesma
   regra vale para a seção tinta, e ter a decisão em dois arquivos foi o que
   deixou o motivo virar barro no escuro por um dia inteiro. Ver
   `.arabesco__traco` em componentes.css. */

.hero__eixo { display: flex; align-items: center; gap: var(--esp-3); color: var(--carmim); margin-bottom: var(--esp-5); }
.hero__eixo::after { content: ''; flex: 1; height: 1px; background: var(--borda); max-width: var(--esp-9); }
.hero__titulo { margin-bottom: var(--esp-2); }
.hero__titulo em { font-style: normal; color: var(--carmim); }
.hero__arabesco { max-width: 26rem; margin-bottom: var(--esp-5); }
.hero__texto { max-width: 34rem; margin-bottom: var(--esp-6); }
.hero__acoes { display: flex; flex-wrap: wrap; gap: var(--esp-3); margin-bottom: var(--esp-6); }
.hero__numeros { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 36rem;
                 border-block: 1px solid var(--borda); }
.hero__numero { padding: var(--esp-4) var(--esp-4) var(--esp-4) 0; }
.hero__numero + .hero__numero { border-left: 1px solid var(--borda); padding-left: var(--esp-4); }
.hero__numero b { display: block; font-family: var(--fonte-titulo); font-size: var(--t-h4); font-weight: var(--peso-normal);
                  font-variation-settings: 'opsz' 48, 'SOFT' 50, 'WONK' 1; line-height: 1.15; white-space: nowrap; }
.hero__numero .rotulo { display: block; margin-top: var(--esp-1); }
.hero__fotos { position: relative; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--esp-3); }
.hero__principal { grid-column: 1 / -1; aspect-ratio: 5 / 4; }
/* 4:3, e não mais 1:1. Todas as derivadas de foto do site são 4:3 — é o recorte
   que o gerador da fase 6 faz uma vez, no arquivo. Um palco quadrado recortaria
   pela segunda vez o que já foi recortado, e o que se perde na segunda vez são
   justamente as laterais da cena: o tapete no chão, a cortina na janela. Com
   4:3, a miniatura mostra o mesmo enquadramento que o card do catálogo. */
.hero__miniatura { aspect-ratio: 4 / 3; }
.hero__ficha { position: absolute; top: var(--esp-4); left: var(--esp-4); z-index: 2;
               background: rgb(var(--algodao-rgb) / .94); box-shadow: var(--elev-2); }
.hero__giro { display: flex; align-items: flex-start; gap: var(--esp-3); margin-top: var(--esp-4); }
.hero__pontos { display: flex; gap: var(--esp-1); padding-top: .45rem; flex: none; }
.hero__pontos span { width: .35rem; height: .35rem; border-radius: var(--rad-total); background: var(--borda-forte);
                     transition: background var(--dur-2) var(--suave); }
.hero__pontos span[data-ativo='true'] { background: var(--carmim); }
.hero__giro p { transition: opacity var(--dur-2) var(--suave); }

.faixa-linhas { background: var(--tinta); color: var(--bruma); overflow: hidden; }
.faixa-linhas__item { display: flex; align-items: center; gap: var(--esp-5); padding-inline: var(--esp-5);
                      white-space: nowrap; font-size: var(--t-rotulo); letter-spacing: var(--tr-marca);
                      text-transform: uppercase; font-variation-settings: 'wdth' 88; padding-block: var(--esp-4); }
.faixa-linhas__losango { color: var(--rose); }

/* PÁGINAS DE SISTEMA — o 404 e o esqueleto de fase.
   Nasceram com style="" no HTML dos modelos. Nenhum valor mudou de lugar: só
   saiu do HTML, onde nada é auditável, para cá, onde tudo é token. */
.erro404        { max-width: var(--largura-texto); margin-inline: auto; }
.erro404__acoes { margin-top: var(--esp-4); }
.esqueleto__titulo { margin-block: var(--esp-3) var(--esp-5); }
.esqueleto__ficha  { margin-bottom: var(--esp-5); }
.esqueleto__aviso  { margin-top: var(--esp-5); max-width: var(--largura-texto); }

/* ── 12 RESPONSIVO DAS SEÇÕES ────────────────────────────────────────────
   Vem depois do bloco 11 de propósito: regra de mesma especificidade só
   vence se vier por último. */
@media (max-width: 1080px) {
  .hero__grade { gap: var(--esp-6); }
}
@media (max-width: 900px) {
  .hero { padding-block: var(--esp-7) var(--esp-8); }
  .hero__grade { grid-template-columns: minmax(0, 1fr); }
  .hero__fotos { order: -1; max-width: 34rem; }
  .hero__principal { aspect-ratio: 16 / 10; }
}
@media (max-width: 640px) {
  .hero__numero b { font-size: var(--t-h5); }
  .hero__numero { padding-inline: var(--esp-2) 0; }
  .hero__numero + .hero__numero { padding-left: var(--esp-2); }
  .hero__acoes .btn { flex: 1 1 100%; justify-content: space-between; }
  /* A regra que existia aqui — miniatura em 4:3 no celular — subiu para o bloco
     11 e passou a valer em toda largura, quando o palco quadrado saiu do
     sistema. Não há mais nada a corrigir neste ponto de quebra. */
  .faixa-linhas__item { padding-block: var(--esp-3); }
  .cabecalho__interno { gap: var(--esp-3); min-height: var(--alt-cabecalho); }
  :root { --alt-cabecalho: 4rem; }
  /* No celular a marca cede altura para o cabeçalho caber em 4rem sem apertar o
     botão de orçamento, que é o que a pessoa vai tocar. */
  .marca__logo { height: 2.3rem; }
  .cabecalho .btn-orcamento { padding-left: var(--esp-1); gap: 0; }
  /* Esconde só aos olhos: com display:none o botão perde o nome para o leitor
     de tela e vira um botão sem rótulo. */
  .cabecalho .btn-orcamento .btn__rotulo {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .modal__cabeca, .modal__corpo, .gaveta__cabeca, .gaveta__lista, .gaveta__pe { padding: var(--esp-4); }
}

/* ── 13 CATÁLOGO NAVEGÁVEL ───────────────────────────────────────────────────
   Home, índice do catálogo, listagem por categoria, página de marca e busca.
   Tudo aqui é composição do que já existe nas folhas anteriores; o que ganhou
   classe própria foi só o que o design system ainda não tinha nome para.
   ────────────────────────────────────────────────────────────────────────── */

/* ESCADA DE ATRASO — a cascata do surgimento, em quatro degraus fixos.
   Existe como classe, e não como style="--atraso:160ms" no HTML, porque valor
   escrito dentro do HTML não obedece a token nenhum e não é auditável. */
.atraso-1 { --atraso: var(--atraso-1); }
.atraso-2 { --atraso: var(--atraso-2); }
.atraso-3 { --atraso: var(--atraso-3); }
.atraso-4 { --atraso: var(--atraso-4); }

/* FOTO QUE AINDA NÃO EXISTE ─────────────────────────────────────────────────
   O terceiro estado da mídia, ao lado de "carregando" e "pronta". A derivada de
   uma peça pode não ter sido gerada ainda; a resposta certa NÃO é uma imagem
   quebrada nem um retângulo cinza mudo, é dizer o que está acontecendo.
   Preenche a caixa inteira do pai (card, painel ou card de categoria), que já
   tem proporção fixa — então nada pula quando a foto de verdade entrar no lugar.
   A textura diagonal é a mesma linguagem da .trama: fio cru, sem imagem. */
.midia-ausente {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--esp-2); padding: var(--esp-4); text-align: center;
  color: var(--texto-brando);
  background-color: var(--bruma);
  background-image: repeating-linear-gradient(45deg, rgb(var(--tinta-rgb) / .05) 0 1px, transparent 1px 8px);
}
.midia-ausente svg { width: 1.6rem; height: 1.6rem; color: var(--borda-forte); }

/* CARD DE CATEGORIA SEM FOTO ────────────────────────────────────────────────
   O card de categoria escreve em --algodao porque o texto dele mora sobre o véu
   escuro de uma foto. Sem foto, o fundo é claro e esse mesmo texto ficaria claro
   sobre claro — contraste na casa de 1,05:1, que é o defeito que passou pela
   verificação automática na fase 2 e só foi achado olhando a tela.
   Este modificador tira o véu e devolve o texto à tinta. Mesma leitura do card,
   contraste certo para o fundo que ele de fato tem. */
.card-categoria--sem-foto { background: var(--bruma); box-shadow: inset 0 0 0 1px var(--borda); }
/* O escurecimento local sai junto com o véu: ele existe para dar fundo escuro a
   um texto claro, e aqui o texto passou a ser escuro. Mantê-lo pintaria tinta
   sobre tinta — o erro que este modificador existe para evitar, ao contrário. */
.card-categoria--sem-foto .card-categoria__texto { color: var(--texto); background: none; }
.card-categoria--sem-foto .card-categoria__seta { border-color: var(--borda-forte); }
.card-categoria--sem-foto:hover .card-categoria__seta { background: var(--tinta); color: var(--algodao); }
/* A etiqueta de foto ausente sobe para o topo: no rodapé do card já está o nome
   da categoria, e as duas centralizadas se atropelariam. */
.card-categoria--sem-foto .midia-ausente { justify-content: flex-start; padding-top: var(--esp-6); }

/* CARD INTEIRO CLICÁVEL, COM UM LINK SÓ ─────────────────────────────────────
   O botão do rodapé do card estica a área de clique por cima do card inteiro.
   Com isso o dedo acerta o card todo, e ainda assim existe UM destino: o teclado
   tabula uma vez e o leitor de tela anuncia um link, não dois iguais.
   O .card já é `position: relative` — é dele que o inset:0 se pendura. */
.card__acao::after { content: ''; position: absolute; inset: 0; z-index: 1; }
/* Rodapé de card com um filho só: o `space-between` do componente jogaria o
   botão para a esquerda, e a leitura do card mudaria de uma lista para outra. */
.card__pe--so-acao { justify-content: flex-end; }

/* AQUI MORAVA a primeira versão dos filtros — fileiras de links com a gramática
   do menu do topo. Ela saiu na fase 17 (viraram caixas marcáveis) e o CSS ficou
   para trás, inerte, com `.filtros__fila` sem nenhum elemento correspondente na
   marcação. Removido em 6/8/2026, junto da barra deitada. A `.filtros` de
   verdade está mais abaixo, no bloco da barra de filtros. */

.listagem__resumo { margin-bottom: var(--esp-5); }

/* PAGINAÇÃO — três colunas para os botões ficarem nas pontas e a contagem no
   meio, com os espaços vazios ocupados por vãos, e não por botões desativados. */
.paginacao {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--esp-4);
  margin-top: var(--esp-7); padding-top: var(--esp-5); border-top: 1px solid var(--borda);
}
.paginacao > :first-child { justify-self: start; }
.paginacao > :last-child  { justify-self: end; }

/* LISTA VAZIA — o .vazio do sistema, com a moldura tracejada que diz "aqui
   caberia conteúdo" em vez de parecer o fim da página. */
.vazio--listagem {
  border: 1px dashed var(--borda-forte); border-radius: var(--rad-2);
  background: rgb(var(--algodao-rgb) / .6);
}
.vazio--listagem .h4 { color: var(--texto); }

.secao__remate { margin-top: var(--esp-7); }

/* CONVITE — o bloco escuro de fim de página, com o argumento à esquerda e a
   ação à direita. Um bloco, não três cards: os três argumentos de revenda são
   informação que o cliente ainda não confirmou, e card vazio é pior que ausente. */
.convite { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--esp-6); align-items: center; }
.convite__texto { max-width: var(--largura-texto); }
.convite__titulo { margin-block: var(--esp-3); }

/* A BUSCA desceu para o bloco da barra de filtros em 6/8/2026, quando o campo
   virou componente e passou a aparecer em três lugares — cabeçalho, testeira de
   listagem e a página de busca. Estava aqui em duplicidade. */

/* PÁGINA DE MARCA */
.marca__cabeca   { margin-top: var(--esp-8); }
/* Fileira de cards de largura FIXA, alinhada à esquerda.
   A .grade--4 divide a largura entre quatro colunas sempre — e uma linha que
   trabalha numa categoria só (Palácio dos Tapetes) ficaria com um card esticado
   sozinho no meio de três colunas vazias. Aqui o card tem sempre o mesmo
   tamanho e a fileira simplesmente acaba onde os cards acabam, seja com um ou
   com oito. É a diferença entre "a grade quebrou" e "é isto que existe". */
.grade--cabe { grid-template-columns: repeat(auto-fill, minmax(0, 17rem)); justify-content: start; }
.marca__pendencia { margin-bottom: var(--esp-6); max-width: var(--largura-texto); }

@media (max-width: 900px) {
  .convite { grid-template-columns: minmax(0, 1fr); gap: var(--esp-5); }
}
@media (max-width: 640px) {
  .paginacao { grid-template-columns: minmax(0, 1fr); justify-items: center; gap: var(--esp-3); }
  .paginacao > :first-child, .paginacao > :last-child { justify-self: center; }
  /* Só na busca da PÁGINA de busca, que é empilhada. No compacto — cabeçalho e
     testeira — o botão é o selo do lado direito do campo, e `width: 100%` aqui
     esmagava o campo até zero: era o campo que sumia, não o botão que crescia. */
  .busca:not(.busca--compacta) .busca__acao { width: 100%; justify-content: space-between; }
}

/* Página de produto — em coluna única a ordem muda: foto, decisão, e só
   depois as garantias e a letra miúda. Ninguém deve rolar três dobras para
   achar o botão de pedir. */
@media (max-width: 1080px) {
  .produto { grid-template-columns: minmax(0, 1fr); gap: var(--esp-6); }
  .produto .galeria, .produto .videos, .produto .produto__extras, .produto .produto__painel {
    grid-column: auto; grid-row: auto;
  }
  /* Em coluna única: prova visual primeiro (foto, vídeo), decisão depois. */
  .produto .galeria { order: 1; }
  .produto .videos { order: 2; }
  .produto .produto__painel { order: 3; }
  .produto .produto__extras { order: 4; }
  .produto__painel, .produto__extras, .produto .videos { max-width: 40rem; }
}
@media (max-width: 640px) {
  .galeria { grid-template-columns: minmax(0, 1fr); }
  .galeria__fitas { flex-direction: row; order: 2; overflow-x: auto; padding-bottom: var(--esp-1); }
  .galeria__fita { flex: 0 0 4.5rem; }
  .produto__medida { grid-template-columns: 1fr; }
  .produto__vezes { display: none; }
  .produto__garantias { grid-template-columns: minmax(0, 1fr); gap: var(--esp-3); }
  .produto__garantia { flex-direction: row; align-items: center; gap: var(--esp-3); }
  .produto__garantia svg { flex: none; }

  /* NO CELULAR A JANELA DA FOTO VAI DE BORDA A BORDA. Ela é a única forma de
     ver a peça de perto em tela de toque — a lupa não existe ali, porque não há
     ponteiro para seguir —, e cada pixel de margem é peça que a cliente não vê.
     A foto passa de ~320 px dentro da página para a largura inteira da tela,
     sozinha, com o resto do site atrás do véu. */
  /* SEM MARGEM NENHUMA EM VOLTA DA FOTO. Aqui a largura da tela é o teto do
     tamanho — uma foto 4:3 em pé não tem como crescer para os lados — e cada
     píxel de padding é peça que a cliente não vê. Medido em 375 px: a foto sai
     de 335 px na página para 375 px na janela. O close-up de verdade quem dá é
     o gesto de pinça do próprio navegador, que a `<meta viewport>` deste site
     nunca bloqueou, sobre um arquivo de 1200 px.

     Recuo zero é também o que faz a conta lá de cima entregar a tela inteira
     de altura à foto: `100dvh - 0 * 2`. Em 375 × 812 isso não muda um pixel do
     tamanho da foto, porque nenhuma das 582 fotos do acervo é mais alta do que
     larga e todas param na largura da tela muito antes de esbarrar no teto de
     altura; quem colhe o ganho é o telefone DEITADO, onde a altura é o que
     falta, e o computador. */
  /* `max-height` repetido aqui de propósito: a regra `.modal { max-height: 92vh }`
     desta mesma faixa de tela tem a MESMA especificidade da declaração lá de
     cima e vem depois dela. Sem esta linha, a janela da foto voltaria a ser
     limitada por aquele teto genérico. */
  .modal--foto { width: 100%; --altura-janela: 100dvh; --recuo-janela: 0px;
                 max-height: var(--altura-janela); border-radius: 0; }
  .modal--foto .foto-cheia { border-radius: 0; }
  .foto-cheia__seta--volta { left: var(--esp-2); }
  .foto-cheia__seta--segue { right: var(--esp-2); }
  .foto-cheia__fechar { top: var(--esp-2); right: var(--esp-2); }
}

/* ── Tapete sob medida: o destaque da home ───────────────────────────────────
   Fundo em tinta de propósito. Esta seção fica entre duas de fundo claro, e o
   corte é o que a faz existir na página — antes ela era uma linha de texto
   entre blocos maiores e passava despercebida.

   O serviço merece isso: escolher peça pronta de catálogo é o que toda fábrica
   de Ibitinga oferece; cortar o tapete na medida do cômodo, com acabamento, é o
   único aqui que a concorrência não copia com uma foto. */
.sob-medida__grade { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
                     gap: var(--esp-8); align-items: center; }
.sob-medida__texto > * + * { margin-top: var(--esp-4); }
.sob-medida__pontos { display: grid; gap: var(--esp-3); list-style: none; padding: 0;
                      margin-top: var(--esp-5); }
.sob-medida__pontos li { display: flex; align-items: flex-start; gap: var(--esp-3);
                         color: var(--texto-inverso); font-size: var(--t-corpo); }
.sob-medida__marca { flex: none; width: 1.15rem; height: 1.15rem; margin-top: .15rem;
                     color: var(--rose); }
.sob-medida__foto { aspect-ratio: 4 / 3; overflow: hidden; }
.sob-medida__foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 60rem) {
  .sob-medida__grade { grid-template-columns: minmax(0, 1fr); gap: var(--esp-6); }
  /* A foto vem primeiro no celular: é ela que explica o que é um tapete
     cortado na medida, antes de qualquer frase. */
  .sob-medida__foto { order: -1; }
}

/* ── Isca do tapete na hero ──────────────────────────────────────────────────
   Link, não botão, e isso é o ponto. O tapete precisa de porta na primeira
   dobra — é o diferencial da fábrica —, mas dois botões de mesmo peso lado a
   lado não hierarquizam: o olho hesita entre eles e nenhum vence. A isca fica
   para quem já sabe que quer tapete; quem veio ver enxoval nem repara nela, que
   é exatamente o desejado. */
.isca { display: inline-flex; align-items: center; gap: var(--esp-2);
        color: var(--texto-inverso); font-size: var(--t-corpo-sm); font-weight: var(--peso-medio);
        padding-block: var(--esp-2); border-bottom: 1px solid var(--borda-inversa);
        transition: color var(--dur-1) var(--suave), border-color var(--dur-1) var(--suave); }
.isca:hover { color: var(--rose); border-bottom-color: var(--rose); }
.isca__seta { width: .85rem; height: .85rem; transition: transform var(--dur-2) var(--saida); }
.isca:hover .isca__seta { transform: translateX(.2rem); }
.hero--foto .isca { text-shadow: var(--sombra-texto-sobre-foto); }
/* O botão e a isca ficam alinhados pela base, não centralizados: alturas
   diferentes centralizadas fazem o menor parecer desalinhado. */
.hero__acoes { align-items: center; }

/* O terceiro número vira porta. Os outros dois continuam sendo dado — fazer de
   "35+ anos" um link prometeria uma página que não existe. */
.hero__numero--porta { text-decoration: none; transition: background var(--dur-1) var(--suave); }
.hero__numero--porta:hover { background: rgb(var(--bruma-rgb) / .08); }
.hero__numero--porta:hover .rotulo { color: var(--rose); }
.hero__numero-regua { width: .8rem; height: .8rem; margin-left: var(--esp-1);
                      vertical-align: -.1em; color: var(--rose); }

@media (max-width: 40rem) {
  /* No celular a isca desce para baixo do botão, que ocupa a largura toda. */
  .hero__acoes { flex-direction: column; align-items: flex-start; gap: var(--esp-4); }
  .hero__acoes .btn { width: 100%; justify-content: space-between; }
}

/* ── PAINEL DE FILTROS (fase 17) ───────────────────────────────────────────
   Substitui a fileira de `.menu__link` que servia de filtro até a fase 16. O
   problema não era funcional: era que aquilo se lia como navegação, e não como
   "aqui você escolhe o que ver". Agora é um formulário de verdade, com caixas
   marcáveis, contagem por opção e o resumo do que está aplicado.

   A caixa é desenhada do zero (o `input` fica invisível mas continua sendo ele
   quem recebe foco e clique) porque a caixa nativa não aceita a cor nem o raio
   do sistema. Nada de `appearance: none` no rótulo inteiro: o alvo continua
   sendo o `<label>`, que é o que dá a área de toque de 44px. */
/* ── A LISTAGEM EM DUAS COLUNAS ─────────────────────────────────────────────
   Filtros à esquerda, peças à direita. A coluna sai do caminho vertical da
   grade: entre a contagem e o primeiro produto não há mais nada.

   260px é o que basta para o nome de uma cor, o quadradinho dela e a contagem
   caberem numa linha sem quebrar — medido com "Azul petróleo", o nome mais
   longo do acervo. Mais que isso rouba da vitrine; menos, e a lista de cores
   começa a quebrar linha. */
.listagem { display: grid; gap: var(--esp-6); align-items: start; }
@media (min-width: 64rem) {
  .listagem { grid-template-columns: 16.25rem minmax(0, 1fr); gap: var(--esp-7); }
}
.listagem__pecas { min-width: 0; }
/* QUATRO COLUNAS VIRAM TRÊS ao lado da coluna de filtros. Medido em 1440: com
   as quatro, cada card cai para 191px de largura e a foto para 143px de altura —
   pequeno demais para se ver o bordado, que é o produto. Com três, o card volta
   a 262px. Uma peça a menos por linha, e a peça visível. */
@media (min-width: 64rem) {
  .listagem__pecas .grade--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ── A COLUNA DE FILTROS ────────────────────────────────────────────────────
   GRUDENTA logo abaixo do cabeçalho: quem está na peça 20 marca "Sofisticata"
   sem rolar de volta ao topo. `max-height` mais rolagem própria porque a coluna
   com as 39 cores abertas é mais alta que a tela — sem isso o fim dela ficaria
   inalcançável para quem grudou no topo. */
.barra-filtros { margin-block: 0 var(--esp-6); }
@media (min-width: 64rem) {
  .barra-filtros {
    position: sticky; top: calc(var(--alt-cabecalho) + var(--esp-4)); z-index: 30;
    margin-block: 0;
  }
}
/* `min-width: 0` em toda a corrente até a caixa. Sem ele, um item de grade tem
   largura mínima igual ao conteúdo, e o nome de cor mais longo com a contagem ao
   lado empurrava a coluna inteira para fora do container — a costura de cada
   seção chegava a atravessar a grade de produtos. */
.barra-filtros, .barra-filtros__interno, .filtros, .filtros > * { min-width: 0; }
/* O cartão branco é a COLUNA. Abaixo de 1024px não há coluna — há um botão que
   abre a gaveta —, e o cartão em volta dele seria uma moldura vazia. */
@media (min-width: 64rem) {
  .barra-filtros__interno {
    background: var(--superficie-alta);
    border: var(--fio-espessura) solid var(--borda); border-radius: var(--rad-3);
    padding: var(--esp-2) var(--esp-4) var(--esp-4);
  }
}

/* O abridor e o cabeçalho da gaveta só existem no celular. */
.barra-filtros__abre,
.barra-filtros__cabeca,
.barra-filtros__fundo { display: none; }

.filtros { display: grid; }

/* ── A SEÇÃO COLAPSÁVEL ─────────────────────────────────────────────────────
   `<details>` nativo: abre e fecha sem JavaScript, chega pronto para leitor de
   tela e o teclado já sabe operá-lo. */
.filtro-secao { border: 0; }
.filtro-secao__cabeca {
  display: flex; align-items: center; gap: var(--esp-2);
  position: relative; cursor: pointer; list-style: none;
  padding-block: var(--esp-4) var(--esp-3);
  color: var(--texto);
}
/* O triângulo que o navegador desenha sozinho sai: o chevron abaixo é o nosso,
   e os dois juntos seriam duas setas dizendo a mesma coisa. */
.filtro-secao__cabeca::-webkit-details-marker { display: none; }
.filtro-secao__cabeca::marker { content: ''; }
.filtro-secao__nome { flex: 1; color: var(--texto); }
.filtro-secao__cabeca:hover .filtro-secao__nome { color: var(--carmim); }
/* O FOCO AQUI É O CONTORNO DO SISTEMA, e não o halo do --elev-foco sozinho.
   Até a auditoria da fase 15 esta linha trazia `outline: none` e deixava como
   único sinal de foco o `--elev-foco`, que é carmim a 28% — medido no pixel da
   tela, rgb(228,196,200) sobre branco dá 1,61:1, e a norma pede 3:1 para
   indicador de foco (WCAG 2.2, 1.4.11). Na prática: quem navegava a barra de
   filtros por teclado não via onde estava.
   O halo continua, agora ACOMPANHANDO o contorno em vez de substituí-lo. */
.filtro-secao__cabeca:focus-visible { box-shadow: var(--elev-foco); border-radius: var(--rad-2); }

.filtro-secao__sinal {
  width: .75rem; height: .75rem; flex: none; color: var(--texto-brando);
  transition: color var(--dur-1) var(--suave);
}
.filtro-secao__sinal--fecha,
[open] > .filtro-secao__cabeca .filtro-secao__sinal--abre { display: none; }
[open] > .filtro-secao__cabeca .filtro-secao__sinal--fecha { display: block; }
.filtro-secao__cabeca:hover .filtro-secao__sinal { color: var(--carmim); }

/* ── A COSTURA, E POR QUE ELA ESTÁ AQUI ─────────────────────────────────────
   Uma coluna branca com títulos e caixas de marcar é o filtro de qualquer loja
   do mundo. Este é o site de uma fábrica de bordados, e o sistema já tem uma
   assinatura — `--ponto` e `--lacuna`, a linha de costura que separa as seções
   institucionais. Ela nunca tinha sido usada num controle.

   Fechada, é um fio contínuo apagado. Aberta, a costura CORRE da esquerda para
   a direita: o mesmo gesto da máquina que borda a peça que está sendo filtrada.
   É o único enfeite desta coluna, e é deliberado — a Chanel manda tirar um
   acessório antes de sair, e o que sobra tem que ser o que importa. */
.filtro-secao__costura {
  position: absolute; inset-inline: 0; bottom: 0; height: var(--fio-espessura);
  background: linear-gradient(90deg, var(--borda-forte) 0 var(--ponto),
                              transparent var(--ponto) calc(var(--ponto) + var(--lacuna)));
  background-size: calc(var(--ponto) + var(--lacuna)) 100%;
  background-repeat: repeat-x;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--dur-3) var(--saida);
}
[open] > .filtro-secao__cabeca .filtro-secao__costura { clip-path: inset(0 0 0 0); }
/* Fechada, o fio continua ali como divisor — apagado, contínuo e discreto. Sem
   ele, as seções fechadas ficariam soltas no branco sem nada as separando. */
.filtro-secao:not([open]) > .filtro-secao__cabeca::after {
  content: ''; position: absolute; inset-inline: 0; bottom: 0;
  height: var(--fio-espessura); background: var(--borda);
}

.filtro-secao__corpo {
  display: flex; flex-direction: column; gap: 0;
  padding: var(--esp-1) 0 var(--esp-2); margin: 0; border: 0;
}

/* ── A OPÇÃO DENTRO DA COLUNA ───────────────────────────────────────────────
   A `.caixa` do sistema é uma PÍLULA com borda própria — nasceu para a barra
   deitada, onde cada opção flutuava solta numa fileira e precisava do próprio
   contorno para se separar da vizinha.

   Empilhada numa coluna estreita, essa mesma pílula vira uma escada de bordas
   arredondadas: dezessete contornos repetidos onde o alinhamento à esquerda já
   basta para dizer que são uma lista. Aqui ela volta a ser uma LINHA — sem
   borda, sem raio, largura inteira — e quem separa uma da outra é o espaço.

   A área de toque continua sendo o `<label>` inteiro, e continua tendo os 44px
   de altura mínima que o dedo precisa. */
.filtro-secao__corpo .caixa {
  display: flex; width: 100%; min-width: 0; min-height: 2.25rem;
  padding: var(--esp-1) var(--esp-2);
  border: 0; border-radius: var(--rad-2); background: none;
  transition: background var(--dur-1) var(--suave), color var(--dur-1) var(--suave);
}
.filtro-secao__corpo .caixa:hover { border-color: transparent; background: rgb(var(--tinta-rgb) / .04); }
.filtro-secao__corpo .caixa:has(input:checked) {
  border-color: transparent; background: rgb(var(--carmim-rgb) / .07); color: var(--carmim);
}
/* A contagem encosta na margem direita: lida em coluna, ela vira uma régua de
   quanto cada opção recorta — e isso só funciona se os números se alinharem. */
.filtro-secao__corpo .caixa__conta { margin-inline-start: auto; }
.filtro-secao__corpo .caixa__texto { min-width: 0; overflow-wrap: anywhere; }
/* A cor é o único grupo que passa de uma dúzia de opções — 39 no catálogo
   inteiro. Com rolagem própria ela para de empurrar os outros filtros para
   fora da tela, que é o defeito que o Felipe apontou no print de referência. */
.filtro-secao__corpo--rola { max-height: 15rem; overflow-y: auto; padding-inline-end: var(--esp-2); }

/* O surgimento das caixas ao abrir. Escalonado nas primeiras, e não em todas:
   uma cascata de 39 cores levaria três segundos para terminar de aparecer. */
[open] > .filtro-secao__corpo > .caixa { animation: surge-caixa var(--dur-2) var(--saida) backwards; }
[open] > .filtro-secao__corpo > .caixa:nth-child(2) { animation-delay: calc(var(--atraso-1) / 2); }
[open] > .filtro-secao__corpo > .caixa:nth-child(3) { animation-delay: var(--atraso-1); }
[open] > .filtro-secao__corpo > .caixa:nth-child(n+4) { animation-delay: var(--atraso-2); }
@keyframes surge-caixa { from { opacity: 0; translate: 0 calc(var(--esp-1) * -1); } }

/* `width: auto` desfaz o `width: 100%` de todo `.campo__controle`; aqui a
   coluna é estreita e o seletor deve ocupá-la inteira. */
.filtros__ordem { min-height: var(--alt-controle); width: 100%; }

.filtros__limpar { display: inline-flex; align-items: center; gap: var(--esp-1);
                   margin-top: var(--esp-4);
                   font-size: var(--t-auxiliar); color: var(--texto-brando); text-decoration: none;
                   transition: color var(--dur-1) var(--suave); }
.filtros__limpar:hover { color: var(--carmim); }
.filtros__limpar svg { width: .7rem; height: .7rem; }

/* ── O QUADRADINHO DE COR ───────────────────────────────────────────────────
   Amostrado das fotos da peça naquela cor (ferramentas/amostrar-cores.php), e
   não escolhido a dedo. A borda interna existe por causa do Branco e do Pérola:
   sem ela, um quadrado quase branco sobre fundo branco some. */
.caixa__amostra {
  width: .95rem; height: .95rem; flex: none; border-radius: var(--rad-1);
  background: var(--amostra);
  box-shadow: inset 0 0 0 var(--fio-espessura) rgb(var(--tinta-rgb) / .18);
}

/* O botão de aplicar só existe para quem não tem JavaScript e para dentro da
   gaveta do celular. As duas palavras do botão são a mesma ação em contextos
   diferentes; o JavaScript acende a que serve. */
.filtros__aplicar { grid-column: 1 / -1; }
.filtros__so-gaveta { display: none; }
.js .filtros__aplicar { display: none; }

.caixa { display: inline-flex; align-items: center; gap: var(--esp-2);
         min-height: var(--alt-controle); padding: var(--esp-2) var(--esp-3);
         border: var(--fio-espessura) solid var(--borda-forte); border-radius: var(--rad-total);
         font-size: var(--t-corpo-sm); color: var(--texto); cursor: pointer;
         background: var(--superficie);
         transition: border-color var(--dur-1) var(--suave), background var(--dur-1) var(--suave); }
.caixa:hover { border-color: var(--carmim); }
.caixa input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.caixa__marca { display: grid; place-items: center; flex: none;
                width: 1.05rem; height: 1.05rem; border-radius: var(--rad-1);
                border: var(--fio-espessura) solid var(--borda-forte); color: transparent;
                transition: background var(--dur-1) var(--suave), color var(--dur-1) var(--suave); }
.caixa__marca svg { width: .7rem; height: .7rem; }
/* MARCADA E COM FOCO SEM `:has()`.
   O `input` vem imediatamente antes de `.caixa__marca` na marcação, então o
   irmão adjacente resolve os dois estados essenciais — o check aparecer e o foco
   ser visível — em qualquer navegador. Isto não é preciosismo: sem o check
   desenhado, a caixa marcada fica idêntica à desmarcada, e o filtro deixa de
   dizer o que está aplicado.

   O `:has()` continua abaixo, mas SÓ para o realce do rótulo inteiro, que é
   enfeite: onde ele não existir, a caixa perde o fundo rosado e mantém tudo o
   que importa. */
.caixa input:checked + .caixa__marca {
  background: var(--carmim); border-color: var(--carmim); color: var(--algodao);
}
.caixa input:focus-visible + .caixa__marca {
  outline: 2px solid var(--carmim); outline-offset: 2px;
}
.caixa:has(input:checked) { border-color: var(--carmim); background: rgb(var(--carmim-rgb) / .06); }
/* A contagem é dado, e por isso vai na fonte de dado. Ela existe para ninguém
   marcar um filtro que devolve zero. */
.caixa__conta { font-family: var(--fonte-dado); font-size: var(--t-auxiliar);
                letter-spacing: var(--tr-dado); color: var(--texto-brando); }
.caixa--vazia { opacity: .55; }
/* ⚠️ LINK DENTRO DE TEXTO CORRIDO É SUBLINHADO, SEMPRE — e esta é a única
   exceção à linha `a { text-decoration: none }` do base.css.
   O motivo é norma e é medição: o carmim do link contra o tinta do texto ao
   redor dá 2,13:1 (#9e2b3b sobre #1b2430), e a WCAG 2.2 §1.4.1 pede 3:1 para
   distinguir link de texto SÓ pela cor. Abaixo disso, quem não separa bem
   vermelho de preto — daltonismo é 8% dos homens — não vê que ali tem link.
   Achado pela segunda rodada de auditoria da fase 15, no aceite da LGPD do
   formulário de revenda, que é o único lugar do site com link no meio de
   frase. Não é regra da `.caixa`: é regra de link em texto, e mora aqui
   porque `.caixa__texto` é onde o site tem um. */
.caixa__texto a { text-decoration: underline; text-underline-offset: var(--desloca-sublinhado); }

/* ── A TESTEIRA DA LISTAGEM ─────────────────────────────────────────────────
   O título de um lado, a busca do outro, na mesma linha. Empilhados eles eram
   duas alturas; lado a lado são uma. A contagem é a legenda do título — vem
   colada nele, e não perdida no fim dos filtros. */
/* `clip` e não `hidden`: os dois cortam o que sangra, mas `hidden` cria um
   contêiner de rolagem e mataria o `position: sticky` da barra de filtros aqui
   dentro. `.secao--lista` é só isso — a permissão de grudar. `.secao--testeira`
   é ela mais o respiro curto do topo, que é o que a página de categoria precisa
   para o produto nascer antes da dobra. */
.secao--lista { overflow: clip; }
.secao--testeira { padding-block: var(--esp-6) var(--esp-9); overflow: clip; }
.testeira { display: flex; flex-wrap: wrap; align-items: flex-end;
            justify-content: space-between; gap: var(--esp-4) var(--esp-6);
            margin-top: var(--esp-4); }
.testeira__nome { display: flex; flex-direction: column; gap: var(--esp-1); min-width: min(100%, 16rem); }
.testeira__texto { max-width: var(--largura-texto); margin-top: var(--esp-2); }
.testeira__conta { margin: var(--esp-3) 0 0; }

/* ── O CAMPO DE BUSCA ───────────────────────────────────────────────────────
   Um componente, três lugares: cabeçalho, testeira de listagem e a página de
   busca inteira. O compacto perde o rótulo visível e a linha de ajuda — numa
   área que existe para ser curta, elas seriam duas linhas a mais. */
.busca { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--esp-3);
         max-width: var(--largura-texto); }
.busca__campo { flex: 1 1 16rem; }
.busca__caixa { position: relative; display: block; }
.busca__lupa { position: absolute; left: var(--esp-3); top: 50%; translate: 0 -50%;
               width: 1rem; height: 1rem; color: var(--texto-brando); pointer-events: none; }
.busca__entrada { padding-inline-start: calc(var(--esp-3) * 2 + 1rem); }
/* O X que o navegador põe dentro de type="search" some: ele muda de desenho em
   cada navegador e briga com o selo do botão ao lado. Apagar é o próprio campo. */
.busca__entrada::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.busca__acao { flex: none; }

/* O COMPACTO É UM CONTROLE SÓ, e não um campo com um botão do lado. Separados,
   a seta parecia uma segunda coisa a decidir — e "digitar" e "enviar" são o
   mesmo gesto. Emendados pela borda, lê-se como uma caixa de busca, que é o que
   é. O raio total é o mesmo das caixas de filtro logo abaixo. */
.busca--compacta { flex-wrap: nowrap; gap: 0; max-width: 22rem; align-items: stretch;
                   border: var(--fio-espessura) solid var(--borda-forte);
                   border-radius: var(--rad-total); background: var(--superficie);
                   transition: border-color var(--dur-1) var(--suave); }
.busca--compacta:hover,
.busca--compacta:focus-within { border-color: var(--carmim); }
.busca--compacta .busca__campo { flex: 1 1 auto; min-width: 0; }
.busca--compacta .busca__entrada { min-height: var(--alt-controle); height: 100%;
                                   border: 0; background: none; border-radius: var(--rad-total); }
/* O anel de foco do sistema vai para a caixa inteira, e não só para o campo:
   dentro de uma borda emendada, um anel só no campo desenharia um retângulo
   dentro de uma pílula. */
.busca--compacta .busca__entrada:focus-visible { outline: none; box-shadow: none; }
.busca--compacta:focus-within { box-shadow: var(--elev-foco); }
.busca--compacta .busca__lupa { left: var(--esp-4); }
.busca--compacta .busca__entrada { padding-inline-start: calc(var(--esp-4) + var(--esp-3) + 1rem); }
.busca__acao--icone { flex: none; width: var(--alt-controle); border: 0; background: none;
                      color: var(--texto-brando); border-radius: var(--rad-total); }
.busca__acao--icone:hover { color: var(--carmim); background: none; }

/* ── A LISTA DE SUGESTÕES ───────────────────────────────────────────────────
   Ela pende do campo, e o campo é quem manda: `.busca__caixa` é `relative`, a
   lista é `absolute` logo abaixo. Assim ela nasce com a largura do campo em
   qualquer um dos três lugares onde o componente aparece, sem nenhuma medida
   escrita duas vezes.

   `z-index` acima do cabeçalho (40) e da barra de filtros (30): a lista abre
   POR CIMA de tudo, inclusive do que estiver grudado no topo. Uma sugestão
   cortada pela metade por uma barra é pior do que sugestão nenhuma. */
.busca__sugestoes {
  position: absolute; top: calc(100% + var(--esp-2)); left: 0; right: 0; z-index: 45;
  /* A lista pode ser MAIS LARGA do que o campo. No cabeçalho ele tem 15rem, e
     "Cortina Dia a Dia" quebrava em duas linhas dentro de uma lista de oito —
     o nome da peça é a única coisa que importa ali e era justamente o que não
     cabia. Como o campo do cabeçalho e o da testeira ficam à direita, a lista
     cresce para a ESQUERDA (`right: 0`, `left: auto`) e nunca sai da tela. */
  min-width: min(24rem, calc(100vw - var(--goteira) * 2));
  margin: 0; padding: var(--esp-2); list-style: none;
  max-height: min(24rem, 60vh); overflow-y: auto; overscroll-behavior: contain;
  background: var(--superficie-alta); border: var(--fio-espessura) solid var(--borda);
  border-radius: var(--rad-3); box-shadow: var(--elev-3);
}
.busca__sugestoes[hidden] { display: none; }

.busca__sugestao {
  display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--esp-3);
  align-items: center; padding: var(--esp-2) var(--esp-3);
  border-radius: var(--rad-2); cursor: pointer;
  transition: background var(--dur-1) var(--suave);
}
/* `aria-selected` E `:hover` pintam igual: a linha marcada pelo teclado e a
   linha sob o ponteiro são o mesmo estado, e desenhá-las diferente faria
   parecer que uma delas é a "de verdade". */
.busca__sugestao:hover,
.busca__sugestao[aria-selected='true'] { background: rgb(var(--carmim-rgb) / .07); }
.busca__sugestao img { width: 2.5rem; height: 2.5rem; object-fit: cover; border-radius: var(--rad-1); }
.busca__sugestao-nome { display: block; font-size: var(--t-corpo-sm); color: var(--texto); }
/* O QUE FOI DIGITADO, EM NEGRITO. `<mark>` traz fundo amarelo do navegador —
   aqui ele é só peso, porque a linha inteira já muda de fundo quando marcada, e
   dois realces na mesma linha brigam. */
.busca__sugestao-nome mark { background: none; color: inherit; font-weight: var(--peso-forte); }
.busca__sugestao-eixo { display: block; font-size: var(--t-auxiliar); color: var(--texto-brando); }

/* A última linha: a saída para o resultado inteiro. Fica separada por um fio,
   porque não é uma peça — é um destino. */
.busca__sugestao--todos {
  grid-template-columns: 1fr; margin-top: var(--esp-2); padding-top: var(--esp-3);
  border-top: var(--fio-espessura) solid var(--borda);
  font-size: var(--t-auxiliar); color: var(--carmim);
}
/* "Procurando…" e "nenhuma peça encontrada" não são opções: a seta do teclado
   não para nelas, e por isso elas também não têm cara de clicável. */
.busca__aviso-linha { padding: var(--esp-3); font-size: var(--t-corpo-sm); color: var(--texto-brando); }

/* No compacto — cabeçalho e testeira — o campo é estreito e mora à direita:
   a lista se ancora pela direita e cresce para a esquerda. Na página de busca o
   campo já é largo e alinhado à esquerda, e ali a lista o acompanha. */
.busca--compacta .busca__sugestoes { left: auto; right: 0; }

.busca__ajuda { margin-top: var(--esp-2); margin-bottom: var(--esp-6); max-width: var(--largura-texto); }
.busca__aviso { margin-bottom: var(--esp-4); max-width: var(--largura-texto); }

/* A busca do cabeçalho. Some cedo — antes de o menu quebrar — e no lugar dela
   fica a lupa que leva para a página de busca. */
.cabecalho .busca { max-width: 15rem; }

/* ── NO CELULAR A BARRA VIRA GAVETA ────────────────────────────────────────
   Deitada não cabe em 375px, e empilhada volta a comer a tela. Some, e no lugar
   fica um botão só. A gaveta é o mesmo desenho da do orçamento — mesmo gesto,
   mesmo X, mesma vinda pela direita —, e não um padrão novo para a pessoa
   aprender. */
@media (max-width: 900px) {
  .barra-filtros { position: static; background: none; backdrop-filter: none;
                   border: 0; border-radius: 0; margin-inline: 0; }
  .barra-filtros__interno { padding-block: 0; }

  .barra-filtros__abre {
    display: inline-flex; align-items: center; gap: var(--esp-2);
    min-height: var(--alt-controle); padding: var(--esp-2) var(--esp-4);
    border: var(--fio-espessura) solid var(--borda-forte); border-radius: var(--rad-total);
    background: var(--superficie); color: var(--texto); text-decoration: none;
    font-size: var(--t-corpo-sm);
    transition: border-color var(--dur-1) var(--suave);
  }
  .barra-filtros__abre:hover { border-color: var(--carmim); }
  .barra-filtros__abre svg { width: 1rem; height: 1rem; color: var(--texto-brando); }
  .barra-filtros__conta { display: grid; place-items: center; min-width: 1.35rem; height: 1.35rem;
                          padding-inline: var(--esp-1); border-radius: var(--rad-total);
                          background: var(--carmim); color: var(--texto-inverso);
                          font-family: var(--fonte-dado); font-size: var(--t-auxiliar); }

  /* SEM JAVASCRIPT a gaveta não abre — então ela não é gaveta: o painel fica no
     fluxo, empilhado, e o botão "Aplicar filtros" fecha o ciclo. É o `.js` no
     <html> que autoriza a virar gaveta, e ele só existe com JavaScript. */
  .js .barra-filtros__painel {
    position: fixed; inset-block: 0; inset-inline-end: 0; z-index: 60;
    width: min(22rem, 90vw); display: flex; flex-direction: column;
    background: var(--superficie); box-shadow: var(--elev-3);
    translate: 100% 0; visibility: hidden;
    transition: translate var(--dur-2) var(--suave), visibility var(--dur-2) var(--suave);
    overflow-y: auto; overscroll-behavior: contain;
  }
  .js .barra-filtros__painel[data-aberto='true'] { translate: 0 0; visibility: visible; }

  /* A SEÇÃO INTEIRA SOBE quando a gaveta abre. `.secao` tem `isolation: isolate`,
     então o `z-index` da gaveta só vale lá dentro — sem isto ela abria por baixo
     do cabeçalho grudento e perdia o próprio botão de fechar. */
  .js[data-filtros='aberto'] .secao--lista,
  .js[data-filtros='aberto'] .secao--testeira { z-index: 50; }

  /* `.js` e `data-filtros` moram no MESMO elemento — o <html> —, então os dois
     seletores se escrevem grudados. Escritos como descendentes, nunca casariam. */
  .js .barra-filtros__fundo { display: block; position: fixed; inset: 0; z-index: 55;
                              background: rgb(var(--tinta-rgb) / .45);
                              opacity: 0; visibility: hidden;
                              transition: opacity var(--dur-2) var(--suave),
                                          visibility var(--dur-2) var(--suave); }
  .js[data-filtros='aberto'] .barra-filtros__fundo { opacity: 1; visibility: visible; }

  .js .barra-filtros__painel .barra-filtros__cabeca {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--esp-4); padding: var(--esp-5);
    border-bottom: var(--fio-espessura) solid var(--borda);
  }
  /* Dentro da gaveta as seções são as MESMAS `<details>` da coluna: mesma
     marcação, mesma costura, mesmo gesto de abrir. Só o respiro muda, porque
     aqui o dedo precisa de alvo maior que o ponteiro. */
  .js .barra-filtros__painel .filtros { padding: var(--esp-5); }
  /* Dentro da gaveta o botão VOLTA: ali marcar uma caixa não pode recarregar a
     página, senão a gaveta fecha na cara de quem ia marcar a segunda. */
  .js .barra-filtros__painel .filtros__aplicar { display: block; margin-top: auto; }
  .js .barra-filtros__painel .filtros__so-sem-js { display: none; }
  .js .barra-filtros__painel .filtros__so-gaveta { display: inline; }

  .testeira { align-items: stretch; }
  /* No celular o campo da testeira ocupa a linha inteira — e com ele a lista de
     sugestões, que se ancora nele. Com o campo estreito e a lista com
     `min-width` de 24rem, ela crescia para a esquerda e saía da tela pela
     borda: 150px de sugestão fora do alcance do dedo. */
  .busca--compacta { max-width: none; width: 100%; }
  /* Volta a se ancorar pelos DOIS lados: no celular o campo ocupa a linha
     inteira, então a lista o acompanha em vez de encolher para caber no
     conteúdo. Precisa da mesma especificidade da regra que a solta à direita
     no desktop, senão aquela vence mesmo aqui dentro. */
  .busca--compacta .busca__sugestoes { left: 0; right: 0; min-width: 0; }
}


/* Catálogo sem capa cadastrada. A coluna da imagem existe no grid do card, e
   deixá-la vazia abriria um buraco sem explicação — aqui ela vira a marca do
   arquivo, no mesmo lugar e no mesmo tamanho que a capa ocuparia. */
.card-catalogo__semcapa {
  display: grid; place-items: center; aspect-ratio: 5 / 7;
  border-radius: var(--rad-1); background: rgb(var(--tinta-rgb) / .05);
  border: var(--fio-espessura) dashed var(--borda-forte); color: var(--texto-brando);
}
.card-catalogo__semcapa svg { width: var(--esp-6); height: var(--esp-6); }

/* ══ O FORMULÁRIO DE REVENDA ═══════════════════════════════════════════════
   A primeira porta do site que aceita dado de alguém. Mora em dois lugares com
   a mesma marcação: a seção do fim da página de revenda e a janela sobreposta
   que qualquer botão pode abrir.

   DUAS COLUNAS na seção: o convite à esquerda, o formulário à direita. O
   convite é curto de propósito — quem rolou a página inteira até aqui já foi
   convencido pelas seções anteriores, e repetir o argumento ao lado do
   formulário só afastaria o primeiro campo. */
.inscricao-grade { display: grid; gap: var(--esp-6); align-items: start; }
@media (min-width: 60rem) {
  .inscricao-grade { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: var(--esp-8); }
  /* O texto acompanha a rolagem do formulário: em telas altas ele some antes de
     a pessoa chegar ao último campo, e com ele some o motivo de preencher. */
  .inscricao-grade__texto { position: sticky; top: calc(var(--alt-cabecalho) + var(--esp-6)); }
}
.inscricao-grade__apoio { margin-top: var(--esp-3); max-width: var(--largura-coluna); }
.inscricao-grade__zap { margin-top: var(--esp-5); }

.inscricao-grade__form {
  background: var(--superficie-alta);
  border: var(--fio-espessura) solid var(--borda); border-radius: var(--rad-3);
  padding: var(--esp-5); box-shadow: var(--elev-1);
}
@media (min-width: 48rem) { .inscricao-grade__form { padding: var(--esp-6); } }

/* Uma coluna no celular, duas onde couber. Telefone e e-mail dividem a linha
   porque são curtos; nome, tipo de pessoa e os textos livres tomam a largura
   inteira, porque quebrar um textarea ao meio não ajuda ninguém a escrever. */
.form-revenda__grade { display: grid; gap: var(--esp-4); }
@media (min-width: 34rem) {
  .form-revenda__grade { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .form-revenda__largo { grid-column: 1 / -1; }
  /* A sigla do estado é sempre duas letras: dar meia linha a ela seria desenhar
     um campo que anuncia caber muito mais do que cabe. */
  .form-revenda__uf { max-width: 8rem; }
}

.form-revenda textarea.campo__controle { min-height: 4.5rem; resize: vertical; }

.form-revenda__opcoes { display: flex; flex-wrap: wrap; gap: var(--esp-3) var(--esp-5); }

/* O CONSENTIMENTO NÃO É UM CAMPO COMO OS OUTROS: ele é a permissão que torna
   todo o resto legítimo. Fica destacado num bloco próprio, com o texto legível —
   consentimento em letra miúda é consentimento que ninguém leu. */
.form-revenda__lgpd {
  align-items: flex-start; gap: var(--esp-3);
  padding: var(--esp-3) var(--esp-4); min-height: 0;
  background: rgb(var(--carmim-rgb) / .04);
  border-color: var(--borda); border-radius: var(--rad-2);
  font-size: var(--t-corpo-sm); line-height: var(--lh-media);
}
.form-revenda__lgpd .caixa__marca { margin-top: .1rem; }
.form-revenda__lgpd .caixa__texto { white-space: normal; }
.form-revenda__lgpd a { color: var(--carmim); }

.form-revenda__acoes { margin-top: var(--esp-5); }
.form-revenda__acoes .btn { width: 100%; }
@media (min-width: 34rem) { .form-revenda__acoes .btn { width: auto; } }

/* A ARMADILHA. Fora da tela em vez de `display: none`: campo escondido por
   `display` é ignorado por parte dos robôs justamente por ser o truque mais
   conhecido, e um campo que existe no fluxo mas ninguém alcança pega mais. O
   `aria-hidden` e o `tabindex="-1"` da marcação mantêm leitor de tela e teclado
   longe dele.

   ⚠️ MAS ESCONDER AQUI NÃO ESCONDE DO PREENCHIMENTO AUTOMÁTICO. O recorte é do
   pai; o campo lá dentro continua com tamanho de campo comum, e é o tamanho
   dele que o navegador mede para decidir se preenche. Em 11/8/2026 o Chrome
   preencheu esta armadilha sozinho e uma inscrição de verdade foi descartada.
   Quem defende contra isso é a marcação — nome sem significado e os `data-` de
   gerenciador de senha, em `form-revenda.php`. Não conte com este bloco. */
.form-revenda__armadilha {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* O aviso de resultado. Ocupa o lugar do formulário quando ele termina, em vez
   de aparecer acima empurrando tudo: a pessoa acabou de tocar num botão no fim
   da página, e é ali que ela está olhando. */
.form-revenda__aviso {
  display: grid; gap: var(--esp-2);
  padding: var(--esp-5); border-radius: var(--rad-2);
  border-inline-start: 3px solid var(--sucesso);
  background: rgb(var(--sucesso-rgb) / .07);
}
.form-revenda__aviso--erro { border-inline-start-color: var(--erro); background: rgb(var(--erro-rgb) / .07); }
.form-revenda__aviso[hidden] { display: none; }
.form-revenda__aviso .btn { justify-self: start; margin-top: var(--esp-2); }

/* ── A JANELA SOBREPOSTA ────────────────────────────────────────────────────
   O mesmo formulário, chamado de qualquer botão do site. Usa o gesto que a
   pessoa já aprendeu no orçamento e nos filtros: fundo escurecido, X no canto,
   fecha no Esc e tocando fora. */
.janela-fundo {
  position: fixed; inset: 0; z-index: 60;
  background: rgb(var(--tinta-rgb) / .55); backdrop-filter: blur(3px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-2) var(--suave), visibility var(--dur-2) var(--suave);
}
.janela {
  position: fixed; z-index: 61; inset-block: 0; inset-inline-end: 0;
  width: min(34rem, 100%); overflow-y: auto; overscroll-behavior: contain;
  background: var(--superficie); box-shadow: var(--elev-3);
  translate: 100% 0; visibility: hidden;
  transition: translate var(--dur-2) var(--saida), visibility var(--dur-2) var(--saida);
}
[data-janela='aberta'] .janela-fundo { opacity: 1; visibility: visible; }
[data-janela='aberta'] .janela { translate: 0 0; visibility: visible; }
.janela__cabeca {
  display: flex; align-items: center; justify-content: space-between; gap: var(--esp-4);
  padding: var(--esp-5); border-bottom: var(--fio-espessura) solid var(--borda);
  position: sticky; top: 0; background: var(--superficie); z-index: 1;
}
.janela__corpo { padding: var(--esp-5); }
.janela__corpo .form-revenda__aviso { margin-bottom: var(--esp-4); }

@media (prefers-reduced-motion: reduce) {
  .janela, .janela-fundo { transition-duration: 1ms; }
}
