/* ============================================================
   LETHAL · Componentes
   Botao, cartao de peca, seletor de tamanho, e os tres estados que
   toda tela precisa ter (carregando, vazio, erro).

   A regra que atravessa este arquivo inteiro: RAIO ZERO, SOMBRA
   NENHUMA, TUDO ALINHADO A ESQUERDA. Sao as tres regras inviolaveis
   do design system, e sao elas que separam este site de um template.
   ============================================================ */

/* ------------------------------------------------------------
   FAMILIA DE BOTOES (FUNDACAO.md 10)
   primario = preenchido · secundario = contorno · terciario = so texto

   Num site preto, o botao primario e CLARO: ele e o unico pedaco de
   papel na tela, e por isso e o unico lugar para onde o olho vai. E a
   mesma logica do sistema no claro (botao escuro sobre fundo claro),
   invertida.

   Regra que o PDV pagou caro: botao NUNCA usa a cor de CAMPO. Quando
   usou, o botao lia como campo e o campo lia como botao, e a tela
   inteira ficou ambigua. Aqui a cor de campo e --graph, e nenhum
   botao a usa.

   O rotulo e caixa-alta com tracking e ALINHADO A ESQUERDA quando o
   botao e largo. Centralizar rotulo em botao de bloco e a regra que
   o design system proibe por escrito.
   ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 48px; padding: 0 var(--s5);
  border: 0; border-radius: var(--raio);
  font-family: var(--fonte-display);
  font-size: var(--fs-micro); font-weight: var(--peso-display);
  letter-spacing: var(--tk-botao); text-transform: uppercase;
  cursor: pointer; text-align: left;
  transition: background var(--transicao), color var(--transicao),
              border-color var(--transicao), opacity var(--transicao);
}
.btn--primario   { background: var(--paper); color: var(--ink); }
.btn--secundario { background: transparent; color: var(--paper); border: 1px solid var(--fio-vivo); }
.btn--terciario  { background: transparent; color: var(--paper-apoio); padding-inline: 0; }

/* O HOVER E O TOQUE DESTES TRES BOTOES MORAM NO `movimento.css`, que e o dono
   unico do `:hover` do site. Aqui ficam a forma e os estados que a forma
   carrega (travado, bloco). La fica como eles RESPONDEM: o secundario e o
   primario preenchem com uma varredura de claro, o terciario so acende.
   Movimento junto e o que impede seis vocabularios de hover em seis arquivos. */

/* Travado e travado: nao promete o que nao da.
   ⚠️ ELE JA FOI `background: var(--graph)`, E ISSO ERA UM DEFEITO ESPERANDO
   O PRIMEIRO FORMULARIO. `--graph` e a superficie de CAMPO, e o FUNDACAO.md
   10 proibe com todas as letras: "botao nunca usa a mesma cor de fundo que
   os campos". Enquanto o site nao pedia nenhum dado, o defeito nao tinha
   como aparecer: nao havia campo na tela para o botao travado imitar. No
   checkout eles ficam a 24px um do outro, e um retangulo cinza embaixo de
   oito retangulos cinzas nao se le como botao desligado, se le como mais um
   campo. E o mesmo estrago que o PDV pagou, chegando pelo outro lado.

   O travado agora nao tem superficie nenhuma: e contorno TRACEJADO, que ja
   e a palavra deste sistema para "existe e nao esta disponivel" (ver o chip
   de tamanho esgotado, mais abaixo). Uma palavra so para a mesma ideia. */
.btn:disabled,
.btn[aria-disabled="true"] {
  background: transparent; color: var(--paper-miudo);
  border: 1px dashed var(--fio); cursor: not-allowed; transform: none;
}

/* Ocupado NAO E travado, e por isso ele nao vira tracejado: o botao continua
   sendo o botao que a pessoa acabou de apertar, so que trabalhando. Ele
   guarda a superficie clara e perde o cursor de mao. Quem troca o rotulo
   para "criando seu pedido..." e o JavaScript, com a frase do dicionario.

   ⚠️⚠️ ESTE COMENTARIO DESCREVIA UMA INTENCAO QUE O CODIGO NUNCA CUMPRIU, E
   ISSO FICOU ASSIM ATE 8/ago. Abaixo dele existia UMA linha, `cursor:
   progress`, e mais nada. Como o JavaScript marca `aria-busy` E `disabled` no
   mesmo instante (sao 19 lugares, todos iguais), quem pintava o botao ocupado
   era a regra de cima: fundo transparente, letra em `--paper-miudo` e CONTORNO
   TRACEJADO. Medido no botao de pedir o codigo, depois da transicao fechar:
   `background: rgba(0,0,0,0)`, `border: dashed 1px rgba(242,241,237,.16)`,
   `animation: none`.

   O estrago nao e de acabamento, e de significado: o tracejado e a palavra
   deste sistema para "existe e nao esta disponivel" (o chip de tamanho
   esgotado usa a mesma), entao o botao que estava TRABALHANDO vestia a roupa
   de "nao da para usar". Sao mensagens opostas ditas com o mesmo desenho, e a
   unica diferenca entre elas era o rotulo. Sem movimento nenhum, a leitura que
   sobra e a mais cara que uma loja pode dar: travou.

   A licao, e ela nao e sobre botao: DOIS ATRIBUTOS MARCADOS JUNTOS PRECISAM
   DE UMA REGRA QUE DECIDA QUEM PINTA. `disabled` diz o que o navegador faz
   (nao aceita clique, e disso a espera precisa mesmo); `aria-busy` diz o que a
   pessoa ve. Quando os dois convivem, o que a pessoa ve e do segundo, e isso
   tem que estar escrito em algum lugar, senao vale a ordem do arquivo.

   Por isso as tres regras abaixo devolvem, uma por variante, exatamente a
   superficie que a variante tinha. Elas sao (0,3,0) contra os (0,2,0) do
   travado, entao ganham por especificidade e nao por posicao: mover este
   bloco no arquivo nao muda mais nada. O MOVIMENTO da espera nao esta aqui,
   esta no `movimento.css` 6, que e o dono unico do movimento do site. */
.btn[aria-busy="true"] { cursor: progress; }
.btn--primario[aria-busy="true"] {
  background: var(--paper); color: var(--ink); border: 0;
}
.btn--secundario[aria-busy="true"] {
  background: transparent; color: var(--paper); border: 1px solid var(--fio-vivo);
}
/* O terciario nunca teve superficie, entao nao ha o que devolver: o que se
   desfaz nele e so a letra apagada do travado. A varredura dele e outra, e o
   motivo esta no `movimento.css` 6. */
.btn--terciario[aria-busy="true"] {
  background: transparent; color: var(--paper-apoio); border: 0;
}
/* A seta do botao de bloco SAI enquanto ele trabalha. Ela quer dizer "isto te
   leva adiante", e no meio da espera ainda nao leva: mante-la seria a mesma
   promessa fora de hora que o tracejado era, pelo outro lado. */
.btn--bloco[aria-busy="true"]::after { display: none; }

/* Botao de bloco: rotulo a esquerda e a seta encostada na direita. A seta e
   desenhada com borda, e nao escrita com o caractere: content vazio nao e
   lido por leitor de tela, e "→" seria. */
.btn--bloco { width: 100%; justify-content: flex-start; }
.btn--bloco::after {
  content: ""; margin-left: auto; width: 8px; height: 8px;
  border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor;
  transform: rotate(45deg);
}
.btn--bloco:disabled::after { display: none; }

/* ------------------------------------------------------------
   CARTAO DE PECA
   O desenho do design system, 02 / System: numero e categoria acima,
   quadro 4:5, nome em caixa-alta, e preco embaixo de uma regua fina.
   SEM selo flutuante sobre a foto e SEM cartao com fundo: o cartao
   com fundo e sombra e o que o documento chama de "template de
   e-commerce", e e o oposto do que ele pede.
   ------------------------------------------------------------ */
.grade {
  display: grid; gap: var(--s6) var(--s5);
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  counter-reset: peca;
}
/* Tres colunas no desktop, que e a coluna do documento. O auto-fill acima ja
   resolveria, mas com 5 pecas ele deixaria a ultima linha torta em telas
   largas: fixar em 3 mantem o ritmo. */
@media (min-width: 1000px) { .grade { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.card { display: block; counter-increment: peca; }
.card__meta {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); margin-bottom: var(--s3);
}
/* O numero da peca vem do contador do CSS, e nao do JavaScript: ele e
   posicao na grade, e posicao e coisa de layout. Fica em aria-hidden no
   HTML, porque "01" antes do nome nao ajuda quem ouve a pagina. */
.card__num::before {
  content: counter(peca, decimal-leading-zero);
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-micro); letter-spacing: .12em;
  color: var(--paper-miudo);
}
.card__tipo { font-size: var(--fs-micro); letter-spacing: var(--tk-rotulo); text-transform: uppercase; color: var(--paper-miudo); }

.card__quadro {
  position: relative;
  aspect-ratio: 4 / 5;              /* o quadro e o mesmo para toda peca */
  background: var(--quadro);
  overflow: hidden;
}
.card__quadro img { width: 100%; height: 100%; object-fit: cover; }
/* A imagem cresce dentro deste quadro no hover, e um veu sobe por cima dela.
   Os dois moram no movimento.css. O `overflow: hidden` acima e o que faz a
   imagem crescer sem o quadro crescer junto, e ele e estrutura, nao efeito. */
/* Peca esgotada: a foto recua, e a palavra vai para a linha do preco. */
.card--esgotado .card__quadro img { opacity: .4; }

/* ⚠️ O `display: block` NAO E ENFEITE, e a falta dele foi um defeito de
   verdade: o nome da peca e um <span>, e MARGEM VERTICAL NAO SE APLICA A
   ELEMENTO INLINE. O `margin-top` abaixo estava escrito, o navegador o
   mostrava na aba de estilo, e mesmo assim o vao real entre a foto e o nome
   media 0,5px: o nome ficava colado na foto. O CSS estava certo; quem
   descartava era o tipo do elemento.
   A licao que fica: em elemento que nao e caixa, margem vertical some em
   silencio. Se um espaco declarado nao aparecer, olhe o `display` antes de
   aumentar o numero.

   Por que continua <span> e nao virou <h3>: o cartao inteiro e um <a>, e o
   nivel certo do titulo mudaria com a pagina (h3 na home, sob o h2 da secao;
   h2 na lista, sob o h1). Um mesmo componente com nivel variavel e como se
   quebra a hierarquia de cabecalhos de um site. O nome ja e lido por quem
   navega por links, que e como esta grade se percorre. */
.card__nome {
  display: block;
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-h3); letter-spacing: var(--tk-nome);
  text-transform: uppercase; line-height: 1.15;
  /* A foto e o maior elemento do cartao, e o nome abre o bloco de texto:
     este e o maior vao de dentro do cartao, e e ele que separa a imagem da
     leitura. Fica um degrau abaixo do vao ENTRE cartoes (--s6, 48px), senao
     o cartao se desmancha em pecas soltas (proximidade: o que esta junto se
     le junto). */
  margin-top: var(--s5);
}
/* Nome e resumo sao UM par: o vao aqui e o menor do cartao, e e o que faz a
   frase pertencer ao nome em vez de flutuar entre ele e o preco. */
.card__resumo { font-size: var(--fs-sm); color: var(--paper-apoio); margin-top: var(--s2); }
.card__rodape {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s4); padding-top: var(--s3);
  border-top: 1px solid var(--fio);
}
.card__preco { font-size: var(--fs-body); font-weight: var(--peso-forte); letter-spacing: var(--tk-nome); }
/* A seta e o unico sinal de "isto e clicavel" no cartao, e ela some quando
   nao ha o que clicar de util. */
.card__seta { width: 8px; height: 8px; border-top: 1.5px solid var(--paper-apoio); border-right: 1.5px solid var(--paper-apoio); transform: rotate(45deg); }
/* hover: movimento.css */

/* "Esgotado" e informacao, nao promocao: ele vive na linha do preco, em
   caixa-alta, e nao num selo flutuante em cima da foto. O design system
   proibe badge; a informacao continua obrigatoria. */
.selo--esgotado {
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
}

/* ------------------------------------------------------------
   CAMPO
   ------------------------------------------------------------
   O PRIMEIRO FORMULARIO DO LETHAL. Ate 5/ago o site nunca tinha pedido um
   dado a ninguem, e a unica coisa que existia era este mesmo `.campo`
   servindo de moldura para o seletor de tamanho, morando no paginas.css.
   Ele subiu para ca quando o checkout virou o segundo consumidor, que e a
   regra escrita no topo daquele arquivo.

   A ANATOMIA, e a ordem dela e a ordem da leitura:

       rotulo   +   dica       ("Complemento" ... "opcional")
       ajuda                   ("e para onde vai a confirmacao do pedido")
       [ caixa                                                          ]
       erro                    ("confira o e-mail: falta o @")

   AS TRES DECISOES QUE ESTE COMPONENTE CARREGA:

   1. O ROTULO FICA VISIVEL SEMPRE. Placeholder nao e rotulo: ele some no
      primeiro caractere, e quem volta ao formulario tres campos depois
      perde a referencia do que estava escrevendo. Placeholder aqui so
      existe para mostrar FORMATO (00000-000), nunca para dizer o nome do
      campo.

   2. A AJUDA VEM ANTES DA CAIXA, e nao depois. Ela existe para ser lida
      ANTES de digitar ("so usamos para falar deste pedido"). Embaixo da
      caixa ela vira nota de rodape, que se le depois de ja ter feito.

   3. O ERRO NAO DEPENDE DE COR, e aqui isso nao e escolha: este site nao
      TEM cor de erro (docs/DESIGN.md 1 - sem cor terciaria). Entao o erro
      se diz com tres sinais somados: a frase, a borda subindo para o papel
      inteiro, e um fio de 2px dentro da caixa, do lado esquerdo. O fio e
      `box-shadow` sem desfoque de proposito: e a unica forma de engrossar
      um lado sem empurrar o conteudo (FUNDACAO.md 10: nada de layout
      pulando, anel via sombra nao empurra nada).
   ------------------------------------------------------------ */
