/* ==========================================================================
   ESTEIRA DUPLA DE IMAGENS — prefixo flux-
   Duas fileiras de fotos paisagem atravessando a tela em sentidos opostos,
   com uma frase centrada entre elas. Sem JS as fileiras andam por animação
   de CSS; com JS o script assume o movimento e acrescenta a reação à
   rolagem.

   Tokens usados:
     --dark-rgb        véu em gradiente sob a legenda, dentro da foto
     --ease            curva única do projeto — transições de inclinação
     --light           texto e contorno da pílula sobre a foto (ilha escura)
     --radius-media    canto da foto
     --rule            fundo do quadro enquanto a foto não pintou

   ILHA ESCURA. Tudo que está sobre a foto lê --light, e não --fg: assim a
   mesma dobra roda numa seção .sec-paper sem virar texto escuro sobre véu
   escuro. O que está fora das fotos (olho, título, apoio) segue o escopo de
   tom da seção, como manda o §3 do contrato.

   OS DOIS PARAFUSOS DE VELOCIDADE SÃO O MESMO EM UNIDADES DIFERENTES.
   --flux-dur é a volta completa da animação de CSS (fallback sem JS);
   --flux-speed é a velocidade em px/s que o script usa. A conversão é
   dur = largura do conjunto ÷ speed. Medido a 1440px de janela: um conjunto
   mede 2 270px, logo 2270 / 40 = 56,7s ≈ o padrão de 56s. Mexeu num, mexa
   no outro — senão o fallback anda num ritmo e o script noutro.

   E ELES NÃO PODEM CASAR EM TODA LARGURA. Duração fixa significa velocidade
   variável: em 390px o conjunto mede 1 356px e a mesma animação de 56s anda
   a 24px/s, 40% do ritmo do desktop. O script, que conta em px/s, anda igual
   em qualquer tela. É a principal razão de ele assumir.
   ========================================================================== */

.flux{
  /* ---- Forma ---- */
  --flux-card:clamp(240px,30vw,440px);   /* largura da foto */
  --flux-gap:clamp(14px,1.6vw,24px);     /* vão entre uma foto e a próxima */
  --flux-space:clamp(30px,5vh,64px);     /* respiro entre esteira e texto */
  --flux-veil:38%;                       /* altura do véu, em fração da foto */

  /* ---- Ritmo ---- */
  --flux-dur:56s;      /* volta completa SEM JavaScript (ver cabeçalho) */
  --flux-speed:40;     /* velocidade de cruzeiro COM JavaScript, em px/s.
                          0 = esteiras paradas, e aí nada mais anda: o teto
                          do impulso é múltiplo desta base. */

  /* ---- Reação à rolagem (lidas pelo script) ---- */
  --flux-react:.35;    /* fração da velocidade da página que vira impulso */
  --flux-boost:6;      /* teto do impulso, em múltiplos de --flux-speed */
  --flux-skew-max:6deg;/* inclinação máxima da foto, no teto do impulso */

  /* Escrita pelo script a cada quadro em que muda. Declarada aqui para o
     componente funcionar colado sem o script.js: sem JS fica 0deg e as
     fotos ficam retas. */
  --flux-skew:0deg;

  display:flex;
  flex-direction:column;
  gap:var(--flux-space);
}

/* ---------------------------------------------------------------- miolo de texto */
/* Único bloco com .wrap. Centrado no eixo horizontal porque as duas esteiras
   já ocupam a página inteira: um texto alinhado à esquerda entre duas
   fileiras simétricas puxa a dobra para um canto sem motivo.
   Não usa .sec-head do core porque .sec-head não é .wrap — aqui os dois
   papéis (coluna da página e cabeçalho centrado) caem no mesmo elemento. */
.flux-body{text-align:center}

/* h2.sec-title do core é (0,1,1); .flux-title sozinha perderia. O seletor
   duplo é o que garante a centralização qualquer que seja a ordem em que as
   folhas foram coladas (§6.4). */
.flux .flux-title{margin-inline:auto}
.flux .flux-lead{margin-inline:auto;max-width:56ch}

