/* ============================================================
   CrIAcao Digital - Nova Home
   home.css - estilos exclusivos da home. Depende de tokens.css
   e criacao-ds.css. Carregue depois dos dois.
   ============================================================ */

/* ---------------- SKIP LINK ---------------- */
.skip-link {
    position: absolute;
    top: -100%;
    left: 1rem;
    z-index: 100;
    padding: .75rem 1.25rem;
    background: var(--cd-azul-600);
    color: var(--cd-prata-100);
    border-radius: var(--cd-r-tag);
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    transition: top var(--cd-dur-fast) ease;
}
.skip-link:focus {
    top: 1rem;
}

/* ---------------- NAVBAR — variante glass sobre o vídeo do hero ----------------
   O DS deixa #navbar transparente até rolar (rgba(8,9,11,0)). Sobre o vídeo do
   hero isso reprova contraste dos links — a casca precisa existir desde o topo. */
#navbar {
    background: rgba(8, 9, 11, .45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom-color: rgba(244, 246, 248, .08);
}
#navbar.is-scrolled {
    background: var(--cd-carbono-950);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}

/* ---------------- HERO — vídeo full-screen ----------------
   Quatro camadas absolutas empilhadas dentro de #topo (.sec já dá
   position:relative + overflow:hidden): vídeo · overlay de contraste ·
   grid + halo · conteúdo. O vídeo cobre a dobra inteira; a moeda já vem
   menor e deslocada para a direita dentro do próprio frame, então o terço
   esquerdo é fundo quase vazio — é onde a headline se apoia.
   #heroDisco é o wrapper e o alvo do GSAP existente (transform/opacity);
   nenhuma regra aqui toca essas duas propriedades — home.js (fase 7) só
   escreve filter. */
.hero-video {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--cd-grad-carbono);
}
.hero-video video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* overlay de contraste — denso à esquerda (onde o texto vive), transparente
   à direita (onde a moeda respira); quatro paradas evitam a faixa de
   transição dura no meio da tela. Vinheta inferior de 30% de altura
   empilhada na mesma camada, servindo às métricas e ao rodapé da dobra. */
.hero-video-overlay {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(to top, var(--cd-carbono-950) 0%, transparent 30%),
        linear-gradient(90deg,
            rgba(8, 9, 11, .92) 0%,
            rgba(8, 9, 11, .72) 30%,
            rgba(8, 9, 11, .38) 58%,
            rgba(8, 9, 11, .15) 100%);
}
/* abaixo de 768px não há espaço para o vídeo respirar e o texto ser
   legível ao mesmo tempo — o texto ganha, overlay uniforme. */
@media (max-width: 767px) {
    .hero-video-overlay {
        background:
            linear-gradient(to top, var(--cd-carbono-950) 0%, transparent 30%),
            rgba(8, 9, 11, .72);
    }
}
.hero-video-grid {
    position: absolute;
    inset: 0;
}

/* enquadramento do vídeo — nunca `center`: a moeda fica à direita do
   frame, então qualquer proporção mais alta que 16:9 cortaria o assunto
   igualmente dos dois lados. Ancorar de 72% a 80% joga o corte para o
   lado esquerdo, que é fundo vazio e já está sob a parte densa do overlay. */
.hero-video video { object-position: 72% center; }         /* ≥1280px */
@media (max-width: 1279px) {
    .hero-video video { object-position: 76% center; }     /* 1024–1279px */
}
@media (max-width: 1023px) {
    .hero-video video { object-position: 80% center; }     /* 768–1023px */
}
@media (max-width: 767px) {
    .hero-video video { object-position: 78% center; }     /* <768px */
}
/* halo azul sobre a moeda — nó separado de #heroDisco: o mousemove do DS
   escreve transform aqui, nunca no wrapper do vídeo. */
.hero-video-halo {
    position: absolute;
    top: 50%;
    right: 8%;
    width: 34vw;
    height: 34vw;
    max-width: 520px;
    max-height: 520px;
    transform: translateY(-50%);
    border-radius: 50%;
    background: radial-gradient(circle, rgba(42, 168, 255, .42) 0%, rgba(10, 111, 209, .12) 46%, transparent 72%);
    filter: blur(32px);
    animation: glowPulse 5s ease-in-out infinite;
    pointer-events: none;
}

/* CTA secundário sobre vídeo — a borda padrão do .btn-ghost (sublinhado
   azul fino) some sobre imagem em movimento; aqui ele vira contorno cheio
   em prata claro, do mesmo tamanho do CTA primário ao lado. */
#heroTexto .btn-ghost {
    color: var(--cd-prata-100);
    border: 1px solid rgba(244, 246, 248, .28);
    border-radius: var(--cd-r-pill);
    /* o padding dos dois CTAs do hero é definido junto, em `#heroTexto .btn`
       (seção da headline abaixo) — aqui só a casca. */
}
#heroTexto .btn-ghost:hover {
    border-color: rgba(244, 246, 248, .5);
    color: #FFFFFF;
}

/* réguas verticais entre métricas visíveis — a métrica "3 dias" nasce
   com [hidden] e não deve deixar buraco nem divisor órfão. */
#heroMetricas > [data-metrica]:not([hidden]) ~ [data-metrica]:not([hidden]) {
    border-left: 1px solid rgba(244, 246, 248, .18);
    padding-left: 2rem;
}
/* abaixo de 768px as métricas empilham (medido: lado a lado a partir de
   767px, empilhadas daí pra baixo) e a régua vertical fica pendurada
   à esquerda da segunda, sem nada pra separar — o próprio `gap` já faz
   o trabalho quando elas estão uma sobre a outra. */
@media (max-width: 767px) {
    #heroMetricas > [data-metrica]:not([hidden]) ~ [data-metrica]:not([hidden]) {
        border-left: none;
        padding-left: 0;
    }
}

/* palavra em destaque no H1 — "o número que importa é azul" (regra do DS,
   §1 do plano). Cor sólida (não metal-bright) + brilho suave: o único
   ponto do texto que não depende do overlay pra se destacar do vídeo. */
#heroTexto h1 .text-azul-400 {
    text-shadow: 0 0 28px rgba(42, 168, 255, .55);
}

/* ---------- HERO: escala tipográfica da headline ----------
   As duas frases são curtas ("O dinheiro entra. Mas não sobra." e
   "Descubra o problema antes que o mês acabe."), então o corpo pode
   crescer bem acima do `.t-h1` de antes (30–46px, calibrado para a
   headline longa de quatro linhas) sem a dobra estourar uma tela.

   As duas escalam pelo mesmo `vw`, então a proporção entre elas é
   constante em qualquer largura (~1,6:1): o H1 sempre maior, mas só um
   degrau — as duas frases precisam ler como um bloco só, não como
   título e legenda. O que separa uma da outra é peso (600 do `.t-h1`
   contra 500 do `.t-h3`) e cor (gradiente metálico contra prata-300
   chapado), não um salto de corpo. */
.hero-h1 {
    font-size: clamp(34px, 5.2vw, 68px);
    /* respiro curto de propósito: o H2 é continuação da frase, não um
       segundo bloco. O espaço grande fica embaixo do H2, separando a
       headline dos CTAs. */
    margin-bottom: clamp(8px, 1vw, 14px);
}

.hero-h2 {
    font-size: clamp(21px, 3.2vw, 42px);
    line-height: 1.14;
    margin-bottom: clamp(24px, 3vw, 40px);
}

/* CTAs do hero um degrau acima do `.btn` padrão — sob uma headline de
   68px, os 14px/15px do DS ficavam órfãos. Os dois botões sobem juntos
   (o ghost tem casca própria, ver regra acima) pra continuarem do mesmo
   tamanho lado a lado. Só no hero: o resto da página segue o DS.
   **Só a partir de 768px:** em 360px o rótulo mais longo ("Quero o
   diagnóstico da minha planilha") passa a quebrar em duas linhas com
   15px/30px, o que engorda o botão em ~26px e empurra a dobra pra fora
   de uma tela. No mobile o tamanho do DS já é proporcional à headline
   de 34px. */
@media (min-width: 768px) {
    #heroTexto .btn {
        font-size: 15px;
        padding: 17px 30px;
    }
}

/* no mobile a moeda está quase toda cortada e o overlay é uniforme, então
   o alinhamento óptico com o centro dela (que é o motivo do padding
   simétrico no desktop) deixa de valer o custo em altura. */
@media (max-width: 767px) {
    #topo {
        padding-top: 5rem;
        padding-bottom: 2.5rem;
    }
}

/* controle de pausa de vídeo (WCAG 2.2.2) — casca compartilhada pelo vídeo
   do hero e pelo vídeo da dobra 2 (planilha). .btn-icone do DS não tem
   fundo definido; aqui ele precisa ler sobre vídeo em movimento mesmo
   onde o overlay/fundo já é fraco. Posição fica em classe própria de
   cada instância, logo abaixo — o vidro é o que se repete. */
.video-controle {
    background: rgba(8, 9, 11, .55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(244, 246, 248, .18);
    color: var(--cd-prata-100);
    font-size: 20px;
}
.video-controle:hover {
    background: rgba(8, 9, 11, .75);
    border-color: rgba(244, 246, 248, .32);
}
.hero-video-controle {
    position: absolute;
    bottom: 24px;
    right: 24px;
    z-index: 20;
}
/* o card da dobra 2 é bem menor que a dobra do hero — 16px em vez de 24px. */
.planilha-controle {
    position: absolute;
    bottom: 16px;
    right: 16px;
    z-index: 2;
}

/* ---------------- ORBS — limite extra no mobile ----------------
   O DS já reduz o blur dos orbs pra 48px abaixo de 1024px
   (criacao-ds.css §16). `filter: blur()` num elemento de dezenas de vw
   ainda é caro em GPU de celular — abaixo de 767px o raio cai mais uma
   vez. Só home.css: index.html carrega só o DS e não é afetado. */
@media (max-width: 767px) {
    .orb { filter: blur(28px); }
}

/* ============================================================
   SEÇÃO 2 — RECONHECIMENTO (a planilha)
   ============================================================ */

/* virada em .card-rule fora de um .card: o crescimento no hover do
   componente original não se aplica (nada aqui é hover-alvo), então a
   barra nasce cheia — único tratamento gráfico da seção. */
#reconhecimento .card-rule > i {
    width: 100%;
}

/* card de vídeo da planilha — `.media-card` do DS pinta `var(--cd-grad-carbono)`
   por padrão (feito pra dobra escura da Vitrine); aqui a dobra é clara e um
   retângulo escuro piscando até o vídeo decodificar é pior que o vazio. */
.media-card--claro {
    background: var(--cd-prata-100);
    border: 1px solid var(--cd-prata-300);
    box-shadow: 0 24px 48px -30px rgba(22, 24, 28, .3);
}
/* .media-card do DS só dimensiona `img` — o vídeo precisa da própria regra. */
.media-card video {
    width: 100%;
    height: auto;
    display: block;
}