/* ⚠️ A DICA FICA COLADA NO ROTULO, E NAO EMPURRADA PARA A BORDA.
   Ate 7/ago aqui havia `justify-content: space-between`, e ele jogava o
   "opcional" para a ponta direita da coluna. Medido na tela do cadastro:
   261px de vao entre "CPF" e "opcional", 207px entre "WhatsApp" e "opcional".
   A essa distancia a palavra para de qualificar o rotulo e vira cabecalho de
   uma segunda coluna — o olho le "CPF" e, muito depois, "opcional", sem ligar
   os dois. Colada, ela e o que sempre foi: um adjetivo do rotulo ao lado dele.

   O `flex-wrap` e a rede do celular: rotulo longo mais dica em coluna estreita
   quebra a linha em vez de espremer as duas. */
.campo__rotulo {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s3);
  margin-bottom: var(--s3);
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
}
.campo__dica { color: var(--paper-miudo); font-weight: var(--peso-normal); letter-spacing: .04em; text-transform: none; font-size: var(--fs-sm); }
/* A dica sobe para o brilho maximo quando ela vira a resposta a um clique:
   e o que acontece quando alguem toca "adicionar a sacola" sem ter
   escolhido o tamanho. O botao responde destacando a pergunta que ficou
   aberta, em vez de nao fazer nada (docs/FLUXO.md 4.1). */
.campo__dica[data-faltando="sim"] { color: var(--paper); font-weight: var(--peso-forte); }

/* A frase que explica para que serve o dado. No bloco de entrega ela e
   obrigacao de LGPD, e nao gentileza: a finalidade dita no momento da
   coleta (COMERCIO.md 13). `--paper-apoio` da 6,57:1, bem acima do piso. */
.campo__ajuda {
  margin-bottom: var(--s3);
  font-size: var(--fs-sm); color: var(--paper-apoio);
  max-width: 46ch;
}
/* ⚠️ A SUBIDA DE 16px SO VALE DENTRO DO CAMPO, e antes ela valia em toda
   parte. O rotulo deixa `--s3` de folga embaixo dele; quando a ajuda vem
   logo em seguida, ela cancela essa folga e cola no rotulo, que e onde ela
   deve ser lida: antes de digitar, junto da pergunta.

   Escrita solta, a mesma regra virava defeito. No bloco de entrega duas
   frases usam esta classe FORA de um `.campo` (o "nao sei o CEP" e o aviso
   da transportadora), e la o -16px nao tinha folga nenhuma para cancelar:
   ele comia o espaco de verdade e grudava a frase no fundo da caixa de
   digitar. Pior, como o atalho `margin` reescreve as quatro direcoes e este
   arquivo carrega depois do base.css, ele ainda apagava o `esp-3` que uma
   delas pedia.

   O seletor de filho e o que separa os dois casos, e ele ganha do `esp-*`
   por especificidade onde precisa ganhar: dentro do campo a subida vale
   sempre, fora dele quem manda e a classe de espaco. */
.campo > .campo__ajuda { margin-top: calc(var(--s3) * -1); }

/* A CAIXA. `--graph` e a superficie de campo declarada no tokens.css, e
   nenhum botao deste site a usa (ver .btn:disabled la em cima, e o motivo
   escrito nele). A borda e `--fio-vivo`: 4,11:1, acima dos 3:1 que uma
   borda precisa quando ela e o unico sinal de que ali se digita. */
.campo__caixa {
  display: block; width: 100%;
  min-height: var(--controle-altura);
  padding: var(--s2) var(--s3);
  background: var(--graph);
  color: var(--paper);
  border: 1px solid var(--fio-vivo);
  border-radius: var(--raio);
  font-size: var(--fs-body);   /* 16px. Abaixo disso o iOS DA ZOOM sozinho no
                                  campo ao receber foco, e a pagina fica torta
                                  ate a pessoa fechar o teclado. */
  transition: border-color var(--transicao), box-shadow var(--transicao);
}
.campo__caixa::placeholder { color: var(--paper-miudo); }
.campo__caixa:disabled { color: var(--paper-miudo); border-style: dashed; cursor: not-allowed; }

/* Preenchido pelo CEP: continua EDITAVEL, e o tom mais baixo diz "isto o
   sistema respondeu por voce" sem travar nada. CEP de rua nova vem
   incompleto, e quem conserta e a pessoa (docs/FLUXO.md 4.4). */
.campo__caixa[data-preenchido="sim"] { color: var(--paper-corpo); }

.campo__caixa[aria-invalid="true"] {
  border-color: var(--paper);
  box-shadow: inset 2px 0 0 0 var(--paper);
}

/* O erro fala no brilho maximo do site: num sistema de duas cores, o papel
   inteiro E o destaque. O quadrado de 8px e o mesmo do `.rotulo--marcado`,
   e ele existe para o erro ter um sinal que nao e cor nem palavra. */
.campo__erro {
  display: flex; align-items: baseline; gap: var(--s2);
  margin-top: var(--s2);
  font-size: var(--fs-sm); font-weight: var(--peso-forte);
  color: var(--paper);
}
.campo__erro::before {
  content: ""; flex: none;
  width: 8px; height: 8px;
  background: var(--paper);
  transform: translateY(-1px);
}

/* ------------------------------------------------------------
   O CODIGO EM QUADRADOS  (7 de agosto)
   ------------------------------------------------------------
   Pedido do Bruno. Num sistema de raio zero, seis quadrados sao o desenho
   mais coerente que existe para um codigo: e o MESMO quadrado de 8px que o
   `.rotulo--marcado` e o `.campo__erro` ja usam, so que grande.

   ⚠️ OS QUADRADOS NAO SAO CAMPOS. Eles sao `aria-hidden`, e por baixo deles
   corre UM `<input>` de verdade. O porque inteiro esta no `js/formulario.js`,
   no comentario do `def.caixas`, e ele e longo porque a alternativa (seis
   inputs) e o que todo mundo faz e quebra colar, apagar e o leitor de tela.
   ------------------------------------------------------------ */
.codigo { position: relative; }

/* O input de verdade cobre a fileira inteira, e e invisivel.
   `color` e `caret-color` transparentes, e nao `opacity: 0`: com opacidade
   zero o Safari deixa de oferecer o codigo do iMessage, que e justamente o
   que o `autocomplete="one-time-code"` existe para ganhar.
   `background: none` e `border: 0` para ele nao desenhar a caixa comprida
   que os quadrados substituem. */
.codigo .campo__caixa {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; padding: 0;
  background: none; border: 0; border-radius: 0;
  color: transparent; caret-color: transparent;
  /* 16px continua sendo o piso: abaixo disso o iOS da zoom ao focar, e aqui
     isso jogaria a fileira inteira para fora da tela. */
  font-size: var(--fs-body);
  /* O anel de foco e desenhado pelos quadrados, e nao por ele. */
  outline: none;
}

.codigo__quadros { display: flex; gap: var(--s3); }
/* No celular estreito o vao de 16px come mais largura que os proprios
   quadrados: a 335px de coluna sao 80px de vao contra 255px de quadrado. */
@media (max-width: 420px) { .codigo__quadros { gap: var(--s2); } }

.codigo__quadro {
  /* ⚠️ O TETO E DE LARGURA, E NUNCA DE ALTURA. Com `max-height` o quadrado
     PARA de ser quadrado assim que a coluna sobra: medido, a 495px eles
     sairam 69 de largura por 64 de altura, porque o `flex` mandava na largura
     e o teto mandava na altura, e o `aspect-ratio` nao tinha como valer nos
     dois. Limitando a largura, a altura vem da razao e o quadrado fecha.
     A 495px de coluna: seis de 64 mais cinco vaos de 16 dao 464px. */
  flex: 1 1 0; min-width: 0; max-width: 64px;
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--graph);
  border: 1px solid var(--fio-vivo);
  border-radius: var(--raio);
  font-size: var(--fs-h3); font-weight: var(--peso-forte);
  color: var(--paper);
  transition: border-color var(--transicao), box-shadow var(--transicao);
}

/* O quadrado da vez, e ele SO acende com o campo focado: aceso sem foco, ele
   prometeria que dali se digita quando o teclado esta em outro lugar. E o
   mesmo fio de 2px por dentro que o `[aria-invalid]` usa, pelo mesmo motivo
   escrito la: engrossar a borda empurraria os seis vizinhos. */
.codigo[data-foco="sim"] .codigo__quadro[data-vez="sim"] {
  border-color: var(--paper);
  box-shadow: inset 0 0 0 1px var(--paper);
}

/* O erro pinta os SEIS, e nao um: o codigo errado e a resposta inteira que
   nao confere, e nao um digito. */
.codigo:has(.campo__caixa[aria-invalid="true"]) .codigo__quadro { border-color: var(--paper); }

/* Dois campos na mesma linha (numero e complemento, cidade e UF). Quebra
   sozinho no celular.

   ⚠️ AS QUATRO LINHAS SAO A ANATOMIA DO `.campo`, NA ORDEM DELA:
   rotulo · ajuda · controle · erro. Elas existem no PAR, e cada `.campo`
   dentro dele se pendura nelas por `subgrid` — e isso e o que faz os dois
   campos alinharem peca a peca em vez de so por fora. O `row-gap` e ZERO de
   proposito: o espaco entre rotulo, ajuda, controle e erro ja esta nas
   margens de cada um deles, e um `gap` aqui somaria por cima de tudo. Por
   isso o vao de 24px e `column-gap`, e nao `gap`. */
.campo-par {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto auto auto auto;
  column-gap: var(--s4); row-gap: 0;
}
@media (max-width: 560px) {
  /* Empilhado nao ha o que alinhar, e as quatro linhas sairiam do lugar:
     dois campos em coluna precisam de OITO. Volta a ser uma coluna simples,
     e o vao de 24px volta a ser vertical. */
  .campo-par { grid-template-columns: 1fr; grid-template-rows: none; row-gap: var(--s4); }
}

/* PAR COM UM CAMPO SO NAO E PAR, E VIRA UMA COLUNA.
   ------------------------------------------------------------
   Quem esconde campo aqui e o PAIS, e nao o tamanho da tela: fora do Brasil
   somem o bairro, o numero e (onde nao existe estado) a UF. Os dois pares do
   endereco sao exatamente cidade/UF e numero/complemento, entao numa compra
   alema cada par fica com UM sobrevivente.

   Sem esta regra o sobrevivente continua ocupando so a primeira das duas
   colunas: MEDIDO na tela alema, `Berlin` numa caixa de 291px com 314px de
   nada do lado, embaixo de CODIGO POSTAL e ENDERECO que ocupam os 605px
   inteiros. Le como campo faltando, e nao como desenho.

   ⚠️ E ELA E A MESMA REGRA QUE O `DESIGN.md` 15 ja tinha escrito para a
   ajuda, so que para o campo: num par, o que existe de um lado so e sempre um
   buraco do tamanho dele no outro. Ou os dois aparecem, ou o par deixa de ser
   par. Com uma coluna o rotulo longo do complemento tambem para de quebrar em
   duas linhas, e a dica `opcional` volta para o lado dele em vez de descer.

   O `:has()` ja e usado neste arquivo (ver `.codigo:has(...)` acima), e o
   seletor de filho e de proposito: par dentro de par nao existe, mas se um
   dia existir, esta regra nao vaza para o de dentro. */
.campo-par:has(> .campo[hidden]) { grid-template-columns: 1fr; }

/* ⚠️ AS DUAS CAIXAS ALINHAM PELA BASE, E ISSO E CONSERTO DE 7/ago.
   Dentro de um par, um campo pode ter frase de ajuda e o outro nao, ou um
   pode ter ajuda de duas linhas e o vizinho de uma. Como cada `.campo` cresce
   de cima para baixo, as caixas de digitar acabavam em alturas diferentes:
   medido na tela `Meu cadastro`, "Bruno" ficava 22px abaixo de "Ferreira", e
   CPF e WhatsApp desalinhavam pelo mesmo motivo. Duas caixas lado a lado em
   alturas diferentes leem como desalinho, e nao como hierarquia.

   `margin-top: auto` na caixa empurra ela (e o erro, que vem depois e nasce
   escondido) para o fim da celula, entao as bases coincidem qualquer que seja
   o tamanho do que vem em cima.

   ⚠️ SO DENTRO DO PAR. Campo sozinho nao tem com quem alinhar, e o `auto` ali
   nao faria nada alem de esperar um defeito futuro.

   ⚠️ E ISTO E A RESERVA, E NAO MAIS O DESENHO. Ler o bloco do `subgrid` logo
   abaixo antes de mexer aqui: quem alinha nos navegadores de hoje e ele, e
   este `margin-top: auto` so volta a valer onde `subgrid` nao existe. */
