/* ═════════════════════════════════════════════════════════════════
   RIVIO — home.css · camada 4 de 5, e SÓ a home a carrega

   As seções da home: clientes, Intelligence Layers (`lay`), Financial
   Intelligence (`fi`), os quatro cards (`cards`, `card`, `cc`, `fx`,
   `rm`), Cases, as duas versões do Advisory (`advisory`, `altv`), Visão e
   o palco do CTA que cresce (`cta-stage`).

   Os blocos estão na ordem em que estavam no `main.css` de origem, e por
   isso a leitura ainda não segue a rolagem da página: a arrumação interna
   é reordenação, e reordenação se faz com o verificador na mão.
   ═════════════════════════════════════════════════════════════════ */

/* Movimento reduzido: a troca ainda acontece, mas sem deslocamento e
   sem espera — quem liga essa opção não deve esperar por coreografia. */
@media (prefers-reduced-motion: reduce) {
  .lay__selo {
    transform: none;
    transition-duration: 0.01s;
  }
  .lay__painel[data-aberto] .lay__selo {
    transition-delay: 0s;
  }
}

/* ─────────────────────────────────────────────────────────────────
   Clientes
   ───────────────────────────────────────────────────────────────── */

.clients {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 28px;
  /* branco, a pedido do cliente. Era `Light-01`. */
  background: #fff;
}

/* Marquee — estado parado. O trilho fica fora do layout e a cópia
   escondida, então acima de 900px a fileira se comporta exatamente como
   o frame do Figma. As regras de movimento estão no breakpoint. */
.marquee {
  display: flex;
  width: 100%;
}

.marquee__track {
  display: contents;
}

/* Seletor com o combinador de filho de propósito: a fileira também carrega
   `.clients__row` / `.dark-section__foot`, que são `display: flex` e vêm
   depois no arquivo. Sem subir a especificidade, o clone apareceria no
   desktop e as duas fileiras dividiriam a largura. */
.marquee__track > .marquee__row--clone {
  display: none;
}

.clients__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  max-width: 1384px;
  margin: 0 auto;
}

/* `--w` é a largura de layout do Figma, declarada por logo no markup.
   Fica em custom property (e não em `style="width:…"`) justamente para o
   breakpoint poder soltá-la — inline venceria qualquer regra. */
.clients__row img {
  height: 40px;
  width: var(--w, auto);
  object-fit: contain;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.9s var(--ease-out-expo),
    transform 0.9s var(--ease-out-expo);
}

.clients.is-in img {
  opacity: 1;
  transform: none;
}

/* ── The headline ────────────────────────────────────────────────
   Single element. Starts at 60px dead-center, scrubs up to a
   full-bleed 161px lockup docked at the top of the screen.
   Sizing + origin are measured in JS so the cap-height lands
   exactly where Figma puts it.                                    */


/* ── Prólogo · o texto é digitado, apagado e reescrito ───────────
   `background-clip: text` on the parent clips the parent's own gradient to
   its glyphs; the caret is a child background, so it paints normally and
   needs its colour set explicitly. */

/* an author `display` beats the UA's `[hidden] { display: none }`, so the
   attribute has to be honoured explicitly — otherwise the caret survives
   `caret.hidden = true`, stays on screen next to the docked lockup, and
   adds its own width to the font-size measurement */


/* solid while keys are "being pressed", blinking while idle */

@keyframes caret-blink {
  0%,
  45% {
    opacity: 1;
  }
  55%,
  100% {
    opacity: 0;
  }
}


/* ── The layer stack ─────────────────────────────────────────────
   Each plate is an isolated glass render. Design geometry:
   plate box 833.33 × 520, stacked with a 38px vertical pitch, the
   whole stack staying optically centred as it grows.              */


/* Absolutely centred rather than layout-centred: the stack is 833px wide
   in design space and would overflow — and mis-align — a narrow viewport
   before `--stage-scale` is applied. */

.plate {
  position: absolute;
  inset: 0;
  opacity: 0;
  will-change: transform, opacity;
  backface-visibility: hidden;
}

.plate img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Soft contact shadow that grows as the stack deepens */

/* ── Bottom-left copy — one block per layer, subtle crossfade ──── */


.layer-copy {
  position: absolute;
  inset: 0 auto auto 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  filter: blur(4px);
  transition: opacity 0.52s var(--ease-out-soft),
    transform 0.62s var(--ease-out-expo), filter 0.52s var(--ease-out-soft),
    visibility 0s linear 0.62s;
}

.layer-copy.is-active {
  opacity: 1;
  visibility: visible;
  transform: none;
  filter: blur(0);
  transition-delay: 0.08s, 0.08s, 0.08s, 0s;
}

/* leaving block drifts up and out */
.layer-copy.is-leaving {
  opacity: 0;
  transform: translateY(-12px);
  filter: blur(4px);
}

.layer-copy__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dark-05);
}

.layer-copy__status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--yellow);
}

.layer-copy[data-status='on'] .layer-copy__status {
  color: var(--blue);
}

.layer-copy__status::before {
  content: '';
  width: 4px;
  height: 4px;
  background: currentColor;
  animation: pulse 2.6s var(--ease-in-out-soft) infinite;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.32;
  }
}

.layer-copy__title {
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  color: var(--dark-02);
}

.layer-copy__desc {
  font-size: 16px;
  line-height: 1.5;
  color: var(--dark-05);
}

/* ── 2 · Prova social ───────────────────────────────────────────── */

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

/* Figma põe um backdrop-blur de 115px sobre a foto. Blurrar a própria
   imagem dá o mesmo resultado e custa uma rasterização, não um filtro de
   backdrop recalculado a cada frame de scroll. */
.cases__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: clip;
}

.cases__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: blur(64px) saturate(1.15);
  transform: scale(1.18);
}

.cases__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
}

/* CARD ÚNICO (2026-09-30, CASE-SIRIO-OCULTO): com um case publicável só,
   a seção deixa de ser carrossel e o card ocupa a COLUNA inteira — a
   largura do trilho menos o recuo, a mesma da cabeça e dos logos. A
   proporção continua a do componente (16:9 no largo, 5:4 abaixo de 900).
   O prefixo (0,2,0) vence também os 84vw do `.case-card` no celular. O
   `initRails` não precisa de nada: sem rolagem, o autoplay não anda. */
.cases--unico .case-card {
  width: 100%;
}

.cases__logos {
  align-items: center;
  mix-blend-mode: lighten;
}

.cases__logos img {
  height: 36px;
  width: var(--w, auto);
  object-fit: contain;
}

/* `[hidden]` PERDE para `display` de autor — a armadilha da § 6 das
   diretrizes. `.dark-section` não declara display, mas basta um dia
   declarar para a seção oculta reaparecer. Esta regra fecha isso. */
.advisory[hidden] {
  display: none;
}

/* ── 3 · Advisory board ─────────────────────────────────────────── */
/* Figma v11 `726:32327` (a seção) + `796:44604` (as nove bios).

   O comportamento é o da seção de referência da legora.com, a pedido do
   cliente: os nove cards ficam no mesmo tamanho e **um deles está
   aberto** — maior, com a biografia embaixo. Setas, pontos, clique no
   card e arrasto trocam qual é. O aberto fica sempre no CENTRO da tela.

   O card aberto não é um card diferente: é o MESMO card escalado por
   400/340 = 1,17647. Conferido nó a nó contra o export — raio 12 →
   14,118 · nome 18 → 21,176 · recuo 16 → 18,824 · caixa do rótulo
   222 → 261,176. É essa relação que vira `--adv-k`, e é ela que
   transforma "abrir um card" numa variável só.

   Nada de `backdrop-filter` no rótulo. O export do MCP devolve
   `backdrop-blur-[4.5px]` nos nove contêineres, mas o RENDER do nó não
   tem desfoque nenhum — é um efeito desligado que o export emite assim
   mesmo. Ver DIRETRIZES § 6. */

/* `--adv-k` precisa ser registrado para poder TRANSICIONAR: sem isto
   `calc(18px * var(--adv-k))` salta de um valor para o outro. Registro
   é global, daí o nome com prefixo — a § 6 das diretrizes já cobrou
   caro por nome curto em escopo compartilhado. */
@property --adv-k {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}

.advisory {
  /* medidas do Figma, lidas também pelo JS para achar o alvo do trilho */
  --adv-larg: 254px;
  --adv-larg-aberta: 298px;
  --adv-alt: 340px;
  --adv-alt-aberta: 400px;
  --adv-folga: 16px;
  --adv-k-aberta: 1.17647; /* 400 / 340 */
  --adv-dur: 0.85s;
}

.advisory__inner {
  display: flex;
  flex-direction: column;
  gap: 32px;
  /* Figma: 80 acima do eyebrow e 80 abaixo da bio */
  padding: 80px 0;
}

.advisory__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: min(712px, calc(100% - 2 * var(--dark-pad)));
  margin-inline: auto;
}

