/* ════════════════════════════════════════════════════════════════
   MOTION — a camada de movimento das telas de identidade
   (2026-09-19, "Harpion Access System")

   Carrega por ÚLTIMO, depois de login.css, portal-theme.css e
   auth-ui.css. Isso é deliberado: duas vezes nesta mesma semana uma
   regra daqui foi silenciosamente derrotada por uma folha que carregava
   depois. Sendo a última, esta não precisa de um único !important.

   Princípio que governa o arquivo inteiro:

       "Quiet when idle, precise when active."

   Parado, quase nada se move. Ao toque, a interface responde na hora.
   Nenhuma animação passiva roda em intervalo curto — a luz da borda e o
   reflexo do card têm ciclos de 9 e 13 segundos, e o que sobra do tempo
   é silêncio.

   E a regra de cor, herdada da referência: cinza é inativo, branco é
   informação, âmbar é atividade, VERDE SÓ QUANDO HÁ VEREDITO. Nada aqui
   fica verde antes de o servidor ter dito sim.
   ════════════════════════════════════════════════════════════════ */

:root {
  --motion-fast: 120ms;
  --motion-ui: 220ms;
  --motion-normal: 350ms;
  --motion-enter: 700ms;

  /* Saída suave, para o que chega e acomoda. */
  --ease-saida: cubic-bezier(0.22, 1, 0.36, 1);
  /* Mecânica, para o que é acionado: parte firme, para firme. */
  --ease-mec: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Comprimento animável para a luz que percorre a borda. */
@property --giro {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}


/* ════════════════════════════════════════════════════════════════
   1. PROFUNDIDADE — o card deixa de ser plano

   Inclinação de no máximo 1,2°. É pouco de propósito: o objetivo não é
   um efeito de cartão 3D, é que a peça pareça ter espessura quando a
   mão passa por cima. Passando disso o texto começa a distorcer e a
   tela vira brinquedo.

   A entrada do painel (auth-ui.css) anima transform com fill-mode
   `both`, o que GRUDARIA `transform: none` no elemento para sempre e
   mataria a inclinação. Por isso ela é redeclarada aqui com
   `backwards`: o estado inicial continua valendo antes de começar, e
   ao terminar a propriedade é devolvida ao elemento. Os cantos podem
   soltar sem risco porque `--braco: 13px` está declarado na própria
   regra do card — é para lá que ele volta.
   ════════════════════════════════════════════════════════════════ */

.login-wrap {
  perspective: 1400px;
}

.login-card {
  animation:
    placaAcende 0.62s var(--ease-saida) 0.18s backwards,
    cantosAbrem 0.5s var(--ease-saida) 0.52s backwards;
  /* --abre-x é a folha esquerda do portão da tela de login (portao.css)
     se afastando. Entra na mesma cadeia de transform em vez de numa
     regra concorrente: duas declarações de transform no mesmo elemento
     e uma apaga a outra. */
  transform:
    translateX(var(--abre-x, 0px))
    rotateX(var(--inc-x, 0deg))
    rotateY(var(--inc-y, 0deg))
    translateZ(var(--inc-z, 0px));
  transition: transform 520ms var(--ease-saida);
}

/* Enquanto a mão está em cima, o card acompanha quase sem atraso; ao
   sair, volta devagar. Duas velocidades para o mesmo movimento. */
.login-card.inclinando {
  transition-duration: 90ms;
}

/* ── Estado 02 ACTIVE: alguém está preenchendo ──
   Os colchetes dos cantos acendem. É o único aviso de que a tela saiu
   do repouso, e não custa nem um pixel de layout. */
.login-card:focus-within {
  --canto: rgba(245, 166, 35, 0.62);
}


/* ════════════════════════════════════════════════════════════════
   2. A LUZ QUE SEGUE O CURSOR

   Camada própria, injetada por motion.js, em vez de mais um plano de
   background no card: o card já empilha oito gradientes para desenhar
   os colchetes dos cantos, e mexer naquela lista para encaixar um nono
   deixaria as duas coisas amarradas uma na outra.

   Muito sutil de propósito. A pessoa tem que perceber profundidade, não
   um holofote correndo atrás do mouse.
   ════════════════════════════════════════════════════════════════ */

.card-luz {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  opacity: 0;
  transition: opacity var(--motion-normal) var(--ease-saida);
  background: radial-gradient(
    360px circle at var(--mx, 50%) var(--my, 0%),
    rgba(255, 209, 102, 0.055),
    transparent 62%
  );
}

.login-card:hover > .card-luz,
.login-card:focus-within > .card-luz {
  opacity: 1;
}


/* ════════════════════════════════════════════════════════════════
   3. A LUZ QUE PERCORRE A BORDA

   Um ponto de luz dá uma volta na borda e some por oito segundos.
   Não é borda dourada piscando: o ciclo é de 9s e a luz só existe
   durante 1,8s dele. O resto é escuro.

   Feito com conic-gradient recortado a 1px por máscara — sem elemento
   extra, sem offset-path (que ainda não aceita cantos arredondados).
   ════════════════════════════════════════════════════════════════ */

.card-luz::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(
    from var(--giro),
    transparent 0turn,
    transparent 0.88turn,
    rgba(245, 166, 35, 0.35) 0.94turn,
    var(--accent-2, #FFD166) 0.985turn,
    transparent 1turn
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  animation: bordaCorre 9s linear 2.4s infinite;
}

@keyframes bordaCorre {
  0%   { --giro: 0deg;   opacity: 0; }
  3%   { opacity: 0.85; }
  17%  { opacity: 0.85; }
  20%  { --giro: 360deg; opacity: 0; }
  100% { --giro: 360deg; opacity: 0; }
}


/* ════════════════════════════════════════════════════════════════
   4. O REFLEXO METÁLICO

   Uma faixa translúcida atravessa o card na diagonal a cada 13s.
   Opacidade baixíssima: tem que ler como luz escorregando em metal
   escovado, não como o brilho de botão de site de promoção.
   ════════════════════════════════════════════════════════════════ */

.card-luz::after {
  content: '';
  position: absolute;
  top: -45%;
  bottom: -45%;
  left: -55%;
  width: 42%;
  pointer-events: none;
  background: linear-gradient(
    to right,
    transparent,
    rgba(255, 246, 222, 0.035) 40%,
    rgba(255, 246, 222, 0.07) 50%,
    rgba(255, 246, 222, 0.035) 60%,
    transparent
  );
  animation: reflexoPassa 13s var(--ease-mec) 4s infinite;
}

@keyframes reflexoPassa {
  0%   { transform: translateX(0) skewX(-15deg);    opacity: 0; }
  2%   { opacity: 1; }
  15%  { opacity: 1; }
  18%  { transform: translateX(380%) skewX(-15deg); opacity: 0; }
  100% { transform: translateX(380%) skewX(-15deg); opacity: 0; }
}

/* A camada de luz fica ABAIXO do conteúdo. auth-ui.css põe
   `.login-card > *` em z-index 1; aqui ela é tirada dessa fila. */
.login-card > .card-luz {
  position: absolute;
  z-index: 0;
}


/* ════════════════════════════════════════════════════════════════
   5. CAMPOS — a energia entra pela borda

   `border-color: laranja` é a solução de todo mundo e não diz nada. O
   que se vê aqui é uma linha de luz CRESCENDO do centro para as pontas
   na base do campo, ao longo de 350ms, enquanto o halo abre. Lê como
   corrente entrando na peça.

   A linha é um plano de background com background-size animado — não
   precisa de pseudo-elemento, que <input> não aceita.
   ════════════════════════════════════════════════════════════════ */

.field input {
  background-color: #0A0906;
  background-image: linear-gradient(
    90deg,
    transparent,
    var(--accent, #F5A623) 28%,
    var(--accent-2, #FFD166) 50%,
    var(--accent, #F5A623) 72%,
    transparent
  );
  background-repeat: no-repeat;
  background-position: 50% calc(100% - 1px);
  background-size: 0% 1px;
  transition:
    border-color var(--motion-ui) var(--ease-mec),
    box-shadow var(--motion-ui) var(--ease-mec),
    background-color var(--motion-ui),
    background-size var(--motion-normal) var(--ease-mec);
}

.field input:hover:not(:focus) {
  border-color: rgba(255, 255, 255, 0.18);
}

.field input:focus {
  background-color: #0D0B07;
  background-size: 86% 1px;
}

/* ── Rótulo: sobe 1px e esquenta ── */
.field label {
  transition:
    color var(--motion-ui) var(--ease-mec),
    transform var(--motion-ui) var(--ease-mec),
    letter-spacing var(--motion-normal) var(--ease-mec);
  transform: translateY(0);
}

.field:focus-within label {
  color: var(--accent, #F5A623);
  transform: translateY(-1px);
  letter-spacing: 0.185em;
}

/* ── Inválido: vermelho contido ──
   `:user-invalid` e não `:invalid`: campo obrigatório vazio já nasce
   inválido, e a tela abriria toda vermelha antes de alguém digitar
   qualquer coisa. `:user-invalid` só vale depois da interação. */
/* SEM pintar o campo de vermelho. A versao anterior trocava a linha de
   energia da base por um gradiente vermelho, e com o preenchimento
   automatico do navegador em cima aquilo virava um bloco roxo cobrindo
   o campo inteiro — exatamente o que o Victor apontou.

   Erro no fim das contas continua sendo AVISO, nao alarme: a borda
   esquenta, um halo fino aparece, e a mensagem embaixo diz o que houve.
   Quem grita e a mensagem, nao o fundo do campo. */
.field input:user-invalid {
  border-color: rgba(255, 77, 109, 0.42);
}

.field input:user-invalid:focus {
  border-color: rgba(255, 77, 109, 0.6);
  box-shadow:
    inset calc(var(--lx) * 4px) calc(var(--ly) * 4px) 9px rgba(0, 0, 0, 0.75),
    0 0 0 2px rgba(255, 77, 109, 0.1);
}

/* ── Erro: micromovimento, não tremedeira ──
   Era ±4px em 400ms. Virou ±3px em 260ms: dá para notar sem parecer
   que a tela levou um tranco. */
.error-msg.show {
  animation: erroCutuca 0.26s var(--ease-mec);
}

@keyframes erroCutuca {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3px); }
  60%      { transform: translateX(3px); }
}


/* ════════════════════════════════════════════════════════════════
   6. O OLHO DA SENHA

   Hover ilumina, clique comprime. O `translateY(-50%)` que centraliza o
   botão tem que ser repetido em toda regra que mexe no transform —
   esquecer isso joga o ícone para fora do campo.
   ════════════════════════════════════════════════════════════════ */

.password-toggle {
  transition:
    color var(--motion-ui),
    background var(--motion-ui),
    filter var(--motion-fast),
    transform var(--motion-fast) var(--ease-mec);
}

.password-toggle:hover {
  filter: brightness(1.3);
}

.password-toggle:active {
  transform: translateY(-50%) scale(0.86);
}

/* A troca do ícone é curta e sem giro completo: é uma pálpebra, não uma
   roleta. */
.password-toggle.is-visible .eye-closed,
.password-toggle:not(.is-visible) .eye-open {
  animation: olhoTroca 170ms var(--ease-saida);
}

@keyframes olhoTroca {
  from { opacity: 0; transform: scale(0.82); }
  to   { opacity: 1; transform: scale(1); }
}


/* ════════════════════════════════════════════════════════════════
   7. BOTÕES — repouso, hover, apertado, processando

   O spinner genérico sai. O próprio botão vira o indicador: o rótulo
   troca para o verbo no gerúndio e uma linha fina corre na base. Não
   representa percentual e não finge representar — é espera indefinida
   mostrada com honestidade.
   ════════════════════════════════════════════════════════════════ */

.btn-login {
  transition:
    background var(--motion-ui) var(--ease-mec),
    box-shadow var(--motion-ui) var(--ease-mec),
    transform var(--motion-fast) var(--ease-mec),
    filter var(--motion-ui);
}

/* A varredura de luz no hover. `::after` já é a barra de progresso do
   estado carregando, então esta mora no `::before`. */
.btn-login::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    105deg,
    transparent 36%,
    rgba(255, 255, 255, 0.4) 50%,
    transparent 64%
  );
  transform: translateX(-130%);
  transition: transform 620ms var(--ease-saida);
}

.btn-login:hover::before {
  transform: translateX(130%);
}

.btn-login:active {
  transform: translateY(1px) scale(0.995);
}

.btn-login:disabled::before {
  display: none;
}

/* ── Estado processando ──
   O rótulo FICA (motion.js troca a palavra) e o spinner sai: dois
   indicadores para a mesma espera é um a mais. */
.btn-login.loading .btn-text {
  display: inline-block;
  animation: verboEntra 240ms var(--ease-saida);
}

.btn-login.loading .spinner {
  display: none;
}

@keyframes verboEntra {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}

.btn-login.loading::after {
  height: 2px;
  background: rgba(11, 10, 7, 0.5);
}

/* ── Estado 03 AUTHORIZED ──
   O Turnstile resolveu. Não é autorização — é só o caminho liberado —
   então o botão ganha luz, e não cor nova. */
.login-card.pronto .btn-login:not(:disabled) {
  filter: brightness(1.05);
}


/* ════════════════════════════════════════════════════════════════
   8. CLOUDFLARE TURNSTILE

   Nada aqui entra no widget. Só o contorno dele: quando o desafio
   passa, uma linha verde atravessa a base do invólucro, uma vez.
   Verde é legítimo aqui — houve um veredito, ainda que não seja o da
   autenticação.
   ════════════════════════════════════════════════════════════════ */

.cf-turnstile {
  position: relative;
  transition: opacity var(--motion-normal);
}

/* ── A barra que enche, e depois o pulso de "no ar" ──
   Duas peças, dois tempos. A barra ENCHE da esquerda para a direita em
   700ms: é o desafio sendo concluído. Depois ela para de encher e passa
   a respirar devagar, num ciclo de 2,6s — o sinal de que a verificação
   segue válida, como a luzinha de um equipamento ligado.

   Ficar piscando rápido seria alarme. A respiração é lenta de
   propósito: presença, não aviso. */
.cf-turnstile::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    rgba(0, 229, 160, 0.35),
    #00e5a0 55%,
    rgba(0, 229, 160, 0.75));
  box-shadow: 0 0 8px rgba(0, 229, 160, 0.45);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
}