.campo-par > .campo { display: flex; flex-direction: column; }
.campo-par > .campo > .campo__caixa,
.campo-par > .campo > .codigo { margin-top: auto; }
@media (max-width: 560px) {
  /* Empilhados, nao ha o que alinhar, e o `auto` esticaria o campo de cima. */
  .campo-par > .campo { display: block; }
}

/* ------------------------------------------------------------
   O PAR ALINHA PECA A PECA  ·  `subgrid`   (8 de agosto)
   ------------------------------------------------------------
   ⚠️ ALINHAR PELA BASE ERA CERTO ATE O ERRO APARECER, E AI ERA ERRADO. O
   Bruno pegou olhando, no par PAIS + TELEFONE do checkout: ao tocar no
   telefone e sair sem preencher, "Falta preencher este campo" nasce EMBAIXO da
   caixa do telefone, a celula inteira cresce por baixo, e o `margin-top: auto`
   da porta de PAIS empurra ela para o novo fundo. MEDIDO na tela: a porta de
   PAIS desceu 63px e ficou pendurada abaixo da caixa do telefone, com os dois
   rotulos ainda lado a lado la em cima. O erro de um campo mexeu no vizinho,
   que e exatamente o "layout pulando" que a `FUNDACAO.md 10` recusa.

   E ELE TINHA UM SEGUNDO BURACO, MAIS ANTIGO E CALADO: a lista de seletores
   do `margin-top: auto` era `.campo__caixa` e `.codigo`, e o telefone nao e
   nenhum dos dois — ele e um `.campo__comDdi` por causa do `+55` colado. O
   mesmo vale para a porta de pais, que so entrava na conta porque ela carrega
   `.campo__caixa` junto com `.campo-pais`. Ou seja: alinhamento por lista de
   nomes, que quebra sozinho toda vez que nasce um tipo de controle novo.

   O CONSERTO TROCA A PERGUNTA. Nao e mais "onde termina cada campo" e sim "que
   PECA e esta": o par declara quatro linhas (rotulo, ajuda, controle, erro), e
   cada `.campo` se pendura nelas com `grid-template-rows: subgrid`. Dai sai
   tudo de uma vez, sem lista de nomes:

     · os rotulos comecam na mesma altura, sempre
     · a ajuda de duas linhas de um lado abre a linha 2 para os DOIS, entao os
       controles continuam alinhados sem ninguem calcular nada
     · o controle e a linha 3, seja ele caixa, DDI, porta de pais ou quadrados
     · O ERRO E A LINHA 4, e ele cresce PARA BAIXO da linha inteira. E este o
       conserto: o erro deixa de empurrar o vizinho porque ele nao mora mais
       dentro da celula do vizinho.

   ⚠️ `@supports` NAO E MEDO, E ROTA DE FUGA. `subgrid` e mais novo que o
   `:has()` que este site ja usa, e um navegador sem ele cairia num par
   desalinhado de verdade (sem as quatro linhas, cada peca acha o proprio
   lugar). Fora do `@supports` fica o desenho de 7/ago, que alinha pela base e
   so erra quando o erro aparece; dentro dele fica este, que nao erra. Quem um
   dia apagar o `@supports` apaga junto o `margin-top: auto` la em cima.
   ------------------------------------------------------------ */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 561px) {
    .campo-par > .campo {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 4;
    }
    /* O `auto` da reserva sai: aqui quem poe cada peca no lugar e a linha. */
    .campo-par > .campo > .campo__caixa,
    .campo-par > .campo > .codigo { margin-top: 0; }

    .campo-par > .campo > .campo__rotulo { grid-row: 1; }
    .campo-par > .campo > .campo__ajuda  { grid-row: 2; }
    /* Os quatro controles que este site tem, na linha 3. A porta de pais nao
       precisa de nome proprio: ela ja e um `.campo__caixa`. */
    .campo-par > .campo > .campo__caixa,
    .campo-par > .campo > .campo__comDdi,
    .campo-par > .campo > .codigo        { grid-row: 3; }
    .campo-par > .campo > .campo__erro   { grid-row: 4; }
  }
}

/* O aceite. O marcador nasce SEM marca (FUNDACAO.md 10: nunca deixar uma
   resposta pre-marcada que ninguem deu), e o alvo de toque e a linha
   inteira, nao o quadradinho de 16px. */
.aceite {
  display: flex; align-items: flex-start; gap: var(--s3);
  cursor: pointer;
  /* 22 do quadrado mais 16 de cada lado passa dos 44px de alvo mesmo quando
     a frase cabe numa linha so. */
  padding-block: var(--s3);
  min-height: var(--alvo);
}
.aceite input {
  flex: none; width: 22px; height: 22px; margin: 0;
  accent-color: var(--paper);   /* sem isto o navegador pinta de azul, que e a
                                   unica cor que este site nao tem */
  cursor: pointer;
}
.aceite__texto { font-size: var(--fs-sm); color: var(--paper-corpo); }
.aceite__texto a { border-bottom: 1px solid var(--fio-vivo); }

/* ------------------------------------------------------------
   SELETOR DE TAMANHO
   Botao de radio de verdade por baixo, para o teclado e o leitor de
   tela funcionarem sem gambiarra.
   ------------------------------------------------------------ */
.tamanhos { display: flex; flex-wrap: wrap; gap: var(--s2); }
.tamanho { position: relative; }
.tamanho input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.tamanho span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 56px; min-height: 48px; padding: 0 var(--s3);
  border: 1px solid var(--fio-vivo); border-radius: var(--raio);
  font-size: var(--fs-sm); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-botao); text-transform: uppercase;
  transition: border-color var(--transicao), color var(--transicao), background var(--transicao);
}
/* Escolhido = invertido. Nao e borda mais grossa: borda que engorda empurra
   o resto da linha e a pagina pula. */
.tamanho input:checked + span { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.tamanho input:focus-visible + span { outline: 2px solid var(--paper); outline-offset: 3px; }
.tamanho input:disabled + span { color: var(--paper-miudo); border-style: dashed; border-color: var(--fio); cursor: not-allowed; }
/* No hover o chip nao marcado PREENCHE, e o preenchimento e uma previa exata
   do que o clique faz: ele para no mesmo desenho do `:checked` acima. Quem
   desenha a varredura e o movimento.css. Chip marcado e chip travado nao
   preenchem: um ja esta preenchido, o outro nao promete o que nao da. */

/* ------------------------------------------------------------
   OS TRES ESTADOS (FUNDACAO.md 12: nao existe so o caminho feliz)
   ------------------------------------------------------------ */
/* Carregando: esqueleto com a FORMA do que vem, nunca a tela zerada.

   ⚠️ "A FORMA DO QUE VEM" E O CONTRATO INTEIRO, E ELE NAO ESTAVA SENDO
   CUMPRIDO NA `/conta` ATE 8/ago. La o esqueleto eram tres linhas de 12px, e
   o que chegava era um rotulo de 20px, um titulo de 33px, uma frase de 26px e
   TRES PORTAS DE 72px CADA. Medido: 36px de esqueleto no lugar de 296px de
   conteudo. Isso nao e uma espera, e uma promessa errada: a tela pula quando
   o dado chega, e o pulo desfaz justamente o que o esqueleto existe para
   comprar, que e a sensacao de continuidade.

   A regra que sobra: **a altura do esqueleto e a altura MEDIDA do que ele
   substitui**, e nao um valor bonito. Os numeros abaixo sairam da tela real,
   um por um. Quem mudar a altura de uma porta ou do titulo mede de novo. */
.esqueleto { background: var(--graph); animation: pulso 1.4s ease-in-out infinite; }
.esqueleto--quadro { aspect-ratio: 4 / 5; }
.esqueleto--linha  { height: 12px; margin-top: var(--s3); }
.esqueleto--curta  { width: 45%; }

/* ---- As formas da CABECA de tela, que as quatro secoes da conta tem ----
   Um rotulo curto (ou o caminho de volta), um titulo grande, e uma frase de
   apoio. As larguras sao proporcao e nao pixel: em coluna estreita elas
   acompanham. */
.esqueleto--rotulo { height: 20px; width: 110px; }
/* ⚠️ A ALTURA DO TITULO E CALCULADA, E NAO ESCRITA EM PIXEL, porque o titulo
   que ele substitui e `clamp(2rem, 5.4vw, 3.5rem)`: ele mede 33px numa coluna
   estreita e 58px num monitor largo. Qualquer numero fixo aqui acertaria em
   UMA largura e erraria em todas as outras, e o erro apareceria como salto no
   momento em que o dado chega. Amarrado aos dois tokens, ele acompanha
   sozinho, inclusive no dia em que a escala mudar. */
.esqueleto--titulo { height: calc(var(--fs-h1) * var(--lh-titulo)); width: 62%; margin-top: var(--s5); }
.esqueleto--apoio  { height: 26px; width: 54%; margin-top: var(--s4); }

/* ---- A LINHA DE LISTA, e ela nao e um retangulo cheio ----
   A porta real tem 72px de altura, mas o que a pessoa VE dentro dela e uma
   palavra a esquerda e uma seta a direita, com muito preto no meio. Um bloco
   de 72px solido prometeria um cartao, e o que chega e uma linha. Entao o
   esqueleto da porta e a CAIXA de 72px (que segura o espaco e o fio) com uma
   barrinha de texto dentro, na altura e na posicao onde a palavra cai. */
.esqueleto-linha-lista {
  height: 72px; display: flex; align-items: center;
  border-top: 1px solid var(--fio);
}
.esqueleto-linha-lista:last-child { border-bottom: 1px solid var(--fio); }
.esqueleto-linha-lista .esqueleto { height: 16px; width: 38%; margin: 0; }

/* A caixa de campo do `Meu cadastro`: rotulo curto em cima, caixa de 52px
   embaixo, no mesmo par de duas colunas que a tela real usa. */
.esqueleto-campo .esqueleto:first-child { height: 14px; width: 46%; margin: 0; }
.esqueleto-campo .esqueleto:last-child  { height: 52px; width: 100%; margin-top: var(--s3); }

@keyframes pulso { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }

/* Estado vazio, de erro e de peca inexistente. ALINHADO A ESQUERDA: o
   documento proibe copy centralizada, e um estado centralizado no meio de
   um site inteiro alinhado a esquerda le como pagina de outro site. */
.estado {
  padding-block: var(--s7);
  border-top: 2px solid var(--regua);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s3);
  grid-column: 1 / -1;
}
.estado__titulo {
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-h2); line-height: var(--lh-titulo);
  letter-spacing: var(--tk-display); text-transform: uppercase;
  margin-left: var(--optico);
}
.estado__texto { color: var(--paper-apoio); max-width: 44ch; }

/* ------------------------------------------------------------
   AVISO
   O painel de desvio: a peca que esgotou enquanto a pessoa preenchia, o
   pagamento que nao abriu. NAO e o `.estado` (aquele e a pagina inteira
   sem conteudo, com titulo de 42px); este e uma interrupcao DENTRO de uma
   tela que continua de pe.

   A anatomia e a mesma do `.rascunho`: fio de 2px na esquerda e o texto
   recuado. Duas coisas com o mesmo peso na pagina lendo do mesmo jeito, e
   a diferenca entre elas e o que dizem, nao como aparecem.

   Sem cor de alerta, e sem exclamacao (docs/FLUXO.md 7): a frase diz o que
   aconteceu e o que fazer agora, nessa ordem.
   ------------------------------------------------------------ */
.aviso {
  border-left: 2px solid var(--paper);
  padding: var(--s4) 0 var(--s4) var(--s4);
  margin-block: var(--s5);
}
.aviso__titulo {
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-sm); letter-spacing: var(--tk-rotulo); text-transform: uppercase;
}
.aviso__texto { margin-top: var(--s2); font-size: var(--fs-sm); color: var(--paper-corpo); max-width: 52ch; }
.aviso__acoes { margin-top: var(--s4); display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }

/* ------------------------------------------------------------
   ICONE (a peca de desenho do cabecalho)
   ------------------------------------------------------------
   ⚠️ ISTO VOLTA A SEGUNDA METADE DE UMA DECISAO ESCRITA, e o motivo mudou.
   O docs/DESIGN.md 4.2 recusou icone com duas frases, e as duas diziam a
   mesma coisa: "nao existe linguagem de icone desenhada para esta marca, e
   inventar quatro simbolos agora e decorar". O motivo nunca foi que icone e
   feio; foi que nao existia LINGUAGEM. Agora existe, ela esta escrita no
   docs/DESIGN.md ("A linguagem de icone") com nove regras e uma espessura
   medida, e por isso os dois icones que ela produziu podem entrar.

   A outra metade da frase daquele documento continua valendo inteira, e e a
   regua que manteve a busca e os favoritos de fora: ICONE QUE NAO LEVA A
   LUGAR NENHUM NAO ENTRA. Os dois que entraram levam — a sacola abre a
   gaveta, a conta abre `/entrar`.

   ------------------------------------------------------------
   POR QUE MASCARA, E NAO <img> NEM SVG DENTRO DO HTML
   ------------------------------------------------------------
   `<img src="icone.svg">` nao herda cor do CSS, entao o hover do topo
   (movimento.css) morreria. SVG escrito dentro do HTML herda, mas o
   cabecalho e COPIADO em oito documentos: corrigir uma curva viraria oito
   edicoes, e a oitava e a que alguem esquece.

   Com mascara o desenho tem um dono (o arquivo) e a cor tem outro (a regra
   que ja existe), que e o FUNDACAO.md 2.8 aplicado a desenho. A mascara le
   so o canal alfa do SVG, e por isso o `stroke` la dentro e preto e nao
   `currentColor`: quem pinta e o `background` daqui.

   ⚠️ CAMINHO ABSOLUTO, SEMPRE (FUNDACAO.md 4.7). `url()` resolve contra o
   arquivo que CONSOME a regra; no PDV isso deu 404 em todos os icones.
   ⚠️ O `-webkit-` VAI JUNTO, senao o Safari antigo nao desenha nada.
   ⚠️ O `?v=` E OBRIGATORIO: `assets/` tem cache de um ano `immutable`
   (vercel.json), entao icone trocado sem carimbo novo e icone velho no
   aparelho de quem ja visitou.
   ------------------------------------------------------------ */
