/* =====================================================================
   kit/components.css — biblioteca de componentes.

   Se um componente existe aqui, a tela NAO redefine: usa. O <style> de
   cada template fica so pro que e' exclusivo daquela tela. Antes desta
   camada, KPI, tabela, modal e badge tinham tres implementacoes
   concorrentes e dois vocabularios de nome (--primario vs --primary).
   ===================================================================== */

/* ============================== GRIDS ============================== */
.grid-2, .grid-3, .grid-4, .grid-sidebar {
  display: grid;
  gap: var(--space-3);
}
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-sidebar { grid-template-columns: 1fr; }

@media (min-width: 720px) {
  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1000px) {
  .grid-2, .grid-3, .grid-4, .grid-sidebar { gap: var(--space-4); }
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-sidebar { grid-template-columns: minmax(0, 1fr) 332px; }
}

/* =============================== BOTOES ===============================
   Alvo de 44px no toque (recomendacao de acessibilidade); cai pra 38px a
   partir de 880px, onde o ponteiro e' preciso. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: inherit; font-size: var(--text-base); font-weight: var(--weight-bold);
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: filter var(--dur-rapida) var(--ease-saida),
              transform var(--dur-rapida) var(--ease-saida),
              background var(--dur-rapida) var(--ease-saida),
              border-color var(--dur-rapida) var(--ease-saida),
              box-shadow var(--dur-base) var(--ease-saida);
}
.btn svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.btn--primary { background: var(--gradient-accent); color: var(--text-on-accent); box-shadow: var(--shadow-accent); }
/* Sobe 1px e o brilho cresce junto: o botao "levanta" pro cursor. */
.btn--primary:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: var(--shadow-accent-lg), 0 0 0 4px var(--accent-soft); }
.btn--primary:active { transform: translateY(0) scale(.97); }

.btn--ghost { background: transparent; border-color: var(--border-default); color: var(--text-secondary); }
.btn--ghost:hover { background: var(--surface-2); color: var(--text-primary); border-color: var(--text-muted); }
.btn--ghost:active { transform: scale(.98); }

.btn--danger { background: var(--danger); color: #2b0a0a; }
.btn--danger:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn--danger:active { transform: translateY(0) scale(.97); }

.btn--sm { min-height: 34px; padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
.btn--lg { min-height: 50px; padding: var(--space-4) var(--space-6); font-size: var(--text-md); }
.btn--bloco { width: 100%; }
.btn:disabled { opacity: .5; cursor: default; transform: none; box-shadow: none; filter: none; }

@media (min-width: 880px) {
  .btn { min-height: 38px; padding: var(--space-2) var(--space-4); }
  .btn--sm { min-height: 32px; }
}

/* Estados do botao de acao (usados por NexiUI.estadoBotao). */
.btn--ok { background: var(--accent); color: var(--text-on-accent); }
.btn--falhou { background: var(--danger); color: #2b0a0a; animation: tremer .4s var(--ease-suave); }
.btn__spinner {
  display: none;
  width: 13px; height: 13px; flex: none;
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, .28);
  border-top-color: currentColor;
  animation: girar .6s linear infinite;
}
.btn--carregando .btn__spinner { display: inline-block; }

/* Botao de icone puro. */
.icon-btn {
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer; padding: 0;
  transition: background var(--transition-base), color var(--transition-base),
              border-color var(--transition-base), transform var(--dur-rapida) var(--ease-saida);
}
.icon-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-btn:hover { background: var(--surface-3); color: var(--text-primary); border-color: var(--text-muted); }
.icon-btn:active { transform: scale(.94); }
.icon-btn--perigo:hover { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger); }
.icon-btn--sm { width: 32px; height: 32px; }
.icon-btn--sm svg { width: 15px; height: 15px; }

/* =============================== BADGES ===============================
   Sempre fundo 10% + borda 28%: em tema escuro o fundo sozinho quase
   desaparece, a borda e' o que da forma ao selo. */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  white-space: nowrap;
  background: var(--accent-soft); border: 1px solid var(--accent-border); color: var(--accent);
}
.badge svg { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.badge--success { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
.badge--info    { background: var(--info-soft);    border-color: var(--info-border);    color: var(--info); }
.badge--warning { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); }
.badge--danger  { background: var(--danger-soft);  border-color: var(--danger-border);  color: var(--danger); }
.badge--rose    { background: var(--rose-soft);    border-color: var(--rose-border);    color: var(--rose); }
.badge--violet  { background: var(--violet-soft);  border-color: var(--violet-border);  color: var(--violet); }
.badge--cyan    { background: var(--cyan-soft);    border-color: var(--cyan-border);    color: var(--cyan); }
.badge--orange  { background: var(--orange-soft);  border-color: var(--orange-border);  color: var(--orange); }
.badge--white   { background: var(--surface-3);     border-color: var(--border-default); color: var(--text-primary); }
.badge--muted   { background: var(--surface-3);    border-color: var(--border-default); color: var(--text-secondary); }

/* Ponto de estado. Forma + cor: da pra distinguir sem depender de
   enxergar diferenca entre verde e vermelho. */
.badge__dot { width: 6px; height: 6px; flex: none; border-radius: 50%; background: currentColor; }
/* Pulsa SO quando representa algo em andamento de verdade. */
.badge__dot--pulsando { animation: pulsar-ponto 1.6s var(--ease-suave) infinite; }
/* Selo que acabou de mudar de valor. */
.badge.mudou { animation: destacar var(--dur-lenta) var(--ease-mola); }

/* =============================== CARDS =============================== */
.card {
  background: var(--surface-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--card-edge), var(--shadow-card);
  overflow: hidden;
}
/* flex-wrap: no celular o cabecalho costuma carregar filtro + busca, e sem
   quebra de linha o ultimo elemento fica cortado fora do card. */
.card__header {
  display: flex; align-items: center; gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-4);
  border-bottom: 1px solid var(--border-default);
}
.card__header > svg { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--accent); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.card__title { font-size: var(--text-base); font-weight: var(--weight-bold); letter-spacing: -.01em; }
.card__subtitle { font-size: var(--text-xs); color: var(--text-muted); }
.card__body { padding: var(--space-4); }
.card--hoverable { cursor: pointer; transition: transform var(--dur-base) var(--ease-saida), border-color var(--dur-base) var(--ease-saida), box-shadow var(--dur-base) var(--ease-saida); }
.card--hoverable:hover { transform: translateY(-2px); border-color: var(--border-accent); box-shadow: var(--card-edge), var(--shadow-card-hover); }
.card--plano { box-shadow: var(--card-edge); }

@media (min-width: 880px) {
  .card__header { padding: var(--space-4) var(--space-5); }
  .card__body { padding: var(--space-5); }
}

/* ================================ KPI ================================
   Cartao de metrica. A letra d'agua (data-watermark) diz do que o cartao
   trata antes de a pessoa ler o rotulo. O glow de canto acompanha a cor
   semantica — e' exclusivo do KPI, nao se repete em card comum. */
