/* Loja de resgate de pontos — composição
   =========================================================================
   Este arquivo NÃO define token. Ele compõe a casca (barra da marca, barra
   de utilidades, faixa de categorias, rodapé) e as peças que só existem
   nesta jornada: cartão de produto, cartão de gift card, carrossel, linha
   de carrinho, cartão de conta a pagar.

   MEDIDAS, e de onde vieram
   Lidas dos <rect> de `assets/telas/desktop/Desktop - 1.0.svg`:
     - conteúdo centrado em 1440 com margem de 44 → faixa útil de 1352;
       aqui vira `--loja-max: 84.5rem` (1352) com respiro de 1.5rem;
     - barra da marca com 96 de altura, faixa de utilidades com 36,
       faixa azul de categorias com 36 (o `translate(0 180)` do arquivo);
     - cartão de produto com 132 de largura de imagem e vão de 22 na
       vitrine; aqui a vitrine é fluida e o cartão tem mínimo de 11.5rem,
       porque a tela desktop do arquivo é de largura fixa e a loja não é;
     - carrinho: subtotal 32.000, frete 200, total 32.200 — a régua da
       aritmética está em `dados.js`, não aqui.

   ORDEM DAS SEÇÕES
   1. base   2. casca   3. vitrine   4. produto   5. gift card
   6. carrinho e checkout   7. contas a pagar   8. rodapé   9. telefone
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

/* =========================================================================
   1. Base
   ========================================================================= */

body {
  margin: 0;
  background-color: var(--surface-page);
  color: var(--text-body);
  font-family: var(--family-ui);
  font-size: var(--text-body-size);
  line-height: var(--text-body-line);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; }

/* Alguns componentes do sistema declaram `display` na própria classe, e um
   `display: flex` vence o `display: none` que o atributo `hidden` traz por
   padrão do navegador. Sem esta linha, o contador do carrinho aparece
   marcando zero mesmo escondido. */
[hidden] { display: none !important; }

.sr-somente {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* O atalho de teclado só aparece quando recebe foco. Sem ele, chegar ao
   conteúdo desta loja custa dezoito tabulações — a barra de utilidades e a
   faixa de categorias vêm antes de tudo. */
.pular {
  position: absolute; inset-block-start: -3rem; inset-inline-start: var(--unit-200);
  z-index: var(--level-tooltip);
  padding: var(--unit-100) var(--unit-200);
  background-color: var(--surface-raised);
  color: var(--link-color);
  border-radius: var(--border-50);
  box-shadow: var(--shadow-overlay);
  transition: inset-block-start 120ms ease;
}
.pular:focus-visible { inset-block-start: var(--unit-100); }

.loja { min-height: 100vh; display: flex; flex-direction: column; }

/* A faixa útil. Uma classe só, usada por toda seção, para que a coluna do
   cabeçalho e a do conteúdo nunca saiam de registro. */
.faixa {
  width: 100%;
  max-width: 84.5rem;      /* 1352 — do rect do arquivo */
  margin-inline: auto;
  padding-inline: var(--unit-300);
}

.loja__conteudo { flex: 1; padding-block: var(--unit-300) var(--unit-600); }

/* Título de seção da vitrine — "Mais vendidos", "Lojas Parceiras".
   O arquivo escreve em 20 bold na cor da marca. */
.secao { margin-block-start: var(--unit-500); }
.secao__topo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--unit-200); margin-block-end: var(--unit-200);
}
.secao__titulo {
  margin: 0;
  font-size: var(--heading-sm-size);
  line-height: var(--heading-sm-line);
  font-weight: var(--weight-bold);
  color: var(--brand-primary-bold);
}

/* =========================================================================
   2. Casca
   ========================================================================= */

/* --- barra da marca ----------------------------------------------------- */

.topo {
  position: sticky; inset-block-start: 0;
  z-index: var(--level-nav);
  background-color: var(--surface-raised);
  box-shadow: inset 0 -1px 0 0 var(--border-subtle);
}

/* A linha da marca em três blocos, arranjados por breakpoint:

     hd e fullhd   [ início ][ busca ··········· ][ fim ]
     tablet        [ início ················ ][ fim ]
                   [ busca ························· ]
     mobile        os blocos se desfazem (display: contents) e valem as
                   regras de telefone, peça a peça.

   Entre os blocos, 16. A busca é a coluna elástica: ela ganha o que sobra. */
.topo__linha {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "inicio busca fim";
  align-items: center;
  column-gap: var(--unit-200);
  min-height: 6rem;                 /* 96 — do rect do arquivo */
  padding-block: var(--unit-150);
}
.topo__bloco { display: flex; align-items: center; gap: var(--unit-200); min-width: 0; }
.topo__bloco--inicio { grid-area: inicio; justify-content: flex-start; }
.topo__bloco--fim { grid-area: fim; justify-content: flex-end; }
.topo__linha > .topo__busca { grid-area: busca; }

/* breakpoint.tablet — e o começo do hd, até 1100: início ao lado do fim,
   busca embaixo na largura toda. Até 1100 porque em linha única o campo da
   busca media 48px em 980; a linha só dá a ele uma largura útil a partir daí
   (168 em 1100). O prefixo `.topo` vence as regras do telefone (até 900),
   que vêm depois no arquivo e se sobrepõem de 768 a 900. */
@media (min-width: 48rem) and (max-width: 68.75rem) {
  .topo .topo__linha {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "inicio fim" "busca busca";
    row-gap: var(--unit-150);
  }
  .topo .topo__bloco--fim .saldo { flex-basis: auto; order: 0; }
  .topo .topo__busca { min-width: 0; }

  /* O menu do endereço volta a abrir preso ao botão, como no desktop. A
     regra do telefone (até 900) o esticava na largura da linha: medido, 853px
     de lista em 900, contra 320 em 979 — dois menus diferentes no mesmo
     breakpoint. */
  .topo .previa--endereco { position: relative; }
  .topo .previa--endereco .sysvc-popup__surface,
  .topo .previa--endereco .sysvc-popup__surface[data-align="end"] {
    inset-inline: 0 auto;
    inset-block-start: calc(100% + var(--popup-gap));
    /* Largura explícita: sem ela o menu se encolhia à largura do botão e
       abria com 178px entre 768 e 900. */
    inline-size: min(var(--popup-max-inline), calc(100vw - var(--unit-400)));
    min-inline-size: 0;
    max-inline-size: none;
  }

  /* O rótulo do endereço aparece no tablet inteiro. A regra do telefone
     (até 900) o escondia de 768 a 900, e o botão virava só ícone no meio do
     mesmo breakpoint em que, em 979, mostra a rua e o CEP. */
  .topo .topo__endereco-rotulo {
    position: static; width: auto; height: auto;
    clip-path: none;
  }
}

/* breakpoint.mobile: sem blocos. */
@media (max-width: 47.9375rem) {
  .topo .topo__linha { display: flex; }
  .topo .topo__bloco { display: contents; }
}

/* A marca é o link para o início, mas o desenho dela tem 20 de altura. O
   alvo vem do bloco, como no sistema: 44 no ponteiro, 48 no toque. */
.topo__marca { display: flex; align-items: center; flex: none; min-block-size: 2.75rem; }
/* 20 de altura em todos os tamanhos: uma marca só, do telefone ao fullhd. */
.topo__marca img { display: block; height: 1.25rem; width: auto; }

/* A busca ocupa o vão do meio. O campo é o do sistema; o botão BUSCAR é o
   `filled`, encostado nele. */
/* Sem o botão ao lado, o formulário é o campo: o vão não separa mais nada. */
.topo__busca { flex: 1; min-width: 12rem; display: flex; }
.topo__busca .sysvc-field { flex: 1; }

/* O saldo. O arquivo desenha uma pílula com contorno azul, o rótulo
   "Saldo", o número em magenta e um "Fechar" à direita.
   DIVERGÊNCIA REGISTRADA: o magenta é `brand.tertiary`, reservado a campanha
   e selo — saldo é dado de sistema. Aqui o número usa `brand.primary.bold`.
   O magenta continua na loja, mas só no selo de campanha. */
.saldo {
  display: inline-flex; align-items: center; gap: var(--unit-100);
  padding: var(--unit-50) var(--unit-100) var(--unit-50) var(--unit-150);
  border-radius: var(--border-full);
  background-color: var(--surface-raised);
  box-shadow: inset 0 0 0 1px var(--brand-primary-default);
  flex: none;
}
.saldo__icone { width: 1.25rem; height: 1.25rem; color: var(--brand-primary-default); }
.saldo__rotulo {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle);
}
/* `min-inline-size` medido contra "98.750c$", o maior valor que o saldo
   deste protótipo assume. Sem ele a pílula encolhe ao ocultar e empurra os
   três ícones ao lado — um interruptor que move o que está em volta é um
   interruptor que se erra na segunda vez. */
.saldo__valor {
  font-size: var(--text-body-size); line-height: var(--text-body-line);
  font-weight: var(--weight-bold); color: var(--brand-primary-bold);
  font-variant-numeric: tabular-nums;
  min-inline-size: 4.75rem;
  text-align: end;
}

/* A máscara. Cinco marcadores fixos: a quantidade de dígitos também diz algo
   sobre o saldo, então ela não é reproduzida. `letter-spacing` porque os
   marcadores colados viram um borrão em 16 bold. */
.saldo__mascara { letter-spacing: .12em; }

/* O olho. Icon Button do sistema, compacto, sem desenho novo — só o encaixe
   na pílula, que é apertada. */
/* O olho fica CONCÊNTRICO ao arco da pílula: pílula de 48 (raio 24), disco
   de 40 (raio 20), 4 de folga em cima, embaixo e à direita. A margem
   negativa de antes encostava o disco na borda, e no hover ele passava da
   moldura. */
.saldo__olho { flex: none; }
.topo .saldo { padding-inline-end: var(--unit-50); }
.saldo__unidade { font-size: var(--text-caption-size); font-weight: var(--weight-bold); }

/* Encostado no FIM. No telefone a coluna dos ícones é a do saldo, que é
   mais larga que os três discos: esticado e alinhado à esquerda, o grupo
   deixava 12px mortos entre o último ícone e a margem de 16, e o cabeçalho
   parecia recuado só desse lado. */
.topo__conta { display: flex; align-items: center; justify-content: flex-end; gap: var(--unit-50); flex: none; }

/* O endereço mora ao lado da marca: é a primeira coisa que decide se um
   produto chega, e ninguém procura isso no meio das categorias. */
.topo__endereco {
  display: inline-flex; align-items: center; gap: var(--unit-100);
  flex: none; white-space: nowrap;
  min-height: 2.75rem;
  font-size: var(--text-ui-size); line-height: var(--text-ui-line);
  font-weight: var(--weight-bold);
  color: var(--link-color);
  text-decoration: none;
  border-radius: var(--border-50);
}
.topo__endereco svg { width: 1.25rem; height: 1.25rem; flex: none; }
.topo__endereco:hover { color: var(--link-color-hovered); }
.topo__endereco:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }

/* O gatilho é um <button> desde que abre o Popup: fundo, borda e fonte não
   se herdam num controle de formulário. */
button.topo__endereco {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit;
}
/* Com endereço escolhido, o rótulo é "rua · CEP · cidade" e pode ser longo.
   Um teto e reticências: a linha da marca não pode empurrar o saldo. */
.topo__endereco-rotulo {
  max-inline-size: 20rem;
  overflow: hidden; text-overflow: ellipsis;
}

/* Dentro da prévia: a lista e o botão de adicionar respiram entre si. */
.previa__enderecos { margin-block: var(--unit-150); }

/* Rótulo curto — breakpoint.hd e menores (até 1366): a rua sem número e o
   CEP. A forma completa fica no fullhd e no nome acessível. */
.topo__endereco-curto { display: none; }
@media (max-width: 85.375rem) {
  .topo__endereco-completo { display: none; }
  .topo__endereco-curto { display: inline; }
}
.previa__adicionar { inline-size: 100%; justify-content: center; }

/* Adicionar endereço: um formulário de uma coluna de leitura, não a tela
   inteira — seis campos esticados em 1600px viram linhas que ninguém lê. */
.endereco-novo { max-inline-size: 48rem; }
.endereco-novo__apoio {
  margin: var(--unit-100) 0 var(--unit-250);
  font-size: var(--text-body-size); line-height: var(--text-body-line);
  color: var(--text-subtle);
}

/* Entre 901 e 1280, com 144 de margem de cada lado, a linha da marca não
   comporta o rótulo: medido em 980, ele empurrava o saldo e a conta 177px
   para fora da tela. O endereço fica só com o ícone — o rótulo continua
   lido por leitor de tela — e a busca aceita ficar mais estreita. */
@media (min-width: 56.3125rem) and (max-width: 80rem) {
  /* A busca fica na mesma linha. Para caber, a carteira do saldo sai — o
     rótulo "Saldo" continua dizendo o que é o número. */
  .saldo__icone { display: none; }
  .topo__busca { min-width: 0; }
}
.topo__extrato {
  display: block; text-align: center;
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
}


/* --- as três prévias do cabeçalho ---------------------------------------
   A superfície, a sombra, o raio, o título e a mensagem são do Popup. O que
   se compõe aqui é a LINHA de dentro dela.

   A linha foi desenhada para o teto do componente — `--popup-max-inline`,
   que é 20rem —, e não o contrário: arte de 40, nome truncado em uma linha,
   apoio embaixo, valor à direita. Alargar a superfície resolveria o nome
   comprido e criaria uma segunda medida de popup na loja, que é justamente
   o que o sistema evita. */

.previa { display: inline-flex; }

/* Sem `gap` na superfície: o Popup já dá o recuo, e as peças de dentro
   trazem a própria distância — assim uma prévia vazia não fica com um vão
   pendurado embaixo da mensagem. */
.previa__superficie { display: block; }

/* A foto do produto preenche a moldura em que cai — cartão, prévia,
   miniatura, palco e linha do carrinho —, recortada pela própria moldura. */
.foto-produto {
  display: block;
  inline-size: 100%; block-size: 100%;
  object-fit: cover;
}
.produto-cartao__arte, .previa__arte, .produto__miniatura, .produto__palco, .linha-item__arte {
  overflow: hidden;
}

.previa__lista {
  display: grid;
  margin-block-start: var(--unit-150);
}

.previa__linha,
.previa__movimento {
  display: flex; align-items: center; gap: var(--unit-150);
  padding-block: var(--unit-100);
  color: var(--text-body); text-decoration: none;
  border-radius: var(--border-50);
}
.previa__linha + .previa__linha,
.previa__movimento + .previa__movimento {
  box-shadow: inset 0 1px 0 0 var(--border-subtle);
}
.previa__linha:hover { background-color: var(--popup-item-hovered); }
.previa__linha:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 4px var(--border-focus);
}

.previa__arte {
  width: 2.5rem; height: 2.5rem; flex: none;
  border-radius: var(--border-50);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--text-disabled);
  overflow: hidden;
}
.previa__arte svg { width: 1.125rem; height: 1.125rem; }
/* A placa do logotipo do gift card. No cartão ela é centralizada sobre a cor
   da marca; nas molduras pequenas (prévia e carrinho) ocupa a moldura com
   uma borda da cor da marca em volta. */
.gift-logo {
  display: grid; place-items: center;
  box-sizing: border-box;
  aspect-ratio: 1;
  inline-size: clamp(3rem, 32%, 7rem);
  padding: var(--unit-100);
  border-radius: var(--border-100);
  background-color: var(--gift-logo-fundo, var(--surface-raised));
  overflow: hidden;
}
.gift-logo img { display: block; inline-size: 100%; block-size: 100%; object-fit: contain; }
.gift-logo--inicial { color: var(--gift-cor, var(--brand-primary-default)); font-weight: var(--weight-black); }
/* Prefixo por especificidade: a regra base de `.gift-cartao__arte`, que
   alinhava o nome em texto ao início, vem depois no arquivo e vencia —
   medido, a placa ficava 71px à esquerda do centro. */
.gift-cartao .gift-cartao__arte,
.gift-pagina__arte .gift-cartao__arte { justify-items: center; }
.previa__arte-gift .gift-logo,
.linha-item__arte .gift-logo {
  inline-size: 78%;
  padding: var(--unit-50);
  border-radius: var(--border-50);
}

.previa__arte-gift {
  width: 100%; height: 100%;
  display: grid; place-items: center;
  background-color: var(--gift-cor);
  color: var(--gift-cor-texto);
  font-weight: var(--weight-black);
}

/* `min-width: 0` é o que deixa o truncamento acontecer: sem ele o item
   flexível não encolhe abaixo do próprio conteúdo, e o nome empurra o valor
   para fora da superfície. */
.previa__texto { display: grid; gap: var(--unit-25); min-width: 0; flex: 1; }
.previa__nome {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.previa__apoio {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle);
}
.previa__valor { flex: none; }

.previa__resto {
  margin: var(--unit-100) 0 0;
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle);
}

.previa__total {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--unit-200);
  margin-block-start: var(--unit-150);
  padding-block-start: var(--unit-150);
  box-shadow: inset 0 1px 0 0 var(--border-subtle);
  font-size: var(--text-ui-size); line-height: var(--text-ui-line);
}
.previa__total-valor {
  font-weight: var(--weight-bold); color: var(--brand-primary-bold);
  font-variant-numeric: tabular-nums;
}

/* O botão de texto que leva à página inteira. Ocupa a largura e fica na
   ponta: é a saída do popup, e saída se procura na borda. */
/* O recuo lateral é o do Botão (compact), e não zero: sem ele o rótulo e a
   seta encostavam na borda do fundo de hover. */
.previa__ir {
  width: 100%; justify-content: space-between;
  margin-block-start: var(--unit-150);
}

/* --- prévia da conta ----------------------------------------------------- */

.previa__email { margin-block-end: var(--unit-150); }

.previa__saldo {
  display: grid; gap: var(--unit-25);
  padding: var(--unit-150);
  border-radius: var(--border-50);
  background-color: var(--surface-sunken);
}
/* `text.subtle` e não: em 12 sobre superfície AFUNDADA ele dá 4,21:1, e o
   piso é 4,5. É a mesma armadilha que o sistema já registrou no Label — o
   mesmo token passa no branco e reprova aqui, porque o fundo mudou. */
.previa__saldo-rotulo {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-body);
}
.previa__saldo-valor {
  font-size: var(--heading-sm-size); line-height: 1.2;
  font-weight: var(--weight-bold); color: var(--brand-primary-bold);
  font-variant-numeric: tabular-nums;
}