.advisory__title {
  margin-top: 24px;
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  color: var(--light-01);
  /* Em `em`, não em px: a fonte é fluida e uma caixa fixa em 712 deixa
     caber mais palavra por linha fora de 1440. 712/36 = 19,778em mantém
     a quebra do Figma ("…da saúde e da / inteligência artificial…"). */
  width: 19.778em;
  max-width: 100%;
}

/* ── Barra de controle ──────────────────────────────────────────── */

/* A barra tem a LARGURA DO CARD ABERTO e é centrada com ele, então as
   setas caem exatamente nas duas extremidades dele e os pontos ficam
   entre as duas. Antes a barra ocupava a coluna inteira e as setas iam
   parar a ~500px dos pontos, sem ler como o mesmo controle. */
.advisory__ctrl {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: var(--adv-larg-aberta);
  margin-inline: auto;
}

/* sem JS não há o que controlar — e a janela vira rolagem nativa */
html:not(.js) .advisory__ctrl {
  display: none;
}

/* mesma peça do Figma que a Prova social usa (642:75649) */
.advisory__seta {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  padding: 0;
  border: 0;
  /* redonda, a pedido do cliente. As outras setas da página (Cases,
     Prova social e a alternativa) continuam com o raio 2 do Figma. */
  border-radius: 50%;
  background: var(--light-16);
  color: #fff;
  cursor: pointer;
  transition:
    background-color 0.3s var(--ease-out-soft),
    opacity 0.3s var(--ease-out-soft);
}

.advisory__seta:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.28);
}

.advisory__seta:disabled {
  opacity: 0.34;
  cursor: default;
}

.advisory__seta svg {
  width: 34px;
  height: 34px;
}

.advisory__pontos {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* O ponto visível tem 4px; o botão tem 18 de altura para o dedo ter
   onde acertar. */
.advisory__ponto {
  display: grid;
  place-items: center;
  width: 12px;
  height: 18px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: width 0.55s var(--ease-out-expo);
}

.advisory__ponto::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: var(--r-redondo);
  background: rgba(255, 255, 255, 0.24);
  transition:
    width 0.55s var(--ease-out-expo),
    background-color 0.55s var(--ease-out-soft);
}

.advisory__ponto.is-ativo {
  width: 28px;
  cursor: default;
}

.advisory__ponto.is-ativo::before {
  width: 20px;
  background: var(--light-01);
}

/* ── A janela e a pista ─────────────────────────────────────────── */

/* A pista anda por `transform`, não por `scrollLeft`. É o que deixa o
   deslize e o crescimento do card em LOCKSTEP: as duas transições têm a
   mesma duração e o mesmo easing, então o centro do card aberto caminha
   monotonicamente do lugar antigo para o novo. Com rolagem suave nativa
   o tempo é do navegador e os dois se descasam. */
.advisory__janela {
  overflow: hidden;
}

html:not(.js) .advisory__janela {
  overflow-x: auto;
}

.advisory__pista {
  display: flex;
  align-items: flex-start;
  gap: var(--adv-folga);
  padding-inline: var(--dark-pad);
  /* a bio é absoluta, então não empurra nada: a altura da fila vem daqui,
     e o JS a calcula com a bio mais alta para a seção não pular de altura
     quando o card aberto muda */
  min-height: var(--adv-fila, 568px);
  transform: translate3d(var(--adv-x, 0px), 0, 0);
  transition: transform var(--adv-dur) var(--ease-out-expo);
  touch-action: pan-y;
}

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

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

.advisory__item {
  position: relative;
  flex: none;
  width: var(--adv-larg);
  transition:
    width var(--adv-dur) var(--ease-out-expo),
    --adv-k var(--adv-dur) var(--ease-out-expo);
}

.advisory__item.is-ativo {
  --adv-k: var(--adv-k-aberta);
  width: var(--adv-larg-aberta);
}

/* As fotos de eco são CENÁRIO, não controle. Sem isto, tocar numa delas
   abria o conselheiro que ela repete — e do último card isso arrastava a
   fileira inteira de volta ao começo, que é exatamente o movimento
   abrupto que o cliente não quer. Com `pointer-events: none` no item, o
   toque cai na pista e não faz nada; o ARRASTO continua funcionando,
   porque quem escuta é a pista. */
.advisory__item[data-adv-eco] {
  pointer-events: none;
}

/* ── O card ─────────────────────────────────────────────────────── */

.advisor {
  display: block;
  position: relative;
  width: 100%;
  height: var(--adv-alt);
  padding: 0;
  border: 0;
  border-radius: calc(var(--r-caixa) * var(--adv-k));
  background: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
  overflow: clip;
  transition: height var(--adv-dur) var(--ease-out-expo);
}

.advisory__item.is-ativo .advisor {
  height: var(--adv-alt-aberta);
  cursor: default;
}

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

/* Retrato colorido do estado Hover, por cima do p&b.
   Entra como `background-image` vindo de `--hover`, declarado por card no
   markup, e a regra que o usa vive dentro de `@media (hover: hover)` — em
   aparelho de toque a URL nunca é resolvida e as 9 fotos não são baixadas. */
.advisor__color {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-position: center;
  background-size: cover;
  opacity: 0;
  transition: opacity 0.55s var(--ease-out-soft);
}

/* véu azul — o Figma o remove no Hover, então ele é uma camada própria
   para poder sair com transição (`background-image` não é animável) */
.advisor::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background: rgba(102, 148, 255, 0.08);
  transition: opacity 0.55s var(--ease-out-soft);
}

.advisor::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 65%, rgba(0, 0, 0, 0.6) 100%);
}

/* O card em evidência mostra o retrato COLORIDO — pedido do cliente. Vale
   em qualquer aparelho, então mora fora do `@media (hover: hover)`.

   A imagem é declarada só onde pode aparecer: no card aberto e nos dois
   vizinhos, que são para onde a navegação vai em seguida. Como as nove
   coloridas somam 399 KB e só uma aparece por vez, isso faz o navegador
   baixar TRÊS em vez de nove — pré-carregamento de vizinho em CSS puro,
   sem uma linha de JS. Em aparelho com hover elas já vinham todas pela
   regra abaixo; o ganho é no toque. */
.advisory__item.is-ativo .advisor__color,
.advisory__item.is-ativo + .advisory__item .advisor__color,
.advisory__item:has(+ .advisory__item.is-ativo) .advisor__color {
  background-image: var(--hover);
}

.advisory__item.is-ativo .advisor__color {
  opacity: 1;
}

/* o véu azul sai junto, como sai no Hover */
.advisory__item.is-ativo .advisor::before {
  opacity: 0;
}

@media (hover: hover) {
  .advisor__color {
    background-image: var(--hover);
  }
  .advisor:hover .advisor__color {
    opacity: 1;
  }
  .advisor:hover::before {
    opacity: 0;
  }
}

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

/* Encostado na base do card, com 16 de recuo interno — como no v11. */
.advisor__meta {
  position: absolute;
  left: calc(16px * var(--adv-k));
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(4px * var(--adv-k));
  width: calc(222px * var(--adv-k));
  padding-block: calc(16px * var(--adv-k));
  text-align: center;
  color: var(--light-01);
}

.advisor__name {
  font-weight: 500;
  font-size: calc(18px * var(--adv-k));
  line-height: 1.5;
  white-space: nowrap;
}

.advisor__role {
  font-size: calc(12px * var(--adv-k));
  line-height: 1.5;
  letter-spacing: -0.01em;
  opacity: 0.75;
}

/* A bio mora sob o card, fora do fluxo — assim a fila não muda de altura
   quando o card aberto muda. `top: 100%` acompanha a altura do card
   enquanto ela cresce, e os 23 são a folga do Figma. */
.advisory__bio {
  position: absolute;
  top: calc(100% + 24px);
  left: 0;
  width: var(--adv-larg-aberta);
  font-weight: 300;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  color: var(--light-64);
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  transition:
    opacity 0.4s var(--ease-out-soft),
    transform 0.55s var(--ease-out-expo);
}

.advisory__item.is-ativo .advisory__bio {
  opacity: 1;
  transform: none;
  /* entra depois de o card ter começado a abrir */
  transition-delay: 0.26s;
}

/* ── Entrada ────────────────────────────────────────────────────── */
/* Quem o observer olha é a JANELA, não cada card. Card a card, uma
   rolagem rápida atravessa os de fora da tela sem que o
   `IntersectionObserver` chegue a reportar interseção, e eles ficam
   invisíveis para sempre — medido, cinco dos nove. O atraso satura no
   quinto, que é o último visível a 1440. */
.js .advisory__item {
  --d: calc(min(var(--adv-i), 4) * 70ms);
  opacity: 0;
  transform: translateY(18px);
}

.js .advisory__janela.is-seen .advisory__item {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.9s var(--ease-out-expo) var(--d),
    transform 1s var(--ease-out-expo) var(--d),
    width var(--adv-dur) var(--ease-out-expo),
    --adv-k var(--adv-dur) var(--ease-out-expo);
}

@media (prefers-reduced-motion: reduce) {
  .advisory {
    --adv-dur: 0.01s;
  }
  .js .advisory__item {
    opacity: 1;
    transform: none;
  }
  .advisory__bio,
  .advisor__color,
  .advisor::before,
  .advisory__ponto,
  .advisory__ponto::before {
    transition: none;
  }
  .advisory__item.is-ativo .advisory__bio {
    transform: none;
  }
}