.planilha-mock {
    position: absolute;
    inset: 0;
    z-index: 4;
    --pilha-rot: 3deg;
    background: var(--cd-carbono-800);
    border: 1px solid rgba(244, 246, 248, .07);
    border-radius: var(--cd-r-card);
    padding: 1rem 1rem 1.1rem;
    box-shadow: 0 30px 60px -32px rgba(22, 24, 28, .5);
    display: flex;
    flex-direction: column;
}
.planilha-mock-topo {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    letter-spacing: .03em;
    color: var(--cd-prata-300);
    padding-bottom: .7rem;
    margin-bottom: .7rem;
    border-bottom: 1px solid rgba(244, 246, 248, .08);
}
.planilha-mock-topo iconify-icon { font-size: 15px; color: var(--cd-prata-500); }
.planilha-mock-grade {
    display: grid;
    grid-template-columns: 26px repeat(4, 1fr);
    gap: 1px;
    background: rgba(244, 246, 248, .07);
    font-family: 'JetBrains Mono', monospace;
}
.planilha-mock-grade > span {
    background: var(--cd-carbono-800);
    padding: 7px 8px;
    font-size: 11px;
    color: var(--cd-prata-300);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.planilha-mock-grade > .pm-canto,
.planilha-mock-grade > .pm-col,
.planilha-mock-grade > .pm-lin {
    color: var(--cd-prata-500);
    text-align: center;
    font-weight: 500;
}
.planilha-mock-grade > .pm-erro { color: var(--cd-erro); }
.planilha-mock-grade > .pm-formula { color: var(--cd-prata-500); font-size: 10px; }
.planilha-mock-grade > .pm-destaque {
    position: relative;
    overflow: visible;
    color: var(--cd-prata-100);
    box-shadow: inset 0 0 0 1.5px var(--cd-azul-400);
    border-radius: 3px;
}
.planilha-mock-abas {
    display: flex;
    gap: 2px;
    margin-top: .7rem;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 88%, transparent 100%);
    mask-image: linear-gradient(90deg, #000 0%, #000 88%, transparent 100%);
}
.planilha-mock-abas::-webkit-scrollbar { display: none; }
.planilha-mock-abas span { flex: none; }
.planilha-mock-abas span {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    padding: 5px 8px;
    background: var(--cd-carbono-900);
    color: var(--cd-prata-500);
    border-radius: 4px 4px 0 0;
    white-space: nowrap;
}
.planilha-mock-abas span.is-ativa { background: var(--cd-carbono-700); color: var(--cd-prata-200); }

/* O `.sr-only` vem do Tailwind, que é CDN — sem rede ele some e as
   descrições só para leitor de tela viram texto corrido no meio da
   página. Redeclarado aqui para não depender da rede. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* Emenda 2 → 3 (claro → escuro). Não usa o `.seam-up` do DS por dois
   motivos: ele termina em carbono-950 (esta dobra é carbono-900) e seu
   gradiente corre `to bottom`, pintando o escuro sobre a seção clara em
   vez de dissolver o claro no escuro. Aqui a cor entra de baixo. */
/* satura em 50% — é onde cai a fronteira (o bloco tem -mt-20/-mb-20, metade
   sobre cada dobra) e a partir dali a própria seção 3 pinta por cima. Sem o
   stop, o fade chegaria só à metade da cor antes de a seção assumir. */
.seam-vao { background: linear-gradient(to bottom, transparent 0%, var(--cd-carbono-900) 50%); }

/* ============================================================
   SEÇÃO 3 — O VÃO: DA DOR AO SISTEMA
   Dobra escura (carbono-900). A faixa conta uma transformação em três
   estados — operação fragmentada → convergência → uma única tela — em
   vez de mostrar território. O que se vende é o percurso, não a tela.
   ============================================================ */

/* as cinco dores, em fila. Casca neutra: são categorias, não acento. */
.vao-dores {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin: 1.75rem 0 0;
    padding: 0;
    list-style: none;
}
.vao-dores li {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--cd-prata-300);
    padding: 8px 16px;
    border-radius: var(--cd-r-pill);
    background: rgba(244, 246, 248, .05);
    box-shadow: inset 0 0 0 1px rgba(244, 246, 248, .12);
}

.vao {
    display: grid;
    grid-template-columns: 40fr 20fr 40fr;
    align-items: stretch;
    margin: 3.5rem 0 0;
}
.vao-estado {
    position: relative;
    min-height: 420px;
    padding: 1.5rem 0;
}
.vao-etapa {
    position: absolute;
    top: 0;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .16em;
    text-transform: uppercase;
    /* prata-500 daria 3.92:1 sobre carbono-900 — reprova num texto de 10px.
       Sobre escuro o prata-400 é o tom correto (6.96:1); a proibição do
       README a esse token vale para fundo claro. */
    color: var(--cd-prata-400);
}
.vao-estado--limpo .vao-etapa { right: 0; }

/* ---- estado 1: a operação fragmentada ---- */
/* mesma caixa que os nós, para as coordenadas do viewBox baterem com os
   `top`/`left` em % dos chips — qualquer inset aqui desalinha os fios */
.vao-fios {
    position: absolute;
    inset: 0;
    /* width/height explícitos: só `inset: 0` não dimensiona um SVG — sem
       eles ele assume o aspect-ratio 1:1 do viewBox, fica mais alto que a
       caixa e os fios descolam dos chips */
    width: 100%;
    height: 100%;
}
.vao-fios path {
    fill: none;
    stroke: var(--cd-prata-500);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    opacity: .5;
}
.vao-no {
    position: absolute;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    letter-spacing: .06em;
    white-space: nowrap;
    color: var(--cd-prata-400);
    background: var(--cd-carbono-950);
    padding: 7px 11px;
    border-radius: var(--cd-r-tag);
    box-shadow: inset 0 0 0 1px rgba(244, 246, 248, .14);
}
.vao-no--1 { top:  8%; left:  2%; transform: rotate(-2.5deg); }
.vao-no--2 { top: 21%; left: 54%; transform: rotate(2deg); }
.vao-no--3 { top: 37%; left:  7%; transform: rotate(1.5deg); }
.vao-no--4 { top: 51%; left: 58%; transform: rotate(-2deg); }
.vao-no--5 { top: 64%; left:  4%; transform: rotate(2.5deg); }

/* a pergunta sem resposta — primeiro dos dois únicos momentos de azul */
.vao-dor {
    position: absolute;
    left: 0;
    right: 1.5rem;
    bottom: .5rem;
    padding: 14px 18px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 13px;
    color: var(--cd-azul-400);
    background: rgba(10, 111, 209, .1);
    border-radius: var(--cd-r-field);
    box-shadow: inset 0 0 0 1px rgba(42, 168, 255, .35);
}

/* ---- estado 2: a convergência ---- */
.vao-estado--funil {
    min-height: auto;
    display: grid;
    place-items: center;
    padding: 0;
}
.vao-convergencia { width: 100%; height: 100%; }
.vao-convergencia path {
    fill: none;
    stroke: var(--cd-prata-500);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    opacity: .45;
}
/* Sólido, sem traço progressivo: com `preserveAspectRatio="none"` o
   stroke-dasharray é medido no espaço já distorcido e sai recortado no
   meio do caminho, mesmo com pathLength. As curvas prata ao redor já
   dizem "convergência" — o fio azul só marca o eixo. */
.vao-convergencia .vao-fio-azul {
    stroke: var(--cd-azul-400);
    opacity: .85;
}

/* ---- estado 3: a única tela ---- */
.vao-estado--limpo {
    display: flex;
    padding-top: 2.5rem;
}
.vao-tela {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 2rem;
    background: var(--cd-carbono-950);
    border-radius: var(--cd-r-card);
    box-shadow:
        inset 0 0 0 1px rgba(244, 246, 248, .1),
        0 30px 60px -40px rgba(0, 0, 0, .9);
}
.vao-tela-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--cd-prata-400);
}
/* segundo e último momento de azul da faixa */
.vao-tela-valor {
    font-family: 'Space Grotesk', sans-serif;
    font-size: clamp(48px, 5vw, 64px);
    font-weight: 600;
    line-height: 1;
    color: var(--cd-azul-400);
    margin: .5rem 0 1.75rem;
}
.vao-tela-linhas { margin: 0; }
.vao-tela-linhas > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 12px 0;
    border-top: 1px solid rgba(244, 246, 248, .1);
}
.vao-tela-linhas dt {
    font-size: 13px;
    color: var(--cd-prata-400);
}
.vao-tela-linhas dd {
    margin: 0;
    font-family: 'JetBrains Mono', monospace;
    font-size: 13px;
    color: var(--cd-prata-200);
}

.vao-destaque {
    max-width: 42ch;
    margin: 3.5rem 0 0;
    padding-left: 1.5rem;
    border-left: 3px solid var(--cd-azul-600);
}

/* Resolução da esquerda para a direita (A7): a tela final nasce sem foco
   e ganha nitidez quando a faixa entra em tela — o percurso é o argumento,
   então a animação resolve o resultado, não a transição.
   O blur é condicionado ao `.js-pronto` que o home.js aplica: quem é dono
   de tirar o blur é o mesmo código que o põe, então um home.js que não
   rode deixa a tela nítida em vez de borrada para sempre. Nunca
   `opacity: 0` — o conteúdo não pode depender de animação para existir. */
.vao.js-pronto .vao-estado--limpo { filter: blur(7px); }
@keyframes vaoResolve {
    from { filter: blur(7px); }
    to   { filter: blur(0); }
}
.vao.js-pronto.is-focado .vao-estado--limpo {
    animation: vaoResolve 1s var(--cd-ease) .45s both;
}
/* mesma especificidade da regra do blur — uma media query não a eleva */
@media (prefers-reduced-motion: reduce) {
    .vao.js-pronto .vao-estado--limpo { filter: none; }
}

@media (max-width: 1023px) {
    /* o eixo gira: o funil deixa de separar colunas e passa a ligar
       linhas, girado 90° dentro de uma caixa quadrada. */
    .vao { grid-template-columns: 1fr; }
    .vao-estado--funil { min-height: 96px; }
    .vao-convergencia {
        width: 96px;
        height: 96px;
        transform: rotate(90deg);
    }
    .vao-estado--limpo { padding-top: 3rem; }
    /* o recuo à direita existia para a pergunta não encostar no funil da
       coluna vizinha; sem colunas vizinhas ele só deixa a caixa torta */
    .vao-dor { right: 0; }
}
@media (max-width: 767px) {
    /* só o caos — `.vao-estado` genérico aqui alcançaria o funil e
       reabriria os 380px de vazio que a regra de 1023px acabou de fechar */
    .vao-estado--caos { min-height: 380px; }
    .vao-no { font-size: 9px; padding: 6px 9px; }
    .vao-dor { font-size: 12px; }
    .vao-tela { padding: 1.5rem; }
}

/* ============================================================
   SEÇÃO 4 — PROVA REAL (Calculadora de Granel)
   ============================================================ */
.prova-intro {
    /* largura ditada pela headline: a 52px, "no fim do mês é tarde demais."
       precisa disto para cair em duas linhas em vez de três. O parágrafo
       abaixo tem largura própria, bem menor. */
    max-width: 820px;
    margin: 0 auto;
    text-align: center;
}
/* o único acento cromático da dobra. `.metal-bright` no h2 pinta o texto
   com `background-clip: text` + `color: transparent`; uma cor explícita
   aqui sobrepõe isso só neste trecho. */
