/*
  Modelos de notificação — a aparência de um alerta, em um só lugar.

  Este arquivo é carregado PELA TV e PELO PAINEL. É de propósito: o preview do
  painel precisa mostrar o que a TV vai mostrar, e a única forma de garantir
  isso é os dois lerem o mesmo CSS. Duas cópias divergem na primeira correção
  que alguém faz com pressa — e um preview que mente é pior do que preview
  nenhum, porque a pessoa só descobre a diferença com a sala olhando.

  ESCALA: nada aqui usa `vmin`.

  A TV desenha em tela cheia; o painel, dentro de uma moldura de alguns
  centímetros. `vmin` resolveria o primeiro caso e faria o segundo sair com
  letras gigantes. Então todo tamanho sai de `--esc`, que cada lado define:
  a TV põe `1vmin`, o painel põe o equivalente a 1vmin do palco de 1920x1080
  que ele encolhe por transform. Mesmas proporções nos dois.
*/

.al-palco {
  --esc: 1vmin;
  --tinta: #f8fafc;
  --fundo-a: #0a1628;
  --fundo-b: #0a1628;
  --realce: #38bdf8;

  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--tinta);
  background: radial-gradient(120% 120% at 50% 0%, var(--fundo-a), var(--fundo-b));
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* A mídia, quando existe, é o fundo: o cartão de texto vai por cima dela. */
.al-midia { position: absolute; inset: 0; }
.al-midia:empty { display: none; }
.al-midia img, .al-midia video {
  width: 100%; height: 100%;
  object-fit: contain;
  background: #000;
}

/* Com mídia atrás, o texto precisa de um véu para continuar legível sobre
   uma foto clara. Sem mídia, o véu não tem o que escurecer e só suja. */
.al-palco.com-midia .al-cartao {
  align-self: flex-end;
  width: 100%;
  padding: calc(var(--esc) * 5) calc(var(--esc) * 7);
  background: linear-gradient(transparent, rgba(0, 0, 0, .88) 55%);
}

.al-cartao {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--esc) * 1.5);
  text-align: center;
  padding: calc(var(--esc) * 4);
}

/* O ícone é SVG, não emoji: um player de TV sem fonte de emoji desenhava um
   quadrado vazio na parede. O tamanho acompanha a escala do palco, como o
   resto do cartão. */
.al-icone {
  line-height: 0;
  filter: drop-shadow(0 calc(var(--esc) * .6) calc(var(--esc) * 1.2) rgba(0, 0, 0, .45));
}
.al-icone svg {
  width: calc(var(--esc) * 14);
  height: calc(var(--esc) * 14);
  display: block;
}
.al-icone:empty { display: none; }

.al-titulo {
  font-size: calc(var(--esc) * 7);
  font-weight: 800;
  letter-spacing: calc(var(--esc) * -.1);
  text-transform: uppercase;
  color: var(--realce);
}
.al-titulo:empty { display: none; }

/* O valor é o que a sala olha primeiro num alerta de venda: é o maior
   elemento da tela, e o único com número tabular — sem isso, "R$ 1.111" e
   "R$ 8.888" saem com larguras diferentes e o número "pula" na troca. */
.al-valor {
  font-size: calc(var(--esc) * 16);
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 calc(var(--esc) * .5) calc(var(--esc) * 2) rgba(0, 0, 0, .5);
}
.al-valor:empty { display: none; }

/* `pre-line` honra a quebra de linha que veio no webhook e continua quebrando
   sozinho no fim da linha. O padrão do navegador transformava `\n` em espaço:
   o texto atravessava o servidor inteiro intacto e morria calado aqui, no
   último passo. `pre` não serve — colaria também os espaços da indentação de
   quem monta a mensagem em várias linhas no n8n. */
.al-texto {
  font-size: calc(var(--esc) * 5);
  font-weight: 600;
  opacity: .92;
  max-width: 80%;
  white-space: pre-line;
}
.al-texto:empty { display: none; }

/* ---------- Os modelos ----------
   Cada um é só um jogo de cores e um efeito. Trocar de modelo não muda
   estrutura nenhuma, e é o que permite acrescentar um modelo novo sem
   tocar no código da TV. */