.icone {
  display: block; flex: none;
  width: 24px; height: 24px;
  background: currentColor;
  -webkit-mask-repeat: no-repeat;   mask-repeat: no-repeat;
  -webkit-mask-position: center;    mask-position: center;
  -webkit-mask-size: 24px 24px;     mask-size: 24px 24px;
}
.icone--sacola {
  -webkit-mask-image: url("/assets/icones/sacola.svg?v=20260805c");
          mask-image: url("/assets/icones/sacola.svg?v=20260805c");
}
.icone--conta {
  -webkit-mask-image: url("/assets/icones/conta.svg?v=20260805c");
          mask-image: url("/assets/icones/conta.svg?v=20260805c");
}
.icone--busca {
  -webkit-mask-image: url("/assets/icones/busca.svg?v=20260805c");
          mask-image: url("/assets/icones/busca.svg?v=20260805c");
}

/* ------------------------------------------------------------
   O QUARTO ICONE: GUARDAR (6/ago)
   ------------------------------------------------------------
   ⚠️ ESTAS DUAS REGRAS SAO O UNICO LUGAR QUE ESCOLHE O SIMBOLO, e isso
   e de proposito. O nome da classe fala da FUNCAO (guardar) e nunca da
   forma (marcador, coracao), entao trocar de simbolo custa dois nomes de
   arquivo aqui e nada mais no site inteiro. Os quatro arquivos existem
   em /assets/icones, e o _medir-guardar.html poe os dois lado a lado no
   tamanho real, que e como este projeto escolhe desenho desde a medicao
   da espessura em 5/ago.

   POR QUE MARCADOR E NAO CORACAO, e a decisao e reversivel numa linha:
   a regra 2 da linguagem (DESIGN.md 11.2) diz que a UNICA curva
   permitida e a que representa uma coisa redonda de verdade, e as duas
   licencas ja foram gastas na cabeca do conta.svg e na lente do
   busca.svg. Os dois arcos de um coracao nao sao objeto redondo nenhum.
   O marcador resolve a mesma funcao com quatro retas.
   E a palavra: o MARCA.md 9.5 lista "lembrete" e "promessa" entre as
   palavras da marca, e o 9.6 poe fora o vocabulario de moda de estacao.
   Coracao e o pictograma de "curtir", que e desejo; marcador e o de
   "guardar", que e lembrete. A marca inteira e a segunda coisa.

   O ESTADO GUARDADO E O ARQUIVO CHEIO, e nao uma cor nova nem um fundo
   claro. Escolhido, neste site, ja tem desenho e ele e preenchido: o
   chip de tamanho `:checked` inverte, a contagem da sacola e um quadrado
   solido, o `.campo__erro` e um quadrado de 8px. E o movimento ja tem a
   palavra: no hover o que nao esta marcado PREENCHE, como previa exata
   do que o clique faz. Aqui e literal.
   ------------------------------------------------------------ */
.icone--guardar {
  -webkit-mask-image: url("/assets/icones/marcador.svg?v=20260806c");
          mask-image: url("/assets/icones/marcador.svg?v=20260806c");
}

/* O QUINTO ICONE: FECHAR (6/ago), o primeiro que NAO e do topo.
   Ele mora no cabecalho das camadas, no lugar onde havia a palavra "FECHAR"
   escrita. O porque da extensao dele ser menor que a dos quatro do topo esta
   no `<desc>` do proprio arquivo, e resume-se a uma frase: a regua dele e a
   letra ao lado, e nao os irmaos, porque ele nunca fica ao lado deles.

   ⚠️ SAO DOIS ARQUIVOS, E NENHUM DOS DOIS E O "PADRAO" (7/ago).
   Nao existe X generico neste site, e a regua explica por que: o tamanho de
   um grafico que encosta em texto e 1,21x a cap height da LETRA VIZINHA
   (DESIGN.md 11.6). Onde a letra muda, o desenho muda junto.

     .icone--fechar          10px de tinta   ao lado do titulo de 12px/600
                                             do painel de idioma
     .icone--fechar-camada   16px de tinta   ao lado do titulo de 20px/800
                                             das quatro camadas

   Escolher a classe, portanto, e escolher o VIZINHO, e nao um tamanho: o X
   de 10 ao lado de um titulo de 20px some, e o de 16 ao lado de um rotulo de
   12px grita mais alto que ele. Uma camada nova copia a linha da camada que
   se parece com ela, e nao "a que nao tem sufixo".

   E os dois desenhos existem porque a espessura 1,5 e lei (DESIGN.md 11.3):
   esticar um arquivo so de 10 para 16 por `mask-size` esticaria o traco de
   1,5 para 2,4 junto. O `<desc>` do fechar-camada.svg tem a conta inteira. */
/* ⚠️ OS DOIS CARIMBOS SAO DIFERENTES DE PROPOSITO, e a regra e a mesma dos
   outros icones: o carimbo e a data em que O ARQUIVO mudou, e nao a data da
   rodada. O fechar.svg nao encostou em 7/ago, entao trocar o `?v=` dele
   mandaria o navegador de quem ja visitou rebaixar de novo um arquivo
   identico. Sacola, conta e busca estao em 20260805c pelo mesmo motivo. */
.icone--fechar {
  -webkit-mask-image: url("/assets/icones/fechar.svg?v=20260806c");
          mask-image: url("/assets/icones/fechar.svg?v=20260806c");
}
.icone--fechar-camada {
  -webkit-mask-image: url("/assets/icones/fechar-camada.svg?v=20260807a");
          mask-image: url("/assets/icones/fechar-camada.svg?v=20260807a");
}
[aria-pressed="true"] > .icone--guardar {
  -webkit-mask-image: url("/assets/icones/marcador-cheio.svg?v=20260806c");
          mask-image: url("/assets/icones/marcador-cheio.svg?v=20260806c");
}

/* ------------------------------------------------------------
   SACOLA (o botao do cabecalho)
   ------------------------------------------------------------
   ⚠️ ISTO VOLTA UMA DECISAO ESCRITA, e a decisao mudou de motivo. O
   docs/DESIGN.md 4.2 tirou a zona de SACOLA do cabecalho do design system
   com esta frase: "o site nao tem busca, conta nem carrinho. Desenhar um
   icone de sacola que nao leva a lugar nenhum e copiar o desenho e mentir
   na funcao". Agora ela leva a algum lugar, entao ela volta.

   ELA ERA TEXTO E VIROU ICONE EM 5/ago, e o comentario que estava aqui
   dizia o contrario: "e texto, e nao icone... nao existe linguagem de icone
   desenhada para esta marca". A frase estava certa no dia em que foi
   escrita e deixou de estar quando a linguagem foi desenhada (ver o bloco
   ICONE, logo acima). O desenho e o mesmo argumento de sempre: o que mudou
   nao foi o gosto, foi o fato.

   O QUE NAO MUDOU: a contagem continua ao lado e continua NAO sendo
   aria-hidden. Lida em voz alta, "Sacola 2" ja diz tudo, e isso dispensa
   uma frase de plural em cada idioma. O nome acessivel agora vive num
   <span class="sr"> dentro do botao, e NAO num aria-label: aria-label
   substituiria o conteudo inteiro, e a contagem sumiria para quem usa
   leitor de tela.

   Ela nasce `hidden` no HTML e so aparece quando o JavaScript liga: uma
   sacola que nao abre nada e a mesma mentira de antes, do avesso.
   ------------------------------------------------------------ */