.cf-turnstile.verificado::after {
  animation:
    barraEnche 700ms var(--ease-mec) forwards,
    respiraNoAr 2.6s var(--ease-saida) 700ms infinite;
}

@keyframes barraEnche {
  from { transform: scaleX(0); opacity: 1; }
  to   { transform: scaleX(1); opacity: 1; }
}

@keyframes respiraNoAr {
  0%, 100% { opacity: 0.32; }
  50%      { opacity: 1; }
}


/* ════════════════════════════════════════════════════════════════
   9. REQUISITOS DA SENHA — o encaixe

   Cada regra cumprida encaixa: 0,96 → 1 em 150ms, sem quicar. O
   retorno é só a transição de cor, que já é suave — animação de volta
   daria a impressão de que desfazer é um evento tão importante quanto
   fazer, e não é.
   ════════════════════════════════════════════════════════════════ */

/* O painel flutuava POR BAIXO do campo seguinte. Defeito antigo, achado
   agora: `.login-card > *` põe z-index 1 em cada filho direto, o que faz
   de #step1 um contexto de empilhamento; dentro dele o painel (z-index
   20) disputava com os irmãos, e o "confirmar senha" — que vem depois no
   DOM — ganhava. Erguer o campo que HOSPEDA o painel resolve na raiz:
   ele sobe inteiro, com o painel junto.

   Continua atravessável: `.forca` é pointer-events:none, então o clique
   no botão embaixo passa direto. */