/* ── O menu se recolhe quando a foto do CTA cresce ────────────────
   A foto passa na frente do menu e ele sai de cena: logo depois vem o
   rodapé, e um menu flutuando sobre a foto em tela cheia não serve a
   ninguém. A classe vem do `grow.js`.

   Duas formas de trazê-lo de volta, ambas pedidas: subir para antes da
   Visão (o `grow.js` cuida, com histerese) ou encostar o ponteiro na
   borda de cima — e a espiada tem que vir DEPOIS, para vencer o
   recolhimento. */
/* `cta-no-topo`, não `cta-a-frente`: o menu segue recolhido rodapé
   adentro, mas a camada alta cai assim que o rodapé encosta na tela —
   senão ele subiria por baixo do palco, que é `fixed`, e ficaria
   coberto. */
.cta-no-topo .cta-stage {
  z-index: 120;
}

.cta-a-frente .nav {
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
}

.cta-a-frente.nav-espiada .nav {
  z-index: 200;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* ═════════════════════════════════════════════════════════════════
   Visão · CTA · Rodapé
   ═════════════════════════════════════════════════════════════════ */

/* ── 7 · Visão ──────────────────────────────────────────────────── */

.vision {
  display: grid;
  place-items: center;
  /* A seção tinha 821px e terminava antes do fim da janela: sobrava uma
     faixa do `[data-grow-track]` — transparente, 2340px — visível abaixo
     dela, lida como espaço morto antes de a foto começar a crescer.

     Ocupando a tela inteira, os dois problemas somem juntos: não há mais
     faixa sobrando, e o `place-items: center` distribui o que sobra em
     cima e embaixo, o que dá o respiro superior que faltava. O padding
     vira PISO, para janelas baixas continuarem com margem. */
  min-height: 100svh;
  padding: max(120px, 9svh) var(--gutter);
  /* Prende os z-index internos da seção. Sem isto a legenda do card
     (`z-index: 1`) escapa e pinta ACIMA do estágio do CTA, e a foto passa
     por trás do texto enquanto cresce. */
  isolation: isolate;
  /* brilho quente no canto superior direito, sobre Light-01
     (Figma 676:740 — radial a 20%, três paradas) */
  background: radial-gradient(
      1250px 770px at 1410px 0,
      rgba(246, 211, 255, 0.8) 0%,
      rgba(222, 232, 255, 0.6) 50%,
      rgba(247, 249, 255, 0) 100%
    ),
    var(--light-01);
  color: var(--dark-02);
}

/* `min-width: 0` (2026-09-27): a `.vision` é grade, e a trilha dela tem
   como piso o mínimo do conteúdo — a soma das LARGURAS declaradas da
   linha de cima (1111), mesmo com o lead podendo encolher. Sem isto a
   caixa não descia de 1111 entre 1101 e ~1163 (ver `.vision__lead`). */
.vision__inner {
  width: 100%;
  min-width: 0;
  max-width: 1216px;
}

.vision__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 48px;
}

/* `flex: 0 1 auto`, e não `none` (2026-09-27): a linha de cima pede
   312 + 48 + 751 = 1111, e entre 1101 e ~1163 a tela dá menos que isso
   por dentro (1052 a 1101). Com as duas colunas rígidas o mínimo subia
   até o `.vision__inner` (a `.vision` é grade centralizada), a caixa
   ficava em 1111 e a página rolava de lado até 1135 — e até 1163 a
   margem direita era menor que a esquerda. Agora é o LEAD que cede
   (253 a 1101): as colunas e a foto continuam com 751, alinhadas pela
   direita como no desktop. Base `auto` (a `width` de 312) e não 312px:
   no empilhado (≤ 1100) a linha vira coluna e uma base fixa viraria
   altura. De ~1163 para cima nada muda — sobra espaço, não encolhe. */
.vision__lead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  width: 312px;
  flex: 0 1 auto;
}

.vision__title {
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  /* lavada azul clara vindo de fora do canto superior direito, sobre
     Dark-02 — é o que deixa "precisa de engenheiros" mais claro */
  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;
}

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

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

.vision__bottom {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 48px;
  margin-top: 58px;
}

/* o link no topo e o card na base fecham na mesma linha que a foto grande */
.vision__aside {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 208px;
  height: 396px;
  flex: none;
}

/* A cor e o peso saíram: eram o que fazia esta CTA destoar da irmã dela
   sobre seção clara. Tudo vem do componente agora. */

/* Moldura da foto grande — é a âncora da transição para o CTA.
   Sem fundo próprio: quem desenha a foto é o estágio, e um fundo escuro
   aqui aparece como faixa preta na menor diferença de arredondamento. */
.vision__shot {
  position: relative;
  width: 752px;
  height: 396px;
  flex: none;
  border-radius: var(--r-caixa);
  overflow: clip;
}

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

/* ── 8 · CTA ────────────────────────────────────────────────────── */

/* O estágio é `fixed` para poder pintar por cima da Visão enquanto a
   moldura ainda coincide com a foto dos fundadores. O rodapé sobe por
   cima dele (z maior) — é o mesmo reveal de antes, sem o `sticky`. */
.cta-stage {
  position: fixed;
  inset: 0;
  /* 0 em repouso: enquanto a moldura é uma janelinha dentro da Visão, o
     resto da página passa por cima. Quando o crescimento começa, o
     `cta-a-frente` a leva para cima da nav (100) — a foto tem que passar
     NA FRENTE do menu, não por baixo. */
  z-index: 0;
  display: flex;
  flex-direction: column;
  /* mais respiro embaixo que em cima: o bloco de chamada mora no rodapé do
     palco e a 80px ficava colado na borda da tela */
  padding: 80px 0 max(80px, 9svh);
  isolation: isolate;
  color: var(--light-01);
  pointer-events: none;
}

/* fora da janela de ação o estágio não pinta nem gasta composição */
.cta-stage[data-live='0'] {
  visibility: hidden;
}

.cta-stage__frame {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--dark-01);
  /* o `clip-path` é escrito a cada frame pelo js/grow.js */
  clip-path: inset(0 round 0);
}

.cta-stage__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 100%;
  transform-origin: 50% 50%;
  will-change: transform;
}

.cta-stage__shot[data-grow-a] {
  object-position: 50% 22%;
}

/* O Figma posiciona a foto do lobby a `top: -52.03%` de uma altura de
   155.73% — ou seja, o recorte começa a 385px de uma sobra de 412.
   `object-position: 50% 93.4%` reproduz isso e continua válido quando a
   moldura vira a viewport inteira. */
.cta-stage__shot[data-grow-b] {
  opacity: 0;
  object-position: 50% 93.4%;
}

.cta-stage__veil {
  position: absolute;
  inset: 0;
  opacity: 0;
  background: rgba(0, 0, 0, 0.24);
}

/* Espaço de scroll que a abertura consome, mais uma pausa.

   A abertura termina por volta de 0,54 de tela depois que o CTA prende; o
   rodapé começa a subir quando a fita acaba. Com 190svh esses dois pontos
   ficavam a ~290px um do outro — o botão "quero ser candidato" aparecia e
   já era coberto, numa janela curta demais para alguém ler a chamada e
   agir. A fita mais longa é essa pausa: a chamada fica inteira em cena por
   cerca de uma tela antes do rodapé entrar. */
.cta-track {
  height: 260svh;
  pointer-events: none;
}

/* Com o oitavo logo (a Rede D'Or, 2026-09-27) a fileira de 32 de altura
   não cabia mais numa linha entre 901 e 1100 e caía em duas, com um logo
   sozinho embaixo. A caixa de cada logo passa a ser a do desenho a 32
   (`width: auto`, como abaixo de 900) em vez da largura do Figma para
   40 — que deixava ~20 de sobra vazia em cada um —, e o vão vai a 32. */
@media (max-width: 1100px) {
  .clients__row {
    flex-wrap: wrap;
    justify-content: center;
    gap: 28px 32px;
  }
  .clients__row img {
    height: 32px;
    width: auto;
  }
}

/* ── Carrossel infinito · abaixo de 900px ──────────────────────────
   Duas fileiras idênticas lado a lado num trilho `max-content`, e o
   trilho translada exatamente −50%: ao fim do ciclo a segunda fileira
   está onde a primeira começou, então o loop não tem emenda e não
   precisa de JS para acontecer.

   Usado em dois lugares — os clientes (§ claro) e os logos dos cases
   (§ escura). A fileira duplicada é criada em runtime; sem JS as duas
   seções caem no layout estático do breakpoint anterior.            */

