* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* `color-scheme` não é decoração: é o que faz o navegador pintar em tom certo o
   que NÃO é nosso — barra de rolagem nativa, calendário do <input type=date>,
   caixa de autopreenchimento, seleção de texto. Sem trocá-lo junto com a
   paleta, o tema claro abriria seletores pretos por cima da tela branca. */
html {
  color-scheme: dark;
}

html[data-tema="claro"] {
  color-scheme: light;
}

body {
  font-family: var(--font-base);
  background: var(--bg-primary);
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  cursor: pointer;
}

input {
  font-family: inherit;
}

ul {
  list-style: none;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: 600;
  line-height: 1.25;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--scroll-polegar);
  border-radius: 10px;
  border: 2px solid transparent;
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--scroll-polegar-hover);
  background-clip: padding-box;
}

/* ============================================================
   Campo de formulário
   ============================================================
   Mora no base.css e não no perfil.css, onde nasceu: `.entrada` é uma primitiva
   de formulário, e três páginas já a usam — o perfil, o Slide Show (o campo de
   segundos) e o servidor de e-mail.

   Isto era um DEFEITO até agora, não uma reorganização: o `slideshow.html` não
   carrega o `perfil.css`, então o `.ss-campo .entrada` só recebia a largura de
   88px que a folha dele define, e o campo de segundos aparecia com a borda
   crua do navegador — cinza-claro em cima do tema escuro. Aqui a primitiva
   alcança quem a usa. */
.entrada {
  width: 100%;
  background: var(--bg-tertiary);
  border: 1px solid var(--border-color);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 14px;
  font-family: inherit;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.entrada::placeholder {
  color: var(--text-muted);
}

.entrada:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Campo permanentemente travado — o e-mail no perfil. */
.entrada.is-bloqueada {
  color: var(--text-secondary);
  cursor: not-allowed;
  background: var(--bg-primary);
}

.entrada.is-bloqueada:focus {
  border-color: var(--border-color);
  box-shadow: none;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Ícones outline. Cobre as duas grafias em uso: .icon (login) e .icone
   (área interna). Sem fill:none/stroke:currentColor as formas nasceriam
   preenchidas de preto — que era por que os ícones do menu sumiam no fundo. */
.icon,
.icone {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ============================================================
   Estados de tela: a espera e o erro
   ============================================================
   Vivem no base.css, e não no analise.css, porque não são das análises:
   a Comunidade e o perfil também esperam e também falham, e essas páginas
   não carregam a folha das análises — 6 mil linhas para reaproveitar um
   símbolo de carregamento seria o contrário de reaproveitar. */

.erro-tela {
  padding: 60px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13.5px;
}

/* ---------- A espera ----------

   Centralizada de verdade, e não um texto no topo: a troca de tela apaga o
   conteúdo, e uma linha cinza no alto do vazio parece página quebrada. No meio,
   com a marca se desenhando, parece o que é — trabalho em curso.

   `min-height` em vez de `height: 100%`: o pai nem sempre tem altura definida
   (a área de análise se dimensiona pelo conteúdo, que neste instante não
   existe), e aí o 100% resolveria para zero e o símbolo colaria no topo. */
.carregando {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-height: min(52vh, 420px);
  color: var(--text-muted);
  font-size: 13.5px;

  /* SÓ APARECE SE DEMORAR. Nasce invisível e leva 180 ms para surgir: numa
     resposta de 80 ms o símbolo piscaria e sumir, e um lampejo assim é mais
     desconfortável que espera nenhuma. Feito com atraso de animação, não com
     `setTimeout`, porque assim não há timer para limpar quando a tela troca
     antes da hora — o elemento some e leva o próprio atraso junto. */
  opacity: 0;
  animation: carregando-surge 220ms ease 180ms forwards;
}

@keyframes carregando-surge {
  to { opacity: 1; }
}

.carregando-marca {
  width: 62px;
  height: 62px;
  overflow: visible;
  fill: none;
  stroke: var(--brand);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* O traço se desenha e depois se apaga, e o ciclo recomeça. `pathLength="1"`
   no SVG normaliza todos os comprimentos para 1 — por isso os valores aqui são
   1 e 0 em qualquer traço, curto ou longo, e mexer no desenho não obriga a
   mexer no CSS. */
.carregando-marca > * {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* `--t` é a vez de cada traço, escrita no HTML. Os quatro partilham a mesma
     animação de 2,4 s e entram escalonados a cada 0,2 s: é o escalonamento que
     faz a marca ser CONSTRUÍDA, e não quatro riscos surgindo juntos. */
  animation: carregando-traco 2.4s ease-in-out infinite;
  animation-delay: calc(var(--t) * 0.2s);
}

@keyframes carregando-traco {
  /*  0-30%  desenha
     30-55%  fica inteiro, para a marca ser reconhecida antes de sumir
     55-80%  apaga pelo mesmo lado em que começou
     80-100% pausa antes de recomeçar, para o ciclo ter respiração */
  0%   { stroke-dashoffset: 1; }
  30%  { stroke-dashoffset: 0; }
  55%  { stroke-dashoffset: 0; }
  80%  { stroke-dashoffset: -1; }
  100% { stroke-dashoffset: -1; }
}

.carregando-texto {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* MOVIMENTO REDUZIDO NÃO É AUSÊNCIA DE SINAL.

   A primeira versão desligava tudo, e o resultado era um ícone morto no meio da
   tela — indistinguível de uma tela travada, que é o oposto do que um indicador
   de carregamento existe para dizer.

   O que a preferência pede é reduzir MOVIMENTO: o que incomoda quem tem
   sensibilidade vestibular é deslocamento, giro, zoom, paralaxe. Uma variação
   de opacidade não desloca nada. Então aqui a marca fica inteira e parada, e
   quem pulsa é o brilho — o traço não se desenha, mas a tela continua dizendo
   que está trabalhando.

   Vale saber: no Windows isso vem de "Efeitos de animação", em Acessibilidade →
   Efeitos visuais. Com ele desligado, o Chrome relata `reduce` e é este bloco
   que vale — foi assim que o ícone apareceu parado na primeira tentativa. */
@media (prefers-reduced-motion: reduce) {
  .carregando {
    opacity: 0;
    animation: carregando-surge 220ms ease 180ms forwards;
  }

  .carregando-marca {
    animation: carregando-pulso 1.8s ease-in-out infinite;
  }

  /* Traço inteiro e sem escalonamento: é o desenho que fica de fora, não a
     marca. */
  .carregando-marca > * {
    animation: none;
    stroke-dashoffset: 0;
  }
}

@keyframes carregando-pulso {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.32; }
}

.erro-titulo {
  font-size: 15px;
  font-weight: 600;
  color: var(--danger-tinta);
  margin-bottom: 6px;
}

.erro-detalhe {
  font-size: 12px;
}