.prova-tarde { color: var(--cd-azul-400); }

/* larga o bastante para cada uma das duas frases caber inteira numa linha —
   o <br> entre elas é que define a quebra, não o acaso da largura */
.prova-resumo {
    max-width: 68ch;
    margin: 1.75rem auto 0;
}
.prova-numeros {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(1.5rem, 5vw, 3.5rem);
    margin-top: 3rem;
}
.prova-num {
    font-family: 'Space Grotesk', sans-serif;
    font-size: clamp(38px, 4.5vw, 52px);
    font-weight: 600;
    line-height: 1;
}
.prova-seta {
    font-size: 26px;
    line-height: 1;
    color: var(--cd-prata-400);
    flex: none;
}
/* fecha a composição centralizada: sem isto o botão fica encostado à
   esquerda depois de todo o bloco de texto centralizado acima */
.prova-cta { text-align: center; }
/* cor explícita: `.t-h4` não define nenhuma, e sem isto o texto herda o
   carbono do body e some sobre o fundo escuro da dobra */
.prova-virada {
    margin-top: 3rem;
    color: var(--cd-prata-100);
}

/* A altura é a entrada, não a largura. `--prova-media-h` trava o celular
   e os dois prints na MESMA altura; cada largura passa a ser consequência
   da proporção. O grid de 12 colunas antigo fazia o contrário — 610px de
   largura no print 01 (proporção 0,598) davam ~1020px de altura, o "print
   que foge da seção". No teto de 580px a fileira (≈324 + 347 + 345 + gaps)
   sobra folga na caixa de 1240px e fica centrada. */
.prova-telas {
    /* o celular é o protagonista da dobra: ele manda na altura... */
    --prova-media-h: clamp(460px, 66vh, 680px);
    /* ...e os cards do carrossel entram como prova secundária, a ~3/4 dele.
       A diferença de tamanho é o que cria a hierarquia. */
    --prova-print-h: calc(var(--prova-media-h) * .76);
    display: flex;
    flex-wrap: wrap;
    align-items: center;   /* prints centrados contra o celular mais alto */
    justify-content: center;
    gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* ---- moldura de celular (exclusiva desta dobra; ainda NÃO é componente
   do DS — promover pra criacao-ds.css/design-system é trabalho à parte).
   Casca em carbono, fio de luz na borda e sombra profunda: o mesmo idioma
   de .media-card--claro e .planilha-mock. O raio grande (não o --cd-r-card
   de 26px) é o que faz ler como aparelho. ---- */
.cd-fone { display: flex; flex-direction: column; align-items: center; margin: 0; flex: none; }
.cd-fone-vidro {
    position: relative;
    height: var(--prova-media-h);
    padding: 14px 10px;
    background: linear-gradient(160deg, #2A2E34 0%, #101216 60%, #1A1D22 100%);
    border: 1px solid rgba(244, 246, 248, .14);
    border-radius: 44px;
    box-shadow:
        0 40px 80px -36px rgba(8, 9, 11, .8),
        inset 0 0 0 2px rgba(8, 9, 11, .6),
        inset 0 1px 1px rgba(244, 246, 248, .06);
}
/* fresta do alto-falante no bezel de cima — sem notch sobre a tela, que
   cobriria o vídeo. */
.cd-fone-alto-falante {
    position: absolute;
    top: 6px; left: 50%;
    transform: translateX(-50%);
    width: 46px; height: 4px;
    border-radius: 999px;
    background: rgba(244, 246, 248, .16);
}
/* a tela recorta o vídeo no raio interno e ancora play + controles nativos.
   `aspect-ratio: 9/16` casa moldura e vídeo antes mesmo de decodificar
   (poster e vídeo são 1080×1920). */
.cd-fone-tela {
    position: relative;
    height: 100%;
    aspect-ratio: 9 / 16;
    border-radius: 32px;
    overflow: hidden;
    background: var(--cd-carbono-950);
}
/* `contain`, não `cover`: dentro do celular tela e vídeo são ambos 9:16,
   então não há corte de um jeito nem de outro — mas no FULLSCREEN o vídeo
   ocupa a tela deitada do monitor, e `cover` esticaria o 9:16 até cobri-la,
   cortando topo e base (o "zoom"). `contain` mostra o vídeo vertical
   inteiro, com barras finas nas laterais. */
.cd-fone-video { display: block; width: 100%; height: 100%; object-fit: contain; }
/* Em tela cheia: reforça o `contain` (alguns motores redefinem object-fit
   ao entrar em fullscreen) e pinta o fundo de preto, pra faixa lateral do
   9:16 numa tela deitada não vazar o carbono da página.
   Medido aqui: NÃO adiantou reservar espaço embaixo com padding. A barra
   de controles do Chrome se ancora na caixa de CONTEÚDO do vídeo, então o
   padding sobe o vídeo e a barra junto — a legenda queimada na borda
   inferior continua na mesma posição relativa, e o vídeo só fica menor.
   Com os controles recolhidos (o padrão durante a reprodução) o quadro
   inteiro aparece, legenda inclusive. */
.cd-fone-video:fullscreen,
.cd-fone-video:-webkit-full-screen {
    /* vw/vh, NUNCA %. Em tela cheia o `height: 100%` da regra acima resolve
       contra o bloco contentor mais próximo — e o `.reveal-up` do DS deixa
       transform/filter no <figure> ancestral, que vira exatamente isso em
       alguns motores. O elemento então fica MAIS ALTO que a janela (medido a
       partir do print do usuário: caixa de ~1426×917 numa tela de 1426×770),
       o quadro transborda embaixo e a leitura é de "zoom cortado". Unidade de
       viewport não depende de ancestral nenhum. O max-* trava o caso oposto. */
    width: 100vw;
    height: 100vh;
    max-width: 100vw;
    max-height: 100vh;
    object-fit: contain;
    object-position: center;
    background: #000;
}
/* play sobre o poster — mesmo vidro do .video-controle, porém maior e
   centralizado; some quando o vídeo começa (.is-tocando no figure). */
.cd-fone-play {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 72px; height: 72px;
    display: grid; place-items: center;
    border-radius: 50%;
    cursor: pointer;
    font-size: 30px;
    padding-left: 4px;               /* óptico: o triângulo pesa à esquerda */
    color: var(--cd-prata-100);
    background: rgba(8, 9, 11, .55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(244, 246, 248, .22);
    box-shadow: 0 8px 24px -8px rgba(8, 9, 11, .7);
    transition: background .24s var(--cd-ease-io), border-color .24s var(--cd-ease-io),
                transform .24s var(--cd-ease-io), opacity .24s ease;
}
.cd-fone-play:hover {
    background: var(--cd-azul-600);
    border-color: rgba(244, 246, 248, .4);
    transform: translate(-50%, -50%) scale(1.06);
}
.cd-fone.is-tocando .cd-fone-play {
    opacity: 0; pointer-events: none;
    transform: translate(-50%, -50%) scale(.85);
}

/* ---- os dois prints, na mesma altura do celular ---- */
/* ---- carrossel coverflow ----
   Ocupa toda a largura que sobra ao lado do celular (`flex: 1`), que é o que
   resolve o vazio da dobra. `min-width: 0` é obrigatório: sem ele um filho
   flex se recusa a encolher abaixo do conteúdo e empurraria a fileira. */
.prova-carrossel {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    align-self: center;
    height: var(--prova-print-h);
}
/* O palco é o referencial de todos os cards, que são absolutos e partem do
   mesmo ponto central — o deslocamento lateral é só transform, por isso a
   troca é barata (nada de reflow) e anima suave. */
.prova-palco {
    position: absolute;
    inset: 0;
    perspective: 1400px;
}
.prova-slide {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: 0;
    height: 100%;
    aspect-ratio: 502 / 839;      /* a família ≈0,598 dos cinco prints */
    border-radius: 28px;
    overflow: hidden;
    background: var(--cd-carbono-900);
    border: 1px solid rgba(244, 246, 248, .12);
    box-shadow: 0 30px 60px -30px rgba(8, 9, 11, .85);
    cursor: pointer;
    /* `transform` e `opacity` só: as duas propriedades que o compositor
       resolve sem repintar. Uma transição em `width`/`left` engasgaria. */
    transition: transform .8s var(--cd-ease), opacity .8s var(--cd-ease),
                box-shadow .8s var(--cd-ease);
    will-change: transform;
}
.prova-slide img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }

/* Véu escuro em vez de opacidade. Os cinco prints são telas claras e muito
   parecidas entre si: baixar a opacidade os transformava num borrão cinza,
   um por cima do outro. O véu deixa cada card NÍTIDO e apenas o afunda no
   carbono da dobra — a profundidade vem da escala e da sombra, não de
   apagar a imagem. */
.prova-slide::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    background: var(--cd-carbono-950);
    opacity: .66;
    transition: opacity .8s var(--cd-ease);
    pointer-events: none;
}

/* O fan. `--passo` é a distância entre um card e o vizinho; mudar só esta
   linha reaperta ou abre o leque inteiro. */
.prova-palco { --passo: 52%; }
.prova-slide[data-pos="0"] {
    transform: translate(-50%, -50%) scale(1);
    z-index: 5;
    /* o card da frente é o único que ganha o azul da marca na borda */
    border-color: rgba(42, 168, 255, .3);
    box-shadow: 0 44px 90px -32px rgba(8, 9, 11, .95);
}
.prova-slide[data-pos="0"]::after { opacity: 0; }

.prova-slide[data-pos="1"],
.prova-slide[data-pos="-1"] { z-index: 4; }
.prova-slide[data-pos="1"]  { transform: translate(calc(-50% + var(--passo)), -50%) scale(.79); }
.prova-slide[data-pos="-1"] { transform: translate(calc(-50% - var(--passo)), -50%) scale(.79); }
.prova-slide[data-pos="1"]::after,
.prova-slide[data-pos="-1"]::after { opacity: .38; }

.prova-slide[data-pos="2"],
.prova-slide[data-pos="-2"] { z-index: 3; }
.prova-slide[data-pos="2"]  { transform: translate(calc(-50% + var(--passo) * 1.62), -50%) scale(.61); }
.prova-slide[data-pos="-2"] { transform: translate(calc(-50% - var(--passo) * 1.62), -50%) scale(.61); }
.prova-slide[data-pos="2"]::after,
.prova-slide[data-pos="-2"]::after { opacity: .68; }

/* qualquer card fora da janela de ±2 fica escondido atrás do central */
.prova-slide[data-pos="fora"] {
    transform: translate(-50%, -50%) scale(.55);
    z-index: 1; opacity: 0; pointer-events: none;
}

.prova-carrossel-pausa {
    position: absolute;
    right: 0;
    bottom: -10px;
    z-index: 6;
    width: 38px;
    height: 38px;
    font-size: 16px;
    display: grid;
    place-items: center;
    cursor: pointer;
}

/* tablet: encolhe a altura antes de empilhar (a proporção 0,76 entre
   celular e cards vem junto, porque --prova-print-h é derivado) */
@media (max-width: 1023px) {
    .prova-telas { --prova-media-h: clamp(400px, 52vw, 560px); }
    /* menos espaço lateral: o leque fecha um pouco pra caber */
    .prova-palco { --passo: 45%; }
}
/* celular: empilha (aparelho em cima, carrossel embaixo) e volta a ser
   dirigido pela largura numa coluna só — mais robusto que forçar altura. */
@media (max-width: 720px) {
    .prova-telas { flex-direction: column; align-items: center; }
    .cd-fone-vidro { height: auto; width: min(80vw, 330px); }
    .cd-fone-tela { height: auto; width: 100%; }
    .prova-carrossel { width: 100%; flex: none; height: min(58vh, 62vw); }
    /* no estreito, os vizinhos entram mais por baixo pra não vazar a tela */
    .prova-palco { --passo: 46%; }
    .prova-carrossel-pausa { right: 50%; transform: translateX(50%); bottom: -18px; }
}
/* respeita a preferência: sem transições nem passagem automática (o
   home.js também não liga o timer quando `reduz` é verdadeiro) */
@media (prefers-reduced-motion: reduce) {
    .prova-slide { transition: none; }
    .cd-fone-play { transition: none; }
}

/* .btn-ghost padrão pinta o texto em azul-600 — medido, isso dá ~4:1
   contra carbono-950, abaixo do 4.5:1 de AA pra texto normal. Mesma
   correção já aplicada no CTA secundário do hero: casca em prata claro
   em vez de depender só da cor do texto. */
#prova .btn-ghost {
    color: var(--cd-prata-100);
    border: 1px solid rgba(244, 246, 248, .28);
    border-radius: var(--cd-r-pill);
    padding: 15px 28px;
}
#prova .btn-ghost:hover {
    border-color: rgba(244, 246, 248, .5);
    color: #FFFFFF;
}

