/* ============================================================
   UM LUGAR COMUNIDADE — SISTEMA CLARO
   Linkpage · movimento
   Toda transição, hover e revelação da página. Só transform,
   translate/scale e opacity — nunca width/height/top/left,
   nunca "transition: all".

   Contrato com o JS (assets/js/linkpage.js, a escrever):
   - .rev entra em cena quando o JS acrescenta .rev--on. Capa e
     marca ganham essa classe na carga (não esperam scroll); o
     resto (ícones sociais, cards) por IntersectionObserver, em
     cascata conforme aparece.
   - .capa__mote-i troca de --ativo quando o JS decide a rotação.
     O item que sai pode receber .capa__mote-i--saida por
     var(--d-cena) antes de as duas classes serem removidas.
   - .px lê --px-y, custom property de comprimento (ex.: "-18px")
     que o JS escreve a cada frame de scroll.
   ============================================================ */

/* ------------------------------------------------------------
   0. GUARDA — prefers-reduced-motion
   Fica no topo por decisão de acessibilidade: zera toda duração
   e força visível qualquer coisa que dependa de classe do JS —
   nada pode sobrar em opacity 0 se a classe nunca chegar a ser
   trocada a tempo.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  .rev, .rev--on {
    opacity: 1 !important;
    transform: none !important;
  }

  .link, .link__foto, .link__seta, .sociais__i {
    transform: none !important;
    translate: 0 0 !important;
    scale: 1 !important;
  }

  .px { transform: none !important; }

  .capa__mote-i {
    position: static !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .capa__mote-i:not(.capa__mote-i--ativo) { display: none !important; }

  /* slideshow do hero: sem Ken Burns, sem clip-path animado — a
     troca de opacidade já fica quase instantânea pelo 0.01ms ali
     em cima; aqui só garante que nenhuma foto trava a meio-caminho
     de um efeito e que a ativa nunca some. */
  .slide__foto, .slide__i { animation: none !important; filter: none !important; }
  .slide__i { clip-path: none !important; transition: none !important; }
  .slide__i--ativo { clip-path: none !important; transition: none !important; }
  .slide__i, .slide__i--ativo { clip-path: none !important; }
}

/* ------------------------------------------------------------
   1. REVELAÇÃO — .rev / data-rev / .rev--on
   Estado inicial é o escondido; .rev--on é o estado final. O
   stagger vem de --i, escrito inline pelo HTML em cada elemento.
   ------------------------------------------------------------ */
.rev {
  transition-property: opacity, transform;
  transition-duration: var(--d-cena);
  transition-timing-function: var(--ease-saida);
  transition-delay: calc(var(--stagger) * var(--i, 0));
  will-change: opacity, transform;
}

.rev[data-rev="fade"]   { opacity: 0; }
.rev[data-rev="sobe"]   { opacity: 0; transform: translateY(var(--e-5)); }
.rev[data-rev="escala"] { opacity: 0; transform: scale(0.86); }

/* Precisa ser .rev.rev--on, e não só .rev--on: o estado escondido acima é
   .rev[data-rev="..."], que pesa classe + atributo. Um .rev--on sozinho pesa
   menos e perde na cascata — foi exatamente esse empate perdido que deixou a
   página em branco em todo navegador sem scroll-driven animation. */
.rev.rev--on {
  opacity: 1;
  transform: none;
}

/* Dois escapes para o estado escondido acima nunca virar página em branco:
   sem JS no documento (html não recebeu .com-js) e socorro por tempo
   (.rev-socorro, aplicado se o módulo de revelação não assumir em 2,5s).
   Ambos são exceção declarada, por isso o !important — precisam vencer
   tanto o estado inicial quanto qualquer transição em curso. */
