/* ==========================================================================
   PRISMA · patterns/assincrono.css — ESPERA E REVELAÇÃO  (D-011)
   --------------------------------------------------------------------------
   REGRA TRANSVERSAL (autora, 19/09/2026 — vale para ÁGORA, HispanoQuest,
   PRISMA e tudo o que vier): toda operação assíncrona PERCEPTÍVEL
     1. mostra que está trabalhando,
     2. diz O QUE está fazendo, em palavras,
     3. e o resultado ENTRA EM CENA — não aparece de estalo.

   LIMIARES — o que a pessoa vê depende de quanto demora:
     < 400 ms      só microfeedback (pressão do botão). Carregador aqui PISCA
                   e faz o sistema parecer mais lento do que é.
     400 ms – 2 s  carregador em linha + uma frase      → .espera-linha
     > 2 s         etapas NOMEADAS + poder cancelar     → .etapas
     região inteira ocupada                             → .veu-espera
     chegou                                             → .revelar
     deu certo, e importa                               → .pulso-sucesso
     não veio nada / deu errado   → .estado, .estado--erro (primitives/feedback.css)
                                    SEMPRE com "Tentar de novo" em .estado-acoes

   O tempo quem mede é patterns/assincrono.js (sem dependência). Este arquivo
   só desenha.

   JÁ EXISTIA e continua valendo: .gerando/.gerando-texto (motion.css),
   .esqueleto*, .progresso*, .spinner, .estado* (feedback.css), .confirmar.

   ACESSO: a região que espera leva aria-busy="true"; a frase vive num
   role="status" aria-live="polite". Estado nunca é só cor ou só movimento.
   ========================================================================== */

/* --- 400 ms – 2 s : carregador em linha + frase -------------------------------- */
.espera-linha {
  display: inline-flex; align-items: center; gap: var(--espaco-2);
  font-size: var(--body-sm-size); color: var(--text-secondary);
}
.espera-linha[hidden] { display: none; }

/* --- > 2 s : ETAPAS ---------------------------------------------------------------
   A linha pertence ao TRABALHO, não a quem executa. Quem executa aparece, pequeno,
   dentro da etapa atual (.etapa-quem) — e pode mudar sem a linha mudar.
     <ol class="etapas">
       <li class="etapa" data-estado="feita">…</li>
       <li class="etapa" data-estado="atual" aria-current="step">…</li>
       <li class="etapa" data-estado="espera">…</li>
     </ol>
   Estados: feita · atual · voce (aguarda decisão humana) · espera · falhou */
.etapas {
  --etapa-marca: 22px;
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: var(--espaco-3);
}
.etapa {
  position: relative;
  display: grid; gap: var(--espaco-2); align-content: start;
  padding-top: calc(var(--etapa-marca) + var(--espaco-3));
  min-width: 0;
}
/* trilho: do centro desta marca até a próxima */
.etapa::before {
  content: ""; position: absolute;
  top: calc(var(--etapa-marca) / 2); left: var(--etapa-marca);
  width: calc(100% - var(--etapa-marca) + var(--espaco-3)); height: 1px;
  background: var(--border-default);
}
.etapa:last-child::before { display: none; }
.etapa[data-estado="feita"]::before { background: var(--border-strong); }

.etapa-marca {
  position: absolute; top: 0; left: 0;
  width: var(--etapa-marca); height: var(--etapa-marca);
  display: grid; place-items: center;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--border-strong);
  color: var(--text-muted);
}
.etapa-marca svg { width: 12px; height: 12px; stroke-width: 2.4; }
.etapa[data-estado="espera"] .etapa-marca svg,
.etapa[data-estado="atual"]  .etapa-marca svg,
.etapa[data-estado="voce"]   .etapa-marca svg { display: none; }

.etapa[data-estado="feita"] .etapa-marca {
  background: var(--text-primary); color: var(--background-canvas); box-shadow: none;
}
.etapa[data-estado="atual"] .etapa-marca { box-shadow: inset 0 0 0 1px var(--text-primary); }
.etapa[data-estado="atual"] .etapa-marca::after,
.etapa[data-estado="voce"]  .etapa-marca::after {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--text-primary);
}
.etapa[data-estado="voce"] .etapa-marca { box-shadow: inset 0 0 0 1px var(--warning); }
.etapa[data-estado="voce"] .etapa-marca::after { background: var(--warning); }
.etapa[data-estado="falhou"] .etapa-marca { box-shadow: inset 0 0 0 1px var(--danger); color: var(--danger); }

