/* ==========================================================================
   IZI — Site
   Origem: Figma "IZI---Site-Final" → frame IZI_Site_Layout (1:8)
   Tokens do arquivo: --izi #E8F100 | --preto #141416 | --branco #FFF

   Sumário
   1. Fontes
   2. Tokens (cor, tipo, espaço, movimento)
   3. Reset e base
   4. Utilitários e animação de entrada
   5. Header e navegação
   6. Hero
   7. Seções, títulos e texto
   8. Cartões IZI
   9. Faixas de foto e divisores
   10. Diferenciais
   11. Clientes
   12. Eventos
   13. Banner final e footer
   14. Breakpoints
   15. Acessibilidade e impressão
   16. Painéis dos pilares
   17. Performance de render
   18. Efeitos (parallax nativo, máscara dos títulos, entrada dos cartões)
   19. Movimento ambiente (o que se move com a página parada)
   20. Idiomas (seletor no nav e barra de sugestão)

   NOTA DE MANUTENÇÃO — movimento: tudo que se move usa as propriedades
   autônomas `translate` / `rotate` / `scale`, nunca o `transform`. As três
   compõem entre si e com o `transform` do layout; o `transform` substitui.
   Foi por isso que a revelação apagava o skew dos diferenciais (§4, §10).
   Se você for animar posição, escala ou giro, use a propriedade autônoma.
   ========================================================================== */

/* ============================ 1. FONTES ============================ */
/* Abadi MT Pro — fonte definida pelo time para o site (substitui as
   June Expt Variable / Carbona Test que constam no arquivo do Figma).

   Cortes usados: Regular 400 (texto), Bold 700 (destaques), ExtraBold 800
   (títulos e display). Escolhi a variante *Pro* e não a AbadiMT simples
   porque só a Pro traz tabela de kerning — sem ela os títulos grandes abrem
   espaços irregulares entre as letras.

   Subsetados para latim + acentos PT-BR (165 glifos) e servidos em WOFF2:
   111 KB -> 42 KB nos três cortes juntos (-62%). Só WOFF2, sem fallback .woff —
   todo navegador com share relevante desde 2016 lê WOFF2, e quem não lê cai
   na pilha de sistema declarada em --font-text/--font-display.

   ATENÇÃO — LICENÇA: Abadi é marca registrada da Monotype. Os arquivos que
   originaram estes webfonts vinham de kits do MyFonts reempacotados, sem
   licença rastreável — a tabela `name` ainda carrega a assinatura
   `com.myfonts.easy.mti.abadi-mt.pro-*.wfkit2`. Antes de qualquer lançamento
   público, substitua os 3 arquivos em assets/fonts/ por um webfont kit emitido
   sob a licença Monotype da Ticketmaster/Live Nation.
   É troca de arquivo, nada de código muda. */

@font-face{
  font-family:"Abadi MT";
  src:url("assets/fonts/abadi-regular.woff2") format("woff2");
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Abadi MT";
  src:url("assets/fonts/abadi-bold.woff2") format("woff2");
  font-weight:700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Abadi MT";
  src:url("assets/fonts/abadi-extrabold.woff2") format("woff2");
  font-weight:800; font-style:normal; font-display:swap;
}

/* ============================ 2. TOKENS ============================ */
:root{
  /* cor */
  --izi:#e8f100;
  --preto:#141416;
  --branco:#fff;
  --preto-80:rgba(20,20,22,.86);
  --izi-20:rgba(232,241,0,.2);

  /* famílias */
  --font-display:"Abadi MT","Gill Sans","Gill Sans MT",Calibri,"Trebuchet MS",sans-serif;
  --font-text:"Abadi MT","Gill Sans","Gill Sans MT",Calibri,"Trebuchet MS",sans-serif;

  /* Display = Abadi MT ExtraBold. A Abadi é estática (sem eixo de variação),
     por isso não há font-variation-settings em lugar nenhum: numa fonte
     estática a propriedade é ignorada pelo navegador. */
  --display-wght:800;
  --display-track:0em;

  /* escala tipográfica fluida — 360px → 1920px */
  --fs-display:clamp(2.25rem,1.05rem + 5.3vw,6.25rem);   /* 36 → 100 */
  --fs-h2:clamp(1.75rem,1rem + 3.3vw,4rem);              /* 28 → 64  */
  --fs-h3:clamp(1.375rem,1.05rem + 1.45vw,2.5rem);       /* 22 → 40  */
  --fs-lead:clamp(1.0625rem,.95rem + .9vw,1.875rem);     /* 17 → 30  */
  --fs-card:clamp(1.0625rem,.9rem + .95vw,1.75rem);      /* 17 → 28  */
  --fs-ev:clamp(1.125rem,.95rem + .95vw,2rem);           /* 18 → 32  */
  --fs-nav:clamp(.875rem,.8rem + .35vw,1.25rem);         /* 14 → 20  */
  --fs-badge:clamp(.75rem,.7rem + .2vw,.9375rem);        /* 12 → 15  */

  /* alturas de linha e ritmo de texto */
  --lh-tight:1;      /* Figma: line height 100% */
  --lh-snug:1.15;
  --lh-body:1.5;
  --measure:62ch;      /* medida de leitura confortável */
  --track-wide:.06em;

  /* escala de espaço fluida */
  --sp-3xs:clamp(.25rem,.2rem + .2vw,.5rem);
  --sp-2xs:clamp(.5rem,.45rem + .3vw,.75rem);
  --sp-xs:clamp(.75rem,.6rem + .6vw,1.25rem);
  --sp-s:clamp(1rem,.85rem + .8vw,1.75rem);
  --sp-m:clamp(1.5rem,1.2rem + 1.4vw,2.5rem);
  --sp-l:clamp(2rem,1.5rem + 2.4vw,4rem);
  --sp-xl:clamp(3rem,2rem + 4vw,6rem);
  --sp-2xl:clamp(4rem,2.5rem + 5.5vw,8.75rem);

  /* layout */
  --gut:clamp(1.25rem,1rem + 5vw,12.5rem);  /* 20px → 200px (margem do Figma) */
  --max:95rem;                              /* 1520px de conteúdo */
  --header-h:clamp(3.75rem,3rem + 2.2vw,6.25rem);

  /* escritas pelo main.js em tempo de execução (valores só de fallback) */
  --py:0px;              /* deslocamento do parallax */
  --reveal-delay:0ms;    /* atraso em cascata da entrada */

  /* movimento */
  --ease-soft:cubic-bezier(.16,1,.3,1);
  --ease-out:cubic-bezier(.22,.61,.36,1);
  /* passa do destino e volta (~6% de overshoot). Usada na entrada dos cartoes
     para o bloco ASSENTAR no lugar em vez de so aparecer. Nao serve para
     opacidade, que seria clampada — ver §18. */
  --ease-back:cubic-bezier(.34,1.46,.64,1);
  --dur-fast:180ms;
  --dur:380ms;
  --dur-slow:820ms;
}

/* ============================ 3. RESET E BASE ============================ */
*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:var(--header-h);
}

body{
  margin:0;
  background:var(--preto);
  color:var(--branco);
  font-family:var(--font-text);
  font-size:var(--fs-lead);
  line-height:var(--lh-body);
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  /* clip, nao hidden: `overflow:hidden` transformaria o <body> em scroll
     container e o scroll-padding-top/scroll-behavior do <html> deixariam de
     valer. `clip` corta igual sem criar scroller. hidden fica de fallback. */
  overflow-x:hidden;
  overflow-x:clip;
}
body.is-locked{overflow:hidden}   /* travamento durante o menu mobile */

img,svg{display:block;max-width:100%}
ul{margin:0;padding:0;list-style:none}
p{margin:0}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}

:focus-visible{
  outline:3px solid var(--izi);
  outline-offset:3px;
}
.section--yellow :focus-visible{outline-color:var(--preto)}

::selection{background:var(--izi);color:var(--preto)}

/* ============================ 4. UTILITÁRIOS ============================ */
.wrap{
  width:100%;
  max-width:calc(var(--max) + var(--gut) * 2);
  margin-inline:auto;
  padding-inline:var(--gut);
}

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

.skip{
  position:fixed;left:-9999px;top:0;z-index:120;
  background:var(--izi);color:var(--preto);
  padding:.7em 1.2em;font-weight:700;
}
.skip:focus{left:.75rem;top:.75rem}

/* entrada suave dos blocos ao rolar (ativada pelo main.js) */
[data-reveal]{
  opacity:0;
  /* `translate`, nao `transform`. As propriedades autonomas translate/rotate/
     scale COMPOEM com transform em vez de substitui-lo, e isso aqui nao e
     estilo: com `transform` a revelacao apagava o `transform:skewX(-8deg)` dos
     .dif__item (§10). Medido no navegador: os quatro itens terminavam em
     `transform:none` enquanto os <span> filhos mantinham o contra-skew de
     +8deg — o paralelogramo virava retangulo e o texto ficava inclinado para o
     lado errado. Em translate, o skew de base sobrevive a revelacao. */
  translate:0 1.75rem;
  transition:
    opacity var(--dur-slow) var(--ease-soft),
    translate var(--dur-slow) var(--ease-soft),
    scale var(--dur-slow) var(--ease-soft);
  transition-delay:var(--reveal-delay,0ms);
  /* sem will-change aqui de proposito: sao ~40 elementos [data-reveal] e o
     hint criaria 40 camadas de composicao no load. opacity/translate/scale ja
     sao propriedades compostas; o ganho era zero e o custo de memoria, real. */
}
[data-reveal].is-in{opacity:1;translate:none;scale:none}
.no-js [data-reveal]{opacity:1;translate:none;scale:none}

