/* ═════════════════════════════════════════════════════════════════
   RIVIO — componentes.css · camada 3 de 5

   O que mais de uma página usa, e página nova pode usar sem pedir
   licença: herói (`hero`, `scroll-hint`), bloco escuro com trilho
   (`dark-section`, `rail`, `rail-nav`), `eyebrow`, card de case
   (`case-card` + a mira), CTA de seta (`cta-seta`), CTA fotográfico
   (`cta`), o texto que acende com a rolagem (`tell`) e o cartão e o
   modal de vídeo (`video-cartao`, `video-modal`, desde 2026-09-23).

   Regra de entrada: um bloco só sobe para cá quando a SEGUNDA página
   precisa dele. Enquanto for de uma página só, mora na folha dela.
   ═════════════════════════════════════════════════════════════════ */

/* só a headline do hero é liberada pela sequência de load — as outras
   linhas do site são disparadas por scroll (`[data-rise-lines]`) */
.js.is-ready .hero__headline .line__i {
  transform: none;
  transition: transform 1.05s var(--ease-out-expo) var(--d, 0ms);
}

/* The photographic plate settles out of a slow push-in */
.js .hero__media {
  opacity: 0;
  transform: scale(1.09);
}

.js.is-ready .hero__media {
  opacity: 1;
  transform: none;
  transition: opacity 1.3s ease 0.05s, transform 2.1s var(--ease-out-expo) 0.05s;
}

/* Landing mid-page (a reload, a restored scroll position) skips the
   sequence — the entrance is for arrivals, not returns. */
.js.is-instant .hero__media {
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .js .hero__media {
    opacity: 1;
    transform: none;
    transition: none !important;
  }
}

/* ─────────────────────────────────────────────────────────────────
   Hero
   ───────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 100svh;
  padding: 102px var(--gutter) 32px;
  overflow: clip;
  isolation: isolate;
  /* the plate fades up out of this, so the open reads as cinematic
     rather than as a white flash */
  background: #23262c;
}

.hero__media {
  position: absolute;
  inset: -6% 0 0;
  z-index: -1;
  pointer-events: none;
}

/* `display: contents` keeps <picture> out of layout, so the <img> stays a
   direct child of .hero__media as far as sizing is concerned */
.hero__media picture {
  display: contents;
}

.hero__media img {
  width: 100%;
  height: 106%;
  object-fit: cover;
  will-change: transform;
}

/* O véu: escuro em cima para a nav, aberto no meio e um FADING leve no
   rodapé, onde estão tag, manchete, lede e o scroll-hint (2026-09-27,
   com a fachada de vidro: "um fading no rodapé da imagem para garantir
   que tenha contraste… tem que ser leve"). O pé foi de 0,34 a 0,58, a
   partir da metade. Medido com o texto escondido, contra o #F7F9FF, no
   pixel p95 (o mais claro atrás das letras): o lede, sobre o reflexo do
   céu, foi de 2,7 a 4,8:1 a 1796 × 1206 e de 3,2 a 5,1:1 a 390 × 844; a
   manchete, de 4,9 a 7,9:1. */
.hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.42) 0%,
    rgba(0, 0, 0, 0.24) 34%,
    rgba(0, 0, 0, 0.24) 50%,
    rgba(0, 0, 0, 0.58) 100%
  );
}

.hero__inner {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

.hero__tag {
  display: inline-flex;
  align-items: center;
  gap: var(--tag-gap);
  padding: 12px 0;
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: var(--tag-corpo);
  line-height: 1.5;
  /* o tracking era 0,72 (0,06em) — único da página fora de 0,04em */
  letter-spacing: var(--tag-track);
  text-transform: uppercase;
  color: var(--light-64);
}

.hero__tag::before {
  content: '';
  width: var(--tag-quad);
  height: var(--tag-quad);
  background: var(--light-48);
}

.hero__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  min-height: 144px;
}

.hero__headline {
  /* CAIXA EM `em`, e é ela que trava a quebra de linha.

     A caixa do Figma é 646 para uma fonte de 60 — 10,7667em. Em `em`,
     caixa e tipo encolhem juntos e o corte fica em "Hospitais
     eficientes / salvam mais vidas." em QUALQUER corpo; a 60 ela
     computa 646 exatos, então nada muda no tamanho de origem.

     Em px a fonte encolhia sozinha e cabia mais palavra por linha:
     medido, de 52 para baixo "salvam" subia para a primeira linha e o
     título virava "Hospitais eficientes salvam / mais vidas.", com
     639px de linha dentro dos 646 — a leitura muda e a mancha quase
     enche a caixa. Mesma armadilha, e mesma solução, do `.tell__text`.
     Se a copy mudar, MEÇA a razão de novo. */
  max-width: 10.7667em;
  font-weight: 300;
  /* O fator em `vw` era 4,167 — 60 ÷ 1440, o valor do Figma — e o teto
     de 60 era alcançado exatamente a 1440. Numa tela de notebook o
     título chegava no tamanho cheio e lia pesado.

     3,9 adia o teto para ~1538 e deixa a faixa de notebook mais leve:
     1280 → 49,9 · 1366 → 53,3 · 1440 → 56,2 · 1512 → 59,0. Pedido do
     cliente ("mais delicado").

     Depois o teto desceu de 60 para 52 (2026-09-25, "reduzir um pouco
     mais, o máximo deve ser 52"). A curva de 3,9vw ficou: o teto chega
     a ~1333 e tudo acima disso — 1366, 1440, monitor grande — lê 52.
     Abaixo de 1333 nada mudou (1280 → 49,9), nem o piso de 34 do
     celular. Como a caixa é em `em`, as quebras de linha não mudam.

     O `min-height: 144px` do `.hero__row` não mudou: a linha dupla
     encolhe para ~125 e a composição do hero fica onde estava.

     O piso desceu de 34 para 28 (2026-09-28, "tá muito grande" no
     celular). O 34 valia de 360 até ~870 — a faixa inteira do celular
     e do tablet em pé. Com 28 a curva de 3,9vw assume a partir de ~718
     (768 → 30, 872 → 34), então não há degrau, e acima de ~870 nada
     muda. Medido de 360 a 880: home em 2 linhas (a caixa é em `em`),
     Quem somos em 3 (a 34 eram 4 até 390) e Carreiras em 3, com
     "Talvez este seja o seu." inteira na última (a 34, a 360, eram 4).
     Contra o h2 de 22 a razão fica 1,27. */
  font-size: clamp(28px, 3.9vw, 52px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--light-01);
}

.hero__aside {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 16px;
  width: 348px;
  padding: 8px 0;
  flex: none;
}

.hero__lede {
  font-size: 16px;
  line-height: 1.5;
  color: var(--light-01);
}

/* Shared "Scroll to explore" affordance */
.scroll-hint {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  line-height: 1.2;
  color: var(--light-80);
}

.scroll-hint svg {
  width: 14px;
  height: 20px;
  overflow: visible;
}

.scroll-hint__wheel {
  animation: wheel 2.4s var(--ease-in-out-soft) infinite;
  transform-origin: 50% 50%;
}

@keyframes wheel {
  0%,
  100% {
    transform: translateY(0);
    opacity: 1;
  }
  45% {
    transform: translateY(4px);
    opacity: 0.35;
  }
  70% {
    transform: translateY(0);
    opacity: 1;
  }
}


/* ── Right rail ─────────────────────────────────────────────────── */


.rail__dot {
  position: relative;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--r-redondo);
  background: rgba(122, 133, 153, 0.32); /* Dark-05 @ 32% */
  overflow: hidden;
  will-change: height;
}

/* the lit pill is Dark-88 @ 30%, crossfaded in as the layer takes over */
.rail__dot > i {
  position: absolute;
  inset: 0;
  border-radius: var(--r-redondo);
  background: rgba(0, 0, 0, 0.3); /* Dark-88 @ 30% opacity */
  opacity: 0;
}

/* ═════════════════════════════════════════════════════════════════
   Bloco escuro — Quote · Prova social · Advisory board
   ═════════════════════════════════════════════════════════════════ */

/* ── Peças compartilhadas pelas duas seções com carrossel ───────── */

.dark-section {
  position: relative;
  background: var(--dark-01);
  color: var(--light-01);
  overflow: clip;
  isolation: isolate;

  /* O recuo do Figma (112 a 1440) é medido da borda esquerda, e é isso que
     ele deve ser enquanto a tela é a moldura do Figma ou menor. Passando
     disso, um recuo fixo deixa a seção grudada na esquerda enquanto o resto
     da página centraliza — que é o que `max-width: 1216px; margin: 0 auto`
     faz nas seções claras. O `max` troca de regra exatamente onde as duas
     se cruzam, a 1440: daí para cima o recuo passa a ser o que centra a
     coluna de 1216, e o carrossel continua sangrando à direita a partir
     dessa mesma borda. */
  --dark-pad: max(clamp(20px, 7.778vw, 112px), (100% - 1216px) / 2);
}

.dark-section__inner {
  display: flex;
  flex-direction: column;
  gap: 60px;
  padding: 120px 0;
}

/* 112px de recuo à esquerda; o carrossel sangra para a direita */
.dark-section__head,
.dark-section__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  width: min(1216px, calc(100% - 2 * var(--dark-pad)));
  margin-left: var(--dark-pad);
}

/* Sem isto o <p> inline-flex do eyebrow herda o strut do bloco pai e a
   linha vira ~20px em vez dos 10 do próprio elemento. */
.dark-section__titles {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--tag-gap);
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: var(--tag-corpo);
  /* o Figma usa text-box-trim cap/alphabetic: a caixa é a cap-height */
  line-height: 0.7;
  letter-spacing: var(--tag-track);
  text-transform: uppercase;
  color: var(--dark-05);
}

.eyebrow::before {
  content: '';
  width: var(--tag-quad);
  height: var(--tag-quad);
  background: currentColor;
}

.dark-section__title {
  max-width: 712px;
  margin-top: 24px;
  font-weight: 400;
  font-size: var(--h2);
  /* 1,24, e não 1,2 (2026-09-27): o título de seção tem UMA entrelinha
     — a do Figma ("36 / 1,24", a dos títulos da Visão e da § 4). Havia
     1,2 e 1,24 lado a lado na mesma página. */
  line-height: 1.24;
  color: var(--light-01);
}

/* prev / next — 34px, Light-16, radius 2 (Figma 642:75649) */
.rail-nav {
  display: flex;
  gap: 6px;
  flex: none;
}

.rail-nav button {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--r-marca);
  background: var(--light-16);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.3s var(--ease-out-soft),
    opacity 0.3s var(--ease-out-soft);
}

.rail-nav button:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.28);
}

.rail-nav button:disabled {
  opacity: 0.34;
  cursor: default;
}

.rail-nav svg {
  width: 34px;
  height: 34px;
}

/* ── O trilho rolável ───────────────────────────────────────────── */

.rail {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--dark-pad);
  padding: 0 var(--dark-pad) 0 var(--dark-pad);
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.rail::-webkit-scrollbar {
  display: none;
}

.rail > * {
  flex: none;
  scroll-snap-align: start;
}

.case-card {
  position: relative;
  width: min(720px, 82vw);
  aspect-ratio: 720 / 405;
  border-radius: var(--r-caixa);
  overflow: clip;
  background: #111;
}

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

.case-card__foot {
  position: absolute;
  inset: auto 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 24px;
}

.case-card__quote {
  max-width: 424px;
  font-size: clamp(16px, 1.53vw, 22px);
  line-height: 1.5;
  color: var(--light-01);
  text-shadow: 0 1px 24px rgba(0, 0, 0, 0.5);
}

.case-card__play {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  /* <button> não herda `color` — sem isto o currentColor do SVG cai no
     default escuro do UA em vez do branco do Figma */
  color: #fff;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: pointer;
  transition: background-color 0.3s var(--ease-out-soft),
    transform 0.4s var(--ease-out-expo);
}

.case-card__play:hover {
  background: rgba(255, 255, 255, 0.44);
  transform: scale(1.06);
}

.case-card__play svg {
  width: 16px;
  height: 16px;
}

/* ── Card de ARTIGO ──────────────────────────────────────────────
   O card de vídeo promete um play; este promete uma leitura. A
   composição da ficha não muda — texto à esquerda, botão redondo à
   direita —, muda o que ela diz: título no lugar da citação, seta no
   lugar do triângulo. E o card INTEIRO vira o link, porque a área de
   clique de um card é o card, não um alvo de 48px no canto. */
.case-card--artigo {
  display: block;
  text-decoration: none;
  color: inherit;
}

/* O anel de foco existe porque o card é um LINK, e um link que só se
   anuncia no hover não existe para quem navega de teclado. Mesma
   receita do `.advisor`, que é o outro card clicável do site. */
.case-card--artigo:focus-visible {
  outline: 2px solid var(--light-01);
  outline-offset: 4px;
}

/* A foto avança de leve no hover. É o que diz "isto é clicável" antes
   de o ponteiro chegar na seta — e num card que ocupa 720px o aviso
   precisa vir da peça inteira, não de um detalhe do rodapé. */
.case-card--artigo img {
  transition: transform 0.9s var(--ease-out-expo);
}

a.case-card--artigo:hover img,
a.case-card--artigo:focus-visible img {
  transform: scale(1.035);
}

.case-card__titulo {
  max-width: 424px;
  font-size: clamp(16px, 1.53vw, 22px);
  line-height: 1.5;
  color: var(--light-01);
  text-shadow: 0 1px 24px rgba(0, 0, 0, 0.5);
  text-wrap: pretty;
}

/* Mesma geometria do `__play`: 48px, vidro fosco, branco. Só o glifo
   muda, e o glifo é o MESMO da `.cta-seta` do resto do site — a seta
   de canto já é o "vai para outro lugar" deste desenho. */
.case-card__ir {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  flex: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  color: #fff;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background-color 0.3s var(--ease-out-soft),
    transform 0.4s var(--ease-out-expo);
}

a.case-card--artigo:hover .case-card__ir,
a.case-card--artigo:focus-visible .case-card__ir {
  background: rgba(255, 255, 255, 0.44);
  transform: scale(1.06);
}

/* A seta aponta para CIMA-direita: é a direção de "abre outra página",
   e era o contrário do play que estava ali.

   E ela é MAIOR de verdade, o que não se resolve mexendo só no `width`
   do <svg>: o glifo da `.cta-seta` desenha num viewBox de 31 mas ocupa
   só 8 dele — a 17px de caixa, a seta visível tinha 4,4px. O viewBox
   aqui é de 12 para um traço de 8, então a seta ocupa dois terços da
   caixa: 12px de seta em 18 de caixa. */
.case-card__ir svg {
  width: 18px;
  height: 18px;
}

/* ── A mira "Ver case" ───────────────────────────────────────────
   Uma pílula que segue o ponteiro dentro do card.

   A mistura é `luminosity`: a pílula impõe a LUZ dela e herda a cor da
   foto. Branco vira o tom mais claro daquela imagem, o texto preto
   vira o mais escuro — pílula clara com letra escura em qualquer
   fundo, e ainda assim tingida pela foto, que é a graça de misturar em
   vez de pintar de branco chapado.

   `difference` foi a primeira tentativa e está descartada por medida,
   não por gosto: ele INVERTE a cor, e sobre o corredor bege do
   primeiro card a pílula saía AZUL, com o texto quase ilegível. Numa
   foto quente o complementar é sempre frio — não é um caso raro, é o
   comportamento.

   Posição, escala e opacidade são escritas pelo JS a cada quadro
   (`--mx`, `--my`, `--k`, `--o`). Não há `transition` nenhuma: uma
   transição no `transform` brigaria com o amortecimento do ponteiro e
   a pílula andaria atrasada duas vezes. */
.case-card__mira {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  display: none;
  padding: 12px 20px;
  border-radius: 1000px;
  /* A fonte de rótulo do site é SEMPRE caixa alta — é assim que ela
     aparece nas tags, e é o único jeito de ela ser reconhecida como a
     mesma voz. Mesmos tokens da `.eyebrow`. */
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: var(--tag-corpo);
  letter-spacing: var(--tag-track);
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  background: #fff;
  color: #000;
  mix-blend-mode: luminosity;
  pointer-events: none;
  opacity: var(--o, 0);
  transform: translate(var(--mx, 0px), var(--my, 0px)) translate(-50%, -50%)
    scale(var(--k, 0.6));
}

/* Só onde existe ponteiro fino. Num toque não há hover, e um rótulo
   que nunca aparece não é affordance nenhuma — por isso a seta da
   ficha continua lá em toda tela: é ela que fala no celular. A classe
   vem do JS, e não do `.js` do <head>: se o módulo não subir, o
   ponteiro do sistema não pode sumir.

   E some só no card que TEM a pílula (`:has`): a classe `tem-mira` vale
   para a página inteira, e os cards da grade da Imprensa (2026-09-27)
   não têm pílula — sem esta guarda o cursor sumia neles e nada
   aparecia no lugar. */
@media (hover: hover) and (pointer: fine) {
  .tem-mira a.case-card--artigo .case-card__mira { display: block; }
  .tem-mira a.case-card--artigo:has(.case-card__mira) { cursor: none; }
}

@media (prefers-reduced-motion: reduce) {
  .case-card--artigo img { transition: none; }
}

