/* ============================================================================
   TáOK — Movimento
   ============================================================================
   Camada de animação, profundidade e parallax. Carrega DEPOIS do app.css.

   ----------------------------------------------------------------------------
   A REGRA QUE SUSTENTA O ARQUIVO INTEIRO
   ----------------------------------------------------------------------------
   Tudo que esconde conteúdo está atrás de `.com-movimento`, uma classe que o
   script do <head> põe no <html> **antes da primeira pintura** e **só quando o
   movimento é permitido**.

   Sem essa trava, o defeito clássico de animação de entrada aparece: o CSS
   define `opacity: 0` esperando que o JS devolva a opacidade, o JS não roda —
   bloqueado, com erro, ou porque a pessoa pediu menos movimento no sistema — e
   o site fica em branco. Conteúdo invisível é pior que conteúdo sem animação.

   Com a trava, a ausência de JS ou de vontade de movimento devolve exatamente o
   site de antes: estático, completo, legível.

   ----------------------------------------------------------------------------
   NENHUMA COR LITERAL
   ----------------------------------------------------------------------------
   Mesma regra do tokens.css. Cor aqui sai de `var(--…)`, sempre — inclusive nos
   véus e auras, que usam os tokens `-rgb` justamente para isso.
   ============================================================================ */

/* ============================================================================
   1. REVELAÇÃO AO ROLAR
   ============================================================================
   `data-revela` no elemento; o JS acrescenta `.revelado` quando ele entra na
   tela. A direção é opcional: `data-revela="esquerda"`, `"direita"`, `"zoom"`.

   `will-change` só enquanto o elemento ainda não apareceu: mantido para sempre,
   ele obriga o navegador a guardar uma camada de composição por elemento e o
   scroll engasga numa página com quarenta cards.
   ============================================================================ */

.com-movimento [data-revela] {
    opacity: 0;
    transform: translate3d(0, var(--revela-desloca), 0);
    will-change: opacity, transform;
    transition:
        opacity   var(--dur-media) var(--ease-entrada),
        transform var(--dur-media) var(--ease-entrada);
    transition-delay: var(--revela-atraso, 0ms);
}

.com-movimento [data-revela="esquerda"] { transform: translate3d(calc(var(--revela-desloca) * -1.4), 0, 0); }
.com-movimento [data-revela="direita"]  { transform: translate3d(calc(var(--revela-desloca) *  1.4), 0, 0); }
.com-movimento [data-revela="zoom"]     { transform: scale(var(--revela-escala)); }
.com-movimento [data-revela="sobe"]     { transform: translate3d(0, calc(var(--revela-desloca) * 1.8), 0); }

.com-movimento [data-revela].revelado {
    opacity: 1;
    transform: none;
    will-change: auto;
}

/* Escalonamento: o JS numera os filhos e o atraso vira uma conta, não uma
   classe por posição. Teto de 8 porque além disso o último card demora tanto
   que parece travamento, não intenção. */
.com-movimento [data-revela-grupo] > * {
    --revela-atraso: calc(var(--revela-indice, 0) * 70ms);
}

/* ============================================================================
   2. PARALLAX
   ============================================================================
   O JS escreve `--parallax-y` em pixels; o CSS só aplica. A divisão importa:
   escrever `style.transform` direto do JS brigaria com qualquer transform que a
   folha de estilo queira pôr no mesmo elemento (um hover, por exemplo).

   `translate3d` e não `top`: o primeiro roda na GPU e não recalcula layout. Com
   `top`, cada pixel de rolagem repagina a seção inteira.
   ============================================================================ */

.com-movimento [data-parallax] {
    transform: translate3d(0, var(--parallax-y, 0px), 0);
    will-change: transform;
}

/* Fundo fixo por CSS puro, para seções que não precisam de JS nenhum.
   `scroll` no celular de propósito: `fixed` em iOS causa tremor e salto de
   altura na barra de endereço, e o efeito não compensa o estrago. */
.fundo-fixo {
    background-attachment: fixed;
    background-size: cover;
    background-position: center;
}
@media (max-width: 992px), (prefers-reduced-motion: reduce) {
    .fundo-fixo { background-attachment: scroll; }
}

/* ============================================================================
   3. HERO CINEMATOGRÁFICO
   ============================================================================
   Três camadas empilhadas: foto → véu → conteúdo. O véu é o que garante que o
   texto branco continue legível quando o cliente trocar a foto por outra mais
   clara — é proteção, não decoração.
   ============================================================================ */

.heroi-cine {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    display: flex;
    align-items: center;
    min-height: clamp(480px, 82vh, 760px);
    padding: calc(var(--header-altura) + 3rem) 0 4rem;
    background: var(--brand-ink);
    color: var(--text-inverso);
}

.heroi-cine__foto {
    position: absolute;
    inset: -12% 0 -12% 0;   /* folga acima e abaixo: é o curso do parallax */
    z-index: -2;
}

.heroi-cine__foto img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 42%;
    display: block;
}

/* No celular a foto larga é cortada pelo meio, e o meio desta foto é areia —
   as pessoas ficam de fora justamente na tela em que a maioria vai entrar.
   Puxar o recorte para a direita traz os corredores de volta. */
@media (max-width: 767.98px) {
    .heroi-cine__foto img { object-position: 72% 45%; }
}

.heroi-cine__veu {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--veu-foto);
}

/* Aura da marca no canto: dá cor de marca a uma foto que não tem nenhuma, sem
   precisar tingir a imagem inteira e destruir a pele das pessoas nela. */
.heroi-cine__aura {
    position: absolute;
    z-index: -1;
    width: min(62vw, 720px);
    aspect-ratio: 1;
    right: -10%;
    top: -18%;
    background: var(--aura-primaria);
    pointer-events: none;
}
.heroi-cine__aura--baixo {
    right: auto; top: auto;
    left: -14%; bottom: -26%;
    width: min(48vw, 520px);
    background: var(--aura-destaque);
}