/* fade das imagens quando carregam */
img[loading="lazy"]{
  opacity:0;
  transition:opacity var(--dur-slow) var(--ease-out);
}
img[loading="lazy"].is-loaded,
.no-js img[loading="lazy"]{opacity:1}

/* parallax: o JS só escreve a variável, o CSS aplica.
   Em `translate` para deixar `scale`/`rotate` livres para o movimento ambiente
   da §19 — as tres propriedades se somam no mesmo elemento. */
[data-parallax]{translate:0 var(--py,0px)}

/* ============================ 5. HEADER E NAV ============================ */
.header{
  position:sticky;top:0;z-index:60;
  min-height:var(--header-h);
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-s);
  padding-inline:var(--gut);
  background:var(--preto);
  transition:
    background var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out),
    backdrop-filter var(--dur) var(--ease-out);
}
.header.is-stuck{
  background:var(--preto-80);
  -webkit-backdrop-filter:blur(14px) saturate(1.1);
          backdrop-filter:blur(14px) saturate(1.1);
  box-shadow:0 1px 0 var(--izi-20),0 12px 32px rgba(0,0,0,.35);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .header.is-stuck{background:var(--preto)}
}

.header__logo{
  display:flex;align-items:center;
  /* O padding lateral com margem negativa só engorda o alvo de toque: no
     celular o link media 24px de largura — o mínimo exato do WCAG 2.5.8, e
     metade dos ~44px confortáveis para o polegar. A margem devolve a posição
     visual; nada se move. */
  padding:var(--sp-2xs) .75rem;
  margin-inline:-.75rem;
  transition:transform var(--dur) var(--ease-soft),opacity var(--dur-fast) linear;
}
.header__logo img{
  height:clamp(1.375rem,1rem + 1vw,2.1875rem);
  width:auto;
}
.header__logo:hover{transform:translateY(-1px);opacity:.85}

.nav{
  display:flex;align-items:center;
  gap:clamp(.5rem,.9vw,1.25rem);
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-nav);
  line-height:1;
  color:var(--izi);
  text-transform:uppercase;
  letter-spacing:.02em;
}
.nav__link{
  position:relative;
  padding-block:.35em;
  transition:opacity var(--dur-fast) var(--ease-out);
}
.nav__link::after{
  content:"";
  position:absolute;left:0;right:0;bottom:0;
  height:2px;background:currentColor;
  transform:scaleX(0);transform-origin:left;
  transition:transform var(--dur) var(--ease-soft);
}
.nav__link:hover{opacity:.75}
.nav__link:hover::after,
.nav__link.is-active::after{transform:scaleX(1)}
.nav__sep{opacity:.45}

/* Seletor de idioma (PT | EN | ES). Reaproveita .nav__link — inclusive o
   sublinhado do ::after — e marca o idioma corrente com aria-current, que é
   estado acessível E seletor: nada de classe .is-current duplicando a fonte
   da verdade. No drawer (≤900px) o grupo herda o layout de coluna do nav e
   os três ficam lado a lado numa linha própria. */
.nav__langs{display:inline-flex;align-items:center;gap:.75em}
.nav__lang{opacity:.55}
.nav__lang[aria-current]{opacity:1}
.nav__lang[aria-current]::after{transform:scaleX(1)}

/* botão hamburguer (só aparece no mobile) */
.burger{
  display:none;
  width:2.75rem;height:2.75rem;
  padding:.6rem;
  align-items:center;justify-content:center;
  flex-direction:column;gap:.3rem;
}
.burger span{
  display:block;width:100%;height:2px;
  background:var(--izi);
  transition:transform var(--dur) var(--ease-soft),opacity var(--dur-fast) linear;
}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(.5rem) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-.5rem) rotate(-45deg)}

/* ============================ 6. HERO ============================ */
.hero{
  position:relative;
  overflow:hidden;
  background:var(--izi);
  width:100%;               /* trava a largura: sem isto, quando min-height
                               supera a altura do aspect-ratio, o Chrome
                               alarga a caixa e a página ganha scroll lateral */
  aspect-ratio:1920/720;
  min-height:min(78svh,34rem);
  display:grid;place-items:center;
  isolation:isolate;
}
.hero__logo{
  margin:0;
  width:min(22.6%,27.25rem);
  /* Duas animações somadas: a entrada e, emendada nela, uma flutuação
     permanente (§19). O atraso é exatamente a duração do hero-in, e elas podem
     coexistir porque hero-in anima transform/opacity enquanto izi-flutua anima
     `translate` — propriedades distintas, sem disputa. */
  animation:
    hero-in 1.1s var(--ease-soft) both,
    izi-flutua 9s 1.1s ease-in-out infinite;
}
.hero__logo img{width:100%;height:auto}
@keyframes hero-in{
  from{opacity:0;transform:translate3d(0,2rem,0) scale(.97)}
  to{opacity:1;transform:none}
}
.hero__deco{
  position:absolute;top:0;left:77.4%;
  width:56.3%;height:auto;
  pointer-events:none;z-index:-1;
}
/* O leque também abre à ESQUERDA (revisão do cliente, 20/08/2026). É o mesmo
   arquivo servido duas vezes — uma requisição de rede, duas caixas.
   Por que o espelho fica no <img> de dentro e não no contêiner: transform-origin
   é uma só por elemento, e aqui duas transformações querem pivôs diferentes. O
   espelho quer pivô no meio (50%), senão a caixa inteira sai de lugar; o giro
   ambiente da §19 quer pivô no centro de curvatura dos arcos, que cai fora da
   imagem. Em dois elementos cada um fica com a sua origem: o <div> gira em
   8% 50% (§19), que é o centro de curvatura já espelhado, e o <img> espelha em
   torno do próprio meio.
   E é `transform:scaleX(-1)`, não `scale:-1 1`, por causa da §2 — `scale` é
   propriedade autônoma e a animação da §19 anima `scale`; ela apagaria o
   espelho no primeiro keyframe. `transform` compõe com as três autônomas. */
.hero__deco--esq{left:auto;right:77.4%}
.hero__deco--esq img{width:100%;height:auto;transform:scaleX(-1)}

/* ============================ 7. SEÇÕES E TEXTO ============================ */
.section{
  position:relative;
  padding-block:var(--sp-2xl);
  overflow:hidden;
}
.section--dark{background:var(--preto);color:var(--branco)}
.section--yellow{background:var(--izi);color:var(--preto)}

.title{
  margin:0 0 var(--sp-l);
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-display);
  line-height:var(--lh-tight);
  letter-spacing:var(--display-track);
  text-align:center;
  text-transform:uppercase;
  text-wrap:balance;
}
.title--yellow{color:var(--izi)}
.title--dark{color:var(--preto)}
/* --fs-h2, não --fs-h3: com h3 o título da seção empatava com o kicker da
   prosa (40px = 40px a 1920) e a hierarquia sumia. Medido nas três línguas:
   2 linhas balanceadas a 1440/1920, 3 linhas a 375, sem scroll horizontal. */
.title--md{font-size:var(--fs-h2);line-height:var(--lh-snug);letter-spacing:0}

.prose{
  max-width:var(--measure);
  margin-inline:auto;
  display:flex;flex-direction:column;
  gap:var(--sp-s);
  font-size:var(--fs-lead);
  line-height:var(--lh-body);
  text-align:center;
  text-wrap:pretty;
}
.prose b{color:var(--izi);font-weight:700}
.section--yellow .prose b{color:var(--preto)}
.prose--tracked{letter-spacing:var(--track-wide);max-width:70ch}
.prose__kicker{
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  color:var(--izi);
  font-size:var(--fs-h3);
  line-height:var(--lh-snug);
  letter-spacing:0;
}

/* grafismo de fundo da seção "Solução completa" */
.solucao__deco{
  position:absolute;left:-10%;top:58%;
  width:120%;max-width:none;height:auto;
  opacity:.9;pointer-events:none;z-index:0;
}
.solucao .wrap,
.eventos .wrap{position:relative;z-index:1}

/* ============================ 8. CARTÕES IZI ============================ */
.cards{
  display:grid;
  gap:var(--sp-m);
  margin-top:var(--sp-xl);
}
.cards--3{grid-template-columns:repeat(3,minmax(0,1fr))}
.cards--4{grid-template-columns:repeat(4,minmax(0,1fr))}

.card{
  position:relative;
  aspect-ratio:375/350;
  display:flex;align-items:center;
  padding:12% 9%;
  background:url("assets/cartao-quem-somos.svg") no-repeat center/100% 100%;
  transition:transform var(--dur) var(--ease-soft),filter var(--dur) var(--ease-out);
}
.card--popup{background-image:url("assets/cartao-popup.svg")}
.card:hover{transform:translateY(-.5rem) rotate(-.6deg);filter:brightness(1.04)}
.card span{
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-card);
  line-height:var(--lh-snug);
  color:var(--preto);
  text-wrap:balance;
}

