/*
 * Componentes reutilizaveis do DonaDeSi (DON-025).
 *
 * O par visual das macros em app/templates/componentes/. Cada bloco aqui
 * corresponde a uma macro; quem escreve template nunca monta a marcacao na
 * mao, entao classe e macro andam sempre juntas.
 *
 * Nenhuma cor literal: tudo vem da camada de componente do tokens.css. Trocar
 * a aparencia de um botao em todo o sistema e uma linha la, nao uma busca por
 * arquivo aqui.
 *
 * Entra depois de layout-site.css/layout-admin.css na ordem de carga: layout
 * posiciona regioes, componente estiliza as pecas dentro delas, e a cascata
 * precisa refletir essa precedencia.
 *
 * Foco nao e reimplementado: o `:focus-visible` de reset.css ja vale para
 * todo elemento focavel, com a cor de foco vinda do token. Reforcar aqui so
 * criaria duas fontes para a mesma decisao.
 *
 * FORA DE ESCOPO -- cada um tem issue propria: grade responsiva de listagem
 * (DON-030), esqueleto de carregamento (DON-031), alertas e toast (DON-032).
 * Card de produto e preco por perfil sao de sprint de dominio.
 */

/* ---------------------------------------------------------------------
 * Utilitarios -- as duas unicas classes do projeto que nao sao componente.
 * Ficam aqui, e nao em reset.css, porque nao normalizam navegador: sao
 * vocabulario que as macros consomem.
 * --------------------------------------------------------------------- */

/* Esconde visualmente sem tirar da arvore de acessibilidade. Nao e
 * `display: none` nem `visibility: hidden`: os dois removem o elemento do
 * que o leitor de tela anuncia, que e exatamente o oposto do que se quer
 * aqui. O rotulo continua no DOM, continua ligado por `for` e continua
 * clicavel -- so nao ocupa espaco. Usado pela macro campo com
 * `rotulo_oculto`, no campo de busca do cabecalho. */
.apenas-leitor-de-tela {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Skip-link: fora da viewport ate receber foco por teclado. Veio de
 * layout-admin.css na DON-026, quando o site tambem passou a ter cabecalho
 * e o atalho deixou de ser exclusivo do painel. */
.pular-para-conteudo {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  transform: translateY(-200%);
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  border-radius: var(--corner-control);
  transition: transform 0.15s ease-in-out;
}

.pular-para-conteudo:focus {
  transform: translateY(0);
}

/* ---------------------------------------------------------------------
 * Botao
 * --------------------------------------------------------------------- */

.botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border: none;
  border-radius: var(--corner-control);
  font-weight: 700;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 120ms ease;
}

.botao-primario {
  background-color: var(--button-primary-bg);
  color: var(--button-primary-fg);
}

.botao-primario:hover {
  background-color: var(--button-primary-bg-hover);
}

.botao-secundario {
  background-color: var(--button-secondary-bg);
  color: var(--button-secondary-fg);
}

.botao-secundario:hover {
  background-color: var(--button-secondary-bg-hover);
}

/* Alvo de toque dos botoes no conteudo do site publico. `#conteudo` so
 * existe em site/base.html, nunca no painel: o .botao global de
 * design-v2.css (40px) continua valendo para o admin. */
#conteudo .botao {
  min-height: 44px;
}

/* Sem :hover proprio: a paleta tem um unico tom de vermelho, e inventar um
 * segundo aqui furaria a fonte unica de cor. Quando --action-danger-hover
 * existir, entra uma regra igual as de cima. */
.botao-perigo {
  background-color: var(--button-danger-bg);
  color: var(--button-danger-fg);
}

/* `:disabled` depois das variantes de proposito: mesma especificidade, e a
 * ultima regra vence -- o botao desabilitado nao pode continuar com a cor da
 * variante. */
.botao:disabled {
  background-color: var(--button-disabled-bg);
  color: var(--button-disabled-fg);
  cursor: default;
}

/* ---------------------------------------------------------------------
 * Campo de formulario
 * --------------------------------------------------------------------- */

.campo {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.campo-rotulo {
  font-weight: 700;
}

.campo-entrada {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--input-border);
  border-radius: var(--corner-control);
  background-color: var(--input-bg);
  color: var(--input-fg);
}

.campo-entrada::placeholder {
  color: var(--input-placeholder);
}

/* A borda vermelha reforca a mensagem de erro; ela nunca e o unico sinal --
 * a macro sempre renderiza o texto do erro junto. */
.campo-com-erro .campo-entrada {
  border-color: var(--input-border-error);
}

.campo-dica {
  color: var(--text-muted);
}

.campo-erro {
  color: var(--input-error-fg);
  font-weight: 600;
}

/* Rotulo de escolha (radio/checkbox) como alvo de toque (DON-150): o
 * quadradinho nativo tem ~13px, e o rotulo inteiro e a area clicavel.
 * `min-height` de 44px e o piso de alvo de toque, como .cabecalho-categoria. */
.opcao-de-escolha {
  display: flex;
  align-items: center;
  gap: var(--spacing-inline-default, .5rem);
  min-height: 44px;
}

/* ---------------------------------------------------------------------
 * Etapas de um fluxo linear (DON-162)
 * --------------------------------------------------------------------- */

/* Trilho de segmentos, e nao bolinhas numeradas ligadas por linha: cada etapa
 * e uma barra que preenche quando concluida, e a atual ganha a barra cheia e o
 * rotulo em negrito. Em 320 px quatro rotulos nao cabem, entao abaixo de
 * 480 px eles saem e o resumo "Etapa N de M - nome" passa a dizer qual e a
 * atual. As cores sao as de texto: o trilho e informacao, nao decoracao. */
.etapas {
  display: grid;
  gap: var(--space-2);
}

