/* ===== Clube de Voleibol Prodígios, esboço =====
   Rascunho de apresentação. Não tem foto real e não tem dado do cliente:
   todo lugar de imagem é um .slot marcado, e todo dado não confirmado é um
   .pend. Os dois somem do código quando o material chegar.

   ---------------------------------------------------------------------
   LINGUAGEM VISUAL
   Montada a partir da referência de hero que o Leo trouxe (template
   esportivo preto e verde). O que veio de lá:

   - barra no topo com marca à esquerda, índice no meio e AÇÃO EM BLOCO
     CHEIO na ponta direita
   - filete PONTILHADO fechando a barra. Ele virou o fio condutor do site:
     volta entre cada seção, no lugar de faixa de fundo alternando
   - título gigante em ITÁLICO PESADO, caixa alta, entrelinha apertada,
     com um QUADRADO colorido no lugar do ponto final
   - atleta RECORTADO sangrando na direita, em cima de forma orgânica
     grande e de um facho de luz que separa a figura do fundo
   - botão de ação + logo de apoiador na mesma linha, embaixo do texto

   O que NÃO veio: o verde ácido. A paleta continua a do brasão do clube,
   azul-noite e dourado, porque cor de marca não se troca por causa de
   template. O verde ali é do template, não do Prodígios.
   ---------------------------------------------------------------------

   Cada cor tem função, senão vira festa:
   preto azulado = base · royal = estrutura · dourado = ação (só ele) */

:root {
  --bg: #050d1e;          /* quase preto, com azul dentro */
  --bg-2: #0a1730;        /* card, painel, cabeçalho de tabela */
  --bg-3: #0e2246;        /* degrau de cima, usado com parcimônia */
  --ink: #f2f6fc;
  --ink-dim: #93a6c6;
  /* Dourado e royal foram AMOSTRADOS do arquivo do escudo em 08/08/2026,
     ponto a ponto, quando o guia de marca foi escrito. Antes eram #ffc72c e
     #1d5bc4, escolhidos no olho e mais berrantes que o brasão de verdade.
     Não precisou clarear pra manter legibilidade: o dourado do escudo sobre
     este fundo dá 9:1 de contraste, e o navy escrito em cima do dourado dá os
     mesmos 9:1. Ou seja, o botão continua sendo o par mais legível da página.
     Fonte da verdade: ../../guia-de-marca.md */
  --amarelo: #dea923;     /* ação: CTA e botão. Não dividir com outra cor */
  --royal: #1c5595;       /* azul da bola e da faixa do escudo: estrutura */
  --royal-claro: #5b9bf0; /* link e rótulo sobre fundo escuro */
  --border: #1a3054;

  --h-topo: 84px;
  --pad: clamp(20px, 4vw, 52px);
  --max: 1320px;

  --display: "Arial Black", "Arial Bold", Gadget, Arial, sans-serif;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--h-topo) + 12px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.62;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
.ancora { display: block; height: 0; overflow: hidden; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ===================================================================
   TELA DE INTRO
   A marca empilhada entra linha por linha e a tela se apaga sozinha.

   QUEM TIRA A INTRO É O CSS, não o script. A animação intro-sair tem
   fill-mode both, então ela para em opacity 0 e visibility hidden e fica
   assim. Isso importa: se o JavaScript falhar por qualquer motivo, a
   página não fica atrás de uma cortina navy pra sempre. O script só
   antecipa a saída quando a pessoa dá algum gesto.

   O fundo é o mesmo --bg do site. A intro não "abre uma cortina", ela
   apaga por cima do próprio fundo, e é isso que faz a passagem pro site
   parecer contínua em vez de corte.
=================================================================== */
.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--bg);
  animation: intro-sair 0.45s ease 1.6s both;
}
@keyframes intro-sair {
  from { opacity: 1; visibility: visible; }
  to   { opacity: 0; visibility: hidden; }
}
/* saída antecipada, quando a pessoa não quer esperar */
.intro--fora {
  animation: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s;
}

.intro-marca {
  --u: clamp(2.1rem, 7vw, 4.2rem);
  display: grid;
  justify-items: start;
  gap: calc(var(--u) * 0.16);
}

/* Cada linha entra no seu tempo. A ordem conta a marca: primeiro o que o
   clube é, depois o nome, depois de onde ele vem.

   O ROTEIRO, em segundos, porque os seis atrasos abaixo só fazem sentido
   juntos:
     0,05  entra "Clube de Voleibol"
     0,16  o nome sobe de trás do recorte
     0,55  o quadrado dourado dá o pulo
     0,60  o filete se desenha
     0,72  entra "Aracaju, Sergipe · 2019", e em 1,08 a marca está inteira
     1,60  começa a apagar, e em 2,05 acabou
   A PAUSA DE MEIO SEGUNDO ENTRE 1,08 E 1,60 É O PONTO DA INTRO. Na primeira
   versão a última linha terminava em 1,40 e a saída começava em 1,45: a marca
   completa nunca chegava a ser vista, ela só piscava montada. Mexer em
   qualquer atraso daqui sem refazer essa conta devolve o problema. */
.intro-cima, .intro-nome, .intro-baixo, .intro-risco { animation-fill-mode: both; }

.intro-cima {
  font-size: calc(var(--u) * 0.235);
  font-weight: 800;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--amarelo);
  line-height: 1;
  animation: intro-surge 0.37s ease 0.05s both;
}

/* O nome sobe de trás de um recorte, como se estivesse sendo revelado por
   uma fenda. O overflow do pai é o que faz o recorte, então ele precisa de
   um bloco próprio: por isso o span interno. */
.intro-nome {
  font-family: var(--display);
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  font-size: var(--u);
  /* 1.06 cortava a palavra em cima e embaixo (19/08/2026, print do Leo): a
     caixa alta em Arial Black (--display) rende ~1.4x o font-size de altura
     real, e o overflow:hidden que faz a "fenda" da revelação cortava os
     ~9px que sobravam de cada lado. Testado com medição de
     getBoundingClientRect (texto vs. caixa) via Edge headless, não só no
     olho — line-height 1.06 tinha a caixa 18px mais baixa que o texto
     desenhado. 1.5 sobra de propósito: a métrica muda entre Arial Black
     (Windows), a substituição do macOS e o sans-serif genérico do celular,
     que é pra onde a pilha de --display cai se nenhum dos dois existir. */
  line-height: 1.5;
  color: var(--ink);
  overflow: hidden;
  animation: intro-abre 0.52s cubic-bezier(0.2, 0.7, 0.3, 1) 0.16s both;
  /* FOLGA DE SEGURANÇA (23/08/2026, print do Leo: "Prodígios" cortado no PC
     dele, e eu não consegui reproduzir aqui em nenhuma largura, escala de
     tela do Windows nem fonte de fallback testada). A caixa deste elemento
     nasce do cálculo de largura do texto, no mesmo pixel — zero folga entre
     "onde o layout acha que a letra termina" e "onde o overflow:hidden
     corta". Itálico em peso 900 pode pintar tinta um pouco além dessa borda
     calculada (a inclinação desloca o traço pra direita, mais peso = traço
     mais grosso), e isso é coisa de RASTERIZAÇÃO: getBoundingClientRect e
     Range, que é como medi tudo, não veem esse tipo de corte — só enxergam
     o layout, nunca o pixel pintado de verdade. Cada motor de fonte (e cada
     ajuste de escala de tela) arredonda esse traço de um jeito, e o do Leo
     pode simplesmente arredondar diferente do daqui.
     A correção não tenta adivinhar a fonte nem a tela: dá um respiro que
     nunca aparece (padding sem cor, sem borda) pro corte ter onde sobrar
     antes de chegar na letra. padding-left continua 0 de propósito — é ele
     que mantém o nome grudado embaixo de "Clube de Voleibol", alinhado à
     esquerda como as outras duas linhas. */
  padding: 0 0.15em 0.1em 0;
}
/* O quadrado amarelo que fechava o nome saiu junto com os dos títulos, ver a
   nota em .pt na seção de tipografia. A intro perdeu com isso o "ploc" do
   ponto entrando depois do nome, e o que sobrou é o filete se desenhando
   embaixo, que já era o gesto mais forte dos dois. */

/* o filete se desenha da esquerda pra direita, na largura do nome.
   A cor NÃO é a --border daqui: ela é navy (#1a3054) e some sobre o fundo
   navy da intro. Na folha de estudo o filete herdava a cor do texto, que era
   clara, e aqui isso se perdeu. Branco a 25% é o mesmo peso visual, agora
   sobre o fundo certo. */
.intro-risco {
  height: 1px;
  width: 100%;
  background: rgba(242, 246, 252, 0.25);
  transform-origin: left center;
  animation: intro-risca 0.34s cubic-bezier(0.2, 0.7, 0.3, 1) 0.6s both;
}

.intro-baixo {
  font-size: calc(var(--u) * 0.2);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-dim);
  line-height: 1;
  animation: intro-surge 0.36s ease 0.72s both;
}