/* Card ainda sem página: nada de ponteiro, nada de anel de foco, nada
   de mira. Ele preenche a seção e diz o que virá — não finge um
   destino. */
article.case-card--artigo { cursor: default; }

/* ── Link com seta ↗ · Advisory e Visão ─────────────────────────── */

/* ── CTA de seta ────────────────────────────────────────────────── */
/* Um componente para as três: "Entenda como funciona", "Leia o manifesto
   completo" e "Quero ser candidato". Antes eram três pesos, dois gaps e
   três tratamentos de elipse — uma assada dentro do SVG, uma inexistente
   e uma de verdade.

   O hover é UM gesto com três partes:

   1 · a seta VOA para fora da elipse, na diagonal para onde aponta, e o
       `overflow: clip` da elipse a corta na borda;
   2 · uma segunda seta entra pela diagonal de baixo à esquerda e para no
       centro, um pouco depois — a elipse troca a seta em vez de
       arrastá-la;
   3 · o texto acende LETRA A LETRA, da esquerda para a direita, como uma
       cabeça de leitura passando.

   A cor fica nos modificadores, de propósito: sobre seção clara a elipse
   é sólida, sobre foto ela é vidro. */

.cta-seta {
  position: relative;
  display: inline-flex;
  /* `inline-flex` num filho de contêiner flex é BLOCKIFICADO para
     `flex`, e aí o `align-items: stretch` do pai estica a CTA na largura.
     Medido na Visão: o link ficava 24,1px mais largo que o conteúdo, e a
     malha e o halo sangravam essa sobra à direita da elipse — parecia
     que a elipse estava deslocada. Isto trava a largura no conteúdo. */
  align-self: flex-start;
  align-items: center;
  gap: var(--cta-gap);
  font-family: var(--font-display);
  font-weight: var(--cta-peso);
  font-size: var(--cta-corpo);
  line-height: 1.2;
  text-transform: uppercase;
}

/* ── o texto que acende ──────────────────────────────────────────── */

/* As letras são embrulhadas em `span` pelo `initCtaSeta`; o espaço fica
   como nó de texto, senão ele colapsa. O índice vem no `--i`, e é ele
   que escalona o atraso — a cabeça de leitura é a soma dos atrasos, não
   um loop. */
/* texto e elipse ficam ACIMA da malha */
.cta-seta__txt,
.cta-seta__elipse {
  position: relative;
  z-index: 1;
}

.cta-seta__txt span {
  /* duração CURTA, de propósito: ver `--cta-letra-dur` nos tokens */
  transition: color var(--cta-letra-dur) linear;
}

/* ── a luz de trás da elipse ─────────────────────────────────────── */
/* Halo CURTO e circular, colado na elipse. A primeira versão era uma
   elipse de 240 × 78 e o cliente recusou: vazando para a direita ela lia
   como mancha, não como luz. Em 76 sobram ~22px de brilho em volta de um
   círculo de 31.

   A cor da marca não vive só aqui — ela está principalmente na COR DOS
   PONTOS, que é o que o cliente pediu. Este halo só levanta o entorno
   imediato da elipse.

   Fica fora do recorte da malha, senão a borda reta dela cortaria o
   halo.

   `translate` e `transform` são propriedades separadas de propósito: uma
   centra, a outra anima a abertura, sem uma sobrescrever a outra. */
.cta-seta__luz {
  position: absolute;
  z-index: 0;
  top: 50%;
  right: calc(var(--cta-elipse) / 2);
  width: var(--cta-luz);
  height: var(--cta-luz);
  translate: 50% -50%;
  transform: scale(0.55);
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    225deg,
    #ffbe78 0%,
    #e992ff 47.6%,
    #6694ff 90%
  );
  /* queda macia e curta: brilho colado na elipse, sem borda visível */
  -webkit-mask-image: radial-gradient(
    closest-side,
    #000 18%,
    rgba(0, 0, 0, 0.4) 52%,
    transparent 100%
  );
  mask-image: radial-gradient(
    closest-side,
    #000 18%,
    rgba(0, 0, 0, 0.4) 52%,
    transparent 100%
  );
  transition:
    opacity 0.5s var(--ease-out-soft),
    transform 0.8s var(--ease-out-expo);
}

.cta-seta:hover .cta-seta__luz {
  opacity: var(--cta-luz-forca);
  transform: scale(1);
}

/* ── a malha de pontinhos ────────────────────────────────────────── */
/* Figma `816:2135`. Lá o frame tem um `bg-gradient-to-r from-white` por
   cima da malha: um VÉU branco que a esconde do lado do texto e a revela
   perto da elipse. Aqui ele virou MÁSCARA, não chapa — pintar branco por
   cima só funcionaria sobre fundo branco, e esta CTA também vive sobre
   foto e sobre a seção lilás.

   Dois elementos, e cada um tem um trabalho: o de fora carrega a máscara
   e a revelação; o de dentro carrega os pontos e a deriva. Se fossem um
   só, animar a deriva moveria a máscara junto e a borda da revelação
   andaria com os pontos. */