.kpi {
  position: relative;
  overflow: hidden;
  background: var(--surface-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  box-shadow: var(--card-edge);
  transition: transform var(--dur-base) var(--ease-saida),
              border-color var(--dur-base) var(--ease-saida),
              box-shadow var(--dur-base) var(--ease-saida);
}
.kpi:hover { transform: translateY(-2px); border-color: var(--border-accent); box-shadow: var(--card-edge), var(--shadow-md); }

/* Letra d'agua. Desliza de leve no hover — da profundidade ao cartao. */
.kpi::after {
  content: attr(data-watermark);
  position: absolute; right: -4px; bottom: -16px;
  font-size: 56px; font-weight: var(--weight-bold);
  line-height: 1; letter-spacing: -.04em;
  color: var(--watermark);
  pointer-events: none;
  transition: transform var(--dur-lenta) var(--ease-saida);
}
.kpi:hover::after { transform: translateX(-4px) translateY(-2px); }

/* Glow de canto: mancha de cor no topo-direito, bem esmaecida. */
.kpi::before {
  content: "";
  position: absolute; top: -40%; right: -20%;
  width: 180px; height: 180px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--kpi-glow, var(--accent-soft)) 0%, transparent 70%);
  pointer-events: none;
  opacity: .9;
}
.kpi--info    { --kpi-glow: var(--info-soft); }
.kpi--warning { --kpi-glow: var(--warning-soft); }
.kpi--danger  { --kpi-glow: var(--danger-soft); }
.kpi--rose    { --kpi-glow: var(--rose-soft); }
.kpi--violet  { --kpi-glow: var(--violet-soft); }
.kpi--cyan    { --kpi-glow: var(--cyan-soft); }
.kpi--orange  { --kpi-glow: var(--orange-soft); }

.kpi__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.kpi__label {
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
}
.kpi__icon {
  display: grid; place-items: center;
  width: 30px; height: 30px; flex: none;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  color: var(--text-muted);
}
.kpi__icon svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.kpi__icon--accent  { background: var(--accent-soft);  border-color: var(--accent-border);  color: var(--accent); }
.kpi__icon--info    { background: var(--info-soft);    border-color: var(--info-border);    color: var(--info); }
.kpi__icon--warning { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); }
.kpi__icon--danger  { background: var(--danger-soft);  border-color: var(--danger-border);  color: var(--danger); }
.kpi__icon--rose    { background: var(--rose-soft);    border-color: var(--rose-border);    color: var(--rose); }
.kpi__icon--violet  { background: var(--violet-soft);  border-color: var(--violet-border);  color: var(--violet); }
.kpi__icon--cyan    { background: var(--cyan-soft);    border-color: var(--cyan-border);    color: var(--cyan); }
.kpi__icon--orange  { background: var(--orange-soft);  border-color: var(--orange-border);  color: var(--orange); }

.kpi__value {
  margin-top: var(--space-3);
  font-size: 26px; font-weight: var(--weight-bold);
  line-height: 1; letter-spacing: -.02em;
  /* tabular-nums: digitos de largura igual, entao o numero nao "pula" de
     largura enquanto a contagem animada roda. */
  font-variant-numeric: tabular-nums;
  display: inline-block;
  transform-origin: left center;
}
.kpi__value.mudou { animation: destacar var(--dur-lenta) var(--ease-mola); }
.kpi__value--accent  { color: var(--accent); }
.kpi__value--info    { color: var(--info); }
.kpi__value--warning { color: var(--warning); }
.kpi__value--danger  { color: var(--danger); }
.kpi__value--rose    { color: var(--rose); }
.kpi__value--violet  { color: var(--violet); }
.kpi__value--cyan    { color: var(--cyan); }
.kpi__value--orange  { color: var(--orange); }

.kpi__footer {
  margin-top: var(--space-2);
  font-size: var(--text-xs); color: var(--text-muted);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
/* Fio de acento no topo + tinta verde: o cartao que importa mais. */
.kpi--featured { border-color: var(--border-accent); }
.kpi--featured::after { color: var(--accent-soft); }
.kpi--featured .kpi__label { color: var(--accent); }

@media (min-width: 880px) {
  .kpi { padding: var(--space-5); }
  .kpi__value { font-size: var(--text-2xl); }
}

/* ============================== DELTA ============================== */
.delta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--text-xs); font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.delta--up { color: var(--accent); }
.delta--dn { color: var(--danger); }
.delta--flat { color: var(--text-muted); }

/* ============================== STAT ============================== */
.stat { min-width: 0; }
.stat__label {
  font-size: 10.5px; font-weight: var(--weight-bold);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-muted);
}
.stat__value {
  margin-top: 3px;
  font-size: var(--text-base); font-weight: var(--weight-semibold);
  color: var(--text-primary);
  word-break: break-word;
}
.stat__value--mono { font-family: var(--font-mono); font-size: var(--text-sm); letter-spacing: -.02em; }
.stat__value--accent { color: var(--accent); }

/* ============================= SECAO =============================
   Cabecalho de secao: chip numerado (ou icone) + titulo + divisoria que
   esvai + contagem. A divisoria em gradiente le como "titulo -> linha",
   nao como uma regua cortando a tela. */
