/* ════════════════════════════════════════════════════════════════════════════
   SOMA · soma-premium.css — o acabamento

   Três coisas, e nenhuma delas inventa componente novo: o botão que já existe
   ganha luz, o título que já existe ganha entrada, e o link que já existe ganha
   um traço que se desenha. É camada de ACABAMENTO sobre o desenho pronto.

   POR QUE ARQUIVO PRÓPRIO (Nível 3)
   Isto vale para a landing e para as onze páginas comerciais. Enfiar em
   `styles.css` seria mexer no global que veste também a plataforma logada, onde
   a tela é ferramenta de trabalho e brilho é ruído. Aqui é aditivo, com prefixo
   próprio, e sai de cena removendo uma linha de `<link>`.

   O QUE NÃO ESTÁ AQUI
   Nada que anime `width`, `height`, `top`, `left` ou `box-shadow` em laço.
   Só `transform`, `opacity`, `clip-path`, `filter` e propriedades registradas
   por `@property` — que o compositor interpola sem repintar.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── A propriedade registrada ────────────────────────────────────────────────
   Sem `@property`, um ângulo dentro de `conic-gradient` é só uma string: o
   navegador não sabe interpolar entre `0deg` e `360deg` e a animação salta.
   Declarado com sintaxe `<angle>`, ele vira número de verdade e o giro fica
   contínuo. É o que separa o brilho que gira do brilho que pisca.

   Técnica trazida do `shiny-call-to-action-button` do repositório de webdesign
   (Ryan Mulligan, MIT), reescrita na chave da casa: teal em vez de azul, uma
   volta em 4,8 s em vez de 3, e sem a trama de pontos — sobre navy ela vira
   sujeira. */
