/* =========================================================
   Componente: Skeleton, Empty State, Tooltip, Spinner
   ========================================================= */

/* ---------- Skeleton ---------- */
.sk-cf {
  background: linear-gradient(90deg, var(--bg-muted) 25%, var(--bg-surface-hover) 37%, var(--bg-muted) 63%);
  background-size: 400% 100%;
  animation: sk-shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
.sk-cf.line { height: 14px; }
.sk-cf.line.sm { height: 10px; }
.sk-cf.circle { border-radius: 50%; }
.sk-cf.title { height: 22px; width: 40%; }
@keyframes sk-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Quem pediu menos movimento nao ganha um degrade correndo na tela sem parar.
   O esqueleto continua existindo (a informacao "esta carregando" e util); o
   que para e a animacao. */
@media (prefers-reduced-motion: reduce) {
  .sk-cf { animation: none; background: var(--bg-muted); }
}

/* Esqueleto de LISTA. As classes saem do JS e vem para ca: antes a silhueta
   morava numa string de classes do Bootstrap com `style=` inline no meio do
   ui.js, e mudar o respiro de um esqueleto exigia mexer em JavaScript. */
.sk-row-cf {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3);
  border-bottom: 1px solid var(--border-color);
}
.sk-wrap-cf > .sk-row-cf:last-child { border-bottom: none; }

/* Esqueleto de TABELA: a silhueta do bloco B (cabecalho de 44px, linhas de
   56px, largura por tipo de coluna). Um esqueleto de lista numa tela que vai
   mostrar tabela faz a pagina saltar quando os dados chegam — que e
   exatamente o solavanco que o esqueleto existe para evitar. */
.sk-table-cf { width: 100%; }
.sk-tr-cf {
  display: flex;
  align-items: center;
  height: var(--tabela-linha-h);
  border-bottom: 1px solid var(--border-color);
}
.sk-tr-cf--head {
  height: var(--tabela-cabecalho-h);
  background: var(--bg-muted);
  border-bottom: 2px solid var(--border-color);
}
.sk-td-cf {
  padding: 0 var(--tabela-pad-x);
  flex: 0 0 auto;
  overflow: hidden;
  /* A largura declarada tem de INCLUIR o padding, como na celula real —
     senao cada coluna do esqueleto sai 28px mais larga que a da tabela. */
  box-sizing: border-box;
}

/* Os tipos relativos do bloco B nao tem largura propria: dividem a sobra.
   Sem isto eles colapsariam (`width: auto` num flex item sem conteudo e 0).

   `flex: <peso> 1 <piso>` reproduz EXATAMENTE a conta do `ajustarLarguras`
   (tableColumns.js): o flexbox da a cada item a sua base e reparte o espaco
   que sobra na proporcao dos pesos — que e, letra por letra,
   `piso + (extra * peso / somaDosPesos)`. A primeira versao usava so
   `flex-grow` sem base e o teste mediu o resultado: uma coluna 22px fora do
   lugar, ou seja, o salto que o esqueleto existe para evitar. Os numeros
   saem das mesmas variaveis que a tabela usa; nao ha copia. */
.sk-td-cf.col-cf--texto { flex: 1 1 var(--col-texto-min); }
.sk-td-cf.col-cf--textolargo { flex: 1.6 1 var(--col-texto-min); }
.sk-td-cf.col-cf--principal { flex: 2 1 var(--col-principal-min); }

/* ---------- Empty state ----------

   O QUE MUDOU E POR QUE

   O desenho anterior era: quadrado pastel de 64px com um icone dentro, titulo
   centralizado embaixo, frase centralizada embaixo do titulo. Esse conjunto
   exato — badge de cor suave, icone generico, frase educada, tudo centralizado
   — e o estado vazio canonico de interface gerada. No dashboard apareciam DOIS
   lado a lado ("Risco de evasão" e "Avaliação Técnica"), identicos na forma, e
   o padrao ficava obvio.

   Ele tambem invertia a hierarquia: o elemento de maior peso visual no cartao
   era um badge decorativo dizendo que ali NAO HA NADA. Quanto mais vazio o
   sistema, mais chamativa a tela.

   Agora o icone e um glifo discreto, sem caixa e sem fundo, e o texto carrega
   a informacao. No compacto, que e o que aparece dentro dos cartoes do
   dashboard, a linha fica ALINHADA A ESQUERDA, na mesma margem do conteudo que
   apareceria ali quando houvesse dado — entao o cartao nao muda de eixo quando
   sai do vazio para o preenchido.
   ---------- */