@media (max-width: 767px) {
    /* devolve largura às duas colunas; em 390px os rótulos ainda caem em
       duas linhas, então `balance` reparte as palavras em vez de deixar
       "todo dia" partido ao meio. Onde não houver suporte, quebra normal. */
    .prova-numeros { gap: 1rem; }
    .prova-seta { font-size: 20px; }
    .prova-numeros .t-caption { text-wrap: balance; }
}

/* ============================================================
   SEÇÃO 5 — O QUE A GENTE CONSTRÓI
   Sequência de foco (A8, home.js): a faixa entra com `.reveal-zoom` (o
   próprio preset do DS já entrega opacidade+escala+blur — a "montagem"
   pedida não precisa de keyframe novo). Depois de todos visíveis, o
   observador dedicado do home.js dá a vez a um card por vez: ele ganha
   `data-estado="ativo"`, sua microanimação roda, e ele assenta em
   `.is-resolvido` — permanente — antes de passar a vez adiante.
   ============================================================ */
.modulo-sistema .t-label { font-weight: 600; }
.modulo-dado { padding-top: 1.25rem; margin-top: 1.25rem; border-top: 1px solid var(--cd-prata-300); }

/* trilho de progresso reaproveitado do catálogo (README: ".card-rule"),
   não um selo novo — a linha que preenche já É o vocabulário do DS pra
   "isto avançou". Fica sob o rótulo `// 0X`, acima do título. */
.modulo-rule { margin: .85rem 0 1.1rem; }

/* transform/opacity/box-shadow/border-color do card já herdam a
   transição de 1s do `.reveal-zoom` (a classe permanece no elemento
   depois da entrada) — não redeclaro `transition` aqui de propósito:
   fazer isso trocaria também o tempo da entrada, que deve continuar
   lenta e deliberada. */
#construimos .modulo-sistema {
    border-color: var(--cd-prata-300);
}
#construimos .modulo-sistema::after {
    /* pulso de ativação — mesma técnica radial do `.flashlight-card::before`
       (que seleciona a mão), aqui disparado pelo estado, não pelo mouse.
       `::before` já pertence à lanterna; este é o segundo slot do card. */
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    background: radial-gradient(480px circle at 20% 15%, rgba(42, 168, 255, .16), transparent 60%);
    opacity: 0;
    pointer-events: none;
}

/* estado RESOLVIDO — já processou; fica marcado, sem check literal.
   Declarado ANTES do estado ATIVO de propósito: as duas regras de
   `border-color` empatam em especificidade (mesma contagem de id +
   classe + atributo/classe), e no fluxo real do JS um card só carrega
   `.is-resolvido` depois que `data-estado="ativo"` já foi removido — mas
   se algum dia coexistirem por um frame, quero que ATIVO vença, e em
   empate quem vem depois no arquivo é quem decide a cascata. */
#construimos .modulo-sistema.is-resolvido {
    border-color: rgba(10, 111, 209, .18);
}
#construimos .modulo-sistema.is-resolvido .modulo-rule > i { width: 100%; }
#construimos .modulo-sistema.is-resolvido .t-label { color: var(--cd-azul-600); }

/* estado ATIVO — é a vez deste card */
#construimos .modulo-sistema[data-estado="ativo"] {
    transform: translateY(-4px) scale(1.012);
    border-color: rgba(10, 111, 209, .4);
    box-shadow: 0 30px 60px -34px rgba(22, 24, 28, .55), 0 0 0 1px rgba(42, 168, 255, .14);
}
#construimos .modulo-sistema[data-estado="ativo"]::after { opacity: 1; transition: opacity .5s var(--cd-ease); }
#construimos .modulo-sistema[data-estado="ativo"] .modulo-rule > i { width: 100%; }

/* enquanto outro card processa, os três de fora recuam — nunca some,
   só perde presença, e volta ao normal assim que ninguém mais está ativo */
#construimosSequencia[data-foco] .modulo-sistema:not([data-estado="ativo"]) {
    opacity: .82;
}

/* ---- estado "aguardando o JS": só existe com `.sequencia-pronta`, que
   home.js aplica ANTES de tudo. Sem JS o container nunca ganha essa
   classe e cada mini-gráfico continua no visual sempre-pronto original
   (barras respirando, barra de progresso nos 78%) — os `data-estado`/
   `.is-resolvido` acima são inertes por si só (só JS os define), mas o
   "neutro antes da vez chegar" precisa deste portão à parte. ---- */
#construimosSequencia.sequencia-pronta .bar-set > span { animation: none; transform: scaleY(.25); }
/* :not(ativo):not(resolvido), não a classe/atributo isolados — se o
   seletor cobrisse também os dois estados finais, ganharia deles na
   cascata (mais específico: id+classe do container > id+atributo do
   card) e a barra travaria em 0% depois de resolvida */
#construimosSequencia.sequencia-pronta .modulo-sistema:not([data-estado="ativo"]):not(.is-resolvido) .modulo-progresso > i { width: 0; }

/* card 01 — custo sobe primeiro, margem entra depois de assentar */
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--custo > span { animation: barGrow .5s var(--cd-ease) both; }
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--custo > span:nth-child(2) { animation-delay: .08s; }
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--custo > span:nth-child(3) { animation-delay: .16s; }
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--margem > span { animation: barGrow .5s var(--cd-ease) both; animation-delay: .5s; }
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--margem > span:nth-child(2) { animation-delay: .58s; }
#construimos .modulo-sistema[data-estado="ativo"] .bar-set--margem > span:nth-child(3) { animation-delay: .66s; }
#construimos .modulo-sistema.is-resolvido .bar-set > span { animation: none; transform: scaleY(1); }

/* card 02 — os três pontos "acendem" em fila; só o 1º ("em estoque") é
   `.dot-live` de verdade (pulso contínuo, já existia). 2º/3º nunca
   pulsam sozinhos — a suspensão do glowPulse é permanente, não presa
   ao portão do JS, porque é a identidade visual deles, não um estado
   de espera. O aceso soma-se ao pulso via múltiplas animações. */
#construimos [data-status="2"], #construimos [data-status="3"] { animation: none; }
@keyframes moduloPontoAcende {
    0% { opacity: .35; transform: scale(.55); }
    55% { opacity: 1; transform: scale(1.4); }
    100% { opacity: 1; transform: scale(1); }
}
#construimos .modulo-sistema[data-estado="ativo"] [data-status="1"] { animation: moduloPontoAcende .45s var(--cd-ease) both, glowPulse 2.2s ease-in-out .45s infinite; }
#construimos .modulo-sistema[data-estado="ativo"] [data-status="2"] { animation: moduloPontoAcende .45s var(--cd-ease) .18s both; }
#construimos .modulo-sistema[data-estado="ativo"] [data-status="3"] { animation: moduloPontoAcende .45s var(--cd-ease) .36s both; }

/* card 03 — a pílula "pop" quando o valor termina de ser processado.
   Puro CSS, sem classe do JS: o atraso de .65s casa com o último degrau
   do valor (o JS escreve em 150/300/450/600ms — ver home.js) sem que os
   dois precisem se coordenar em tempo de execução. */
@keyframes moduloBadgePop {
    0% { opacity: 0; transform: scale(.7); }
    65% { opacity: 1; transform: scale(1.08); }
    100% { opacity: 1; transform: scale(1); }
}
#construimos .modulo-sistema[data-estado="ativo"] #moduloOrcamentoBadge { animation: moduloBadgePop .4s var(--cd-ease) .65s both; }

/* card 04 — a barra some as costas do número, que o JS conta em degraus */
#construimos .modulo-progresso > i { width: var(--meta); transition: width 1.05s var(--cd-ease); }