@media (max-width: 900px) {
  .marquee {
    overflow: hidden;
    /* o trilho é muito mais largo que a viewport, e um container flex
       centralizado colocaria o item que transborda em
       (container − item) / 2 — ou seja, começando centenas de px à
       esquerda. Ele tem que começar em 0. */
    justify-content: flex-start;
    /* os logos somem nas bordas em vez de serem cortados */
    -webkit-mask-image: linear-gradient(
      90deg,
      transparent 0,
      #000 40px,
      #000 calc(100% - 40px),
      transparent 100%
    );
    mask-image: linear-gradient(
      90deg,
      transparent 0,
      #000 40px,
      #000 calc(100% - 40px),
      transparent 100%
    );
  }

  .marquee__track {
    display: flex;
    width: max-content;
    /* sem isto o trilho é espremido pelo `.marquee`, que tem a largura da
       viewport — e as fileiras encolhem em vez de transbordar */
    flex: none;
    animation: marquee-loop var(--marquee-dur, 30s) linear infinite;
  }

  .marquee__row {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: center;
    width: auto;
    max-width: none;
    margin: 0;
    gap: var(--marquee-gap, 44px);
    /* metade do gap de cada lado, para a emenda entre as duas fileiras
       ter exatamente o mesmo respiro do gap interno */
    padding: 0 calc(var(--marquee-gap, 44px) / 2);
  }

  .marquee__row,
  .marquee__row img {
    flex: none;
  }

  /* mesma especificidade da regra que esconde o clone acima de 900px */
  .marquee__track > .marquee__row--clone {
    display: flex;
    pointer-events: none;
  }

  /* logos maiores e mais juntos que no desktop: no celular a fileira é lida
     em movimento, não varrida de uma vez */
  .marquee {
    --marquee-gap: 26px;
    --marquee-dur: 24s;
  }

  .clients {
    padding: 24px 0;
  }

  /* solta a largura do Figma: aqui o logo é dimensionado pela altura e o
     `--w` só limitaria a escala */
  .marquee__row img {
    width: auto;
  }

  .clients__row img {
    height: 46px;
  }

  .cases__logos img {
    height: 42px;
  }
}

@keyframes marquee-loop {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

@media (max-width: 1100px) {
  .vision__top,
  .vision__bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 40px;
  }
  .vision__lead,
  .vision__cols,
  .vision__aside,
  .vision__shot {
    width: 100%;
  }
  /* o link volta a ficar acima do card, e a moldura grande vira fluida */
  .vision__aside {
    flex-direction: row;
    align-items: flex-end;
    justify-content: flex-start;
    gap: 40px;
    height: auto;
  }
  .vision__shot {
    height: auto;
    aspect-ratio: 751 / 396;
  }
  .vision__cols p {
    line-height: 1.6;
  }
}

@media (max-width: 860px) {
  .advisory__title,
.vision__title {
    margin-top: 12px;
  }

  /* ── 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. */
  .vision {
    padding: 88px var(--gutter);
  }

  /* ── Cabeçalho da Visão, alinhado ao padrão da página ───────────
     O vão entre a tag e o h2 dava 30 e não os 12 do resto do site: o
     `.vision__lead` é uma coluna flex com `gap: 18px`, e o gap SOMA ao
     `margin-top: 12px` que a regra geral aplica ao título. Zerar o gap
     aqui deixa o padrão sozinho no comando. */
  .vision__lead {
    gap: 0;
  }

  /* metade do vão entre o h2 e o texto: 40 → 20 */
  .vision__top {
    gap: 20px;
  }

  /* ── O título perdia a segunda linha ────────────────────────────
     "engenheiros." sumia. Não era corte nem animação — as duas linhas
     estavam com `opacity: 1`, e pintar o texto de vermelho revelava as
     duas. Quem apagava era o próprio título: ele é pintado por
     `background-clip: text` com uma lavada radial medida em pixels
     ABSOLUTOS (540×470 a partir de 366,-190), calibrada para a caixa de
     312px do desktop. Na caixa de 196px do celular a parte clara do
     gradiente cai justamente sobre a segunda linha, e #dde7ff sobre
     Light-01 é invisível.

     No celular a lavada não tem o que decorar — o título tem duas
     linhas curtas — então ela sai e a cor volta a ser chapada. */
  .vision__title {
    background-image: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--dark-02);
  }

  /* ── A CTA vai para o lado direito do card ──────────────────────
     Ali havia 107px de espaço morto à direita do card de 208. Estreita,
     a CTA quebra o texto em mais linhas e a seta sobe para cima dele.

     `min-width: 0` não é enfeite: sem ele um item flex não encolhe
     abaixo do conteúdo, e foi exatamente esse piso que uma vez somou
     384px de mínimo nesta linha e esticou a PÁGINA inteira para 404.

     **Esta linha tem um piso REAL, e abaixo de 375 ele não cabe** — ver
     o `@media (max-width: 374px)` logo depois deste bloco. */
  .vision__aside {
    flex-direction: row;
    align-items: flex-start;
    gap: 20px;
  }

  .vision__aside .founders-card {
    order: 1;
    flex: none;
  }

  .vision__link {
    order: 2;
    flex: 1 1 auto;
    min-width: 0;
    /* fecha embaixo, na mesma linha da base do card */
    align-self: flex-end;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 12px;
  }

  /* a seta em cima, o texto embaixo */
  .vision__link .cta-seta__elipse {
    order: 1;
  }
  .vision__link .cta-seta__txt {
    order: 2;
  }
  .vision__cols {
    flex-direction: column;
    gap: 20px;
  }
  .layer-copy__desc {
    font-size: var(--p-mobile);
  }
}

/* só na faixa em que os logos ainda são uma fileira estática — abaixo de
   900px eles viram marquee, e estas regras venceriam as do trilho por
   ordem de origem */
@media (max-width: 1100px) {
@media not all and (max-width: 900px) {
  .cases__logos {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 28px 40px;
  }
  .cases__logos img {
    height: 28px;
  }
}
}

@media (prefers-reduced-motion: reduce) {
  .layer-copy__status::before {
    animation: none;
  }
  .layer-copy {
    filter: none;
    transform: none;
    transition-duration: 0.18s;
  }
  .layer-copy.is-leaving {
    transform: none;
    filter: none;
  }
  .clients__row img {
    transition: none;
    opacity: 1;
    transform: none;
  }
  /* the marquee stops; the rail becomes swipeable instead */
  .clients__track {
    animation: none;
  }
  .clients {
    overflow-x: auto;
    scrollbar-width: none;
  }
}

/* ═════════════════════════════════════════════════════════════════
   4 · Financial Intelligence — a constelação
   Figma v11 `716:21245` + `Financial Intelligence-parte-01/02/03`

   Um palco preso com cinco atos em cima da mesma fita (ver `fi.js`). O
   JS escreve cinco números no palco e o CSS desenha tudo a partir deles:

     --s  escala da constelação (0,32 → 1)
     --v  opacidade dela
     --h  presença da headline grande
     --c  presença do texto central
     --b  presença da tag e do parágrafo

   **`--u` é o píxel de design.** O frame do Figma é 1440 × 816 e a
   constelação é posicionada nele; `--u` converte para a tela mantendo a
   composição inteira dentro da menor dimensão, como um `contain`. Sem
   isso, posicionar em `%` esticaria a constelação junto com a proporção
   da janela.
   ═════════════════════════════════════════════════════════════════ */

.fi {
  /* sobe uma tela para dentro da fita da § 3, pelo mesmo motivo que a
     headline sozinha subia: aquela última tela lá é scroll morto */
  margin-top: calc(var(--tell-solo-sobe) * -1svh);
}

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

.fi__stage {
  position: sticky;
  top: 0;
  display: grid;
  place-items: center;
  height: 100svh;
  padding: 32px 18px;
  /* Light-01, a pedido do cliente. Era branco puro. */
  background: var(--light-01);
  overflow: clip;

  /* 1 px de design → px de tela.

     A altura disponível DESCONTA a nav: o frame do Figma tem 1440 × 816
     e não tem barra por cima, então encaixar a composição na tela cheia
     põe a foto de cima atrás do menu. Com `(100svh − 56) / 816` e o
     deslocamento de meia nav abaixo, a composição inteira cai exatamente
     na faixa livre — a borda de cima dela para em y = 56, medido. */
  --u: min(0.06944vw, calc((100svh - 56px) / 816));

  /* Quanto a constelação se afasta na vertical. Em tela estreita o `--u`
     encolhe com a LARGURA e o texto não, então as fotos caem em cima
     dele; empurrá-las para fora da faixa do texto é o que salva a
     composição sem redesenhá-la. */
  --dy-mult: 1;

  --s: 0.32;
  --g: 0;
  --v: 0;
  --h: 1;
  --c: 0;
  --b: 0;
}

/* ── a constelação ─ o `.constelacao` da `componentes.css` ────────
   O grupo e as fotos subiram para lá em 2026-09-28, quando o "Quem
   constrói" do Quem somos passou a ser uma constelação também. Aqui
   ficam as pastilhas, que são só desta seção. */

/* A pastilha da foto 6 passa da borda direita dela — é assim no Figma,
   onde o contêiner tem 193 de largura para uma foto de 160 e não recorta
   nada. As outras duas fotos com pastilha recortam, também como lá. */
.constelacao__foto--livre {
  overflow: visible;
}

