/*
 * Primitivos de UI do sdk-ui, traduzindo (não importando) os variants do
 * ZardUI usados pelas telas-alvo (Contratos, Evolution, Meta-WABA):
 * button.variants.ts, badge.variants.ts, alert.variants.ts,
 * input.variants.ts, table.variants.ts (b2b-v2-site/src/app/shared/components).
 *
 * São classes CSS puras (sem Tailwind) porque o apps-proxy não tem
 * pipeline de build de front-end — mantém a filosofia atual do projeto
 * (scripts simples, sem bundler novo).
 */

/* ---------- Button (zr-btn) ---------- */
.zr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap;
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 500;
  height: 2.25rem;
  padding: 0.5rem 1rem;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color 0.15s, opacity 0.15s;
  outline: none;
}
.zr-btn:disabled {
  pointer-events: none;
  opacity: 0.5;
}
.zr-btn:focus-visible {
  border-color: var(--ring);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 50%, transparent);
}
.zr-btn--sm { height: 2rem; padding: 0 0.75rem; gap: 0.375rem; }
.zr-btn--lg { height: 2.5rem; padding: 0 1.5rem; }
/* 🔴 Mesma armadilha do `.zr-alert[hidden]` abaixo — achada em verificação na
   tela (T-B1, "Configurações do funil"): o botão "Tornar padrão" continuava
   visível e clicável com `hidden` posto pelo JS, porque `display:inline-flex`
   é regra de AUTOR e vence o `[hidden] { display:none }` do navegador. Vale
   para todo `.zr-btn` escondido por `elemento.hidden = true` no projeto —
   quem usa `style.display='none'` explícito nunca bateu nisso. */
.zr-btn[hidden] { display: none; }

.zr-btn--default {
  background: var(--primary);
  color: var(--primary-foreground);
}
.zr-btn--default:hover { opacity: 0.9; }

.zr-btn--secondary {
  background: var(--secondary);
  color: var(--secondary-foreground);
}
.zr-btn--secondary:hover { opacity: 0.8; }

.zr-btn--outline {
  background: var(--background);
  color: var(--foreground);
  border-color: var(--border);
}
.zr-btn--outline:hover { background: var(--accent); color: var(--accent-foreground); }

.zr-btn--destructive {
  background: var(--destructive);
  color: var(--destructive-foreground);
}
.zr-btn--destructive:hover { opacity: 0.9; }

.zr-btn--ghost {
  background: transparent;
  color: var(--foreground);
}
.zr-btn--ghost:hover { background: var(--accent); color: var(--accent-foreground); }

/* ---------- Badge (zr-badge) ---------- */
.zr-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  width: fit-content;
  white-space: nowrap;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  padding: 0.125rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
}
.zr-badge--pill { border-radius: 9999px; }
/* Mesma armadilha de `.zr-btn[hidden]` acima, mesmo achado — `.zr-badge`
   também fixa `display` como regra de autor. */
.zr-badge[hidden] { display: none; }