.heroi-cine h1 {
    color: var(--text-inverso);
    font-size: clamp(2.3rem, 6vw, 4.2rem);
    line-height: 1.03;
    letter-spacing: -0.03em;
    text-wrap: balance;
    margin-bottom: 1rem;
}

.heroi-cine p.heroi-cine__linha {
    color: rgba(255, 255, 255, 0.84);
    font-size: clamp(1rem, 1.6vw, 1.2rem);
    max-width: 46ch;
    text-wrap: pretty;
}

/* Texto em gradiente. `background-clip: text` precisa do texto transparente —
   e do fallback por cima, porque navegador sem suporte mostraria nada. */
.texto-gradiente {
    color: var(--accent);
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
    .texto-gradiente {
        background: var(--gradiente-texto);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
    }
}

/* Sublinhado que se desenha quando o hero aparece. */
.risco-marca {
    position: relative;
    display: inline-block;
}
.risco-marca::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0.06em;
    height: 0.16em;
    background: var(--accent);
    border-radius: var(--radius-pill);
    transform: scaleX(0);
    transform-origin: left center;
    z-index: -1;
}
.com-movimento .risco-marca::after {
    transition: transform var(--dur-lenta) var(--ease-entrada) 320ms;
}
.risco-marca.revelado::after,
.revelado .risco-marca::after { transform: scaleX(1); }

/* Seta de "role para ver mais". Some assim que a pessoa rola. */
.heroi-rolar {
    position: absolute;
    left: 50%; bottom: 1.4rem;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.6);
    font-size: 1.5rem;
    line-height: 1;
    transition: opacity var(--dur-media) var(--ease-suave);
}
.com-movimento .heroi-rolar { animation: taok-flutua 2.4s var(--ease-suave) infinite; }
.rolou .heroi-rolar { opacity: 0; }

@keyframes taok-flutua {
    0%, 100% { transform: translate(-50%, 0); }
    50%      { transform: translate(-50%, 9px); }
}

/* ============================================================================
   4. PROFUNDIDADE E RESPOSTA AO PONTEIRO
   ============================================================================ */

/* DOIS PRÉ-REQUISITOS, e ignorar qualquer um deixa marca na tela.

   1. O elemento precisa ter SUPERFÍCIE PRÓPRIA — fundo, borda e `border-radius`.
      A classe só acrescenta profundidade a um card que já existe; ela não cria
      o card. Numa caixa transparente e sem raio, a `box-shadow` vira um
      retângulo de cantos retos em volta do nada, e o `border-color` não tem
      borda para pintar. Foi o que aconteceu com os passos da home.

   2. O elemento precisa SER CLICÁVEL. Levantar sob o ponteiro é a promessa
      visual de que ali se clica; num bloco informativo isso é a mesma classe de
      defeito do `docs/07 §6.1` — a interface oferecendo o que não entrega. */
.cartao-elevado {
    transition:
        transform   var(--dur-rapida) var(--ease-suave),
        box-shadow  var(--dur-rapida) var(--ease-suave),
        border-color var(--dur-rapida) var(--ease-suave);
}
@media (hover: hover) {
    .cartao-elevado:hover {
        transform: translateY(-6px);
        box-shadow: var(--shadow-lg);
        border-color: rgba(var(--primary-rgb), 0.35);
    }
}

/* Brilho que atravessa o card no hover. `overflow: hidden` no card é
   pré-requisito — sem ele o brilho escapa por cima do vizinho. */
.cartao-brilho { position: relative; overflow: hidden; }
.cartao-brilho::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(105deg,
        transparent 38%,
        rgba(255, 255, 255, 0.22) 50%,
        transparent 62%);
    transform: translateX(-120%);
    pointer-events: none;
}
@media (hover: hover) {
    .com-movimento .cartao-brilho:hover::before {
        transform: translateX(120%);
        transition: transform 720ms var(--ease-suave);
    }
}

/* Zoom lento na foto dentro de um card, sem mexer no card. */
.foto-zoom { overflow: hidden; }
.foto-zoom img {
    transition: transform 620ms var(--ease-entrada);
    will-change: transform;
}
@media (hover: hover) {
    .foto-zoom:hover img { transform: scale(1.07); }
}

/* Botão com preenchimento que cresce do centro. */
.btn-anima { position: relative; overflow: hidden; z-index: 0; }
.btn-anima::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--gradient-primary);
    opacity: 0;
    z-index: -1;
    transition: opacity var(--dur-rapida) var(--ease-suave);
}
@media (hover: hover) {
    .btn-anima:hover::before { opacity: 1; }
    .btn-anima:hover { transform: translateY(-2px); box-shadow: var(--shadow-destaque); }
}

/* ============================================================================
   5. VIDRO — cabeçalho que condensa ao rolar
   ============================================================================ */

.barra-vidro {
    transition:
        background-color var(--dur-media) var(--ease-suave),
        box-shadow       var(--dur-media) var(--ease-suave),
        border-color     var(--dur-media) var(--ease-suave);
}
.rolou .barra-vidro {
    background-color: var(--vidro-fundo);
    border-bottom-color: var(--vidro-borda);
    box-shadow: var(--shadow-md);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .rolou .barra-vidro {
        -webkit-backdrop-filter: blur(var(--vidro-desfoque)) saturate(160%);
        backdrop-filter: blur(var(--vidro-desfoque)) saturate(160%);
    }
}

/* Barra de progresso da leitura, no topo. */
.progresso-leitura {
    position: fixed;
    top: 0; left: 0;
    height: 3px;
    width: 100%;
    transform: scaleX(var(--progresso, 0));
    transform-origin: left center;
    background: var(--gradiente-texto);
    z-index: 1090;
    pointer-events: none;
}

