/* ============================================================================
   BORDADOS SMANIOTTO — DESIGN SYSTEM v1 · COMPONENTES
   Ibitinga/SP · Grupo Smaniotto · Smaniotto · Sofisticata · Palácio dos Tapetes

   Ambiente (fundo animado), movimento (surgimento e a costura), layout
   (container, seções, grades) e os componentes: botão, campo, chip de cor,
   badge, tooltip, card, ficha, navegação, modal, gaveta, tabela de dados
   e os dois tipos de aviso. Depende de tokens.css e base.css.
   ========================================================================== */

/* ── 03 AMBIENTE ─────────────────────────────────────────────────────────── */
/* Uma única camada ambiente para a página inteira: fios de linha à deriva no
   canvas + véu de brilho. As seções variam por material (bruma/algodão/tinta),
   não por efeito — assim o movimento de fundo é contínuo e nunca compete. */
#fundo-fios {
  position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .5;
}
.veu {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: var(--grad-bastidor);
  opacity: .55;
}
.trama {
  position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image:
    repeating-linear-gradient(90deg, rgb(var(--tinta-rgb) / .04) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(0deg,  rgb(var(--tinta-rgb) / .04) 0 1px, transparent 1px 9px);
}
.secao--tinta .trama {
  background-image:
    repeating-linear-gradient(90deg, rgb(var(--bruma-rgb) / .05) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(0deg,  rgb(var(--bruma-rgb) / .05) 0 1px, transparent 1px 9px);
}
.brilho {
  position: absolute; border-radius: var(--rad-total); pointer-events: none;
  filter: blur(90px); opacity: .5;
  animation: derivar 22s var(--suave) infinite alternate;
}
.brilho--rose   { background: rgb(var(--rose-rgb) / .55); }
.brilho--carmim { background: rgb(var(--carmim-rgb) / .35); animation-duration: 28s; animation-direction: alternate-reverse; }
@keyframes derivar {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(4%, -6%, 0) scale(1.12); }
}

/* ── 04 MOVIMENTO ────────────────────────────────────────────────────────── */
/* Surgimento — mesma nomenclatura dos templates de referência. */
.js .surge      { opacity: 0; transform: translateY(22px); }
.js .surge-lento{ opacity: 0; transform: translateY(34px); }
.js .surge.visivel, .js .surge-lento.visivel {
  opacity: 1; transform: none;
  transition: opacity var(--dur-3) var(--saida), transform var(--dur-3) var(--saida);
  transition-delay: var(--atraso, 0ms);
}
.js .revela-linha { display: inline-flex; overflow: hidden; vertical-align: top; }
.js .revela-palavra { display: inline-block; transform: translateY(115%); }
.js .visivel > .revela-linha > .revela-palavra,
.js .revela-linha.visivel > .revela-palavra {
  transform: translateY(0);
  transition: transform var(--dur-4) var(--saida);
  transition-delay: var(--atraso, 0ms);
}

/* A COSTURA — assinatura do sistema.
   Ponto corrido que se desenha da esquerda para a direita quando entra em tela.
   Usada em 3 escalas: divisória de seção, arabesco do hero, estado de componente. */
.costura { position: relative; height: var(--esp-6); overflow: hidden; transition: --avanco var(--dur-4) var(--saida); }
.costura__trilho {
  position: absolute; inset: 0;
  clip-path: inset(0 calc((1 - var(--avanco)) * 100%) 0 0);
}
.js .costura:not(.visivel) { --avanco: 0; }
.costura__fio {
  position: absolute; top: 50%; left: 0; right: 0; height: 0;
  border-top: var(--fio-espessura) dashed var(--carmim);
  opacity: .7;
}
.costura__no {
  position: absolute; top: 50%; left: calc(var(--avanco) * 100%);
  width: var(--esp-2); height: var(--esp-2); margin: calc(var(--esp-1) * -1) 0 0 calc(var(--esp-1) * -1);
  background: var(--carmim); border-radius: var(--rad-total);
  box-shadow: 0 0 0 4px rgb(var(--carmim-rgb) / .18);
}
.secao--tinta .costura__fio { border-color: var(--rose); }
.secao--tinta .costura__no  { background: var(--rose); box-shadow: 0 0 0 4px rgb(var(--rose-rgb) / .18); }

/* A COSTURA EM PÉ — a mesma assinatura, girada, servindo de espinha para uma
   sequência de passos.

   POR QUE ELA EXISTE. Um "como funciona" com círculos numerados é o desenho
   que qualquer site tem, e não diz nada sobre quem está do outro lado. Esta
   fábrica borda: a linha que costura os passos é literalmente o que ela faz o
   dia inteiro. O caminho da revendedora é desenhado como uma costura correndo
   de cima para baixo, e cada passo é um nó dessa linha.

   É o mesmo mecanismo do `.costura` horizontal — `--avanco` registrado com
   @property, avançando de 0 a 1 quando o elemento entra na tela pelo
   IntersectionObserver — só que o recorte é vertical. Sem JavaScript, e com
   movimento reduzido ligado, `--avanco` fica em 1 e a linha nasce inteira: a
   sequência continua legível, só não se desenha na frente de quem olha. */
.costura-vertical { position: relative; }
.costura-vertical__trilho {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--fio-espessura);
  border-left: var(--fio-espessura) dashed var(--carmim); opacity: .7;
  /* O recorte come de BAIXO para cima, então a linha desce conforme avança. */
  clip-path: inset(0 0 calc((1 - var(--avanco)) * 100%) 0);
}
.secao--tinta .costura-vertical__trilho { border-color: var(--rose); }
.js .costura-vertical:not(.visivel) { --avanco: 0; }
.costura-vertical { transition: --avanco var(--dur-4) var(--saida); }

/* Arabesco — o motivo de bordado do hero, desenhado ponto a ponto. */
/* ── ⚠️ A COR E A OPACIDADE MORAM NO `.arabesco`, NUNCA NO `.arabesco__traco` ──
   O motivo é definido UMA vez, num `<defs>`, e desenhado por `<use>`. O que
   aparece na tela é o CLONE, e num clone de `<use>` só seletor SIMPLES pega:
   `.arabesco__traco` alcança, `.hero--foto .arabesco__traco` não alcança nunca,
   porque os ancestrais do clone estão do outro lado da fronteira de sombra.

   Isso custou um dia inteiro em 11/8/2026. Existia uma regra
   `.hero--foto .arabesco__traco { stroke: var(--rose) }` em padroes.css que
   estava MORTA desde que foi escrita — e o pior: `getComputedStyle` no path do
   `<defs>` respondia "rose", porque o original REALMENTE era rose. Só o
   desenhado não era. O motivo era carmim a 55% em todo lugar, inclusive sobre
   foto escura: compõe #632836 sobre a tinta, 1,4:1, um vermelho sujo que o
   Felipe descreveu como "o vetor não aparece".

   A saída é o idioma que o sprite de ícones deste projeto já usa: o traço pinta
   `currentColor`, e quem decide a cor é o `color` do contêiner. `color` é
   HERDADA e atravessa a fronteira do `<use>`; `stroke` casado por seletor com
   ancestral, não. Mesma coisa para a transparência: `opacity` no contêiner é
   opacidade de grupo e funciona; no clone, por seletor com ancestral, não.

   O ganho é maior do que a cor: agora cada cópia obedece ao SEU contexto, e não
   ao lugar onde os `<defs>` calharam de ficar. */
.arabesco { width: 100%; height: auto; overflow: visible; color: var(--carmim); opacity: .55; }
.arabesco__traco {
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-dasharray: var(--ponto) var(--lacuna);
}

/* Sobre fundo escuro: rose, como todo acento da família do carmim sobre a tinta
   — são doze regras neste arquivo, e o motivo era a única exceção.

   E SEM DILUIÇÃO. Compor uma cor clara a 55% sobre fundo escuro não a deixa
   discreta, mistura com o fundo até virar barro. A delicadeza do bordado já vem
   do traço de 1,6px e do pontilhado `--ponto`/`--lacuna`: a transparência era um
   segundo véu fazendo o trabalho que o ponto já fazia, e só no escuro cobrava.
   Sobre fundo claro a diluição fica, porque lá ela funciona — carmim a 55% sobre
   a bruma é o rubor certo.

   `:is()` com os dois contextos porque o fundo é o mesmo e o contêiner não:
   mesmo idioma do `:is(.secao--tinta, .menu-movel)` dos botões. */
:is(.secao--tinta, .hero--foto) .arabesco { color: var(--rose); opacity: 1; }
.arabesco-porta { transition: --avanco 2200ms var(--saida); }
.arabesco-mascara { clip-path: inset(0 calc((1 - var(--avanco)) * 100%) 0 0); }
.js .arabesco-porta:not(.visivel) { --avanco: 0; }

