/* ==========================================================================
   COLUNAS EM CASCATA — prefixo fall-
   Quatro esteiras verticais de foto, inclinadas e ampliadas até sangrar as
   bordas, com as pontas desvanecendo em máscara. Por cima, parado no centro,
   o bloco de texto da dobra.

   Tokens LIDOS:
     --dark-rgb          o véu do miolo e o selo das pontas (opacidade sobre
                         a superfície escura do projeto, nunca cor crua)
     --rule              tinta da caixa da foto enquanto ela não chega
     --radius-media      canto da foto

   Tokens ESCRITOS (parafusos de primitiva do core, ver core/base.css):
     --display-xl        corpo do título, alimentado aqui por --fall-title
     --display-xl-lh     entrelinha dele
     --head-max          largura do .sec-head

   A cor do texto não aparece neste arquivo: vem do escopo de tom da seção
   pelas classes do core (.eyebrow, .display-xl, .sec-lead, .btn). A coluna
   também não: é o .wrap, e ele não é refeito aqui (contrato §4).

   SEM JavaScript. O laço é CSS puro: cada trilho anda -50% da própria
   altura, que é a altura exata de um dos dois conjuntos idênticos.

   TRÊS DECISÕES QUE EXPLICAM O ARQUIVO INTEIRO:

   1. A máscara mora no .fall-board e o transform no .fall-grid, que é filho
      dele. Máscara é aplicada no espaço LOCAL do elemento: no mesmo elemento
      que o rotate, ela gira junto e o desvanecimento entra torto na tela.

   2. Só transform anima. A opacidade da foto, o véu e a máscara são estados
      fixos; o que se move é um translateY por coluna, em quatro camadas
      compostas. Nenhum filter, nenhum blur e nenhuma sombra em laço.

   3. Nada aqui sobrescreve o escopo de tom. O texto lê --fg herdado da
      seção; o véu é opacidade sobre --dark-rgb. Trocar .sec-dark por
      .sec-deep funciona sem tocar no componente — .sec-paper não (ver ficha).
   ========================================================================== */

.fall{
  /* Altura do palco. Não é uma dobra de altura de conteúdo: é um quadro, e
     o texto é centrado dentro dele. 88vh e não 100vh de propósito — a fatia
     da dobra seguinte aparecendo embaixo é o que diz "a página continua". */
  --fall-h:clamp(560px,88vh,900px);

  --fall-cols:4;                    /* colunas da parede (3 ≤900px, 2 ≤560px) */
  --fall-gap:clamp(12px,1.4vw,22px);/* vão entre colunas E entre fotos */

  /* Inclinação e ampliação andam juntas: girar sem ampliar descobre os
     cantos. A conta que liga as duas está na ficha; em resumo, para a
     parede cobrir a largura da tela é preciso
        zoom >= cos(tilt) + (altura/largura) * sen(tilt).
     1.16 cobre com folga em qualquer proporção de desktop; abaixo de 560px
     a tela fica alta e estreita, a conta sobe, e por isso lá o tilt cai
     para -4deg e o zoom sobe para 1.24. */
  --fall-tilt:-6deg;
  --fall-zoom:1.16;

  /* Opacidade da foto em repouso. É o primeiro parafuso a mexer se o texto
     ficar difícil de ler sobre uma parede clara — antes de engrossar o véu,
     que apaga a parede inteira. */
  --fall-dim:.55;

  /* Corpo da frase. Alimenta os dois parafusos da primitiva .display-xl do
     core (ver core/base.css). A entrelinha é 1.08, não o .95 padrão: aquele
     serve a título de uma ou duas palavras, e aqui são duas linhas de frase
     inteira, com ascendente e descendente para não colidirem. */
  --fall-title:clamp(28px,4.6vw,62px);
  --display-xl:var(--fall-title);
  --display-xl-lh:1.08;

  position:relative;
  /* Quem segura a ampliação é este overflow. Sem ele, o .fall-grid ampliado
     vazaria para fora da seção e a página ganharia barra horizontal. */
  overflow:hidden;

  /* min-height e não height: o palco tem a altura do quadro, mas se a frase
     crescer (tradução mais longa, corpo maior no tema) a seção cresce junto
     em vez de cortar o texto no overflow acima. */
  min-height:var(--fall-h);
  display:grid;
  place-items:center;
}