.al-palco.m-venda {
  --fundo-a: #064e3b; --fundo-b: #022c22;
  --realce: #fbbf24; --tinta: #ecfdf5;
}
.al-palco.m-meta {
  --fundo-a: #78350f; --fundo-b: #451a03;
  --realce: #fde68a; --tinta: #fffbeb;
}
.al-palco.m-cliente {
  --fundo-a: #1e3a8a; --fundo-b: #0f172a;
  --realce: #93c5fd; --tinta: #eff6ff;
}
.al-palco.m-aviso {
  --fundo-a: #713f12; --fundo-b: #422006;
  --realce: #facc15; --tinta: #fefce8;
}
.al-palco.m-urgente {
  --fundo-a: #7f1d1d; --fundo-b: #450a0a;
  --realce: #fca5a5; --tinta: #fef2f2;
}
.al-palco.m-limpo {
  --fundo-a: #0a1628; --fundo-b: #020617;
  --realce: #e2e8f0; --tinta: #f8fafc;
}

/* ---------- Efeitos ---------- */

/*
  O confete: papel picado feito de elementos, animado pelo COMPOSITOR.

  A versão anterior era um canvas repintado a cada quadro, e num Raspberry Pi 4
  isso levava o processo de GPU a 133% — o confete descia aos saltos justamente
  quando a sala olhava. Aqui cada peça é um elemento que só muda `transform` e
  `opacity`: o navegador move camadas prontas, sem repintar, na thread de
  composição — que segue fluida mesmo com a principal ocupada.

  As variáveis vêm sorteadas do JavaScript, uma vez, na criação. Depois disso
  não há JavaScript nenhum envolvido na animação.
*/
.al-papel {
  position: absolute;
  top: calc(var(--esc) * -6);
  left: var(--x);
  width: calc(var(--esc) * var(--l));
  height: calc(var(--esc) * var(--l) * 2.2);
  border-radius: 1px;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  /* `linear` de propósito: papel caindo não tem aceleração perceptível na
     distância de uma tela, e qualquer curva custa mais para interpolar. */
  animation-name: al-cair;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
  will-change: transform, opacity;
}

@keyframes al-cair {
  0%   { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg); }
  8%   { opacity: 1; }
  85%  { opacity: 1; }
  100% {
    opacity: 0;
    transform: translate3d(var(--desvio), 115vh, 0) rotate(var(--giro));
  }
}

/* Entrada: o alerta aparece de baixo, não do nada. Um corte seco em tela
   cheia parece defeito de sinal; meio segundo de movimento parece intenção. */
.al-palco > .al-cartao { animation: al-subir .45s cubic-bezier(.2, .8, .25, 1) both; }
@keyframes al-subir {
  from { opacity: 0; transform: translateY(calc(var(--esc) * 4)) scale(.96); }
  to   { opacity: 1; transform: none; }
}

/* O valor chega depois do resto e com um empurrão — é o gesto que faz a sala
   olhar para o número em vez de ler a tela toda de cima a baixo. */
.al-valor { animation: al-bater .55s .18s cubic-bezier(.2, 1.5, .3, 1) both; }
@keyframes al-bater {
  from { opacity: 0; transform: scale(.55); }
  to   { opacity: 1; transform: none; }
}

/* Aviso e urgente pulsam a borda: sem som, é o que diferencia "olhe aqui" de
   "está escrito aqui". O urgente pulsa mais rápido e mais forte. */
.al-palco.m-aviso   { animation: al-borda 2.4s ease-in-out infinite; }
.al-palco.m-urgente { animation: al-borda 1.1s ease-in-out infinite; }
@keyframes al-borda {
  0%, 100% { box-shadow: inset 0 0 0 calc(var(--esc) * .8) rgba(250, 204, 21, 0); }
  50%      { box-shadow: inset 0 0 0 calc(var(--esc) * .8) var(--realce); }
}

/* Meta batida: um brilho que gira devagar atrás do troféu. */
.al-palco.m-meta::before {
  content: "";
  position: absolute;
  inset: -30%;
  background: conic-gradient(from 0deg, transparent 0 12%, rgba(253, 230, 138, .16) 18%,
              transparent 26% 62%, rgba(253, 230, 138, .12) 70%, transparent 78%);
  animation: al-girar 9s linear infinite;
}
@keyframes al-girar { to { transform: rotate(1turn); } }

/*
  Respeitar quem pediu menos movimento.

  Uma TV de recepção não tem quem clique em "reduzir animações", mas o painel
  roda no computador de alguém — e essa pessoa pode ter pedido. O alerta
  continua aparecendo; só para de se mexer.
*/
@media (prefers-reduced-motion: reduce) {
  .al-palco, .al-palco > .al-cartao, .al-valor, .al-palco.m-meta::before {
    animation: none !important;
  }
  /* O papel some de vez: parado no alto da tela ele viraria sujeira. */
  .al-papel { display: none; }
}