/* Marquise das três linhas */
.marquise { display: flex; width: max-content; animation: correr 34s linear infinite; }
@keyframes correr { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.marquise__faixa:hover .marquise, .marquise:focus-within { animation-play-state: paused; }

/* ── 05 LAYOUT ───────────────────────────────────────────────────────────── */
.envolucro { width: 100%; max-width: var(--largura-max); margin-inline: auto; padding-inline: var(--goteira); }
.secao { position: relative; padding-block: var(--esp-9); isolation: isolate; overflow: hidden; }
.secao--curta { padding-block: var(--esp-7); }
.secao--algodao { background: rgb(var(--algodao-rgb) / .9); }
.secao--tinta { background: var(--tinta); color: var(--texto-inverso); --sob: var(--tinta); --anel-selecao: var(--rose); }
.secao--tinta .h1, .secao--tinta .h2, .secao--tinta .h3 { color: var(--algodao); }
.secao__conteudo { position: relative; z-index: 1; }

.cabeca-secao { display: flex; flex-direction: column; gap: var(--esp-3); margin-bottom: var(--esp-7); max-width: var(--largura-texto); }
.cabeca-secao__eixo { display: flex; align-items: center; gap: var(--esp-3); color: var(--carmim); }
.cabeca-secao__eixo::after { content: ''; flex: 1; height: 1px; background: var(--borda); }
.secao--tinta .cabeca-secao__eixo { color: var(--rose); }
.secao--tinta .cabeca-secao__eixo::after { background: var(--borda-inversa); }

.grade { display: grid; gap: var(--esp-5); }
.grade--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grade--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grade--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grade--auto { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.pilha { display: flex; flex-direction: column; gap: var(--esp-4); }
.linha { display: flex; flex-wrap: wrap; align-items: center; gap: var(--esp-3); }
/* Os dois únicos alinhamentos que a linha precisa além do padrão. Existem como
   modificador porque estavam escritos como style="" dentro do HTML em cinco
   lugares — e estilo no HTML não obedece a nenhum token. */
.linha--entre  { justify-content: space-between; }
.linha--centro { justify-content: center; }

/* Painel de foto — imagem com véu e aproximação suave no hover. */
.painel { position: relative; overflow: hidden; background: var(--bruma); border-radius: var(--rad-1); }
.painel > img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.1s var(--saida); }
.painel::after { content: ''; position: absolute; inset: 0; background: var(--grad-veu); pointer-events: none; }
.painel--limpo::after { display: none; }
.painel:hover > img { transform: scale(1.05); }
/* O texto sobre a foto carrega o próprio escurecimento, e não só o véu do
   painel: o véu ainda é fraco na altura em que o rótulo cai, e sobre foto clara
   — que é a maioria deste acervo — o texto ficava ilegível. A folga em cima
   existe para o gradiente ter onde se dissolver antes de encostar na foto.

   A folga de cima é --esp-6, e não mais do que isso, porque o mesmo bloco serve
   painéis grandes e miniaturas: numa miniatura de 130px de altura, uma folga
   maior faria o escurecimento comer metade da foto.

   ⚠️ AS TRÊS LINHAS ACIMA JÁ ESTIVERAM FORA DO COMENTÁRIO, por um fechamento a
   mais na linha de cima, e o efeito passou despercebido por semanas: o CSS
   inválido no topo de uma regra faz o navegador DESCARTAR A REGRA INTEIRA, em
   silêncio. `.painel__texto` simplesmente não existia, e as três legendas sobre
   foto do ds1.html apareciam soltas, em algodão sobre foto clara. Achado pelo
   ferramentas/conferir-tokens.php, que nasceu na fase 15 justamente disto. */
.painel__texto { position: absolute; inset: auto 0 0 0; z-index: 1; padding: var(--esp-6) var(--esp-4) var(--esp-4);
                 color: var(--algodao); background: var(--grad-rotulo); }

/* ── 06 COMPONENTES ──────────────────────────────────────────────────────── */

/* BOTÃO ---------------------------------------------------------------------
   Estrutura: <button class="btn btn--primario"> rótulo <span class="btn__selo">
   ícone </span></button>. O selo é o quadrado de ícone que inverte no hover —
   é o gesto de botão do sistema, repetido em todas as variantes.

   ── ⚠️ O RECUO É ASSIMÉTRICO SÓ QUANDO HÁ SELO, E ISSO CUSTOU UMA FASE ─────

   `--btn-recuo` (24 px) à esquerda contra 4 px à direita não é descuido: o selo
   é um quadrado de 32 px encostado na borda direita, e é ELE que faz o peso
   daquele lado. Some o selo e o recuo vira defeito — o texto nasce empurrado
   para a direita, com 24 px de folga de um lado e 4 do outro.

   Foi exatamente o que aconteceu quando a fase N1B tirou o selo dos 149 botões
   da lista de peças do painel: decisão certa (*"repetido 149 vezes, ele era
   barulho"*), mas o recuo ficou. Medido na tela em 21/8/2026, antes da correção:
   "Tirar do ar" com 93,41 px e o texto colado na borda direita; "Pôr no ar" com
   86,39 px; e os dois numa mesma coluna, com a borda esquerda dançando 7 px de
   linha para linha.

   Por isso o recuo mora numa variável e a regra logo abaixo do bloco de
   variantes o devolve DOS DOIS LADOS quando não há selo. Quem muda o recuo —
   `--grande`, `--fantasma`, `--icone` — troca a variável, e a simetria segue
   sozinha.

   ── E UM `text-align` SÓ, PARA TODA TAG ────────────────────────────────────

   O mesmo `.btn` é escrito como <button>, <a>, <label> e <span>, e o padrão do
   navegador só centra o texto do <button>: os outros herdavam `start`. Na
   janela de confirmação isso deixava os DOIS botões lado a lado alinhando de
   jeitos diferentes. `justify-content` centra o conteúdo dentro do botão (o que
   importa quando ele tem largura mínima, como o `.btn--par`), e `text-align`
   centra as linhas dentro do rótulo (o que importa quando ele quebra em duas).
   `.btn--largo` e `.btn--icone` redeclaram o que precisam, logo abaixo. */
.btn {
  --btn-fundo: var(--carmim); --btn-texto: var(--algodao); --btn-borda: transparent;
  --btn-recuo: var(--esp-5);
  position: relative; display: inline-flex; align-items: center; gap: var(--esp-4);
  justify-content: center; text-align: center;
  padding: var(--esp-1) var(--esp-1) var(--esp-1) var(--btn-recuo);
  min-height: var(--alt-controle);
  background: var(--btn-fundo); color: var(--btn-texto);
  border: 1px solid var(--btn-borda); border-radius: var(--rad-1);
  font-size: var(--t-corpo-sm); font-weight: var(--peso-medio); line-height: 1;
  cursor: pointer; overflow: hidden; isolation: isolate;
  transition: background var(--dur-1) var(--suave), color var(--dur-1) var(--suave),
              border-color var(--dur-1) var(--suave), transform var(--dur-2) var(--saida),
              box-shadow var(--dur-2) var(--saida);
}
.btn__selo {
  display: grid; place-items: center; width: 2rem; height: 2rem; flex: none;
  background: rgb(var(--algodao-rgb) / .16); border-radius: var(--rad-1);
  transition: background var(--dur-1) var(--suave), color var(--dur-1) var(--suave),
              transform var(--dur-2) var(--saida);
}
.btn__selo svg { width: 1.05rem; height: 1.05rem; }
/* Brilho que atravessa o botão no hover — o reflexo do fio de cetim. */
.btn::before {
  content: ''; position: absolute; inset: 0; z-index: -1; transform: translateX(-101%);
  background: linear-gradient(100deg, transparent, rgb(var(--algodao-rgb) / .22) 42%, transparent 72%);
  transition: transform var(--dur-3) var(--saida);
}
.btn:hover::before { transform: translateX(101%); }
.btn:hover { transform: translateY(-2px); box-shadow: var(--elev-2); }
.btn:active { transform: translateY(0); box-shadow: none; }
.btn:hover .btn__selo { background: var(--algodao); color: var(--btn-fundo); transform: translateX(2px); }

/* Uma variação de tamanho, não de cor. Existe para o único lugar da página em
   que o botão não concorre com nenhum outro: a chamada principal da hero. Onde
   houver dois botões lado a lado, use o tamanho normal — um botão grande ao
   lado de um pequeno não hierarquiza, só desequilibra. */
.btn--grande { --btn-recuo: var(--esp-6);
               padding: var(--esp-2) var(--esp-2) var(--esp-2) var(--btn-recuo);
               min-height: var(--alt-controle-grande); font-size: var(--t-corpo); }

.btn--primario  { --btn-fundo: var(--carmim); }
.btn--primario:hover { --btn-fundo: var(--carmim-forte); }
.btn--secundario { --btn-fundo: transparent; --btn-texto: var(--tinta); --btn-borda: var(--borda-forte); }
.btn--secundario .btn__selo { background: rgb(var(--tinta-rgb) / .08); }
.btn--secundario:hover { --btn-borda: var(--carmim); --btn-texto: var(--carmim); }
.btn--secundario:hover .btn__selo { background: var(--carmim); color: var(--algodao); }
/* O fantasma já nasceu simétrico — `padding-inline` nos dois lados —, porque
   ele nunca teve moldura para o selo equilibrar. Continua assim, agora pela
   variável, para a regra de simetria lá embaixo ler o mesmo valor. */
.btn--fantasma { --btn-fundo: transparent; --btn-texto: var(--texto-brando); --btn-borda: transparent;
                 --btn-recuo: var(--esp-3); padding-inline: var(--btn-recuo); gap: var(--esp-2); }
.btn--fantasma:hover { --btn-texto: var(--carmim); transform: none; box-shadow: none; }
.btn--fantasma .btn__selo { background: transparent; width: 1.25rem; height: 1.25rem; }
/* O selo do fantasma não inverte: sem fundo próprio, a regra geral pintaria o
   ícone da cor do fundo do botão — que é transparente — e ele sumiria. */
.btn--fantasma:hover .btn__selo { background: transparent; color: inherit; }
.btn--zap { --btn-fundo: var(--zap); }
.btn--zap:hover { --btn-fundo: var(--zap-forte); }
.btn--tinta { --btn-fundo: var(--tinta); }
.btn--tinta:hover { --btn-fundo: var(--tinta-alta); }
/* O botão de ícone é um quadrado do tamanho do controle e não tem rótulo: recuo
   nenhum, dos dois lados. `--btn-recuo: 0` é o que faz a regra de simetria lá
   embaixo devolver zero em vez dos 24 px do padrão. */
.btn--icone {
  --btn-recuo: 0;
  padding: 0; width: var(--alt-controle); height: var(--alt-controle); gap: 0; justify-content: center;
  --btn-fundo: transparent; --btn-texto: var(--tinta); --btn-borda: var(--borda);
}
.btn--icone svg { width: 1.15rem; height: 1.15rem; }
.btn--icone:hover { --btn-fundo: var(--tinta); --btn-texto: var(--algodao); --btn-borda: var(--tinta); }
.btn--largo { width: 100%; justify-content: space-between; }

/* ── ⚠️ BOTÃO SEM SELO: O RECUO VOLTA A SER SIMÉTRICO ─────────────────────
   A regra que conserta o defeito descrito lá em cima. Ela vem DEPOIS de todas
   as variantes de propósito, para ler o `--btn-recuo` que cada uma escolheu:
   24 px no padrão, 32 no `--grande`, 12 no `--fantasma`, 0 no `--icone`.

   `:where()` mantém esta regra em (0,1,0), a MESMA especificidade das
   variantes. Sem ele, `:has(.btn__selo)` a levaria a (0,2,0) e ela passaria a
   ganhar de qualquer variante de uma classe só — inclusive de variantes
   escritas DEPOIS, em outro arquivo, que é onde o estrago apareceria sem aviso.
   Medido em 21/8/2026: com uma variante `.qualquer { padding-inline: 5px }`
   declarada depois, a regra com `:where()` cede os 5 px; sem `:where()` ela
   impõe os 24 px do padrão.

   ⚠️ O que NÃO é o motivo: `.btn--icone` não corre risco nenhum aqui, e a
   especificidade não tem nada a ver com isso. Ele declara `--btn-recuo: 0`, e
   uma regra que LÊ a variável devolve o valor da própria variante — 0 px de
   recuo com `:where()` e 0 px sem ele, medido nos dois. Quem protege as
   variantes de valor é a variável; o `:where()` protege as de declaração.

   O selo ESCONDIDO por `display:none` ainda casa em `:has()` — o elemento
   continua na árvore —, e então esta regra NÃO age: o recuo do botão continua
   sendo o assimétrico, como se o selo estivesse lá. Quem esconde selo decide o
   recuo no mesmo lugar em que esconde. Hoje são dois: a barra do painel em
   375 px, que redeclara `padding-inline` (ver painel.css), e o "Salvar" de
   campo, que é `--fantasma` e já nasce simétrico — nada a fazer. */
.btn:where(:not(:has(.btn__selo))) { padding-inline: var(--btn-recuo); }

/* ── BOTÕES QUE DIVIDEM UMA COLUNA OU UMA LINHA ───────────────────────────
   Botão isolado tem a largura do seu rótulo, e está certo. Mas quando dois ou
   mais aparecem lado a lado dizendo a mesma família de coisa — "Deixar no ar" e
   "Tirar do ar" na janela de confirmação —, ou empilhados na mesma coluna de
   uma lista — "Tirar do ar" e "Pôr no ar" nas 149 linhas de peça —, larguras
   diferentes fazem a borda esquerda dançar de linha para linha. Medido em
   21/8/2026, em 1440 px: antes de tudo, 105,13 contra 93,41 na janela e 93,41
   contra 86,39 na lista; com o recuo simétrico já corrigido e ainda sem esta
   regra, 125,13 contra 113,41 e 113,41 contra 106,39. A diferença sobrevive à
   correção do recuo porque ela nunca foi do recuo: é do rótulo.

   `--largura-botao-acao` é o teto medido dessa família de rótulos, e o porquê
   do número está no tokens.css. Como o conteúdo é centrado pelo
   `justify-content` do `.btn`, a folga que sobra num rótulo curto não aparece
   de um lado só. Rótulo que passar do teto faz o botão crescer — não corta
   texto —, e aí a largura comum se perde: é o preço de o rótulo vir do banco. */
.btn--par { min-width: var(--largura-botao-acao); }

/* Sobre fundo tinta — a seção tinta E o menu móvel (ver a nota em base.css).
   Sem o menu nesta lista, o --btn-texto do botão de ícone continuava valendo
   var(--tinta): o × de fechar era desenhado em tinta sobre tinta — a MESMA cor,
   contraste 1,00:1. O ícone estava lá, do tamanho certo, e simplesmente não
   dava para ver. Era esse o bug do "quadrado vazio" no menu do celular. */
:is(.secao--tinta, .menu-movel) .btn--secundario { --btn-texto: var(--bruma); --btn-borda: var(--borda-inversa); }
:is(.secao--tinta, .menu-movel) .btn--secundario:hover { --btn-texto: var(--tinta); --btn-fundo: var(--rose); --btn-borda: var(--rose); }
:is(.secao--tinta, .menu-movel) .btn--secundario .btn__selo { background: rgb(var(--bruma-rgb) / .12); }
:is(.secao--tinta, .menu-movel) .btn--icone { --btn-texto: var(--bruma); --btn-borda: var(--borda-inversa); }
/* O hover do botão de ícone inverte para tinta. Sobre fundo tinta isso é
   invisível — inverte para o claro, que é o mesmo gesto lido ao contrário. */
:is(.secao--tinta, .menu-movel) .btn--icone:hover { --btn-fundo: var(--bruma); --btn-texto: var(--tinta); --btn-borda: var(--bruma); }
/* O fantasma é o único dos três que não tinha inversão, e o buraco custou caro:
   var(--texto-brando) sobre a tinta dá contraste 2,49:1 — abaixo do mínimo
   legível de 4,5:1 — e o hover, que troca para var(--carmim), PIORA para 2,13:1.
   O gesto ficava invertido: encostar o mouse apagava mais o botão.

   Sobre claro nada muda, e lá o fantasma sempre esteve certo: 6,08:1 em repouso
   e 7,09:1 no hover.

   Onde isto aparecia na tela: "Trocar de tapete" e "Usar 5,00 m" no medidor de
   tapete — que é justamente o botão que tira a pessoa do estado de erro —, o
   "Limpar tudo" da gaveta de orçamento e as setas do reprodutor de vídeo. Um
   controle de resgate que parece texto desativado é uma recusa sem saída. */
:is(.secao--tinta, .menu-movel) .btn--fantasma { --btn-texto: rgb(var(--bruma-rgb) / .82); }
:is(.secao--tinta, .menu-movel) .btn--fantasma:hover { --btn-texto: var(--rose); }

.btn[disabled], .btn[aria-disabled='true'] {
  --btn-fundo: rgb(var(--tinta-rgb) / .1); --btn-texto: rgb(var(--tinta-rgb) / .38); --btn-borda: transparent;
  cursor: not-allowed; transform: none; box-shadow: none;
}
.btn[disabled]::before { display: none; }
.btn[disabled] .btn__selo { background: rgb(var(--tinta-rgb) / .06); }

/* Carregando: o selo vira uma bobina de linha girando. */
.btn[data-estado='carregando'] { pointer-events: none; }
.btn[data-estado='carregando'] .btn__selo svg { display: none; }
.btn[data-estado='carregando'] .btn__selo::after {
  content: ''; width: 1rem; height: 1rem; border-radius: var(--rad-total);
  border: 1.5px dashed currentColor; border-top-color: transparent;
  animation: bobinar 900ms linear infinite;
}
@keyframes bobinar { to { transform: rotate(360deg); } }

/* CAMPO ---------------------------------------------------------------------
   <label class="campo"><span class="campo__rotulo">…</span>
   <input class="campo__controle"><span class="campo__ajuda">…</span></label> */
.campo { display: flex; flex-direction: column; gap: var(--esp-2); }
.campo__rotulo { 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); }
.campo__controle {
  width: 100%; padding: var(--esp-3) var(--esp-4); min-height: var(--alt-controle);
  background: var(--superficie-alta); color: var(--texto);
  border: 1px solid var(--borda); border-radius: var(--rad-1);
  font-size: var(--t-corpo-sm);
  transition: border-color var(--dur-1) var(--suave), box-shadow var(--dur-1) var(--suave), background var(--dur-1) var(--suave);
}
.campo__controle::placeholder { color: rgb(var(--castanho-rgb) / .6); }
.campo__controle:hover { border-color: var(--borda-forte); }
.campo__controle:focus { outline: none; border-color: var(--carmim); box-shadow: var(--elev-foco); }
.campo__controle:disabled { background: rgb(var(--tinta-rgb) / .04); color: rgb(var(--tinta-rgb) / .4); cursor: not-allowed; }
textarea.campo__controle { min-height: 7rem; resize: vertical; line-height: var(--lh-corpo); }
select.campo__controle {
  appearance: none; padding-right: var(--esp-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.35rem) 1.2rem, calc(100% - 1rem) 1.2rem;
  background-size: 6px 6px, 6px 6px; background-repeat: no-repeat;
}
.campo__ajuda { font-size: var(--t-auxiliar); color: var(--texto-brando); }
/* A MENSAGEM DE ERRO DO CAMPO. Nasce sem altura e só ocupa espaço quando tem o
   que dizer — assim o formulário não reserva uma faixa vazia embaixo de cada
   campo "por precaução", que empurraria o botão de envio para longe. */