.previa__movimento { align-items: flex-start; }
.previa__movimento-valor {
  flex: none;
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Entrada e saída não se separam só pela cor: o sinal + e − vem no texto,
   e é ele que carrega a informação em preto e branco. */
.previa__movimento-valor[data-sinal="entrada"] { color: var(--alert-success-bold); }
.previa__movimento-valor[data-sinal="saida"] { color: var(--text-body); }


/* A prévia pendurada na faixa de categorias é a mesma do cabeçalho. Só o
   invólucro muda: ele não pode ser `inline-flex` com largura própria, senão
   o item deixa de encolher junto com a faixa quando ela quebra. */
.previa--categoria { display: inline-flex; }
.previa--categoria .sysvc-popup__surface {
  /* O menu é azul; a superfície é branca e precisa de um degrau de sombra
     maior para não parecer colada na faixa. */
  box-shadow: inset 0 0 0 var(--popup-stroke) var(--popup-border), var(--shadow-overlay);
}

/* --- faixa de categorias ------------------------------------------------ */

.categorias {
  background-color: var(--brand-primary-default);
}
/* QUEBRA, e não rolagem — a razão é técnica e não estética.
   `overflow-x: auto` faz o `overflow-y` computar `auto` junto, e os dois
   RECORTAM. Com a faixa rolando, a superfície do popup era cortada na altura
   da barra: sobrava uma tira branca de 44 e nada mais.

   Medido no navegador: os sete itens pedem 1036 numa linha, e a faixa útil
   tem 1352 — cabem com folga. Abaixo de ~1060 a faixa quebra em duas linhas,
   que é o que uma barra de navegação deve fazer quando o espaço acaba. */
.categorias__linha {
  display: flex; align-items: center;
  gap: 0 var(--unit-300);
  min-height: 2.75rem;
}
/* O item é um <button> desde que passou a abrir prévia, e por isso o reset
   local: fonte, fundo e borda não se herdam num controle de formulário. */
.categorias__item {
  display: inline-flex; align-items: center; gap: var(--unit-100);
  flex: none; white-space: nowrap;
  padding: var(--unit-100) 0;
  color: var(--text-negative);
  font-family: inherit;
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold); letter-spacing: .04em; text-transform: uppercase;
  text-decoration: none; border-radius: var(--border-50);
  background: none; border: 0; cursor: pointer;
  /* Alvo de 44 mesmo com o rótulo de 16: a faixa é a navegação principal e
     não pode depender de precisão de ponteiro. */
  min-height: 2.75rem;
}
.categorias__item svg { width: 1.125rem; height: 1.125rem; }
.categorias__item:hover { text-decoration: underline; text-underline-offset: 3px; }
.categorias__item:focus-visible { outline: 2px solid var(--surface-raised); outline-offset: 2px; }
.categorias__item[aria-current="true"] { text-decoration: underline; text-underline-offset: 3px; }
.categorias__item[aria-expanded="true"] { text-decoration: underline; text-underline-offset: 3px; }
.categorias__item[aria-current="page"] { text-decoration: underline; text-underline-offset: 3px; }

/* Os três grupos da faixa. O do meio quebra em linhas quando não cabe; o do
   fim é empurrado para a ponta e nunca quebra ao meio. */
/* Gap de 16, e não 24, entre as categorias: com 24 os oito itens pediam
   1105 e o grupo tem 1054 em 1920 — a faixa quebrava em duas linhas. */
.categorias__principais {
  display: flex; align-items: center; flex-wrap: wrap;
  /* Espaçamento dinâmico: 16 é o MÍNIMO, e é com ele que montarCasca() mede
     quais categorias cabem. A sobra da linha é distribuída entre as que
     ficaram, para o grupo terminar sempre encostado nas lojas. */
  gap: 0 var(--unit-200);
  justify-content: space-between;
  /* Só este grupo quebra. Sem `flex: 1` e `min-width: 0`, a LINHA inteira
     quebrava e mandava as lojas e o boleto para baixo das categorias. */
  flex: 1 1 0; min-width: 0;
}
.categorias__fim {
  display: flex; align-items: center; gap: var(--unit-300);
  flex: none; margin-inline-start: auto;
}
/* "Todas as categorias" é a porta para as demais: um fio separa a porta das
   categorias que ela abre. */
.categorias__todas {
  padding-inline-end: var(--unit-300);
  box-shadow: inset calc(var(--stroke-100) * -1) 0 0 var(--button-surface-negative-disabled);   /* o branco translúcido do sistema sobre a marca */
}
.categorias__boleto { flex: none; }

/* A ação da faixa é TEXT ONLY com ícone, e não o contorno: a faixa já é uma
   barra inteira de marca, e um contorno branco em volta do rótulo desenhava
   uma segunda caixa dentro de uma caixa. Fica o rótulo, o ícone e o vão.
   O estilo continua sendo o `negative` do sistema — é dele que vêm o branco
   do rótulo, o véu de hover e o anel de foco; some só o contorno em repouso,
   que é o que separa um text de um outlined. */
.categorias__acao { box-shadow: none; }
.categorias__acao:hover { box-shadow: none; }
.categorias__acao:active { box-shadow: none; }
/* A ação de gift card é do telefone; no desktop a faixa já tem "Gift card"
   entre as categorias, e dois seriam o mesmo destino duas vezes. */
.categorias__gift { display: none; }

/* Um fio branco separa as categorias do que não é categoria — as lojas e o
   boleto. Branco cheio (text.negative), e não o translúcido da porta: aqui a
   fronteira é entre dois tipos de coisa, e não entre a porta e o que ela abre. */
.categorias__fim {
  padding-inline-start: var(--unit-300);
  box-shadow: inset var(--stroke-100) 0 0 var(--text-negative);
}

/* --- menu de Todas as categorias ----------------------------------------
   Um Popup em duas colunas: a lista, e a prévia da categoria ativa ao lado.
   É a única superfície da loja que passa do teto de 20rem do componente —
   duas colunas não cabem em 20rem, e a prévia ao lado é o que faz o menu
   valer mais que a gaveta. Divergência registrada no README. */
.previa--todas { display: inline-flex; }
.previa--todas .menu-categorias {
  display: grid;
  grid-template-columns: 16rem minmax(0, 1fr);
  column-gap: var(--unit-200);
  inline-size: min(44rem, calc(100vw - var(--unit-400)));
  max-inline-size: none;
  box-shadow: inset 0 0 0 var(--popup-stroke) var(--popup-border), var(--shadow-overlay);
}
.previa--todas .menu-categorias[hidden] { display: none; }
.menu-categorias__lista {
  align-content: start;
  padding-inline-end: var(--unit-200);
  box-shadow: inset calc(var(--stroke-100) * -1) 0 0 var(--border-subtle);
}
.menu-categorias__item--ativo { background-color: var(--popup-item-hovered); }
.menu-categorias__seta { margin-inline-start: auto; }
.menu-categorias__divisor {
  block-size: var(--stroke-100);
  margin-block: var(--unit-100);
  background-color: var(--border-subtle);
}
.menu-categorias__painel { min-inline-size: 0; }

/* Telefone: só a lista. A prévia ao lado não cabe, e tocar num item já leva
   à categoria. */
@media (max-width: 47.9375rem) {
  .previa--todas .menu-categorias { grid-template-columns: minmax(0, 1fr); }
  .menu-categorias__painel, .menu-categorias__seta { display: none; }
  .menu-categorias__lista { padding-inline-end: 0; box-shadow: none; }

  /* Mesmo alinhamento das prévias do cabeçalho: a superfície ancora na
     faixa, e não no botão, e ocupa a largura útil com os 16 do breakpoint
     de cada lado. Presa ao botão ela começava onde o botão começa e ia até
     onde coubesse — nunca nos dois recuos ao mesmo tempo. */
  .categorias .previa--todas { position: static; }
  .categorias .previa--todas .menu-categorias,
  .categorias .previa--todas .menu-categorias[data-align="end"] {
    inset-inline: var(--unit-200);
    inset-block-start: calc(100% + var(--popup-gap));
    inline-size: auto;
    min-inline-size: 0;
    max-inline-size: none;
  }
}

/* --- menu de Lojas parceiras ---------------------------------------------
   Horizontal e da largura da janela. O invólucro do Popup deixa de ser a
   referência (position: static) e a superfície ancora na faixa azul inteira;
   por dentro, a .faixa repete a margem do breakpoint, e as lojas alinham com
   o conteúdo da página. Como a do menu de categorias, passa do teto de 20rem
   do componente — divergência registrada no README. */
.categorias { position: relative; }
.categorias .previa--lojas { position: static; }
.categorias .previa--lojas .menu-lojas,
.categorias .previa--lojas .menu-lojas[data-align="end"] {
  inset-block-start: 100%; inset-block-end: auto;
  inset-inline: 0;
  inline-size: auto; min-inline-size: 0; max-inline-size: none;
  padding: var(--unit-300) 0;
  border-radius: 0;
  box-shadow: inset 0 -1px 0 0 var(--border-subtle), var(--shadow-overlay);
}
.categorias .previa--lojas .menu-lojas[hidden] { display: none; }
/* Uma linha só, sempre: quando as lojas não cabem (no hd estreito), a linha
   rola para o lado em vez de quebrar — horizontal é a disposição do menu. */
.categorias .previa--lojas .menu-lojas__lista {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 7.5rem;
  justify-content: start;
  gap: var(--unit-200);
  overflow-x: auto;
  padding-block: var(--unit-50);
}
.categorias .menu-lojas__item {
  flex-direction: column; justify-content: center; gap: var(--unit-100);
  padding: var(--unit-150) var(--unit-100);
  text-align: center;
}
.menu-lojas__nome { font-weight: var(--weight-bold); }
.categorias .menu-lojas__item:hover .parceiro__disco { box-shadow: inset 0 0 0 2px var(--brand-primary-default); }

/* As categorias que não cabem na linha recebem `hidden` em montarCasca(). */
.categorias__principais > [hidden] { display: none; }

/* Tablet e celular: nenhuma categoria na faixa, só a porta e o boleto. Elas,
   Gift card e Lojas parceiras estão no menu de Todas as categorias. Sem
   categorias ao lado, o fio branco não separa nada e sai. */
@media (max-width: 61.1875rem) {
  .categorias__principais,
  .categorias__fim > .categorias__item,
  .categorias__fim > .previa--lojas { display: none; }
  .categorias__fim { padding-inline-start: 0; box-shadow: none; }
}

/* =========================================================================
   FULL HD — o site inteiro
   =========================================================================
   Os quatro breakpoints do sistema, aplicados ao site inteiro:

     breakpoint.mobile    até 767      margem 16    gutter 8
     breakpoint.tablet    768 – 979    margem 32    gutter 8
     breakpoint.hd        980 – 1366   margem 64    gutter 16
     breakpoint.fullhd    1367 em diante  margem 144  gutter 24

   Cabeçalho, corpo e rodapé correm de ponta a ponta e a margem faz o
   trabalho da caixa — "a margem faz o trabalho de uma caixa", diz a página
   do grid. A antiga caixa centrada de 1352 era uma segunda caixa em cima
   dessa.

   COMO ESTÁ ESCRITO
   Cada faixa de largura só escolhe QUAIS tokens valem, em dois apelidos
   locais — --faixa-margem e --faixa-gutter. As regras de layout leem os
   apelidos e não sabem em que breakpoint estão. Os números são todos do
   sistema; nada aqui define valor. */
@media (min-width: 48rem) and (max-width: 61.1875rem) {
  .loja { --faixa-margem: var(--grid-tablet-margin); --faixa-gutter: var(--grid-tablet-gutter); }
}
@media (min-width: 61.25rem) and (max-width: 85.375rem) {
  .loja { --faixa-margem: var(--grid-hd-margin); --faixa-gutter: var(--grid-hd-gutter); }
}
@media (min-width: 85.4375rem) {
  .loja { --faixa-margem: var(--grid-fullhd-margin); --faixa-gutter: var(--grid-fullhd-gutter); }

  /* Vitrines da página inicial no fullhd — produtos e gift cards: seis por
     vez, cada cartão em 2 de 12 colunas — (100% − 5 gutters) / 6. O gancho da
     tela dá o peso para vencer as regras gerais (3 de 12 e 4 de 12), que vêm
     depois no arquivo. */
  .loja[data-tela="inicio"] .vitrine {
    grid-auto-columns: calc((100% - 5 * var(--faixa-gutter)) / 6);
  }
}

/* Do tablet para cima. A especificidade destes seletores vence o `.faixa`
   de 16 do bloco do telefone, que vem depois no arquivo e se sobrepõe de
   768 a 900. Abaixo de 768 vale aquele: 16, a margem do mobile. */
@media (min-width: 48rem) {
  .topo .faixa,
  #conteudo > .faixa,
  .rodape .faixa {
    max-width: none;
    padding-inline: var(--faixa-margem);
  }
}

@media (min-width: 61.25rem) {
  /* As 12 colunas. A vitrine rola na horizontal, e cada cartão ocupa um
     número INTEIRO de colunas — é o que faz a grade existir de fato, e não
     só como número na documentação:
       produto   3 de 12 → quatro por linha (a nota do fullhd: "nesta tela um
                           cartão de produto ocupa três delas")
       gift card 4 de 12 → três por linha; a arte é retangular e pede mais
     A conta: largura de N colunas = (100% − 11 gutters) / 12 × N + (N − 1)
     gutters, que para N = 3 simplifica em (100% − 3 gutters) / 4. */
  /* Prefixo `.loja` por especificidade: as regras base de `.vitrine` e
     `.parceiros` vêm DEPOIS no arquivo e, com o mesmo peso, venciam —
     medido, o gutter ficava em 16 em todas as larguras. */
  .loja .vitrine {
    gap: var(--faixa-gutter);
    grid-auto-columns: calc((100% - 3 * var(--faixa-gutter)) / 4);
  }
  .loja .vitrine--gift {
    grid-auto-columns: calc((100% - 2 * var(--faixa-gutter)) / 3);
  }
  .loja .parceiros { gap: var(--faixa-gutter); }

}

/* Tablet — breakpoint.tablet: 6 colunas, gutter de 8. O cartão ocupa
   número inteiro de colunas, como no desktop:
     produto   2 de 6 → três por linha: (100% − 2 gutters) / 3
     gift card 3 de 6 → dois por linha: (100% − 1 gutter) / 2 */
@media (min-width: 48rem) and (max-width: 61.1875rem) {
  .loja .vitrine {
    gap: var(--faixa-gutter);
    grid-auto-columns: calc((100% - 2 * var(--faixa-gutter)) / 3);
  }
  .loja .vitrine--gift {
    grid-auto-columns: calc((100% - var(--faixa-gutter)) / 2);
  }
  .loja .parceiros { gap: var(--faixa-gutter); }
}

/* --- trilha ------------------------------------------------------------- */

.trilha { padding-block: var(--unit-200) 0; }

/* =========================================================================
   3. Vitrine
   ========================================================================= */

/* --- carrossel de campanha ---------------------------------------------- */

.campanha { position: relative; margin-block-start: var(--unit-300); }

.campanha__palco {
  position: relative; overflow: hidden;
  border-radius: var(--border-100);
  background-color: var(--surface-sunken);
}

.campanha__slide {
  display: grid; align-content: center; gap: var(--unit-150);
  min-height: 15rem;
  /* O respiro lateral abre espaço para as setas: elas ficam sobre o palco,
     e com o padding de 32 o texto passava por baixo delas. */
  padding: var(--unit-500) var(--unit-1000);
  background: linear-gradient(100deg,
              var(--brand-primary-bold) 0%,
              var(--brand-primary-default) 55%,
              var(--brand-secondary-default) 130%);
  color: var(--text-negative);
}
.campanha__slide[hidden] { display: none; }

/* A imagem da campanha (gerada no Higgsfield, ver README). Ocupa a metade
   direita do palco; um véu com o degradê da marca vai da esquerda opaca até
   transparente, para o texto branco ler sobre qualquer imagem — escura como a
   da Cyber Monday ou clara como a das contas. A imagem é decorativa (`alt`
   vazio): o título e o texto do slide já dizem tudo. */
.campanha__slide { position: relative; isolation: isolate; }
.campanha__imagem {
  position: absolute; inset-block: 0; inset-inline-end: 0;
  inline-size: 60%; block-size: 100%;
  object-fit: cover; object-position: center;
  z-index: -2;
}
.campanha__slide:has(.campanha__imagem)::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg,
              var(--brand-primary-bold) 0%,
              var(--brand-primary-bold) 40%,
              transparent 75%);
}
/* Tablet e celular: a imagem vira fundo do slide inteiro, com o véu cobrindo
   mais — não há metade direita onde ela caiba ao lado do texto. */
@media (max-width: 61.1875rem) {
  .campanha__imagem { inline-size: 100%; }
  .campanha__slide:has(.campanha__imagem)::before {
    background: linear-gradient(90deg,
                var(--brand-primary-bold) 0%,
                var(--brand-primary-bold) 35%,
                transparent 110%);
    opacity: .92;
  }
}

/* O selo é o único lugar da loja em que a terciária entra. Ver §6 de
   `dados.js` e §1 de `sys-vc/CONTEXTO.md`. */
.campanha__selo {
  justify-self: start;
  display: inline-block;
  padding: var(--unit-25) var(--unit-100);
  border-radius: var(--border-50);
  background-color: var(--brand-tertiary-default);
  color: var(--text-negative);
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: .06em;
}
.campanha__titulo {
  margin: 0; color: var(--text-negative);
  font-size: var(--heading-xl-size); line-height: var(--heading-xl-line);
  font-weight: var(--weight-black);
}
.campanha__texto {
  margin: 0; max-width: 34rem; color: var(--text-negative);
  font-size: var(--text-body-size); line-height: var(--text-body-line);
}
.campanha__acao { margin-block-start: var(--unit-100); justify-self: start; }

.campanha__seta {
  position: absolute; inset-block-start: 50%; translate: 0 -50%;
  z-index: 1;
  background-color: var(--surface-raised);
  box-shadow: var(--shadow-overlay);
}
.campanha__seta--antes { inset-inline-start: var(--unit-150); }
.campanha__seta--depois { inset-inline-end: var(--unit-150); }

.campanha__pontos { display: flex; justify-content: center; margin-block-start: var(--unit-150); }

/* --- grade de produtos --------------------------------------------------- */

/* O carrossel de produtos do arquivo rola na horizontal e mostra 4,5
   cartões. Aqui a mesma lista é uma FAIXA ROLÁVEL em telas largas e uma
   grade que quebra no telefone: um carrossel com seta em tela de 360 esconde
   metade do sortimento atrás de um gesto que ninguém descobre. */
.vitrine {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(11.5rem, 1fr);
  gap: var(--unit-200);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-block-end: var(--unit-100);
  scrollbar-width: thin;
}
.vitrine > * { scroll-snap-align: start; }

/* Coluna mínima de 16.5rem (264), e não 11.5rem (184). O nome do produto
   é a informação que decide o clique, e em 184 ele vinha cortado em três
   linhas com reticência em quase todo cartão. Em 264 sobram 240 dentro do
   recuo — a mesma largura de nome da vitrine, e a medida em que o esqueleto
   do título varia de cartão para cartão em vez de encostar no limite.
   No telefone quem manda continua sendo a regra de duas colunas. */
.grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
  gap: var(--unit-200);
}

/* --- cartão de produto --------------------------------------------------- */

.produto-cartao {
  position: relative;
  display: flex; flex-direction: column; gap: var(--unit-100);
  padding: var(--unit-150);
  background-color: var(--surface-raised);
  border-radius: var(--border-100);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  transition: box-shadow var(--card-transition, 120ms ease), translate 120ms ease;
}
.produto-cartao:hover { box-shadow: var(--shadow-overlay); translate: 0 -2px; }
.produto-cartao:focus-within { box-shadow: inset 0 0 0 2px var(--border-focus); }