.cta-seta__malha {
  position: absolute;
  /* sangra para fora da caixa: os pontos precisam de onde vir */
  inset: -10px;
  z-index: 0;
  overflow: clip;
  border-radius: var(--r-redondo);
  opacity: 0;
  /* entra deslizando de baixo da elipse */
  transform: translateX(10px);
  pointer-events: none;
  transition:
    opacity 0.5s var(--ease-out-soft),
    transform 0.7s var(--ease-out-expo);
  /* o véu do Figma, invertido: nada no texto, cheio na elipse */
  -webkit-mask-image: linear-gradient(to right, transparent 8.7%, #000 100%);
  mask-image: linear-gradient(to right, transparent 8.7%, #000 100%);
}

.cta-seta:hover .cta-seta__malha {
  opacity: 1;
  transform: none;
  /* entra por último: os pontos são atmosfera, não um quarto evento */
  transition-delay: 0.12s;
}

/* PAPÉIS INVERTIDOS: o fundo é o campo de COR e a máscara é o padrão de
   pontos. Assim cada ponto pega a cor do lugar onde está — cinza perto
   do texto, cores da marca perto da elipse — em vez de todos terem a
   mesma cor com uma chapa colorida por cima.

   O campo de cor deriva junto com os pontos, mas o laço anda um passo
   só (6,5px) num campo de centenas: o deslocamento de cor é
   imperceptível. */
.cta-seta__malha i {
  position: absolute;
  /* folga para a deriva nunca descobrir a borda */
  inset: -20px;
  background-image: linear-gradient(
    to right,
    var(--cta-ponto) 0%,
    var(--cta-ponto) 52%,
    var(--cta-ponto-quente) 84%,
    var(--cta-ponto-frio) 100%
  );
  -webkit-mask-image: radial-gradient(
    circle at center,
    #000 0,
    #000 var(--cta-malha-raio),
    transparent var(--cta-malha-borda)
  );
  mask-image: radial-gradient(
    circle at center,
    #000 0,
    #000 var(--cta-malha-raio),
    transparent var(--cta-malha-borda)
  );
  -webkit-mask-size: var(--cta-malha-passo) var(--cta-malha-passo);
  mask-size: var(--cta-malha-passo) var(--cta-malha-passo);
  animation: cta-deriva var(--cta-malha-deriva) linear infinite;
  animation-play-state: paused;
}

.cta-seta:hover .cta-seta__malha i {
  animation-play-state: running;
}

/* Um passo exato — o fim do ciclo é idêntico ao começo, então o laço não
   tem emenda. Para a ESQUERDA: os pontos saem de trás da elipse e vão
   embora na direção do texto. */
@keyframes cta-deriva {
  to {
    transform: translateX(calc(var(--cta-malha-passo) * -1));
  }
}

.cta-seta:hover .cta-seta__txt span {
  transition-delay: calc(var(--i, 0) * var(--cta-letra));
}

/* ── a elipse ────────────────────────────────────────────────────── */

.cta-seta__elipse {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--cta-elipse);
  height: var(--cta-elipse);
  flex: none;
  border-radius: 50%;
  /* é o que corta a seta que voa para fora */
  overflow: clip;
  transition:
    transform var(--cta-dur) var(--ease-out-expo),
    background-color var(--cta-dur) var(--ease-out-soft);
}

.cta-seta:hover .cta-seta__elipse {
  transform: scale(var(--cta-cresce));
}

/* ── as duas setas ───────────────────────────────────────────────── */

.cta-seta__glifo {
  position: absolute;
  width: var(--cta-elipse);
  height: var(--cta-elipse);
  /* o Figma exporta a seta apontando para baixo; o espelho é o que a põe
     apontando para cima */
  transform: scaleY(-1);
  transition: transform var(--cta-dur) var(--ease-out-expo);
}

/* A ORDEM aqui importa e não é intercambiável: o `translate` tem de vir
   ANTES do `scaleY(-1)`. Depois dele, o deslocamento acontece dentro do
   sistema já invertido e o −16 vira +16 — a seta desce em vez de subir.
   Era o que a implementação antiga fazia; medido na matriz:
   `scaleY(-1) translate(3px,-3px)` resolve para (3, +3). */
.cta-seta:hover .cta-seta__glifo--sai {
  transform: translate(var(--cta-voa), calc(var(--cta-voa) * -1)) scaleY(-1);
}

/* a de trás espera fora da elipse, na diagonal de baixo à esquerda */
.cta-seta__glifo--entra {
  transform: translate(calc(var(--cta-voa) * -1), var(--cta-voa)) scaleY(-1);
}

.cta-seta:hover .cta-seta__glifo--entra {
  transform: scaleY(-1);
  /* o atraso só existe na ENTRADA: ao tirar o cursor, as duas voltam
     juntas, senão a saída fica arrastada */
  transition-delay: var(--cta-atraso);
}

/* ── sobre seção clara ───────────────────────────────────────────── */

.cta-seta--escura {
  color: var(--dark-03, #49505c);
  --cta-ponto: rgba(73, 80, 92, 0.34);
}

.cta-seta--escura .cta-seta__elipse {
  background: #49505c;
}

.cta-seta--escura:hover .cta-seta__elipse {
  background: #3b414c;
}

.cta-seta--escura:hover .cta-seta__txt span {
  color: #1c2027;
}

/* ── sobre foto ──────────────────────────────────────────────────── */

.cta-seta--clara {
  /* O repouso é levemente apagado para o acender ter para onde ir: em
     branco pleno a cabeça de leitura não teria contraste nenhum. */
  color: rgba(247, 249, 255, 0.78);
  --cta-ponto: rgba(255, 255, 255, 0.62);
}

.cta-seta--clara .cta-seta__luz {
  width: var(--cta-luz-foto);
  height: var(--cta-luz-foto);
}

.cta-seta--clara:hover .cta-seta__luz {
  opacity: var(--cta-luz-forca-foto);
}

.cta-seta--clara .cta-seta__elipse {
  background: rgba(255, 255, 255, 0.32);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.cta-seta--clara:hover .cta-seta__elipse {
  background: rgba(255, 255, 255, 0.5);
}

.cta-seta--clara:hover .cta-seta__txt span {
  color: #fff;
}

/* Posição da CTA dentro do bloco do CTA. É a única coisa que sobrou da
   `.cta__action`: o resto virou componente. */
.cta__action {
  margin-top: 36px;
}

/* Ocupa a largura do contêiner, com a elipse na borda. É o oposto do
   `align-self: flex-start` da base, e aqui é de propósito: na Visão a
   CTA e o card dos fundadores são irmãos na mesma coluna, e ela tem de
   ter a MESMA largura dele. Sem isto ela media 183,9 contra os 208 do
   card. */
.cta-seta--largo {
  align-self: stretch;
  justify-content: space-between;
}

/* dentro do cabeçalho dos cards a CTA divide uma caixa de 292 com o
   título, então ali ela abre em vez de encostar */
.cta-seta--card {
  display: flex;
  justify-content: space-between;
  width: 292px;
}

.cta-seta--card .cta-seta__txt {
  width: 146px;
}

/* ── variante de DOWNLOAD (2026-09-27, "já que é um botão de download…
   uma variante desse botão com uma seta apontada para baixo") ───────
   O MESMO glifo, sem desenho novo: exportado ele aponta para baixo e à
   direita (↘); girado 45° ele aponta para baixo, com a ponta em V. O
   gesto do hover é o da base, só que vertical — a seta desce e sai, e
   a de trás entra por cima. O percurso é o da diagonal da base
   (`--cta-voa` × √2), para sair da elipse do mesmo jeito.
   Primeiro uso: "Baixar o kit de marca", na Imprensa. */
.cta-seta--baixar .cta-seta__glifo {
  transform: rotate(45deg);
}

.cta-seta--baixar:hover .cta-seta__glifo--sai {
  transform: translateY(calc(var(--cta-voa) * 1.4142)) rotate(45deg);
}

.cta-seta--baixar .cta-seta__glifo--entra {
  transform: translateY(calc(var(--cta-voa) * -1.4142)) rotate(45deg);
}

.cta-seta--baixar:hover .cta-seta__glifo--entra {
  transform: rotate(45deg);
}

@media (prefers-reduced-motion: reduce) {
  .cta-seta__txt span,
  .cta-seta__elipse,
  .cta-seta__glifo,
  .cta-seta__malha,
  .cta-seta__luz {
    transition: none;
  }
  /* nada pode se mover sozinho */
  .cta-seta__malha i,
  .cta-seta:hover .cta-seta__malha i {
    animation: none;
  }
  .cta-seta:hover .cta-seta__txt span,
  .cta-seta:hover .cta-seta__glifo--entra {
    transition-delay: 0s;
  }
}

.cta__inner {
  opacity: 0;
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: space-between;
  gap: 60px;
  padding-left: var(--dark-pad);
  padding-right: var(--gutter);
}

.cta__badge {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: var(--r-marca);
  background: var(--light-16);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.cta__badge svg {
  width: 16px;
  height: 16px;
}

.cta__block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  max-width: 734px;
}

.cta__title {
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  color: var(--light-01);
}

.cta__lede {
  font-weight: 300;
  font-size: 16px;
  line-height: 1.5;
  color: var(--light-01);
}

/* `.eyebrow--maior` foi removido, e a classe saiu do markup junto: ele
   era 12 / SemiBold / quadrado 8, que é exatamente o padrão agora. */

/* eyebrow claro, sobre foto. Só a COR muda; medida vem do padrão. */
.eyebrow--light {
  color: rgba(255, 255, 255, 0.8);
}

@media (max-width: 1100px) {
  /* ── O hero empilhado tem DOIS ritmos, não um ────────────────────
     Tag, headline e lede são uma informação só e têm de ler agrupadas;
     o "Scroll to explore" é outra coisa — é instrução, não conteúdo — e
     precisa de um corte claro antes dele.

     Medido antes: os três vãos ópticos eram 30,4 · 25,6 · 23,0. Quase
     iguais, e em ordem DECRESCENTE — ou seja, o maior respiro estava
     dentro do grupo e o menor separava o que devia ficar separado. Os
     quatro liam como uma pilha só.

     **Os números de CSS abaixo são diferentes entre si de propósito.**
     O que se vê é o vão ÓPTICO — de tinta a tinta — e cada par tem uma
     sobra de entrelinha própria no meio: a tag some 5,9, a headline e o
     lede somam 11,6, o lede e o hint somam 7,0. Escrever o mesmo `gap`
     nos três daria três vãos visualmente diferentes, que é exatamente o
     defeito que estava aqui. Se mexer, **mire o óptico e meça**. */
  .hero__row {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  /* A tag carrega `padding: 12px 0` do desktop, e ele SOMA ao gap do
     `.hero__inner` — era o que fazia o primeiro vão ser o maior dos três
     apesar de ter o menor `gap`. No celular o respiro vem todo do gap. */
  .hero__tag {
    padding-block: 0;
  }
  .hero__inner {
    gap: 10px;
  }
  .hero__aside {
    width: 100%;
    max-width: 420px;
    /* o corte entre o grupo e a instrução */
    gap: 32px;
  }
}

@media (max-width: 860px) {
  .dark-section__title {
    margin-top: 12px;
  }

  .cta__title {
    width: 100%;
    max-width: none;
  }

  /* A etiqueta a 12 do título, como em todo cabeçalho no celular
     (2026-09-27, DIRETRIZES § 3): o bloco é uma coluna de vão 24, e o
     vão fica 24 entre título, texto e CTA. */
  .cta__block > .eyebrow {
    margin-bottom: -12px;
  }

  /* ── UM recuo lateral para a página inteira ─────────────────────
     Havia quatro a 375: 20 no hero, § 2, § 3, Visão e rodapé; 29,2 nas
     seções escuras (`--dark-pad`, que é `7.778vw` e só faz sentido
     enquanto a tela é larga); e 40 na § 4.6, por recuo duplo.

     No celular todos passam a ser `--gutter`. A conta de porcentagem do
     desktop continua intacta acima de 860. */
  .dark-section,
.cta {
    --dark-pad: var(--gutter);
  }

  /* ── Corpo de texto no celular ──────────────────────────────────
     Entre 12 e 14, a pedido do cliente. Vale para o texto CORRIDO — o
     que se lê. Fica de fora, de propósito, o texto que é ARTE: os
     rótulos dentro das ilustrações dos cards da § 4.6 (`cc__*`) estão
     em píxel de design e escalam com o desenho; subi-los quebraria a
     ilustração. */
  .hero__lede,
.cta__lede,
.case-card__quote {
    font-size: var(--p-mobile);
  }
  /* COMENTÁRIO ÓRFÃO REMOVIDO: aqui havia um bloco descrevendo a CTA e
     o card "voltando a empilhar", mas a regra saiu em 24/08, quando o
     cliente pediu os dois lado a lado. O texto ficou descrevendo código
     que não existe mais. A história dele está no HISTORICO; o que vale
     hoje é o `@media (max-width: 374px)` no fim deste arquivo. */

  .cta {
    min-height: 92svh;
  }
  .cta__inner {
    gap: 44px;
  }
  .cta__action {
    margin-top: 20px;
    gap: 20px;
  }
}

/* ── Bloco escuro · responsivo ──────────────────────────────────── */

@media (max-width: 1100px) {
  .dark-section__inner {
    gap: 44px;
    padding: 88px 0;
  }
}

@media (max-width: 860px) {
  .dark-section__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }
  /* os botões perdem a função onde o dedo já arrasta */
  .rail-nav {
    display: none;
  }
  /* o card fica mais alto para a frase caber sem cobrir o rosto */
  .case-card {
    width: 84vw;
    aspect-ratio: 5 / 4;
  }
  .case-card__foot {
    padding: 18px;
    gap: 14px;
  }
  .case-card__quote {
    /* dentro da faixa de 12–14 do corpo de texto no celular */
    font-size: var(--p-mobile);
    line-height: 1.45;
  }
  .case-card__play {
    width: 40px;
    height: 40px;
  }
  .case-card__play svg {
    width: 14px;
    height: 14px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-hint__wheel {
    animation: none;
  }
}

/* ═════════════════════════════════════════════════════════════════
   2 · Apresentação da Rivio — o texto que se revela lendo
   Figma v11 `722:31873` (o parágrafo) e `722:31870` (o título curto)

   Um palco só para os dois frames do Figma. A fita se divide em quatro
   atos, e a medida de cada um está em `tokens.css`:

     leitura → o parágrafo acende letra a letra
     troca   → o parágrafo sai e "Healthcare AI Services Co" entra
     curto   → o título curto acende do mesmo jeito
     cobre   → o palco fica PRESO enquanto a § 3 sobe por cima

   O fundo é branco a pedido do cliente; o Figma pinta Light-01 com a
   lavada lilás a 30% (DIRETRIZES § 8).
   ═════════════════════════════════════════════════════════════════ */

.tell__track {
  height: calc(
    (
        100 + var(--tell-leitura) + var(--tell-troca) + var(--tell-curto) +
          var(--tell-cobre)
      ) * 1svh
  );
}

.tell__stage {
  position: sticky;
  top: 0;
  display: grid;
  place-items: center;
  height: 100svh;
  padding: 32px 18px;
  background: #fff;

  /* a troca entre os dois textos, escrita pelo JS */
  --troca: 0;
}

/* Os dois textos dividem a mesma célula: o curto nasce exatamente onde
   o parágrafo estava, que é o que faz um "virar" o outro. */
.tell__text {
  grid-area: 1 / 1;
  /* A caixa do Figma é 1000 para uma fonte de 60 — 16,667em. Em `em` a
     quebra de linha fica IGUAL em qualquer largura: caixa e tipo
     encolhem juntos. Em px a fonte encolhia sozinha e cabia mais
     palavra por linha, mudando a quebra fora de 1440. */
  width: min(16.667em, 100%);
  font-weight: 300;
  font-size: clamp(30px, 4.167vw, 60px);
  line-height: 1.24;
  letter-spacing: -0.04em; /* −2.4px em 60 */
  text-align: center;
  /* Sem `text-wrap: balance`: ele iguala o comprimento das linhas, e o
     Figma quebra guloso — enche cada linha até não caber mais. Era o que
     punha "nova" na segunda linha em vez da primeira. */
  /* A cor de repouso é o fim do gradiente do Figma — o texto "ainda não
     lido". Quem acende cada letra é o JS. */
  color: var(--tell-apagado);
}

/* A troca é SEQUENCIAL, não um crossfade: o parágrafo sai nos primeiros
   45% e o título só chega depois dos 55%. Com os dois no ar ao mesmo
   tempo o palco vira uma sobreposição ilegível — sai um, entra o outro,
   e o respiro branco no meio é o que faz um "virar" o outro. */
.tell__text--longo {
  --f: clamp(0, calc((0.45 - var(--troca)) / 0.45), 1);
  opacity: var(--f);
  transform: translateY(calc((1 - var(--f)) * -20px));
}

/* ── O título curto é a PORTA da seção das camadas ────────────────
   Ele herdava `.tell__text` inteiro — mesmo corpo, peso e centralização
   — e entrava com o fade + subida que a página usa em tudo. Passava
   despercebido justamente onde deveria nomear o que vem a seguir.

   Agora ele faz três coisas, e nenhuma delas é de layout:

   1 · CRESCE de pequeno até a largura cheia (`scale`).
   2 · É PREENCHIDO pelo topo da própria seção das camadas: camada 1 em
       70,7% e as cinco tiras em 5,86%, exatamente os valores de
       `--lay-aberto` e `--lay-tira`. Não há asset novo — são as mesmas
       fotos que a § 3 já carregou.
   3 · É EMPURRADO para cima pela borda superior da `.lay`, que já sobe
       por cima desta seção por margem negativa. O texto nunca passa por
       baixo dela: `--empurra` é sempre ≤ 0 e cola a base do texto na
       borda da seção.

   Escala e translação são composição pura — medido a 4K, zero frames
   perdidos. O `letter-spacing` que isto substitui era propriedade de
   LAYOUT e refluía o texto a cada frame. */
.tell__text--curto {
  /* Até o FIM da fatia. Em `/0.34` o crescimento gastava um terço dela e
     os dois terços restantes viravam espera parada. O parágrafo sai em
     0…0,45, então começar em 0,42 mantém o respiro branco entre os
     dois. */
  --f: clamp(0, calc((var(--troca) - 0.42) / 0.58), 1);
  --cresce: calc(0.34 + var(--f) * 0.66);
  --empurra: 0px;
  /* `max-content` e não `auto`: com `nowrap` o texto transborda a caixa,
     e `background-clip: text` só pinta DENTRO dela — a última letra saía
     sem preenchimento. A caixa tem que acompanhar o texto. */
  width: max-content;
  max-width: none;
  /* LARGURA DE TELA, e os dois números saem de UMA razão medida.

     A razão entre largura renderizada e corpo é **11,0334** para as 25
     letras de "Healthcare AI Services Co" nesta fonte, neste peso e com
     este `letter-spacing` — medida com uma sonda de 100px, não estimada.
     (A copy anterior, "Hospital Intelligence", media 8,6434, e é de onde
     vinham o 8,64 e o 11,3 que estavam aqui. Trocar o texto invalida a
     razão: se a copy mudar de novo, MEÇA outra vez.)

     O `min` é o que garante os 28px de cada lado: um corpo de
     `(100vw − 56px) / 11,04` produz a largura da tela menos os dois
     respiros. O divisor é arredondado para CIMA da razão medida, de
     propósito — para baixo o texto fica alguns décimos mais largo que a
     folga e raspa a borda.

     O teto em `vw` mantém a proporção em tela larga: 100vw pediria
     9,063vw de corpo, e 8,85 guarda a mesma folga relativa que o 11,3
     guardava antes. Acima de ~2440px é ele que manda e a margem sobra —
     nunca falta. */
  font-size: min(8.85vw, calc((100vw - 56px) / 11.04));
  letter-spacing: -0.04em;
  white-space: nowrap;

  /* O preenchimento é a foto da CAMADA 1, uma só.

     Eram as seis fotos lado a lado, nas proporções da seção. A intenção
     era boa — as colunas caíam onde as da § 3 caem — mas as emendas
     verticais cortavam as letras no meio, e um talho abrupto dentro de
     um glifo lê como defeito, não como continuidade. Com uma imagem só o
     recorte fica limpo, o paralaxe fica trivial e a pintura fica mais
     barata: uma camada de fundo em vez de seis.

     `100vw auto` mantém a foto na escala da tela — é o que preserva a
     leitura de continuação com a seção logo abaixo — e sobra altura de
     sobra para o paralaxe correr: a 1440 a imagem tem 810px contra os
     ~190px da caixa do texto.

     `--par` desce o preenchimento enquanto as letras sobem. */
  --par: 0px;
  background-image: url('../assets/layers-v2/layer-1-1672.webp');
  background-size: 100vw auto;
  background-position: center calc(100% + var(--par));
  background-repeat: no-repeat;
  background-origin: border-box;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;

  opacity: var(--f);
  transform: translateY(var(--empurra)) scale(var(--cresce));
  transform-origin: center center;
  will-change: transform;
}

/* Cada letra é um `.tell__c` com a animação `tell-acende`, que anima
   `color` — e cor de filho pinta POR CIMA do `background-clip: text` do
   pai, deixando o título chapado. Acender letra a letra é o gesto do
   PARÁGRAFO, que se lê como leitura; o título não o quer. Zerar a
   animação aqui devolve as letras à cor herdada (transparente) e o
   recorte do pai passa a aparecer através delas. */
.tell__text--curto .tell__c {
  animation: none;
  color: inherit;
}

/* Sem JS o texto tem que continuar legível: sem `--empurra` ele fica
   parado, e sem preenchimento visível ele sumiria. */
.no-js .tell__text--curto,
:root:not(.js) .tell__text--curto {
  background-image: none;
  color: var(--dark-02);
}

@media (max-width: 900px) {
  .tell__text--curto {
    /* 36 = 2 × 18: no celular o respiro lateral deste título é 18px, não
       os 28 do desktop — a tela é estreita e cada pixel de margem custa
       corpo de letra.

       SEM teto em `vw`. Com ele, a partir de ~700px de largura era o
       teto que mandava e a margem subia para 32 — mais que os 18
       pedidos. Aqui a largura é que dita o corpo, sempre.

       O divisor é o do desktop MAIS 0,04, e o `padding-right` é o par
       disso: o `letter-spacing` negativo encolhe também o vão DEPOIS da
       última letra, então a caixa fica mais estreita que a tinta e ela
       transbordava ~2px à direita — 20px de margem de um lado contra 16
       do outro. Devolvendo esse vão à caixa, a tinta centra. A relação
       vale para qualquer copy: era 8,64 → 8,68, agora é 11,04 → 11,08. */
    font-size: calc((100vw - 36px) / 11.08);
    padding-right: 0.04em;

    /* O palco tem o respiro da PÁGINA (`--gutter`, 20px), e este título
       quer 18. A diferença é exatamente 2px de cada lado — em vez de
       mudar o respiro do palco, que vale também para o parágrafo e é
       padrão do site, o título sangra os 2px que faltam.

       Não é só estética: com 354px de caixa dentro de 350 de espaço
       útil, ele não cabia, a centralização degradava para "encostar na
       esquerda" e ele transbordava 4px à direita — 20 de margem de um
       lado contra 16 do outro. */
    margin-inline: -2px;
  }
}

/* Cada letra é um span; a palavra inteira não quebra no meio. */
.tell__p {
  display: inline-block;
  white-space: nowrap;
}

/* A acesa de UMA letra, medida no GIF de referência: ela apaga quase
   até o fundo, acende clara no acento e só então assenta na cor final.
   São três estados — `transition` só sabe interpolar dois, por isso é
   uma animação.

   Ela nasce PAUSADA: quem a percorre é o scroll, escrevendo `--t`
   (0…1) através do `animation-delay` negativo. Assim a cor continua
   morando no CSS e o JS só escreve um número. */
@keyframes tell-acende {
  0% {
    color: var(--tell-apagado);
  }
  18% {
    color: var(--tell-acento);
  }
  100% {
    color: var(--tell-aceso);
  }
}

.tell__c {
  animation: tell-acende 1s linear paused both;
  animation-delay: calc(var(--t, 0) * -1s);
}

/* Sem JS, ou com movimento reduzido, o texto é só texto — legível, na
   cor final, sem palco preso e sem um texto por cima do outro.

   `scripting: none` cobre o caso em que os módulos não carregam: aí não
   existem os spans das letras, e sem esta regra o parágrafo ficaria
   preso na cor de "ainda não lido" — apagado — por 510svh de fita. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  .tell__track {
    height: auto;
  }
  .tell__stage {
    position: static;
    height: auto;
    min-height: 100svh;
    gap: 48px;
    padding: 120px 18px;
  }
  .tell__text {
    grid-area: auto;
    color: var(--tell-aceso);
    opacity: 1;
    transform: none;
  }
  .tell__c {
    animation: none;
    color: var(--tell-aceso);
  }
}

@media (max-width: 900px) {
  .tell__stage {
    padding: 32px var(--gutter);
  }
}

@media (max-width: 900px) {
  .cta-seta--card {
    width: auto;
  }
}

/* Sem palco preso — movimento reduzido ou sem JS — nada sobe por cima de
   nada: a margem negativa comeria a seção vizinha inteira em vez de
   revelá-la. Precisa vir DEPOIS da regra acima: mesma especificidade,
   quem vence é a última. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  .tell--solo {
    margin-top: 0;
  }
}

/* ── Responsivo ─────────────────────────────────────────────────── */

/* ── § 4.6 no celular: scroll lateral dirigido pelo scroll da tela ──
   Pedido do cliente: "enquanto o usuário estiver rolando pra baixo o
   scroll lateral dos cards vai funcionando e vai mostrando todos os
   cards; quando mostrar o último a tela desce."

   Palco preso numa fita, e o trilho anda em X por `transform` — não por
   `scrollLeft`, que teria tempo próprio e brigaria com o dedo. O
   `cards.js` escreve um número; quem desenha é o CSS.

   E a CTA vai para BAIXO dos cards. O truque para isso sem mexer no
   markup é `display: contents` no cabeçalho: os filhos dele viram itens
   diretos do `.cards__inner`, e aí o `order` pode intercalá-los com o
   trilho. */
@media (max-width: 900px) {
  .cta-seta--card {
    order: 3;
    width: auto;
    margin: 0 var(--gutter);
  }
}

/* ── Voltar ao início ────────────────────────────────────────────
   Nasceu na /obrigado (Figma 1109:2199) e subiu para cá quando a 404
   passou a usá-lo — segunda página, mesma peça.
   Seta para a ESQUERDA, e não a diagonal que sai: o gesto é voltar, e
   a diagonal do site significa "abrir outra coisa". */
.voltar {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--light-64);
  transition: color 0.28s var(--ease-out-soft);
}

.voltar__txt {
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.voltar:hover { color: var(--light-01); }

/* A elipse é CSS e o glifo é o vetor do Figma — mesma divisão do
   `.case-card__ir`, que já é a linguagem de botão redondo do site. */
.voltar__elipse {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.24);
  color: var(--light-01);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transition: background-color 0.3s var(--ease-out-soft),
    transform 0.4s var(--ease-out-expo);
}

.voltar__elipse svg { width: 100%; height: 100%; display: block; }

.voltar:hover .voltar__elipse {
  background: rgba(255, 255, 255, 0.36);
  transform: translateX(-4px);
}

.voltar:focus-visible {
  outline: 2px solid var(--light-01);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ═════════════════════════════════════════════════════════════════
   O que subiu da home em 2026-09-18, quando a página "Quem somos"
   passou a usar também: o Advisory board (`altv`) e o card dos
   fundadores. Os blocos vieram INTEIROS, na ordem em que estavam, e a
   sonda da home foi gravada antes e depois — mover regra não muda a
   regra, muda a ordem, e a ordem é o desempate.
   ═════════════════════════════════════════════════════════════════ */

/* ── 3b · Advisory board · ALTERNATIVA ──────────────────────────── */
/* Estudo, logo abaixo da versão de cima, para comparar as duas na mesma
   página. Linguagem trazida pelo cliente (a seção "Our People" da Cult).

   O que muda em relação à de cima, ponto a ponto:
     A · cards soltos com folga de 16   B · fita contígua, sangrando
     A · aberto cresce nos dois eixos   B · aberto transborda a fita
     A · fechados em contraste cheio    B · fechados lavados
     A · bio sob o card                 B · nome, cargo e bio numa faixa
     A · pontos de navegação            B · contador 01 / 9

   Cabeçalho, título e setas são os MESMOS das outras seções escuras —
   `.dark-section__head`, `.dark-section__title`, `.rail-nav`. A
   alternativa é da fita, não da tipografia. */

/* Registrada para poder TRANSICIONAR dentro de `calc()`. Registro é
   global — daí o prefixo. */
@property --altv-k {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* Estas duas são registradas por outro motivo: para o JS conseguir LER o
   valor delas. `getComputedStyle` de custom property não registrada
   devolve o TOKEN — `max(96px, calc(…))` — e o `parseFloat` dá `NaN`.
   Ver DIRETRIZES § 6. */
@property --altv-larga {
  syntax: '<length>';
  inherits: true;
  initial-value: 190px;
}

@property --altv-larga-aberta {
  syntax: '<length>';
  inherits: true;
  initial-value: 298px;
}

.altv {
  --altv-alta: 340px; /* altura da fita */
  --altv-alta-aberta: 420px; /* a aberta transborda 40 para cada lado */
  --altv-larga-aberta: 298px;
  /* A fechada é fluida para a fita SEMPRE cobrir a tela: seis delas mais
     a aberta enchem a largura, e as de fora sangram nas duas bordas. O
     piso de 96 é o que salva a tela estreita, onde a conta daria 13px. */
  --altv-larga: max(96px, calc((100vw - var(--altv-larga-aberta)) / 6));
  --altv-dur: 0.85s;
}

.altv__inner {
  gap: 48px;
}

/* Entre 901 e 1100 quem manda no vão é o bloco escuro: 44, o mesmo do
   `.dark-section__inner` do `componentes.css`. Quando tudo morava num
   arquivo só, aquela regra vinha DEPOIS desta e vencia o empate de
   especificidade; repartido, `home.css` carrega depois e os 48 passariam
   a valer nessa faixa. Esta linha escreve o resultado que já existia —
   apontado pelo `ferramentas/ordem-regras.mjs`. */
@media (max-width: 1100px) {
  .altv__inner {
    gap: 44px;
  }
}

/* Setas redondas, a pedido do cliente — no advisory e em Cases. Cada
   uma mira o contêiner da SUA seção, não o `.rail-nav` genérico: ele é
   componente compartilhado, e arredondá-lo mudaria tudo que o usa de uma
   vez, inclusive o que ainda não existe. */
.altv__ctrl button,
.cases .rail-nav button {
  border-radius: 50%;
}

/* Só importa no celular, onde o contador entra nesta barra:
   `.rail-nav` não declara `align-items`, então vale `stretch`, e o
   parágrafo esticava para os 34px da barra com o texto assentado no
   TOPO da caixa, acima do centro das setas. Os botões têm altura fixa,
   então centrar não mexe neles em layout nenhum. */
.altv__ctrl {
  align-items: center;
}


/* ── A fita ──────────────────────────────────────────────────────── */

/* NÃO centralize a pista aqui. Ela é MAIS LARGA que o palco, e um item
   centralizado que transborda é posicionado em `(palco − pista) / 2` —
   ou seja bem à esquerda, com o deslocamento do JS somando por cima de
   um começo que não é zero. Armadilha da § 6 das diretrizes, medida de
   novo aqui: a fita nascia em x = 571. A pista começa em zero e quem a
   posiciona é só o `transform`. */
.altv__palco {
  position: relative;
  /* a aberta transborda; o palco reserva a altura da maior */
  min-height: var(--altv-alta-aberta);
}

.altv__pista {
  display: flex;
  align-items: center;
  /* CONTÍGUA: sem folga nenhuma entre as fotos */
  gap: 0;
  min-height: var(--altv-alta-aberta);
  transform: translate3d(var(--altv-x, 0px), 0, 0);
  transition: transform var(--altv-dur) var(--ease-out-expo);
  touch-action: pan-y;
}

.altv__pista.is-arrastando {
  transition: none;
  cursor: grabbing;
}

/* posicionar sem animação (boot, resize) — sem o cursor de arrasto junto */
.altv__pista.is-instantanea {
  transition: none;
}

.altv__item {
  position: relative;
  z-index: 0;
  flex: none;
  width: var(--altv-larga);
  transition:
    width var(--altv-dur) var(--ease-out-expo),
    --altv-k var(--altv-dur) var(--ease-out-expo);
}

.altv__item.is-ativo {
  --altv-k: 1;
  z-index: 1;
  width: var(--altv-larga-aberta);
}

/* cenário, não controle — mesma razão da seção de cima */
.altv__item[data-altv-eco] {
  pointer-events: none;
}

.altv__foto {
  display: block;
  position: relative;
  width: 100%;
  /* 340 → 420: a aberta transborda a fita 40 para cima e 40 para baixo,
     porque a pista alinha pelo centro */
  height: calc(var(--altv-alta) + 80px * var(--altv-k));
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  overflow: clip;
  /* O raio também nasce em ZERO e cresce com `--altv-k`. Tem de ser
     assim: um raio fixo arredondaria as fechadas e a fita deixaria de
     ser contígua — apareceriam entalhes brancos nas emendas. Só a que
     está em evidência ganha canto, e ele chega no mesmo passo em que ela
     cresce, sem uma segunda conta de tempo. */
  border-radius: calc(var(--r-caixa) * var(--altv-k));
  /* a sombra segue a mesma regra */
  box-shadow: 0 calc(18px * var(--altv-k)) calc(48px * var(--altv-k))
    rgba(0, 0, 0, calc(0.55 * var(--altv-k)));
  transition: height var(--altv-dur) var(--ease-out-expo);
}

.altv__item.is-ativo .altv__foto {
  cursor: default;
}

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

/* O retrato COLORIDO, por cima do p&b. Aparece só quando a foto está em
   evidência, e a opacidade dele É o `--altv-k` — não uma transição
   própria. Assim a cor chega exatamente no mesmo passo em que a foto
   cresce, sem duas contas de tempo para descasar.

   O `src` nasce vazio e o JS o preenche sob demanda: as nove coloridas
   somam 399 KB e só uma aparece por vez. Ver `advisory-b.js`. */
.altv__cor {
  opacity: var(--altv-k);
}

/* As fechadas ficam lavadas — é o que faz a aberta saltar sem precisar
   de moldura. */
.altv__foto::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--dark-01);
  opacity: calc(0.52 - 0.52 * var(--altv-k));
  transition: opacity var(--altv-dur) var(--ease-out-expo);
}

.altv__foto:hover::after {
  opacity: calc(0.3 - 0.3 * var(--altv-k));
}

.altv__foto:focus-visible {
  outline: 2px solid var(--light-01);
  outline-offset: -2px;
}

/* a bio mora na faixa de baixo; aqui ela é só dado para o JS ler */
.altv__bio {
  display: none;
}

/* ── A faixa de baixo ────────────────────────────────────────────── */

/* Mesma caixa do cabeçalho, para o nome nascer no eixo do título. */
/* A coluna do nome tem a largura EXATA do retrato aberto: o bloco de
   texto nasce debaixo dele, no mesmo eixo e na mesma medida, e a bio
   começa logo depois da borda direita da foto. Antes a primeira coluna
   era `1fr` e empurrava a bio para x = 570 — 128px longe do nome. */
.altv__base {
  display: grid;
  /* Terceira coluna, `auto`: o contador. No desktop ele fecha esta
     faixa; no celular o controlador o move para a barra das setas. */
  grid-template-columns: var(--altv-larga-aberta) minmax(0, 1fr) auto;
  align-items: start;
  gap: 32px;
  width: min(1216px, calc(100% - 2 * var(--dark-pad)));
  margin-left: var(--dark-pad);
}

.altv__nome {
  font-weight: 500;
  font-size: 18px;
  line-height: 1.3;
}

.altv__cargo {
  margin-top: 4px;
  font-weight: 300;
  font-size: 14px;
  line-height: 1.5;
  color: var(--light-64);
}

.altv__texto {
  /* Em `em`, para a medida acompanhar o corpo se ele mudar: 40em a 14px
     são 560, que dão ~68 caracteres por linha. Sem o teto a coluna iria
     a 804 e a linha passaria de 110 caracteres. */
  max-width: 40em;
  font-weight: 300;
  font-size: 14px;
  line-height: 1.5;
  color: var(--light-64);
}

/* Nome, cargo e bio trocam juntos, com um respiro no meio — sem isso os
   dois textos se cruzam e viram borrão. Mesma lição da § 2. */
.altv__quem,
.altv__texto {
  transition:
    opacity 0.34s var(--ease-out-soft),
    transform 0.5s var(--ease-out-expo);
}

.altv__quem.is-trocando,
.altv__texto.is-trocando {
  opacity: 0;
  transform: translateY(10px);
}

/* ── A ALTURA DA BIO É RESERVADA ─────────────────────────────────
   As nove bios não têm o mesmo número de linhas, e a área de texto fica
   ACIMA de tudo o que vem depois na página — então cada troca de
   conselheiro empurrava a seção inteira e o que está abaixo dela.

   Medido: a 1440 oito bios ocupam 3 linhas e a do Mat ocupa 4; a 1024
   todas ocupam 4; a 375 seis ocupam 5 e três ocupam 6. Reservar o pior
   caso de cada faixa custa uma linha de espaço em branco e devolve uma
   seção que não se mexe enquanto o leitor clica nas setas.

   `lh` é a unidade certa aqui porque o que se reserva é NÚMERO DE
   LINHAS, não uma altura: se a tipografia mudar, a reserva acompanha.
   Onde ela não existir, a declaração cai e volta o comportamento de
   hoje — degrada para o que já era. */
.altv__texto { min-height: 4lh; }

.altv__conta {
  font-family: var(--font-label);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.033em;
  color: var(--light-64);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── 3c · Advisory board CLARO — TESTE ENCERRADO, e o escuro venceu ─
   Este bloco está INERTE. Ele só age se a classe `altv--clara` estiver
   na `<section>` do `index.html`, e ela não está.

   História, para ninguém refazer a conta: o cliente pediu a seção clara,
   ela foi ao ar em 2026-09-08 e a preferência voltou para a escura no
   mesmo dia. O bloco ficou porque o custo de guardá-lo é de 40 linhas
   inertes e o de recriá-lo é medir tudo de novo — cliente muda de ideia,
   e da segunda vez isto aqui é uma linha de HTML.

   ── PARA TESTAR O CLARO DE NOVO ──────────────────────────────────
   Na tag `<section>` do `index.html`:
     1. acrescente `altv--clara` à lista de classes;
     2. TIRE o atributo `data-nav-light`.

   O `data-nav-light` é o que manda o menu clarear ao passar por cima da
   seção. Sobre fundo claro isso apaga o menu — e é o erro que não
   aparece com a página parada, só ao rolar.

   O que ele troca é SÓ cor: nove declarações. A geometria toda (o
   `--dark-pad`, o `__inner`, o `__head`, a fita que sangra à direita)
   continua vindo do `dark-section`, que é por isso que a classe fica na
   seção nos dois estados. */
.altv--clara {
  background: var(--light-01);
  color: var(--dark-02);
}

.altv--clara .dark-section__title { color: var(--dark-01); }

/* Os três textos de apoio eram `--light-64` (branco a 64%), que sobre
   claro some. `--dark-03` é o cinza de corpo das páginas de case — o
   mesmo papel, do outro lado. */
.altv--clara .altv__cargo,
.altv--clara .altv__texto,
.altv--clara .altv__conta {
  color: var(--dark-03);
}

/* As setas do carrossel invertem junto: elas eram branco a 16% sobre
   escuro, e o equivalente do outro lado é o preto da marca na mesma
   fração. Preenchimento, nunca contorno. */
.altv--clara .rail-nav button {
  background: rgba(24, 27, 31, 0.08);
  color: var(--dark-01);
}

.altv--clara .rail-nav button:hover:not(:disabled) {
  background: rgba(24, 27, 31, 0.16);
}

/* O véu do retrato NÃO inverte, e isso é deliberado: ele é o que
   dessatura a foto fechada e revela a cor ao abrir. É tratamento de
   imagem, não cor de superfície — clareá-lo apagaria o efeito inteiro. */

@media (max-width: 900px) {
  /* Seis, e não quatro: a coluna estreita quebra as mesmas bios em mais
     linhas. Aqui o pulo já existia antes das bios novas — River Mist e
     Fernando Carneiro já iam a 6 contra 5 dos outros. */
  .altv__texto { min-height: 6lh; }

  /* COMPACTO o bastante para foto e texto caberem na MESMA tela. Antes a
     seção media 982px (1,21 telas) e a bio acabava em y = 862, abaixo da
     dobra de 812 — o leitor via o retrato ou o texto, nunca os dois. */
  .altv {
    /* a ABERTA é `--altv-alta + 80` (ela transborda 40 para cada lado),
       então 160 aqui dá 240 de foto aberta — não adianta mexer só no
       `--altv-alta-aberta`, que serve para o palco reservar altura */
    --altv-alta: 160px;
    --altv-alta-aberta: 240px;
    --altv-larga-aberta: 200px;
    gap: 24px;
    min-height: 0;
    /* o respiro da seção mora no miolo; aqui ele seria somado e a seção
       passaria de uma tela, jogando os controles abaixo da dobra */
    padding: 0;
  }

  /* `.altv .altv__inner` e não só `.altv__inner`: há um
     `.dark-section__inner` numa media query POSTERIOR com a mesma
     especificidade, e ele vencia — o miolo ficava com 88 de respiro e 44
     de gap, empurrando os controles 49px abaixo da dobra. */
  .altv .altv__inner {
    gap: 20px;
    /* 72 em cima e não 48: a nav tem 56 e a seção começa em y = 0, então
       com 48 o eyebrow nascia ATRÁS da barra. Embaixo cabe menos, e o
       que importa ali é os controles ficarem acima da dobra. */
    padding: 72px 0 40px;
  }

  .altv__topo {
    flex-direction: column;
    gap: 16px;
  }

  .altv__base {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  /* Os controles descem para o FIM da seção, ao alcance do polegar.
     Estavam no cabeçalho, no alto da tela — e, pior, invisíveis: a regra
     genérica `.rail-nav { display: none }` abaixo de 860 existe porque
     nos carrosséis de ROLAGEM NATIVA o dedo já arrasta. Este não é: ele
     é dirigido por `transform`, e sem os botões não há como avançar.

     `display: contents` no cabeçalho faz o título e os controles virarem
     irmãos do palco, e o `order` os intercala. */
  .dark-section__head:has(.altv__ctrl) {
    display: contents;
  }

  .altv .dark-section__titles {
    order: 1;
    width: min(1216px, calc(100% - 2 * var(--dark-pad)));
    margin-left: var(--dark-pad);
  }

  .altv__palco {
    order: 2;
  }

  .altv__base {
    order: 3;
  }

  /* `.altv .altv__ctrl` e não só `.altv__ctrl`: a regra genérica
     `.rail-nav { display: none }` abaixo de 860 tem a MESMA
     especificidade e vem depois no arquivo — empate, quem vence é a
     última. Uma classe a mais resolve. */
  .altv .altv__ctrl {
    order: 4;
    display: flex;
    /* Setas de um lado, contador do outro: a barra ocupa a largura do
       conteúdo e os dois extremos ficam no alcance do polegar. */
    justify-content: space-between;
    gap: 12px;
    width: min(1216px, calc(100% - 2 * var(--dark-pad)));
    margin-left: var(--dark-pad);
  }

  /* As duas setas continuam coladas uma na outra; quem vai para a ponta
     oposta é só o contador. */
  .altv .altv__ctrl button + button {
    margin-right: auto;
  }

}

@media (prefers-reduced-motion: reduce) {
  .altv {
    --altv-dur: 0.01s;
  }

  .altv__quem,
  .altv__texto {
    transition: none;
  }
}

.founders-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 208px;
  height: 240px;
  border-radius: var(--r-caixa);
  overflow: clip;
  background: #1a1a1a;
}

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

.founders-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 56.656%, rgba(0, 0, 0, 0.8) 100%);
}

.founders-card__names {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  height: 44px;
  padding: 8px;
  color: rgba(255, 255, 255, 0.8);
}

.founders-card__names > div:last-child {
  text-align: right;
}

.founders-card__name {
  font-weight: 500;
  font-size: 12px;
  line-height: 1;
  margin-bottom: 4px;
}

.founders-card__role {
  font-size: 10px;
  line-height: 1.2;
  letter-spacing: -0.008em;
  opacity: 0.75;
}

/* Os dois ajustes de celular que moravam no `@media (max-width: 860px)`
   da home, com o mesmo corte. */
@media (max-width: 860px) {
  .altv .dark-section__title {
    margin-top: 12px;
  }

  .altv__bio {
    font-size: var(--p-mobile);
  }

  .founders-card__role {
    font-size: var(--p-mobile-min);
  }
}

/* ═════════════════════════════════════════════════════════════════
   O BLOCO DE LEITURA — `.leitura`
   Lead à esquerda (eyebrow + título, 312), prosa à direita (751, em
   duas colunas de 14/18,1). É a "Nossa visão" da home, medida por
   medida, nas páginas institucionais (Quem somos, Imprensa). Subiu da
   `quem-somos.css` em 2026-09-18, quando a segunda página precisou.
   ═════════════════════════════════════════════════════════════════ */
.leitura {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 48px;
  width: min(1216px, calc(100% - 2 * var(--gutter)));
  margin: 0 auto;
}

/* `flex: 0 1 auto` e não `none` (2026-09-27): 312 + 48 + 751 = 1111
   rígidos passavam da caixa a 1161–1162 (o bloco só empilha a 1160) —
   a mesma armadilha da Visão da home. O lead cede; as colunas não. */
.leitura__lead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  width: 312px;
  flex: 0 1 auto;
}

.leitura__titulo {
  margin: 0;
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  color: var(--dark-01);
}

.leitura__cols {
  display: flex;
  gap: 48px;
  width: 752px;
  flex: none;
}

.leitura__cols p {
  flex: 1;
  margin: 0;
  font-weight: 300;
  font-size: 14px;
  line-height: 18px;
  color: #0f0f0f;
}

.leitura__cols--um p { max-width: 560px; }


/* Médio: empilha. Estreito: a prosa vira uma coluna no corpo do
   celular. Os cortes são os do site (1160 é onde 312 + 48 + 751 deixa
   de caber com folga; 860 é o corte de corpo dos tokens). */
/* Empilhado, os vãos da Visão da home (2026-09-27, DIRETRIZES § 3):
   título → texto 40 e, abaixo de 861, 20; etiqueta → título 12 abaixo de
   861. Eram 32 e 18 em qualquer largura. */
@media (max-width: 1160px) {
  .leitura {
    flex-direction: column;
    gap: 40px;
  }

  .leitura__lead,
  .leitura__cols {
    width: 100%;
  }
}

@media (max-width: 860px) {
  .leitura { gap: 20px; }
  .leitura__lead { gap: 12px; }
  .leitura__cols { flex-direction: column; gap: 16px; }
  .leitura__cols p { font-size: var(--p-mobile); line-height: 1.5; }
}

/* ═════════════════════════════════════════════════════════════════
   O CTA FOTOGRÁFICO — `foto-cta` (2026-09-18)

   O fecho das páginas da família home: a foto do lobby sangrando, o
   selo, e o `cta__block` (eyebrow, título, lede, `cta-seta`). Ele existia
   em QUATRO cópias de página — `case-cta`, `carr-fecho`, `pcta`, `qs-cta`
   — e a página de cases seria a quinta. Sobe aqui com as medidas da
   `qs-cta`, e as páginas NOVAS usam esta. O Carreiras convergiu em
   2026-09-27 (`.foto-cta.carr-fecho`); `case-cta` e `pcta` continuam
   com a cópia delas, já com este recuo: convergir o resto é refatoração,
   e só fecha com sonda antes/depois em cada página (§ 4 das diretrizes)
   — dívida registrada no ESTADO.
   ═════════════════════════════════════════════════════════════════ */
.foto-cta {
  position: relative;
  display: flex;
  padding-block: var(--cta-foto-pad);
  overflow: clip;
  isolation: isolate;
  color: var(--light-01);
}

.foto-cta__foto {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--dark-01);
}

