/* ==========================================================================
   components.css — pecas isoladas e reaproveitaveis
   ========================================================================== */

/* --- indicador de rolagem do hero ----------------------------------------
   Um tracinho que desce e some, em loop. Feito com gradiente e nao com dois
   elementos: e uma linha so, com transparencia nas pontas, e o que anima e a
   posicao do fundo dentro dela.
*/
.hero__indicador-linha {
  width: 1px;
  height: 64px;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    var(--tinta) 35%,
    var(--tinta) 65%,
    transparent 100%
  );
  background-size: 100% 40%;
  background-repeat: no-repeat;
  /* Fora da area visivel no comeco, para o traco "entrar" pelo topo. */
  background-position: 0 -40%;
  animation: descer 2.4s var(--curva) infinite;

  /* A linha e uma faixa fina de 1px que anima sozinha. contain: paint avisa o
     navegador que nada dela pinta fora da caixa, entao ele nao precisa
     recalcular o resto do hero a cada quadro. */
  contain: paint;
}

@keyframes descer {
  0%   { background-position: 0 -40%; opacity: 0; }
  25%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { background-position: 0 140%; opacity: 0; }
}

/* Com movimento reduzido o loop infinito some por completo — o bloco global
   do base.css so encurta a duracao, e uma animacao infinita de 0.01ms vira
   uma tremedeira. Aqui a gente desliga de verdade e deixa a linha parada. */
@media (prefers-reduced-motion: reduce) {
  .hero__indicador-linha {
    animation: none;
    background-position: 0 30%;
    opacity: 1;
  }
}

/* ==========================================================================
   PRELOADER do tour
   ========================================================================== */

.preloader {
  /* absolute dentro do palco, que e sticky. Nao ocupa espaco no fluxo, entao
     sair da tela nao encolhe o documento nem desloca gatilho nenhum. */
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 1.25rem;
  padding: var(--gutter);
  background: var(--fundo);
  text-align: center;

  transition: opacity 0.6s var(--curva), visibility 0.6s;
}

/* Estado "pronto": some por opacidade E por visibility.
   Só opacity deixaria um retangulo invisivel capturando clique por cima do
   tour; visibility resolve isso e ainda tira os textos da arvore de
   acessibilidade, para o leitor de tela nao ler "0%" para sempre. */
.preloader.esta-pronto {
  opacity: 0;
  visibility: hidden;
}

.preloader__rotulo {
  font-size: var(--t-miudo);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--tinta-fraca);
}

.preloader__barra {
  width: min(280px, 70vw);
  height: 2px;
  background: var(--linha);
  overflow: hidden;
}

.preloader__preenchimento {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--realce);

  /* scaleX em vez de width: transform nao dispara recalculo de layout, entao
     a barra anda numa camada propria sem custo por quadro. */
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.25s linear;
}

.preloader__porcento {
  font-family: var(--fonte-titulo);
  font-size: 1.5rem;
  /* Tabular: os digitos passam a ter todos a mesma largura, entao o numero
     nao "pula" ao trocar de 8% para 11%. */
  font-variant-numeric: tabular-nums;
  color: var(--tinta);
}

/* ==========================================================================
   LEGENDAS do tour
   ========================================================================== */

/* O veu da base do palco. Nao e enfeite: as legendas passam por cima de
   centenas de frames diferentes, incluindo uma cozinha branca estourada de
   luz. Um gradiente fixo na base resolve todos de uma vez — a alternativa
   seria medir o brilho do frame atual a cada quadro, que custa getImageData
   por frame e nao vale o preco. */
.tour__veu {
  position: absolute;
  inset: auto 0 0 0;
  height: 55%;
  pointer-events: none;   /* nao rouba clique nem selecao de texto */
  background: linear-gradient(
    to top,
    rgba(16, 15, 13, 0.90) 0%,
    rgba(16, 15, 13, 0.78) 26%,
    rgba(16, 15, 13, 0.52) 50%,
    rgba(16, 15, 13, 0.22) 74%,
    rgba(16, 15, 13, 0) 100%
  );
}