@keyframes intro-surge {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes intro-abre {
  from { opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(14px); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); transform: none; }
}
@keyframes intro-risca {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ===================================================================
   CORTINA, transição entre páginas do site (20/08/2026)
   Pedido do Leo, em duas etapas: primeiro só entre o site normal e a área
   de cadastro (cadastro.html / efetivar.html); depois, no mesmo dia,
   "toda transição do site deve ter essa animação" — agora vale pra
   qualquer link entre as três páginas, nos dois sentidos, em vez do corte
   seco de uma navegação comum. O painel fica de fora: não é linkado do site
   público, é área separada, com login próprio.

   É LITERALMENTE UMA CORTINA: fecha subindo de baixo pra cima cobrindo a
   página de origem, e a página de destino já nasce coberta por ela, abrindo
   pra cima logo em seguida. Como são páginas de verdade (sem build, sem
   SPA), a única ponte entre o clique numa página e o load da outra é o
   sessionStorage — ligarCortina() em script.js grava a intenção antes de
   navegar, e o script inline logo abaixo do #cortina de cada página lê essa
   marca e decide se abre a cortina ou nasce do jeito normal.

   Z-INDEX 250, acima de tudo (o mais alto do site antes dela era 210, no
   pop-up de ficha do técnico): enquanto está fechando ou aberta, nada pode
   aparecer por cima e estragar o corte.

   SÓ LIGA NOS LINKS COM data-cortina, e SÓ EM LINK QUE MUDA DE PÁGINA. Âncora
   de rolagem dentro da própria página (#clube, #turmas...) não leva o
   atributo: cortina em cima de quem só está descendo a tela seria confundir
   "rolar" com "sair daqui", os dois gestos ficariam parecidos demais. */
.cortina {
  position: fixed;
  inset: 0;
  z-index: 250;
  background: var(--bg);
  transform: translateY(100%);
  pointer-events: none;
}
.cortina--fechando {
  animation: cortina-fecha 0.42s cubic-bezier(0.6, 0, 0.4, 1) forwards;
  pointer-events: auto;
}
.cortina--abrindo {
  animation: cortina-abre 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes cortina-fecha {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes cortina-abre {
  /* começa em 0 (cobrindo por inteiro) mesmo a página nunca tendo passado
     por --fechando: é assim que a página de destino nasce escondida atrás
     da cortina, sem um quadro sequer do conteúdo aparecendo antes dela */
  from { transform: translateY(0); }
  to   { transform: translateY(-100%); }
}
@media (prefers-reduced-motion: reduce) {
  .cortina--fechando, .cortina--abrindo { animation-duration: 0.001s; }
}

/* ===== Luz que segue o mouse pelo site inteiro (13/08/2026) =====
   Versão do brilho que já existia só no hero da ATA, mas fixa na tela em vez
   de presa a uma seção: ela usa as coordenadas do cursor direto, sem
   descontar rolagem, e por isso acompanha o mouse em qualquer ponto da
   página. Quem persegue o cursor com folga (em vez de colar nele) é o
   script, em ligarBrilhoGlobal() (script.js): a variável --x/--y chega de lá.

   POR QUE mix-blend-mode: screen, E NÃO SÓ opacity. O site inteiro é fundo
   navy, ponta a ponta, sem seção clara, então dá pra assumir isso e deixar a
   luz só SOMAR claridade em vez de cobrir com uma cor. Onde passa por cima
   de algo escuro, clareia; onde passa por cima da placa branca do escudo no
   cabeçalho, soma com branco e não muda nada, porque branco mais qualquer
   luz continua branco. Nunca escurece nem embaça o que está por baixo, então
   pode ficar por cima de tudo (z-index acima da barra do topo) sem atrapalhar
   leitura em lugar nenhum. */
.brilho-global {
  position: fixed;
  top: 0;
  left: 0;
  width: 640px;
  height: 640px;
  margin: -320px 0 0 -320px;
  border-radius: 50%;
  /* Metade do brilho de antes (era 0.28 / 0.09), a pedido do Leo em
     19/08/2026. Com mix-blend-mode: screen a luz SOMA com o que está embaixo,
     então sobre o navy escuro do site ela rendia bem mais do que o número
     sugere, e passava de "acompanhar o mouse" pra "lavar o texto por onde
     passa". O miolo continua sendo o dobro da borda, que é o que dá a forma
     de foco de luz em vez de mancha chapada. */
  background: radial-gradient(circle, rgba(222, 169, 35, 0.13), rgba(222, 169, 35, 0.045) 45%, transparent 70%);
  transform: translate3d(var(--x, 50vw), var(--y, 30vh), 0);
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
  will-change: transform;

  /* ATRÁS DO CONTEÚDO, não por cima (19/08/2026, a pedido do Leo). Estava em
     150, acima de tudo, e com mix-blend-mode: screen ele clareava o que
     passasse embaixo — inclusive o rosto dos professores nos cartões.

     Como funciona agora: a luz fica em 0 e o #conteudo sobe pra 1, criando
     uma camada acima dela. O fundo da página (body, navy) continua abaixo de
     tudo, então a luz tem contra o que somar e aparece nos vãos entre as
     seções, que são transparentes. Onde existe algo pintado por cima (cartão,
     placa de patrocinador, capa), ela simplesmente não chega.

     É por isso que a luz sumiu de cima do vídeo da abertura: a .capa tem
     fundo próprio. Foi de propósito, e é o mesmo motivo pelo qual ela não
     lava mais o rosto de ninguém. */
  z-index: 0;
}
/* a camada que cobre a luz. Sem ela, a luz continuaria por cima de tudo que
   não tem z-index próprio */
#conteudo { position: relative; z-index: 1; }
.brilho-global--ativo { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .brilho-global { display: none; }
}

.pular {
  position: absolute; left: -9999px; top: 8px; z-index: 200;
  background: var(--amarelo); color: #050d1e;
  padding: 10px 16px; font-weight: 800;
}
.pular:focus { left: 8px; }

.faixa {
  width: min(100%, var(--max));
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* O filete pontilhado dourado que vinha da referência foi removido em
   08/08/2026, a pedido do Leo. Sobre o azul do clube ele lia como sujeira de
   tela, não como divisória. O que separa seção agora é só o respiro. */

/* ===== Tipografia =====
   Itálico pesado em caixa alta, entrelinha apertada, exatamente como o
   título da referência. Arial Black é fonte de sistema: sem arquivo
   externo, sem requisição, sem build. */
h1, h2, h3, .marca-nome, .rodape-lema, .turma-num, .trilha-num, .numeros-grade b {
  font-family: var(--display);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.02em;
}
h1, h2, .rodape-lema { font-style: italic; line-height: 0.94; margin: 0 0 18px; }
/* Teto baixou de 6rem pra 4.4rem em 08/08/2026, a pedido do Leo: em monitor
   grande a chamada de três linhas comia a abertura inteira e empurrava o
   parágrafo e os botões pra fora da tela. Baixou de novo pra 3.8rem em
   19/08/2026, mesmo motivo, a chamada de três linhas ("Venha fazer parte
   desta força") ainda pesava demais no topo. */
h1 { font-size: clamp(1.9rem, 4.5vw, 3.8rem); }
h2 { font-size: clamp(1.9rem, 4.2vw, 3.3rem); }
h3 { font-size: 1.2rem; line-height: 1.1; margin: 0 0 8px; letter-spacing: -0.01em; }

h1 em, h2 em { font-style: italic; color: var(--amarelo); }

/* O QUADRADO AMARELO NO LUGAR DO PONTO FINAL SAIU (17/08/2026, a pedido do
   Leo). Ele vinha da folha de referência que serviu de base pro layout, e
   fechava cada título: h1 da abertura, os sete h2 de seção, a marca d'água do
   rodapé e o nome na tela de intro.

   O motivo de sair: é assinatura de OUTRA marca. A identidade do Prodígios é o
   escudo, o navy e o amarelo do brasão, e o quadradinho não diz nada sobre o
   clube, só marca de onde o desenho veio. Amarelo no site continua existindo,
   nos lugares onde ele significa algo: o botão de ação, a palavra destacada
   dentro do título, o traço que abre cada passo da matrícula.

   Se algum dia voltar, volta como elemento da marca, não como enfeite de
   título, e aí volta nos quatro lugares de uma vez: .pt nos títulos e
   .intro-pt na intro. */

p { margin: 0 0 16px; color: var(--ink-dim); }

.olho, .rotulo, .turma-pub, .dados dt, .fim-dados dt,
.grade thead th, .numeros-grade span, .slot-tag, .rodape-info {
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-style: normal;
}
.olho {
  font-size: 0.7rem;
  font-weight: 800;
  color: var(--amarelo);
  margin: 0 0 14px;
}
.olho b { color: var(--royal-claro); margin: 0 4px; }
.rotulo { font-size: 0.66rem; font-weight: 700; color: var(--royal-claro); margin: 0 0 8px; }

.cabeca { margin-bottom: 42px; }
.cabeca-lead, .capa-lead { max-width: 60ch; font-size: 1.02rem; }
.cabeca h2 { margin-bottom: 16px; }

/* ===== A régua dourada do título (24/08/2026) =====
   Um risco curto embaixo do h2 de cada seção, que se DESENHA da esquerda pra
   direita quando a seção entra. É o movimento de "expandir" pedido pelo Leo,
   posto no lugar que toda seção tem: o título.

   Fica em position: absolute pra não empurrar o lead nem entrar na conta do
   margin-bottom do h2 — o risco mora dentro do respiro que já existia ali,
   então nenhuma seção mudou de altura por causa dele.

   O estado padrão é o risco INTEIRO, e o encolhido só vale quando o script
   marcou o título pra revelar (ver .numeros-grade pra a mesma armadilha):
   nas telas de matrícula a .cabeca mora em .faixa-form, que o seletor de
   blocos do script não alcança, e sem esta ordem o risco sumiria justamente
   lá. */
.cabeca h2 { position: relative; }
.cabeca h2::after {
  content: "";
  position: absolute;
  left: 0; bottom: -5px;
  width: 54px; height: 3px;
  background: var(--amarelo);
  transform-origin: 0 50%;
  transition: transform 0.6s cubic-bezier(0.16, 0.72, 0.24, 1) 0.16s;
}
.cabeca.revelar h2::after { transform: scaleX(0); }
.cabeca.revelar.visivel h2::after { transform: scaleX(1); }

/* Sublinhado de verdade, não border-bottom. Dois motivos: ele desvia dos
   descendentes do "g" e do "p" em vez de cortá-los, e sobretudo ele fica
   preso ao texto. A borda vive na caixa, então qualquer respiro que o link
   ganhe pra virar alvo de toque no celular (ver a media query) empurraria a
   borda pra longe da palavra. */
.link {
  color: var(--royal-claro);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(91, 155, 240, 0.45);
}
.link:hover { color: var(--amarelo); text-decoration-color: var(--amarelo); }

/* ===== Espaço reservado de imagem =====
   Não é imagem quebrada, é pedido de material. Diz na própria tela qual foto
   entra ali, então a página vale como lista de pendências pro cliente na
   hora da apresentação. */
.slot {
  position: relative;
  display: block;
  background:
    repeating-linear-gradient(135deg, rgba(91, 155, 240, 0.05) 0 2px, transparent 2px 10px),
    var(--bg-2);
  border: 1px solid var(--border);
  overflow: hidden;
}
.slot::before, .slot::after {
  content: "";
  position: absolute;
  width: 14px; height: 14px;
  border: 2px solid var(--amarelo);
  opacity: 0.5;
}
.slot::before { top: 8px; left: 8px; border-right: 0; border-bottom: 0; }
.slot::after { bottom: 8px; right: 8px; border-left: 0; border-top: 0; }

.slot-tag {
  position: absolute;
  left: 26px; bottom: 22px;
  max-width: calc(100% - 52px);
  font-size: 0.62rem;
  line-height: 1.6;
  font-weight: 700;
  color: var(--ink-dim);
}

/* ===== Botões, em bloco reto como o da referência ===== */
.botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 26px;
  font-family: var(--display);
  font-style: italic;
  font-weight: 900;
  font-size: 0.86rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  border: 2px solid transparent;
  cursor: pointer;
  /* o transform sobe junto: é ele que dá o "dá pra clicar" antes de qualquer
     mudança de cor. Curva com saída rápida e chegada macia. */
  transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease,
              transform 0.18s cubic-bezier(0.2, 0.7, 0.3, 1), box-shadow 0.18s ease;
}
/* sobe e engorda um fio (24/08/2026). O translate sozinho some em botão
   pequeno, que é a maioria deles aqui ("Quero essa turma" tem 0,74rem); a
   escala é o que faz o alvo crescer sob o cursor mesmo quando o passo de
   2px é curto demais pra ser notado */
.botao:hover { transform: translateY(-2px) scale(1.035); }
/* apertar AFUNDA o botão, e mais rápido do que ele subiu. Antes ele só
   voltava pro lugar; passando de 1,035 pra 0,985 o clique ganha os dois
   sentidos do gesto, que é o que faz parecer um botão de verdade. */
.botao:active { transform: translateY(0) scale(0.985); transition-duration: 0.06s; }
.botao:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

.botao-cheio { background: var(--amarelo); color: #050d1e; }
.botao-cheio:hover { background: #fff; box-shadow: 0 10px 22px rgba(0, 0, 0, 0.38); }

/* ===== Lâmina de luz no botão cheio (23/08/2026) =====
   Uma faixa clara atravessa o botão uma vez, no hover. É só no .botao-cheio,
   que é o botão de ação do site inteiro ("Venha fazer parte", "Quero essa
   turma"): pôr em todo botão gastaria o efeito e faria o secundário disputar
   atenção com o principal.

   O recorte mora no próprio botão (overflow: hidden) e não num pai, porque
   pai que recorta é o que mata position:sticky — a mesma armadilha que já
   está escrita no CLAUDE.md sobre o vídeo da abertura.
   A LÂMINA PRECISA PASSAR POR BAIXO DA PALAVRA, e conseguir isso pede as
   duas linhas abaixo juntas, não só o z-index:
   - `isolation: isolate` faz o botão virar um contexto de empilhamento
     próprio. Sem ele, o z-index -1 jogaria a lâmina pra trás do FUNDO do
     botão e ela sumiria por completo.
   - dentro desse contexto, z-index -1 pinta depois do fundo e antes do
     texto, que é exatamente a camada onde ela tem que estar.
   Não dá pra resolver marcando os filhos (`.botao-cheio > *`): o conteúdo
   destes botões é texto solto, e nó de texto não aceita z-index. */
.botao-cheio { position: relative; overflow: hidden; isolation: isolate; }
.botao-cheio::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0; bottom: 0;
  left: -60%;
  width: 45%;
  background: linear-gradient(100deg,
    transparent 0%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 100%);
  transform: skewX(-18deg);
  pointer-events: none;
  opacity: 0;
}
.botao-cheio:hover::after { animation: lamina 0.62s cubic-bezier(0.3, 0.6, 0.4, 1); }
@keyframes lamina {
  0% { left: -60%; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { left: 115%; opacity: 0; }
}
/* `background: none` não é redundante: até 19/08/2026 todo .botao-linha era
   um <a>, que já nasce transparente, e o primeiro <button> com essa classe
   (o "Voltar" do cadastro) saiu cinza claro do navegador, com o texto quase
   ilegível. Botão tem fundo próprio por padrão, link não. */
.botao-linha { background: none; border-color: var(--border); color: var(--ink); }
.botao-linha:hover { border-color: var(--amarelo); color: var(--amarelo); }
.botao-g { padding: 17px 34px; font-size: 1rem; }
.botao-p { padding: 10px 18px; font-size: 0.74rem; }

/* ===================================================================
   BARRA DO TOPO
   Fixa e sem fundo por cima da abertura, pra foto do atleta subir por trás
   dela. Ganha fundo sólido assim que a página desce.
=================================================================== */
.topo {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 80;
  transition: background 0.25s ease;
}

/* ===== Fio de progresso da leitura (23/08/2026) =====
   Um fio dourado no alto da tela que cresce conforme a página desce. Esta é
   uma home longa (dez seções, mais a abertura em vídeo), e não havia nada
   dizendo quanto ainda falta — a barra de rolagem do navegador some sozinha
   no celular e some no desktop enquanto ninguém rola.

   Fica em 81, um degrau acima do cabeçalho: colado no topo, embaixo dele o
   fio ficaria escondido atrás da barra sólida assim que ela acende.

   O tamanho vem de transform: scaleX, e nunca de width. Mexer em width força
   o navegador a recalcular layout a cada quadro de rolagem, que é o caminho
   mais curto pra travar a página no celular; scaleX é só composição, roda na
   GPU e não toca no layout de ninguém. */
.progresso {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  z-index: 81;
  background: linear-gradient(90deg, var(--royal), var(--amarelo));
  transform: scaleX(var(--lido, 0));
  transform-origin: 0 50%;
  pointer-events: none;
  /* enquanto a abertura em vídeo está na tela o fio não aparece: lá a
     rolagem é a linha do tempo do vídeo, não leitura de página, e um fio
     correndo por cima da cena disputa com ela */
  opacity: 0;
  transition: opacity 0.3s ease;
}
.progresso.is-visivel { opacity: 1; }
.topo.solido { background: rgba(5, 13, 30, 0.95); backdrop-filter: blur(12px); }

.topo .faixa {
  display: flex;
  align-items: center;
  gap: 20px;
  height: var(--h-topo);
}

/* marca: escudo + nome em itálico pesado + selo cheio, no espírito do
   "SPORT be" da referência */
.marca { display: flex; align-items: center; gap: 10px; margin-right: auto; }
/* O escudo inteiro, sem recorte, a pedido do Leo em 08/08/2026. Ele tem o nome
   do clube escrito dentro da faixa e um contorno azul-noite, então precisa de
   tamanho pra não virar borrão no fundo escuro.

   PLACA BRANCA, 08/08/2026. Tamanho sozinho não resolvia: o contorno do escudo
   é azul-noite e o fundo da barra também, então a silhueta se dissolvia e o
   dourado ficava boiando. Sobre branco o contorno reaparece e o "PRODÍGIOS" de
   dentro da faixa fica legível, que era o problema.

   A placa é justa: 4px de branco em volta, o mínimo pro contorno navy não
   encostar na borda. Menos que isso ela vira recorte apertado no brasão, que
   é o "não pode" da seção 02 do guia.

   A CAIXA SEGUE A PROPORÇÃO DO ESCUDO APARADO (mais alto que largo, ~0,70).
   Antes ela era 76x68, quase quadrada, porque foi calculada em cima do arquivo
   original de 535x467, que é 57% margem transparente. Com object-fit: contain,
   o navegador encaixa o arquivo inteiro, margem vazia inclusive, então sobrava
   um anel branco grosso que o padding não explicava. Aparar o arquivo resolveu
   na origem: agora 4px de padding é 4px de branco na tela.

   20/08/2026: marca.png foi refeito a partir de "Logo pro max.png", um envio
   mais nítido do cliente (3899x3659 contra os 535x467 do Logo.png antigo), com
   transparência de verdade em vez de fundo branco chapado. A proporção do
   recorte (672x972, ~0,69) ficou praticamente igual à anterior, então a caixa
   não mudou, só a nitidez do arquivo dentro dela.
   Escudo com ~56px de altura na placa de 64px, acima do mínimo de 55px do guia. */
.marca-escudo {
  width: 48px; height: 64px;
  flex: 0 0 48px;
  display: grid;
  place-items: center;
  padding: 4px;
  background: #fff;
  border-radius: 3px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}
.marca-escudo img { display: block; width: 100%; height: 100%; object-fit: contain; }
.marca-nome { font-size: 1.5rem; font-style: italic; line-height: 1; }

.menu { display: flex; gap: 26px; }
.menu a {
  position: relative;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-dim);
  transition: color 0.15s ease;
}
/* fio dourado que cresce da esquerda. Vive no ::after pra não empurrar o
   layout do índice quando aparece */
.menu a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -7px;
  height: 2px;
  background: var(--amarelo);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.menu a:hover { color: var(--ink); }
.menu a:hover::after, .menu a.ativo::after { transform: scaleX(1); }
.menu a.ativo { color: var(--amarelo); }
/* Separado de .ativo de propósito: aquela classe é do scroll-spy em
   script.js (ligarIndice, só pega link[href^="#"]) e liga/desliga sozinha
   conforme a seção visível. "Efetivar matrícula" aponta pra outra página,
   o observador nem olha pra ela — reusar .ativo aqui ia deixar uma classe
   com nome errado grudada num link que nunca é "a seção atual".
   E não é .destaque (a citação em itálico de "O clube", mais abaixo nesta
   folha): mesmo nome pra coisa diferente confunde quem for mexer depois. */
.menu a.realce { color: var(--amarelo); }

.menu-btn {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 42px;
  padding: 0 9px;
  background: none;
  border: 1px solid var(--border);
  cursor: pointer;
}
.menu-btn span { display: block; height: 2px; background: var(--ink); transition: transform 0.2s ease, opacity 0.2s ease; }
.menu-btn[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-btn[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ===================================================================
   ABERTURA
=================================================================== */
/* Sem overflow: hidden aqui. Ancestral com overflow recortado vira o
   scrollport do position: sticky, e o palco pararia de grudar no topo.
   Quem recorta o vídeo agora é .capa-palco, que não é ancestral do sticky. */
.capa {
  position: relative;
  padding-top: var(--h-topo);
  /* Centro deslocado de 66% pra 58% e raio maior (19/08/2026, a pedido do
     Leo): o azul mais claro do meio bleedava só perto do vídeo, e a faixa
     atrás do texto ficava lisa demais, lendo como um retângulo preto colado
     ao lado da cena, não como o mesmo fundo continuando. */
  /* Núcleo mais claro e mais azul em 24/08/2026 (o hero estava "muito cinza",
     palavra do Leo). #16325f é navy quase neutro: espalhado por 52% da
     abertura, ele vira o cinza-azulado que dava o tom apagado. #1d4a86 é o
     mesmo azul da marca com luz dentro, e a parada do meio desceu de 52% pra
     46% pra a queda pro preto acontecer mais longe do centro, deixando a
     região do texto assentada em cor e não em cinza. */
  background:
    radial-gradient(135% 115% at 58% 42%, #1d4a86 0%, #0c1e3f 46%, #050d1e 100%);
}

/* A pista é o curso de scroll que o vídeo consome. Sem o modo scrub ligado ela
   não tem altura própria: a abertura fica com uma tela e o vídeo fica parado no
   pôster. Quem liga é o script, e só quando vale a pena (ver .capa--scrub). */
.capa-pista { position: relative; }
.capa-palco {
  position: relative;
  display: flex;
  align-items: center;
  min-height: min(80vh, 760px);
  overflow: hidden;
}

/* Modo scrub: a pista estica e o palco gruda no topo, então a página rola
   por trás de uma abertura parada. É esse desencontro que vira a linha do
   tempo do vídeo.
   (O clipe tinha 6 segundos quando veio; o corte no clímax, feito em
   10/08/2026, deixou o arquivo em 4.)

   A CONTA DA ALTURA, porque ela não pode ser mexida sozinha. Eram 230vh, ou
   seja 130vh de curso (230 menos a tela) pros 4 segundos, uns 32,5vh por
   segundo. Em 11/08/2026 entrou uma PAUSA NO FIM, a pedido do Leo: o vídeo
   acabava junto com a pista e o último quadro, que é o clímax do ataque,
   passava batido. A pausa nasceu com 1 segundo e virou 2 no mesmo dia, porque
   com 1 a abertura ainda soltava rápido demais. São 2 x 32,5vh a mais de
   curso, daí 295vh.

   Quem faz a pausa acontecer é o medir() do script.js, que espalha a rolagem
   por 4+2 segundos e trava o vídeo nos 4. MEXER AQUI SEM MEXER LÁ desregula
   os dois: aumentar só esta altura deixa a esfregada lenta em vez de pausar,
   e mudar só o script deixa a pausa maior que a pista e come o fim do
   ataque. A constante que faz par com este número é SEGURA_FIM.

   A conta, pra quando mudar de novo: altura = 100vh + 32,5vh x (4 + SEGURA_FIM). */
.capa--scrub .capa-pista { height: 295vh; }
/* o recuo do cabeçalho migra pro palco: com ele na .capa, a pista inteira
   desceria e sobraria uma faixa navy no topo enquanto o palco está grudado */
.capa--scrub { padding-top: 0; }
.capa--scrub .capa-palco {
  position: sticky;
  top: 0;
  height: 100vh;
  min-height: 0;
  padding-top: var(--h-topo);
}

/* O vídeo sangra a abertura inteira, atrás de tudo, e é empurrado pra direita
   porque o texto mora na esquerda. Até 11/08/2026 quem empurrava era só o
   object-position, e ele não dava conta: o clipe é 16:9 e a abertura é mais
   quadrada, então sobram uns 160px de corte horizontal pra distribuir e mais
   nada. O Ácacio Júnior passava por trás de "FORMAMOS" e de "ATLETAS", e a
   camisa com o nome dele ficava atrás da letra.

   Quem empurra de verdade agora é o translateX. Duas coisas que parecem
   detalhe e não são:

   - NADA DE scale JUNTO. A tentativa óbvia era translateX + scale pra tapar a
     falta na esquerda, e ela piora o problema em vez de resolver: o clipe
     termina em close, e ampliar o close faz o atleta crescer mais rápido do
     que a translação o afasta. Testado, a cabeça voltava pra cima do texto no
     fim exato em que o efeito tem que brilhar
   - A FALTA NA ESQUERDA NÃO APARECE. O translateX descobre 14% da largura, e
     ali embaixo está o mesmo navy do radial da .capa, coberto por um véu que
     nos primeiros 30% é praticamente opaco. Não há o que ver

   O object-position caiu de 70% pra 18% no mesmo movimento: puxar o
   enquadramento pro lado esquerdo do arquivo devolve conteúdo à direita da
   tela, e é o que soma com a translação em vez de brigar com ela. */
.capa-video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 18% 42%;
  transform: translateX(14%);
  /* o clipe é de estúdio claro e a abertura é navy. Escurecer e tirar um pouco
     de saturação é metade do casamento; a outra metade é o véu.
     Brightness subiu de 0,78 pra 0,92 em 13/08/2026, a pedido do Leo: o vídeo
     estava saindo apagado demais por trás do véu.
     Baixou pra 0,6 em 19/08/2026, motivo oposto: o fundo claro de estúdio
     continuava visível demais onde o véu afina, e a faixa atrás do texto
     (opaca, navy) ficava parecendo um retângulo colado ao lado da cena, não
     o mesmo fundo continuando por trás do atleta. */
  /* 24/08/2026, "o hero está muito cinza". Estava mesmo, e o filtro era
     metade da causa: saturate(0.72) tirava a cor e brightness(0.6) tirava a
     luz, então sobrava justamente cinza-azulado — a camisa do atleta, o tom
     de pele e a bola morriam todos na mesma faixa de meio-tom.
     A tentação era só devolver o brilho, e ela erra: o problema que o 0.6
     resolvia (fundo claro de estúdio brigando com a faixa de texto à
     esquerda) volta na hora. Quem resolve contraste de texto é o VÉU, que
     tapa a esquerda de propósito; escurecer o quadro inteiro pra proteger um
     canto dele é apagar a cena pra resolver a legenda.
     Então: brilho quase de volta ao natural, saturação ACIMA de 1 (o clipe
     nasce lavado) e o véu abaixo é que ficou com a conta do contraste. */
  filter: saturate(1.12) contrast(1.08) brightness(0.94);
}

/* O véu é o que costura vídeo e paleta. Três camadas, nessa ordem:
   1. navy sólido na esquerda virando quase transparente na direita, que é o
      que garante contraste pro texto sem escurecer o atleta
   2. navy subindo do rodapé, pra emendar na faixa de números sem linha
   3. um sopro de royal em cima do atleta, que devolve a cor do clube ao clipe

   OS TRÊS ÚLTIMOS PARES DA CAMADA 1 BAIXARAM em 13/08/2026 (0,92/0,45/0,3
   pra 0,92/0,32/0,16): o vídeo estava sumindo debaixo do véu bem onde o
   atleta aparece, do meio pra direita. O primeiro par (4%, praticamente
   opaco) ficou como estava, porque é a zona atrás do texto e continua
   precisando cobrir sem deixar o vídeo brigar com a leitura. */
.capa-veu {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* Camada 3 alargada em 19/08/2026: cobria só perto do atleta (78% 40%,
     raio 70%/90%), e o resto do vídeo ficava sem nenhum tom de royal,
     contrastando com o navy do painel de texto. Agora o sopro de azul cobre
     o quadro quase inteiro, o que junto com o brightness mais baixo do vídeo
     (ver .capa-video) aproxima a cor visível em qualquer ponto do fundo. */
  /* REESCRITO EM 24/08/2026, junto com o filtro do vídeo, pelo mesmo motivo
     ("muito cinza"). Duas mudanças, e a segunda é a que mais pesava:

     1. A camada 1 agora CAI MAIS RÁPIDO e termina em zero, em vez de 0,16.
        Aquele resto de navy espalhado até o fim cobria o lado direito
        inteiro com um cinza de baixa opacidade — pouco pra esconder o
        atleta, o suficiente pra lavar a cor dele. A esquerda continua
        praticamente opaca, que é o que segura a leitura do texto: o véu
        assumiu a conta do contraste que o brightness fazia antes.
     2. A camada 3 era um radial de 120%x140% cobrindo QUASE O QUADRO INTEIRO
        com um azul de 0,42 — ou seja, um filtro cinza-azulado chapado por
        cima de tudo, que é literalmente a descrição do problema. Virou uma
        luz concentrada em cima do atleta, mais forte no miolo e acabando
        bem antes das bordas: pinta onde tem cena, em vez de pintar a tela.
     3. Camada nova, dourada, no alto à direita: é a única fonte quente da
        abertura e é ela que tira a leitura de "foto azul" — pouca coisa
        (0,14) e bem aberta, só pra dar temperatura ao contraluz.
     4. Camada nova descendo do topo. Devolver o brilho ao vídeo reacendeu o
        TETO DO ESTÚDIO, que no clipe é um cinza claro liso ocupando toda a
        faixa de cima à direita — e cinza claro continua cinza por mais
        saturação que se ponha, porque saturar não inventa cor onde não há.
        A saída é pintar por cima só ali: forte no topo, limpa antes da
        metade, sem encostar no atleta, que mora do meio pra baixo. É a
        diferença entre tratar a região que estava cinza e apagar o quadro
        inteiro pra resolvê-la, que era o que o brightness(0.6) fazia. */
  background:
    linear-gradient(100deg, #050d1e 3%, rgba(5, 13, 30, 0.93) 19%, rgba(5, 13, 30, 0.4) 46%, rgba(5, 13, 30, 0.1) 76%, rgba(5, 13, 30, 0.12) 100%),
    linear-gradient(to top, #050d1e 0%, transparent 34%),
    linear-gradient(to bottom, rgba(11, 32, 68, 0.5) 0%, rgba(11, 32, 68, 0.2) 28%, transparent 52%),
    radial-gradient(52% 62% at 78% 20%, rgba(222, 169, 35, 0.16), transparent 70%),
    radial-gradient(92% 100% at 74% 44%, rgba(38, 108, 190, 0.5), transparent 76%);
}

.capa-grade {
  position: relative;
  z-index: 3;
  width: min(100%, var(--max));
  margin-inline: auto;
  padding: clamp(40px, 6vh, 76px) var(--pad);
}
/* ===== Os três braços do hero =====
   DOURADOS E MENORES (19/08/2026, a pedido do Leo).

   Emoji não aceita `color`: são glifos coloridos, o navegador desenha a arte
   pronta da fonte e ignora a cor do texto. O que funciona é filtro de imagem, e
   a ordem importa:
     grayscale(1)  apaga a cor original, seja o marrom do tom de pele aqui, seja
                   o desenho diferente do Android ou do iPhone. É o que faz o
                   resultado sair igual em todo aparelho, e não só no Windows
     sepia(1)      re-tinge o cinza num âmbar de base
     saturate/hue  puxam esse âmbar até o dourado do clube
   O relevo do desenho sobrevive porque o filtro mexe na cor, não na forma.

   NÃO É SVG DESENHADO À MÃO. Tentei quatro silhuetas antes disso e todas
   liam como bota ou patinho no tamanho pequeno; o emoji, mesmo tingido,
   continua sendo um braço reconhecível. E "outro emoji de bíceps" não existe:
   💪 é o único do Unicode, o que muda de aparelho pra aparelho é a fonte.

   TAMANHO: 1em (o original) fazia cada braço ter a altura de uma maiúscula
   inteira e brigar com a frase; 0.44em ficou pequeno demais e eles viraram
   três pontinhos. 0.6em é o meio: lê como braço e continua abaixo da linha do
   texto. O vertical-align desceu junto, de 0.28 pra 0.2, porque ele é medido
   na fonte do próprio elemento — crescendo o emoji sem mexer nele, os três
   subiriam acima da caixa alta. */
.forca {
  display: inline-block;
  font-style: normal;         /* o h1 é itálico e inclinava os três */
  font-size: 0.6em;
  line-height: 1;
  vertical-align: 0.2em;      /* alinha com o meio da caixa alta, não com a base */
  letter-spacing: 0.02em;
  filter: grayscale(1) sepia(1) saturate(5) hue-rotate(12deg) brightness(1.15);
}

.capa-texto { max-width: min(660px, 54%); }
.capa-texto h1 { margin-bottom: 26px; }
.capa-lead { margin-bottom: 36px; }
.capa-lead b { color: var(--ink); }

.capa-pe { display: flex; flex-wrap: wrap; align-items: center; gap: 22px 30px; }

/* faixa de números fechando a abertura */
.capa-numeros {
  position: relative;
  z-index: 3;
  border-top: 1px solid var(--border);
  background: rgba(5, 13, 30, 0.55);
}
.numeros-grade {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  padding-block: 22px;
}
/* O fio dourado é um ::before, e não a border-left que era antes, só pra ele
   poder CRESCER de cima pra baixo quando a faixa entra em cena (24/08/2026).
   Border não anima altura; um elemento com transform: scaleY sim, e de graça,
   porque escala roda na composição. Parado, o resultado desenhado é
   exatamente o mesmo fio de 2px de antes. */
.numeros-grade > div { position: relative; padding-left: 14px; }
.numeros-grade > div::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--amarelo);
  transform-origin: 50% 0;
  /* atrás do número, que já está subindo: o fio risca depois que o texto
     chegou, senão os dois movimentos disputam o mesmo instante */
  transition: transform 0.55s cubic-bezier(0.16, 0.72, 0.24, 1) 0.18s;
}
/* O ESTADO PADRÃO É O FIO INTEIRO, e o encolhido só existe quando o script
   marcou o elemento pra revelar. Ao contrário: sem IntersectionObserver (ou
   com o JavaScript fora do ar) ninguém nunca ganha .visivel, e o fio ficaria
   escalado a zero pra sempre — some um detalhe da marca por causa de uma
   animação que nem chegou a rodar. É a mesma regra que o .revelar já segue:
   quem não é animado nasce pronto. */
.numeros-grade > div.revelar::before { transform: scaleY(0); }
.numeros-grade > div.revelar.visivel::before { transform: scaleY(1); }
.numeros-grade b { display: block; font-size: clamp(1.2rem, 2.4vw, 1.9rem); font-style: italic; line-height: 1.1; }
.numeros-grade span { display: block; font-size: 0.6rem; font-weight: 700; color: var(--ink-dim); }

/* ===================================================================
   SEÇÕES
=================================================================== */
.secao { padding: clamp(58px, 8vh, 96px) 0; }

/* ===== O clube ===== */
.clube-grade { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 34px 54px; }
.destaque {
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}
.clube-texto p:last-child { margin-bottom: 0; }

.pilares { list-style: none; margin: 0; padding: 0; }
.pilares li {
  padding: 14px 0 14px 16px;
  border-left: 2px solid var(--border);
  /* desliza pra direita no hover (24/08/2026): a lista é o único bloco desta
     seção que responde ao mouse, e só a troca de cor da borda era discreta
     demais pra dizer isso. O passo é curto porque são três itens colados */
  transition: border-color 0.16s ease, transform 0.32s cubic-bezier(0.16, 0.72, 0.24, 1);
}
.pilares li:hover { border-left-color: var(--amarelo); transform: translateX(7px); }
.pilares b { display: block; font-size: 0.96rem; }
.pilares span { font-size: 0.86rem; color: var(--ink-dim); }

/* ===== Comissão técnica =====
   Cartão de elenco: retrato em 3:4, degradê subindo do navy pra fechar a
   base da foto, e a placa de nome apoiada nesse degradê.

   O fundo do cartão é o CREME das artes do clube, não o navy do site. É de
   propósito: as fotos que existem hoje foram tiradas contra um lençol claro,
   então creme faz o lençol virar fundo de estúdio em vez de mancha. Quando os
   recortes com fundo novo chegarem, essa mesma moldura serve, e aí dá pra
   trocar o creme por navy sem mexer em mais nada. */
/* ===== A vitrine =====
   Um card no meio, em tamanho de gente, e os vizinhos recuando pros lados.
   Quem coloca cada card no lugar é o script: ele escreve --x, --e e --o em
   cada um conforme a distância dele até o centro, e o CSS só obedece. Isso
   deixa a régua das posições num lugar só, em vez de espalhada em classes. */
.elenco {
  --carta: clamp(210px, 22vw, 290px);
  position: relative;
  display: grid;
  justify-items: center;

  /* O RECORTE NÃO É ENFEITE. Os cards de fora são posicionados por transform e
     continuam ocupando espaço de rolagem mesmo escondidos: numa tela de 360 o
     vizinho chega a 548px e a página inteira passa a rolar pro lado. Medido.
     No desktop nada estoura, mas a regra fica aqui pra valer sempre, porque é
     a largura da tela que decide se estoura, não o CSS.

     O respiro em cima e embaixo existe pra sombra do card do meio não ser
     decepada pelo próprio recorte, e a margem negativa devolve o espaço, pra
     a seção não crescer 80px por causa de um detalhe de sombra. */
  overflow: hidden;
  padding-block: 40px;
  margin-block: -40px;
}

.elenco-palco {
  position: relative;
  width: 100%;
  /* a altura é escrita pelo script, medindo o card mais alto. Os cards são
     posicionados por cima uns dos outros e não empurram nada, então sem isso
     o palco teria altura zero e a seção colapsaria. */
}

.tecnicos { position: relative; }

.tec {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--carta);
  margin-left: calc(var(--carta) / -2);
  overflow: hidden;
  background: var(--bg-2);
  /* RETÂNGULO INTEIRO, sem o canto cortado (12/08/2026, a pedido do Leo).
     O corte é o motivo da família com os cartões de turma, mas aqui ele
     brigava com o fio que corre a borda: a volta chegava no canto, encontrava
     a diagonal e parecia que faltava um pedaço do card. Movimento em volta de
     forma fechada precisa de forma fechada.
     O corte continua nos cartões de turma e nas fotos da seção Na quadra, que
     não têm fio correndo. */
  /* --x, --e e --o vêm do script. O translateX é em % da largura do próprio
     card, então a régua continua valendo quando --carta muda de tamanho. */
  transform: translateX(var(--x, 0)) scale(var(--e, 1));
  opacity: var(--o, 1);
  transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.3, 1), opacity 0.45s ease;
}

/* O véu que escurece quem não está no meio. Ele existe porque escurecer com
   opacity deixaria o card TRANSPARENTE, e aí o retrato de trás apareceria
   através do da frente: dois rostos sobrepostos e nenhum reconhecível.
   Assim o card continua opaco e só recebe uma demão de navy por cima. */
.tec::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: rgba(5, 13, 30, var(--v, 0));
  transition: background 0.45s ease;
}
/* quem está no meio é o único que recebe clique de navegação; os de fora
   viram alvo pra trazer pro centro */
.tec[data-fora] { cursor: pointer; }
.tec--ativo { box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5); }

/* ===== O fio que corre a borda do card do meio =====
   Eram quatro cantos dourados parados. Em 12/08/2026 viraram uma linha que dá
   a volta no card, a pedido do Leo.

   COMO ISSO É FEITO, porque não é óbvio. O elemento .tec-fio é uma moldura de
   2px: ele tem padding de 2px e uma máscara que apaga o miolo, sobrando só o
   anel da borda. Dentro dele gira um quadrado grande com um degradê cônico,
   onde quase tudo é transparente e um pedaço é dourado aceso. Girando por
   trás da máscara, o que se vê é o brilho passeando pela borda.

   POR QUE UM ELEMENTO E UM QUADRADO GIRANDO, e não simplesmente animar o
   ângulo do conic-gradient: animar `from <angle>` exige registrar a variável
   com @property, e onde isso não existe o gradiente inteiro vira inválido e a
   moldura some. Girar um elemento é transform puro, funciona em todo lugar e
   ainda roda na GPU. O quadrado tem 220% da largura do card justamente pra
   cobrir a diagonal dele em qualquer ângulo do giro, senão apareceria um
   canto vazio a cada volta.

   O fundo dourado apagado do próprio .tec-fio é a linha contínua por baixo:
   sem ela, o card do meio ficaria sem marcação nenhuma no instante em que o
   brilho está do outro lado.

   O ÂNGULO VEM DO SCRIPT, NÃO DE UM @keyframes (13/08/2026). Antes o giro
   era um @keyframes de ritmo fixo. Passar o mouse ou o foco por cima da
   vitrine agora acelera o fio, e soltar desacelera devagar em vez de voltar
   de um salto: é uma mola de velocidade, não uma troca de duration. CSS não
   faz isso sozinho porque mudar animation-duration no meio de uma volta
   recalcula o progresso e dá um solavanco visível. O script escreve o
   ângulo em --fio-ang a cada quadro (ligarBrilho, script.js) direto no
   #elenco, e a propriedade desce por herança até este ::before. Cor e
   desenho do cometa continuam os mesmos de sempre, só o relógio mudou de
   lugar. */
.tec-fio {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
  padding: 3px;
  /* O TRILHO É ESCURO, e é isso que faz o giro aparecer (12/08/2026).
     Passei por duas versões erradas antes: na primeira o dourado de base
     estava fraco demais e o card ficava sem moldura; na segunda ficou forte
     demais, e aí o brilho passando por cima de uma linha dourada contínua
     virava quase invisível, porque dourado sobre dourado não contrasta.
     Agora o trilho é o mesmo navy das bordas do site. O que corre em cima é
     dourado sobre escuro, que é o contraste que faz o olho ver a volta. */
  background: var(--border);
  opacity: 0;
  transition: opacity 0.35s ease;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.tec--ativo .tec-fio { opacity: 1; }

.tec-fio::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 220%;
  aspect-ratio: 1;
  /* DOIS CORPOS DE LUZ, em lados opostos, e o resto do anel fica escuro.
     Um cometa só deixava três lados do card apagados a maior parte do tempo,
     e sem nada aceso no campo de visão o giro não se lê. Com dois em oposição
     sempre há luz em movimento, e o vão escuro entre eles é justamente o que
     torna o giro visível: é a parte apagada que prova que algo está andando.
     O núcleo é #fff6dc, o dourado clareado, e não branco puro: branco puro ao
     lado do dourado do escudo lê como estouro de foto. */
  background: conic-gradient(
    from 0deg,
    transparent 0 2%,
    rgba(222, 169, 35, 0.55) 7%,
    #fff6dc 12%,
    rgba(222, 169, 35, 0.55) 17%,
    transparent 23% 52%,
    rgba(222, 169, 35, 0.55) 57%,
    #fff6dc 62%,
    rgba(222, 169, 35, 0.55) 67%,
    transparent 73% 100%
  );
  transform: translate(-50%, -50%) rotate(var(--fio-ang, 0deg));
}

/* .ficha-tec-seta (seta da ficha do professor) usa o MESMO desenho, pedido
   explícito do Leo em 22/08/2026 depois de uma primeira versão menor e sem o
   anel de luz: "bonita e elegante como a de passar os professores pro lado".
   Selector conjunto pra garantir que as duas nunca se desalinham de novo. */
.elenco-seta,
.ficha-tec-seta {
  position: absolute;
  top: 50%;
  /* Acima de qualquer card. O script empilha os cards de 10 pra baixo, e com
     a seta em 6 ela funcionava no desktop e SUMIA no celular: lá os vizinhos
     chegam na borda da tela e passavam por cima dela. */
  z-index: 20;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  padding: 0;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--ink);
  background: rgba(5, 13, 30, 0.55);
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}
.elenco-seta:hover, .ficha-tec-seta:hover { background: var(--amarelo); color: #050d1e; border-color: var(--amarelo); }
.elenco-seta:focus-visible, .ficha-tec-seta:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

/* O mesmo fio correndo, agora em volta da seta. Aqui é bem mais simples que
   no card: círculo é simétrico no giro, então dá pra girar o PRÓPRIO elemento
   do degradê, sem quadrado grande escondido atrás de máscara. A máscara aqui
   só abre o buraco do meio pra virar anel.
   O giro é mais rápido que o do card (2,8s contra 4,5s) porque a volta é
   muito menor: no mesmo tempo, o brilho pareceria estar se arrastando. */
.elenco-seta::before, .ficha-tec-seta::before {
  content: "";
  position: absolute;
  inset: -4px;
  z-index: -1;
  border-radius: 50%;
  pointer-events: none;
  /* mesma régua do card: dois corpos de luz em oposição e o vão escuro entre
     eles, pra a seta e o card contarem a mesma história */
  background: conic-gradient(
    from 0deg,
    var(--border) 0 3%,
    rgba(222, 169, 35, 0.55) 9%,
    #fff6dc 14%,
    rgba(222, 169, 35, 0.55) 19%,
    var(--border) 26% 53%,
    rgba(222, 169, 35, 0.55) 59%,
    #fff6dc 64%,
    rgba(222, 169, 35, 0.55) 69%,
    var(--border) 76% 100%
  );
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
          mask: radial-gradient(closest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  animation: correr-fio-redondo 2.8s linear infinite;
}
@keyframes correr-fio-redondo {
  to { transform: rotate(360deg); }
}
/* com o botão cheio de dourado no hover, o anel vira ruído em volta dele */
.elenco-seta:hover::before, .ficha-tec-seta:hover::before { opacity: 0; }
/* AFASTADAS DA BORDA (19/08/2026). Estavam em 0, encostadas na parede do
   .elenco, e o .elenco tem overflow: hidden por outro motivo (o card vizinho
   estourava a rolagem lateral no celular). O anel de luz da seta é um ::before
   com inset: -4px, ou seja, ele nasce 4px MAIOR que o botão — e eram esses 4px
   que o recorte comia, deixando o círculo com as duas laterais cegadas.
   Medido nas duas pontas, nas quatro larguras: folga era exatamente 0.
   10px dá os 4px do anel mais respiro, e não some com o corredor que as setas
   têm no celular. */
.elenco-seta--tras { left: 10px; }
.elenco-seta--frente { right: 10px; }

/* Posição da seta da FICHA (não da vitrine): fora da caixa, no fundo escuro,
   nunca em cima de foto ou texto (pedido do Leo em 22/08/2026, depois de a
   primeira versão ficar por cima da lista de formação). A caixa é centrada
   sozinha (ver .ficha-tec-caixa) com largura min(820px, 100vw - 32px), então
   a distância do centro da tela até a borda dela é min(410px, 50vw - 16px);
   a seta soma mais 64px (46px dela + 18px de respiro) pra fora dessa borda.
   Sem folga extra pro celular: ali a caixa quase toca as bordas da tela e
   sobra, o override em @media (max-width: 720px) resolve. */
.ficha-tec-seta {
  left: auto; right: auto;
}
.ficha-tec-seta--tras { left: calc(50% - min(410px, calc(50vw - 16px)) - 64px); }
.ficha-tec-seta--frente { right: calc(50% - min(410px, calc(50vw - 16px)) - 64px); }

/* ===== "Ver formação", em todo cartão de professor =====
   SEMPRE VISÍVEL (19/08/2026, a pedido do Leo). A primeira versão só aparecia
   ao passar o mouse, e botão que só existe depois de descobrir que existe não
   convida ninguém a clicar — além de ser invisível no celular, onde não há
   mouse pra passar. */
.tec-mais {
  margin-top: 12px;
  padding: 8px 14px;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #050d1e;
  background: var(--amarelo);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}
.tec-mais:hover { background: #f0c243; transform: translateY(-1px); }
.tec-mais:focus-visible { outline: 2px solid #fff6dc; outline-offset: 3px; }

.elenco-pontos { display: flex; gap: 4px; margin-top: 18px; }
/* O traço tem 4px de altura, e 4px não é alvo de toque: a norma pede 24. O
   padding estica a área clicável pra 30x28 e o background-clip: content-box
   segura a tinta dentro do traço, então o dedo ganha espaço sem o desenho
   engordar. O gap encolheu junto porque o respiro agora vem do padding. */
.elenco-pontos button {
  width: 30px; height: 4px;
  padding: 12px 3px;
  background: var(--border);
  background-clip: content-box;
  border: 0;
  box-sizing: content-box;
  cursor: pointer;
  transition: background 0.2s ease;
}
/* background-COLOR, e não o atalho background. O atalho reescreve todas as
   partes que ele cobre, inclusive o background-clip: content-box lá de cima,
   que volta pro padrão border-box. O resultado era o ponto selecionado pintar
   a área de toque inteira e virar um bloco de 30x28 no meio de quatro
   tracinhos de 4px. */
.elenco-pontos button[aria-selected="true"] { background-color: var(--amarelo); }
.elenco-pontos button:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 4px; }

.tec-foto {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: #e8e4dc; /* creme das artes, atrás da foto */
}
.tec-foto img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* --foco vem do style de cada cartão: é a altura do enquadramento, o único
     número que muda de pessoa pra pessoa */
  object-position: 50% var(--foco, 20%);
  /* levíssima correção de cor pras cinco fotos parecerem do mesmo dia */
  filter: saturate(0.92) contrast(1.04);
}

/* o degradê que costura a foto na placa de nome. Fica no ::after do
   contêiner, e não na imagem, pra não entrar no object-fit */
.tec-foto::after {
  content: "";
  position: absolute; inset: auto 0 0 0;
  height: 46%;
  background: linear-gradient(to top, var(--bg-2) 6%, rgba(10, 23, 48, 0.72) 46%, transparent 100%);
  pointer-events: none;
}

/* O bloco de texto sobe 46px pra encostar no degradê da foto. Isso funcionava
   enquanto ele tinha altura conhecida; com o rótulo de função quebrando em
   duas linhas no celular (o "[ FUNÇÃO A CONFIRMAR ]"), a primeira linha subia
   pra cima da camisa clara e o laranja sumia dentro dela.
   Por isso o véu vive aqui e não só na foto: preso ao próprio texto, ele
   cobre a faixa de sobreposição seja qual for a altura do bloco. O degradê da
   foto continua, os dois se somam. */
.tec-txt {
  position: relative;
  padding: 0 18px 20px;
  margin-top: -46px;
  background: linear-gradient(to bottom, rgba(10, 23, 48, 0) 0, rgba(10, 23, 48, 0.92) 30px, var(--bg-2) 52px);
}
.tec--chefe .tec-txt {
  background: linear-gradient(to bottom, rgba(14, 34, 70, 0) 0, rgba(14, 34, 70, 0.92) 30px, var(--bg-3) 52px);
}
.tec-cargo {
  font-size: 0.56rem; font-weight: 800; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--amarelo);
  margin: 0 0 6px;
}
.tec-txt h3 { font-size: 1.35rem; font-style: italic; margin-bottom: 8px; }
.tec-bio { font-size: 0.86rem; margin: 0 0 8px; }

/* O chefe da comissão ganha o degrau de cima no fundo. O canto dourado que ele
   tinha saiu em 11/08/2026, junto com a virada pra vitrine: o ::after do .tec
   virou o véu que escurece quem não está no meio, e um só pseudo-elemento não
   faz as duas coisas. A perda é pequena, porque quem está no centro já recebe
   a moldura dourada dos quatro cantos, e o "Responsável técnico" escrito na
   placa diz o cargo sem depender de enfeite. */
.tec--chefe { background: var(--bg-3); }
.tec--chefe .tec-foto::after { background: linear-gradient(to top, var(--bg-3) 6%, rgba(14, 34, 70, 0.72) 46%, transparent 100%); }

/* ===== Turmas ===== */
.turmas { display: grid; grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); gap: 18px; }
/* Três colunas fixas no monitor grande, e não o que o auto-fit escolher.
   São 6 cartões: com 4 colunas a segunda fileira fica com dois cartões e dois
   buracos, o que faz o bloco parecer inacabado bem na seção que mais precisa
   parecer completa. Com 3, fecha 3 e 3. */
@media (min-width: 1000px) { .turmas { grid-template-columns: repeat(3, 1fr); } }

/* RETÂNGULO INTEIRO, cantos arredondados (19/08/2026, a pedido do Leo). O bico
   diagonal no alto à direita saiu: é o mesmo corte que já tinha saído das
   fotos da esteira em 17/08, e nos cartões de turma ele fazia o bloco parecer
   um adesivo com a ponta descolando. O clip-path também impedia qualquer
   brilho em volta, porque recortava tudo que passasse da borda. */
.turma {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  padding: 26px 24px 24px;
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.26);
  transition:
    transform 0.5s cubic-bezier(0.16, 0.72, 0.24, 1),
    box-shadow 0.5s cubic-bezier(0.16, 0.72, 0.24, 1),
    border-color 0.35s ease,
    background 0.35s ease;
}

/* ANEL DE LUZ, só na borda.
   O truque das duas máscaras é o que transforma um retângulo pintado num
   contorno de 1px: a primeira máscara cobre a área de conteúdo, a segunda
   cobre o elemento inteiro, e o `exclude` deixa só a diferença entre as duas,
   que é exatamente a faixa do padding. Sem isso, o degradê pintaria o cartão
   inteiro e o texto sumiria por cima dele. */
.turma::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(140deg,
    rgba(222, 169, 35, 0.85) 0%,
    rgba(91, 155, 240, 0.45) 38%,
    transparent 68%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}

.turma:hover,
.turma:focus-within {
  background: var(--bg-3);
  border-color: transparent;
  /* Sobe E cresce (24/08/2026). Só a subida movia o cartão pra perto do topo;
     com a escala junto ele vem pra FRENTE, que é o que a sombra maior e o
     anel aceso já estavam contando. 1,018 é pouco de propósito: numa grade de
     quatro, escala grande empurra visualmente os vizinhos e a fileira inteira
     parece tremer quando o mouse atravessa ela. */
  transform: translateY(-8px) scale(1.018);
  /* dois planos: a sombra que afasta o cartão do fundo, e o halo dourado
     bem aberto e fraco, que é o que lê como brilho e não como contorno */
  box-shadow:
    0 26px 50px rgba(0, 0, 0, 0.45),
    0 0 40px -8px rgba(222, 169, 35, 0.32);
}
.turma:hover::before,
.turma:focus-within::before { opacity: 1; }

/* o número acende junto, senão o cartão inteiro se move e ele fica parado */
.turma-num {
  font-size: 2.4rem;
  line-height: 1;
  color: rgba(91, 155, 240, 0.42);
  margin-bottom: 10px;
  transform-origin: 0 100%;   /* cresce a partir do canto, não do centro */
  transition: color 0.45s ease, transform 0.5s cubic-bezier(0.16, 0.72, 0.24, 1);
}
.turma:hover .turma-num,
.turma:focus-within .turma-num { color: rgba(222, 169, 35, 0.75); transform: scale(1.12); }
/* ===== Tipografia dos cartões de turma =====
   Saíram do Arial Black itálico (19/08/2026, escolha do Leo entre três
   direções). Passam a usar a sans do sistema, a mesma do corpo do site, em
   caixa alta com peso 800 e as letras afastadas.

   POR QUE ISSO É "TROCAR A FONTE" mesmo sendo sans de novo: --display é Arial
   Black, uma família à parte; o corpo é Segoe UI no Windows e San Francisco no
   Mac. São desenhos diferentes, e a diferença fica óbvia lado a lado com o
   hero, que continua em Arial Black.

   O tracking é o que faz o trabalho aqui. Caixa alta apertada grita; caixa
   alta espaçada é a mesma palavra dita baixo, e era esse o pedido.

   NOTA PRA QUEM MEXER NO GUIA DE MARCA: a seção 04 ainda manda Arial Black
   itálico em todo título. Esta seção é a exceção combinada, não um
   esquecimento. Se virar padrão do site, o guia é que precisa mudar. */
.turmas h3 {
  font-family: inherit;
  font-style: normal;
  font-weight: 800;
  font-size: 1.16rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}
.turma-num {
  font-family: inherit;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.turma-pub {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--amarelo);
  margin: 6px 0 14px;
}
.turma > p { font-size: 0.92rem; letter-spacing: 0.005em; }

.dados { display: flex; flex-wrap: wrap; gap: 0 22px; margin: 6px 0 20px; padding-top: 14px; border-top: 1px solid var(--border); }
/* as duas colunas repartem a largura do card por igual: masculino e feminino
   treinam em horários diferentes, então cada gênero é uma coluna, não uma
   linha de "dias" e outra de "horário" */
.dados > div { flex: 1 1 0; min-width: 92px; }
.dados dt { font-size: 0.58rem; font-weight: 800; color: var(--royal-claro); margin-bottom: 3px; }
.dados dd { margin: 0 0 8px; font-size: 0.9rem; line-height: 1.4; color: var(--ink); }
/* Cor e tamanho subiram de --ink-dim/0.72rem pra --ink/0.82rem em 20/08/2026,
   a pedido do Leo: "a partir dos X anos" é a idade mínima da turma, informação
   que decide se o pai manda mensagem ou não, e o tratamento de rodapé (cor
   apagada, fonte pequena) escondia justamente o dado mais prático da linha. */
.dados dd i { font-style: normal; font-weight: 600; font-size: 0.82rem; line-height: 1.3; color: var(--ink); }

/* ===== Vídeo dentro do card de turma (22/08/2026) =====
   Mesma ideia da ATA (poster com a logo, botão de play redondo, clique abre
   um vídeo tocando por cima da página), só que ali é UM vídeo por card e aqui
   são OITO: cada coluna de .dados (Masculino/Feminino, Turma A/Turma B) ganha
   o próprio vídeo, porque foi assim que o clube gravou e nomeou os arquivos.
   Por isso o vídeo mora dentro da coluna, em cima do dt/dd, em vez de
   dominar o card inteiro como na ATA: com 8 vídeos pra caber em 4 cards, um
   vídeo em tela cheia por card ocuparia o dobro do espaço que o card tem.
   max-width trava o tamanho pra não estourar em telas largas com poucas
   colunas (a "Escolinha" some numa fileira de 3 no desktop). */
.turma-video {
  position: relative;
  display: block;
  width: 100%;
  max-width: 128px;
  aspect-ratio: 4 / 5;
  margin: 0 0 10px;
  padding: 0;
  border: none;
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  background: var(--bg-3);
}
.turma-video-media {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 30%;
  pointer-events: none;
  /* o selo cresce por dentro do próprio recorte quando o cartão acende
     (24/08/2026): quem já tem overflow: hidden ganha esse movimento de graça,
     e é o que faz o cartão inteiro parecer vivo em vez de só levantar */
  transition: transform 0.7s cubic-bezier(0.16, 0.72, 0.24, 1);
}
.turma:hover .turma-video-media,
.turma:focus-within .turma-video-media { transform: scale(1.09); }
/* degradê embaixo, igual ao da ATA: sem ele o botão de play some em cima de
   trecho claro do vídeo/logo */
.turma-video::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(5, 13, 30, 0) 55%, rgba(5, 13, 30, 0.6) 100%);
}
.turma-video-play {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 32px; height: 32px;
  border-radius: 50%;
  background: rgba(5, 13, 30, 0.55);
  border: 2px solid var(--amarelo);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  transition: transform 0.2s ease, background 0.2s ease;
}
.turma-video-play svg { width: 13px; height: 13px; color: var(--amarelo); margin-left: 2px; }
.turma-video:hover .turma-video-play,
.turma-video:focus-visible .turma-video-play { transform: translate(-50%, -50%) scale(1.12); background: var(--amarelo); }
.turma-video:hover .turma-video-play svg,
.turma-video:focus-visible .turma-video-play svg { color: #050d1e; }
.turma-video:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

/* Nota de critério da turma, hoje só no avançado. Fica acima do botão e
   colada na lista de horários, porque completa a informação da lista em vez
   de abrir assunto novo. */
.turma-nota {
  margin: -8px 0 20px;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--ink-dim);
}
.turma .botao { margin-top: auto; align-self: flex-start; }