.produto-cartao__arte {
  aspect-ratio: 1;
  border-radius: var(--border-50);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--text-disabled);
  overflow: hidden;
}
.produto-cartao__arte svg { width: 2.5rem; height: 2.5rem; }

/* O coração fica sobre a arte, no canto. O arquivo põe embaixo, centrado;
   aqui ele sobe para o canto porque no cartão fluido o centro varia com o
   comprimento do nome, e um alvo que anda é um alvo que se erra. */
.produto-cartao__favorito {
  position: absolute; inset-block-start: var(--unit-200); inset-inline-end: var(--unit-200);
  background-color: var(--surface-raised);
}
/* O coração marcado é AZUL, e não magenta: é ação de sistema, e a terciária
   só vale para campanha e selo. O arquivo mobile já o desenha em azul. */
/* O alvo é o `__icon`, e não o botão: o Icon Button pinta o próprio glifo
   com `--icon-button-icon-default`, que ganha de uma cor herdada. */
.produto-cartao__favorito[aria-pressed="true"] .sysvc-icon-button__icon {
  color: var(--brand-primary-bold);
  fill: currentColor;
}

.produto-cartao__nome {
  margin: 0;
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold); color: var(--text-body);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.produto-cartao__nome a { color: inherit; text-decoration: none; }
.produto-cartao__nome a:focus-visible { outline: none; }

/* O cartão inteiro leva ao produto. Quem clica na foto ou no preço está
   pedindo o produto, e não havia nada ali para clicar.

   Um pseudoelemento do link do nome cobre a caixa, em vez de um segundo
   <a> em volta de tudo: o cartão continua tendo UM link só — um <a>
   envolvendo foto, coração e preço leria "link, Notebook…, botão favoritar,
   1.200 c$" numa tira só, e aninhar o botão dentro do link é HTML inválido.
   Assim o leitor de tela e o Tab continuam encontrando o nome, que é o que
   diz para onde se vai.

   O cartão já era position: relative por causa do coração, e o coração sobe
   uma camada para continuar sendo ele mesmo: ele é a outra ação do cartão, e
   não pode virar parte do alvo grande. */
.produto-cartao__nome a::after { content: ""; position: absolute; inset: 0; }
.produto-cartao__favorito { z-index: 1; }

/* O sublinhado responde ao cartão, e não só ao nome: com a caixa toda
   clicável, o ponteiro quase nunca está sobre as letras. */
.produto-cartao:hover .produto-cartao__nome a { text-decoration: underline; }

.produto-cartao__ref {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle);
}

.produto-cartao__preco { margin-block-start: auto; }
.produto-cartao__parceiro {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle); text-transform: uppercase; letter-spacing: .03em;
  /* No alto, e nao ao centro: o nome da loja quebra em ate tres linhas no
     cartao estreito, e um disco centrado no bloco todo fica boiando longe da
     palavra a que pertence. Os -2px acertam o disco de 20 sobre a linha de
     16 — medido. */
  display: flex; align-items: flex-start; gap: var(--unit-100);
}
/* O menor dos quatro discos. Sem o contorno interno dos grandes: a 20px ele
   engoliria a arte em vez de emoldurá-la. */
.produto-cartao__marca {
  flex: none; margin-block-start: -.125rem;
  width: 1.25rem; height: 1.25rem; border-radius: var(--border-full);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--brand-primary-bold);
  font-size: .625rem; font-weight: var(--weight-black);
}

/* O preço. O arquivo escreve o número em 20 bold azul e o "c$" menor, na
   linha de base. O `c$` é unidade, não decimal: fica no mesmo tom, um degrau
   menor, e nunca sozinho. */
.preco {
  display: inline-flex; align-items: baseline; gap: .15em;
  color: var(--brand-primary-bold);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.preco__numero { font-size: var(--heading-sm-size); line-height: 1.2; }
.preco__unidade { font-size: var(--text-caption-size); font-weight: var(--weight-bold); }
.preco--grande .preco__numero { font-size: var(--heading-lg-size); }
.preco--pequeno .preco__numero { font-size: var(--text-body-size); }

/* --- lojas parceiras ----------------------------------------------------- */

.parceiros { display: flex; flex-wrap: wrap; gap: var(--unit-300); }
.parceiro {
  display: grid; justify-items: center; gap: var(--unit-100);
  width: 7rem; text-decoration: none; color: var(--text-subtle);
  border-radius: var(--border-50);
}
.parceiro:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.parceiro__disco {
  width: 4.5rem; height: 4.5rem; border-radius: var(--border-full);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--brand-primary-bold);
  font-size: var(--heading-sm-size); font-weight: var(--weight-black);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  transition: box-shadow 120ms ease;
}
.parceiro:hover .parceiro__disco { box-shadow: inset 0 0 0 2px var(--brand-primary-default); }
/* A arte da marca sobre fundo claro: entra reduzida, com folga, sobre o disco
   da cor declarada em `logoFundo` — branco, na prática. Sem essa cor o disco
   seguiria o tema e o quadrado branco do arquivo apareceria dentro dele. */
/* O COMPORTAMENTO da arte mora aqui, uma vez só; a MEDIDA mora em cada lugar
   que hospeda o disco — 4,5rem na vitrine e no menu do cabeçalho, 3rem na
   página do parceiro, 2,75rem no rodapé, 1,5rem na ficha do produto e 1,25rem
   no cartão.

   Dupla classe de propósito: assim a cor de fundo daqui vence a do disco que
   hospeda sem depender da ordem do arquivo. */
.marca { overflow: hidden; }
.marca.marca--logo { background-color: var(--parceiro-logo-fundo, var(--surface-raised)); }
.marca.marca--logo img {
  inline-size: 70%; block-size: 70%; object-fit: contain;
  /* A arte que veio com margem própria cresce por aqui, e o disco apara o
     que passar. Medida em dados.js, junto do arquivo — a margem é do
     arquivo, e não do desenho desta tela. */
  scale: var(--parceiro-logo-zoom, 1);
}

/* A arte que já é um quadrado com a cor da marca no fundo: ocupa o disco
   INTEIRO e a máscara redonda apara os cantos, como uma foto de perfil.
   `cover` e não `contain`: contain deixaria faixas do disco aparecendo em
   volta de uma arte que já traz o próprio fundo. */
.marca.marca--cheio { background-color: transparent; }
.marca.marca--cheio img {
  inline-size: 100%; block-size: 100%; object-fit: cover;
  scale: var(--parceiro-logo-zoom, 1);
}
.parceiro__nome {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  text-align: center;
}


/* --- filtro e ordenação da lista ----------------------------------------
   O painel é o organismo `system/Componentes/Organismos/filtros-pesquisa.svg`:
   Accordion com ícone, rótulo, chevron, e a ação de texto alinhada ao fim.
   O que se compõe aqui é só o INTERIOR dele — a caixa, o cabeçalho, a
   abertura e o chevron são do componente. */

.lista__topo {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--unit-300); flex-wrap: wrap;
  margin-block-end: var(--unit-250);
}
.lista__identidade { display: grid; gap: var(--unit-25); }
.lista__conta { display: block; }

/* Com a marca, a identidade vira duas colunas: o disco à esquerda, atravessando
   as duas linhas, e o título com a contagem à direita. `align-items: center`
   centra o disco no conjunto das duas, e não em uma delas. */
.lista__identidade--marca {
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: var(--unit-200);
}
.lista__identidade--marca > .lista__marca { grid-row: 1 / span 2; }
.lista__marca {
  width: 3rem; height: 3rem; border-radius: var(--border-full);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--brand-primary-bold);
  font-size: var(--heading-sm-size); font-weight: var(--weight-black);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  overflow: hidden;
}

/* O gatilho do Dropdown é a caixa do Campo, de 72 de altura — larga demais
   para a linha do título se ocupasse a faixa inteira. Fica em 16rem, que é
   onde "Mais relevantes" cabe sem truncar. */
.lista__ordem { flex: 0 0 auto; width: min(16rem, 100%); }

.filtros { margin-block-end: var(--unit-250); }

/* Lista: foto pequena à esquerda, texto à direita, uma coluna. A foto cresce
   na tela larga — 5rem numa linha de 1273 é uma miniatura, e o cartão deitado
   existe justamente para dar ao nome do produto a largura toda. */
.grade--lista { grid-template-columns: minmax(0, 1fr); }
.grade--lista .produto-cartao {
  display: grid; grid-template-columns: 5rem minmax(0, 1fr);
  column-gap: var(--unit-150); row-gap: var(--unit-50); align-items: start;
}
.grade--lista .produto-cartao__arte { grid-row: 1 / span 4; }
.grade--lista .produto-cartao__favorito { inset-block-start: var(--unit-100); inset-inline-end: var(--unit-100); }
.grade--lista .produto-cartao__nome { padding-inline-end: var(--unit-500); }

@media (min-width: 56.3125rem) {
  .grade--lista .produto-cartao { grid-template-columns: 7rem minmax(0, 1fr); column-gap: var(--unit-250); }
}

/* A coluna de ordenar e filtrar.
   =========================================================================
   No telefone ela não existe: `display: contents` dissolve a caixa e os dois
   blocos voltam ao fluxo da seção, na ordem de sempre — Ordenar por logo
   abaixo do título, e o filtro flutuante em seguida.

   Do hd para cima ela é a navegação lateral da lista: mesma largura do resumo
   das etapas (18rem), mesmo grude na rolagem. O gatilho do Accordion some —
   não há o que abrir quando o painel É a coluna — e a superfície deixa de
   flutuar. Filtrar e ordenar ficam à vista enquanto se olha a grade, que é o
   contrário do painel que cobre o que se está filtrando. */
.lista__antes, .lista__resultado, .lista__lado { display: contents; }

@media (min-width: 56.3125rem) {
  /* Duas colunas e duas linhas, nomeadas: a coluna da direita atravessa as
     duas, e o resultado ocupa a linha de baixo à esquerda. Sem as áreas, o
     `1 / -1` do aside não tem a que se agarrar — medido, ele esticava a
     primeira linha em 690 e a grade descia junto. */
  /* Só quando a coluna existe: com um produto só (ou nenhum) não há o que
     ordenar nem filtrar, e sem o `:has` sobrava uma faixa vazia de 288 ao
     lado do estado vazio. */
  .lista:has(.lista__lado) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 18rem;
    grid-template-areas: "antes lado" "resultado lado";
    grid-template-rows: auto 1fr;
    column-gap: var(--faixa-gutter, var(--unit-400));
    align-items: start;
  }
  .lista__antes { display: block; grid-area: antes; min-inline-size: 0; }
  .lista__resultado { display: block; grid-area: resultado; min-inline-size: 0; }
  .lista__lado {
    display: grid; gap: var(--unit-250);
    grid-area: lado; min-inline-size: 0;
    position: sticky; inset-block-start: 7rem;
  }
  .lista__lado .lista__ordem,
  .lista__lado .lista__visao { inline-size: 100%; max-inline-size: none; }
  .lista__lado .filtros { margin-block-end: 0; }
  /* Não há o que abrir quando o painel É a coluna. */
  .lista__lado .filtro-flutuante__gatilho { display: none; }
  .lista__lado .filtro-flutuante__superficie {
    position: static;
    box-shadow: inset 0 0 0 1px var(--border-subtle);
  }
}

/* O contador ao lado do rótulo. É o Badge do sistema; só o vão é daqui.
   O número não substitui os chips — ele diz QUANTOS, e os chips dizem
   QUAIS. Com o painel fechado, os dois juntos é que fecham a conta. */
.filtros__conta { margin-inline-start: var(--unit-100); vertical-align: middle; }

.filtros__grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--unit-300);
  align-items: start;
}

.filtros__grupo { margin: 0; padding: 0; border: 0; min-width: 0; }

.filtros__legenda {
  padding: 0;
  margin-block-end: var(--unit-100);
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  font-weight: var(--weight-bold);
  color: var(--text-subtle);
  text-transform: uppercase; letter-spacing: .05em;
}

.filtros__faixa { display: flex; gap: var(--unit-150); }
.filtros__faixa .sysvc-field { flex: 1; min-width: 0; }

.filtros__saldo { margin-block-start: var(--unit-150); display: grid; gap: var(--unit-25); }
.filtros__nota {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle);
  /* Recuo do alvo do checkbox, para a nota alinhar com o rótulo dele e não
     com a caixa. */
  padding-inline-start: calc(var(--checkbox-size) + var(--checkbox-gap));
}

.filtros__erro { color: var(--text-danger); }

/* A ação de texto alinhada ao fim, como no arquivo. */
.filtros__acoes {
  display: flex; justify-content: flex-end; gap: var(--unit-100);
  margin-block-start: var(--unit-250);
}

.filtros-aplicados {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--unit-100) var(--unit-150);
  margin-block-end: var(--unit-250);
}

@media (max-width: 900px) {
  /* No telefone o Dropdown vai para a linha de baixo, inteiro: metade de
     um gatilho de 72 ao lado de um título de duas linhas não é legível. */
  .lista__ordem { width: 100%; }
  .filtros__faixa { flex-wrap: wrap; }
  .filtros__faixa .sysvc-field { flex-basis: 100%; }
}

/* =========================================================================
   4. Gift card
   ========================================================================= */

/* A vitrine de gift card usa a mesma faixa rolável dos produtos, mas o
   cartão é mais largo: a arte é retangular, na proporção do cartão físico
   (1,586:1, a do ISO/IEC 7810 ID-1). */
.vitrine--gift { grid-auto-columns: minmax(15rem, 1fr); }
.grade--gift { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }

.gift-cartao {
  /* Caixa de referência do alvo que cobre o cartão inteiro. */
  position: relative;
  display: flex; flex-direction: column;
  background-color: var(--surface-raised);
  border-radius: var(--border-100);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  overflow: hidden;
  transition: box-shadow 120ms ease, translate 120ms ease;
}
.gift-cartao:hover { box-shadow: var(--shadow-overlay); translate: 0 -2px; }
.gift-cartao:focus-within { box-shadow: inset 0 0 0 2px var(--border-focus); }

/* A arte: bloco na cor da marca com o nome escrito.
   REGISTRO: nenhum logotipo de terceiro é reproduzido — não temos os
   arquivos, e um logotipo aproximado é pior que nenhum. Quando a arte
   oficial existir, ela entra como imagem de fundo deste mesmo bloco. */
.gift-cartao__arte {
  aspect-ratio: 1.586;
  display: grid; align-content: center; justify-items: start;
  gap: var(--unit-50);
  padding: var(--unit-250);
  background-color: var(--gift-cor, var(--brand-primary-default));
  color: var(--gift-cor-texto, var(--text-negative));
}
.gift-cartao__marca { font-size: var(--heading-md-size); font-weight: var(--weight-black); letter-spacing: -.01em; }
/* O sobre-rótulo "Gift card" vive no CORPO do cartão, sobre a superfície
   branca — e não sobre a arte.
   REGISTRO DA DECISÃO: ele estava dentro da arte, e ali a cor de fundo é a
   da marca do parceiro, que muda a cada cartão. Medido no navegador, o
   rótulo de 12 bold reprovava em dois dos dez (iFood 4,46 e Rappi 3,44
   contra os 4,5 exigidos), e não há tratamento de cor que sirva para dez
   fundos arbitrários ao mesmo tempo. Sobre a superfície, o número é um só
   e é conhecido. O nome da marca, que ficou na arte, é 24 black — texto
   grande, limiar de 3:1, e o menor dos dez dá 3,44. */
.gift-cartao__tipo {
  font-size: var(--text-caption-size); font-weight: var(--weight-bold);
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-subtle);
}
.gift-cartao__chip {
  position: absolute; inset-block-end: var(--unit-250); inset-inline-end: var(--unit-250);
  width: 2rem; height: 1.5rem; border-radius: var(--border-50);
  background-color: currentColor; opacity: .25;
}

.gift-cartao__corpo {
  display: flex; flex-direction: column; gap: var(--unit-100);
  padding: var(--unit-200); flex: 1;
}
.gift-cartao__nome { margin: 0; font-size: var(--text-ui-size); font-weight: var(--weight-bold); }
.gift-cartao__nome a { color: inherit; text-decoration: none; }

/* O cartão inteiro leva ao gift card, como no cartão de produto: a arte da
   marca é o que se olha primeiro e era a única parte não clicável. Mesmo
   recurso de lá — o pseudoelemento do link do nome cobre a caixa, e o cartão
   segue com um link só. Aqui não há coração para levantar: a arte é
   decorativa, e o cartão tem uma ação só. */
.gift-cartao__nome a::after { content: ""; position: absolute; inset: 0; }
.gift-cartao:hover .gift-cartao__nome a { text-decoration: underline; }
.gift-cartao__faixa {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  color: var(--text-subtle); margin-block-start: auto;
}

/* --- página do gift card ------------------------------------------------- */

/* Mesma diagramação do carrinho: o que se lê fica na navegação principal,
   e o que se decide — valor, saldo, botões — fica no painel da direita, com
   a mesma largura e o mesmo grude do resumo do carrinho. A arte deixou de
   ser uma coluna: ela é a abertura do conteúdo, e no telefone não disputa
   espaço com o texto. */
.gift-pagina {
  /* Duas colunas do breakpoint para a arte — a largura de um cartão de gift
     card na vitrine é 4 de 12, e aqui, lida e não escolhida, ela vale
     metade disso. A conta é a do próprio grid: 100% desta caixa É a faixa,
     porque ela é filha direta dela, então a coluna sai de
     (largura - 11 vãos) / 12, e duas colunas somam o vão do meio. */
  --gift-arte: calc((100% - 11 * var(--faixa-gutter, 1rem)) / 12 * 2 + var(--faixa-gutter, 1rem));
  display: grid;
  grid-template-columns: var(--gift-arte) minmax(0, 1fr) 18rem;
  grid-template-areas:
    "cabeca cabeca resumo"
    "arte   texto  resumo"
    "extras extras resumo";
  gap: var(--unit-300) var(--faixa-gutter, var(--unit-400));
  align-items: start;
}
@media (min-width: 85.4375rem) {
  .loja .gift-pagina { grid-template-columns: var(--gift-arte) minmax(0, 1fr) 20rem; }
}
.gift-pagina__cabeca { grid-area: cabeca; display: grid; gap: var(--unit-50); }
.gift-pagina__arte { grid-area: arte; }
.gift-pagina__texto { grid-area: texto; display: grid; gap: var(--unit-300); align-content: start; }
.gift-pagina__extras { grid-area: extras; }
.gift-pagina > .resumo { grid-area: resumo; }
/* Pela terceira vez nesta loja: item de grade não encolhe abaixo do próprio
   conteúdo — o nome da marca, 24 black, media 352 de mínimo e empurrava a
   arte para fora da margem no telefone. */
.gift-pagina > * { min-inline-size: 0; }
.gift-resumo__valor { font-size: var(--heading-sm-size); line-height: var(--heading-sm-line); font-weight: var(--weight-bold); }
.gift-pagina__arte { position: relative; border-radius: var(--border-100); overflow: hidden; }

