/* ==========================================================================
   ANIMAÇÕES
   Movimento discreto e curto. Nada decorativo: cada animação comunica
   entrada, saída ou carregamento.
   ========================================================================== */

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes view-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@keyframes rail-in {
  from { height: 0; opacity: 0; }
  to   { height: 20px; opacity: 1; }
}

@keyframes toast-in {
  from { opacity: 0; transform: translateX(24px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

@keyframes toast-out {
  to { opacity: 0; transform: translateX(24px); }
}

@keyframes modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

@keyframes shimmer {
  from { background-position: -600px 0; }
  to   { background-position: 600px 0; }
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* --- Carregamento por esqueleto ------------------------------------------ */

.skeleton {
  background-color: var(--bg-inset);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    var(--border-subtle) 40%,
    var(--border-default) 50%,
    var(--border-subtle) 60%,
    transparent 100%
  );
  background-size: 600px 100%;
  background-repeat: no-repeat;
  border-radius: var(--radius-sm);
  animation: shimmer 1.6s linear infinite;
}

.skeleton--text  { height: 12px; margin-block: 4px; }
.skeleton--title { height: 18px; width: 45%; }
.skeleton--value { height: 30px; width: 60%; }
.skeleton--chart { height: 100%; min-height: 200px; border-radius: var(--radius-md); }
.skeleton--pill  { height: 22px; width: 88px; border-radius: var(--radius-pill); }

/* --- Indicador circular de progresso ------------------------------------- */

.spinner {
  width: 18px;
  height: 18px;
  border: 2px solid var(--border-default);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}

/* --- Barra de progresso indeterminada ------------------------------------ */

.progress {
  position: relative;
  height: 3px;
  overflow: hidden;
  background: var(--border-subtle);
  border-radius: var(--radius-pill);
}

.progress__bar {
  height: 100%;
  background: var(--accent);
  border-radius: inherit;
  transition: width var(--duration-normal) var(--ease-out);
}

/* --- Onda das miniaturas da visão geral ----------------------------------

   As barrinhas sob cada módulo da tela de abertura são desenho: dão o
   formato do período em poucos pixels e não se leem número a número. Uma
   onda lenta atravessando da direita para a esquerda dá vida à abertura sem
   pedir atenção — o atraso negativo por barra adianta a fase de cada uma, e
   é isso que faz o relevo parecer caminhar. */

@keyframes sparkline-onda {
  0%, 100% { opacity: 0.38; transform: scaleY(1); }
  45%      { opacity: 0.85; transform: scaleY(1.06); }
}

.sparkline__bar {
  transform-origin: bottom;
  animation: sparkline-onda 3.2s var(--ease-in-out, ease-in-out) infinite;
  animation-delay: calc(var(--onda, 0) * -120ms);
}

/* Passar o cursor interrompe a onda: ali o gesto é ler um mês, não admirar */
.sparkline:hover .sparkline__bar {
  animation: none;
  opacity: 0.3;
}

.sparkline__bar:hover { opacity: 1; }

/* --- Preferência de movimento reduzido ----------------------------------- */

@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;
  }
}

@keyframes value-pulse {
  0%   { opacity: 0.35; transform: translateY(3px); }
  100% { opacity: 1; transform: none; }
}

@keyframes line-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes bar-grow {
  to { transform: scaleY(1); }
}

@keyframes bar-grow-x {
  to { transform: scaleX(1); }
}