.etapas-resumo {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.etapas-lista {
  display: grid;
  grid-auto-columns: minmax(0, 1fr);
  grid-auto-flow: column;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.etapas-item {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.etapas-marcador {
  height: 4px;
  border-radius: var(--radius-full);
  background-color: var(--border-subtle);
}

.etapas-item-concluida .etapas-marcador {
  background-color: var(--text-secondary);
}

.etapas-item-atual .etapas-marcador {
  background-color: var(--text-primary);
}

.etapas-texto {
  display: none;
  overflow-wrap: anywhere;
  color: var(--text-muted);
  font-size: 0.75rem;
}

.etapas-item-atual .etapas-texto {
  color: var(--text-primary);
  font-weight: 700;
}

@media (min-width: 480px) {
  .etapas-texto {
    display: block;
  }

  .etapas-resumo-nome {
    display: none;
  }
}

/* ---------------------------------------------------------------------
 * Opcoes em cartao -- radio unico com contexto (DON-162)
 * --------------------------------------------------------------------- */

/* O `border: 0` tira a moldura padrao do fieldset, como em .matriz-modulo. */
.opcoes {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.opcoes-lista {
  display: grid;
  gap: var(--space-2);
}

/* O cartao inteiro e o <label>: o alvo de toque passa dos 44 px sem depender
 * do circulo nativo, que continua visivel a esquerda e e quem recebe o foco. */
.opcao-cartao {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-3);
  min-height: 56px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--corner-control);
  background-color: var(--card-bg);
  color: var(--card-fg);
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}

.opcao-cartao:hover {
  border-color: var(--border-strong);
}

.opcao-cartao:has(.opcao-cartao-entrada:checked) {
  border-color: var(--text-primary);
  background-color: var(--surface-sunken);
  box-shadow: inset 0 0 0 1px var(--text-primary);
}

.opcao-cartao:has(.opcao-cartao-entrada:focus-visible) {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

.opcao-cartao-entrada {
  width: 1.125rem;
  height: 1.125rem;
  margin: 0;
  accent-color: var(--action-primary);
}

.opcao-cartao-icone {
  display: inline-flex;
  color: var(--text-secondary);
}

.opcao-cartao-texto {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.opcao-cartao-titulo {
  font-weight: 700;
}

/* Destino mascarado (e-mail, telefone): sem espaco para quebrar, entao a
 * quebra e em qualquer ponto para nao empurrar a largura do cartao. */
.opcao-cartao-detalhe {
  overflow-wrap: anywhere;
  color: var(--text-muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.opcoes.campo-com-erro .opcao-cartao {
  border-color: var(--input-border-error);
}

/* ---------------------------------------------------------------------
 * Selo -- atributo comercial do produto, canto reto
 * --------------------------------------------------------------------- */

.selo {
  display: inline-block;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--corner-control);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.selo-novo {
  background-color: var(--badge-new-bg);
  color: var(--badge-new-fg);
}

.selo-promocao {
  background-color: var(--badge-sale-bg);
  color: var(--badge-sale-fg);
}

.selo-destaque {
  background-color: var(--badge-highlight-bg);
  color: var(--badge-highlight-fg);
}

.selo-neutro {
  background-color: var(--badge-neutral-bg);
  color: var(--badge-neutral-fg);
}

/* ---------------------------------------------------------------------
 * Pilula -- estado de um fluxo, canto redondo
 * --------------------------------------------------------------------- */

.pilula {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--corner-pill);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.pilula-rascunho {
  background-color: var(--pill-draft-bg);
  color: var(--pill-draft-fg);
}

.pilula-pendente {
  background-color: var(--pill-pending-bg);
  color: var(--pill-pending-fg);
}

.pilula-aprovado {
  background-color: var(--pill-approved-bg);
  color: var(--pill-approved-fg);
}

.pilula-recusado {
  background-color: var(--pill-rejected-bg);
  color: var(--pill-rejected-fg);
}

.pilula-concluido {
  background-color: var(--pill-done-bg);
  color: var(--pill-done-fg);
}

/* ---------------------------------------------------------------------
 * Cartao
 * --------------------------------------------------------------------- */

.cartao {
  padding: var(--space-4);
  border: 1px solid var(--card-border);
  border-radius: var(--corner-surface);
  background-color: var(--card-bg);
  color: var(--card-fg);
}

.cartao-titulo {
  margin-bottom: var(--space-3);
  font-size: 1.125rem;
}

/* ---------------------------------------------------------------------
 * Cabecalho do site -- duas faixas: identidade/acoes e categorias
 * --------------------------------------------------------------------- */

.cabecalho {
  background-color: var(--header-bg);
  color: var(--header-fg);
  border-bottom: 1px solid var(--header-border);
}

/* Faixa 1. `flex-wrap` em vez de media query: no celular a busca desce para a
 * segunda linha sozinha, sem precisar de breakpoint para descrever isso. */
.cabecalho-identidade {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--spacing-container-padding-inline);
}

.cabecalho-marca {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 700;
  font-size: 1.25rem;
  text-decoration: none;
  color: inherit;
}

/* O acento da marca e o mesmo filete da categoria ativa: uma cor de acento
 * so, usada em dois lugares pequenos. */
.cabecalho-marca-acento {
  color: var(--accent-default);
}

.cabecalho-busca {
  flex: 1 1 12rem;
  min-width: 0;
}

/* `margin-inline-start: auto` empurra as acoes para a borda oposta sem
 * precisar de um wrapper so para isso. */
.cabecalho-acoes {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-inline-start: auto;
}

.cabecalho-acao {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  min-width: 44px;
  color: var(--header-item-fg);
  text-decoration: none;
  font-weight: 600;
}

.cabecalho-acao:hover {
  color: var(--header-item-active-fg);
}

.cabecalho-contador {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  padding-inline: var(--space-1);
  border-radius: var(--corner-pill);
  background-color: var(--header-counter-bg);
  color: var(--header-counter-fg);
  font-size: 0.6875rem;
  font-weight: 700;
}

/* Botao do drawer de categorias (DON-030).
 *
 * Nasce escondido e so aparece quando o JavaScript marca o documento: sem o
 * modulo nao ha o que alternar, e um botao inerte e pior que botao nenhum.
 * A regra que o mostra esta logo abaixo, junto da que esconde a faixa --
 * as duas dependem da mesma marca e por isso vivem lado a lado.
 *
 * `min-height`/`min-width` de 44px cumprem o alvo de toque, como
 * .cabecalho-categoria e .painel-alternar ja fazem. */
.cabecalho-alternar {
  display: none;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--corner-control);
  background-color: transparent;
  color: var(--header-item-fg);
  cursor: pointer;
}

.cabecalho-alternar:hover {
  color: var(--header-item-active-fg);
}

/* O tracinho e o de cima; os outros dois sao pseudo-elementos posicionados a
 * partir dele. Tres <span> no HTML diriam ao leitor de tela que ha tres
 * coisas ali, quando ha uma so -- e ela ja e `aria-hidden`. */
.cabecalho-alternar-traco,
.cabecalho-alternar-traco::before,
.cabecalho-alternar-traco::after {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: var(--corner-control);
  background-color: currentColor;
}

.cabecalho-alternar-traco {
  position: relative;
}

.cabecalho-alternar-traco::before,
.cabecalho-alternar-traco::after {
  position: absolute;
  content: "";
}

.cabecalho-alternar-traco::before {
  top: -6px;
}

.cabecalho-alternar-traco::after {
  top: 6px;
}

/* As duas regras que a marca do JavaScript autoriza. Sem
 * `data-categorias-do-site` no <html> nenhuma das duas casa: o botao segue
 * escondido e a faixa segue visivel, rolando na horizontal como antes da
 * DON-030. Ver app/static/js/comportamentos/categorias-do-site.js.
 *
 * `display: none` na faixa, e nao apenas fora da tela: escondida so por
 * posicao, as oito categorias continuariam tabulaveis, e quem navega por
 * teclado passaria por todas elas antes de chegar ao conteudo. */
[data-categorias-do-site] .cabecalho-alternar {
  display: inline-flex;
}

[data-categorias-do-site] .cabecalho-categorias[data-fechado] {
  display: none;
}

/* Faixa 2. No celular ela rola na horizontal em vez de quebrar em varias
 * linhas e empurrar o conteudo da pagina para baixo. Esconder a barra de
 * rolagem e so desenho: a regiao continua rolavel por teclado, por roda e
 * por toque. */
.cabecalho-categorias {
  overflow-x: auto;
  scrollbar-width: none;
  border-top: 1px solid var(--header-border);
}

.cabecalho-categorias::-webkit-scrollbar {
  display: none;
}

.cabecalho-lista {
  display: flex;
  gap: var(--space-5);
  margin: 0;
  padding: 0 var(--spacing-container-padding-inline);
  list-style: none;
  white-space: nowrap;
}

/* A borda transparente reserva o espaco do filete: sem ela o item saltaria
 * 2px ao virar ativo. O `min-height` cumpre o alvo de toque de 44px. */
.cabecalho-categoria {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: var(--space-2);
  border-bottom: 2px solid transparent;
  color: var(--header-item-fg);
  text-decoration: none;
  font-weight: 600;
}

.cabecalho-categoria:hover {
  color: var(--header-item-active-fg);
}

/* Estado ativo marcado por cor E filete -- nunca so por cor, que sozinha nao
 * comunica para quem nao a distingue. */
.cabecalho-categoria-ativa {
  color: var(--header-item-active-fg);
  border-bottom-color: var(--header-indicator);
}

/* Alvo de toque do alternador de tema no cabecalho do SITE, escopado ao
 * .cabecalho: o .tema-alternar global (design-v2.css) serve tambem o painel
 * admin e nao muda aqui. */
.cabecalho .tema-alternar {
  min-height: 44px;
  min-width: 44px;
}

/* md (768px) -- ver a escala de breakpoints em tokens.css. E aqui que a
 * navegacao do site troca de forma: o drawer vira faixa permanente. */
@media (min-width: 768px) {
  .cabecalho-identidade,
  .cabecalho-lista {
    padding-inline: var(--space-6);
  }

  /* A faixa cabe inteira: o botao perde a funcao e as categorias voltam,
   * mesmo que o drawer tenha sido fechado numa largura menor. Sem esta
   * segunda regra, redimensionar a janela com o drawer fechado deixaria o
   * desktop sem navegacao de categoria. */
  [data-categorias-do-site] .cabecalho-alternar {
    display: none;
  }

  [data-categorias-do-site] .cabecalho-categorias[data-fechado] {
    display: block;
  }
}

/* ---------------------------------------------------------------------
 * Tabela
 * --------------------------------------------------------------------- */

/* O involucro rola no eixo horizontal em vez de deixar a tabela empurrar a
 * largura da pagina inteira -- no celular, uma listagem de seis colunas
 * quebraria o layout de todas as telas. */
.tabela-rolagem {
  overflow-x: auto;
}

.tabela {
  width: 100%;
  border-collapse: collapse;
}

.tabela-legenda {
  margin-bottom: var(--space-2);
  text-align: left;
  color: var(--text-secondary);
}

.tabela th {
  padding: var(--space-3) var(--space-4);
  background-color: var(--table-header-bg);
  color: var(--table-header-fg);
  text-align: left;
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.tabela td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--table-row-border);
}

/* Numero alinhado a direita e com digito de largura fixa: e o que faz os
 * valores alinharem casa decimal com casa decimal na vertical, que e como se
 * confere uma coluna de dinheiro. */
.tabela-numero {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
 * Painel administrativo -- topbar e barra lateral
 * --------------------------------------------------------------------- */

.painel-topbar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--spacing-container-padding-inline);
  background-color: var(--topbar-bg);
  color: var(--topbar-fg);
  border-bottom: 1px solid var(--topbar-border);
}

.painel-marca {
  font-weight: 700;
  font-size: 1.125rem;
  text-decoration: none;
  color: inherit;
}

.painel-marca-acento {
  color: var(--accent-default);
}

/* O titulo da tela some no celular: com marca, botao e acoes disputando a
 * mesma linha, ele seria o primeiro a quebrar o layout -- e e a informacao
 * que o <h1> do conteudo repete logo abaixo. */
.painel-titulo {
  display: none;
  margin: 0;
  color: var(--text-secondary);
}

.painel-acoes {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-inline-start: auto;
}

.painel-acao {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  color: var(--topbar-item-fg);
  text-decoration: none;
  font-weight: 600;
}

.painel-acao:hover {
  color: var(--text-primary);
}

/* O Sair e um <button> dentro de <form> (DON-164), e tem de parecer as outras
 * acoes, que sao links: tira o fundo, a borda, o respiro e a fonte padrao do
 * botao. A borda e o respiro lateral voltam pelo design-v2.css, igual nos
 * links -- por isso `:where()`: a especificidade fica a de `.painel-acao`, e o
 * arquivo carregado depois vence. O form nao pode quebrar a linha das acoes. */
.painel-sair {
  display: contents;
}

:where(button).painel-acao {
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.painel-acao svg {
  width: 1rem;
  height: 1rem;
}

.painel-contador {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  padding-inline: var(--space-1);
  border-radius: var(--corner-pill);
  background-color: var(--topbar-counter-bg);
  color: var(--topbar-counter-fg);
  font-size: 0.6875rem;
  font-weight: 700;
}

.painel-alternar {
  min-height: 44px;
  padding-inline: var(--space-3);
  border: 1px solid var(--topbar-border);
  border-radius: var(--corner-control);
  background-color: var(--topbar-item-bg);
  color: var(--topbar-item-fg);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.painel-menu {
  background-color: var(--sidebar-bg);
  color: var(--sidebar-fg);
  padding-block: var(--space-4);
}

.painel-grupo + .painel-grupo {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--sidebar-border);
}

.painel-grupo-titulo {
  margin: 0 0 var(--space-2);
  padding-inline: var(--spacing-container-padding-inline);
  color: var(--sidebar-grupo-fg);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.painel-lista {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* `display: block` e nao inline-flex: no menu lateral o alvo de clique e a
 * faixa inteira, da borda esquerda a direita -- e o que faz a linha do item
 * ativo se ler como uma aba selecionada, e nao como um texto pintado.
 * A borda transparente reserva o espaco do filete, senao o item saltaria
 * 3px ao virar ativo. */
.painel-item {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--spacing-container-padding-inline);
  border-inline-start: 3px solid transparent;
  background-color: var(--sidebar-item-bg);
  color: var(--sidebar-item-fg);
  text-decoration: none;
}

.painel-item:hover {
  text-decoration: underline;
}

/* Estado ativo marcado por fundo E filete -- nunca so por cor, que sozinha
 * nao comunica para quem nao a distingue. */
.painel-item-ativo {
  background-color: var(--sidebar-item-active-bg);
  color: var(--sidebar-item-active-fg);
  border-inline-start-color: var(--accent-default);
  font-weight: 600;
}

/* O menu so pode ser escondido depois que o JavaScript marcou o documento:
 * sem o modulo, `[data-menu-do-painel]` nunca aparece, a regra nunca casa e
 * o painel continua navegavel. Ver app/static/js/comportamentos/menu-do-painel.js.
 *
 * `display: none` de proposito, e nao apenas fora da tela: escondido so por
 * posicao, o menu continuaria tabulavel, e quem navega por teclado passaria
 * por vinte itens invisiveis antes de chegar ao conteudo. */
[data-menu-do-painel] .painel-menu[data-fechado] {
  display: none;
}

/* md (768px) -- ver a escala de breakpoints em tokens.css. */
@media (min-width: 768px) {
  .painel-topbar {
    padding-inline: var(--space-6);
  }

  .painel-titulo {
    display: block;
  }

  /* A partir daqui a grade poe o menu na coluna da esquerda: o botao perde a
   * funcao e o menu fica sempre visivel, mesmo que tenha sido fechado numa
   * largura menor. */
  .painel-alternar {
    display: none;
  }

  [data-menu-do-painel] .painel-menu[data-fechado] {
    display: block;
  }
}

/* ---------------------------------------------------------------------
 * Rodape -- tres faixas no site, so a legal no painel
 * --------------------------------------------------------------------- */

.rodape {
  background-color: var(--footer-bg);
  color: var(--footer-fg);
  border-top: 1px solid var(--footer-border);
}

/* `auto-fit` com `minmax` em vez de media query: as colunas se acomodam
 * sozinhas conforme a largura disponivel -- uma no celular, duas no tablet,
 * tres no desktop -- sem ninguem ter que escolher os breakpoints, e sem
 * quebrar se a quarta coluna aparecer quando o banco existir (Sprint 6). */
.rodape-navegacao {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--space-5);
  padding: var(--spacing-region-gap) var(--spacing-container-padding-inline);
}

.rodape-titulo {
  margin: 0 0 var(--space-3);
  color: var(--footer-titulo-fg);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.rodape-lista,
.rodape-redes,
.rodape-lista-legal {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rodape-lista li + li,
.rodape-redes li + li {
  margin-top: var(--space-2);
}

/* `min-height` de 44px cumpre o alvo de toque: no celular os links do rodape
 * ficam empilhados e proximos, e sem area minima o dedo erra o vizinho.
 * `inline-flex` para a altura valer sem esticar o link ate a largura da
 * coluna -- o alvo acompanha o texto. */
.rodape-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  min-width: 44px;
  color: var(--footer-link-fg);
  text-decoration: none;
}

/* Sublinhado no hover, nao no repouso: no repouso o que distingue o link e a
 * cor E a posicao (lista de navegacao). Sublinhar tudo o tempo todo deixaria
 * a faixa visualmente mais pesada que o conteudo da pagina. */
.rodape-link:hover {
  text-decoration: underline;
}

.rodape-contato {
  padding: 0 var(--spacing-container-padding-inline) var(--spacing-region-gap);
}

/* A faixa legal encosta na borda inferior da tela e fecha o rodape: borda no
 * topo dela, nao embaixo. */
.rodape-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--spacing-container-padding-inline);
  border-top: 1px solid var(--footer-border);
  font-size: 0.8125rem;
}

.rodape-assinatura {
  margin: 0;
}

.rodape-lista-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* No painel a unica faixa e a legal, e ela ja tem a borda do proprio .rodape
 * em cima -- a segunda borda viraria filete duplo. */
.rodape-compacto .rodape-legal {
  border-top: 0;
}

/* md (768px) -- ver a escala de breakpoints em tokens.css. So padding: as
 * colunas do rodape ja se acomodam sozinhas por `auto-fit`. */
@media (min-width: 768px) {
  .rodape-navegacao,
  .rodape-contato,
  .rodape-legal {
    padding-inline: var(--space-6);
  }
}

/* ---------------------------------------------------------------------
 * Grade de listagem de produtos
 * --------------------------------------------------------------------- */

/* `auto-fit` com `minmax` em vez de media query, pela mesma razao do rodape:
 * as colunas se acomodam conforme a largura -- uma no celular, duas ou tres
 * no tablet, quatro no desktop -- sem ninguem escolher os breakpoints e sem
 * quebrar quando a largura do container mudar.
 *
 * 14rem e o piso porque abaixo disso a foto do produto fica menor que o
 * polegar que a toca. Em 320px (a tela mais estreita que ainda se atende) a
 * conta da uma coluna so, que e o certo: duas colunas de 7rem nao mostram
 * uma joia.
 *
 * A grade e so a grade. O cartao de produto -- foto, nome, preco, selo -- e
 * de sprint de dominio (Sprint 6); aqui `.grade-de-produtos > *` nao recebe
 * estilo nenhum, para o cartao poder nascer sem ter que desfazer nada. */
.grade-de-produtos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--spacing-region-gap);
}