@property --soma-giro {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* ── A RÉGUA DO MOVIMENTO ────────────────────────────────────────────────────
   Medido nos três arquivos de arte: 53 durações distintas — 13 na maquete, 10
   aqui, 30 na home. Isso não é um sistema, é acúmulo: cada peça foi afinada
   sozinha, e 0,28 · 0,30 · 0,32 são a MESMA intenção escrita de três jeitos. O
   olho não lê três velocidades ali; lê uma só, mal calibrada. Somadas, elas
   tiram do conjunto a coisa mais valiosa que um movimento pode ter: um tempo
   RECONHECÍVEL.

   Quatro tempos e duas curvas dão conta de tudo que a área comercial faz.

   MORA AQUI, e não em `page-home.css`, porque este arquivo é o que as DOZE
   páginas comerciais carregam — a home só alcança duas. Um token consumido em
   página que não o define não vira valor: vira declaração inválida, e a
   transição some. Definição num lugar só, consumo em todos.

   DURAÇÃO é a assinatura do gesto; ATRASO é o ritmo entre gestos. O
   escalonamento continua vivo, mas no `delay`, que é o lugar dele. Variar a
   duração faz o gesto parecer inconstante em vez de ritmado. */
:root {
  --m-rapido: .24s;   /* resposta ao ponteiro: hover, foco, seta */
  --m-medio:  .42s;   /* mudança de estado: acender, abrir, trocar */
  --m-lento:  .72s;   /* entrada de peça: card, linha, foto */
  --m-cena:   1.05s;  /* coreografia: lâmina, clarão, símbolo */

  /* Duas curvas, e cada uma diz uma coisa. A de ENTRADA sai rápido e assenta
     devagar — é a curva de uma câmera que para. A de SAÍDA faz o contrário:
     hesita e vai embora — é o que faz algo parecer que decidiu sair, em vez de
     ter sido desligado. */
  --m-entra: cubic-bezier(.16, .84, .26, 1);
  --m-sai:   cubic-bezier(.55, .06, .25, 1);
}

@keyframes soma-anel-gira { to { --soma-giro: 360deg; } }

/* ══ 0 · O CAMPO — UM FUNDO SÓ PARA AS DOZE PÁGINAS ═════════════════════════
   Este bloco veio de `page-home.css`, onde nasceu servindo a landing e o
   contato. A razão que o prendia lá — "carregado por exatamente duas páginas" —
   deixou de valer no momento em que o fundo passou a ser o mesmo em toda a área
   comercial. Ele sobe para cá pelo mesmo argumento da régua do movimento acima:
   este é o arquivo que as DOZE páginas carregam, e é o último `<link>` de todas
   elas. Definição num lugar só, consumo em todos.

   ── O QUE O CAMPO É ─────────────────────────────────────────────────────────
   Um navy COM LUZ: fundo na borda, aceso no meio. `--d-piso` é a cor mais
   funda, a dos cantos; `--d-campo` é o azul que a pessoa lê como "a cor da
   página". Um valor único daria ou preto chapado ou azul lavado — é a distância
   entre os dois que faz o campo parecer magnético.

   ── POR QUE ELE É `fixed`, E NÃO FUNDO DE `body` ────────────────────────────
   Fundo de `body` rola com o documento: as poças ficam paradas numa altura do
   PAPEL e passam por você enquanto desce. Onde uma poça acabava e a seguinte não
   tinha começado, o tom mudava igual da esquerda à direita — a assinatura de uma
   emenda. Do tamanho da JANELA, o campo não rola: o que rola é o conteúdo, por
   cima. Não existe mais "onde uma seção acaba e a outra começa" para o fundo,
   porque o fundo é sempre o mesmo quadro. Emenda passa a ser impossível por
   construção, e não por ajuste fino.

   É também o que o faz ler como MAGNÉTICO: a luz fica com você em vez de ficar
   para trás. Você desce a página e ela continua acesa no mesmo lugar.

   ── A ORDEM ─────────────────────────────────────────────────────────────────
   canvas do `html` → campo (`-2`) → grão (`-1`) → conteúdo. O `body` não pinta:
   fundo próprio opaco ficaria NA FRENTE de um filho com z-index negativo, e o
   campo existiria sem nunca ser visto.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  --d-piso:  #030A16;
  --d-campo: #071A30;
}
html { background-color: var(--d-piso); }
body { background-color: transparent; }

body::before {
  background:
    /* a poça grande, alta e à esquerda: é ela que dá o corpo azul */
    radial-gradient(120% 86% at 18% 8%,
      color-mix(in srgb, var(--c-blue) 46%, transparent) 0%,
      color-mix(in srgb, var(--c-blue) 16%, transparent) 38%,
      transparent 76%),
    /* o realce teal — a luz da casa, baixa e larga, entrando pela direita */
    radial-gradient(96% 70% at 88% 62%,
      color-mix(in srgb, var(--c-teal) 22%, transparent) 0%,
      color-mix(in srgb, var(--c-teal-d) 9%, transparent) 42%,
      transparent 78%),
    /* o violeta, quase invisível, só para o azul não ficar químico */
    radial-gradient(80% 60% at 44% 96%,
      color-mix(in srgb, var(--c-violet) 12%, transparent) 0%,
      transparent 70%),
    /* e o corpo do navy por baixo de tudo */
    linear-gradient(168deg, var(--d-campo) 0%, var(--d-piso) 62%, #020711 100%);
  content: '';
  inset: -12%;                 /* folga para a deriva não descobrir a borda */
  pointer-events: none;
  position: fixed;
  z-index: -2;
  /* A DERIVA. Trinta e quatro segundos para ir e voltar, em `transform` puro —
     composição na GPU, zero repintura. É o que separa "gradiente pintado" de
     "campo vivo": o olho não vê o movimento, mas percebe que a superfície
     respira. Sem isso o fundo é bonito e morto. */
  animation: campo-deriva 34s cubic-bezier(.45, 0, .55, 1) infinite alternate;
  will-change: transform;
}
@keyframes campo-deriva {
  from { transform: translate3d(-1.6%, -1.1%, 0) scale(1.00); }
  to   { transform: translate3d( 1.6%,  1.4%, 0) scale(1.06); }
}

/* O GRÃO. Ruído aditivo em modo normal, fixo por cima do campo. Degradê grande
   em tela grande mostra BANDAS — degraus de um valor de 8 bits para o outro, e
   em navy escuro elas aparecem como listas. Aditivo não pergunta quanto o fundo
   tem: a autoridade é a mesma no pé e no topo, que é o que `overlay` não
   consegue fazer sobre quase-preto.

   `color-interpolation-filters='sRGB'` é obrigatório: o padrão de filtro SVG é
   linearRGB, e nele os mesmos coeficientes entregam outro ruído. `numOctaves=1`
   e não 3: uma oitava dá grão fino de um pixel, que é o que ditera; três somam
   harmônicos de baixa frequência — nuvem, não grão. */
body::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='r' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='1' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='.07 0 0 0 -.0135 .46 0 0 0 -.09 .62 0 0 0 -.1215 0 0 0 0 .034'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23r)'/%3E%3C/svg%3E");
  content: '';
  inset: 0;
  pointer-events: none;
  position: fixed;
  z-index: -1;
}