.section { margin-bottom: var(--space-6); }
.section__head {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.section__head > svg { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.section__head h2 {
  margin: 0;
  font-size: var(--text-md); font-weight: var(--weight-bold);
  letter-spacing: -.01em; white-space: nowrap;
}
.section__num {
  display: grid; place-items: center;
  width: 24px; height: 24px; flex: none;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-xs); font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.section__line { flex: 1; height: 1px; min-width: var(--space-4); background: var(--gradient-divider); }
.section__count {
  flex: none;
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* ============================== TABELA ==============================
   Mobile-first: por padrao cada registro e' um CARTAO (uma tabela de 8
   colunas e' ilegivel em 390px). A partir de 880px vira tabela de
   verdade. As celulas carregam `data-label` pro rotulo do modo cartao. */
.table-wrap { padding: var(--space-3) var(--space-4) var(--space-4); }
.table { width: 100%; border-collapse: collapse; }
.table thead { display: none; }
.table tbody tr {
  display: block;
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  transition: border-color var(--dur-base) var(--ease-saida), transform var(--dur-rapida) var(--ease-saida);
}
.table tbody td {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  font-size: var(--text-base); color: var(--text-secondary);
  text-align: right;
  border-bottom: 1px solid var(--border-subtle);
}
.table tbody td::before {
  content: attr(data-label);
  flex: none;
  font-size: 10.5px; font-weight: var(--weight-bold);
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted); text-align: left;
}
.table tbody td:last-child { border-bottom: none; padding-bottom: 0; }

/* Celula-titulo do cartao (nome), com avatar da inicial.
   O avatar e' ::before (nao um elemento): o JS le `.table__lead`.textContent
   pra montar o dialogo de exclusao, e conteudo gerado por CSS nao entra no
   textContent — a inicial nao vaza pro nome. */
.table__lead {
  display: flex !important; align-items: center; justify-content: flex-start !important;
  gap: var(--space-3);
  text-align: left !important;
  font-size: var(--text-md) !important; font-weight: var(--weight-bold);
  color: var(--text-primary) !important;
  padding: 0 0 var(--space-3) !important;
  margin-bottom: var(--space-1);
}
/* Seletor precisa ser MAIS especifico que `.table tbody td::before` (que
   escreve o data-label do modo cartao), senao a bolha do avatar sai com a
   palavra "NOME" dentro em vez da inicial. */
.table tbody td.table__lead::before {
  content: attr(data-inicial);
  flex: none;
  width: 34px; height: 34px;
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  display: grid; place-items: center;
  font-size: var(--text-base); font-weight: var(--weight-bold);
  letter-spacing: 0; text-transform: uppercase;
}
/* Nome + linha de apoio dentro da mesma celula (usado quando o avatar e' um
   elemento de verdade, nao o ::before de .table__lead). */
.table__lead-name { font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--text-primary); }
.table__lead-sub { font-size: var(--text-xs); color: var(--text-muted); font-weight: var(--weight-medium); margin-top: 2px; }

/* Numero: monoespacado tabular, alinhado a direita. */
.table .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.table .num--accent { color: var(--accent); font-weight: var(--weight-bold); }

/* Linha clicavel. */
.table tbody tr.clicavel { cursor: pointer; }
.table tbody tr.clicavel:active { border-color: var(--border-accent); transform: scale(.99); }

/* Entrada em cascata (aplicada 1x, ver JS).

   `backwards`, NAO `both`: o motivo de ter fill-mode aqui e' so' o ANTES —
   com `animation-delay` escalonado (--fila-passo * --i), sem isso a linha
   apareceria inteira e SO' DEPOIS voltaria pro opacity:0 pra animar, um
   flash antes da vez dela. `backwards` cobre exatamente essa fase.

   `both` cobria essa MESMA fase e AINDA segurava `transform: none` pra
   sempre depois que a animacao termina — animacao com fill-mode ativo tem
   prioridade sobre CSS normal, entao qualquer `:hover { transform: ... }'
   declarado depois NUNCA se aplicava em nenhuma linha vinda do servidor.
   Foi assim que o hover de deslizar a linha (.clicavel:hover, abaixo) foi
   descoberto morto: o computed style continuava travado em identidade,
   `:hover` ou não. */
.table tbody tr.linha-entra { animation: entrar-subindo var(--dur-lenta) var(--ease-saida) backwards; animation-delay: calc(var(--fila-passo) * var(--i, 0)); }
/* Linha que chegou depois do carregamento: acende e apaga. Mesmo motivo do
   `backwards` acima na 1a animacao; a 2a (acender-linha) fica com `both` —
   ela so' anima `background`, nao trava `transform` nenhum. */
.table tbody tr.linha-nova { animation: entrar-subindo var(--dur-lenta) var(--ease-saida) backwards, acender-linha 1.6s var(--ease-suave) .2s both; }
.table tbody tr.linha-saindo { animation: linha-sai var(--dur-base) var(--ease-suave) forwards; pointer-events: none; }

@media (min-width: 880px) {
  .table-wrap { padding: 0; overflow-x: auto; }
  .table { min-width: 860px; }
  .table thead { display: table-header-group; }
  .table th {
    position: sticky; top: 0; z-index: 1;
    text-align: left;
    padding: var(--space-3) var(--space-4);
    background: var(--surface-2);
    border-bottom: 1px solid var(--border-default);
    font-size: 10.5px; font-weight: var(--weight-bold);
    letter-spacing: .07em; text-transform: uppercase;
    color: var(--text-muted);
    white-space: nowrap;
  }
  .table tbody tr {
    display: table-row;
    background: none; border: none; border-radius: 0;
    padding: 0; margin: 0;
  }
  .table tbody tr:hover { background: var(--surface-2); }

  /* ---------------- Lixeira sob demanda + colunas deslizando ----------------
     So' desktop, de proposito: em touch o :hover fica "preso" apos o toque
     (a linha ficaria com a lixeira presa a mostra ate' tocar em outro lugar),
     e escondê-la ali tornaria impossivel excluir pelo celular. No modo
     cartao (abaixo deste breakpoint) a lixeira continua sempre visivel.

     A COLUNA DE ACOES TEM LARGURA FIXA (ver colgroup em admin.html) —
     GRANDE O SUFICIENTE PROS DOIS BOTOES O TEMPO TODO. A lixeira so' troca
     opacidade/pointer-events, nunca largura: a primeira versao fazia ela
     nascer com width:0 e crescer no hover, o que alargava a TABELA INTEIRA
     a cada hover (reflow de verdade). Isso é o suspeito nº1 do "some depois
     de passar o mouse algumas vezes": a cada hover ligando/desligando a
     pagina inteira sofria reflow, e um mouse parado (sem novo mousemove)
     sobre uma linha que se moveu alguns px por baixo dele pode deixar de
     estar "em cima" da linha. Fade puro (opacidade) não move nada, então
     não tem como esse mecanismo acontecer mais.

     As colunas do meio deslizam pra esquerda tambem — SO' PARA A VISTA
     (transform nao muda o tamanho real da celula). `--desliza-colunas`
     medido pra nao estourar o gap real entre Nome e a proxima coluna
     (~16px com o padding denso de .table--dense) — 10px deixa uns 6px de
     folga mesmo no pico do hover. */
  .table tbody tr.clicavel .acao-excluir {
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-rapida) var(--ease-saida);
  }
  .table tbody tr.clicavel:hover .acao-excluir {
    opacity: 1; pointer-events: auto;
  }

  /* `.celula-desliza` (span interno da celula, ver admin.html/rh-formularios.js)
     recebe o transform — NAO o `<td>` direto. O `<td>` carrega o padding que
     da o respiro entre colunas; transformar ele desloca o padding JUNTO, e o
     texto encosta no da coluna anterior sem espaco nenhum. `display:block` +
     `width:100%` tambem e' o que deixa `.tabela-formularios` truncar com
     reticencias (ver abaixo) — um inline-block sem largura declarada nunca
     estoura o container, entao a reticencia nunca disparava. */
  .table tbody tr.clicavel .celula-desliza {
    display: block; width: 100%;
    transition: transform var(--dur-base) var(--ease-saida);
  }
  .table tbody tr.clicavel { --desliza-colunas: 10px; }
  .table tbody tr.clicavel:hover .celula-desliza {
    transform: translateX(calc(-1 * var(--desliza-colunas)));
  }

  /* ---------------- Tabela de formularios: largura fixa por coluna ----------------
     table-layout:auto (padrao) mede cada coluna pelo conteudo mais largo —
     com 7 colunas de texto isso passava de 1140px, nunca cabendo num
     notebook comum (1366/1440) sem rolagem horizontal. Aqui a largura vem
     do <colgroup> em admin.html, fixa, e o conteudo que se adapta: nome,
     e-mail e "criado por" sao dado real (sem tamanho garantido) e truncam
     com reticencias — o valor completo continua no popup "Ver dados
     enviados". Remuneracao/Criado em/Status sao valores curtos e conhecidos
     (ver app/main.py), a coluna foi medida pra caber eles inteiros. */
  .tabela-formularios { table-layout: fixed; }
  /* Ellipsis em TODA coluna de texto, nao so' nome/e-mail/criado-por: medido,
     mesmo Remuneracao e Status (valores curtos e conhecidos hoje) estouravam
     a celula em 11px sem cortar nada — pior que truncar, o texto vazava
     visualmente por cima da coluna seguinte. A largura no colgroup ja cabe o
     conteudo atual inteiro; isto e' so' a rede de seguranca se o texto
     crescer um dia. */
  .tabela-formularios .celula-desliza {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Nome quebra em ate' 2 linhas em vez de truncar com "..." — nome de
     pessoa cortado ("Gustavo Silv...") e' pior que ocupar uma linha a mais.
     `.table__lead` (base, fora deste bloco) forca white-space:nowrap; aqui
     precisa de uma segunda regra MAIS especifica pra vencer, nao
     '!important' (nenhum dos dois usa). -webkit-line-clamp e' suporte real
     em Chromium/Firefox/Safari ha' anos apesar do prefixo — e' o jeito
     padrao de travar em N linhas com reticencia so' se passar disso (nome
     absurdamente longo nao estica a linha pro infinito).

     Nome fica num flex (`.table__lead`, avatar + texto): min-width:0
     "destrava" o item flex pra poder encolher abaixo do proprio conteudo —
     sem isso a flexbox nunca deixa o texto quebrar, so' estoura pro lado.
     `align-items:center` (herdado da regra base) ja resolve os dois casos:
     nome de 1 linha fica centralizado ao lado do avatar como sempre foi, e
     nome de 2 linhas centraliza o avatar na altura do bloco inteiro — nao
     precisou de override aqui. */
  .tabela-formularios .table__lead { white-space: normal; }
  .tabela-formularios .nome-texto {
    flex: 1; min-width: 0;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; word-break: break-word; line-height: 1.25;
  }
  .tabela-formularios td.acoes { padding-left: var(--space-2); padding-right: var(--space-2); }

  .table tbody td {
    display: table-cell;
    padding: var(--space-3) var(--space-4);
    text-align: left;
    font-size: var(--text-sm);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: middle;
  }
  .table tbody td::before { display: none; }
  /* O avatar continua no desktop: e' a ancora visual da linha. Precisa ser
     reafirmado porque a regra acima esconde todo ::before de celula. */
  .table tbody td.table__lead::before { display: grid; width: 30px; height: 30px; font-size: var(--text-sm); }
  .table__lead {
    font-size: var(--text-base) !important;
    padding: var(--space-3) var(--space-4) !important;
    margin: 0;
    /* Nome em uma linha: quebrar "Gustavo Silva Marques" em tres linhas
       desalinha as alturas e polui a varredura vertical da coluna. */
    white-space: nowrap;
  }
  .table .num { text-align: right; }
  /* Comparar datas ao correr o olho pela coluna exige que cada uma
     ocupe uma linha so. */
  .table .nowrap { white-space: nowrap; }
  .table--dense tbody td, .table--dense th { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
  /* `.table__lead` tem padding/font-size proprios com `!important` (linha
     527) — sobrevivem a `.table--dense` normalmente. Aqui precisa sobreviver
     tambem, ou a coluna Nome fica com padding/fonte MAIORES que as outras
     6 (que encolheram), desperdicando largura que falta em outro lugar. */
  .tabela-formularios.table--dense .table__lead {
    padding: var(--space-2) var(--space-3) !important;
    font-size: var(--text-xs) !important;
  }
  .table--zebra tbody tr:nth-child(even) { background: rgba(255, 255, 255, .014); }
  .table--zebra tbody tr:nth-child(even):hover { background: var(--surface-2); }
  /* Detalhe expandido embaixo da linha-mae (master-detail sem modal). */
  .table tbody tr.sub { background: var(--surface-2); }
  .table tbody tr.sub td { font-size: var(--text-xs); color: var(--text-muted); }
}

/* Coluna de acoes no fim da linha. Os botoes ficam agrupados a direita: no
   modo cartao o rotulo empurra (margin-right:auto), no modo tabela a
   propria celula alinha ao fim. */
.table td.acoes { text-align: right; gap: 6px; }
.table td.acoes::before { content: attr(data-label); margin-right: auto; }
@media (min-width: 880px) {
  .table td.acoes { display: flex; align-items: center; justify-content: flex-end; white-space: nowrap; }
}

/* ============================ LISTA ============================
   Lista arejada com avatar — para conjunto curado (pessoas), nao para
   triagem em massa (isso e' tabela). */
.list { display: flex; flex-direction: column; }
.list-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  transition: background var(--dur-rapida) var(--ease-saida);
}
.list-row:last-child { border-bottom: none; }
.list-row:hover { background: var(--surface-2); }
.list-row__avatar {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex: none;
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-sm); font-weight: var(--weight-bold);
  text-transform: uppercase;
  overflow: hidden;
}
.list-row__avatar--photo { padding: 0; border-color: var(--border-default); }
.list-row__avatar--photo img { width: 100%; height: 100%; object-fit: cover; }
.list-row__main { min-width: 0; flex: 1; }
/* display:block: sao <span> na marcacao, e sem isto o nome e o subtitulo
   saem colados na mesma linha ("Copia da CNH ou RGArquivo anexado"). */