/* ---------------------------------------------------------------------
 * Pagina de erro -- 403, 404, 500 e o generico
 * --------------------------------------------------------------------- */

/* O 500 nao herda layout nenhum (ver erros/500.html), entao ele traz a
 * propria moldura de pagina. Nos outros o site/base.html ja cuida disso. */
.erro-pagina {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: var(--error-page-bg);
}

.erro-pagina main {
  flex: 1;
  display: flex;
  padding: var(--spacing-region-gap) var(--spacing-container-padding-inline);
}

/* `max-width` em `ch` e nao em pixel: a medida acompanha o tamanho da fonte,
 * entao quem aumenta o corpo do texto no navegador continua com a mesma
 * quantidade de caracteres por linha. */
.erro {
  max-width: 60ch;
  margin-inline: auto;
  padding-block: var(--space-7);
  color: var(--error-page-fg);
  text-align: center;
}

/* Decoracao: quem le com leitor de tela nao recebe este numero (a marcacao o
 * esconde), e o titulo logo abaixo diz o mesmo em palavras. Por isso ele pode
 * ser grande e abafado ao mesmo tempo. */
.erro-codigo {
  margin: 0;
  color: var(--error-page-codigo-fg);
  font-size: 3.5rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.02em;
}

.erro-titulo {
  margin: var(--space-4) 0 0;
  font-size: 1.5rem;
}