.campo__erro { font-size: var(--t-auxiliar); color: var(--erro); font-weight: var(--peso-medio); }
.campo__erro:empty { display: none; }
/* "opcional" ao lado do rótulo: quem lê um formulário decide o que pular pelo
   que NÃO está marcado como necessário. Marcar o opcional é mais honesto do que
   marcar sete campos com asterisco. */
.campo__opcional { font-weight: var(--peso-normal); color: var(--texto-brando);
                   text-transform: none; letter-spacing: var(--tr-normal); }
.campo[data-estado='erro'] .campo__controle { border-color: var(--erro); box-shadow: 0 0 0 3px rgb(var(--erro-rgb) / .16); }
.campo[data-estado='erro'] .campo__ajuda { color: var(--erro); font-weight: var(--peso-medio); }
.campo[data-estado='ok'] .campo__controle { border-color: var(--sucesso); }
.secao--tinta .campo__rotulo, .secao--tinta .campo__ajuda { color: rgb(var(--bruma-rgb) / .7); }
.secao--tinta .campo__controle { background: rgb(var(--bruma-rgb) / .07); border-color: var(--borda-inversa); color: var(--algodao); }
.secao--tinta .campo__controle::placeholder { color: rgb(var(--bruma-rgb) / .45); }
.secao--tinta .campo__controle:focus { border-color: var(--rose); box-shadow: 0 0 0 3px rgb(var(--rose-rgb) / .25); }

/* Caixa e opção: o marcador é um ponto de bordado. */
.opcao { display: flex; align-items: flex-start; gap: var(--esp-3); cursor: pointer; font-size: var(--t-corpo-sm); }
.opcao input { position: absolute; opacity: 0; width: 0; height: 0; }
.opcao__marca {
  flex: none; display: grid; place-items: center; width: 1.25rem; height: 1.25rem; margin-top: .12rem;
  border: 1px solid var(--borda-forte); border-radius: var(--rad-1); background: var(--superficie-alta);
  transition: background var(--dur-1) var(--suave), border-color var(--dur-1) var(--suave);
}
.opcao--radio .opcao__marca { border-radius: var(--rad-total); }
.opcao__marca svg { width: .8rem; height: .8rem; color: var(--algodao); opacity: 0; transform: scale(.5);
                    transition: opacity var(--dur-1) var(--saida), transform var(--dur-2) var(--saida); }