/* o degrau mais alto e o card de ajuda usam o dourado */
.turma--topo { background: var(--bg-3); border-color: rgba(222, 169, 35, 0.28); }
.turma--topo .turma-num { color: rgba(222, 169, 35, 0.6); }
/* nele o anel já fica meio aceso parado: é o cartão que o clube quer que a
   pessoa olhe primeiro, e o realce some no hover dos outros se ele não tiver
   nada a mais */
.turma--topo::before { opacity: 0.45; }
.turma--ajuda { background: transparent; justify-content: center; }
.turma--ajuda h3 { font-size: 1.45rem; }
.turma--ajuda .botao { margin-top: 18px; }

/* Setas do carrossel de turmas, só existem enquanto celular (25/08/2026, a
   pedido do Leo: "ao invés de rodar pra baixo, ter um botão pra rodar pro
   lado"). No desktop/tablet a grade de 2-3 colunas já mostra tudo de uma vez
   e a trilha nem rola, então as setas ficam escondidas por padrão e só
   aparecem dentro da media query onde a .turmas vira trilha horizontal. */
.turmas-nav { display: none; }
.turmas-seta {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.turmas-seta:hover, .turmas-seta:focus-visible { border-color: var(--amarelo); color: var(--amarelo); outline: none; }
.turmas-seta:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

/* ===== Horários ===== */
/* rolagem própria: a grade é larga e o corpo da página nunca pode rolar pro
   lado no celular.

   O tabindex="0" no HTML não é enfeite de acessibilidade: contêiner que rola
   e não recebe foco é contêiner que quem navega por teclado não consegue
   rolar. Como ele vira parada de tabulação, precisa de anel de foco visível.

   A dica escrita embaixo diz que tem mais coisa pro lado. Em 360px a tabela
   mostra menos da metade das colunas, e tabela cortada sem aviso nenhum lê
   como layout quebrado, não como "arrasta". Ela só aparece onde a tabela de
   fato não cabe (ver a media query lá embaixo). */
.grade-wrap { overflow-x: auto; }
.grade-wrap:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

.grade-dica {
  display: none;
  margin: 10px 0 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--royal-claro);
}
.grade-dica::after { content: " \2192"; }
.grade { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 0.94rem; }
.grade thead th {
  background: var(--royal);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 800;
  text-align: left;
  padding: 12px 20px;
}
.grade tbody th, .grade tbody td {
  text-align: left;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  font-weight: 400;
}
.grade tbody th { color: var(--ink); font-weight: 700; }
.grade tbody td { color: var(--ink-dim); }
.grade tbody tr:nth-child(odd) { background: rgba(10, 23, 48, 0.55); }
/* A linha ACENDE em vez de trocar de cor de estalo (24/08/2026): a transição
   entra e o texto apagado das colunas de horário sobe pro branco cheio junto
   do fundo. Numa grade de nove linhas onde as células vizinhas são todas
   parecidas, é o que confirma qual linha o olho está seguindo. */