/* ---------------------------------------------------------------- parede */
/* O board não gira: ele existe para carregar a máscara das pontas e para
   recortar a parede no tamanho da seção. A máscara fica aqui, e não na
   própria .fall, porque a seção também pinta o FUNDO (--bg, vindo do core):
   mascarada, ela ficaria transparente nas pontas e deixaria passar o corpo
   da página — invisível num projeto todo escuro, um vinco claro no primeiro
   projeto que não for.

   mask-repeat:no-repeat é obrigatório. O padrão é repeat, e aí o que
   ultrapassa a caixa (a parede ampliada ultrapassa) receberia o gradiente
   ladrilhado, com faixas de desvanecimento no meio da foto. */
.fall-board{
  position:absolute;inset:0;z-index:0;
  mask-image:linear-gradient(to bottom,transparent 0,#000 14%,#000 86%,transparent 100%);
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 14%,#000 86%,transparent 100%);
  mask-repeat:no-repeat;
  -webkit-mask-repeat:no-repeat;
}

/* O que gira e amplia. Uma linha de grid, --fall-cols colunas iguais.

   grid-template-rows:100% é obrigatório e não é decoração. Linha implícita é
   auto, e auto em grid dimensiona pelo CONTEÚDO: a linha nasceria com a
   altura do trilho (3.797px medidos a 1440), a coluna herdaria essa altura e
   a caixa da parede deixaria de ter relação com a caixa da seção. Continua
   funcionando por acidente — o corte vem da máscara — mas qualquer medida
   feita depois (a minha inclusive) passa a mentir. Com 100% a coluna é a
   janela de --fall-h, e o que passa por ela é o trilho. */
.fall-grid{
  position:absolute;inset:0;
  display:grid;
  grid-template-columns:repeat(var(--fall-cols),1fr);
  grid-template-rows:100%;
  gap:var(--fall-gap);
  transform:rotate(var(--fall-tilt,-6deg)) scale(var(--fall-zoom,1.16));
}

/* A coluna é só a caixa: quem transborda é o trilho, e o corte vem do
   board acima. Sem overflow próprio aqui — seriam mais quatro contextos de
   composição sem nada a recortar que a máscara já não recorte. */
.fall-col{min-width:0}

/* O QUE ANDA. Uma volta inteira é a altura de UM conjunto, e o trilho tem
   dois — daí o -50%. O trilho não pode ganhar gap: com gap g entre os dois
   conjuntos, a altura vira 2S+g e -50% passa a ser S+g/2, meio vão fora do
   lugar a cada volta.

   O delay é NEGATIVO e diferente por coluna (no style do .fall-col). Sem
   ele as quatro colunas começam alinhadas no quadro zero e a parede abre
   com uma fileira de topos na mesma linha, que é justamente o que a
   inclinação existe para desmanchar. */
.fall-track{
  display:flex;flex-direction:column;
  will-change:transform;
  animation:fallRun var(--fall-dur,52s) linear infinite;
  animation-delay:var(--fall-delay,0s);
}
/* Colunas vizinhas em sentidos opostos. reverse e não um segundo keyframe:
   os dois extremos do laço são o mesmo quadro, então a mesma animação
   servida de trás para frente fecha igual. */
.fall-col--down .fall-track{animation-direction:reverse}

@keyframes fallRun{
  from{transform:translateY(0)}
  to{transform:translateY(-50%)}
}

/* A parede congela onde nasceu, e o texto lê igual — ele nunca dependeu do
   movimento. Cada coluna passa a mostrar o começo do seu primeiro conjunto:
   por isso a ficha manda pôr as melhores fotos nas quatro primeiras. */
@media(prefers-reduced-motion:reduce){
  .fall-track{animation:none}
}

/* O padding embaixo do conjunto é a EMENDA, não sobra: o gap separa as
   fotos dentro de um conjunto e não separa a última foto de um conjunto da
   primeira do seguinte. Tem de valer exatamente --fall-gap; qualquer outro
   valor troca o encontro sem vão por um vão diferente dos demais, uma vez
   por volta, sempre no mesmo ponto. */
.fall-set{
  display:flex;flex-direction:column;
  gap:var(--fall-gap);
  padding-block-end:var(--fall-gap);
}

.fall-img{
  width:100%;
  aspect-ratio:3/4;
  object-fit:cover;
  border-radius:var(--radius-media);
  /* Opacidade na FOTO, não no board. No board seria uma propriedade só,
     mas um grupo com opacidade obriga o navegador a compor a subárvore
     inteira a cada quadro — e a subárvore inteira é o que está animando. */
  opacity:var(--fall-dim);
  /* Caixa da foto enquanto ela não chega: sem isso a parede pisca em
     retângulos do fundo da seção durante o carregamento. */
  background:var(--rule);
}

/* ---------------------------------------------------------------- véu */
/* Duas camadas. A elipse escurece o miolo, que é onde o texto mora, e solta
   as bordas para a parede continuar visível — véu chapado apagaria a foto
   toda e sobraria uma dobra escura com texto no meio. O gradiente vertical
   é fraco e sela as pontas contra as dobras vizinhas, como o .hero-fade.
   Sem backdrop-filter: seria desfoque sobre a área inteira da tela, com
   quatro esteiras se movendo por baixo. */
.fall-veil{
  position:absolute;inset:0;z-index:1;
  pointer-events:none;
  background:
    radial-gradient(68% 74% at 50% 50%,
      rgba(var(--dark-rgb),.82) 0%,
      rgba(var(--dark-rgb),.66) 34%,
      rgba(var(--dark-rgb),.24) 68%,
      rgba(var(--dark-rgb),0) 100%),
    linear-gradient(to bottom,
      rgba(var(--dark-rgb),.46) 0%,
      rgba(var(--dark-rgb),0) 30%,
      rgba(var(--dark-rgb),0) 70%,
      rgba(var(--dark-rgb),.46) 100%);
}

/* ---------------------------------------------------------------- texto */
/* O .wrap continua sendo a única coluna (contrato §4). O que esta classe
   faz é só pôr o bloco acima do véu — a centralização vem do grid da seção. */
.fall-body{position:relative;z-index:2}

/* Cabeçalho centrado é a primitiva .sec-head do core; aqui só a largura.
   720px em vez dos 760 padrão para a frase quebrar onde o <br> manda,
   também nas telas médias. */
.fall-head{--head-max:720px}

.fall-title{margin-top:clamp(14px,2vh,22px)}
.fall-cta{margin-top:clamp(24px,4vh,34px)}

/* ---------------------------------------------------------------- mobile */
/* A quarta coluna sai de cena em vez de espremer: quatro colunas em 900px
   dão foto de 210px, e a 3/4 isso é um selo, não uma imagem. O display:none
   é obrigatório junto com --fall-cols — o grid manda o filho que sobra para
   uma segunda linha, e a parede viraria duas fileiras. */
@media(max-width:900px){
  .fall{--fall-cols:3}
  .fall-col:nth-child(4){display:none}
}

/* Tela alta e estreita: a conta do zoom sobe (a diagonal da tela pesa mais)
   e a inclinação tem de baixar, senão os cantos descobrem. -4deg pede 1.13
   em 390x742; 1.24 cobre também os aparelhos 9:19.5 e sobra margem para a
   variação de tela cheia. */
@media(max-width:560px){
  .fall{
    --fall-cols:2;
    --fall-tilt:-4deg;
    --fall-zoom:1.24;
    --fall-title:clamp(24px,6.6vw,30px);
  }
  .fall-col:nth-child(n+3){display:none}
}