/* ============================================================================
   6. NÚMEROS QUE CONTAM
   ============================================================================
   `font-variant-numeric: tabular-nums` evita o pior detalhe de contador
   animado: com números de larguras diferentes, o bloco inteiro sacode
   horizontalmente enquanto conta.
   ============================================================================ */

[data-contador] { font-variant-numeric: tabular-nums; }

/* ============================================================================
   7. FAIXA CORRIDA (marquee)
   ============================================================================
   Duas cópias do conteúdo lado a lado e um deslocamento de exatamente -50%: é
   o que faz a volta ser imperceptível. `aria-hidden` na segunda cópia, senão o
   leitor de tela lê tudo duas vezes.
   ============================================================================ */

.faixa-corrida {
    display: flex;
    overflow: hidden;
    gap: 0;
    mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
}
.faixa-corrida__trilho {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 2.5rem;
    padding-right: 2.5rem;
}
.com-movimento .faixa-corrida__trilho {
    animation: taok-desliza var(--faixa-duracao, 34s) linear infinite;
}
.faixa-corrida:hover .faixa-corrida__trilho { animation-play-state: paused; }

@keyframes taok-desliza {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-100%, 0, 0); }
}

/* ============================================================================
   8. DETALHES DE MARCA
   ============================================================================ */

/* Malha de pontos: dá textura a uma seção lisa sem pesar um kilobyte de imagem. */
.textura-pontos {
    position: relative;
    isolation: isolate;
}
.textura-pontos::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image: radial-gradient(rgba(var(--primary-rgb), 0.16) 1px, transparent 1px);
    background-size: 22px 22px;
    -webkit-mask-image: radial-gradient(ellipse at center, black 20%, transparent 72%);
    mask-image: radial-gradient(ellipse at center, black 20%, transparent 72%);
    pointer-events: none;
}

/* Selo de contagem regressiva e etiquetas que pulsam de leve. */
.com-movimento .pulsa-marca {
    animation: taok-pulsa 2.6s var(--ease-suave) infinite;
}
@keyframes taok-pulsa {
    0%, 100% { box-shadow: 0 0 0 0   rgba(var(--primary-rgb), 0.45); }
    70%      { box-shadow: 0 0 0 14px rgba(var(--primary-rgb), 0); }
}

/* Entrada de página: só o conteúdo principal, e rápida. Animar a página inteira
   a cada clique é o tipo de efeito que impressiona uma vez e irrita sempre. */
.com-movimento .entrada-pagina {
    animation: taok-entra var(--dur-media) var(--ease-entrada) both;
}
@keyframes taok-entra {
    from { opacity: 0; transform: translate3d(0, 10px, 0); }
    to   { opacity: 1; transform: none; }
}

/* Esqueleto de carregamento, para quando há espera real. */
.esqueleto {
    background: linear-gradient(90deg,
        var(--bg-hover) 25%, var(--bg-sunken) 37%, var(--bg-hover) 63%);
    background-size: 400% 100%;
    border-radius: var(--radius-sm);
}
.com-movimento .esqueleto { animation: taok-esqueleto 1.4s ease infinite; }
@keyframes taok-esqueleto {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}

/* ============================================================================
   9. MENOS MOVIMENTO — a rede de segurança final
   ============================================================================
   O `.com-movimento` já impede o script de ligar o movimento quando a pessoa
   pediu menos. Isto aqui é o cinto por cima: se alguma regra escapar da trava,
   ou se a preferência mudar com a página aberta, nada anima e — o que mais
   importa — nada fica invisível.
   ============================================================================ */

@media (prefers-reduced-motion: reduce) {
    [data-revela],
    [data-revela].revelado {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
    [data-parallax]        { transform: none !important; }
    .risco-marca::after    { transform: scaleX(1) !important; transition: none !important; }
    .faixa-corrida__trilho { animation: none !important; }
    .heroi-rolar           { animation: none !important; }
    .foto-zoom img,
    .cartao-elevado        { transition: none !important; }
    .cartao-brilho::before { display: none !important; }
}

/* ============================================================================
   10. COMPONENTES DA NOVA LINGUAGEM VISUAL
   ============================================================================
   Moram aqui, e não no app.css, porque só existem por causa da camada de
   movimento: hero sobre foto, vidro, faixa corrida e trilha de passos. Quem
   remover este arquivo remove junto o que ele sustenta, sem deixar regra órfã.
   ============================================================================ */

/* ------------------------------------------------- hero: conteúdo */
.heroi-cine__conteudo { max-width: 760px; }

.heroi-selo {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 7px 16px 7px 12px;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: var(--text-inverso);
    font-size: 0.82rem; font-weight: 600; letter-spacing: 0.02em;
    margin-bottom: 1.1rem;
}
.heroi-selo__ponto {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--accent);
    flex: 0 0 auto;
}
.com-movimento .heroi-selo__ponto { animation: taok-farol 2s var(--ease-suave) infinite; }
@keyframes taok-farol {
    0%, 100% { box-shadow: 0 0 0 0   rgba(var(--accent-rgb), 0.7); }
    70%      { box-shadow: 0 0 0 10px rgba(var(--accent-rgb), 0); }
}

/* ------------------------------------------------- hero: busca em vidro */
/* O campo de busca sobre foto precisa de fundo próprio: translúcido puro deixa
   o texto digitado brigar com a imagem. Vidro resolve os dois — separa do fundo
   e mantém a foto viva atrás. */
.busca-hero--vidro {
    background: var(--vidro-fundo);
    border: 1px solid var(--vidro-borda);
    padding-left: 46px;
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .busca-hero--vidro {
        -webkit-backdrop-filter: blur(var(--vidro-desfoque)) saturate(150%);
        backdrop-filter: blur(var(--vidro-desfoque)) saturate(150%);
    }
}
.busca-hero__icone {
    position: absolute; left: 16px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
    font-size: 1.05rem;
}
.busca-hero--vidro .form-select { flex: 0 1 150px; }