.grade tbody th, .grade tbody td { transition: background 0.24s ease, color 0.24s ease; }
.grade tbody tr:hover th, .grade tbody tr:hover td { background: rgba(29, 91, 196, 0.14); }
.grade tbody tr:hover td { color: var(--ink); }

/* linha que veio dos cartões de turma do próprio clube. Marcada pra ficar
   claro, na apresentação, o que é dado real e o que é espaço reservado. */
.confirmada th { box-shadow: inset 4px 0 0 var(--amarelo); }
.confirmada td { color: var(--ink); }

.nota-pe { margin-top: 18px; font-size: 0.88rem; }
.marca-ok { display: inline-block; width: 4px; height: 12px; background: var(--amarelo); vertical-align: -1px; margin-right: 6px; }

/* ===== Matrícula ===== */
.trilha { list-style: none; margin: 0 0 40px; padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 0 20px; }
.trilha li { position: relative; padding: 26px 16px 0 0; border-top: 3px solid var(--border); }
/* O tico dourado corre da esquerda pra direita quando o passo entra
   (24/08/2026). Cada passo já entra em cascata pela grade, então os quatro
   riscos acontecem um atrás do outro e a régua da matrícula se desenha
   sozinha, na ordem em que a pessoa vai cumprir. */
.trilha li::before {
  content: ""; position: absolute; top: -3px; left: 0;
  width: 42px; height: 3px; background: var(--amarelo);
  transform-origin: 0 50%;
  transition: transform 0.5s cubic-bezier(0.16, 0.72, 0.24, 1) 0.2s;
}
/* mesma regra do fio dos números: nasce desenhado, e só encolhe quando existe
   alguém pra animar ele de volta */
.trilha li.revelar::before { transform: scaleX(0); }
.trilha li.revelar.visivel::before { transform: scaleX(1); }
.trilha-num { display: block; font-size: 1.7rem; font-style: italic; line-height: 1; color: rgba(91, 155, 240, 0.45); margin-bottom: 10px; }
.trilha h3 { font-size: 1.02rem; font-style: italic; }
.trilha p { font-size: 0.88rem; margin: 0; }