.zr-badge--default { background: var(--primary); color: var(--primary-foreground); }
.zr-badge--secondary { background: var(--secondary); color: var(--secondary-foreground); }
.zr-badge--destructive { background: var(--destructive); color: #fff; }
.zr-badge--outline { background: transparent; color: var(--foreground); border-color: var(--border); }

/* ---------- Alert / status message (zr-alert) ---------- */
.zr-alert {
  position: relative;
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  border-radius: var(--radius-lg);
  padding: 0.875rem 1rem;
  font-size: 0.875rem;
  border: 1px solid var(--border);
}
/* 🔴 `display:flex` acima é regra de AUTOR e vence o `[hidden] { display:none }`
   do navegador — então um alerta vazio, com o atributo `hidden` posto pelo JS,
   continua ocupando espaço como uma caixa com borda e nada dentro. Foi assim
   que o painel de BI apareceu com um retângulo vazio no topo, achado em
   conferência na tela. Vale para os 34 `.zr-alert[hidden]` do projeto, não só
   para aquele — `PainelBase.anunciar()` esconde por `el.hidden`, que é o
   caminho certo, e era o CSS que não deixava. Mesma armadilha já registrada
   para `.modal[hidden]` em `public/styles.css`. */
.zr-alert[hidden] { display: none; }

.zr-alert--info    { color: var(--info);    background: var(--info-bg-soft);    border-color: color-mix(in srgb, var(--info) 35%, transparent); }
.zr-alert--success { color: var(--success); background: var(--success-bg-soft); border-color: color-mix(in srgb, var(--success) 35%, transparent); }
.zr-alert--warning  { color: var(--warning);  background: var(--warning-bg-soft);  border-color: color-mix(in srgb, var(--warning) 35%, transparent); }
.zr-alert--error   { color: var(--destructive); background: var(--error-bg-soft); border-color: color-mix(in srgb, var(--destructive) 35%, transparent); }

/* ---------- Input / select / textarea (zr-input) ---------- */
.zr-input,
.zr-select,
.zr-textarea {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--input);
  background: var(--background);
  color: var(--foreground);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  padding: 0 0.75rem;
  height: 2.5rem;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.zr-textarea { height: auto; min-height: 5rem; padding: 0.5rem 0.75rem; resize: vertical; }
.zr-input::placeholder, .zr-textarea::placeholder { color: var(--muted-foreground); }
.zr-input:focus-visible,
.zr-select:focus-visible,
.zr-textarea:focus-visible {
  border-color: var(--ring);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 50%, transparent);
}
.zr-input:disabled, .zr-select:disabled, .zr-textarea:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.zr-input--error, .zr-select--error { border-color: var(--destructive); }
.zr-input--success, .zr-select--success { border-color: var(--success); }

.zr-checkbox {
  width: 1rem;
  height: 1rem;
  border-radius: var(--radius-sm);
  accent-color: var(--primary);
}

.zr-label {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--foreground);
  display: block;
  margin-bottom: 0.25rem;
}

/* 🔴 `.zr-help` era usada e NUNCA foi declarada — 9 vezes na Central de
   Ingestão BI e 3 no `index.html`, desde que aquelas telas nasceram. Classe
   inexistente não dá erro: o texto de ajuda simplesmente saía do tamanho e da
   cor do corpo, competindo com o rótulo do campo em vez de se apagar atrás
   dele. Achado por `public/js/__tests__/bi-titulos-classes.test.js` na
   primeira execução, contra código que já estava em produção.
   Irmã de `.zr-label`: o par rótulo/ajuda de um campo de formulário. */
.zr-help {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--muted-foreground);
}

/* ---------- Table (zr-table) ---------- */
.zr-table-wrap { overflow: auto; }
.zr-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  color: var(--foreground);
}
.zr-table thead tr { border-bottom: 1px solid var(--border); }
.zr-table th {
  height: 2.5rem;
  padding: 0.5rem;
  text-align: left;
  font-weight: 500;
  color: var(--muted-foreground);
}
.zr-table td { padding: 0.5rem; vertical-align: middle; }
.zr-table tbody tr { border-bottom: 1px solid var(--border); transition: background-color 0.15s; }
.zr-table tbody tr:last-child { border-bottom: 0; }
.zr-table tbody tr:hover { background: color-mix(in oklch, var(--muted) 50%, transparent); }

/* ---------- Tabs (zr-tabs) ---------- */
.zr-tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--border);
  /* 🔴 Sem isto, uma barra com rótulos longos empurra a PÁGINA para o lado em
     tela estreita — o piso de qualidade do DESIGN.md proíbe scroll horizontal
     do body. Medido na sessão 124 a 375px: as três abas do BI somam 307px num
     container de 278px, e a página inteira passava a rolar. O mockup daquela
     tela já declarava esta linha na cópia local dele, o que mostra que a falta
     era do primitivo, não da tela. `flex-shrink: 0` no botão é o par: sem ele,
     o flex espreme os rótulos em vez de deixar rolar. */
  overflow-x: auto;
}
.zr-tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0.5rem 0.875rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--muted-foreground);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.zr-tab:hover { color: var(--foreground); }
.zr-tab.active { color: var(--foreground); border-bottom-color: var(--primary); }
/* Aba desabilitada (ex.: Geografia sem carga de cobertura) — visível, sem
   clique, com cadeado. O `:disabled` já bloqueia o clique nativo. */
.zr-tab:disabled { cursor: not-allowed; opacity: 0.5; }
.zr-tab:disabled:hover { color: var(--muted-foreground); }
.zr-tab--travada::before { content: "\1F512"; margin-right: 0.3rem; font-size: 0.85em; }

