/* ── O serviço acordando (assets/js/helpers/servico.js) ────────────────────
   Uma caixa só, no rodapé da tela, para toda espera de /api/*. Fica sempre no
   DOM (região viva que nasce com o texto nem sempre é anunciada) e some por
   opacidade. Cores por variável: cada página ajusta ao próprio tema, e o
   padrão é uma superfície escura com texto claro (contraste de 13:1), que lê
   bem sobre o app claro e sobre o login escuro. */

.obs-servico {
  --servico-fundo: #1c2333;
  --servico-tinta: #f3f5fa;
  --servico-fraco: #b4bdd0;
  --servico-borda: rgba(255, 255, 255, .12);
  --servico-acento: #8fb4ff;
  --servico-erro: #ff9aa9;
  --servico-botao: #f3f5fa;
  --servico-botao-tinta: #141a27;

  position: fixed; z-index: 2000; left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  width: min(33rem, calc(100% - 32px));
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  column-gap: 12px; row-gap: 8px;
  padding: 12px 14px 15px; overflow: hidden;
  border: 1px solid var(--servico-borda); border-radius: 12px;
  background: var(--servico-fundo); color: var(--servico-tinta);
  box-shadow: 0 14px 36px rgba(8, 12, 22, .32), 0 2px 8px rgba(8, 12, 22, .18);
  font: 500 14px/1.45 "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  opacity: 0; pointer-events: none;
  transform: translate(-50%, 14px);
  transition: opacity .18s ease-out, transform .18s ease-out;
}
.obs-servico:not([data-estagio="oculto"]) {
  opacity: 1; pointer-events: auto; transform: translate(-50%, 0);
}

.obs-servico-texto { margin: 0; min-width: 0; }
.obs-servico-tempo {
  color: var(--servico-fraco); font-size: 12.5px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* O sinal: anel que gira enquanto espera, ponto de exclamação no erro. */
.obs-servico-sinal {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .22); border-top-color: var(--servico-acento);
  animation: obs-servico-gira .8s linear infinite;
}
@keyframes obs-servico-gira { to { transform: rotate(360deg); } }

/* A trilha avança contra os 30 s anunciados (a largura vem do JS). No estágio
   "Conectando…" ela ainda não sabe quanto falta: um brilho corre por ela. */
.obs-servico-trilho {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(255, 255, 255, .08);
}
.obs-servico-barra {
  position: absolute; inset: 0; transform-origin: left center; transform: scaleX(0);
  background: var(--servico-acento); transition: transform 1s linear;
}
.obs-servico[data-estagio="conectando"] .obs-servico-trilho {
  background: linear-gradient(90deg, transparent 0, var(--servico-acento) 50%, transparent 100%)
              0 0 / 40% 100% no-repeat, rgba(255, 255, 255, .08);
  animation: obs-servico-corre 1.3s ease-in-out infinite;
}
@keyframes obs-servico-corre {
  from { background-position: -40% 0, 0 0; }
  to   { background-position: 140% 0, 0 0; }
}

/* Erro: nada gira, e o que se pede é uma ação. */
.obs-servico[data-estagio="erro"] { border-color: color-mix(in srgb, var(--servico-erro) 45%, transparent); }
.obs-servico[data-estagio="erro"] .obs-servico-sinal {
  animation: none; border: 0; background: var(--servico-erro); position: relative;
}
.obs-servico[data-estagio="erro"] .obs-servico-sinal::after {
  content: "!"; position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--servico-fundo); font: 800 11px/1 system-ui, sans-serif;
}
.obs-servico[data-estagio="erro"] .obs-servico-trilho { display: none; }

.obs-servico-acoes { grid-column: 2 / -1; display: flex; gap: 8px; align-items: center; }
.obs-servico:not([data-estagio="erro"]) .obs-servico-acoes { display: none; }
.obs-servico-repetir {
  min-height: 36px; padding: 6px 14px; border: 0; border-radius: 8px; cursor: pointer;
  background: var(--servico-botao); color: var(--servico-botao-tinta);
  font: inherit; font-weight: 700;
}
.obs-servico-fechar {
  margin-left: auto; width: 36px; height: 36px; border: 0; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--servico-fraco); font: 400 22px/1 system-ui, sans-serif;
}
.obs-servico-fechar:hover { background: rgba(255, 255, 255, .08); color: var(--servico-tinta); }
.obs-servico button:focus-visible { outline: 2px solid var(--servico-acento); outline-offset: 2px; }
.obs-servico [hidden] { display: none !important; }

@media (max-width: 420px) {
  .obs-servico { font-size: 13.5px; }
}

/* Movimento reduzido: o anel vira um ponto fixo, a trilha não corre nem
   desliza. A mensagem e o contador continuam dizendo o mesmo. */
@media (prefers-reduced-motion: reduce) {
  .obs-servico { transition: none; }
  .obs-servico-sinal { animation: none; border-color: var(--servico-acento); }
  .obs-servico[data-estagio="conectando"] .obs-servico-trilho { animation: none; }
  .obs-servico-barra { transition: none; }
}

/* ── Botão esperando a própria resposta ─────────────────────────────────
   O spinner que entra no rótulo do botão (login, convidar, salvar, sair…).
   Herda a cor do texto do botão, então serve em botão cheio e vazado. */
.obs-girando {
  display: inline-block; width: 1em; height: 1em; flex: 0 0 auto;
  vertical-align: -.15em; margin-right: .45em;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  animation: obs-servico-gira .75s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .obs-girando { animation: none; border-right-color: currentColor; opacity: .7; }
}

/* ── Esqueleto de lista ──────────────────────────────────────────────────
   "Ainda não sei" tem cara própria, diferente de "não há nada": linhas cinzas
   no lugar das pessoas e convites enquanto a API responde. Cores do tema do
   app, com reserva para página sem os tokens. */
.obs-esqueleto-lista { list-style: none; margin: 4px 0 12px; padding: 0; display: grid; gap: 4px; }
.obs-esqueleto-lista li { display: flex; align-items: center; gap: 12px; padding: 9px 0; }
.obs-esqueleto-avatar { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; }
.obs-esqueleto-linhas { flex: 1; display: grid; gap: 7px; }
.obs-esqueleto-linhas span { display: block; height: 10px; border-radius: 5px; width: 55%; }
.obs-esqueleto-linhas span + span { height: 8px; width: 82%; }
.obs-esqueleto-lista li:nth-child(2n) .obs-esqueleto-linhas span { width: 42%; }
.obs-esqueleto-lista li:nth-child(2n) .obs-esqueleto-linhas span + span { width: 68%; }
.obs-esqueleto-avatar, .obs-esqueleto-linhas span {
  background-color: var(--obs-border, #e2e6f0);
  background-image: linear-gradient(90deg, transparent 0,
    color-mix(in srgb, var(--obs-surface, #fff) 65%, transparent) 50%, transparent 100%);
  background-size: 200% 100%; background-repeat: no-repeat;
  animation: obs-esqueleto 1.4s ease-in-out infinite;
}
@keyframes obs-esqueleto { from { background-position: 150% 0; } to { background-position: -50% 0; } }
@media (prefers-reduced-motion: reduce) {
  .obs-esqueleto-avatar, .obs-esqueleto-linhas span { animation: none; background-image: none; }
}