.empty-cf {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-12) var(--space-6);
  gap: var(--space-2);
}
/* Leva "layout premium": o icone do vazio ganha o CIRCULO soft da primaria,
   como o icone do indicador — o vazio deixa de ser um glifo cinza apagado no
   meio do nada e vira um convite com a cor da marca. */
.empty-cf__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-full);
  background: var(--color-primary-soft);
  color: var(--color-primary);
  font-size: 1.4rem;
  margin-bottom: var(--space-2);
}
.empty-cf__title { font-size: var(--text-lg); font-weight: var(--fw-semibold); margin: 0; }
.empty-cf__text { color: var(--text-secondary); max-width: 340px; margin: 0; }

/* Variante para painel DENTRO de card (widget do dashboard, carrinho, lista de
   variantes). O respiro de tela cheia deixaria o card tres vezes mais alto
   vazio do que cheio — e a tela saltaria quando o primeiro item entrasse.

   GRID, e nao `flex-direction: row`. A versao anterior desta regra virou uma
   LINHA, e funcionava enquanto o vazio tinha so icone + titulo (o caso dos
   cartoes do dashboard). Mas o mesmo componente tambem e usado com TEXTO de
   apoio e com BOTAO de acao — e a marcacao e plana: icone, titulo, texto e
   botao sao irmaos diretos. Numa linha, os quatro viravam quatro colunas
   espremidas lado a lado, cada uma com duas palavras por linha. Foi o que os
   prints de Documentos e Avaliacao mostraram.

   Com grid o icone ocupa a primeira coluna e TODO o resto empilha na segunda,
   independente de quantos elementos existam — inclusive o proximo que alguem
   acrescentar. E o layout de "objeto de midia" classico, sem precisar mudar o
   HTML nem embrulhar nada em <div>. */
.empty-cf--compacto {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  align-items: start;
  text-align: left;
  padding: var(--space-4) 0;
}
.empty-cf--compacto .empty-cf__icon {
  grid-column: 1;
  grid-row: 1 / span 2;
  /* Circulo menor dentro de cartao: o de 56px dobraria a altura do vazio. */
  width: 36px;
  height: 36px;
  font-size: 0.9rem;
  margin-bottom: 0;
}
.empty-cf--compacto { align-items: center; }
/* Tudo o que nao e o icone vai para a coluna 2 e empilha. */
.empty-cf--compacto > :not(.empty-cf__icon) { grid-column: 2; }

.empty-cf--compacto .empty-cf__title {
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  line-height: 1.5;
}
.empty-cf--compacto .empty-cf__text {
  font-size: var(--text-sm);
  color: var(--text-muted);
  max-width: 46ch;
}
/* O botao nao estica: ele tem o tamanho do proprio rotulo e comeca alinhado
   com o texto acima. Esticado, um "Nova avaliacao" de 14 caracteres viraria
   uma barra atravessando o cartao. */
.empty-cf--compacto > .btn-cf,
.empty-cf--compacto > a.btn-cf {
  justify-self: start;
  margin-top: var(--space-2);
}

/* ---------- Spinner ---------- */
.spinner-cf {
  width: 20px; height: 20px;
  border: 2px solid var(--border-color);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: sp-rotate 0.7s linear infinite;
  display: inline-block;
}
@keyframes sp-rotate { to { transform: rotate(360deg); } }
/* Dentro de botao o spinner tem de acompanhar a COR DO TEXTO: o `.spinner-cf`
   solto usa a primaria fixa e sumiria dentro do botao primario, que ja e dela.
   Anel em currentColor com o topo vago — sem `color-mix`, que nao e usado em
   lugar nenhum deste projeto. */
.spinner-cf--btn {
  border-color: currentColor;
  border-top-color: transparent;
}
.spinner-cf--sm { width: 14px; height: 14px; border-width: 2px; vertical-align: -2px; }
/* Um spinner parado nao comunica nada; quem pediu menos movimento ainda
   precisa saber que a acao esta em curso. Some o giro, fica o anel. */
@media (prefers-reduced-motion: reduce) {
  .spinner-cf { animation-duration: 2.4s; }
}

/* ---------- Tooltip ---------- */
.tt-cf { position: relative; display: inline-flex; }
.tt-cf__bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--neutral-900);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  padding: 5px 9px;
  border-radius: var(--radius-xs);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  z-index: 1200;
  box-shadow: var(--shadow-md);
}
.tt-cf__bubble::after {
  content: '';
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--neutral-900);
}
.tt-cf:hover .tt-cf__bubble,
.tt-cf:focus-within .tt-cf__bubble {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
[data-theme='dark'] .tt-cf__bubble { background: var(--neutral-700); }
[data-theme='dark'] .tt-cf__bubble::after { border-top-color: var(--neutral-700); }