/* Os valores disponíveis são CHIPS do sistema, em escolha única. O
   `sysvc-chip-group` já traz a fila que quebra linha e o vão de 8; aqui
   sobra o respiro em volta.

   O que foi APAGADO daqui: a largura mínima de 7,5rem e o realce do botão
   escolhido. O Chip tem desenho próprio para aplicado e disponível, e
   pintá-lo por fora seria descrever de novo — pior — o que a peça já sabe. */
.gift-valores { margin-block: var(--unit-200); }

/* =========================================================================
   5. Produto
   ========================================================================= */

.produto {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) minmax(0, 22rem);
  gap: var(--unit-300);
  align-items: start;
  margin-block-start: var(--unit-200);
}

.produto__miniaturas { display: grid; gap: var(--unit-100); }
.produto__miniatura {
  aspect-ratio: 1; border-radius: var(--border-50);
  background-color: var(--surface-sunken);
  display: grid; place-items: center; color: var(--text-disabled);
  cursor: pointer; border: 0; padding: 0;
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}
.produto__miniatura[aria-current="true"] { box-shadow: inset 0 0 0 2px var(--brand-primary-default); }
.produto__miniatura:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.produto__miniatura svg { width: 1.5rem; height: 1.5rem; }

/* A foto principal tem teto de 36rem (576): quadrada na largura da coluna, ela
   media 1145 em 1920 — mais alta que a tela, com o painel de compra
   empurrado para longe dela. Centralizada na coluna quando sobra largura. */
.produto__palco {
  inline-size: min(100%, 36rem); justify-self: center;
  aspect-ratio: 1; border-radius: var(--border-100);
  background-color: var(--surface-sunken);
  display: grid; place-items: center; color: var(--text-disabled);
}
.produto__palco svg { width: 5rem; height: 5rem; }

.produto__painel { display: grid; gap: var(--unit-200); }
.produto__nome {
  margin: 0;
  font-size: var(--heading-sm-size); line-height: var(--heading-sm-line);
  font-weight: var(--weight-bold); color: var(--brand-primary-bold);
}
.produto__meta {
  font-size: var(--text-caption-size); color: var(--text-subtle); text-transform: uppercase;
  /* Sem o ponto separador que havia aqui: com o disco, as duas partes já se
     distinguem sozinhas, e na tela estreita o ponto sobrava no fim da linha
     de cima depois que a loja descia para a de baixo. */
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--unit-200);
}
/* O disco da loja na ficha do produto: o mesmo tamanho da linha de texto que
   ele acompanha, e sem contorno — o comportamento vem de `.marca`. */
.produto__marca {
  flex: none;
  width: 1.5rem; height: 1.5rem; border-radius: var(--border-full);
  background-color: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--brand-primary-bold);
  font-size: .6875rem; font-weight: var(--weight-black);
}
.produto__loja { display: inline-flex; align-items: center; gap: var(--unit-100); }

.escolha { display: flex; align-items: center; gap: var(--unit-150); flex-wrap: wrap; }
/* A fila de chips ocupa o vão que sobra da linha, e quebra dentro dele em
   vez de empurrar o rótulo para cima. */
.escolha .sysvc-chip-group { flex: 1; min-width: 0; }
.escolha__rotulo {
  font-size: var(--text-caption-size); font-weight: var(--weight-bold);
  color: var(--text-subtle); text-transform: uppercase; letter-spacing: .05em;
  min-width: 4.5rem;
}

/* A cor é um Chip com um disco antes do rótulo.

   DIVERGÊNCIA REGISTRADA da página do Chip, que lista entre os "não faça":
   "mais de dois níveis de informação na pílula: nome e ×, nada além". O
   disco é um terceiro. Ele entra assim mesmo porque um seletor de cor sem a
   cor não é um seletor de cor — o nome "Grafite" não diz a quem escolhe qual
   é o tom. E a regra que importa continua de pé: a cor NUNCA é a única
   pista, porque o nome está escrito ao lado dela, dentro da mesma pílula, e
   o estado escolhido tem preenchimento além de `aria-pressed`.

   O disco é decorativo (`aria-hidden`) e ganha contorno de 1px: sem ele o
   branco desapareceria dentro da pílula branca. */
.cor-chip__disco {
  flex: none;
  width: 0.875rem; height: 0.875rem;
  border-radius: var(--border-full);
  background-color: var(--cor);
  box-shadow: inset 0 0 0 1px var(--border-default);
}

/* EMPILHADOS, e a peça é do sistema: `sysvc-button-group--stack` existe
   exatamente para isto — "empilhado por escolha, e não por contagem: rótulos
   longos". É o caso. Lado a lado, "Adicionar ao carrinho" quebrava em duas
   linhas e "Resgatar agora" ficava numa só: dois botões da mesma altura com
   contagens de linha diferentes, e a coluna do produto tem 22rem, não a
   largura da tela.

   A grade de duas colunas que estava aqui foi apagada — não substituída. O
   grupo já sabe empilhar, e uma segunda descrição do mesmo arranjo é a que
   envelhece sem ninguém notar.

   A ORDEM é a do arquivo: "Adicionar ao carrinho" antes de "Resgatar agora",
   como o `Produto - 1.0.svg` desenha da esquerda para a direita. O empilhar
   não foi usado como desculpa para reordenar. */
.produto__acoes { margin-block: var(--unit-50); }

/* O bloco do CEP. O arquivo pinta o fundo de um verde-água claro; aqui é
   `brand.secondary.light`, o token que representa esse tom no sistema. */
.frete {
  display: flex; align-items: center; gap: var(--unit-200); flex-wrap: wrap;
  padding: var(--unit-200);
  border-radius: var(--border-100);
  background-color: var(--brand-secondary-light);
}
.frete__texto { font-size: var(--text-ui-size); line-height: var(--text-ui-line); color: var(--brand-primary-bold); font-weight: var(--weight-bold); }
.frete__campo { display: flex; gap: var(--unit-100); flex: 1; min-width: 14rem; }
.frete__campo .sysvc-field { flex: 1; }

/* --- detalhes ------------------------------------------------------------ */

.detalhes { width: 100%; border-collapse: collapse; margin-block-start: var(--unit-200); }
.detalhes th, .detalhes td {
  text-align: start; padding: var(--unit-150) var(--unit-200);
  font-size: var(--text-ui-size); line-height: var(--text-ui-line);
  box-shadow: inset 0 -1px 0 0 var(--border-subtle);
  vertical-align: top;
}
.detalhes th { width: 14rem; background-color: var(--surface-sunken); font-weight: var(--weight-bold); color: var(--text-body); }
.detalhes td { background-color: var(--surface-raised); }

/* =========================================================================
   6. Carrinho e checkout
   ========================================================================= */

/* A barra da direita é o PAINEL do grid (`PAINEL_LARGURA`, sys-vc/data.js):
   288 no hd, 320 no fullhd — a mesma regra da conclusão. */
.checkout { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--faixa-gutter, var(--unit-400)); align-items: start; }
@media (min-width: 85.4375rem) {
  .loja .checkout { grid-template-columns: minmax(0, 1fr) 20rem; }
}

.linha-item {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto auto;
  gap: var(--unit-200); align-items: center;
  padding-block: var(--unit-250);
  box-shadow: inset 0 -1px 0 0 var(--border-subtle);
}
.linha-item__arte {
  width: 5rem; aspect-ratio: 1; border-radius: var(--border-50);
  background-color: var(--surface-sunken);
  display: grid; place-items: center; color: var(--text-disabled);
  overflow: hidden;
}
.linha-item__arte svg { width: 1.75rem; height: 1.75rem; }
.linha-item__arte--gift { background-color: var(--gift-cor); color: var(--gift-cor-texto); font-weight: var(--weight-black); font-size: var(--text-caption-size); }
.linha-item__nome { margin: 0; font-size: var(--text-ui-size); line-height: var(--text-ui-line); font-weight: var(--weight-bold); }
.linha-item__meta { font-size: var(--text-caption-size); color: var(--text-subtle); }
.linha-item__fim { display: grid; justify-items: end; gap: var(--unit-100); }

/* Quantidade: menos, número, mais. O número é um `input`, e não texto —
   trocar 1 por 12 com dois cliques é pior que digitar. */
/* Uma coluna só, do tamanho do controle: assim o rótulo tem sobre o que se
   centralizar. Sem isso a coluna é a da célula que hospeda a peça, e o
   "Qtd." acompanhava o alinhamento do bloco — ia para a esquerda no
   telefone e para a direita onde a linha alinhava ao fim. Como o menos e o
   mais são simétricos, o centro do controle É o centro da caixa do número. */
.quantidade { display: grid; grid-template-columns: max-content; justify-items: center; gap: var(--unit-50); }
.quantidade__rotulo {
  font-size: var(--text-caption-size); font-weight: var(--weight-bold);
  color: var(--text-subtle); text-transform: uppercase; letter-spacing: .05em;
  /* No próprio rótulo, e não herdado do container: cada breakpoint mexe no
     `justify-items` do bloco para posicioná-lo na linha, e o rótulo não pode
     ir junto. */
  justify-self: center;
}
.quantidade__controle { display: flex; align-items: center; gap: var(--unit-50); }
.quantidade__campo {
  /* 44 para acompanhar o mais e o menos ao lado, que voltaram ao padrão. */
  width: 3rem; height: 2.75rem; text-align: center;
  font-family: inherit; font-size: var(--text-ui-size); font-weight: var(--weight-bold);
  color: var(--text-body);
  background-color: var(--surface-raised);
  border: 0; border-radius: var(--border-50);
  box-shadow: inset 0 0 0 1px var(--border-default);
  font-variant-numeric: tabular-nums;
}
.quantidade__campo:focus-visible { outline: 2px solid var(--border-focus); outline-offset: -2px; }

/* --- resumo -------------------------------------------------------------- */

.resumo {
  position: sticky; inset-block-start: 7rem;
  /* `minmax(0, 1fr)` e não a coluna implícita: item de grade tem
     `min-width: auto` e não encolhe abaixo do próprio conteúdo. Um Botão de
     utilidade com descrição comprida — que corta com reticências dentro de
     si — empurrava a coluna inteira para fora da tela em vez de cortar. */
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--unit-150);
  padding: var(--unit-300);
  background-color: var(--surface-raised);
  border-radius: var(--border-100);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}
.resumo__linha {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--unit-200);
  font-size: var(--text-ui-size); line-height: var(--text-ui-line);
}
.resumo__rotulo { color: var(--text-subtle); }
.resumo__valor { font-variant-numeric: tabular-nums; font-weight: var(--weight-bold); }
.resumo__regua { height: 1px; background-color: var(--border-subtle); margin-block: var(--unit-50); }
.resumo__total { font-size: var(--text-body-size); font-weight: var(--weight-bold); color: var(--brand-primary-bold); }

/* Saldo depois da compra: a única linha que pode ficar vermelha, e ela
   avisa em texto — não só em cor. */
.resumo__aviso { margin-block-start: var(--unit-100); }

/* Os botões da etapa moram DENTRO do resumo: a caixa que mostra o total é a
   mesma que oferece a saída. Empilhados e em largura cheia, porque a coluna
   tem 288 e dois botões lado a lado ali ficariam com o rótulo espremido.
   A margem é 12 porque o resumo é grade com vão de 12, e os dois se somam:
   dá os 24 que separam a decisão dos números. */
.resumo__acoes { margin-block-start: var(--unit-150); }

/* Os modais de cadastro da loja — endereço e cartão — alinham as ações à
   ESQUERDA, e não à direita como o rodapé do Modal faz por padrão. Aqui o
   rodapé fecha um formulário, e o Salvar fica na mesma vertical do primeiro
   campo: o olho desce a coluna de campos e encontra o botão no fim dela, que
   é o mesmo alinhamento das telas de cadastro em Meus dados. */
#modal-endereco .sysvc-modal__footer,
#modal-cartao .sysvc-modal__footer { justify-content: flex-start; }

/* O UF ocupa 1 das 6 colunas do formulário, o que serve na tela larga de
   Meus dados e não serve dentro do Modal: ali a coluna mede 59, o gatilho
   do Dropdown gasta 16 de recuo de cada lado, e sobrava ZERO para o texto —
   o rótulo "UF" e a sigla ficavam cortados até sumir. No modal ele ocupa
   duas colunas, com um piso de 7rem para o caso de a caixa encolher mais:
   o campo tem de caber duas letras, o rótulo e a seta. */
/* Só onde o formulário tem as SEIS colunas. Do tablet para baixo ele já
   vira duas, e ali o UF ocupa metade da linha — sobra espaço. Spans de 2 e 4
   numa grade de 2 colunas criariam colunas implícitas: medido, a grade virou
   "12,5 12,5 127 127" e os rótulos dos campos foram cortados. */
@media (min-width: 56.3125rem) {
  #modal-endereco #uf-endereco {
    grid-column: span 2;
    min-inline-size: 7rem;
  }
  /* E a Cidade cede a coluna que o UF ganhou: 4 + 2 fecham a linha, e os
     dois continuam lado a lado como na tela de Meus dados. */
  #modal-endereco .formulario__campo--5 { grid-column: span 4; }

  /* O menu do Dropdown tem largura mínima de 192 e nasce preso à ESQUERDA do
     gatilho. Com o UF no fim da linha, ele crescia para fora do modal — 958
     contra os 923 da borda — e o corpo ganhava rolagem lateral (515 num vão
     de 480). Preso ao fim, cresce para dentro: o menu é mais largo que o
     campo porque mostra a sigla e o nome do estado, e é o lado de dentro que
     tem espaço. Só aqui: no telefone o UF é a coluna da ESQUERDA, e preso ao
     fim ele saía 12px pela borda de lá. */
  #modal-endereco #uf-endereco .sysvc-dropdown__menu { inset-inline: auto 0; }
}

/* O Popup do CVV abre para CIMA dentro do modal. Ele vira sozinho quando não
   cabe na janela — é o que o script do sistema mede —, mas aqui quem corta
   não é a janela e sim o corpo do Modal, que rola: o CVV é o último campo, e
   dos 120 de altura da explicação 88 ficavam escondidos abaixo da borda. Para
   cima ele abre sobre os campos já preenchidos, que é onde há espaço. */
#modal-cartao .cvv-ajuda .sysvc-popup__surface {
  inset-block-start: auto;
  inset-block-end: calc(100% + var(--popup-gap));
}

/* A frase de apoio do modal divide a explicação com o corpo: sem margem em
   cima, porque o cabeçalho já dá o vão. */
.sysvc-modal__body > .endereco-novo__apoio { margin-block: 0 var(--unit-250); }

/* O recado de "só gift card" era um Status em frase, e Status é rótulo de
   estado: uma linha, sem quebra prevista — a frase passava da margem no
   telefone. Virou aviso em linha, como os outros recados da loja. Quem dá o
   espaço é o hospedeiro, porque o aviso não tem margem própria: 20 da lista
   de itens, que é o que a frase tinha antes. */
.carrinho__aviso { margin-block-start: var(--unit-250); }


/* O olho da prévia da conta e o dos cartões de resumo. Mesmo botão, encaixes
   diferentes: na prévia ele fica no canto do bloco afundado; no resumo,
   colado ao número, que é alinhado à direita. */
.previa__saldo { position: relative; }
.previa__olho {
  position: absolute;
  inset-block-start: var(--unit-100);
  inset-inline-end: var(--unit-100);
}
.previa__saldo-valor { min-inline-size: 0; }

.resumo__valor { display: inline-flex; align-items: center; gap: var(--unit-50); }
.resumo__valor .saldo__olho { margin-inline-end: 0; }

/* --- endereço ------------------------------------------------------------ */

/* O quadro do endereço único saiu daqui junto com a tela que o usava:
   quem desenha a lista agora é o Botão de opção do sistema. */

/* O painel elevado. Não é decoração, é contraste MEDIDO.

   A página do Botão de controle já registra o problema: o rótulo neutro dá
   4,73:1 sobre o cartão branco e 4,44:1 sobre `surface.page`. O rótulo do
   Field cai na mesma conta — 16 bold em `brand.primary.default` mede os
   mesmos 4,44:1 sobre o fundo da página, e 16 bold não é texto grande, então
   o piso é 4,5 e não 3.

   Por isso grade de atalhos e formulário vivem os dois aqui dentro, e não
   soltos no fundo. É a mesma armadilha que o sistema registrou para o Label,
   aparecendo de novo em outra peça. */
.painel {
  padding: var(--unit-200);
  border-radius: var(--border-100);
  background-color: var(--surface-raised);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}

.formulario__campo--1 { grid-column: span 1; }
.formulario { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--unit-200); }
.formulario__campo--2 { grid-column: span 2; }
.formulario__campo--3 { grid-column: span 3; }
.formulario__campo--4 { grid-column: span 4; }
.formulario__campo--5 { grid-column: span 5; }
.formulario__campo--6 { grid-column: span 6; }

/* --- pagamento ----------------------------------------------------------- */

/* O acordeão de formas de pagamento saiu daqui junto com a tela. A escolha é
   do Botão de opção agora, que não abre painel: a diferença entre as duas
   formas cabe no conteúdo do próprio cartão. */
/* O CVV é um campo só, e um campo só não ocupa a linha inteira: seis
   dígitos numa caixa de 600px pedem para ser lidos como outra coisa. */
.cvv-linha { margin-block-start: var(--unit-250); }
.cvv-linha__campo { max-inline-size: 12rem; }

.cartao-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--unit-200); }
.cartao-form__largo { grid-column: 1 / -1; }

/* A divisão pontos + cartão. A barra mostra quanto sai de cada um: dois
   números somando o total, e a barra é a mesma informação em forma — quem
   não lê o número vê a proporção. */
.divisao { display: grid; gap: var(--unit-100); margin-block-start: var(--unit-200); }
.divisao__barra {
  height: .5rem; border-radius: var(--border-full);
  background-color: var(--surface-sunken); overflow: hidden;
  display: flex;
}
.divisao__parte--pontos { background-color: var(--brand-primary-default); }
.divisao__parte--cartao { background-color: var(--brand-secondary-default); }
.divisao__legenda { display: flex; gap: var(--unit-300); flex-wrap: wrap; font-size: var(--text-caption-size); }
.divisao__chave { display: inline-flex; align-items: center; gap: var(--unit-50); }
.divisao__disco { width: .625rem; height: .625rem; border-radius: var(--border-full); }

/* --- conclusão ----------------------------------------------------------- */

/* Duas colunas, na mesma medida do carrinho e das contas: o principal à
   esquerda, a barra lateral de 22rem à direita. */
/* A barra da direita é o PAINEL do grid do sistema (`sys-vc/data.js`,
   PAINEL_LARGURA): 288 no hd, 320 no fullhd. Abaixo de 980 não há painel —
   a tela vira uma coluna (regra de estreito, mais abaixo). */