.foto-cta__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 100%;
}

.foto-cta__foto::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.24);
}

.foto-cta__inner {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--cta-foto-gap);
  padding-left: max(clamp(20px, 7.778vw, 112px), (100% - 1216px) / 2);
  padding-right: var(--gutter);
}

/* No celular, a altura do conteúdo com o mesmo 96 (2026-09-27: os
   92% da tela de 2026-09-24 saíram quando as CTAs passaram a envolver o
   conteúdo — ver `--cta-foto-pad` no `tokens.css`). */
@media (max-width: 860px) {
  .foto-cta__inner { padding-left: var(--gutter); gap: var(--cta-foto-gap-m); }
}

/* ═════════════════════════════════════════════════════════════════
   O HERÓI COM VÍDEO · desde 2026-09-23
   Nasceu na página de carreiras (`.carr-hero`) e subiu quando a de
   produto passou a abrir do mesmo jeito: o vídeo em tela cheia, o
   véu, a manchete com o convite para rolar e, na mesma linha, o
   cartão que abre o filme (`.video-cartao`, logo abaixo). A manchete
   de cada página mede a sua caixa na folha da página. Os textos são os
   de origem — "a home", "o obrigado" e as medidas são de carreiras.
   ═════════════════════════════════════════════════════════════════ */