/* ===== Cartão de foto (.galeria-foto) =====
   Base compartilhada por toda foto clicável com lupa: os quadros das duas
   travessias ("Na quadra" e "O elenco", ver ligarTravessia em script.js) e
   qualquer esteira de foto que venha a existir de novo no futuro.

   ONDE ESTAVA ANTES: até 25/08/2026 "O elenco" era uma ESTEIRA que corria
   sozinha — mesmo esqueleto da faixa de patrocínio (.esteira/.esteira-trilho,
   laço de -50%, animação por CSS), com o modificador .esteira--fotos aqui em
   cima definindo o que era diferente (sem borda, respiro maior, duração
   própria por ID). Virou travessia no mesmo dia que "Na quadra", a pedido do
   Leo, e o modificador (junto com #galeriaElenco e a trava .esteira--presa
   que pausava a animação enquanto a lupa estava aberta) saiu inteiro: nada
   na página usa mais .esteira--fotos, e código morto que ninguém lê some,
   não fica de enfeite. A faixa de patrocínio continua com .esteira puro,
   sem o modificador — está viva e intacta, só perdeu a variante de foto.

   O CARTÃO EM SI, agora a parte que não mudou: todos na mesma moldura 4:5 em
   pé, com object-fit: cover. A fila regular é o
   que faz a faixa ler como faixa, e o corte não come informação porque essas
   são FOTOS, sem texto embutido (o oposto das artes do torneio, que traziam o
   cabeçalho e a placa "PÓDIO" dentro da imagem e por isso não podiam ser
   cortadas de jeito nenhum). Quem mostra a foto inteira é a lupa.

   Houve uma versão de altura fixa e largura livre, em que cada cartão ficava
   com a proporção da própria foto, e ela foi desfeita no mesmo dia: nasceu de
   eu ler "card completo" como "foto sem recorte", quando o pedido era tirar o
   canto cortado aqui embaixo.

   É <button> de verdade, e não div: toque de celular não tem hover, então a
   lupa também abre no clique, e teclado chega nela pelo Tab. O reset de
   aparência de botão aqui embaixo existe por causa disso. */
.galeria-foto {
  flex: 0 0 auto;
  width: clamp(158px, 21vw, 224px);
  aspect-ratio: 4 / 5;
  padding: 0;
  overflow: hidden;
  background: var(--bg-2);
  border: 0;
  cursor: zoom-in;
  /* RETÂNGULO INTEIRO, sem o canto cortado (17/08/2026, a pedido do Leo).
     Os cartões de turma e de professor têm esse bico diagonal no alto à
     direita, e eu tinha repetido ele aqui pra família bater. Nos outros o
     corte cai sobre fundo ou sobre degradê; sobre foto de jogo ele lê como
     dobra de papel, uma quina faltando em cima da imagem. */
  transition: filter 0.2s ease;
}
/* --foco é o mesmo gancho de enquadramento dos cartões de professor: vem
   inline no <img> quando o assunto da foto não está no meio dela. Nenhuma das
   oito precisa hoje, e o padrão 50% 50% serve, mas o gancho fica porque foto
   nova entra sem tocar no CSS.

   ATENÇÃO ao mexer nele: qual eixo o cover corta depende da proporção da foto
   contra a do cartão (4:5, ou 0,8). As cinco fotos 1:1 são mais largas que a
   moldura, então nelas o corte é nas LATERAIS e mexer no valor vertical não
   faz nada. Só as duas 3:4 (1440x1920) cortam em cima e embaixo. */
.galeria-foto img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--foco, 50% 50%);
  /* Quem cresce é a IMAGEM dentro da moldura, não o cartão. O cartão tem
     overflow: hidden, então a foto avança por baixo da borda e volta, sem
     empurrar o vizinho nem ser decepada pelo recorte da esteira. Ampliar o
     cartão faria as duas coisas.
     A curva é de saída (rápido no começo, freando no fim) e o tempo é longo
     de propósito: crescimento de imagem em 0,2s lê como estalo. */
  transform: scale(1);
  /* 0,9s. Já esteve em 0,55 e ainda lia como estalo (19/08/2026). Numa esteira
     que anda sozinha, o zoom concorre com o movimento do trilho: pra ser lido
     como "a foto está crescendo" e não como "a foto pulou", ele precisa durar
     mais que o olho leva pra reparar nele. */
  transition: transform 0.9s cubic-bezier(0.16, 0.72, 0.24, 1);
}
/* a foto sob o mouse acende e as vizinhas ficam como estão: a esteira inteira
   já parou de andar, o realce só diz qual delas a lupa está mostrando */
.galeria-foto:hover, .galeria-foto:focus-visible { filter: brightness(1.12) saturate(1.05); }
.galeria-foto:hover img, .galeria-foto:focus-visible img { transform: scale(1.07); }
.galeria-foto:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

/* Lupa: cópia ampliada da foto sob o mouse, presa à tela (position: fixed) e
   centralizada pelo script no cartão.

   ELA CRESCE EM CIMA DA FAIXA, e não acima dela. A primeira versão tentava
   encaixar a lupa no espaço livre acima do cartão, com queda pra baixo quando
   não cabia, e não cabia nunca: num notebook de 900px sobram uns 200px acima
   da faixa e 260 abaixo, e uma foto em pé que vale a pena olhar tem 400 e
   poucos. O resultado era a lupa encostada no topo da tela, cobrindo o título
   da seção. Centralizada, ela lê como a própria foto crescendo no lugar.

   pointer-events: none É ESTRUTURAL, não enfeite: a lupa cobre o cartão que a
   abriu e, se recebesse ponteiro, o mouse entraria nela, sairia do cartão, a
   lupa fecharia, o mouse voltaria pro cartão e ela abriria de novo, num piscar
   sem fim.

   Fecha com visibility + opacity, e NÃO com display: none, porque o script
   precisa medir a caixa antes de mostrar pra centralizar. Elemento com
   display: none não tem medida nenhuma.

   A LARGURA VEM DA FOTO (width: max-content), o contrário do normal: a altura
   é o que a tela limita, então quem manda é a altura da imagem, e a caixa se
   ajusta. Fixar a largura e deixar a altura livre encheria a lupa de tarja
   preta nas laterais nas fotos 1:1, ou estouraria a tela nas 3:4. */
.galeria-lupa {
  position: fixed;
  top: 0; left: 0;
  z-index: 80;
  margin: 0;
  width: max-content;
  max-width: 92vw;
  /* moldura igual nos quatro lados: quando havia legenda, o pé era mais
     estreito pra ela encostar na foto */
  padding: 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  transform: scale(0.94);
  pointer-events: none;
  /* Mais lento e com curva de saída (era 0,16s linear-ish, a pedido do Leo em
     19/08/2026): a lupa abria como se piscasse. Sair é um pouco mais rápido
     que entrar, que é como o olho espera — o que chega se anuncia, o que sai
     não precisa de cerimônia. O 0.94 de partida é menor que o 0.97 anterior
     justamente pra o movimento ser percebido como crescer, e não como aparecer. */
  transition: opacity 0.32s ease, transform 0.38s cubic-bezier(0.4, 0, 0.7, 1), visibility 0.38s;
}
.galeria-lupa--ativa {
  transition: opacity 0.34s ease, transform 0.62s cubic-bezier(0.16, 0.72, 0.24, 1), visibility 0s;
}
.galeria-lupa--ativa { opacity: 1; visibility: visible; transform: none; }
/* A proporção de cada foto vem em --ar, escrita pelo script a partir dos
   atributos width/height do <img> do cartão. Com altura e proporção definidas,
   a largura é consequência: a foto aparece inteira, sem corte e sem tarja.
   O 4/5 daqui é só o piso pro primeiro quadro, antes de qualquer hover. */
.galeria-lupa img {
  display: block;
  /* o 78vw é o que segura a foto QUADRADA no celular: nela a largura é igual à
     altura, e sem esse terceiro limite a caixa passaria da tela e ia depender
     do max-width pra ser cortada */
  height: min(58vh, 520px, 78vw);
  width: auto;
  max-width: 100%;
  aspect-ratio: var(--ar, 4 / 5);
  /* rede de segurança: se o max-width ainda apertar a caixa em alguma tela, a
     altura continua a que foi pedida e a proporção quebraria. Com o contain a
     foto perde um pouco de tamanho, e nunca a forma */
  object-fit: contain;
  background: #050d1e;
}

.galeria-dica {
  margin: 0 0 4px;
  font-size: 0.76rem;
  color: var(--ink-dim);
}

/* ===================================================================
   NA QUADRA: A TRAVESSIA (25/08/2026)
===================================================================
   O palco gruda no topo e a fila de fotos caminha PRA O LADO enquanto a
   página desce. A rolagem continua sendo vertical, de verdade: o que é
   lateral é só a animação. Ideia trazida pelo Leo de prints do
   walk.productions, com a mecânica que a abertura já usa pro vídeo.

   TRÊS PEÇAS, E CADA UMA TEM UM PORQUÊ DE ESTAR ONDE ESTÁ:
   .travessia         a PISTA. É ela que tem altura de sobra, e essa altura
                      é o curso de rolagem que o palco consome preso
   .travessia-palco   o que GRUDA (position: sticky). Sem overflow recortado
                      em nenhum ancestral dele, senão o ancestral vira o
                      scrollport e o palco para de grudar. Foi o que já
                      pegou a abertura uma vez
   .travessia-janela  quem RECORTA. É filha do palco, não mãe, exatamente por
                      causa da linha acima

   O ESTADO PADRÃO DAQUI É A ROLAGEM LATERAL COMUM, não o palco preso. Quem
   prende é .travessia--fixa, escrita pelo script só quando vale a pena (tela
   larga, sem prefers-reduced-motion). Sem script, no celular ou com movimento
   reduzido, a janela é uma fila que se arrasta com o dedo e nenhuma foto fica
   inalcançável atrás de um overflow: hidden. Mesma escolha do .capa--scrub.

   A CONTA DA ALTURA DA PISTA mora aqui no CSS, e não no script, pra ela
   valer já no PRIMEIRO QUADRO. Se o script esticasse a pista depois, tudo
   que está abaixo desta seção desceria de repente, e quem recarrega a página
   no meio dela seria largado longe do lugar (foi o que aconteceu com a pista
   do vídeo em 13/08/2026). A largura do trilho é previsível: são --quadros
   cartões de largura conhecida, mais o vão entre eles e a borda das pontas.
   O 1,04 é a média dos fatores de tamanho lá embaixo (1,26 / 0,82 / 1 / 1,1),
   e não precisa ser exato: o script MEDE a distância real e usa ela pra
   andar. O que o CSS decide aqui é só o RITMO, quanto se rola por pixel
   andado. */
.travessia {
  /* O LIMITE DE ALTURA (o 25,3vh) É O QUE MANDA, não a largura, na maior parte
     das telas de desktop. A janela é o que sobra da tela depois do cabeçalho e
     do rodapé de controle, e os dois são texto de altura quase fixa em px:
     numa tela baixa eles comem uma fatia bem maior do que numa alta. O quadro
     maior do ciclo tem 1,26 × 1,25 de altura em cima disso, mais o desvio
     vertical que empurra ele ainda mais alto — e foi ficando raso demais que
     a foto começou a ser decepada pelo overflow da janela.
     ERA 27VH ATÉ 25/08/2026, quando a dica de uso subiu pro cabeçalho (virou
     .travessia-dica, ver .travessia-topo mais abaixo) e engordou o topo da
     seção em texto — o mesmo corte de 5px que motivou o número original
     voltou, agora numa janela um pouco menos alta. 25,3vh foi recalibrado
     medindo de novo, não estimado.
     Mexeu neste número, na altura do cabeçalho, ou no desvio vertical dos
     cartões, refaz a medida numa tela baixa antes de dar por pronto. */
  --quadro-w: clamp(150px, min(21vw, 25.3vh), 306px);
  --quadro-gap: clamp(13px, 1.5vw, 26px);
  /* Borda das pontas: respiro, e só. Houve uma versão em que ela valia MEIA
     TELA, e o motivo era real: a primeira e a última foto nunca alcançavam o
     meio da janela (no começo o trilho está em zero, no fim já andou tudo), e
     as duas passavam a travessia inteira escondidas. A meia tela resolvia
     isso e criava outro problema pior — metade da tela vazia no primeiro
     quadro da seção, que é justamente o quadro que a pessoa vê ao chegar.
     Quem resolve isso agora é o script, com uma LINHA DE FOCO QUE VARRE a
     janela (procurar focoIni/focoFim em ligarTravessia): ela começa em cima
     da primeira foto e termina em cima da última, em vez de ficar parada no
     meio. Cada foto ganha o momento dela sem custar tela vazia, e o trilho
     ficou uns 30% mais curto de quebra. */
  --quadro-borda: clamp(20px, 6vw, 130px);
  /* Quantos pixels de rolagem cada pixel de caminhada lateral custa. É ele que
     decide o comprimento da parte presa: pista = uma tela + curso × ritmo.

     O NÚMERO SE CALIBRA PELA ROLAGEM POR FOTO, não pelo ritmo em si, porque o
     ritmo sozinho não diz nada — ele depende do comprimento do trilho, que
     depende do tamanho da tela. A conta que importa é
     `curso × ritmo ÷ (fotos − 1)`, quanto se rola pra trocar de foto. Em 1,55
     isso dá umas 170px numa tela de 1600 e 126px numa de 1280, entre uma e
     duas voltas de roda de mouse por foto. Abaixo de umas 120px a foto passa
     antes de ser vista; acima de umas 250px a seção vira escada longa demais.
     Da última vez esse número foi mexido às cegas (0,85, e depois 1,75 sem
     refazer a conta): com o trilho encurtado pela borda menor, 0,85 tinha
     virado 87px por foto, metade do que dava antes com o mesmo valor. Ritmo
     não se copia entre versões, se recalcula. */
  --ritmo: 1.55;
  --palco-h: calc(100vh - var(--h-topo));
  --trilho-w: calc(2 * var(--quadro-borda) + var(--quadros, 9) * (var(--quadro-w) * 1.04 + var(--quadro-gap)));
  --curso: max(0px, calc(var(--trilho-w) - 100vw));
  position: relative;
}
.travessia--fixa { height: calc(var(--palco-h) + var(--curso) * var(--ritmo)); }

.travessia-palco { display: flex; flex-direction: column; }
.travessia--fixa .travessia-palco {
  position: sticky;
  top: var(--h-topo);
  height: var(--palco-h);
}

/* O cabeçalho FICA na tela o tempo todo da travessia, que é o que a
   referência faz: "PROJETOS" parado no alto enquanto os projetos passam por
   baixo. Sem isso, o título sai de cena logo no começo e a pessoa passa duas
   telas olhando foto sem saber do que é a seção.
   A margem do .cabeca comum é grande demais pra um cabeçalho que divide a
   tela com a fila e com o rodapé de controle. */
.travessia-topo {
  flex: 0 0 auto;
  padding-top: clamp(18px, 3vh, 40px);
  /* duas colunas: título à esquerda, dica de uso encostada na base dele, à
     direita. O alinhamento é pela BASE (align-items: end) pra a dica assentar
     na mesma linha da frase de apoio do título, e não flutuar no meio de um
     bloco de três alturas diferentes */
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 12px clamp(20px, 4vw, 60px);
}
.travessia-topo .cabeca { margin-bottom: clamp(14px, 2.4vh, 30px); }
.travessia-dica { text-align: right; margin-bottom: clamp(20px, 3vh, 36px); }
@media (max-width: 720px) {
  .travessia-topo { grid-template-columns: 1fr; }
  .travessia-dica { text-align: left; margin-bottom: 18px; }
}
/* Tela estreita: a legenda sobe pra uma linha só dela e embaixo fica
   "‹ 05/09 ›". Em linha única, o título da foto não tem onde encolher (é uma
   frase, não uma palavra) e empurrava a seta de avançar pra fora da tela —
   a seta sumia sem deixar rastro, que é o pior tipo de quebra. */
/* 760 e não 620: o ponto de virada é onde a linha única APERTA, não onde ela
   estoura. Entre uns 620 e uns 740 as duas setas ainda cabem na conta, mas
   sobra tão pouco pro título da foto que ele quebra em duas linhas e a barra
   fica torta. Virar antes é de graça — numa tela de 700px duas linhas de
   controle não incomodam ninguém. */
@media (max-width: 760px) {
  /* GRADE COM ÁREAS NOMEADAS, e não flex-wrap com order: a versão com wrap
     dependia de o título ocupar uma linha inteira sozinho pra empurrar as
     setas pra baixo, e quando ele não ocupava, tudo voltava pra uma linha só
     e a seta de avançar saía da tela. Grade não tem esse "quando": cada peça
     tem lugar fixo, linha de cima pro título, linha de baixo pros controles. */
  .travessia-controle {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "leg  leg   leg"
      "ant  conta prox";
    row-gap: 12px;
  }
  .travessia-legenda { grid-area: leg; justify-content: flex-start; text-align: left; }
  .travessia-conta { grid-area: conta; text-align: center; }
  .travessia-seta:first-of-type { grid-area: ant; }
  .travessia-seta:last-of-type { grid-area: prox; justify-self: end; }
}

.travessia-janela {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  /* padrão: fila que se arrasta. O --fixa troca por overflow: hidden */
  overflow-x: auto;
  overflow-y: hidden;
  /* sem scroll-snap: a linha de foco que revela a foto VARRE a janela (ela
     nao fica no meio), entao um encaixe que centraliza o cartao brigaria com
     a revelacao em vez de ajudar */
  scrollbar-width: none;
}
.travessia-janela::-webkit-scrollbar { display: none; }
.travessia--fixa .travessia-janela { overflow: hidden; }

.travessia-trilho {
  display: flex;
  align-items: center;
  /* Trava explícita: o trilho é item flexível da janela e item flexível
     encolhe por padrão, o que faria offsetWidth mentir sobre a largura real
     da fila (e o script anda exatamente o que o offsetWidth diz).
     HONESTIDADE SOBRE ESTA LINHA: ela entrou como conserto de uma foto que
     aparecia cortada no fim do curso, e NÃO era isso. Testado dos dois jeitos,
     o trilho nunca encolhia: o min-width automático de item flexível já
     inclui o padding, então não havia o que ceder. A foto cortada era erro da
     captura headless, não do site. A linha fica porque a intenção é certa e
     custa nada, mas não atribua bug nenhum a ela. */
  flex: 0 0 auto;
  gap: var(--quadro-gap);
  padding-inline: var(--quadro-borda);
  padding-block: clamp(10px, 2vh, 26px);
  width: max-content;
  will-change: transform;
}