.field:has(> .forca) {
  z-index: 30;
}

.forca-regras li {
  transform: scale(1);
  transition:
    color var(--motion-ui),
    border-color var(--motion-ui),
    background var(--motion-ui),
    transform var(--motion-ui) var(--ease-mec);
}

.forca-regras li.ok {
  animation: regraEncaixa 150ms var(--ease-mec);
}

.forca-regras li.ok::before {
  content: '✓';
  margin-right: 4px;
  display: inline-block;
  animation: regraCheca 180ms var(--ease-saida);
}

@keyframes regraEncaixa {
  from { transform: scale(0.96); }
  to   { transform: scale(1); }
}

@keyframes regraCheca {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: scale(1); }
}


/* ════════════════════════════════════════════════════════════════
   10. AS DUAS ETAPAS DO CADASTRO

   O indicador vira um trilho: dois pontos ligados por uma linha, e a
   energia percorre de um ao outro quando a etapa avança. Antes eram
   duas bolinhas soltas a 8px uma da outra, sem nada dizendo que uma
   leva à outra.
   ════════════════════════════════════════════════════════════════ */

.step-indicator {
  position: relative;
  gap: 38px;
}

.step-indicator::before,
.step-indicator::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 34px;
  height: 1px;
  margin: -1px 0 0 -17px;
}