.erro-texto {
  margin: var(--space-3) 0 0;
  color: var(--error-page-texto-fg);
}

/* `flex-wrap` para os dois botoes empilharem no celular em vez de espremerem;
 * `justify-content` porque o bloco inteiro e centrado. */
.erro-acoes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--spacing-region-gap);
}

/* ---------------------------------------------------------------------
 * Estados de carregamento -- esqueleto e girador (DON-031)
 * --------------------------------------------------------------------- */

/* MOVIMENTO REDUZIDO: nao ha bloco de `prefers-reduced-motion` aqui de
 * proposito. O reset.css ja neutraliza toda animacao do documento com
 * `!important`, e as duas animacoes abaixo entram nessa regra. Repetir a
 * media query neste arquivo criaria dois lugares para manter em acordo, e o
 * dia em que eles divergissem o defeito seria invisivel para quem nao pede
 * menos movimento.
 *
 * O que importa e que nenhum dos dois componentes DEPENDE da animacao para
 * informar: o esqueleto ja ocupa a forma do conteudo parado, e o girador tem
 * o rotulo em .apenas-leitor-de-tela. Com a animacao morta os dois viram
 * figuras estaticas, e continuam dizendo a mesma coisa. */

.esqueleto {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* A barra e o esqueleto inteiro sao a mesma superficie animada. O gradiente
 * e mais largo que o elemento (200%) justamente para poder atravessa-lo: o
 * que se move e a posicao do fundo, nao o elemento -- animar `background-position`
 * nao dispara layout nem repaint de vizinho, ao contrario de animar `left`. */
.esqueleto-linha,
.esqueleto-midia {
  border-radius: var(--corner-control);
  background-color: var(--skeleton-bg);
  background-image: linear-gradient(
    90deg,
    var(--skeleton-bg) 0%,
    var(--skeleton-highlight) 50%,
    var(--skeleton-bg) 100%
  );
  background-size: 200% 100%;
  animation: esqueleto-brilho 1.4s ease-in-out infinite;
}

.esqueleto-linha {
  height: 0.75rem;
}

/* A ultima linha de um bloco de texto real quase nunca chega ao fim da
 * coluna. Sem isto o esqueleto vira um retangulo perfeito, que nao se parece
 * com texto nenhum. */
.esqueleto-texto .esqueleto-linha:last-child {
  width: 60%;
}

.esqueleto-linha-titulo {
  height: 1.25rem;
  width: 40%;
}

/* `aspect-ratio` em vez de altura fixa: a area reservada acompanha a largura
 * da coluna da grade, entao o cartao nao salta quando a foto chega. E o
 * motivo de existir esqueleto em vez de girador. */
.esqueleto-midia {
  aspect-ratio: 1 / 1;
  width: 100%;
}

/* Na tabela cada linha ocupa a largura inteira e a altura de uma celula. */
.esqueleto-tabela .esqueleto-linha {
  height: 2.5rem;
}

@keyframes esqueleto-brilho {
  from {
    background-position: 200% 0;
  }

  to {
    background-position: -200% 0;
  }
}

.girador {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Tres quartos do anel na cor da trilha e um quarto na cor do indicador: e a
 * emenda entre as duas que se ve girar. Anel de cor unica girando e um anel
 * parado. */
.girador-anel {
  display: block;
  width: 100%;
  height: 100%;
  border: 2px solid var(--spinner-track);
  border-top-color: var(--spinner-indicator);
  border-radius: var(--corner-pill);
  animation: girador-giro 700ms linear infinite;
}

.girador-pequeno {
  width: 1rem;
  height: 1rem;
}

.girador-medio {
  width: 1.5rem;
  height: 1.5rem;
}

.girador-grande {
  width: 2.5rem;
  height: 2.5rem;
}

/* No botao o anel herda a cor do texto: o botao primario tem fundo vinho, e a
 * trilha cinza do girador solto sumiria nele. */
.botao .girador-anel {
  border-color: currentColor;
  border-top-color: transparent;
}

@keyframes girador-giro {
  to {
    transform: rotate(1turn);
  }
}

/* O botao ocupado fica com a aparencia de desabilitado do sistema, mas por
 * um motivo diferente: nao e "voce nao pode", e "ja estou fazendo". Quem
 * comunica a diferenca e o `aria-busy` no HTML e o girador na tela.
 *
 * `cursor: progress` e nao `not-allowed`, pelo mesmo motivo. */
.botao[aria-busy="true"] {
  cursor: progress;
}

/* A regiao que espera nao tem aparencia propria -- ela existe para carregar o
 * `aria-busy`. O seletor esta aqui so para o dia em que precisar de uma, e
 * para que ninguem invente uma classe paralela. */
.regiao-carregando {
  display: block;
}

/* ---------------------------------------------------------------------
 * Alerta -- mensagem do sistema para o usuario (DON-032)
 * --------------------------------------------------------------------- */

/* O filete lateral e a segunda pista da variante, junto do icone: quem nao
 * distingue as cores continua vendo tres marcas diferentes -- forma do
 * icone, texto e posicao. Nunca so a cor. */
.alerta {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-inline-start: 4px solid;
  border-radius: var(--corner-surface);
}

.alerta-sucesso {
  background-color: var(--alerta-sucesso-bg);
  color: var(--alerta-sucesso-fg);
  border-inline-start-color: var(--alerta-sucesso-border);
}

.alerta-erro {
  background-color: var(--alerta-erro-bg);
  color: var(--alerta-erro-fg);
  border-inline-start-color: var(--alerta-erro-border);
}

.alerta-aviso {
  background-color: var(--alerta-aviso-bg);
  color: var(--alerta-aviso-fg);
  border-inline-start-color: var(--alerta-aviso-border);
}

.alerta-info {
  background-color: var(--alerta-info-bg);
  color: var(--alerta-info-fg);
  border-inline-start-color: var(--alerta-info-border);
}

/* `currentColor` de proposito: o icone acompanha a tinta da variante, entao
 * nao ha um quinto par de tokens so para ele -- e nao ha como o icone e o
 * texto sairem de sincronia. */
.alerta-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 1.5rem;
  height: 1.5rem;
  border-radius: var(--corner-pill);
  border: 2px solid currentColor;
  font-weight: 700;
  font-size: 0.8125rem;
  line-height: 1;
}

.alerta-corpo {
  flex: 1;
  min-width: 0;
}

.alerta-titulo {
  margin: 0;
  font-weight: 700;
}

.alerta-mensagem {
  margin: 0;
}

/* Titulo e mensagem juntos: o espaco entra entre eles, e nao como margem de
 * um dos dois, para o alerta sem titulo nao ficar com folga sobrando. */
.alerta-titulo + .alerta-mensagem,
.alerta-titulo + * {
  margin-top: var(--space-1);
}

/* O link dentro do alerta herda a tinta da variante: um link vinho dentro de
 * um alerta de erro vermelho competiria com a propria mensagem. O sublinhado
 * e o que o marca como link, e nao a cor. */
.alerta a {
  color: inherit;
  text-decoration: underline;
}

/* O botao de dispensar so aparece com o JavaScript, pelo mesmo motivo do
 * botao de categorias da DON-030: sem o modulo ele nao faz nada, e botao
 * inerte e pior que botao nenhum. A marca vem de
 * app/static/js/comportamentos/alerta.js. */
.alerta-dispensar {
  display: none;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
  margin: calc(var(--space-3) * -1) calc(var(--space-4) * -1)
    calc(var(--space-3) * -1) 0;
  padding: 0;
  border: 0;
  background-color: transparent;
  color: inherit;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

[data-alerta] .alerta-dispensar {
  display: inline-flex;
}

/* Regiao dos alertas injetados depois do carregamento.
 *
 * `position: fixed` para o toast nao empurrar o layout da pagina quando
 * chega -- conteudo que salta debaixo do cursor faz o usuario clicar no que
 * nao queria.
 *
 * Vazia ela nao pode interceptar clique: `pointer-events: none` no
 * container e `auto` nos alertas devolve a interacao so a eles. Sem isso uma
 * faixa invisivel no topo da tela engoliria os cliques do cabecalho. */
.regiao-de-alertas {
  position: fixed;
  z-index: 100;
  top: var(--space-4);
  inset-inline: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
}

.regiao-de-alertas > * {
  pointer-events: auto;
}

/* md (768px) -- ver a escala de breakpoints em tokens.css. No desktop o
 * toast nao precisa da largura inteira; encosta na direita, com teto de
 * largura para a linha nao ficar longa demais para ler. */
@media (min-width: 768px) {
  .regiao-de-alertas {
    inset-inline: auto var(--space-5);
    width: min(28rem, calc(100% - var(--space-8)));
  }
}

/* ---------------------------------------------------------------------
 * Selecao -- <select> com a mesma moldura do campo de texto
 * --------------------------------------------------------------------- */

/* Herda `.campo-entrada`; so o que difere de um <input> mora aqui. O
 * `appearance: base-select` nao entra: a seta do sistema e o unico indicador
 * de que aquilo abre uma lista, e desenhar a nossa custaria um sprite para
 * cada tema sem ganhar nada. */
.campo-selecao {
  /* Sem isso o select nasce com a largura da maior opcao, e um papel de nome
   * longo estica a coluna do formulario inteiro. */
  max-width: 100%;
}

.campo-selecao[multiple] {
  /* Rolagem propria: uma loja com vinte papeis nao pode empurrar o botao de
   * salvar para fora da tela. */
  max-height: 12rem;
  overflow-y: auto;
}

/* ---------------------------------------------------------------------
 * Paginacao -- navegacao entre as fatias de uma listagem
 * --------------------------------------------------------------------- */

.paginacao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-4);
}