.opcao input:checked + .opcao__marca { background: var(--carmim); border-color: var(--carmim); }
.opcao input:checked + .opcao__marca svg { opacity: 1; transform: scale(1); }
.opcao input:focus-visible + .opcao__marca { outline: 2px solid var(--carmim); outline-offset: 3px; }
.opcao input:disabled + .opcao__marca { background: rgb(var(--tinta-rgb) / .06); border-color: var(--borda); }
.opcao input:disabled ~ .opcao__texto { color: rgb(var(--tinta-rgb) / .4); }

/* Chip de cor — o vocabulário do catálogo: PALHA, TABACO, VERMELHO…
   O chip é preenchido com a cor real do produto. O texto vira claro ou escuro
   conforme a luminância do preenchimento (calculada no carregamento), de modo
   que o nome continua legível em cima de branco, de vermelho ou de preto.
   Estrutura: <button class="chip-cor" aria-pressed="false" style="--chip:#…"
              title="Nome"><span class="chip-cor__marca">✓</span>Nome</button> */
.chip-cor {
  --chip-anel: rgb(var(--tinta-rgb) / .2);
  display: inline-flex; align-items: center; gap: var(--esp-2);
  padding: var(--esp-2) var(--esp-4); min-height: 2.25rem;
  border: 0; border-radius: var(--rad-total);
  background: var(--chip, var(--bruma)); color: var(--tinta);
  box-shadow: inset 0 0 0 1px var(--chip-anel);
  font-size: var(--t-rotulo); font-weight: var(--peso-forte); letter-spacing: var(--tr-chip);
  text-transform: uppercase; font-variation-settings: 'wdth' 88;
  cursor: pointer;
  transition: box-shadow var(--dur-1) var(--suave), transform var(--dur-2) var(--saida);
}
.chip-cor[data-tom='escuro'] { --chip-anel: rgb(var(--algodao-rgb) / .3); color: var(--algodao); }
.chip-cor__marca { display: grid; place-items: center; width: 0; overflow: hidden; opacity: 0;
                   transition: width var(--dur-2) var(--saida), opacity var(--dur-1) var(--suave); }
.chip-cor__marca svg { width: .85rem; height: .85rem; }
.chip-cor:hover { transform: translateY(-1px); box-shadow: inset 0 0 0 1px var(--chip-anel), var(--elev-1); }
/* Selecionado: anel interno na cor do texto + halo externo no acento, com uma
   folga na cor do que está atrás. Num preenchimento escuro (tabaco, preto) o
   anel interno sozinho some dentro da própria cor — o halo é o que garante
   que dá para ver a seleção em qualquer chip. */
.chip-cor[aria-pressed='true'] {
  box-shadow: inset 0 0 0 2px currentColor,
              0 0 0 2px var(--sob),
              0 0 0 4px var(--anel-selecao);
}
.chip-cor[aria-pressed='true'] .chip-cor__marca { width: .85rem; opacity: 1; }
.chip-cor[aria-pressed='true']:hover {
  box-shadow: inset 0 0 0 2px currentColor,
              0 0 0 2px var(--sob),
              0 0 0 4px var(--anel-selecao),
              var(--elev-1);
}

/* AMOSTRA DE COR — a foto da peça naquela cor, no lugar da palavra ------------

   O CHIP DE CIMA CONTINUA VALENDO, e é ele que aparece na cor que tem
   `amostra_hex` cadastrado. Esta amostra é para o caso que o site tem hoje: 223
   cores sem hex nenhum, então onze chips de texto lado a lado, cinco deles bege
   — CASTOR, MESCLA BEGE, NUDE, PÉROLA, TRIGO. Ninguém distingue os cinco pela
   palavra, e a única saída era clicar um por um.

   A FOTO É UM AMBIENTE, e não um retalho de tecido. Por isso o nome fica: a
   miniatura desambigua, a palavra nomeia. Uma sozinha não faz o trabalho da
   outra, e trocar o nome pela foto seria perder o vocabulário do catálogo, que é
   o que a vendedora usa no WhatsApp.

   MEDIDA: 4,5rem de largura em 4:3, que é o formato de toda derivada do site.
   Onze amostras cabem em duas fileiras a 1440 e três a 375 — a MESMA altura que
   as onze pílulas de texto ocupavam. Aumentar mais empurraria o botão de
   orçamento para fora da tela, que é o oposto do que esta mudança quer.

   Estrutura: <a class="amostra-cor" aria-current="true"><span class="amostra-cor__foto">
                <img …><span class="amostra-cor__marca">✓</span></span>
                <span class="amostra-cor__nome">Castor</span></a> */
/* `align-items: flex-start` NÃO é enfeite. Sem ele o filho mais baixo da fileira
   é esticado até a altura do mais alto — e uma pílula de texto esticada, com
   `border-radius` total, vira um círculo enorme no meio das fotos. Foi assim que
   a Cortina Dia a Dia apareceu, com uma foto e um balão. */
.amostras { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--esp-3); }
.amostra-cor {
  display: flex; flex-direction: column; gap: var(--esp-2);
  width: 4.5rem; text-decoration: none; cursor: pointer;
  transition: transform var(--dur-2) var(--saida);
}
.amostra-cor__foto {
  position: relative; display: block; overflow: hidden;
  border-radius: var(--rad-1); background: var(--bruma);
  box-shadow: inset 0 0 0 1px var(--borda);
  transition: box-shadow var(--dur-1) var(--suave);
}
.amostra-cor__foto img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }

/* A LADRILHO SEM FOTO. Numa peça em que ALGUMA cor tem foto, a cor que não tem
   entra como ladrilho vazio, e não como pílula de texto: uma fileira de retângulos
   com um balão no meio se lê como defeito, e a forma repetida é o que faz a
   fileira ser lida como um controle só.

   O preenchimento é `--chip`, a mesma variável do chip de texto — ou seja, no dia
   em que o cliente informar `amostra_hex`, o ladrilho passa a sair na cor de
   verdade sem que nada aqui mude. Sem hex, sai na bruma, e quem informa é o nome
   embaixo, como sempre foi. */
.amostra-cor__foto--vazia { aspect-ratio: 4 / 3; background: var(--chip, var(--bruma)); }
.amostra-cor__nome {
  font-size: var(--t-rotulo); font-weight: var(--peso-forte); letter-spacing: var(--tr-chip);
  text-transform: uppercase; font-variation-settings: 'wdth' 88;
  color: rgb(var(--tinta-rgb) / .68); line-height: 1.2;
  transition: color var(--dur-1) var(--suave);
}
.amostra-cor:hover { transform: translateY(-2px); }
.amostra-cor:hover .amostra-cor__foto { box-shadow: inset 0 0 0 1px var(--borda), var(--elev-1); }
.amostra-cor:hover .amostra-cor__nome { color: var(--tinta); }
.amostra-cor:focus-visible { outline: none; }
.amostra-cor:focus-visible .amostra-cor__foto {
  outline: 2px solid var(--carmim); outline-offset: 3px;
}

/* A MARCA DE CONFERIDO fica sobre a foto, e não ao lado do nome como no chip:
   sobre imagem, forma se lê onde cor não se lê. É o segundo sinal da seleção — o
   primeiro é o halo — e é de propósito que um dos dois não dependa de cor. */
.amostra-cor__marca {
  position: absolute; inset-block-start: var(--esp-1); inset-inline-end: var(--esp-1);
  display: grid; place-items: center; width: 1.15rem; height: 1.15rem;
  border-radius: var(--rad-total); background: var(--carmim); color: var(--algodao);
  opacity: 0; transform: scale(.5);
  transition: opacity var(--dur-1) var(--saida), transform var(--dur-2) var(--saida);
}
.amostra-cor__marca svg { width: .7rem; height: .7rem; }

/* Selecionada: o mesmo halo de duas camadas do chip — folga na cor do que está
   atrás, depois o anel de acento. O anel INTERNO do chip não vem junto: sobre
   foto ele desaparece dentro da própria imagem. */
.amostra-cor[aria-current='true'] .amostra-cor__foto {
  box-shadow: 0 0 0 2px var(--sob), 0 0 0 4px var(--anel-selecao);
}
.amostra-cor[aria-current='true']:hover .amostra-cor__foto {
  box-shadow: 0 0 0 2px var(--sob), 0 0 0 4px var(--anel-selecao), var(--elev-1);
}
.amostra-cor[aria-current='true'] .amostra-cor__marca { opacity: 1; transform: scale(1); }
.amostra-cor[aria-current='true'] .amostra-cor__nome { color: var(--tinta); }

/* Esgotada: a foto perde a cor e o nome esmaece. Continua na tela — saber que a
   cor existe e está fora é informação, e some-la faria a pessoa procurar. */
.amostra-cor[aria-disabled='true'] { cursor: not-allowed; }
.amostra-cor[aria-disabled='true']:hover { transform: none; }
.amostra-cor[aria-disabled='true'] .amostra-cor__foto img { filter: grayscale(1); opacity: .45; }
.amostra-cor[aria-disabled='true'] .amostra-cor__nome { color: rgb(var(--tinta-rgb) / .38); }

@media (prefers-reduced-motion: reduce) {
  .amostra-cor, .amostra-cor__foto, .amostra-cor__nome, .amostra-cor__marca { transition: none; }
  .amostra-cor:hover { transform: none; }
}

/* BLOCO -------------------------------------------------------------------
   O painel com borda: um pedaço de conteúdo que se lê como uma unidade, com
   título opcional separado por tracejado. Morou em documentacao.css até
   5/8/2026, porque até então só a documentação tinha painéis; mudou de folha
   quando as páginas institucionais da fase 11 passaram a precisar dele — que é
   o que o cabeçalho daquele arquivo manda fazer, em vez de copiar a regra.
   O `.bloco--vitrine` ficou lá: aquele é de demonstração. */
.bloco { padding: var(--esp-5); background: var(--superficie-alta); border: 1px solid var(--borda); border-radius: var(--rad-2); }
.bloco__titulo { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-4); margin-bottom: var(--esp-4);
                 padding-bottom: var(--esp-3); border-bottom: 1px dashed var(--borda); }