/* As pastilhas de vidro sobre as fotos — `backdrop-filter` de verdade.

   Eu as tinha feito chapadas por precaução, achando que o
   `transform: scale()` do grupo mataria o desfoque. **Medido: não
   mata.** Com a escala travada em 0,7, o desvio-padrão dos pixels dentro
   da pastilha cai de 33,23 (chapa) para 31,42 (desfoque) — o filtro está
   funcionando. Quem cria fronteira de composição é `opacity < 1` e
   `filter` num ancestral, não `transform`.

   O único momento em que elas achatam é a entrada, enquanto `--v` ainda
   é menor que 1 — e ali as fotos têm um terço do tamanho. */
.fi__chip {
  position: absolute;
  left: calc(var(--cx) * var(--u));
  top: calc(var(--cy) * var(--u));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  width: calc(44 * var(--u));
  height: calc(44 * var(--u));
  padding: calc(6 * var(--u));
  border: calc(0.5 * var(--u)) solid rgba(255, 255, 255, 0.32);
  border-radius: calc(8 * var(--u));
  background: rgba(255, 255, 255, 0.68);
  backdrop-filter: blur(calc(10 * var(--u)));
  -webkit-backdrop-filter: blur(calc(10 * var(--u)));
  box-shadow: 0 calc(6 * var(--u)) calc(16 * var(--u)) rgba(0, 0, 0, 0.08);
  color: #4b4a52; /* gray/800 da biblioteca do produto; não é variável do site */
  font-family: var(--font-body, 'Funnel Sans'), system-ui, sans-serif;
  font-size: calc(12 * var(--u));
  line-height: 1;
  white-space: nowrap;
}

/* a pílula deitada: ícone e texto lado a lado */
.fi__chip:not(.fi__chip--quad) {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: calc(6 * var(--u));
  width: auto;
  height: auto;
  padding: calc(12 * var(--u)) calc(16 * var(--u)) calc(12 * var(--u))
    calc(12 * var(--u));
  border-radius: calc(12 * var(--u));
  background: rgba(255, 255, 255, 0.6);
  font-size: calc(14 * var(--u));
}

/* A pastilha da foto 6 tem folga maior entre ícone e texto (16 contra 6)
   e recuo igual dos quatro lados — é o que a deixa com os 159 de largura
   do Figma, transbordando 33 da borda da foto. */
/* dupla classe de propósito: `.fi__chip:not(.fi__chip--quad)` acima tem
   especificidade 0,2,0 e ganharia de uma classe só */
.fi__chip.fi__chip--larga {
  gap: calc(16 * var(--u));
  padding: calc(12 * var(--u));
}

/* a de trás, que só espia: o Figma a desenha 0,3% menor */
.fi__chip--atras {
  transform: scale(0.997);
  opacity: 0.92;
}

.fi__chip b {
  font-weight: 400;
}

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

/* ── o texto ─────────────────────────────────────────────────────── */

/* Os dois textos dividem a mesma célula do palco, como na § 2: o bloco
   nasce exatamente onde a headline estava. */
.fi__headline,
.fi__bloco {
  grid-area: 1 / 1;
  position: relative;
}

.fi__headline {
  width: auto;
  opacity: var(--h);
  transform: translateY(calc((1 - var(--h)) * -20px));
}

/* A caixa é 480 para uma fonte de 36 — 13,333em. Em `em` a quebra de
   linha fica IGUAL em qualquer largura, porque caixa e tipo encolhem
   juntos; em px a fonte crescia sozinha até 42 e quebrava a frase em
   outro lugar. Mesma lição da § 2. */
.fi__bloco {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  width: min(13.333em, 100%);
  /* O bloco nasce do tamanho PADRÃO de h2: assim o título da § 4 mede o
     mesmo que os outros, e o lede continua sendo a proporção do Figma
     (14/36) em cima dele. Antes vinha de `--u` e a 375 dava título 24
     com lede de 9,33 — a proporção que o cliente apontou. */
  font-size: max(var(--h2), calc(36 * var(--u)));
  text-align: center;
  opacity: var(--c);
  transform: translateY(calc((1 - var(--c)) * 20px));
}

/* a tag e o parágrafo chegam depois do título */
.fi__tag {
  /* Não acompanha o `em` do bloco — no Figma é medida fixa. Mas lê o
     TOKEN, não um 12 cravado: cravado, ela era a única tag da página
     fora do padrão no celular. O token também é px, então o bloco
     continua sem influência sobre ela. */
  font-size: var(--tag-corpo);
}

.fi__tag,
.fi__lede {
  opacity: var(--b);
  transform: translateY(calc((1 - var(--b)) * 12px));
}

.fi__titulo {
  /* Funnel Display Regular 36 / 1,24. O Figma pinta o texto com um
     sólido Dark-02 e uma lavada radial azul por cima, recortada no
     texto — é o brilho que clareia a primeira metade da frase. */
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1em;
  line-height: 1.24;
  color: var(--dark-02);
  background:
    radial-gradient(
      calc(681 * var(--u)) calc(483 * var(--u)) at calc(563 * var(--u))
        calc(-190 * var(--u)),
      rgba(221, 231, 255, 1) 0%,
      rgba(221, 231, 255, 0) 100%
    ),
    linear-gradient(var(--dark-02), var(--dark-02));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.fi__lede {
  font-family: var(--font-display);
  font-weight: 400;
  /* 14/36 é a proporção do Figma, mas com piso: em tela estreita ela
     sozinha levava o lede a 9,33px. */
  font-size: max(var(--p-mobile-min), 0.3889em);
  line-height: 1.5;
  color: var(--dark-05);
}

/* Sem palco preso o palco é só o quadro final, legível e parado. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  .fi {
    margin-top: 0;
  }
  .fi__track {
    height: auto;
  }
  .fi__stage {
    position: static;
    height: auto;
    min-height: 100svh;
    --s: 1;
    --v: 1;
    --h: 0;
    --c: 1;
    --b: 1;
  }
  .fi__headline {
    display: none;
  }
}

@media (max-width: 900px) {
  .fi__stage {
    padding: 32px var(--gutter);
    /* 2,8 e não 2,4: a reserva da nav empurrou a composição meia barra
       para baixo e a foto 2, que é a menos deslocada de cima, passou a
       encostar no topo do bloco de texto. Medido em 375: 311…348 contra
       um texto que começa em 342. */
    --dy-mult: 2.8;
  }
}

/* ═════════════════════════════════════════════════════════════════
   4.6 · Financial Intelligence — os quatro cards
   Figma v11 `722:31120`

   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,
   que foi o pedido.

   **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`, que o `cards.js` põe quando a
   seção aparece — motion de ENTRADA é temporizado (DIRETRIZES § 5.1).
   ═════════════════════════════════════════════════════════════════ */

/* A § 4.6 SOBE POR CIMA da § 4, que fica presa no lugar — mesmo
   mecanismo da § 3 sobre a § 2. A margem negativa faz esta seção começar
   `--fi-cobre` antes do fim da fita da constelação, e o `z-index` a põe
   na frente. É por isso que o fundo aqui precisa ser OPACO: com fundo
   transparente a constelação apareceria atrás dos cards. */
.cards {
  position: relative;
  z-index: 1;
  margin-top: calc(var(--fi-cobre) * -1svh);
  padding: 120px 0;
  background: #fff;
}

.cards__inner {
  width: min(1216px, 100% - var(--gutter) * 2);
  margin: 0 auto;
}

/* ── cabeçalho ───────────────────────────────────────────────────── */

.cards__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 60px;
}

.cards__titulo {
  /* mesma lavada radial do título da § 4, recortada no texto */
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--h2);
  line-height: 1.24;
  background:
    radial-gradient(
      810px 230px at 836px -96px,
      rgba(221, 231, 255, 1) 0%,
      rgba(221, 231, 255, 0) 100%
    ),
    linear-gradient(var(--dark-02), var(--dark-02));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.cards__grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 16px;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  list-style: none;
}

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

/* O CARD (`.card`, as três ilustrações e as animações) mora no
   `componentes.css` desde 2026-09-25, quando o Quem somos passou a usar
   as mesmas ilustrações. Aqui fica o que é da SEÇÃO: a entrada por cima
   da constelação, o cabeçalho e o trilho. */

/* ── telas menores ───────────────────────────────────────────────── */

@media (max-width: 1100px) {
  .cards__grid {
    grid-auto-columns: min(292px, 74vw);
  }
}

@media (max-width: 900px) {
  .cards {
    padding: 80px 0;
  }
  .cards__head {
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 40px;
  }
}




/* ═════════════════════════════════════════════════════════════════
   3 · Intelligence Layers — o acordeão
   Figma v11 `693:17088`…`714:21005`

   Seis painéis lado a lado. O ativo ocupa 1018 de 1440 e os outros
   cinco viram tiras de 84,4 — é a proporção do Figma, e é o que faz o
   gesto do acordeão existir: a foto que abre empurra as outras para a
   borda em vez de trocar de slide.

   A largura de cada painel é uma variável só (`--lay-aberto`), então a
   transição é uma interpolação de `flex-grow` — nada de `width` em px,
   que travaria a soma em 1440.
   ═════════════════════════════════════════════════════════════════ */