/* ===== O quadro =====
   .travessia .quadro, com DUAS classes, e isso não é capricho: o mesmo
   elemento também é .galeria-foto (pra herdar a lupa e o foco de teclado), e
   .galeria-foto define largura, proporção e hover próprios. Com uma classe
   só, o empate de especificidade seria decidido pela ordem no arquivo, que é
   o tipo de coisa que quebra no dia em que alguém move um bloco.

   --p (0 a 1) É O CORAÇÃO DISSO. O script escreve nele o quanto a foto está
   perto do meio da janela, e todo o resto é conta em cima dele. O padrão do
   var() é 1, ou seja FOTO REVELADA: sem script, ninguém fica olhando pra uma
   fila de retângulos escuros. É a mesma regra do .revelar, que nasce desenhado
   e só se esconde quando a classe entra.

   --dx (-1 a 1) é a mesma distância COM SINAL, e serve só pro paralaxe da
   imagem dentro da moldura. É ele que faz a foto arrastar um pouco dentro do
   próprio quadro enquanto o quadro atravessa a tela, que é o detalhe que
   vende o movimento lateral.

   --fator e --desvio quebram a fila regular: tamanho e altura alternando num
   ciclo de quatro. Fila de retângulos idênticos lê como esteira; com o ciclo,
   lê como colagem passando. Vem do jeito que a referência monta cada projeto
   com peças de tamanhos diferentes. */
.travessia .quadro {
  position: relative;
  flex: 0 0 auto;
  width: calc(var(--quadro-w) * var(--fator, 1));
  aspect-ratio: 4 / 5;
  align-self: center;

  background: var(--bg-2);
  filter: none;   /* o brightness do .galeria-foto:hover não se aplica aqui */
  transform:
    translate3d(0, calc(var(--desvio, 0px) + (1 - var(--p, 1)) * 30px), 0)
    scale(calc(0.86 + 0.14 * var(--p, 1)));
}
/* O desvio sai do TAMANHO DO QUADRO, e não de vh: assim ele encolhe junto com
   a foto e a fila nunca fica com um desnível grande demais pro que sobrou de
   janela. Em vh eles andavam separados, e numa tela baixa o quadro diminuía
   enquanto o degrau continuava do mesmo tamanho. */
.travessia .quadro:nth-child(4n + 1) { --fator: 1.26; --desvio: calc(var(--quadro-w) * -0.075); }
.travessia .quadro:nth-child(4n + 2) { --fator: 0.82; --desvio: calc(var(--quadro-w) * 0.145); }
.travessia .quadro:nth-child(4n + 3) { --fator: 1;    --desvio: calc(var(--quadro-w) * -0.145); }
.travessia .quadro:nth-child(4n + 4) { --fator: 1.1;  --desvio: calc(var(--quadro-w) * 0.075); }
/* Janela baixa (notebook de 720p com a barra do navegador em cima): a fila
   fica reta. O degrau é o que sobra quando não há altura pra ele, e uma foto
   decepada pelo recorte custa muito mais do que a colagem rende. */
@media (max-height: 730px) {
  .travessia .quadro { --desvio: 0px; }
}

/* O VÉU. É ele que esconde a foto que ainda não chegou no meio. Navy do
   próprio site, e não preto: preto chapado sobre foto lê como imagem
   quebrada, o navy lê como a foto ainda no escuro. Para em 0,88 de propósito
   — uma silhueta apagada ainda diz "tem foto ali", um retângulo sólido não.
   Opacidade em pseudo-elemento é composta na GPU, que é o motivo de o véu ser
   isto e não um filter: brightness recalculado a cada quadro em cima de nove
   imagens grandes. */
.travessia .quadro::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* Quase opaco por dentro, e é o véu inteiro que sobe e desce pela opacidade.
     Na primeira versão o degradê ia de 0,72 a 0,96, e o resultado era que a
     foto a meio caminho do foco continuava perfeitamente legível: 0,72 de cor
     vezes 0,5 de opacidade cobre só 36 por cento. Com o degradê fechado, o
     quanto se vê passa a ser de fato o --p, que é o que o efeito promete. */
  background: linear-gradient(176deg, rgba(6, 16, 34, 0.94), rgba(5, 13, 30, 1) 74%);
  /* O VÉU SEGUE 1 − p², e não 1 − p. Com a curva reta, a foto vizinha da que
     está no foco ficava com uns 0,7 de p e portanto 70% revelada: quase tão
     acesa quanto a do meio, e aí não havia "uma foto de cada vez", havia três.
     Elevando o p ao quadrado, o véu só abre de verdade perto do fim, então a
     vizinha fica pela metade e a de trás dela some. Quem NÃO usa a curva
     torta é o movimento (escala, subida, paralaxe): lá o p reto é o que
     mantém a caminhada suave. Esconder e mover são coisas diferentes e não
     precisam da mesma curva. */
  opacity: calc(0.92 * (1 - var(--p, 1) * var(--p, 1)));
}

/* O filete dourado que se desenha embaixo do quadro conforme ele chega no
   meio. Mesmo movimento da régua do título de seção e do risco da trilha:
   scaleX a partir da esquerda, que é transform puro e não pede layout. */
.travessia .quadro::before {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  z-index: 2;
  background: var(--amarelo);
  transform: scaleX(var(--p, 1));
  transform-origin: 0 50%;
  /* o filete também apaga junto com a foto: em cima de um quadro escondido,
     dourado cheio brilhava mais que a própria foto e virava a coisa mais forte
     da tela, exatamente onde não era pra ter nada chamando */
  opacity: calc(0.18 + 0.82 * var(--p, 1));
}

/* A escala mínima da imagem é 1,12, e não 1: o paralaxe move a foto 3,5% da
   largura pra cada lado, e com scale 1 esse empurrão descobriria a borda da
   moldura. 12% de escala sobrando dá 6% de folga de cada lado, quase o dobro
   do que o paralaxe usa. Mexeu num dos dois números, confere o outro.
   O filter fica na CLASSE, não no --p: saturação é caro de recalcular a cada
   quadro, e trocando por classe o navegador interpola sozinho a transição
   quando o foco muda de foto, que acontece uma vez por segundo, não 60. */
.travessia .quadro img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--foco, 50% 50%);
  transform:
    translate3d(calc(var(--dx, 0) * -3.5%), 0, 0)
    scale(calc(1.26 - 0.14 * var(--p, 1)));
  filter: saturate(0.5) contrast(0.98);
  transition: filter 0.55s ease;
}
.travessia .quadro.is-foco img { filter: saturate(1.06) contrast(1.04); }
/* a foto do meio é a única que responde ao ponteiro com brilho: as outras
   estão escondidas de propósito, e acender uma delas desmancharia o efeito */
.travessia .quadro.is-foco:hover img { filter: saturate(1.12) contrast(1.06) brightness(1.06); }

/* ===== Rodapé de controle ===== */
.travessia-pe { flex: 0 0 auto; padding-bottom: clamp(14px, 2.4vh, 34px); }
.travessia-controle {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.6vw, 20px);
}
.travessia-legenda {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  display: flex;
  justify-content: center;
  text-align: center;
}
.travessia-titulo {
  font-family: var(--display);
  font-style: italic;
  text-transform: uppercase;
  font-size: clamp(0.92rem, 1.5vw, 1.32rem);
  line-height: 1.1;
}
.travessia-conta { font-size: 0.68rem; letter-spacing: 0.14em; color: var(--ink-dim); }
.travessia-conta b { color: var(--ink); }

.travessia-seta {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  font-size: 1.5rem; line-height: 1;
  color: var(--ink);
  background: none;
  border: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.travessia-seta:hover:not([disabled]) {
  background: var(--amarelo);
  border-color: var(--amarelo);
  color: #050d1e;
  transform: translateY(-2px);
}
.travessia-seta:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }
.travessia-seta[disabled] { opacity: 0.32; cursor: default; }

/* ===== A régua =====
   Traços curtos com um marcador maior a cada cinco, e a agulha dourada
   correndo em cima. Veio direto das prints: é ela que diz de relance quanto
   da fila já passou e quanto falta, informação que uma barra de progresso lisa
   também daria, mas sem o ar de linha do tempo — e é justamente disso que a
   seção trata, uma linha do tempo que se percorre.

   A AGULHA É UM ELEMENTO DE LARGURA CHEIA COM BORDA SÓ NA ESQUERDA, e o
   truque está aí: porcentagem em translateX se resolve contra a largura do
   PRÓPRIO elemento, não a do pai. Com largura de 100% menos os 2px da borda,
   translateX(100%) leva a borda exatamente até a ponta direita da régua. É o
   jeito de mover isso com transform puro; a alternativa óbvia (animar o
   `left`) pede layout a cada quadro. */
.travessia-regua {
  position: relative;
  height: 22px;
  margin-top: clamp(10px, 1.6vh, 18px);
  border-top: 1px solid var(--border);
  overflow: hidden;
  background:
    repeating-linear-gradient(90deg, rgba(147, 166, 198, 0.4) 0 1px, transparent 1px 110px) 0 0 / 100% 15px no-repeat,
    repeating-linear-gradient(90deg, var(--border) 0 1px, transparent 1px 22px) 0 0 / 100% 8px no-repeat;
}
.travessia-agulha {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: calc(100% - 2px);
  border-left: 2px solid var(--amarelo);
  pointer-events: none;
  transform: translate3d(calc(var(--prog, 0) * 100%), 0, 0);
}
/* o losango no topo da agulha, centrado nos 2px da borda: 1px de centro menos
   4px de meia-largura dá o -3px */
.travessia-agulha::before {
  content: "";
  position: absolute;
  left: -3px; top: 1px;
  width: 8px; height: 8px;
  background: var(--amarelo);
  transform: rotate(45deg);
}

/* Fila arrastável (sem script, celular, movimento reduzido): o cabeçalho volta
   a ter o respiro normal de seção e a fila ganha altura própria, porque não há
   mais tela cheia pra dividir. O rodapé de controle continua servindo — as
   setas rolam a janela na horizontal em vez de rolar a página. */
.travessia:not(.travessia--fixa) .travessia-topo { padding-top: 0; }
.travessia:not(.travessia--fixa) .travessia-topo .cabeca { margin-bottom: 30px; }
.travessia:not(.travessia--fixa) .travessia-trilho { padding-block: 28px; }
.travessia:not(.travessia--fixa) .travessia-pe { padding-top: 6px; }

/* ===== Ficha do técnico (pop-up) ===== */
.ficha-tec { position: fixed; inset: 0; z-index: 210; }
.ficha-tec[hidden] { display: none; }

/* ANIMAÇÃO DE ENTRADA E SAÍDA.
   O estado fechado (sem .is-aberta) é o ponto de partida E o de chegada: a
   mesma regra serve pra abrir e pra fechar, então não existe um caminho de
   volta escrito separado que pode divergir do de ida.
   Quem controla o hidden é o script, com espera igual ao tempo daqui: hidden é
   display: none e cortaria a animação de saída pela metade. */
.ficha-tec { opacity: 0; transition: opacity 0.26s ease; }
.ficha-tec.is-aberta { opacity: 1; }