@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; }
}

/* O RODAPÉ ENTRA NO CAMPO. Ele pinta `--d-bg-2` em `styles.css` e sozinho já
   desenhava a emenda de baixo: uma faixa de outra cor atravessando a página
   inteira no pé. Aqui fica transparente e o campo segue por dentro dele; o fio
   de cima continua marcando onde o conteúdo termina. */
.foot { background: transparent; }

/* ══ 1 · O BOTÃO ════════════════════════════════════════════════════════════
   O primário é o único elemento da página com direito a brilho próprio, e por
   isso ele tem de ser o único. Um fio de luz percorre a borda, devagar, sem
   parar — o suficiente para o olho voltar a ele depois de ler o texto.

   O anel vive na BORDA, não no fundo: `padding-box` para o preenchimento e
   `border-box` para o cônico. O fundo continua sendo o gradiente da marca; o
   que gira é uma linha de um pixel em volta. Brilho no fundo mancharia o texto;
   na borda, ele contorna. */
.btn-primary {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  transition: transform var(--m-rapido) var(--ease-out), filter var(--m-rapido) var(--ease-out);
}

/* O FIO QUE GIRA — num só bloco.
   Estava partido em duas regras `.btn-primary::before`, e a segunda, sem
   `animation`, não redeclarava nada — mas a leitura ficou ambígua e o giro não
   subiu. Uma regra só, e a máscara junto: `padding` + `mask-composite: exclude`
   recorta o miolo e deixa passar exatamente a moldura de 1,2 px. Sem a máscara
   o cônico pinta o botão inteiro e o texto perde contraste. */