.etapa-nome {
  font-size: var(--body-sm-size); font-weight: 500; line-height: 1.3;
  color: var(--text-muted);
}
.etapa[data-estado="feita"] .etapa-nome { color: var(--text-secondary); }
.etapa[data-estado="atual"] .etapa-nome,
.etapa[data-estado="voce"]  .etapa-nome { color: var(--text-primary); }
.etapa-quem {
  font-size: var(--caption-size); line-height: 1.45; color: var(--text-muted);
  max-width: 24ch;
}

/* a marca da etapa atual respira — é o "estou trabalhando". Só opacidade. */
@media (prefers-reduced-motion: no-preference) {
  .etapa[data-estado="atual"] .etapa-marca::after { animation: etapa-viva 1.6s var(--easing-movimento) infinite alternate; }
  [data-reduzir-movimento] .etapa[data-estado="atual"] .etapa-marca::after { animation: none; }
}
@keyframes etapa-viva { from { opacity: 1; } to { opacity: .35; } }

/* celular: a linha deita — vira trilho vertical */
@media (max-width: 720px) {
  .etapas { grid-auto-flow: row; grid-auto-columns: auto; gap: 0; }
  .etapa { padding-top: 0; padding-left: calc(var(--etapa-marca) + var(--espaco-4)); padding-bottom: var(--espaco-5);
           grid-template-columns: minmax(0, 1fr); }
  .etapa::before { top: var(--etapa-marca); left: calc(var(--etapa-marca) / 2);
                   width: 1px; height: calc(100% - var(--etapa-marca)); }
  .etapa:last-child { padding-bottom: 0; }
  .etapa-quem { max-width: none; }
}

/* --- REGIÃO INTEIRA OCUPADA ------------------------------------------------------
   O conteúdo antigo continua visível por baixo, esmaecido: some o susto de "sumiu
   tudo". A região-mãe precisa de position: relative e aria-busy="true". */
.veu-espera {
  position: absolute; inset: 0; z-index: 5;
  display: grid; place-items: center; align-content: center; gap: var(--espaco-3);
  border-radius: inherit;
  background-color: color-mix(in srgb, var(--background-canvas) 62%, transparent);
  -webkit-backdrop-filter: blur(var(--glass-blur-clear));
          backdrop-filter: blur(var(--glass-blur-clear));
  color: var(--text-primary); font-size: var(--body-sm-size); text-align: center;
  opacity: 1;
  transition: opacity var(--motion-default) var(--easing-standard);
}
.veu-espera[hidden] { display: none; }
@starting-style { .veu-espera { opacity: 0; } }

/* --- REVELAÇÃO ---------------------------------------------------------------------
   O resultado chega de um leve desfoque para o nítido, subindo 8px. Transição, não
   keyframe: se chegar outro resultado no meio, retoma de onde está (skill animate §6).
   Desfoque de 6px — abaixo dos 20px que custam caro no Safari.
     <div class="revelar" data-revelado="false"> … </div>   → "true" quando chega */
.revelar {
  transition:
    opacity   var(--motion-slow) var(--easing-enter),
    transform var(--motion-slow) var(--easing-enter),
    filter    var(--motion-slow) var(--easing-enter);
}
.revelar[data-revelado="false"] {
  opacity: 0; transform: translateY(8px) scale(.985); filter: blur(6px);
  pointer-events: none;
}
/* vários resultados: entram em fila de 45ms, como .entrada-sequencia */
.revelar[data-revelado="true"] > .revelar-item { transition-delay: calc(var(--i, 0) * 45ms); }

@media (prefers-reduced-motion: reduce) {
  .revelar { transition: opacity var(--motion-default) linear; }
  .revelar[data-revelado="false"] { transform: none; filter: none; }
}
[data-reduzir-movimento] .revelar { transition: opacity var(--motion-default) linear; }
[data-reduzir-movimento] .revelar[data-revelado="false"] { transform: none; filter: none; }

/* --- DEU CERTO, E IMPORTA ------------------------------------------------------------
   Um anel que se abre UMA vez. Raro de propósito: sucesso de rotina não pulsa
   (skill apple-design §13 — feedback demais ensina a ignorar todo feedback). */
.pulso-sucesso { position: relative; }
.pulso-sucesso::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: 0 0 0 2px var(--success);
  opacity: 0; pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .pulso-sucesso[data-pulsar]::after { animation: pulso-sucesso 640ms var(--easing-standard) 1; }
  [data-reduzir-movimento] .pulso-sucesso[data-pulsar]::after { animation: none; }
}
@keyframes pulso-sucesso {
  from { opacity: .7; transform: scale(.97); }
  to   { opacity: 0;  transform: scale(1.06); }
}