.ficha-tec-fundo {
  position: absolute; inset: 0;
  background: rgba(2, 6, 16, 0.78);
  backdrop-filter: blur(3px);
}
.ficha-tec-caixa {
  position: relative;
  z-index: 1;
  display: grid;
  /* foto à esquerda com largura fixa, texto tomando o resto: a foto é 3:4 e
     esticar ela pra acompanhar uma coluna elástica deformaria o retrato */
  grid-template-columns: minmax(0, 290px) minmax(0, 1fr);
  gap: 0;
  width: min(820px, calc(100vw - 32px));
  max-height: min(84vh, 540px);
  margin: max(16px, calc(50vh - 270px)) auto 0;
  overflow: hidden;
  background: var(--bg-2, #0a1730);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);

  /* Sobe um pouco e cresce, em vez de só aparecer. A curva de entrada passa de
     1 no fim (0.34 > 1) e dá um respiro de mola no último quadro, que é o que
     faz o pop-up parecer que chegou em vez de ter sido colado. */
  opacity: 0;
  transform: translateY(22px) scale(0.965);
  transition: opacity 0.22s ease, transform 0.26s cubic-bezier(0.4, 0, 0.7, 1);
}
.ficha-tec.is-aberta .ficha-tec-caixa {
  opacity: 1;
  transform: none;
  transition: opacity 0.26s ease, transform 0.42s cubic-bezier(0.2, 0.9, 0.34, 1);
}
.ficha-tec-fechar {
  position: absolute;
  top: 10px; right: 12px;
  z-index: 2;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  font-size: 1.5rem; line-height: 1;
  color: var(--ink);
  background: rgba(5, 13, 30, 0.6);
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
}
.ficha-tec-fechar:hover { background: var(--amarelo); color: #050d1e; border-color: var(--amarelo); }
.ficha-tec-fechar:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

.ficha-tec-foto { position: relative; background: #050d1e; }
.ficha-tec-foto img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}
/* o degradê existe pra o nome ter contraste em cima de qualquer foto, sem
   depender de a parte de baixo dela ser escura por sorte */
.ficha-tec-selo {
  position: absolute;
  inset: auto 0 0 0;
  padding: 46px 20px 18px;
  background: linear-gradient(to top, rgba(5, 13, 30, 0.95) 30%, transparent);
}
.ficha-tec-nome {
  margin: 0;
  font-family: var(--fonte-titulo, inherit);
  font-size: 1.1rem;
  font-weight: 900;
  line-height: 1.05;
  text-transform: uppercase;
}
.ficha-tec-cargo {
  margin: 5px 0 0;
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amarelo);
}

.ficha-tec-lado {
  padding: 24px 26px;
  overflow-y: auto;
}
/* rótulo da coluna. Faz o papel de cabeçalho sem competir com o nome, que já
   está grande em cima da foto */
.ficha-tec-secao {
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--amarelo);
}
.ficha-tec-lead {
  margin: 0 0 16px;
  color: var(--ink-dim);
  font-size: 0.82rem;
  line-height: 1.55;
}
.ficha-tec-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.ficha-tec-lista li {
  position: relative;
  padding: 9px 12px 9px 34px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.78rem;
  line-height: 1.45;
}
/* marca de conferido desenhada em CSS, sem fonte de ícone nem SVG externo */
.ficha-tec-lista li::before {
  content: "";
  position: absolute;
  left: 13px; top: 50%;
  width: 5px; height: 9px;
  margin-top: -6px;
  border: solid var(--amarelo);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.ficha-tec-cref {
  margin: 14px 0 0;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* Empilha no celular: 340px de foto ao lado de texto não cabe, e a foto
   vira uma tira alta e fina se insistir na coluna. */
@media (max-width: 720px) {
  .ficha-tec-caixa {
    grid-template-columns: 1fr;
    max-height: 88vh;
    margin-top: 6vh;
    overflow-y: auto;
  }
  .ficha-tec-foto { height: 260px; }
  .ficha-tec-lado { padding: 22px 20px 26px; overflow: visible; }
  /* No celular a caixa quase encosta nas duas bordas da tela (16px de
     margem cada lado) e não sobra "fora dela" pra seta morar, diferente do
     desktop. Aqui ela volta pra dentro, presa na faixa da foto:
     - left/right fixos a partir da borda da TELA, não mais o calc() que
       soma 64px de fora da caixa (não cabe, e sobraria negativo)
     - top: 130px é o meio dos 260px de .ficha-tec-foto, porque com a caixa
       inteira rolando (overflow-y: auto) um top: 50% miraria o meio da
       altura travada, não o meio da foto */
  .ficha-tec-seta { top: 130px; left: auto; right: auto; transform: translateY(-50%); }
  .ficha-tec-seta--tras { left: 24px; }
  .ficha-tec-seta--frente { right: 24px; }
}

/* ===== Pop-up do vídeo da turma =====
   Mesmo desenho de fundo escurecido + caixa central da .ficha-tec, com
   controles nativos do navegador em vez de interface própria: é vídeo de
   verdade tocando, não um carrossel, então o play/pause/tela cheia do
   próprio navegador já resolve. */
/* ===================================================================
   PORTA DE AVISO DO "EFETIVAR MATRÍCULA" (24/08/2026)
   Mesma mecânica de .ficha-tec e .video-lightbox: o estado fechado é o
   ponto de partida E o de chegada, então abrir e fechar usam a mesma
   regra e não existe caminho de volta escrito à parte pra divergir.
   Quem devolve o [hidden] é o script, esperando o tempo daqui.
=================================================================== */
.confirma { position: fixed; inset: 0; z-index: 220; opacity: 0; transition: opacity 0.24s ease; }
.confirma[hidden] { display: none; }
.confirma.is-aberta { opacity: 1; }
.confirma-fundo {
  position: absolute; inset: 0;
  background: rgba(2, 6, 16, 0.8);
  backdrop-filter: blur(3px);
}
.confirma-caixa {
  position: relative;
  z-index: 1;
  width: min(500px, calc(100vw - 32px));
  margin: max(16px, calc(50vh - 210px)) auto 0;
  padding: 30px 30px 28px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-top: 3px solid var(--amarelo);
  border-radius: 14px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
  /* sobe e cresce, com a curva passando de 1 no fim: o respiro de mola no
     último quadro é o que faz a caixa parecer que chegou, não que foi colada */
  opacity: 0;
  transform: translateY(20px) scale(0.965);
  transition: opacity 0.2s ease, transform 0.26s cubic-bezier(0.4, 0, 0.7, 1);
}
.confirma.is-aberta .confirma-caixa { opacity: 1; transform: none; }
.confirma-caixa h2 { font-size: clamp(1.5rem, 3.4vw, 2rem); margin: 6px 0 14px; }
.confirma-caixa p { font-size: 0.95rem; }
.confirma-caixa b { color: var(--ink); }
.confirma-nota {
  padding-left: 14px;
  border-left: 2px solid var(--royal);
  font-size: 0.86rem !important;
  margin-bottom: 24px;
}
/* empilha no celular: dois botões lado a lado em 360px viram duas colunas
   estreitas com o texto quebrando no meio da frase */
.confirma-acoes { display: flex; flex-wrap: wrap; gap: 10px; }
.confirma-acoes .botao { flex: 1 1 auto; }

.video-lightbox { position: fixed; inset: 0; z-index: 210; opacity: 0; transition: opacity 0.26s ease; }
.video-lightbox[hidden] { display: none; }
.video-lightbox.is-aberto { opacity: 1; }
.video-lightbox-fundo {
  position: absolute; inset: 0;
  background: rgba(2, 6, 16, 0.85);
  backdrop-filter: blur(3px);
}
.video-lightbox-caixa {
  position: relative;
  z-index: 1;
  width: min(92vw, 420px);
  margin: max(16px, calc(50vh - 320px)) auto 0;
  opacity: 0;
  transform: translateY(22px) scale(0.965);
  transition: opacity 0.22s ease, transform 0.26s cubic-bezier(0.4, 0, 0.7, 1);
}
.video-lightbox.is-aberto .video-lightbox-caixa { opacity: 1; transform: none; }
.video-lightbox-caixa video {
  display: block;
  width: 100%;
  max-height: 80vh;
  border-radius: 14px;
  background: #000;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
.video-lightbox-fechar {
  position: absolute;
  /* dentro da caixa, não por cima, igual .ficha-tec-fechar: com a caixa
     centrada por margem (não por flex), um botão "acima" dela pode nascer
     fora da tela quando a margem de topo encolhe num celular baixo. */
  top: 8px; right: 8px;
  z-index: 2;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  font-size: 1.5rem; line-height: 1;
  color: var(--ink);
  background: rgba(5, 13, 30, 0.7);
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
}
.video-lightbox-fechar:hover { background: var(--amarelo); color: #050d1e; border-color: var(--amarelo); }
.video-lightbox-fechar:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 3px; }

/* ===== Patrocínio ===== */
/* A máscara nas duas pontas existe porque a esteira sangra a tela inteira e o
   corte reto na borda partia a placa do primeiro e do último patrocinador ao
   meio. Marca de quem paga cortada na metade lê como erro de site, e é
   justamente a marca de quem paga. Com o desvanecimento, a placa entra e sai
   da faixa em vez de bater na parede. */
.esteira {
  overflow: hidden;
  border-block: 1px solid var(--border);
  padding: 26px 0;
  margin-bottom: 22px;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 72px, #000 calc(100% - 72px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 72px, #000 calc(100% - 72px), transparent 100%);
}
.esteira-trilho { display: flex; width: max-content; animation: correr 38s linear infinite; }
/* margem no item em vez de gap no contêiner: com gap, metade da largura não
   corresponde a metade dos itens e o laço dá um pulinho a cada volta */
.esteira-trilho > * { margin-right: 16px; }
@keyframes correr { to { transform: translateX(-50%); } }
.esteira:hover .esteira-trilho, .esteira:focus-within .esteira-trilho { animation-play-state: paused; }

/* Placa do patrocinador.
   Fundo branco de propósito, e não o navy do site: as sete marcas têm cores
   próprias (verde, vermelho, laranja, azul) e várias vieram em JPG com fundo
   branco chapado. Inverter ou cinzar logo de patrocinador não é opção, ele
   paga justamente pra aparecer com a cor dele.

   O mix-blend-mode: multiply é o que costura o resto: sobre placa branca, o
   branco do JPG some e só a marca sobra, sem contorno de quadrado. Nos dois
   logos que vieram com transparência de verdade (Ortoplan e Sonnar) ele não
   muda nada, então serve pros sete sem exceção. */
/* flex com align-items: stretch, e NÃO grid com place-items: center.
   Com o grid centralizado, a altura da área de grid deixa de ser definida e
   o height: 100% da imagem cai pra altura intrínseca: as cinco logos
   quadradas (300x300) estouravam a placa pra baixo, atravessando a faixa.
   No flex esticado a imagem recebe a altura do conteúdo sem depender de
   porcentagem, e o object-fit: contain centraliza sozinho. */
.patro {
  flex: 0 0 190px;
  width: 190px; height: 120px;
  display: flex; align-items: stretch;
  padding: 12px 18px;
  background: #fff;
  border-radius: 3px;
  /* Mesma curva e quase o mesmo tempo das fotos da esteira de cima, pra as
     duas faixas que correm se comportarem igual. Aqui quem cresce é a PLACA
     inteira, e não a logo dentro dela: a placa é branca e a logo usa
     mix-blend-mode: multiply contra esse branco, então ampliar só a imagem
     faria a marca vazar pra fora do branco e sujar a borda. */
  transform: scale(1);
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.patro:hover, .patro:focus-visible { transform: scale(1.06); }
.patro img {
  width: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/* O logo da Sonnar é um círculo azul dentro de um quadrado PRETO. O preto foi
   recortado no arquivo, com máscara circular, senão a placa branca ficaria com
   um quadrado escuro no meio. O raio aqui só garante a borda limpa. */
.patro--redonda img { border-radius: 50%; }

/* ===== Contato ===== */
.secao--fim { background: radial-gradient(90% 130% at 22% 0%, rgba(29, 91, 196, 0.22), transparent 68%); }
.fim-grade { display: grid; grid-template-columns: 0.95fr 1.05fr; gap: 40px 54px; align-items: center; }
.fim-chamada { font-size: clamp(2rem, 4.4vw, 3.3rem); }
.fim-acoes { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.fim-dados { margin: 26px 0; }
.fim-dados > div { display: grid; grid-template-columns: 104px 1fr; gap: 14px; align-items: baseline; padding: 14px 0; border-bottom: 1px solid var(--border); }
.fim-dados > div:first-child { border-top: 1px solid var(--border); }
.fim-dados dt { font-size: 0.58rem; font-weight: 800; color: var(--royal-claro); }
.fim-dados dd { margin: 0; font-size: 0.94rem; }
.fim-mapa iframe { display: block; border-radius: 3px; border: 1px solid var(--border); }

/* ===== Rodapé ===== */
.rodape-grade { padding-block: 40px; display: grid; gap: 18px; }
.rodape-lema {
  font-size: clamp(1.5rem, 5vw, 3.2rem);
  color: transparent;
  -webkit-text-stroke: 1px var(--border);
  margin: 0;
}
.rodape-info { font-size: 0.6rem; font-weight: 700; color: var(--ink-dim); margin: 0; }

/* ===== Entrada dos blocos =====
   Sobe e aparece. A curva tem saída rápida e chegada macia, senão a entrada
   lê como fade de slide, não como movimento. O atraso de cada item de grade
   é escrito pelo script, em transition-delay. */
.revelar {
  opacity: 0;
  transform: translateY(26px);
  /* A opacidade termina ANTES do movimento (0,5s contra 0,72s), de propósito.
     Igualadas, o elemento chega no lugar no mesmo instante em que fica
     legível e a entrada lê como um corte; com a opacidade adiantada, ele
     termina de assentar já visível, e é esse rabo de movimento que dá a
     sensação de peso em vez de fade. */
  transition:
    opacity 0.5s ease,
    transform 0.72s cubic-bezier(0.16, 0.72, 0.24, 1);
  will-change: opacity, transform;
}
.revelar.visivel { opacity: 1; transform: none; will-change: auto; }

/* Item de grade (cartão de turma, passo da matrícula, número da abertura).
   Sobe mais e vem de menor: cartão que cresce lê como objeto chegando na
   frente, e é o que separa a cascata da grade da subida simples de um bloco
   de texto. A escala é pequena de propósito — 0,94 já é bastante quando são
   quatro cartões entrando um atrás do outro, e passar disso vira zoom. */
.revelar--cresce {
  transform: translateY(32px) scale(0.94);
  transform-origin: 50% 85%;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* A intro é 100% movimento: ela não informa nada que não esteja no h1 logo
     abaixo. Pra quem pediu menos movimento, o certo é não existir, e não
     existir mais devagar. */
  .intro { display: none; }
  .revelar, .revelar--cresce { opacity: 1; transform: none; transition: none; transition-delay: 0s !important; }
  .esteira-trilho { animation: none; }
  /* o cartão para de subir, mas o anel de luz fica: ele não se move, e é o que
     diz qual cartão está sob o cursor */
  .turma, .turma::before { transition: none; }
  .turma:hover, .turma:focus-within, .botao:hover, .botao:active { transform: none; }

  /* ===== O que foi acrescentado em 24/08/2026 =====
     Os riscos dourados (título de seção, fio dos números, tico de cada passo
     da matrícula) FICAM DESENHADOS, inteiros e parados. Eles não são
     enfeite de entrada: são marcação de hierarquia, e sumir com eles pra
     quem pediu menos movimento seria tirar informação, não animação. O que
     sai é só o ato de se desenharem. */
  .cabeca h2::after,
  .cabeca.revelar h2::after,
  .cabeca.revelar.visivel h2::after,
  .trilha li::before,
  .trilha li.revelar::before,
  .trilha li.revelar.visivel::before {
    transform: scaleX(1);
    transition: none;
  }
  .numeros-grade > div::before,
  .numeros-grade > div.revelar::before,
  .numeros-grade > div.revelar.visivel::before {
    transform: scaleY(1);
    transition: none;
  }
  /* o selo do vídeo e o número do cartão param de crescer; a troca de cor do
     número continua, porque é ela que responde ao mouse */
  .turma-video-media, .turma-num { transition: none; }
  .turma:hover .turma-video-media,
  .turma:focus-within .turma-video-media,
  .turma:hover .turma-num,
  .turma:focus-within .turma-num { transform: none; }
  /* a lista de pilares troca a cor da borda e não desliza mais */
  .pilares li { transition: border-color 0.16s ease; }
  .pilares li:hover { transform: none; }
  .grade tbody th, .grade tbody td { transition: none; }
  /* As duas esteiras crescem no hover. Quem pediu menos movimento continua
     tendo o realce (filtro na foto, sombra na placa), sem a ampliação. */
  .galeria-foto img, .patro { transition: none; }
  .galeria-foto:hover img, .galeria-foto:focus-visible img { transform: none; }
  .patro:hover, .patro:focus-visible { transform: none; }
  /* o botão da ficha aparece na hora, sem subir */
  .tec-mais { transition: none; transform: none; }
  /* o pop-up abre e fecha na hora. O script já sabe disso e tira o hidden
     sem esperar animação nenhuma. */
  .ficha-tec, .ficha-tec-caixa { transition: none; }
  .confirma, .confirma-caixa { transition: none; }
  .confirma-caixa { transform: none; }
  .ficha-tec-caixa { transform: none; }
  .menu a::after { transition: none; }
  /* Aqui é transition: none, e NUNCA transform: none. O transform do .tec não
     é enfeite de hover, é o que põe cada card no lugar dele na vitrine:
     zerar ele empilharia os cinco em cima do outro no meio da tela. O que sai
     é só o deslizamento entre uma posição e a próxima. */
  .tec { transition: none; }

  /* O cometa sai de cena, a moldura fica. Ela não é enfeite: é o que diz qual
     card está escolhido, e some junto seria trocar um problema por outro.
     Sem o giro ela vira uma linha dourada firme em volta, que cumpre o mesmo
     papel com movimento nenhum. A seta continua marcada pela borda própria. */
  .tec-fio::before, .elenco-seta::before, .ficha-tec-seta::before { display: none; }
  .tec-fio { background: var(--amarelo); }

  .galeria-lupa { transition: none; }

  /* ===== A travessia (25/08/2026) =====
     O palco NÃO prende: quem decide isso é o script, que sai fora com
     movimento reduzido e deixa a fila no estado padrão do CSS, uma faixa que
     se arrasta pro lado. E as fotos ficam TODAS reveladas, porque o script
     também não escreve --p nesse caso e o var(--p, 1) vale.
     O que sobra pra tirar aqui é o que ainda seria movimento: a saturação
     trocando quando o foco muda de foto, e o pulinho da seta no hover. A
     legenda, a régua e a agulha ficam: elas não se movem sozinhas, dizem onde
     a pessoa está na fila, e sumir com elas deixaria a versão calma pior. */
  .travessia .quadro img, .travessia-seta { transition: none; }
  .travessia-seta:hover:not([disabled]) { transform: none; }

  /* ===== Matrícula (23/08/2026) =====
     O passo troca na hora, sem deslizar, e a bolinha do trilho não pulsa.
     O que FICA é a cor: dourado no passo atual, azul no já cumprido. Era ela
     que dizia onde a pessoa está no meio da matrícula, e o movimento só
     reforçava — tirar a cor junto deixaria a tela sem resposta nenhuma. */
  .passo, .passo-marca, .passo-marca span,
  .passo-marca.is-atual span,
  .campo-erro:not([hidden]), .form-mensagem:not([hidden]) {
    animation: none;
    transition: none;
  }
  .campo input, .campo select, .campo textarea { transition: none; }

  /* A lâmina do botão é 100% enfeite: não diz nada que a mudança de cor do
     hover já não diga. Some inteira. */
  .botao-cheio:hover::after { animation: none; }

  /* O FIO DE PROGRESSO FICA. Ele não é enfeite: é a única coisa na página
     que responde "quanto ainda falta", e quem pediu menos movimento não
     pediu menos informação. O que sai é só o aparecer/desaparecer suave;
     o fio em si continua acompanhando a rolagem, porque acompanhar a
     rolagem é a função dele. */
  .progresso { transition: none; }
}

/* ===================================================================
   TELAS MENORES
=================================================================== */
@media (max-width: 1180px) {
  .menu { gap: 18px; }
  .menu a { font-size: 0.72rem; letter-spacing: 0.1em; }
  .clube-grade, .fim-grade { grid-template-columns: 1fr; }
  .capa-texto { max-width: min(620px, 58%); }
}

/* Faixa do notebook pequeno e do tablet deitado, entre o índice inteiro e o
   menu de abrir. Aqui não cabem marca, seis itens e o botão na mesma linha:
   "O clube" partia em duas linhas e o "Quero treinar" virava um bloco de duas
   alturas, torto ao lado do resto. Quem sai é o botão, não o índice, porque
   "Contato" continua ali levando ao mesmo lugar e o índice é a navegação. */
@media (max-width: 1100px) {
  .topo-cta { display: none; }
}
/* item de índice nunca quebra no meio: ele é um rótulo, não um parágrafo */
.menu a { white-space: nowrap; }

@media (max-width: 980px) {
  /* a vitrine encolhe a carta e aproxima os vizinhos; quem cuida das posições
     é o script, que lê estas duas medidas */
  .elenco { --carta: clamp(190px, 30vw, 250px); }
  .trilha { grid-template-columns: repeat(2, 1fr); gap: 30px 20px; }
}

/* ponto em que o índice do topo vira menu de abrir */
@media (max-width: 900px) {
  /* 72px, não 66px: a placa branca do escudo precisa caber com respiro, e o
     guia de marca fixa 55px como altura mínima do escudo em tela. Espremer a
     barra aqui seria quebrar a regra logo na primeira aplicação dela.
     A placa não muda de tamanho no celular: quem cede espaço é o nome ao lado. */
  :root { --h-topo: 72px; }

  .menu-btn { display: flex; }
  .topo-cta { display: none; }
  .topo:has(.menu.aberto) { background: rgba(5, 13, 30, 0.98); }

  .menu {
    position: absolute;
    top: var(--h-topo); left: 0; right: 0;
    flex-direction: column;
    gap: 0;
    padding: 6px var(--pad) 22px;
    background: rgba(5, 13, 30, 0.98);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
    transform: translateY(-115%);
    visibility: hidden;
    transition: transform 0.26s ease, visibility 0.26s;
  }
  .menu.aberto { transform: translateY(0); visibility: visible; }
  .menu a { padding: 14px 0; font-size: 0.9rem; border-bottom: 1px solid var(--border); }

  /* No celular o texto ocupa a largura toda e o vídeo fica só de atmosfera
     atrás dele. O modo scrub não liga nessa faixa (ver script.js), então aqui
     a abertura é sempre de uma tela.

     Sem o translateX daqui pra baixo. Ele existe pra tirar o atleta de trás
     da chamada, e aqui a chamada ocupa a linha inteira: não há "atrás dele"
     pra onde fugir.

     REVISTO EM 25/08/2026, a pedido do Leo ("a escala do vídeo tá muito
     grande pelo celular, quero que apareça o jogador por completo"). A
     PRIMEIRA tentativa trocou cover por contain com a foto encostada embaixo,
     e isso resolveu o corte só pra criar um problema pior: a foto saiu de
     trás do texto e virou um retrato emoldurado abaixo dele, descaracterizando
     a abertura (o vídeo é atmosfera atrás da chamada em toda a página, ver o
     parágrafo acima — "atrás dele" existe, e é o navy da .capa). Revertido
     pro cover, corrigindo o de verdade: o tamanho da pista.

     Com min-height fixo (620px) o corte amplia pela ALTURA do clipe (16:9
     deitado numa faixa alta e estreita), e sobrava só ~37% da largura pra
     mostrar uma figura que ocupa 43% do quadro (26% a 69%): não cabia
     inteira em NENHUM enquadramento horizontal. O tamanho fixo era o erro,
     porque a fração visível (visível/largura = 0,5625 × tela/pista) só
     cresce se a pista ENCOLHER, e min(78vh,620px) não encolhe com a LARGURA
     da tela, só com a altura dela — daí depender de vh e não de vw.
     Trocado por 105vw (com teto de 480px pra não esticar em tablet deitado
     onde a faixa já vale 900px de largura): a pista vira função da largura
     da tela, e a fração visível fica ~54% pra qualquer celular, folga de
     sobra pros 43% da figura. Object-position ficou como estava (46% 50%):
     o centro da figura (47,5%) continua dentro da folga nova. */
  .capa-palco { min-height: min(105vw, 480px); }
  .capa-video { object-position: 46% 50%; transform: none; }
  .capa-texto { max-width: 100%; }
  .capa-grade { padding-bottom: 30px; }

  /* O véu original (.capa-veu, lá em cima) foi calibrado pro desktop, onde o
     texto mora numa coluna à esquerda e o vídeo é empurrado pra direita via
     translateX. A primeira camada dele é um gradiente de 100deg, e a ANCORA
     desse ângulo (o lado oposto à direção, onde a cor entra opaca) cai no
     canto SUPERIOR ESQUERDO da caixa — de propósito lá, porque é onde o texto
     começa. No celular a chamada ocupa a largura inteira (ver acima, "não há
     atrás dele pra onde fugir") e esse mesmo canto vira uma mancha escura sem
     função nenhuma, só sobrando do desenho feito pro outro layout (24/08,
     print do Leo mostrando a mancha). Reescrito pra celular: um gradiente
     vertical só, escuro em cima (onde a chamada precisa de contraste) e
     limpo no meio (onde o jogador aparece), sem direção diagonal nenhuma
     pra ancorar num canto. As duas luzes radiais (dourada e azul) também
     saem: elas miravam 74-78% no eixo horizontal, o ponto onde o atleta cai
     SÓ no enquadramento empurrado do desktop — no celular, sem o translateX,
     esse ponto não é o atleta, é só mais um brilho fora de lugar.

     A PARTE CLARA FICOU CINZA, NÃO AZUL (25/08/2026, print do Leo: "o fundo
     dele ainda tem que ser azul pra combinar com o resto da página"). O
     clipe tem fundo de estúdio claro (cinza quase neutro), e baixar só a
     opacidade do navy quase-preto (--bg) escurece essa cinza sem tingir ela:
     preto semitransparente em cima de cinza continua lendo como cinza mais
     escuro. PRIMEIRA CORREÇÃO trocou só a parada do meio do gradiente pra
     royal — e ficou azul SÓ ali, com o topo e o rodapé continuando pretos
     (segundo print do Leo: "só tá azul no meio, é em tudo"). O ponto que
     faltava: um gradiente só, com UMA cor de cada vez nas paradas, nunca ia
     ficar azul em toda parte, porque em cada altura só existe a cor daquela
     parada.

     A SAÍDA É SEPARAR AS DUAS CAMADAS. O véu tem duas funções que não são a
     mesma conta: contraste pro texto (varia com a altura, mais forte em
     cima) e cor da marca (constante, tem que estar em QUALQUER altura). Uma
     camada só, tentando fazer as duas coisas ao mesmo tempo, sempre vai
     sacrificar uma pela outra. Aqui são duas: a primeira é o gradiente de
     contraste, em navy quase-preto (--bg) e com o teto de opacidade mais
     baixo que antes (0.5, não 0.85) porque agora ele SOMA com a segunda
     camada, um chapado de royal (--royal) na MESMA opacidade do início ao
     fim da tela — essa é a que garante azul em qualquer altura, do topo ao
     rodapé, sem depender de em que parada do gradiente o pixel caiu. */
  .capa-veu {
    background:
      linear-gradient(to bottom, rgba(5, 13, 30, 0.5) 0%, rgba(5, 13, 30, 0.22) 30%, rgba(5, 13, 30, 0.08) 55%, rgba(5, 13, 30, 0.32) 100%),
      rgba(28, 85, 149, 0.55);
  }

  .numeros-grade { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  /* No celular a carta encolhe pra sobrar corredor pras setas nas bordas.
     Sem isso elas pousariam em cima do rosto, que é justamente o que a seção
     existe pra mostrar. Os vizinhos só espiam pela borda: cinco cards
     visíveis numa tela de 360 viram uma pilha ilegível. */
  .elenco { --carta: min(66vw, 250px); }
  .elenco-seta { width: 40px; height: 40px; font-size: 1.5rem; }

  /* A vitrine sangra até a borda da tela aqui. Sem isso o recorte cairia na
     margem da .faixa e os vizinhos seriam cortados 20px antes da borda, no
     meio do nada. A margem negativa e o padding se anulam, então o card do
     meio continua centrado exatamente onde estava. */
  .elenco {
    margin-inline: calc(var(--pad) * -1);
    padding-inline: var(--pad);
  }
  /* ===== Turmas em trilha, não em pilha (25/08/2026) =====
     Empilhado (grid de 1 coluna) o celular tinha que rolar a seção inteira
     pra passar da Escolinha pro card de ajuda: 6 cards de texto denso, um
     embaixo do outro. Vira uma trilha horizontal com scroll-snap, e as setas
     do .turmas-nav (ver script.js, ligarTurmasCarrossel) avançam um cartão
     por clique pra quem não quer arrastar com o dedo.

     O sangramento até a borda é o mesmo truque do .elenco logo acima: margem
     negativa tira a trilha do padding da .faixa, o padding-inline devolve só
     nela, e o cartão fica alinhado com o resto da página enquanto o
     PRÓXIMO cartão espia pela borda direita, avisando que dá pra continuar. */
  .turmas-nav {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-bottom: 14px;
  }
  .turmas {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin-inline: calc(var(--pad) * -1);
    padding-inline: var(--pad);
  }
  .turmas::-webkit-scrollbar { display: none; }
  /* 86% e não 100%: a fatia do próximo cartão espiando na borda é o que faz a
     trilha se ler como "tem mais", sem precisar da dica de texto que a
     tabela de horários usava. */
  .turma { flex: 0 0 86%; scroll-snap-align: start; }

  /* a tabela de horários não cabe aqui: em vez de rolar pro lado, cada linha
     vira um cartão empilhado (ver data-rotulo no HTML e o ::before abaixo).
     TROCADO EM 25/08/2026, a pedido do Leo ("está completamente cortado,
     tendo que mover a tela pro lado"). A largura mínima de 760px da .grade
     não muda: ela é o que garante espaço de sobra pras 5 colunas no desktop,
     e aqui embaixo ela para de valer porque a tabela vira blocos, não
     colunas. Diminuir fonte pra caber 760px em 360px passava de 2mm de
     altura de letra, ilegível; virar cartão é o "de outra forma" que o Leo
     deixou em aberto. */
  .grade-wrap { overflow-x: visible; }
  .grade { min-width: 0; width: 100%; }
  /* thead continua no documento pro leitor de tela (cada rótulo de coluna
     ainda existe e faz par com o data-rotulo repetido no ::before), só sai
     da tela: display:none tiraria os <th> da árvore de acessibilidade
     também, e o clip/tamanho de 1px é a técnica padrão pra evitar isso. */
  .grade thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0; margin: -1px; padding: 0;
  }
  .grade, .grade tbody, .grade tr, .grade tbody th, .grade tbody td { display: block; width: 100%; }
  .grade tbody tr {
    margin-bottom: 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: rgba(10, 23, 48, 0.55);
  }
  .grade tbody tr:last-child { margin-bottom: 0; }
  .grade tbody th {
    padding: 14px 16px 8px;
    border-bottom: 1px dashed var(--border);
    font-size: 1.02rem;
  }
  /* o rótulo da coluna, que em tabela normal mora no <thead>, volta aqui na
     frente de cada valor. attr(data-rotulo) lê o mesmo texto que já está no
     <th scope="col"> lá em cima, então as duas fontes nunca podem discordar:
     mudou o nome da coluna, muda nos dois lugares (thead e cada td). */
  .grade tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    padding: 9px 16px;
    border-bottom: none;
  }
  .grade tbody td:last-child { padding-bottom: 14px; }
  .grade tbody td::before {
    content: attr(data-rotulo);
    flex-shrink: 0;
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--royal-claro);
  }
  /* O VALOR PRECISA DE min-width: 0 PRA QUEBRAR LINHA, não só de espaço.
     Item de flex tem largura mínima automática igual à do conteúdo sem
     quebra (min-width: auto), então sem isso "Terça, quinta e sábado" e
     companhia ignoravam o gap e estouravam a lateral do cartão em vez de
     descer pra segunda linha — a régua de texto que devia acompanhar não
     aparecia, e o texto simplesmente saía cortado da tela. O valor sempre
     mora num <span> (ou no <i> das duas turmas "por nível técnico"): é ele
     quem recebe a regra, nunca o td, porque o ::before continua sendo o
     primeiro item do mesmo flex e não pode encolher. */
  .grade tbody td > span, .grade tbody td > i {
    flex: 1 1 auto;
    min-width: 0;
    text-align: right;
  }
  .grade-dica { display: none; }

  /* Alvo de toque. Link de texto corrido tem a altura da linha, uns 21px, e
     dedo não acerta isso: a norma pede 24px de altura mínima. O respiro em
     cima e embaixo resolve sem mexer no tamanho da letra, e o sublinhado
     continua colado na palavra porque agora ele é text-decoration, não borda.
     inline-block é o que faz o padding vertical valer: em inline puro ele
     pinta pra fora da linha e não aumenta a área de clique. */
  .link {
    display: inline-block;
    padding-block: 5px;
  }
}

@media (max-width: 560px) {
  /* o escudo NÃO encolhe mais aqui. Antes caía pra 48px de altura, abaixo do
     mínimo do guia. Quem cede espaço no celular é o nome ao lado, não o
     brasão. Mesmo assim sobra largura: placa 74 + nome 99 + selo 28 + botão 42
     cabem em tela de 360px. */
  .marca-nome { font-size: 1.2rem; }
  .trilha { grid-template-columns: 1fr; }
  .capa-pe .botao, .fim-acoes .botao { width: 100%; }
  .capa-pe { gap: 18px; }
}

/* ===== Desconto de família (seção Turmas) =====
   Faixa de destaque, não cartão de turma: ela não é uma quinta turma e não
   pode entrar na grade, senão vira "mais uma opção" em vez de uma condição
   que vale pra todas. */
.familia {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 30px 48px;
  align-items: center;
  margin-top: 34px;
  padding: 34px clamp(24px, 4vw, 44px);
  border: 1px solid var(--border);
  border-left: 3px solid var(--amarelo);
  border-radius: 4px;
  background:
    linear-gradient(100deg, rgba(222, 169, 35, 0.08), transparent 62%),
    var(--bg-2);
}
.familia h3 {
  font-family: var(--display);
  font-style: italic;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 0.96;
  font-size: clamp(1.5rem, 2.8vw, 2.1rem);
  margin: 0 0 14px;
}
.familia h3 em { font-style: italic; color: var(--amarelo); }
.familia-texto p:last-child { margin: 0; max-width: 46ch; }

.familia-selos { display: flex; gap: 16px; }
.familia-selo {
  flex: 1;
  padding: 20px 18px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  text-align: center;
}
.familia-selo b {
  display: block;
  font-family: var(--display);
  font-style: italic;
  font-size: 2.3rem;
  line-height: 1;
  color: var(--ink);
}
.familia-selo span {
  display: block;
  margin-top: 8px;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.familia-selo--forte { border-color: var(--amarelo); }
.familia-selo--forte b { color: var(--amarelo); }

@media (max-width: 860px) {
  .familia { grid-template-columns: 1fr; }
}

/* ===== Formulário de cadastro (cadastro.html) ===== */
.form-cadastro { display: flex; flex-direction: column; gap: 20px; margin-top: 8px; }
/* Mesmo tratamento das perguntas em bloco: amarelo, negrito e maior. Eram
   cinza-azulado sobre azul, tom irmão do fundo, e sumiam ao lado da resposta
   que a pessoa acabou de digitar. */
.campo label {
  display: block;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--amarelo);
  margin-bottom: 8px;
}
.campo input, .campo select {
  width: 100%;
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--ink);
  font-size: 0.96rem;
  font-family: inherit;
}
.campo input:focus, .campo select:focus { outline: 2px solid var(--amarelo); outline-offset: 1px; }
/* campo que falhou na validação (19/08/2026): borda vermelha, a mesma cor do
   .form-mensagem--erro que já existe no fim do formulário */
.campo input[aria-invalid="true"], .campo select[aria-invalid="true"] { border-color: #e2564a; }
.campo-check {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-2);
  font-size: 0.9rem;
  cursor: pointer;
}
.campo-check input { width: 18px; height: 18px; accent-color: var(--amarelo); }
.campo textarea {
  width: 100%;
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--ink);
  font-size: 0.96rem;
  font-family: inherit;
  resize: vertical;
}
.campo textarea:focus { outline: 2px solid var(--amarelo); outline-offset: 1px; }
.campo-dica { font-size: 0.8rem; color: var(--ink-dim); margin: 8px 0 0; }
.campo-erro { font-size: 0.8rem; color: #e2564a; margin: 8px 0 0; font-weight: 600; }

/* ===== Desconto de família, dentro do cadastro =====
   Borda dourada e não a cinza dos outros blocos: é o único lugar do formulário
   que oferece alguma coisa em vez de pedir. */
.familia-form {
  border: 1px solid rgba(222, 169, 35, 0.4);
  border-radius: 6px;
  background: linear-gradient(140deg, rgba(222, 169, 35, 0.08), transparent 60%), var(--bg-2);
  padding: 18px;
}
.familia-form-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
.familia-form-topo .olho { margin: 0; }
.familia-form-selos { display: flex; gap: 8px; }
.familia-form-selos span {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 4px 10px;
  border: 1px solid rgba(222, 169, 35, 0.35);
  border-radius: 999px;
  font-size: 0.68rem;
  color: var(--ink-dim);
  white-space: nowrap;
}
.familia-form-selos b { font-size: 0.9rem; color: var(--amarelo); }
.familia-form-nota {
  margin: 10px 0 14px;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-dim);
}
.familia-form .campo { margin-top: 14px; }
.campo-dica-topo { margin: 0 0 12px; }
.form-mensagem { padding: 12px 16px; border-radius: 6px; font-size: 0.9rem; }
.form-mensagem--sucesso { background: rgba(63, 168, 95, 0.14); border: 1px solid #3fa85f; }
.form-mensagem--erro { background: rgba(226, 86, 74, 0.14); border: 1px solid #e2564a; }

/* ===== Matrícula em três passos (cadastro.html) =====
   A ordem é do Ácacio: dados, termo, aula experimental. O trilho no topo
   existe pra pessoa saber que responder as perguntas não é o fim, e quanto
   falta: formulário longo sem fim visível é formulário abandonado. */
/* Não herda de .faixa de propósito, ver o comentário no cadastro.html */
.faixa-form {
  width: min(100%, 680px);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.passos-trilho {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  list-style: none;
  margin: 0 0 38px;
  padding: 0;
}
.passo-marca {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
  opacity: 0.55;
}
.passo-marca span {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border);
  font-size: 0.76rem;
  letter-spacing: 0;
}
.passo-marca.is-atual { color: var(--amarelo); opacity: 1; }
.passo-marca.is-atual span { border-color: var(--amarelo); color: var(--amarelo); }
/* passo já cumprido fica legível, mas sem competir com o atual */
.passo-marca.is-feito { opacity: 1; color: var(--royal-claro); }
.passo-marca.is-feito span { border-color: var(--royal-claro); color: var(--royal-claro); }

/* ===== O trilho de passos se mexe quando o passo muda (23/08/2026) =====
   A marca trocava de cor num quadro só. Como a pessoa acabou de rolar pro
   topo do bloco quando isso acontece (ver irPara em cadastro.js), a troca
   ficava fora do campo de visão dela: chegava no topo e o trilho já estava
   com a cor nova, sem nada dizendo que avançou.
   A bolinha do passo atual dá uma pulsada curta, uma vez só. É o único
   movimento que chama atenção em toda a matrícula, e ele existe porque
   avançar de passo é a única coisa que a pessoa precisa perceber que
   aconteceu. */
.passo-marca { transition: color 0.3s ease, opacity 0.3s ease; }
.passo-marca span { transition: border-color 0.3s ease, color 0.3s ease; }
.passo-marca.is-atual span { animation: passo-pulsa 0.45s ease both; }
@keyframes passo-pulsa {
  0% { transform: scale(1); }
  45% { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(222, 169, 35, 0.16); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(222, 169, 35, 0); }
}

/* ===== Entrada de cada passo =====
   O .faixa-form fica de fora da revelação por scroll de propósito (está
   escrito no cadastro.html: num formulário, campo que aparece conforme a
   pessoa rola atrapalha em vez de ajudar). Mas TROCAR de passo é outra
   coisa: aí a tela inteira muda de conteúdo, e sem transição os três passos
   parecem a mesma página que piscou.
   Vem da direita, na direção em que o trilho anda. Voltar (o botão Voltar do
   passo 2) recebe .passo--voltando do cadastro.js e vem da esquerda, senão
   avançar e voltar teriam o mesmo gesto e o movimento mentiria sobre o que
   aconteceu. */
.passo { animation: passo-entra 0.32s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.passo--voltando { animation-name: passo-volta; }
@keyframes passo-entra {
  from { opacity: 0; transform: translateX(18px); }
  to { opacity: 1; transform: none; }
}
@keyframes passo-volta {
  from { opacity: 0; transform: translateX(-18px); }
  to { opacity: 1; transform: none; }
}

/* ===== Campos =====
   A borda acompanha o anel de foco. Sem isso o anel dourado fica em volta de
   uma caixa que continua com a borda apagada, e o campo ativo não se destaca
   de verdade num formulário de nove campos. */
.campo input, .campo select, .campo textarea {
  transition: border-color 0.16s ease, background 0.16s ease;
}
.campo input:focus, .campo select:focus, .campo textarea:focus {
  border-color: var(--amarelo);
}
/* erro que aparece embaixo do campo desliza, senão ele empurra o resto do
   formulário pra baixo de um quadro pro outro e a pessoa perde a linha */
.campo-erro:not([hidden]) { animation: erro-entra 0.2s ease both; }
@keyframes erro-entra {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
/* a resposta do envio (sucesso ou falha) é o momento mais importante da
   página: é a única confirmação de que o cadastro foi */
.form-mensagem:not([hidden]) { animation: passo-entra 0.3s cubic-bezier(0.2, 0.7, 0.3, 1) both; }

/* margin-top dá o respiro onde a pergunta mora, FORA da caixa: sem ele a
   legend absoluta ficaria colada no campo anterior */
.campo-grupo {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-2);
  padding: 18px 18px 8px;
  margin: 30px 0 0;
}

/* ===== A pergunta de cada bloco =====
   FORA DA CAIXA, por cima da borda (19/08/2026, a pedido do Leo, que corrigiu
   a primeira tentativa: dentro da caixa ainda lia como preso na aba errada).
   `position: absolute` tira a legend do encaixe padrão do fieldset (o
   navegador normalmente abre um buraco no traço de cima pra ela caber) e
   deixa ela pairar acima da borda, como rótulo flutuante — o mesmo padrão
   visual dos rótulos comuns (".campo label"), que já ficam acima do campo.

   Cor e peso: amarelo em negrito. Era cinza-azulado sobre azul, a mesma
   família de tom do fundo, e por isso não se destacava do que estava
   respondendo. Corpo de 0.78 pra 0.95rem, que é o "2 a 4 tamanhos" pedido. */
.campo-grupo legend {
  position: absolute;
  top: -28px;
  left: 0;
  padding: 0;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--amarelo);
}
.campo-radio {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 0;
  font-size: 0.94rem;
  cursor: pointer;
}
.campo-radio input { width: 18px; height: 18px; flex: 0 0 18px; accent-color: var(--amarelo); }
.campo-radio b { color: var(--ink); }

.form-acoes { display: flex; flex-wrap: wrap; gap: 12px; }
.form-acoes .botao { flex: 1 1 auto; text-align: center; }

/* O termo em caixa própria, com rolagem interna. Ele é longo de propósito
   (23 itens no PDF do clube), e sem o recorte a página vira uma parede de
   texto que empurra o aceite pra três telas abaixo. */
.termo {
  max-height: 460px;
  overflow-y: auto;
  padding: 24px 26px;
  margin-bottom: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-2);
  font-size: 0.92rem;
  line-height: 1.62;
}
.termo:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 2px; }
.termo p { margin: 0 0 14px; }
.termo b { color: var(--ink); }
.termo h3 {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-style: normal;
  color: var(--amarelo);
  margin: 26px 0 12px;
}
.termo h3:first-of-type { margin-top: 18px; }
.termo-resp {
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
  color: var(--ink-dim);
  font-size: 0.86rem;
}

/* tabela larga rola dentro da própria caixa, nunca faz a página rolar de lado */
.termo-tabela-rolagem { overflow-x: auto; margin: 0 0 18px; }
.termo-tabela { border-collapse: collapse; width: 100%; min-width: 380px; }
.termo-tabela th, .termo-tabela td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  white-space: nowrap;
}
.termo-tabela thead th {
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--royal-claro);
}
.termo-tabela tbody th { font-weight: 700; color: var(--ink); }
.termo-tabela td { color: var(--amarelo); font-weight: 700; }

.fim-cartao {
  padding: 20px 22px;
  margin-bottom: 26px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--amarelo);
  border-radius: 6px;
  background: var(--bg-2);
}
.fim-cartao p:last-child { margin: 0; }