.paginacao-lista {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* 44px de alvo de toque, como o botao de categorias: no celular a paginacao
 * fica no fim da lista, onde o polegar erra com mais facilidade. */
.paginacao-numero,
.paginacao-passo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding-inline: var(--space-2);
  border-radius: var(--corner-control);
  color: var(--text-link);
}

/* A pagina atual nao e link e nao pode parecer um: cor de texto normal e
 * fundo marcado, para o estado ficar visivel tambem em monocromatico. */
.paginacao-atual {
  background-color: var(--surface-sunken);
  color: var(--text-primary);
  font-weight: 700;
}

.paginacao-corte {
  padding-inline: var(--space-1);
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------
 * Estado vazio -- a listagem sem nenhuma linha
 * --------------------------------------------------------------------- */

.estado-vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  border: 1px dashed var(--border-subtle);
  border-radius: var(--corner-surface);
  background-color: var(--surface-raised);
  text-align: center;
}

.estado-vazio-descricao {
  max-width: 44ch;
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------
 * Matriz de permissoes do papel (DON-046)
 * --------------------------------------------------------------------- */

/* Um fieldset por modulo. O `border: 0` e para tirar a moldura padrao do
 * navegador, que desenha uma caixa fina e cinza que nao combina com nenhum
 * outro agrupamento do painel -- a separacao visual aqui e a linha de cima. */
.matriz-modulo {
  margin: 0;
  padding: var(--space-4) 0 0;
  border: 0;
  border-top: 1px solid var(--border-subtle);
}

.matriz-modulo-titulo {
  padding: 0;
  font-weight: 600;
  color: var(--text-secondary);
}

/* `auto-fill` com minimo em ch, e nao um numero fixo de colunas: no celular
 * cabe uma, no monitor cabem tres, e nenhuma das duas precisa de media query
 * propria. O involucro `.tabela-rolagem` continua garantindo que um rotulo
 * longo demais role no lugar de empurrar a largura da pagina. */
.matriz-lista {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(28ch, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-5);
  padding: 0;
  list-style: none;
}

.matriz-item {
  min-width: 0;
}

/* O rotulo inteiro e a area de clique, e nao so o quadradinho: alvo de toque
 * de 16px e pequeno demais para o dedo, e uma matriz e feita de dezenas de
 * cliques seguidos. */
.matriz-caixa {
  display: flex;
  gap: var(--space-2);
  align-items: start;
  padding: var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--corner-control);
  background-color: var(--surface-raised);
  cursor: pointer;
}