.conclusao { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--faixa-gutter, var(--unit-400)); align-items: start; }
@media (min-width: 85.4375rem) {
  .loja .conclusao { grid-template-columns: minmax(0, 1fr) 20rem; }
}
.conclusao__principal { display: grid; gap: var(--unit-300); min-width: 0; }
.conclusao__lateral { gap: var(--unit-250); }
.conclusao__bloco { display: grid; gap: var(--unit-100); }
.conclusao__bloco > .sysvc-status { justify-self: start; }

/* Pedido aberto de Meus pedidos: a pergunta e o botão text-only na mesma
   linha, e o botão desce para baixo da pergunta quando não cabe. */
.conclusao__suporte { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--unit-100); }
.conclusao__suporte > .sysvc-text { margin: 0; }
/* "Voltar aos pedidos" logo depois do recibo, no pedido aberto da lista. */
.conclusao__voltar { justify-content: flex-start; }

/* O Total que fecha o recibo sobe DOIS degraus da escala em rótulo e valor:
   rótulo n2 → 0 (12 → 16), valor 0 → 1 (16 → 22; o meio passo 05 conta como
   degrau). Composição da loja — o Recibo do sistema mantém a quantia só na cor. */
/* Item com foto ao lado do nome, como no carrinho: a miniatura do carrinho em
   3rem, e o valor centrado na altura da foto. */
.conclusao .conclusao__item { align-items: center; }
.conclusao .conclusao__item-rotulo { display: flex; align-items: center; gap: var(--unit-150); min-width: 0; }
.conclusao .conclusao__item-arte { flex: none; width: 3rem; }

.conclusao .conclusao__total .sysvc-receipt__rotulo {
  font-size: var(--scale-size-0); line-height: var(--scale-height-0);
}
.conclusao .conclusao__total .sysvc-receipt__valor {
  font-size: var(--scale-size-1); line-height: var(--scale-height-1);
}
/* Nota e extrato lado a lado, metade e metade. Em 22rem os dois rótulos em
   caixa alta não cabem numa linha — o grupo vazava 126px da barra —, então o
   rótulo quebra dentro do próprio botão em vez de empurrar a coluna. */
/* Empilhados, um por linha. O Button group do sistema é grade com
   `grid-auto-flow: column` — só a coluna única não basta, o fluxo também vira. */
.conclusao .conclusao__acoes { display: grid; grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); gap: var(--unit-100); }
.conclusao .conclusao__acoes > .sysvc-button { justify-content: center; }

/* Na barra lateral o rastreio fica em pé: quatro paradas lado a lado em
   22rem quebravam cada rótulo em três linhas. O fio passa a ser vertical,
   entre os discos. */
/* Prefixo `.conclusao`: a regra base de `.rastreio` vem DEPOIS no arquivo e,
   com o mesmo peso, zerava o gap. */
.conclusao .rastreio--vertical { flex-direction: column; gap: var(--unit-200); margin-block: var(--unit-100) 0; }
/* Em pé há largura de sobra: o rótulo solta o teto de 7rem e fica numa linha. */
.conclusao .rastreio--vertical .rastreio__rotulo { max-width: none; text-align: start; white-space: nowrap; }
.rastreio--vertical .rastreio__parada {
  display: flex; align-items: center; gap: var(--unit-150);
}
.rastreio--vertical .rastreio__parada + .rastreio__parada::before {
  inset-inline-start: calc(1.375rem - 1px); inset-inline-end: auto;
  inset-block-start: auto; inset-block-end: 100%;
  width: 2px; height: var(--unit-200);
}

/* O rastreio. Quatro paradas; a atual tem anel VERDE e rótulo em negrito —
   de novo, cor e forma juntas. */
.rastreio { display: flex; align-items: flex-start; gap: 0; margin-block: var(--unit-200); }
.rastreio__parada { flex: 1; display: grid; justify-items: center; gap: var(--unit-100); position: relative; }
.rastreio__parada + .rastreio__parada::before {
  content: ''; position: absolute;
  inset-block-start: 1.375rem; inset-inline-end: 50%; width: 100%;
  height: 2px; background-color: var(--border-default);
}
.rastreio__parada--feita + .rastreio__parada::before,
.rastreio__parada--feita::before { background-color: var(--alert-success-bold); }
.rastreio__disco {
  position: relative; z-index: 1;
  width: 2.75rem; height: 2.75rem; border-radius: var(--border-full);
  display: grid; place-items: center;
  background-color: var(--surface-page);
  box-shadow: inset 0 0 0 2px var(--border-default);
  color: var(--text-subtle);
}
.rastreio__parada--feita .rastreio__disco {
  box-shadow: inset 0 0 0 3px var(--alert-success-bold);
  color: var(--alert-success-bold);
}
.rastreio__disco svg { width: 1.375rem; height: 1.375rem; }
.rastreio__rotulo {
  font-size: var(--text-caption-size); line-height: var(--text-caption-line);
  text-align: center; color: var(--text-subtle); max-width: 7rem;
}
.rastreio__parada--feita .rastreio__rotulo { color: var(--alert-success-bold); font-weight: var(--weight-bold); }

/* O código do gift card entregue. Monoespaçado, porque é para conferir
   caractere a caractere. */
/* Os gift cards entregues.
   =========================================================================
   Eram uma faixa cinza com o código dentro, desenhada aqui. Viraram Recibo:
   um gift card entregue é um comprovante — tem quantia, tem de quem é, e tem
   o código que prova. A mesma pergunta de quem abre um comprovante de conta.

   Empilhados, e não `--horizontal`: estes recibos são fichas estreitas lado
   a lado, e a distribuição horizontal é a de quando a folha ocupa a seção
   principal da página. O `auto-fill` com mínimo de 15rem é o que decide
   quantos cabem por linha.

   O botão de copiar fica FORA da folha: recibo é dado, não ação. */
.gift-entregues {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--unit-250);
  margin-block-start: var(--unit-250);
}
/* O `justify-items: start` que estava aqui encolhia a folha para a largura
   do conteúdo — um recibo de 40px com o código quebrando letra a letra. Quem
   se alinha à esquerda é só o botão. */
.gift-entregue { display: grid; gap: var(--unit-150); align-content: start; }
.gift-entregue__copiar { justify-self: start; }
.conclusao__lateral .gift-entregue__copiar { justify-self: center; }
.gift-painel { display: grid; gap: var(--unit-100); margin: 0; }
.gift-painel dd { margin: 0; text-align: end; }
.gift-painel dt { color: var(--text-subtle); }

/* =========================================================================
   7. Contas a pagar (boleto)
   ========================================================================= */

/* Painel do grid: 288 no hd, 320 no fullhd. */
.contas { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--faixa-gutter, var(--unit-400)); align-items: start; }
@media (min-width: 85.4375rem) {
  .loja .contas { grid-template-columns: minmax(0, 1fr) 20rem; }
}

/* A linha digitável. Monoespaçada e com espaçamento largo: 47 dígitos numa
   fonte proporcional são impossíveis de conferir contra o papel. */
.linha-digitavel {
  font-family: var(--family-mono);
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
}
.contas__campo .sysvc-field__input { font-family: var(--family-mono); letter-spacing: .04em; }

/* O cartão de conta desenhado à mão saiu daqui: quem desenha a lista de
   contas agora é o Botão de opção do sistema. Sobra o `__content`, que
   precisa deixar o Status respirar em vez de tratá-lo como palavra. */
.sysvc-option__content .sysvc-status { margin-inline-end: var(--unit-50); }

/* O recibo desta loja é PROVA.
   =========================================================================
   A mesa branca que morava aqui foi embora, e ela conta uma história curta:
   quando o Recibo chegou, a folha era `elevation.surface` — #F7F8F9, a
   mesma cor da página desta loja. O rasgo do topo, que a documentação chama
   de "o componente", era invisível, porque dente de máscara é recorte e
   recorte só aparece contra outra cor. Esta loja pôs uma mesa branca atrás.

   O sistema resolveu na raiz, e melhor: a folha subiu para `surface.high`
   (branca no claro) e ganhou a sombra `overlay` em forma de FILTRO — com a
   silhueta dos dentes, porque papel rasgado projeta sombra rasgada. Quem
   separa a folha da página agora é a sombra, e ela vem na peça. A mesa virou
   uma caixa a mais em volta de nada.

   O que ficou é só a dívida de contraste que o componente registra e ensina
   a pagar: "o rótulo em grey.600 sobre a folha é 3,23:1 — abaixo dos 4,5 de
   texto pequeno. Onde o comprovante for a prova de uma operação — disputa,
   reembolso —, troque `--receipt-label-color` por `--text-subtle`, que dá
   5,08:1 na folha branca."

   É o caso das quatro telas desta loja: conta paga com código de
   autenticação, pedido concluído com nota fiscal, conta a conferir antes de
   pagar e o extrato de pontos. Todo recibo daqui é prova de alguma coisa.

   Isto NÃO define token: reaponta um token do componente para outro token do
   sistema, no escopo desta peça — o mecanismo que a própria documentação
   prescreve. */
.recibo--prova { --receipt-label-color: var(--text-subtle); }

/* O saldo do extrato mora na quantia do recibo, e leva o olho junto. */
.recibo__saldo { display: inline-flex; align-items: center; gap: var(--unit-50); }
/* A folha do extrato não ocupa a página inteira: ela é o cabeçalho da
   tabela que vem embaixo, e não o assunto. */
.extrato__recibo { max-inline-size: 30rem; margin-block: var(--unit-250); }

/* O comprovante deixou de ser uma folha centrada sozinha na página: ele
   agora divide a tela com a coluna de saldo, como as outras duas telas de
   conta. O `max-width` que o centrava saiu junto — quem dá a largura é a
   grade `.contas`. */
/* UMA coluna: a classe `conclusao` que ele carrega junto traz a grade de
   duas — 1fr mais 18rem —, e o comprovante caía na segunda. A folha ficava
   com 288 numa coluna de 919, e o Recibo, que se mede pelo próprio
   contêiner, desenhava a forma estreita: rótulo e valor empilhados, como no
   telefone. Com uma coluna a folha ocupa os 919 e o Recibo volta à forma
   horizontal. */
.comprovante {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: var(--unit-250); align-content: start;
}

/* A QUANTIA DO COMPROVANTE CRESCE — divergência registrada.
   =========================================================================
   A página do Recibo é explícita ao contrário: "ela NÃO muda de tamanho:
   muda de cor. Um comprovante inteiro em cinza com uma linha em teal já diz
   qual é a linha; aumentar o corpo junto seria dizer duas vezes."

   Aqui ela cresce assim mesmo, e só NESTA tela. O motivo é o que a tela é:
   as outras folhas da loja são resumos que se leem inteiros — o pedido, a
   conta a conferir. Esta é a que a pessoa abre depois, para achar UM número:
   quanto saiu. É a folha que se guarda, se imprime e se manda para alguém.

   O que a regra protege continua de pé: a quantia é uma só, o teal continua
   sendo dela, e nenhum outro valor da folha cresce junto — se todos
   crescessem, o tamanho deixaria de dizer algo, que é exatamente o que a
   documentação alerta.

   Vai para 24/29 (`scale-2`), o degrau seguinte da escala, e não um valor
   escrito à mão. */
.comprovante .sysvc-receipt__linha--quantia .sysvc-receipt__valor {
  font-size: var(--scale-size-2);
  line-height: var(--scale-height-2);
}

/* =========================================================================
   8. Rodapé
   ========================================================================= */

.rodape { margin-block-start: var(--unit-800); background-color: var(--brand-primary-default); color: var(--text-negative); }
.rodape__grade {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--unit-400); padding-block: var(--unit-500);
}
.rodape__titulo {
  margin: 0 0 var(--unit-200);
  font-size: var(--text-body-size); font-weight: var(--weight-bold); color: var(--text-negative);
}
.rodape__lista { margin: 0; padding: 0; list-style: none; columns: 2; column-gap: var(--unit-200); }
.rodape__lista li { margin-block-end: var(--unit-50); break-inside: avoid; }
/* Sem `opacity`: ela reduz o contraste medido sem aparecer na medição da
   cor declarada, e a legenda do rodapé é 12 regular sobre a marca — já
   está em 4,73, e um véu de 10% a jogaria abaixo dos 4,5. */
.rodape__legenda { font-size: var(--text-caption-size); line-height: var(--text-caption-line); color: var(--text-negative); }

.rodape__parceiros { display: flex; flex-wrap: wrap; gap: var(--unit-150); }
/* O mesmo desenho do disco da vitrine, na medida do rodapé. O `span` de fora
   só existe para carregar o `title`: o disco é o de dentro, e é nele que a
   máscara mora. */
.rodape__parceiro { display: grid; }
.rodape__parceiro-disco {
  width: 2.75rem; height: 2.75rem; border-radius: var(--border-full);
  background-color: color-mix(in srgb, var(--surface-raised) 25%, transparent);
  display: grid; place-items: center;
  color: var(--text-negative); font-weight: var(--weight-bold);
  font-size: var(--text-caption-size);
  overflow: hidden;
}

.rodape__fecho {
  background-color: var(--brand-primary-bold);
  padding-block: var(--unit-300);
  display: grid; gap: var(--unit-100); justify-items: center; text-align: center;
}
.rodape__marca img { height: 1.5rem; }

/* =========================================================================
   9. Telefone
   =========================================================================
   O corte é 900: abaixo dele o painel do produto não cabe ao lado da arte
   sem espremer o nome a duas palavras por linha. */

.telefone-so { display: none; }