/* A § 3 SOBE POR CIMA da § 2, que fica presa no lugar: a margem
   negativa faz a fita dela começar `--tell-cobre` antes do fim da fita
   da apresentação, e o z-index põe esta seção na frente. É por isso que
   o fundo aqui precisa ser opaco. */
.lay {
  position: relative;
  z-index: 1;
  margin-top: calc(var(--tell-cobre) * -1svh);
}

@media (prefers-reduced-motion: reduce), (scripting: none) {
  .lay,
.cards {
    margin-top: 0;
  }
}

/* O palco prende enquanto os seis passam: seis camadas mais um respiro
   no fim, sete passos. Uma tela para a janela, e o CURSO em pixels —
   ver `--lay-passo` nos tokens: em `svh` a mesma seção custava 686px por
   camada numa janela de 800 e 926px numa de 1080. */
.lay__track {
  height: calc(100svh + 7 * var(--lay-passo));
}

.lay__stage {
  position: sticky;
  top: 0;
  /* O fundo mora no PALCO, não na seção: assim ele apaga junto com o
     `--sai` e o que está atrás — a headline da § 4 — aparece por baixo.
     Na seção ele ficaria opaco até o fim da fita e seguraria uma tela
     inteira de branco entre uma coisa e outra.

     BRANCO, não `Light-01`: é este fundo que aparece acima da faixa de
     fotos enquanto o recorte da abertura ainda está fechado, e em
     `Light-01` ele lia como uma tira cinza chegando antes da seção. */
  background: #fff;
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100svh;
  /* Sem empurrão para a nav: a faixa de fotos nasce em y = 0 e passa POR
     BAIXO dela. Havia 56px de reserva aqui, e a faixa clara que sobrava
     em cima da foto era o que o cliente pediu para tirar — agora que a
     nav é vidro com scrim, ela não precisa de chão próprio. */
  overflow: clip;

  /* Os três atos da referência, escritos pelo JS a partir do scroll:
     `--abre` de 0 a 1 na chegada, `--sai` de 0 a 1 na despedida. */
  --abre: 1;
  --sai: 0;

  /* fecho: o conjunto sobe e apaga, como no GIF */
  transform: translateY(calc(var(--sai) * -9%));
  opacity: calc(1 - var(--sai));
}

/* A seção ocupa a tela inteira: a barra de baixo reserva o que o texto
   precisa e a fileira de fotos fica com todo o resto. Em tela baixa é a
   foto que cede — o texto nunca. */

/* A janela fica parada e a pista corre por dentro dela.

   O recorte da abertura mora AQUI, e não na pista, porque `clip-path`
   recorta em relação à caixa do próprio elemento: posto na pista, ele
   viajava junto com o deslize e cortava o lado direito da tela conforme
   as camadas avançavam. */
.lay__janela {
  flex: 1;
  min-height: 0;
  overflow: clip;
  /* Abertura: a faixa é revelada de baixo para cima, a partir da barra.
     Recorte, não altura — a foto não deforma enquanto aparece, que é o
     que a referência mostra. */
  clip-path: inset(calc((1 - var(--abre)) * 100%) 0 0 0);
}

/* ── A pista de painéis ─────────────────────────────────────────
   No Figma o painel aberto está **sempre em x = 0** e as cinco tiras
   seguem em ordem cíclica: depois da Layer-03 vêm 04, 05, 06, 01, 02.
   Não é um acordeão de posição fixa — é um carrossel que gira.

   Daí a lista aparecer duas vezes na pista: a partir de qualquer ativo,
   os cinco seguintes existem à direita. A pista desliza uma tira por
   camada (`--k`), e é esse deslize somado ao encolhimento do painel que
   produz o gesto da referência — o que estava aberto sai pela esquerda
   enquanto o próximo abre. */

.lay__pista {
  --lay-aberto: 70.7%; /* 1018 / 1440 */
  --lay-tira: calc((100% - var(--lay-aberto)) / 5);
  display: flex;
  width: 100%;
  height: 100%;
  /* O deslize é o passo puro: como o painel agora é 1px mais largo em
     vez de avançar 1px menos, o avanço de cada tira é exatamente
     `--lay-tira` e o aberto para em x = 0 sem correção. */
  transform: translateX(calc(var(--k) * -1 * var(--lay-tira)));
  transition: transform var(--lay-dur) var(--lay-ease);
}

.lay__painel {
  position: relative;
  flex: 0 0 auto;
  /* 1px A MAIS que o passo, não 1px a menos de passo. O painel se
     sobrepõe ao vizinho e fecha a emenda (que aparecia como filete claro,
     porque cada painel é camada de composição própria), mas o AVANÇO
     continua sendo exatamente `--lay-tira`. Descontar o pixel do avanço,
     como era antes, encurtava a fileira em 5px — cinco emendas — e o
     sétimo painel aparecia como um filete no canto direito da tela. */
  /* A largura é a ABERTURA, não um estado. `--a` vem do scroll a cada
     frame (ver `escreverAberturas`): 0 = tira, 1 = aberta. Não há
     transição aqui de propósito — quem dita o ritmo é o dedo. */
  width: calc(
    var(--lay-tira) + 1px + var(--a, 0) * (var(--lay-aberto) - var(--lay-tira))
  );
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  overflow: clip;
  cursor: pointer;
}

/* As larguras caem em posição fracionária (83,50 · 1090,97 …) e cada
   painel é uma camada de composição própria por causa do
   `backdrop-filter` da etiqueta. Duas camadas vizinhas arredondadas
   para o pixel do dispositivo deixam escapar meia coluna do fundo — e
   como o fundo é quase branco, virava um filete claro entre as tiras.
   1px de sobreposição fecha a emenda; o deslize acima desconta. */
.lay__painel + .lay__painel {
  margin-left: -1px;
}

.lay__painel[data-aberto] {
  cursor: default;
}

.lay__painel picture {
  display: contents;
}

.lay__painel picture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── A etiqueta é um painel de vidro ─────────────────────────────
   O Figma **não** filtra a foto: ele põe por cima um painel com
   `backdrop-blur: 17` e preto a 32% (nó `693:17148`). É o mesmo
   componente nos dois estados — o que muda é só a caixa. Na tira ele
   cobre o painel inteiro, e é daí que vem o desfoque da tira toda; no
   painel aberto ele encolhe para 60 × 150, recuado 32 da borda.

   Filtrar a imagem, como eu tinha feito, dá outro resultado: `filter`
   desfoca o conteúdo e puxa a borda para dentro, enquanto
   `backdrop-filter` desfoca o que está atrás e respeita a caixa. */

.lay__aba {
  position: absolute;
  /* SANGRA 1px para cada lado. Este painel é camada de composição
     própria (tem `backdrop-filter`) e a caixa dele é arredondada para o
     pixel do dispositivo — nas posições fracionárias das tiras isso
     deixava a primeira coluna da foto SEM o escurecimento, e ela
     aparecia como um filete claro na emenda: 213 de luz contra 159 da
     foto já escurecida. O `overflow: clip` do painel corta o excesso. */
  left: -1px;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 18px;
  width: calc(100% + 2px);
  height: 100%;
  padding: 24px;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  color: var(--light-01);
  /* NADA de geometria aqui. Animar `width`, `height` e `left` juntos era
     o que produzia o ricochete: as três chegam ao fim em ritmos
     visualmente diferentes, e uma caixa grande encolhendo até virar
     pastilha lê como elástico. Este selo só acende e apaga. */
  /* Sai na PRIMEIRA metade da abertura e o selo entra na segunda, com
     um vão entre 0,45 e 0,55 onde nenhum dos dois está cheio. É esse vão
     que preserva a troca sequencial que o cliente pediu — sem ele os
     dois cruzariam em 50% e virariam borrão. */
  opacity: clamp(0, calc((0.45 - var(--a, 0)) / 0.45), 1);
  transition: background-color var(--lay-dur) var(--lay-ease);
}

/* ── O selo da camada ABERTA ──────────────────────────────────────
   Componente PRÓPRIO, não a mesma caixa encolhida. A troca deixa de ser
   uma deformação e passa a ser o que é: um rótulo sai, outro entra.
   Nenhuma propriedade de layout anima — só `opacity` e `transform`, que
   o compositor resolve sem repintar. */
.lay__selo {
  position: absolute;
  left: 32px;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 18px;
  width: 60px;
  height: 150px;
  padding: 24px;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  color: var(--light-01);
  opacity: clamp(0, calc((var(--a, 0) - 0.55) / 0.45), 1);
  transform: translateY(calc((1 - var(--a, 0)) * 10px));
  pointer-events: none;
}

.lay__painel[data-aberto] .lay__aba {
  pointer-events: none;
}

@media (hover: hover) {
  .lay__painel:not([data-aberto]):hover .lay__aba {
    background: rgba(0, 0, 0, 0.2);
  }
}

.lay__num {
  font-family: var(--font-label);
  font-weight: 300; /* Bai Jamjuree Light, como o Figma pede */
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--light-01);
}