/* ── O herói ─────────────────────────────────────────────────────
   Geometria do herói da home — `100svh`, conteúdo ancorado embaixo,
   mesmo recuo. A mídia é o vídeo de b-roll do site atual, reencodado
   sem a trilha de áudio (vazia) e servido daqui, nunca de host externo.

   `#23262c` no fundo pelo mesmo motivo da home: o pôster sobe a partir
   dele e a abertura lê como cinema em vez de estouro branco. */
.hero-video {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 100svh;
  padding: 102px var(--gutter) 32px;
  overflow: clip;
  isolation: isolate;
  background: #23262c;
}

.hero-video__media {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.hero-video__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* O VÉU. Sem ele o texto branco depende do que estiver no quadro, e um
   vídeo muda de quadro 24 vezes por segundo — o contraste deixaria de
   ser medida e viraria sorte. Mais denso embaixo, onde o texto mora. */
.hero-video__veu {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(18, 20, 24, 0.42) 0%,
    rgba(18, 20, 24, 0.14) 38%,
    rgba(18, 20, 24, 0.64) 78%,
    rgba(18, 20, 24, 0.84) 100%
  );
}

.hero-video__inner {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

.hero-video__row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 48px;
  min-height: 144px;
}


/* A manchete com o convite para rolar embaixo. 28 entre os dois: é o
   vão que a CTA tinha aqui, e o convite ocupa o lugar dela. */
.hero-video__chamada {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 28px;
  min-width: 0;
}

/* ── O título contra o cartão ────────────────────────────────────
   Compacto, o cartão mede 265 × 76 e o título mantém a quebra por
   frase ao lado dele até bem abaixo do notebook. Folga medida entre a
   primeira frase e o espaço que sobra ao lado do cartão: 35 a 1024, 20
   a 980, 14 a 960, 7 a 940, ZERO a 920 — e a 901 o título dobra para 3
   linhas.

   O corte fica em 980, onde a folga ainda é de 20px: abaixo dele o
   cartão desce para baixo do convite para rolar, que é o arranjo do
   estreito. (Com os 432 do cartão anterior o mesmo corte caía em 1440.) */
@media not all and (min-width: 980px) {
  .hero-video__row {
    flex-direction: column;
    align-items: flex-start;
    gap: 28px;
    min-height: 0;
  }
}

/* ═════════════════════════════════════════════════════════════════
   O VÍDEO: o cartão que abre e o modal · desde 2026-09-23
   Nasceram na página de carreiras (`.carr-video`, `.carr-modal`) e
   subiram quando a SEGUNDA página — a de produto — precisou deles. O JS
   é o `js/video.js`. Os textos abaixo são os de origem: "o obrigado",
   "o título" e "o herói" são os de carreiras, onde as medidas foram
   tiradas.
   ═════════════════════════════════════════════════════════════════ */

/* ── O cartão do vídeo ───────────────────────────────────────────
   A LINGUAGEM do `.ob__case` da página de obrigado — chapa preta a 24%
   com desfoque de 14, miniatura com raio, rótulo em caixa alta, título e
   a elipse de vidro —, em tamanho COMPACTO. Com os 432 do obrigado ele
   lia como um segundo bloco de conteúdo ao lado do título; pedido do
   Jefferson: "tem q ser mais compacto, esta muito largo". Aqui ele é um
   objeto de ação, e tem a largura do que carrega.

   O raio sai da mesma conta do obrigado, que é raio da miniatura mais o
   respiro (12 + 8 = 20 lá): 10 + 6 = 14 aqui. Com essa conta as duas
   curvas ficam concêntricas, e a chapa não parece mais redonda que a
   foto dentro dela. */
.video-cartao {
  display: flex;
  align-items: center;
  gap: 18px;
  flex: none;
  max-width: 100%;
  /* mais proeminente, a pedido: miniatura de 96, título de 18, play de
     40, e o vidro a partir de BRANCO a 8% (não preto), que destaca mais
     sobre o vídeo. Sem contorno — o projeto nunca usa. */
  padding: 8px 20px 8px 8px;
  border: 0;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  font: inherit;
  color: var(--light-01);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.3s var(--ease-out-soft);
}

.video-cartao:hover { background: rgba(255, 255, 255, 0.14); }

.video-cartao:focus-visible {
  outline: 2px solid var(--light-01);
  outline-offset: 4px;
}

/* A capa: a miniatura com o play PEQUENO por cima, centrado — a pedido
   ("deixa o player pequeno e coloca dentro do card da imagem"). */
.video-cartao__capa {
  position: relative;
  flex: none;
  width: 96px;
  height: 96px;
}

.video-cartao__foto {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 12px;
  object-fit: cover;
}

.video-cartao__txt {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

/* Os corpos do degrau de 560 do obrigado, 11 e 14 — os que ele usa
   quando o cartão encolhe. */
.video-cartao__rot {
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: var(--tag-track);
  text-transform: uppercase;
  color: var(--light-64);
}

.video-cartao__tit {
  font-weight: 400;
  font-size: 18px;
  line-height: 1.4;
  color: var(--light-01);
  white-space: nowrap;
}

/* A elipse do obrigado (`.ob__elipse--card`), com o play no lugar da
   seta, e CENTRADA na altura: num cartão de 76 ela no canto de cima
   ficaria colada na borda. No hover ela clareia e cresce, em vez de
   andar na diagonal. O triângulo desloca 1px à direita — centrado pela
   caixa ele parece puxado para a esquerda, porque a massa dele está no
   lado reto. */
.video-cartao__elipse {
  display: grid;
  place-items: center;
  position: absolute;
  left: 50%;
  top: 50%;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transition: background-color 0.3s var(--ease-out-soft),
    transform 0.4s var(--ease-out-expo);
}

.video-cartao__elipse svg {
  width: 12px;
  height: 12px;
  margin-left: 2px;
}

.video-cartao:hover .video-cartao__elipse {
  background: rgba(255, 255, 255, 0.36);
  transform: scale(1.12);
}

/* ── O herói com vídeo e o cartão, no estreito ── */
@media (max-width: 900px) {
  .hero-video { padding: 96px var(--gutter) 24px; }

  /* No celular a manchete manda: sem o convite para rolar (o gesto é
     óbvio no toque) e com o card do vídeo COMPACTO — uma pílula da
     largura do conteúdo, miniatura de 44 com o play de 20 dentro, só o
     título em 14 (o rótulo "Vídeo" sai; a miniatura com play já diz) e
     um vidro mais leve, para não competir com a headline. */
  /* …e o convite para rolar volta só como ÍCONE, à direita, na linha do
     card (centrado na altura dele, 56): "agora até cabe o icone do
     scroll down do lado direito, mas sem o texto". O texto some por
     `font-size: 0` (continua no DOM para leitor de tela). */
  .hero-video__row {
    position: relative;
    flex-direction: column;
    align-items: flex-start;
    gap: 28px;
    min-height: 0;
  }

  .hero-video .scroll-hint {
    position: absolute;
    right: 0;
    bottom: 18px;
    gap: 0;
    font-size: 0;
  }

  .video-cartao {
    gap: 12px;
    padding: 6px 16px 6px 6px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }

  .video-cartao__capa { width: 44px; height: 44px; }
  .video-cartao__foto { border-radius: 8px; }
  .video-cartao__rot { display: none; }

  .video-cartao__tit {
    font-size: 14px;
    color: var(--light-80);
  }

  .video-cartao__elipse {
    width: 20px;
    height: 20px;
    margin: -10px 0 0 -10px;
  }

  .video-cartao__elipse svg { width: 8px; height: 8px; margin-left: 1px; }
}

/* ── O modal ─────────────────────────────────────────────────────
   `<dialog>` na camada de topo, em tela cheia, com o vídeo centrado. O
   `display: grid` mora em `[open]`: escrito no seletor da classe ele
   VENCERIA o `dialog:not([open]) { display: none }` do navegador —
   folha de autor ganha da do agente —, e o modal fechado continuaria
   desenhado por cima da página. É a mesma armadilha do `[hidden]`. */
.video-modal {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 72px var(--gutter);
  border: 0;
  background: transparent;
  color: var(--light-01);
  overflow: hidden;
}

.video-modal[open] {
  display: grid;
  place-items: center;
}

.video-modal::backdrop {
  background: rgba(12, 13, 16, 0.88);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* A caixa cabe nos DOIS eixos: 16:9 limitado pela largura e pela
   altura da janela menos o respiro. Numa tela baixa e larga, só a
   largura deixaria o vídeo sair por baixo. */
.video-modal__caixa {
  position: relative;
  width: min(1216px, 100%, calc((100svh - 144px) * 16 / 9));
  aspect-ratio: 16 / 9;
  border-radius: var(--r-caixa);
  overflow: clip;
  background: #000;
}

.video-modal__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

/* O fechar é o botão de 42 × 42 com raio 6 do artigo — a mesma forma de
   ação do site —, preenchido e sem traço. Fica no CANTO DA TELA, e não
   sobre o vídeo, para não cobrir os controles nativos do player. */
.video-modal__fechar {
  position: fixed;
  top: 16px;
  right: var(--gutter);
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.12);
  color: var(--light-01);
  cursor: pointer;
  transition: background-color 0.28s var(--ease-out-soft);
}

.video-modal__fechar:hover { background: rgba(255, 255, 255, 0.22); }

.video-modal__fechar:focus-visible {
  outline: 2px solid var(--light-01);
  outline-offset: 4px;
}

.video-modal__fechar svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.4;
}

/* A entrada: o véu acende e a caixa sobe 16px enquanto aparece. Só a
   entrada anima — fechar é instantâneo, que é o que se espera de um
   "fechar". */
@keyframes video-modal-acende { from { opacity: 0; } }
@keyframes video-modal-sobe { from { opacity: 0; transform: translateY(16px) scale(0.98); } }

.video-modal[open],
.video-modal[open]::backdrop { animation: video-modal-acende 0.32s var(--ease-out-soft); }
.video-modal[open] .video-modal__caixa { animation: video-modal-sobe 0.5s var(--ease-out-expo) 0.04s both; }

/* No celular em pé o vídeo é o de retrato, 9:16, e a caixa acompanha. */
@media (max-width: 900px) and (orientation: portrait) {
  .video-modal { padding: 72px var(--gutter) 24px; }

  .video-modal__caixa {
    width: min(100%, calc((100svh - 96px) * 9 / 16));
    aspect-ratio: 9 / 16;
  }
}

@media (prefers-reduced-motion: reduce) {
  .video-modal[open],
  .video-modal[open]::backdrop,
  .video-modal[open] .video-modal__caixa { animation: none; }
}

/* O modal com o vídeo SEMPRE deitado (o filme de produto só existe em
   16:9): a regra do retrato acima não vale para ele. */
@media (max-width: 900px) and (orientation: portrait) {
  .video-modal--deitado .video-modal__caixa {
    width: 100%;
    aspect-ratio: 16 / 9;
  }
}

/* ═════════════════════════════════════════════════════════════════
   OS AROS · Figma 1162:2227
   Subiu do `carreiras.css` em 2026-09-25, quando o Quem somos passou a
   usar o mesmo palco (com a frase "Somos engenheiros, enfermeiros
   auditores…"). O JS é o `js/aros.js`; cada página liga com `initAros`.

   Um palco preso com a mecânica da constelação da home. O JS escreve
   números — `--k` e `--a` em cada aro; `--k`, `--giro` e `--fecha` em cada
   pessoa; `--c`, `--o`, `--v` e `--f` no palco —, e quem desenha é o CSS.

   O que é de cada página fica na folha dela: como a seção entra (no
   Carreiras, por cima da fita da § 2), como sai, e a caixa da frase
   (`--aros-caixa`, `--aros-meia`) quando a copy muda de tamanho.
   ═════════════════════════════════════════════════════════════════ */

/* 250svh de rolagem presa (190 no celular). Foram 400 (roda demais), 200
   (rápido demais) e 280; a divisão em atos está em `ATOS`, no JS. */
.aros { --aros-fita: 250; }

@media (max-width: 860px) {
  .aros { --aros-fita: 190; }
}

.aros__fita {
  height: calc((100 + var(--aros-fita)) * 1svh);
}

.aros__palco {
  position: sticky;
  top: 0;
  display: grid;
  place-items: center;
  height: 100svh;
  padding: 32px 18px;
  overflow: clip;
  background: #fff;

  /* 1 px de design → px de tela. O limite de altura NÃO é o frame
     inteiro (1002): é a faixa que as pessoas ocupam, do topo do avatar-8
     (y 132) à base do avatar-3 e do avatar-7 (y 885) — 753 de design.
     Os aros podem sangrar pela tela; as pessoas não. Da altura saem a
     nav (56) e 24 de respiro de cada lado. */
  --u: min(0.06944vw, calc((100svh - 104px) / 753));

  /* A POSIÇÃO tem uma unidade por eixo. No largo as duas são a própria
     `--u` e a composição é a do Figma, sem distorção. No estreito cada
     eixo ganha a sua (ver o `@media` de 900). `--faixa` é a distância
     mínima entre a frase e as pessoas, e é zero no largo — lá a
     composição do Figma já não põe ninguém sobre o texto. */
  --ux: var(--u);
  --uy: var(--u);
  --faixa: 0px;
  /* Meia nav para baixo, como a constelação: centra a composição na
     faixa livre abaixo do menu. */
  --desce: 28px;

  --c: 1;
  --o: 0;
  --v: 1;
}

/* Com JS o palco nasce vazio e o `aros.js` o preenche. Sem JS, ou
   se o módulo não carregar, os valores acima são o quadro final. */
.js .aros__palco { --c: 0; --f: 0; }

/* A opacidade do PALCO INTEIRO é a entrada por sobreposição (`--f`).
   Ela mora no palco e não no grupo porque é a seção que acende, com
   fundo e tudo — o fundo branco por cima do texto da § 2 é o que o
   apaga. Não há `backdrop-filter` aqui dentro, então a opacidade no
   ancestral não mata vidro nenhum. */