@media (max-width: 900px) {
  .desktop-so { display: none !important; }
  .telefone-so { display: initial; }

  .faixa { padding-inline: var(--unit-200); }

  .topo__linha { min-height: 3.5rem; gap: var(--unit-150); flex-wrap: wrap; }
  .topo__busca { order: 3; flex-basis: 100%; }
  /* O saldo NÃO some no telefone. Numa loja de pontos ele é o dado que
     decide se a pessoa pode resgatar — escondê-lo para poupar largura é
     esconder o preço. Ele desce para depois da marca e o grupo de ícones
     vai para a ponta. */
  /* O saldo não estica: a sobra da linha é do endereço, que é o texto que
     cresce. A palavra "Saldo" sai — o ícone de carteira já diz o que é o
     número, e são 45px que o endereço usa para caber. */
  .saldo { order: 2; flex: none; justify-content: center; }
  .topo__conta { margin-inline-start: auto; order: 1; }

  /* O cabeçalho do telefone gruda no topo — mas encolhendo. Parado, ele tem
     três linhas e comeria um quarto da tela; rolado, ficam só a marca, os
     ícones e a busca, e a faixa fixa mede 112. O que sai — endereço, saldo e
     a faixa azul — é leitura de chegada, e volta assim que se volta ao topo. */
  /* As três peças que saem ENCOLHEM, e não somem de um quadro para o outro:
     a altura vai a zero junto com a opacidade, e a faixa fixa desce ao
     tamanho novo no mesmo movimento. As regras estão no fim do arquivo,
     junto da explicação do `interpolate-size`. */

  .produto { grid-template-columns: minmax(0, 1fr); }
  .produto__miniaturas { grid-auto-flow: column; grid-auto-columns: 3.5rem; justify-content: start; order: 2; }
  .produto__palco { order: 1; }
  .produto__painel { order: 3; }

  .checkout, .contas, .gift-pagina, .conclusao { grid-template-columns: minmax(0, 1fr); }
  /* A pilha, na ordem em que se lê: nome, cartão, descrição e valores,
     utilidades e, por último, a decisão. */
  .gift-pagina { grid-template-areas: "cabeca" "arte" "texto" "extras" "resumo"; }
  .gift-pagina__arte { max-inline-size: 22rem; }
  .resumo { position: static; }

  .linha-item { grid-template-columns: 4rem minmax(0, 1fr); }
  .linha-item__arte { width: 4rem; }
  .linha-item .quantidade, .linha-item__fim { grid-column: 2; justify-items: start; }

  .formulario { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .formulario__campo--3, .formulario__campo--4, .formulario__campo--5, .formulario__campo--6 { grid-column: 1 / -1; }

  .cartao-form { grid-template-columns: minmax(0, 1fr); }

  /* No telefone a faixa fica só com a porta e a ação: "Todas as categorias"
     e "Pagar boleto". As categorias, Gift card e Lojas parceiras estão no
     menu de Todas as categorias — os arquivos `mobile/1.0 Home*.svg` não têm a faixa inteira, e
     ela empilharia quatro linhas de caixa alta azul. */
  .categorias__principais,
  .categorias__fim > .categorias__item,
  .categorias__fim > .previa--lojas { display: none; }

  /* Em 375 a porta (193) e o boleto (171) não cabem lado a lado com as
     margens: medido, a página estourava. Aqui a faixa volta a quebrar, e a
     porta perde o fio, que só separa algo quando há categorias ao lado. */
  .categorias__linha { flex-wrap: wrap; justify-content: space-between; gap: 0 var(--unit-200); }
  .categorias__boleto { display: none; }
  /* O compacto tem 40 de altura, e aqui ele é botão de dedo: sobe ao piso
     de alvo sem virar o botão de 56, que dobraria a faixa. */
  .categorias__gift { display: inline-flex; min-block-size: 2.75rem; }
  .categorias__todas { padding-inline-end: 0; box-shadow: none; }

  /* O endereço fica só com o ícone e desce para a linha do SALDO: ele diz
     PARA ONDE a compra vai e o saldo diz COM QUANTO — a mesma pergunta,
     lado a lado. Em cima ele disputava a linha com os três ícones da conta.
     O rótulo continua lido por leitor de tela. A marca estica para empurrar
     os ícones ao fim da primeira linha, e é isso que garante a quebra. */
  .topo__endereco { order: 2; flex: 1 1 auto; min-width: 0; }

  /* A prévia do endereço, no telefone, ancora na LINHA do cabeçalho e não no
     botão: o botão fica no meio da tela, e o Popup, virando para o fim,
     começava em −102px — um terço da lista fora da tela. Com 16 de cada
     lado ela ocupa a largura útil, que é o que a lista de endereços pede. */
  .previa--endereco { order: 2; position: static; min-width: 0; }
  .topo__linha { position: relative; }
  .previa--endereco .sysvc-popup__surface,
  .previa--endereco .sysvc-popup__surface[data-align="end"] {
    inset-inline: var(--unit-200);
    /* Logo abaixo da primeira linha do cabeçalho (marca e ícones, 56), e não
       da linha inteira: medido, ela abria em 260, embaixo da busca. */
    inset-block-start: calc(3.5rem + var(--popup-gap));
    /* A largura sai dos dois recuos. Sem zerar as medidas do Popup, a lista
       impunha a dela e passava 25px da borda. */
    inline-size: auto;
    min-inline-size: 0;
    max-inline-size: none;
  }
  /* O rótulo aparece: um alfinete sozinho não diz que falta um endereço, e
     é justamente no telefone que essa é a primeira decisão da compra. O que
     não couber vira reticência — o Popup ao lado mostra o endereço inteiro. */
  .topo__endereco-rotulo {
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  .campanha__slide { min-height: 12rem; padding: var(--unit-300); }
  .campanha__titulo { font-size: var(--heading-lg-size); line-height: var(--heading-lg-line); }
  .campanha__seta { display: none; }

  .rastreio__rotulo { font-size: 0.6875rem; }
}

/* A pilha de avisos. Fica no canto, acima de tudo. */
.avisos {
  position: fixed; inset-block-end: var(--unit-300); inset-inline-end: var(--unit-300);
  z-index: var(--level-tooltip);
  display: grid; gap: var(--unit-100); justify-items: end;
  pointer-events: none;
}
.avisos > * { pointer-events: auto; }


/* =========================================================================
   PAINEL DO CLIENTE
   =========================================================================
   Três áreas: menu | corpo | painel. Os números são os tokens dos
   breakpoints com navegação e painel (tokens.css 1.0.2):

     breakpoint.hd-painel      980 – 1366   menu 240   painel 288   margem 32   gutter 16
     breakpoint.fullhd-painel  1367 +       menu 320   painel 320   margem 48   gutter 24

   Menu e painel ficam fora do grid; a margem é a do corpo, entre os dois.
   Abaixo de 980 não há navegação persistente: as três áreas empilham, e o
   corpo volta à margem da faixa (16 no celular, 32 no tablet).
   ========================================================================= */

.painel-cliente {
  --pc-menu: var(--menu-width-hd);
  --pc-painel: var(--panel-width-hd);
  --pc-margem: var(--grid-hd-painel-margin);
  --pc-gutter: var(--grid-hd-painel-gutter);
  display: grid;
  grid-template-columns: var(--pc-menu) minmax(0, 1fr) var(--pc-painel);
  align-items: stretch;
  min-block-size: 70vh;
  box-shadow: inset 0 1px 0 0 var(--border-subtle);
}
@media (min-width: 85.4375rem) {
  .loja .painel-cliente {
    --pc-menu: var(--menu-width-fullhd);
    --pc-painel: var(--panel-width-fullhd);
    --pc-margem: var(--grid-fullhd-painel-margin);
    --pc-gutter: var(--grid-fullhd-painel-gutter);
  }
}

/* Menu: a base do menu lateral do admin — superfície elevada, 16 de folga
   por dentro, item de 48 com raio. */
.painel-cliente__menu {
  /* Fixo na rolagem, logo abaixo do cabeçalho — como o menu do admin, que
     gruda abaixo da barra. --topo-altura é medida em montarCasca(). Mais alto
     que a janela, rola por dentro. */
  position: sticky; inset-block-start: var(--topo-altura, 0px);
  align-self: start;
  /* A altura dos itens, com teto na janela. Com a altura da janela inteira o
     menu era empurrado para fora assim que o painel acabava — numa página
     curta, a 180 de rolagem —, mesmo com os itens ocupando um terço dela. */
  max-block-size: calc(100vh - var(--topo-altura, 0px));
  overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: var(--unit-200);
  padding-block: var(--unit-300);
}
/* O painel vai até o rodapé. Nas outras telas o rodapé abre com 64 de
   respiro; aqui esse vão cortava a coluna do menu antes do fim. O conteúdo
   cresce para ocupar a sobra da janela, e o painel cresce junto. */
.loja:has(.painel-cliente) .rodape { margin-block-start: 0; }
/* O `main` tem 24 em cima e 48 embaixo para as telas comuns; eram esses 48
   que ainda separavam o painel do rodapé. Aqui o painel encosta no cabeçalho
   e no rodapé — o respiro fica por dentro dele. */
.loja:has(.painel-cliente) #conteudo { flex: 1 0 auto; display: flex; flex-direction: column; padding-block: 0; }
.loja .painel-cliente { flex: 1 0 auto; }

/* A coluna do menu continua branca e com o fio até o fim do painel: quem pinta
   é o próprio painel, e não o menu, que agora tem só a altura dos itens. */
.painel-cliente {
  background-image: linear-gradient(to right,
    var(--surface-raised) calc(var(--pc-menu) - 1px),
    var(--border-subtle) calc(var(--pc-menu) - 1px) var(--pc-menu),
    transparent var(--pc-menu));
}
.painel-cliente__quem { padding-inline: var(--unit-400); }
.painel-cliente__nome {
  margin: 0; font-size: var(--scale-size-0); line-height: var(--scale-height-0); /* 16/22 — um degrau acima do 14 do título de popup */
  font-weight: var(--popup-title-weight); color: var(--popup-title-color);
}
.painel-cliente__email {
  margin: 0; font-size: var(--popup-message-size); line-height: var(--popup-message-line);
  color: var(--text-subtle); overflow-wrap: anywhere;
}
.painel-cliente__menu .sysvc-menu { padding-inline: var(--unit-200); }
.painel-cliente__menu .sysvc-menu-item { min-height: 3rem; border-radius: var(--border-50); text-decoration: none; }

/* Corpo: a margem do breakpoint -painel. As telas trazem uma .faixa por
   dentro; aqui ela não repete margem nenhuma. */
/* O ritmo vertical do painel mora AQUI, e não em `style=` de cada tela: 32
   (unit.400) acima do título, 24 (unit.300) entre o título e o conteúdo, e
   64 (unit.800) antes do rodapé. Antes cada tela trazia a própria margem, e
   elas discordavam entre si. */
.painel-cliente__corpo {
  min-width: 0;
  padding: var(--unit-400) var(--pc-margem) var(--unit-800);
}
.painel-cliente__corpo .faixa { max-width: none; padding-inline: 0; }
.painel-cliente__corpo > .faixa,
.painel-cliente__corpo > .faixa > .secao { margin-block-start: 0 !important; }

/* Título da página: o mesmo do admin (.pagina__titulo) — Heading xxl, cor
   do corpo (--text-body), e não o azul do título de seção da loja. */
.painel-cliente .painel-cliente__titulo {
  color: var(--text-body);
  /* O vão entre título e conteúdo, num token só (24). O admin usa 16 num
     título que vem seguido de texto de apoio; aqui o que vem embaixo é
     controle — filtro, lista, tabela —, e 16 encostava demais. */
  margin-block-end: var(--unit-300);
}

/* Filtro do extrato: os grupos um embaixo do outro, e não na grade de
   colunas do filtro da lista — são três recortes de naturezas diferentes
   (quando, o quê, quanto mostrar), lidos um a um. */
/* O conteúdo do filtro flutua sobre a tabela, como o painel de filtro do
   admin: posicionado contra o bloco, largura da coluna, e a sombra dizendo
   que está ACIMA — encostado na tabela e sem sombra, os dois leriam como
   uma peça só. */
/* O bloco do filtro é a referência do painel flutuante, nas duas telas que
   têm filtro: a lista de produtos e o extrato. */
.filtros { position: relative; }

/* Aberto, este gatilho NÃO engorda. O Accordion cresce de 48 para 64 quando
   o cabeçalho expande (--accordion-open-height, padding de 12), porque ali o
   painel mora dentro do cartão e ele deixa de ser uma linha. Aqui o painel
   flutua, e o cartão continua sendo só o gatilho: os 16 a mais empurravam a
   tabela para baixo toda vez que o filtro abria — justamente o que o painel
   flutuante veio evitar.

   A regra é a mesma que o sistema já usa na variante --form ("aberto, o
   cabeçalho do formulário não engorda: quem cresce é o painel"), com os
   tokens do estado fechado. */
.filtro-flutuante__gatilho:has(.sysvc-accordion__header[aria-expanded="true"]) > .sysvc-accordion__header {
  min-height: calc(var(--accordion-height) - var(--accordion-border) * 2);
  padding-block: var(--accordion-padding-block);
}
.filtro-flutuante__superficie {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100% + var(--unit-100));
  z-index: var(--level-card);
  padding: var(--unit-300);
  border-radius: var(--border-100);
  background-color: var(--surface-raised);
  box-shadow: var(--shadow-overlay);
}
.filtro-flutuante__superficie[hidden] { display: none; }

.filtros__grade--vertical { grid-template-columns: minmax(0, 1fr); gap: var(--unit-250); }
/* Um divisor entre as categorias de filtro. Contorno por sombra interna,
   como no resto do sistema — uma borda mudaria a caixa do fieldset.

   O fio fica no FIM do grupo anterior, e não no começo do seguinte: o
   navegador desenha a <legend> sobre a borda superior do fieldset, e uma
   linha ali cortava o rótulo ao meio ("ENTRADA", "MOSTRAR POR VEZ"). No fim
   do grupo não há legenda nenhuma, e a linha cai no vão entre os dois. */
.filtros__grade--vertical .filtros__grupo:not(:last-of-type) {
  padding-block-end: var(--unit-250);
  box-shadow: inset 0 -1px 0 0 var(--border-subtle);
}
/* A linha dos botões não tem legenda: aqui o fio pode vir em cima. */
.filtros__grade--vertical .filtros__acoes {
  padding-block-start: var(--unit-250);
  box-shadow: inset 0 1px 0 0 var(--border-subtle);
}
/* Os dois campos de data e o dropdown têm teto de leitura: esticados na
   largura da tabela, viram caixas grandes demais para o que pedem. */
.filtros__grade--vertical .filtros__faixa { max-inline-size: 28rem; }
.filtros__grade--vertical .filtros__faixa-unica { max-inline-size: 28rem; }
.filtros__dropdown { inline-size: min(16rem, 100%); }
/* A contagem entre o filtro e a tabela. */
.extrato-conta { margin-block: 0 var(--unit-150); }

/* Painel direito: o .resumo das telas existentes na MESMA composição de
   antes — cartão com raio e contorno, da altura do conteúdo, grudado na
   rolagem abaixo do cabeçalho. Não é barra de ponta a ponta: a coluna do
   painel leva também a margem do breakpoint, e o cartão mantém a largura do
   painel (288 / 320) sem encostar na borda da janela. */
.painel-cliente {
  grid-template-columns: var(--pc-menu) minmax(0, 1fr) calc(var(--pc-painel) + var(--pc-margem));
}
.painel-cliente .painel-cliente__lateral,
.painel-cliente .conclusao__lateral {
  align-self: start;
  inset-block-start: calc(var(--topo-altura, 0px) + var(--unit-300));
  margin-block-start: var(--unit-300);
  margin-inline-end: var(--pc-margem);
}

/* Detalhe do pedido: a conclusão tem o próprio painel. O corpo ocupa meio e
   painel, e a grade da conclusão reproduz a coluna do painel. */
.painel-cliente__corpo--com-painel { grid-column: 2 / -1; padding: 0; }
.painel-cliente__corpo--com-painel > .faixa { margin-block-start: 0 !important; }
.painel-cliente .conclusao {
  grid-template-columns: minmax(0, 1fr) calc(var(--pc-painel) + var(--pc-margem));
  gap: 0; align-items: start;
}
.painel-cliente .conclusao__principal {
  align-content: start;
  padding: var(--unit-300) var(--pc-margem) var(--unit-800);
}

/* Sem navegação persistente (abaixo de 980): tudo empilha. */
@media (max-width: 61.1875rem) {
  .painel-cliente { grid-template-columns: minmax(0, 1fr); box-shadow: none; background-image: none; }
  /* Empilhado, o menu é um bloco no topo: nada de grudar nem de ter a altura
     da janela. */
  .painel-cliente__menu {
    position: static; block-size: auto; overflow: visible;
    box-shadow: inset 0 -1px 0 0 var(--border-subtle);
  }
  .painel-cliente__corpo { padding-inline: var(--faixa-margem, var(--unit-200)); }
  .painel-cliente__corpo--com-painel { grid-column: auto; padding: 0; }
  .painel-cliente .conclusao { grid-template-columns: minmax(0, 1fr); }
  .painel-cliente .conclusao__principal { padding-inline: var(--faixa-margem, var(--unit-200)); }
  .painel-cliente .painel-cliente__lateral,
  .painel-cliente .conclusao__lateral {
    position: static;
    margin: 0 var(--faixa-margem, var(--unit-200)) var(--unit-400);
  }
}

/* Filtro em colunas (em teste em Meus pedidos).
   Os checklists correm na HORIZONTAL, quebrando linha quando faltar
   espaço: são poucas opções curtas, e em pé ocupavam a altura do painel.
   As categorias ficam em uma coluna até o HD e em duas no FullHD, onde a
   superfície é larga o bastante para dois grupos lado a lado. A linha dos
   botões ocupa sempre a largura toda. */
.filtros__grade--colunas .sysvc-checkbox-group {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--unit-150) var(--unit-300);
}
@media (min-width: 85.4375rem) {
  .loja .filtros__grade--colunas {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--unit-400);
  }
  .loja .filtros__grade--colunas .filtros__acoes { grid-column: 1 / -1; }
  /* Categoria que sobra sozinha na última linha estende até o fim. */
  .loja .filtros__grade--colunas .filtros__grupo:last-of-type:nth-of-type(odd) { grid-column: 1 / -1; }
  /* Em duas colunas o fio de baixo
     sai de toda a última linha — um grupo sozinho ou os dois do par. */
  .loja .filtros__grade--colunas .filtros__grupo:nth-last-of-type(2):nth-of-type(odd),
  .loja .filtros__grade--colunas .filtros__grupo:last-of-type {
    padding-block-end: 0;
    box-shadow: none;
  }
}
/* Botões à esquerda, com a ação principal (Filtrar) primeiro: começam na
   mesma margem em que a leitura das categorias começa. */
.filtros__grade--colunas .filtros__acoes { justify-content: flex-start; }

/* Cartão de pedido: o componente foi para o sistema (sys-order-card.css).
   Aqui fica só o logotipo do gift card, que é peça da loja. */
.sysvc-order-card__media--brand .gift-logo { inline-size: 78%; padding: var(--unit-50); border-radius: var(--border-50); }

/* "Meu painel": o rótulo do menu lateral, acima de quem está logado. */
.painel-cliente__titulo-menu { margin: 0 0 var(--unit-150); padding-inline: var(--unit-400); }
/* Baixar extrato: abaixo da tabela. */
.extrato-baixar { margin-block-start: var(--unit-300); }

/* Meus dados — Cartões do sistema, um por assunto. O titular vem primeiro
   e com o maior corpo da tela: é a resposta para "esta conta é minha?". */
.dados__pessoa,
.dados__bloco { margin-block-end: var(--unit-300); }
.dados__pessoa { display: grid; gap: var(--unit-50); }
.dados__nome {
  margin: var(--unit-50) 0 0;
  font-size: var(--scale-size-2); line-height: var(--scale-height-2);
  font-weight: var(--weight-bold); color: var(--text-title);
}
.dados__email { margin: 0; font-size: var(--scale-size-0); line-height: var(--scale-height-0); color: var(--text-body); overflow-wrap: anywhere; }
.dados__cabeca {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--unit-100) var(--unit-200); margin-block-end: var(--unit-200);
}
.dados__cabeca .secao__titulo { margin: 0; }
.dados__acoes { margin-block-start: var(--unit-200); justify-content: flex-start; }
.dados__padrao { margin-inline-start: var(--unit-100); vertical-align: middle; }

/* Trilha dentro do painel (formulários de Meus dados): 24 até o título,
   o mesmo degrau entre título e conteúdo. */
.painel-cliente__corpo > .trilha { margin-block-end: var(--unit-300); }

/* Ajuda do CVV: o popup abre alinhado à direita do ícone, que fica na borda
   do campo, para não sair da coluna. */
.cvv-ajuda .sysvc-popup__surface { inset-inline-start: auto; inset-inline-end: 0; }

/* No telefone a superfície tem 320 fixos e se alinha pela direita do ícone,
   que fica a 48 da borda (16 da margem da página mais o recuo do painel).
   320 a partir dali começa a 7px da tela: dentro, mas por cima da margem de
   navegação. O teto passa a ser a largura da janela menos os 32 das duas
   margens e os 32 que o ícone já está para dentro — assim a ponta esquerda
   para exatamente na margem. */
@media (max-width: 47.9375rem) {
  .cvv-ajuda .sysvc-popup__surface { max-inline-size: calc(100vw - var(--unit-800)); }
}

/* Sair da conta: token de perigo (text.danger) no rótulo e no ícone, nos
   dois menus. O divisor separa a ação do resto da navegação. */
.sair,
.sair .sysvc-popup__item-icon,
.sair .sysvc-menu-item__icon { color: var(--text-danger); }
button.sair { inline-size: 100%; border: 0; background: none; font: inherit; text-align: start; cursor: pointer; }
.sysvc-popup__surface .sair__divisor { margin-inline: calc(var(--popup-padding) * -1); }

/* Legenda de Meus dados: diz que os botões agem sobre a opção marcada. */
.dados__legenda { margin: calc(var(--unit-100) * -1) 0 var(--unit-200); }

/* Excluir endereço: abaixo do formulário de edição, separado do Salvar. */
.endereco-excluir { margin-block-start: var(--unit-300); justify-content: flex-start; }

/* Sair da conta: o hover também é de perigo, e não o cinza neutro do item
   de menu — a ação é de perigo do começo ao fim. */
.sair:hover { background-color: var(--button-surface-danger-wash-hovered); }
.sair:active { background-color: var(--button-surface-danger-wash-pressed); }

/* Verificação do cartão e confirmação: coluna de leitura, marca de
   carregamento à esquerda do texto de espera. */
.verificacao { display: grid; gap: var(--unit-200); max-inline-size: 40rem; }
.verificacao > .sysvc-text { margin: 0; }
.verificacao__corpo { display: grid; justify-items: start; gap: var(--unit-200); }
.verificacao__corpo > .sysvc-text { margin: 0; }
.verificacao__acoes { margin-block-start: var(--unit-100); }

/* =========================================================================
   Mobile (abaixo de 768)
   ========================================================================= */

/* Menu do painel: o Dropdown só aparece no celular. */
.painel-cliente__seletor { display: none; }
/* Status em Dropdown de itens de menu: também só no celular. */
.status-menu { display: none; }
/* Grade ou lista, em qualquer largura: o alternador mora na coluna de
   ordenar e filtrar, e o que ele faz — uma coluna de cartões deitados no
   lugar da grade — vale tanto na tela larga quanto no telefone. */
.lista__visao { display: grid; }

@media (max-width: 47.9375rem) {
  .painel-cliente__seletor { display: block; padding-inline: var(--unit-200); margin-block-end: var(--unit-100); }
  .painel-cliente__menu .sysvc-menu > a.sysvc-menu-item { display: none; }
  .painel-cliente__titulo-menu { display: none; }

  /* Botões do filtro preenchem a largura, divididos por igual. */
  .filtros__acoes > .sysvc-button { flex: 1 1 0; }

  .status-caixas { display: none; }
  .status-menu { display: block; }

  /* Extrato: a tabela rola para o lado e a coluna de data fica parada. */
  .extrato-tabela { min-inline-size: 34rem; }
  .extrato-tabela .sysvc-table__head,
  .extrato-tabela .sysvc-table__cell { white-space: nowrap; }
  .extrato-tabela .sysvc-table__head:first-child,
  .extrato-tabela .sysvc-table__cell:first-child {
    position: sticky; inset-inline-start: 0; z-index: 1;
    /* A borda de coluna some quando a célula gruda; a sombra interna
       desenha a divisória por cima do que passa por baixo. */
    box-shadow: inset -1px 0 0 0 var(--table-border);
  }
  .extrato-tabela .sysvc-table__head:first-child { background-color: var(--table-header-surface); }
  .extrato-tabela .sysvc-table__cell:first-child { background-color: var(--table-surface); }
}