.list-row__name { display: block; font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-row__sub { display: block; font-size: var(--text-xs); color: var(--text-muted); margin-top: 2px; }
.list-row__end { display: flex; align-items: center; gap: var(--space-2); flex: none; }

/* ============================= ALERTA ============================= */
.alert {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  font-size: var(--text-sm); line-height: 1.55;
  background: var(--info-soft); border: 1px solid var(--info-border); color: var(--text-secondary);
}
/* O atributo `hidden` vale `display: none`, mas ele vem da folha do navegador e
   perde de QUALQUER regra de classe — inclusive do `display: flex` acima. Sem
   esta linha, `<div class="alert" hidden>` aparece na tela como se o hidden nao
   existisse. Vale pra todo componente do kit que troca o `display`. */
.alert[hidden] { display: none; }
.alert > svg { width: 17px; height: 17px; flex: none; margin-top: 1px; fill: none; stroke: var(--info); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.alert a { color: inherit; font-weight: var(--weight-bold); text-decoration: underline; }
.alert--info    { background: var(--info-soft);    border-color: var(--info-border); }
.alert--info > svg    { stroke: var(--info); }
.alert--warning { background: var(--warning-soft); border-color: var(--warning-border); }
.alert--warning > svg { stroke: var(--warning); }
.alert--danger  { background: var(--danger-soft);  border-color: var(--danger-border); }
.alert--danger > svg  { stroke: var(--danger); }
.alert--success { background: var(--accent-soft);  border-color: var(--accent-border); }
.alert--success > svg { stroke: var(--accent); }

/* ========================== ESTADO VAZIO ==========================
   Tabela em branco nao diz se nao ha dado ou se o filtro zerou o
   resultado. O vazio precisa dizer qual dos dois e' e o que fazer. */
.empty {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-3);
  padding: var(--space-12) var(--space-5);
  text-align: center;
}
.empty__icon {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: var(--radius-full);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  color: var(--text-muted);
}
.empty__icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.empty__title { font-size: var(--text-md); font-weight: var(--weight-semibold); }
.empty__desc { margin: 0; font-size: var(--text-sm); color: var(--text-muted); max-width: 46ch; line-height: 1.6; }

/* ============================ PROGRESSO ============================ */
.progress {
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--surface-3);
  overflow: hidden;
}
.progress--lg { height: 10px; }
.progress__fill {
  height: 100%;
  border-radius: inherit;
  background: var(--gradient-accent);
  /* Largura E' animada aqui de proposito: e' o unico jeito de uma barra
     crescer, e ela e' pequena e isolada (nao arrasta layout em volta). */
  transition: width var(--dur-lenta) var(--ease-saida);
}
.progress__fill--warning { background: var(--gradient-warning); }
.progress__fill--danger { background: var(--gradient-danger); }
.progress__fill--info { background: var(--gradient-info); }

