/* ==========================================================================
   DESTAQUE DE TEXTO PELO SCROLL — prefixo dts-
   A frase de manifesto que nasce apagada e acende unidade por unidade
   conforme a dobra passa pela janela. Escovado, reversível, preso ao scroll.

   Tokens usados:
     --fg                tinta da frase (a primitiva .display-xl já a lê)
     --accent-ink        tinta do realce, com --accent de fallback
     --display           a face do manifesto, via .display-xl
     --sec-gap           respiro da faixa, por multiplicação

   O QUE O JAVASCRIPT ESCREVE, e é só isto:
     --dts-p    na raiz, uma vez por quadro    progresso da dobra, 0 a 1
     --dts-n    na raiz, uma vez na carga      quantas unidades existem
     --dts-i    em cada unidade, na carga      o índice dela, a partir de 0

   Todo o resto é conta de CSS. A escolha está explicada no bloco da
   opacidade, e ela é o coração da peça.
   ========================================================================== */

.dts{
  /* --------------------------------------------------------------- repouso
     OPACIDADE DA FRASE APAGADA. O original da referência usa .38, e .38 NÃO
     PASSA aqui — este é o ajuste de acessibilidade que a tradução trouxe.

     Medido no tema liberta-wealth, escopo .sec-dark (--fg #f2f0ec e
     --accent #c6ceaa sobre --dark #0a0a0a), compondo a tinta contra o fundo
     na opacidade de repouso:

       opacidade | texto (--fg) | realce (--accent-ink)
       ----------|--------------|----------------------
       .38       |    3,22:1    |    2,57:1   <- o valor do original
       .42       |    3,70:1    |    2,90:1
       .46       |    4,23:1    |    3,26:1   <- o daqui
       .50       |    4,81:1    |    3,66:1
       1 (aceso) |   17,39:1    |   12,08:1

     O mínimo da WCAG para TEXTO GRANDE (medido no palco: 48,96px em peso
     700; o piso do clamp é 25px, e o limite de "texto grande" é 18,66px em
     negrito) é 3:1. O texto do original já passava raspando; o REALCE em
     accent não passava, e é justamente ele que a peça quer que se leia. Como
     a pessoa pode simplesmente parar de rolar, o estado apagado não é um
     quadro de transição: é um estado que fica na tela, e tem de fechar
     contraste sozinho.

     Quem baixar este parafuso abaixo de .42 quebra o AA da frase, e abaixo
     de .46 quebra o do realce. Ver a ficha. */
  --dts-off:.46;

  /* --------------------------------------------------- sobreposição do laço
     Quantas "fatias" de progresso cada unidade leva para ir de apagada a
     acesa. 1 = estritamente sequencial (uma acaba, a outra começa), e lê
     como interruptor. 2 = cada unidade leva o dobro da fatia e a seguinte
     começa na metade do caminho da anterior — duas acendendo ao mesmo tempo,
     que é o que faz a leitura parecer uma onda e não um contador.

     Acima de 3 as unidades acendem quase juntas e a peça vira um fade só. */
  --dts-k:2;

  /* ------------------------------------------------------ janela de cálculo
     Em % da altura da janela, medido do topo dela.
       --dts-start  onde o TOPO do bloco está quando o progresso é 0
       --dts-end    onde a BASE do bloco está quando o progresso é 1

     Por que assim, e não "a seção passando pelo meio da tela": esta conta
     tem de servir a um bloco BAIXO (uma frase de quatro linhas, ~280px) e a
     uma seção PINADA ALTA (300vh de palco com a frase grudada dentro). O
     percurso do progresso é (start - end) da janela MAIS a altura do próprio
     bloco, então ele cresce junto com a peça: a frase de quatro linhas deste
     markup acende ao longo de 648px de rolagem (medido em 1440x900, com o
     bloco em 432px de altura), e uma seção pinada de 300vh acende ao longo
     dela inteira, sem nenhum ajuste. Ver a ficha e o script.js.

     82 E 58 SAIRAM DE UMA MEDICAO, e o primeiro par tentado (76 e 34) estava
     errado por um motivo que so' o numero mostra: com a base do bloco indo
     ate' 34% da janela, a ultima linha da frase de quatro linhas (432px de
     altura, medida em 1440x900) so' fechava com o topo do bloco em -126px --
     a primeira linha ja' tinha saido pela borda de cima quando a ultima
     acendeu, e a frase inteira acesa nunca chegava a existir na tela.

     Com 82 e 58 o progresso fecha com o bloco em 90..522 da janela: inteiro
     dentro, na metade de cima. Medido no mesmo palco: com o bloco centrado
     verticalmente o progresso esta' em 0,78 e a ultima linha em 70% do
     caminho -- ainda ha o que ver acendendo quando a frase ja' esta' toda na
     tela, que e' exatamente o efeito que se quer. */
  --dts-start:82;
  --dts-end:58;

  /* Parafusos da primitiva .display-xl do core (fallback dentro do var(),
     por isso entram aqui no ancestral e não na regra do .dts-txt).
     A entrelinha é MUITO maior que o .95 padrão dela: lá o título tem uma ou
     duas palavras; aqui são quatro frases inteiras, e apertar a entrelinha
     cola uma linha na outra justamente onde a peça pede que o olho ande
     linha a linha. */
  --display-xl:clamp(25px,3.4vw,50px);
  --display-xl-lh:1.26;

  /* FAIXA, NÃO DOBRA — quando a peça for colada sozinha numa seção só dela.
     Dentro de uma dobra que já tem .sec-pad isto não faz nada, porque é
     margem e não padding: o respiro do palco continua sendo o do palco. */
  margin-block:calc(var(--sec-gap) * .12);
}