.matriz-caixa:hover {
  border-color: var(--border-strong);
}

/* A caixa nasce com o tamanho de fonte do input, que e menor que o do texto.
 * Fixar aqui evita que ela encolha quando o rotulo quebra em duas linhas. */
.matriz-caixa input[type="checkbox"] {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--button-primary-bg);
  cursor: pointer;
}

/* Somente leitura: a caixa desabilitada continua legivel, mas para de
 * convidar ao clique. */
.matriz-caixa:has(input:disabled) {
  cursor: default;
  background-color: var(--surface-sunken);
}

.matriz-caixa:has(input:disabled) input[type="checkbox"] {
  cursor: default;
}

.matriz-rotulo {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.matriz-nome {
  font-weight: 500;
}

/* `break-all` porque slug e uma palavra so, sem espaco onde quebrar: sem
 * isto, `catalogo.exportar_relatorio` estoura a coluna no celular. */
.matriz-slug {
  color: var(--text-secondary);
  word-break: break-all;
}

.matriz-descricao {
  color: var(--text-muted);
}

/* O botao do modulo e criado pelo JavaScript (ver
 * comportamentos/matriz-de-permissoes.js). Sem o modulo, ele nunca existe no
 * DOM e esta regra nunca casa -- ninguem ve um controle que nao funciona. */
.matriz-alternador {
  margin-left: var(--space-3);
}

/* ---------------------------------------------------------------------
 * Dialogo de confirmacao (DON-079)
 *
 * <dialog> nativo. O navegador ja centraliza, prende o foco e desenha o
 * ::backdrop -- o que falta aqui e so a pele.
 *
 * `dialog` nasce com `display: none` do user agent e o proprio navegador o
 * troca para `block` em `[open]`. Por isso NAO ha `display` nestas regras:
 * escrever um aqui venceria o do user agent e o dialogo ficaria visivel
 * fechado -- que e exatamente a falha que quebraria a melhoria progressiva
 * (sem JavaScript o <dialog> tem que ficar invisivel, e o formulario posta
 * direto).
 * --------------------------------------------------------------------- */

.dialogo {
  max-width: 28rem;
  /* `min()` para caber no celular: 28rem estouraria uma tela de 360px, e o
   * <dialog> nao encolhe sozinho. */
  width: min(28rem, calc(100vw - var(--space-6)));
  padding: var(--space-5);
  border: 1px solid var(--dialogo-border);
  border-radius: var(--corner-surface);
  background-color: var(--dialogo-bg);
  color: var(--dialogo-fg);
}

.dialogo::backdrop {
  background-color: var(--dialogo-veu);
}

.dialogo-titulo {
  margin: 0 0 var(--space-3);
  font-size: 1.125rem;
}

.dialogo-detalhe {
  margin: 0 0 var(--space-5);
  color: var(--text-secondary);
}

/* `wrap-reverse` com `flex-end`: no desktop os botoes ficam a direita com
 * Confirmar por ultimo; quando faltar largura eles empilham com Confirmar em
 * CIMA, e nao embaixo -- a acao destrutiva nao deve ser a que o polegar
 * alcanca primeiro num celular. */
.dialogo-acoes {
  display: flex;
  flex-wrap: wrap-reverse;
  justify-content: flex-end;
  gap: var(--space-2);
}

/* Explica por que sobrou so "Excluir" numa sessao bloqueada. */
.aviso-de-operacao {
  margin: var(--space-3) 0 0;
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------
 * Card de produto do site publico (DON-121)
 *
 * `grid-template-columns` com `minmax(0, 1fr)` em vez de `1fr`: uma grid
 * item sem `minmax(0, ...)` herda um minimo implicito do proprio conteudo
 * (`auto`), entao um nome de produto sem espaco (uma unica palavra longa)
 * estoura a largura da coluna em vez de quebrar. `min-width: 0` no proprio
 * card repete a mesma correcao para quando ele mora dentro de outra grid
 * (a listagem, DON-122) que faria a mesma conta errada por fora.
 * --------------------------------------------------------------------- */

.cartao-produto {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  gap: var(--space-2);
  color: var(--card-fg);
  text-decoration: none;
}

.cartao-produto-imagem {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--card-border);
  border-radius: var(--corner-surface);
  background-color: var(--surface-sunken);
  color: var(--text-muted);
}

/* DON-128: a capa preenche o quadrado 1:1 do card, cortada pelo object-fit. */
.cartao-produto-imagem img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cartao-produto-corpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  gap: var(--space-1);
}