@media (max-width: 575.98px) {
    .busca-hero--vidro { padding-left: 10px; }
    .busca-hero__icone { display: none; }
}

/* ------------------------------------------------- hero: números */
/* ------------------------------------------------- faixa de modalidades */
.faixa-modalidades {
    background: var(--brand-ink);
    border-top: 1px solid rgba(var(--accent-rgb), 0.25);
    border-bottom: 1px solid rgba(var(--accent-rgb), 0.25);
    padding: 14px 0;
}
.faixa-item {
    display: inline-flex; align-items: center; gap: 9px;
    white-space: nowrap;
    color: rgba(255, 255, 255, 0.76);
    font-family: var(--font-titulo);
    font-weight: 500; font-size: 1.02rem;
    text-decoration: none;
    transition: color var(--transition-fast);
}
.faixa-item i { color: var(--accent); font-size: 1.15rem; }
.faixa-item:hover { color: var(--text-inverso); text-decoration: none; }
[data-theme="dark"] :where(.faixa-item) { color: rgba(255, 255, 255, 0.76); }
[data-theme="dark"] :where(.faixa-item:hover) { color: var(--text-inverso); }

/* ------------------------------------------------- etiqueta de seção */
.secao-etiqueta {
    display: inline-block;
    font-size: 0.74rem; font-weight: 700;
    letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--primary);
    margin-bottom: 6px;
}
[data-theme="dark"] .secao-etiqueta { color: var(--primary-texto-escuro); }
.secao-etiqueta--clara { color: var(--accent); }
[data-theme="dark"] .secao-etiqueta--clara { color: var(--accent); }

/* ------------------------------------------------- tiles de categoria */
.categoria-tile { position: relative; padding-right: 40px !important; }
.categoria-total { color: var(--text-muted); }
.categoria-seta {
    position: absolute; right: 14px; top: 50%;
    transform: translateY(-50%) translateX(-6px);
    color: var(--primary);
    opacity: 0;
    transition: opacity var(--transition-fast), transform var(--transition-fast);
}
@media (hover: hover) {
    .categoria-tile:hover .categoria-seta { opacity: 1; transform: translateY(-50%) translateX(0); }
}
[data-theme="dark"] .categoria-seta { color: var(--primary-texto-escuro); }

/* ------------------------------------------------- trilha dos passos */
/* A linha só aparece a partir de lg, onde os quatro passos ficam lado a lado.
   Empilhados no celular, uma linha horizontal ligaria coisa nenhuma. */
.trilha-passos { position: relative; }
.trilha-passos__linha { display: none; }

@media (min-width: 992px) {
    .trilha-passos__linha {
        display: block;
        position: absolute;
        top: 46px; left: 12%; right: 12%;
        height: 2px;
        background: linear-gradient(90deg,
            rgba(var(--primary-rgb), 0) 0%,
            rgba(var(--primary-rgb), 0.35) 18%,
            rgba(var(--accent-rgb), 0.55) 50%,
            rgba(var(--primary-rgb), 0.35) 82%,
            rgba(var(--primary-rgb), 0) 100%);
        z-index: 0;
    }
    .trilha-passos .row { position: relative; z-index: 1; }
}

/* ------------------------------------------------- faixa do organizador */
.secao-organizador { position: relative; }

.faixa-organizador {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}
/* O seletor antigo era `> div:first-child`, e o primeiro filho agora é a aura.
   Nomear a coluna de texto resolve sem depender de posição — que é o tipo de
   acoplamento que quebra em silêncio quando alguém acrescenta um elemento. */
.faixa-organizador__texto { flex: 1 1 380px; position: relative; z-index: 1; }

.faixa-organizador__aura {
    position: absolute; z-index: -1;
    width: min(70%, 620px); aspect-ratio: 1;
    right: -12%; top: -40%;
    background: var(--aura-primaria);
    pointer-events: none;
}

.lista-beneficios {
    list-style: none; padding: 0;
    margin: 1.4rem 0 0;
    display: grid; gap: 10px;
}
.lista-beneficios li {
    display: flex; align-items: flex-start; gap: 10px;
    color: rgba(255, 255, 255, 0.88);
    font-size: 0.95rem;
}
.lista-beneficios i {
    color: var(--accent);
    font-size: 1.1rem; line-height: 1.4;
    flex: 0 0 auto;
}

/* ============================================================================
   11. TELAS DE ACESSO — entrar, cadastrar, recuperar senha
   ============================================================================
   Duas colunas no desktop: ambiente à esquerda, formulário à direita. No
   celular o painel some por inteiro — não encolhe, some. Uma foto ocupando 40%
   da altura empurraria o campo de senha para fora da primeira dobra, e quem
   abre "entrar" no celular quer o teclado, não a paisagem.
   ============================================================================ */

/* QUEM FAZ A CONTA DE ALTURA É O NAVEGADOR, NÃO O CSS.
 *
 * O DEFEITO QUE ISTO CONSERTA: aqui pedia-se `100vh - cabeçalho`, mas o rodapé
 * vem DEPOIS e é somado por baixo. Com o rodapé completo (442px), a tela de
 * entrar terminava com 569px de rolagem numa janela de 945px — e o pior nem era
 * rolar: o painel ilustrado, ancorado embaixo, ficava com a lista de itens 23px
 * fora da dobra. A pessoa via uma lista cortada, sem nada indicando que havia
 * mais.
 *
 * A PRIMEIRA CORREÇÃO FOI PIOR QUE O DEFEITO, e vale registrar: troquei por
 * `calc(100dvh - cabeçalho - rodapé)`, com a altura do rodapé num token. Ficou
 * exato nas três larguras de desktop — e errado por 12px no telefone, onde os
 * links do rodapé quebram para a segunda linha e ele mede 68px em vez dos 56
 * que o token prometia. Número mágico que descreve a altura de um elemento com
 * texto dentro está errado em alguma largura; só não se sabe qual.
 *
 * A conta certa já existia na página: `.pagina` é `flex` em coluna com
 * `min-height: 100dvh` e `main` é `flex: 1 0 auto` (app.css §2) — o `main` JÁ
 * recebe a sobra entre cabeçalho e rodapé, medida pelo navegador, com o rodapé
 * que existir. Só faltava repassá-la para dentro.
 *
 * `.conteudo-acesso` (posta no `main` pelo layout) o torna flex em coluna, e o
 * `flex: 1` abaixo faz a grade ocupar essa sobra. Zero aritmética, zero token
 * de altura, certo em qualquer largura. */