@media (max-width: 47.9375rem) {
  /* Grade de produtos em duas colunas no celular (os gift cards seguem com
     a própria grade). */
  .grade:not(.grade--lista):not(.grade--gift) { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--unit-150); }

  /* Botões empilhados, na largura toda, sempre que houver mais de um lado
     a lado: no polegar, alvo largo vale mais que economia de altura. A
     ordem é a do HTML — a ação principal primeiro. */
  .sysvc-button-group:not(.sysvc-button-group--block),
  .filtros__acoes {
    display: flex; flex-direction: column; align-items: stretch;
  }
  .sysvc-button-group > .sysvc-button,
  .filtros__acoes > .sysvc-button { inline-size: 100%; flex: 0 0 auto; justify-content: center; }

  /* O alternador ocupa a largura da tela. */
  .lista__visao { max-inline-size: none; }

  /* Sair vai para dentro do Dropdown de Meu painel. */
  .painel-cliente__menu .sysvc-menu { display: none; }
}


/* =========================================================================
   Alvo de toque — o piso do sistema, aplicado às peças locais

   O sistema fixou 44 no ponteiro e 48 no toque, e as peças do sys-vc já
   sobem sozinhas em (pointer: coarse). As classes daqui precisam da mesma
   regra: quem tem 44 escrito no arquivo sobe para 48 quando o dedo é o
   ponteiro. Vale em qualquer largura — quem decide é o apontador, e não o
   tamanho da janela: um tablet largo continua sendo dedo.
   ========================================================================= */
@media (pointer: coarse) {
  .topo__marca,
  .topo__endereco,
  .categorias__item,
  .previa__linha,
  .previa__movimento,
  .categorias__gift { min-block-size: 3rem; }
  /* O campo da quantidade NÃO sobe: ele fica entre dois Icon Buttons, que
     têm 44 nos dois apontadores. Subir só ele desalinharia a fileira. */
}


/* =========================================================================
   O cabeçalho do telefone é uma GRADE, e não uma linha que quebra

   São três linhas com um par em cada uma:
     marca ....... ícones da conta
     endereço .... saldo
     busca (largura inteira)

   Em flex isso não se escreve: quebrar por ordem colocaria marca, endereço e
   ícones na mesma linha, e forçar o endereço para baixo com base 0 o
   espremia a 6px na sobra da primeira. O par de cada linha não é vizinho no
   HTML — quem decide onde cada um cai é a grade, com áreas nomeadas.

   Os blocos do cabeçalho viram display:contents para que os cinco itens
   sejam filhos diretos da grade.
   ========================================================================= */