.tour__legendas {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(2.5rem, 8vh, 5rem);
  width: min(38ch, calc(100% - var(--gutter) * 2));

  /* As legendas ficam empilhadas no MESMO ponto: uma grade de uma celula
     onde todas ocupam a linha 1 e a coluna 1. E o jeito de sobrepor sem
     position: absolute em cada filha — e, de quebra, a altura da caixa passa
     a ser a da legenda mais alta, entao nada se mexe na troca. */
  display: grid;
}

.legenda {
  grid-area: 1 / 1;

  /* Escondida por OPACIDADE. Nunca display:none nem visibility:hidden: as
     duas tirariam o texto da arvore de acessibilidade, e sao justamente
     estas 7 legendas que servem de alternativa textual para o <canvas>. */
  opacity: 0;

  /* pointer-events: none na inativa evita que uma legenda invisivel bloqueie
     a selecao da que esta na tela. A ativa reativa logo abaixo. */
  pointer-events: none;

  text-shadow: 0 1px 18px rgba(16, 15, 13, 0.7),
               0 1px 3px rgba(16, 15, 13, 0.45);
}

.legenda__titulo {
  font-size: clamp(1.75rem, 4vw, 3rem);
  margin-bottom: 0.5rem;
}

.legenda__texto {
  font-size: var(--t-medio);
  color: var(--tinta);
  opacity: 0.86;
}

/* Movimento reduzido: as sete viram uma lista de texto empilhada, que e o
   conteudo real da secao. A grade de celula unica desmancha. */
.tour__legendas.esta-em-lista {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  position: static;
  width: auto;
}

.tour__legendas.esta-em-lista .legenda {
  pointer-events: auto;
  text-shadow: none;
}

/* ==========================================================================
   FORMULARIO
   ========================================================================== */

.formulario {
  display: grid;
  gap: 1.5rem;
  margin-top: clamp(2rem, 5vh, 3rem);
  max-width: 30rem;
}

.campo { display: grid; gap: 0.5rem; }

.campo__rotulo {
  font-size: var(--t-miudo);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tinta-fraca);
}

.campo__entrada {
  width: 100%;
  padding: 0.85rem 1rem;
  background: transparent;
  border: 1px solid var(--linha);
  color: var(--tinta);
  transition: border-color 0.2s var(--curva);
}

.campo__entrada:hover { border-color: rgba(242, 239, 233, 0.3); }
.campo__entrada:focus-visible { border-color: var(--realce); }

/* O <select> herda o fundo do sistema na lista suspensa, que em tema claro
   fica branco sobre branco. Pintar as <option> explicitamente e o unico
   jeito de garantir contraste nos dois temas. */
.campo__entrada option { background: var(--fundo-alto); color: var(--tinta); }

/* aria-invalid e um atributo, nao uma classe — e da para estiliza-lo direto.
   Vantagem: o estado visual e o estado anunciado pelo leitor de tela sao a
   MESMA fonte. Nao ha como um ficar certo e o outro errado. */