.cartao-produto-nome {
  overflow-wrap: anywhere;
  color: var(--text-primary);
}

.cartao-produto-preco {
  color: var(--text-secondary);
  font-weight: 700;
}

/* Promocao (DON-129): selo no canto da imagem e preco anterior riscado,
 * menor, acima do promocional em destaque. */
.cartao-produto-selo {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
}

.cartao-produto-preco-anterior {
  display: block;
  color: var(--text-muted);
  font-weight: 400;
  font-size: 0.875em;
}

/* ---------------------------------------------------------------------
 * Pagina publica de categoria/subcategoria (DON-123)
 *
 * So a moldura e a navegacao entre categoria e subcategorias -- a grade de
 * produtos ja e `.grade-de-produtos` (acima) e o card, a paginacao e o
 * estado vazio ja tem CSS proprio. Sem cor propria: tudo sai de token.
 * --------------------------------------------------------------------- */

.pagina-categoria {
  display: grid;
  gap: var(--spacing-region-gap);
}

.pagina-categoria-cabecalho {
  display: grid;
  gap: var(--space-2);
}

.pagina-categoria-descricao {
  color: var(--text-secondary);
}

.pagina-categoria-navegacao-lista {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}

.pagina-categoria-navegacao-item a,
.pagina-categoria-navegacao-item span {
  display: inline-flex;
  padding-block: var(--space-1);
  padding-inline: var(--space-3);
  border-radius: var(--corner-pill);
  border: 1px solid var(--card-border);
  color: var(--text-secondary);
  text-decoration: none;
}

