/* Efeito de vitória.
 *
 * O player já teve um desenho próprio, com Math.random() nas faíscas, e ele foi
 * apagado por bom motivo: divergia do renderer canônico e o quadro era
 * irreprodutível. Este efeito não recria aquilo. Ele não desenha nada no canvas,
 * não toca em `pianoflow-frame-renderer.js` e não introduz um segundo palco —
 * é uma camada de DOM construída inteiramente com os tokens de data/themes.
 *
 * Os portões que ele precisa passar, e como cada um foi resolvido:
 *
 *   FX-1  nada acima de três flashes por segundo, em nenhuma região da tela.
 *         A animação tem UMA subida de opacidade e UMA descida, em 1,6 s. Isso
 *         é 0,625 reversão por segundo — cinco vezes abaixo do limite da WCAG
 *         2.3.1. Não existe pisca, alternância nem inversão de luminância, e o
 *         teste conta as reversões nos keyframes em vez de acreditar nesta nota.
 *
 *   FX-2  `prefers-reduced-motion: reduce` troca a animação por um ESTADO FINAL
 *         ESTÁTICO legível — não por uma animação mais lenta. Quem pediu menos
 *         movimento pediu menos movimento, não movimento devagar.
 *
 *   FX-3  funciona nos três temas, inclusive no claro. Nenhuma cor literal
 *         entra neste arquivo: tudo sai de var(--…), e o teste reprova hex.
 *
 *   FX-4  o quadro continua determinístico. Não há Math.random() aqui nem no
 *         módulo que dispara isto; posição e tempo são fixos.
 *
 * E mais três coisas que o protocolo exige e que não são visuais:
 *   · nenhum som toca — não existe áudio neste efeito, e nada aqui é só sonoro;
 *   · o efeito não cobre o que o aluno precisa ler: ele fica sobre a barra de
 *     seções, `pointer-events: none`, e sai sozinho;
 *   · o texto é anunciado por aria-live, então quem não vê a animação recebe a
 *     mesma informação.
 */

.celebration {
  position: absolute;
  left: 50%;
  bottom: 22%;
  transform: translateX(-50%);
  z-index: 4;

  display: flex;
  align-items: center;
  gap: 10px;

  padding: 10px 18px;
  border-radius: 999px;

  /* Tudo em token. Um efeito que só funcionasse no tema escuro não está pronto. */
  background: var(--phsp-panel);
  border: 1px solid var(--phsp-accent);
  color: var(--phsp-text-primary);
  box-shadow: 0 6px 24px var(--phsp-shadow);

  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  max-width: min(92vw, 480px);

  /* Não rouba o clique de nada que esteja embaixo. */
  pointer-events: none;
}

.celebration-mark {
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  border: 2px solid var(--phsp-accent);
  /* Um preenchimento parcial, fixo: o mesmo desenho toda vez. */
  background: linear-gradient(to top, var(--phsp-accent) 0 50%, transparent 50% 100%);
}

.celebration-text { overflow: hidden; text-overflow: ellipsis; }
.celebration-sub {
  font-weight: 400;
  font-size: 12.5px;
  color: var(--phsp-text-muted);
}

/* Uma subida e uma descida. Duas reversões em 1,6 s = 1,25 mudança de direção
 * por segundo, e nenhuma delas é um pisca: são rampas. */
@keyframes celebration-in {
  0%   { opacity: 0; transform: translateX(-50%) translateY(6px); }
  22%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  78%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-4px); }
}

.celebration.is-playing {
  animation: celebration-in 1600ms ease-out both;
}

/* FX-2. Estado final estático e legível — sem animação nenhuma, e não uma
 * versão lenta dela. O aviso continua aparecendo e continua saindo por conta do
 * temporizador em JavaScript, que é o mesmo nos dois caminhos. */
@media (prefers-reduced-motion: reduce) {
  .celebration.is-playing {
    animation: none;
    opacity: 1;
    transform: translateX(-50%);
  }
}

/* A unidade inteira concluída é a única variação, e ela muda a espessura da
 * borda — não acrescenta pisca nem segundo tempo de animação. */
.celebration.is-complete { border-width: 2px; }

@media (max-width: 640px) {
  .celebration { bottom: 16%; font-size: 13px; padding: 8px 14px; }
}