.step-indicator::before {
  background: var(--border-strong, rgba(255, 255, 255, 0.15));
}

/* A energia. Parada em zero; corre quando o data-indo muda. */
.step-indicator::after {
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 6px var(--accent-glow);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--motion-normal) var(--ease-mec);
}

.step-indicator[data-indo="2"]::after {
  transform: scaleX(1);
}

.step-dot {
  transition:
    background var(--motion-ui) var(--ease-mec),
    box-shadow var(--motion-ui) var(--ease-mec),
    transform var(--motion-ui) var(--ease-mec);
}

.step-dot.active {
  transform: scale(1.25);
}

/* ── A troca de conteúdo ──
   Sai para um lado, entra pelo outro. Sequencial e não sobreposto: as
   duas etapas têm alturas diferentes, e cruzá-las exigiria tirar uma
   do fluxo — o que faria o card saltar de tamanho no meio da transição.
   200ms saindo + 340ms entrando continua sendo imediato. */
.step.etapa-sai {
  animation: etapaSaiEsq 200ms var(--ease-mec) both;
}

.step.etapa-sai-tras {
  animation: etapaSaiDir 200ms var(--ease-mec) both;
}

.step.etapa-entra {
  animation: etapaEntraDir 340ms var(--ease-saida) both;
}