@media (max-width: 47.9375rem) {
  .topo .topo__linha {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "marca    conta"
      "endereco saldo"
      "busca    busca";
    row-gap: var(--unit-150);
    column-gap: var(--unit-150);
  }
  .topo .topo__bloco { display: contents; }

  .topo .topo__marca { grid-area: marca; justify-self: start; }
  .topo .topo__conta { grid-area: conta; margin-inline-start: 0; }
  .topo .previa--endereco { grid-area: endereco; min-width: 0; }
  /* A pílula aperta os recuos no telefone: cada pixel que ela devolve é
     pixel de rótulo do endereço, que é texto e trunca. O número e o olho
     não mudam de tamanho. */
  .topo .saldo {
    grid-area: saldo; flex: none; justify-self: end;
    gap: var(--unit-50);
    /* À direita quem encosta na borda é o disco de 44 do olho, com 4 de
       recuo: o glifo de 24 fica a 14 da borda da pílula. À esquerda não há
       disco, então o recuo tem de valer os mesmos 14 para os dois ícones
       respirarem igual. */
    padding: var(--unit-50) 0 var(--unit-50) var(--unit-150);
  }
  /* A palavra Saldo sai só no telefone: o ícone de carteira já diz o que é
     o número, e são 45px que vão para o rótulo do endereço ao lado. */
  .topo .saldo .saldo__rotulo { display: none; }
  .topo .topo__busca { grid-area: busca; }

  /* O endereço ocupa a coluna que sobra e o que não couber vira reticência:
     o texto cresce com o endereço salvo, e o número do saldo não encolhe. */
  /* Vão de 4 entre o alfinete e o texto, e não 8: em 375 o rótulo inteiro
     cabia por zero pixel, e uma fonte meio ponto mais larga o truncaria. */
  .topo .topo__endereco { display: flex; min-width: 0; gap: var(--unit-50); }
  .topo .topo__endereco-rotulo {
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
}

/* =========================================================================
   Sugestões da busca

   A superfície do Popup, mas com a largura do CAMPO: aqui ela não é um menu
   ao lado de um gatilho pequeno, é a continuação da caixa em que se digita,
   e uma largura própria a faria parecer outra coisa flutuando por perto.
   ========================================================================= */
/* O invólucro não ancora a superfície: quem ancora é o formulário, para
   que a lista tenha a largura do campo MAIS o botão de buscar. Presa ao
   campo, ela parava antes da lupa e o pé cortava o rótulo em duas linhas. */
.busca-sugestoes { flex: 1; min-inline-size: 0; position: static; }
.topo__busca { position: relative; }
.busca-sugestoes__superficie {
  inset-inline: 0;
  inline-size: auto; min-inline-size: 0; max-inline-size: none;
  display: grid; gap: var(--unit-100);
  padding: var(--unit-100);
}

.busca-sugestoes__termo { inline-size: 100%; text-align: start; }
/* O digitado fica normal e o que a sugestão acrescenta fica em negrito. */
.busca-sugestoes__digitado { font-weight: var(--weight-regular); }
.busca-sugestoes__termo .sysvc-menu-item__label { font-weight: var(--weight-bold); }

/* Fio entre os termos e os produtos: são duas respostas diferentes à mesma
   digitação — completar a palavra e ir ao produto. */
.busca-sugestoes__produtos {
  display: grid;
  padding-block-start: var(--unit-100);
  box-shadow: inset 0 1px 0 0 var(--border-subtle);
}
.busca-sugestoes .previa__linha { padding-inline: var(--unit-100); }
.busca-sugestoes .previa__ir { inline-size: 100%; justify-content: center; }

/* Limpar a busca: centralizado na caixa, como a lupa do outro lado — os
   dois ícones do campo se olham na mesma altura. Nada de alinhamento
   próprio: a caixa do campo já centraliza.

   Vale no telefone também. O X do teclado do sistema só aparece em alguns
   navegadores e some com o teclado fechado; um botão do desenho está sempre
   lá, e no dedo apagar palavra por palavra é justamente o que mais custa. */

/* =========================================================================
   Esqueleto — agora do sistema

   As peças (.sysvc-skeleton) foram para o sys.vc, §41 dos tokens e
   sys-skeleton.css. Aqui ficam só os ARRANJOS: a forma que as peças tomam
   nas sugestões da busca e nos menus flutuantes do cabeçalho — que é o que
   pertence a esta loja, e não ao sistema.
   ========================================================================= */

.busca-esqueleto { display: grid; gap: var(--unit-100); }
.busca-esqueleto__termo {
  display: flex; align-items: center; gap: var(--unit-150);
  /* 52, que é a altura medida do Item de menu com o rótulo dentro — e não
     o piso de 44: é a linha real que o esqueleto está imitando. */
  min-block-size: 3.25rem; padding-inline: var(--unit-150);
}
.busca-esqueleto__produto {
  display: flex; align-items: center; gap: var(--unit-150);
  padding-block: var(--unit-100); padding-inline: var(--unit-100);
}
.busca-esqueleto__texto { flex: 1; min-inline-size: 0; display: grid; gap: var(--unit-50); }

/* A linha de um menu flutuante esperando: a vaga da foto (ou do ícone), o
   texto e o valor. Repete a geometria da linha de prévia de verdade — 40 de
   arte e 56 de linha —, então o menu não muda de tamanho quando o conteúdo
   chega. */
.menu-esqueleto { display: grid; gap: var(--unit-100); }
.menu-esqueleto__linha {
  display: flex; align-items: center; gap: var(--unit-150);
  min-block-size: 3.5rem;
}
.menu-esqueleto__linha--alta {
  /* 84: a altura medida do Botão de opção com rótulo e endereço. */
  min-block-size: 5.25rem;
  padding: var(--unit-150);
  border-radius: var(--border-100);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}
.menu-esqueleto__texto { flex: 1; min-inline-size: 0; display: grid; gap: var(--unit-50); }

/* Linha baixa: o item do menu de categorias tem 40, e não 56. */
.menu-esqueleto__linha--baixa { min-block-size: 2.5rem; }

/* O menu de lojas é horizontal: uma coluna por loja, disco em cima. */
.menu-esqueleto-lojas {
  display: grid;
  grid-auto-flow: column;
  justify-content: start;
  gap: var(--unit-300);
  padding-block: var(--unit-200);
}
.menu-esqueleto-lojas__item {
  display: grid; justify-items: center; gap: var(--unit-100);
  inline-size: 7rem;
}

/* O cartão de produto esperando. A grade e a vitrine já dão a coluna: aqui
   só se empilha foto, nome, referência e preço, com os vãos do cartão. */
.esqueleto-cartao {
  display: grid;
  gap: var(--unit-100);
  align-content: start;
  /* O recuo do cartão de verdade: sem ele a foto do esqueleto encostaria na
     borda da coluna e mediria mais que a foto que vai substituí-la. */
  padding: var(--unit-150);
}
.esqueleto-cartao__ref { inline-size: 45%; }
.esqueleto-cartao__preco { inline-size: 5rem; block-size: 1.25rem; }
.esqueleto-cartao__parceiro { inline-size: 60%; }
/* O nome: no desktop entre 160 e 240, vindo de --titulo-largura, e nunca
   mais largo que a coluna. No telefone a coluna mede 166, então a medida
   vira proporção — 240 ali seria a linha inteira em todos os cartões. */
.esqueleto-cartao__titulo { inline-size: min(100%, var(--titulo-largura, 12rem)); }
@media (max-width: 47.9375rem) {
  .esqueleto-cartao__titulo { inline-size: 85%; }
}

/* --- a capa de espera ----------------------------------------------------
   O bloco de verdade fica escondido e a capa entra no lugar dele. Por isso
   a capa herda as classes de layout quando o bloco é grade ou vitrine: as
   peças em cinza precisam cair nas mesmas colunas. */
.esqueleto-capa { min-inline-size: 0; }

/* Um pedido esperando — a geometria do Cartão de pedido. */
.esqueleto-pedidos { display: grid; gap: var(--unit-150); }
.esqueleto-pedido {
  display: flex; align-items: center; gap: var(--unit-200);
  padding: var(--unit-150);
  border-radius: var(--border-100);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  background-color: var(--surface-raised);
}
.esqueleto-pedido__foto { inline-size: 5rem; block-size: 5rem; border-radius: var(--border-50); }
.esqueleto-pedido--compacto .esqueleto-pedido__foto { inline-size: 4rem; block-size: 4rem; }
.esqueleto-pedido__texto { flex: 1; min-inline-size: 0; display: grid; gap: var(--unit-100); }
.esqueleto-pedido__cabecalho { display: flex; align-items: center; gap: var(--unit-150); }

/* A tabela: o cabeçalho continua escrito, e o que espera são as linhas. */
.esqueleto-tabela {
  display: grid;
  grid-template-columns: repeat(var(--colunas, 4), minmax(0, 1fr));
  gap: var(--unit-200) var(--unit-300);
  padding-block: var(--unit-200);
}

/* Texto em bloco: recibo, painel de compra, etapa do checkout, formulário. */
.esqueleto-bloco { display: grid; gap: var(--unit-150); }
.esqueleto-bloco .sysvc-skeleton--title { block-size: var(--unit-300); inline-size: 45%; }


/* A grade do cabeçalho rolado no telefone: sem a linha do endereço e do
   saldo, restam duas — marca com ícones, e a busca embaixo. Sem isto a
   linha vazia continuaria ali, cobrando o vão de 12. */
/* =========================================================================
   O cabeçalho que encolhe ao rolar, sem corte seco

   As peças que saem — endereço, saldo e a faixa azul — encolhem até zero em
   vez de sumirem de um quadro para o outro, e a barra fixa se assenta na
   altura nova no mesmo movimento. A linha da grade some junto, porque uma
   linha de itens com 0 de altura mede 0 — sobra o vão dela, e por isso o
   `row-gap` também anda.

   **O que encolhe é o teto, e não a altura.** `block-size: auto` num item de
   grade esticado continua `auto` para a transição, e o navegador saltava
   direto para 0 — nem `interpolate-size: allow-keywords` resolve, porque
   quem decide a altura ali é a linha da grade, e não a propriedade. Com
   `max-block-size` a medida é uma distância de verdade dos dois lados, e o
   teto empurra a peça para baixo sem pressa. Cada uma tem o teto medido da
   sua altura, para o tempo não sobrar em quem é mais baixo.

   Quem pediu menos movimento recebe o corte, que é o que ele pediu.
   ========================================================================= */
:root { interpolate-size: allow-keywords; }

@media (max-width: 47.9375rem) {
  .topo .previa--endereco,
  .topo .saldo,
  .categorias {
    overflow: hidden;
    transition:
      max-block-size 220ms cubic-bezier(.2, .8, .2, 1),
      opacity 140ms ease;
  }
  /* A faixa azul hospeda dois menus flutuantes, e o recorte que faz ela
     encolher cortava os dois na altura dela — o menu de Todas as categorias
     aparecia rente à faixa, sem sombra e sem o resto da lista, como se não
     fosse camada nenhuma. Parada, a faixa não recorta; ela só passa a
     recortar no instante em que começa a encolher, e devolve o `visible` no
     fim da volta. É o que `allow-discrete` faz: troca o valor no começo de
     uma transição e no fim da outra, e não na metade. */
  .categorias {
    overflow: visible;
    transition:
      max-block-size 220ms cubic-bezier(.2, .8, .2, 1),
      opacity 140ms ease,
      overflow 220ms allow-discrete;
  }
  [data-rolado="true"] .categorias { overflow: hidden; }
  .topo .previa--endereco { max-block-size: 3rem; }   /* 48, medido */
  .topo .saldo            { max-block-size: 3.5rem; } /* 56 */
  .categorias             { max-block-size: 3rem; }   /* 48 */
  .topo .topo__linha { transition: row-gap 220ms cubic-bezier(.2, .8, .2, 1); }

  [data-rolado="true"] .topo .previa--endereco,
  [data-rolado="true"] .topo .saldo,
  [data-rolado="true"] .categorias {
    max-block-size: 0;
    opacity: 0;
    /* A pílula do saldo tem contorno: sem apagar a borda, sobra um fio de
       1px atravessando o cabeçalho depois que a altura chega a zero. */
    box-shadow: none;
  }
  [data-rolado="true"] .topo .topo__linha { row-gap: var(--unit-75, 6px); }

  @media (prefers-reduced-motion: reduce) {
    .topo .previa--endereco,
    .topo .saldo,
    .categorias,
    .topo .topo__linha { transition: none; }
  }
}

/* --- a troca do esqueleto pelo conteúdo ---------------------------------
   Um atrás do outro, e não por cima: o esqueleto está no fluxo, e cruzar os
   dois dobraria a altura do bloco no meio da troca. A capa sai em 140ms e o
   conteúdo entra subindo 6px em 200 — o mesmo movimento curto do cabeçalho
   que encolhe. */
.esqueleto-capa {
  opacity: 1;
  transition: opacity 140ms ease;
}
.esqueleto-capa[data-saindo] { opacity: 0; }

.aparecendo { animation: esqueleto-chega 200ms cubic-bezier(.2, .8, .2, 1) both; }
@keyframes esqueleto-chega {
  from { opacity: 0; translate: 0 6px; }
  to   { opacity: 1; translate: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
  .esqueleto-capa { transition: none; }
  .aparecendo { animation: none; }
}

/* =========================================================================
   As prévias do cabeçalho no telefone: presas à LINHA, e não ao ícone

   O Popup vira para o fim quando não cabe, mas os três ícones ficam na
   ponta direita de uma tela de 375: virando, a superfície de 320 começava
   fora da tela pela esquerda — foi o que o print mostrou. A regra é a mesma
   que o endereço já usava: a prévia deixa de ser o bloco de referência, a
   superfície ancora na linha do cabeçalho e ocupa a largura útil, com os
   16 do breakpoint de cada lado.

   Vale também como regra geral desta loja: no telefone nada rola para o
   lado, salvo carrossel — a vitrine e a tabela do extrato, que são os dois
   casos em que rolar É a leitura.
   ========================================================================= */
@media (max-width: 47.9375rem) {
  .topo__conta .previa { position: static; }
  .topo__conta .previa__superficie,
  .topo__conta .previa__superficie[data-align="end"] {
    inset-inline: var(--unit-200);
    /* Abaixo da primeira linha do cabeçalho (marca e ícones, 56). */
    inset-block-start: calc(3.5rem + var(--popup-gap));
    inline-size: auto;
    min-inline-size: 0;
    max-inline-size: none;
  }
}

/* Lojas parceiras no telefone — a regra pronta, para o dia em que o botão
   voltar à faixa. Hoje ele está escondido até 900 (o caminho para as lojas
   é o item dentro de Todas as categorias, que leva à página), então nada
   disto pinta na tela; está escrito para o menu já nascer alinhado como os
   outros, e não de novo colado ao botão.

   Diferença para o desktop: lá a superfície é uma faixa de borda a borda,
   com as lojas alinhadas ao conteúdo por dentro; em 375 uma faixa inteira
   sem raio parece um segundo cabeçalho, e as oito lojas numa linha só
   rolariam para o lado — que é o que esta loja não faz no telefone, salvo
   carrossel. Aqui ela vira um menu como os outros: 16 de cada lado, raio do
   Popup, e as lojas em grade de quatro colunas, que cabem nos 343. */
@media (max-width: 47.9375rem) {
  .categorias .previa--lojas .menu-lojas,
  .categorias .previa--lojas .menu-lojas[data-align="end"] {
    inset-inline: var(--unit-200);
    inset-block-start: calc(100% + var(--popup-gap));
    inline-size: auto;
    padding: var(--unit-200) 0;
    border-radius: var(--popup-radius);
    box-shadow: inset 0 0 0 var(--popup-stroke) var(--popup-border), var(--shadow-overlay);
  }
  .categorias .previa--lojas .menu-lojas__faixa { padding-inline: var(--unit-200); }
  .categorias .previa--lojas .menu-lojas__lista {
    grid-auto-flow: row;
    /* Três colunas, e não quatro: o disco tem 72, e quatro deles com os
       vãos pedem 336 numa faixa de 311 — a lista voltaria a rolar de lado. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-columns: auto;
    overflow-x: visible;
  }
  .categorias .previa--lojas .menu-lojas__item,
  .categorias .previa--lojas .menu-lojas__lista .parceiro {
    inline-size: auto; min-inline-size: 0;
  }
}

/* =========================================================================
   Produto, carrinho e conclusão no telefone (ajustes de leitura)
   ========================================================================= */

/* A ficha do produto — favorito, nome, referência, loja e preço — é um bloco
   irmão do palco. No desktop ela divide a coluna da direita com o painel de
   compra, na mesma ordem de antes; as áreas dizem isso, e não a ordem do
   HTML. */
.produto {
  grid-template-areas:
    "mini palco ficha"
    "mini palco painel";
  grid-template-rows: auto 1fr;
}
.produto__miniaturas { grid-area: mini; }
.produto__palco { grid-area: palco; }
.produto__ficha { grid-area: ficha; display: grid; gap: var(--unit-200); align-content: start; }
/* Preso à tela de produto: a classe do painel também veste o gift card,
   que não tem áreas nomeadas. Solto, o nome `painel` abria uma coluna
   implícita lá e a arte encolhia até 0 de largura. */
.produto > .produto__painel { grid-area: painel; }

/* A descrição do produto ganha espaço: a coluna do rótulo era 224 fixos,
   largura de tabela larga; num telefone ela comia dois terços da linha e a
   descrição quebrava palavra a palavra. Agora o rótulo ocupa o que precisa
   e o resto é da descrição. */
.detalhes th { width: auto; white-space: nowrap; }
.detalhes td { width: 100%; }

@media (max-width: 47.9375rem) {
  /* A ficha sobe para antes da foto: nome e preço decidem se a foto vale a
     rolagem. Depois vêm as miniaturas e o painel de compra. */
  .produto {
    grid-template-areas: "ficha" "palco" "mini" "painel";
    grid-template-rows: auto;
  }

  /* Rótulo e descrição empilham: lado a lado, em 343, sobra menos de metade
     da linha para o que a pessoa veio ler. */
  .detalhes th, .detalhes td { display: block; width: auto; white-space: normal; }
  /* Recuo igual em cima e embaixo: com o fim zerado, o rótulo encostava na
     borda da faixa cinza e a dupla lia torta. Faixa e descrição ficam cada
     uma com o texto no meio da sua. */
  .detalhes th { box-shadow: none; }

  /* O preço do item sobe para logo abaixo do nome; no fim da linha fica só
     o Remover. */
  /* O bloco de texto do item vira grade: em fluxo normal os vãos saíam da
     entrelinha — 5px entre nome e referência —, e 5 não é medida do
     sistema. Com a grade, nome, referência e preço ficam a 4. */
  /* A foto atravessa as três linhas da coluna de texto e todos os blocos
     alinham pelo topo: antes a altura da foto (64) esticava a primeira
     linha, e o vão entre o texto e a quantidade virava 31 em vez dos 16 da
     grade. */
  .linha-item { align-items: start; }
  .linha-item__arte { grid-row: 1 / -1; }
  .linha-item__texto { display: grid; gap: var(--unit-50); }
  .linha-item__preco { display: block; }

  /* Remover ao LADO da quantidade, e não embaixo dela. São as duas ações da
     linha — mudar quanto e tirar —, e lidas uma sobre a outra pareciam dois
     blocos sem relação, além de gastarem 48 de altura a mais por item.

     A terceira coluna é `auto`: ela mede o botão, e o que sobra fica com o
     texto. Medido a 375: sobram 343 de faixa, e a fila pede 64 + 16 + 144 +
     16 + 90 = 330. */
  .linha-item { grid-template-columns: 4rem minmax(0, 1fr) auto; }
  .linha-item__texto { grid-column: 2 / -1; }
  .linha-item .quantidade { grid-column: 2; }
  .linha-item__fim { grid-column: 3; justify-items: end; align-self: center; }


}

/* No desktop o preço mora na ponta da linha, como sempre. */
@media (min-width: 48rem) {
  .linha-item__preco { display: none; }
}

/* A conclusão no telefone: nada mais largo que a coluna ----------------
   O recibo e o aviso de e-mail são GRADES dentro de uma grade, e item de
   grade nasce com largura mínima igual ao conteúdo: o nome do produto e o
   e-mail do participante empurravam os dois para 435 numa coluna de 343 —
   era isso que fazia a página rolar para o lado e o texto passar da margem.
   Zerar o mínimo devolve a decisão à coluna, e a palavra que não couber
   quebra. É também o que acende a consulta de container do Recibo: abaixo
   de 480 ele empilha rótulo e valor sozinho, que é o desenho dele para
   largura curta. */
.conclusao__principal > *,
.conclusao__lateral > * { min-inline-size: 0; }
.conclusao .sysvc-receipt,
.conclusao .conclusao__email { min-inline-size: 0; }
.conclusao .sysvc-receipt__rotulo,
.conclusao .sysvc-receipt__valor,
.conclusao .sysvc-utility__title,
.conclusao .sysvc-utility__description { min-inline-size: 0; overflow-wrap: anywhere; }
.conclusao .conclusao__item-rotulo > span { min-inline-size: 0; overflow-wrap: anywhere; }

/* --- aviso em linha ------------------------------------------------------
   O Botão de utilidade estático como recado. O tom entra só no ÍCONE: o
   fundo colorido do alerta não existe no sistema, e pintar a caixa aqui
   seria inventar um componente em vez de usar um. */
/* Item de grade nasce com largura mínima de conteúdo: sem zerar, a caixa
   do aviso media mais que a coluna e passava da margem — o mesmo que já
   tinha acontecido com o recibo da conclusão. */
.aviso-linha, .aviso-linha .sysvc-utility { min-inline-size: 0; }
.produto__painel > *, .produto__ficha > *, .resumo > * { min-inline-size: 0; }
/* Sem margem própria: quem espaça é a coluna em que ele cai — o painel do
   produto (16) e o resumo (12). Uma margem aqui somava a esse vão e tirava
   o aviso do ritmo dos dois. */
/* O Botão de utilidade não tem recuo vertical — numa lista, quem dá a
   altura é o item de 56. Como recado, o texto encostava nas bordas da
   caixa: 8 em cima e embaixo. */
/* O ícone acompanha a PRIMEIRA LINHA, e não o meio do bloco. O componente
   centraliza tudo, o que é certo para um item de menu de uma linha; com
   título mais descrição o ícone descia 8 e ficava entre as duas linhas, sem
   apontar para nenhuma. Vale para todo recado da loja — o :has da descrição
   é o que distingue o recado do item de menu, que segue centralizado. */
.aviso-linha .sysvc-utility,
.sysvc-utility--static:has(.sysvc-utility__description) { align-items: flex-start; }

/* O recuo vertical vale para TODO Botão de utilidade estático da loja, e não
   só para o aviso: o componente tem 54 de altura mínima e recuo só nos
   lados, porque numa lista de menu o conteúdo é uma linha e a altura basta.
   Nesta loja ele é usado como RECADO — título mais uma descrição que quebra
   —, e aí o texto passa dos 54 e encosta nas bordas. Com 8 em cima e
   embaixo, o item de uma linha não muda (a altura mínima manda) e o de duas
   ou três respira. */
.sysvc-utility--static { padding-block: var(--unit-100); }
.aviso-linha .sysvc-utility__text { min-inline-size: 0; }
/* No Botão de utilidade a descrição é UMA linha com reticência — lá ela é
   apoio de um item de menu. Como recado, a frase inteira é o recado: aqui
   ela quebra. */
.aviso-linha .sysvc-utility__title,
.aviso-linha .sysvc-utility__description { overflow-wrap: anywhere; }
/* Vale para todo recado da loja, e não só para o aviso: onde o Botão de
   utilidade carrega uma FRASE — o e-mail da conclusão é o caso —, cortar
   com reticência esconde justamente o dado (o endereço de e-mail). Nos
   itens de menu, que são rótulo curto, nada muda. */
/* O título também é UMA linha com reticência no componente, e um recado
   tem título de frase: "Este resgate passa do limite do cartão" virava
   "Este resgate passa do limi…" a 375. Quebra igual à descrição. */
/* Também no painel lateral: "Pagamentos feitos até as 20h compensam no
   mesmo dia útil" é uma FRASE, e numa coluna de 288 ela era cortada com
   reticência — a informação que some é justamente o prazo. Onde o Botão de
   utilidade carrega frase, ela quebra em quantas linhas precisar. */
.aviso-linha .sysvc-utility__title,
.aviso-linha .sysvc-utility__description,
.conclusao__email .sysvc-utility__description,
.resumo .sysvc-utility__description {
  white-space: normal; overflow: visible; text-overflow: clip;
}
.aviso-linha--atencao .sysvc-utility__icon { color: var(--alert-caution-default); }
.aviso-linha--sucesso .sysvc-utility__icon { color: var(--alert-success-default, var(--brand-primary-default)); }
/* O erro pinta o ícone de vermelho, e nada mais: a caixa continua sendo a
   mesma do aviso. Fundo de alerta não existe no sistema, e aqui ele
   competiria com o botão desativado logo abaixo, que é quem carrega a
   consequência da regra. */
.aviso-linha--erro .sysvc-utility__icon { color: var(--alert-danger-default); }

/* O favoritar é um bloco próprio na grade do produto. */
.produto { grid-template-areas:
    "mini palco favoritar"
    "mini palco ficha"
    "mini palco painel";
  grid-template-rows: auto auto 1fr;
  /* A coluna da direita agora são TRÊS blocos empilhados, e o vão entre eles
     é o vão de dentro dela (16), e não o de entre colunas (24): favoritar,
     ficha e painel são um bloco só de leitura, partido para poder mudar de
     lugar no telefone. */
  column-gap: var(--unit-300);
  row-gap: var(--unit-200);
}
.produto__favoritar { grid-area: favoritar; }

@media (max-width: 47.9375rem) {
  /* Ficha, foto, miniaturas, favoritar e só então o painel de compra. */
  .produto {
    grid-template-areas: "ficha" "palco" "mini" "favoritar" "painel";
    grid-template-rows: auto;
    /* Empilhado, o vão volta a 24: aqui os blocos são seções da página, e
       não linhas de uma coluna. */
    row-gap: var(--unit-300);
  }


}

/* Pagamento no telefone: os dois controles de cartão, um por linha. Lado a
   lado eles medem 152, e "Editar o escolhido" fica com o rótulo espremido
   contra as bordas do próprio botão — numa etapa de pagamento, o rótulo é o
   que separa criar um cartão de mexer no que já existe. */
@media (max-width: 47.9375rem) {
  .sysvc-control-grid { --control-columns: 1; }
}




/* =========================================================================
   Faixa de pontos no Range, e o painel de filtro em uma coluna
   ========================================================================= */

/* A legenda do fieldset já diz "Faixa de pontos", então a linha de cima do
   Range leva só a leitura. Com um filho só, o space-between do componente a
   deixaria à esquerda, colada embaixo da legenda; à direita ela fecha a
   linha da legenda e o par "o quê / quanto" se lê de uma vez. */
.filtros__range .sysvc-range__head { justify-content: flex-end; }

/* O ponto do Range tem metade do diâmetro para fora do trilho nas duas
   pontas. Sem esse respiro ele encosta na borda da coluna. */
.filtros__range { padding-inline: var(--unit-25); }

/* Grupo de botões empilhado dentro do painel: o .filtros__acoes original é
   uma linha alinhada ao fim, e aqui manda a pilha do componente. O fio de
   cima e o recuo continuam vindo da regra do grade--vertical. */
.filtros__acoes.sysvc-button-group--stack {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: var(--unit-150);
}

/* A coluna da lista segue o mesmo par de larguras do resumo das etapas —
   18rem no hd, 20rem no fullhd. Sem o segundo degrau ela ficava 32 mais
   estreita que o painel do carrinho na mesma tela, e as duas navegações
   laterais da loja não podem ter medidas diferentes. */
@media (min-width: 85.4375rem) {
  .loja .lista:has(.lista__lado) { grid-template-columns: minmax(0, 1fr) 20rem; }
}

/* Abaixo do hd a coluna se dissolve com `display: contents`, e com ela vai
   embora o gap que separava os três blocos — Ordenar por, alternador e o
   gatilho do filtro ficavam colados um no outro. O vão volta como margem de
   cada bloco, no mesmo 20 que a coluna usava. */
@media (max-width: 56.25rem) {
  .lista__lado > * { margin-block-end: var(--unit-250); }
}

/* Painel do Cliente sem a terceira faixa: a tela traz a própria navegação
   lateral no corpo — é o caso do Histórico, cuja lista põe ordenar e filtrar
   à direita como nas categorias e nos favoritos. O corpo vai até onde o
   resumo da conta ia, e a margem da direita continua sendo a dele.
   Só onde existe navegação persistente: abaixo de 980 tudo empilha. */
@media (min-width: 61.25rem) {
  .loja .painel-cliente--lado-proprio { grid-template-columns: var(--pc-menu) minmax(0, 1fr); }
  /* Onde há duas faixas, o resumo da conta sai: a da direita é a de filtro.
     Empilhado (abaixo de 980) ele fica, como em todas as outras telas do
     painel — ali não há disputa por faixa nenhuma. */
  .loja .painel-cliente--lado-proprio > .painel-cliente__lateral { display: none; }
}

/* O par de datas do filtro de pedidos, na coluna estreita: lado a lado eles
   ficariam com 114 cada, e um campo de data não cabe nisso. Uma por linha,
   como já acontece no telefone. */
@media (min-width: 56.3125rem) {
  .lista__lado .filtros__faixa { flex-wrap: wrap; }
  .lista__lado .filtros__faixa .sysvc-field { flex-basis: 100%; }
}

/* O título do painel de filtro. Flutuante, quem nomeia o painel é o cabeçalho
   do Accordion que o abre, e um título repetiria a frase logo abaixo dela. Na
   coluna esse cabeçalho some — e sem o título o filtro ficava sendo a única
   caixa da navegação lateral sem nome, ao lado de um "Saldo" e de um "Resumo
   da conta" que têm o seu. */
.filtros__titulo { display: none; }
@media (min-width: 56.3125rem) {
  .lista__lado .filtros__titulo { display: block; margin-block-end: var(--unit-250); }
}

/* O cabeçalho sobe enquanto o véu de menu está aceso. É a obrigação que vem
   com o nível de menu do Blanket, e ela existe por causa do contexto de
   empilhamento: o `.topo` é sticky com z-index, então tudo o que mora nele
   — inclusive a superfície do popup, que pede 400 — vale 200 visto de fora,
   e o véu passaria por cima do menu.

   O `:has` mora no `body` porque o véu é irmão do `.loja`: o Blanket se
   pendura no corpo da página, e não dentro do aplicativo. */
body:has(.sysvc-blanket--menu) .topo { z-index: var(--level-flyout); }


/* =========================================================================
   Tablet (48rem a 56,25rem) — o que era do telefone e vazou para cá

   A causa de quase tudo nesta seção é uma só: o bloco `max-width: 900px`
   deste arquivo carrega regras escritas para o TELEFONE — empilhar o
   produto, empilhar o gift card, quebrar a linha do carrinho em duas
   colunas. De 768 a 900 elas continuam valendo, e ali a largura já é de
   sobra para a composição de duas colunas. Esta seção vem DEPOIS delas, no
   fim do arquivo, e é o que as corrige no tablet.
   ========================================================================= */

@media (min-width: 48rem) and (max-width: 56.25rem) {

  /* --- produto: a foto principal em cima, as miniaturas embaixo ----------
     O defeito era de grade, e não de ordem: o bloco do telefone trocava as
     colunas por `1fr` e deixava de pé as ÁREAS de três colunas do desktop.
     Medido a 834: as colunas saíam 157 / 0 / 549 — a do palco em ZERO, com
     as miniaturas ocupando o lugar da foto.

     Aqui a grade volta a ter duas colunas de verdade. O palco atravessa as
     três primeiras linhas e as miniaturas ficam embaixo dele; favoritar,
     ficha e painel empilham na coluna da direita, na mesma ordem de leitura
     do desktop. */
  .produto {
    /* Metade e metade, e a metade é EXATA: o grid do tablet tem 6 colunas de
       119,16 com vão de 8, e duas caixas de 1fr separadas por um vão somam
       3 colunas + 2 vãos de cada lado — os mesmos 374 da faixa azul. Fazer
       a conta com `calc` daria o mesmo número e envelheceria pior: quem
       mudar o gutter do breakpoint mudaria a conta em dois lugares. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--faixa-gutter, var(--unit-300));
    grid-template-areas:
      "palco favoritar"
      "palco ficha"
      "palco painel"
      "mini  painel";
    grid-template-rows: auto auto auto 1fr;
  }
  /* Deitadas, como no telefone: em pé elas fariam uma coluna de 3,5rem ao
     lado de uma foto que agora ocupa a largura toda da sua coluna. */
  .produto__miniaturas {
    grid-auto-flow: column; grid-auto-columns: 3.5rem;
    justify-content: start; align-self: start;
  }

  /* --- gift card: a compra ao lado do conteúdo, como no desktop ----------
     Duas colunas: o que se lê à esquerda, o que se decide à direita. A arte
     deixa de ser coluna e vira a abertura do texto — a largura do tablet não
     comporta arte, texto e resumo lado a lado sem espremer os três. */
  .gift-pagina {
    /* A mesma metade e metade da página de produto: duas caixas de `1fr`
       separadas por um vão somam 3 colunas + 2 vãos de cada lado. As duas
       telas de compra passam a cair nos mesmos x, e a leitura de uma não
       reeduca a outra. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--faixa-gutter, var(--unit-300));
    grid-template-areas:
      "cabeca resumo"
      "arte   resumo"
      "texto  resumo"
      "extras resumo";
  }
  /* A arte acompanha a coluna, em vez de um teto próprio: numa coluna de 374
     um teto de 18rem (288) deixaria 86 de sobra à direita dela, e o cartão
     lido é a abertura do texto — não um bloco menor ao lado dele. */
  .gift-pagina__arte { max-inline-size: none; }

  /* --- carrinho: item, quantidade e remover na horizontal ----------------
     A linha volta às quatro colunas do desktop. No telefone ela quebra em
     duas porque 343 não comporta a fila; a 768 comporta com folga, e
     empilhada ela gastava 240 de altura por item. */
  .linha-item { grid-template-columns: 5rem minmax(0, 1fr) auto auto; align-items: center; }
  .linha-item__arte { width: 5rem; grid-row: auto; }
  .linha-item .quantidade { grid-column: auto; }
  .linha-item__fim { grid-column: auto; justify-items: end; }
  .linha-item__texto { display: block; }

}

/* O menu do painel vira Dropdown em TODA largura sem navegação persistente,
   e não só no telefone. O painel deixa de ter coluna própria abaixo de 980;
   daí para baixo a lista de quatro itens de 48 é um bloco atravessado no
   topo de todas as telas do painel, que é justamente o que o Dropdown veio
   resolver no celular. O seletor já traz o "Sair da conta" no segundo grupo,
   então nada se perde ao esconder a lista. */
@media (min-width: 48rem) and (max-width: 61.1875rem) {
  .painel-cliente__seletor {
    display: block;
    padding-inline: var(--faixa-margem, var(--unit-200));
    margin-block-end: var(--unit-100);
  }
  .painel-cliente__titulo-menu { display: none; }
  .painel-cliente__menu .sysvc-menu { display: none; }
}