.sacola {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  /* `min-width` entrou junto com o icone: vazia, ela e so o desenho de 24px
     mais 16px de folga, que da 40 e fica abaixo do piso de dedo. */
  min-width: var(--alvo); min-height: var(--alvo); padding: 0 var(--s2);
  background: transparent; border: 0; cursor: pointer;
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* A contagem nao usa selo redondo (raio zero) nem cor: ela e um quadrado de
   papel com o numero em tinta, que e o mesmo desenho do que esta "marcado"
   em toda parte deste site (chip de tamanho, filtro). */
.sacola__conta {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 4px;
  background: var(--paper); color: var(--ink);
  font-size: var(--fs-micro); font-weight: var(--peso-display);
  letter-spacing: 0;
}
.sacola[data-vazia="sim"] .sacola__conta { display: none; }
/* hover: movimento.css */

/* ------------------------------------------------------------
   GUARDAR (o botao que marca a peca) e GUARDADOS (a porta no topo)
   ------------------------------------------------------------
   ⚠️ ISTO VOLTA A TERCEIRA DECISAO ESCRITA DESTE DOCUMENTO, e ela era a
   mais dura das tres. A tabela do docs/DESIGN.md 11.5 tinha uma linha
   so dizendo "nao, e nao e depois", e o motivo eram duas frases:
   "favorito e dado com dono, e dado com dono obriga banco e cai na
   LGPD" e "o MARCA.md 4 proibe mecanica de colecao".

   As duas cairam, e por motivo diferente cada uma. A primeira e falsa
   com a prova do lado: a SACOLA guarda a mesma forma de dado (uma lista
   de codigos de produto) em localStorage desde 5/ago, e o comentario
   dela diz por que isso nao e dado pessoal. A segunda cita uma regra que
   nao existe: o MARCA.md 4 proibe "comparacao entre membros, ranking,
   quem e mais", e uma lista privada nao compara ninguem com ninguem.

   O QUE NAO CAIU e a regua que decidiu o desenho: "icone que nao leva a
   lugar nenhum nao entra". Lista vazia e lugar nenhum, entao a porta do
   topo so existe quando existe o que guardar (js/guardados-gaveta.js).
   Medido: com a lista vazia, o cabecalho continua exatamente o de
   ontem, tres icones e as duas siglas.

   UM DESENHO SO, TRES LUGARES: o cartao da grade, a pagina da peca e o
   proprio topo. O que muda entre eles e a caixa em volta, nunca a tinta.
   ------------------------------------------------------------ */
.guardar {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-width: var(--alvo); min-height: var(--alvo);
  background: transparent; border: 0; padding: 0; cursor: pointer;
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* Guardada: a tinta sobe para o papel inteiro. E o mesmo salto do chip
   de tamanho escolhido, e ele e o unico jeito que este site tem de dizer
   "escolhido" sem cor: num sistema de duas cores, o papel E o destaque. */
.guardar[aria-pressed="true"] { color: var(--paper); }
.guardar:focus-visible { outline: 2px solid var(--paper); outline-offset: 2px; }
/* hover: movimento.css */

/* ---- A porta no topo ----
   ⚠️ ELA NAO E UM BOTAO DE ALTERNANCIA, e por isso nao carrega
   `aria-pressed` nem `data-guardar`. E uma PORTA: abre a camada e nao
   guarda nada. E o que a mantem sempre vazada, e o que faz o ouvinte de
   clique dos outros botoes passar direto por ela.
   O `padding` e o mesmo da sacola, para os dois quadrados de contagem
   respirarem igual na mesma barra. */
.guardar--porta { padding: 0 var(--s2); }
/* Lista vazia: some o quadrado da contagem, e a porta FICA. Exatamente o
   que a `.sacola[data-vazia]` faz duas regras acima, e de propósito: duas
   portas do mesmo cabeçalho com regras diferentes para o mesmo estado
   deixam a barra imprevisível. Ver o porquê inteiro no
   js/guardados-gaveta.js, em `ligarPorta`. */
.guardar--porta[data-vazia="sim"] .guardar__conta { display: none; }

/* A contagem da porta e a MESMA da sacola, e por isso divide a regra em
   vez de copia-la: dois quadrados de papel com numero dentro que
   divergissem em 1px seriam vistos lado a lado na mesma barra. */
.guardar__conta {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 4px;
  background: var(--paper); color: var(--ink);
  font-size: var(--fs-micro); font-weight: var(--peso-display);
  letter-spacing: 0;
}

/* ---- No cartao da grade ----
   ⚠️ ELE NAO FLUTUA SOBRE A FOTO, e este site ja decidiu isso tres
   vezes: o design system proibe badge (4.1), o selo de "esgotado" desceu
   para a linha do preco em vez de ficar sobre a imagem (4.2), e a marca
   d'agua do "L" saiu do hero com a frase "7% sobre fotografia e sujeira,
   nao discricao" (9.6). A Renner poe o coracao dela sobre a foto; aqui
   ele fica na linha de cima, que e a linha que ja diz o que a peca e.

   POR QUE NA LINHA DE CIMA E NAO NA DO PRECO: a linha do preco e onde a
   decisao de comprar acontece, e ela ja tem o preco e a seta. Um terceiro
   alvo ali dividiria a atencao no unico momento em que ela vale dinheiro.

   POSICAO ABSOLUTA para o alvo de 44px nao engordar a linha de cima: a
   tinta de 24px encosta na borda direita do cartao e a folga de 10px de
   cada lado cai por fora, sobre a margem que ja existia. O
   `padding-right` do .card__meta e o que impede a categoria de passar por
   baixo dele. */
.card { position: relative; }
.card__link { display: block; }
/* ⚠️ 48px E NAO 32px, E A DIFERENCA FOI MEDIDA. Com 32 o ALVO de 44px do
   botao passava 2px por cima da caixa da categoria: a tinta ficava longe,
   mas o dedo que tocasse o fim da palavra "CAMISETA" abriria o guardar em
   vez da peca. Alvo se confere pela caixa, e nunca pelo desenho. */
.card__meta { padding-right: var(--s6); }
.card__guardar {
  position: absolute; top: -10px; right: -10px;
  width: var(--alvo); height: var(--alvo);
}

/* ---- Na pagina da peca ----
   Quadrado, do tamanho do primario, ao lado dele. Com borda, porque ali
   ele nao esta numa barra de icones: esta sozinho ao lado de um botao, e
   sem caixa ele pareceria um enfeite ao lado do CTA em vez de um
   segundo controle. E a mesma borda do .btn--secundario. */
.guardar--caixa {
  flex: none;
  /* 48px e a altura do .btn, e a largura acompanha para o quadrado ser
     quadrado de verdade. `align-items: stretch` na linha faz os dois
     terminarem exatamente na mesma altura mesmo se o primario crescer
     com uma palavra longa em ingles. */
  width: 48px; min-height: 48px;
  border: 1px solid var(--fio-vivo);
}
.peca__acao-linha { display: flex; align-items: stretch; gap: var(--s3); }
.peca__acao-linha .btn { flex: 1; }

/* ------------------------------------------------------------
   CONTA (a porta, ao lado da sacola)
   ------------------------------------------------------------
   E UM LINK DE VERDADE, e nao um botao que troca de tela por JavaScript:
   sem script ele continua levando a `/entrar`, o clique do meio abre em
   outra aba, e o endereco muda junto. Mesma decisao dos dois links do
   idioma (base.css).

   ⚠️ ELE NAO TEM ESTADO ACESO PARA QUEM JA ENTROU. Um segundo tom claro no
   topo seria um segundo sinal forte disputando com o CTA primario, que e
   exatamente o que tirou o retangulo branco do idioma (base.css). Quem esta
   dentro descobre isso ao clicar: o proprio servidor manda para `/conta`.
   O que muda por dentro e so o nome acessivel, escrito pelo JavaScript.
   ------------------------------------------------------------ */
.conta {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--alvo); min-height: var(--alvo);
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* hover: movimento.css */

/* ------------------------------------------------------------
   O MONOGRAMA  (7 de agosto)
   ------------------------------------------------------------
   Ele substitui o desenho do bonequinho para quem esta dentro, e quem faz a
   troca e o `marcarConta()` do `js/ui.js`, onde o porque esta escrito por
   extenso.

   ⚠️ QUADRADO. O `docs/DESIGN.md 4.1` chama raio zero de regra inviolavel
   numero um, e a referencia que pediu isto (a Renner) usa circulo. Circulo
   aqui seria a primeira coisa arredondada do site, encostada em quatro
   icones de canto vivo. O quadrado ja e motivo grafico desta marca: e o
   mesmo do `.rotulo--marcado::before` e do `.campo__erro::before`.

   ⚠️ ELE GANHOU MOLDURA EM 8/ago, E O MOTIVO E QUE ELE ESTAVA DIZENDO A
   MESMA COISA QUE O CONTADOR DA SACOLA.

   O `.sacola__conta` e um quadrado de papel de 20px com tinta escura dentro.
   O monograma era um quadrado de papel de 22px com tinta escura dentro. Dois
   pixels de diferenca, a mesma superficie, a mesma tinta, um do lado do outro
   na mesma barra: o Bruno pegou olhando e a queixa foi literal — "o quadrado
   do 2 e o quadrado do B sao a mesma coisa". E eram, e o problema nao e de
   acabamento: chip solido de papel neste site QUER DIZER quantidade marcada
   (o contador, o chip de tamanho, o filtro ligado). O monograma nao e uma
   quantidade, e uma PESSOA.

   O QUE SEPARA OS DOIS AGORA E O VOCABULARIO, E ELE JA EXISTIA NA BARRA: a
   bandeira do idioma, tres icones a direita, e uma IMAGEM DENTRO DE UMA
   MOLDURA de 1px (ver `.idioma-porta__bandeira`). O monograma passa a falar
   essa lingua — moldura de 1px, um vao de 3px de passe-partout, e a mancha de
   papel montada dentro dela. Ele deixa de ser um chip e vira um retrato, que e
   exatamente o que ele e: o lugar da foto de quem esta dentro, com a inicial
   ocupando esse lugar enquanto foto nao existe.

   ⚠️ 28px POR FORA, 20px DE PAPEL POR DENTRO, e as duas medidas tem conta.
   Os 28 sao a moldura mais o vao mais o miolo (1+3+20+3+1) e continuam
   folgados dentro do alvo de 44px que o `.conta` da. Os 20 sao o miolo: o
   quadrado ENCOLHEU de 22 para 20 ao ganhar a moldura, e nao cresceu.

   Isso e o que mantem de pe a regra do `.conta` la em cima — o icone nao
   acende para quem esta dentro, porque um segundo tom claro no topo disputa
   com o CTA primario (FUNDACAO.md 10). A conta que a autorizava era de AREA, e
   ela melhorou: 400px2 de tinta clara aqui contra 10.272px2 do botao primario,
   1 para 26, onde antes era 484px2 e 1 para 21. A moldura nao entra nessa
   conta porque ela e `--fio-vivo`, que e traco e nao superficie.

   ⚠️ `background-clip: content-box` E O QUE FAZ ISTO EM UM ELEMENTO SO. O
   fundo de papel para na caixa de conteudo, entao os 3px de `padding` ficam
   com o fundo da barra atras deles e viram o vao da moldura. Sem ele o papel
   vaza ate a borda e a moldura encosta no miolo, que e o desenho errado. Nada
   de sombra e nada de um segundo `<span>`: o `js/ui.js` cria UM elemento.

   ⚠️ QUADRADO. O `docs/DESIGN.md 4.1` chama raio zero de regra inviolavel
   numero um, e a referencia que pediu isto (a Renner) usa circulo. Circulo
   aqui seria a primeira coisa arredondada do site, encostada em quatro
   icones de canto vivo — e a moldura so piora esse caso, porque moldura
   redonda em volta de miolo redondo e o desenho mais distante que existe
   deste sistema.

   Sem largura de alvo propria: quem da os 44px e o `.conta` em volta. */
.conta__monograma {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
  width: 28px; height: 28px;
  padding: 3px;
  background: var(--paper);
  background-clip: content-box;
  color: var(--ink);
  border: 1px solid var(--fio-vivo);
  border-radius: var(--raio);
  font-family: var(--fonte-display);
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  /* A letra e uma so, entao o espacamento de rotulo empurraria ela para fora
     do centro: ele abre espaco DEPOIS do caractere, e nao dos dois lados. */
  letter-spacing: 0;
  line-height: 1;
  /* O `.conta` muda de cor no hover, e o monograma nao pode ir junto: ele nao
     e tinta de icone, e a mancha clara dele e a mesma sempre. A moldura segue
     a mesma regra, e por isso ela e `--fio-vivo` e nao `currentColor`: uma
     moldura de retrato que pisca no hover viraria estado, e ela nao e estado. */
  transition: none;
}

/* ------------------------------------------------------------
   BUSCA (a lupa, e a camada que ela abre)
   ------------------------------------------------------------
   ⚠️ ISTO VOLTA A OUTRA METADE DA DECISAO ESCRITA. O docs/DESIGN.md 4.2
   tirou a zona de BUSCAR do cabecalho com esta frase: "o site nao tem
   busca, conta nem carrinho; desenhar um icone que nao leva a lugar nenhum
   e copiar o desenho e mentir na funcao". As tres zonas voltaram, e as tres
   pelo mesmo teste, um de cada vez: a sacola quando a gaveta nasceu, a
   conta quando /entrar nasceu, e a busca agora que existe o que buscar.

   O motivo da recusa da BUSCA especificamente era outro, e mais forte:
   "busca num catalogo de 5 pecas e um campo que devolve a mesma lista".
   Isso continua verdade para FILTRAR e e falso para ACHAR, e a diferenca
   esta escrita no js/busca.js. O que a camada NUNCA faz e despejar as cinco
   pecas com o campo vazio, que seria exatamente a mesma lista de novo.

   ⚠️ A LUPA NASCE `hidden`, como a sacola. Sem JavaScript ela nao aparece,
   e o caminho de sempre (o menu "Pecas") continua inteiro. Lupa que nao
   abre nada e a mesma mentira, do avesso.
   ------------------------------------------------------------ */
.busca-abrir {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--alvo); min-height: var(--alvo);
  background: transparent; border: 0; cursor: pointer;
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* hover: movimento.css */

/* A CAMADA. Ela desce do TOPO, e nao da direita como a gaveta, e a
   diferenca nao e enfeite: a busca comeca no cabecalho, entao ela cresce de
   onde o dedo tocou. A gaveta vem da direita porque a sacola mora la. */
.busca {
  padding: 0; border: 0; border-radius: var(--raio);
  background: var(--ink); color: var(--paper);
  margin: 0 auto 0 auto;   /* encosta em cima, centrada na largura */
  width: min(720px, 100%);
  max-height: min(80vh, 100%);
  border-bottom: 1px solid var(--fio);
  flex-direction: column;
}
.busca[open] { display: flex; }
@supports (height: 1dvh) { .busca { max-height: min(80dvh, 100%); } }

.busca__cabeca {
  flex: none;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--fio);
}
/* A lupa aqui dentro e DECORACAO e nao controle: quem busca ja esta com o
   cursor no campo. Por isso ela e mais apagada que a do cabecalho e nao tem
   alvo de dedo nenhum. */
.busca__lupa { color: var(--paper-miudo); flex: none; }

.busca__campo {
  flex: 1 1 auto; min-width: 0;
  background: transparent; border: 0; border-radius: var(--raio);
  padding: var(--s3) 0;
  color: var(--paper);
  font-family: inherit; font-size: var(--fs-h3); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-nome);
}
/* ⚠️ O ANEL DE FOCO SAI DAQUI, E SO DAQUI. O campo ocupa a barra inteira e
   ja e obviamente o que esta focado quando a camada abre: o anel em volta
   dele desenharia um retangulo em torno de meia tela. Em todo o resto do
   site o foco vem do base.css e nao se mexe. */
.busca__campo:focus { outline: 0; }
.busca__campo::placeholder { color: var(--paper-miudo); opacity: 1; }
/* O "x" que o Chrome e o Safari poem dentro de `type="search"`: ele e
   redondo, e o raio deste site e zero. Sai, e quem limpa e o Esc. */
.busca__campo::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.busca__corpo { flex: 1 1 auto; overflow-y: auto; padding: var(--s4) var(--s5) var(--s5); }

.busca__aviso { color: var(--paper-corpo); font-size: var(--fs-sm); }
.busca__aviso--fraco { color: var(--paper-miudo); margin-top: var(--s2); }
.busca__conta {
  color: var(--paper-miudo);
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  margin-bottom: var(--s3);
}