.secao--tinta .bloco { background: rgb(var(--bruma-rgb) / .05); border-color: var(--borda-inversa); }

/* BADGE ------------------------------------------------------------------- */
.badge { display: inline-flex; align-items: center; gap: var(--esp-2); padding: .3rem var(--esp-3);
         border-radius: var(--rad-1); font-size: var(--t-rotulo); font-weight: var(--peso-forte);
         letter-spacing: var(--tr-rotulo); text-transform: uppercase; font-variation-settings: 'wdth' 88;
         background: rgb(var(--tinta-rgb) / .08); color: var(--tinta); }
.badge--novidade { background: var(--carmim); color: var(--algodao); }
.badge--destaque { background: var(--rose); color: var(--tinta); }
.badge--promocao { background: var(--atencao); color: var(--algodao); }
.badge--medida  { background: rgb(var(--algodao-rgb) / .94); color: var(--carmim); box-shadow: inset 0 0 0 1px currentColor; }
.badge--pronta  { background: rgb(var(--sucesso-rgb) / .12); color: var(--sucesso); }
.badge--pulsa::before { content: ''; width: .4rem; height: .4rem; border-radius: var(--rad-total);
                        background: currentColor; animation: pulsar 2s var(--suave) infinite; }
@keyframes pulsar { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(1.6); } }

/* TOOLTIP — abre no hover e no foco de teclado. */
.dica { position: relative; display: inline-flex; }
.dica__balao {
  position: absolute; bottom: calc(100% + var(--esp-3)); left: 50%; z-index: 20;
  transform: translate(-50%, var(--esp-2)); width: max-content; max-width: 15rem;
  padding: var(--esp-2) var(--esp-3); background: var(--tinta); color: var(--bruma);
  border-radius: var(--rad-2); font-size: var(--t-auxiliar); line-height: var(--lh-media);
  opacity: 0; pointer-events: none; box-shadow: var(--elev-2);
  transition: opacity var(--dur-1) var(--suave), transform var(--dur-2) var(--saida);
}
.dica__balao::after { content: ''; position: absolute; top: 100%; left: 50%; margin-left: -5px;
                      border: 5px solid transparent; border-top-color: var(--tinta); }
.dica:hover .dica__balao, .dica:focus-within .dica__balao { opacity: 1; transform: translate(-50%, 0); }

/* CARD ---------------------------------------------------------------------
   Três tipos: produto, categoria e revendedora. Todos compartilham a moldura
   e o fio de linha que corre no topo quando o card é focado ou apontado. */
.card {
  position: relative; display: flex; flex-direction: column;
  background: var(--superficie-alta); border: 1px solid var(--borda); border-radius: var(--rad-2);
  overflow: hidden; transition: transform var(--dur-2) var(--saida), box-shadow var(--dur-2) var(--saida), border-color var(--dur-1) var(--suave);
}
.card::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px; z-index: 2;
  background: var(--grad-fio); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-3) var(--saida);
}
.card:hover, .card:focus-within { transform: translateY(-4px); box-shadow: var(--elev-2); border-color: var(--borda-forte); }
.card:hover::before, .card:focus-within::before { transform: scaleX(1); }
.card__midia { position: relative; aspect-ratio: 4 / 3; background: var(--bruma); overflow: hidden; }
.card__midia img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-4) var(--saida); }
.card:hover .card__midia img { transform: scale(1.06); }
.card__selos { position: absolute; top: var(--esp-3); left: var(--esp-3); z-index: 1; display: flex; gap: var(--esp-2); flex-wrap: wrap; }
.card__corpo { display: flex; flex-direction: column; gap: var(--esp-3); padding: var(--esp-4); flex: 1; }
.card__titulo { font-family: var(--fonte-titulo); font-size: var(--t-h4); font-weight: var(--peso-normal); line-height: var(--lh-titulo);
                font-variation-settings: 'opsz' 48, 'SOFT' 40; }
.card__pe { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-3);
            padding: var(--esp-3) var(--esp-4); border-top: 1px solid var(--borda); margin-top: auto; }

/* Ficha técnica — a linguagem do catálogo impresso do cliente:
   código, medida e composição. É o que a vendedora precisa ler no WhatsApp. */
.ficha { display: flex; flex-wrap: wrap; gap: var(--esp-1) var(--esp-3); padding: var(--esp-2) var(--esp-3);
         background: rgb(var(--tinta-rgb) / .04); border-left: 2px solid var(--carmim); }
.ficha__item { display: flex; gap: var(--esp-2); align-items: baseline; }
.ficha__chave { font-size: var(--t-rotulo); letter-spacing: var(--tr-ficha); text-transform: uppercase; color: var(--texto-brando); }
.ficha__valor { font-family: var(--fonte-dado); font-size: var(--t-auxiliar); font-variant-numeric: tabular-nums; }
.secao--tinta .ficha { background: rgb(var(--bruma-rgb) / .07); border-left-color: var(--rose); }

/* Card de categoria — foto cheia com véu, sem moldura. */
.card-categoria { position: relative; display: block; aspect-ratio: 3 / 4; overflow: hidden; border-radius: var(--rad-2);
                  transition: transform var(--dur-2) var(--saida), box-shadow var(--dur-2) var(--saida); }
.card-categoria:hover { transform: translateY(-4px); box-shadow: var(--elev-3); }
.card-categoria img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-4) var(--saida); }
.card-categoria:hover img { transform: scale(1.07); }
.card-categoria__veu { position: absolute; inset: 0; background: var(--grad-veu); }
/* Mesma decisão do .painel__texto: escurecimento local atrás do texto, além do
   véu da foto. Sem ele, a contagem de peças — 11px, caixa alta — ficava em
   2,8:1 sobre foto clara. Com ele, passa de 8:1 em qualquer foto. */
.card-categoria__texto { position: absolute; inset: auto 0 0 0; padding: var(--esp-8) var(--esp-5) var(--esp-5);
                         color: var(--algodao); background: var(--grad-rotulo);
                         display: flex; flex-direction: column; gap: var(--esp-2); }
.card-categoria__seta { display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border: 1px solid rgb(var(--algodao-rgb) / .45);
                        border-radius: var(--rad-1); transition: background var(--dur-1) var(--suave), color var(--dur-1) var(--suave); }
.card-categoria:hover .card-categoria__seta { background: var(--algodao); color: var(--tinta); }
.card-categoria__seta svg { width: 1rem; height: 1rem; }

/* Card de revendedora — bloco de argumento, sem foto. */
.card-revenda { display: flex; flex-direction: column; gap: var(--esp-3); padding: var(--esp-5);
                background: rgb(var(--bruma-rgb) / .06); border: 1px solid var(--borda-inversa); border-radius: var(--rad-2);
                transition: background var(--dur-2) var(--suave), transform var(--dur-2) var(--saida); }
.card-revenda:hover { background: rgb(var(--bruma-rgb) / .1); transform: translateY(-3px); }
.card-revenda__icone { display: grid; place-items: center; width: var(--alt-controle); height: var(--alt-controle); border-radius: var(--rad-1);
                       background: rgb(var(--rose-rgb) / .16); color: var(--rose); }
.card-revenda__icone svg { width: 1.35rem; height: 1.35rem; }

/* NAVEGAÇÃO ---------------------------------------------------------------- */
.barra-topo { background: var(--tinta); color: rgb(var(--bruma-rgb) / .8); font-size: var(--t-rotulo);
              letter-spacing: var(--tr-rotulo); text-transform: uppercase; font-variation-settings: 'wdth' 88; }
.barra-topo__interno { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-5); min-height: 2.5rem; }
.barra-topo a:hover { color: var(--rose); }

.cabecalho { position: sticky; top: 0; z-index: 40; background: rgb(var(--algodao-rgb) / .88);
             backdrop-filter: blur(14px); border-bottom: 1px solid var(--borda); }
.cabecalho__interno { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-5); min-height: var(--alt-cabecalho); }
.marca { display: inline-flex; align-items: center; gap: var(--esp-3); }
/* O LOGOTIPO DA FÁBRICA. Altura fixa e largura pela proporção do desenho
   (283,46 × 85,45): o filete duplo e o ornamento da direita só se leem se o
   conjunto não for espremido. `flex: none` porque num cabeçalho apertado quem
   cede é o menu, nunca a marca. */
.marca__logo { height: 2.9rem; width: auto; aspect-ratio: 283.46 / 85.45;
               color: var(--marca-tinta); flex: none; }
/* AQUI MORAVAM `.marca__bastidor` e `.marca__nome` — o bastidor de bordado que
   girava devagar e o nome montado com a Fraunces. Eram o substituto do logotipo
   enquanto ele não existia, e saíram em 6/8/2026, quando o arquivo da fábrica
   chegou. O ícone `#ico-bastidor` continua no sprite: ele é usado na página de
   erro e na de revenda, e não tinha nada de errado — o que saiu foi o conjunto
   que fazia as vezes de marca. */

.menu { display: flex; align-items: center; gap: var(--esp-1); }
/* `white-space: nowrap`: rótulo de navegação não quebra no meio. "Sob medida"
   virava duas linhas quando o menu ficava apertado — no ds1.html, que tem nove
   seções, isso acontecia já a 1280px — e o cabeçalho inteiro crescia por causa
   de um item. Dois itens curtos empilhados leem como dois links, não como um. */
.menu__link { position: relative; padding: var(--esp-2) var(--esp-3); font-size: var(--t-corpo-sm); color: var(--texto-brando);
              white-space: nowrap;
              transition: color var(--dur-1) var(--suave); }
.menu__link::after { content: ''; position: absolute; left: var(--esp-3); right: var(--esp-3); bottom: .35rem; height: 0;
                     border-top: var(--fio-espessura) dashed var(--carmim);
                     transform: scaleX(0); transform-origin: left; transition: transform var(--dur-2) var(--saida); }
.menu__link:hover, .menu__link[aria-current='true'] { color: var(--texto); }
.menu__link:hover::after, .menu__link[aria-current='true']::after { transform: scaleX(1); }

.acoes-cabecalho { display: flex; align-items: center; gap: var(--esp-2); }
/* A busca do topo cede antes do menu: em tela larga é o campo, e a partir de
   1100px vira a lupa que leva para a página de busca. Os dois nunca aparecem
   juntos — seriam duas portas para a mesma sala, lado a lado. */