/* ============================ 9. FOTOS E DIVISORES ============================ */
/* AFASTAR O ZOOM SEM PERDER A FOLGA DO PARALLAX (revisão do cliente,
   20/08/2026: "diminuir/afastar o zoom da foto para que não fique o amarelo do
   cartão com o amarelo da outra seção").
   Antes: a foto era recortada em 1920/900 pelo próprio <img> e depois ampliada
   com `scale:1.2` para o parallax ter folga. Isso pintava a imagem 20% mais
   larga que a caixa — os cartões chegavam grandes e cortados na borda de baixo,
   encostando o amarelo do cartão no amarelo dos Diferenciais logo abaixo.
   Agora quem recorta é a SEÇÃO (aspect-ratio 1920/900 + overflow:hidden) e a
   imagem fica no tamanho natural (1920/1280, `scale` nenhum). Consequências
   medidas a 1440: a foto é pintada 1440x960 dentro de um quadro de 1440x675,
   ou seja, tudo 20% menor e com a largura inteira visível em vez de 83%.
   INVARIANTE DA §9 PRESERVADO, e com mais margem: a sobra vertical é
   (960-675)/2 = 142,5px = 14,8% da altura da imagem, contra os 8% de amplitude
   da §18. Antes eram 10% contra 8%.
   `align-content:center` é o que divide essa sobra em cima e embaixo; sem ele o
   grid alinha no início e o recorte mostraria o TOPO da foto, não o meio.
   Cuidado ao mexer: o `sizes` do HTML descreve o tamanho RENDERIZADO, então ele
   caiu de 120vw para 100vw junto com o `scale` (CLAUDE.md §3.2). */
.band{
  background:var(--izi);
  overflow:hidden;
  aspect-ratio:1920/900;
  display:grid;align-content:center;
}
.band img{
  width:100%;
  height:auto;              /* sem isto, o atributo height="" do HTML vence
                               o aspect-ratio e a proporção se perde */
  aspect-ratio:1920/1280;   /* a nativa da foto: nada de recorte no <img> */
  object-fit:cover;
}

.duo{
  background:var(--izi);
  display:grid;grid-template-columns:1fr 1fr;
}
.duo figure{margin:0;overflow:hidden}
.duo img{
  width:100%;
  height:auto;              /* idem .band img */
  aspect-ratio:960/1000;
  object-fit:cover;
  scale:1.2;                /* folga de recorte para o parallax da §18. A .band
                               resolve isso por sobra vertical (comentário
                               acima); aqui a caixa tem a proporção da foto, não
                               há sobra, e o `scale` continua sendo a folga. */
}

/* A margem negativa é ASSIMÉTRICA de propósito — e isso era um bug visível
   ("as ondas estão cortando", revisão do cliente de 20/08/2026).
   Os dois divisores têm seção amarela em cima e escura embaixo. A linha 0 do SVG
   é 100% amarela (medido: 1920 de 1920 pixels), então sobrepor o topo na seção
   amarela é invisível e fecha o hairline de arredondamento. Embaixo é o
   contrário: a silhueta amarela ENCOSTA na borda inferior do SVG em dois vales
   (x≈889-940 e x≈1790-1829, medido por amostragem de pixel), e -7px de
   margem-bottom fazia a seção escura seguinte cobrir justamente as pontas
   desses vales — a curva virava um corte reto de ~170px de largura.
   Embaixo não há hairline a fechar: a última linha do divisor já é #141416,
   igual à seção seguinte e igual ao fundo do <body>. */
.divider{
  width:100%;height:auto;
  margin-block:calc(var(--sp-3xs) * -1) 0;
}

/* ============================ 10. DIFERENCIAIS ============================ */
/* REESCRITO NA REVISÃO DE 20/08/2026. O cliente vetou os paralelogramos
   ("esses retângulos fogem da ID") e pediu, com mockup, o MESMO cartão dos
   pilares que ficam abaixo de "Vamos fazer do jeito IZI?" — quatro deles, em
   preto, sem a marca IZI no meio. O que saiu daqui:
   • `transform:skewX(-8deg)` no item + contra-skew de +8deg no <span>. Era a
     origem do bug de especificidade documentado na §4 e no CLAUDE.md §10;
   • a grade 2 + marca + 2 e o `.dif__mark`;
   • `aspect-ratio:275/344` (retrato) → 375/350, a proporção do cartão.
   O cartão preto é `assets/cartao-diferencial.svg`: o path de `cartao-popup.svg`
   (o dos pilares) com fill e stroke em #141416. Precisou ser arquivo novo porque
   o CSP não aceita `data:` URI e não havia cartão preto em assets/.
   O padding 12% 9% é o mesmo de `.card` — a caixa de conteúdo cai dentro da
   cunha, e é ele que faz a geometria escalar sozinha (o mesmo raciocínio da §12:
   padding em % resolve contra a largura do bloco contenedor, que num item de
   grid é a área de grid). */
.dif{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--sp-m);
}
.dif__item{
  aspect-ratio:375/350;
  display:flex;align-items:center;
  padding:12% 9%;
  background:url("assets/cartao-diferencial.svg") no-repeat center/100% 100%;
  color:var(--branco);
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-card);
  line-height:var(--lh-snug);
  /* `transform` no hover, como em `.ev` (§12) e por exatamente o mesmo motivo:
     `.dif__item` é [data-reveal] e a revelação usa translate/scale/rotate. */
  transition:transform var(--dur) var(--ease-soft),filter var(--dur) var(--ease-out);
}
.dif__item span{display:block;text-wrap:balance}
/* `brightness` num cartão quase preto quase não aparece; o que se lê é a
   subida. 1.45 sobre #141416 dá #1d1d20 — um degrau, não um flash. */
.dif__item:hover{transform:translateY(-.5rem) rotate(-.6deg);filter:brightness(1.45)}

/* ============================ 11. CLIENTES ============================ */
.clientes{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--sp-m);
}
.cliente{
  position:relative;
  aspect-ratio:394/350;
  display:grid;place-items:center;
  padding:14%;
  background:no-repeat center/100% 100%;
  transition:transform var(--dur) var(--ease-soft);
}
.cliente:hover{transform:translateY(-.5rem)}
/* GSH (--4) e Diverti (--6) apareciam "sem fundo" (revisão do cliente,
   20/08/2026). Causa medida no arquivo: `cartao-cliente.svg` é
   `fill="none" stroke="#141416"` — contorno, sem preenchimento nenhum. Os
   quatro irmãos usam a família `cliente-card-*.svg`, que tem o cartão da frente
   preenchido (`id="Cartao_2"`, `fill="#141416"`).
   Os dois foram para `cliente-card-2.svg`, a variante espelhada, e não para a
   normal, porque assim a segunda fileira fica espelhada-normal-espelhada contra
   normal-espelhada-normal da primeira. Ficam três referências ao mesmo arquivo
   e uma requisição só.
   Conferido antes de escurecer o fundo: GSH é dourado (#FFBE3C, luminância 192)
   e Diverti é laranja (#FA6A41, 134) — as duas artes se leem sobre #141416.
   `cliente-card-1.svg` não serve para reaproveitar: traz o logo da Live Nation
   embutido. */
.cliente--1{background-image:url("assets/cliente-card-1.svg")}
.cliente--2,
.cliente--4,
.cliente--6{background-image:url("assets/cliente-card-2.svg")}
.cliente--3{background-image:url("assets/cliente-card-3.svg")}
.cliente--5{background-image:url("assets/cliente-card-4.svg")}
.cliente img{
  max-width:76%;max-height:46%;
  width:auto;height:auto;
  object-fit:contain;
}

/* ============================ 12. EVENTOS ============================ */
/* GEOMETRIA DO CARTÃO — ler antes de mexer em padding ou posicionamento aqui.
   O cartão não é um retângulo: é uma CUNHA que abre para a direita. Medido no
   path dos SVGs (viewBox 375.618 × 351):

       borda de cima    (33.4, 58.6) → (326.6,   1.3)   inclinação −0.195
       borda de baixo   (33.4,292.5) → (326.6, 349.7)   inclinação +0.195
       lateral esquerda x=0.5    de y  98.5 a 252.5   (curta: 154 de altura)
       lateral direita  x=375.1  de y  41.2 a 309.8   (alta:  268 de altura)

   Consequência que já custou um bug: a borda de baixo DESCE para a direita, e a
   de cima SOBE. Então a faixa vertical utilizável é mais estreita à ESQUERDA, e
   quem manda no limite é o x MENOR do conteúdo, não o maior. Ao recuar 10% na
   horizontal (x=37.6), sobra y de 58.6 a 292.5 — ou seja, 16.7% a 83.3% da
   altura.

   Por isso o padding vertical (18%) é MAIOR que o horizontal (10%) e simétrico:
   a caixa de conteúdo inteira cai dentro da cunha, com ~7px de folga em cima e
   embaixo. É um invariante independente do rótulo — nome curto, longo ou em três
   linhas, nada escapa do contorno.

   O que havia antes: `align-items:flex-end` com `padding:10% 9%`. Como
   porcentagem de padding resolve contra a LARGURA nos quatro lados, o padding de
   baixo valia 29.7px numa caixa de 277px — o rótulo terminava em 89% da altura,
   6% abaixo do contorno. Medido: TODOS os 13 rótulos ficavam 16.5px fora da
   silhueta (as placas de foto, 28.5px), e o traço amarelo passava por cima do
   texto. Sobravam ainda 168px mortos acima do rótulo num cartão de 277px. */