.campo__entrada[aria-invalid='true'] { border-color: #d98b6a; }

.campo__erro { font-size: var(--t-miudo); color: #d98b6a; }

.botao {
  justify-self: start;
  padding: 0.9rem 2rem;
  background: var(--tinta);
  color: var(--fundo);
  border: 1px solid var(--tinta);
  cursor: pointer;
  font-size: var(--t-miudo);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: background-color 0.25s var(--curva), color 0.25s var(--curva);
}

.botao:hover { background: transparent; color: var(--tinta); }

.formulario__aviso {
  font-size: var(--t-miudo);
  color: var(--realce);
  /* Comeca invisivel por OPACIDADE, nunca por display:none. A regiao viva
     precisa estar no DOM e visivel para a arvore de acessibilidade desde o
     inicio — regiao criada ou revelada no mesmo instante da mensagem
     costuma nao ser anunciada por leitor de tela. */
  opacity: 0;
  transition: opacity 0.4s var(--curva);
}

.formulario__aviso.esta-visivel { opacity: 1; }

/* ==========================================================================
   LIGHTBOX
   ========================================================================== */

.lightbox {
  /* padding: 0 e obrigatorio, nao estetica.
     O <dialog> vem com 16px de padding por padrao, e clique nesse padding
     tem o proprio <dialog> como alvo — ou seja, o "clique fora fecha"
     dispararia numa faixa que o usuario ve como sendo de dentro do modal. */
  padding: 0;
  border: 0;
  max-width: 100vw;
  max-height: 100dvh;
  width: 100%;
  height: 100%;
  background: transparent;
  color: var(--tinta);
  overflow: hidden;
}

.lightbox::backdrop { background: rgba(16, 15, 13, 0.94); }

.lightbox__interior {
  height: 100%;
  display: grid;
  place-content: center;
  gap: 1rem;
  padding: clamp(3rem, 8vh, 5rem) clamp(3.5rem, 9vw, 6rem);
}

.lightbox__foto {
  max-width: min(1200px, 100%);
  /* Altura limitada pela janela menos o espaco da legenda, senao uma foto
     alta empurra o texto para fora da tela. */
  max-height: calc(100dvh - 12rem);
  width: auto;
  height: auto;
  margin-inline: auto;
  object-fit: contain;
}

.lightbox__legenda { text-align: center; max-width: 60ch; margin-inline: auto; }

.lightbox__contador {
  text-align: center;
  font-size: var(--t-miudo);
  letter-spacing: 0.18em;
  color: var(--tinta-fraca);
  font-variant-numeric: tabular-nums;
}

.lightbox__botao {
  position: absolute;
  background: none;
  border: 0;
  color: var(--tinta);
  cursor: pointer;
  line-height: 1;
  /* 44x44 e o alvo minimo recomendado para toque. Um X de 2rem tem area
     clicavel de uns 20px se ninguem reservar espaco em volta. */
  min-width: 44px;
  min-height: 44px;
  opacity: 0.7;
  transition: opacity 0.2s var(--curva);
}

.lightbox__botao:hover,
.lightbox__botao:focus-visible { opacity: 1; }

.lightbox__botao--fechar { top: 1rem; right: 1rem; font-size: 2.25rem; }

.lightbox__botao--anterior,
.lightbox__botao--proxima {
  top: 50%;
  transform: translateY(-50%);
  font-size: 3rem;
}

.lightbox__botao--anterior { left: 0.25rem; }
.lightbox__botao--proxima { right: 0.25rem; }

/* ==========================================================================
   BOTAO FLUTUANTE
   ========================================================================== */

.flutuante {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: 50;

  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.25rem;

  /* Verde escurecido de #1f8a4c para #157a41. Nao foi gosto: o tom
     anterior dava 4,38:1 contra o branco e o rotulo tem 13px, que a WCAG
     trata como texto pequeno e exige 4,5:1. Escurecer o fundo foi mais
     barato do que aumentar a fonte de um botao flutuante. Agora da 5,4:1. */
  background: #157a41;
  color: #fff;
  text-decoration: none;
  font-size: var(--t-miudo);
  letter-spacing: 0.08em;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);

  /* Escondido ate o hero sair da tela. visibility junto com opacity para o
     botao nao capturar clique enquanto invisivel — e para sair da ordem de
     Tab, que e o detalhe que quase todo mundo esquece. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.75rem);
  transition: opacity 0.35s var(--curva),
              transform 0.35s var(--curva),
              visibility 0.35s;
}

.flutuante.esta-visivel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.flutuante__icone { width: 1.35rem; height: 1.35rem; flex: none; }

@media (max-width: 480px) {
  /* No celular sobra so o icone: o rotulo comeria metade da largura da tela
     por cima do conteudo. O nome continua acessivel pelo texto do link. */
  .flutuante__texto {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .flutuante { padding: 0.9rem; border-radius: 50%; }
}

/* Link que substitui o tour sob movimento reduzido. Ver js/captions.js. */
.tour__atalho {
  display: inline-block;
  margin-top: 2.5rem;
  padding-bottom: 0.25rem;
  color: var(--realce);
  border-bottom: 1px solid currentColor;
  text-decoration: none;
}

.tour__atalho:hover { color: var(--tinta); }

/* --------------------------------------------------------------------------
   Ajustes de toque
   --------------------------------------------------------------------------
   O ponteiro grosseiro nao e "tela pequena": um notebook com tela sensivel
   ao toque tem 1400px de largura e dedo. Por isso a consulta e por
   `pointer: coarse`, e nao por max-width.
   -------------------------------------------------------------------------- */
@media (pointer: coarse) {
  /* No dedo nao existe estado de passagem do mouse: o "hover" fica preso
     depois do toque e a foto continua ampliada ate alguem tocar em outra. */
  .galeria__item:hover img { transform: none; opacity: 1; }

  /* As setas do lightbox ficam grandes o bastante para o polegar e saem da
     borda, onde o gesto de voltar do sistema costuma comer o toque. */
  .lightbox__botao--anterior,
  .lightbox__botao--proxima { min-width: 56px; min-height: 56px; }
  .lightbox__botao--anterior { left: 0.5rem; }
  .lightbox__botao--proxima { right: 0.5rem; }
}

/* ==========================================================================
   REVELACOES — estado inicial
   ==========================================================================

   Estas regras sao o unico lugar que decide COMO cada elemento comeca. O
   js/reveal.js so anima ate o repouso (gsap.to), nunca redeclara o inicio —
   com o inicio nos dois lugares, um dia eles discordariam.

   Tudo pendurado em .js-revelar, que so existe se o JavaScript estiver
   vivo. Ver o comentario grande no <head> do index.html: sem essa classe a
   pagina inteira nasce visivel, que e como ela precisa falhar.

   O tour nao tem marcador nenhum e nao e tocado por nada aqui.
   ========================================================================== */

.js-revelar [data-revelar='texto'],
.js-revelar [data-revelar='ladrilho'] {
  opacity: 0;
  transform: translateY(28px);
}

/* A cortina. Os quatro valores do inset() sao as bordas cima / direita /
   baixo / esquerda: 100% embaixo fecha a persiana por completo, e abrir ate
   0% revela a foto de cima para baixo.

   Todos os valores em %, inclusive os zeros. O GSAP interpola numero a
   numero dentro da funcao, e misturar 0 com 0% e onde essa interpolacao
   costuma quebrar sem avisar. */
.js-revelar [data-revelar='foto'] {
  clip-path: inset(0% 0% 100% 0%);
}

/* A imagem comeca 12% maior e assenta em 1 enquanto a cortina sobe. As duas
   animacoes tem duracoes diferentes de proposito — ver js/reveal.js. */
.js-revelar [data-revelar='foto'] img {
  transform: scale(1.12);
}

/* Movimento reduzido tratado tambem aqui, e nao so no JavaScript.

   O modulo remove a classe .js-revelar quando detecta a preferencia, mas
   ele e um modulo: roda depois da primeira pintura. Sem estas regras haveria
   um instante com o conteudo escondido — curto, porem exatamente o tipo de
   piscar que a preferencia pede para nao existir. Custa quatro linhas. */
@media (prefers-reduced-motion: reduce) {
  .js-revelar [data-revelar] {
    opacity: 1;
    transform: none;
    clip-path: none;
  }
  .js-revelar [data-revelar='foto'] img { transform: none; }
}