@media (max-width: 480px) {
    .modulo-dado { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    /* redundante com o bloco global (que já zera toda `transition-duration`),
       mas explícito: nada nesta seção deve depender do relógio da fila. */
    #construimos .modulo-sistema[data-estado="ativo"] { transform: none; }
    #construimosSequencia[data-foco] .modulo-sistema:not([data-estado="ativo"]) { opacity: 1; }
}

/* o `.btn-ghost` padrão do DS (10px/8px de padding, pensado pra link
   inline) mede ~38px de alvo de toque aqui — abaixo dos 44px mínimos.
   #heroTexto e #prova já corrigem isso com casca própria (ver acima);
   este é o terceiro e único ghost da home sem essa correção. */
#construimos .btn-ghost { min-height: 44px; }

/* ============================================================
   SEÇÃO 6 — MÉTODO CrIAção
   A dobra que argumenta sendo ordenada — sem orbs, sem sweep (ver o
   comentário na marcação da seção). A sequência de foco (A13, home.js)
   é deliberadamente mais discreta que a da §5: aqui não há foco/recuo
   entre irmãos, só uma procissão — o traço avança um segmento, o passo
   seguinte assenta no seu visual definitivo, sem brilho de destaque.
   ============================================================ */

/* a ênfase da fórmula completa — glow curto, sem exagero. Dispara em
   `.active` (o mesmo `.reveal-up` que já revela o fragmento), com atraso
   grande o bastante pra só começar depois que a transição de entrada
   (delay-700 + --cd-dur-slow ≈ 1.9s) já tiver terminado. */
@keyframes metodoFormulaGlow {
    0%, 100% { text-shadow: none; }
    50% { text-shadow: 0 0 18px rgba(42, 168, 255, .45); }
}
.metodo-formula-final.active { animation: metodoFormulaGlow 1s var(--cd-ease) 2s both; }

.metodo-etapas { position: relative; margin-top: 3rem; }
.metodo-traco {
    display: none;
    position: absolute;
    top: 22px;
    left: 22px;
    right: 22px;
    height: 4px;
    width: calc(100% - 44px);
    overflow: visible;
}
.metodo-traco path { stroke-dasharray: 1; }
/* substitui a antiga animação de um passo só (`homeTraceDraw`, que
   ficou órfã — não há mais nenhum outro traço na página usando-a,
   removida). `--progresso` é escrito pelo home.js a cada passo que
   avança. Fora do portão `.metodo-pronto`, o traço fica sempre completo
   (seguro sem JS); só sob o portão o fallback vira 0 (vazio) — sem essa
   distinção, o traço apareceria cheio por um instante e encolheria de
   volta a 25% assim que a sequência de fato começasse a escrever
   `--progresso`, num piscar visível antes de redesenhar. */
#metodoTracoPath { stroke-dashoffset: 0; transition: stroke-dashoffset .7s var(--cd-ease); }
.metodo-etapas.metodo-pronto #metodoTracoPath { stroke-dashoffset: calc(1 - var(--progresso, 0)); }
/* o brilho final (A13, node 4): a linha inteira ganha um traço azul
   muito discreto por cima, só depois que a fila termina — não um
   destaque, um "assentar". */
.metodo-traco-glow {
    stroke-dashoffset: 0;
    opacity: 0;
    transition: opacity 1.1s var(--cd-ease);
}
.metodo-etapas.metodo-completo .metodo-traco-glow { opacity: .3; }
@media (min-width: 768px) {
    .metodo-traco { display: block; }
}

.etapa-marca {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 13px;
    font-weight: 600;
    color: var(--cd-carbono-700);
    transition: transform .4s var(--cd-ease), opacity .4s var(--cd-ease);
}
/* identidade de cada etapa — contorno tracejado → sólido → preenchido →
   azul. Permanente, nunca um estado de espera: mesmo sem JS, é isto que
   aparece desde o primeiro frame. */
/* as marcas 01 e 02 nasciam quase sem corpo sobre o prata-200 desta
   seção (contorno fino + preenchimento a 12%): a progressão
   contorno→sólido continua, mas com peso suficiente pra se separar do
   fundo. Superfície branca em vez de transparente dá a mesma leitura
   de "ainda vazio" sem desaparecer. */
.etapa-metodo--1 .etapa-marca { border: 1.5px dashed var(--cd-carbono-700); background: rgba(255, 255, 255, .55); }
.etapa-metodo--2 .etapa-marca { border: 1.5px solid var(--cd-carbono-700); background: rgba(69, 75, 84, .22); }
.etapa-metodo--3 .etapa-marca { border: 1.5px solid var(--cd-carbono-700); background: var(--cd-carbono-700); color: var(--cd-prata-100); }
.etapa-metodo--4 .etapa-marca { border: 1.5px solid var(--cd-azul-600); background: var(--cd-carbono-800); color: var(--cd-prata-100); box-shadow: 0 0 0 4px rgba(10, 111, 209, .14); }
.etapa-metodo--4 .etapa-marca .dot-live { position: absolute; top: -3px; right: -3px; }

/* ---- portão do JS (mesmo papel do `.sequencia-pronta` da §5): só sob
   esta classe o texto nasce neutro/esperando. Sem JS, título e parágrafo
   ficam visíveis desde o load — nunca escondidos por um script que não
   rodou. A marca também nasce discreta (menor, mais clara), sem tocar
   nas quatro regras de identidade acima. ---- */
.metodo-etapas.metodo-pronto .etapa-metodo h3,
.metodo-etapas.metodo-pronto .etapa-metodo p {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(6px);
    transition: opacity .8s var(--cd-ease), transform .8s var(--cd-ease), filter .8s var(--cd-ease);
}
.metodo-etapas.metodo-pronto .etapa-metodo p { transition-delay: .25s; }
.metodo-etapas.metodo-pronto .etapa-marca { opacity: .5; transform: scale(.82); }

/* estado RESOLVIDO — antes do ATIVO no arquivo por especificidade
   empatada (mesma lógica da §5: em empate, quem vem depois vence, e
   quero ATIVO por cima caso os dois coexistam por um instante). */
.metodo-etapas.metodo-pronto .etapa-metodo.is-resolvido h3,
.metodo-etapas.metodo-pronto .etapa-metodo.is-resolvido p {
    opacity: 1; transform: none; filter: none;
}
.metodo-etapas.metodo-pronto .etapa-metodo.is-resolvido .etapa-marca { opacity: 1; transform: scale(1); }

/* estado ATIVO — o traço acabou de chegar neste passo */
.metodo-etapas.metodo-pronto .etapa-metodo[data-estado="ativo"] h3,
.metodo-etapas.metodo-pronto .etapa-metodo[data-estado="ativo"] p {
    opacity: 1; transform: none; filter: none;
}
.metodo-etapas.metodo-pronto .etapa-metodo[data-estado="ativo"] .etapa-marca {
    opacity: 1;
    animation: metodoMarcaPop .5s var(--cd-ease) both;
}
@keyframes metodoMarcaPop {
    0% { transform: scale(.82); }
    55% { transform: scale(1.12); }
    100% { transform: scale(1); }
}

/* toque único da etapa 03 — "construção progressiva": o parágrafo se
   revela da esquerda pra direita, como algo sendo montado, em vez do
   fade comum dos outros três. É a única personalidade bespoke da fila:
   dar uma a cada uma das quatro seria repetir o mesmo truque quatro
   vezes (a §5 já fez isso); aqui só a mais literal ganha corpo.
   Dispara só em ATIVO — quando `data-estado` é removido ao resolver, a
   animação deixa de estar atribuída e `clip-path` some por completo (sem
   regra própria pra ele fora da animação), o que já deixa o texto
   totalmente visível: não preciso de uma segunda regra pra ".is-resolvido"
   segurar o resultado, e evito o parágrafo "revelar" duas vezes. */
.metodo-etapas.metodo-pronto .etapa-metodo--3[data-estado="ativo"] .metodo-texto-constroi {
    animation: metodoConstroi .7s var(--cd-ease) .15s both;
}
@keyframes metodoConstroi {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

@media (max-width: 767px) {
    .metodo-etapas .grid { position: relative; }
    /* mesma variável `--progresso` do traço horizontal do desktop — sem
       isso a versão mobile ficaria com uma linha de fundo sempre
       completa, alheia à fila que o home.js está de fato conduzindo.
       Mesmo par de regras/fallback do `#metodoTracoPath`: fora do
       portão, altura sempre completa (seguro sem JS); só sob
       `.metodo-pronto` o fallback vira 0. */
    .metodo-etapas .grid::before {
        content: "";
        position: absolute;
        left: 21px;
        top: 22px;
        height: calc(100% - 44px);
        width: 2px;
        background: var(--cd-carbono-700);
        opacity: .25;
        transition: height .7s var(--cd-ease);
    }
    .metodo-etapas.metodo-pronto .grid::before {
        height: calc((100% - 44px) * var(--progresso, 0));
    }
    /* nó à esquerda, conteúdo à direita — grid em vez de reestruturar o
       HTML: a marca ocupa as duas linhas (número + parágrafo), título e
       texto ficam na segunda coluna. A progressão contorno→sólido dos
       nós continua legível porque a coluna 1 nunca muda de lugar. */
    .etapa-metodo {
        display: grid;
        grid-template-columns: 44px 1fr;
        column-gap: 1.25rem;
        align-items: start;
    }
    .etapa-metodo .etapa-marca { grid-column: 1; grid-row: 1 / 3; }
    .etapa-metodo h3 { grid-column: 2; grid-row: 1; margin-top: 0; }
    .etapa-metodo p { grid-column: 2; grid-row: 2; }
}

/* ============================================================
   SEÇÃO 7 — ANTES E DEPOIS
   ============================================================ */
.tabela-antes-depois { width: 100%; border-collapse: collapse; }
.tabela-antes-depois thead th {
    text-align: left;
    padding: 0 20px 16px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--cd-prata-400);
    border-bottom: 1px solid rgba(244, 246, 248, .12);
    font-weight: 500;
}
.tabela-antes-depois .th-seta { width: 60px; }
.tabela-antes-depois td { padding: 22px 20px; vertical-align: middle; }
.tabela-antes-depois tbody tr + tr td { border-top: 1px solid rgba(244, 246, 248, .08); }
/* Antes: carbono-700 é uma cor pensada pra texto sobre fundo claro (a
   dobra 2 usa ela assim) — nesta dobra escura ela ficaria a ~2.3:1,
   bem abaixo de AA. prata-400 é o equivalente "apagado" que o próprio
   DS reserva pra fundo escuro (regra 2 do DS: só não entra sobre
   claro). Desvio do rascunho do plano, que citava carbono-700 aqui. */
.td-antes {
    color: var(--cd-prata-400);
    background: rgba(0, 0, 0, .16);
}
.td-antes strong { color: var(--cd-prata-200); font-weight: 600; }
.td-depois {
    color: var(--cd-prata-100);
    border-left: 2px solid var(--cd-azul-600);
    padding-left: 24px;
}
.td-depois strong { font-weight: 600; }
.td-seta { text-align: center; color: var(--cd-prata-500); font-size: 20px; }
.td-seta iconify-icon { transition: color .3s var(--cd-ease), text-shadow .3s var(--cd-ease); }
.ad-txt { display: block; }

/* ---- ANTES→DEPOIS: transformação linha a linha ----
   Nunca anima o `<td>` em si — `clip-path`/`transform` em cima de
   `display:table-cell` é inconsistente entre engines e mexe com o
   layout da tabela. Todo efeito mira o `<span class="ad-txt">` de
   dentro, ou (na seta) o `<iconify-icon>`; a célula continua neutra. */

/* trilho central + ponto que viaja: mede em px (home.js), não em
   fração — as quatro linhas quebram em alturas diferentes, e uma
   fração igual (25/50/75/100%) desalinharia do centro real da linha
   assim que ANTES e DEPOIS quebrassem de jeitos distintos. Só existe
   no desktop: no mobile o DEPOIS já ganha `border-top` azul por linha
   (media query abaixo), não há coluna central pra esse trilho ocupar. */
.ad-shell { position: relative; }
.ad-trilha {
    display: none;
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--ad-left, 50%);
    width: 2px;
    transform: translateX(-50%);
    background: linear-gradient(to bottom, transparent, rgba(10, 111, 209, .28), transparent);
    pointer-events: none;
}
.ad-dot {
    display: none;
    position: absolute;
    top: var(--ad-top, 0px);
    left: var(--ad-left, 50%);
    width: 8px;
    height: 8px;
    margin: -4px 0 0 -4px;
    border-radius: 50%;
    background: var(--cd-azul-400);
    box-shadow: 0 0 12px 2px rgba(42, 168, 255, .6);
    opacity: 0;
    transition: top .5s var(--cd-ease), opacity .3s var(--cd-ease);
    pointer-events: none;
    z-index: 2;
}
.ad-dot.ad-dot-ativo { opacity: 1; }
.ad-dot.ad-dot-pulso { animation: adDotPulso .3s var(--cd-ease); }
@keyframes adDotPulso {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.8); }
}