/* TEM DE SER GRID, não flex — e isso não é preferência. Todo o encaixe do rótulo
   na cunha depende de `padding` em %, e porcentagem de padding resolve contra a
   largura do BLOCO CONTENEDOR, não contra a largura do próprio elemento. Num
   item de grid o bloco contenedor é a ÁREA DE GRID (≈297px a 1440), então 10%
   vale 29.7px, proporcional ao cartão — é o que faz a geometria escalar de 375px
   a 4K sozinha. Num item de flex o bloco contenedor é o container inteiro
   (1264px), e o mesmo 10% vira 126px. Medido ao tentar: o padding foi para
   227px/126px e o cartão explodiu.
   Custo aceito: são 13 eventos e 13 é primo, então a última fileira fica com 1
   cartão e 3 células vazias à direita em 4 colunas. Não há conserto em CSS que
   não custe caro — grid não centraliza fileira incompleta; flex centralizaria
   mas quebra as porcentagens acima; fazer as 3 fotos ocuparem 2 colunas fecharia
   as 16 células, mas exigiria `grid-auto-flow:dense` (ordem visual ≠ ordem do
   DOM) e recortaria fotos retrato em caixas deitadas. Nenhuma contagem de
   colunas resolve: 13 só divide por 1 e 13. */
.grid-eventos{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(min(16.5rem,100%),1fr));
  gap:var(--sp-s);
}
.ev{
  position:relative;
  aspect-ratio:375/350;
  display:flex;align-items:center;
  padding:18% 10%;
  transition:transform var(--dur) var(--ease-soft),filter var(--dur) var(--ease-out);
}
/* O contorno saiu de `background` de `.ev` para um ::before só para poder ser
   espelhado (`scale:-1 1`) — background-image não é transformável. Ver a nota de
   variação de forma abaixo. */
.ev::before{
  content:"";
  position:absolute;inset:0;
  background:url("assets/cartao.svg") no-repeat center/100% 100%;
}
/* Variação de forma REAL: 1 em cada 3 cartões de texto tem a cunha espelhada,
   abrindo para a esquerda. Antes havia duas regras nth-child trocando o
   background por `evento-cartao-a.svg` e `-b.svg` — e isso era decorativo no
   sentido ruim: `cartao.svg` e `evento-cartao-a.svg` eram BYTE A BYTE idênticos
   (md5 f727920f…, 494 bytes cada) e o `-b` só acrescentava `fill="#141416"`,
   invisível sobre o fundo escuro da seção. Os 13 cartões saíam iguais, ao
   contrário do que o comentário antigo afirmava. Os dois SVGs órfãos foram
   apagados.
   Espelhar é seguro justamente porque o rótulo está centralizado: a faixa
   utilizável do cartão espelhado é o espelho da original, e o centro vertical
   (y=175.5) está dentro dela nas duas orientações. Com `align-items:flex-end`
   isso não valeria.

   REVISÃO DE 20/08/2026 — "mudaria as direções dos cards para ficar mais
   harmônico". Era `:not(.ev--foto):nth-child(3n+2)`, que espelhava 2, 5, 8 e 11
   e pulava as fotos: o período 3 não se alinhava com a contagem de colunas e
   três cartões ficavam fora do ritmo. Agora é `:nth-child(even)`, e o período 2
   fecha nas duas paridades possíveis — o que importa, porque a grade é
   `auto-fill` e o número de colunas varia com a largura (medido: 2 a 768px, 3 a
   1280px, 4 a 1440px, 5 a 1920px). Com número PAR de colunas cada coluna fica com
   orientação fixa (►◄►◄ em todas as fileiras); com número ÍMPAR o padrão vira
   xadrez, e a alternância aparece na diagonal. Os dois leem como ritmo; o
   período 3 sobre 4 ou 5 colunas não lia como nada.
   As fotos entraram no esquema: a máscara não é transformável, mas o espelho
   podia ir para dentro do próprio SVG (`mask-cartao-espelhado.svg`). Isso
   espelha a SILHUETA, não a foto — a imagem continua na orientação original,
   como tem de ser. E o rótulo passou a ser centralizado na vertical (ver
   `.ev__badge`), o que é o que torna o espelho seguro nas fotos também. */
.ev:nth-child(even)::before{scale:-1 1}
.ev--foto:nth-child(even){
  -webkit-mask-image:url("assets/mask-cartao-espelhado.svg");
          mask-image:url("assets/mask-cartao-espelhado.svg");
}
/* Hover fica em `transform` DE PROPÓSITO, contra a regra geral do §2. É o único
   lugar do arquivo onde isso é certo: `.ev` é `[data-reveal]`, e a revelação usa
   translate/scale/rotate. Usar as autônomas aqui brigaria com ela; `transform` é
   um canal separado que COMPÕE com as três. */
.ev:hover{transform:translateY(-.5rem) scale(1.015)}
.ev>span:not(.ev__badge){
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-ev);
  line-height:var(--lh-snug);
  color:var(--izi);
  text-transform:uppercase;
  text-wrap:balance;
}
/* Os SVGs de cartão são só contorno (fill="none"), então o texto tem de ser
   amarelo em TODOS. Antes as regras nth-child pintavam alguns de amarelo e os
   demais herdavam --preto, ficando invisíveis sobre o fundo escuro. */

/* A MÁSCARA FICA AQUI, no cartão — não no <picture> e não no <img>. Já esteve
   nos dois, e cada posição tem um modo de falhar próprio:

   1. No <img>: a máscara escala junto com o que anima (`izi-respira` no §19 e o
      `scale(1.06)` do hover). A cunha crescia e o `overflow:hidden` cortava as
      pontas esquerda e direita, que é onde ela é mais larga. Medido: 303×283
      dentro de um cartão de 277 de altura.
   2. No <picture>: a geometria fica certa em repouso, mas aparece um FIO DE 1px
      da foto por fora da cunha, ao longo da caixa retangular do cartão, sempre
      que o cartão está com hover. Foi o que o usuário viu: "uma borda estranha
      com um pedaço da imagem". A causa é composição, não geometria — verificado
      medindo: a máscara recorta perfeitamente até `scale(1.5)` quando nada está
      animando. O fio só nasce quando o cartão E o <img> animam ao mesmo tempo:
      o `transform` do hover promove o cartão a camada, a animação promove o
      <img> a outra, e a máscara no <picture> fica numa terceira superfície no
      meio. Na borda das duas superfícies sobra 1px onde a máscara não é
      aplicada. Descartados por medição, todos ainda com o fio: `will-change` e
      `translateZ(0)` no quadro, `isolation:isolate`, `overflow:hidden` no
      quadro, `padding:1px` no quadro, encolher a máscara (`calc(100% - 2px)` e
      `- 4px`) e alargar o quadro 4px para o anel cair fora do `overflow` do
      cartão. Nenhum resolve, porque nenhum tira a máscara do meio.

   No cartão funciona porque a máscara passa a viver no MESMO elemento que o
   `transform` do hover: uma superfície só, e os descendentes — inclusive o <img>
   promovido — são compostos dentro dela antes de a máscara ser aplicada.
   Também não recria o problema (1): o cartão escala 1.015 no hover, mas escala
   junto com o contorno e com tudo mais, então a cunha continua coerente com a
   silhueta em vez de deslizar por baixo dela.
   Preço esperado, que na prática não se materializou: o ::before do contorno é
   filho do cartão, então a metade externa do traço (~0.8px na horizontal) passa a
   ser recortada pela máscara. Medido lado a lado — tira de 8px sobre a borda
   direita, com hover, capturada a 8× nas duas configurações — a largura e o brilho
   do traço são indistinguíveis. A borda da máscara tem antialiasing, então o que
   sobra do traço é multiplicado por um alpha em rampa em vez de cortado a meio, e
   a diferença fica sub-pixel. */
.ev--foto{
  padding:0;overflow:hidden;
  -webkit-mask:url("assets/mask-cartao.svg") no-repeat center/100% 100%;
          mask:url("assets/mask-cartao.svg") no-repeat center/100% 100%;
}
/* O contorno amarelo vale para os cartões de foto TAMBÉM, e por cima da imagem.
   Sem ele a silhueta simplesmente não se lê: a máscara recorta a cunha
   corretamente (verificado por amostragem de alpha, 7 pontos), mas as fotos são
   escuras nas bordas e o fundo da seção é #141416 — recorte certo, contraste
   nenhum. Lado a lado com um cartão de texto, a foto parecia um retângulo de
   cantos arredondados. O `z-index` é necessário porque o ::before pinta antes do
   <picture> na ordem natural; sem ele o traço fica atrás da foto. */