/* ---------------------------------------------------------------- esteira */
/* A máscara é o que faz a fileira "atravessar" em vez de "começar e acabar":
   sem ela o recorte corta a foto no meio com borda dura e o olho lê que
   alguma coisa quebrou. 6% de cada lado — a 1440px, 86px de dissolvência. */
.flux-rail{
  overflow:hidden;
  /* Sentido do trilho, lido pelas fotos na conta da inclinação. O valor
     numérico mora no data-flux-rail para haver uma fonte só: o script lê o
     mesmo atributo. */
  --flux-dir:-1;
  --flux-dir-back:1;
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
}
.flux-rail[data-flux-rail="1"]{--flux-dir:1;--flux-dir-back:-1}

.flux-track{
  display:flex;
  width:max-content;
  animation:fluxRun var(--flux-dur) linear infinite;
  /* Só o elemento que anda ganha camada própria. */
  will-change:transform;
}
/* Movimento reduzido: as duas esteiras param onde estão, no começo da fila.
   O script nem assume nesse caso — não põe .is-driven e não escreve
   transform —, então esta regra é a única coisa que decide. Daí a ordem
   editorial da ficha: as cinco primeiras fotos de cada esteira têm de ser
   as melhores, porque podem ser as únicas que alguém vê. */
@media(prefers-reduced-motion:reduce){
  .flux-track{animation-name:none}
}

/* O trilho anda -50%, que é a largura EXATA de um conjunto — e só é exata
   porque o vão entre conjuntos é padding do próprio conjunto, não gap do
   trilho. Com gap no trilho a largura total seria 2×conjunto + 1 vão, -50%
   cairia no lugar errado e o laço daria um solavanco por volta. */