.aros__palco { opacity: var(--f, 1); }

/* O grupo só desce meia nav e apaga no fim (`--v`). Ele NÃO gira nem
   escala: girando como um bloco, aros e pessoas pareciam uma peça só —
   pedido do Jefferson. Na saída cada aro apaga no lugar (`--a`, nele), e
   cada pessoa orbita o centro com o próprio ângulo e o próprio tempo
   (`--giro` e `--fecha`, nela). */
.aros__grupo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: translateY(var(--desce));
  opacity: var(--v);
}

/* ── Os aros ─────────────────────────────────────────────────────
   O SVG exportado, 1470 × 1470, centrado. O traço é Dark-05 (o
   `#7A8599` do export, que é a variável do Figma) e o grupo leva os 10%
   de opacidade do arquivo. O desenho em si nunca se transforma, e na
   saída nenhum aro muda de tamanho: cada um só apaga (`--a`, ver
   `aros.js`). */
.aros__aros {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(1470 * var(--u));
  height: calc(1470 * var(--u));
  transform: translate(-50%, -50%);
  overflow: visible;
  color: var(--dark-05);
}

/* Cada aro cresce do centro do desenho. `view-box` faz o `735px 735px`
   ser o centro em unidade do SVG, e não da caixa do círculo.

   `non-scaling-stroke` mantém o traço em 1,5 de tela enquanto o aro
   cresce e em qualquer largura: sem ele, no celular a unidade cai para
   ~0,5 e o traço de 1,5 de design viraria 0,7px — some. */
.aros__aros circle {
  --k: 1;
  /* A saída: só opacidade. O `--k` da entrada fica em 1 e o aro apaga no
     próprio tamanho — com o raio mudando, o traço fino lia como GIRO. */
  --a: 1;
  transform-box: view-box;
  transform-origin: 50% 50%;
  transform: scale(var(--k));
  opacity: calc(var(--k) * var(--a));
  vector-effect: non-scaling-stroke;
}

/* ── As pessoas ──────────────────────────────────────────────────
   Cada uma guarda o centro do Figma (`--dx`/`--dy`) e a medida (`--t`).
   `--k` leva a pessoa do centro até lá, crescendo de 20% até o tamanho
   cheio.

   A SAÍDA é uma órbita PRÓPRIA em volta do centro dos aros:
   `rotate(giro) translate(posição) rotate(−giro)`. O primeiro `rotate`
   vira o vetor da posição em torno do centro do palco (onde o
   `translate(-50%, -50%)` pôs a pessoa); o segundo desvira a foto, que
   chega ao fim tão reta quanto começou. `--fecha` (de 1 a 0,3) puxa a
   pessoa para o centro e a encolhe junto, acompanhando os aros. Cada uma
   tem o seu `--giro` — as de dentro andam mais — e a sua janela de tempo
   (ver `aros.js`). */
.aros__pessoa {
  --k: 1;
  --giro: 0;
  --fecha: 1;
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--t) * var(--u));
  height: calc(var(--t) * var(--u));
  margin: 0;
  border-radius: 50%;
  overflow: clip;
  /* O eixo vertical sai da FAIXA em volta da frase: `--sy` é o sentido
     (acima ou abaixo, no markup) e `--dy × --sy` é a distância do Figma
     sem sinal. No largo a faixa é zero e a conta volta a ser `dy × u`. */
  transform: translate(-50%, -50%)
    rotate(calc(var(--giro) * 1deg))
    translate(
      calc(var(--dx) * var(--ux) * var(--k) * var(--fecha)),
      calc(var(--sy) * (var(--faixa) + var(--dy) * var(--sy) * var(--uy)) * var(--k) * var(--fecha))
    )
    rotate(calc(var(--giro) * -1deg))
    scale(calc((0.2 + 0.8 * var(--k)) * var(--fecha)));
  /* Aparece no primeiro quarto do caminho: sai do centro já visível, em
     vez de acender só quando chega. */
  opacity: clamp(0, calc(var(--k) * 4), 1);
}

.js .aros__aros circle,
.js .aros__pessoa { --k: 0; }

.aros__pessoa img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── A frase ─────────────────────────────────────────────────────
   Funnel Display 36 / 1,24 numa caixa de 536 — 14,889em, para a quebra
   não mudar com a largura (a lição da § 2 e da constelação). O corpo é
   o `--h2` da página com piso no do Figma escalado.

   SEM `text-wrap: balance`. O Figma quebra guloso — enche cada linha
   até não caber mais — e o `balance` iguala as linhas: com ele a frase
   saía "Conheça os missionários / que já entraram nessa / …" contra o
   "Conheça os missionários que já / entraram nessa guerra contra / …"
   do arquivo. É a mesma armadilha da § 2 da home.

   A pintura é a do Figma: Dark-02 com a lavada `#DDE7FF` recortada no
   texto. A lavada é o SVG que o `get_design_context` exporta, tal como
   veio, esticado na caixa (`preserveAspectRatio='none'`): ela é uma
   ELIPSE INCLINADA — os dois eixos da matriz do Figma não são
   perpendiculares —, e isso o `radial-gradient` do CSS não desenha. A
   primeira versão aproximava pelos eixos (1016 × 935) e clareava a frase
   inteira; no arquivo só o lado direito de cima clareia, e "Conheça" e
   o começo das linhas ficam escuros.

   A ENTRADA É AOS POUCOS (`--c`, de 0 a 1). Só opacidade e 20px lia como
   a frase "caindo" na tela — pedido do Jefferson. A frase agora nasce do
   CENTRO para as bordas, como os aros e as pessoas: uma máscara radial
   de borda larga (40% da caixa) cresce até passar dos cantos, e o
   desfoque vai de 10px a zero no mesmo número. Opacidade por palavra não
   serve aqui: a pintura é UM fundo recortado no parágrafo inteiro, e a
   opacidade de um `<span>` não alcança o fundo do pai.

   A SAÍDA é a da constelação (`--o`): desce 20px e apaga. */
