/* ═══════════════════════════════════════════════════════════════════════════
   tokens.css — fontes, cores, escala tipográfica, ritmo, movimento, geometria.

   REGRA DE ESPELHO: toda constante daqui que também existe em js/config.js está
   marcada com o nome do export. CSS não importa de JS, então main.js deve
   reescrever no :root as que variam em tempo de execução:

     --track-vh   <- config.TRACK_VH        (e o override ?track=)
     --beat-rise  <- config.BEAT_RISE
     --loader-bail<- config.LOAD_TIMEOUT_MS

   Os valores literais abaixo são o mesmo número que está no config hoje, para
   que a página fique correta mesmo antes do JS subir. Se um deles divergir do
   config, o config vence — reescreva aqui.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── Fontes auto-hospedadas ────────────────────────────────────────────────
   Caminhos relativos ao ARQUIVO CSS (css/), portanto ../assets/. Nunca /assets. */
@font-face {
  font-family: 'Poppins';
  src: url('../assets/fonts/Poppins-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/Inter-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/Inter-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ── Cor. Os nomes --vl-purple e --vl-lime são CONTRATO: os dois SVGs
     inlinados os consomem como var(--vl-purple, #4a007a) / var(--vl-lime,
     #cfff06). Renomear qualquer um dos dois descolore a marca. ──────────── */
  --vl-purple:        #4A007A;   /* palco */
  --vl-lime:          #CFFF06;   /* acento — SÓ dentro de bloco roxo */
  --vl-bg:            #F4F1EC;   /* off-white quente, base da camada de venda */
  --vl-ink:           #1A0A24;   /* quase-preto com viés roxo. Nunca preto neutro */
  --vl-card:          #FFFFFF;
  --vl-rule:          #E4DFD6;   /* divisória */

  --vl-ink-soft:      #3B2B45;   /* leitura corrida sobre off-white */
  --vl-ink-mute:      #5C4A66;   /* legenda */
  --vl-ink-faint:     #6B5A74;   /* nota, rodapé, marcação de origem */

  --vl-on-purple:     #FFFFFF;
  --vl-on-purple-soft: rgba(255, 255, 255, .72);
  --vl-on-purple-rule: rgba(255, 255, 255, .16);

  /* Barra translúcida: o off-white da marca com transparência, nunca cinza. */
  --vl-veil:          rgba(244, 241, 236, .82);

  /* ── Famílias ─────────────────────────────────────────────────────────── */
  --f-display: 'Poppins', 'Brandon Grotesque', system-ui, sans-serif;
  --f-body:    'Inter', system-ui, -apple-system, sans-serif;

  /* ── Escala tipográfica (DNA).
     tamanho / espaçamento entre letras / entrelinha, peso SEMPRE 500 nos
     títulos: a hierarquia vem de tamanho e cor, nunca de peso.
       96 / -1,5% / 1,05      64 / -0,9% / 1,06     48 / -0,3% / 1,10
       32 / +0,4% / 1,15      rótulo 21 / +1,1% / 1,20
       leitura 17 / -0,2% / 1,50   legenda 14 / -0,1% / 1,55
     O espaçamento entre letras cruza o zero perto de 50px: aperta em cima,
     abre embaixo. Os clamp() abaixo mantêm essa curva ao longo da largura. ── */
  --t-xl:      clamp(72px, 6.66vw, 96px);
  --t-lg:      clamp(48px, 4.44vw, 64px);
  --t-md:      clamp(36px, 3.33vw, 48px);
  --t-sm:      clamp(26px, 2.22vw, 32px);
  --t-label:   clamp(18px, 1.46vw, 21px);
  --t-lead:    20px;   /* leitura grande */
  --t-body:    17px;
  --t-caption: 14px;

  --tk-xl:      -.015em;
  --tk-lg:      -.009em;
  --tk-md:      -.003em;
  --tk-sm:       .004em;
  --tk-label:    .011em;
  --tk-body:    -.002em;
  --tk-caption: -.001em;

  --lh-xl: 1.05;
  --lh-lg: 1.06;
  --lh-md: 1.10;
  --lh-sm: 1.15;
  --lh-label: 1.20;
  --lh-body: 1.50;
  --lh-caption: 1.55;

  /* ── Espaço. Base 4px, tudo múltiplo dela (DNA). ──────────────────────── */
  --s-1:   4px;
  --s-2:   8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  20px;
  --s-6:  24px;
  --s-8:  32px;
  --s-10: 40px;
  --s-12: 48px;
  --s-16: 64px;
  --s-18: 72px;
  --s-20: 80px;
  --s-24: 96px;
  --s-32: 128px;
  --s-40: 160px;

  /* Alvo de toque mínimo, composto na própria escala de 4px do DNA
     (--s-10 + --s-1 = 44px). Um botão de barra com 31,6px de altura é metade
     de um polegar; esta é a régua, e ela vale em qualquer largura. */
  --tap-min: calc(var(--s-10) + var(--s-1));

  --raio: 8px;                       /* raio de canto do DNA */

  /* A primeira linha livre ACIMA da marcação de origem, medida e não estimada:
     a marcação fica em bottom 24px e mede 30px (12px de texto a 1.2 mais
     var(--s-2) em cima e embaixo). Somada a folga de var(--s-3), dá 66px.

     Existe como token porque DOIS elementos se penduram nela — o convite a
     descer no começo da rolagem e a saída de WhatsApp no fecho — e eles nunca
     podem discordar sobre onde a marcação começa. Cada um soma o
     env(safe-area-inset-bottom) no uso. */
  --faixa-origem: calc(24px + 30px + var(--s-3));

  /* A borda esquerda da coluna de leitura do palco. Nasceu inline em
     .stage__copy e ganhou nome quando a troca de looks passou a precisar da
     MESMA borda: duas cópias dessa expressão sairiam do lugar na primeira vez
     que alguém mexesse no contêiner. */
  --coluna-esq: max(
    env(safe-area-inset-left),
    calc((100vw - min(87.5vw, var(--container-max))) / 2)
  );
  --container-pct: 87.5%;
  --container-max: 1260px;
  --container-w: min(87.5vw, 1260px); /* espelho do acima, para usar em calc() */
  --leitura-max: 450px;               /* bloco de leitura nunca passa disso */
  --secao-y: var(--s-40);             /* 160 / 128 / 96 por faixa */

  /* ── Movimento. ASSINATURA ÚNICA — config.SIGNATURE + config.DURATION.
     Qualquer easing ou duração que não saia daqui é defeito. ────────────── */
  --ease-out:    cubic-bezier(0.215, 0.610, 0.355, 1.000);
  --ease-in:     cubic-bezier(0.550, 0.055, 0.675, 0.190);
  --ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1.000);
  --dur-quick:  180ms;
  --dur-base:   320ms;
  --dur-slow:   560ms;
  --dur-reveal: 900ms;

  /* ── Trilho e beats ───────────────────────────────────────────────────── */
  --track-vh: 620;      /* espelho de config.TRACK_VH — main.js reescreve */
  --beat-rise: 24px;    /* espelho de config.BEAT_RISE */

  /* ── Geometria do quadro. config.NATIVE, e é o ÚNICO par de dimensões que
     existe neste projeto: não há etapa de recorte e não há segundo formato.
     Qualquer outra dupla de medidas que apareça em algum lugar é defeito. ── */
  --native-w: 768;
  --native-h: 960;

  /* ── Lockup. config.NAV_MARK_H / NAV_WORD_H / NAV_GAP e as proporções dos
     viewBox (config.MARK_ASPECT / WORD_ASPECT). A caixa do slot é px fixo:
     é isso que impede o cabeçalho de refluir quando o voo assume. ───────── */
  --mark-aspect: calc(163.14 / 185.54);   /* 0.87927 */
  --word-aspect: calc(271.51 / 51.12);    /* 5.31123 */
  --nav-mark-h: 28px;
  --nav-word-h: 17.5px;
  --nav-gap:     9.6px;
  --nav-mark-w: calc(var(--nav-mark-h) * var(--mark-aspect));
  --nav-word-w: calc(var(--nav-word-h) * var(--word-aspect));
  --nav-slot-w: calc(var(--nav-mark-w) + var(--nav-gap) + var(--nav-word-w));
  --nav-pad-y: var(--s-5);
  --nav-h: calc(var(--nav-mark-h) + var(--nav-pad-y) * 2);   /* 68px */

  /* ── Palco ────────────────────────────────────────────────────────────── */
  --stage-gap: var(--s-18);
  /* Altura de referência do poço: min(86svh, 980px), com uma guarda a mais —
     o poço fica centralizado na vertical, então a folga de cima é metade do
     que sobra; limitar a 100svh menos duas alturas de barra garante que o topo
     do poço nunca entre por baixo da barra translúcida em telas baixas
     (1440x800, 1280x720). Em telas altas quem manda é o 86svh. */
  --well-h-cap: min(
    calc(86 * var(--vh-unit)),
    calc(100 * var(--vh-unit) - var(--nav-h) * 2),
    980px
  );
  /* O palco é composição travada em 100svh e a coluna de texto tem 450px: o
     título extra grande do DNA (96px) viraria cinco linhas nessa medida e
     encostaria na barra. O título da primeira dobra usa esta escala própria;
     os 96px do token --t-xl seguem valendo fora do trilho. */
  --t-stage-xl: clamp(44px, 4.9vw, 72px);
  /* O número do cartão roxo quando o beat `proof` precisa caber em menos
     espaço — por falta de largura (735-935) ou por falta de altura (tela
     baixa). Um valor só, para que os dois apertos sejam provavelmente o mesmo
     aperto; é o topo do clamp de --t-md, e não um degrau novo na escala. */
  --dado-beat-apertado: 48px;
  --copy-reserve: 420px;   /* piso reservado do bloco de beats: nenhum beat
                              reflui o layout quando o texto muda de tamanho */

  /* ── Loader ───────────────────────────────────────────────────────────── */
  --loader-p: 0;            /* 0..1, escrito por loader.js em #loader */

  /* Comprimento de cada traço do desenho, em unidades de usuário do viewBox
     163,14 x 185,54. MEDIDOS com getTotalLength() sobre exatamente os mesmos
     `d` que estão no index.html, e arredondados PARA CIMA para que o traço
     feche um fio antes de --loader-p chegar a 1 — nunca depois, que deixaria
     um dente por desenhar no quadro final:

       silhueta do V  643,596 -> 644
       losango        154,273 -> 155
       entalhe         81,274 ->  82

     A ponta da caneta anda --loader-len-total * --loader-p, então a divisão
     entre os três traços É a proporção dos comprimentos: velocidade constante,
     sem nenhum ponto de corte escolhido a gosto. Se o desenho mudar (e ele não
     deve), meça de novo. */
  --loader-len-v:       644;
  --loader-len-losango: 155;
  --loader-len-entalhe:  82;
  --loader-len-total: calc(
    var(--loader-len-v) + var(--loader-len-losango) + var(--loader-len-entalhe)
  );
  /* Altura do desenho. Os extremos são o espelho de config.MARK_H_MIN (56) e
     config.MARK_H_MAX (220) — a mesma faixa em que o símbolo pode viver. */
  --loader-mark-h: clamp(56px, 40vw, 220px);
  /* Espessura da caneta, em unidades de usuário: escala junto com o desenho. */
  --loader-stroke-w: 2.5;

  /* DELIBERADAMENTE MAIOR que config.LOAD_TIMEOUT_MS (12000), não igual.
     Quando os dois eram 12000 a animação loaderBail já estava rodando no exato
     quadro em que _fade() entrava; .is-done zera a animação e o Chrome não
     inicia transição quando a mudança de propriedade coincide com a remoção da
     animação que a controlava. Resultado medido: opacity 0.9232 -> 0 em um
     quadro, com visibility:hidden no mesmo quadro — corte seco justamente no
     caminho degradado que o usuário de conexão lenta vê. Este é o último
     recurso para JS travado, não um concorrente do caminho normal. */
  --loader-bail: 15000ms;

  /* ── Trilha de rolagem ────────────────────────────────────────────────────
     js/rail.js escreve --rail-p (0..1) em #scrubRail a cada tick. Não existe
     valor aqui de propósito: cada uso é var(--rail-p, 0), então tanto faz se o
     rail.js escrever no elemento ou no :root — uma declaração neste bloco
     sombrearia a herança e quebraria o segundo caso.

     A passagem marcada é a TROCA, e sai do config, não de números soltos:
     config.FRAME_MAP diz p 0,680 -> quadro 280 (a troca começa) e p 0,860 ->
     quadro 330 (a troca termina, e é também config.HANDOFF.start). O mesmo
     0,860 é onde a trilha começa a sumir, para não competir com o pouso. */
  --rail-marca-a: 0.680;
  --rail-marca-b: 0.860;
  --rail-w: 2px;
  --rail-cursor-h: var(--s-6);

  /* ── Camadas ──────────────────────────────────────────────────────────── */
  --z-poster: 1;
  --z-canvas: 2;
  /* A peça trocada, ACIMA do canvas e do vídeo (os dois em --z-canvas) e abaixo
     da marcação de origem. Existe como token porque errar este número não
     produz erro nenhum: a camada carrega, decodifica, anuncia e reporta
     opacidade 1 — e o canvas segue pintando por cima dela. Foi exatamente o que
     aconteceu quando ela nasceu em z 1, e só o olho pegou. */
  --z-troca: 3;
  --z-origem: 4;
  --z-rail:  40;   /* abaixo da barra de propósito: se um dia se cruzarem, a
                      barra ganha e a trilha some por baixo dela */
  /* A marcação de origem fica ENTRE o painel e a barra: acima de qualquer
     conteúdo que o painel carregue, abaixo do menu que continua navegável.
     É garantia de marca, então é a única coisa que o painel não pode cobrir. */
  --z-origem-fixa: 46;
  --z-painel: 45;  /* ACIMA do palco e da trilha, ABAIXO da barra: o menu tem
                      de continuar clicável com o painel aberto, senão o único
                      jeito de trocar de seção seria fechar e reabrir. */
  --z-nav:   50;
  /* O PROVADOR fica ACIMA DA BARRA, ao contrário do painel.
     A diferença não é gosto: o painel usa a barra como menu dele — é por ela
     que se troca de seção e é lá que mora o Fechar. O provador não; ele tem o
     próprio Fechar e a barra atrás dele fica INERTE de verdade. Uma barra
     visível e clicável por cima de um diálogo que declara ter o foco preso
     seria a mesma mentira que tirou o aria-modal do painel. */
  --z-provador: 60;
  --z-flight: 90;
  --z-loader: 100;
}

/* ── Unidade de altura de viewport ────────────────────────────────────────
   svh é constante durante o recolhimento da barra de URL do iOS; dvh não é, e
   é por isso que dvh está proibido aqui. Uma única chave, um único @supports:
   todo o resto do projeto usa calc(N * var(--vh-unit)). */
:root { --vh-unit: 1vh; }
@supports (height: 1svh) {
  :root { --vh-unit: 1svh; }
}

/* ── Faixas. 1069+ desktop · 735-1068 intermediária · 734- celular.
   735 é o espelho de config.TIER_BREAKPOINT e governa QUAL PASTA de quadros
   carrega; 734/1068 são os cortes de layout do DNA. ─────────────────────── */
@media (max-width: 1068px) {
  :root {
    --t-xl:    clamp(56px, 6.7vw, 72px);
    --t-lg:    clamp(40px, 4.5vw, 48px);
    --t-md:    clamp(32px, 3.4vw, 36px);
    --t-sm:    clamp(24px, 2.5vw, 26px);
    --t-label: clamp(17px, 1.7vw, 18px);
    --secao-y: var(--s-32);
    --stage-gap: var(--s-12);
    --copy-reserve: 340px;
  }
}

@media (max-width: 734px) {
  :root {
    /* O título extra grande cai para metade (DNA), e o espaçamento entre
       letras cruza o zero: aperta menos em cima, abre embaixo. */
    --t-xl:    clamp(38px, 12.2vw, 48px);
    --t-lg:    clamp(26px, 8.2vw, 32px);
    --t-md:    clamp(24px, 7.4vw, 28px);
    --t-sm:    clamp(21px, 5.6vw, 24px);
    --t-label: 15px;
    --t-body:  16px;
    --tk-xl:   -.003em;
    --tk-lg:    .004em;
    --tk-md:    .004em;
    --secao-y: var(--s-24);
    --nav-pad-y: var(--s-4);
    --nav-h: calc(var(--nav-mark-h) + var(--nav-pad-y) * 2);  /* 60px */

    /* No celular este número faz DOIS trabalhos, e é de propósito que seja um
       só: é o piso do cartão de texto e é o que a conta do poço desconta dos
       100svh. Com um número só, poço + cartão fecham exatamente a altura do
       palco e nada pode ser cortado pelo overflow:clip.

       360 é medido, não escolhido: o cartão mais alto de toda a faixa é 339,1px
       (390 de largura, onde o título ainda cai em três linhas). 320 dá 317,9 ·
       430 dá 328,8 · 734 dá 294,9. Sobram ~21px para uma tradução mais longa. O
       inset de baixo entra somado porque o enchimento do cartão também o soma —
       sem isso, um aparelho com faixa inferior estouraria o piso em 34px. */
    --copy-reserve: calc(360px + env(safe-area-inset-bottom));
  }
}