.ev--foto::before{z-index:1}
/* Sem máscara aqui — ela está no cartão, pelo motivo explicado lá em cima. O que
   sobra nesta regra é dimensionamento, e ele continua obrigatório.
   O <picture> é o item de flex, e sem `align-self:stretch` ele é dimensionado
   pelo CONTEÚDO: o `height:100%` do <img> passa a resolver contra uma altura
   indefinida, cai para `auto` e a foto assume a altura intrínseca — 372px dentro
   de um cartão de 277px. O `overflow:hidden` escondia o estrago, e o resultado é
   pior do que parece: com a máscara ainda aqui, `mask-size:100% 100%` desenhava a
   cunha ao longo dos 372px e o cartão recortava só a FATIA DO MEIO, justamente
   onde a cunha tem largura cheia. Daí as fotos saírem retangulares mesmo com a
   máscara ativa e carregando (verificar a propriedade computada não bastava; era
   preciso medir a caixa). Com o stretch, o <picture> fica com a altura do cartão
   e o <img> fica 297×277 — que é o que a máscara no cartão espera cobrir. */
.ev--foto>picture{align-self:stretch;display:block;width:100%}
.ev--foto img{
  width:100%;height:100%;
  object-fit:cover;
  /* as tres propriedades numa lista so: havia uma segunda regra .ev--foto img
     mais abaixo que redeclarava transition e, por vencer em ordem, apagava o
     fade de opacity do lazy-load. */
  transition:
    transform 1.1s var(--ease-soft),
    filter var(--dur) var(--ease-out),
    opacity var(--dur-slow) var(--ease-out);
}
.ev--foto:hover img{transform:scale(1.06)}
/* A placa era o pior caso: `left:6%;bottom:7%` punha a base 28.5px ABAIXO da
   silhueta recortada, então ela ficava pendurada no vazio embaixo da foto.
   Cuidado com a mistura de unidades: `bottom` em % resolve contra a ALTURA,
   enquanto padding em % resolve contra a largura — não são intercambiáveis.
   `bottom:20%` → base em 80% da altura (y=280.8) contra a borda inferior em
   y=293.3 no x da placa (10% → x=37.6): ~10px de folga.
   A largura foi de 29% para 32% para desapertar "IMAGINE DRAGONS", que é o
   rótulo mais longo e quebrava em duas linhas justas.

   REVISÃO DE 20/08/2026 — "o nome dos eventos com foto centralizado no bloco".
   Saiu de `left:6%;bottom:20%` para o centro nos DOIS eixos, alinhando com o
   rótulo dos cartões de texto (que é `align-items:center`). Isso não é só
   estética: é o que libera o espelho das fotos (ver a nota do `::before`).
   E centralizar na horizontal deixa a placa INDIFERENTE à orientação, o que é
   uma propriedade mais forte do que a folga que ela tinha antes: a cunha
   espelhada é o espelho da original em torno de x=50%, então uma caixa centrada
   em x=50% vê exatamente a mesma faixa útil nas duas.
   A conta, no viewBox 375.618x351 da máscara: a aresta de cima cai com
   inclinação -0,195 de (33,4; 58,5) até (326,6; 1,27), e a de baixo sobe na
   mesma taxa. A placa tem 32% de largura, logo ocupa x de 34% a 66%; o x mais
   apertado é 34% (=127,7), onde a faixa útil vai de y 40,1 a 310,9, ou seja
   11,4% a 88,6% da altura. A placa mede 32% da altura do cartão (32% da largura
   × 100/107 de proporção ÷ 350/375 de proporção do cartão) e centrada ocupa 34%
   a 66%. Sobram ~22 pontos percentuais em cada lado — a maior folga que essa
   placa já teve. `bottom:20%` não sobreviveria ao espelho: a base cairia fora da
   silhueta do lado curto.

   REVISÃO 2 DE 20/08/2026 — "a caixa com o nome dos artistas mais para a
   esquerda". `left` foi de 50% para 33%; o eixo VERTICAL continua centrado, e é
   ele que paga a conta do espelho agora: a placa ocupa x de 17% a 49%, e no x
   mais apertado (17%, ponta estreita do cartão normal) a faixa útil entre as
   arestas vai de 15% a 85% da altura — a placa centrada ocupa 34% a 66%, folga
   de ~19 pontos percentuais por lado. No cartão espelhado esses mesmos x caem
   na metade ALTA da cunha, com folga maior ainda. Medido a 1440: ~50px até a
   borda esquerda e ~91px até cada aresta, nas duas orientações. Se `left`
   descer de ~20% a placa encosta na borda vertical esquerda antes de qualquer
   aresta; refaça esta conta antes de mexer.
   `translate` aqui é LAYOUT, não movimento: nada anima translate nesta placa
   (ela não é [data-reveal] nem [data-parallax]), então não há disputa com a §2. */
.ev__badge{
  position:absolute;left:33%;top:50%;translate:-50% -50%;
  display:grid;place-items:center;
  width:32%;aspect-ratio:107/100;
  padding:0 9% 4%;
  background:url("assets/badge-placa.svg") no-repeat center/100% 100%;
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  /* Piso .75rem, não .6rem: o 1vw segue a VIEWPORT, mas a placa segue o CARTÃO
     (width:32%) — e no celular o cartão é quase a tela inteira. Com piso .6rem
     o rótulo saía 9,6px numa placa de ~98px: placa grande, texto ilegível. Como
     a largura do cartão só varia de ~264 a ~400px em todas as viewports, o
     resultado efetivo é 12–13px sempre. Fit re-medido no pior caso (IMAGINE
     DRAGONS, cartão mínimo, duas orientações) — conta do comentário acima. */
  font-size:clamp(.75rem,1vw,.8125rem);
  line-height:1.05;
  color:var(--preto);
  text-align:center;
  text-transform:uppercase;
  text-wrap:balance;
}

/* ============================ 13. FINAL E FOOTER ============================ */
.final{
  display:grid;
  grid-template-columns:1fr 1fr;
  align-items:center;
  background:var(--izi);color:var(--preto);
  overflow:hidden;
}
.final__text{padding:var(--sp-2xl) var(--gut)}
.final__text h2{
  margin:0;
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  font-size:var(--fs-h2);
  /* "diminuir o espaçamento vertical do texto" (cliente, 20/08/2026). Era
     var(--lh-snug) (1.15). 1.0 foi testado e reprovado: o circunflexo de
     "EXPERIÊNCIA" quase encosta na linha de cima — e só o pt tem acento aqui,
     então o aperto máximo é ditado por ele. Se mudar, mude o margin-block do
     .final__logo junto (a conta está lá embaixo). */
  line-height:1.05;
  letter-spacing:var(--display-track);
  text-transform:uppercase;
}
/* "O texto está quebrado" (revisão do cliente, 20/08/2026). Estava, e a causa
   não era a quebra de linha: era o TAMANHO desta marca.
   Medido a 1920: a marca vinha com `width:clamp(...,9.5vw,11.5rem)` = 182px de
   largura e 167px de altura, dentro de uma linha de 73,6px (64px x 1.15). Um
   inline-block contribui para a caixa de linha com a sua ALTURA DE MARGEM, então
   a terceira linha inflava de 74 para 168px e a base de "completa e" ia para
   180px abaixo de "experiência" — um buraco no meio do título, com a marca
   flutuando alta ao lado. As três linhas do texto ficavam a 183, 257 e 437px.
   Correção: a marca passa a ser dimensionada em EM, e as margens verticais
   negativas devolvem a contribuição dela ao tamanho da própria linha
   (na entrelinha de 1.15 a conta era simétrica, (1.6em - 1.15em)/2 = .225em;
   com a de 1.05 pedida pelo cliente em 20/08/2026 os valores foram medidos, e
   são assimétricos — ver o comentário na própria regra). Assim ela continua
   grande em
   relação ao texto (1,6x a altura da linha), acompanha a tipografia fluida
   sozinha e não abre buraco nenhum: o ritmo das três linhas volta a ser
   uniforme. A sobra de ~18px que ela projeta para cima cai num vazio — a linha
   de cima termina antes de onde a marca começa. */
.final__logo{
  /* -.25em (era -.35em): com a entrelinha mais justa a marca ficava mergulhada
     demais abaixo da linha de base; subir .1em centra o desenho com o texto. */
  display:inline-block;vertical-align:-.25em;
  width:auto;height:1.6em;
  margin-left:.18em;
  /* Assimétrico de propósito: subir a marca (vertical-align -.25em) empurra a
     projeção dela para CIMA da linha, e o lado de cima precisa de mais margem
     negativa que a conta simétrica dá. Medido a 1440: com -.275em em cima a 3ª
     linha descia 2,4px fora do ritmo; -.325em/-.275em devolve as três linhas ao
     passo exato de line-height (66,7px). */
  margin-block:-.325em -.275em;
}
.final__img{overflow:hidden;height:100%}
.final__img img{
  width:100%;height:100%;
  aspect-ratio:1/1;
  object-fit:cover;
  scale:1.2;                /* idem .duo img: a caixa é 1/1 e a foto é 1/1, logo
                               não há sobra de recorte; o `scale` é a folga. */
}