.conteudo-acesso { display: flex; flex-direction: column; }
.conteudo-acesso > .tela-acesso { flex: 1; }

.tela-acesso {
    display: grid;
    grid-template-columns: 1fr;
}

.tela-acesso__forma {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2.5rem 1rem 3.5rem;
}
.tela-acesso__forma > * { width: 100%; }

.acesso-painel { display: none; }

@media (min-width: 992px) {
    .tela-acesso { grid-template-columns: minmax(0, 46%) minmax(0, 1fr); }

    /* GRUDADO, e não simplesmente alto.
       O formulário de cadastro é comprido; sem isto o painel acompanha a altura
       dele e a frase, ancorada embaixo, só aparece depois de rolar dois metros
       de foto escura. Grudado, o painel ocupa uma tela e fica lá enquanto o
       formulário passa — que é o comportamento que se espera de um painel de
       ambiente. */
    .acesso-painel {
        display: block;
        position: sticky;

        /* GRUDA ABAIXO DO CABEÇALHO, não no topo da janela.
           O `.cabecalho` é `position: sticky; top: 0` e fica na tela o tempo
           todo. Com `top: 0` aqui, o painel escorregava POR BAIXO dele ao rolar
           o cadastro, e a logo do painel sumia atrás da barra preta. */
        top: var(--header-total);
        align-self: start;

        /* DUAS SITUAÇÕES, UM VALOR SÓ.
         *
         *   · Tela curta (entrar, recuperar senha): a grade cabe na janela, e
         *     `100%` faz o painel preencher exatamente a coluna dele — sem
         *     sobra, sem corte.
         *   · Tela comprida (criar conta): a grade é mais alta que a janela, e
         *     `100%` esticaria o painel por toda ela; aí vale o segundo termo,
         *     que é uma tela útil, e o `sticky` acima faz o resto.
         *
         * Era `height: 100vh` — a janela INTEIRA num elemento que começa 71px
         * abaixo do topo. O painel terminava 71px fora da tela, levando junto a
         * lista de itens que mora ancorada no pé dele. */
        height: min(100%, calc(100dvh - var(--header-total)));

        overflow: hidden;
        isolation: isolate;
        background: var(--brand-ink);
    }
    .tela-acesso__forma { padding: 3rem 2.5rem; }
}

.acesso-painel__foto { position: absolute; inset: 0; z-index: -2; }
.acesso-painel__foto img {
    width: 100%; height: 100%;
    object-fit: cover; object-position: center 55%;
    display: block;
}
.acesso-painel__veu {
    position: absolute; inset: 0; z-index: -1;
    background: var(--veu-foto-suave);
}
.acesso-painel__aura {
    position: absolute; z-index: -1;
    left: -30%; top: -20%;
    width: 90%; aspect-ratio: 1;
    background: var(--aura-primaria);
    pointer-events: none;
}

.acesso-painel__conteudo {
    position: relative;
    height: 100%;
    display: flex; flex-direction: column; justify-content: flex-end;
    padding: 3rem;
    color: var(--text-inverso);
}

.acesso-painel__frase {
    font-family: var(--font-titulo);
    font-size: clamp(1.5rem, 2.4vw, 2.1rem);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.02em;
    max-width: 16ch;
    margin-bottom: 1.6rem;
    text-wrap: balance;
}

.acesso-painel__itens {
    list-style: none; padding: 0; margin: 0;
    display: grid; gap: 11px;
}
.acesso-painel__itens li {
    display: flex; align-items: flex-start; gap: 10px;
    color: rgba(255, 255, 255, 0.82);
    font-size: 0.94rem;
}
.acesso-painel__itens i {
    color: var(--accent);
    font-size: 1.05rem; line-height: 1.4;
    flex: 0 0 auto;
}

/* A COLUNA É A SUPERFÍCIE, NÃO O CARTÃO.
   O cartão perde borda, sombra e fundo no desktop — com o painel escuro ao
   lado já há separação, e moldura dupla aperta a tela. Mas a decisão estava
   pela metade: sem o cartão, o formulário ficava solto em cima do
   `--bg-body` (#f6f5f2, quase branco), sem nada que dissesse onde começa a
   área de trabalho. Campo de senha flutuando num fundo chapado é o que faz a
   tela parecer inacabada.

   A correção é dar a superfície à COLUNA. Vira o padrão de duas metades —
   foto escura de um lado, painel branco do outro — em vez de cartão branco
   sobre fundo quase branco, que é invisível de qualquer jeito. No celular o
   painel não existe e o cartão volta a ter a moldura dele, que lá é o que
   separa o formulário do fundo. */
@media (min-width: 992px) {
    .tela-acesso__forma {
        background: var(--bg-surface);
        border-left: 1px solid var(--border);
    }
    .tela-acesso__forma .cartao {
        border-color: transparent;
        box-shadow: none;
        background: transparent;
    }
    /* O cartão já não é uma moldura: o respiro de dentro dele é redundante com
       o da coluna, e somados jogam o formulário para o meio da tela. */
    .tela-acesso__forma .cartao-corpo { padding: 0 !important; }
}