/* O desenho da frase é a primitiva .display-xl do core. Sobra aqui só o que
   é desta peça: a medida de leitura. Manifesto em linha longa demais deixa
   de ser peça gráfica e vira parágrafo grande. */
.dts-txt{max-width:22ch}

/* ---------------------------------------------------------------- unidades */

/* A linha é uma CAIXA, não um trecho inline com <br> depois: assim a quebra
   está na estrutura, o reveal tem em que pegar e a opacidade se aplica a uma
   caixa inteira sem herdar espaço de linha do vizinho. */
.dts-ln{display:block}

/* A palavra é inline-block pela mesma razão que a .w do core é: para não se
   partir no meio quando a linha vira. Não é a .w — a .w é do core e
   componente não a estiliza (contrato §5). */
.dts-w{display:inline-block}

/* ---------------------------------------------------------------- a conta
   O CORAÇÃO DA PEÇA, e o motivo de o script escrever UMA propriedade por
   quadro em vez de uma opacidade por unidade.

   Cada unidade lê o progresso global (--dts-p) e o próprio índice (--dts-i)
   e resolve sozinha quanto já acendeu:

     total = n - 1 + k          fatias de progresso que o laço inteiro ocupa
     local = (p * total - i) / k    o quanto ESTA unidade já andou, 0 a 1
     opacidade = off + (1 - off) * local,  presa entre off e 1

   O clamp() faz as duas pontas: abaixo de zero fica em `off`, acima de um
   fica em 1. Nenhum Math.min no JavaScript, nenhuma escrita por unidade.

   SE O SCRIPT NÃO RODAR, --dts-i e --dts-n não existem, o var() sem fallback
   torna a declaração inválida no tempo de valor computado, e `opacity` — que
   não é herdada — volta ao valor inicial, 1. Ou seja: sem script a frase
   aparece ACESA E INTEIRA, que é exatamente o que se quer. Isto foi medido,
   não deduzido: apagando --dts-i de uma unidade com a página carregada, o
   computado dela vai para 1. As duas media queries abaixo declaram o mesmo
   caso de propósito, para não depender de um efeito colateral da cascata.

   SEM transition, e é decisão: o valor É a posição do scroll. Qualquer
   amortecimento transformaria "escovado" em "atrasado", e numa rolagem de
   volta o rastro ficaria para trás da mão. A suavidade vem do --dts-k, que
   sobrepõe as unidades, não de uma curva no tempo.

   SEM will-change também: a propriedade muda por recálculo de estilo, não
   por animação de compositor, e reservar uma camada por palavra custaria
   memória de vídeo para não acelerar nada. */
.dts-ln,
.dts-w{
  opacity:clamp(
    var(--dts-off),
    calc(
      var(--dts-off) +
      (1 - var(--dts-off)) *
      (var(--dts-p) * (var(--dts-n) - 1 + var(--dts-k)) - var(--dts-i)) / var(--dts-k)
    ),
    1
  );
}

/* Colada à regra que ela desliga, como manda o §6.6. Com movimento reduzido
   o script nem assina o laço de rolagem (ver script.js) e --dts-p nunca
   nasce; esta linha é a que garante que a frase fique acesa por escrito, e
   não por acidente de cascata. */
@media(prefers-reduced-motion:reduce){
  .dts-ln,
  .dts-w{opacity:1}
}

/* Mesma garantia para quem está sem JavaScript — bloqueador, erro de rede,
   script desligado. O conteúdo inteiro está no HTML e tem de ser legível.
   É a mesma consulta que o core/motion.css usa para devolver [data-rv]. */
@media (scripting: none){
  .dts-ln,
  .dts-w{opacity:1}
}

/* ---------------------------------------------------------------- realce */
/* Elemento descendente do próprio prefixo, em conteúdo de prosa — o caso
   permitido pelo §6.3. O autor do texto escreve <em> onde quiser dentro da
   frase, sem pedir uma classe a ninguém.

   A TINTA É --accent-ink, NUNCA --accent (§3): em escopo escuro os dois são
   o mesmo valor, mas numa .sec-paper o accent puro dá 1.36:1 com o sage da
   Liberta sobre o creme. O fallback mantém de pé quem colar a frase fora de
   um escopo de tom. */
.dts-txt em{
  font-style:italic;
  color:var(--accent-ink,var(--accent));
}

/* ---------------------------------------------------------------- mobile */
/* A medida de leitura sobe em tela estreita: 22ch num corpo de 25px já é
   mais largo que a coluna, e o teto acabaria cortando a frase em mais linhas
   do que o autor escreveu — o que desmancharia a contagem de unidades que ele
   calibrou. Soltar o teto devolve a quebra ao <span> de cada linha. */
@media(max-width:640px){
  .dts-txt{max-width:none}
  .dts{--display-xl-lh:1.3}
}