.footer{
  display:flex;align-items:center;justify-content:center;
  gap:var(--sp-l);
  min-height:6.25rem;
  padding:var(--sp-m) var(--gut);
  background:var(--preto);
}
.footer a{
  display:block;
  transition:transform var(--dur) var(--ease-soft),opacity var(--dur-fast) linear;
}
.footer a:hover{transform:translateY(-.25rem);opacity:.8}
.footer img{width:clamp(2.375rem,3vw,3.4375rem);height:auto}

/* ============================ 14. BREAKPOINTS ============================ */

/* --- tablet / notebook estreito --- */
@media (max-width:1024px){
  .cards--4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .grid-eventos{grid-template-columns:repeat(auto-fill,minmax(min(14rem,100%),1fr))}
}

/* --- tablet retrato: menu vira drawer --- */
@media (max-width:900px){
  .burger{display:flex}

  .nav{
    position:fixed;
    inset:var(--header-h) 0 auto 0;
    flex-direction:column;align-items:flex-start;
    gap:var(--sp-xs);
    padding:var(--sp-l) var(--gut) var(--sp-xl);
    background:var(--preto-80);
    -webkit-backdrop-filter:blur(18px);
            backdrop-filter:blur(18px);
    border-top:1px solid var(--izi-20);
    font-size:clamp(1.25rem,4.5vw,2rem);
    /* O drawer é fixed e o body fica travado (.is-locked) enquanto está aberto,
       então NADA na página rola. Medido a 320x256 com texto em 200%: o drawer ia
       até 633px e três dos quatro links ficavam fora da tela, inalcançáveis —
       perda de conteúdo (WCAG 1.4.4 e 1.4.10). Limitar a altura ao que sobra
       abaixo do header e deixar o próprio drawer rolar resolve. */
    max-height:calc(100svh - var(--header-h));
    overflow-y:auto;
    overscroll-behavior:contain;    /* não repassa o scroll para a página atrás */
    opacity:0;visibility:hidden;
    transform:translate3d(0,-1rem,0);
    transition:
      opacity var(--dur) var(--ease-out),
      transform var(--dur) var(--ease-soft),
      visibility var(--dur) step-end;
  }
  .nav.is-open{
    opacity:1;visibility:visible;transform:none;
    transition:
      opacity var(--dur) var(--ease-out),
      transform var(--dur) var(--ease-soft),
      visibility 0s;
  }
  .nav__sep{display:none}
  .nav__link{padding-block:.25em}

  .cards--3{grid-template-columns:repeat(2,minmax(0,1fr))}
  .clientes{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* Diferenciais em 2x2, igual aos pilares (.cards--4) a partir de 1024px. Aqui
     não há mais nada a desfazer: desde a revisão de 20/08/2026 os diferenciais
     são cartões, não paralelogramos, então o bloco antigo que zerava o skew, o
     contra-skew e o alinhamento à direita saiu junto com o `.dif__mark`. */
  .dif{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-s)}

  .final{grid-template-columns:1fr}
  .final__img img{aspect-ratio:16/10}
  .solucao__deco{display:none}
  .hero__deco{left:62%;width:72%}
  /* o espelhado ancora pela direita — repetido aqui porque esta regra é
     posterior no arquivo e `left:62%` venceria o `left:auto` da §6 */
  .hero__deco--esq{left:auto;right:62%}
}

/* --- mobile --- */
@media (max-width:600px){
  .title{text-align:left}
  .prose{text-align:left}
  .prose--tracked{letter-spacing:.03em}

  .cards--3,.cards--4,.clientes{grid-template-columns:1fr;gap:var(--sp-s)}
  .dif{grid-template-columns:1fr}
  .card,.dif__item{aspect-ratio:375/300;padding:10% 8%}

  .duo{grid-template-columns:1fr}
  .duo img{aspect-ratio:4/3}
  /* No mobile o quadro é mais alto (4/3) do que a foto (3/2), então o esquema da
     §9 se inverte: a imagem em tamanho natural ficaria MAIS BAIXA que o quadro e
     abriria faixa amarela em cima e embaixo. Aqui a foto volta a preencher o
     quadro e a folga do parallax volta a vir do `scale` — 1.2 => 10% por lado,
     contra os 8% de amplitude. O `sizes` do HTML acompanha: 120vw abaixo de
     600px, 100vw acima. */
  .band{aspect-ratio:4/3}
  .band img{aspect-ratio:4/3;scale:1.2}

  .grid-eventos{grid-template-columns:repeat(auto-fill,minmax(min(13rem,100%),1fr));gap:var(--sp-xs)}

  .hero{min-height:58svh;aspect-ratio:auto;padding-block:var(--sp-xl)}
  .hero__logo{width:56%}

  .footer{gap:var(--sp-m)}
}

/* --- telas largas: não deixar o texto esticar --- */
@media (min-width:1921px){
  .hero{aspect-ratio:auto;height:44vw;max-height:56rem}
}

/* ============================ 15. ACESSIBILIDADE ============================ */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
  }
  /* `animation-iteration-count:1` acima já para as animações infinitas da §19,
     mas ele não desfaz o estado: as três propriedades autônomas precisam ser
     zeradas à mão, senão o elemento congela no primeiro frame do keyframe. */
  [data-reveal]{opacity:1!important;translate:none!important;scale:none!important;rotate:none!important}
  [data-parallax]{translate:none!important;rotate:none!important;scale:none!important}
  .hero__logo,.ev--foto img{animation:none!important}
  /* Sem `.band img,.duo img,.final__img img{scale:1}` aqui: as três fotos também
     são [data-parallax], então o `scale:none!important` da regra acima já as
     alcança — e `none` é a identidade, idêntico a `1` no resultado. A declaração
     sem !important nunca ganhava do !important e era código morto. Efeito
     colateral desejado: sem parallax a folga de recorte da §9 não é necessária,
     e a foto aparece inteira em vez de 20% ampliada. */
}