/* Texto de apoio sob um título. Vira classe porque estava repetido como
   `style="color:var(--text-secondary)"` em dezenas de telas — e atributo de
   estilo inline é exatamente o que a auditoria de cor literal não consegue
   distinguir de uma cor cravada. */
.texto-apoio { color: var(--text-secondary); }

/* A logo é filha de um flex em coluna, e `align-items` padrão é `stretch` — o
   que estica a imagem para a largura inteira do painel, ignorando o
   `width: auto` da classe `.logo`. Um `align-self` resolve sem mexer no
   alinhamento do resto. */
.acesso-painel__conteudo .logo { align-self: flex-start; }

/* ============================================================================
   12. PÁGINA DO EVENTO — capa com mais ar
   ============================================================================
   O cabeçalho já existia com banner e véu (`app.css §15`). O que muda aqui é a
   respiração: mais altura, uma aura da marca e um leve zoom na capa, para a
   página do evento parecer a peça de conversão que é — e não uma faixa preta
   com texto por cima.
   ============================================================================ */

.evento-topo { padding-block: 52px 56px; overflow: hidden; isolation: isolate; }

/* A OPACIDADE DO VÉU SAIU DAQUI, e a mudança tem motivo.
   ---------------------------------------------------------------------------
   Esta folha carrega DEPOIS da `app.css` e a regra tinha a mesma especificidade
   — então o `opacity: 0.42` escrito aqui vencia o da `app.css` em silêncio.
   Efeito prático: mexer no véu no arquivo onde ele está documentado não fazia
   nada, e a regra de celular que eu tinha escrito lá simplesmente não existia.
   É o que o comentário do `head.php` avisa: "animacoes.css pode esconder alguma
   coisa".

   Esta folha cuida de MOVIMENTO. O véu é aparência do componente e voltou para
   a `app.css`, junto do gradiente que o acompanha — os dois decidem a mesma
   coisa e separá-los foi o que criou a confusão. */
.evento-topo.com-banner::before {
    /* A capa cresce devagar enquanto a página está aberta. É lento de propósito:
       rápido vira distração na tela em que a pessoa está decidindo se paga. */
    transform: scale(1.04);
}
.com-movimento .evento-topo.com-banner::before {
    animation: taok-respira 18s var(--ease-suave) infinite alternate;
}
@keyframes taok-respira {
    from { transform: scale(1.04); }
    to   { transform: scale(1.11); }
}

.evento-topo::after { z-index: 0; }

/* Aura da marca sobre a capa: liga a foto do organizador à identidade da
   plataforma sem tingir a imagem inteira. */
.evento-topo.com-banner .container-taok::before {
    content: "";
    position: absolute;
    z-index: -1;
    right: -14%; top: -60%;
    width: min(60vw, 620px); aspect-ratio: 1;
    background: var(--aura-primaria);
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .evento-topo.com-banner::before { animation: none !important; transform: none !important; }
}

/* ============================================================================
   13. ETAPAS DA COMPRA
   ============================================================================
   A linha que liga as bolhas é um `::before` do item, não um elemento à parte:
   assim ela nunca fica dessincronizada da quantidade de etapas, que varia entre
   a inscrição e a loja.
   ============================================================================ */

.passos-compra {
    display: flex;
    list-style: none;
    counter-reset: passo;
    gap: 0;
    overflow-x: auto;
    scrollbar-width: none;

    /* O RESPIRO VERTICAL É O QUE IMPEDE O TOPO DA BOLHA DE SER CORTADO.
       ------------------------------------------------------------------------
       `overflow-x: auto` NÃO recorta só na horizontal. O CSS não permite um eixo
       rolar e o outro transbordar: pedir `auto` num promove o outro a `auto`
       também, e este elemento vira um contêiner de rolagem nas DUAS direções.
       Medido: `getComputedStyle(.passos-compra).overflow` devolvia "auto auto".

       A bolha da etapa ATUAL passa do topo por dois motivos somados, e os dois
       são intencionais:
         • `transform: scale(1.08)` — ~1,5px acima numa bolha de 36px;
         • o pulso `taok-pulsa`, que é um `box-shadow` de spread indo a 14px.
       Medido a 411px: topo da bolha em 316 contra 317 do contêiner, com o brilho
       chegando a ~7px acima. Tudo isso era cortado por uma régua horizontal que
       nem estava rolando.

       É a MESMA armadilha do `body { overflow-x: hidden }` que escondia o
       seletor de data (tokens.css §"rolagem"): esconder ou rolar um eixo tem
       preço no outro, e o preço aparece longe de onde a linha foi escrita.

       A correção não é tirar o `overflow-x` — ele é a rede de proteção para um
       fluxo de cinco etapas ou um rótulo comprido. É dar ao contêiner a altura
       que o brilho precisa (18px cobre os 14 do pulso, a escala e uma folga de
       arredondamento entre navegadores) e devolver
       o espaço ao layout pela margem negativa: a régua ocupa exatamente o mesmo
       lugar de antes, e nada é recortado. */
    padding: 18px 0;
    margin: -18px 0 calc(1.75rem - 18px);
}
.passos-compra::-webkit-scrollbar { display: none; }

.passos-compra__item {
    position: relative;
    flex: 1 1 0;
    min-width: 116px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    padding-inline: 6px;
}

/* A linha sai da bolha anterior e vai até esta. O primeiro item não tem linha
   à esquerda, senão ela começa no vazio. */
.passos-compra__item + .passos-compra__item::before {
    content: "";
    position: absolute;
    top: 17px;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var(--border-forte);
    z-index: 0;
}
.passos-compra__item--feito::before,
.passos-compra__item--atual::before { background: var(--primary); }