.busca__lista { list-style: none; margin: 0; padding: 0; }
.busca__item + .busca__item { border-top: 1px solid var(--fio); }
.busca__link {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) 0;
  min-height: var(--alvo);
  text-decoration: none; color: inherit;
}
.busca__quadro { flex: none; width: 48px; height: 60px; overflow: hidden; background: var(--ink-claro, #141414); }
.busca__quadro img { width: 100%; height: 100%; object-fit: cover; display: block; }
.busca__texto { flex: 1 1 auto; min-width: 0; }
.busca__nome {
  display: block;
  font-weight: var(--peso-forte); letter-spacing: var(--tk-nome); text-transform: uppercase;
  font-size: var(--fs-sm);
}
/* Uma linha so, e cortada com reticencias: o resumo aqui e pista, e nao
   leitura. Duas linhas de resumo empurrariam o quarto resultado para fora
   da tela do celular. */
.busca__resumo {
  display: block; margin-top: 2px;
  color: var(--paper-miudo); font-size: var(--fs-micro);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.busca__preco {
  flex: none;
  font-size: var(--fs-sm); font-weight: var(--peso-forte);
  color: var(--paper-corpo);
}

/* ------------------------------------------------------------
   GAVETA (a sacola em camada flutuante)
   ------------------------------------------------------------
   E um <dialog> de verdade, e nao uma <div> com z-index. O que vem de
   graca com o elemento nativo: Esc fecha, o foco fica preso dentro, o
   resto da pagina vira inerte para o leitor de tela, e a camada nasce na
   camada de cima do navegador, sem disputa de z-index com o cabecalho
   grudado. Escrever isso a mao sao umas cem linhas que ninguem revisa.

   ⚠️ A CABECA E O RODAPE SAO FIXOS E O CORPO ROLA POR DENTRO. Camada
   flutuante que nao cabe na tela e defeito conhecido, ja custou tempo no
   PDV, e a cura e esta: a pagina nunca rola por baixo, e o total e o botao
   nunca saem de vista (COMERCIO.md 6.3).

   NO COMPUTADOR ela encosta na direita, 420px. NO CELULAR vira folha de
   baixo, ate 90% da altura (docs/FLUXO.md 6).
   ------------------------------------------------------------ */
.gaveta {
  padding: 0; border: 0; border-radius: var(--raio);
  background: var(--ink); color: var(--paper);
  max-height: 100%;
  /* Encosta na direita: `margin-left: auto` empurra, e os zeros de cima e
     de baixo tiram o centramento que o navegador da de fabrica ao dialogo. */
  margin: 0 0 0 auto;
  width: min(var(--largura-gaveta), 100%);
  height: 100%;
  border-left: 1px solid var(--fio);
  flex-direction: column;   /* so vale com [open]; ver abaixo */
}
/* `display` do <dialog> fechado e `none`, e o navegador o devolve como
   `block` ao abrir. Sem esta linha o flex nao vale e o corpo nao rola. */
.gaveta[open] { display: flex; }
/* O veu e de TODA camada, e nao so da gaveta: no dia em que existirem duas
   camadas com dois escuros diferentes, a segunda parece de outro site. */
dialog::backdrop { background: var(--veu-camada); }

.gaveta__cabeca {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--fio);
}
.gaveta__titulo,
.camada__titulo {
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-h3); letter-spacing: var(--tk-nome); text-transform: uppercase;
}
/* ------------------------------------------------------------
   O FECHAR
   ------------------------------------------------------------
   Ele e o mesmo nas cinco camadas que existem hoje (sacola, guardados,
   busca, politicas e o painel de idioma), entao nao pertence a nenhuma
   delas: e uma peca so, com um nome so.

   ⚠️ ELE ERA A PALAVRA "FECHAR" E VIROU O X, e em duas datas: o painel de
   idioma em 6/ago, as outras quatro em 7/ago. O nome acessivel nao saiu
   junto, ele so parou de ser desenhado: vive num `<span class="sr">` dentro
   do botao, com a chave `geral.fechar`, escrita nos quatro idiomas. E a
   regra 9 da linguagem de icone (DESIGN.md 11.2), e ela e o que separa
   "trocar a palavra pelo simbolo" de "apagar a palavra".

   ⚠️ AQUI NAO SOBROU NENHUMA PROPRIEDADE DE TEXTO, e a ausencia e a
   mudanca. Estavam escritos `font-size`, `font-weight`, `letter-spacing` e
   `text-transform`, que desenhavam a palavra. Nenhum dos cinco botoes tem
   mais texto visivel, e o `.sr` e uma caixa de 1px recortada: as quatro
   linhas passaram a nao mudar um pixel de nada. Ficar "por seguranca" era
   deixar quatro linhas que o proximo leitor gastaria tempo entendendo
   (FUNDACAO.md 4.5).

   O QUE FICOU E O `color`, e ele nao e decoracao: o desenho e
   `background: currentColor` (ver .icone la em cima), entao a cor do botao
   E a cor do X, e o acender do hover (movimento.css) continua sendo uma
   linha so para os dois estados.
   ------------------------------------------------------------ */
.fechar {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--alvo); min-height: var(--alvo);
  /* ⚠️ QUEM ANDA E O ALVO, E A TINTA FICA PARADA NA LINHA DE CONTEUDO.
     O alvo de 44 e centrado num desenho que ocupa bem menos que isso, entao
     ele sobra `(alvo - tinta) / 2` de cada lado do X. Sem puxar essa sobra
     de volta, o X pararia longe da borda e o cabecalho leria torto, porque a
     linha que o olho enxerga a direita e a da TINTA, e nao a da caixa
     invisivel de 44px que o dedo acerta. Puxando exatamente a sobra, o alvo
     cresce para dentro da calha e o desenho encosta na mesma linha vertical
     onde o titulo comeca do outro lado.

     ⚠️ E POR ISSO A CONTA LE `--tinta-fechar`, EM VEZ DE UM NUMERO ESCRITO.
     Sao dois tamanhos de X (10 no painel, 16 nas camadas, ver .icone--fechar
     la em cima), e um puxao fixo alinharia um e desalinharia o outro em 3px.
     Quem declara o valor e o cabecalho, logo abaixo, porque e la que mora a
     letra que serve de regua.

     O `+ 1px` e o corte da diagonal, e ele e medido: um traco de 1,5 a 45
     graus estende 0,53px alem do fim do caminho em cada ponta, entao a tinta
     e ~1px mais larga do que o caminho do arquivo diz. Meio pixel arredonda
     para um inteiro de proposito: margem fracionaria poe o quadro de 24px da
     mascara num meio pixel e borra o traco de 1,5 a 1x, que e o mesmo motivo
     da regra 6 da linguagem de icone.

     A conta devolve -16px com tinta de 10, que e ao caractere o valor que
     estava escrito a mao aqui desde 6/ago: o painel de idioma nao se moveu
     um pixel quando esta regra passou a ser derivada. E devolve -13px com
     tinta de 16. Medido nas cinco camadas, a 1280px, a 390 e a 360: nos dois
     tamanhos a tinta para 0,47px antes da linha de conteudo, mesmo com as
     calhas sendo 24, 25, 32 e 33, que e o que um numero fixo nao alcanca. */
  margin-right: calc((var(--tinta-fechar, 10px) - var(--alvo)) / 2 + 1px);
  background: transparent; border: 0; cursor: pointer;
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* A regua do X e a LETRA AO LADO (DESIGN.md 11.6), entao quem escolhe o
   tamanho e o cabecalho, e nao o botao: e o cabecalho que sabe se o vizinho
   do X e um titulo de 20px ou um rotulo de 12px. Camada nova declara a sua
   aqui, na linha que couber, e ganha o alinhamento de graca.
   ⚠️ O 10px de reserva la em cima existe para a camada que esquecer: com ele
   o X para 3px ANTES da linha, que le como respiro. Sem reserva nenhuma o
   `calc` inteiro seria invalido, a margem viraria zero e o X andaria 13px
   para dentro, que le como defeito. */
.gaveta__cabeca,
.camada__cabeca,
.busca__cabeca { --tinta-fechar: 16px; }
.painel-idioma__cabeca { --tinta-fechar: 10px; }
.gaveta__corpo { flex: 1 1 auto; overflow-y: auto; padding: var(--s5); }
.gaveta__rodape { flex: none; padding: var(--s5); border-top: 1px solid var(--fio); }

/* A alca da folha do celular. No computador ela nao existe, porque nao ha
   arrasto: la se fecha no Esc, no botao ou no clique fora. */
.gaveta__alca { display: none; }

.gaveta__item {
  display: grid; grid-template-columns: 64px minmax(0, 1fr);
  gap: var(--s3) var(--s4);
  padding-block: var(--s4);
  border-top: 1px solid var(--fio);
}
.gaveta__item:first-child { border-top: 0; padding-top: 0; }
.gaveta__item:last-child { border-bottom: 1px solid var(--fio); }
/* O quadro da miniatura e o mesmo 4:5 do cartao: a peca aparece na sacola
   com o mesmo recorte com que apareceu na vitrine. */
.gaveta__foto { aspect-ratio: 4 / 5; background: var(--quadro); overflow: hidden; }
.gaveta__foto img { width: 100%; height: 100%; object-fit: cover; }
.gaveta__nome {
  display: block;
  font-family: var(--fonte-display); font-weight: var(--peso-display);
  font-size: var(--fs-sm); letter-spacing: var(--tk-nome);
  text-transform: uppercase; line-height: 1.2;
}
.gaveta__linha { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-top: var(--s2); }
.gaveta__tamanho { font-size: var(--fs-sm); color: var(--paper-apoio); }
.gaveta__preco { font-size: var(--fs-sm); font-weight: var(--peso-forte); letter-spacing: var(--tk-nome); }
.gaveta__controles { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-top: var(--s3); }
/* Peca que saiu do catalogo ou esgotou desde ontem: a linha esmaece e o
   unico controle que sobra e tirar. Ela NAO some sozinha: sumir sem avisar
   e a pessoa descobrir no total (docs/FLUXO.md 4.2). */
.gaveta__item[data-morto="sim"] .gaveta__foto img { opacity: .3; }
.gaveta__item[data-morto="sim"] .gaveta__nome { color: var(--paper-apoio); }
.gaveta__nota { margin-top: var(--s2); font-size: var(--fs-sm); color: var(--paper-miudo); }

/* Os meios aceitos, em tom baixo, respondendo "voces aceitam o que eu uso?"
   antes do clique (docs/FLUXO.md 1.3). SEM bandeira de cartao: enquanto o
   provedor nao estiver escolhido, dizer "visa, master, elo" e prometer o
   que ninguem contratou ainda. */
.gaveta__meios {
  margin-top: var(--s4);
  font-size: var(--fs-micro); letter-spacing: var(--tk-rotulo);
  text-transform: uppercase; color: var(--paper-miudo);
}

@media (max-width: 700px) {
  .gaveta {
    margin: auto auto 0;            /* encosta embaixo */
    width: 100%;
    height: auto;
    max-height: var(--gaveta-altura);
    /* ⚠️ `max-width: none` NAO E SOBRA, e sem ele o `width: 100%` acima e
       uma mentira. Todo <dialog> nasce com `max-width: calc(100% - 6px - 2em)`
       na folha de estilo DO NAVEGADOR, ou seja, 38px a menos. Medido numa
       tela de 375: a folha saia com 337px e as margens `auto` a centravam,
       deixando 19px de pagina aparecendo de cada lado. O desenho pede folha
       de baixo encostada nas bordas (docs/FLUXO.md 6), e uma folha que
       flutua no meio com duas frestas e outra coisa. No computador ele nao
       muda nada: la a largura e 420px, bem abaixo do teto do navegador. */
    max-width: none;
    border-left: 0; border-top: 1px solid var(--fio);
  }
  /* A alca e o alvo do arrasto e o sinal de que da para arrastar. Ela fica
     na cabeca da folha, que e a area que a mao alcanca sem cobrir o
     conteudo. */
  .gaveta__alca {
    display: block; width: 44px; height: 4px;
    background: var(--fio-vivo);
    margin: var(--s3) auto calc(var(--s3) * -1);
    flex: none;
  }
  .gaveta__cabeca, .gaveta__corpo, .gaveta__rodape { padding-inline: var(--s4); }
  /* O arrasto para fechar mora no movimento.css, com o resto do movimento. */
}

/* Enquanto a gaveta esta aberta a pagina nao rola atras dela. A classe e
   escrita pelo JavaScript, e nao por `:has()`, porque aqui certeza vale
   mais que elegancia: o dia em que um navegador nao souber `:has` o
   defeito e a pagina rolando por baixo da camada, que e justamente o que
   esta regra existe para impedir.
   `scrollbar-gutter` reserva a calha da barra de rolagem o tempo todo, para
   a pagina nao dar um pulo lateral no instante em que a rolagem some. */
html { scrollbar-gutter: stable; }
html.gaveta-aberta { overflow: hidden; }

/* ------------------------------------------------------------
   CAMADA (a folha de leitura)
   ------------------------------------------------------------
   Serve ao que se le sem sair de onde se esta: a politica de troca e a de
   privacidade, abertas do aceite do checkout. Sair da pagina para ler duas
   linhas de regra e perder o formulario inteiro que a pessoa acabou de
   preencher (docs/FLUXO.md 4.5).

   Mesma especie da gaveta (dialogo nativo, mesmo veu), outra forma: ela
   nao encosta em borda nenhuma, porque nao e um painel da pagina, e um
   documento por cima dela.
   ------------------------------------------------------------ */
.camada {
  padding: 0; border: 1px solid var(--fio); border-radius: var(--raio);
  background: var(--ink); color: var(--paper);
  width: min(60ch, calc(100% - var(--s5) * 2));
  max-height: min(80vh, 720px);
  overflow: hidden;
  flex-direction: column;
}
.camada[open] { display: flex; }
.camada__cabeca {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--fio);
}
.camada__corpo { flex: 1 1 auto; overflow-y: auto; padding: var(--s5); }

/* ------------------------------------------------------------
   O TEXTO DAS DUAS POLITICAS
   ------------------------------------------------------------
   Elas sao os unicos textos LONGOS que o site mostra numa camada, e por isso
   ganham medida propria: o corpo padrao foi medido para paragrafo de marca,
   de tres ou quatro linhas, e nao para uma pagina de regras.

   ⚠️ `pre-line` e o que transforma os `\n` do textos.js em quebras de linha.
   E o mesmo caminho do manifesto da pagina da marca: partir a politica em
   vinte chaves faria a traducao perder o fio, e o numero de itens de uma
   regra muda entre os idiomas.

   ⚠️ A MEDIDA DE LEITURA E 62ch. Regra em linha de 120 caracteres nao se le,
   se pula, e regra que ninguem le e o mesmo que regra nao publicada. */
.politica__corpo {
  white-space: pre-line;
  max-width: 62ch;
  line-height: 1.65;
}
.politica__corpo + .politica__secao { margin-top: var(--s5); }

/* O titulo da secao. Ele existe para a pessoa VARRER ate achar a parte que
   interessa, e nao para decorar: por isso ganha caixa alta, tracking e a cor
   cheia, enquanto o corpo fica no apoio. A hierarquia aqui e peso e cor, e
   nao tamanho: numa camada que ja rola, titulo grande empurra a regra para
   fora da tela.
   ⚠️ 13px com tracking `.14em` fica acima do piso de 12px do projeto e e a
   mesma familia de rotulo que a home usa nos selos de secao. */
.politica__secao {
  margin-bottom: var(--s2);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper);
}
.faixa--claro .politica__secao { color: var(--ink); }

/* A versao fica no fim, discreta e legivel: ela nao e enfeite juridico, e o
   que liga ESTE texto ao pedido que a pessoa fez. O piso de contraste do
   projeto e 4,5:1, e por isso ela usa o apoio e nunca um cinza mais fraco
   (docs/DESIGN.md 3). */