@keyframes fluxRun{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
.flux-rail[data-flux-rail="1"] .flux-track{animation-direction:reverse}

/* Quando o script assume, a animação sai de cena e quem escreve o transform
   é ele. animation-name e não a abreviação animation: a abreviação também
   zeraria o animation-direction da regra acima, e o dia em que alguém tirar
   o .is-driven a esteira de baixo voltaria andando para o lado errado. */
.flux.is-driven .flux-track{animation-name:none}

.flux-set{
  display:flex;
  gap:var(--flux-gap);
  /* Mantém o vão na emenda entre as duas cópias — ver o comentário do
     keyframe. */
  padding-inline-end:var(--flux-gap);
}

.flux-item{flex:0 0 var(--flux-card);min-width:0}

/* ---------------------------------------------------------------- foto */
/* A INCLINAÇÃO É DO QUADRO INTEIRO, não da imagem dentro dele. Inclinar só
   a <img> a descolaria das bordas do quadro e abriria fresta do fundo nos
   dois cantos; inclinando o quadro, foto, véu e legenda viajam juntos.

   Ela não abre nem fecha o vão entre fotos vizinhas: skewX desloca cada
   ponto por y·tanθ, e como toda a fileira tem a mesma altura e o mesmo
   transform-origin, duas fotos vizinhas se deslocam pelo mesmo tanto em
   cada altura. Medido a 6deg: vão constante em 22,00px do topo à base.

   A transição é o que faz a volta ser macia: o script reescreve --flux-skew
   quadro a quadro enquanto o impulso decai, e sem ela a foto endireitaria
   em degraus. .3s é curto o bastante para a subida ainda parecer resposta,
   e não atraso. */
.flux-card{
  position:relative;
  aspect-ratio:16/10;
  overflow:hidden;
  border-radius:var(--radius-media);
  background:var(--rule);
  margin:0;
  transform:skewX(calc(var(--flux-skew) * var(--flux-dir)));
  transition:transform .3s var(--ease);
}
/* Sem movimento reduzido não há inclinação para animar — o script não
   escreve --flux-skew. A transição some junto para não sobrar máquina
   ligada sem nada a transicionar. */
@media(prefers-reduced-motion:reduce){
  .flux-card{transition:none}
}

.flux-img{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  object-position:50% 50%;
}

/* VÉU E LEGENDA SÃO DOIS ELEMENTOS, e não um só com padding — a mesma
   separação do conteudo/pilares-texto-na-foto, e por um motivo medido: a
   máscara vale para o elemento INTEIRO, filhos incluídos. Com a pílula
   dentro do véu, o topo dela caía junto com o degradê (60% de opacidade em
   390px, onde o véu é baixo) e a legenda ficava meio apagada. Separados, a
   máscara amacia só o véu e o texto fica cheio.

   A ALTURA É FRAÇÃO DA FOTO, não padding em px. Com padding fixo, o mesmo
   véu que ocupa 35% de uma foto de 270px ocupa 52% de uma de 156px — medido
   em 390px, metade da imagem sumia sob o degradê. Em fração, a proporção é
   a mesma em qualquer largura.

   O desfoque é SEMPRE mascarado (contrato §6): sem a máscara, backdrop-filter
   em caixa reta desenha uma linha dura contra a parte nítida da foto e a
   faixa lê "chapada". Blur de 3px, o mesmo do midia/galeria-scroll-horizontal.
   Medido nesta dobra, com 20 véus e as fotos andando: 4,20ms de mediana de
   quadro com e sem o desfoque — ele não custa na linha principal, porque
   quem o desenha é o compositor. */
.flux-veil{
  position:absolute;left:0;right:0;bottom:0;z-index:1;
  height:var(--flux-veil);
  pointer-events:none;
  background:linear-gradient(to top,
    rgba(var(--dark-rgb),.9) 0%,
    rgba(var(--dark-rgb),.5) 48%,
    transparent 100%);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  mask-image:linear-gradient(to top,#000 0%,rgba(0,0,0,.9) 44%,transparent 100%);
  -webkit-mask-image:linear-gradient(to top,#000 0%,rgba(0,0,0,.9) 44%,transparent 100%);
}

.flux-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:0 16px 14px;
  margin:0;
  pointer-events:none;
}

/* Reaproveita a .pill do core — forma, respiro e tracking vêm de lá; só o
   tom muda, porque a pílula está sobre foto. Seletor duplo de propósito:
   .pill e .flux-tag têm a mesma especificidade, e o §6.4 proíbe depender de
   qual folha carregou primeiro.

   A contra-inclinação é o que mantém a legenda em pé enquanto a foto
   inclina. Sem ela o rótulo tomba junto e a dobra passa a parecer quebrada,
   e não veloz. A origem é o canto inferior esquerdo — o mesmo ponto em que
   a pílula está ancorada —, então ela endireita sem sair do lugar. */
.flux-card .flux-tag{
  display:inline-block;
  max-width:100%;
  color:var(--light);
  border-color:color-mix(in srgb,var(--light) 32%,transparent);
  transform:skewX(calc(var(--flux-skew) * var(--flux-dir-back)));
  transform-origin:0 100%;
  transition:transform .3s var(--ease);
  /* Uma linha, sempre: pílula de duas linhas perde a forma de pílula. O par
     overflow + ellipsis é a rede — passou do que cabe, a legenda corta com
     reticências em vez de ser decepada pelo recorte da foto. Medido em
     390px: cabem 24 caracteres na pílula, e é esse o limite editorial da
     ficha. Aos 30, ela vazava 13,1px para fora do quadro. */
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
@media(prefers-reduced-motion:reduce){
  .flux-card .flux-tag{transition:none}
}

/* ---------------------------------------------------------------- mobile */
/* A reação à rolagem CONTINUA no toque — é lá que ela fica mais bonita,
   porque o gesto de arremesso produz velocidades que o mouse não alcança.
   O que muda é o ganho: --flux-react cai de .35 para .2, senão o mesmo
   arremesso passa do teto do impulso a cada gesto e a esteira vira borrão.
   O teto da inclinação também baixa: em foto pequena, 6deg é proporcional-
   mente muito mais tombo do que em foto de 440px. */
@media(max-width:760px){
  .flux{
    --flux-card:min(64vw,300px);
    --flux-gap:12px;
    --flux-space:clamp(24px,4vh,40px);
    --flux-react:.2;
    --flux-skew-max:4deg;
  }
  .flux-cap{padding:0 12px 11px}
}