/* ============================== CHIPS ============================== */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px var(--space-3);
  border-radius: var(--radius-full);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  white-space: nowrap;
}
.chip svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.chip--clickable { cursor: pointer; transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base), transform var(--dur-rapida) var(--ease-saida); }
.chip--clickable:hover { background: var(--surface-3); color: var(--text-primary); }
.chip--clickable:active { transform: scale(.96); }
.chip--active { background: var(--surface-3); color: var(--text-primary); border-color: var(--text-muted); }
.chip--accent.chip--active { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
.chip__count {
  font-variant-numeric: tabular-nums;
  font-size: 10.5px;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, .06);
}

/* ======================= CONTROLE SEGMENTADO =======================
   Selecao exclusiva com 2-4 opcoes: mostra todas ao mesmo tempo, ao
   contrario de um <select>, que esconde as alternativas atras de um
   clique. O indicador desliza entre as opcoes. */
.segmented {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border-radius: var(--radius);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
}
.segmented__item {
  padding: 7px var(--space-3);
  border: none; background: none;
  border-radius: var(--radius-sm);
  font-family: inherit; font-size: var(--text-xs); font-weight: var(--weight-semibold);
  color: var(--text-muted);
  cursor: pointer; white-space: nowrap;
  transition: background var(--transition-base), color var(--transition-base);
}
.segmented__item:hover { color: var(--text-primary); }
.segmented__item.active { background: var(--surface-3); color: var(--text-primary); box-shadow: var(--shadow-sm); }
.segmented__item.active[data-tom="accent"] { background: var(--accent-soft); color: var(--accent); }
.segmented__item.active[data-tom="danger"] { background: var(--danger-soft); color: var(--danger); }
.segmented__item.active[data-tom="warning"] { background: var(--warning-soft); color: var(--warning); }
.segmented__item.active[data-tom="info"] { background: var(--info-soft); color: var(--info); }
.segmented__item.active[data-tom="orange"] { background: var(--orange-soft); color: var(--orange); }
.segmented__item.active[data-tom="violet"] { background: var(--violet-soft); color: var(--violet); }
.segmented__item.active[data-tom="muted"] { background: var(--surface-3); color: var(--text-secondary); }

/* ============================ SEARCHBAR ============================ */
.searchbar {
  position: relative;
  display: flex; align-items: center;
  flex: 1; min-width: 0;
}
.searchbar > svg {
  position: absolute; left: var(--space-3);
  width: 15px; height: 15px;
  fill: none; stroke: var(--text-muted); stroke-width: 2; stroke-linecap: round;
  pointer-events: none;
  transition: stroke var(--transition-base);
}
.searchbar:focus-within > svg { stroke: var(--accent); }
.searchbar input { padding-left: 36px; }
/* Cruz nativa do type=search em tema escuro fica invisivel; usamos a
   nossa (botao .searchbar__limpar). */
.searchbar input::-webkit-search-cancel-button { display: none; }
.searchbar__limpar {
  position: absolute; right: 6px;
  display: none; place-items: center;
  width: 26px; height: 26px;
  border: none; background: none; padding: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted); cursor: pointer;
}
.searchbar__limpar svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.searchbar__limpar:hover { background: var(--surface-3); color: var(--text-primary); }
.searchbar--preenchida .searchbar__limpar { display: grid; }

/* ============================ FORMULARIO ============================ */
.form-grid { display: flex; flex-direction: column; gap: var(--space-4); }
.field { min-width: 0; }
.field__label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: 10.5px; font-weight: var(--weight-bold);
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-muted);
}
.field__hint { display: block; margin-top: 6px; font-size: var(--text-xs); color: var(--text-muted); line-height: 1.5; }
.field__erro { display: none; margin-top: 6px; font-size: var(--text-xs); color: var(--danger); font-weight: var(--weight-semibold); }
.field--erro .field__erro { display: block; }
.field--erro .input { border-color: var(--danger-border); }
.field--ok .input { border-color: var(--accent-border); }

/* 16px no mobile: abaixo disso o iOS da zoom na pagina ao focar o campo
   e joga o formulario pra fora da tela. Cai pro token no desktop. */
.input {
  width: 100%;
  min-height: 44px;
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  font-family: inherit; font-size: 16px; font-weight: var(--weight-medium);
  color: var(--text-primary);
  transition: border-color var(--transition-base), box-shadow var(--transition-base), background var(--transition-base);
}
.input::placeholder { color: var(--text-muted); }
.input:focus {
  outline: none;
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
  background: var(--surface-3);
}
textarea.input { min-height: 92px; resize: vertical; line-height: 1.55; }
/* Seta do select desenhada por nos: a nativa nao aceita cor em tema
   escuro e aparece como um triangulo claro fora da paleta. */
select.input {
  appearance: none;
  padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23737784' stroke-width='2'%3E%3Cpath d='M6 8l4 4 4-4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 16px;
}
/* A lista ABERTA do select e' desenhada pelo sistema e herda cor e fundo do
   proprio <select> — inclusive um fundo translucido, que sobre o branco padrao
   do popup clareia e engole texto claro. Fixar no <option> mantem a lista
   legivel em qualquer estado do campo, agora e se alguem adicionar um fundo
   de erro/aviso depois. */
select.input option,
select.input optgroup {
  background-color: var(--surface-2);
  color: var(--text-primary);
}
/* Opcao vazia ("Selecione"): so um degrau mais apagada. Nao --text-muted, que
   sobre --surface-2 daria 3,8:1 — abaixo do minimo de 4,5:1 pra texto, e aqui
   ela e' item clicavel da lista, nao placeholder. */
select.input option[value=""] { color: var(--text-secondary); }
/* Sem isto o navegador pinta o campo autopreenchido de amarelo/azul
   (cor propria dele, ignora o background). box-shadow inset e' o unico
   caminho que ele respeita. */
.input:-webkit-autofill,
.input:-webkit-autofill:hover,
.input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text-primary);
  -webkit-box-shadow: 0 0 0 1000px var(--surface-2) inset;
  box-shadow: 0 0 0 1000px var(--surface-2) inset;
  caret-color: var(--text-primary);
  transition: background-color 9999s ease-in-out 0s;
}
@media (min-width: 880px) {
  .input { min-height: 38px; font-size: var(--text-base); }
}

/* Campo com icone dentro. O icone se posiciona por ESTA caixa, nao pelo
   .field inteiro: o .field inclui o rotulo acima, e centrar em 50% dele
   deixaria o icone acima do centro do input. */
.field__caixa { position: relative; display: block; }
.field__caixa > svg {
  position: absolute; left: var(--space-4); top: 50%;
  transform: translateY(-50%);
  width: 15px; height: 15px;
  color: var(--text-secondary);
  pointer-events: none;
  transition: color var(--transition-base), transform var(--dur-base) var(--ease-mola);
}
.field__caixa:focus-within > svg { color: var(--accent-hover); transform: translateY(-50%) scale(1.1); }
.field__caixa .input { padding-left: 42px; }

/* Botao de revelar senha. Fica DENTRO de .field__caixa, do lado oposto ao
   icone do campo. O svg dele nao herda o estilo de `.field__caixa > svg`
   porque nao e' filho direto — esta dentro do <button> —, entao nao vira
   `pointer-events: none`, que mataria justamente o clique. */