/* ---- portão do JS: DEPOIS nasce escondido só sob esta classe — sem
   ela (sem JS, ou IntersectionObserver ausente) a tabela real continua
   plenamente legível desde o primeiro frame, como sempre foi. ---- */
.tabela-antes-depois.ad-pronto .td-depois .ad-txt {
    opacity: 0;
    filter: blur(10px);
    transform: translateX(-10px) scaleX(1.04);
    transition: opacity .55s var(--cd-ease), filter .55s var(--cd-ease), transform .55s var(--cd-ease);
}
.tabela-antes-depois.ad-pronto .td-antes .ad-txt {
    transition: opacity .3s var(--cd-ease), filter .3s var(--cd-ease), transform .3s var(--cd-ease);
}

/* fase 1 — instabilidade: uma sacudida tipográfica curta e discreta,
   não um glitch. `letter-spacing` entra só na keyframe (retorna a
   `normal` antes do fim) — nunca fica um valor residual que mudaria a
   largura intrínseca da célula fora da janela da animação. */
.tabela-antes-depois.ad-pronto tr[data-fase="instavel"] .td-antes .ad-txt {
    animation: adInstavel .2s linear;
}
@keyframes adInstavel {
    0%, 100% { transform: translateX(0); text-shadow: none; }
    30% { transform: translateX(-2px); text-shadow: 2px 0 rgba(154, 163, 174, .35); }
    60% { transform: translateX(2px); text-shadow: -2px 0 rgba(154, 163, 174, .35); letter-spacing: .01em; }
}

/* fase 2 — condensação: o texto é "puxado" em direção à seta. `scaleX`
   no lugar de `letter-spacing` sustentado — comprimir por spacing
   mudaria a largura real do texto e sacudiria a coluna da tabela;
   `scaleX` é só compositor, não reflui nada. */
.tabela-antes-depois.ad-pronto tr[data-fase="condensando"] .td-antes .ad-txt,
.tabela-antes-depois.ad-pronto tr[data-fase="energia"] .td-antes .ad-txt {
    opacity: .45;
    filter: blur(3px);
    transform: translateX(10px) scaleX(.94);
}

/* fase 3 — energia: a seta acende e a régua azul daquela linha ganha
   brilho. O `scale()` da seta fica só no desktop (media query mais
   abaixo) — no mobile a seta já carrega `transform: rotate(90deg)`
   fixo, e uma keyframe que também escreve `transform` substituiria a
   rotação por um instante, virando a seta de lado. */
.tabela-antes-depois.ad-pronto tr[data-fase="energia"] .td-seta iconify-icon {
    color: var(--cd-azul-400);
    text-shadow: 0 0 14px rgba(42, 168, 255, .7);
}
.tabela-antes-depois.ad-pronto tr[data-fase="energia"] .td-depois,
.tabela-antes-depois.ad-pronto tr[data-fase="revelado"] .td-depois {
    border-left-color: var(--cd-azul-400);
    box-shadow: -2px 0 10px -2px rgba(42, 168, 255, .5);
    transition: border-left-color .3s var(--cd-ease), box-shadow .3s var(--cd-ease);
}

/* fase 4 — revelado / repouso: DEPOIS assenta sólido e ANTES volta ao
   normal. A diferença de nitidez é o argumento só durante o percurso —
   no repouso final os dois lados continuam 100% legíveis, nada de
   conteúdo preso num estado borrado (regra de acessibilidade do DS:
   nada essencial pode depender de um estado de animação pra aparecer). */
.tabela-antes-depois.ad-pronto tr[data-fase="revelado"] .td-antes .ad-txt,
.tabela-antes-depois.ad-pronto tr[data-fase="revelado"] .td-depois .ad-txt,
.tabela-antes-depois.ad-pronto tr.is-resolvido .td-antes .ad-txt,
.tabela-antes-depois.ad-pronto tr.is-resolvido .td-depois .ad-txt {
    opacity: 1;
    filter: none;
    transform: none;
}
.tabela-antes-depois.ad-pronto tr.is-resolvido .td-depois {
    border-left-color: var(--cd-azul-600);
    box-shadow: none;
}
.tabela-antes-depois.ad-pronto tr.is-resolvido .td-seta iconify-icon {
    color: var(--cd-azul-600);
}

@media (min-width: 768px) {
    /* o "acende" da seta ganha o pequeno impulso de escala aqui —
       fora do alcance do `transform: rotate(90deg)` do mobile. */
    .tabela-antes-depois.ad-pronto tr[data-fase="energia"] .td-seta iconify-icon {
        animation: adSetaAcende .35s var(--cd-ease);
    }
    @keyframes adSetaAcende {
        0% { transform: scale(1); }
        50% { transform: scale(1.35); }
        100% { transform: scale(1); }
    }
    .ad-trilha, .ad-dot { display: block; }
}

@media (max-width: 767px) {
    .tabela-antes-depois thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
    .tabela-antes-depois, .tabela-antes-depois tbody, .tabela-antes-depois tr, .tabela-antes-depois td {
        display: block;
        width: 100%;
    }
    .tabela-antes-depois tbody tr {
        margin-bottom: 24px;
        border: none !important;
    }
    .tabela-antes-depois tbody tr:last-child { margin-bottom: 0; }
    .tabela-antes-depois td { padding: 0; border: none !important; }
    .td-antes { padding: 18px 20px; margin-bottom: 2px; }
    .td-seta {
        padding: 10px 0;
        transform: rotate(90deg);
        font-size: 18px;
    }
    .td-depois { border-left: none; border-top: 2px solid var(--cd-azul-600); padding: 18px 20px 18px 24px; }
}

/* ============================================================
   SEÇÃO 8 — O QUE A GENTE NÃO FAZ
   Zero azul — é o único momento da página sem o acento (decisão do
   plano, reafirmada pelo usuário ao escrever esta animação: "manter
   zero azul" venceu a opção de um azul transitório no pulso/×). Toda
   pista de "sistema decidindo" vem de movimento e contraste, nunca de
   cor. Também não ganhou grid de fundo: a seção nunca teve `.sec-bg`
   (ausência de ornamento é o argumento de honestidade dela) — o "pulso
   que atravessa o grid" do brief original foi redirecionado pra baixo
   de cada item (ver `.recusa::after` abaixo), não construído sobre um
   fundo que a seção deliberadamente nunca teve.
   ============================================================ */
.recusa {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
    padding: 2.25rem 0;
    border-bottom: 1px solid rgba(244, 246, 248, .1);
    position: relative;
}
.recusa:first-child { padding-top: 0; }
/* ícone: era o glyph combinado `solar:close-circle-linear` (um único
   path dentro do shadow DOM do custom element do Iconify) — não dá pra
   desenhar as duas diagonais em sequência dentro de um path que já
   nasce fechado. Trocado por um SVG inline (mesma técnica
   `pathLength="1"` de §6/§7), pensado pra bater o mesmo peso visual do
   glyph antigo em repouso: círculo + X, 24px, prata-500, stroke 1.5. */
.recusa-icone {
    width: 24px;
    height: 24px;
    flex: none;
    margin-top: .2em;
    color: var(--cd-prata-500);
    overflow: visible;
}
.recusa-icone circle,
.recusa-icone line {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
}
.recusa-icone line { stroke-linecap: round; }
/* fora do portão (sem JS) o × já nasce completo — só existe traço
   parcial sob `.filtro-pronto`, nunca por padrão. */
.recusa-x { stroke-dasharray: 1px; stroke-dashoffset: 0; }

/* pulso redirecionado: uma régua que preenche da esquerda pra direita
   por cima da régua estática do `.recusa` (acima), e depois desaparece
   de novo — o repouso final é sempre a régua original, com ou sem JS,
   então nada de acessibilidade depende desse traço passageiro. */
.recusa::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 2px;
    background: var(--cd-prata-300);
    transform: scaleX(1);
    transform-origin: left;
    opacity: 0;
    pointer-events: none;
}

/* ---- portão do JS: sem ele (sem JS, ou reduced motion) os quatro
   itens já nascem no visual definitivo — ícone e texto plenamente
   visíveis, X completo, régua estática. ---- */
#naoFazemosGrid.filtro-pronto .recusa p,
#naoFazemosGrid.filtro-pronto .recusa .recusa-icone {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(6px);
    transition: opacity .5s var(--cd-ease), transform .5s var(--cd-ease), filter .5s var(--cd-ease);
}
#naoFazemosGrid.filtro-pronto .recusa .recusa-x {
    stroke-dashoffset: 1px;
    transition: stroke-dashoffset .13s linear;
}
#naoFazemosGrid.filtro-pronto .recusa::after {
    transform: scaleX(0);
    transition: transform .28s var(--cd-ease), opacity .28s var(--cd-ease);
}

/* fase 1 — neutro: o item chega como possibilidade, baixa presença,
   círculo visível, X ainda não existe (dasharray some, linhas em
   branco). */
#naoFazemosGrid.filtro-pronto .recusa[data-fase="neutro"] p,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="neutro"] .recusa-icone,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="decidindo"] p,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="decidindo"] .recusa-icone {
    opacity: .5;
    transform: none;
    filter: none;
}

/* fase 2 — decidindo: as duas diagonais desenham em sequência (~250ms,
   a mesma janela que o brief pediu) enquanto a régua embaixo preenche
   — o "pulso" e a formação do × acontecem juntos, não um depois do
   outro; é a leitura literal da própria tabela de tempo do brief
   (aparece → × construído, um intervalo só). */
/* o × precisa continuar desenhado depois que "decidindo" passa — sem
   repetir o valor em "definido"/`.is-resolvido`, a única regra que
   ainda bateria seria a do portão (`stroke-dashoffset: 1px`, ver
   acima) e o × sumiria de novo bem no instante em que o item termina
   (mesmo cuidado do traço da §6 e do trilho da §7: toda fase
   transitória precisa de uma âncora no estado de repouso). */
#naoFazemosGrid.filtro-pronto .recusa[data-fase="decidindo"] .recusa-x-1,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"] .recusa-x-1,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido .recusa-x-1 {
    stroke-dashoffset: 0;
}
#naoFazemosGrid.filtro-pronto .recusa[data-fase="decidindo"] .recusa-x-2,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"] .recusa-x-2,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido .recusa-x-2 {
    stroke-dashoffset: 0;
    transition-delay: .12s;
}
#naoFazemosGrid.filtro-pronto .recusa[data-fase="decidindo"]::after {
    transform: scaleX(1);
    opacity: 1;
}