.btn-primary::before {
  animation: soma-anel-gira 4.8s linear infinite;
  background: conic-gradient(from var(--soma-giro),
    transparent 0%,
    color-mix(in srgb, var(--d-ink) 76%, transparent) 6%,
    transparent 14%,
    transparent 50%,
    color-mix(in srgb, var(--d-ink) 36%, transparent) 56%,
    transparent 64%);
  border-radius: inherit;
  content: '';
  inset: -1px;
  opacity: .6;
  padding: 1.2px;
  pointer-events: none;
  position: absolute;
  z-index: -1;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

@media (hover: hover) {
  .btn-primary:hover { filter: brightness(1.06); transform: translateY(-1px); }
  .btn-primary:hover::before { opacity: 1; }
  /* A SETA FICA PARADA. O comentário antigo aqui dizia que «a seta anda quando o
     botão é apontado — o gesto diz para onde ele leva», e a intenção era boa; o
     problema é que ela nunca andou sozinha. `styles.css` já movia o DISCO
     (`.btn:hover .arr`) 3px, e esta regra movia o GLIFO dentro do disco outros
     3px. O glifo terminava 6px à direita e descentrado do próprio círculo — o
     desvio que o dono apontou.
     A transição fica declarada de propósito: se algum estado futuro voltar a
     transformar a seta, ele nasce suave em vez de saltar. Hoje nada a
     transforma, e é isso que se quer. */
  .btn .arr svg, .btn-primary svg, .btn-ghost svg {
    transition: transform var(--m-rapido) var(--ease-out);
  }
}
.btn-primary:active { transform: translateY(0) scale(.985); }

/* ── O ÍMÃ ──────────────────────────────────────────────────────────────────
   `soma-premium.js` escreve `--ima-x` e `--ima-y` conforme o ponteiro se
   aproxima. O botão anda alguns pixels na direção da mão antes de ser clicado.
   É pequeno de propósito: um deslocamento grande vira brincadeira e faz o alvo
   fugir do cursor — o mesmo erro que a câmera da maquete cometia. */
.btn.tem-ima {
  transform: translate3d(var(--ima-x, 0), var(--ima-y, 0), 0);
  transition: transform var(--m-rapido) cubic-bezier(.2, .8, .3, 1), filter var(--m-rapido) var(--ease-out);
}
.btn.tem-ima:active { transform: translate3d(var(--ima-x, 0), var(--ima-y, 0), 0) scale(.985); }

/* ══ 2 · O TÍTULO ═══════════════════════════════════════════════════════════
   Cada linha do título sobe por trás de uma fresta, com atraso entre elas. É a
   entrada mais antiga do cinema e continua sendo a mais legível: o olho lê na
   ordem em que o texto chega, e a frase se monta em vez de aparecer.

   POR LINHA, NÃO POR LETRA. Animação por letra é vistosa e ilegível: em
   português, com acento e palavra longa, ela vira chuva. E custa um elemento
   por caractere. A linha é a unidade da leitura.

   `overflow: clip` no invólucro e `translateY` no filho — nada de `clip-path`
   animado, que força recomposição de camada em cada quadro. */
.soma-linha {
  display: block;
  overflow: clip;
  padding-bottom: .08em;   /* espaço para a perna do "g" e do "ç" não ser cortada */
}
/* ── QUEM DIZ QUANDO O TÍTULO ENTRA ─────────────────────────────────────────
   O `soma-editorial.js` já mantém um `IntersectionObserver` sobre tudo que tem
   `[data-soma-item]` — e todos os títulos-alvo desta página têm. Ele põe
   `.is-fora` no que ainda não chegou e tira quando chega.

   A primeira versão daqui criava um SEGUNDO observador para a mesma pergunta.
   Dois donos do mesmo fato é a receita de estados que discordam, e foi o que
   aconteceu: os títulos ficaram escondidos porque o observador novo não
   entregou o primeiro lote — a entrega é assíncrona e este arquivo roda depois
   de `fonts.ready`, quando aquele ciclo de renderização já passou.

   Agora não há observador aqui. A subida da linha é uma leitura do estado que
   o editorial já publica: fora, escondido; dentro, no lugar. Um dono só.

   E o fallback é o certo: sem JavaScript nenhum, `.is-fora` nunca é posto,
   `:not(.is-fora)` casa desde o primeiro quadro, e o título nasce no lugar. */
/* ── ESTA CAMADA NÃO ESCONDE NADA ────────────────────────────────────────────
   A versão anterior prendia a subida da linha ao `.is-fora` do editorial. Ao
   medir, os cinco títulos apareceram com `opacity: 0` — quatro ainda com a
   classe e UM sem ela e mesmo assim invisível. Ou seja: o estado do qual eu
   dependia não é confiável no momento em que leio.

   Acoplar acabamento a um estado incerto é como o texto ficou invisível. E o
   custo do erro é assimétrico: um título sem entrada é uma página menos
   bonita; um título que não aparece é uma página quebrada.

   Então o padrão aqui é VISÍVEL, sempre. A linha nasce no lugar. O gesto de
   subida fica reservado para quando o editorial estiver em cena — e se ele
   nunca entrar, nada se perde além do movimento.

   `.soma-linha` continua existindo e continua sendo a fresta: quem quiser
   religar a subida acrescenta uma regra, não refaz a marcação. */
.soma-linha > i {
  display: block;
  font-style: inherit;
  transform: none;
  transition: transform var(--m-cena) cubic-bezier(.16, .84, .26, 1);
  transition-delay: calc(var(--ln, 0) * 90ms);
}

/* ══ 3 · O ELO — O MENU NÃO DESENHA NADA EM VOLTA DA PALAVRA ════════════════
   Aqui morava o traço do menu: um `::after` de um pixel que se desenhava da
   esquerda para a direita no hover e se recolhia pela direita ao sair. Era um
   gesto bonito, e saiu por decisão de desenho: no menu da SOMA a palavra é o
   elemento, e nada é desenhado em volta dela — sem barra embaixo, sem cartão
   atrás. O único sinal é a cor, e o brilho branco no item da página atual.

   O `position: relative` foi junto: existia só para ancorar esse `::after`. */

/* ══ 4 · A CHEGADA DA SEÇÃO ═════════════════════════════════════════════════
   Aqui havia um `!important` sobre a duração e a curva de `[data-soma-item]`,
   para dar às entradas o tempo de câmera em vez de tempo de interface.

   SAIU, e o motivo é de disciplina. Ao medir, os cinco títulos apareceram com
   `opacity: 0` — estado que é do editorial, não meu. Enquanto essa reveleção
   não estiver confirmada em navegador de verdade, este arquivo não põe a mão em
   nenhuma propriedade que o editorial controla: com `!important` no meio, uma
   investigação sobre por que algo não aparece começa perguntando se fui eu.

   A curva de cinema volta quando a entrada estiver confirmada, e volta no
   arquivo dono do efeito — `soma-editorial.css` —, não daqui por cima. */

/* ══ 5 · SEM MOVIMENTO ══════════════════════════════════════════════════════
   Não é degradação: é a mesma página, parada. Os títulos nascem no lugar, o
   anel não gira, o ímã não puxa. Nada fica escondido. */
@media (prefers-reduced-motion: reduce) {
  .btn-primary::before { animation: none; opacity: .5; }
  .soma-linha > i { transform: none; transition: none; }
  .btn.tem-ima { transform: none; transition: none; }
  [data-soma-item] { transition-duration: var(--m-rapido) !important; }
}


/* ════════════════════════════════════════════════════════════════════════════
   6 · O MOVIMENTO DAS SEÇÕES

   Até aqui só o herói, o mosaico, a maquete e a órbita se moviam. Da metade da
   página para baixo tudo entrava com a mesma revelação genérica do editorial —
   um bloco inteiro subindo de uma vez —, e o resultado é que a segunda metade
   lê como documento e a primeira como filme.

   Isto não acrescenta um sistema novo. Ele PEGA CARONA no que já existe: o
   `soma-editorial.js` põe e tira `.is-fora`, e tudo abaixo é leitura desse
   estado. Zero JavaScript novo, zero observador novo, zero dependência.

   A REGRA QUE ORGANIZA TUDO: o que é da MESMA FAMÍLIA entra em cascata, não
   junto. Sete soluções aparecendo no mesmo quadro é um bloco piscando; sete
   aparecendo a 70 ms de distância é uma lista sendo escrita. O atraso vem de
   `:nth-child`, sem uma linha de script.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── 6.1 · O TÍTULO VOLTA A SUBIR ───────────────────────────────────────────
   A fresta e a linha já estavam montadas pelo `soma-premium.js`; o que faltava
   era o estado escondido, que eu tinha removido por desconfiar do `.is-fora`.
   Medido em navegador de verdade: o editorial tira a classe corretamente, e o
   título que já está em quadro nasce com opacidade 1. A desconfiança era minha,
   não do código. */
[data-soma-item].is-fora .soma-linha > i {
  transform: translateY(105%);
  transition: none;          /* escondido não anima — só a volta é gesto */
}

/* ── 6.2 · QUEM ENTRA É A LINHA, NÃO O BLOCO ────────────────────────────────
   Aqui havia uma cascata em `:nth-child` sobre os filhos de cada família. Era
   invisível, e a razão é de composição: o CONTÊINER carregava o
   `data-soma-item`, então o editorial esmaecia o bloco inteiro como uma peça
   só — e qualquer escalonamento lá dentro acontecia debaixo de um pai que já
   estava sumindo junto.

   A correção foi na marcação, não em mais CSS: o `data-soma-item` desceu do
   contêiner para CADA linha. O editorial já escalona irmãos nativamente (ele
   escreve `transition-delay` incremental item a item), então a cascata passou
   a existir de graça, com um dono só.

   Ficou aqui apenas o que o editorial não sabe fazer: o preenchimento da grade
   e o feixe da linha viva.
   ────────────────────────────────────────────────────────────────────────── */

/* ── 6.3 · A GRADE DA ESCALA SE PREENCHE ────────────────────────────────────
   A tabela não aparece pronta: as colunas entram da esquerda para a direita,
   como quem monta a escala dia a dia. É o gesto do produto virando gesto de
   tela — e a célula vaga é a última a chegar, sozinha, o que faz dela o ponto
   de chegada da animação e não mais um item da fila. */
.pm-tabela tbody td,
.pm-tabela tbody th {
  opacity: 1;
  transition: opacity var(--m-medio) var(--ease-out);
}
.is-fora .pm-tabela tbody td,
.is-fora .pm-tabela tbody th { opacity: 0; }
.pm-tabela tbody tr:nth-child(1) td { transition-delay: 120ms; }
.pm-tabela tbody tr:nth-child(2) td { transition-delay: 190ms; }
.pm-tabela tbody tr:nth-child(3) td { transition-delay: 260ms; }
.pm-tabela tbody td:nth-child(2)  { transition-delay: 140ms; }
.pm-tabela tbody td:nth-child(3)  { transition-delay: 200ms; }
.pm-tabela tbody td:nth-child(4)  { transition-delay: 260ms; }
.pm-tabela tbody td:nth-child(5)  { transition-delay: 320ms; }
.pm-tabela tbody td:nth-child(6)  { transition-delay: 380ms; }
.pm-tabela tbody td:nth-child(7)  { transition-delay: 440ms; }
.pm-vaga { transition-delay: 760ms !important; }   /* a vaga chega por último */

/* ── 6.4 · O FEIXE NA LINHA VIVA ────────────────────────────────────────────
   Mesma técnica do anel do botão — `@property` num ângulo, para o navegador
   saber interpolar —, aplicada ao fio de 2 px que marca a solução ativa. Em vez
   de um traço aceso e parado, uma luz percorre o fio de cima a baixo.

   Só na linha VIVA. Sete feixes correndo ao mesmo tempo seria uma cortina de
   luz; um só é um cursor dizendo "é esta". */
.sol-item.esta-vivo::before {
  background: linear-gradient(180deg,
    transparent 0%,
    var(--c-teal) 22%,
    color-mix(in srgb, var(--d-ink) 88%, transparent) 50%,
    var(--c-teal) 78%,
    transparent 100%);
  background-size: 100% 260%;
  animation: sol-feixe 2.6s linear infinite;
}
@keyframes sol-feixe {
  from { background-position: 0 -160%; }
  to   { background-position: 0  160%; }
}

/* ── 6.5 · O CARD RESPONDE AO PONTEIRO ──────────────────────────────────────
   Os três tempos da SAVYME e as três ideias do Plantel ganham o mesmo gesto
   curto de elevação. Dois pixels e um fio que acende: o suficiente para a peça
   parecer tocável, longe do bastante de "card que pula". */
@media (hover: hover) {
  .sv-tempo, .plantel-ideias > div {
    transition: opacity var(--m-lento) var(--ease-out), transform var(--m-medio) var(--ease-out),
                border-color var(--m-medio) var(--ease-out);
  }
  .sv-tempo:hover, .plantel-ideias > div:hover {
    border-top-color: color-mix(in srgb, var(--c-teal) 52%, transparent);
    transform: translateY(-2px);
  }
}

/* ── 6.6 · SEM MOVIMENTO ────────────────────────────────────────────────────
   A mesma página, parada e completa. Nada fica escondido esperando um evento
   que não vai acontecer. */
@media (prefers-reduced-motion: reduce) {
  [data-soma-item].is-fora .soma-linha > i,
  [data-soma-item].is-fora .sol-item,
  [data-soma-item].is-fora .sv-tempo,
  [data-soma-item].is-fora > div,
  .is-fora .pm-tabela tbody td,
  .is-fora .pm-tabela tbody th {
    opacity: 1;
    transform: none;
  }
  .sol-item.esta-vivo::before { animation: none; background: var(--c-teal); }
}


/* ════════════════════════════════════════════════════════════════════════════
   7 · A CENA DIRIGIDA PELA ROLAGEM

   Tudo abaixo é `animation-timeline: view()`: o relógio da animação não é o
   tempo, é a POSIÇÃO do elemento na janela. Rolar para frente adianta; rolar
   para trás rebobina. Nada dispara e "acaba" — o quadro é sempre função de
   onde a peça está.

   POR QUE ISSO E NÃO UMA BIBLIOTECA. O catálogo do repositório foi conferido
   um a um: das 27 peças de card, galeria e scroll, VINTE E TRÊS dependem de
   GSAP, ScrollTrigger, Lenis, three.js ou anime.js. Num projeto sem bundler,
   trazer três bibliotecas por CDN para animar cartão é pagar 120 KB e uma
   thread de rAF pelo que o navegador já faz sozinho, no compositor.

   As quatro vanilla do catálogo apontavam todas para cá — e a técnica veio da
   `css-view-timeline-shine-effect`, portada para a paleta da casa.

   O `@supports` é a rede: onde `view()` não existe (Safari antigo, Firefox
   sem a flag), nada disto se aplica e a revelação do editorial continua
   valendo sozinha. Ninguém vê página quebrada; vê página com menos brilho.
   ════════════════════════════════════════════════════════════════════════════ */

/* o ângulo do brilho precisa ser NÚMERO para o navegador interpolar; sem
   `@property` ele é string e a varredura salta em vez de correr */
@property --gleam-x {
  syntax: "<percentage>";
  initial-value: -30%;
  inherits: false;
}

@supports (animation-timeline: view()) {

  /* ── 7.1 · O BRILHO DE ENTRADA ─────────────────────────────────────────────
     Uma lâmina de luz atravessa a peça enquanto ela sobe pela janela. Não é
     hover nem laço infinito: é a própria rolagem que a move, então a mão da
     pessoa é que conduz a luz. É o que faz a página parecer material — vidro
     pega reflexo quando você inclina, e aqui inclinar é rolar.

     ── O ALCANCE, MEDIDO ────────────────────────────────────────────────────
     Este comentário sempre disse `entry 8% cover 52%`. O código dizia outra
     coisa: `entry 0% entry 100%`. A diferença não é acadêmica.

     `entry` dura o TAMANHO DO ELEMENTO. Medido nesta página, com janela de
     900px:

         .plantel-ideias > div   86px →  8,7% da travessia
         .sol-item              197px → 18,0%
         .sv-tempo              240px → 21,1%
         .pm-grade              266px → 22,8%

     E esses 9 a 23% acontecem todos na borda de BAIXO da janela — o trecho em
     que a peça está entrando e ninguém está lendo. Quando ela chega à zona de
     leitura, a animação acabou faz tempo. Foi o que a medição mostrou: linha do
     tempo em 43,5%, animação já em `finished`.

     Por isso todo alcance daqui para baixo termina em `cover`, não em `entry`:
     o movimento acompanha a peça ATÉ o meio da tela, que é onde o olho está. */
  .sol-item::after,
  .sv-tempo::after,
  .plantel-ideias > div::after {
    background: linear-gradient(105deg,
      transparent 0%,
      transparent calc(var(--gleam-x) - 14%),
      color-mix(in srgb, var(--d-ink) 9%, transparent) var(--gleam-x),
      transparent calc(var(--gleam-x) + 14%),
      transparent 100%);
    content: '';
    inset: 0;
    pointer-events: none;
    position: absolute;
    z-index: 1;
    animation: soma-gleam linear both;
    animation-timeline: view();
    animation-range: entry 12% cover 46%;
  }
  .sv-tempo, .plantel-ideias > div { position: relative; }
  @keyframes soma-gleam {
    from { --gleam-x: -30%; }
    to   { --gleam-x: 130%; }
  }

  /* ── 7.2 · A DERIVA DA FOTOGRAFIA ──────────────────────────────────────────
     Toda foto grande cresce um fio enquanto atravessa a janela. Um e meio por
     cento do começo ao fim — invisível como movimento, decisivo como sensação:
     é a diferença entre uma imagem colada na página e uma imagem que está
     ACONTECENDO enquanto se passa por ela.

     Só `transform`: composição na GPU, zero repintura, zero custo de layout.

     ── `.orb-chapa img` SAIU COM A BANDA DELA ────────────────────────────────
     Havia aqui um quarto seletor, `.orb-chapa img` — a fotografia de fundo do
     orbital, a maior chapa da página (1425 × 1242 a 1440). A banda 06 deixou de
     ser o orbital e virou A PAREDE, que é elevação frontal em CSS e não tem
     fotografia nenhuma: não há imagem para derivar, e o seletor virou regra
     morta apontando para um elemento que não existe mais.

     Fica registrado porque o parágrafo que morreu aqui defendia uma decisão que
     continua boa para as três que sobraram: a deriva é por ROLAGEM e não por
     tempo, porque presa ao tempo ela roda para sempre, inclusive fora da tela,
     e presa à rolagem acontece exatamente quando alguém está olhando.

     E o `20_PLANO/DIRECAO_CINEMATOGRAFICA.md`, etapa 5, pede esta deriva em
     TEMPO — 26s, `alternate`, infinita. A daqui é por ROLAGEM, e é melhor pelo
     motivo que o próprio plano dá para preferi-la: o movimento existe «enquanto
     se passa por ela». Preso ao tempo, ele roda para sempre, inclusive fora da
     tela; preso à rolagem, ele acontece exatamente quando alguém está olhando, e
     custa zero quando ninguém está. Fica registrado que a etapa está cumprida
     por um caminho diferente do escrito, e por quê. */
  .home-foto img,
  .sol-quadro img,
  .quem-fala-sec img {
    animation: soma-deriva linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  @keyframes soma-deriva {
    from { transform: scale(1.055) translate3d(0, -0.8%, 0); }
    to   { transform: scale(1.005) translate3d(0,  0.8%, 0); }
  }

  /* ── 7.3 · A PROFUNDIDADE DA LINHA ─────────────────────────────────────────
     As sete soluções entram com um grau e meio de inclinação que se desfaz ao
     chegar ao centro de leitura. Um grau e meio é quase nada — e é justamente
     por ser quase nada que funciona: o olho registra "veio de algum lugar" sem
     conseguir dizer de onde. Acima de uns três graus vira carrossel de loja. */
  .sol-item {
    animation: soma-endireita linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 38%;
    transform-origin: 50% 120%;
  }
  @keyframes soma-endireita {
    from { transform: perspective(900px) rotateX(1.6deg) translate3d(0, 14px, 0); }
    to   { transform: none; }
  }

  /* ── 7.4 · A GRADE RESPIRA ─────────────────────────────────────────────────
     A tabela da escala ganha um leve avanço em profundidade ao entrar. Aqui a
     origem é o TOPO: a grade se abre para baixo, como uma folha que se estende
     — o gesto de quem abre a escala do mês, não o de um card que salta. */
  .pm-grade {
    animation: soma-abre linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 36%;
    transform-origin: 50% 0;
  }
  @keyframes soma-abre {
    from { opacity: .55; transform: perspective(1100px) rotateX(3.4deg) scale(.985); }
    to   { opacity: 1;   transform: none; }
  }

  /* ── 7.5 · O CARTÃO DA ÓRBITA ──────────────────────────────────────────────
     Os retratos ganham foco conforme sobem. Entram levemente dessaturados e
     chegam inteiros no meio da janela — o anel deixa de ser um mural parado e
     passa a ter um ponto de nitidez que acompanha a leitura. */
  .orbita-card img {
    animation: soma-foca linear both;
    animation-timeline: view();
    animation-range: entry 10% cover 44%;
  }
  @keyframes soma-foca {
    from { filter: saturate(.42) brightness(.78); }
    to   { filter: saturate(.9)  brightness(1);   }
  }
}

/* onde `view()` não existe, nada acima se aplica — e a revelação do editorial
   continua sendo a entrada de todas as peças. Nada fica escondido. */
@media (prefers-reduced-motion: reduce) {
  @supports (animation-timeline: view()) {
    .sol-item, .pm-grade, .home-foto img, .sol-quadro img,
    .quem-fala-sec img, .orbita-card img,
    .sol-item::after, .sv-tempo::after, .plantel-ideias > div::after {
      animation: none !important;
      transform: none !important;
    }
  }
}