.field__olho {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition-base), background var(--transition-base);
}
.field__olho:hover { color: var(--text-primary); background: var(--surface-3); }
.field__olho:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.field__olho svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
/* Espaco pro botao nao cobrir o texto digitado. Classe explicita em vez de
   `:has(.field__olho)`: o seletor funciona nos navegadores atuais, mas a
   consequencia de ele nao valer e' o texto da senha passando por baixo do
   botao — nao vale correr o risco por uma classe a menos no markup. */
.field__caixa--olho .input { padding-right: 44px; }

/* ============================== STEPPER ============================== */
.stepper {
  display: inline-flex; align-items: stretch;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  overflow: hidden;
}
.stepper__btn {
  width: 34px;
  border: none; background: none;
  color: var(--text-secondary);
  font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-bold);
  cursor: pointer;
  transition: background var(--transition-base), color var(--transition-base);
}
.stepper__btn:hover { background: var(--surface-3); color: var(--text-primary); }
.stepper__input {
  width: 76px;
  border: none; background: none;
  border-left: 1px solid var(--border-default);
  border-right: 1px solid var(--border-default);
  padding: var(--space-2);
  color: var(--text-primary);
  font-family: var(--font-mono); font-size: var(--text-base);
  font-variant-numeric: tabular-nums; text-align: center;
}
.stepper__input:focus { outline: none; }
/* Setas nativas do number: escondidas (temos os botoes). */
.stepper__input::-webkit-outer-spin-button,
.stepper__input::-webkit-inner-spin-button { appearance: none; margin: 0; }
.stepper__input:disabled { color: var(--accent); }

/* ============================= TIMELINE =============================
   Grid [trilho | conteudo]. O conector em gradiente liga um no' ao
   proximo; o ultimo item nao tem conector. */
.timeline { display: flex; flex-direction: column; }
.timeline__item { display: grid; grid-template-columns: 26px 1fr; gap: var(--space-3); }
.timeline__rail { display: flex; flex-direction: column; align-items: center; }
.timeline__node {
  display: grid; place-items: center;
  width: 26px; height: 26px; flex: none;
  border-radius: var(--radius-full);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  color: var(--text-muted);
  font-size: 10px; font-weight: var(--weight-bold);
}
.timeline__node svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.timeline__node--accent  { background: var(--accent-soft);  border-color: var(--accent-border);  color: var(--accent);  box-shadow: 0 0 0 4px var(--accent-soft); }
.timeline__node--info    { background: var(--info-soft);    border-color: var(--info-border);    color: var(--info);    box-shadow: 0 0 0 4px var(--info-soft); }
.timeline__node--warning { background: var(--warning-soft); border-color: var(--warning-border); color: var(--warning); box-shadow: 0 0 0 4px var(--warning-soft); }
.timeline__node--danger  { background: var(--danger-soft);  border-color: var(--danger-border);  color: var(--danger);  box-shadow: 0 0 0 4px var(--danger-soft); }
.timeline__node--violet  { background: var(--violet-soft);  border-color: var(--violet-border);  color: var(--violet);  box-shadow: 0 0 0 4px var(--violet-soft); }
.timeline__node--cyan    { background: var(--cyan-soft);    border-color: var(--cyan-border);    color: var(--cyan);    box-shadow: 0 0 0 4px var(--cyan-soft); }
.timeline__connector { flex: 1; width: 1.5px; min-height: var(--space-4); background: linear-gradient(180deg, var(--border-default), rgba(255, 255, 255, .04)); }
.timeline__content { padding-bottom: var(--space-4); min-width: 0; }
.timeline__label { font-size: 10.5px; font-weight: var(--weight-bold); letter-spacing: .07em; text-transform: uppercase; color: var(--text-muted); }
.timeline__texto { margin: 3px 0 0; font-size: var(--text-sm); color: var(--text-primary); line-height: 1.55; }
.timeline__item:last-child .timeline__content { padding-bottom: 0; }

/* ============================== MODAL ============================== */
.modal-overlay {
  display: none;
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  /* Sem backdrop-filter, e aqui o motivo e' pior que na topbar: o elemento que
     ROLA era o mesmo que tinha o desfoque. Cada tique da roda invalidava o
     backdrop inteiro e obrigava a refazer o blur da tela cheia — era por isso
     que o popup de detalhe parecia o mais travado de todos.
     O escurecimento abaixo ja isola o popup do fundo; os 4px de blur somavam
     pouco e custavam metade do quadro. */
  background: rgba(4, 8, 6, .82);
  overflow-y: auto;
  /* Nao encadeia o scroll na pagina de tras: chegar no fim do popup e continuar
     rolando movia o painel embaixo, o que parecia engasgo. */
  overscroll-behavior: contain;
  align-items: flex-start; justify-content: center;
}
.modal-overlay.aberto { display: flex; animation: surgir-overlay var(--dur-base) var(--ease-saida) both; }
/* Saida animada: NexiUI.closeModal poe .fechando e so depois esconde —
   antes o popup desaparecia num corte seco. */
.modal-overlay.fechando { animation: sumir-overlay var(--dur-rapida) var(--ease-suave) both; }
.modal-overlay.fechando .modal { animation: descer-modal var(--dur-rapida) var(--ease-suave) both; }

.modal {
  background: var(--surface-1);
  border: 1px solid var(--border-default);
  width: 100%; max-width: 560px;
  min-height: 100vh;
  padding: var(--space-5) var(--space-4) var(--space-8);
  animation: subir-modal var(--dur-lenta) var(--ease-saida) both;
}
.modal__head {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--border-default);
}
.modal__head > svg { width: 17px; height: 17px; flex: none; margin-top: 2px; fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.modal__title { margin: 0; font-size: var(--text-md); font-weight: var(--weight-bold); letter-spacing: -.01em; flex: 1; }
.modal__sub { margin: 3px 0 0; font-size: var(--text-sm); color: var(--text-muted); font-weight: var(--weight-regular); }
.modal__close { margin-left: auto; }
.modal__body { min-width: 0; }
.modal__foot {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2);
  margin-top: var(--space-6);
  flex-wrap: wrap;
}
.modal--largo { max-width: 1080px; }

@media (min-width: 880px) {
  .modal-overlay { padding: var(--space-10) var(--space-5); }
  .modal {
    min-height: 0;
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: var(--shadow-xl);
  }
  .modal__title { font-size: var(--text-lg); }
}

/* ============================== TOAST ==============================
   Feedback de acao. Substitui alert()/confirm() do navegador, que
   travam a pagina, ignoram o tema e denunciam protótipo. */
.toast-container {
  position: fixed;
  bottom: calc(var(--tabbar-altura) + var(--space-4));
  left: var(--space-4); right: var(--space-4);
  z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--space-2);
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  background: var(--surface-1);
  border: 1px solid var(--border-default);
  box-shadow: var(--shadow-lg);
  color: var(--text-primary);
  font-size: var(--text-sm); font-weight: var(--weight-semibold);
  pointer-events: auto;
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--dur-base) var(--ease-saida), transform var(--dur-base) var(--ease-saida);
}
.toast.mostrar { opacity: 1; transform: none; }
.toast__ico { display: grid; place-items: center; width: 22px; height: 22px; flex: none; border-radius: var(--radius-full); background: var(--accent-soft); color: var(--accent); }
.toast__ico svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.toast--erro .toast__ico { background: var(--danger-soft); color: var(--danger); }
.toast--erro { border-color: var(--danger-border); }
.toast--aviso .toast__ico { background: var(--warning-soft); color: var(--warning); }
.toast--aviso { border-color: var(--warning-border); }
/* Botao de acao dentro do aviso ("Copiar e-mail"): oferece o passo
   seguinte sem obrigar a procurar onde ele fica. */