.pagina-categoria-navegacao-item span[aria-current="page"] {
  color: var(--text-on-action);
  background-color: var(--action-primary);
  border-color: var(--action-primary);
  font-weight: 700;
}

/* ---------------------------------------------------------------------
 * Pagina de busca (DON-125) -- formulario de filtros e lista de filtros
 * aplicados, no mesmo padrao da pagina de categoria: so moldura, sem cor
 * propria (tudo sai de token).
 * --------------------------------------------------------------------- */

.pagina-busca {
  display: grid;
  gap: var(--spacing-region-gap);
  padding-inline: var(--spacing-container-padding-inline);
}

.pagina-busca-filtros {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.pagina-busca-filtros-aplicados {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Link que remove um filtro aplicado: `min-height` de 44px cumpre o alvo
 * de toque, como .cabecalho-categoria e .rodape-link ja fazem. */
.pilula-removivel {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 44px;
  padding-inline: var(--space-3);
  border-radius: var(--corner-pill);
  border: 1px solid var(--card-border);
  color: var(--text-secondary);
  text-decoration: none;
}

/* Pagina de produto (DON-125) ----------------------------------------------
   Mobile first: uma coluna; imagem e corpo lado a lado a partir de 768px.
   minmax(0, 1fr) e min-width: 0 impedem nome/descricao longos de estourar a
   largura em telas estreitas (mesma defesa do cartao-produto). */
.pagina-produto {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--spacing-region-gap);
  padding-inline: var(--spacing-container-padding-inline);
  min-width: 0;
}

.pagina-produto-imagem {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--card-border);
  border-radius: var(--corner-surface);
  background-color: var(--surface-sunken);
  color: var(--text-muted);
}

.pagina-produto-corpo {
  display: grid;
  gap: var(--space-3);
  min-width: 0;
}

.pagina-produto-nome,
.pagina-produto-descricao,
.pagina-produto-variante-nome {
  overflow-wrap: anywhere;
}

.pagina-produto-categoria,
.pagina-produto-descricao {
  color: var(--text-secondary);
}

/* Link da categoria na pagina de produto: e um <a>, e sem display flexivo
 * o min-height nao se aplica (elemento inline nao tem altura). Alvo de
 * toque de 44px, como os demais links do site. */
.pagina-produto-categoria a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.pagina-produto-preco,
.pagina-produto-destaque {
  color: var(--text-primary);
  font-weight: 600;
}

.pagina-produto-esgotado,
.pagina-produto-sem-preco,
.pagina-produto-variante-esgotado {
  color: var(--text-muted);
}

.pagina-produto-variantes-lista {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pagina-produto-variantes-item a {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--corner-control);
  color: var(--text-primary);
  text-decoration: none;
  min-width: 0;
}

.pagina-produto-variantes-item a[aria-current="true"] {
  border-color: var(--accent-default);
}

@media (min-width: 768px) {
  .pagina-produto {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

/* ---------------------------------------------------------------------
 * Home publica (DON-122) -- so o layout das secoes; a grade de produtos
 * e o card ja tem CSS proprio (.grade-de-produtos, .cartao-produto).
 * `minmax(0, 1fr)` e `min-width: 0` repetem a mesma defesa de estouro de
 * largura das demais paginas do site (mobile first, sem cor propria).
 * --------------------------------------------------------------------- */

.pagina-home {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--spacing-region-gap);
  padding-inline: var(--spacing-container-padding-inline);
  min-width: 0;
}

.pagina-home-secao {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  min-width: 0;
}

.pagina-home-secao-cabecalho {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.pagina-home-secao-ver-todos {
  color: var(--accent-default);
}

/* Faixa fixa do preview da Home no painel (DON-141). Sticky no topo para
 * acompanhar a rolagem; tokens existentes, sem cor propria. Alvos de toque
 * de 44px no input e nos botoes. */
.faixa-de-preview {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--spacing-container-padding-inline);
  background-color: var(--surface-inverse);
  color: var(--text-on-inverse);
  border-bottom: 1px solid var(--border-subtle);
}

.faixa-de-preview p {
  margin: 0;
}

.faixa-de-preview input,
.faixa-de-preview .botao {
  min-height: 44px;
}

/* ---------------------------------------------------------------------
 * Carrossel de banners da Home (DON-160) -- mobile first, sem cor propria.
 * Sem JavaScript a faixa rola na horizontal com scroll-snap: todos os
 * banners continuam acessiveis. Com o modulo, `.carrossel-ativo` esconde a
 * rolagem e mostra um slide por vez.
 * --------------------------------------------------------------------- */

.carrossel-faixa {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.carrossel-slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
}

.carrossel-slide img {
  width: 100%;
  height: auto;
}

.carrossel-ativo .carrossel-faixa {
  overflow: hidden;
}

.carrossel-ativo .carrossel-slide[aria-hidden="true"] {
  display: none;
}

.carrossel-controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.carrossel-controle,
.carrossel-indicador,
.carrossel-pausar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding-inline: var(--space-3);
  border: 1px solid var(--card-border);
  border-radius: var(--corner-control);
  background-color: var(--surface-raised);
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}

.cartao-categoria {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--card-border);
  border-radius: var(--corner-surface);
  background-color: var(--surface-raised);
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 600;
}

.chamada-da-home {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-5);
  border: 1px solid var(--card-border);
  border-radius: var(--corner-surface);
  background-color: var(--surface-raised);
}

.chamada-da-home a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-link);
}

/* md (768px) -- ver a escala de breakpoints em tokens.css. */
@media (min-width: 768px) {
  .chamada-da-home {
    padding: var(--space-6);
  }
}

/* DON-213: login da revendedora, celular-primeiro (a partir de 360 px, toques de 44 px). */
.pagina-login-revendedora {
  box-sizing: border-box;
  max-width: 100%;
}

.pagina-login-revendedora .botao,
.pagina-login-revendedora .campo-entrada,
.pagina-login-revendedora a {
  min-height: 44px;
}

.pagina-login-revendedora .botao {
  width: 100%;
}
