/* ===========================================================================
   Confere.la · MOVIMENTO
   Nenhuma animação aqui é enfeite: cada uma carrega um dado.
   · a régua que desenha       → a redação abriu
   · a etiqueta que decodifica → o sistema leu
   · o dígito que rola         → o placar mudou AGORA
   · o banner que bate         → saiu veredito
   · o card que pisca          → foi contra ESTE candidato
   · o feixe que varre         → a IA está processando neste instante
   Tudo desliga em prefers-reduced-motion.
   =========================================================================== */

/* ------------------------------------------------------------ 1. abertura */

@keyframes draw-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes draw-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes iris { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes bloom { from { opacity: 0; filter: blur(10px); transform: scale(.96); } to { opacity: 1; filter: blur(0); transform: none; } }

.boot .masthead { animation: fade .5s var(--ease) both; }
.boot .wordmark { animation: bloom .7s var(--ease-out) both .1s; }
.boot .rule,
.boot .rule--seg,
.boot .tick { transform-origin: left center; animation: draw-x .6s var(--ease-out) both .25s; }
.boot .screen { animation: rise .7s var(--ease-out) both .18s; }
.boot .confer { animation: rise .7s var(--ease-out) both .34s; }
/* os seis cards entram em cascata, de cima para baixo */
.boot .card { animation: rise .55s var(--ease-out) both; }
.boot .card:nth-child(1) { animation-delay: .30s; }
.boot .card:nth-child(2) { animation-delay: .36s; }
.boot .card:nth-child(3) { animation-delay: .42s; }
.boot .card:nth-child(4) { animation-delay: .48s; }
.boot .card:nth-child(5) { animation-delay: .54s; }
.boot .card:nth-child(6) { animation-delay: .60s; }
.boot .card-photo { animation: iris .8s var(--ease-out) both .5s; }
.boot .ad { animation: fade .6s var(--ease) both .68s; }
.boot .footer { animation: fade .6s var(--ease) both .7s; }

/* ------------------------------------------------- 2. etiqueta decodificando */
/* O JS troca os caracteres; o CSS só entrega o brilho de varredura. */

.lab[data-decoding='true'] {
  color: var(--ink-3);
  animation: lab-scan .9s linear infinite;
}
@keyframes lab-scan { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

/* --------------------------------------------------------- 3. odômetro */
/* Um dígito é uma janela de 10 andares; trocar de valor é subir de andar. */

.odo { display: inline-flex; overflow: hidden; height: 1em; line-height: 1; vertical-align: baseline; }
.odo-col { display: block; height: 1em; overflow: hidden; }
.odo-strip {
  display: flex; flex-direction: column;
  transition: transform .7s var(--slam);
  will-change: transform;
}
.odo-strip span { height: 1em; line-height: 1; display: block; text-align: center; }

/* o número pisca e salta quando incrementa */
@keyframes num-pop {
  0% { transform: none; }
  35% { transform: translateY(-3px) scale(1.18); }
  100% { transform: none; }
}
.card-score .n.is-hit { animation: num-pop .55s var(--slam); }

/* ------------------------------------------------------- 4. veredito bate */

@keyframes slam {
  0% { opacity: 0; transform: scale(1.09) translateY(-6px); }
  55% { opacity: 1; transform: scale(.985) translateY(0); }
  100% { opacity: 1; transform: none; }
}
.verdict.is-new { animation: slam .5s var(--slam) both; }

/* clarão que atravessa o banner uma vez */
.verdict.is-new::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, #fff 55%, transparent) 50%, transparent 80%);
  transform: translateX(-100%);
  animation: sweep .8s var(--ease-out) .12s both;
  pointer-events: none;
}
@keyframes sweep { to { transform: translateX(100%); } }

/* onda de choque saindo do banner */
@keyframes shock {
  from { opacity: .5; transform: scaleX(.2); }
  to { opacity: 0; transform: scaleX(1); }
}
.verdict.is-new::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--v-ink); transform-origin: left center;
  animation: shock .7s var(--ease-out) both;
}

/* a afirmação recebendo o carimbo: um leve recuo, como papel batido */
@keyframes knock {
  0% { transform: none; }
  20% { transform: translateX(-3px); }
  45% { transform: translateX(2px); }
  70% { transform: translateX(-1px); }
  100% { transform: none; }
}
.confer-claim.is-new { animation: knock .45s var(--ease) both; }

/* --------------------------------------------- 5. o card inteiro reage */

@keyframes card-flash {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--flash) 60%, transparent); }
  100% { box-shadow: 0 0 0 14px transparent; }
}
.card.is-hit { animation: card-flash .9s var(--ease-out) both; }
.card.is-hit[data-hit='verdadeiro'] { --flash: var(--card-ok); }
.card.is-hit[data-hit='falso'] { --flash: var(--card-bad); }
.card.is-hit[data-hit='impreciso'] { --flash: var(--card-mid); }

/* ------------------------------------------------------- 6. sinal ao vivo removido */

/* varredura de linha no tema escuro: a tela tem sinal */
.screen-body::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  opacity: calc(var(--scan) * .35);
  background: repeating-linear-gradient(to bottom, transparent 0 3px, rgba(255, 255, 255, .022) 3px 4px);
}

/* --------------------------------------------- 8. entrada da conferência */

@keyframes card-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
.confer-body.is-new > * { animation: card-in .5s var(--ease-out) both; }
.confer-body.is-new > *:nth-child(2) { animation-delay: .05s; }
.confer-body.is-new > *:nth-child(3) { animation-delay: .1s; }
.confer-body.is-new > *:nth-child(4) { animation-delay: .15s; }

/* --------------------------------------------- 8.1. processamento / checking */

@keyframes cf-checking-pulse {
  0% { opacity: 0.5; }
  50% { opacity: 1; }
  100% { opacity: 0.5; }
}
.confer[data-state='checking'] .verdict {
  animation: cf-checking-pulse 1.5s infinite ease-in-out;
}
.confer[data-state='checking'] .confer-claim {
  animation: cf-checking-pulse 1.5s infinite ease-in-out;
}

/* ----------------------------------------------------- 9. cursor do texto */

@keyframes blink { 0%, 45% { opacity: 1; } 55%, 100% { opacity: 0; } }
.ticker .caret { animation: blink 1.05s steps(1) infinite; }

/* -------------------------------------------------- 10. troca de tema */

@keyframes theme-wipe {
  from { opacity: .85; }
  to { opacity: 0; }
}
.theme-wipe {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  background: var(--bg-2);
  animation: theme-wipe .45s var(--ease-out) both;
}

/* -------------------------------------------------- 10.1. Animação do card inteiro de veredito */

@keyframes cf-verdict-reveal {
  from { opacity: 0; transform: scaleY(0.7); transform-origin: top; filter: brightness(1.3); }
  to { opacity: 1; transform: none; filter: none; }
}
.verdict.is-new {
  animation: cf-verdict-reveal 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes cf-verdict-sweep {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
.verdict::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.12) 50%, transparent 100%);
  transform: translateX(-100%);
  pointer-events: none;
}
.verdict.is-new::after {
  animation: cf-verdict-sweep 1.2s cubic-bezier(0.16, 1, 0.3, 1) both 0.15s;
}

/* --------------------------------------------------- 11. respeito ao usuário */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .live-dot[data-on='true'], .scanbar::after { animation: none !important; }
  .live-dot[data-on='true']::after { display: none; }
  .odo-strip { transition: none; }
}