.toast__acao {
  margin-left: auto; flex: none;
  padding: 5px var(--space-3);
  border: 1px solid var(--accent-border);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: inherit; font-size: var(--text-xs); font-weight: var(--weight-bold);
  cursor: pointer;
  transition: filter var(--transition-base);
}
.toast__acao:hover { filter: brightness(1.2); }

@media (min-width: 880px) {
  .toast-container {
    bottom: auto; left: auto;
    top: calc(var(--topbar-altura) + var(--space-4));
    right: var(--space-5);
    max-width: 380px;
  }
  .toast { transform: translateX(18px); }
  .toast.mostrar { transform: none; }
}

/* ============================ PAGINACAO ============================ */
.paginacao { display: flex; align-items: center; gap: var(--space-2); }
.paginacao__num {
  font-variant-numeric: tabular-nums; font-weight: var(--weight-semibold);
  min-width: 82px; text-align: center; font-size: var(--text-sm);
  color: var(--text-secondary);
}
.paginacao__ir { display: flex; align-items: center; gap: var(--space-2); color: var(--text-muted); font-size: var(--text-sm); }
.paginacao__ir .input { width: 62px; text-align: center; font-family: var(--font-mono); font-variant-numeric: tabular-nums; padding: var(--space-2); }

/* ============================== TABS ==============================
   Sub-abas de uma tela. O sublinhado do item ativo cresce do centro. */
.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--border-default); overflow-x: auto; }
.tabs__tab {
  position: relative;
  padding: var(--space-3) var(--space-4);
  border: none; background: none;
  font-family: inherit; font-size: var(--text-base); font-weight: var(--weight-semibold);
  color: var(--text-muted);
  cursor: pointer; white-space: nowrap;
  transition: color var(--transition-base);
}
.tabs__tab:hover { color: var(--text-secondary); }
.tabs__tab[aria-selected="true"] { color: var(--accent); }
.tabs__tab[aria-selected="true"]::after {
  content: "";
  position: absolute; left: var(--space-3); right: var(--space-3); bottom: -1px;
  height: 2px; border-radius: 2px 2px 0 0;
  background: var(--accent);
  transform: scaleX(0);
  animation: sublinhado-entra var(--dur-base) var(--ease-saida) forwards;
}

/* ======================== GRAFICO DE BARRAS ========================
   Barras horizontais desenhadas com div (sem biblioteca externa): o
   design system e' auto-suficiente e a CSP nao libera CDN. */
.hbars { display: flex; flex-direction: column; gap: var(--space-3); }
.hbar { display: grid; grid-template-columns: 96px 1fr auto; align-items: center; gap: var(--space-3); }
.hbar__label { font-size: var(--text-xs); color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* display:block nos dois: sao <span>, e altura/largura nao se aplicam a
   elemento inline. A trilha escapa por ser filha de um grid (que
   blockifica), mas o fill esta dentro dela — sem isto ele nao pinta nada. */
.hbar__trilha { display: block; height: 8px; border-radius: var(--radius-full); background: var(--surface-3); overflow: hidden; }
.hbar__fill { display: block; height: 100%; border-radius: inherit; background: var(--gradient-accent); width: 0; transition: width var(--dur-lenta) var(--ease-saida); }
.hbar__val { font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-muted); min-width: 28px; text-align: right; }

/* ===================== GRAFICO DE COLUNAS (dias) =====================
   Serie curta no tempo. Coluna com altura proporcional; a de hoje fica
   em verde. Tooltip nativa via <title> — sem JS de posicionamento. */