.passos-compra__bolha {
    position: relative;
    z-index: 1;
    width: 36px; height: 36px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-titulo);
    font-weight: 700; font-size: 0.95rem;
    background: var(--bg-surface);
    color: var(--text-muted);
    border: 2px solid var(--border-forte);
    transition: all var(--transition-normal);
}
.passos-compra__item--feito .passos-compra__bolha {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
}
.passos-compra__item--atual .passos-compra__bolha {
    background: var(--primary);
    border-color: var(--primary);
    color: var(--on-primary);
    transform: scale(1.08);
}
.com-movimento .passos-compra__item--atual .passos-compra__bolha {
    animation: taok-pulsa 2.6s var(--ease-suave) infinite;
}

.passos-compra__rotulo {
    font-size: 0.82rem;
    line-height: 1.25;
    color: var(--text-muted);
    max-width: 14ch;
}
.passos-compra__item--atual .passos-compra__rotulo {
    color: var(--text-primary);
    font-weight: 600;
}
.passos-compra__item--feito .passos-compra__rotulo { color: var(--text-secondary); }

@media (max-width: 575.98px) {
    .passos-compra__item { min-width: 88px; }
    .passos-compra__rotulo { font-size: 0.74rem; }
}

/* NO CELULAR ESTREITO, AS QUATRO ETAPAS TÊM DE CABER.
   ---------------------------------------------------------------------------
   Com `min-width: 88px`, quatro etapas pedem 352px. Num aparelho de 320px a
   régua tinha 288px úteis: a quarta bolha ficava INTEIRA fora da tela, e o
   `scrollbar-width: none` acima tirava qualquer sinal de que dava para arrastar.
   Medido: `scrollWidth 352` contra `clientWidth 288`.

   O efeito para quem usa é o oposto do que a régua existe para fazer: ela está
   ali para dizer "faltam duas", e escondia a última — o número aparecia cortado
   pela borda, como se estivesse atrás de alguma coisa.

   `min-width: 0` com o `flex: 1 1 0` que já existe deixa as quatro dividirem o
   que houver, em qualquer largura. O resto encolhe junto para o texto não virar
   uma coluna de letras. */
@media (max-width: 400px) {
    .passos-compra__item { min-width: 0; padding-inline: 2px; }

    .passos-compra__bolha { width: 30px; height: 30px; font-size: 0.85rem; }

    /* A linha acompanha o centro da bolha menor: 30/2 menos a metade dos 2px. */
    .passos-compra__item + .passos-compra__item::before { top: 14px; }

    .passos-compra__rotulo { font-size: 0.68rem; max-width: 11ch; }
}

/* ============================================================================
   14. SLIDES DE FUNDO
   ============================================================================
   A DECISÃO QUE TORNA ISTO SEGURO: O QUE GIRA É A FOTO, NÃO O CONTEÚDO.

   Carrossel de conteúdo é um problema conhecido de acessibilidade — some texto
   antes de a pessoa terminar de ler, e quem usa leitor de tela nunca sabe
   quantos itens existem. Aqui o título, a busca e os botões ficam PARADOS; só a
   imagem atrás troca. Ninguém perde informação por não ser rápido o bastante, e
   a marcação não precisa de `aria-live` nem de `role="region"`.

   Por isso as fotos são `aria-hidden` e o alternador é opcional: ele muda o
   ambiente, não a mensagem.
   ============================================================================ */

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

.slides__item {
    position: absolute;
    inset: 0;
    opacity: 0;
    /* `visibility` junto com a opacidade tira o slide inativo da árvore de
       composição. Só com `opacity: 0` o navegador continua pintando as cinco
       fotos a cada quadro, e o celular esquenta à toa. */
    visibility: hidden;
    transition: opacity 1100ms var(--ease-suave), visibility 0s linear 1100ms;
}
.slides__item.ativo {
    opacity: 1;
    visibility: visible;
    transition: opacity 1100ms var(--ease-suave), visibility 0s;
}

.slides__item img {
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: center 42%;
    display: block;
}
@media (max-width: 767.98px) {
    .slides__item img { object-position: 68% 45%; }
}

/* Ken Burns: a foto ativa cresce devagar durante a própria exibição. É o que
   impede o slide parado de parecer uma imagem travada. */
.com-movimento .slides__item.ativo img {
    animation: taok-kenburns 9s var(--ease-suave) forwards;
}
@keyframes taok-kenburns {
    from { transform: scale(1.0); }
    to   { transform: scale(1.07); }
}

/* ------------------------------------------------- alternador */
.slides-pontos {
    position: absolute;
    z-index: 3;
    right: 2rem; bottom: 2rem;
    display: flex; gap: 9px;
    padding: 0; margin: 0;
    list-style: none;
}
.slides-pontos__btn {
    width: 9px; height: 9px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.36);
    cursor: pointer;
    transition: background var(--transition-fast), width var(--transition-normal);
}
.slides-pontos__btn:hover { background: rgba(255, 255, 255, 0.66); }
.slides-pontos__btn[aria-pressed="true"] {
    background: var(--accent);
    width: 26px;
}

@media (max-width: 767.98px) {
    .slides-pontos { right: 1rem; bottom: 4.4rem; }
}

/* Sem movimento: fica o primeiro slide e pronto. Os pontos somem porque sem
   troca automática eles prometeriam um controle que não tem o que controlar. */
@media (prefers-reduced-motion: reduce) {
    .slides__item { transition: none !important; }
    .slides__item.ativo img { animation: none !important; transform: none !important; }
}

/* Sem `.com-movimento` o animacoes.js sai logo no início e o carrossel não
   troca de slide — então os pontos viram botões que não fazem nada. Controle
   que não controla é pior que controle ausente: some.
   Vale para "reduzir movimento" ligado E para JS bloqueado, que é justamente o
   que a classe distingue. */
html:not(.com-movimento) .slides-pontos { display: none; }