@media print{
  .header,.burger,.nav,.footer,.hero__deco,.solucao__deco,.langbar{display:none!important}
  body{background:#fff;color:#000}
  .section{padding-block:1.5rem;page-break-inside:avoid}
  [data-reveal]{opacity:1!important;translate:none!important;scale:none!important;rotate:none!important}
}

/* ============================ 16. PAINÉIS DOS PILARES (rev. 5) ============================ */
.card__toggle{
  all:unset;
  display:flex;align-items:center;
  /* align-self:stretch, NÃO height:100%. No WebKit (iOS Safari, medido no
     WebKit 26), height:100% de um filho resolve em ciclo contra a altura que o
     pai tira do aspect-ratio e infla o cartão para um QUADRADO maior que a
     própria coluna — a 375px ele saía 386×386 em vez de 306×245, vazava a
     viewport e cobria o painel de baixo (print do cliente, 20/08/2026). O
     stretch dá a mesma altura sem porcentagem. Mesmo padrão do
     .ev--foto>picture, pelo mesmo motivo. */
  width:100%;align-self:stretch;
  cursor:pointer;
  font:inherit;
  /* --preto explícito, NÃO `inherit`. O cartão está dentro de .section--dark,
     que pinta a cor de texto de branco; mas o cartao-popup.svg é preenchido de
     amarelo sólido (#E8F100). Com `color:inherit` o "+" do ::after saía branco
     sobre amarelo: 1,14:1 medido no navegador, praticamente invisível — e ele é
     o único sinal de que o cartão abre. O rótulo escapava porque `.card span`
     já declarava --preto; o pseudo-elemento não tinha quem o salvasse.
     Em preto com opacity .7 o "+" fica em 7,8:1 e o tom discreto se mantém. */
  color:var(--preto);
  -webkit-tap-highlight-color:transparent;
}
.card__toggle:focus-visible{
  /* anel PRETO: com offset 4px o anel cai 16px dentro do cartão amarelo, então
     um outline var(--izi) era amarelo sobre amarelo — foco invisível (2.4.7). */
  outline:3px solid var(--preto);
  outline-offset:4px;
  border-radius:4px;
}
.card__toggle::after{
  content:"+";
  margin-left:auto;
  font-family:var(--font-display);
  font-size:1.5em;line-height:1;
  opacity:.7;
  transition:transform var(--dur) var(--ease-soft),opacity var(--dur) var(--ease-out);
}
.card.is-aberto .card__toggle::after{transform:rotate(45deg);opacity:1}
.card.is-aberto{filter:brightness(1.08);transform:translateY(-4px)}

.painel{
  margin-top:var(--sp-m);
  padding:var(--sp-m) var(--sp-l);
  border:2px solid var(--izi);
  border-radius:1.25rem;
  background:rgba(255,255,255,.03);
}
.painel__titulo{
  margin:0 0 var(--sp-s);
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  /* --fs-h3, não --fs-card: com fs-card (28px) o título ficava MENOR que os
     bullets da própria lista (30px) — hierarquia invertida. A 40px o pior
     título ("Dashboard e inteligencia en la palma de tu mano", es) ainda dá
     1 linha a 1440/1920 e 3 linhas dentro da caixa a 375. */
  font-size:var(--fs-h3);
  text-transform:uppercase;
  color:var(--izi);
}
/* "uns pontos amarelos tipo bullets" (cliente, 20/08/2026). O reset global
   ul{list-style:none} apagava o marcador mas o padding-left de 1.1em ficava —
   recuo sem bullet, que lia como texto desalinhado. Devolver o disc e colorir
   via ::marker é CSS puro (nada de imagem: o CSP proíbe data:, ver §6 do
   CLAUDE.md); onde ::marker não pega cor, degrada para bullet branco. */
.painel__lista{
  margin:0;padding-left:1.1em;
  display:grid;gap:.55em;
  list-style:disc;
  color:var(--branco);
  line-height:var(--lh-body);
}
.painel__lista li{padding-left:.15em}
.painel__lista li::marker{color:var(--izi)}

@media (max-width:640px){
  .painel{padding:var(--sp-s) var(--sp-m)}
}
@media (prefers-reduced-motion:reduce){
  .card.is-aberto{transform:none}
  .card__toggle::after{transition:none}
}

/* ============================ 17. PERFORMANCE DE RENDER ============================ */
/* Página tem ~8000px. Sem isto o navegador calcula layout e paint de tudo de
   uma vez. content-visibility deixa cada seção fora de vista de lado até
   chegar perto; contain-intrinsic-size evita que a barra de rolagem pule. */
/* Só nas seções SEM parallax. Aprendido na auditoria: quando o navegador
   pula uma subárvore com content-visibility, a ViewTimeline dos elementos
   dentro dela fica travada em 0 — justamente na entrada, que é quando o
   parallax deveria começar. Resultado: o movimento aparecia de repente.
   Por isso .band, .duo e .final ficam de fora. */
.section{
  content-visibility:auto;
  contain-intrinsic-size:auto 700px;
}
/* O hero é o primeiro paint — nunca pode ser adiado. E a .solucao hospeda
   um sujeito de parallax, então também fica fora do content-visibility. */
.hero,.solucao{content-visibility:visible}

/* ============================ 18. EFEITOS ============================ */
/* --------------------------------------------------------------------------
   Parallax nativo (scroll-driven animations). Onde o navegador suporta
   animation-timeline, o movimento sai do main thread e roda no compositor:
   mais suave e sem custo de JS por scroll. O main.js detecta o suporte e
   desliga a versão em JS para os dois não brigarem.
   -------------------------------------------------------------------------- */
@supports (animation-timeline: view()) {
  /* ATENÇÃO ao motivo do view-timeline-name aqui, descoberto medindo no
     navegador: `animation-timeline: view()` mede a posição do elemento dentro
     do seu SCROLL CONTAINER mais próximo — e `overflow:hidden` já cria um
     scroll container. Como .band, .duo figure, .final__img, .hero e .solucao
     todos usam overflow:hidden para recortar a foto, a timeline media a imagem
     dentro de uma caixa que nunca rola: o progresso ficava congelado em 50% e
     o parallax não saía do lugar.
     Solução: nomear a timeline no elemento que RECORTA (esse sim está no fluxo
     do documento e rola normalmente) e animar o filho contra ela. */
  .band{view-timeline-name:--tl-faixa}
  .duo figure:first-child{view-timeline-name:--tl-duo-a}
  .duo figure:last-child{view-timeline-name:--tl-duo-b}
  .final{view-timeline-name:--tl-final}       /* na seção, não no .final__img:
                                                 ele também está dentro de um
                                                 overflow:hidden */
  .hero{view-timeline-name:--tl-hero}
  .solucao{view-timeline-name:--tl-solucao}

  html.tem-sda [data-parallax]{
    animation:desliza linear both;
    animation-range:cover 0% cover 100%;
    will-change:translate;
  }

  /* AMPLITUDE EM % DA ALTURA DO PRÓPRIO ELEMENTO, não em vh — a mudança que
     resolveu metade do "parece estático".
     Com `--amp` em vh, a amplitude era fixa e a folga do recorte (§9) escalava
     com o elemento, então a mesma regra ficava tímida no desktop e arriscada no
     celular: medido a 375px, a antiga amplitude de 7vh já passava da folga do
     .band. Em %, translate resolve contra a altura da própria imagem, logo a
     razão amplitude/folga é constante em qualquer viewport — dá para subir o
     movimento até ser perceptível sem nunca abrir a borda do recorte.

     Os valores param bem abaixo da folga da §9 de propósito. Medido a
     375x812, com 13% no .duo da direita a borda chegava a 2,2px de abrir — sem
     bug visível, mas sem margem nenhuma para um celular mais estreito e alto.
     Com 9% sobram ~13px. E vale lembrar do que a medição mostrou: no desktop a
     amplitude antiga (7vh = 63px) já era equivalente a estes ~8% — nunca foi a
     amplitude que fazia a página parecer estática, e sim o fato de o movimento
     existir só durante a rolagem. Isso é o que a §19 resolve. */
  html.tem-sda .band img        {animation-timeline:--tl-faixa;  --amp:8%}
  html.tem-sda .duo figure:first-child img{animation-timeline:--tl-duo-a; --amp:7%}
  html.tem-sda .duo figure:last-child img {animation-timeline:--tl-duo-b; --amp:9%}
  html.tem-sda .final__img img  {animation-timeline:--tl-final;  --amp:8%}

  /* Os dois elementos decorativos acumulam parallax E movimento ambiente (§19),
     então precisam da lista explícita: `animation` é um atalho, e a regra
     genérica [data-parallax] acima substituiria a animação ambiente inteira.
     O segundo item de cada lista usa `auto` como timeline — o relógio normal.
     Repetir o par (nome, timeline) é chato, mas o alternativo era espalhar
     animation-name/duration/... em seis declarações por elemento. */
  html.tem-sda .hero__deco[data-parallax]{
    animation:
      desliza auto linear both,
      izi-arcos 16s var(--ease-soft) infinite;
    animation-timeline:--tl-hero,auto;
    animation-range:cover 0% cover 100%,normal;
    /* Amplitude generosa e ainda assim segura: o SVG é transparente, quem
       recorta é o .hero, e o leque já sobra para fora à direita.
       Antes eram 3vh — medido, o elemento percorria 21px na página inteira e
       congelava em progresso 1 a partir de y≈769. */
    --amp:9vh;
  }
  /* O `animation-delay:-5.4s` que a §19 dá ao leque espelhado é apagado aqui: o
     atalho `animation` acima zera delay, e `html.tem-sda .hero__deco[data-parallax]`
     (0,3,1) vence `.hero__deco.hero__deco--esq` (0,2,0) por especificidade, não
     por ordem. Então o atraso volta como lista, na mesma ordem das duas
     animações. O 0s do primeiro item é indiferente na prática — delay é ignorado
     em animação com animation-timeline —, mas a lista tem que ter dois valores
     ou o segundo não recebe o -5.4s. */
  html.tem-sda .hero__deco--esq[data-parallax]{animation-delay:0s,-5.4s}
  html.tem-sda .solucao__deco[data-parallax]{
    animation:
      desliza auto linear both,
      izi-respira 13s ease-in-out infinite;
    animation-timeline:--tl-solucao,auto;
    animation-range:cover 0% cover 100%,normal;
    --amp:9vh;
  }

  @keyframes desliza{
    from{translate:0 calc(var(--amp, 8%) * -1)}
    to  {translate:0 var(--amp, 8%)}
  }
}

/* --------------------------------------------------------------------------
   Entrada dos títulos: a palavra sobe por trás de uma máscara, em vez de
   só aparecer. Mais próximo do gesto do layout, e barato (transform+clip).
   -------------------------------------------------------------------------- */
.title{
  clip-path:inset(-20% -5% -20% -5%);
}
.title[data-reveal]{
  opacity:1;                       /* a máscara já esconde; sem duplo fade */
  translate:none;
}
.title[data-reveal] > span.mask{
  display:inline-block;
  translate:0 110%;
  transition:translate 1s var(--ease-soft) var(--reveal-delay,0ms);
}
.title[data-reveal].is-in > span.mask{translate:none}

/* Cards: sobem, assentam e giram de volta ao esquadro.
   Os três eixos (translate, scale, rotate) são propriedades autônomas, então o
   `transform:skewX()` de base dos .dif__item continua valendo durante a entrada
   — era esse o bug corrigido em §4.
   O overshoot do --ease-back vale só para geometria; a opacidade fica no ease
   normal, porque passar de 1 seria clampado e o fade sairia irregular. */
.card[data-reveal],
.ev[data-reveal],
.cliente[data-reveal],
.dif__item[data-reveal]{
  translate:0 1.75rem;
  scale:.97;
  rotate:-.5deg;
  transition:
    opacity var(--dur-slow) var(--ease-out) var(--reveal-delay,0ms),
    translate .9s var(--ease-back) var(--reveal-delay,0ms),
    scale .9s var(--ease-back) var(--reveal-delay,0ms),
    rotate .9s var(--ease-back) var(--reveal-delay,0ms);
}
/* Alterna o lado do giro para a cascata não parecer uma esteira */
.card:nth-child(even)[data-reveal],
.ev:nth-child(even)[data-reveal],
.cliente:nth-child(even)[data-reveal],
.dif__item:nth-child(even)[data-reveal]{rotate:.5deg}

.card[data-reveal].is-in,
.ev[data-reveal].is-in,
.cliente[data-reveal].is-in,
.dif__item[data-reveal].is-in{
  translate:none;
  scale:none;
  rotate:none;
}

/* Foto de evento: o zoom do hover ganha um clarear sutil da máscara
   (a lista de transition vive na regra unica da secao 12) */
.ev--foto:hover img{filter:saturate(1.08) contrast(1.03)}

/* Respeito total a quem pediu menos movimento */
@media (prefers-reduced-motion:reduce){
  .title[data-reveal] > span.mask{transition:none;translate:none}
  /* As duas regras seguintes existem porque a genérica não alcança os dois
     elementos de lista dupla (§18): `html.tem-sda .hero__deco[data-parallax]`
     tem especificidade maior que `html.tem-sda [data-parallax]`, então venceria.
     O `animation-duration:.01ms!important` da §15 também não resolveria: numa
     animação com animation-timeline a duração é ignorada, e
     animation-iteration-count não interrompe movimento ligado à rolagem. */
  html.tem-sda [data-parallax]{animation:none}
  html.tem-sda .hero__deco[data-parallax],
  html.tem-sda .solucao__deco[data-parallax]{animation:none}
  .card[data-reveal],.ev[data-reveal],.cliente[data-reveal],.dif__item[data-reveal]{
    translate:none;
    scale:none;
    rotate:none;
  }
}

/* ============================ 19. MOVIMENTO AMBIENTE ============================ */
/* --------------------------------------------------------------------------
   Por que esta seção existe. O parallax da §18 funciona, mas só existe
   ENQUANTO a página rola, e as revelações são one-shot (o main.js faz
   io.unobserve depois da primeira entrada). Consequência medida no navegador:
   parado em qualquer ponto da página, absolutamente nada se movia — e no herói,
   que é a primeira impressão, o movimento acabava 1,1s depois do load.
   O que falta não é mais parallax, é uma linha de base de vida própria: lenta,
   contínua, independente de rolagem.

   Regras que essa vida segue:
   • ciclos longos (9–17s) e amplitudes de 1 a 4% — se der para cronometrar,
     está rápido demais;
   • períodos dessincronizados, com atraso negativo para começar no meio do
     ciclo: dois elementos respirando em uníssono leem como carrossel;
   • sempre translate/rotate/scale, nunca transform, para somar com o parallax
     e com o skew/hover do layout;
   • baseadas em TEMPO, não em rolagem — por isso são seguras dentro das seções
     com content-visibility:auto. O que o content-visibility congela é a
     ViewTimeline (§17), não o relógio das animações.

   WCAG 2.2.2 (Pause, Stop, Hide) — decisão consciente, vale registrar. O
   critério fala de conteúdo em movimento que começa sozinho e dura mais de 5s,
   e estas animações são infinitas. O que sustenta a conformidade aqui:
   • o conteúdo é decorativo, não informativo — .hero__deco e .solucao__deco são
     aria-hidden="true", e nenhuma informação depende do movimento;
   • @media (prefers-reduced-motion:reduce) desliga tudo (§15), que é o
     mecanismo de controle na prática, no nível do sistema operacional;
   • as amplitudes (1 a 4%, ciclos de 9 a 17s) ficam abaixo do limiar de
     distração — nada pisca, nada cruza a tela, nada compete com a leitura.
   Se algum dia o movimento crescer, ou passar a carregar informação, aí um
   controle explícito de pausa deixa de ser opcional.
   -------------------------------------------------------------------------- */

/* O leque de arcos do herói gira em torno do próprio centro de curvatura. Os
   arcos são concêntricos e esse centro cai fora da imagem, à direita — daí o
   transform-origin deslocado. Girar em torno do centro geométrico da caixa
   deformaria o leque em vez de varrê-lo. */
@keyframes izi-arcos{
  0%,100%{rotate:0deg;    scale:1}
  50%    {rotate:-1.1deg; scale:1.03}
}

/* Flutuação vertical. A amplitude em % resolve contra a altura do próprio
   elemento, então é proporcional em qualquer tela. */
@keyframes izi-flutua{
  0%,100%{translate:0 0}
  50%    {translate:0 -2.6%}
}

/* Respiração de foto: um zoom quase imperceptível que nunca chega à borda,
   porque as fotos já vivem recortadas (§9). */
@keyframes izi-respira{
  0%,100%{scale:1}
  50%    {scale:1.04}
}

.hero__deco{
  transform-origin:92% 50%;
  animation:izi-arcos 16s var(--ease-soft) infinite;
}
/* O leque da esquerda é o mesmo SVG espelhado (§6), então o centro de curvatura
   também espelha: 92% viram 8%. Selecionado com as duas classes (0,2,0) porque
   `.hero__deco--esq` sozinho empata com `.hero__deco` e este bloco vem depois no
   arquivo — a especificidade tira a ordem de origem da conta.
   O atraso negativo é o mesmo motivo dos ciclos primos das fotos de evento: com
   0 os dois leques varreriam em uníssono e o movimento leria como a página
   inteira tremendo, não como dois elementos vivos. */
.hero__deco.hero__deco--esq{
  transform-origin:8% 50%;
  animation-delay:-5.4s;
}

/* Fotos da grade de eventos. Ciclos primos entre si e um atraso negativo em
   cada terço para as três nunca coincidirem. O `scale` do keyframe multiplica
   com o `transform:scale(1.06)` do hover (§12) em vez de disputar com ele. */
.ev--foto img{animation:izi-respira 14s ease-in-out infinite}
/* As três fotos estão nas posições 4, 7 e 10 da lista. As regras antigas usavam
   :nth-child(3n) e :nth-child(3n+2) — que valem 3,6,9,12 e 2,5,8,11 e portanto
   NÃO alcançam 4, 7 nem 10. Resultado medido: as três respiravam em uníssono,
   com 14s e atraso 0, exatamente o que os ciclos primos entre si e o atraso
   negativo existem para evitar. As posições abaixo são literais porque a lista
   de eventos é conteúdo fixo; se ela mudar, revisar aqui. */
.ev--foto:nth-child(7)  img{animation-duration:17s;animation-delay:-4.6s}
.ev--foto:nth-child(10) img{animation-duration:19s;animation-delay:-9.3s}

/* Os arcos duplicados da seção da solução acompanham, em contraciclo com o
   herói (13s contra 16s), para as duas peças amarelas não pulsarem juntas. */
.solucao__deco{
  transform-origin:50% 50%;
  animation:izi-respira 13s ease-in-out infinite;
}

/* ============================ 20. IDIOMAS ============================ */
/* Barra de sugestão de idioma, injetada pelo main.js quando o idioma do
   navegador não bate com o da página e o leitor ainda não escolheu (localStorage
   izi-lang). É sugestão, nunca redirect: redirecionar por Accept-Language
   quebra indexação (o Googlebot rastreia em inglês a partir dos EUA) e prende
   quem quer ler noutra língua.
   A centragem usa `translate` (§2: propriedade autônoma) — se um dia ela ganhar
   animação de entrada em keyframe, o -50% tem de constar em CADA frame, senão o
   frame o substitui e a barra pula para a esquerda. A entrada de hoje anima só
   opacity justamente para não tocar nisso. */
.langbar{
  position:fixed;left:50%;bottom:max(1rem,env(safe-area-inset-bottom));
  translate:-50% 0;
  z-index:70;                       /* acima do header (60) — é a última coisa injetada */
  display:flex;align-items:center;gap:.25rem;
  /* width:max-content porque um fixed com left:50% encolhe para o espaço entre
     o offset e a borda direita (metade da viewport — medido: 188px a 375, texto
     em 4 linhas). Com max-content + o teto de max-width, a barra usa a largura
     do conteúdo até 92vw e o texto quebra no máximo em duas linhas. */
  width:max-content;
  max-width:min(92vw,30rem);
  padding:.3rem .3rem .3rem 1.15rem;
  background:var(--preto);
  border:1px solid var(--izi-20);
  border-radius:999px;
  box-shadow:0 12px 32px rgba(0,0,0,.35);
  color:var(--branco);
  font-size:clamp(.875rem,.8rem+.3vw,1rem);
  animation:langbar-entra .5s var(--ease-out) both;
}
@keyframes langbar-entra{from{opacity:0}to{opacity:1}}
/* Sem white-space:nowrap: a frase em inglês tem ~357px e a barra ~345px de teto
   a 375 de viewport (92vw) — medido; com nowrap ela estourava o pill. Deixada
   quebrar, vira duas linhas no mobile e continua uma só no desktop. */
.langbar__link{
  font-family:var(--font-display);
  font-weight:var(--display-wght);
  color:var(--izi);
  padding:.5em .4em;
}
.langbar__link:hover{text-decoration:underline}
/* 2.75rem = 44px: mesmo alvo de toque do .burger (WCAG 2.5.8 com folga) */
.langbar__close{
  width:2.75rem;height:2.75rem;
  flex:none;
  border-radius:50%;
  font-size:1.25rem;line-height:1;
  color:var(--branco);opacity:.7;
  transition:opacity var(--dur-fast) var(--ease-out);
}
.langbar__close:hover{opacity:1}