.aros__texto {
  position: relative;
  grid-area: 1 / 1;
  /* 14,889em é a caixa do Carreiras (536 a 36); outra copy define a sua
     em `--aros-caixa`. */
  width: min(var(--aros-caixa, 14.889em), 100%);
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  /* Teto de 36, o valor do Figma a 1440 (2026-09-25, "o tamanho máximo
     deve ser 36"): acima disso a escala dos aros levava a frase a 46,7
     a 1920. Os aros e as pessoas continuam crescendo; só a frase para. */
  font-size: min(36px, max(var(--h2), calc(36 * var(--u))));
  line-height: 1.24;
  text-align: center;
  background:
    url("data:image/svg+xml;utf8,<svg viewBox='0 0 536 180' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><rect x='0' y='0' height='100%' width='100%' fill='url(%23grad)' opacity='1'/><defs><radialGradient id='grad' gradientUnits='userSpaceOnUse' cx='0' cy='0' r='10' gradientTransform='matrix(-61.151 81.1 -16.712 -91.963 629.28 -380)'><stop stop-color='rgba(221,231,255,1)' offset='0'/><stop stop-color='rgba(221,231,255,0)' offset='1'/></radialGradient></defs></svg>"),
    linear-gradient(var(--dark-02), var(--dark-02));
  background-size: 100% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  opacity: calc(1 - var(--o));
  filter: blur(calc((1 - var(--c)) * 10px));
  transform: translateY(calc((1 - var(--c) + var(--o)) * 20px));
  -webkit-mask-image: radial-gradient(farthest-corner at 50% 50%, #000 calc(var(--c) * 140% - 40%), transparent calc(var(--c) * 140%));
  mask-image: radial-gradient(farthest-corner at 50% 50%, #000 calc(var(--c) * 140% - 40%), transparent calc(var(--c) * 140%));
}

@media (max-width: 900px) {
  /* ── O estreito ────────────────────────────────────────────────
     A primeira versão usava UMA unidade (`100vw / 760`) e afastava as
     pessoas na vertical com um multiplicador. Medido: a 375, 6 das 13
     ficavam inteiramente fora da tela e 3 cortadas; a 768, as 13 saíam,
     porque ali a unidade passava a do desktop. Numa tela estreita e alta
     a composição do Figma (1325 de largura por 753 de altura) não cabe
     com a mesma escala nos dois eixos.

     Então cada eixo tem a sua:

     · TAMANHO (fotos e aros) continua em `--u`, da largura com janela de
       760 — com 1440 as fotos de 60 cairiam para 16px.
     · HORIZONTAL (`--ux`): a pessoa mais afastada do centro, a p5 em
       630 de design, encosta na borda com 8px de folga, contando o raio
       dela (45).
     · VERTICAL (`--uy`): as pessoas saem de uma FAIXA em volta da frase
       — meia altura dela, ~3,1 corpos para 4 ou 5 linhas de 1,24, mais
       16 de folga — e ocupam o resto da altura até 64px das bordas,
       contando o raio. A mais afastada na vertical está a 354 de design.

     Sem descer meia nav: a margem de 64 já a desconta, e a faixa precisa
     estar centrada na frase, que é centrada no palco. */
  .aros__palco {
    padding: 32px var(--gutter);
    --u: min(calc(100vw / 760), calc((100svh - 104px) / 753));
    --ux: calc((50vw - 8px - 45 * var(--u)) / 630);
    --faixa: calc(min(36px, max(var(--h2), 36 * var(--u))) * 3.1 + 16px);
    --uy: calc((50svh - 64px - 45 * var(--u) - var(--faixa)) / 354);
    --desce: 0px;

    /* Os AROS no estreito têm unidade própria (`--ua`): o menor aro com
       raio de 58vw, então os seis sangram pelas laterais e o miolo fica
       livre para a frase — "deixando o centro da seção mais livre". As
       pessoas saem da composição do Figma e ganham posições próprias
       (`--mx`/`--my` no markup, px de design nessa unidade), espalhadas
       entre os aros e mais perto do texto: seis acima, sete abaixo, a
       mais afastada a 500 de design. Na vertical a unidade encolhe se a
       janela for baixa (`--uya`), para ninguém passar por baixo do menu. */
    --ua: calc(58vw / 359.25);
    /* `--aros-afasta`: quanto as pessoas se afastam da frase na vertical,
       além da posição de `--my` — zero no Carreiras. Uma frase mais alta
       (a do Quem somos, seis linhas) define o seu, e a unidade vertical
       desconta o mesmo tanto para ninguém passar das bordas. */
    --aros-afasta: 0px;
    --uya: min(var(--ua), calc((50svh - 72px - var(--aros-afasta)) / 525));
  }

  /* `max-width: none`: o reset do site limita `svg` a 100% da largura,
     e aqui o aro PRECISA ser maior que a tela. */
  .aros__aros {
    width: calc(1470 * var(--ua));
    height: calc(1470 * var(--ua));
    max-width: none;
  }

  .aros__pessoa {
    transform: translate(-50%, -50%)
      rotate(calc(var(--giro) * 1deg))
      translate(
        calc(var(--mx) * var(--ua) * var(--k) * var(--fecha)),
        calc((var(--my) * var(--uya) + var(--sy) * var(--aros-afasta)) * var(--k) * var(--fecha))
      )
      rotate(calc(var(--giro) * -1deg))
      scale(calc((0.2 + 0.8 * var(--k)) * var(--fecha)));
  }
}

/* Sem movimento, ou sem JS: o quadro final, parado, sem palco preso. Vem
   DEPOIS das regras acima: mesma especificidade, vence a última. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  .aros__fita { height: auto; }

  .aros__palco {
    position: relative;
    height: auto;
    min-height: 100svh;
  }

  .js .aros__palco { --c: 1; --f: 1; }

  .js .aros__aros circle,
  .js .aros__pessoa { --k: 1; }
}


/* ═════════════════════════════════════════════════════════════════
   O CARD DE ILUSTRAÇÃO — o dos quatro cards do Financial Intelligence
   da home (Figma v11 `722:31120`). Subiu do `home.css` em 2026-09-25,
   quando o Quem somos passou a usar três das ilustrações nos blocos de
   "O que a Rivio é". A entrada é o `cards.js` (`initCardsEntrada`).

   Três ilustrações são VETOR remontado em DOM e uma é foto. Remontar em
   vez de exportar bitmap é o que permite animar o que está DENTRO delas.

   **A unidade aqui é o píxel de design.** Cada ilustração é uma caixa de
   292 × 360 no Figma; `--d` converte por unidade de container
   (`100cqw / 292`), então tudo lá dentro é a medida do Figma e a
   ilustração inteira escala junto com o card. Nenhum px fixo.

   As animações entram por `is-vivo` — motion de ENTRADA é temporizado
   (DIRETRIZES § 5.1). SEM JS o card fica invisível (`opacity: 0`): a
   página que usa o card TEM de ligar o `initCardsEntrada`.
   ═════════════════════════════════════════════════════════════════ */

.card {
  scroll-snap-align: start;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 24px;

  /* DOIS RELÓGIOS, e é isso que faz a fila ser rápida sem virar
     bagunça:

     1 · a CHEGADA dos cards é uma onda curta — 180ms entre um e outro,
         contra uma duração de entrada de 600ms, então eles se sobrepõem
         e o olho lê como um gesto só;
     2 · o movimento INTERNO de cada card é contado a partir da chegada
         DELE (todas as regras lá dentro somam `--base`), não do fim do
         card anterior. Os internos rodam em paralelo.

     Antes o passo era 1000ms, escolhido para o interno de um card
     terminar antes de o próximo aparecer. Isso punha o quarto card
     começando aos 3s e a fila inteira em quase 4 — lento para uma
     fileira de quatro. Esperar o vizinho não é requisito: cada card se
     explica sozinho.

     Um card que entra sozinho — o trilho no celular — recebe ordem 0 e
     anima na hora. */
  --ordem: 0;

  /* FASE 1 · a chegada. 280 de passo × 3 + 560 de duração = 1400ms
     exatos para os quatro terminarem de aparecer. */
  --passo: 280ms;
  --base: calc(var(--ordem) * var(--passo));

  /* FASE 2 · o movimento interno, que só começa quando o último card
     acabou de chegar.

     A conta não fecha sozinha: a história interna de UM card leva ~1,7s
     hoje (a rota desenha em 0,9s a partir dos 0,79s). Quatro delas "uma
     de cada vez" em 1,4s exige comprimir — `--esc` é esse fator, e ele
     escala atrasos E durações juntos, para o desenho não descolar do
     ritmo. A 0,5 cada história cai para ~850ms e sobram 183ms de passo
     entre cards: 3 × 183 + 850 = 1399ms.

     Se ficar apressado, é este único número que se afrouxa. */
  --fase2: 1400ms;
  --esc: 0.5;
  --passo-int: 183ms;
  --dentro: calc(var(--fase2) + var(--ordem) * var(--passo-int));

  opacity: 0;
  transform: translateY(16px);
}

.card.is-vivo {
  animation: card-entra 0.56s var(--ease-out-soft) var(--base) forwards;
}

@keyframes card-entra {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card__arte {
  container-type: inline-size;
  position: relative;
  aspect-ratio: 292 / 360;
  border-radius: var(--r-caixa);
  overflow: clip;

  /* 1 px de design */
  --d: calc(100cqw / 292);
}

/* O Figma tem DOIS contêineres: o card com gap 24 (arte → texto) e o
   bloco de texto com gap 12 (título → descrição). Sem o bloco, o gap do
   card se somava à margem e dava 36 entre título e descrição. */
.card__texto {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* os cards 1 e 3 têm 16 de recuo à direita no texto */
.card__texto--recuo {
  padding-right: 16px;
}

.card__titulo {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 20px;
  line-height: 1.24;
  color: var(--dark-03, #49505c);
}

.card__desc {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--dark-05);
}

/* ═══ 1 · Auditoria contínua ═══════════════════════════════════════ */

.card__arte--fx {
  background: var(--light-01);
}

/* A "Main Image" (`722:31124`) é uma TEXTURA DE PONTOS de 348 × 348
   centrada em 50% / 50%+163, com uma lavada radial por cima. O MCP não
   exporta o preenchimento de imagem — devolveu só o gradiente —, então a
   malha é reconstruída: o passo e o raio saem do render, e a cor é a
   variável do próprio card ("default dark dot fill", #292929).
   Registrado em DIRETRIZES § 8, como o gradiente da § 3. */
.fx__pontos {
  position: absolute;
  left: 50%;
  top: calc(50% + 163 * var(--d));
  width: calc(348 * var(--d));
  height: calc(348 * var(--d));
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background-image: radial-gradient(
    circle at center,
    rgba(41, 41, 41, 0.11) 0,
    rgba(41, 41, 41, 0.11) calc(0.62 * var(--d)),
    transparent calc(0.78 * var(--d))
  );
  background-size: calc(6.5 * var(--d)) calc(6.5 * var(--d));
  -webkit-mask-image: radial-gradient(closest-side, #000 42%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 42%, transparent 100%);
}

/* O halo: no Figma é um círculo de 242 com desfoque de 60 a 25%. O SVG
   exportado veio SEM fill — o `<circle>` sai invisível —, e o
   preenchimento é o Brand/Gradient, o mesmo do prisma
   (#FFBE78 → #E992FF → #6694FF). Por isso ele é CSS e não `<img>`. */
.fx__halo {
  position: absolute;
  left: 50%;
  top: calc(360 * var(--d));
  width: calc(242 * var(--d));
  height: calc(242 * var(--d));
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--grad-brand);
  filter: blur(calc(60 * var(--d)));
  opacity: 0.22;
}

/* Acima das pastas: o nó de cada rota fica na BASE do corpo da pasta e,
   desenhado por baixo, some atrás dela. As linhas não cruzam pasta
   nenhuma — saem da base e descem —, então subir a camada é seguro. */
.fx__linhas {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
}

.fx__rota path {
  fill: none;
  stroke: rgba(122, 133, 153, 0.34);
  stroke-width: 0.8;
  stroke-linecap: round;
  /* desenhadas na entrada */
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
}

/* o pulso que desce pela rota até o núcleo */
.fx__pulso path {
  fill: none;
  stroke: var(--blue);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-dasharray: 14 190;
  stroke-dashoffset: 14;
  opacity: 0;
}

.fx__pasta {
  position: absolute;
  left: calc(var(--x) * var(--d));
  top: calc(var(--y) * var(--d));
  width: calc(53.712 * var(--d));
  opacity: 0;
  transform: translateY(calc(6 * var(--d)));
}

.fx__pasta img {
  display: block;
  width: 100%;
  height: calc(36.508 * var(--d));
}

/* o painel translúcido com o rótulo, que nasce 9,87 abaixo do ícone */
/* O CORPO da pasta.

   O `pasta.svg` é só uma chapa cinza chapada (`#7A8599` a 32%) — a aba.
   O corpo, com o degradê que clareia para baixo, o filete branco em cima
   e o rótulo dentro, é ESTE painel: 43,85 de altura começando 9,87
   abaixo do topo, ou seja passando 17 além da chapa.

   O export dá só `rgba(221,231,255,.18)` porque o Tailwind do MCP
   colapsa fills empilhados; o degradê e o filete saíram do render, e o
   desfoque de fundo é leve — 3, não 8: a 8 o cinza da aba sumia e o
   cliente apontou o exagero. */
.fx__rot {
  position: absolute;
  left: 0;
  top: calc(9.866 * var(--d));
  display: block;
  width: 100%;
  height: calc(43.847 * var(--d));
  padding: calc(var(--ty) * var(--d)) 0 0 calc(5.968 * var(--d));
  border-top: calc(0.7 * var(--d)) solid rgba(255, 255, 255, 0.9);
  border-radius: calc(5.968 * var(--d));
  background: linear-gradient(rgba(221, 231, 255, 0.18), rgba(221, 231, 255, 0.18)),
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0.88) 62%,
      rgba(255, 255, 255, 0.94) 100%
    );
  backdrop-filter: blur(calc(3 * var(--d)));
  -webkit-backdrop-filter: blur(calc(3 * var(--d)));
  box-shadow: 0 calc(2 * var(--d)) calc(7 * var(--d)) rgba(49, 53, 61, 0.06);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: calc(7.46 * var(--d));
  line-height: 1;
  color: rgba(0, 0, 0, 0.76);
  white-space: nowrap;
}

/* o nó de onde cada rota sai, na base do corpo da pasta */
.fx__no circle {
  fill: rgba(122, 133, 153, 0.55);
}

.fx__nucleo {
  position: absolute;
  left: calc(120 * var(--d));
  top: calc(274 * var(--d));
  width: calc(51 * var(--d));
  height: calc(46 * var(--d));
  opacity: 0;
  transform: scale(0.72);
  transform-origin: 50% 60%;
}

.fx__prisma {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.fx__molecula {
  position: absolute;
  left: calc(6.6 * var(--d));
  top: calc(7.5 * var(--d));
  width: calc(38.06 * var(--d));
  height: calc(32.9 * var(--d));
}

.fx__ponto {
  position: absolute;
  left: calc((var(--x) - 120) * var(--d));
  top: calc((var(--y) - 274) * var(--d));
  width: calc(2.6 * var(--d));
  height: calc(2.6 * var(--d));
}

/* ═══ 2 · Controle do ciclo ════════════════════════════════════════ */

.card__arte--cc {
  background: var(--light-01);
}

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

/* O painel tem 960 × 540 e mora em 48 · 64: o card recorta e o que se vê
   é o canto superior esquerdo dele, em escala 1:1 do Figma. */
.cc__painel {
  position: absolute;
  left: calc(48 * var(--d));
  top: calc(64 * var(--d));
  display: flex;
  gap: 0;
  width: calc(960 * var(--d));
  height: calc(540 * var(--d));
  padding: calc(7.75 * var(--d));
  border: calc(0.25 * var(--d)) solid rgba(255, 255, 255, 0.32);
  border-radius: calc(19 * var(--d));
  background: rgba(255, 255, 255, 0.68);
  backdrop-filter: blur(calc(30 * var(--d)));
  -webkit-backdrop-filter: blur(calc(30 * var(--d)));
  opacity: 0;
  transform: translateY(calc(10 * var(--d)));
}

.cc__lateral {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: calc(4 * var(--d));
  align-self: stretch;
  padding: calc(6 * var(--d));
  border-radius: calc(8 * var(--d));
  background: rgba(255, 255, 255, 0.32);
}

/* QUADRADOS, com o ícone centrado: 28 × 28, que é o que a barra
   colapsada do Command Center mostra. Eu os tinha feito do tamanho do
   conteúdo, com o ícone à esquerda. */
.cc__item {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(28 * var(--d));
  height: calc(28 * var(--d));
  border-radius: calc(6 * var(--d));
  background: rgba(255, 255, 255, 0.4);
  opacity: 0;
}

/* o item ativo é branco mais forte — no Figma é o das pastas */
.cc__item--ativo {
  background: rgba(255, 255, 255, 0.9);
}

/* Cada ícone com a proporção dele — os SVG do Figma vêm com
   `preserveAspectRatio="none"` e uma medida única distorce todos. */
.cc__ico {
  display: block;
  width: calc(var(--iw) * var(--d));
  height: calc(var(--ih) * var(--d));
}

.cc__col {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: calc(20 * var(--d));
  min-width: 0;
  padding: calc(4 * var(--d)) calc(20 * var(--d));
  font-family: 'Funnel Sans', system-ui, sans-serif;
}

.cc__h1 {
  font-weight: 500;
  font-size: calc(15 * var(--d));
  line-height: calc(18 * var(--d));
  color: #222226;
}

.cc__bloco {
  display: flex;
  flex-direction: column;
  gap: calc(8 * var(--d));
  width: calc(756 * var(--d));
}

.cc__h2 {
  font-weight: 500;
  font-size: calc(12 * var(--d));
  line-height: calc(16 * var(--d));
  color: #222226;
}

.cc__grafico {
  display: flex;
  flex-direction: column;
  gap: calc(12 * var(--d));
  padding: calc(12 * var(--d));
  border-radius: calc(8 * var(--d));
  background: rgba(255, 255, 255, 0.48);
}

.cc__total {
  font-size: calc(7 * var(--d));
  line-height: calc(10 * var(--d));
  color: #777482;
}

.cc__total b {
  font-weight: 400;
  color: #4b4a52;
}

.cc__barra {
  display: flex;
  gap: calc(2 * var(--d));
}

.cc__faixa {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  width: calc(var(--w) * var(--d));
  padding: calc(4 * var(--d));
  background: var(--c);
  color: var(--t);
  font-size: calc(10 * var(--d));
  line-height: calc(14 * var(--d));
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* crescem na entrada */
  transform: scaleX(0);
  transform-origin: left center;
}

/* a verde é `flex: 1` no Figma: ocupa o que sobra */
.cc__faixa--resto {
  flex: 1;
  width: auto;
  min-width: 0;
}

.cc__faixa:first-child {
  border-radius: calc(4 * var(--d)) 0 0 calc(4 * var(--d));
}

.cc__faixa:last-child {
  border-radius: 0 calc(4 * var(--d)) calc(4 * var(--d)) 0;
}

.cc__legenda {
  display: flex;
  gap: calc(8 * var(--d));
  font-size: calc(6 * var(--d));
  line-height: calc(10 * var(--d));
  color: rgba(0, 0, 0, 0.52);
}

.cc__legenda span {
  display: flex;
  align-items: center;
  gap: calc(4 * var(--d));
  white-space: nowrap;
}

.cc__legenda img {
  width: calc(4 * var(--d));
  height: calc(4 * var(--d));
}

/* As abas: 4px de tipo, sublinhado indigo na ativa e a borda de 0,5 do
   grupo — as medidas do Figma, não as que eu tinha estimado. */
.cc__abas {
  display: flex;
  gap: calc(2 * var(--d));
  align-self: stretch;
  border-bottom: calc(0.5 * var(--d)) solid #e5e5e7;
  font-weight: 500;
  font-size: calc(4 * var(--d));
  line-height: calc(6 * var(--d));
  color: #777482;
}

.cc__abas span {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(4 * var(--d));
  padding: calc(6 * var(--d)) calc(8 * var(--d));
  white-space: nowrap;
}

.cc__abas img {
  width: calc(8 * var(--d));
  height: calc(8 * var(--d));
}

.cc__abas .is-ativa {
  border-bottom: calc(1 * var(--d)) solid #7d70e4;
  color: #222226;
}

.cc__busca {
  display: flex;
  align-items: center;
  gap: calc(8 * var(--d));
  align-self: stretch;
  padding: calc(4 * var(--d)) calc(12 * var(--d));
  border: calc(0.5 * var(--d)) solid #e5e5e7;
  border-radius: calc(4 * var(--d));
  background: rgba(255, 255, 255, 0.48);
  font-size: calc(8 * var(--d));
  line-height: calc(12 * var(--d));
  color: #777482;
}

.cc__busca img {
  width: calc(var(--iw) * var(--d));
  height: calc(var(--ih) * var(--d));
}

.cc__tabela {
  align-self: stretch;
  border-radius: calc(8 * var(--d));
  overflow: clip;
}

.cc__coluna {
  padding: calc(8 * var(--d)) calc(12 * var(--d));
  background: #f8f8f8;
  font-weight: 500;
  font-size: calc(7 * var(--d));
  line-height: calc(10 * var(--d));
  color: #92909b;
}

/* ═══ 3 · Faturamento e glosas ═════════════════════════════════════ */

/* O gradiente mora num FILHO, não no container.

   `--d` usa unidade de container (`cqw`) e um elemento não consulta a si
   mesmo: dentro do próprio `.card__arte` o `100cqw` cai para o container
   de fora e o raio computava **3964px** em vez de 804 — o gradiente
   inteiro saía da tela e o card ficava branco. */
.rm__fundo {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4)),
    radial-gradient(
      calc(804 * var(--d)) calc(455 * var(--d)) at calc(146 * var(--d)) 0,
      #ffffff 0%,
      #c5d7ff 77.06%,
      #96b6ff 88.53%,
      #6694ff 100%
    );
}

.rm__pilha {
  position: absolute;
  inset: 0;
}

.rm__folha {
  position: absolute;
  left: calc(var(--x) * var(--d));
  top: calc(var(--y) * var(--d));
  transform-origin: 50% 100%;
  display: flex;
  align-items: center;
  gap: calc(var(--pl) * var(--d));
  width: calc(var(--w) * var(--d));
  height: calc(var(--h) * var(--d));
  padding: calc(var(--pl) * var(--d)) calc(var(--pr) * var(--d)) calc(var(--pl) * var(--d))
    calc(var(--pl) * var(--d));
  border: calc(var(--bd) * var(--d)) solid rgba(255, 255, 255, 0.32);
  border-radius: calc(var(--r) * var(--d));
  background: rgba(255, 255, 255, 0.68);
  /* cada folha tem o SEU desfoque de fundo, borda e sombra — o Figma
     escalona os cinco valores junto com o tamanho */
  backdrop-filter: blur(calc(var(--bb) * var(--d)));
  -webkit-backdrop-filter: blur(calc(var(--bb) * var(--d)));
  box-shadow: 0 calc(var(--sy) * var(--d)) calc(var(--sb) * var(--d))
    rgba(0, 0, 0, var(--sa));
  /* a profundidade de campo do Figma: quanto mais atrás, mais fora de foco */
  filter: blur(calc(var(--bl) * var(--d)));
  opacity: 0;
  /* cada folha chega de baixo, um pouco menor, e assenta na pilha */
  transform: translateY(calc(26 * var(--d))) scale(0.94);
}

.rm__folha img {
  flex: none;
  width: calc(var(--ic) * var(--d));
  height: calc(var(--ic) * var(--d));
}

.rm__txt {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-family: 'Funnel Sans', system-ui, sans-serif;
}

.rm__txt b {
  font-weight: 700;
  font-size: calc(var(--ts) * var(--d));
  line-height: calc(var(--tl) * var(--d));
  color: #4b4a52;
}

.rm__txt i {
  overflow: hidden;
  font-style: normal;
  font-size: calc(var(--ds) * var(--d));
  line-height: calc(var(--dl) * var(--d));
  color: #777482;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ═══ 4 · Performance em contrato ══════════════════════════════════ */

.card__arte--foto img {
  position: absolute;
  left: 0;
  top: 0.12%;
  width: 100%;
  height: 108.15%;
  object-fit: cover;
  transform: scale(1.06);
  transition: transform 1.4s var(--ease-out-soft) 0.25s;
}

/* ═════════════════════════════════════════════════════════════════
   As animações — entram com `is-vivo`
   ═════════════════════════════════════════════════════════════════ */

.card.is-vivo .fx__pasta {
  animation: card-sobe calc(0.62s * var(--esc)) var(--ease-out-soft) forwards;
  animation-delay: calc(var(--dentro) + 250ms * var(--esc) + var(--i) * 90ms * var(--esc));
}

.card.is-vivo .fx__rota path {
  animation: fx-desenha calc(0.9s * var(--esc)) var(--ease-out-soft) forwards;
  animation-delay: calc(var(--dentro) + 610ms * var(--esc));
}

.card.is-vivo .fx__rota path:nth-child(2) { animation-delay: calc(var(--dentro) + 670ms * var(--esc)); }
.card.is-vivo .fx__rota path:nth-child(3) { animation-delay: calc(var(--dentro) + 730ms * var(--esc)); }
.card.is-vivo .fx__rota path:nth-child(4) { animation-delay: calc(var(--dentro) + 790ms * var(--esc)); }

.card.is-vivo .fx__nucleo {
  animation: fx-nucleo calc(0.7s * var(--esc)) var(--ease-out-expo) forwards;
  animation-delay: calc(var(--dentro) + 970ms * var(--esc));
}

/* `--atraso`, e não `--d`: aqui `--d` é o píxel de design (um
   comprimento) e somá-lo a um tempo invalida o `animation-delay`
   inteiro — a animação cairia para zero e os quatro pulsos sairiam
   juntos. */
.card.is-vivo .fx__pulso path {
  animation: fx-pulso 2.6s linear infinite;
  animation-delay: calc(var(--dentro) + 1450ms * var(--esc) + var(--atraso, 0ms));
}

.card.is-vivo .cc__painel {
  animation: card-sobe calc(0.8s * var(--esc)) var(--ease-out-soft) forwards;
  animation-delay: calc(var(--dentro) + 250ms * var(--esc));
}

.card.is-vivo .cc__item {
  animation: cc-item calc(0.5s * var(--esc)) var(--ease-out-soft) forwards;
  animation-delay: calc(var(--dentro) + 550ms * var(--esc) + var(--i) * 70ms * var(--esc));
}

.card.is-vivo .cc__faixa {
  animation: cc-faixa 0.8s var(--ease-out-expo) forwards;
  animation-delay: calc(var(--dentro) + 850ms * var(--esc) + var(--i) * 120ms * var(--esc));
}

/* A pilha se monta de trás para a frente: 140ms entre uma folha e a
   seguinte, cada uma subindo 26 e crescendo de 0,94 até assentar. */
.card.is-vivo .rm__folha {
  animation: rm-empilha 0.72s var(--ease-out-expo) forwards;
  animation-delay: calc(var(--dentro) + 250ms * var(--esc) + var(--i) * 140ms * var(--esc));
}

.card.is-vivo .card__arte--foto img {
  transform: scale(1);
  transition-delay: calc(var(--dentro) + 250ms * var(--esc));
}

@keyframes rm-empilha {
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes card-sobe {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes cc-item {
  to {
    opacity: 1;
  }
}

@keyframes fx-desenha {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes fx-nucleo {
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes fx-pulso {
  0% {
    stroke-dashoffset: 14;
    opacity: 0;
  }
  8% {
    opacity: 0.9;
  }
  46% {
    stroke-dashoffset: -190;
    opacity: 0.9;
  }
  54%,
  100% {
    stroke-dashoffset: -190;
    opacity: 0;
  }
}

@keyframes cc-faixa {
  to {
    transform: scaleX(1);
  }
}

/* Sem movimento, tudo no quadro final. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  .card,
  .fx__pasta,
  .fx__nucleo,
  .cc__painel,
  .cc__item,
  .rm__folha {
    opacity: 1;
    transform: none !important;
    animation: none;
  }
  .fx__rota path {
    stroke-dashoffset: 0;
  }
  .fx__pulso {
    display: none;
  }
  .cc__faixa {
    transform: none;
    animation: none;
  }
  .card__arte--foto img {
    transform: none;
  }
}


/* ═════════════════════════════════════════════════════════════════
   BLOCOS DO QUEM SOMOS QUE A IMPRENSA TAMBÉM USA · desde 2026-09-27
   Nasceram no `quem-somos.css` (como `.qs-cabeca`, `.qs-ganhos` e
   `.qs-inv`) e subiram quando a Imprensa pediu os mesmos: o cabeçalho
   empilhado, os cards dos benefícios ("A Rivio em números") e os
   investidores em placas. Movidos sem mudar valor — a geometria do
   Quem somos foi comparada antes e depois.
   ═════════════════════════════════════════════════════════════════ */

/* O CABEÇALHO DE SEÇÃO EMPILHADO — etiqueta, título e, quando há, o
   texto embaixo — com os valores do cabeçalho da HOME (2026-09-27,
   "revise o nosso padrão de espaçamento entre título e texto… a gente
   já tem um padrão disso na página home… não pode ficar inventando regra
   de CSS"): o da seção escura e do Contato (`componentes.css`:
   `.dark-section__title` e `.cta__block` / `.cta__lede`). Etiqueta →
   título 18 (12 abaixo de 861; era 24, o da seção escura, até
   2026-09-28 — ver o título logo abaixo), título `var(--h2)` até 712,
   título → texto 24, texto 16 / 1,5 / 300 (o `--p-mobile` abaixo de
   861).
   Substitui o cabeçalho próprio do "Como operamos" (vão de 18) e o bloco
   da Visão empilhado dos investidores (18 / 32 / 14): os 18 e o texto de
   14 são do formato da VISÃO — título AO LADO das colunas —, que
   continua valendo no "Quem constrói". Usam: "Como operamos" e
   "Investidores" do Quem somos; "Fundadores" e "Investidores" da
   Imprensa. */
.cabeca-pilha {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: min(1216px, calc(100% - 2 * var(--gutter)));
  margin: 0 auto;
}

/* O TÍTULO de seção CLARA é o da Visão da home (2026-09-28, "isso aqui
   está representando o nosso estilo padrão de título quando a seção é
   fundo branco? O espaçamento entre tag e título… a cor do título"): 18
   da etiqueta (12 no celular — o `gap` do `.vision__lead`), 36 / 1,24 /
   400, Dark-02 com a lavada azul-clara vinda de fora do canto superior
   direito, recortada no texto (os mesmos 540 × 470 a 366, −190 da
   `.vision__title` e do `.qs-quem__titulo`). O 24 e o Dark-01 chapado
   eram os da seção ESCURA (`.dark-section__title`), e o componente só
   aparece em seção clara. No celular a lavada sai e a cor fica chapada,
   como na Visão: numa caixa estreita a parte clara caía sobre a segunda
   linha. */
.cabeca-pilha .leitura__titulo {
  max-width: 712px;
  margin-top: 18px;
  background-image: radial-gradient(
      540px 470px at 366px -190px,
      #dde7ff 0%,
      rgba(221, 231, 255, 0) 100%
    ),
    linear-gradient(90deg, var(--dark-02), var(--dark-02));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.cabeca-pilha__texto {
  max-width: 560px;
  margin: 24px 0 0;
  font-weight: 300;
  font-size: 16px;
  line-height: 1.5;
  color: #0f0f0f;
}

@media (max-width: 860px) {
  .cabeca-pilha .leitura__titulo {
    margin-top: 12px;
    background-image: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--dark-02);
  }
  .cabeca-pilha__texto { font-size: var(--p-mobile); }
}

/* ── § 6b · Os benefícios na prática (claro) ─────────────────────
   Seção própria desde 2026-09-27, no formato da referência que o
   Jefferson mandou ("separada da sessão… degradê cinza claro, de cima
   para baixo, indo para o branco"): o título no centro e os quatro
   cards lado a lado, cada um descendo um tanto (`--desce` no markup),
   BRANCOS no alto e se dissolvendo no fundo embaixo. O cinza do topo é
   o Dark-05 a 18% sobre o branco. Sem contorno: a etiqueta se separa do
   card pela sombra curta. Tipografia de peças existentes: o título é o
   `.leitura__titulo`; o número, o `.cs-res__val` dos cases (300, 44–64,
   a unidade num `small` MENOR e em minúscula — "MINUTOS" na caixa alta
   do `.cs-num__val small` brigava com o número); a frase a 14 em
   Dark-03 (o Dark-05 da referência dava 3,4:1 no pé). A ETIQUETA é de
   uma linha nos quatro: 12, o corpo das etiquetas do site, com ícone de
   20 — "Aprovação na primeira submissão" mede 225 a 14 e não cabia no
   card de 236 por dentro. Por isso também quatro colunas só de 1280
   para cima (a 1101 o card tinha 195 por dentro); abaixo, duas.
   O degradê termina no Light-01, o fundo da seção seguinte (em branco
   puro ficava uma emenda). */
.ganhos {
  padding: 120px var(--gutter) 160px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--dark-05) 18%, #fff) 0%, var(--light-01) 100%);
}

.ganhos__titulo {
  max-width: 712px;
  margin: 0 auto 72px;
  text-align: center;
  text-wrap: balance;
}

.ganhos__lista {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: start;
  gap: 16px;
  max-width: 1216px;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.ganhos__card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: 380px;
  margin-top: var(--desce, 0px);
  padding: 24px;
  border-radius: var(--r-caixa);
  background: linear-gradient(180deg, #fff 0%, rgba(255, 255, 255, 0.7) 45%, rgba(255, 255, 255, 0) 100%);
}

.ganhos__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 4px 10px 4px 4px;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(24, 27, 31, 0.08), 0 6px 14px -6px rgba(24, 27, 31, 0.12);
  font-weight: 400;
  font-size: 12px;
  line-height: 1.3;
  color: var(--dark-03);
  white-space: nowrap;
}

.ganhos__chip img {
  width: 20px;
  height: 20px;
  flex: none;
}

.ganhos__val {
  margin: 40px 0 0;
  font-weight: 300;
  font-size: clamp(44px, 4.45vw, 64px);
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--dark-01);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ganhos__val small {
  margin-left: 0.2em;
  font-weight: 300;
  font-size: 0.36em;
  line-height: 1;
  letter-spacing: 0;
  color: var(--dark-05);
}

.ganhos__frase {
  margin: auto 0 0;
  padding-top: 40px;
  font-weight: 300;
  font-size: 14px;
  line-height: 1.5;
  color: var(--dark-03);
  text-wrap: pretty;
}

.ganhos__frase strong {
  font-weight: 400;
  color: var(--dark-01);
}

/* Abaixo de 1280: dois por linha; a coluna da direita desce 48, o
   degrau da referência em duas colunas. */
@media not all and (min-width: 1280px) {
  .ganhos__lista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ganhos__card { margin-top: 0; }
  .ganhos__card:nth-child(even) { margin-top: 48px; }
}

@media (max-width: 860px) {
  .ganhos { padding: 80px var(--gutter) 96px; }
  .ganhos__titulo { margin-bottom: 40px; }
  .ganhos__lista { gap: 12px; }
  .ganhos__card { min-height: 320px; padding: 24px; }
}

/* Uma coluna, sem degrau — empilhado, o degrau só abriria vão. A 640 e
   não a 560: em duas colunas a etiqueta mais longa (233) só cabe com o
   card de 281, o que pede ~615 de tela. */
@media (max-width: 640px) {
  .ganhos__lista { grid-template-columns: minmax(0, 1fr); }
  .ganhos__card,
  .ganhos__card:nth-child(even) { min-height: 0; margin-top: 0; }
  .ganhos__val { margin-top: 32px; }
  .ganhos__frase { padding-top: 32px; }
}

/* ── Os cards de números: a MICROINTERAÇÃO, em todo lugar ──────────
   2026-09-27: "essa seção precisa de micro-interação… um efeito mais
   elaborado quando os cards vão aparecendo. Em todos os lugares que esse
   formato aparece". É a dos números de Produtos, que era só de lá, agora
   do formato (benefícios do Quem somos, números da Imprensa e de
   Produtos):

   A CHEGADA, presa ao scroll (`js/ganhos.js` escreve `--q` de 0 a 1 na
   seção e liga `.ganhos--movel`; em Produtos quem escreve é o
   `produtos.js`, e a seção diz `data-ganhos-proprio`). Três camadas no
   mesmo número: o CARD sobe a partir de `--vel`svh — 14, 28, 42, 56, da
   esquerda para a direita, a onda de Produtos — e acende; o NÚMERO sobe
   32px a mais dentro dele; o ÍCONE cresce de 80% e a FRASE acende por
   último. Só `translate`, `scale` e `opacity`: o hover é `transform` e
   não briga com nenhum dos três. Sem JS ou com movimento reduzido, `--q`
   é 1 e tudo está no lugar.

   O HOVER (ponteiro fino): o card sobe 6px, e só. Ele teve sombra, a
   malha de pontos da CTA seguindo o ponteiro, o ícone crescendo e a frase
   escurecendo; o cliente tirou tudo (2026-09-27, "não faz sentido…
   a sombra embaixo do card e… essa malha de pontos dentro. Vamos fazer
   só o hover dele subindo um pouquinho"). */
.ganhos__card { transition: transform 0.7s var(--ease-out-expo); }

.ganhos__card:nth-child(1) { --vel: 14; }
.ganhos__card:nth-child(2) { --vel: 28; }
.ganhos__card:nth-child(3) { --vel: 42; }
.ganhos__card:nth-child(4) { --vel: 56; }

/* O ícone sozinho na placa de 32 — o tamanho dos cards de case (o
   `.case-cards li > img`). O SVG é a placa branca com o traço; sobre o
   card branco ela ganha a sombra curta das etiquetas (sem contorno). */
.ganhos__icone {
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(24, 27, 31, 0.08), 0 6px 14px -6px rgba(24, 27, 31, 0.12);
}

.ganhos--movel .ganhos__card {
  translate: 0 calc((1 - var(--q, 1)) * var(--vel, 0) * 1svh);
  opacity: clamp(0, var(--q, 1) * 2.4 - 0.2, 1);
}

:is(.ganhos--movel, [data-ganhos-proprio]) .ganhos__val {
  translate: 0 calc((1 - var(--q, 1)) * 32px);
}

:is(.ganhos--movel, [data-ganhos-proprio]) :is(.ganhos__icone, .ganhos__chip) {
  scale: calc(0.8 + 0.2 * clamp(0, var(--q, 1) * 2 - 0.5, 1));
}

:is(.ganhos--movel, [data-ganhos-proprio]) .ganhos__frase {
  opacity: clamp(0, var(--q, 1) * 2.5 - 1.3, 1);
}

@media (hover: hover) and (pointer: fine) {
  .ganhos__card:hover { transform: translateY(-6px); }
}

@media (prefers-reduced-motion: reduce) {
  .ganhos__card { transition: none; }
}

/* ── Investidores ─────────────────────────────────────────────────── */
/* 160 em cima e embaixo (era 120; 2026-09-27, "um pouco mais alta…
   para arejar, senão fica espremida entre a seção escura do Advisory e
   a CTA") — o respiro da aspa escura dos cases (`.case-aspa`) e do pé
   dos benefícios; 96 no celular (era 80), o pé dos benefícios. */
.investidores {
  padding: 160px 0;
  background: #fff;
}

/* O título numa linha e a descrição embaixo (2026-09-27): o cabeçalho
   `.cabeca-pilha` (ver "Como operamos"). */

/* Os investidores em PLACAS (2026-09-27, "o mesmo formato da nossa
   seção de escala, o logo certo dessas empresas dentro de cards… ainda
   no fundo claro"): a placa do mural da Escala (`.qs-mural`, proporção
   397 × 280, raio da caixa, 24 de respiro) em Light-01 sobre o branco
   da seção — o fundo dos cards claros dos cases —, quatro numa linha.
   Eram os nomes em texto, com fio em cima, enquanto não havia logo.
   O `--w` do markup é a largura do logo a 1440 e vira FRAÇÃO da placa
   (÷ 247, a largura de dentro dela ali), como no mural da Escala. */
.investidores__mural {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  width: min(1216px, calc(100% - 2 * var(--gutter)));
  margin: 56px auto 0;
  padding: 0;
  list-style: none;
}

.investidores__mural li {
  display: grid;
  place-items: center;
  aspect-ratio: 397 / 280;
  padding: 24px;
  border-radius: var(--r-caixa);
  background: var(--light-01);
}

.investidores__mural img {
  display: block;
  width: calc(var(--w) / 247 * 100%);
  height: auto;
}

@media (max-width: 1100px) {
  .investidores__mural li { padding: 16px; }
}

@media (max-width: 860px) {
  .investidores { padding: 96px 0; }

  /* Duas por linha. Na placa pequena o logo ocupa mais dela (÷ 190 em
     vez de 247; o Endeavor chega a 87%): a 390, com ÷ 247, o "positive
     ventures" ficava com letra de 7px. Com teto de 1,3× o tamanho do
     desktop: nas placas largas de 641 a 860 o ÷ 190 passava de 80%. */
  .investidores__mural { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 40px; }
  .investidores__mural li { padding: 12px; }
  .investidores__mural img { width: min(calc(var(--w) / 190 * 100%), calc(var(--w) * 1.3px)); }
}

/* ═════════════════════════════════════════════════════════════════
   A CONSTELAÇÃO — `.constelacao` e `.constelacao__foto` (2026-09-28)

   O grupo de fotos que cresce do centro de um palco preso e, na saída,
   orbita. Nasceu na § 4 da home (Financial Intelligence, `fi.js`) e subiu
   para cá quando o "Quem constrói" do Quem somos passou a ser uma
   constelação (`quem-somos.js`). O PALCO é de cada página e declara as
   variáveis que isto lê:

     --u        o píxel de design (o frame do Figma é 1440 × 816)
     --s        a escala do grupo (nasce pequena e cresce até 1)
     --g        a órbita da saída, em graus
     --v        a opacidade do grupo
     --dy-mult  quanto a composição se afasta na vertical (celular)
     --dy-u     (opcional) o píxel VERTICAL, quando a página precisa
                limitá-lo pela altura da tela; sem ele vale
                `--u × --dy-mult`, que é o que a home usa
     --dx-u     (opcional) o píxel HORIZONTAL, idem; sem ele vale `--u`
     --dy-px    (opcional, por foto) a posição vertical FINAL, em px, quando
                a página desenha as posições à mão (o Quem somos no
                celular); sem ele vale `--dy` na escala acima

   Cada foto traz no `style` a coordenada do centro dela em relação ao
   centro do palco (`--dx`, `--dy`), a caixa (`--w`, `--h`) e o raio
   (`--r`), tudo em píxel de design. Os valores e os comentários abaixo
   são os da home, sem mudança — ela foi comparada pixel a pixel antes e
   depois da mudança de lugar.
   ═════════════════════════════════════════════════════════════════ */


/* Um zoom só, em torno do centro: as fotos guardam a coordenada final
   (parte-02) e quem cresce é o grupo. */
.constelacao {
  position: absolute;
  inset: 0;
  /* meia nav para baixo: é o que centra a composição na faixa livre em
     vez de na tela inteira. O `translate` vem antes do `scale` na lista,
     logo é aplicado DEPOIS — não escala junto. */
  /* A ordem importa: a lista é aplicada da direita para a esquerda, ou
     seja escala, depois GIRA, depois desce. Assim o giro acontece em
     torno do centro da composição e o deslocamento de meia nav não gira
     junto. */
  transform: translateY(28px) rotate(calc(var(--g) * 1deg)) scale(var(--s));
  opacity: var(--v);
  pointer-events: none;
}

/* O recorte arredondado mora na IMAGEM, não na caixa: assim a caixa
   pode deixar uma pastilha transbordar sem perder o canto da foto. */
.constelacao__foto {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  margin: 0;
  border-radius: calc(var(--r) * var(--u));
  overflow: clip;
  /* O `rotate` NEGATIVO no fim da lista é o que faz a foto ORBITAR sem
     girar no próprio eixo.

     A lista se aplica da direita para a esquerda, então este giro
     acontece PRIMEIRO, em torno do centro da própria foto. Depois o
     grupo gira +`--g` em torno do centro da seção e leva a foto junto —
     e esse giro do grupo também gira a foto. Os dois se cancelam: sobra
     o deslocamento em arco, que é a órbita, e a foto chega ao fim do
     movimento tão reta quanto começou.

     Pedido explícito do cliente: "todas devem rotacionar para a direita
     como se o centro fosse a seção […] a imagem não deve rotacionar no
     próprio eixo". */
  transform: translate(-50%, -50%)
    translate(
      calc(var(--dx) * var(--dx-u, var(--u))),
      var(--dy-px, calc(var(--dy) * var(--dy-u, calc(var(--u) * var(--dy-mult)))))
    )
    rotate(calc(var(--g) * -1deg));
}

/* O `<picture>` não gera caixa, mas é ele o pai da `img` na herança: sem
   repassar o raio, o `inherit` dela chegaria em zero. */
.constelacao__foto picture {
  display: contents;
  border-radius: inherit;
}

.constelacao__foto picture img {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}