.politica__versao {
  margin-top: var(--s5);
  padding-top: var(--s3);
  border-top: 1px solid var(--fio);
  font-size: 14px;
  color: var(--ink-apoio);
}

/* ------------------------------------------------------------
   RESUMO (subtotal, entrega, total)
   Tres consumidores: a gaveta, a coluna fixa do /finalizar e a barra do
   celular. Por isso ele mora aqui e nao numa pagina.
   ------------------------------------------------------------ */
.resumo { display: block; }
.resumo__linha {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); padding-block: var(--s2);
  font-size: var(--fs-sm); color: var(--paper-apoio);
}
.resumo__linha dt, .resumo__linha dd { margin: 0; }
/* ⚠️ QUEM PROTEGE A COLUNA DO DINHEIRO E ISTO. Com `flex-shrink: 0` no valor,
   quem cede espaco e sempre o texto da esquerda, que e o que pode ceder: preco
   espremido contra a borda nao tem conserto, e rotulo longo quebrando em duas
   linhas tem. O caso que cobra isto e a linha do desconto, que carrega o codigo
   do cupom junto ("Desconto · PRIMEIRACOMPRA"). E o valor nunca e comprido — e
   dinheiro, ou o link de calcular o frete.

   ⚠️ ATE 9/ago ISTO TAMBEM SEGURAVA O PRAZO, que morava dentro do `<dt>` da
   entrega. Ele saiu de la e virou a `.resumo__nota` (o porque esta na
   `js/ui.js`, em cima da `resumoHTML()`), mas a regra fica: ela nasceu para o
   prazo e continua valendo para o cupom. */
.resumo__linha dd { flex-shrink: 0; }
/* ⚠️ O DESCONTO SOBE PARA O TOM CHEIO, e e a unica linha do resumo que faz
   isso alem do total. Ele e a unica que a pessoa CONQUISTOU, e num site sem
   cor de estado (o Bruno decidiu preto e branco, entao nao existe verde de
   "voce economizou") quem carrega o significado e o valor de cinza.

   ⚠️ E ELE NAO GANHA COR NENHUMA POR ISSO. Um verde aqui seria a primeira cor
   do site inteiro, e ela apareceria justamente no lugar onde toda loja grita.
   O sinal e o menos na frente do numero e o tom da linha. */
.resumo__linha--desconto { color: var(--paper); }
.resumo__linha--total {
  margin-top: var(--s3); padding-top: var(--s3);
  border-top: 1px solid var(--fio);
  font-size: var(--fs-body); font-weight: var(--peso-forte);
  color: var(--paper);
  letter-spacing: var(--tk-nome);
}
/* ------------------------------------------------------------
   A ACAO NO LUGAR DO VALOR
   Enquanto o destino nao fechou, a linha da entrega nao carrega numero: ela
   carrega o gesto que fecha a pendencia, e a linha do TOTAL nao existe. O
   porque esta na `js/ui.js`, em cima da `resumoHTML()`.
   ------------------------------------------------------------ */
.resumo__linha--acao { align-items: center; }
/* ⚠️ ELA NAO E UM BOTAO COM MOLDURA, e isso e decisao e nao economia: o unico
   primario deste rodape e o que leva a compra adiante, e uma segunda caixa
   desenhada aqui disputaria o olho com ele (um primario por momento). O que
   ela veste e a gramatica de link do resto do site — tom cheio e fio embaixo.

   ⚠️ E O RESET E OBRIGATORIO. O `base.css` so herda a fonte e a cor; fundo,
   moldura e `appearance` continuam os do sistema, e sem isto a linha do resumo
   ganharia uma caixa cinza no meio dela. Foi o defeito que a `.pais-linha` teve
   em 8/ago, e ele volta em todo `<button>` que nasce fora dos `.btn`. */
.resumo__acao {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: 0;
  color: var(--paper); cursor: pointer; text-align: right;
  /* O sublinhado e `text-decoration` e nao `border-bottom` de proposito: com
     borda, o padding do alvo empurraria o fio para longe da letra. */
  text-decoration: underline; text-underline-offset: 4px;
  text-decoration-thickness: 1px; text-decoration-color: var(--fio-vivo);
  /* O alvo cresce nos dois sentidos e a margem negativa devolve o espaco, entao
     o ritmo das linhas do resumo fica exatamente como estava.

     ⚠️ E O `padding-inline: 0` NAO E ENFEITE. O `<button>` nasce com
     `padding: 1px 6px` do navegador, e `appearance: none` NAO tira isso. A
     caixa do botao alinhava certo com o `R$ 258,00` de cima, mas a LETRA (e o
     sublinhado junto com ela) parava 6px antes — a coluna da direita ficava
     torta numa linha so. Medido na tela: `conteudoRight` 6px menor que o das
     linhas vizinhas. Vale para todo `<button>` que entra numa coluna alinhada
     a direita. */
  padding-inline: 0;
  padding-block: var(--s3); margin-block: calc(var(--s3) * -1);
}
.resumo__acao:hover, .resumo__acao:focus-visible { text-decoration-color: var(--paper); }

/* A ULTIMA LINHA DA CAIXA, E ELA E SEMPRE SOBRE A ENTREGA.
   Uma vaga so, duas frases que se revezam: com o destino aberto ela avisa que o
   total esta parcial; com o destino fechado ela diz quando a peca chega. As
   duas nunca coexistem — quem decide e a `resumoHTML()` na `js/ui.js`, e o
   porque de o prazo ter vindo parar aqui esta escrito la em cima dela.

   O tom e o piso (`--paper-miudo`) porque nenhuma das duas disputa com o total:
   quem decide a compra e o numero, e estas duas frases sao o que tira a duvida
   depois que o numero ja convenceu. */
.resumo__nota { margin-top: var(--s3); font-size: var(--fs-sm); color: var(--paper-miudo); }
/* ⚠️ E ELA NAO TEM ICONE, e a ausencia e decisao de 9/ago e nao esquecimento.
   Uma caixa de entrega foi desenhada para a frente da frase do prazo, medida
   (11px de extensao, 1,21x a cap height da letra vizinha) e provada nas cinco
   linguas. O Bruno recusou pela regua do docs/DESIGN.md 11.5: icone que nao
   leva a lugar nenhum nao entra. A linha da recusa esta la, com o desenho
   descrito, e e ela que evita a proposta voltar daqui a tres meses. */

/* ------------------------------------------------------------
   QUANTIDADE
   Alvo de 44 em cada lado, inclusive na lixeira (docs/FLUXO.md 6).
   ------------------------------------------------------------ */
.quantidade { display: inline-flex; align-items: center; border: 1px solid var(--fio-vivo); }
.quantidade__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--alvo); height: var(--alvo);
  background: transparent; border: 0; cursor: pointer;
  color: var(--paper); font-size: var(--fs-body); line-height: 1;
  transition: background var(--transicao), color var(--transicao);
}
.quantidade__btn:disabled { color: var(--paper-miudo); cursor: not-allowed; }
.quantidade__n {
  min-width: 32px; text-align: center;
  font-size: var(--fs-sm); font-weight: var(--peso-forte);
  font-variant-numeric: tabular-nums;   /* o numero nao muda de largura de 1
                                           para 2, entao os botoes nao andam */
}
.tirar {
  display: inline-flex; align-items: center;
  min-height: var(--alvo); padding-inline: var(--s2);
  background: transparent; border: 0; cursor: pointer;
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
  transition: color var(--transicao);
}
/* hover de .fechar, .tirar e .quantidade__btn: movimento.css */

/* ------------------------------------------------------------
   BLOCOS DE APOIO
   ------------------------------------------------------------ */
/* Marcador do que ainda NAO EXISTE. A classe sai do HTML quando o texto real
   entrar. Ela existe para um buraco de conteudo nunca subir em silencio:
   a origem da marca e o unico texto que ninguem escreve no lugar do Bruno
   (MARCA.md 19.1), e ela precisa gritar enquanto estiver faltando. */
.rascunho { border-left: 2px solid var(--fio-vivo); padding-left: var(--s4); }
/* O marcador e um elemento de verdade, com chave no dicionario, e nao um
   ::before com attr(): texto de interface escrito no HTML e exatamente o que
   o portao de idiomas do montar.sh nao consegue conferir. */
.rascunho__marca {
  display: block; margin-bottom: var(--s3);
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
}
/* Dentro do bloco claro o marcador inverte junto. */
.faixa--claro .rascunho { border-left-color: var(--fio-claro-vivo); }
.faixa--claro .rascunho__marca { color: var(--ink-apoio); }

/* ------------------------------------------------------------
   A PORTA DO IDIOMA, E O PAINEL QUE ELA ABRE  (6 de agosto)
   ------------------------------------------------------------
   Substitui a fileira de siglas que morava no `base.css`. O porque de
   existir uma porta em vez de quatro links, e o porque de a bandeira ter
   voltado depois de o site recusa-la duas vezes por escrito, estao no
   `js/idioma-painel.js`, em cima.

   ⚠️ A COR DAS BANDEIRAS E A PRIMEIRA COR DA INTERFACE, e ela e excecao
   declarada, nao brecha. Vale a mesma leitura da emenda de 6/ago do
   `DESIGN.md §1`, que separou INTERFACE de FOTOGRAFIA: a bandeira de um
   pais e do pais, como a cor de uma foto e do mundo. O `tokens.css` nao
   ganhou uma linha por causa disto, e nada mais no site fica colorido.

   A contencao e geometrica, e por isso ela e conferivel: a bandeira NUNCA
   e maior que a letra ao lado (18x12 na barra, 24x16 no painel), e sempre
   tem a sigla ou o nome da lingua do lado. Cor pequena e acompanhada nao
   compete com o CTA primario; foi exatamente isso que a caixa branca do
   `PT` fazia errado antes do redesenho, puxando o olho antes do botao
   "Ver as pecas" (FUNDACAO.md §10: um CTA primario por momento).
   ------------------------------------------------------------ */
.idioma-porta {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: var(--alvo); padding: 0 var(--s2);
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: .08em;
  color: var(--paper-miudo);
  background: none; border: 0; border-radius: var(--raio);
  cursor: pointer;
  transition: color var(--transicao);
}
.idioma-porta__sigla { line-height: 1; }

/* ⚠️ A MOLDURA NAO E ENFEITE, E O MOTIVO E MEDIDO: o preto da bandeira da
   Alemanha e #000000 e o fundo do site e #0a0a0a, que dao 1,03:1 entre si.
   Sem ela, a faixa de cima da bandeira alema simplesmente nao existe na
   tela, e a bandeira chega com um terco faltando. A secao 2 da
   `_medir-bandeira.html` existe so para provar isto.

   ============================================================
   ⚠️ `box-sizing: content-box`, E ELE E O CONSERTO DE UM DEFEITO QUE O
   BRUNO PEGOU OLHANDO, em 6/ago: "no lado esquerdo e direito das bandeiras
   existe um espacamento que nao esta preenchido".

   Ele estava certo, e a causa e uma corrente de tres elos:

     1. o site inteiro roda em `box-sizing: border-box`, entao o `width`
        INCLUI a moldura de 1px de cada lado;
     2. com 18x12 declarados, a area de imagem virava 16x10, cuja proporcao
        e 1,600, e nao os 1,500 do viewBox 24x16 do arquivo;
     3. o `preserveAspectRatio` do SVG e `xMidYMid meet` por padrao, entao o
        desenho encaixa pela ALTURA, fica com 15x10 e centraliza.

   Resultado: 0,5px transparente de cada lado, entre o desenho e a moldura.
   Meio pixel, invisivel em captura e visivel no olho de quem procurou.

   `content-box` faz o `width` valer para a IMAGEM, e a moldura passa a
   somar por fora. A area de imagem volta a ser 3:2 exato e o desenho
   preenche a moldura inteira, que era o que a moldura sempre prometeu.

   ============================================================
   O TAMANHO, E ELE MUDOU JUNTO, por uma medicao do mesmo dia.

   A regra escrita aqui sempre foi "a bandeira nunca e maior que a letra ao
   lado". Ela foi escrita supondo que 12px de bandeira igualassem 12px de
   fonte. NAO IGUALAM: a sigla e Archivo 12px em peso 600, e a altura real
   das maiusculas dela e 8,23px. A bandeira de 12px era 1,46x a letra, ou
   seja, a propria regra estava sendo quebrada pelo numero que a escreveu.

   As duas medidas passaram a sair da CAP HEIGHT do texto ao lado, e as duas
   guardam a MESMA razao, que e o que faz a porta e o painel lerem como um
   sistema so:

       porta    sigla 12px  ->  cap 8,23px  ->  bandeira 15x10  =  1,21x
       painel   nome 16px   ->  cap 11,57px ->  bandeira 21x14  =  1,21x

   Os dois sao multiplos inteiros de 3:2 (5x e 7x), entao a proporcao fecha
   sem fracao e a coordenada continua inteira, que e a regra 6 da linguagem
   de icone aplicada a um desenho que nao e icone.
   ============================================================ */
.idioma-porta__bandeira,
.idioma-linha__bandeira {
  display: block; flex: none;
  box-sizing: content-box;
  border: 1px solid var(--fio-vivo);
  border-radius: 0;
}
.idioma-porta__bandeira { width: 15px; height: 10px; }
.idioma-linha__bandeira { width: 21px; height: 14px; }