/* O Figma monta isto como um texto girado −90° dentro de uma caixa de
   8 × 43. Reproduzir a caixa literalmente não funciona: o texto tem
   ~40px e transborda dela, e o giro passa a acontecer em volta do
   centro da CAIXA, não do que se vê — media 18px fora do eixo.

   `writing-mode` resolve na origem: o elemento já nasce vertical, com a
   caixa do tamanho do próprio texto, e centraliza sozinho. O
   `rotate(180deg)` é o que faz ler de baixo para cima. */
.lay__rot {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--font-label);
  font-weight: 500;
  font-size: 12px;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--light-01);
}

.lay__marca {
  width: 8px;
  height: 8px;
  flex: none;
  opacity: 0.7;
}

/* ── A barra branca de baixo ────────────────────────────────────── */

.lay__barra {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 60px;
  flex: none;
  min-height: 180px; /* a altura do Figma vira PISO, não teto */
  padding: 32px;
  background: var(--light-01);
}

.lay__copias {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 60px;
  flex: 1;
  min-width: 0;
}

.lay__copia {
  display: flex;
  align-items: stretch;
  gap: 60px;
  width: 100%;
}

.lay__copia[hidden] {
  display: none;
}

/* A troca de camada é um passo lateral, não um fade preguiçoso: na
   referência o rótulo sai por um lado e o novo entra pelo outro,
   desacelerando até parar. `--vem` (+1 ou −1) é a direção, e o JS a
   define pelo sentido do movimento.

   Os três blocos entram escalonados — status, título, descrição —
   porque na referência os itens de baixo chegam depois da foto
   assentar. */
.lay__copia {
  animation: lay-entra 0.62s var(--ease-out-expo) both;
}

.lay__glifo,
.lay__status,
.lay__titulo,
.lay__desc {
  animation: lay-linha 0.62s var(--ease-out-expo) both;
}

.lay__copia .lay__glifo {
  animation-delay: 0ms;
}

.lay__copia .lay__status {
  animation-delay: 60ms;
}

.lay__copia .lay__titulo {
  animation-delay: 110ms;
}

.lay__copia .lay__desc {
  animation-delay: 160ms;
}

@keyframes lay-entra {
  from {
    opacity: 0;
  }
}

@keyframes lay-linha {
  from {
    opacity: 0;
    transform: translateX(calc(var(--vem, 1) * 42px));
  }
}

/* A barra inteira também chega depois da faixa de fotos abrir. */
.lay__barra {
  opacity: clamp(0, calc((var(--abre) - 0.45) / 0.55), 1);
  transform: translateY(calc((1 - var(--abre)) * 14px));
}

/* Cada glifo tem proporção própria (de 1,00 a 1,33) e todos vêm com
   `preserveAspectRatio="none"`: forçar uma medida só distorcia quatro
   dos seis — o octógono virava oval. A caixa de 60 é a do Figma; a
   imagem entra com a medida dela e só encolhe se passar. */
.lay__glifo {
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  flex: none;
  align-self: flex-start;
}

.lay__glifo img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}

.lay__lista {
  position: absolute;
  left: 0;
  bottom: 4px;
  width: 60px;
  height: 6px;
  opacity: 0.5;
}

.lay__texto {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 648px;
  max-width: 100%;
}

.lay__status {
  display: inline-flex;
  align-items: center;
  gap: var(--tag-gap);
  font-family: var(--font-label);
  font-weight: var(--tag-peso);
  font-size: var(--tag-corpo);
  line-height: 1;
  letter-spacing: var(--tag-track);
  text-transform: uppercase;
}

.lay__ponto {
  width: var(--tag-quad);
  height: var(--tag-quad);
  background: currentColor;
}

.lay__status--on {
  color: var(--blue);
}

.lay__status--building {
  color: var(--yellow);
}

.lay__titulo {
  margin-top: 12px; /* status(14) + 12 = 26, o topo do título no Figma */
  font-weight: 400;
  font-size: clamp(22px, 1.944vw, 28px);
  line-height: 1.2;
  color: var(--dark-02);
}

.lay__desc {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--dark-05);
}

/* ── Prev · trilho · Next ───────────────────────────────────────── */

.lay__nav {
  display: flex;
  align-items: center;
  gap: 24px;
  flex: none;
}

.lay__seta {
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dark-05);
  cursor: pointer;
  transition: color 0.3s var(--ease-out-soft), opacity 0.3s var(--ease-out-soft);
}

.lay__seta:hover {
  color: var(--dark-02);
}

.lay__seta[disabled] {
  opacity: 0.3;
  cursor: default;
}