/* fase 3 — definido / repouso: texto e ícone em contraste total, X
   permanece (mesmos valores de `.is-resolvido`, sem salto visual
   quando a classe troca pelo atributo). O brilho do × é neutro
   (`drop-shadow` branco-frio, nunca azul) e passageiro — a régua volta
   a opacity 0, sobra só a borda estática original por baixo. */
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"] p,
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"] .recusa-icone,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido p,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido .recusa-icone {
    opacity: 1;
    transform: none;
    filter: none;
}
/* sem `transition:` própria de propósito: declarar uma aqui (mesmo que
   só pra `filter`) venceria a cascata do `transition` (propriedade
   única, não cumulativa) e derrubaria silenciosamente a transição de
   `opacity`/`transform` herdada da regra do portão — o ícone saltaria
   direto pro estado final em vez de suavizar junto com o texto. O
   `filter .5s` do portão já cobre esta troca. */
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"] .recusa-icone,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido .recusa-icone {
    filter: drop-shadow(0 0 4px rgba(244, 246, 248, .4));
}
#naoFazemosGrid.filtro-pronto .recusa[data-fase="definido"]::after,
#naoFazemosGrid.filtro-pronto .recusa.is-resolvido::after {
    /* `transform` repetido de propósito: sem ele, ao sair de "decidindo"
       a régua perderia o `scaleX(1)` (a única regra que ainda bateria
       seria a do portão, `scaleX(0)`) e encolheria na hora — antes até
       de `opacity` começar a sumir, já que redeclarar `transition` aqui
       (só pra opacity) também derrubaria a transição de `transform` do
       portão, pelo mesmo motivo do ícone acima. Mantendo os dois
       valores explícitos, a régua desaparece esticada, só em opacity. */
    opacity: 0;
    transform: scaleX(1);
    transition: opacity .4s var(--cd-ease) .1s, transform .4s var(--cd-ease) .1s;
}

/* ============================================================
   SEÇÃO 9 — DEPOIS DA ENTREGA
   "Always On / System Care": a seção fica sticky/pinned enquanto o
   usuário rola, e o progresso do scroll — não um timer — decide qual
   dos cinco itens está ativo, com reversão ao rolar pra cima. Isso é
   estruturalmente diferente de toda animação anterior da home (§3-§8
   são todas "IntersectionObserver dispara uma vez, fila de
   setTimeout, para o frente só"): aqui não existe fila nem
   `.is-resolvido` — cada frame de scroll recalcula os cinco estados
   do zero a partir de `progresso` (0 a 1). Nenhuma regra de transição
   "só de ida" sobrevive a esse modelo.

   O pin é vanilla, não GSAP — a regra do projeto ("GSAP cuida só do
   paralaxe do hero, não estenda ScrollTrigger pra fora dele")
   continua valendo à risca: um listener de `scroll` que escreve uma
   custom property e um atributo não toca nenhuma propriedade que o
   GSAP já escreve em `#heroTexto`/`#heroDisco`. */

/* `.sec` (criacao-ds.css) tem `overflow: hidden` — necessário pra
   conter os orbs/sweep decorativos, mas isso quebra `position: sticky`
   em QUALQUER descendente (a regra vale pra ancestrais, não só o pai
   direto). Não dá pra mudar `.sec` global (9 outras seções dependem
   dela) — a troca fica isolada aqui, e só quando o pin de fato liga:
   sem JS/mobile/reduced-motion, `#pos-entrega` continua com o mesmo
   `overflow: hidden` de sempre, layout idêntico ao que já existia. */
#pos-entrega.pos-pin-ativo { overflow: visible; }

/* dono do `inset:0` do `.sec-bg` (substitui `.sec` nesse papel só
   aqui) — sem isto, o fundo decorativo tentaria se ancorar em
   `#pos-entrega`, que no modo pin fica alto (350vh) e esticaria o
   grid/orbs por toda essa altura em vez de ficar do tamanho da tela
   pinada. */
.pos-entrega-pin { position: relative; }
@media (min-width: 768px) {
    /* a altura extra é só o "trilho" que o scroll percorre enquanto o
       pin segura os 100vh na tela — 350vh = 100vh do pin + 250vh de
       percurso pras cinco etapas (~50vh cada, ritmo deliberado, sem
       arrastar). Gatilho: `.pos-pin-ativo`, escrito pelo home.js só
       quando o pin de fato vai rodar — herda o mesmo princípio do
       "spacer não existe sem JS" do resto da home. */
    #pos-entrega.pos-pin-ativo { height: 350vh; }
    .pos-pin-ativo .pos-entrega-pin {
        position: sticky;
        top: 0;
        height: 100vh;
        display: flex;
        align-items: center;
        overflow: hidden;
    }
    /* compacta o conteúdo pra caber inteiro nos 100vh do pin — o
       `py-24 md:py-32` da seção já não sobra espaço nenhum quando o
       card precisa caber junto com o eyebrow e o título na mesma
       tela. Só ativo sob o pin; a versão normal (sem JS/mobile)
       mantém o respiro original. */
    .pos-pin-ativo .card-glass { padding: 1.75rem 2.25rem; }
    .pos-pin-ativo #pos-entrega-titulo { margin-top: .5rem; }
    .pos-pin-ativo .pos-entrega-pin .card-glass { margin-top: 1.5rem; }
}

.pos-entrega-icone {
    font-size: 20px;
    flex: none;
    margin-top: .15em;
    color: var(--cd-prata-500);
    transition: color .25s var(--cd-ease), transform .25s var(--cd-ease), filter .25s var(--cd-ease);
}
.pos-entrega-nota {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--cd-prata-300);
}

/* ---- status: "○ AGUARDANDO ENTREGA" → "● SISTEMA NO AR" →
   "● SISTEMA ACOMPANHADO" → "● ALWAYS ON". Decorativo — restate o que
   a lista já diz, por isso `aria-hidden`, não `aria-live` (um live
   region disparando a cada rolagem seria ruído pro leitor de tela). */
.pos-entrega-status {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin-bottom: 1.5rem;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--cd-prata-500);
}
.pos-entrega-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
    border: 1.5px solid var(--cd-prata-400);
    background: transparent;
    transition: background .3s var(--cd-ease), border-color .3s var(--cd-ease), box-shadow .3s var(--cd-ease);
}
.pos-entrega-status[data-ligado="true"] .pos-entrega-status-dot {
    border-color: var(--cd-azul-400);
    background: var(--cd-azul-400);
    box-shadow: 0 0 10px 2px rgba(42, 168, 255, .5);
}
/* "No ar. Protegido. Acompanhado." — só existe no estado final de
   verdade (A16), não em "ligado" (que já vale desde a primeira etapa).
   Atributo próprio (`data-final`) de propósito — acoplar isso a
   `data-ligado` faria o texto aparecer assim que o primeiro item
   acendesse, bem cedo demais. Fica sempre no DOM (nada de textContent
   trocado às pressas) e some por opacity o resto do tempo. */
.pos-entrega-status-final {
    opacity: 0;
    font-style: italic;
    transition: opacity .4s var(--cd-ease);
}
.pos-entrega-status[data-final="true"] .pos-entrega-status-final { opacity: 1; }

/* ---- trilho + preenchimento: mesma ideia de §6/§7 (`--progresso`
   herdada de um ancestral comum), mas aqui a "linha" é só decoração —
   os cinco itens não mudam de altura durante o scroll (nada reflui),
   então não existe o problema de §7 de alturas desiguais; o valor de
   `--progresso` já vem calibrado pelas posições reais dos ícones
   (medidas uma vez pelo home.js), não por fração igual do índice. */
.pos-entrega-lista { position: relative; }
.pos-entrega-lista::before {
    content: "";
    position: absolute;
    left: 9px;
    top: 10px;
    bottom: 10px;
    width: 2px;
    background: var(--cd-prata-300);
}
.pos-entrega-lista::after {
    content: "";
    position: absolute;
    left: 9px;
    top: 10px;
    width: 2px;
    /* fallback 1 (não 0): sem `.pos-pronto` o home.js nunca escreve
       `--progresso` — o trilho precisa nascer cheio, coerente com os
       ícones/texto que também já nascem resolvidos sem JS. */
    height: calc((100% - 20px) * var(--progresso, 1));
    background: var(--cd-azul-400);
}

/* ---- os três estados de cada item: por vir (padrão) → ativo → já
   passou. Nada de `.is-resolvido` aqui — `data-estado` é reescrito do
   zero a cada tick de scroll (ver home.js), então cada regra precisa
   valer sozinha, sem depender de uma classe acumulada de execuções
   anteriores.

   Portão `.pos-pronto` (no `<ul>`): sem JS, sem IntersectionObserver,
   com reduced motion ou abaixo de 768px, o pin nunca liga e esta
   classe nunca chega a existir — os cinco itens ficam no visual final
   de sempre (ícone `prata-500`, texto 100%, exatamente como a versão
   estática desta seção sempre foi). O status (acima) usa o mesmo
   princípio: nasce com `data-ligado="true"` e o texto "Always on." no
   HTML — só o `home.js`, ao decidir rodar o pin, reescreve pra
   "Aguardando entrega" no ponto de partida. */
.pos-entrega-lista.pos-pronto [data-item] {
    transition: opacity .25s var(--cd-ease);
}
.pos-entrega-lista.pos-pronto [data-item] > span {
    transition: opacity .25s var(--cd-ease), color .25s var(--cd-ease);
}
/* por vir — de baixa presença, mas nunca ilegível (nada de opacidade
   que reprove contraste: é ênfase temporária, o item já existe por
   completo no DOM e chega a 100% assim que o scroll alcança ele). */
.pos-entrega-lista.pos-pronto [data-item] .pos-entrega-icone { color: var(--cd-prata-400); }
.pos-entrega-lista.pos-pronto [data-item] > span { opacity: .68; }

/* ativo — maior destaque: ícone acende em azul com leve glow e escala,
   texto em contraste total. */
.pos-entrega-lista.pos-pronto [data-item][data-estado="ativo"] .pos-entrega-icone {
    color: var(--cd-azul-400);
    transform: scale(1.14);
    filter: drop-shadow(0 0 6px rgba(42, 168, 255, .5));
}
.pos-entrega-lista.pos-pronto [data-item][data-estado="ativo"] > span { opacity: 1; }

/* concluído — assentado: ícone em carbono sólido (nem apagado, nem
   brilhando — "isso já está garantido"), texto em contraste total. */
.pos-entrega-lista.pos-pronto [data-item][data-estado="concluido"] .pos-entrega-icone { color: var(--cd-carbono-700); }
.pos-entrega-lista.pos-pronto [data-item][data-estado="concluido"] > span { opacity: 1; }

/* microanimações por função (A16) — um toque só, curto, disparado
   de novo toda vez que o item ENTRA em "ativo" (inclusive ao rolar de
   volta pra cima e cruzar a fronteira outra vez — é o comportamento
   certo pra algo scroll-scrubbed, não um efeito de "primeira vez").
   Nenhuma delas é um loop: `loading spinner` é exatamente o visual
   que o brief pediu pra evitar. */