/* ---------- Card / panel container ---------- */
.zr-card {
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

/* ---------- Skeleton (zr-skeleton) ----------
 * Placeholder com a FORMA do conteúdo que está chegando. Não é spinner: o
 * spinner diz "espere" e nada mais; o skeleton diz o que vem, quanto vem, e
 * ocupa o espaço final — que é o que impede o salto de layout quando o dado
 * chega. Tamanho é do call site (`style="height: …; width: …"`), porque quem
 * sabe a forma da linha é a tela, não o primitivo.
 *
 * Sincronização: os variants.ts de skeleton do b2b-v2-site NÃO foram
 * conferidos (o repo não está disponível aqui) — ver DESIGN.md, "Os dois
 * últimos (sessão 117)".
 */
.zr-skeleton {
  background: var(--accent);
  border-radius: var(--radius-md);
  animation: zr-pulsar 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes zr-pulsar {
  50% { opacity: 0.5; }
}

/* ---------- Empty state (zr-empty) ----------
 * Tela vazia com as TRÊS partes que o DESIGN.md ("Texto de interface" §4) exige:
 * o que é, por que está vazia, e a ação que a preenche. A ação é o ponto —
 * `Nenhum registro encontrado.` sozinho é um beco sem saída, e era o padrão do
 * portal até a sessão 117.
 *
 * A ação NÃO ganha estilo próprio aqui: ponha um `.zr-btn` + variante dentro.
 * Duplicar o botão seria criar um segundo botão que diverge do primeiro.
 */
.zr-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2.5rem 1.5rem;
  text-align: center;
}
/* 🔴 Mesma armadilha do `.zr-alert[hidden]` acima, achada de novo em
   verificação na tela (T-B1, "Configurações do funil"): `display:flex` é
   regra de AUTOR e vence o `[hidden] { display:none }` do navegador, então
   `elemento.hidden = true` sozinho não escondia o estado vazio — ele
   continuava ocupando a tela, com o ícone/título/descrição por cima do
   conteúdo real. Sem este override, TODO `.zr-empty` escondido por JS no
   projeto tem o mesmo defeito, não só este. */
.zr-empty[hidden] { display: none; }
.zr-empty-icone {
  font-size: 1.75rem;
  line-height: 1;
  margin-bottom: 0.25rem;
  opacity: 0.6;
}
.zr-empty-titulo {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--foreground);
}
/* `--muted-foreground` sobre `--background` mede 4.74:1 no navegador — passa AA
   (4.5:1) para os 14px. É o mesmo par do texto secundário do shell, já medido
   na sessão 104; não reduza a fonte daqui sem remedir. */
.zr-empty-descricao {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted-foreground);
  max-width: 42ch;
}
/* Só respira acima do botão quando ele existe — estado vazio sem ação (uma
   busca sem resultado, por exemplo) não fica com folga sobrando embaixo. */
.zr-empty > .zr-btn {
  margin-top: 0.5rem;
}

/* ---------- Sino de notificação (Help-Desk) ----------
 * Compartilhado entre suporte-painel.html e o topbar do produto inteiro em
 * index.html — é o mesmo widget nos dois cabeçalhos, ver
 * public/js/notificacoes-bell.js. Ícone em `currentColor` (preto no tema
 * claro) porque emoji não obedece `color`; badge é só uma bolinha (sem
 * número) — ver `renderizarBadge()`.
 */