/* ============================================================================
   15. AVISO DE COOKIES
   ============================================================================
   Discreto de propósito: uma faixa ancorada embaixo, não um modal. Modal de
   cookie sequestra a primeira impressão do site e força uma decisão antes de a
   pessoa ver o que veio ver — e aqui não há decisão nenhuma a tomar, só um
   aviso a ler (`partials/aviso-cookies.php`).

   Por isso também NÃO escurece o fundo, NÃO prende o foco e NÃO bloqueia o
   scroll: dá para ignorar a barra, navegar o site e fechá-la depois.
   ============================================================================ */

.aviso-cookies {
    position: fixed;
    z-index: 1040;            /* acima do conteúdo, abaixo dos modais do Bootstrap */
    left: 1rem; right: 1rem; bottom: 1rem;
    margin-inline: auto;
    max-width: 660px;

    display: flex;
    align-items: center;
    gap: 1.1rem;

    padding: 0.95rem 1.15rem;
    border-radius: var(--radius-lg);
    border: 1px solid var(--vidro-borda);
    background: var(--vidro-fundo);
    backdrop-filter: blur(var(--vidro-desfoque));
    -webkit-backdrop-filter: blur(var(--vidro-desfoque));
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
}

.aviso-cookies__texto { flex: 1 1 auto; min-width: 0; }

.aviso-cookies__texto p {
    margin: 0 0 2px;
    font-size: 0.86rem;
    line-height: 1.45;
    color: var(--text-secondary);
}
.aviso-cookies__texto strong { color: var(--text-primary); }

.aviso-cookies__texto a {
    font-size: 0.8rem;
    color: var(--primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.aviso-cookies__acao { flex: 0 0 auto; margin: 0; }

/* O rodapé abre espaço para o aviso não cobrir a última linha da página. Lê a
   mesma `--reserva-pe` da rolagem (`app.css §2`) — um número só para as duas
   coisas, que é o que impede a folga de ficar menor que a barra.

   OS DOIS RODAPÉS, e não só o completo. O enxuto das telas de acesso nasceu
   sem esta linha, e o defeito foi medido: `elementFromPoint` no meio do link
   "Aviso de privacidade" devolvia `DIV.aviso-cookies`. O link estava na tela,
   com a cor certa, e não recebia clique — e logo ele, que é o que a cláusula
   11 obriga a manter alcançável. É a mesma armadilha do docs/07 §8.16: a
   folga e o aviso saírem do mesmo lugar, senão um aparece sem o outro. */
.com-aviso-cookies .rodape,
.com-aviso-cookies .rodape-enxuto { padding-bottom: var(--reserva-pe); }

/* E A FOLGA SAI DO MIOLO, NÃO DO TAMANHO DA PÁGINA.
   Nas telas de acesso a página cabe exatamente na janela; um rodapé 132px mais
   alto devolveria a rolagem que esta entrega veio tirar. `.pagina > main` é
   `flex: 1 0 auto` — cresce mas não encolhe. Aqui ele pode encolher, então a
   folga é descontada do espaço sobrando entre cabeçalho e rodapé, que nestas
   telas existe de sobra.

   Encolher não corta nada: `min-height: auto` de item flex não deixa o `main`
   ficar menor que o próprio conteúdo. Na tela de criar conta, que é mais alta
   que a janela, ele simplesmente não encolhe e a página rola — como deve. */
.com-aviso-cookies .conteudo-acesso { flex-shrink: 1; }

/* COM A BARRA DE INSCRIÇÃO NA TELA, O AVISO SOBE PARA CIMA DELA.
   Os dois são `position: fixed` no pé, e o aviso tem z-index maior (1040 contra
   1035): sem isto ele cobre o "Inscrever-se" da página de evento no celular —
   o botão mais importante do produto, na tela onde a maioria se inscreve. E
   cobre justamente na primeira visita, que é quando o aviso aparece.
   `~` porque o aviso é irmão de `.pagina` no HTML (fica depois do rodapé no
   DOM de propósito, para não entrar na ordem de tabulação). */
@media (max-width: 991px) {
    .pagina:has(.barra-inscricao) ~ .aviso-cookies {
        bottom: calc(var(--barra-inscricao-altura) + env(safe-area-inset-bottom, 0px) + 0.6rem);
    }
}

/* Entrada: sobe de baixo, uma vez. `.com-movimento` porque sem a classe o JS
   não roda — e uma animação de entrada sem quem a dispare não pode ser o que
   decide se a barra é visível. Aqui a barra já nasce visível; a animação só
   suaviza a chegada de quem tem movimento. */
.com-movimento .aviso-cookies {
    animation: aviso-cookies-entra var(--dur-media) var(--ease-entrada) both;
    animation-delay: 700ms;   /* deixa a página chegar primeiro */
}

@keyframes aviso-cookies-entra {
    from { opacity: 0; transform: translate3d(0, 18px, 0); }
    to   { opacity: 1; transform: none; }
}

/* Saída, disparada pelo app.js ao reconhecer. Sem movimento a barra some
   direto — o JS remove o elemento de qualquer jeito. */
.aviso-cookies--saindo {
    opacity: 0;
    transform: translate3d(0, 12px, 0);
    transition: opacity var(--dur-rapida) var(--ease-suave),
                transform var(--dur-rapida) var(--ease-suave);
}

@media (max-width: 575.98px) {
    /* No celular a barra vira duas linhas e o botão ocupa a largura: um botão
       de 60px no canto, ao lado de três linhas de texto, é alvo pequeno demais
       para o polegar. */
    .aviso-cookies {
        flex-direction: column;
        align-items: stretch;
        gap: 0.7rem;
        left: 0.6rem; right: 0.6rem; bottom: 0.6rem;
    }
    .aviso-cookies__acao .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .aviso-cookies          { animation: none !important; }
    .aviso-cookies--saindo  { transition: none !important; }
}

/* Impressão: a barra não faz sentido no papel. */
@media print {
    .aviso-cookies { display: none !important; }
}