.cabecalho__lupa { display: none; }
@media (max-width: 1100px) {
  .cabecalho__busca { display: none; }
  .cabecalho__lupa { display: inline-flex; }
}
.contador { position: absolute; top: -.35rem; right: -.35rem; min-width: 1.15rem; height: 1.15rem; padding: 0 .25rem;
            display: grid; place-items: center; background: var(--carmim); color: var(--algodao);
            border-radius: var(--rad-total); font-size: var(--t-micro); font-weight: var(--peso-bold); font-variant-numeric: tabular-nums; }
.contador[hidden] { display: none; }
.btn-orcamento { position: relative; }
.btn-orcamento.pulou { animation: pular 480ms var(--saida); }
@keyframes pular { 0%, 100% { transform: none; } 35% { transform: translateY(-6px) scale(1.04); } }

.abre-menu { display: none; }
/* O menu móvel é uma SUPERFÍCIE ESCURA que não é uma .secao--tinta: pinta o
   mesmo --tinta de fundo, então precisa dos mesmos acertos de contraste. Os
   dois valores abaixo são os que a .secao--tinta também declara — a cor do que
   está atrás (para abrir folga no halo de seleção) e a cor desse halo. */
.menu-movel { position: fixed; inset: 0; z-index: 45; background: var(--tinta); color: var(--bruma);
              --sob: var(--tinta); --anel-selecao: var(--rose);
              display: flex; flex-direction: column; gap: var(--esp-2); padding: var(--esp-6) var(--goteira);
              /* Tela cheia com conteúdo variável: sem rolagem própria, um menu
                 com muitos itens deixaria o contato inalcançável em tela baixa.
                 Sem `overscroll-behavior: contain` de propósito — quem abre o
                 menu já tranca a rolagem do body (ver alternarMenu no site.js),
                 então não há para onde a rolagem escapar; e a propriedade num
                 elemento fixo do tamanho da viewport trava a captura de tela do
                 próprio Chrome, o que impede conferir o menu com os olhos. */
              overflow-y: auto;
              transform: translateY(-100%); visibility: hidden;
              /* A visibilidade troca de uma vez, nunca gradualmente — o que muda
                 é QUANDO. Ao fechar, ela espera a saída terminar (atraso de
                 --dur-3), senão o menu sumiria antes de deslizar para fora. Ao
                 abrir, troca na hora (regra abaixo, sem atraso).
                 Isto não é detalhe de animação: enquanto o valor calculado for
                 `hidden`, o teclado não consegue entrar no menu, porque .focus()
                 é ignorado em elemento invisível. Transição em `visibility` sem
                 atraso separado segura o valor em `hidden` no primeiro quadro e
                 o foco se perde. */
              transition: transform var(--dur-3) var(--saida), visibility 0s linear var(--dur-3); }
.menu-movel[data-aberto='true'] { transform: none; visibility: visible;
              transition: transform var(--dur-3) var(--saida), visibility 0s; }
.menu-movel__topo { justify-content: space-between; }
.menu-movel__link { padding: var(--esp-4) 0; border-bottom: 1px solid var(--borda-inversa);
                    font-family: var(--fonte-titulo); font-size: var(--t-h4); }
/* CONTATO DENTRO DO MENU ----------------------------------------------------
   O menu ocupa a tela inteira e sobra espaço embaixo dos links. É onde entra a
   ação: `margin-top:auto` cola o bloco no rodapé do menu, que é onde o polegar
   alcança sem reposicionar a mão. O botão é um só, e qual botão é o dado que
   decide — ver o comentário em src/modelos/layout.php.
   O max-width existe para o tablet: em 768 px o menu tem a largura toda, e um
   botão do comprimento inteiro parece formulário, não ação. */
.menu-movel__contato { margin-top: auto; padding-top: var(--esp-6);
                       display: flex; flex-direction: column; gap: var(--esp-3);
                       max-width: var(--largura-coluna); }

/* RODAPÉ ------------------------------------------------------------------
   As três colunas e a linha de direitos. Estavam escritas como style="" dentro
   do layout.php; aqui obedecem aos tokens como o resto do sistema. */
.rodape__grade { padding-bottom: var(--esp-6); border-bottom: 1px solid var(--borda-inversa); }
.rodape__sobre { margin-top: var(--esp-4); max-width: var(--largura-coluna); }
.rodape__pe    { padding-top: var(--esp-5); }
/* A marca sobre fundo tinta: o bastidor vira rose e a assinatura clareia. Era
   um style="color:…" em cada um dos dois. */
/* A VERSÃO PARA FUNDO ESCURO. O marrom do logotipo tem 2,3:1 sobre a tinta do
   rodapé — ele não some, mas afunda, e uma marca que afunda no próprio rodapé
   se lê como imagem que não carregou. A rosa é a mesma que o bastidor já usava
   ali, e é o que qualquer manual de marca chama de versão invertida: um desenho
   só, duas tintas, escolhidas pelo fundo. */
.secao--tinta .marca__logo { color: var(--rose); }
.secao--tinta .marca__bastidor { color: var(--rose); }
.secao--tinta .marca__nome span { color: rgb(var(--bruma-rgb) / .6); }

/* MODAL e GAVETA ----------------------------------------------------------- */
.fundo-modal { position: fixed; inset: 0; z-index: 50; 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); }
.fundo-modal[data-aberto='true'] { opacity: 1; visibility: visible; }
/* Centrado nos dois eixos: inset 0 + margin auto + altura pelo conteúdo.
   O max-height segura o modal dentro da tela e a rolagem fica interna. */
.modal { position: fixed; inset: 0; z-index: 51; margin: auto;
         width: min(46rem, calc(100% - var(--esp-5) * 2));
         height: fit-content; max-height: min(86dvh, 54rem);
         overflow-y: auto; overscroll-behavior: contain;
         background: var(--superficie); border-radius: var(--rad-3);
         box-shadow: var(--elev-3); opacity: 0; transform: translateY(var(--esp-5)) scale(.98);
         transition: opacity var(--dur-2) var(--suave), transform var(--dur-3) var(--saida); }
.modal[data-aberto='true'] { opacity: 1; transform: none; }
/* Cabeça e pé grudados precisam vencer qualquer coisa posicionada dentro do
   corpo — a etiqueta da prévia de medida, por exemplo. */
.modal__cabeca { position: sticky; top: 0; z-index: 3; display: flex; align-items: flex-start; justify-content: space-between;
                 gap: var(--esp-4); padding: var(--esp-5); background: var(--superficie); border-bottom: 1px solid var(--borda); }
.modal__corpo { position: relative; z-index: 1; padding: var(--esp-5); display: flex; flex-direction: column; gap: var(--esp-5); }
.modal__pe { position: sticky; bottom: 0; z-index: 3; padding: var(--esp-4) var(--esp-5); background: var(--superficie);
             border-top: 1px solid var(--borda); display: flex; flex-direction: column; gap: var(--esp-3); }

.gaveta { position: fixed; inset: 0 0 0 auto; z-index: 51; width: min(26rem, 100%); display: flex; flex-direction: column;
          background: var(--superficie); box-shadow: var(--elev-3); transform: translateX(101%);
          transition: transform var(--dur-3) var(--saida); }
.gaveta[data-aberto='true'] { transform: none; }
.gaveta__cabeca { display: flex; align-items: center; justify-content: space-between; gap: var(--esp-4);
                  padding: var(--esp-5); border-bottom: 1px solid var(--borda); }
.gaveta__lista { flex: 1; overflow-y: auto; padding: var(--esp-4) var(--esp-5); display: flex; flex-direction: column; gap: var(--esp-3); }
.gaveta__pe { padding: var(--esp-5); border-top: 1px solid var(--borda); display: flex; flex-direction: column; gap: var(--esp-3); }
.item-orcamento { display: grid; grid-template-columns: 3.5rem 1fr auto; gap: var(--esp-3); align-items: center;
                  padding-bottom: var(--esp-3); border-bottom: 1px dashed var(--borda); }
.item-orcamento img { width: 3.5rem; height: 3.5rem; object-fit: cover; border-radius: var(--rad-1); }
.contagem { display: inline-flex; align-items: center; border: 1px solid var(--borda); border-radius: var(--rad-1); }
.contagem button { width: 1.9rem; height: 1.9rem; display: grid; place-items: center; background: none; border: 0; cursor: pointer; color: var(--texto-brando); }
.contagem button:hover { color: var(--carmim); }
.contagem button svg { width: .8rem; height: .8rem; }
.contagem output { min-width: 1.6rem; text-align: center; font-family: var(--fonte-dado); font-size: var(--t-auxiliar); }
.vazio { display: flex; flex-direction: column; align-items: center; gap: var(--esp-3); padding: var(--esp-8) var(--esp-4); text-align: center; color: var(--texto-brando); }
/* FILHO DIRETO, não descendente. O estado vazio quase sempre termina com um
   botão de saída, e o botão traz o próprio ícone dentro do selo. Com `.vazio svg`
   esse ícone também virava ilustração de 2,5rem: uma seta gigante e desbotada
   estourando para fora do botão. Só o ícone que é filho direto do bloco é a
   ilustração do estado. */
.vazio > svg { width: 2.5rem; height: 2.5rem; color: var(--borda-forte); }

.tabela-spec { width: 100%; border-collapse: collapse; font-size: var(--t-corpo-sm); }
.tabela-spec th, .tabela-spec td { padding: var(--esp-3); text-align: left; border-bottom: 1px solid var(--borda); vertical-align: top; }
.tabela-spec th { font-size: var(--t-rotulo); letter-spacing: var(--tr-rotulo); text-transform: uppercase;
                  font-variation-settings: 'wdth' 88; color: var(--texto-brando); font-weight: var(--peso-forte); white-space: nowrap; }
.tabela-spec td:not(:first-child) { font-family: var(--fonte-dado); font-size: var(--t-auxiliar); }
.tabela-spec tbody tr:hover { background: rgb(var(--tinta-rgb) / .03); }
.rolagem-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.secao--tinta .tabela-spec th, .secao--tinta .tabela-spec td { border-color: var(--borda-inversa); }
.aviso { display: flex; gap: var(--esp-3); padding: var(--esp-4); border-radius: var(--rad-2);
         background: rgb(var(--atencao-rgb) / .1); border-left: 3px solid var(--atencao); font-size: var(--t-corpo-sm); }