.lay__pontos {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Seis posições, uma por camada. A ativa é a pílula de 60 do Figma e as
   outras são pontos de 6 — ou seja, a barra **é** o indicador e anda
   junto com a camada, em vez de ficar parada num canto. */
.lay__bolinha {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: var(--r-redondo);
  background: var(--dark-05);
  opacity: 0.25;
  transition: width 0.5s var(--ease-out-expo),
    opacity 0.5s var(--ease-out-soft);
}

.lay__bolinha[data-ativo] {
  width: 60px;
  opacity: 0.5;
}

@media (max-width: 900px) {
  .cards {
    /* 100 de palco preso + 220 de percurso lateral */
    height: 320svh;
    padding: 0;
  }

  .cards__inner {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 24px;
    /* LARGURA CHEIA aqui. O contêiner já era `100% − 2×gutter` e os
       filhos ganharam margem própria: o recuo virava 40, o dobro do
       resto da página. Agora o recuo mora só nos filhos, e o trilho
       pode sangrar até a borda — que é o que um carrossel precisa. */
    width: 100%;
    height: 100svh;
    padding: 72px 0 32px;
    overflow: clip;
  }

  /* dissolve o cabeçalho: título e CTA viram irmãos do trilho */
  .cards__head {
    display: contents;
  }

  .cards__titulo {
    order: 1;
    margin: 0 var(--gutter);
  }

  .cards__grid {
    order: 2;
    display: flex;
    grid-auto-flow: unset;
    gap: 16px;
    /* a rolagem nativa sai: quem manda é o scroll da página */
    overflow: visible;
    scroll-snap-type: none;
    padding-inline: var(--gutter);
    transform: translate3d(var(--cx, 0px), 0, 0);
    will-change: transform;
  }

  .cards__grid > .card {
    flex: 0 0 min(292px, calc(100vw - var(--gutter) * 2));
  }

  /* sem JS ou com movimento reduzido o trilho volta a rolar com o dedo */
  html:not(.js) .cards__grid,
  .cards__grid.is-manual {
    overflow-x: auto;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cards__grid {
    transform: none;
  }
}

@media (max-width: 900px) {
  .lay__track {
    /* mesmo custo por camada que estava em `svh` num aparelho típico
       (~460px), agora independente da altura da tela */
    --lay-passo: 460px;
    height: calc(100svh + 7 * var(--lay-passo));
  }
  .lay__pista-nao-usada {
    --lay-aberto: 62%;
    height: min(420px, 52svh);
  }
  .lay__aba {
    width: 44px;
    padding: 12px 0 10px;
  }
  .lay__barra {
    height: auto;
    padding: 24px var(--gutter);
  }
  /* O card de texto EMPILHA: ícone em cima, texto embaixo — e não lado a
     lado, que a 375 espremia o texto numa coluna de ~250 e o cortava.
     `min-width: 0` nos dois é o que permite encolher: item de flex tem
     `min-width: auto` por padrão e se recusa a ficar menor que o próprio
     conteúdo, empurrando a caixa para fora da tela. */
  .lay__copias,
  .lay__copia {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
    min-width: 0;
    width: 100%;
  }
  .lay__texto {
    min-width: 0;
  }
  .lay__glifo {
    width: 44px;
    height: 44px;
    flex: none;
  }
  .lay__lista {
    display: none;
  }
  .lay__nav {
    display: none;
  }
  .lay__barra {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }

  /* ── O ACORDEÃO VIRA VERTICAL ─────────────────────────────────────
     A tela do celular é vertical: seis colunas de 23px são ilegíveis, e
     era isso que estava ali. A tradução é de EIXO, não de mecanismo — o
     `layers.js` continua escrevendo o mesmo `--k` e o mesmo
     `data-aberto`; o que muda é que a porcentagem passa a ser de ALTURA
     e o deslize passa a ser em Y.

     Pedido do cliente, e ele definiu também a divisão do espaço: o bloco
     de texto tem altura FIXA e o que sobra acima vai para as camadas. */
  /* SEM deslize e SEM ordem cíclica no celular. É a diferença que o
     cliente pediu: a camada 1 não vai para o fim quando a 2 abre — ela
     fica FECHADA EM CIMA. Com a pista parada e os painéis na ordem do
     DOM, quem está antes da aberta fica acima e quem está depois fica
     abaixo, que é o comportamento de acordeão de verdade.

     Os clones existem só para a rotação do desktop; aqui eles sairiam
     como seis tiras repetidas no fim da coluna. */
  /* ── A pista NÃO pede o palco inteiro ────────────────────────────
     `.lay__pista` tem `height: 100%` (do desktop, onde ela é a única
     filha). No celular ela divide o palco com a barra de texto, e
     100% + 220px não cabe em 100svh.

     No WebKit de desktop o `flex-shrink` encolhia a pista e o defeito
     ficava invisível — foi por isso que oito tamanhos de tela e o palco
     forçado de 852 a 640px não reproduziram nada. **No iOS 18.7 a pista
     fica com os 699px inteiros** e a barra é desenhada POR CIMA dos
     últimos 220: medido no aparelho, palco 0..699, barra 479..699,
     enquanto L4/L5/L6 ocupavam 585..699. Some tudo abaixo de 479 — as
     fitas de baixo e o rótulo da própria camada aberta.

     A janela (`flex: 1`) já tinha a altura certa. Quem errava era o
     passo seguinte: `height: 100%` na pista é PORCENTAGEM, e o iOS não
     a resolve contra uma altura que veio de `flex-grow` — cai para
     `auto`, e a pista volta a medir o conteúdo. A conta bate no
     aparelho: 190 das cinco fitas + 509 da foto aberta = os 699 que ele
     reportou, exatamente o palco inteiro.

     A pista passa a preencher a janela por FLEX, não por porcentagem:
     a janela vira contêiner de coluna e a pista pega a sobra com
     `flex: 1 1 auto`. `min-height: 0` autoriza os dois a ficarem
     menores que o conteúdo — item de flex em coluna tem
     `min-height: auto`, que se recusa a encolher. Nada aqui depende de
     porcentagem nem de `flex-shrink`, então não há motor onde caia. */
  .lay__janela {
    display: flex;
    flex-direction: column;
  }

  .lay__pista {
    flex-direction: column;
    transform: none;
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
  }

  .lay__painel[data-clone] {
    display: none;
  }

  /* Altura por FLEX, não por porcentagem. A porcentagem com o `+1px` de
     emenda caía em posição fracionária e dava tiras de 31 e de 33 na
     mesma coluna, com filete claro entre algumas — na horizontal aquele
     pixel resolvia uma emenda, na vertical ele CRIAVA uma. Com
     `flex-basis` fixo todas as fechadas medem igual e a aberta recebe o
     resto exato, sem arredondamento sobrando. */
  .lay__painel {
    width: 100%;
    height: auto;
    /* `min-height: 0` é obrigatório: item de flex em COLUNA tem
       `min-height: auto`, que se recusa a encolher abaixo do conteúdo. A
       foto da camada tem 211px de altura natural a 375, então o
       `flex-basis: 44px` era simplesmente ignorado e as seis ficavam com
       211 cada. Mesmo defeito do `min-width: 0` no card de texto. */
    min-height: 0;
    /* No celular a abertura vira `flex-grow`. Como a soma das aberturas
       é sempre 1, quem estiver com `--a: 1` recebe TODA a sobra e dois
       vizinhos em 0,5 a dividem — o mesmo deslize contínuo do desktop,
       sem precisar saber qual é a altura final. */
    flex-grow: var(--a, 0);
    flex-shrink: 0;
    flex-basis: var(--lay-tira-alt);
  }

  .lay__painel[data-aberto] {
    width: 100%;
  }

  /* a etiqueta acompanha: sangra em cima e embaixo, e o rótulo volta a
     ser horizontal — em pé ele só fazia sentido numa coluna estreita */
  .lay__aba {
    left: 0;
    top: -1px;
    bottom: auto;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    width: 100%;
    height: calc(100% + 2px);
    padding: 0 var(--gutter);
  }

  .lay__rot {
    writing-mode: horizontal-tb;
    transform: none;
  }

  /* ABERTA: o vidro vira PASTILHA, não faixa.

     A tira fechada É a faixa — ela ocupa a altura toda do painel porque
     não há mais nada ali. A aberta tem uma foto para mostrar, e cobri-la
     de ponta a ponta com um véu desfocado esconde justamente o conteúdo
     que abriu. No desktop a aberta já era pastilha (60 × 150 a 32 da
     borda); aqui ela é a mesma ideia deitada — pastilha no canto
     inferior esquerdo em vez de faixa vertical.

     CANTO VIVO, a pedido do cliente — e é o mesmo canto do selo no
     desktop, que nunca teve raio. Ele tinha ganhado `--r-chip` quando a
     escala de raios entrou; o token existe para rótulo SOLTO sobre um
     fundo, e aqui o selo é o mesmo vidro das tiras fechadas, que são
     retas de ponta a ponta. Arredondado, ele lia como um objeto
     estranho pousado na foto em vez do resto da mesma família. */
  .lay__selo {
    left: var(--gutter);
    right: auto;
    top: auto;
    bottom: var(--gutter);
    width: fit-content;
    height: auto;
    min-height: 0;
    padding: 8px 14px;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
  }

  /* ALTURA FIXA para o texto: sem isto a barra muda de altura a cada
     camada (as descrições têm 3 ou 4 linhas) e a faixa de imagens pula
     junto. Fixa, o espaço restante das camadas é constante. */
  /* 220 e não 248: as seis cópias medem 185px de conteúdo (medido num
     clone da mesma largura — 129 a 133 caracteres cada, uniformes), e o
     respiro cai de 24 para 16. 185 + 32 = 217, com 3px de folga para
     variação de métrica de fonte. Abaixo disso a última linha corta. */
  .lay__barra {
    height: 220px;
    padding: 16px var(--gutter);
    flex: none;
    justify-content: flex-start;
  }

  /* ── O menu sai de cena enquanto a § 3 manda ───────────────────
     São 56px de nav mais 56px de reserva no palco para a primeira fita
     não nascer atrás dela: 112px, que no celular é justamente o que
     falta para a camada aberta e as seis fitas lerem na mesma tela.
     Sem a nav, a reserva também deixa de ter motivo. */
  html.lay-manda .nav {
    opacity: 0;
    transform: translateY(-100%);
    pointer-events: none;
  }

  html.lay-manda .lay__stage {
    padding-top: 0;
  }

  /* altura de cada camada FECHADA. 44 e não 31: a 31 elas liam como
     achatadas, e é o que sobra da janela que vai para a foto aberta. */
  .lay__stage {
    --lay-tira-alt: 38px;
    /* No desktop a faixa começa em y = 0 de propósito (a nav é vidro e a
       foto passa por baixo — § 8 das diretrizes). Com o acordeão
       VERTICAL isso esconderia a primeira tira inteira atrás do menu:
       ela tem 44 e a nav tem 56. Aqui a faixa desce uma barra, e as seis
       ficam alcançáveis. */
    padding-top: 56px;
  }

  /* O número era 20 contra 12 do rótulo e dominava a tira. Aqui os dois
     ficam perto, que é o que faz "1 LAYER" ler como uma etiqueta só. */
  .lay__num {
    font-size: 16px;
  }

  .lay__rot {
    font-size: 12px;
    letter-spacing: 0.1em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lay__painel,
  .lay__aba,
  .lay__copia,
  .lay__glifo,
  .lay__status,
  .lay__titulo,
  .lay__desc,
  .lay__bolinha {
    transition: none;
    animation: none;
  }

  /* sem movimento a seção simplesmente está lá */
  .lay__stage {
    transform: none;
    opacity: 1;
  }



  .lay__janela {
    clip-path: none;
  }

  .lay__barra {
    opacity: 1;
    transform: none;
  }
}

/* ═════════════════════════════════════════════════════════════════
   Abaixo de 375: a CTA da Visão desce para baixo do card

   A linha "card + CTA" da Visão tem um piso REAL, e ele não cabe em
   tela estreita: card **208** (`flex: none`) + gap **20** + a menor
   largura em que a CTA ainda lê (**~107**, a palavra "MANIFESTO") somam
   **335**. A 375 isso empata exatamente com os 335 úteis — passa raspando.
   A 320 sobram 280, e faltam 55.

   E o sintoma NUNCA aparece perto da causa. Como a coluna da Visão tem
   `flex-shrink: 0`, esse mínimo sobe até o `.vision__inner` e **estica o
   viewport de layout**: a 320 o documento passa a medir 349. A nav é
   `position: fixed`, então ela se dimensiona pelo viewport ESTICADO e
   não pelos 320 visíveis — o seletor de idioma cai 9px fora da tela e
   parece que "o menu quebrou". É a mesma história da entrada
   2026-08-21 (32) do histórico, uma largura abaixo.

   Medido, a 320: com a Visão escondida o documento volta a 320 na hora,
   e a nav junto.

   **Por que empilhar, e não desfazer o lado a lado** · Os dois lado a
   lado são pedido explícito do cliente (24/08). Mas o pedido dele tinha
   DUAS opções — "ou em baixo da foto ou ao lado direito" — e esta é a
   outra. Acima de 374 nada muda: o arranjo aprovado continua de pé.
   ═════════════════════════════════════════════════════════════════ */
@media (max-width: 374px) {
  .vision__bottom .vision__aside {
    flex-wrap: wrap;
    gap: 24px;
  }

  /* base de 100% força a quebra; o `order: 2` que já existe mantém a
     CTA DEPOIS do card, que é a opção "em baixo da foto" */
  .vision__bottom .vision__aside .vision__link {
    flex: 1 1 100%;
  }
}