@keyframes posEntregaGiraUmaVez { from { transform: scale(1.14) rotate(0deg); } to { transform: scale(1.14) rotate(360deg); } }
.pos-entrega-lista [data-item]:nth-child(2)[data-estado="ativo"] .pos-entrega-icone {
    animation: posEntregaGiraUmaVez .6s var(--cd-ease);
}
@keyframes posEntregaAcena { 0%, 100% { transform: scale(1.14) translateY(0); } 40% { transform: scale(1.14) translateY(-3px); } 70% { transform: scale(1.14) translateY(1px); } }
.pos-entrega-lista [data-item]:nth-child(3)[data-estado="ativo"] .pos-entrega-icone {
    animation: posEntregaAcena .5s var(--cd-ease);
}
@keyframes posEntregaSobe { from { transform: scale(1.14) translateY(3px); } to { transform: scale(1.14) translateY(0); } }
.pos-entrega-lista [data-item]:nth-child(4)[data-estado="ativo"] .pos-entrega-icone {
    animation: posEntregaSobe .4s var(--cd-ease);
}
@keyframes posEntregaEncaixa { from { transform: scale(1.14) rotate(0deg); } to { transform: scale(1.14) rotate(45deg); } }
.pos-entrega-lista [data-item]:nth-child(5)[data-estado="ativo"] .pos-entrega-icone {
    animation: posEntregaEncaixa .35s var(--cd-ease) both;
}
.pos-entrega-lista [data-item]:nth-child(5)[data-estado="concluido"] .pos-entrega-icone { transform: rotate(45deg); }

/* ============================================================
   SEÇÃO 10 — CTA FINAL
   "From Chaos to Clarity": diferente de §9, esta seção NÃO fica
   pinada — o brief pede sticky só "caso necessário", e aqui o custo
   seria real (o CTA é o momento de conversão da página; obrigar o
   visitante a rolar 2-3 telas depois de já ver o botão é fricção no
   pior lugar possível, e §11 — o formulário que o botão aponta — fica
   logo abaixo). A animação lê o progresso da seção cruzando a
   viewport (entra por baixo → assenta no topo), sem spacer, sem
   sticky, sem precisar mexer no `overflow` do `.sec` de novo.

   Reaproveita o `.cta-eco` que já existia (o eco quase invisível da
   planilha do hero/§2) em vez de criar fragmentos soltos — é a MESMA
   planilha ecoando, e trocar isso por spans espalhados perderia
   exatamente essa leitura ("isto é o que rolou lá em cima"). */
.btn-beam { display: inline-block; }
.cta-eco {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    /* --cta-eco-fade e --cta-eco-escala: sem JS (ou antes do primeiro
       tick de scroll) o eco fica exatamente como sempre foi —
       opacidade de repouso .08, sem encolher. */
    opacity: calc(.08 * var(--cta-eco-fade, 1));
    transform: scale(var(--cta-eco-escala, 1));
}
.cta-eco .planilha-mock {
    position: static;
    transform: rotate(-4deg) scale(1.25);
}
/* elementos de erro/duplicidade — primeiros a sumir (0-30% do
   progresso da seção): o nome de arquivo confuso no topo, o `#REF!` e
   as abas duplicadas. Fallback 1 (visível) sem JS, igual ao resto do
   eco — a leitura estática original não muda. */
.planilha-mock-topo,
.pm-erro,
.pm-duplicado {
    opacity: var(--cta-erro, 1);
}
/* a linha azul que atravessa as abas que sobraram (30-60%) — some
   sozinha quando `.cta-eco` inteiro apaga depois dos 60%, não precisa
   de regra própria pra isso (opacidade de ancestral já compõe). Sem
   JS não existe — `--cta-linha` nunca sai de 0. */
.planilha-mock-abas { position: relative; }
.planilha-mock-abas::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 1.5px;
    background: var(--cd-azul-400);
    opacity: .65;
    transform: scaleX(var(--cta-linha, 0));
    transform-origin: left;
}

/* ============================================================
   SEÇÃO 11 — RODAPÉ E FORMULÁRIO
   ============================================================ */
/* .field-label/.field-helper nascem em prata-500 (pensados pra viver
   dentro de um .card branco, como no index.html) — direto sobre o
   carbono-950 deste rodapé isso mede ~4.4:1, abaixo do 4.5:1 de AA.
   prata-300 (e azul-400 no foco) resolvem sem precisar embrulhar o
   formulário num card. */
#contato .field-label { color: var(--cd-prata-300); }
#contato .field-helper { color: var(--cd-prata-400); }
#contato .field:focus-within .field-label { color: var(--cd-azul-400); }

/* ---- os campos sobre fundo escuro ----
   O `.input` base é branco puro com texto carbono-900: foi desenhado
   pra viver dentro de um `.card` claro, e é assim que o index.html o
   documenta. Aqui ele caía direto sobre `carbono-950` — quatro lajes
   brancas cravadas no fundo quase preto, sem nenhuma relação com a
   linguagem de vidro/metal do resto da página. A regra base NÃO muda
   (o index.html depende dela); a troca é escopada em `#contato` e
   adota o vocabulário escuro que o DS já tem em `.motion-card`
   (criacao-ds.css): superfície translúcida + borda de 1px em luz
   baixa. Contrastes medidos (compondo a superfície translúcida sobre o
   carbono-950, o que dá rgb(16,18,21)): texto `prata-100` 17.32:1,
   placeholder `prata-400` 7.35:1, borda de foco `azul-400` 7.27:1 —
   os três passam (o mínimo é 4.5:1 pra texto e 3:1 pra borda). A
   ressalva do README sobre `prata-400` é pra fundo CLARO (lá ele dá
   2.36:1); sobre escuro ele é justamente o tom apagado do DS, e
   placeholder é o uso que a regra permite. */
#contato .input {
    font-size: 16px;
    background: rgba(22, 24, 28, .6);
    border-color: rgba(244, 246, 248, .12);
    color: var(--cd-prata-100);
    /* faz o popup nativo do <select> e o caret seguirem o tema escuro —
       sem isto o campo fica escuro e a lista de opções abre branca. */
    color-scheme: dark;
}
#contato .input::placeholder { color: var(--cd-prata-400); }
#contato .input:hover { border-color: rgba(244, 246, 248, .22); }
/* o anel de foco padrão é `rgba(42,168,255,.16)` — calibrado pra
   aparecer sobre branco. Sobre esta superfície escura ele some quase
   por completo, então sobe pra .28 e a borda também acende: foco de
   teclado tem que continuar inconfundível. */
#contato .input:focus {
    background: rgba(22, 24, 28, .85);
    border-color: var(--cd-azul-400);
    box-shadow: 0 0 0 4px rgba(42, 168, 255, .28);
}
/* seta própria no select — a nativa é desenhada pelo SO e não
   acompanha nem a cor nem o raio do resto do campo. */
#contato select.input {
    appearance: none;
    -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, var(--cd-prata-300) 50%),
                      linear-gradient(135deg, var(--cd-prata-300) 50%, transparent 50%);
    background-position: calc(100% - 22px) calc(50% + 2px), calc(100% - 16px) calc(50% + 2px);
    background-size: 6px 6px, 6px 6px;
    background-repeat: no-repeat;
    padding-right: 44px;
}

/* Cheguei a montar aqui um traço `scaleX` sob o campo em foco (o
   idioma do `.nav-link::after`). Tirei depois de olhar: no campo em
   foco a borda inteira já acende em `azul-400` com o anel por fora, e
   uma barra azul por cima de uma borda que já está azul não aparece.
   O idioma do sublinhado serve pro link da navbar, que não tem borda
   nenhuma; aqui ele seria CSS sem efeito visível. */

/* o botão inerte (destino ainda é pendência — ver o comentário no
   HTML) deixa de ser uma barra azul da largura toda do formulário. */
#contato .form-contato button[type="button"] { align-self: flex-start; }

/* links do rodapé: a transição de cor já vinha por utilitário do
   Tailwind; aqui ganham também o sublinhado que cresce, o mesmo
   `.nav-link::after` que a navbar usa — é o idioma de link do DS. */
.rodape-secoes a {
    position: relative;
    color: var(--cd-prata-400);
    transition: color var(--cd-dur-fast) ease;
}
.rodape-secoes a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -3px;
    height: 1px;
    background: var(--cd-grad-azul);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--cd-dur) var(--cd-ease);
}
.rodape-secoes a:hover { color: var(--cd-prata-100); }
.rodape-secoes a:hover::after { transform: scaleX(1); }

/* Entrada em cascata dos cinco links. Sem observer novo e sem uma
   décima responsabilidade no home.js: os itens pegam carona no
   `.active` que o observador compartilhado do DS já põe no bloco pai
   (`.reveal-up delay-300`). Não usei `.reveal` nos próprios `<li>` de
   propósito — reveal dentro de reveal multiplica as duas opacidades e
   o resultado fica embolado; aqui o pai já terminou de entrar quando
   os itens começam. */
.rodape-institucional .rodape-secoes li {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity var(--cd-dur) var(--cd-ease), transform var(--cd-dur) var(--cd-ease);
}
.rodape-institucional.active .rodape-secoes li { opacity: 1; transform: none; }
.rodape-institucional.active .rodape-secoes li:nth-child(1) { transition-delay: .45s; }
.rodape-institucional.active .rodape-secoes li:nth-child(2) { transition-delay: .52s; }
.rodape-institucional.active .rodape-secoes li:nth-child(3) { transition-delay: .59s; }
.rodape-institucional.active .rodape-secoes li:nth-child(4) { transition-delay: .66s; }
.rodape-institucional.active .rodape-secoes li:nth-child(5) { transition-delay: .73s; }

/* Nota honesta sobre o estado escondido: assim como o `.reveal` do
   próprio DS (criacao-ds.css:131), estes itens dependem do JS pôr
   `.active` — sem JS nenhum, ficam invisíveis. Não é um problema novo
   que estou introduzindo, é o contrato de reveal que a página inteira
   já segue; se um dia isso mudar, muda lá na base, não só aqui. Com
   `prefers-reduced-motion` não há risco: o criacao-ds.js marca tudo
   como ativo de imediato, e o bloco abaixo ainda tira o deslocamento. */
@media (prefers-reduced-motion: reduce) {
    .rodape-institucional .rodape-secoes li { opacity: 1; transform: none; transition: none; }
}

/* ---- marca d'água ----
   Era um `<span>` com `font-size: 15vw` e `white-space: nowrap`: a
   frase media 1703px numa caixa de 1590px, e o `overflow:hidden`
   cortava o "C" e o "l" das pontas — além dos descendentes do "ç" e do
   "g", que caíam fora da linha em `line-height:1`. Agora é um SVG com
   `viewBox` + `textLength`: a largura vira unidade de usuário, então o
   encaixe é exato em qualquer viewport e continua exato se a Space
   Grotesk não carregar. */
#contato .marca-dagua {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    pointer-events: none;
    user-select: none;
    opacity: .045;
}
#contato .marca-dagua svg {
    display: block;
    width: 100%;
    height: auto;
}
#contato .marca-dagua text {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 700;
    font-size: 116px;
    fill: var(--cd-prata-100);
}