.aviso svg { width: 1.15rem; height: 1.15rem; flex: none; color: var(--atencao); margin-top: .15rem; }

/* ── ⚠️ AS TRÊS GRAVIDADES DO AVISO MORAM AQUI, E NÃO NA TELA QUE AS USA ──
   O aviso nasceu âmbar, que é o "preste atenção" do sistema. Só que o painel
   usa a mesma caixa para dizer três coisas diferentes — deu certo, precisa de
   atenção, não aconteceu —, e até 22/8/2026 as cores de "deu certo" e de "não
   aconteceu" estavam escritas dentro do bloco da LISTA DE PEÇAS, presas ao
   nome `.painel-pecas__aviso`.

   A fase N3 pediu a mesma caixa numa segunda tela, e a escolha era copiar as
   quatro regras ou subi-las para o componente. Cor de estado é do componente:
   quem escrever a terceira tela não deveria precisar saber que a segunda
   existiu. `data-gravidade` e não uma classe modificadora porque o valor vem do
   servidor como DADO — é o mesmo `gravidade` que as funções de aviso do painel
   devolvem —, e atributo é onde dado mora.

   Sem valor, ou com valor `atencao`, o aviso continua âmbar: é o padrão de
   cima, e não há regra nenhuma a escrever para ele. */
.aviso[data-gravidade='ok'] {
  background: rgb(var(--sucesso-rgb) / .1); border-left-color: var(--sucesso);
}
.aviso[data-gravidade='ok'] svg { color: var(--sucesso); }
.aviso[data-gravidade='erro'] {
  background: rgb(var(--erro-rgb) / .1); border-left-color: var(--erro);
}
.aviso[data-gravidade='erro'] svg { color: var(--erro); }
.secao--tinta .aviso { background: rgb(var(--rose-rgb) / .12); border-left-color: var(--rose); }
.secao--tinta .aviso svg { color: var(--rose); }

.aviso-vivo { position: fixed; left: 50%; bottom: var(--esp-6); z-index: 60; transform: translate(-50%, 1rem);
              display: flex; align-items: center; gap: var(--esp-3); padding: var(--esp-3) var(--esp-5);
              background: var(--tinta); color: var(--bruma); border-radius: var(--rad-total); box-shadow: var(--elev-3);
              font-size: var(--t-corpo-sm); opacity: 0; pointer-events: none;
              transition: opacity var(--dur-2) var(--suave), transform var(--dur-2) var(--saida); }
.aviso-vivo[data-aberto='true'] { opacity: 1; transform: translate(-50%, 0); }
.aviso-vivo svg { width: 1rem; height: 1rem; color: var(--rose); }

/* ── O AVISO DE COOKIES — fase 19A, 14/9/2026 ──────────────────────────────
   Só existe na página com o código do Google Tag Manager preenchido no painel,
   e só aparece na PRIMEIRA ROLAGEM da primeira visita — ou ao carregar, se a
   página não rola, ou quando a pessoa o reabre pelo rodapé ou pela
   privacidade. Não é ao abrir a página porque não há canto seguro: aberto de
   saída, ele cobria o botão principal da home; o porquê está no
   consentimento.js. A marcação está no layout.php; o desenho, no ds1.html.

   NENHUM TOKEN NOVO. O cartão é `.secao--tinta` na própria marcação, e com isso
   herda o foco rose, o botão secundário claro, a trama e a costura rose — o que
   está escrito aqui é só o que é dele: onde fica, como entra e a assinatura.

   ⚠️ A CAMADA: 35. Medido nas folhas em 14/9/2026, as camadas que ele precisa
   respeitar são estas, e ele fica ENTRE a barra de filtros e o cabeçalho:
     30  a barra de filtros grudada da listagem       ← o cartão passa por cima
     40  o cabeçalho (e as sugestões da busca dentro dele)
     45  o menu do celular                             ┐
     50  o fundo escurecido  ·  51 gaveta e janela     │ tudo o que COBRE a
     55  o fundo dos filtros no celular                │ página cobre o cartão
     60  a gaveta dos filtros, a foto em tela cheia    │
     60  o aviso vivo                                  ┘
   O aviso vivo também mora embaixo, e em 768 e 375 px ele cairia em cima do
   cartão — por isso ele sobe enquanto o cartão está aberto, na regra do fim. */
.consentimento {
  position: fixed; left: var(--goteira); bottom: var(--goteira); z-index: 35;
  width: min(var(--largura-coluna), calc(100% - var(--goteira) * 2));
  padding: var(--esp-6) var(--esp-5) var(--esp-5);
  /* O contorno claro existe por causa da home: o cartão é tinta, a hero é uma
     foto escura, e a sombra — que também é tinta — some em cima dela. Visto na
     tela em 14/9/2026, a 500 px: sem o contorno a borda do cartão se perdia na
     cama da foto. É a mesma borda inversa das superfícies escuras do sistema. */
  border: 1px solid var(--borda-inversa);
  border-radius: var(--rad-2); box-shadow: var(--elev-3);
  opacity: 0; transform: translateY(var(--esp-5));
  transition: opacity var(--dur-2) var(--entrada), transform var(--dur-2) var(--entrada);
}
.consentimento[data-aberto='true'] {
  opacity: 1; transform: none;
  transition: opacity var(--dur-3) var(--saida), transform var(--dur-3) var(--saida);
}

/* A ASSINATURA: a costura na borda de cima, com o nó na ponta. É a mesma linha
   que divide as seções do site, e é o que faz o aviso parecer peça desta fábrica
   e não o banner que todo site tem. Ela se borda UMA vez, quando o cartão sobe
   — e é o cartão que manda, e não o `.visivel` que o site.js acende ao rolar:
   o cartão nasce escondido, e o observador de rolagem não sabe quando ele
   aparece. As duas regras abaixo têm a especificidade da regra geral da
   costura e vêm depois dela nesta folha, que é o que as faz valer. */
.consentimento__costura { position: absolute; top: 0; left: var(--esp-5); right: var(--esp-5); overflow: visible; }
/* ⚠️ O NÓ INTEIRO NA PONTA. A costura geral corta o que passa da própria caixa —
   pelo `overflow` e pelo recorte do trilho —, e quando ela termina o nó para
   EXATAMENTE na borda direita, com a metade de fora cortada. Numa costura da
   largura da página isso some; num cartão de 26 rem, visto na tela em 14/9/2026,
   o nó saía como meia bolinha e parecia defeito. O recorte daqui ganha uma folga
   de `--esp-2` em cima, embaixo e à direita — o raio do nó mais o anel dele —, e
   o avanço da esquerda para a direita continua igual. */
.consentimento__costura .costura__trilho {
  clip-path: inset(calc(var(--esp-2) * -1) calc((1 - var(--avanco)) * 100% - var(--esp-2)) calc(var(--esp-2) * -1) 0);
}
.consentimento .costura { --avanco: 0; transition: --avanco var(--dur-2) var(--entrada); }
.consentimento[data-aberto='true'] .costura { --avanco: 1; transition: --avanco var(--dur-4) var(--saida) var(--atraso-2); }

/* Acima da trama, que é absoluta e seria pintada por cima do texto. */
.consentimento__conteudo { position: relative; display: flex; flex-direction: column; gap: var(--esp-2); }
.consentimento__titulo {
  font-family: var(--fonte-titulo); font-size: var(--t-h5); font-weight: var(--peso-normal);
  line-height: var(--lh-media); color: var(--algodao);
  font-variation-settings: 'opsz' 48, 'SOFT' 40, 'WONK' 0;
}
.consentimento__texto { font-size: var(--t-corpo-sm); line-height: var(--lh-corpo); color: rgb(var(--bruma-rgb) / .7); }
/* Sublinhado obrigatório: fica no meio de texto corrido — a régua 1.4.1.
   ⚠️ DESDE A FASE 19C É UM <button>, E NÃO UM <a>: "Gerenciar preferências"
   abre a janela de preferências em vez de levar a outra página. O botão veste
   a roupa do link — sem recuo, sem fundo, sem borda — e continua sublinhado,
   porque no meio da frase é o sublinhado que diz "isto se aperta". Tamanho e
   entrelinha vêm do parágrafo, pelo `font: inherit` do base.css. */
.consentimento__link { padding: 0; background: none; border: 0; cursor: pointer;
                       color: var(--rose); text-decoration: underline; text-underline-offset: var(--desloca-sublinhado); white-space: nowrap; }
.consentimento__link:hover { color: var(--algodao); }
/* OS DOIS BOTÕES TÊM A MESMA LARGURA E A MESMA ALTURA. "Aceitar" grande e
   "Recusar" miúdo é padrão escuro; a diferença entre eles fica só na cor. */
.consentimento__acoes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--esp-3); margin-top: var(--esp-3); }

/* O aviso vivo sobe acima do cartão aberto. A altura é medida pelo script e
   escrita em `--altura-consentimento`: o texto vem do banco e quebra em mais ou
   menos linhas conforme a largura da tela. */
[data-consentimento='aberto'] .aviso-vivo { bottom: calc(var(--goteira) + var(--altura-consentimento, 0px) + var(--esp-3)); }

/* AS DUAS PORTAS DE VOLTAR AO AVISO. O link do rodapé é um <button>, porque
   abre o aviso em vez de levar a outra página, vestido com a mesma letra do link
   da privacidade ao lado. O recuo vertical leva o alvo do toque a 24 px, o piso
   da régua 2.5.8, sem mexer no tamanho da letra. */
.rodape__legal { gap: var(--esp-5); }
.rodape__cookies { padding: var(--esp-1) 0; background: none; border: 0; cursor: pointer; }

/* Com movimento reduzido: aparece e some sem deslocamento, e a costura nasce
   inteira. A regra geral do base.css já encurta a duração, mas não o ATRASO —
   sem esta linha a costura esperaria os 160 ms do `--atraso-2` para saltar. */
@media (prefers-reduced-motion: reduce) {
  .consentimento, .consentimento[data-aberto='true'] { transform: none; }
  .consentimento .costura, .consentimento[data-aberto='true'] .costura { --avanco: 1; transition: none; }
}