.sino {
  position: relative;
  display: inline-flex;
}
.sino-icone {
  /* Tamanho vem do token (.zr-icone). Aqui fica só a cor, que é o que distingue
     este uso — ver docs/specs/ICONES.md §6. */
  color: var(--foreground);
}
/* Bolinha de "tem não lida", sem número — só liga/desliga (ver renderizarBadge). */
.sino-badge {
  position: absolute;
  top: 0.15rem;
  right: 0.15rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 9999px;
  background: var(--destructive);
}
.sino-dropdown {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  width: 22rem;
  max-height: 26rem;
  overflow-y: auto;
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 24px color-mix(in oklch, black 20%, transparent);
  z-index: 50;
}
.sino-dropdown-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.8rem;
  font-weight: 600;
}
.sino-lista { display: flex; flex-direction: column; }
.sino-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.8rem;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  font-size: 0.8rem;
  color: inherit;
}
.sino-item:last-child { border-bottom: none; }
.sino-item:hover { background: color-mix(in oklch, var(--muted) 50%, transparent); }
.sino-item--nao-lido { background: color-mix(in oklch, var(--primary) 6%, transparent); }
.sino-item-linha1 { display: flex; gap: 0.4rem; font-weight: 600; }
.sino-item-assunto { font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sino-item-linha2 { color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sino-item-quando { color: var(--muted-foreground); font-size: 0.7rem; }
.sino-vazio { padding: 1.2rem 0.8rem; text-align: center; color: var(--muted-foreground); font-size: 0.8rem; }

/* =========================================================================
   PISO DE QUALIDADE — movimento reduzido
   =========================================================================
   Preferência do SISTEMA OPERACIONAL, não do produto: não existe tela onde
   ligá-la, e quem tem sensibilidade vestibular não tem outro escape. Vem por
   último no arquivo de propósito — precisa vencer as regras acima, e a
   especificidade dentro de `@media` é a mesma do seletor sem ele.

   `!important` aqui é deliberado: o alvo inclui `style` inline e animação
   declarada em qualquer folha, que a cascata normal não alcança.

   Não neutraliza `opacity`/`color` — só a PASSAGEM entre estados. O botão
   continua mudando de cor no hover; ele só para de levar 150ms para isso.

   Guardado por public/js/__tests__/piso-qualidade.test.js.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────────────
   Ícone — `.zr-icone`
   Especificação: docs/specs/ICONES.md §6. O markup NUNCA é escrito à mão: sai de
   `icone()` (public/js/icone.js), que é quem decide o prefixo, o caminho do sprite
   e entre `aria-hidden` e `role="img"`.

   🔴 A COR não é declarada aqui, e isso NÃO é omissão: os símbolos trazem
   `fill="currentColor"` como atributo de apresentação, herdado pela árvore-sombra
   do `<use>`. O ícone segue a `color` do elemento que o usa — o token do botão, do
   badge, do que for — no claro e no escuro, sem regra extra. Declarar `color` ou
   `fill` em `.zr-icone` QUEBRARIA isso: o ícone passaria a ter cor própria e
   deixaria de acompanhar o estado (hover, desabilitado, tema).
   Verificado em navegador (B0, 19/09/2026): a cor computada acompanhou o token nos
   dois esquemas.

   ⚠️ O atributo era `stroke="currentColor"` enquanto a biblioteca era Tabler, que
   desenha por TRAÇO; o Phosphor (21/09/2026) desenha por PREENCHIMENTO. Quem gera o
   sprite carimba o atributo certo (`scripts/gerar-sprite-icones.mjs`) — aqui não há
   nada a mudar, mas a nota fica porque "não declarar cor" só funciona enquanto o
   símbolo trouxer o SEU atributo.
   ───────────────────────────────────────────────────────────────────────────── */
.zr-icone {
  width: var(--icon-size-default, 16px);
  height: var(--icon-size-default, 16px);
  flex-shrink: 0;           /* não encolhe dentro de botão em flex */
  vertical-align: -0.125em; /* alinha com a linha de base do texto */
}

/* 🔴 Estado vazio pede tamanho de ILUSTRAÇÃO, não de interface (16px). A tela vazia
   existe para CONVIDAR a agir (DESIGN.md, "Texto de interface"), e um traço de 16px
   ali fica frio — foi o argumento que segurou esta conversão até 2026-09-20. O tom
   suave continua vindo do `opacity` de `.zr-empty-icone`, que envolve o ícone. */
.zr-icone--vazio {
  width: var(--icon-size-vazio, 1.75rem);
  height: var(--icon-size-vazio, 1.75rem);
}

.zr-icone--badge {
  width: var(--icon-size-badge, 12px);
  height: var(--icon-size-badge, 12px);
}

/* 🔴 Mesma armadilha do `.zr-btn[hidden]`/`.zr-badge[hidden]`/`.zr-empty[hidden]`
   acima — esta é a QUINTA vez. Um primitivo que fixa `display` como regra de autor
   VENCE o `[hidden]` do navegador por empate de especificidade + ordem no arquivo,
   e o elemento "escondido" continua ocupando espaço e clicável. O `.zr-icone` nasce
   com o override para não repetir. */
.zr-icone[hidden] { display: none; }