html:not(.com-js) .rev,
.rev-socorro .rev {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* ------------------------------------------------------------
   2. CARDS — .link
   Hover/toque usam translate isolado de transform pra não
   disputar propriedade com a entrada em cena — .link já é .rev
   com data-rev="sobe", que anima transform na chegada. Zoom da
   foto e deslize da seta ficam nos filhos, sem esse conflito.
   ------------------------------------------------------------ */
.link {
  translate: 0 0;
  transition: translate var(--d-ui) var(--ease-suave);
}

.link__media {
  overflow: hidden; /* contém o zoom da foto dentro do card */
}

.link__foto {
  transition: transform var(--d-bloco) var(--ease-saida);
}

.link__seta {
  display: inline-block;
  transition: transform var(--d-ui) var(--ease-suave);
}

@media (hover: hover) {
  .link:hover             { translate: 0 -2px; }
  .link:hover .link__foto { transform: scale(1.06); }
  .link:hover .link__seta { transform: translateX(6px); }
}

/* navegação por teclado espelha o hover */
.link:focus-visible             { translate: 0 -2px; }
.link:focus-visible .link__foto { transform: scale(1.06); }
.link:focus-visible .link__seta { transform: translateX(6px); }

/* feedback de toque — pressionado volta a 0 */
.link:active { translate: 0 0; }

@media (hover: none) {
  .link:active             { translate: 0 -2px; }
  .link:active .link__foto { transform: scale(1.06); }
  .link:active .link__seta { transform: translateX(6px); }
}

/* ------------------------------------------------------------
   3. PARALLAX DA CAPA — .px[data-px]
   --px-y é escrita pelo JS a cada frame de scroll. Só
   translate3d, sem transition — acompanha o scroll direto,
   sem atraso somado por cima do atraso do próprio scroll.
   ------------------------------------------------------------ */
.px {
  will-change: transform;
  transform: translate3d(0, var(--px-y, 0px), 0);
}

/* ------------------------------------------------------------
   4. MOTE ROTATIVO — .capa__mote / .capa__mote-i
   Máscara em overflow:hidden. Item ativo entra de baixo com
   --ease-saida; item de saída sobe e some com --ease-entrada —
   a mesma dupla que os tokens já nomeiam pra entrada e saída de
   elemento em tela.
   ------------------------------------------------------------ */
.capa__mote {
  position: relative;
  overflow: hidden;
}

.capa__mote-i {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(100%);
  transition: transform var(--d-cena) var(--ease-saida),
              opacity   var(--d-cena) var(--ease-saida);
  will-change: transform, opacity;
}

.capa__mote-i--ativo {
  position: relative;
  opacity: 1;
  transform: translateY(0);
}

/* classe transitória que o JS pode aplicar no item de saída
   antes de soltar as duas classes — ver contrato no topo */
.capa__mote-i--saida {
  opacity: 0;
  transform: translateY(-100%);
  transition: transform var(--d-cena) var(--ease-entrada),
              opacity   var(--d-cena) var(--ease-entrada);
}

/* duração de leitura de cada frase é intervalo do JS, não deste
   arquivo — recomendação: 3200–4000ms de permanência por frase */

/* ------------------------------------------------------------
   5. ÍCONES SOCIAIS — .sociais__i
   Mesmo motivo dos cards: translate/scale isolados porque a
   entrada (.rev[data-rev="escala"]) já anima transform.
   ------------------------------------------------------------ */
.sociais__i {
  translate: 0 0;
  scale: 1;
  transition: translate var(--d-micro) var(--ease-suave),
              scale     var(--d-micro) var(--ease-suave),
              color     var(--d-micro) var(--ease-suave);
}

.sociais__i:hover,
.sociais__i:focus-visible {
  translate: 0 -3px;
  scale: 1.08;
  color: var(--c-laranja);
}

@media (hover: none) {
  .sociais__i:active {
    translate: 0 -3px;
    scale: 1.08;
    color: var(--c-laranja);
  }
}

/* ------------------------------------------------------------
   6. SLIDESHOW DO HERO — .slide__i / .slide__foto
   Crossfade em opacity, var(--d-cinema) — o mesmo token que os
   tokens já nomeiam pra "estouro tipográfico, hero". O efeito de
   entrada além do fade é um clip-path que revela de baixo pra
   cima, na mesma transição (mesma origem de disparo: a troca de
   .slide__i--ativo pelo JS, sem passo extra).

   Ken Burns roda só na foto ativa — scale 1 → 1.08 com leve
   deslocamento, direção alternando por :nth-child(odd)/(even) pra
   não virar repetição mecânica. Duração: var(--d-cinema) × 3 =
   4200ms, o mesmo INTERVALO do JS (assets/js/linkpage.js) — múltiplo
   do token de propósito, não coincidência, pra não duplicar o
   número em dois arquivos sem build entre eles.

   A troca cor/mono ganha tratamento à parte: a foto colorida entra
   "ganhando cor", saturação subindo nos primeiros 600ms — a mono já
   nasce no tom dela, não precisa de nada.
   ------------------------------------------------------------ */
/* TRANSICAO: cobertura, nao crossfade.
   A foto que entra e revelada de baixo para cima por cima da anterior.
   A anterior nao desbota: ela fica opaca embaixo e so e descartada
   (opacity 0, sem fade) DEPOIS que a nova terminou de cobrir — por isso
   a transicao de opacity tem duracao 0s e delay igual ao tempo da revelacao. */
.slide__i {
  clip-path: inset(100% 0 0 0);
  transition: opacity 0s linear var(--d-cinema);
  will-change: clip-path;
}
.slide__i--ativo {
  clip-path: inset(0 0 0 0);
  transition:
    clip-path var(--d-cinema) var(--ease-firme),
    opacity 0s linear 0s;
}

.slide__foto { will-change: transform; }

.slide__i:nth-child(odd).slide__i--ativo .slide__foto {
  animation: hero-zoom-a calc(var(--d-cinema) * 3) linear forwards;
}
.slide__i:nth-child(even).slide__i--ativo .slide__foto {
  animation: hero-zoom-b calc(var(--d-cinema) * 3) linear forwards;
}

@keyframes hero-zoom-a {
  from { transform: scale(1)    translate(0, 0); }
  to   { transform: scale(1.08) translate(-1.5%, -1%); }
}
@keyframes hero-zoom-b {
  from { transform: scale(1)    translate(0, 0); }
  to   { transform: scale(1.08) translate(1.5%, 1%); }
}

/* filtro no figure (.slide__i), não na foto — evita disputar a
   propriedade "animation" no mesmo elemento que já roda o Ken
   Burns, e o filter no pai já afeta o filho renderizado */
.slide__i[data-cor="cor"].slide__i--ativo {
  animation: hero-satura 600ms linear both;
}
@keyframes hero-satura {
  from { filter: saturate(0); }
  to   { filter: saturate(1); }
}

/* ------------------------------------------------------------
   7. UMA COISA POR VEZ
   O stagger de --i já espalha os irmãos no tempo dentro de cada
   grupo, e capa, ícones e cards têm gatilho próprio — nunca dois
   efeitos grandes disputando o mesmo instante de tela.
   ------------------------------------------------------------ */

/* ------------------------------------------------------------
   8. REVELAÇÃO NATIVA — removida em 18/08/2026
   Havia aqui um bloco @supports (animation-timeline: view()) que
   amarrava .rev ao scroll com animation-range: entry 0% cover 25%.
   No Safari do iPhone a página inteira mede pouco mais de uma tela
   e meia, então os elementos da última dobra nunca completavam o
   range: a animação travava no quadro inicial, que é opacity 0, e
   como animação vence regra normal em cascata, o .rev--on que o JS
   aplica não conseguia mais revelar nada. Resultado no aparelho:
   só a foto da capa aparecia.
   A revelação agora é responsabilidade única do IntersectionObserver
   em linkpage.js — ele revela pelo que está visível, não pelo scroll
   que ainda resta, e por isso funciona em página curta.
   ------------------------------------------------------------ */