/* O mesmo chevron do `.link-seta` (base.css:232): duas bordas de 1,5px
   giradas 45 graus. Aqui ele aponta para BAIXO, que e para onde o painel
   desce. Nao ha um segundo desenho de seta no site. */
.idioma-porta__chevron {
  width: 6px; height: 6px; margin-left: -2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--transicao);
}

/* ---- O PAINEL ----
   Encosta em CIMA e a DIREITA, embaixo da propria porta. O eixo nao e
   escolha de gosto: o `DESIGN.md §6.10` ja diz que a camada entra pela
   borda em que mora, e esta mora no canto superior direito. */
.painel-idioma {
  padding: 0; border: 1px solid var(--fio); border-radius: var(--raio);
  background: var(--ink); color: var(--paper);
  width: min(320px, calc(100% - var(--s4) * 2));
  /* ⚠️ ELE DESCE DA PORTA, e nao da borda da janela. As duas medidas sao
     escritas pelo `js/idioma-painel.js` na hora de abrir, a partir de onde a
     porta esta de verdade. Os valores de reserva servem a um caso so: se o
     painel for aberto sem porta (por codigo), ele ainda encosta no canto.

     Por que MEDIR em vez de usar `--altura-topo`: aquele token e a altura do
     cabecalho sozinho (72px), e acima dele mora a barra de aviso, que nem
     toda pagina tem. Uma conta fixa acertaria a home e erraria o resto, e o
     erro seria um painel flutuando sobre a marca.

     `auto` nos dois lados que empurram. Os zeros que sairam daqui tambem
     tiravam o centramento que o navegador da de fabrica ao dialogo, e as
     margens de cima e da direita seguem fazendo isso.

     ⚠️ O `max()` E CINTO E SUSPENSORIO, e o suspensorio ja salvou uma vez.
     O `js/idioma-painel.js` tambem poda as duas medidas em zero, e o porque
     esta escrito la: com `innerWidth` valendo 0, a conta da direita vira
     negativa, e margem negativa nao desloca o painel, ela ALARGA a caixa,
     estoura o `calc(100% - …)` da largura e colapsa o painel inteiro para os
     2px das proprias bordas. Este `max()` faz o CSS recusar o numero ruim
     mesmo que um dia alguem mexa no JavaScript e tire a poda de la. Custa
     nada e o defeito que ele barra e invisivel ate acontecer. */
  margin: max(0px, var(--de-cima, var(--s3))) max(0px, var(--da-direita, var(--s3))) auto auto;
  max-height: max(120px, calc(100% - var(--de-cima, var(--s3)) - var(--s4)));
  overflow: hidden;
  flex-direction: column;
}
.painel-idioma[open] { display: flex; }

.painel-idioma__cabeca {
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--fio);
}
.painel-idioma__titulo {
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
}
/* O foco vai para o titulo ao abrir, e sem isto o navegador desenha um anel
   em volta de um texto que nao e clicavel. O anel dos controles fica. */
.painel-idioma__titulo:focus { outline: none; }

.painel-idioma__lista { list-style: none; margin: 0; padding: 0; overflow-y: auto; }

/* A LINHA. A bandeira acha, o nome diz, a sigla confirma.
   O nome da lingua vem escrito NELA MESMA (Deutsch, e nao Alemao), porque
   quem procura a propria lingua numa lista procura a palavra que conhece. */
.idioma-linha {
  display: flex; align-items: center; gap: var(--s3);
  min-height: var(--alvo); padding: var(--s2) var(--s4);
  color: var(--paper-miudo);
  border-bottom: 1px solid var(--fio);
  transition: color var(--transicao), background-color var(--transicao);
}
.painel-idioma__lista li:last-child .idioma-linha { border-bottom: 0; }
.idioma-linha__nome { flex: 1 1 auto; }
.idioma-linha__sigla {
  flex: none;
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: .08em;
  color: var(--paper-miudo);
}
/* O idioma de agora ganha a cor cheia, que e o mesmo tratamento que o `PT`
   ativo tinha na fileira antiga. Sem superficie clara: ela e do CTA. */
.idioma-linha[aria-current="true"] { color: var(--paper); }
.idioma-linha[aria-current="true"] .idioma-linha__sigla { color: var(--paper); }
/* hover: movimento.css */

/* O aperto do celular. A outra metade dele (o `gap` do grupo da direita)
   mora no `base.css`, junto do `.topo__direita`, e la esta a conta inteira
   de por que os dois existem.

   O padding da DIREITA sai porque a porta e o ultimo item da barra e ja tem
   a calha do cabecalho como respiro; o da esquerda fica, para a bandeira nao
   colar no icone da conta. O alvo de toque nao muda: a altura continua em
   44px e a largura vai a 64px, bem acima do minimo. */
@media (max-width: 480px) {
  .idioma-porta { padding-right: 0; }
}

/* ============================================================
   O PAIS  ·  A ESTRELA, O DDI E O SELETOR   (8 de agosto)
   ------------------------------------------------------------
   Tres pecas que nasceram juntas porque respondem a mesma pergunta do
   `js/paises.js`: de que pais e esta pessoa. O raciocinio de cada uma esta
   no arquivo que a desenha; aqui ficam so as medidas.
   ============================================================ */

/* ---- A ESTRELA ----
   ⚠️ ELA E BRANCA, E NAO VERMELHA. A referencia que o Bruno mandou (a tela
   "Complete your account" da Arc'teryx) usa vermelho, e aquilo esta certo la:
   a tela dela e branca e o vermelho e a unica marca da pagina.

   Aqui ele seria a PRIMEIRA COR da interface. O `DESIGN.md §1` fecha a
   paleta em preto e branco, e a unica excecao ja aberta esta escrita no
   `publicar/desenhar-bandeiras.mjs` — a cor de uma bandeira e do pais, como
   a cor de uma fotografia e do mundo. Um asterisco nao e nem uma coisa nem
   outra: e interface.

   O que substitui o vermelho e o que este sistema tem de sobra: o rotulo vive
   em `--paper-miudo` por causa do `.campo__rotulo`, e a estrela sobe para
   `--paper` cheio. Sao 5,66:1 contra 14,4:1 lado a lado, na mesma palavra. O
   `margin-left` de 2px e o vao optico: colada, ela vira parte da ultima letra.

   O `aria-hidden` esta no HTML (`js/formulario.js`), e o `required` do
   `<input>` e quem avisa quem nao ve a tela. */
.campo__estrela {
  margin-left: 2px;
  color: var(--paper);
  font-weight: var(--peso-forte);
}

/* ---- O DDI COLADO NO TELEFONE ----
   Uma caixa so partida em duas, e nao dois campos. O `+55` nao e digitavel:
   quem o troca e o campo de pais. Por isso ele nao tem borda propria — a
   borda e do conjunto, e o fio de 1px entre as duas metades e o que diz que
   sao duas metades.

   ⚠️ O `flex: none` MAIS O `min-width` SAO O QUE SEGURAM O `+595`. Sem eles a
   caixinha encolhe conforme o numero de digitos do DDI, e a caixa de digitar
   muda de largura ao trocar de pais — layout pulando, que a `FUNDACAO.md 10`
   recusa. 3,5ch cabe de `+1` a `+595` sem folga sobrando no menor. */
.campo__comDdi { display: flex; align-items: stretch; }
.campo__ddi {
  flex: none;
  display: flex; align-items: center; justify-content: center;
  min-width: 3.5ch;
  padding-inline: var(--s3);
  background: var(--graph);
  color: var(--paper-corpo);
  border: 1px solid var(--fio-vivo);
  border-right: 0;
  font-size: var(--fs-body);
  font-variant-numeric: tabular-nums;
}
/* A caixa de digitar perde o canto da esquerda para o conjunto ficar um so.
   Com `--raio: 0` isto nao muda um pixel hoje; existe para o dia em que o
   raio deixar de ser zero, porque nesse dia ninguem lembraria de vir aqui. */
.campo__comDdi .campo__caixa { border-start-start-radius: 0; border-end-start-radius: 0; }

/* ---- A PORTA DO PAIS ----
   Ela e um `<button>` vestido de campo: mesma altura, mesma borda, mesmo
   fundo. O porque de nao ser um `<select>` esta escrito por extenso no
   `js/formulario.js`, e o resumo e uma linha: `<option>` nao aceita imagem. */
.campo-pais {
  display: flex; align-items: center; gap: var(--s3);
  text-align: left;
}
.campo-pais__nome { flex: 1 1 auto; }
.campo-pais__bandeira,
.pais-linha__bandeira {
  display: block; flex: none;
  box-sizing: content-box;
  width: 21px; height: 14px;
  border: 1px solid var(--fio-vivo);
  border-radius: 0;
}
/* O mesmo chevron do `.idioma-porta__chevron`, e nao um segundo desenho de
   seta: duas bordas de 1,5px giradas 45 graus, apontando para baixo. */
.campo-pais__chevron {
  flex: none;
  width: 6px; height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}
.campo-pais[aria-expanded="true"] .campo-pais__chevron { transform: translateY(1px) rotate(-135deg); }

/* ---- O PAINEL ----
   ⚠️ ELE E CENTRADO, E O DE IDIOMA NAO. A diferenca nao e de gosto: a porta do
   idioma mora num canto fixo da barra, entao a camada desce dela (regra do
   `DESIGN.md §6.10`, a camada entra pela borda em que mora). O campo de pais
   mora no meio de um formulario que rola, e ancorar nele poria o painel meio
   fora da tela em metade das posicoes. Sem ancora, o centro e a unica posicao
   que nao depende de onde o campo esta.

   Por isso aqui NAO existem `--de-cima` e `--da-direita`: as margens de
   fabrica do `<dialog>` ja centram, e sobrescreve-las e que tirava o
   centramento la. */
.painel-pais {
  padding: 0; border: 1px solid var(--fio); border-radius: var(--raio);
  background: var(--ink); color: var(--paper);
  width: min(360px, calc(100% - var(--s4) * 2));
  max-height: min(70vh, 560px);
  overflow: hidden;
  flex-direction: column;
}
.painel-pais[open] { display: flex; }

.painel-pais__cabeca {
  --tinta-fechar: 10px;
  flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--fio);
}
.painel-pais__titulo {
  font-size: var(--fs-micro); font-weight: var(--peso-forte);
  letter-spacing: var(--tk-rotulo); text-transform: uppercase;
  color: var(--paper-miudo);
}
/* ⚠️ `overscroll-behavior: contain` E O CONSERTO DE UM DEFEITO DE CELULAR:
   sem ele, chegar ao fim da lista de vinte e continuar arrastando rola a
   PAGINA atras do painel, e a pessoa fecha o painel achando que travou. */
.painel-pais__lista {
  list-style: none; margin: 0; padding: 0;
  overflow-y: auto; overscroll-behavior: contain;
}

/* ⚠️ O `background` E O `border: 0` NAO SAO ENFEITE: SEM ELES A LISTA INTEIRA
   NASCE PARECENDO SELECIONADA, e foi assim que ela subiu em 8/ago.

   Esta linha foi copiada do `.idioma-linha`, que e um `<a>`. `<a>` nao tem
   folha de fabrica; `<button>` tem. O navegador desenhava `ButtonFace` de
   fundo e `2px outset` de borda, e como a unica borda que esta regra
   reescrevia era a DE BAIXO, sobravam tres lados de moldura clara em volta de
   um retangulo cinza. MEDIDO na tela, com a lista aberta: fundo
   `rgb(107,107,107)`, borda `2px outset rgb(255,255,255)`.

   O estrago nao e de acabamento, e de SIGNIFICADO. Superficie clara neste site
   quer dizer "marcado" (e o `.rotulo--marcado`, o chip de tamanho, o contador
   da sacola). Vinte linhas claras diziam vinte paises marcados ao mesmo tempo,
   e apagavam o unico sinal que a lista tem para dizer qual e o de agora: o
   `aria-current`, que so muda a COR DA LETRA e nao tem como vencer um fundo.

   Todo `<button>` deste arquivo carrega este reset — `.idioma-porta`,
   `.busca-abrir`, `.fechar`, `.quantidade__btn`. Este era o unico que nao. */
.pais-linha {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  min-height: var(--alvo); padding: var(--s2) var(--s4);
  background: transparent;
  color: var(--paper-miudo);
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--fio);
  cursor: pointer;
  transition: color var(--transicao), background-color var(--transicao);
}
.painel-pais__lista li:last-child .pais-linha { border-bottom: 0; }

/* ⚠️ O ANEL DE FOCO VAI PARA DENTRO, e o motivo e geometrico: a linha ocupa a
   largura inteira da lista, e a lista rola (`overflow-y: auto`, que faz o
   navegador tratar o eixo x como `auto` tambem). Com os `+3px` de fabrica do
   `base.css` o anel nasce 5px FORA da linha nos dois lados e a lista o corta:
   quem atravessa os vinte paises pelo teclado ve meio anel. Para dentro ele
   aparece inteiro, com a mesma espessura e a mesma cor. */
.pais-linha:focus-visible { outline-offset: -3px; }
.pais-linha__nome { flex: 1 1 auto; }
.pais-linha__ddi {
  flex: none;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--paper-miudo);
}
/* O pais de agora ganha a cor cheia, exatamente como o idioma de agora no
   outro painel. Sem superficie clara: ela e do CTA. */
.pais-linha[aria-current="true"] { color: var(--paper); }
.pais-linha[aria-current="true"] .pais-linha__ddi { color: var(--paper); }
/* hover: movimento.css */