.colunas { display: flex; align-items: flex-end; gap: 3px; height: 84px; }
.coluna {
  position: relative;
  flex: 1; min-width: 0;
  display: flex; align-items: flex-end;
  height: 100%;
  border-radius: 3px 3px 0 0;
  background: none; border: none; padding: 0;
  cursor: default;
}
.coluna__barra {
  display: block;
  width: 100%;
  min-height: 2px;
  border-radius: 3px 3px 0 0;
  background: var(--surface-3);
  transform-origin: bottom;
  transition: background var(--transition-base), transform var(--dur-base) var(--ease-saida);
}
.coluna:hover .coluna__barra { background: var(--text-muted); }
.coluna--valor .coluna__barra { background: var(--info); opacity: .55; }
.coluna--valor:hover .coluna__barra { opacity: 1; }
.coluna--hoje .coluna__barra { background: var(--gradient-accent); opacity: 1; }
.colunas__eixo { display: flex; justify-content: space-between; margin-top: var(--space-2); font-size: 10px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ============================= DOBRA =============================
   Seção de formulário que se recolhe (<details>/<summary> nativo — sem
   JS, com teclado e leitor de tela de graça).

   Serve pro bloco que JA' esta' resolvido: os dados pessoais de quem veio
   de um formulário assinado. Treze campos preenchidos empilhados na frente
   escondem o que ainda precisa de decisão. */
.dobra {
  border: 1px solid var(--border-default);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.dobra__resumo {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  font-size: var(--text-sm); font-weight: var(--weight-semibold);
  border-radius: inherit;
  transition: background var(--transition-base);
  /* Some com o triângulo nativo (que difere em cada navegador) — a seta é
     a nossa, e ela gira. */
  list-style: none;
}
.dobra__resumo::-webkit-details-marker { display: none; }
.dobra__resumo:hover { background: var(--surface-3); }
.dobra__seta {
  width: 14px; height: 14px; flex: none;
  color: var(--text-muted);
  transition: transform var(--dur-base) var(--ease-saida);
}
.dobra[open] > .dobra__resumo > .dobra__seta { transform: rotate(90deg); }
.dobra[open] > .dobra__resumo { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.dobra__titulo { color: var(--text-primary); }
.dobra__nota {
  min-width: 0;
  font-size: var(--text-xs); font-weight: var(--weight-regular); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Selo verde quando o bloco está resolvido — é o que diz "não precisa
   abrir". Ver adm-dobra-nota em rh-pessoas.js. */
.dobra__nota--pronto { color: var(--accent); font-weight: var(--weight-semibold); }
.dobra__corpo {
  display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-4);
  border-top: 1px solid var(--border-default);
}

/* ====================== FILA DE CANDIDATOS ======================
   Popup "Quem ja assinou": escolher uma pessoa cujo formulario assinado
   ja tem os dados pessoais, em vez de redigitar tudo na admissao.

   POR QUE CARTAO E NAO LINHA DE LISTA: a promessa da tela e' "nao precisa
   preencher". Uma linha com nome + botao nao mostra o que sera' aproveitado
   — quem olha nao sabe o que ganha antes de clicar. O cartao tem espaco pra
   dizer QUAIS campos vieram prontos, e e' isso que faz a tela se explicar
   sozinha.

   O CARTAO INTEIRO E' UM <button>. Alvo de toque do tamanho do cartao no
   celular, foco e Enter de graca pelo teclado, e nada de elemento
   interativo dentro de elemento interativo (que quebra leitor de tela). O
   "Usar estes dados" e' pintura, nao botao — ver .candidato__cta. */
.fila-candidatos {
  display: grid;
  gap: var(--space-3);
  /* auto-fill + minmax: 1 coluna no celular, 2-3 no modal largo, sem uma
     media query por faixa. O minimo de 268px e' a largura em que o nome
     completo de uma pessoa ainda cabe em duas linhas. */
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
}

.candidato {
  position: relative;
  display: flex; flex-direction: column; gap: var(--space-3);
  width: 100%;
  padding: var(--space-4);
  padding-left: calc(var(--space-4) + 3px);   /* espaco da faixa de urgencia */
  text-align: left;
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--card-edge);
  color: inherit; font: inherit;
  cursor: pointer;
  overflow: hidden;
  transition: transform var(--dur-rapida) var(--ease-saida),
              border-color var(--transition-base),
              box-shadow var(--transition-base),
              background var(--transition-base);
}
.candidato:hover {
  transform: translateY(-2px);
  background: var(--surface-3);
  border-color: var(--accent-border);
  box-shadow: var(--shadow-card-hover);
}
.candidato:active { transform: translateY(0) scale(.995); }

/* Faixa de urgencia. Vertical na borda esquerda: em uma grade de cartoes
   ela alinha numa coluna so', entao a fila "se le" de relance sem precisar
   comparar texto de data um por um. */
.candidato::before {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: 3px;
  background: var(--border-default);
  transition: background var(--transition-base);
}
.candidato--atencao::before { background: var(--gradient-warning); }
.candidato--urgente::before { background: var(--gradient-danger); }
.candidato--urgente { border-color: var(--danger-border); }
.candidato--urgente:hover { border-color: var(--danger); }

.candidato__topo { display: flex; align-items: flex-start; gap: var(--space-3); }
.candidato__avatar {
  display: grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-full);
  background: var(--surface-3);
  color: var(--text-on-accent);
  font-size: var(--text-sm); font-weight: var(--weight-bold);
  text-transform: uppercase;
}
/* Cor derivada do NOME (hash no JS), nao da ordem na lista: assim a mesma
   pessoa tem sempre a mesma cor, e a lista reordenada nao repinta tudo. */
.candidato__avatar--accent { background: var(--gradient-accent); }
.candidato__avatar--info   { background: var(--gradient-info); }
.candidato__avatar--rose   { background: var(--gradient-rose); }
.candidato__avatar--violet { background: var(--gradient-violet); }
.candidato__avatar--cyan   { background: var(--gradient-cyan); }
.candidato__avatar--orange { background: var(--gradient-orange); }

.candidato__ident { min-width: 0; flex: 1; }
.candidato__nome {
  display: block;
  font-size: var(--text-base); font-weight: var(--weight-semibold);
  color: var(--text-primary); line-height: 1.35;
  /* Quebra em 2 linhas em vez de reticencias: nome de pessoa cortado
     ("Gustavo Silva Marques…") atrapalha justamente a tarefa da tela, que
     e' reconhecer quem e'. */
  overflow-wrap: anywhere;
}
.candidato__meta {
  display: block;
  margin-top: 3px;
  font-size: var(--text-xs); color: var(--text-muted);
}
.candidato__valor { color: var(--accent); font-weight: var(--weight-semibold); }

/* ---- O que ja veio pronto (a informacao que justifica a tela) ---- */
.candidato__prontos { display: flex; flex-wrap: wrap; gap: 5px; }
.candidato__pronto {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px;
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: 10.5px; font-weight: var(--weight-semibold);
  white-space: nowrap;
}
.candidato__pronto svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
/* Campo que o formulario NAO trouxe: fica visivel, apagado, pra dizer o que
   vai precisar de digitacao. Esconder daria a impressao de cadastro
   completo e a surpresa viria no formulario. */
.candidato__pronto--falta {
  background: transparent;
  border-color: var(--border-default);
  border-style: dashed;
  color: var(--text-muted);
}

.candidato__pe {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2);
  margin-top: auto;              /* cola no fim: cartoes de alturas
                                    diferentes alinham o rodape */
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}
.candidato__espera {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--text-xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.candidato__espera svg { width: 12px; height: 12px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.candidato--atencao .candidato__espera { color: var(--warning); }
.candidato--urgente .candidato__espera { color: var(--danger); font-weight: var(--weight-semibold); }

/* Pintura de botao, dentro de um <button> real (o cartao). Por isso e'
   <span>: um <button> aqui seria interativo dentro de interativo. */
.candidato__cta {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px var(--space-3);
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  white-space: nowrap;
  transition: background var(--transition-base), color var(--transition-base), gap var(--dur-rapida) var(--ease-saida);
}
.candidato__cta svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.candidato:hover .candidato__cta {
  background: var(--accent); color: var(--text-on-accent);
  gap: var(--space-2);          /* a seta "anda" 3px no hover */
}

/* ---- Cabecalho da fila: contagem + busca ---- */
.fila-topo {
  display: flex; align-items: center; gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.fila-topo__contagem {
  font-size: var(--text-sm); color: var(--text-secondary);
}
.fila-topo__contagem strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.fila-topo .searchbar { min-width: 180px; }

/* ---- Skeleton: a FORMA do cartao enquanto o dado nao chegou ---- */
.candidato-skeleton {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
}
.candidato-skeleton__linha { height: 11px; border-radius: var(--radius-full); }
.candidato-skeleton__topo { display: flex; align-items: center; gap: var(--space-3); }
.candidato-skeleton__avatar { width: 38px; height: 38px; border-radius: var(--radius-full); flex: none; }

@media (max-width: 520px) {
  /* No celular o rodape empilha: "assinado há 12 dias" + CTA lado a lado
     em 300px apertaria o texto a ponto de quebrar em duas linhas torta. */
  .candidato__pe { flex-direction: column; align-items: stretch; gap: var(--space-3); }
  .candidato__cta { justify-content: center; padding: var(--space-2) var(--space-3); }
  .fila-topo .searchbar { min-width: 100%; }
}

/* ============================ UTILITARIOS ============================ */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--text-muted); }
.empurra { margin-left: auto; }
.linha-flex { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

/* Tecla de atalho exibida na interface. */
.kbd {
  display: inline-grid; place-items: center;
  min-width: 19px; height: 19px;
  padding: 0 5px;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  border: 1px solid var(--border-default);
  border-bottom-width: 2px;
  font-family: var(--font-mono); font-size: 10px; font-weight: var(--weight-bold);
  color: var(--text-muted);
}

/* Botao de copiar valor (CPF, CNPJ, e-mail). */
.copiar {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; flex: none;
  border: none; background: none; padding: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted); cursor: pointer;
  opacity: 0;
  transition: opacity var(--transition-base), background var(--transition-base), color var(--transition-base);
}
.copiar svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.copiar:hover { background: var(--surface-3); color: var(--accent); }
.copiar:focus-visible { opacity: 1; }
/* No toque nao existe hover: o botao fica sempre visivel. */
@media (hover: none) { .copiar { opacity: 1; } }