/* ── A JANELA DE PREFERÊNCIAS — fase 19C, 14/9/2026 ────────────────────────
   Abre no "Gerenciar preferências" do cartão, no "Cookies" do rodapé e no
   "Mudar minha escolha" da privacidade. É o `.modal` do sistema inteiro — véu,
   abertura, Esc, clique fora, foco preso e devolvido vêm do site.js —, e o que
   esta folha acrescenta é a medida, a lista das permissões e a costura. A
   marcação está no layout.php; o desenho e o porquê, no ds1.html.

   A LARGURA É A DE LEITURA, e não as 46 rem do modal: o miolo desta janela são
   três parágrafos curtos, e 46 rem dariam linhas longas demais no computador.
   `--largura-texto` é a medida de leitura do sistema. */
.modal--preferencias { width: min(var(--largura-texto), calc(100% - var(--esp-5) * 2)); }

/* A CABEÇA É TINTA, E O CORPO CONTINUA CLARO — decisão do Felipe, 14/9/2026.
   A janela nasceu toda algodão, com a costura carmim sob o título, e a leitura
   da verificação foi "correta, perto do apagado": quem apertava "Gerenciar
   preferências" num cartão tinta, com trama e costura rose, caía numa peça sem
   parentesco nenhum com ele. Agora a cabeça É o cartão — a mesma superfície, a
   mesma trama, o título claro e a costura rose com o nó —, e o corpo, onde se
   lê e se escolhe, fica claro. Ele recusou a janela inteira em tinta: são três
   parágrafos e dois interruptores, e é no claro que o carmim do "Aceitar
   todos" e do interruptor ligado funciona. A ousadia fica num lugar só.

   NENHUMA REGRA DE CONTRASTE FOI ESCRITA DE NOVO. A cabeça leva `.secao--tinta`
   na marcação, como o cartão, e com isso vêm o × claro com o hover invertido,
   o contorno de foco rose do base.css, a trama clara e a costura rose. Duas
   coisas são reditas aqui, e só duas:
     · o FUNDO, por ordem na folha: `.modal__cabeca` pinta `--superficie` mais
       abaixo que `.secao--tinta`, com a mesma força, e ganharia;
     · a COR DO TÍTULO. `.secao--tinta` só leva `.h1`, `.h2` e `.h3` ao
       algodão, e este título é `.h4`: sem a linha abaixo ele saía bruma,
       medido na tela em 14/9/2026. O cartão resolve igual, no próprio
       `.consentimento__titulo`, e estender a regra geral ao `.h4` mudaria
       títulos das outras seções tinta do site.

   O raio de cima não pediu nada: o `.modal` rola por dentro, e `overflow`
   diferente de `visible` recorta os filhos no arredondado da própria caixa. */
.modal--preferencias .modal__cabeca { align-items: center; border-bottom: 0;
                                       background: var(--tinta); padding-bottom: var(--esp-6); }
/* O título em algodão, como o do cartão — o porquê de a cor estar aqui está
   logo acima. E acima da trama, que é absoluta e seria pintada por cima dele: o
   mesmo acerto do `.consentimento__conteudo`. O × não precisa, `.btn` já é
   relativo. */
.modal--preferencias .modal__cabeca .h4 { position: relative; color: var(--algodao); }

/* A ASSINATURA, UMA SÓ: a costura rente à borda de baixo da cabeça, do lado
   escuro. É o gesto das seções do site — título, costura, conteúdo — e a mesma
   linha do cartão que abriu a janela, na MESMA geometria, espelhada: lá o fio
   corre no meio dos `--esp-6` de recuo de cima; aqui, no meio dos `--esp-6` de
   recuo de baixo. É o pesponto da barra de um tecido. Ela se borda uma vez,
   quando a janela abre. Nenhuma outra linha daqui é costura: as divisórias
   entre as permissões são o fio liso do sistema, e a divisa com o corpo é a
   própria troca de tecido, sem fio nenhum.

   ⚠️ NÃO DEVOLVER O FIO PARA CIMA DA BORDA. Até esta rodada ele corria
   exatamente na divisa, meio para cada lado, o que funcionava em carmim sobre
   o claro. Com a cabeça tinta ele é rose, e rose sobre algodão não aparece:
   testado na tela a 375 px em 14/9/2026, a metade de baixo dos pontos se
   dissolvia no corpo e o nó saía meia bolinha rosada. O recuo de baixo maior é
   o preço de o fio caber inteiro no escuro, medido em 14/9/2026: a janela foi
   de 640,7 para 656,7 px de altura a 375 px, onde o padroes.css encolhe o
   recuo da cabeça, e de 559,3 para 567,3 px a 768 e a 1440. Nas três, sem
   rolagem por dentro.

   Ela mora DENTRO da cabeça, que é grudenta no topo: rolando a janela no
   celular, a costura vai junto com o título. */
.preferencias__costura { position: absolute; left: var(--esp-5); right: var(--esp-5); bottom: 0; overflow: visible; }
/* O recorte com folga do cartão, para o nó não sair cortado ao meio na ponta
   direita — o porquê está em `.consentimento__costura .costura__trilho`. */
.preferencias__costura .costura__trilho {
  clip-path: inset(calc(var(--esp-2) * -1) calc((1 - var(--avanco)) * 100% - var(--esp-2)) calc(var(--esp-2) * -1) 0);
}
.modal--preferencias .costura { --avanco: 0; transition: --avanco var(--dur-2) var(--entrada); }
.modal--preferencias[data-aberto='true'] .costura { --avanco: 1; transition: --avanco var(--dur-4) var(--saida) var(--atraso-2); }

/* AS TRÊS PERMISSÕES. O nome à esquerda e, na mesma linha, o interruptor — ou
   o "Sempre ligados" dos necessários, que não se desligam. O texto desce por
   baixo dos dois, na largura inteira, para a coluna do nome não virar tira. */
.preferencias { display: flex; flex-direction: column; }
.preferencia {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
  gap: var(--esp-2) var(--esp-4); padding-block: var(--esp-4);
  border-top: 1px solid var(--borda);
}
.preferencia:first-child { padding-top: 0; border-top: 0; }
.preferencia:last-child { padding-bottom: 0; }
.preferencia__nome label { cursor: pointer; }
.preferencia__estado { font-size: var(--t-corpo-sm); line-height: var(--lh-media); color: var(--texto-brando); white-space: nowrap; }
.preferencia__texto { grid-column: 1 / -1; font-size: var(--t-corpo-sm); line-height: var(--lh-corpo); color: var(--texto-brando); }
/* Link no fim de um parágrafo: sublinhado, pela régua 1.4.1, como o do cartão. */
.preferencias__link { color: var(--carmim); text-decoration: underline; text-underline-offset: var(--desloca-sublinhado); }
.preferencias__link:hover { color: var(--carmim-forte); }
/* Os dois botões com a mesma largura e a mesma altura, pela razão do cartão:
   entre gravar o que se escolheu e aceitar tudo, a diferença fica só na cor. */
.preferencias__acoes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--esp-3); }
/* O RECUO CAI PARA `--esp-3`, nos dois lados — a regra de simetria do botão sem
   selo lê esta variável. Visto na tela a 375 px em 14/9/2026: com os 24 px do
   padrão, cada botão tinha 133,5 px e "Salvar escolhas" e "Aceitar todos"
   quebravam em duas linhas. Não muda nada no computador, onde o botão sobra. */
.preferencias__acoes .btn { --btn-recuo: var(--esp-3); }

/* Abaixo de 640 px o padroes.css encolhe o recuo da cabeça para `--esp-4`, e a
   costura acompanha, para começar e terminar alinhada ao título. */
@media (max-width: 640px) {
  .preferencias__costura { left: var(--esp-4); right: var(--esp-4); }
}

@media (prefers-reduced-motion: reduce) {
  .modal--preferencias .costura, .modal--preferencias[data-aberto='true'] .costura { --avanco: 1; transition: none; }
}

/* ── O INTERRUPTOR — fase 19C, 14/9/2026 ───────────────────────────────────
   Liga ou desliga uma coisa só. Nasceu para a janela de preferências, e é o
   primeiro do site: o `.opcao` é caixa de marcar de formulário, e o painel
   resolve o dele com duas opções escritas ("Sim" e "Não"), que ali cabem
   porque cada campo tem a linha inteira.

   É o `<input type="checkbox" role="switch">` NATIVO, vestido: o Espaço, o
   rótulo clicável e o "ligado/desligado" do leitor de tela vêm do navegador, e
   nenhuma linha de JavaScript é dele. O nome vem do `<label for>`, e a
   explicação, do `aria-describedby`.

   ⚠️ O ESTADO NÃO DEPENDE SÓ DA COR. Desligado, a bolinha fica à esquerda,
   castanha, num trilho só contornado; ligado, vai para a direita, clara, sobre
   o trilho carmim cheio. Posição e preenchimento mudam juntos.

   Trilho de `--alt-controle` por `--esp-5`: largo como um alvo de dedo, e o
   rótulo ao lado também liga. O foco é o contorno carmim do base.css, que
   acompanha o arredondado. */
.interruptor {
  appearance: none; -webkit-appearance: none; flex: none; position: relative; margin: 0; cursor: pointer;
  width: var(--alt-controle); height: var(--esp-5);
  border: var(--fio-espessura) solid var(--texto-brando); border-radius: var(--rad-total);
  background: var(--superficie);
  transition: background var(--dur-1) var(--suave), border-color var(--dur-1) var(--suave);
}
.interruptor::before {
  content: ''; position: absolute; top: 50%; left: var(--esp-1);
  width: var(--esp-4); height: var(--esp-4); margin-top: calc(var(--esp-4) / -2);
  border-radius: var(--rad-total); background: var(--texto-brando);
  transition: transform var(--dur-2) var(--saida), background var(--dur-1) var(--suave);
}
.interruptor:hover { border-color: var(--carmim); }
.interruptor:checked { background: var(--carmim); border-color: var(--carmim); }
/* O caminho da bolinha é o trilho por dentro menos ela e as duas folgas. */
.interruptor:checked::before {
  background: var(--algodao);
  transform: translateX(calc(var(--alt-controle) - var(--esp-4) - var(--esp-1) * 2 - var(--fio-espessura) * 2));
}