.step.etapa-entra-tras {
  animation: etapaEntraEsq 340ms var(--ease-saida) both;
}

@keyframes etapaSaiEsq {
  to { opacity: 0; transform: translateX(-16px) scale(0.985); }
}

@keyframes etapaSaiDir {
  to { opacity: 0; transform: translateX(16px) scale(0.985); }
}

@keyframes etapaEntraDir {
  from { opacity: 0; transform: translateX(16px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}

@keyframes etapaEntraEsq {
  from { opacity: 0; transform: translateX(-16px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}


/* ════════════════════════════════════════════════════════════════
   11. A MARCA

   Revela de baixo para cima por clip-path e um brilho fino atravessa
   uma vez. Depois disso ela fica parada para sempre — logo que se mexe
   sozinha na tela em que a pessoa digita a senha é ruído.

   O brilho é recortado pela própria arte, com máscara alfa do webp: é
   a mesma técnica do .led-sweep do portal-theme, que recorta a luz pelo
   desenho do hero. Sem isso o reflexo seria um retângulo passando por
   cima da logo.
   ════════════════════════════════════════════════════════════════ */

.login-logo {
  position: relative;
}

/* fill-mode `backwards`, não `both`: com `both` o clip-path do último
   quadro fica grudado no elemento para sempre, e `inset(0)` recorta na
   caixa de borda — o drop-shadow âmbar da marca (22px de desfoque,
   portal-theme.css) era cortado rente. Com `backwards` a propriedade é
   devolvida ao terminar e o brilho volta inteiro. */
.login-logo img {
  animation: marcaRevela 700ms var(--ease-saida) backwards;
}

@keyframes marcaRevela {
  from { opacity: 0; clip-path: inset(0 0 42% 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

.login-logo::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-mask: url("../assets/logo-harpiontech.webp") center / contain no-repeat;
          mask: url("../assets/logo-harpiontech.webp") center / contain no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
  background: linear-gradient(
    104deg,
    transparent 40%,
    rgba(255, 248, 224, 0.75) 50%,
    transparent 60%
  ) no-repeat;
  background-size: 300% 100%;
  mix-blend-mode: screen;
  animation: marcaBrilha 1s var(--ease-mec) 0.52s both;
}

@keyframes marcaBrilha {
  0%   { background-position: 210% 0;  opacity: 0; }
  14%  { opacity: 1; }
  80%  { opacity: 1; }
  100% { background-position: -110% 0; opacity: 0; }
}


/* ════════════════════════════════════════════════════════════════
   12. O FUNDO — paralaxe, não partículas

   Duas camadas que já existiam passam a responder ao ponteiro em
   amplitudes diferentes: a arte do hero anda 2px, a grade técnica anda
   6px. É o suficiente para o fundo deixar de ser um adesivo colado
   atrás do card.

   A folga nas bordas (`inset: -10px`) existe porque deslocar uma camada
   `cover` sem sobra descobriria a borda oposta.

   Nada de partículas novas: o canvas de vento dourado já está lá, e
   somar pontinhos numa tela de login é exatamente o tipo de enfeite que
   o pedido excluiu.
   ════════════════════════════════════════════════════════════════ */

body::before {
  inset: -10px;
  translate: var(--par-x1, 0px) var(--par-y1, 0px);
  transition: translate 700ms var(--ease-saida);
  animation: derivaFundo 26s ease-in-out infinite;
}

/* Deriva quase imperceptível, num ciclo longo. Usa `transform` enquanto
   a paralaxe usa `translate` — são propriedades distintas e compõem sem
   uma apagar a outra. O scaleX(-1) do portal-theme é preservado aqui,
   senão a arte espelharia de volta. */
@keyframes derivaFundo {
  0%, 100% { transform: scaleX(-1) translate3d(0, 0, 0); }
  50%      { transform: scaleX(-1) translate3d(0, -7px, 0); }
}

.bg-grid {
  inset: -12px;
  translate: var(--par-x2, 0px) var(--par-y2, 0px);
  transition: translate 620ms var(--ease-saida);
}


/* ════════════════════════════════════════════════════════════════
   13. LINKS SECUNDÁRIOS

   O texto anda 1px, a seta anda 4px. É a seta que carrega o sentido do
   link, então é ela que se adianta.
   ════════════════════════════════════════════════════════════════ */

.login-footer a,
.no-access a,
.field a,
a.elo {
  display: inline-block;
  transition:
    color var(--motion-ui) var(--ease-mec),
    filter var(--motion-ui),
    transform var(--motion-ui) var(--ease-mec);
}

.login-footer a:hover,
.no-access a:hover,
.field a:hover,
a.elo:hover {
  filter: brightness(1.25);
}

.seta {
  display: inline-block;
  font-style: normal;
  transition: transform var(--motion-ui) var(--ease-mec);
}

/* Seta à direita puxa o link para a frente; seta à esquerda puxa para
   trás. O sentido do movimento é o sentido da navegação. */
:hover > .seta-dir { transform: translateX(4px); }
:hover > .seta-esq { transform: translateX(-4px); }

a:has(> .seta-dir):hover { transform: translateX(1px); }
a:has(> .seta-esq):hover { transform: translateX(-1px); }


/* ════════════════════════════════════════════════════════════════
   14. CONTA CONFIRMADA — o pulso

   O anel do selo e a marca dentro dele já se desenham (auth-ui.css).
   Faltava o terceiro tempo: um pulso verde que se abre pelo card e
   some. Ele começa em 1,0s, depois de a marca estar batida — pulso
   antes do veredito seria comemorar cedo.

   Fica preso ao card porque .login-card tem overflow hidden.
   ════════════════════════════════════════════════════════════════ */

.confirmado {
  position: relative;
}

.confirmado::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 47px;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  border: 1px solid #00e5a0;
  pointer-events: none;
  animation: pulsoVerde 1.15s var(--ease-saida) 1s both;
}

@keyframes pulsoVerde {
  from { transform: scale(1);  opacity: 0.75; }
  to   { transform: scale(52); opacity: 0; }
}

/* Estado 03 AUTHORIZED de verdade: agora existe veredito, e só agora os
   colchetes do card trocam de âmbar para verde. */
.login-card.autorizado {
  --canto: rgba(0, 229, 160, 0.5);
}


/* ════════════════════════════════════════════════════════════════
   15. O DESTRAVAMENTO

   Duas placas se afastam e revelam o que vem depois. Duração fixa de
   400ms, e a navegação sai no fim — nem um milissegundo a mais: a
   animação preenche um tempo que existiria de qualquer jeito (o
   carregamento da próxima página), não inventa espera nova.
   ════════════════════════════════════════════════════════════════ */

.destrava {
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  overflow: hidden;
}

.destrava i {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50.5%;
  background: #0A0906;
  opacity: 0;
}

.destrava i:first-child {
  left: 0;
  border-right: 1px solid var(--accent, #F5A623);
  box-shadow: 6px 0 24px rgba(245, 166, 35, 0.3);
  animation: placaEsquerda 400ms var(--ease-mec) forwards;
}

.destrava i:last-child {
  right: 0;
  border-left: 1px solid var(--accent, #F5A623);
  box-shadow: -6px 0 24px rgba(245, 166, 35, 0.3);
  animation: placaDireita 400ms var(--ease-mec) forwards;
}

@keyframes placaEsquerda {
  0%   { opacity: 0; transform: translateX(0); }
  22%  { opacity: 1; transform: translateX(0); }
  100% { opacity: 1; transform: translateX(-100%); }
}

@keyframes placaDireita {
  0%   { opacity: 0; transform: translateX(0); }
  22%  { opacity: 1; transform: translateX(0); }
  100% { opacity: 1; transform: translateX(100%); }
}


/* ════════════════════════════════════════════════════════════════
   16. TOQUE

   Sem ponteiro fino não existe nada para seguir: inclinação, luz do
   cursor e paralaxe saem. O que fica é tudo o que responde a foco,
   estado e veredito — que é justamente o que importa em quem está
   digitando com o polegar.
   ════════════════════════════════════════════════════════════════ */

@media (hover: none), (pointer: coarse) {
  .login-card {
    transform: none;
    transition: none;
  }

  .card-luz {
    display: none;
  }

  body::before,
  .bg-grid {
    translate: none;
    transition: none;
  }

  body::before {
    animation: none;
  }

  .btn-login::before {
    display: none;
  }
}


/* ════════════════════════════════════════════════════════════════
   17. MOVIMENTO REDUZIDO

   Sai tudo o que é decorativo e passivo. Fica o que informa: o campo
   em foco, a regra cumprida, o veredito, o erro. A tela continua
   dizendo a mesma coisa — só para de se mexer para dizer.
   ════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .card-luz,
  .card-luz::before,
  .card-luz::after,
  .login-logo::after,
  .btn-login::before,
  .destrava {
    display: none;
  }

  /* `animation: none` precisa ser repetido aqui. auth-ui.css já desliga a
     entrada do painel sob movimento reduzido, mas esta folha carrega
     depois e a redeclara na seção 1 — sem esta linha, a preferência da
     pessoa seria revogada por ordem de carregamento. */
  .login-card {
    animation: none;
    transform: none;
    transition: none;
  }

  .login-logo img,
  body::before,
  .confirmado::after,
  .forca-regras li.ok,
  .forca-regras li.ok::before,
  .cf-turnstile.verificado::after,
  .btn-login.loading .btn-text,
  .step.etapa-sai,
  .step.etapa-sai-tras,
  .step.etapa-entra,
  .step.etapa-entra-tras,
  .cf-turnstile.verificado::after {
    animation: none;
    transform: scaleX(1);
    opacity: 1;
  }

  .error-msg.show {
    animation: none;
  }

  body::before,
  .bg-grid {
    translate: none;
    transition: none;
  }

  /* A barra do botão fica: é o único sinal de que algo está em
     andamento, e tirá-la deixaria o botão mudo durante a espera. */
  .btn-login.loading::after {
    animation-duration: 1.6s;
  }
}
