/* ========================================================
   TRANSOFT — Identidade Visual
   ======================================================== */
:root{
  --bg-0:#05070d;
  --bg-1:#0a0e18;
  --bg-2:#0f1422;
  --surface:#11162338;
  --surface-2:#161c2e80;
  --border:#1c2440;
  --border-2:#243056;
  --text:#e7ecf6;
  --text-dim:#9aa5bf;
  --text-mute:#5f6a85;
  --primary:#0D6EE9;
  --primary-2:#3a8dff;
  --primary-glow:rgba(13,110,233,.55);
  --primary-soft:rgba(13,110,233,.12);
  --accent:#7cc4ff;
  --radius:14px;
  --radius-lg:22px;
  --shadow-glow:0 0 0 1px rgba(13,110,233,.25), 0 30px 90px -30px rgba(13,110,233,.55);
  --font-sans:"Raleway",system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  --font-display:"Raleway",sans-serif;
  --ease-out:cubic-bezier(.22,1,.36,1);
}

/* ========================================================
   RESET E BASE
   ======================================================== */
*,*::before,*::after{box-sizing:border-box}
/* overflow-x:hidden também no html (não só no body): em vários navegadores
   mobile é o <html>, não o <body>, quem controla o scroll horizontal da
   página — um body{overflow-x:hidden} sozinho nem sempre é suficiente pra
   suprimir o swipe horizontal quando algum descendente transborda. */
html{scroll-behavior:auto;-webkit-text-size-adjust:100%;overflow-x:hidden}
body{
  margin:0;
  font-family:var(--font-sans);
  background:var(--bg-0);
  color:var(--text);
  line-height:1.55;
  font-weight:400;
  letter-spacing:-.005em;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
img,svg,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer;border:0;background:none;color:inherit}
ul{list-style:none;margin:0;padding:0}
h1,h2,h3,h4,h5{font-family:var(--font-display);font-weight:600;letter-spacing:-.022em;margin:0;line-height:1.1}
p{margin:0}
::selection{background:var(--primary);color:#fff}

/* Grade e brilho ambiente globais */
body::before{
  content:"";
  position:fixed;inset:0;
  background:
    radial-gradient(800px 600px at 80% -10%, rgba(13,110,233,.18), transparent 60%),
    radial-gradient(700px 500px at -10% 30%, rgba(58,141,255,.10), transparent 60%),
    radial-gradient(900px 700px at 50% 110%, rgba(13,110,233,.12), transparent 60%);
  pointer-events:none;
  z-index:0;
}
body::after{
  content:"";
  position:fixed;inset:0;
  background-image:
    linear-gradient(rgba(255,255,255,.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.025) 1px, transparent 1px);
  background-size:60px 60px;
  mask-image:radial-gradient(ellipse at 50% 30%, #000 30%, transparent 75%);
  -webkit-mask-image:radial-gradient(ellipse at 50% 30%, #000 30%, transparent 75%);
  pointer-events:none;
  z-index:0;
}

/* container principal */
.container{
  width:100%;
  max-width:1240px;
  margin:0 auto;
  padding:0 28px;
  position:relative;
  z-index:1;
}

/* ========================================================
   NAVBAR — efeito vidro ao rolar
   ======================================================== */
.nav{
  position:fixed;
  top:0;left:0;right:0;
  z-index:100;
  padding:18px 0;
  transition:padding .35s var(--ease-out), border-color .35s var(--ease-out);
  border-bottom:1px solid transparent;
}
/* fundo/blur do header num pseudo-elemento à parte, não direto no .nav —
   `backdrop-filter` (e `filter`) num elemento cria um "containing block"
   novo pra qualquer descendente com position:fixed. .nav__menu (a gaveta
   mobile), .nav__close e .nav__toggle são todos position:fixed e
   descendentes de .nav — com o backdrop-filter direto no .nav, ao rolar a
   página (`.nav.scrolled` liga o backdrop-filter) o fixed desses elementos
   passava a ser relativo à CAIXA DO .nav (~90-120px de altura) em vez do
   viewport inteiro, então a gaveta ficava espremida/cortada dentro dessa
   altura pequena em vez de cobrir a tela toda — só acontecia com a página
   rolada porque só `.scrolled` tinha backdrop-filter (no topo, sem
   `.scrolled`, o .nav não tem filter nenhum, então o bug não aparece).
   Um ::before não é ancestral de .nav__menu/.nav__close/.nav__toggle
   (são todos irmãos dentro de .nav), então mover o backdrop-filter pra cá
   resolve sem tirar o efeito visual — o pseudo-elemento cobre a mesma
   área (inset:0) atrás de tudo (z-index:-1). */
.nav::before{
  content:'';
  position:absolute;inset:0;z-index:-1;
  background:transparent;
}
/* sem transition de background/backdrop-filter de propósito — pedido
   explícito do usuário: animar os dois juntos (opacidade do branco subindo
   ao mesmo tempo que o blur) passava por um estado intermediário de
   "vidro transparente" (branco parcial + blur parcial) bem visível antes
   de chegar no branco opaco final. A troca agora é instantânea junto com
   o toggle de `.scrolled` — sai do topo 100% transparente e vira vidro
   branco de uma vez, sem gradiente perceptível no meio do caminho. */
.nav.scrolled{
  padding:10px 0;
  border-bottom:1px solid rgba(11,15,26,.08);
  box-shadow:0 10px 40px -20px rgba(11,15,26,.25);
}
/* fundo branco glassmórfico ao rolar — pedido explícito do usuário, no
   lugar do vidro escuro que a barra usava antes (mesma técnica de sempre,
   só invertendo a paleta: branco quase opaco + blur, em vez de escuro). */
.nav.scrolled::before{
  background:rgba(255,255,255,.75);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
}
.nav__inner{
  display:flex;align-items:center;justify-content:space-between;gap:24px;
}
.brand{display:flex;align-items:center;gap:10px;font-family:var(--font-display);font-weight:700;font-size:20px;letter-spacing:-.02em}
.brand img,.brand video{height:34px;width:auto;display:block}
/* troca de logo ao rolar — pedido explícito do usuário: a logo negativa
   (branca, pensada pro fundo escuro/transparente do topo da página) some
   e dá lugar à colorida assim que a barra vira o vidro branco acima, pro
   contraste continuar bom. Os dois <video> ficam sempre carregados/
   tocando (nenhum dos dois usa display:none no sentido de pausar o
   vídeo) — só a visibilidade alterna via `.nav.scrolled`, sem precisar de
   JS pra trocar o `src` (evita qualquer recarregamento/flicker do vídeo
   a cada scroll).
   Bug real corrigido: `.nav__logo--colorida{display:none}` sozinha (1
   classe, especificidade 0,1,0) perdia pra `.brand video{display:block}`
   logo acima (1 classe + 1 elemento, 0,1,1) — resultado: as duas logos
   apareciam juntas no topo, já que o `display:none` nunca vencia a cascata.
   Escopado com `.brand` na frente (0,2,0) pra garantir que vença. */
.brand .nav__logo--colorida{display:none}
.nav.scrolled .nav__logo--negativa{display:none}
.nav.scrolled .nav__logo--colorida{display:block}
/* logo em vídeo do cabeçalho um pouco maior que a imagem estática (34px) —
   pedido do usuário pra dar pra ler o slogan "seu melhor prompt" que
   aparece no vídeo, que fica pequeno/ilegível no tamanho padrão. */
.brand video{height:84px}
.footer__brand .brand img.brand__img--full{height:32px}

.nav__menu{display:flex;align-items:center;gap:2px;white-space:nowrap}
.nav__item{position:relative}
.nav__link{
  position:relative;
  display:inline-flex;align-items:center;gap:6px;
  padding:10px 14px;
  font-size:14px;
  font-weight:500;
  color:var(--text-dim);
  transition:color .25s var(--ease-out);
  white-space:nowrap;
}
.nav__link::after{
  content:"";
  position:absolute;left:14px;right:14px;bottom:4px;
  height:1.5px;
  background:linear-gradient(90deg, var(--primary-2), var(--primary));
  border-radius:2px;
  transform-origin:right center;
  transform:scaleX(0);
  transition:transform .45s var(--ease-out);
}
.nav__link:hover::after{
  transform-origin:left center;
  transform:scaleX(1);
}
.nav__link.active{color:#fff}
.nav__link.active::after{transform:scaleX(1);transform-origin:left center}
.nav__link:hover{color:#fff}
.nav__link .chev{width:10px;height:10px;transition:transform .3s var(--ease-out)}
.nav__item:hover .chev{transform:rotate(180deg)}

.nav__sub{
  position:absolute;
  top:calc(100% + 14px);
  left:50%;
  transform:translateX(-50%) translateY(10px);
  min-width:320px;
  padding:10px;
  border-radius:16px;
  /* o backdrop-filter (blur) nesse elemento não está renderizando de forma
     confiável (reportado repetidas vezes pelo usuário — o menu continuava
     "vendo" o conteúdo atrás quase sem desfoque, mesmo com a receita
     idêntica à da barra de navegação). Pra garantir opacidade real sem
     depender só do blur, o fundo agora é quase sólido (.94) com um brilho
     diagonal sutil por cima (o gradient antes do rgba, de cima-esquerda pra
     baixo-direita) — é esse brilho, mais a borda clara e a sombra, que
     ainda vende a sensação de "vidro", mesmo sem o conteúdo de trás
     realmente aparecer desfocado atrás. isolation:isolate + backdrop-filter
     continuam aqui como reforço pra quando o navegador suportar de verdade. */
  isolation:isolate;
  background:
    linear-gradient(160deg, rgba(255,255,255,.07), rgba(255,255,255,0) 45%),
    rgba(8,11,20,.94);
  backdrop-filter:blur(18px) saturate(140%);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  border:1px solid rgba(255,255,255,.1);
  box-shadow:0 20px 60px -20px rgba(0,0,0,.6), 0 0 0 1px rgba(13,110,233,.08);
  opacity:0;visibility:hidden;
  transition:opacity .25s var(--ease-out), transform .25s var(--ease-out), visibility .25s;
}
.nav__item:hover .nav__sub,.nav__item:focus-within .nav__sub{
  opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);
}
.nav__sub::before{
  content:"";
  position:absolute;top:-6px;left:50%;transform:translateX(-50%) rotate(45deg);
  width:12px;height:12px;
  background:rgba(8,11,20,.94);
  border-left:1px solid rgba(255,255,255,.08);
  border-top:1px solid rgba(255,255,255,.08);
}
.nav__sub a{
  display:flex;align-items:flex-start;gap:12px;
  padding:12px 14px;
  border-radius:10px;
  transition:background .2s;
}
.nav__sub a:hover{background:rgba(13,110,233,.10)}
.nav__sub a::after{display:none}
.nav__sub .ico{
  width:36px;height:36px;flex:0 0 36px;
  border-radius:9px;
  background:linear-gradient(135deg,rgba(13,110,233,.18),rgba(58,141,255,.08));
  border:1px solid rgba(13,110,233,.25);
  display:grid;place-items:center;color:var(--primary-2);
}
.nav__sub .ico svg{width:18px;height:18px}
.nav__sub .t{font-size:14px;color:#fff;font-weight:600;display:block}
.nav__sub .d{font-size:12px;color:var(--text-mute);display:block;margin-top:2px}

/* botão do SAA: fica de fora do vocabulário visual dos outros CTAs do site
   de propósito (pedido do usuário) — o .btn--primary usa gradiente
   (--primary → --primary-2); aqui é cor sólida, chapada, num único tom
   (--primary), sem gradiente e sem transparência (a primeira tentativa foi
   um contorno em vidro, sutil demais pro gosto do usuário; a segunda foi
   fundo escuro sólido, que ele também não gostou). No hover, troca pra um
   azul mais claro/vívido (--primary-2), também sólido — uma transição de
   cor nítida, sem o efeito de "revelar gradiente" dos outros botões. */
.nav__cta{
  display:inline-flex;align-items:center;gap:7px;
  padding:10px 20px;
  border-radius:999px;
  font-weight:700;font-size:13px;letter-spacing:.04em;text-transform:uppercase;
  color:#fff !important;
  background:var(--primary);
  border:1.5px solid var(--primary);
  white-space:nowrap;
  position:relative;
  /* borda de luz estática — sobrou do efeito de pulso que existia antes (o
     usuário pediu pra tirar a animação, mas manter esse brilho parado).
     Três camadas em vez de um anel só (0 0 0 3px liso, que ficava "duro"):
     um filete fino e mais claro colado na borda, um anel mais largo e
     suave por fora dele, e um glow difuso (blur) por trás de tudo — dá
     profundidade de luz em vez de uma linha sólida. */
  box-shadow:
    0 0 0 1px rgba(124,196,255,.55),
    0 0 0 4px rgba(13,110,233,.22),
    0 0 20px rgba(13,110,233,.45);
  transition:color .3s var(--ease-out), background .3s var(--ease-out), border-color .3s var(--ease-out), box-shadow .3s var(--ease-out), transform .25s var(--ease-out);
}
.nav__cta::after{display:none !important}
.nav__cta svg{transition:transform .3s var(--ease-out)}
.nav__cta:hover{
  color:#fff !important;
  background:var(--primary-2);
  border-color:var(--primary-2);
  transform:translateY(-2px);
  box-shadow:
    0 0 0 1px rgba(124,196,255,.7),
    0 0 0 4px rgba(13,110,233,.3),
    0 0 26px rgba(13,110,233,.6),
    0 14px 36px -10px var(--primary-glow);
}
.nav__cta:hover svg{transform:translate(2px,-2px)}

.nav__toggle{
  display:none;width:44px;height:44px;border-radius:12px;
  border:1px solid rgba(255,255,255,.10);
  background:rgba(255,255,255,.04);
  position:relative;z-index:110;
  transition:background .25s, border-color .25s;
}
.nav__toggle:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.18)}
.nav__toggle span{display:block;width:18px;height:1.6px;background:#fff;margin:4px auto;transition:transform .3s var(--ease-out), opacity .25s, background .25s var(--ease-out)}
/* contraste do hambúrguer sobre o vidro branco — as linhas brancas e o
   selo translúcido claro (pensados pro topo escuro/transparente da
   página) ficariam praticamente invisíveis sobre `.nav.scrolled::before`
   (branco). Inverte pra tons escuros só nesse estado. */
.nav.scrolled .nav__toggle{
  border-color:rgba(11,15,26,.14);
  background:rgba(11,15,26,.04);
}
.nav.scrolled .nav__toggle:hover{background:rgba(11,15,26,.08);border-color:rgba(11,15,26,.22)}
.nav.scrolled .nav__toggle span{background:#0b0f1a}
.nav.open .nav__toggle span:nth-child(1){transform:translateY(5.6px) rotate(45deg)}
.nav.open .nav__toggle span:nth-child(2){opacity:0;transform:scaleX(0)}
.nav.open .nav__toggle span:nth-child(3){transform:translateY(-5.6px) rotate(-45deg)}

/* ------------------------------------------------------
   Menu "mobile" (gaveta + hambúrguer) — pedido explícito do
   usuário pra ser o único modo de navegação, em qualquer
   largura de tela (era antes um sistema responsivo que
   media se o menu desktop em linha única cabia — ver
   initNavFit() removida do main.js, CLAUDE.md). `.is-mobile`
   agora é aplicada incondicionalmente por um script inline
   síncrono (ver HTML, logo depois de </header>), sempre, já
   na primeira renderização — não há mais layout desktop
   nenhum pra "flashear".
   ------------------------------------------------------ */
.nav.is-mobile .nav__toggle{display:block}
/* some assim que a gaveta abre — o fechamento passa a ser só pelo
   .nav__close, que fica bem posicionado dentro da própria gaveta (ver
   abaixo). Evita ter dois controles parecidos (abrir/fechar) disputando
   espaço/atenção ao mesmo tempo. */
.nav.is-mobile.open .nav__toggle{display:none}
body.nav-open{overflow:hidden}
body.founder-modal-open{overflow:hidden}
body.craft-lightbox-open{overflow:hidden}

/* botão de fechar dedicado — elemento à parte do .nav__toggle (que só
   abre), fixo no mesmo canto onde a gaveta se ancora (right:0), então
   sempre cai bem alinhado dentro dela, em vez de depender de onde o
   toggle calhou de ficar na barra de navegação. Pedido explícito do
   usuário. */
.nav__close{
  display:none;
  position:fixed;top:18px;right:22px;
  width:40px;height:40px;border-radius:50%;
  align-items:center;justify-content:center;
  /* claro sobre a gaveta branca — o selo translúcido branco + ícone branco
     de antes eram pensados pra gaveta escura; invertido pra tons escuros
     (mesma técnica de contraste já usada no `.nav__toggle` sobre o vidro
     branco da barra, ver seção acima). */
  border:1px solid rgba(11,15,26,.14);
  background:rgba(11,15,26,.05);
  color:#0b0f1a;
  z-index:110;
  transition:background .25s var(--ease-out), border-color .25s var(--ease-out), transform .3s var(--ease-out);
}
.nav__close svg{width:18px;height:18px;display:block}
.nav__close:hover{background:rgba(13,110,233,.14);border-color:rgba(13,110,233,.4);transform:rotate(90deg)}
.nav.is-mobile.open .nav__close{display:flex}

.nav.is-mobile .nav__menu{
  position:fixed;top:0;right:0;bottom:0;
  width:min(400px,88vw);
  flex-direction:column;align-items:stretch;gap:2px;
  padding:100px 14px 40px 22px;
  /* gaveta branca glassmórfica — pedido explícito do usuário, pra
     acompanhar o mesmo vidro branco que a barra de navegação já ganhou ao
     rolar (ver "Barra de navegação — vidro branco..." no CLAUDE.md). Era
     um gradiente escuro; agora é quase-branco sólido (.98, mesmo motivo de
     opacidade alta do `.nav__sub` — backdrop-filter não é confiável em
     todo navegador) com o mesmo brilho azul radial sutil de antes por
     cima. Todos os elementos filhos (`.nav__link`, `.nav__sub`,
     `.nav__close` etc.) precisaram do mesmo tratamento claro→escuro já
     usado nas outras seções de tema claro do site (`--text-mute` no
     lugar de `--text-dim`, `#0b0f1a` no lugar de `#fff`). */
  background:
    radial-gradient(400px 200px at 100% 0%, rgba(13,110,233,.10), transparent 65%),
    rgba(255,255,255,.98);
  backdrop-filter:blur(24px) saturate(160%);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
  border-left:1px solid rgba(11,15,26,.08);
  transform:translateX(100%);
  transition:transform .45s var(--ease-out);
  overflow-y:auto;
  z-index:105;
  /* barra de rolagem discreta e personalizada, no lugar da padrão do navegador */
  scrollbar-width:thin;
  scrollbar-color:rgba(13,110,233,.55) transparent;
}
.nav.is-mobile .nav__menu::-webkit-scrollbar{width:5px}
.nav.is-mobile .nav__menu::-webkit-scrollbar-track{background:transparent}
.nav.is-mobile .nav__menu::-webkit-scrollbar-thumb{
  background:rgba(13,110,233,.5);border-radius:999px;
}
.nav.is-mobile .nav__menu::-webkit-scrollbar-thumb:hover{background:rgba(58,141,255,.7)}
/* box-shadow só quando a gaveta está aberta (não na regra base acima) —
   bug real reportado pelo usuário: com offset negativo (-40px, estende a
   sombra pra ESQUERDA do elemento) e 80px de blur, uma fatia da sombra
   continuava visível colada na borda direita da viewport mesmo com a
   gaveta fechada/fora da tela (translateX(100%) desloca a caixa inteira,
   sombra incluída, mas não o suficiente pra tirar o blur de vista) —
   uma "sombra fantasma" grudada na lateral direita em toda página, sempre,
   já que .nav__menu é position:fixed relativo à viewport, não a nenhuma
   seção. Escopando o box-shadow só pro estado .open, ele nunca é
   renderizado enquanto a gaveta está fechada, eliminando o vazamento. */
.nav.is-mobile.open .nav__menu{transform:translateX(0);box-shadow:-40px 0 80px -20px rgba(0,0,0,.6)}

.nav.is-mobile .nav__link{
  width:100%;
  padding:14px 18px;
  font-size:16px;
  font-weight:500;
  border-radius:12px;
  /* --text-mute no lugar de --text (que é quase-branco, pensado pro fundo
     escuro de antes) — mesma troca já usada em toda seção de tema claro
     do site (--text-mute dá ~5:1 de contraste sobre branco, --text/--text-dim
     ficam bem mais fracos). */
  color:var(--text-mute);
  transition:background .25s var(--ease-out), color .25s var(--ease-out), padding-left .25s var(--ease-out);
}
.nav.is-mobile .nav__link::after{display:none}
.nav.is-mobile .nav__link:hover{
  background:rgba(13,110,233,.10);
  color:#0b0f1a;
  padding-left:24px;
}
/* pill preenchida com o mesmo gradiente dos CTAs primários (.btn--primary/
   .nav__cta) pra "aqui é a página atual" ler mais como um estado sólido e
   óbvio, em vez da barrinha lateral + fundo quase transparente de antes
   (o usuário não gostou de como tinha ficado). Sem o padding-left extra
   do hover — a página atual já é uma âncora fixa, não precisa do mesmo
   "empurrão" de affordance que o hover usa pra sinalizar interatividade. */
.nav.is-mobile .nav__link.active{
  background:linear-gradient(135deg,var(--primary) 0%,var(--primary-2) 100%);
  color:#fff;
  box-shadow:0 8px 22px -10px var(--primary-glow);
}

.nav.is-mobile .nav__item{width:100%}
.nav.is-mobile .nav__item > .nav__link{justify-content:space-between}
/* submenu do Transnet: colapsado por padrão, abre em acordeão ao tocar no
   botão "Transnet" (JS alterna .is-open no .nav__item — ver initNav em
   main.js). Antes ficava sempre visível (position:static;opacity:1) e o
   próprio "Transnet" era um <a href="#"> que, por estar dentro do
   .nav__menu, disparava o fechamento da gaveta inteira ao ser tocado —
   bug corrigido junto (o gatilho virou <button>, que o listener de
   "fechar ao clicar em link" ignora). */
.nav.is-mobile .nav__sub{
  position:static;transform:none;
  box-shadow:none;background:rgba(11,15,26,.03);border:1px solid rgba(11,15,26,.07);
  min-width:0;
  border-radius:12px;
  max-height:0;opacity:0;visibility:hidden;overflow:hidden;
  padding:0 6px;margin:0;
  transition:max-height .35s var(--ease-out), opacity .25s var(--ease-out), margin .3s var(--ease-out), padding .3s var(--ease-out);
}
.nav.is-mobile .nav__item.is-open .nav__sub{
  max-height:640px;opacity:1;visibility:visible;
  padding:6px;margin:4px 0 8px;
}
.nav.is-mobile .nav__item.is-open > .nav__link .chev{transform:rotate(180deg)}
.nav.is-mobile .nav__sub::before{display:none}
.nav.is-mobile .nav__sub a{padding:12px}
/* selo do ícone: mesma receita de conversão claro→escuro já usada em
   .pillars-section--light .pillar__icon (tint neutro + cor --primary, no
   lugar do tint azul translúcido pensado pro fundo escuro). */
.nav.is-mobile .nav__sub .ico{
  width:32px;height:32px;flex:0 0 32px;
  background:rgba(11,15,26,.05);
  border-color:rgba(11,15,26,.09);
  color:var(--primary);
}
/* .t vem branco (#fff) na regra genérica de .nav__sub (pensada pro
   dropdown desktop escuro, hoje sem uso real já que o site inteiro roda
   em modo .is-mobile) — override aqui pra ficar escuro sobre a gaveta
   branca. */
.nav.is-mobile .nav__sub .t{font-size:13.5px;color:#0b0f1a}
.nav.is-mobile .nav__sub .d{font-size:11.5px}

.nav.is-mobile .nav__cta{
  margin-top:22px;
  justify-content:center;
  padding:16px 22px;
  font-size:15px;
  width:calc(100% - 8px);
}

/* escurecimento de fundo atrás da gaveta do menu */
.nav__backdrop{
  position:fixed;inset:0;
  background:rgba(3,5,10,.55);
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
  opacity:0;visibility:hidden;
  transition:opacity .35s var(--ease-out), visibility .35s;
  z-index:99;
}
.nav.is-mobile.open ~ .nav__backdrop{opacity:1;visibility:visible}

/* revelação escalonada dos itens do menu mobile */
.nav.is-mobile .nav__menu > *{
  opacity:0;
  transform:translateX(30px);
  transition:opacity .4s var(--ease-out), transform .4s var(--ease-out);
}
.nav.is-mobile.open .nav__menu > *{opacity:1;transform:translateX(0)}
.nav.is-mobile.open .nav__menu > *:nth-child(1){transition-delay:.10s}
.nav.is-mobile.open .nav__menu > *:nth-child(2){transition-delay:.15s}
.nav.is-mobile.open .nav__menu > *:nth-child(3){transition-delay:.20s}
.nav.is-mobile.open .nav__menu > *:nth-child(4){transition-delay:.25s}
.nav.is-mobile.open .nav__menu > *:nth-child(5){transition-delay:.30s}
.nav.is-mobile.open .nav__menu > *:nth-child(6){transition-delay:.35s}
.nav.is-mobile.open .nav__menu > *:nth-child(7){transition-delay:.40s}
.nav.is-mobile.open .nav__menu > *:nth-child(8){transition-delay:.45s}


/* ========================================================
   HERO
   ======================================================== */
.hero{
  position:relative;
  z-index:1; /* fica acima da grade/brilho global fixo (body::after, z-index:0),
                que senão pintaria por cima da seção — é conteúdo gerado, então
                fica por último entre os irmãos do mesmo nível de empilhamento
                e ficaria acima do hero (e do scroll-reel dentro dele) sem
                isso. */
  min-height:100vh;
  display:flex;align-items:center;
  padding:140px 0 80px;
  overflow:hidden;
  isolation:isolate;
}
.hero__bg{
  /* inset negativo pra dar folga ao blur do vídeo logo abaixo — sem essa
     margem, blur() amostra pixels além da borda do elemento e aparece uma
     franja mais clara bem no limite do vídeo (mesma pegadinha documentada
     em .page-header__bg/.erp-card__img); o .hero pai já tem overflow:hidden,
     então esse excesso é cortado sem sobrar nenhum vazio visível. */
  position:absolute;inset:-8px;z-index:-2;
}
.hero__video,
.hero__canvas{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  filter:blur(2px);
}
.hero__overlay{
  position:absolute;inset:0;z-index:-1;
  background:
    linear-gradient(90deg, rgba(5,7,13,.92) 0%, rgba(5,7,13,.65) 45%, rgba(5,7,13,.15) 70%, rgba(5,7,13,.35) 100%),
    linear-gradient(180deg, rgba(5,7,13,.35) 0%, transparent 30%, rgba(5,7,13,.8) 100%);
}
.hero__grid{
  display:grid;
  grid-template-columns:1.1fr .9fr;
  gap:60px;
  align-items:center;
}
/* dá mais espaço à coluna direita — pedido explícito do usuário pra o
   vídeo dos heroes de Gestão (dentro do .notebook-frame) ficar maior.
   Modificador em vez de mudar `.hero__grid` genérico, que os heroes
   com `.phone-frame` (super-app.html) e a logo (transnet-ia.html)
   continuam usando sem alteração. */
.hero__grid--video{grid-template-columns:1fr 1.15fr}
.hero__left{max-width:640px}

.hero__phrase{
  margin-top:22px;
  font-family:var(--font-display);
  font-size:clamp(28px,3.6vw,46px);
  line-height:1.1;
  font-weight:600;
  color:#fff;
  letter-spacing:-.025em;
  min-height:1.2em;
}
.hero__phrase .caret{
  display:inline-block;width:3px;height:.95em;vertical-align:-12%;
  margin-left:4px;background:var(--primary-2);
  animation:blink 1s steps(2) infinite;
}
@keyframes blink{50%{opacity:0}}

.hero__rotator{
  margin-top:14px;
  /* Corresponde ao font-size do hero__rotator-word (1.2 de line-height +
     .24em de padding) = 1.44x. O JS (fitWords) substitui isso pela altura
     real medida assim que as fontes carregam. */
  height:clamp(43.2px,6.624vw,86.4px);
  overflow-y:hidden;
  overflow-x:visible;
  position:relative;
  padding-bottom:8px;
  max-width:100%;
}
.hero__rotator-track{
  display:flex;flex-direction:column;
  padding-bottom:.15em;
  width:100%;
}
.hero__rotator-word{
  font-family:var(--font-display);
  font-weight:800;
  font-size:clamp(30px,4.6vw,60px);
  line-height:1.2;
  letter-spacing:-.03em;
  /* cor sólida (não mais degradê/animação — testado e descartado a pedido do
     usuário): azul vívido que contrasta bem com o fundo escuro do hero, sem
     cair pro lado ciano/turquesa. */
  color:var(--primary-2);
  white-space:nowrap;
  padding:.08em 2px .16em 0;
  overflow:visible;
}
@media (max-width:480px){
  .hero__rotator-word{font-size:clamp(24px,7.8vw,34px);white-space:normal;line-height:1.15}
}

.hero__sub{
  margin-top:28px;
  font-size:17px;color:var(--text-dim);max-width:520px;
}

.hero__actions{display:flex;gap:14px;margin-top:34px;flex-wrap:wrap}
.btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:14px 26px;
  border-radius:999px;
  font-weight:600;font-size:14.5px;
  transition:transform .25s var(--ease-out), box-shadow .25s, background .25s;
  position:relative;overflow:hidden;isolation:isolate;
}
.btn--primary{
  background:linear-gradient(135deg,var(--primary) 0%,var(--primary-2) 100%);
  color:#fff;
  box-shadow:0 12px 36px -10px var(--primary-glow), inset 0 0 0 1px rgba(255,255,255,.15);
}
.btn--primary::before{
  content:'';
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(135deg, var(--primary-2) 0%, #6fb1ff 100%);
  transform:scaleX(0);transform-origin:left center;
  transition:transform .45s var(--ease-out);
}
.btn--primary:hover::before{transform:scaleX(1)}
.btn--primary:hover{transform:translateY(-2px);box-shadow:0 20px 44px -12px var(--primary-glow)}
/* botões "Conhecer Soluções": degradê dinâmico no fundo (pedido do
   usuário) — fundo maior que o botão (background-size:300%) com a posição
   deslizando em loop, dá a sensação de um brilho correndo pela cor de
   fundo. Só nesses botões (classe extra .btn--solucoes, não em todo
   .btn--primary) — o resto dos CTAs primários do site continua com o
   gradiente estático de sempre. */
.btn--solucoes{
  background:linear-gradient(90deg,var(--primary) 0%,var(--primary-2) 33%,var(--accent) 66%,var(--primary) 100%);
  background-size:300% auto;
  animation:btnSolucoesShift 9s linear infinite;
}
@keyframes btnSolucoesShift{
  0%{background-position:0% 50%}
  100%{background-position:300% 50%}
}
@media (prefers-reduced-motion: reduce){
  .btn--solucoes{animation:none}
}
.btn--ghost{
  color:#fff;
  border:1px solid rgba(255,255,255,.12);
  background:rgba(255,255,255,.03);
  backdrop-filter:blur(10px);
}
.btn--ghost:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.22)}
.btn .arrow{transition:transform .25s}
.btn:hover .arrow{transform:translateX(3px)}

.hero__stats{
  display:flex;gap:38px;margin-top:48px;flex-wrap:wrap;
}
.hero__stat .n{font-family:var(--font-display);font-size:28px;font-weight:700;color:#fff;letter-spacing:-.02em}
.hero__stat .l{font-size:12.5px;color:var(--text-mute);text-transform:uppercase;letter-spacing:.12em;margin-top:4px}

.hero__right{position:relative;display:flex;align-items:center;justify-content:center}
/* reduz um pouco o vídeo institucional (logo_40_anos) reaproveitado aqui —
   .showcase__video é width:100% por padrão, então precisa desse limite
   específico só nesse contexto. */
.hero__right .showcase__video{width:78%}

/* cards de vidro flutuantes do lado direito */
.float-card{
  position:absolute;
  padding:18px;
  border-radius:18px;
  background:rgba(15,20,35,.55);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  border:1px solid rgba(255,255,255,.08);
  box-shadow:0 30px 80px -30px rgba(0,0,0,.7);
  will-change:transform;
  cursor:grab;
  touch-action:none;
  user-select:none;
}
.float-card.is-dragging{
  cursor:grabbing;
  box-shadow:0 40px 100px -30px rgba(0,0,0,.85);
  z-index:20;
}
/* botão "x" pra estourar/fechar o balão — pedido explícito do usuário.
   position:absolute (o próprio .float-card já é um elemento posicionado,
   serve de containing block sem precisar de position:relative extra),
   canto superior direito, por cima do conteúdo (z-index maior que o
   texto interno, que não tem z-index próprio). touch-action:auto (não
   herda o touch-action:none do card, que existe só pra liberar o gesto
   de arrastar) — sem isso um toque no "x" no mobile poderia ser
   interpretado como início de arrasto em vez de tap. */
.float-card__close{
  position:absolute;top:8px;right:8px;z-index:3;
  width:22px;height:22px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.14);
  color:var(--text-dim);
  cursor:pointer;touch-action:auto;
  transition:background .2s,color .2s,border-color .2s;
}
.float-card__close svg{width:11px;height:11px;pointer-events:none}
.float-card__close:hover{background:rgba(220,38,38,.22);border-color:rgba(220,38,38,.5);color:#fff}
/* animação de "estourar" — só o fallback sem GSAP usa isso via classe;
   com GSAP disponível, initFloatCardsClose() anima via gsap.to() direto
   (ver main.js), porque o card já tem duas tweens contínuas do GSAP
   (deriva + parallax, ambas mexendo em transform) rodando nele o tempo
   todo — uma @keyframes CSS mexendo em transform ao mesmo tempo brigaria
   com o GSAP. O JS sempre mata essas tweens (gsap.killTweensOf) antes de
   iniciar o "estouro", então as duas abordagens nunca se sobrepõem. */
@keyframes floatCardPop{
  0%{transform:scale(1);opacity:1}
  40%{transform:scale(1.12);opacity:1}
  100%{transform:scale(.2);opacity:0}
}
.float-card.is-popping{animation:floatCardPop .35s var(--ease-out) forwards;pointer-events:none}
.float-card .h{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.float-card .h .ic{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,var(--primary),var(--primary-2));display:grid;place-items:center;color:#fff}
.float-card .h .ic svg{width:16px;height:16px}
/* balões de "Ecossistema Transoft" reaproveitam .ic--logo (mesma classe
   já usada nos itens de logo da lista .showcase__list, ver seção
   "Seção 'Uma empresa de tecnologia...'" no CLAUDE.md) — essa regra
   específica (mesma especificidade de .float-card .h .ic acima, 3
   classes, mas declarada depois) sobrescreve o quadrado fixo 32x32
   genérico pra manter a largura automática que os logos precisam. */
.float-card .h .ic--logo{width:auto;height:36px;padding:0 10px}
.float-card .h .ic--logo img{max-height:18px;max-width:100px}
.float-card .h .t{font-size:13px;color:var(--text-dim)}
.float-card .v{font-family:var(--font-display);font-weight:700;font-size:24px;color:#fff;letter-spacing:-.02em}
.float-card .s{font-size:12px;color:var(--primary-2);margin-top:4px;font-weight:600}
/* descrição de produto (balões do "Ecossistema Transoft") — texto mais
   longo que o .s original (que era só uma métrica curta tipo "+12% vs
   ontem"), por isso cor mais neutra e sem negrito, pra não brigar com o
   nome do produto (.v) logo acima. */
.float-card__desc{font-size:12px;color:var(--text-dim);margin-top:6px;line-height:1.5}

.fc-1{top:6%;right:6%;width:230px}
.fc-2{top:42%;right:36%;width:260px}
.fc-3{bottom:8%;right:0%;width:250px}
/* posições próprias pro contexto do "Ecossistema Transoft" — o container
   (.showcase__visual--floatcards) é bem menor que o .hero__right
   original, então os 3 balões precisam de um arranjo mais compacto. */
.showcase__visual--floatcards .fc-1{top:8%;right:8%;width:220px}
.showcase__visual--floatcards .fc-2{top:40%;left:6%;width:210px}
.showcase__visual--floatcards .fc-3{bottom:6%;right:12%;width:215px}

/* barrinhas do mini gráfico */
.fc-chart{display:flex;align-items:flex-end;gap:5px;height:46px;margin-top:10px}
.fc-chart i{display:block;flex:1;border-radius:3px;background:linear-gradient(180deg,var(--primary-2),var(--primary));opacity:.85}

@media (max-width:980px){
  .hero{padding:120px 0 60px}
  .hero__grid{grid-template-columns:1fr;gap:48px}
  .hero__overlay{background:linear-gradient(180deg, rgba(5,7,13,.3) 0%, rgba(5,7,13,.85) 60%, rgba(5,7,13,.95) 100%)}
  .hero__right{display:none}
}

/* ========================================================
   SEÇÕES / GENÉRICO
   ======================================================== */
.section{padding:120px 0;position:relative}
.section--tight{padding:90px 0}

.particles-bg{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.particles-bg canvas{display:block;width:100%;height:100%}
.section__head{text-align:center;max-width:760px;margin:0 auto 70px}
/* só o título da seção de depoimentos ("Como Transformamos sua Gestão")
   precisa ficar numa linha só — nowrap direto no h2 (não no
   .section__head inteiro), pra não alargar também o parágrafo de apoio
   logo abaixo, que pode continuar quebrando normalmente. */
#depoimentos .section__title{white-space:nowrap}
/* modificador genérico pra qualquer outro título de seção que precise
   ficar numa linha só (ex.: "O Módulo Administrativo entrega", que
   quebrava em duas linhas por causa do max-width:760px do
   .section__head) — mesma técnica do nowrap de #depoimentos acima,
   só reaproveitável sem precisar de um seletor por id. */
.section__title--nowrap{white-space:nowrap}
@media (max-width:640px){
  /* em telas pequenas o nowrap acima estouraria a largura da viewport —
     volta a quebrar normalmente, igual aos outros títulos de seção. */
  #depoimentos .section__title{white-space:normal}
  .section__title--nowrap{white-space:normal}
}
.section__head.left{text-align:left;margin-left:0}
/* pequeno rótulo azul acima do título de seção — genérico, reaproveitável
   em qualquer .section__head (estreado na seção de valores do sobre.html,
   "Nossos valores" acima de "No que a Transoft acredita"). .section__title
   já tem margin-top:18px, que cuida sozinho do espaçamento abaixo deste
   rótulo sem precisar de margin extra aqui. */
.section__eyebrow{
  display:block;
  font-size:13px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-dim);font-weight:700;
}
.section__title{
  font-size:clamp(32px,3.6vw,52px);
  margin-top:18px;color:#fff;
  font-weight:700;letter-spacing:-.025em;
}
.section__title span{
  color:var(--primary-2);
}
.section__lead{margin-top:18px;color:var(--text-dim);font-size:17px;line-height:1.6}

/* ========================================================
   MARQUEE — segmentos
   ======================================================== */
.marquee{
  position:relative;
  padding:38px 0;
  overflow:hidden;
}
.marquee::before,.marquee::after{
  content:"";position:absolute;top:0;bottom:0;width:140px;z-index:2;pointer-events:none;
}
.marquee::before{left:0;background:linear-gradient(90deg,var(--bg-0),transparent)}
.marquee::after{right:0;background:linear-gradient(-90deg,var(--bg-0),transparent)}
.marquee__track{
  display:flex;gap:60px;width:max-content;
  animation:marqueeScroll var(--marquee-duration,32s) linear infinite;
}
.marquee__set{display:flex;gap:60px}
.marquee__item{
  display:flex;align-items:center;gap:14px;
  font-family:var(--font-display);font-weight:600;font-size:22px;color:var(--text-dim);
  white-space:nowrap;
}
.marquee__item svg{width:22px;height:22px;color:var(--primary-2);flex-shrink:0}
/* variante do marquee pra logos de clientes (sobre.html, "Empresas que
   confiam em nós") — reaproveita o mesmo .marquee/[data-marquee-track]
   genérico (initMarquee() já clona qualquer .marquee__set que encontrar,
   sem precisar de mudança nenhuma no JS), só troca o conteúdo do
   .marquee__set de texto+ícone por <img> direto. Mesmo tratamento
   "dim → branco no hover" do .clients-strip da home. */
.marquee__logo{height:72px;width:auto;object-fit:contain;opacity:.5;transition:opacity .3s;flex-shrink:0}
.marquee__logo:hover{opacity:1}
/* gap maior só nesta instância — os logos ficaram bem maiores (72px, ver
   .marquee__logo acima) e o gap:60px genérico (compartilhado com a faixa de
   texto "Urbano · Fretamento..." da home) ficava apertado demais nesta
   escala. Escopado do mesmo jeito que o resto dos overrides desta seção. */
.clients-marquee-section .marquee__track,
.clients-marquee-section .marquee__set{gap:88px}
.clients-marquee__btn{margin-top:32px}
@keyframes marqueeScroll{to{transform:translateX(var(--marquee-shift,-50%))}}

/* ========================================================
   CONHEÇA NOSSO FUNDADOR (sobre.html) — resumo + modal "BioWiki"
   ======================================================== */
.founder{max-width:800px}
.founder__lead{margin-top:18px;color:var(--text-dim);font-size:16px;line-height:1.75}
.founder__lead strong{color:#fff;font-weight:700}
.founder__lead strong.founder__hl{color:var(--primary-2)}
/* Layout conferido direto na página de referência real
   (tecnomobile.com.br/sobre-nos — o usuário apontou que as tentativas
   anteriores, "adivinhando" pelas capturas, não batiam com o site de
   verdade). Duas correções que só ficaram claras vendo o HTML fonte:
   1) a foto NÃO é cortada por uma caixa de altura fixa — lá é só
      max-width:130px com altura automática (a imagem aparece inteira, do
      jeito que o arquivo é, sem object-fit nenhum). Removido o cálculo de
      altura fixa/object-fit:cover que eu tinha colocado antes.
   2) o botão "Visualizar BioWiki" fica DENTRO da coluna de nome/cargo
      (abaixo do "CEO"), não numa linha separada por baixo de tudo — a
      foto fica à esquerda, alinhada ao centro vertical dessa coluna
      inteira (foto + nome/cargo/botão), não só do nome. */
.founder__profile{display:flex;align-items:center;gap:24px;flex-wrap:wrap;margin-top:36px}
.founder__photo{width:100%;max-width:130px;height:auto;display:block;border-radius:15px;flex-shrink:0;box-shadow:3px 2px 16px -4px rgba(0,0,0,.5)}
.founder__info{display:flex;flex-direction:column;align-items:flex-start}
.founder__name{font-weight:700;color:#fff;font-size:18px;line-height:1.3}
.founder__role{color:var(--text-dim);font-size:14px;margin-top:4px;margin-bottom:18px}

/* modal "BioWiki" — estrutura copiada da referência enviada pelo usuário
   (foto grande à esquerda + card de conteúdo à direita, tag/nome/cargo,
   texto rolável, ícone do LinkedIn no canto inferior direito, botão de
   fechar circular flutuando no canto superior direito, fundo desfocado),
   com as cores adaptadas pra identidade escura do site em vez do card
   branco da referência. Mesma técnica de overlay fixed+backdrop-filter já
   usada no .nav__backdrop do menu mobile. */
.founder-modal{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:center;justify-content:center;
  padding:24px;
  opacity:0;visibility:hidden;
  transition:opacity .35s var(--ease-out), visibility .35s;
}
.founder-modal.is-open{opacity:1;visibility:visible}
.founder-modal__backdrop{
  position:absolute;inset:0;
  background:rgba(3,5,10,.72);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
/* altura fixa (não max-height) — conferido no CSS de origem
   (#biowikModal .modal-dialog{height:407px} no desktop), é a altura do
   modal que é fixa, não a largura da coluna da foto (ver .founder-modal__photo
   abaixo). Usei 420px (bem perto do 407px original) com min() só de
   segurança pra não estourar em telas curtas, o que a referência não
   tinha — telas muito baixas ali provavelmente já vazavam também. */
.founder-modal__box{
  position:relative;display:flex;
  width:100%;max-width:820px;height:min(420px,82vh);
  border-radius:24px;overflow:hidden;
  background:linear-gradient(180deg, rgba(15,20,35,.98) 0%, rgba(8,12,22,.98) 100%);
  border:1px solid rgba(255,255,255,.08);
  box-shadow:0 40px 100px -30px rgba(0,0,0,.7);
  transform:translateY(24px) scale(.97);opacity:0;
  transition:transform .4s var(--ease-out), opacity .4s var(--ease-out);
}
.founder-modal.is-open .founder-modal__box{transform:translateY(0) scale(1);opacity:1}
.founder-modal__close{
  position:absolute;top:16px;right:16px;z-index:2;
  width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  color:#fff;transition:background .25s;
}
.founder-modal__close:hover{background:rgba(255,255,255,.18)}
.founder-modal__close svg{width:16px;height:16px}
/* foto: ALTURA 100% do modal, LARGURA automática (acompanha a proporção
   real da imagem) — não o contrário. No CSS de origem é literalmente
   `#biowikModal .modal-img-biowiki{height:100% !important;width:auto}`;
   minha primeira tentativa tinha invertido essa relação (coluna de
   largura fixa, foto encaixada dentro via object-fit), o que podia sobrar
   espaço vazio do lado da foto em vez dela preencher naturalmente. */
.founder-modal__photo-col{flex:0 0 auto;height:100%}
.founder-modal__photo{height:100%;width:auto;object-fit:cover;display:block}
.founder-modal__content{flex:1;min-width:0;display:flex;flex-direction:column;padding:32px 36px}
.founder-modal__head{padding-bottom:20px;border-bottom:1px solid rgba(255,255,255,.08)}
.founder-modal__tag{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--text-dim)}
.founder-modal__name{font-family:var(--font-display);font-weight:700;font-size:20px;color:#fff;margin-top:6px}
.founder-modal__role{color:var(--text-dim);font-size:14px;margin-top:2px}
/* min-height:0 é necessário aqui: sem isso, um filho flex com flex:1
   dentro de um pai flex-column (.founder-modal__content) nunca encolhe
   abaixo da altura do próprio conteúdo, e o overflow-y:auto nunca chega a
   rolar de verdade — pegadinha clássica de flexbox. */
/* barra de rolagem discreta e personalizada, mesmo padrão já usado no
   .nav__menu mobile — track transparente (deixa o fundo escuro do próprio
   modal aparecer, em vez da barra branca padrão do navegador) com só a
   barrinha arrastável (thumb) visível. */
.founder-modal__body{flex:1;min-height:0;overflow-y:auto;margin-top:20px;padding-right:8px;scrollbar-width:thin;scrollbar-color:rgba(13,110,233,.55) transparent}
.founder-modal__body::-webkit-scrollbar{width:5px}
.founder-modal__body::-webkit-scrollbar-track{background:transparent}
.founder-modal__body::-webkit-scrollbar-thumb{background:rgba(13,110,233,.5);border-radius:999px}
.founder-modal__body::-webkit-scrollbar-thumb:hover{background:rgba(58,141,255,.7)}
.founder-modal__body p{font-size:14.5px;color:var(--text-dim);line-height:1.7;margin-bottom:14px}
.founder-modal__body p:last-child{margin-bottom:0}
.founder-modal__linkedin{
  align-self:flex-end;flex-shrink:0;margin-top:16px;
  width:34px;height:34px;border-radius:8px;
  display:grid;place-items:center;
  background:#0a66c2;color:#fff;
}
.founder-modal__linkedin svg{width:18px;height:18px}
/* abaixo de 576px o site de origem troca a foto retangular inteira por um
   avatar circular pequeno e recortado (150×150, object-fit:cover,
   object-position:top pra manter o rosto enquadrado) — mesmo breakpoint e
   valores exatos do CSS real (#biowikModal .modal-img-biowiki{height:150px;
   width:150px} + >img{border-radius:100%;object-fit:cover;object-position:top}).
   Diferente do resto (altura 100%/largura auto), aqui a referência crop a
   foto de propósito, então reproduzi o crop também em vez de manter
   "sempre inteira" a qualquer custo. */
@media (max-width:575px){
  .founder-modal__box{flex-direction:column;height:auto;max-height:90vh}
  .founder-modal__photo-col{height:auto;flex:0 0 auto;padding-top:28px;display:flex;justify-content:center}
  .founder-modal__photo{width:110px;height:110px;border-radius:50%;object-fit:cover;object-position:top}
  .founder-modal__content{padding:24px}
}

/* ========================================================
   REDES SOCIAIS (sobre.html) — seção abaixo de "Conheça nosso fundador"
   ======================================================== */
.social-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:22px;
  margin-top:10px;
}
/* mesma técnica de anel-de-gradiente-só-no-hover já usada em .integ-card
   (mask-composite:exclude) — reaproveitada aqui pra manter os cards
   visualmente na mesma linguagem do resto do site, sem inventar um
   componente novo do zero. */
.social-card{
  position:relative;isolation:isolate;
  padding:28px;
  border-radius:var(--radius-lg);
  background:rgba(15,20,35,.4);
  border:1px solid rgba(255,255,255,.07);
  transition:transform .35s var(--ease-out), border-color .35s, box-shadow .35s;
}
.social-card::before{
  content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1.5px;
  background:linear-gradient(135deg, var(--primary) 0%, var(--primary-2) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:0;transition:opacity .35s;
  pointer-events:none;
}
.social-card:hover{
  transform:translateY(-6px);
  border-color:transparent;
  box-shadow:0 24px 48px -20px rgba(5,7,13,.6);
}
.social-card:hover::before{opacity:1}
/* .social-grid usa .reveal-stagger (não .reveal por card) — a regra
   genérica `.reveal-stagger.in > *{transform:none}` (ver seção "Reveal ao
   rolar") empata em especificidade com `.social-card:hover` (duas classes
   contando o pseudo-classe cada) e vem depois no arquivo, então vencia e
   cancelava o "subir" no hover depois do card já ter entrado em vista —
   mesmo conflito já documentado nos cards do ERP (`.erp-card.reveal.in:
   hover`). Correção: especificidade extra de propósito, três classes. */
.social-grid.reveal-stagger .social-card:hover{transform:translateY(-6px)}

.social-card__top{display:flex;align-items:center;gap:16px}
/* selo do ícone neutro (sem cor de marca nem hover próprio) — pedido
   explícito do usuário depois de ver a versão com selo colorido por rede
   e leve escala/rotação no hover; mesmo tratamento visual de outros
   selos de ícone do site (ex.: .tl-mark__icon). */
.social-card__icon{
  width:52px;height:52px;flex-shrink:0;border-radius:14px;
  display:grid;place-items:center;
  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.1);
  color:var(--primary-2);
  transition:background .15s, border-color .15s, color .15s;
}
.social-card__icon svg{width:24px;height:24px}

.social-card__info{display:flex;flex-direction:column;min-width:0}
.social-card__name{font-weight:700;color:#fff;font-size:16px;transition:color .15s}
.social-card__handle{color:var(--text-dim);font-size:13.5px;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:color .15s}

.social-card__btn{width:100%;justify-content:center;margin-top:22px;transition:transform .25s var(--ease-out), box-shadow .25s, background .15s, color .15s, border-color .15s}

/* Fundo claro sólido da seção, pedido explícito do usuário.
   `position:relative;z-index:1` pelo motivo de sempre: sem isso a grade
   ambiente global (`body::after`, fixed/z-index:0) pintaria por cima do
   fundo sólido em vez de ficar atrás dele. */
.social-section{position:relative;z-index:1;background:#e2e7f0}
.social-section .section__title{color:#0b0f1a}
.social-section .social-card{background:#e9edf5;border-color:rgba(11,15,26,.08);transition:background-color .15s, transform .35s var(--ease-out), border-color .15s, box-shadow .35s}
.social-section .social-card__icon{background:rgba(11,15,26,.05);border-color:rgba(11,15,26,.09);color:var(--primary)}
.social-section .social-card__name{color:#0b0f1a}
.social-section .social-card__handle{color:var(--text-mute)}
.social-section .social-card__btn{color:#0b0f1a;border-color:rgba(11,15,26,.16);background:rgba(11,15,26,.03)}
/* Hover: em vez do anel de gradiente (::before, ver receita genérica do
   .social-card acima), o card claro "vira" escuro — pedido explícito do
   usuário ("a cor do card se altere para um azul mais escuro"). Precisa
   desligar o ::before herdado (`opacity:0` vence o `opacity:1` da regra
   genérica por ter mais especificidade) e reescrever a cor de cada
   elemento filho pro par claro-sobre-escuro, já que o texto/ícone/botão
   dessa seção foram pensados pra ficar sobre um card claro. */
.social-section .social-card:hover{
  background:#0d1f3d;
  border-color:transparent;
  box-shadow:0 24px 48px -20px rgba(5,7,13,.45);
}
.social-section .social-card:hover::before{opacity:0}
.social-section .social-card:hover .social-card__icon{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14);color:var(--primary-2)}
.social-section .social-card:hover .social-card__name{color:#fff}
.social-section .social-card:hover .social-card__handle{color:var(--text-dim)}
.social-section .social-card:hover .social-card__btn{color:#fff;border-color:rgba(255,255,255,.18);background:rgba(255,255,255,.06)}
.social-section .social-card:hover .social-card__btn:hover{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.34)}

/* ========================================================
   CARDS DE FUNCIONALIDADES / GRADE DE MÓDULOS
   ======================================================== */
.grid{display:grid;gap:22px}
.grid--3{grid-template-columns:repeat(3,1fr)}
.grid--4{grid-template-columns:repeat(4,1fr)}
.grid--2{grid-template-columns:repeat(2,1fr)}
@media (max-width:1024px){.grid--4{grid-template-columns:repeat(2,1fr)}.grid--3{grid-template-columns:repeat(2,1fr)}}
@media (max-width:680px){.grid--4,.grid--3,.grid--2{grid-template-columns:1fr}}

.card{
  position:relative;
  padding:32px;
  border-radius:var(--radius-lg);
  background:linear-gradient(180deg, rgba(20,26,42,.55) 0%, rgba(12,16,28,.55) 100%);
  border:1px solid rgba(255,255,255,.06);
  overflow:hidden;
  transition:border-color .35s, transform .35s var(--ease-out);
  isolation:isolate;
}
.card::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:radial-gradient(420px 220px at var(--mx,50%) var(--my,0%), rgba(13,110,233,.18), transparent 65%);
  opacity:0;transition:opacity .35s;
}
.card:hover{transform:translateY(-4px);border-color:rgba(13,110,233,.35)}
.card:hover::before{opacity:1}
.card__icon{
  width:50px;height:50px;border-radius:13px;
  display:grid;place-items:center;
  background:linear-gradient(135deg, rgba(13,110,233,.22), rgba(58,141,255,.10));
  border:1px solid rgba(13,110,233,.35);
  color:var(--primary-2);
  margin-bottom:22px;
  box-shadow:inset 0 0 20px rgba(13,110,233,.18);
}
.card__icon svg{width:22px;height:22px}
.card__title{font-size:19px;color:#fff;font-weight:600;margin-bottom:10px;letter-spacing:-.01em}
.card__text{color:var(--text-dim);font-size:14.5px;line-height:1.6}
.card__link{
  display:inline-flex;align-items:center;gap:6px;
  margin-top:18px;font-size:13px;font-weight:600;color:var(--primary-2);
  letter-spacing:.02em;
}
.card__link svg{width:14px;height:14px;transition:transform .25s}
.card__link:hover svg{transform:translateX(3px)}

/* ========================================================
   STRIPE / SHOWCASE (imagem de notebook)
   ======================================================== */
/* fica acima da grade/brilho global fixo (body::after, z-index:0) — mesma
   pegadinha de empilhamento documentada pro .hero no CLAUDE.md. Necessário
   aqui agora que essa seção hospeda o scroll-reel. */
#sobre-resumo{z-index:1}
.showcase{
  display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:center;
}
.showcase__visual{
  position:relative;border-radius:24px;overflow:hidden;
  background:linear-gradient(180deg,#0c1224 0%, #050810 100%);
  border:1px solid rgba(255,255,255,.06);
  padding:30px;
  box-shadow:0 50px 100px -40px rgba(0,0,0,.7);
}
.showcase__visual::before{
  content:"";position:absolute;inset:-1px;border-radius:24px;padding:1px;
  background:linear-gradient(135deg,rgba(13,110,233,.4),transparent 50%,rgba(13,110,233,.2));
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;
}
.showcase__visual--video{
  padding:0;display:flex;align-items:center;justify-content:center;
  background:transparent;box-shadow:none;border:none;
}
.showcase__visual--video::before{display:none}
.showcase__video{width:100%;height:auto;display:block}

/* prints reais das telas do Transnet (assets/img/telas-transnet/*.webp) no
   lugar do .dash (mockup de gráfico falso) na 2ª seção das 3 páginas de
   Gestão — mesmo tratamento "sem cartão" do .showcase__visual--video, já
   que os prints já vêm com sombra/perspectiva própria (composição de 3
   telas em ângulo) sobre fundo transparente; um card por baixo só
   duplicaria a sombra e destoaria. */
.showcase__visual--screens{
  padding:0;display:flex;align-items:center;justify-content:center;
  background:transparent;box-shadow:none;border:none;
  overflow:visible;isolation:isolate;
}
.showcase__visual--screens::before{display:none}
/* iluminação atrás dos prints — pedido explícito do usuário ("coloque uma
   iluminação atrás das imagens das telas que ficam à direita do texto").
   Mesma receita do .ia-hero-visual::before (glow radial bem desfocado, sem
   nenhuma aresta reta, isolation:isolate + z-index:-1 pra ficar atrás do
   <img> sem depender de ordem no DOM): overflow, que a base .showcase__visual
   deixa em hidden, precisou virar visible aqui — do contrário o glow
   (inset negativo, de propósito maior que a própria imagem) seria cortado
   pela borda arredondada do card antes de conseguir "vazar" ao redor do
   print. */
.showcase__visual--screens::after{
  content:"";position:absolute;inset:-15% -10%;z-index:-1;
  background:radial-gradient(closest-side, rgba(13,110,233,.4), transparent 70%);
  filter:blur(60px);
  pointer-events:none;
}
.showcase__img{width:100%;height:auto;display:block}

/* Fundo da seção "Uma empresa de tecnologia..." (não do card à direita,
   que continua com sua própria foto — ver .showcase__visual--floatcards
   logo abaixo) — pedido explícito do usuário. Véu escuro (::before,
   z-index:0) garante contraste do texto por cima; .container já é
   z-index:1 globalmente (ver topo do arquivo), então nada mais precisa
   de ajuste. */
.empresa-section{
  position:relative;z-index:1;overflow:hidden;
  background-image:url('../img/background_bulcao_igrejinha.webp');
  background-size:cover;background-position:center;
}
.empresa-section::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:rgba(5,7,13,.87);
}
/* Contraste reforçado em 2 camadas — véu mais opaco (acima) já resolve a
   maior parte, mas texto branco/cinza direto sobre foto ainda corre risco
   em trechos mais claros dela; text-shadow garante legibilidade mesmo
   ali, mesma técnica já usada no rótulo dos .ramo-panel. */
.empresa-section .section__title{text-shadow:0 4px 18px rgba(0,0,0,.55)}
.empresa-section .section__lead{
  color:rgba(255,255,255,.85);
  text-shadow:0 2px 10px rgba(0,0,0,.5);
}

/* "Ecossistema Transoft" reaproveitando os balões flutuantes/arrastáveis
   (.float-card, ver "Estatísticas flutuantes" no CLAUDE.md) no lugar do
   .dash quadrado — pedido explícito do usuário ("esse quadrado feio e
   nada moderno"). Precisa de altura própria pra ancorar os .float-card
   (position:absolute), mesmo raciocínio já usado no
   .showcase__visual--scrollreel logo abaixo. */
.showcase__visual--floatcards{
  height:760px;
  background-image:url('../img/sala_reuniao.webp');
  background-size:cover;
  background-position:center;
}
/* véu escuro por cima da foto — mesma técnica de camadas por z-index já
   documentada em outras seções do site (.tl-slide, .erp-card): foto
   (background-image do próprio elemento, sempre atrás de tudo) → véu
   (::after, z-index:0) → rótulo/balões (z-index:1/2). Sem o véu, o
   rótulo "Ecossistema Transoft" e o texto dos balões perderiam contraste
   dependendo do trecho da foto atrás deles. */
.showcase__visual--floatcards::after{
  content:'';position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg, rgba(5,7,13,.8) 0%, rgba(5,7,13,.6) 45%, rgba(5,7,13,.88) 100%);
}
/* rótulo "Ecossistema Transoft · 3 produtos" — fica atrás dos balões mas
   na frente do véu, ancorado no canto superior esquerdo do card, dando
   contexto pro que os 3 balões representam sem precisar de outro card. */
.showcase__eco{
  position:absolute;top:30px;left:30px;z-index:1;
  display:flex;align-items:center;gap:10px;
}
.showcase__visual--floatcards .float-card{z-index:2}
.showcase__eco-label{font-size:13px;color:var(--text-dim);font-weight:600}
.showcase__eco-pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--primary-2);background:rgba(13,110,233,.12);border:1px solid rgba(13,110,233,.3)}

/* reel de sequência de frames controlado pelo scroll (movido pra cá do
   hero — ver CLAUDE.md). Mesmo tratamento "sem cartão" do
   .showcase__visual--video: os frames já vêm com fundo transparente
   recortado, então o veículo flutua direto sobre a seção em vez de ficar
   num painel. Um fundo escuro radial suave (::before) fica atrás só por
   contraste/legibilidade, sem parecer um cartão com bordas duras.
   Diagramado exatamente como era no hero: coluna-âncora de altura fixa +
   um reel maior que o normal, posicionado de forma absoluta — NÃO é o
   dimensionamento simples de 100%-da-coluna que .showcase__visual--video
   usa. overflow:visible sobrescreve o overflow:hidden herdado de
   .showcase__visual, que estava cortando o reel ampliado (por isso ele
   parecia cortado antes disso). */
.showcase__visual--scrollreel{
  padding:0;background:transparent;box-shadow:none;border:none;
  overflow:visible;
  position:relative;
  height:560px;
}
.showcase__visual--scrollreel::before{display:none}
.scrollreel{
  position:absolute;
  top:50%;
  right:-22%;
  width:min(170%, 950px);
  aspect-ratio:5/3;
  transform:translateY(-50%);
  z-index:4;
  pointer-events:none;
}
.scrollreel::before{
  content:'';
  position:absolute;
  inset:-10%;
  background:radial-gradient(ellipse at center, rgba(5,7,13,.45) 0%, rgba(5,7,13,.22) 50%, transparent 75%);
  z-index:-1;
}
.scrollreel-canvas{display:block;width:100%;height:100%}

.showcase__list{display:flex;flex-direction:column;gap:14px}
.showcase__item{
  display:flex;gap:14px;padding:18px;border-radius:14px;
  background:rgba(255,255,255,.025);border:1px solid rgba(255,255,255,.05);
  transition:background .25s, border-color .25s, transform .25s;
}
.showcase__item:hover{background:rgba(13,110,233,.08);border-color:rgba(13,110,233,.25);transform:translateX(6px)}
.showcase__item .ic{
  width:42px;height:42px;flex:0 0 42px;border-radius:11px;
  background:linear-gradient(135deg, rgba(13,110,233,.22), rgba(58,141,255,.10));
  border:1px solid rgba(13,110,233,.3);color:var(--primary-2);
  display:grid;place-items:center;
}
.showcase__item .ic svg{width:18px;height:18px}
/* variante pra logo de verdade no lugar do ícone genérico — os 3 logos
   (Transnet, Tecnomobile, Mercado na Rede) são wordmarks horizontais com
   proporções bem diferentes entre si (a do Transnet é bem mais larga que
   as outras duas), então a caixa vira largura automática (em vez do
   quadrado fixo 42x42 do ícone) que se ajusta ao conteúdo; a imagem em si
   usa max-height+max-width (não object-fit, não tem "caixa" fixa pra
   encaixar) pra cada logo ficar do maior tamanho legível possível sem
   estourar o espaço disponível na linha. */
.showcase__item .ic--logo{width:auto;height:44px;flex:0 0 auto;padding:0 14px}
.showcase__item .ic--logo img{max-height:22px;max-width:120px;width:auto;height:auto;display:block}
.showcase__item .t{font-size:15px;color:#fff;font-weight:600}
.showcase__item .d{font-size:13px;color:var(--text-mute);margin-top:2px}

/* tira de logos de clientes, no fim da #sobre-resumo — apagada por
   padrão, branca total no hover. Fica dentro do .container (sem o truque
   de overflow do scrollreel): um flex row simples com wrap, então sempre
   respeita a largura de conteúdo normal da seção, independente do
   tamanho da viewport. O título pequeno fica num wrapper à parte
   (.clients-strip-wrap) pra não entrar no fluxo flex-wrap das logos. */
.clients-strip-wrap{
  margin-top:90px;
  padding-top:44px;
  border-top:1px solid rgba(255,255,255,.08);
}
.clients-strip__title{
  text-align:center;
  font-size:13px;
  color:#fff;
  text-transform:uppercase;
  letter-spacing:.12em;
  margin:0 0 28px;
}
.clients-strip{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:center;
  gap:44px;
}
.clients-strip img{
  height:58px;
  width:auto;
  max-width:260px;
  object-fit:contain;
  opacity:.4;
  transition:opacity .3s var(--ease-out);
}
.clients-strip img:hover{opacity:1}

@media (max-width:980px){
  .showcase{grid-template-columns:1fr;gap:40px}
  .showcase__visual--scrollreel{display:none}
}

@media (max-width:640px){
  .clients-strip-wrap{margin-top:60px;padding-top:32px}
  .clients-strip__title{margin-bottom:20px}
  .clients-strip{gap:30px}
  .clients-strip img{height:44px;max-width:200px}
}

/* imagem do celular do Super App */
.app-visual{
  position:relative;
  display:flex;justify-content:center;align-items:center;
  padding:30px 0;
}
/* glow reduzido — pedido explícito do usuário ("reduza um pouco o
   tamanho dessa sombra... para que não pegue nos cards abaixo dela"):
   `inset:-10%` (glow 10% maior que a própria imagem em cada lado) somado
   ao `blur(30px)` vazava até os `.feat-item` logo abaixo, na única
   página que usa `.app-visual` hoje. Reduzido pra `inset:6%` (agora
   menor que a imagem, não maior) + `blur(22px)`, mais contido. */
.app-visual::before{
  content:"";
  position:absolute;inset:6%;
  background:radial-gradient(closest-side, rgba(13,110,233,.32), transparent 70%);
  filter:blur(22px);
  z-index:0;
}
.app-visual__img{
  position:relative;z-index:1;
  width:100%;max-width:320px;height:auto;
  filter:drop-shadow(0 40px 70px rgba(0,0,0,.55));
}
@media (max-width:980px){
  .app-visual{padding:10px 0}
  .app-visual__img{max-width:240px}
}

/* dashboard falso dentro do showcase */
.dash{
  background:rgba(10,14,24,.7);border:1px solid rgba(255,255,255,.06);
  border-radius:14px;padding:18px;
}
.dash__row{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.dash__title{font-size:13px;color:var(--text-dim);font-weight:600}
.dash__pill{padding:3px 10px;border-radius:999px;font-size:11px;font-weight:600;color:var(--primary-2);background:rgba(13,110,233,.12);border:1px solid rgba(13,110,233,.3)}
.dash__chart{display:flex;align-items:flex-end;gap:6px;height:120px;margin-top:18px}
.dash__chart i{flex:1;border-radius:4px 4px 0 0;background:linear-gradient(180deg,var(--primary-2) 0%, rgba(13,110,233,.2) 100%)}
.dash__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:18px}
.dash__kpi{padding:12px;border-radius:10px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04)}
.dash__kpi .n{font-family:var(--font-display);font-size:18px;font-weight:700;color:#fff}
.dash__kpi .l{font-size:10.5px;color:var(--text-mute);text-transform:uppercase;letter-spacing:.1em;margin-top:2px}

/* ========================================================
   RAMOS DE ATUAÇÃO — accordion de 5 barras horizontais (expande no hover)
   ======================================================== */
/* z-index:1 pelo mesmo motivo de sempre — sem isso a grade ambiente global
   (body::after, position:fixed;z-index:0) pintaria por cima da seção.
   Fundo claro sólido, mesma receita padrão de "seção branca" do site (ver
   "Convenções gerais" no CLAUDE.md). */
.ramos-section{position:relative;z-index:1;background:#e2e7f0}
.ramos-section .section__title{color:#0b0f1a}
.ramos-section .section__lead{color:var(--text-mute)}
.ramos-section .section__lead strong{color:var(--primary);font-weight:700}

/* Redesenho pedido pelo usuário ("design mais bonito, dê ênfase nos ramos
   por meio dos elementos da seção"), substituindo o grid "bento" anterior
   (1 card grande + 4 pequenos em posições fixas). São 5 barras horizontais
   empilhadas (largura cheia, altura igual por padrão) — a interação
   (hover) que dá ênfase a um ramo de cada vez: a barra sob o cursor cresce
   em altura (`flex`), o nome aumenta de tamanho e a foto ganha um leve
   zoom, enquanto as outras 4 encolhem levemente pra abrir espaço. Mesma
   técnica de "galeria acordeão" de antes (moda/agência), só com o eixo
   principal do flex trocado de linha pra coluna — pedido explícito do
   usuário ("cards horizontais ao invés de verticais"), depois de ver a
   primeira versão como uma fileira de painéis altos e estreitos (retrato).
   `flex-direction:column` já faz o `flex`/`flex-grow` de cada `.ramo-panel`
   controlar a altura em vez da largura, então a mecânica de hover
   (`flex:2.6`/`flex:.72`, `:has()`) não precisou de nenhuma mudança de
   lógica — só o eixo em que ela atua. */
.ramos-accordion{
  display:flex;flex-direction:column;gap:14px;height:620px;margin-top:56px;
}
.ramo-panel{
  position:relative;flex:1;min-height:0;width:100%;
  border-radius:22px;overflow:hidden;cursor:pointer;
  background:#e9edf5;border:1px solid rgba(11,15,26,.08);
  transition:flex .7s var(--ease-out), box-shadow .5s var(--ease-out);
}
/* preto e branco em repouso, colorido só no hover — pedido explícito do
   usuário. filter:grayscale(1) por padrão, zerado (grayscale(0)) no hover
   do .ramo-panel (não do próprio __img, mesmo motivo de sempre: o hover
   precisa disparar em qualquer parte da barra, não só sobre a imagem). */
.ramo-panel__img{
  position:absolute;inset:-10px;z-index:0;
  background-size:cover;background-position:center;
  transform:scale(1.05);
  filter:grayscale(1);
  transition:transform .8s var(--ease-out), filter .6s var(--ease-out);
}
/* véu escuro uniforme (não mais degradê de baixo pra cima) — com o nome
   agora centralizado (ver .ramo-panel__name), o texto pode cair em
   qualquer altura da barra, então precisa de contraste parelho na área
   inteira, não só embaixo. */
.ramo-panel::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:rgba(5,7,13,.5);
}
/* nome do ramo centralizado (repouso e hover), sem o selo numerado —
   pedido explícito do usuário ("deixe o título do ramo centralizado. E
   retire o número"). `inset:0` + flex centraliza nas duas dimensões,
   independente da altura da barra (baixa em repouso, alta no hover). */
.ramo-panel__name{
  position:absolute;inset:0;z-index:2;
  display:flex;align-items:center;justify-content:center;
  text-align:center;padding:0 24px;
  color:#fff;font-family:var(--font-display);font-weight:800;
  letter-spacing:-.01em;line-height:1.05;font-size:24px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 4px 20px rgba(0,0,0,.65);
  transition:font-size .5s var(--ease-out);
}
/* hover só em dispositivos com ponteiro de verdade (mouse/trackpad) — em
   touch, sem estado de hover persistente, o acordeão fica com as 5 barras
   sempre na mesma altura (ver breakpoints abaixo), sem risco de uma barra
   ficar "presa" expandida depois de um toque. */
@media (hover:hover){
  .ramo-panel:hover{flex:2.6;box-shadow:0 28px 56px -22px rgba(5,7,13,.4)}
  .ramos-accordion:has(.ramo-panel:hover) .ramo-panel:not(:hover){flex:.72}
  .ramo-panel:hover .ramo-panel__img{transform:scale(1.14);filter:grayscale(0)}
  .ramo-panel:hover .ramo-panel__name{font-size:42px}
}
@media (max-width:900px){
  .ramos-accordion{height:520px}
  .ramo-panel__name{font-size:20px}
}
@media (max-width:520px){
  .ramos-accordion{height:420px;gap:10px}
  .ramo-panel__name{font-size:17px}
}

/* ========================================================
   CONHEÇA NOSSO ERP — resumo dos 3 módulos, cards com imagem
   ======================================================== */
/* overflow-x:hidden por precaução: os cards com .reveal--from-left/-right
   (ver seção ERP mais abaixo) partem de translateX(±56px) antes de revelar,
   mas o .container só tem 28px de padding lateral — sobram 28px de
   transbordo real além da borda da viewport em telas estreitas, que o
   overflow-x:hidden global do body nem sempre pega a tempo em mobile
   (causava scroll horizontal no #erp, reportado pelo usuário testando em
   Galaxy S24 FE). Clipar aqui, perto da fonte do problema, resolve sem
   depender só da rede de segurança global. */
.erp-section{position:relative;z-index:1;overflow-x:hidden}
/* fundo claro sólido — pedido explícito do usuário, mesma receita padrão
   de sempre pra "seção branca" (ver "Convenções gerais" no CLAUDE.md).
   Usada nas 2 seções novas ("Módulos do ERP Transnet IA" e "Conheça
   outros recursos do ERP Transnet") que herdaram os 6 .erp-card ao serem
   separadas da seção original (que continua escura). Os cards em si
   (.erp-card) não precisaram de nenhum ajuste — já são auto-contidos
   (imagem + degradê escuro + texto branco), funcionam sobre qualquer
   fundo de seção, igual ao .ramo-card em .ramos-section. */
.erp-section--light{background:#e2e7f0}
.erp-section--light .section__title{color:#0b0f1a}
.erp-section--light .section__lead{color:var(--text-mute)}
/* print real do módulo Administrativo (assets/img/telas-transnet/, mesma
   imagem já usada em gestao-administrativa.html) entre o lead e o grid de
   cards — pedido explícito do usuário. Já vem com moldura/sombra "assadas"
   na própria imagem sobre fundo transparente, então é só centralizar, sem
   nenhum card/fundo por baixo (mesmo tratamento "sem cartão" do
   .showcase__visual--screens usado nas páginas de Gestão). */
.erp-showcase-img{display:flex;justify-content:center;margin-bottom:56px}
.erp-showcase-img img{width:100%;max-width:820px;height:auto;display:block}
/* botão "Conhecer módulos de gestão" — pedido explícito do usuário, leva
   até #modulos-erp (a seção com os 3 cards Operacional/Frotas/
   Administrativa, ver acima). Texto diferente de "Conhecer Soluções", então
   não usa `.btn--solucoes` (classe reservada só pro texto exato, ver
   "Convenções gerais" no CLAUDE.md). Passou por `.btn--primary` sólido e
   depois `.btn--ghost` (contorno translúcido), até o usuário pedir "um
   botão sem fundo e bordas" — virou `.btn--text` (já existente, ver
   `.modules__cta` mais abaixo: só texto + seta, sublinhado que desliza no
   hover, sem pílula/fundo/borda nenhuma). Também moveu de lugar (pedido do
   mesmo comentário, "centralizado e abaixo da imagem") — saiu de dentro do
   `.section__head` (que fica antes da imagem, alinhado à esquerda) e virou
   irmão de `.erp-showcase-img`, num wrapper próprio só pra centralizar. */
.erp-showcase__btn-wrap{display:flex;justify-content:center}
/* volta a ser um grid de 2 linhas (uma trinca só) — as 3 páginas de "Conheça
   nosso ERP" foram separadas em 2 seções (ver .erp-section--light), cada
   uma com seu próprio .erp-grid de 3 cards, então não precisa mais caber
   6 cards/4 linhas num grid só. height:640px é a altura original de uma
   trinca (antes de ter sido dobrada pra 1300px quando as 2 trincas
   dividiam o mesmo grid). */
.erp-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-template-rows:repeat(2,1fr);
  gap:20px;
  height:640px;
}
.erp-card{
  position:relative;
  border-radius:var(--radius-lg);
  overflow:hidden;
  border:1px solid rgba(255,255,255,.08);
  box-shadow:0 20px 50px -25px rgba(0,0,0,.6);
  transition:transform .4s var(--ease-out), box-shadow .4s var(--ease-out);
}
/* cada card agora também carrega .reveal (entrada individual, ver mais
   abaixo) — `transition` é shorthand: a regra `.reveal{transition:...}`
   (mesma especificidade, mas declarada bem depois no arquivo) substituiria
   inteira a lista acima em vez de somar, derrubando a transition do
   box-shadow e trocando a duração do transform de .4s pra 1s (deixando o
   hover-lift lento). Esta regra, mais específica, reescreve a lista inteira
   já combinando as três: opacity 1s pra entrada suave, transform .5s
   (equilíbrio entre a entrada e o hover-lift) e box-shadow .4s preservado. */
.erp-card.reveal{transition:opacity 1s var(--ease-out), transform .5s var(--ease-out), box-shadow .4s var(--ease-out)}
.erp-card:hover{transform:translateY(-4px);box-shadow:0 26px 60px -22px rgba(0,0,0,.7)}
/* `.reveal.in{transform:none}` tem a mesma especificidade de
   `.erp-card:hover` acima e vem depois no arquivo, então venceria no hover
   depois de revelado, cancelando o lift. Essa regra (3 classes) tem
   especificidade maior de propósito, garantindo que o hover sempre lift
   independente da ordem/estado do reveal. */
.erp-card.reveal.in:hover{transform:translateY(-4px)}
.erp-card__img{
  /* elemento de verdade (não pseudo-elemento) só pra imagem de fundo,
     separado do degradê e do texto, pra poder aplicar blur nela sem
     afetar o resto. Fora do hover: levemente embaçada; no hover: nitidez
     plena. scale(1.08) evita a borda do blur "vazar" um fiapo transparente
     na beirada do card.
     (Chegou a ser um ::before lendo a url de uma custom property --card-bg
     setada inline — não funcionou: url() relativo dentro de custom
     property resolve relativo à folha de estilo onde o var() é usado
     [assets/css/style.css], não relativo ao HTML onde a variável foi
     declarada, então a imagem quebrava. Elemento real com
     background-image inline não tem esse problema.) */
  position:absolute;inset:0;z-index:0;
  background-size:cover;
  background-position:center;
  filter:blur(3px);
  transform:scale(1.08);
  transition:filter .5s var(--ease-out), transform .5s var(--ease-out);
}
.erp-card:hover .erp-card__img{
  filter:blur(0);
  transform:scale(1);
}
.erp-card::before{
  /* degradê horizontal: preto na esquerda até transparente na direita —
     garante leitura do título/texto/botão (que começam colados na borda
     esquerda do card) em cima de qualquer imagem de fundo. */
  content:'';
  position:absolute;inset:0;z-index:1;
  background:linear-gradient(90deg, rgba(5,7,13,1) 0%, rgba(5,7,13,.2) 62%, rgba(5,7,13,0) 100%);
}
.erp-card--operacional{grid-column:1;grid-row:1 / span 2}
.erp-card--frotas{grid-column:2;grid-row:1}
.erp-card--administrativa{grid-column:2;grid-row:2}
/* segunda trinca (SuperApp/Transnet IA/Power BI) — hoje num .erp-grid
   próprio, dentro da seção "Conheça outros recursos do ERP Transnet"
   (separada da primeira trinca, ver .erp-section--light); linhas 1/2
   (antes eram 3/4, de quando as duas trincas dividiam o mesmo grid de 4
   linhas). Mesmo layout assimétrico da primeira trinca, só que espelhado:
   o card grande (SuperApp) fica na coluna da DIREITA, os dois empilhados
   na ESQUERDA (pedido explícito do usuário pra inverter o lado em relação
   à primeira trinca). */
.erp-card--superapp{grid-column:2;grid-row:1 / span 2}
.erp-card--transnetia{grid-column:1;grid-row:1}
.erp-card--powerbi{grid-column:1;grid-row:2}
.erp-card__body{
  position:absolute;left:0;right:0;bottom:0;
  padding:28px;
  z-index:2;
}
.erp-card__title{
  font-family:var(--font-display);font-weight:700;font-size:22px;color:#fff;
  letter-spacing:-.01em;margin-bottom:8px;
}
.erp-card__text{
  font-size:14px;line-height:1.55;color:rgba(255,255,255,.72);
  max-width:380px;margin-bottom:18px;
}
.erp-card__btn{
  display:inline-flex;align-items:center;gap:8px;
  padding:10px 18px;
  border-radius:999px;
  font-size:13.5px;font-weight:600;color:#fff;
  border:1px solid rgba(255,255,255,.3);
  background:rgba(255,255,255,.06);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  transition:background .25s var(--ease-out), border-color .25s var(--ease-out), transform .25s var(--ease-out);
}
.erp-card__btn svg{transition:transform .25s var(--ease-out)}
.erp-card__btn:hover{
  background:linear-gradient(135deg,var(--primary) 0%,var(--primary-2) 100%);
  border-color:transparent;
  transform:translateY(-2px);
}
.erp-card__btn:hover svg{transform:translateX(3px)}
@media (max-width:900px){
  /* colunas/linhas fixas viram uma coluna só, cards empilhados na ordem
     do DOM (Operacional, Frotas, Administrativa) — mesma quebra de
     breakpoint do .ai-grid logo acima, já que essa seção vive colada nele. */
  .erp-grid{grid-template-columns:1fr;grid-template-rows:none;height:auto;gap:16px}
  .erp-card{grid-column:auto;grid-row:auto;height:360px}
}
@media (max-width:480px){
  .erp-card{height:300px}
  .erp-card__body{padding:22px}
  .erp-card__title{font-size:19px}
}

/* ========================================================
   RECURSOS INTEGRADOS — vitrine interativa (SuperApp/Transnet IA/Power BI)
   ======================================================== */
/* Substitui a antiga grade estática de .erp-card por uma vitrine com abas:
   lista à esquerda (acordeão — só o item ativo mostra a descrição, mesma
   técnica de max-height/opacity já usada em .tl-mark__text) e um painel
   visual à direita que faz crossfade entre as 3 imagens reais (mesmas já
   usadas nos cards antigos) conforme o item ativo, via initTabs() genérico
   (data-tabs/data-tab/data-panel — nenhuma linha de JS nova). */
.recursos-showcase{
  display:grid;grid-template-columns:.92fr 1.08fr;gap:40px;
  margin-top:56px;align-items:stretch;
}
.recursos-list{display:flex;flex-direction:column;gap:14px;justify-content:center}
/* botões com design glassmórfico — pedido explícito do usuário.
   backdrop-filter:blur desfoca a grade ambiente global (body::after) por
   trás de cada botão; fundo/borda um pouco mais opacos que o padrão
   "vidro" de outras seções (.05/.12, vs .02/.07 antes) pra compensar e
   continuar lendo como "vidro fosco", não transparente demais. Nenhum
   descendente position:fixed/absolute aqui dentro, então não há risco do
   bug de containing-block já documentado no projeto. */
.recursos-item{
  display:flex;align-items:center;gap:18px;width:100%;
  text-align:left;cursor:pointer;
  padding:22px 24px;border-radius:18px;
  background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.12);
  border-left:3px solid transparent;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 8px 24px -16px rgba(0,0,0,.5);
  transition:background-color .3s var(--ease-out), border-color .3s var(--ease-out), transform .3s var(--ease-out);
}
.recursos-item:hover{background:rgba(255,255,255,.08)}
.recursos-item.active{
  background:linear-gradient(120deg, rgba(13,110,233,.22), rgba(255,255,255,.06));
  border-color:rgba(255,255,255,.16);
  border-left-color:var(--primary-2);
}
.recursos-item__icon{
  flex:0 0 auto;width:46px;height:46px;border-radius:13px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(255,255,255,.05);color:var(--text-dim);
  transition:background-color .3s var(--ease-out), color .3s var(--ease-out);
}
.recursos-item__icon svg{width:22px;height:22px}
.recursos-item.active .recursos-item__icon{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));color:#fff;
}
.recursos-item__body{flex:1;min-width:0}
.recursos-item__title{
  display:block;font-family:var(--font-display);font-weight:700;
  font-size:18px;color:#fff;letter-spacing:-.01em;
}

.recursos-visual{
  position:relative;border-radius:26px;overflow:hidden;
  aspect-ratio:4/3;
  box-shadow:0 30px 70px -24px rgba(0,0,0,.6);
}
.recursos-panel{
  position:absolute;inset:0;opacity:0;pointer-events:none;z-index:0;
  transition:opacity .5s var(--ease-out);
}
.recursos-panel.active{opacity:1;pointer-events:auto;z-index:1}
.recursos-panel__img{
  position:absolute;inset:0;z-index:0;
  background-size:cover;background-position:center;
}
.recursos-panel::before{
  content:'';position:absolute;inset:0;z-index:1;
  background:linear-gradient(0deg, rgba(5,7,13,.92) 0%, rgba(5,7,13,.35) 55%, rgba(5,7,13,0) 100%);
}
.recursos-panel__body{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:32px;display:flex;align-items:center;justify-content:space-between;gap:20px;
}
/* wrapper título+descrição — pedido explícito do usuário pra mover a
   descrição de dentro do botão de controle (esquerda) pra dentro do
   card com a imagem (direita). flex:1/min-width:0 deixa o texto encolher
   quando precisar, sem empurrar o .recursos-panel__btn pra fora do card. */
.recursos-panel__text{flex:1;min-width:0}
.recursos-panel__title{
  font-family:var(--font-display);font-weight:700;font-size:26px;color:#fff;letter-spacing:-.01em;
}
.recursos-panel__desc{
  margin-top:8px;font-size:14px;line-height:1.55;
  color:rgba(255,255,255,.72);max-width:380px;
}
.recursos-panel__btn{flex:0 0 auto}
@media (max-width:900px){
  .recursos-showcase{grid-template-columns:1fr;gap:24px}
  .recursos-visual{aspect-ratio:16/11}
}
@media (max-width:480px){
  .recursos-item{padding:18px 18px}
  .recursos-panel__body{padding:22px;flex-direction:column;align-items:flex-start;gap:14px}
  .recursos-panel__title{font-size:21px}
}

/* ========================================================
   SHOWCASE DE IA — bloco de chat / consulta
   ======================================================== */
.ai-wave-canvas{
  position:absolute;inset:0;
  width:100%;height:100%;
  pointer-events:none;
  z-index:0;
}

.ai-block{
  position:relative;
  padding:60px;
  border-radius:30px;
  background:
    radial-gradient(800px 400px at 90% 0%, rgba(13,110,233,.20), transparent 60%),
    linear-gradient(180deg, rgba(15,20,35,.7) 0%, rgba(8,12,22,.7) 100%);
  border:1px solid rgba(255,255,255,.08);
  overflow:hidden;
}
.ai-block::after{
  content:"";position:absolute;inset:-1px;border-radius:30px;padding:1px;
  background:linear-gradient(135deg,rgba(13,110,233,.5),transparent 40%,rgba(58,141,255,.3));
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;
}
.ai-grid{display:grid;grid-template-columns:1fr 1fr;gap:50px;align-items:center}
@media (max-width:900px){.ai-grid{grid-template-columns:1fr}.ai-block{padding:40px 28px}}
.ai-prompt{
  background:rgba(8,12,22,.7);
  border:1px solid rgba(255,255,255,.08);
  border-radius:18px;
  padding:22px;
  font-family:"JetBrains Mono","SF Mono",monospace;
  font-size:14px;color:var(--text);
  position:relative;
}
.ai-prompt .label{font-size:11px;color:var(--primary-2);letter-spacing:.15em;text-transform:uppercase;margin-bottom:10px}
.ai-prompt .q{color:#fff;font-weight:500}
.ai-prompt .cursor{display:inline-block;width:7px;height:14px;background:var(--primary-2);vertical-align:-2px;margin-left:2px;animation:blink 1s steps(2) infinite}

/* indicador de captação de áudio, logo acima da caixinha de pergunta —
   ícone de microfone + onda sonora. Fica "ligado" (.is-listening, aplicada
   via JS em initAiPanels/animateQuestion) só enquanto a pergunta está
   sendo "digitada" no slide ativo; fora disso fica discreto/parado. */
.ai-mic{
  display:flex;align-items:center;gap:12px;
  margin-bottom:14px;
  padding:10px 14px;
  border-radius:14px;
  background:rgba(8,12,22,.5);
  border:1px solid rgba(255,255,255,.06);
}
.ai-mic__btn{
  position:relative;flex:0 0 auto;
  width:34px;height:34px;border-radius:50%;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  display:grid;place-items:center;color:#fff;
}
.ai-mic__btn svg{width:16px;height:16px}
.ai-mic__rec{
  position:absolute;top:-2px;right:-2px;
  width:9px;height:9px;border-radius:50%;
  background:#e0475c;
  box-shadow:0 0 0 2px rgba(8,12,22,.9);
  opacity:.35;
  transition:opacity .3s;
}
.ai-mic.is-listening .ai-mic__rec{opacity:1;animation:aiMicPulse 1.1s ease-in-out infinite}
.ai-mic__wave{
  display:flex;align-items:center;justify-content:space-between;
  height:18px;flex:1;min-width:0;
}
.ai-mic__wave i{
  flex:0 0 auto;
  width:2px;height:4px;border-radius:2px;
  background:var(--primary-2);
  opacity:.45;
  transition:height .2s, opacity .3s;
}
.ai-mic.is-listening .ai-mic__wave i{
  opacity:1;
  animation:aiMicWave .9s ease-in-out infinite;
  /* 60 barras × .015s ≈ .9s (a duração da própria animação) — o atraso
     total de uma ponta à outra fecha um ciclo completo, então a onda
     sempre lê como uma varredura contínua, não importa quantas barras
     tenham (recalcular esse fator pra .9/quantidade se o número de <i>
     mudar de novo). */
  animation-delay:calc(var(--i, 0) * .015s);
}
@keyframes aiMicPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.7);opacity:.5}}
@keyframes aiMicWave{0%,100%{height:4px}50%{height:18px}}

/* pedido explícito do usuário: separar o relatório gerado (.ai-answer) do
   resto do painel (mic + pergunta + texto de apoio, agrupados em
   .ai-report__query) — "separe os dois elementos desse elemento pai
   branco, e não com um texto". Antes, .ai-prompt (rgba(8,12,22,.7)) e
   .ai-answer (rgba(8,12,22,.65)) tinham praticamente a mesma cor de fundo
   e nenhuma sombra, então liam como um bloco só dentro do .ai-block (o
   "elemento pai"), apesar de já serem elementos separados no DOM. Uma
   1ª tentativa usou um textinho/divisória ("Relatório gerado pela IA")
   entre os dois — **removida a pedido do usuário**, que não queria
   resolver isso com texto. Solução atual: os dois viram cartões próprios,
   cada um com seu fundo/borda — `.ai-report__query` (plano, sem sombra) e
   `.ai-answer` (elevado, borda azulada + sombra de verdade) — bounded box
   contra bounded box já basta pra ler como "dois elementos", sem precisar
   de nenhum rótulo explicando a relação entre eles. */
.ai-report__query{
  padding:24px;border-radius:18px;
  background:rgba(255,255,255,.02);
  border:1px solid rgba(255,255,255,.06);
}
.ai-answer{
  padding:24px;border-radius:18px;background:rgba(8,12,22,.65);
  border:1px solid rgba(13,110,233,.25);
  box-shadow:0 24px 50px -28px rgba(13,110,233,.35);
}
.ai-answer h4{font-size:14px;color:var(--text-dim);font-weight:600;margin-bottom:14px;display:flex;align-items:center;gap:8px}
.ai-answer h4 .dot{width:6px;height:6px;border-radius:50%;background:#22c55e;box-shadow:0 0 10px #22c55e}
.ai-bars{display:flex;align-items:flex-end;gap:8px;height:160px}
.ai-bars div{flex:1;border-radius:5px 5px 0 0;background:linear-gradient(180deg,var(--primary-2),rgba(13,110,233,.2));position:relative}
.ai-bars div span{position:absolute;bottom:-22px;left:50%;transform:translateX(-50%);font-size:10.5px;color:var(--text-mute);white-space:nowrap}
.ai-bars div b{position:absolute;top:-20px;left:50%;transform:translateX(-50%);font-size:11px;color:#fff;font-weight:600}

/* slider de IA — abas + painéis com múltiplas perguntas */
.ai-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:32px}
.ai-tab{
  padding:9px 20px;border-radius:999px;
  border:1px solid rgba(255,255,255,.08);
  background:rgba(255,255,255,.03);
  color:var(--text-dim);font-weight:600;font-size:13px;
  transition:all .25s;
}
.ai-tab:hover{color:#fff;border-color:rgba(255,255,255,.2)}
.ai-tab.active{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  color:#fff;border-color:transparent;
  box-shadow:0 10px 26px -10px var(--primary-glow);
}
.ai-panel{display:none}
.ai-panel.active{display:block}

/* gráfico de linha */
.ai-line__svg{width:100%;height:180px;display:block;overflow:visible}
.ai-line__stroke{filter:drop-shadow(0 0 6px rgba(58,141,255,.5))}
.ai-line__dot{fill:var(--primary-2);stroke:#0b1220;stroke-width:2;transform-box:fill-box;transform-origin:center}
.ai-line__labels{display:flex;justify-content:space-between;margin-top:6px;font-size:10.5px;color:var(--text-mute)}

/* tabela */
.ai-table{width:100%;border-collapse:collapse;font-size:13px}
.ai-table th{
  text-align:left;padding:0 10px 12px;
  font-size:10.5px;font-weight:600;color:var(--text-mute);
  text-transform:uppercase;letter-spacing:.1em;
  border-bottom:1px solid rgba(255,255,255,.08);
}
.ai-table td{padding:12px 10px;color:#fff;border-bottom:1px solid rgba(255,255,255,.05)}
.ai-table tr:last-child td{border-bottom:none}
.ai-table th:first-child,.ai-table td:first-child{padding-left:0}
.ai-table th:last-child,.ai-table td:last-child{text-align:right}
@keyframes aiRowIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}

/* "Veja como funciona nossa IA na prática" — versão clara (seção branca),
   pedido explícito do usuário: mesma receita padrão de sempre (ver
   "Convenções gerais" — fundo #e2e7f0, título #0b0f1a, lead/eyebrow em
   var(--text-mute), nunca --primary-2 em cima de claro) + "elementos
   brancos": o .ai-block (moldura externa) vira um cartão branco sólido; os
   painéis internos (.ai-prompt/.ai-answer, que no tema escuro já eram um
   tom mais escuro que o .ai-block) viram um cinza neutro #eef2f8 — um tom
   abaixo do branco, mesma lógica de "cartão elevado" já usada em toda seção
   branca do site; e as peças de dentro desses painéis (.ai-kpi,
   .ai-insight__box) voltam a branco sólido, recriando a mesma hierarquia de
   camadas do tema escuro (claro/escuro/claro), só invertida. A onda de
   fundo (initWaveGrid) ganha cores próprias via data-wave-base/data-wave-peak
   no canvas (ver main.js) — o par azul-claro pensado pro fundo escuro
   desapareceria quase por completo sobre #e2e7f0. */
.ai-section--light{position:relative;z-index:1;background:#e2e7f0}
.ai-section--light .section__title{color:#0b0f1a}
.ai-section--light .section__lead{color:var(--text-mute)}

.ai-section--light .ai-block{
  background:#fff;
  border-color:rgba(11,15,26,.08);
  box-shadow:0 24px 60px -32px rgba(11,15,26,.18);
}
.ai-section--light .ai-block::after{
  background:linear-gradient(135deg,rgba(13,110,233,.35),transparent 40%,rgba(13,110,233,.12));
}

/* :not(.active) é necessário aqui — sem ele, esta regra (2 classes) empata
   em especificidade com a regra global .ai-tab.active (2 classes) e, por
   vir depois no arquivo, venceria e apagaria o fundo em gradiente + texto
   branco da aba ativa, deixando o "slide atual" quase indistinguível dos
   outros (só uma tinta muito sutil, sem contraste real). */
.ai-section--light .ai-tab:not(.active){background:rgba(11,15,26,.04);border-color:rgba(11,15,26,.08);color:var(--text-mute)}
.ai-section--light .ai-tab:not(.active):hover{color:#0b0f1a;border-color:rgba(11,15,26,.16)}
/* reforço explícito (não só depender da regra global sobreviver à cascata):
   a aba ativa continua a pill sólida em gradiente da marca, só com a sombra
   um pouco mais suave — o fundo branco da seção já dá contraste de sobra,
   sem precisar do glow forte pensado pro fundo escuro. */
.ai-section--light .ai-tab.active{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  color:#fff;border-color:transparent;
  box-shadow:0 10px 24px -10px rgba(13,110,233,.4);
}

.ai-section--light .ai-prompt{background:#eef2f8;border-color:rgba(11,15,26,.08);color:#0b0f1a}
.ai-section--light .ai-prompt .label{color:var(--primary)}
.ai-section--light .ai-prompt .q{color:#0b0f1a}
.ai-section--light .ai-prompt .cursor{background:var(--primary)}

.ai-section--light .ai-mic{background:rgba(11,15,26,.04);border-color:rgba(11,15,26,.08)}
.ai-section--light .ai-mic__rec{box-shadow:0 0 0 2px #eef2f8}
.ai-section--light .ai-mic__wave i{background:var(--primary)}

/* mesma ideia do tema escuro: fundo continua o mesmo tom neutro de
   .ai-prompt (não pode virar branco — os .ai-kpi/.ai-insight__box
   internos já são brancos, e brancos-sobre-branco voltaria a "sumir" a
   hierarquia), só a borda/sombra ganham um tom azul pra dar sensação de
   elevação e separar do bloco de pergunta logo acima, que continua liso
   (sem sombra). */
.ai-section--light .ai-answer{
  background:#eef2f8;
  border-color:rgba(13,110,233,.3);
  box-shadow:0 20px 40px -28px rgba(13,110,233,.3);
}
.ai-section--light .ai-report__head h4{color:#0b0f1a}
.ai-section--light .ai-report__head span{color:var(--text-mute)}
.ai-section--light .ai-report__query{background:#eef2f8;border-color:rgba(11,15,26,.08)}

/* border-top/right/bottom-color, não o shorthand border-color: o KPI tem
   um selo lateral colorido (border-left, var(--primary-2) por padrão ou
   #f5a524/#e0475c/#22c55e nas variantes --warn/--danger/--ok) — border-color
   reseta as 4 bordas de uma vez, inclusive a esquerda, apagando esse selo
   (bug real reportado pelo usuário: os cards apareciam todos brancos, sem
   nenhuma faixa colorida). */
.ai-section--light .ai-kpi{background:#fff;border-top-color:rgba(11,15,26,.08);border-right-color:rgba(11,15,26,.08);border-bottom-color:rgba(11,15,26,.08)}
.ai-section--light .ai-kpi__label{color:var(--text-mute)}
.ai-section--light .ai-kpi__value{color:#0b0f1a}
.ai-section--light .ai-kpi__sub{color:var(--text-mute)}

.ai-section--light .ai-hbar__label{color:var(--text-mute)}
.ai-section--light .ai-hbar__track{background:rgba(11,15,26,.08)}
.ai-section--light .ai-hbar__value{color:#0b0f1a}

.ai-section--light .ai-tables-2col h5{color:var(--text-mute)}
.ai-section--light .ai-table th{color:var(--text-mute);border-bottom-color:rgba(11,15,26,.1)}
.ai-section--light .ai-table td{color:#0b0f1a;border-bottom-color:rgba(11,15,26,.06)}

.ai-section--light .ai-insight__box{background:#fff;border-color:rgba(11,15,26,.08)}
.ai-section--light .ai-insight__box h5{color:var(--primary)}
.ai-section--light .ai-insight__box p{color:var(--text-mute)}
.ai-section--light .ai-insight__logic{background:rgba(13,110,233,.07);border-color:rgba(13,110,233,.22);color:#0b0f1a}

.ai-section--light .ai-summary{background:rgba(13,110,233,.07);border-color:rgba(13,110,233,.22)}
.ai-section--light .ai-summary__item{color:var(--text-mute)}
.ai-section--light .ai-summary__item b{color:var(--primary)}

/* ========================================================
   GRADE DE INTEGRAÇÕES
   ======================================================== */
/* Redesenho completo, pedido explícito do usuário: "quero que a seção de
   integrações deixe de ser um carrossel e vire uma seção com cards, quero
   a seção com um tema branco e quero que você acrescente algum elemento
   ao fundo que diferencie um pouco a seção." Deixou de ser carrossel
   (trilho horizontal com scroll/arrasto + setas de navegação) e virou
   grid estático — todos os 12 `.integ-card` visíveis de uma vez, sem
   scroll horizontal. Como essa seção é replicada **idêntica** em 5
   páginas (`gestao-operacional.html`, `gestao-frotas.html`,
   `gestao-administrativa.html`, `power-bi.html`, `transnet-ia.html`, ver
   CLAUDE.md), o redesenho foi aplicado nas 5 de uma vez, mantendo a
   sincronia que já era regra pra esse componente — confirmado com o
   usuário antes de mexer, já que é uma mudança estrutural grande.
   `.integ-carousel`/`.integ-track`/`.integ-nav` (CSS do carrossel) foram
   **removidos por completo** (não deixados como código morto) — eram
   exclusivos deste componente, que não é mais um carrossel em nenhuma
   página do site, então não há motivo pra manter. */
.integrations{position:relative;z-index:1}

/* "Seção branca" — mesma receita padrão de sempre (ver "Convenções
   gerais" no CLAUDE.md). Modificador `--light` mesmo não havendo mais
   nenhuma instância escura desse componente (todas as 5 páginas usam o
   mesmo HTML/CSS) — mantém a convenção do projeto de nomear o tema
   explicitamente, útil se algum dia pedir pra reverter só essa seção. */
.integrations--light{background:#e2e7f0}
.integrations--light .section__title{color:#0b0f1a}
.integrations--light .section__lead{color:var(--text-mute)}

/* Elemento de fundo pra diferenciar a seção, a pedido do usuário ("seja
   criativo") — reaproveita o canvas `[data-wave-grid]` (grade pontilhada
   que ondula e reage ao mouse, já generalizado em `initWaveGridAll()`,
   ver "Grade de onda" no CLAUDE.md) com as mesmas cores calibradas pro
   tema claro já usadas em `#ai` (home) e nos heroes das páginas de
   Gestão (`data-wave-base="15,23,42" data-wave-peak="13,110,233"` —
   pontos escuro-marinho em repouso, acendendo pro azul da marca nos
   picos/perto do cursor). Zero JS novo — só o atributo no `<canvas>`.
   `.integrations` já tinha `position:relative`, então o canvas
   (`position:absolute;inset:0;z-index:0`) já se ancora certo; `.container
   {z-index:1}` (regra global) garante que os cards fiquem por cima. */

/* Grid estático no lugar do trilho — `repeat(6,1fr)` fecha as 12 integrações
   em 2 linhas de 6 no desktop, mesma técnica de colunas fixas + breakpoints
   já usada em `.craft`/`.pillars`. */
.integ-grid{
  display:grid;grid-template-columns:repeat(6,1fr);gap:20px;
  margin-top:56px;
}
@media (max-width:980px){.integ-grid{grid-template-columns:repeat(4,1fr)}}
@media (max-width:640px){.integ-grid{grid-template-columns:repeat(3,1fr)}}
@media (max-width:420px){.integ-grid{grid-template-columns:repeat(2,1fr)}}

/* Redesenho do card — pedido explícito do usuário ("não gostei da
   interação, faça essa seção de uma forma mais bonita"), depois de duas
   rodadas anteriores (fundo azul claro no hover, depois ícone sem
   rotação) não terem ficado satisfatórias. 4 mudanças, todas voltando a
   uma linguagem mais próxima do resto do site (mais previsível = mais
   "bonita" nesse caso) + um ajuste de layout novo:
   1. Hover volta a "virar" azul-escuro sólido (mesma receita comprovada
      de `.pillar`/`.social-card`/`.bi-pillar`, abandonando o experimento
      "azul claro" da rodada anterior) — texto/ícone voltam a claro só no
      hover, mesmo contraste alto de sempre.
   2. Removido o brilho de spotlight que seguia o mouse (`::after`,
      radial-gradient com `--mx`/`--my`) — com o hover já mudando fundo +
      ícone + texto + anel de gradiente, mais uma camada de brilho ficava
      visualmente carregado; a interação agora é mais limpa/direta.
      `initSpotlight()` (main.js) continua rodando sem nenhuma mudança —
      ela seta as custom properties `--mx`/`--my` em qualquer `.card,
      .integ-card`, e simplesmente não sobra nenhum CSS pra consumi-las
      aqui agora (inofensivo, outras seções com `.card` continuam usando).
   3. Ícone ganhou um leve tingimento azul já em repouso (`rgba(13,110,
      233,.08)`, era tint neutro cinza) — mais vida antes do hover, sem
      abandonar `var(--primary)` como cor do traço (mesma regra de
      contraste de sempre).
   4. Cards com altura mínima uniforme (`min-height:152px` +
      `display:flex;flex-direction:column;justify-content:center`) — os
      12 nomes têm comprimentos bem diferentes ("GPS" vs. "APC - Contador
      Automático de Passageiros"), então sem isso a grade ficava com
      bordas inferiores desalinhadas (cards de 1 linha de texto ficavam
      visivelmente mais baixos que os de 2 linhas); agora todos fecham a
      grade com a mesma altura, ícone+texto sempre centralizados
      verticalmente. */
.integ-card{
  position:relative;isolation:isolate;
  display:flex;flex-direction:column;justify-content:center;min-height:152px;
  padding:24px 18px;
  border-radius:16px;
  background:#e9edf5;
  border:1px solid rgba(11,15,26,.08);
  box-shadow:0 12px 28px -22px rgba(11,15,26,.2);
  text-align:center;
  transition:transform .4s var(--ease-out), border-color .35s, box-shadow .4s, background .3s;
}
/* anel de gradiente, escondido até o hover — inalterado, já funciona
   sobre qualquer fundo de card */
.integ-card::before{
  content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1.5px;
  background:linear-gradient(135deg, var(--primary) 0%, var(--primary-2) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:0;transition:opacity .35s;
  pointer-events:none;
}
.integ-card:hover{
  background:#0d1f3d;
  border-color:transparent;
  transform:translateY(-8px);
  box-shadow:0 24px 48px -20px rgba(5,7,13,.45);
}
.integ-card:hover::before{opacity:1}
.integ-card .ic{
  width:46px;height:46px;border-radius:12px;margin:0 auto 14px;
  display:grid;place-items:center;
  background:rgba(13,110,233,.08);
  border:1px solid rgba(13,110,233,.16);
  color:var(--primary);
  transition:transform .35s var(--ease-out), box-shadow .35s, background .35s, border-color .35s, color .35s;
}
.integ-card .ic svg{width:22px;height:22px}
.integ-card .t{font-size:13px;color:#0b0f1a;font-weight:600;transition:color .3s}
.integ-card:hover .ic{
  transform:scale(1.14);
  box-shadow:0 0 26px rgba(13,110,233,.5);
  background:rgba(255,255,255,.1);
  border-color:rgba(255,255,255,.18);
  color:var(--primary-2);
}
.integ-card:hover .t{color:#fff}
/* botão "Conhecer soluções" abaixo do grid — pedido explícito do
   usuário, mesmo markup canônico de sempre (`.btn.btn--primary
   .btn--solucoes` + seta, ver "Convenções gerais" no CLAUDE.md). */
.integ-cta{display:flex;justify-content:center;margin-top:48px}

/* ========================================================
   SEÇÃO DE MÓDULOS — Abas
   ======================================================== */
.modules{position:relative}
.modules::before,.modules::after{
  content:"";position:absolute;left:0;right:0;height:140px;z-index:1;pointer-events:none;
}
.modules::before{top:0;background:linear-gradient(180deg, var(--bg-0), transparent)}
.modules::after{bottom:0;background:linear-gradient(0deg, var(--bg-0), transparent)}
.modules__tabs{
  display:flex;flex-wrap:wrap;gap:10px;
  justify-content:center;margin-bottom:48px;
}
.modules__tab{
  padding:11px 22px;border-radius:999px;
  border:1px solid rgba(255,255,255,.08);
  background:rgba(255,255,255,.025);
  color:var(--text-dim);font-weight:500;font-size:14px;
  transition:all .25s;
}
.modules__tab:hover{color:#fff;border-color:rgba(255,255,255,.18)}
.modules__tab.active{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  color:#fff;border-color:transparent;
  box-shadow:0 10px 30px -10px var(--primary-glow);
}
.modules__panel{display:none}
.modules__panel.active{display:grid}
/* botão "Conhecer módulo", um por painel de aba — pedido explícito do
   usuário, com design "completamente diferente" do CTA principal do
   site (`.btn--primary.btn--solucoes`, pill sólida com gradiente
   animado). `.btn--text` é o oposto disso de propósito: sem fundo, sem
   borda, sem formato de pílula — só texto + seta, com um sublinhado que
   desliza da direita pra esquerda no hover (mesma técnica do
   `.nav__link::after`). Ainda usa a classe base `.btn` (herda o
   `display:inline-flex` e o `.btn:hover .arrow{transform:translateX(3px)}`
   genérico), só sobrescrevendo o que faz parecer um botão sólido.
   `.modules__cta` cuida só do posicionamento dentro do grid de cards
   (`grid-column:1/-1` pra ocupar a linha inteira embaixo dos 6 `.card`,
   já que é um item a mais dentro do mesmo `.grid.grid--3`). `overflow:
   visible` sobrescreve o `overflow:hidden` herdado do `.btn` base (lá
   serve pra conter o brilho deslizante do `.btn--primary::before`) — sem
   isso o sublinhado (`::after`, posicionado em `bottom:-3px`, fora da
   caixa) ficaria cortado/invisível. */
.btn--text{
  padding:0;background:none;border:none;border-radius:0;
  color:#fff;font-weight:700;
  position:relative;overflow:visible;
  transition:color .25s;
}
.btn--text::after{
  content:"";position:absolute;left:0;right:0;bottom:-3px;
  height:1.5px;background:currentColor;
  transform:scaleX(0);transform-origin:right center;
  transition:transform .35s var(--ease-out);
}
.btn--text:hover{color:var(--accent);background:none}
.btn--text:hover::after{transform:scaleX(1);transform-origin:left center}
.modules__cta{grid-column:1/-1;justify-self:center;margin-top:10px}

/* ========================================================
   DEPOIMENTOS — carrossel
   ======================================================== */
.testimonials{position:relative}
.testimonial{
  padding:40px;border-radius:20px;
  background:linear-gradient(180deg, rgba(20,26,42,.55), rgba(12,16,28,.4));
  border:1px solid rgba(255,255,255,.06);
  position:relative;
  height:100%;
}
.testimonial__quote{font-size:16px;line-height:1.75;color:var(--text);margin-bottom:26px}
.testimonial__head{display:flex;align-items:center;gap:14px}
.testimonial__avatar{
  width:52px;height:52px;border-radius:50%;
  object-fit:cover;
  border:2px solid rgba(58,141,255,.4);
  flex-shrink:0;
}
.testimonial__name{font-size:14.5px;color:#fff;font-weight:600}
.testimonial__role{font-size:12.5px;color:var(--text-mute);margin-top:2px}

.testi-slider{position:relative;max-width:740px;margin:0 auto}
.testi-viewport{overflow:hidden;border-radius:20px}
.testi-track{display:flex;transition:transform .6s cubic-bezier(.22,1,.36,1)}
.testi-slide{flex:0 0 100%;min-width:0}

.testi-nav{
  position:absolute;top:50%;transform:translateY(-50%);
  width:46px;height:46px;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.12);
  color:#fff;
  backdrop-filter:blur(10px);
  transition:all .25s;
  z-index:2;
}
.testi-nav:hover{background:linear-gradient(135deg,var(--primary),var(--primary-2));border-color:transparent;box-shadow:0 10px 26px -10px var(--primary-glow)}
.testi-nav svg{width:20px;height:20px}
.testi-nav--prev{left:-64px}
.testi-nav--next{right:-64px}
@media (max-width:900px){.testi-nav--prev{left:-4px}.testi-nav--next{right:-4px}}
@media (max-width:640px){.testi-nav{display:none}}

.testi-dots{display:flex;justify-content:center;gap:8px;margin-top:28px}
.testi-dot{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.18);transition:all .3s}
.testi-dot.active{width:24px;border-radius:999px;background:linear-gradient(90deg,var(--primary),var(--primary-2))}

/* ========================================================
   CTA / RODAPÉ
   ======================================================== */
.cta-block{
  position:relative;
  padding:80px 60px;
  border-radius:30px;
  text-align:center;
  background:
    radial-gradient(600px 300px at 50% 0%, rgba(13,110,233,.3), transparent 60%),
    linear-gradient(180deg, rgba(15,20,35,.6) 0%, rgba(8,12,22,.6) 100%);
  border:1px solid rgba(13,110,233,.25);
  overflow:hidden;
}
.cta-block h2{font-size:clamp(28px,3.4vw,46px);color:#fff;letter-spacing:-.025em;margin-bottom:18px}
.cta-block p{color:var(--text-dim);font-size:17px;max-width:560px;margin:0 auto 32px}
.cta-block .btns{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}
@media (max-width:680px){.cta-block{padding:54px 28px}}

/* ========================================================
   CONTATO — "Vamos conversar" (formulário + informações)
   ======================================================== */
.contact-section{position:relative}
.contact-grid{
  display:grid;
  grid-template-columns:.8fr 1.2fr;
  gap:44px;
  margin-top:56px;
  align-items:start;
}
.contact-info{
  padding:36px 32px;
  border-radius:var(--radius-lg);
  background:linear-gradient(180deg, rgba(15,20,35,.55) 0%, rgba(8,12,22,.55) 100%);
  border:1px solid var(--border);
  position:sticky;
  top:110px;
}
.contact-info__brand{font-family:var(--font-display);font-weight:700;font-size:17px;color:#fff;letter-spacing:-.01em;margin-bottom:6px}
.contact-info__email{display:inline-block;font-size:14.5px;color:var(--primary-2);margin-bottom:30px;transition:color .2s}
.contact-info__email:hover{color:var(--accent)}
.contact-info__block{margin-bottom:24px}
.contact-info__block h4{
  display:flex;align-items:center;gap:8px;
  font-family:var(--font-sans);font-size:13.5px;font-weight:600;
  color:#fff;text-transform:uppercase;letter-spacing:.06em;
  margin-bottom:8px;
}
.contact-info__block h4 svg{width:15px;height:15px;color:var(--primary-2);flex:0 0 auto}
.contact-info__block p{font-size:14px;line-height:1.7;color:var(--text-dim)}
.contact-info__social{margin-top:30px}

.contact-form{
  padding:36px;
  border-radius:var(--radius-lg);
  background:linear-gradient(180deg, rgba(17,22,35,.55) 0%, rgba(10,14,24,.55) 100%);
  border:1px solid var(--border);
}
.contact-form__cols{display:grid;grid-template-columns:1fr 1fr;gap:0 20px}
.contact-form__col{display:flex;flex-direction:column;gap:16px}
.field{display:flex;flex-direction:column;gap:7px}
.field label{font-size:12.5px;font-weight:600;color:var(--text-dim);letter-spacing:.02em}
.field--grow{flex:1}
.field--grow textarea{flex:1;min-height:118px}

.field input,
.field textarea,
.field select{
  width:100%;
  padding:13px 16px;
  border-radius:12px;
  background:rgba(255,255,255,.03);
  border:1px solid var(--border-2);
  color:var(--text);
  font-family:var(--font-sans);
  font-size:14.5px;
  transition:border-color .2s, background .2s, box-shadow .2s;
  resize:vertical;
}
.field input::placeholder,
.field textarea::placeholder{color:var(--text-mute)}
.field input:hover,
.field textarea:hover,
.field select:hover{border-color:rgba(255,255,255,.22)}
.field input:focus,
.field textarea:focus,
.field select:focus{
  outline:none;
  border-color:var(--primary-2);
  background:rgba(13,110,233,.06);
  box-shadow:0 0 0 3px rgba(13,110,233,.15);
}
.field input:invalid[data-touched="true"],
.field textarea:invalid[data-touched="true"],
.field select:invalid[data-touched="true"]{border-color:#e0475c}

.select-wrap{position:relative}
.select-wrap::after{
  content:"";
  position:absolute;right:16px;top:50%;
  width:9px;height:9px;
  border-right:1.6px solid var(--text-dim);
  border-bottom:1.6px solid var(--text-dim);
  transform:translateY(-70%) rotate(45deg);
  pointer-events:none;
}
.field select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:38px}
.field select option{background:#0f1422;color:var(--text)}

.contact-form__verify{margin-top:22px}

.contact-form__consent{margin-top:16px;font-size:12.5px;line-height:1.6;color:var(--text-mute)}
.contact-form__consent a{color:var(--text-dim);text-decoration:underline;text-underline-offset:2px}
.contact-form__consent a:hover{color:var(--primary-2)}

.contact-form__submit{margin-top:22px;width:100%;justify-content:center}
.contact-form__submit[disabled]{opacity:.65;cursor:default}
.contact-form__submit .btn__label{display:inline-block}

.contact-form__status{
  margin-top:14px;font-size:13.5px;min-height:1px;
  display:none;align-items:center;gap:8px;
  padding:12px 14px;border-radius:10px;
}
.contact-form__status.ok{display:flex;color:#7ee0a8;background:rgba(46,196,120,.1);border:1px solid rgba(46,196,120,.25)}
.contact-form__status.err{display:flex;color:#ff9aa8;background:rgba(224,71,92,.1);border:1px solid rgba(224,71,92,.25)}

@media (max-width:900px){
  .contact-grid{grid-template-columns:1fr;gap:28px}
  .contact-info{position:static}
}
@media (max-width:640px){
  .contact-form{padding:24px}
  .contact-info{padding:28px 22px}
  .contact-form__cols{grid-template-columns:1fr}
}

.footer{
  margin-top:80px;
  padding:80px 0 40px;
  border-top:1px solid rgba(255,255,255,.06);
  background:rgba(5,7,13,.5);
  position:relative;z-index:1;
}
.footer__grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:48px;margin-bottom:60px}
@media (max-width:900px){.footer__grid{grid-template-columns:1fr 1fr;gap:36px}}
@media (max-width:540px){.footer__grid{grid-template-columns:1fr}}
.footer__brand .brand{margin-bottom:18px}
.footer__about{font-size:14px;color:var(--text-dim);line-height:1.7;max-width:340px}
.footer__h{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#fff;font-weight:600;margin-bottom:18px}
.footer__list{display:flex;flex-direction:column;gap:10px}
.footer__list a{font-size:14px;color:var(--text-dim);transition:color .2s}
.footer__list a:hover{color:var(--primary-2)}
.footer__bottom{
  display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;
  padding-top:30px;border-top:1px solid rgba(255,255,255,.05);
  font-size:13px;color:var(--text-mute);
}
.footer__social{display:flex;gap:10px}
.footer__social a{
  width:36px;height:36px;border-radius:10px;
  display:grid;place-items:center;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06);
  color:var(--text-dim);transition:all .2s;
}
.footer__social a:hover{background:rgba(13,110,233,.15);border-color:var(--primary);color:#fff}
.footer__social svg{width:16px;height:16px}

/* ========================================================
   CABEÇALHO DE PÁGINA (páginas internas)
   ======================================================== */
.page-header{
  padding:200px 0 100px;
  text-align:center;
  position:relative;
  background:
    radial-gradient(600px 300px at 50% 0%, rgba(13,110,233,.25), transparent 60%);
}
.page-header h1{
  font-size:clamp(40px,5vw,70px);
  color:#fff;letter-spacing:-.028em;
}
.page-header h1 span{
  color:var(--primary-2);
}
.page-header p{margin-top:22px;color:var(--text-dim);font-size:18px;max-width:680px;margin-left:auto;margin-right:auto}

/* balões de estatística flutuantes/arrastáveis (.float-card, ver
   "Estatísticas flutuantes" no CLAUDE.md) reaproveitados no hero de
   gestao-operacional.html — modificador em vez de mexer no .page-header
   genérico (as outras páginas internas não têm esses balões). Os 3
   .float-card são irmãos do .container (não filhos dele) de propósito:
   initFloatCardsDrag() usa o próprio parentElement de cada card como
   referência de posição E limite de arrasto, então precisam do
   .page-header inteiro (largura cheia da seção) como referência, não a
   coluna estreita de texto centralizado (max-width:680px) — do contrário
   ficariam confinados a uma área minúscula. overflow:hidden no
   .page-header--floatcards evita qualquer chance de scroll horizontal se
   um card for arrastado bem pra margem. text-align:left sobrescreve o
   text-align:center herdado do .page-header (pensado só pro título/
   parágrafo centralizados) — o conteúdo interno do balão (rótulo, número,
   estatística) sempre foi desenhado pra ler alinhado à esquerda.
   z-index:2 nos balões é proposital — pedido explícito do usuário pra
   eles se sobreporem ao título e ao resto do conteúdo do hero, não
   ficarem restritos às margens vazias. Sem isso, o `.container{z-index:1}`
   global (regra no topo do arquivo) pintaria por cima dos balões mesmo
   onde eles se sobrepõem visualmente, já que .float-card não tinha
   z-index próprio (auto perde pra qualquer z-index positivo, não importa
   a ordem no DOM). */
.page-header--floatcards{overflow:hidden}
.page-header--floatcards .float-card{text-align:left;z-index:2}
.page-header--floatcards .fc-1{top:26%;left:16%;width:210px}
.page-header--floatcards .fc-2{top:22%;right:14%;width:220px}
.page-header--floatcards .fc-3{bottom:14%;left:32%;width:215px}
/* some no mobile — pedido explícito do usuário, pra garantir responsivo:
   os balões se sobrepõem de propósito ao título (ver comentário acima),
   e numa tela estreita esse mesmo overlap vira sobreposição de verdade em
   cima do texto, sem espaço pra "flutuar" ao redor dele como no desktop.
   Mesmo breakpoint já usado em outras seções do site pra simplificar
   layouts em telas estreitas. */
@media (max-width:900px){
  .page-header--floatcards .float-card{display:none}
}

/* hero banner com imagem de fundo — só em gestao-operacional.html
   (.page-header--banner), pedido explícito do usuário. Imagem real
   escolhida por ele: assets/img/cards_ERP/operacional.webp (mesma foto já
   usada no card "Transnet" da seção "Conheça nosso ERP" da home — origem
   em retrato, 937×1678, então background-size:cover corta bastante altura
   pra caber numa faixa larga e baixa como esse hero; aceitável mantendo
   center). Mesma técnica de camadas por z-index já usada em .erp-card/
   .tl-slide/.page-header--video: imagem (0) → véu escuro (1) → conteúdo
   (2). `.page-header__scrim` é reaproveitado tal qual do
   `.page-header--video` (mesmo gradiente escuro + brilho azul radial),
   não precisou de nenhuma variação nova — funciona igual bem sobre
   qualquer imagem/vídeo de fundo. */
.page-header--banner{overflow:hidden;padding:260px 0 140px;min-height:95vh;display:flex;align-items:center}
.page-header__bg{
  position:absolute;inset:-20px;z-index:0;
  background-size:cover;background-position:center;
  filter:saturate(1.05) brightness(.8) blur(4px);
}
.page-header--banner .container{position:relative;z-index:2}

/* variante "split" — só em transnet-ia.html (.page-header--split), pedido
   explícito do usuário pra essa página ser "um pouco diferente das
   outras": sem imagem de banner, texto alinhado à esquerda (não
   centralizado como o .page-header genérico) e uma logo ao lado, em vez
   de balões ou fundo com foto. Reaproveita `.hero__grid`/`.hero__left`/
   `.hero__right` (o grid de 2 colunas texto/visual que já existe pro
   hero da home) em vez de criar um grid novo — texto na coluna esquerda,
   logo na direita; no mobile, `.hero__right{display:none}` (regra já
   existente, ver `@media(max-width:980px)` acima) esconde a logo e o
   grid vira coluna única, sem precisar de nenhuma regra nova aqui.
   `text-align:left` sobrescreve o `text-align:center` do `.page-header`
   base — como é herdado, basta essa única declaração pro h1/p (que não
   têm `text-align` próprio) alinharem à esquerda também. */
.page-header--split{text-align:left;min-height:95vh;display:flex;align-items:center;overflow:hidden}
/* pontos de luz desfocados no hero das 3 páginas de Gestão — pedido explícito
   do usuário ("coloque pontos de luz desfocados que se movimentam pela seção,
   eles não devem se sobrepor aos elementos da seção, ele irá se sobrepor
   apenas ao plano de fundo delas"). Reaproveita o canvas [data-ambient-lights]
   genérico (initAmbientLights(), main.js) sem nenhuma mudança de JS — mesmo
   efeito já usado em #sobre-resumo e na galeria do Power BI. Diferente
   dessas outras instâncias (onde o wrapper fica sempre em z-index:0, abaixo
   do .container por ter um número menor), aqui a seção já tem
   .page-header__bg (imagem, z:0) e .page-header__scrim (véu escuro, z:1) por
   baixo — sem subir esse z-index, os focos ficariam escondidos atrás do véu
   escuro. z-index:1 empata com o véu e com o .container; o empate é
   resolvido pela ordem no DOM (este wrapper vem depois do véu e antes do
   .container no HTML), mesma técnica de empate proposital já usada entre
   .page-header__scrim e .container — resultado: os focos pintam por cima do
   véu/imagem de fundo, mas o conteúdo real (texto, botão, notebook) ainda
   pinta por cima deles, já que vem depois no DOM. */
.page-header--split .particles-bg{z-index:1}
/* suaviza a costura entre o hero e a seção seguinte — pedido explícito do
   usuário ("deixe a transição entre a seção inicial e a segunda mais
   suave"). Sem isso, a rede de partículas (`.particle-canvas`) do fundo
   terminava seca bem na borda inferior da seção, criando um corte visível
   contra a seção 2. Mesma técnica de degradê já usada em `.modules::after`
   (`#modulos`) — aqui só o rodapé precisa (o topo já fica atrás da nav). */
.page-header--split::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:140px;z-index:1;
  background:linear-gradient(0deg, var(--bg-0), transparent);
  pointer-events:none;
}
/* visual do hero — era só a logo "ERP Transnet IA" (wordmark), trocada a
   pedido explícito do usuário pela imagem real das telas de relatórios
   gerados pela IA (assets/img/relatorios_transnet_ia.webp, composição
   pronta com várias telas + sombra "assadas" sobre fundo transparente,
   mesmo padrão de telas-transnet-*.webp/telas_superapp.webp já usados em
   outras páginas). Mantida a mesma receita visual que a logo já usava —
   sem nenhuma caixa/cartão delimitando (a 1ª versão da logo tinha um
   painel com fundo+borda, reprovado pelo usuário: "não gostei como ficou
   essa imagem com o retângulo marcado") — só o glow (blur bem maior e
   mais espalhado, sem nenhuma aresta reta) atrás da imagem, deixando-a
   parecer parte do fundo tecnológico em vez de um cartão colado por cima
   dele. max-width subiu de 380px (suficiente pra um wordmark simples)
   pra 640px — a nova imagem tem conteúdo de verdade (texto de UI nas
   telas), precisa de mais espaço pra ficar legível. */
.ia-hero-visual{
  position:relative;isolation:isolate;
  width:100%;display:flex;align-items:center;justify-content:center;
}
.ia-hero-visual::before{
  content:"";position:absolute;inset:-30% -10%;z-index:-1;
  background:radial-gradient(closest-side, rgba(13,110,233,.4), transparent 72%);
  filter:blur(50px);
}
.ia-hero-visual img{width:100%;max-width:640px;height:auto;display:block}

/* variante com vídeo de fundo — só em sobre.html (.page-header--video),
   modificador em vez de mudar o .page-header genérico (as outras 6
   páginas internas continuam com o fundo estático de sempre). Camadas por
   z-index, mesma técnica já usada em .erp-card/.tl-slide: vídeo (0) →
   véu de gradiente pro contraste do texto (1) → conteúdo (2). */
/* hero de verdade — ocupa a tela inteira (min-height:100vh, não mais só
   padding grande), mesma receita do .hero da home: min-height:vh +
   display:flex;align-items:center pra centralizar o conteúdo dentro dessa
   altura, em vez de depender só de padding fixo pra "empurrar" a seção
   pra baixo. video/scrim são position:absolute, então saem do fluxo flex
   e continuam cobrindo inset:0 normalmente — só o .container participa do
   center. */
.page-header--video{
  overflow:hidden;
  min-height:100vh;
  display:flex;align-items:center;
  padding:140px 0 80px;
}
.page-header__video{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;object-fit:cover;object-position:top;
  filter:saturate(1.05) brightness(.85);
}
/* véu escuro leve — pedido explícito do usuário depois de ter pedido a
   remoção completa do véu forte anterior ("coloque uma sombra leve no
   background"). Tom uniforme bem mais sutil (.36, era .78-.9 na versão
   forte; começou em .28, escurecido "só mais um pouco" a pedido do
   usuário) na maior parte da seção; só nos últimos 38% sobe até
   opacidade 1 (mesma cor de --bg-0) pra continuar "derretendo" no fundo
   da seção seguinte sem deixar uma linha visível na costura — mesma
   técnica de sempre, só que partindo de um tom bem mais claro. */
.page-header__scrim{
  position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg, rgba(5,7,13,.36) 0%, rgba(5,7,13,.36) 62%, rgba(5,7,13,1) 100%);
}
.page-header--video .container{position:relative;z-index:2}
/* texto alinhado à esquerda em vez do centralizado padrão do
   .page-header — pedido do usuário pra fugir do hero-centralizado-
   genérico (o layout mais batido/"cara de IA" pra uma seção assim);
   .page-header__content limita a largura do bloco de texto (senão, sem
   centralização, o parágrafo esticaria até a borda direita do container
   inteiro em telas largas). */
.page-header--video{text-align:left}
/* largura maior que a genérica de outras seções — "Construindo tecnologia"
   (a primeira linha digitada) precisa caber inteira numa linha só nas
   larguras de desktop mais comuns; com 640px ela quebrava numa terceira
   linha extra, além do <br> proposital antes de "desde 1986.". */
.page-header__content{max-width:820px}
.page-header--video p{margin-left:0;margin-right:0}
/* .page-header h1 span{color:var(--primary-2)} (regra genérica, pensada
   pras outras 6 páginas — lá só o trecho em destaque vem dentro de um
   <span>) deixava os dois .page-header__type azuis aqui, já que agora o
   <h1> inteiro é dividido em dois <span> (um por linha digitada, ver
   initHeroTypewriter()), não só o destaque. Mesma especificidade da regra
   genérica (.page-header--video h1 span = 1 classe + 2 tags, igual a
   .page-header h1 span) — como esta vem depois no arquivo, vence e volta
   o texto pro branco padrão do <h1>. :not(.page-header__shine) exclui o
   span que tem o degradê animado (ver abaixo) — senão esta regra venceria
   por especificidade e sobrescreveria o color:transparent que o
   background-clip:text precisa pra funcionar. */
.page-header--video h1 span:not(.page-header__shine){color:#fff}
/* título virou o elemento secundário da seção (ver .hero-quote logo
   abaixo) — pedido explícito do usuário pra inverter tamanho/evidência
   entre título e citação, com a citação virando o texto "de destaque" e
   o título encolhendo. Mesma especificidade de ".page-header h1" (1
   classe + 1 elemento) — como esta vem depois no arquivo, vence. */
.page-header--video h1{
  font-size:clamp(18px,2vw,22px);
  font-weight:500;letter-spacing:-.01em;
  color:var(--text-dim);
  margin-top:20px;
}
/* sweep de brilho periódico no texto em destaque — o gradiente fica
   praticamente parado (só a cor sólida --primary-2 visível) e a cada
   ciclo uma faixa clara varre o texto uma vez e some, em vez de um brilho
   deslizando sem parar (versão anterior, trocada a pedido do usuário por
   um efeito "mais legal", inspirado em botões premium com esse tipo de
   sweep). Técnica: background bem maior que o texto (250%) com a faixa
   clara no meio do gradiente; a posição anima de bem à direita (fora da
   view) até bem à esquerda (fora da view) só nos primeiros ~18% do ciclo
   — o resto do tempo (18%→100%) fica parada nessa posição final, sem
   nenhuma mudança visível, até o próximo ciclo. */
.page-header__shine{
  background:linear-gradient(100deg,
    var(--primary-2) 0%, var(--primary-2) 42%,
    #fff 50%,
    var(--primary-2) 58%, var(--primary-2) 100%);
  background-size:250% 100%;
  background-position:200% 0;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:pageHeaderSweep 4.5s ease-in-out infinite;
}
@keyframes pageHeaderSweep{
  0%{background-position:200% 0}
  18%{background-position:-40% 0}
  100%{background-position:-40% 0}
}
@media (prefers-reduced-motion:reduce){
  .page-header__shine{animation:none;background:none;color:var(--primary-2)}
}
.page-header__actions{margin-top:36px}

/* Citação de JK rolando devagar na vertical (discurso inteiro, sem
   segmentar em trechos que alternam — versão anterior, revertida a
   pedido do usuário), agora ACIMA do título e como elemento em maior
   evidência da seção — pedido explícito do usuário pra inverter tanto a
   posição quanto o tamanho/destaque entre o título e a citação (era o
   inverso: título grande em cima, citação pequena embaixo). Tamanho/peso
   trocados com o que o <h1> tinha antes (clamp(40px,5vw,70px),
   font-display, branco); o <h1> (ver acima, ".page-header--video h1")
   herdou o tamanho pequeno que a citação tinha. Itálico mantido — ainda
   lê como citação, só que agora grande. Seletores prefixados com
   .hero-quote (2 classes) de propósito — a regra genérica ".page-header
   p{margin-top:22px;color:var(--text-dim);font-size:18px;max-width:680px;
   margin-left:auto;margin-right:auto}" (1 classe + 1 elemento) tem a
   mesma especificidade que ".hero-quote__scroll" sozinho (1 classe), e
   por vir depois no arquivo venceria; ".hero-quote .hero-quote__scroll"
   (2 classes) garante que esta regra sempre vença, independente da
   ordem. */
.hero-quote{position:relative;margin-top:0;max-width:820px}
/* texto inteiro rolando devagar dentro de uma janela fixa. Altura do
   viewport em `em` (não px fixo), pra acompanhar o clamp() de font-size
   do texto em qualquer largura de tela: ~3 linhas visíveis de cada vez
   (3 × line-height 1.15 + uma folga pequena pra não cortar a linha de
   cima/baixo no meio da rolagem). Máscara em degradê nas bordas de
   cima/baixo — pedido explícito do usuário depois de ver o corte seco no
   meio de uma linha (o `overflow:hidden` sempre cortou ali, só que sem
   nenhuma transição visual suavizando); a linha que está entrando/saindo
   agora esmaece até transparente antes de tocar a borda, em vez de ser
   cortada de repente. */
.hero-quote__viewport{
  position:relative;overflow:hidden;
  font-size:clamp(40px,5vw,70px);
  height:3.85em;
  mask-image:linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, #000 22%, #000 78%, transparent 100%);
}
/* --hq-start/--hq-end setados via JS (initHeroQuoteScroll(), main.js) com
   a altura real medida do viewport e do parágrafo — garante que o texto
   comece exatamente na borda de baixo da janela (sem atraso vazio no
   início do ciclo) e só termine de fato depois de sair inteiro pela borda
   de cima (sem cortar a última linha). Fallback (sem JS, ou antes do JS
   rodar) usa %, relativo à própria altura do parágrafo — ainda funciona,
   só não encaixa perfeitamente nas bordas da janela. */
.hero-quote .hero-quote__scroll{
  position:absolute;top:0;left:0;width:100%;margin:0;
  color:#fff;font-style:italic;font-family:var(--font-display);
  font-weight:600;letter-spacing:-.025em;
  font-size:1em;line-height:1.15;
  animation:heroQuoteScroll 26s linear infinite;
}
@keyframes heroQuoteScroll{
  from{transform:translateY(var(--hq-start,100%))}
  to{transform:translateY(var(--hq-end,-100%))}
}
@media (prefers-reduced-motion:reduce){
  .hero-quote__viewport{height:auto;overflow:visible;mask-image:none;-webkit-mask-image:none}
  .hero-quote .hero-quote__scroll{position:static;animation:none;transform:none}
}
/* referência da citação — pedido explícito do usuário, fonte pequena
   embaixo do texto rolando. Não é .hero-quote__scroll (fica fora da
   janela/animação, sempre visível, parada). */
.hero-quote .hero-quote__cite{
  margin:14px 0 0;color:var(--text-dim);
  font-size:14px;font-style:normal;letter-spacing:0;
}


/* alvo das animações de revelar */
.reveal{opacity:0;transform:translateY(40px);transition:opacity 1s var(--ease-out), transform 1s var(--ease-out)}
.reveal.in{opacity:1;transform:none}
/* variações de direção — só trocam o transform de partida; `.reveal.in`
   acima já cobre o estado final (`transform:none`) igual pras 4. Usadas
   pelos cards da #erp (ver bloco ERP), mas genéricas o bastante pra
   qualquer `.reveal` que precise vir de um lado específico. */
.reveal--from-left{transform:translateX(-56px)}
.reveal--from-right{transform:translateX(56px)}
.reveal--from-top{transform:translateY(-56px)}
.reveal--from-bottom{transform:translateY(56px)}
.reveal-stagger > *{opacity:0;transform:translateY(30px);transition:opacity .8s var(--ease-out), transform .8s var(--ease-out)}
.reveal-stagger.in > *{opacity:1;transform:none}
.reveal-stagger.in > *:nth-child(1){transition-delay:.05s}
.reveal-stagger.in > *:nth-child(2){transition-delay:.12s}
.reveal-stagger.in > *:nth-child(3){transition-delay:.19s}
.reveal-stagger.in > *:nth-child(4){transition-delay:.26s}
.reveal-stagger.in > *:nth-child(5){transition-delay:.33s}
.reveal-stagger.in > *:nth-child(6){transition-delay:.40s}
.reveal-stagger.in > *:nth-child(7){transition-delay:.47s}
.reveal-stagger.in > *:nth-child(8){transition-delay:.54s}

/* blog */
.posts{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
@media (max-width:980px){.posts{grid-template-columns:repeat(2,1fr)}}
@media (max-width:640px){.posts{grid-template-columns:1fr}}
.post{
  display:flex;flex-direction:column;
  border-radius:18px;overflow:hidden;
  background:rgba(15,20,35,.45);border:1px solid rgba(255,255,255,.06);
  transition:transform .35s var(--ease-out), border-color .25s;
}
.post:hover{transform:translateY(-4px);border-color:rgba(13,110,233,.35)}
.post__cover{height:200px;position:relative;overflow:hidden;background:linear-gradient(135deg,rgba(13,110,233,.5),rgba(8,12,22,.9))}
.post__cover::after{
  content:"";position:absolute;inset:0;
  background-image:linear-gradient(rgba(255,255,255,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.08) 1px,transparent 1px);
  background-size:30px 30px;
  mask-image:radial-gradient(ellipse at 50% 50%,#000 30%,transparent 80%);
}
.post__body{padding:24px;flex:1;display:flex;flex-direction:column}
.post__tag{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--primary-2);font-weight:600;margin-bottom:10px}
.post__title{font-size:18px;color:#fff;font-weight:600;line-height:1.3;margin-bottom:10px}
.post__excerpt{font-size:14px;color:var(--text-dim);line-height:1.6;flex:1}
.post__meta{display:flex;justify-content:space-between;align-items:center;margin-top:18px;padding-top:16px;border-top:1px solid rgba(255,255,255,.05);font-size:12px;color:var(--text-mute)}

/* base de conhecimento */
.kb-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
@media (max-width:980px){.kb-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:640px){.kb-grid{grid-template-columns:1fr}}
.kb-cat{padding:30px;border-radius:18px;background:rgba(15,20,35,.45);border:1px solid rgba(255,255,255,.06);transition:all .3s}
.kb-cat:hover{border-color:rgba(13,110,233,.35);transform:translateY(-3px)}
.kb-cat .ic{width:46px;height:46px;border-radius:12px;background:linear-gradient(135deg,rgba(13,110,233,.22),rgba(58,141,255,.08));border:1px solid rgba(13,110,233,.3);display:grid;place-items:center;color:var(--primary-2);margin-bottom:18px}
.kb-cat h3{font-size:18px;color:#fff;font-weight:600;margin-bottom:8px}
.kb-cat p{font-size:13.5px;color:var(--text-dim);margin-bottom:18px}
.kb-cat ul{display:flex;flex-direction:column;gap:8px}
.kb-cat ul a{font-size:13.5px;color:var(--text-dim);display:flex;align-items:center;gap:8px}
.kb-cat ul a:hover{color:var(--primary-2)}
.kb-cat ul a::before{content:"›";color:var(--primary-2);font-weight:700}

.kb-search{
  max-width:640px;margin:0 auto 60px;
  position:relative;
}
.kb-search input{
  width:100%;padding:18px 22px 18px 56px;
  border-radius:14px;
  background:rgba(15,20,35,.55);
  border:1px solid rgba(255,255,255,.08);
  color:#fff;font-size:15px;outline:none;font-family:inherit;
  transition:border-color .2s, background .2s;
}
.kb-search input:focus{border-color:var(--primary);background:rgba(15,20,35,.8)}
.kb-search svg{position:absolute;left:20px;top:50%;transform:translateY(-50%);width:20px;height:20px;color:var(--text-mute)}

/* trabalhe conosco */
.job-list{display:flex;flex-direction:column;gap:14px}
.job{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:24px 28px;
  border-radius:16px;
  background:rgba(15,20,35,.45);
  border:1px solid rgba(255,255,255,.06);
  transition:all .25s;
}
.job:hover{border-color:rgba(13,110,233,.35);background:rgba(13,110,233,.05)}
.job__left{display:flex;align-items:center;gap:18px}
.job__tag{padding:5px 11px;border-radius:6px;background:rgba(13,110,233,.12);color:var(--primary-2);font-size:11px;font-weight:600;letter-spacing:.06em;border:1px solid rgba(13,110,233,.3)}
.job__t{font-size:16px;color:#fff;font-weight:600}
.job__m{font-size:13px;color:var(--text-mute);margin-top:3px}
.job__btn{padding:10px 18px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);color:#fff;font-size:13px;font-weight:500;transition:all .25s;display:flex;align-items:center;gap:6px;flex-shrink:0}
.job__btn:hover{background:var(--primary);border-color:var(--primary)}
@media (max-width:680px){.job{flex-direction:column;align-items:flex-start}}

/* linha do tempo — carrossel por década com abas, estilo "Adobe Firefly"
   (referência visual enviada pelo usuário). Abas trocam a década (.tl-slide);
   dentro do slide ativo, os marcos funcionam em acordeão — só o marco
   clicado expande ícone+título+descrição, os outros ficam só com
   ícone+título (ver initTimelineCarousel() no main.js). */
/* trilho único arredondado envolvendo as abas (referência: barra de tabs
   do Adobe Firefly) — só a aba ativa vira uma pill preenchida, as outras
   ficam só como texto dentro do mesmo trilho, sem borda/fundo próprios.
   Cores seguem a identidade do site (gradiente --primary→--primary-2 na
   aba ativa), só o layout foi copiado da referência. A pill ativa é um
   elemento à parte (.tl-tabs__indicator, position:absolute), não o
   background do próprio botão — é isso que permite ela "deslizar" de uma
   aba pra outra (transform/width animados via transition) em vez de só
   aparecer/desaparecer de repente. Posição/tamanho calculados em JS
   (moveIndicator() dentro de initTimelineCarousel(), main.js), já que
   dependem da largura real de cada botão (texto variável). */
.tl-tabs{position:relative;display:flex;flex-wrap:wrap;gap:4px;width:fit-content;max-width:100%;margin:0 auto 28px;padding:6px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08)}
.tl-tabs__indicator{position:absolute;top:0;left:0;border-radius:999px;background:linear-gradient(135deg,var(--primary),var(--primary-2));box-shadow:0 10px 26px -10px var(--primary-glow);transition:transform .35s var(--ease-out), width .35s var(--ease-out), height .35s var(--ease-out);z-index:0;pointer-events:none}
.tl-tab{position:relative;z-index:1;padding:10px 22px;border-radius:999px;border:none;background:transparent;color:var(--text-dim);font-weight:600;font-size:14px;transition:color .25s}
.tl-tab:hover{color:#fff}
.tl-tab.active{color:#fff}

.tl-carousel{position:relative}
.tl-slide{display:none;position:relative;overflow:hidden;border-radius:28px;min-height:600px;border:1px solid rgba(255,255,255,.08)}
.tl-slide.active{display:block}

/* imagem (ou vídeo) de fundo full-bleed, uma por década — não mais por
   marco (ver .tl-mark, que perdeu data-tl-bg: os marcos só abrem/fecham o
   próprio texto no acordeão, sem trocar o fundo do slide). background-image
   inline no próprio .tl-slide__bg (mesma técnica/motivo do .erp-card__img:
   custom property com url() relativo quebraria, pois resolveria relativo à
   folha de estilo em vez do HTML) cobre o caso de foto; se um dia for
   vídeo, basta colocar um <video> dentro do .tl-slide__bg (ver regra
   abaixo) no lugar do background-image. background-color é o fallback
   enquanto a imagem/vídeo real não existe. */
.tl-slide__bg{position:absolute;inset:0;z-index:0;width:100%;height:100%;background-color:#0b0f1a;background-size:cover;background-position:center}
.tl-slide__bg img,.tl-slide__bg video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center}

/* gradiente escuro-esquerda → transparente-direita, mesma receita do
   .erp-card::before, garantindo contraste pro texto sobreposto à esquerda */
/* mais paradas que o degradê original, com queda gradual (nunca mais que
   ~.2 de opacidade entre uma parada e a seguinte) — pedido explícito do
   usuário depois de ver uma "linha" nítida separando a área escura da
   clara, mais visível ainda agora que o fundo é vídeo (movimento chama
   atenção pra qualquer costura). */
.tl-slide::before{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(90deg, rgba(5,7,13,.96) 0%, rgba(5,7,13,.9) 20%, rgba(5,7,13,.76) 38%, rgba(5,7,13,.56) 54%, rgba(5,7,13,.34) 68%, rgba(5,7,13,.14) 82%, rgba(5,7,13,0) 100%)}

/* área de texto alargada (era 540px) — pedido explícito do usuário pra
   caber mais texto no acordeão sem depender só do max-height do
   .tl-mark__text (ver logo abaixo). */
.tl-slide__body{position:relative;z-index:2;max-width:660px;padding:56px}
.tl-slide__title{font-family:var(--font-display);font-size:26px;color:#fff;margin-bottom:12px}
.tl-slide__lead{font-size:15px;color:var(--text-dim);line-height:1.7;margin-bottom:32px}

/* marcos em acordeão — mesma técnica de max-height do .nav__sub mobile */
.tl-marks{display:flex;flex-direction:column;gap:4px}
/* linha divisória só aparece encostada no marco ativo (acima e abaixo
   dele) — entre dois marcos inativos fica sem linha nenhuma. Por isso a
   borda começa transparente em todos e só o .active (mais o irmão logo
   depois dele, que é quem desenha a linha de baixo) recebe a cor real. */
.tl-mark{text-align:left;padding:12px 0;border-top:1px solid transparent;transition:border-color .3s}
.tl-mark:first-child{border-top:none}
.tl-mark.active,
.tl-mark.active + .tl-mark{border-top-color:rgba(255,255,255,.08)}
.tl-mark__head{display:flex;align-items:center;gap:12px}
.tl-mark__icon{width:32px;height:32px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.06);color:var(--primary-2);flex-shrink:0;transition:background .3s,color .3s}
.tl-mark__icon svg{width:16px;height:16px}
.tl-mark__title{font-size:15px;font-weight:600;color:#fff}
.tl-mark__text{display:block;max-height:0;opacity:0;overflow:hidden;font-size:13px;color:var(--text-dim);line-height:1.6;padding-left:44px;transition:max-height .4s var(--ease-out), opacity .3s var(--ease-out), margin-top .4s var(--ease-out)}
.tl-mark.active .tl-mark__text{max-height:180px;opacity:1;margin-top:8px}
.tl-mark.active .tl-mark__icon{background:linear-gradient(135deg,var(--primary),var(--primary-2));color:#fff}

/* botão "Conhecer soluções" por marco/slide, pedido explícito do usuário,
   posicionado no canto inferior direito do card — é irmão do
   .tl-slide__body (não filho dele), pra poder se posicionar relativo ao
   card inteiro (.tl-slide, que já tem position:relative) em vez de ficar
   preso à coluna de texto de 540px. Sobra bastante espaço vazio à direita
   (onde a imagem de fundo aparece livre, sem texto por cima), então o
   botão absoluto não esbarra em nada no desktop. */
.tl-slide__cta{position:absolute;right:40px;bottom:40px;z-index:2}

@media (max-width:900px){
  /* trilho de abas vira barra horizontal arrastável/deslizável (scroll
     nativo por toque) em vez de quebrar em várias linhas empilhadas —
     pedido explícito do usuário depois de ver as 5 abas quebrando em 3
     linhas no mobile (`flex-wrap:wrap` da regra genérica). `flex-wrap:
     nowrap` impede a quebra; `overflow-x:auto` deixa o conteúdo (mais
     largo que o trilho) rolar horizontalmente — a largura do `.tl-tabs`
     continua limitada por `max-width:100%` (regra genérica), então é o
     conteúdo interno que estoura e rola, não o elemento em si. Scrollbar
     escondida (`scrollbar-width:none`/`::-webkit-scrollbar{display:none}`)
     pra parecer um gesto de arrastar, não uma barra de rolagem comum.
     `.tl-tabs__indicator` (posicionado via `offsetLeft/offsetTop`, ver
     `moveIndicator()` no main.js) continua funcionando sem nenhuma
     mudança: esses valores são relativos ao `.tl-tabs` (seu
     `offsetParent`), não à viewport, então a pill acompanha a aba certa
     mesmo com o trilho rolado.
     Toque já rola nativo por causa do `overflow-x:auto`; o `cursor:grab`/
     `.is-dragging{cursor:grabbing}` abaixo são pro arrasto por
     mouse/trackpad, que não tem gesto de rolagem nativo — ver o bloco de
     `pointerdown/move/up` em `initTimelineCarousel()` (main.js) que move
     `root.scrollLeft` conforme o ponteiro anda. */
  .tl-tabs{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;justify-content:flex-start;cursor:grab}
  .tl-tabs::-webkit-scrollbar{display:none}
  .tl-tabs.is-dragging{cursor:grabbing}
  .tl-tab{flex-shrink:0}
  /* escurecimento leve nas duas pontas, sinalizando que dá pra arrastar
     pra ver mais abas — pedido explícito do usuário. Camadas extras de
     `background-image` (não um ::before/::after à parte) de propósito:
     um pseudo-elemento posicionado dentro do próprio `.tl-tabs` rolaria
     junto com o conteúdo (ele também é filho do elemento com
     overflow-x:auto), saindo de vista assim que o usuário rolasse —
     `background-image` num elemento não acompanha o *conteúdo* dele ao
     rolar (`background-attachment` padrão é `scroll`, que trava o fundo
     na caixa do próprio elemento, não no conteúdo interno), então essas
     duas manchas ficam sempre grudadas nas pontas visíveis do trilho,
     não importa o quanto ele tenha rolado. `border-radius:999px` do
     `.tl-tabs` já corta essas manchas na forma de pílula de graça
     (background sempre respeita o border-radius por padrão). */
  .tl-tabs{
    background-image:
      linear-gradient(90deg, rgba(5,7,13,.55) 0%, transparent 100%),
      linear-gradient(-90deg, rgba(5,7,13,.55) 0%, transparent 100%);
    background-repeat:no-repeat;
    background-position:left center, right center;
    background-size:32px 100%, 32px 100%;
  }
  .tl-slide{min-height:auto}
  .tl-slide__body{max-width:none;padding:32px 24px}
  .tl-slide::before{background:linear-gradient(180deg, rgba(5,7,13,.45) 0%, rgba(5,7,13,.62) 30%, rgba(5,7,13,.82) 55%, rgba(5,7,13,.94) 78%, rgba(5,7,13,.97) 100%)}
  /* no mobile o .tl-slide__body passa a ocupar a largura toda e cresce
     conforme os marcos abrem/fecham no acordeão — um botão absoluto fixo
     no canto inferior do card correria o risco de sobrepor o último
     marco. Em vez disso, o botão sai do position:absolute e volta ao
     fluxo normal (depois do .tl-slide__body, mesmo nível dentro do
     .tl-slide), com a margem esquerda automática fazendo o alinhamento à
     direita sem precisar de wrapper novo — display:flex (não
     inline-flex) é o que permite essa margem automática funcionar aqui,
     já que só caixas de bloco participam desse truque. */
  .tl-slide__cta{position:relative;z-index:2;display:flex;width:fit-content;margin:28px 24px 32px auto}
}

/* "Seção branca" — pedido explícito do usuário ("transforme a seção da
   linha do tempo... em uma seção branca"), mesma receita padrão de
   sempre (ver "Convenções gerais" no CLAUDE.md), aplicada via modificador
   próprio (`.tl-section--light`, mesmo padrão de `.ai-section--light`/
   `.erp-section--light`/`.pillars-section--light`) em vez de editar as
   regras base do componente. Os `.tl-slide` (cada década) **não**
   precisaram de nenhum ajuste — já são cards auto-contidos (imagem +
   degradê escuro + texto branco, mesma técnica de `.erp-card`/
   `.ramo-panel`), funcionam sobre qualquer fundo de seção. Só a "casca"
   fora dos slides (fundo da seção, título, trilho de abas) precisou de
   tema claro. */
.tl-section--light{position:relative;z-index:1;background:#e2e7f0}
.tl-section--light .section__title{color:#0b0f1a}
/* .tl-tabs usava um tom translúcido branco (pensado pro fundo escuro
   original) — quase invisível sobre #e2e7f0. `background-color`/
   `border-color` (não o shorthand `background`) de propósito: o
   shorthand resetaria `background-image` pra `none`, apagando o
   escurecimento leve nas pontas do trilho no mobile (`.tl-tabs{
   background-image:...}` dentro do media query logo acima) — aqui só
   trocamos a cor de base, sem mexer nesses dois gradientes extras. */
.tl-section--light .tl-tabs{background-color:rgba(11,15,26,.05);border-color:rgba(11,15,26,.1)}
/* `:not(.active)` evita empate de especificidade com `.tl-tab.active
   {color:#fff}` (mesma pegadinha já documentada em `.ai-section--light
   .ai-tab:not(.active)`) — a aba ativa já fica branca por cima do
   gradiente sólido do indicador, funciona igual em qualquer fundo de
   seção, não precisa de override. */
.tl-section--light .tl-tab:not(.active){color:var(--text-mute)}
.tl-section--light .tl-tab:not(.active):hover{color:#0b0f1a}

/* valores (página sobre) — lista editorial full-width, não grid de cards.
   Segunda versão: a primeira (grid 2x2 de caixas escuras arredondadas com
   numerozinho colorido) foi trocada a pedido do usuário por "parecer
   design genérico de IA". Motivo do redesenho: fugir da caixa-com-borda-
   arredondada-e-número-colorido (o padrão mais batido de landing page) e ir
   pra algo que não existe em nenhuma outra seção do site — numerais
   grandes "vazados" (só contorno, via -webkit-text-stroke, sem preenchimento)
   que só ganham cor (o gradiente --primary→--primary-2, mesma receita de
   outros destaques do site) no hover, junto com um leve deslocamento da
   linha inteira. Divisória horizontal simples entre itens, mesma
   linguagem das linhas entre marcos da linha do tempo (`.tl-mark`, ver
   seção própria) — reaproveita um padrão que já existe nesta mesma
   página em vez de inventar um terceiro estilo de borda. */
.values{display:flex;flex-direction:column}
.value{
  position:relative;
  display:grid;grid-template-columns:140px 1fr;align-items:center;gap:32px;
  padding:36px 4px;
  border-top:1px solid rgba(255,255,255,.08);
  transition:padding-left .4s var(--ease-out);
}
.value:first-child{border-top:none}
.value:hover{padding-left:16px}
.value__num{
  font-family:var(--font-display);font-weight:800;font-size:68px;line-height:1;letter-spacing:-.02em;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.16);
  transition:color .4s var(--ease-out);
}
.value:hover .value__num{
  -webkit-text-stroke:1.5px transparent;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.value h4{font-size:21px;font-weight:700;color:#fff;margin-bottom:10px}
.value p{font-size:14.5px;color:var(--text-dim);line-height:1.7;max-width:620px}
@media (max-width:640px){
  .value{grid-template-columns:1fr;gap:12px}
  .value__num{font-size:44px}
}

/* página de funcionalidades do módulo */
.feat-list__btn{margin-top:24px}
.feat-list{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
@media (max-width:680px){.feat-list{grid-template-columns:1fr}}
/* variante de largura cheia — pedido explícito do usuário ("essa seção
   está muito longa, conserte isso"): os 18 cards (super-app.html) viviam
   dentro da coluna de texto do `.showcase` (metade da largura do
   container), forçando 9 linhas de 2 colunas — bem mais alto que a
   imagem ao lado. Movida pra fora do `.showcase` (agora irmã dele,
   largura cheia do `.container`) e com mais colunas (`repeat(4,1fr)`),
   os mesmos 18 cards fecham em só 5 linhas. */
.feat-list--wide{grid-template-columns:repeat(4,1fr)}
@media (max-width:980px){.feat-list--wide{grid-template-columns:repeat(3,1fr)}}
@media (max-width:720px){.feat-list--wide{grid-template-columns:repeat(2,1fr)}}
@media (max-width:460px){.feat-list--wide{grid-template-columns:1fr}}
.feat-item{
  display:flex;gap:14px;
  padding:22px;border-radius:14px;
  background:rgba(15,20,35,.45);border:1px solid rgba(255,255,255,.06);
  transition:all .25s;
}
.feat-item:hover{border-color:rgba(13,110,233,.3)}
/* .feat-item .ic continua em uso — não é mais referenciado pelas 3 páginas
   de Gestão (ver .feat-item__num abaixo), mas o mesmo componente .feat-item
   também é usado em super-app.html (seção "Completo para motoristas e
   colaboradores"), que continua com o selo de ícone SVG de sempre; por
   isso essa regra não podia ser removida. */
.feat-item .ic{width:38px;height:38px;flex:0 0 38px;border-radius:10px;background:linear-gradient(135deg,rgba(13,110,233,.22),rgba(58,141,255,.06));border:1px solid rgba(13,110,233,.3);color:var(--primary-2);display:grid;place-items:center}
.feat-item .ic svg{width:18px;height:18px}
.feat-item h4{font-size:15px;color:#fff;margin-bottom:4px;font-weight:600}
.feat-item p{font-size:13.5px;color:var(--text-dim);line-height:1.55}
/* numeração no lugar do ícone SVG — pedido explícito do usuário ("tire os
   ícones dos cards e substitua por outra coisa"), só nas 3 páginas de
   Gestão (gestao-operacional/frotas/administrativa.html — super-app.html
   não foi tocada, ver nota acima). O .feat-list--plain que existia só pra
   gestao-operacional.html (removia fundo/borda do .ic ali) foi removido —
   diretamente substituído por este componente, não só pausado. Mesmo
   estilo do círculo sólido com gradiente já usado em .ia-step__num
   (stepper "Como funciona" de transnet-ia.html), só menor (38px, o mesmo
   tamanho que o .ic ocupava) pra caber no layout horizontal ícone+texto do
   .feat-item, em vez do stepper vertical/centralizado de onde o estilo foi
   copiado. */
.feat-item__num{
  width:38px;height:38px;flex:0 0 38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  color:#fff;font-weight:800;font-size:13px;
  box-shadow:0 8px 20px -8px var(--primary-glow);
}

/* "Completo para motoristas e colaboradores" (super-app.html) — "seção
   branca", mesma receita padrão de sempre (ver "Convenções gerais" no
   CLAUDE.md), pedido explícito do usuário junto com a reconstrução dos
   18 `.feat-item`. Modificador `.completo-section` na `<section>` — não
   editei `.feat-item`/`.ic` direto porque são compartilhados com as 3
   páginas de Gestão (o container `.feat-item` ainda é comum às duas
   variantes, ícone SVG ou `__num`; só a variante com ícone, exclusiva
   desta página, muda de cor aqui). */
.completo-section{position:relative;z-index:1;background:#e2e7f0}
.completo-section .section__title{color:#0b0f1a}
.completo-section .section__title span{color:var(--primary)}
.completo-section .section__lead{color:var(--text-mute)}
.completo-section .feat-item{background:#e9edf5;border-color:rgba(11,15,26,.08)}
.completo-section .feat-item h4{color:#0b0f1a}
.completo-section .feat-item p{color:var(--text-mute)}
.completo-section .feat-item .ic{background:rgba(11,15,26,.05);border-color:rgba(11,15,26,.09);color:var(--primary)}
/* layout "pill" de linha única — pedido explícito do usuário, com
   imagem de referência (cards curtos, ícone circular + título numa
   linha só), "mantenha a paleta de cores atual e mude apenas o layout".
   Escopado em `.completo-section` (não editando `.feat-item`/`.ic` base)
   porque as 3 páginas de Gestão continuam com `.feat-item__num` +
   título + descrição empilhados, que precisam da altura/padding maior
   do componente original — só esta página, sem descrição nos cards (ver
   "Descrições removidas dos 18 cards" acima), cabe no formato de linha
   única. */
.completo-section .feat-item{align-items:center;border-radius:18px;padding:16px 22px}
.completo-section .feat-item h4{margin-bottom:0}
.completo-section .feat-item .ic{border-radius:50%}
/* hover sutil — pedido explícito do usuário ("crie uma interação sutil
   para o hover dos cards dessa seção"): só um leve levantamento + sombra
   suave, sem trocar de cor (a receita "vira azul-escuro sólido" de
   outras seções claras foi deliberadamente deixada de fora aqui, pra
   manter discreto). */
.completo-section .feat-item:hover{transform:translateY(-3px);box-shadow:0 14px 26px -16px rgba(13,110,233,.35)}

/* utilitário */
.text-center{text-align:center}
.mt-24{margin-top:24px}
.mt-48{margin-top:48px}
/* esconde visualmente mas mantém acessível a leitores de tela — classe
   utilitária genérica. Chegou a ser usada na citação de JK do hero de
   sobre.html (ver .hero-quote) enquanto o carrossel visual era
   aria-hidden; desde que o texto passou a rolar por inteiro, sempre
   visível (já legível por leitor de tela, sem duplicata), ficou sem uso —
   mantida disponível pra reuso futuro. */
.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}

/* ========================================================
   FORMULÁRIO DE CONTATO
   ======================================================== */
.contact{
  position:relative;
  padding:110px 0 40px;
}
.contact__head{text-align:center;margin-bottom:60px}
.contact__eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--primary-2);font-weight:600;
  padding:6px 14px;border-radius:999px;
  background:rgba(13,110,233,.08);border:1px solid rgba(13,110,233,.22);
}
.contact__eyebrow::before{content:"";width:14px;height:1px;background:var(--primary-2)}
.contact__title{
  font-family:var(--font-display);
  font-size:clamp(36px,4.4vw,58px);
  color:#fff;letter-spacing:-.028em;font-weight:700;
  margin-top:18px;
}
.contact__title span{
  color:var(--primary-2);
}
.contact__lead{
  margin-top:16px;color:var(--text-dim);font-size:17px;
  max-width:600px;margin-left:auto;margin-right:auto;
}

.contact__grid{
  display:grid;
  grid-template-columns:.85fr 1.35fr;
  gap:60px;
  align-items:start;
}
@media (max-width:940px){
  .contact__grid{grid-template-columns:1fr;gap:40px}
}

/* coluna esquerda — informações */
.contact__info{
  padding:36px;
  border-radius:24px;
  background:
    radial-gradient(500px 300px at 0% 0%, rgba(13,110,233,.18), transparent 60%),
    linear-gradient(180deg, rgba(15,20,35,.55) 0%, rgba(8,12,22,.55) 100%);
  border:1px solid rgba(255,255,255,.06);
  position:relative;
  overflow:hidden;
}
.contact__info::before{
  content:"";position:absolute;inset:-1px;border-radius:24px;padding:1px;
  background:linear-gradient(135deg,rgba(13,110,233,.5),transparent 55%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;
}
.contact__company{font-size:15px;color:#fff;font-weight:600;margin-bottom:6px}
.contact__email{
  font-size:15px;color:var(--primary-2);
  display:inline-flex;align-items:center;gap:8px;
  margin-bottom:32px;font-weight:500;
  transition:color .2s;
}
.contact__email:hover{color:#7cc4ff}
.contact__email svg{width:16px;height:16px}

.contact__branch{margin-bottom:26px;padding-bottom:26px;border-bottom:1px solid rgba(255,255,255,.06)}
.contact__branch:last-child{border-bottom:0;padding-bottom:0;margin-bottom:0}
.contact__branch h4{
  font-family:var(--font-display);font-weight:700;
  font-size:13px;letter-spacing:.14em;text-transform:uppercase;
  color:#fff;margin-bottom:12px;
  display:flex;align-items:center;gap:10px;
}
.contact__branch h4 .pin{
  width:26px;height:26px;border-radius:8px;
  background:linear-gradient(135deg,rgba(13,110,233,.25),rgba(58,141,255,.10));
  border:1px solid rgba(13,110,233,.3);
  display:grid;place-items:center;color:var(--primary-2);
}
.contact__branch h4 .pin svg{width:14px;height:14px}
.contact__branch p{font-size:14px;color:var(--text-dim);line-height:1.65;margin-bottom:4px}
.contact__branch a{color:#fff;font-weight:600;transition:color .2s}
.contact__branch a:hover{color:var(--primary-2)}

/* coluna direita — formulário */
.contact__form{
  padding:40px;
  border-radius:24px;
  background:linear-gradient(180deg, rgba(15,20,35,.55) 0%, rgba(8,12,22,.55) 100%);
  border:1px solid rgba(255,255,255,.06);
  position:relative;
}
@media (max-width:520px){
  .contact__form{padding:28px 22px}
  .contact__info{padding:28px 22px}
}

.form-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:16px;
}
.form-field{position:relative}
.form-field.full{grid-column:1 / -1}
.form-field.rows-3{grid-row:span 3}
@media (max-width:640px){
  .form-grid{grid-template-columns:1fr}
  .form-field.rows-3{grid-row:auto}
}

.form-input,
.form-select,
.form-textarea{
  width:100%;
  padding:16px 18px;
  font-family:inherit;font-size:15px;
  color:#fff;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.08);
  border-radius:12px;
  outline:none;
  transition:border-color .25s, background .25s, box-shadow .25s;
}
.form-textarea{
  resize:vertical;
  min-height:100%;
  height:100%;
  font-family:inherit;
  line-height:1.55;
}
.form-input::placeholder,
.form-textarea::placeholder{color:var(--text-mute)}
.form-input:hover,
.form-select:hover,
.form-textarea:hover{border-color:rgba(255,255,255,.14)}
.form-input:focus,
.form-select:focus,
.form-textarea:focus{
  border-color:var(--primary);
  background:rgba(13,110,233,.05);
  box-shadow:0 0 0 4px rgba(13,110,233,.12);
}

/* seta do select */
.form-select{
  appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'><path d='M1 1.5L6 6.5L11 1.5' stroke='%237cc4ff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat;
  background-position:right 18px center;
  padding-right:44px;
  cursor:pointer;
  color:var(--text-mute);
}
.form-select.has-value{color:#fff}
.form-select option{background:#0a0e18;color:#fff}

.form-check{
  display:flex;align-items:flex-start;gap:12px;
  margin-top:22px;
  font-size:13px;color:var(--text-dim);line-height:1.6;
}
.form-check input{
  appearance:none;-webkit-appearance:none;
  width:18px;height:18px;flex:0 0 18px;
  border:1px solid rgba(255,255,255,.20);
  border-radius:5px;
  background:rgba(255,255,255,.03);
  cursor:pointer;position:relative;margin-top:2px;
  transition:border-color .2s, background .2s;
}
.form-check input:hover{border-color:var(--primary)}
.form-check input:checked{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  border-color:transparent;
}
.form-check input:checked::after{
  content:"";position:absolute;left:5px;top:2px;
  width:5px;height:9px;
  border:solid #fff;border-width:0 2px 2px 0;
  transform:rotate(45deg);
}
.form-check a{color:var(--primary-2);font-weight:600}
.form-check a:hover{text-decoration:underline}

.form-fake-recaptcha{
  display:flex;align-items:center;gap:14px;
  padding:14px 18px;margin-top:22px;
  border-radius:10px;
  background:rgba(255,255,255,.02);
  border:1px solid rgba(255,255,255,.08);
  font-size:13px;color:var(--text-dim);
}
.form-fake-recaptcha .box{
  width:22px;height:22px;border-radius:4px;
  border:1.5px solid rgba(255,255,255,.25);
  background:rgba(255,255,255,.03);
}
.form-fake-recaptcha .brand{margin-left:auto;font-size:10px;letter-spacing:.1em;color:var(--text-mute);text-align:right}
.form-fake-recaptcha .brand b{display:block;color:#fff;font-size:11px;font-weight:700;letter-spacing:0}

.form-submit{
  width:100%;
  margin-top:22px;
  padding:18px 24px;
  border-radius:14px;
  background:linear-gradient(135deg,var(--primary) 0%,var(--primary-2) 100%);
  color:#fff;font-weight:700;font-size:15px;letter-spacing:.06em;
  text-transform:uppercase;
  box-shadow:0 12px 36px -10px var(--primary-glow), inset 0 0 0 1px rgba(255,255,255,.15);
  transition:transform .25s var(--ease-out), box-shadow .25s;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
}
.form-submit:hover{transform:translateY(-2px);box-shadow:0 20px 44px -12px var(--primary-glow)}
.form-submit .arrow{transition:transform .25s}

/* ========================================================
   PILARES DE VALOR — .pillars/.pillar (componente genérico)
   ======================================================== */
/* 3 (ou mais) cartões de valor com ícone no topo centralizado — nasceu
   em transnet/power-bi.html (".bi-pillars"/".bi-pillar", ver CLAUDE.md),
   generalizado (renomeado, sem duplicar CSS) quando transnet-ia.html
   precisou do mesmo componente. Mesma técnica de anel-de-gradiente-só-
   no-hover já usada em .integ-card/.social-card, só que em formato de
   pilar (ícone no topo) em vez do selo lateral que .feat-item usa.
   `.pillars-section--light` (bloco logo abaixo) é um modificador à parte —
   a variante de tema claro da seção que contém `.pillar`s, reaproveitada
   depois em `super-app.html` também (nasceu como `.bi-pillars-section`,
   nome específico do Power BI, renomeado quando deixou de ser exclusiva
   de uma página só). */
.pillars{
  display:grid;grid-template-columns:repeat(3,1fr);gap:24px;
  margin-top:56px;
}
/* instância de "3 pilares" ao lado de uma imagem (`.showcase`, ver
   `super-app.html` — pedido explícito do usuário pra encaixar
   `tela_home_superapp.webp` na seção) — coluna única empilhada em vez de
   3 lado a lado (não cabe numa metade de `.showcase`), texto alinhado à
   esquerda pra acompanhar o título/lead acima, que também são left por
   padrão nesse contexto (sem `.section__head`, ver HTML). Escopado por
   `.showcase .pillars`, não precisa de um novo modificador de seção —
   só bate quando `.pillars` vive dentro de um `.showcase` mesmo. */
.showcase .pillars{grid-template-columns:1fr;gap:16px;margin-top:40px}
.showcase .pillar{text-align:left;padding:20px 24px}
/* pedido explícito do usuário, em seguida ("não coloque ícones, conecte
   os cards por meio de linhas") — `.pillar__icon` (selo com SVG) saiu,
   trocado por `.pillar__node` (um ponto sólido) + uma linha vertical
   única atrás de todo o `.pillars--connected` (`::before`, `top:0;
   bottom:0`, com degradê que esvanece nas duas pontas em vez de cortar
   seco — perdoa qualquer imprecisão de alinhamento com o nó do 1º/último
   card). A linha só fica visível nos vãos entre os cards: dentro de cada
   `.pillar` ela some atrás do fundo opaco do próprio card (`.pillar` tem
   z-index:1 > a linha, que fica no z-index padrão/auto do `::before`),
   então o efeito final é "nó marcando o topo de cada card + segmento de
   linha conectando um card ao próximo" — não precisa calcular a posição
   exata da linha por card, só alinhar a coordenada X com o centro do nó
   (`left:28px`, nó com `width:10px` a partir do `padding-left:24px` do
   card = centro em 29px). */
.pillars--connected{position:relative}
.pillars--connected::before{
  content:"";position:absolute;left:28px;top:0;bottom:0;width:2px;
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(13,110,233,.35) 12%,
    rgba(13,110,233,.35) 88%,
    transparent 100%);
  z-index:0;
}
.pillars--connected .pillar{position:relative;z-index:1}
.pillars--connected .pillar__node{
  display:block;width:10px;height:10px;border-radius:50%;
  margin:2px 0 16px;
  background:var(--primary);
  box-shadow:0 0 0 4px rgba(13,110,233,.15);
}
/* glow atrás da screenshot, mesma receita do `.app-visual::before` (seção
   "Completo para..." desta mesma página) — reaproveitado pra manter a
   mesma linguagem visual entre as 2 imagens de celular da página.
   Nasceu com a imagem dentro de um `.phone-frame` (moldura própria,
   border+notch) — removido a pedido do usuário ("não coloque um mockup
   de celular, pode deixar só a imagem"): `tela_home_superapp.webp` já é
   uma composição pronta com o aparelho "assado" na própria imagem (mesmo
   padrão de `telas_superapp.webp`/`telas-transnet-*.webp` usados em
   outras páginas), então a moldura de CSS por cima duplicava o aparelho
   (um celular desenhado dentro de outro). `.pillars-section__img` é só
   a imagem crua, mesmo tratamento de `.app-visual__img` (sizing +
   drop-shadow, sem borda/recorte). */
.pillars-section__visual{
  position:relative;
  display:flex;flex-direction:column;justify-content:center;align-items:center;
  padding:20px 0;
}
.pillars-section__visual::before{
  content:"";position:absolute;inset:-10%;
  background:radial-gradient(closest-side, rgba(13,110,233,.28), transparent 70%);
  filter:blur(30px);z-index:0;
}
.pillars-section__img{
  position:relative;z-index:1;
  width:100%;max-width:280px;height:auto;
  filter:drop-shadow(0 40px 70px rgba(0,0,0,.35));
}
/* botão "Explorar funcionalidades" abaixo da imagem — pedido explícito
   do usuário. Passou por `.btn--ghost` (translúcido escuro, depois
   branco sólido) até o usuário pedir "troque esse botão pelo botão de
   CTA" — virou `.btn--primary` puro (mesmo gradiente `--primary`→
   `--primary-2` do resto dos CTAs primários do site). Não usa
   `.btn--solucoes` porque o texto não é "Conhecer Soluções" — essa
   classe é reservada só pro texto exato (ver "Convenções gerais" no
   CLAUDE.md). Já funciona sobre o fundo claro da seção sem nenhum
   override de cor (`.btn--primary` é uma pill sólida com cor própria,
   não depende do fundo por trás) — só precisou do posicionamento. */
.pillars-section__btn{position:relative;z-index:1;margin-top:24px}
/* seção "Personalização" (super-app.html). Chegou a ter `background:
   var(--bg-2)` (um tom mais claro que o preto padrão, pra suavizar a
   transição vindo da seção clara anterior) e depois uma versão branca —
   ambas revertidas. Fundo customizado removido de vez a pedido do
   usuário ("deixe o background da mesma forma que da seção de
   feedbacks") — `#depoimentos` (home) não define nenhum `background`
   próprio (`.testimonials{position:relative}`, sem cor), só herda o
   preto padrão do site (`--bg-0`, do `body`); pra bater exatamente igual,
   `.brand-section` também deixou de fixar uma cor própria, só
   `position:relative;z-index:1` (continua necessário pelo motivo de
   sempre: ancorar o `.particles-bg`/canvas e proteger contra a grade
   ambiente global). */
/* redesenho "escuro e premium" — pedido explícito do usuário ("Refaça
   essa seção, quero que ela seja uma seção escura e premium"). Fundo
   deixou de ser só `--bg-0` plano e ganhou um brilho radial azul bem
   sutil no topo (`radial-gradient`, ~900px de raio, esmaece antes de
   30% da altura) — mesma ideia de "spotlight" usada em vários produtos
   SaaS premium: dá profundidade sem competir com a rede de partículas
   (`data-subtle`) nem com o texto por cima. */
.brand-section{
  position:relative;z-index:1;
  background:radial-gradient(ellipse 900px 460px at 50% -8%, rgba(13,110,233,.16), transparent 70%), var(--bg-0);
}
/* botão "Conhecer soluções" abaixo dos 2 `.brand-feature` — pedido
   explícito do usuário, markup canônico de sempre (ver "Convenções
   gerais" no CLAUDE.md). */
.brand-section__cta{display:flex;justify-content:center;margin-top:56px}
/* "Feature spotlight" — pedido explícito do usuário ("não gostei muito
   do design dessa nova seção, melhore ele"), depois da 1ª versão (grid
   de `.pillar` — o mesmo componente de card já usado na seção "3
   pilares" logo acima) ter ficado repetitiva/genérica. 2 painéis
   horizontais largos (ícone maior + texto), não mais caixas quadradas
   lado a lado — mais editorial, e não duplica o vocabulário visual da
   seção anterior na mesma página. Numeral grande "vazado" ao fundo
   (`.brand-feature__num`, mesma técnica de `.value__num`/`.pillar__num`
   já usada em outras páginas) dá um toque de riqueza visual sem repetir
   o selo de ícone genérico como único elemento decorativo.
   Cards elevados a "vidro premium" na mesma rodada do fundo com glow:
   `backdrop-filter:blur` (o card agora deixa passar/desfoca a luz do
   fundo atrás dele, em vez de só um tom quase-sólido), fundo em degradê
   sutil (não mais cor chapada), borda com leve tom azul (não mais cinza
   neutro) e sombra própria mais profunda — cada card lê como um painel
   de vidro flutuando sobre o glow, não uma caixa lisa. Uma linha de
   brilho fina no topo (`::after`, gradiente que esvanece nas pontas)
   simula o reflexo de uma borda de vidro biselada, reforçando a leitura
   "premium" sem precisar de mais nenhum elemento novo. */
.brand-features{
  display:flex;flex-direction:column;gap:22px;
  max-width:820px;margin:52px auto 0;
}
.brand-feature{
  position:relative;isolation:isolate;overflow:hidden;
  display:flex;align-items:center;gap:28px;
  padding:36px 40px;border-radius:24px;
  background:linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.015));
  border:1px solid rgba(90,150,255,.16);
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  box-shadow:0 30px 60px -34px rgba(0,0,0,.6);
  transition:transform .35s var(--ease-out), border-color .35s, box-shadow .35s, background .3s;
}
.brand-feature::after{
  content:"";position:absolute;top:0;left:32px;right:32px;height:1px;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent);
  pointer-events:none;
}
.brand-feature:hover{
  transform:translateY(-5px);
  border-color:transparent;
  box-shadow:0 34px 70px -30px rgba(13,110,233,.4);
}
.brand-feature::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  -webkit-mask:linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:0;transition:opacity .35s;pointer-events:none;
}
.brand-feature:hover::before{opacity:1}
.brand-feature__body{position:relative;z-index:1}
.brand-feature__body h3{font-size:22px;font-weight:700;color:#fff;margin-bottom:8px;letter-spacing:-.01em}
.brand-feature__body p{font-size:15px;color:var(--text-dim);line-height:1.6;max-width:480px}
.brand-feature__num{
  position:absolute;right:28px;top:50%;transform:translateY(-50%);
  z-index:0;font-family:var(--font-display);font-weight:800;
  font-size:96px;line-height:1;letter-spacing:-.02em;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.1);
  pointer-events:none;
}
@media (max-width:640px){
  .brand-feature{flex-wrap:wrap;padding:30px 26px;gap:18px}
  .brand-feature__num{display:none}
}
.pillar{
  position:relative;
  padding:32px 28px;border-radius:20px;
  background:rgba(255,255,255,.02);
  border:1px solid rgba(255,255,255,.07);
  text-align:center;
  transition:transform .35s var(--ease-out), box-shadow .35s, background-color .15s, border-color .15s;
}
.pillar::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  -webkit-mask:linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  opacity:0;transition:opacity .35s;pointer-events:none;
}
.pillar:hover{transform:translateY(-6px);box-shadow:0 24px 60px -24px rgba(13,110,233,.4)}
.pillar:hover::before{opacity:1}
.pillar__icon{
  width:52px;height:52px;margin:0 auto 20px;
  display:flex;align-items:center;justify-content:center;
  border-radius:14px;background:rgba(13,110,233,.12);color:var(--primary-2);
  transition:background-color .15s, border-color .15s, color .15s;
}
.pillar__icon svg{width:24px;height:24px}
.pillar h3{font-size:19px;font-weight:700;color:#fff;margin-bottom:10px;transition:color .15s}
.pillar p{font-size:15px;color:var(--text-dim);line-height:1.6;transition:color .15s}
@media (max-width:820px){
  .pillars{grid-template-columns:1fr;gap:18px}
}

/* Variante numerada — pedido explícito do usuário, só na 1ª seção
   ("3 pilares") de transnet-ia.html: "não quero ícones nos cards mas sim
   números... que o número parece uma marca d'água". Modificador
   (`.pillars--numbered`, no `.pillars`, não em `.pillar__icon` — os 2
   outros usos de `.pillar` no site, power-bi.html e super-app.html,
   continuam com ícone normal) trocando o `.pillar__icon` (selo com SVG)
   por `.pillar__num`, um numeral grande centralizado no topo do card, no
   lugar onde o ícone ficava.
   Passou por várias rodadas de cor — mesmo azul em 3 opacidades, depois 3
   tons de azul do site (`--accent`/`--primary-2`/`--primary`) ainda com
   opacidade crescente, depois 3 tons "fortes" sólidos (`--primary-2`/
   `--primary`/um tom novo mais profundo, sem opacidade nenhuma) — até o
   usuário pedir de volta o visual original ("deixe vazado como estava
   antes"). **Versão final = a primeira**: "vazado", só contorno via
   `-webkit-text-stroke` (sem preenchimento, mesma técnica de
   `.value__num`, seção "Nossos valores" em `sobre.html`), que ganha o
   gradiente da marca (`--primary`→`--primary-2`, via `background-clip:
   text`) só no hover do card — é isso que lê como "marca d'água": um
   numeral grande, oco, quase invisível em repouso, que só "acende" ao
   interagir. */
.pillars--numbered .pillar__num{
  display:block;margin:0 auto 16px;
  font-family:var(--font-display);font-weight:800;font-size:56px;line-height:1;letter-spacing:-.02em;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.16);
  transition:color .4s var(--ease-out);
}
.pillars--numbered .pillar:hover .pillar__num{
  -webkit-text-stroke:1.5px transparent;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* Cards glassmórficos — pedido explícito do usuário ("quero que os cards
   desfoquem o fundo, quero eles como elementos glassmórficos"), só nesta
   instância (`.pillars--numbered`, mesmo escopo de todas as mudanças
   anteriores nesta seção — power-bi.html/super-app.html continuam com o
   `.pillar` padrão, sem blur). `backdrop-filter:blur` desfoca o que está
   atrás do card (a grade de pontos ambiente do fundo, `body::after`, e o
   canvas de partículas do hero logo acima) através dele — só tem efeito
   visível porque agora há algo com textura por trás pra desfocar; fundo
   um pouco mais opaco que o `.pillar` padrão (`rgba(255,255,255,.06)`,
   era `.02`) e borda um pouco mais visível (`.14`, era `.07`) reforçam a
   leitura de "vidro fosco" em vez de só "levemente mais claro que o
   fundo". `-webkit-backdrop-filter` necessário pro Safari. */
.pillars--numbered .pillar{
  background-color:rgba(255,255,255,.06);
  border-color:rgba(255,255,255,.14);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
}

/* Fundo claro sólido — pedido explícito do usuário, mesma receita exata
   da seção "Redes sociais" (.social-section, sobre.html): fundo cinza-
   azulado (#e2e7f0), cards num tom levemente mais claro (#e9edf5), ícone
   com selo neutro (sem tint azul), textos reescritos pro contraste certo
   sobre claro (--text-mute em vez de --text-dim, que só dá ~2.5:1 sobre
   fundo claro), e no hover o card "vira" azul-escuro (#0d1f3d) em vez do
   anel de gradiente — mesmo motivo: o anel (::before) foi desenhado pra
   contrastar com um fundo escuro, ficaria fraco/estranho aqui. */
.pillars-section--light{position:relative;z-index:1;background:#e2e7f0}
.pillars-section--light .section__eyebrow{color:var(--text-mute)}
.pillars-section--light .section__title{color:#0b0f1a}
.pillars-section--light .section__lead{color:var(--text-mute)}
.pillars-section--light .pillar{background:#e9edf5;border-color:rgba(11,15,26,.08)}
.pillars-section--light .pillar__icon{background:rgba(11,15,26,.05);border-color:rgba(11,15,26,.09);color:var(--primary)}
.pillars-section--light .pillar h3{color:#0b0f1a}
.pillars-section--light .pillar p{color:var(--text-mute)}
.pillars-section--light .pillar:hover{
  background:#0d1f3d;
  border-color:transparent;
  box-shadow:0 24px 48px -20px rgba(5,7,13,.45);
}
.pillars-section--light .pillar:hover::before{opacity:0}
.pillars-section--light .pillar:hover .pillar__icon{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14);color:var(--primary-2)}
.pillars-section--light .pillar:hover h3{color:#fff}
.pillars-section--light .pillar:hover p{color:var(--text-dim)}

/* ========================================================
   POWER BI — galeria de painéis (abas + prints reais)
   ======================================================== */
/* reaproveita .modules__tabs/.modules__tab (mesmo pill-row de #modulos,
   ver CLAUDE.md) pro seletor de categoria; .bi-panel é novo, já que o
   conteúdo (texto + print emoldurado) não tem nada a ver com o grid de
   .card do painel de módulos. position:relative é necessário pro
   .particles-bg (position:absolute;inset:0) se ancorar nesta seção, não
   num ancestral mais acima (mesma regra que .modules já tem). */
.bi-gallery{position:relative}
.bi-panel{
  display:none;
  grid-template-columns:minmax(240px,360px) 1fr;
  gap:48px;align-items:center;
  margin-top:8px;padding:40px;border-radius:28px;
  background:linear-gradient(160deg, rgba(13,110,233,.08), rgba(255,255,255,.015));
  border:1px solid rgba(255,255,255,.08);
}
.bi-panel.active{display:grid}
.bi-panel__text h3{font-size:27px;font-weight:700;color:#fff;margin-bottom:14px}
.bi-panel__text p{font-size:16px;color:var(--text-dim);line-height:1.65}
.bi-panel__frame{
  border-radius:18px;overflow:hidden;background:#0b0f1a;
  border:1px solid rgba(255,255,255,.12);
  box-shadow:0 30px 70px -24px rgba(0,0,0,.6), 0 0 0 1px rgba(13,110,233,.15);
}
/* barra de "janela" fake — só um toque de identidade de produto de
   verdade (o print já mostra a UI real do Power BI logo abaixo). */
.bi-panel__bar{
  display:flex;gap:7px;align-items:center;
  padding:12px 16px;background:#12161f;
  border-bottom:1px solid rgba(255,255,255,.06);
}
.bi-panel__bar i{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.15)}
.bi-panel__bar i:nth-child(1){background:#ff5f57}
.bi-panel__bar i:nth-child(2){background:#febc2e}
.bi-panel__bar i:nth-child(3){background:#28c840}
.bi-panel__frame img{display:block;width:100%;height:auto}
.bi-gallery__cta{display:flex;justify-content:center;margin-top:48px}
@media (max-width:900px){
  .bi-panel{grid-template-columns:1fr;padding:24px;gap:24px}
}

/* ========================================================
   TRANSNET IA — "Como funciona" (3 passos numerados)
   ======================================================== */
/* Stepper horizontal simples — 3 círculos numerados ligados por uma linha
   fina em gradiente, cada um com título+texto embaixo. Mais direto que
   reaproveitar `.pillars` aqui (que já é usado na seção de valor logo
   acima, na mesma página) — variar a forma (numeração vs. ícone) entre
   as duas seções vizinhas evita que a página inteira vire "grid de 3
   cards" repetido sem necessidade. */
.ia-steps{
  display:grid;grid-template-columns:repeat(3,1fr);gap:32px;
  margin-top:56px;position:relative;
}
.ia-steps::before{
  content:"";position:absolute;top:26px;
  left:calc(16.666% + 26px);right:calc(16.666% + 26px);
  height:2px;background:linear-gradient(90deg,var(--primary),var(--primary-2));
  opacity:.35;z-index:0;
}
.ia-step{position:relative;text-align:center;padding:0 12px;z-index:1}
.ia-step__num{
  width:52px;height:52px;margin:0 auto 20px;
  display:flex;align-items:center;justify-content:center;
  border-radius:50%;background:linear-gradient(135deg,var(--primary),var(--primary-2));
  color:#fff;font-weight:800;font-size:19px;
  box-shadow:0 10px 30px -10px var(--primary-glow);
}
.ia-step h3{font-size:18px;font-weight:700;color:#fff;margin-bottom:8px}
.ia-step p{font-size:14.5px;color:var(--text-dim);line-height:1.6;max-width:280px;margin:0 auto}
@media (max-width:820px){
  .ia-steps{grid-template-columns:1fr;gap:40px}
  .ia-steps::before{display:none}
}

/* Fundo claro sólido — pedido explícito do usuário, mesma receita exata já
   usada em `.social-section` (sobre.html) e `.pillars-section--light` (Power
   BI): fundo cinza-azulado (#e2e7f0), título em #0b0f1a, lead/texto em
   --text-mute (não --text-dim, que só dá ~2.5:1 de contraste sobre fundo
   claro, contra ~5:1 do --text-mute). Diferente das outras duas, não há
   "card" aqui pra recolorir nem estado de hover pra trocar de tema — é só
   texto solto sobre o fundo, então a receita fica mais enxuta (sem
   transitions/hover, que não têm propósito aqui). O círculo numerado
   (`.ia-step__num`) não precisou de override: já é um selo sólido com
   gradiente + número branco, contrasta igual sobre claro ou escuro. */
.ia-steps-section{position:relative;z-index:1;background:#e2e7f0}
.ia-steps-section .section__title{color:#0b0f1a}
.ia-steps-section .section__lead{color:var(--text-mute)}
.ia-steps-section .ia-step h3{color:#0b0f1a}
.ia-steps-section .ia-step p{color:var(--text-mute)}

/* ========================================================
   TRANSNET IA — seção de demonstração (.ai-block reaproveitado)
   ======================================================== */
/* position:relative necessário pro .ai-wave-canvas (position:absolute;
   inset:0) se ancorar nesta seção, não num ancestral mais acima (mesma
   regra que .bi-gallery precisou pro .particles-bg — ver CLAUDE.md,
   "Luzes ambiente"/"Grade de onda"). */
.ia-demo{position:relative}
.ia-demo__cta{display:flex;justify-content:center;margin-top:48px}

/* variante de .ai-grid pra caber um relatório executivo inteiro (KPIs +
   gráfico/tabelas + resumo) embaixo do prompt, em vez do gráfico simples
   ao lado dele — o .ai-grid padrão (2 colunas, usado em index.html#ai)
   fica estreito demais pra um mockup de relatório real; aqui o prompt
   fica em cima e o relatório ocupa a largura inteira do .ai-block abaixo.
   Escopado como modificador (não mexe em .ai-grid) porque index.html
   continua usando o layout de 2 colunas original. */
.ai-grid--report{grid-template-columns:1fr;gap:32px}

/* RELATÓRIO EXECUTIVO — mockup fiel ao formato real que a Transnet IA
   gera (ver captura enviada pelo usuário: KPIs, ranking, tabelas e um
   "Resumo executivo" com 1) O que aconteceu 2) Por que aconteceu 3) O que
   deve ser feito). Reaproveita .ai-answer como moldura externa. */
.ai-report__head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:20px}
.ai-report__head h4{font-size:16px;font-weight:700;color:#fff}
.ai-report__head span{font-size:13px;color:var(--text-mute)}

.ai-kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.ai-kpi{
  padding:14px 16px;border-radius:12px;
  background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);
  border-left:3px solid var(--primary-2);
}
/* variações de cor do selo lateral — mesma convenção de KPI colorido por
   categoria já vista na captura real (positivo/atenção/risco), sem
   inventar uma paleta nova: reaproveita as cores que o site já usa em
   outros indicadores de status (verde do .ai-answer h4 .dot, âmbar/
   vermelho do restante do site). */
.ai-kpi--warn{border-left-color:#f5a524}
.ai-kpi--danger{border-left-color:#e0475c}
.ai-kpi--ok{border-left-color:#22c55e}
.ai-kpi__label{font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--text-mute);margin-bottom:6px}
.ai-kpi__value{font-size:18px;font-weight:800;color:#fff;line-height:1.15}
.ai-kpi__sub{font-size:11.5px;color:var(--text-dim);margin-top:4px}
@media (max-width:640px){.ai-kpis{grid-template-columns:repeat(2,1fr)}}

/* ranking horizontal — mesmo papel do .ai-bars (barras verticais já
   existentes), só que deitado, pro layout "linha + barra + valor" da
   captura real ("Linhas com maior receita"). Nome/estrutura deliberadamente
   paralelos a .ai-bars: .ai-hbar__fill[data-v] é o equivalente ao
   .ai-bars div[data-v] que animateBars() já lê — animateHBars() (main.js)
   segue a mesma receita, só anima width em vez de height. */
.ai-hbars{display:flex;flex-direction:column;gap:12px;margin-top:20px}
.ai-hbar{display:grid;grid-template-columns:52px 1fr auto;align-items:center;gap:12px}
.ai-hbar__label{font-size:13px;font-weight:700;color:var(--text-dim)}
.ai-hbar__track{height:8px;border-radius:999px;background:rgba(255,255,255,.06);overflow:hidden}
.ai-hbar__fill{display:block;height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,var(--primary),var(--primary-2))}
.ai-hbar__value{font-size:13px;font-weight:700;color:#fff;white-space:nowrap}

/* 2 tabelas lado a lado (reaproveita .ai-table em cada coluna) — "Mais
   rentáveis / Menos eficientes" e "Ranking de Criticidade" na captura
   real usam exatamente esse formato de comparação em par. */
.ai-tables-2col{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-top:24px}
.ai-tables-2col h5{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-mute);margin-bottom:12px}
@media (max-width:720px){.ai-tables-2col{grid-template-columns:1fr}}

/* cruzamento de variáveis ("Raio-X de um Insight") — Coluna A + Coluna B
   levando a um cruzamento lógico e uma ação sugerida, mesma estrutura do
   Material de Apoio Folder.pdf. Compacto o bastante pra caber dentro de
   um .ai-report sem virar uma seção à parte. */
.ai-insight{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.ai-insight__box{padding:14px 16px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}
.ai-insight__box h5{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--primary-2);margin-bottom:8px}
.ai-insight__box p{font-size:13px;color:var(--text-dim);line-height:1.55}
.ai-insight__logic{
  grid-column:1/-1;margin-top:2px;padding:14px 16px;border-radius:12px;
  background:rgba(13,110,233,.08);border:1px solid rgba(13,110,233,.25);
  font-size:13.5px;color:#fff;font-style:italic;text-align:center;
}
@media (max-width:640px){.ai-insight{grid-template-columns:1fr}}

/* resumo executivo — a caixa "1) O que aconteceu 2) Por que aconteceu
   3) O que deve ser feito" que todo relatório real da IA gera (ver
   Assistente IA.pdf, prompt CONTEXTO/AÇÃO). */
.ai-summary{
  margin-top:24px;padding:18px 20px;border-radius:14px;
  background:rgba(13,110,233,.08);border:1px solid rgba(13,110,233,.25);
}
.ai-summary__item{font-size:13.5px;color:var(--text-dim);line-height:1.65}
.ai-summary__item+.ai-summary__item{margin-top:10px}
.ai-summary__item b{color:var(--primary-2);font-weight:700}

/* ========================================================
   TRANSNET IA — "Método Tradicional × Novo Padrão" e C.R.A.F.T.
   ======================================================== */
/* comparação antes/depois — reaproveitada duas vezes nesta página: na
   seção "A Evolução da Rotina de Análise" (sem IA × com Transnet IA) e,
   com o mesmo componente, no exemplo "Pedido comum × Comando C.R.A.F.T."
   dentro da seção do método. Coluna da esquerda em cinza neutro (extração
   manual, resultado genérico); coluna da direita com o azul da marca
   (resultado da IA), cada item com ícone de check só do lado "novo". */
.ia-compare{display:grid;grid-template-columns:1fr 1fr;gap:32px;margin-top:48px}
.ia-compare__col h3{font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:20px;text-align:center}
.ia-compare__col--old h3{color:var(--text-mute)}
.ia-compare__col--new h3{color:var(--primary-2)}
.ia-compare__item{
  padding:16px 18px;border-radius:14px;margin-bottom:12px;
  font-size:14px;line-height:1.55;
}
.ia-compare__col--old .ia-compare__item{
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.07);
  color:var(--text-dim);
}
.ia-compare__col--new .ia-compare__item{
  background:rgba(13,110,233,.06);border:1px solid rgba(13,110,233,.28);
  color:#fff;display:flex;gap:12px;align-items:flex-start;
}
.ia-compare__item svg{flex:0 0 auto;width:19px;height:19px;color:var(--primary-2);margin-top:2px}
@media (max-width:780px){.ia-compare{grid-template-columns:1fr;gap:16px}}

/* "Seção branca" — pedido explícito do usuário ("a terceira seção seja
   branca"), mesma receita padrão de sempre (ver "Convenções gerais" no
   CLAUDE.md). Modificador próprio (`.ia-evolution-section`) em vez de
   editar `.ia-compare` direto, já que esse componente é compartilhado com
   a instância dentro de `.craft-section` (que continua escura, não fez
   parte deste pedido). */
.ia-evolution-section{position:relative;z-index:1;background:#e2e7f0}
.ia-evolution-section .section__title{color:#0b0f1a}
.ia-evolution-section .section__lead{color:var(--text-mute)}
.ia-evolution-section .ia-compare__col--new h3{color:var(--primary)}
.ia-evolution-section .ia-compare__col--old .ia-compare__item{
  background:#e9edf5;border-color:rgba(11,15,26,.08);color:var(--text-mute);
}
.ia-evolution-section .ia-compare__col--new .ia-compare__item{
  background:rgba(13,110,233,.07);border-color:rgba(13,110,233,.22);color:#0b0f1a;
}
.ia-evolution-section .ia-compare__item svg{color:var(--primary)}

/* espaço entre .craft-section e .craft-results-section reduzido — pedido
   explícito do usuário ("reduza um pouco do espaço"). As duas usam
   .section--tight (padding:90px 0), então o vão entre elas somava 180px
   (90 de baixo + 90 de cima); reduzindo só os lados que se tocam (bottom
   de uma, top da outra) pra 40px cada, o vão cai pra 80px sem afetar o
   respiro no topo/base de nenhuma das duas com as seções vizinhas. */
.craft-section{padding-bottom:40px}
.craft-results-section{padding-top:40px}

/* segunda instância do .ia-compare (exemplo "Pedido comum × Comando
   C.R.A.F.T.", dentro da seção .craft-section, irmã do .craft — não
   descendente dele) — só precisa de mais respiro acima, escopado aqui
   em vez de mexer no componente genérico. */
.craft-section .ia-compare{margin-top:56px}
/* esta instância não tem ícone de check (só a citação + o resultado em
   <em>) — sem esse override, herdaria display:flex de
   .ia-compare__col--new .ia-compare__item (pensado pro par ícone+texto do
   uso genérico) e a citação/resultado ficariam lado a lado em vez de
   empilhados. */
.craft-section .ia-compare__item{display:block}
.craft-section .ia-compare__item em{display:block;margin-top:10px;color:var(--text-mute);font-style:italic;font-size:12.5px}

/* 5 engrenagens do C.R.A.F.T. — Contexto/Papel/Ação/Formato/Tom, cada uma
   com a letra em destaque (mesmo gradiente de texto do .btn--solucoes) +
   instrução curta + exemplo real do framework (Material de Apoio
   Folder.pdf, "A Anatomia do Comando Perfeito"). */
.craft{display:grid;grid-template-columns:repeat(5,1fr);gap:18px;margin-top:48px}
/* glassmórfico, tema branco — 2 pedidos explícitos do usuário em
   sequência ("faça esses cards glassmórficos", depois "faça esses cards
   com um tema branco"), único uso de `.craft__item` no site, então
   editado direto na regra base (sem modificador). A seção
   (`.craft-section`) continua escura de propósito — só os cards viraram
   "vidro branco fosco": fundo quase opaco (`rgba(255,255,255,.92)`, era
   `rgba(255,255,255,.05)` na 1ª rodada) ainda com `backdrop-filter:blur`
   (mantém a leitura de vidro, agora com tingimento branco em vez de
   escuro) — `-webkit-backdrop-filter` necessário pro Safari. Textos
   internos reescritos pro contraste certo sobre claro (mesma regra de
   sempre: `#0b0f1a` pro título, `var(--text-mute)` pro texto de apoio,
   nunca `var(--text-dim)`, que só dá ~2.5:1 sobre fundo claro). O
   `.craft__letter` (gradiente `--primary`→`--primary-2` via
   `background-clip:text`) não precisou de ajuste — já lê bem tanto sobre
   claro quanto sobre escuro. */
.craft__item{
  padding:26px 18px;border-radius:16px;text-align:center;
  background:rgba(255,255,255,.92);border:1px solid rgba(11,15,26,.08);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  transition:transform .3s, border-color .3s;
}
.craft__item:hover{transform:translateY(-6px);border-color:rgba(13,110,233,.35)}
.craft__letter{
  font-family:var(--font-display);font-size:36px;font-weight:800;line-height:1;
  background:linear-gradient(135deg,var(--primary),var(--primary-2));
  -webkit-background-clip:text;background-clip:text;color:transparent;
  margin-bottom:10px;
}
.craft__item h3{font-size:14px;font-weight:700;color:#0b0f1a;margin-bottom:10px}
.craft__item p{font-size:12.5px;color:var(--text-mute);line-height:1.55}
.craft__item p em{display:block;margin-top:10px;color:var(--text-mute);font-style:italic}
@media (max-width:980px){.craft{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.craft{grid-template-columns:1fr}}

/* Carrossel "Veja a diferença no resultado" — pedido explícito do
   usuário, com 2 prints reais (assets/img/resultado_sem_craft.webp /
   resultado_com_craft.webp, telas de relatório em retrato) mostrando o
   resultado de gerar o relatório sem/com o método C.R.A.F.T., espelhando
   a mesma ideia de comparação já usada no .ia-compare da seção anterior
   ("Pedido comum × Comando C.R.A.F.T."). Pedido de ser "simples e não
   tão grande" — em vez de um trilho com scroll/setas (como
   .integ-carousel já teve e foi descontinuado), virou uma alternância
   por 2 abas (mesmo pill-toggle de .ai-tabs/.modules__tabs), já que só
   há 2 imagens pra comparar. Ganhou seção própria (`.craft-results-
   section`, sem nenhuma regra própria além do que `.section` genérico já
   dá — só existe como seletor pra facilitar achar este bloco) — pedido
   explícito do usuário ("faça uma seção só para a visualização dessa
   carrossel"), separada de `.craft-section` (o método em si). */
.craft-results__carousel{max-width:360px;margin:0 auto;text-align:center}
.craft-results__tabs{
  display:inline-flex;gap:4px;padding:4px;border-radius:999px;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);
  margin-bottom:20px;
}
.craft-results__tab{
  padding:8px 18px;border-radius:999px;
  font-size:12.5px;font-weight:600;color:var(--text-dim);
  cursor:pointer;transition:background-color .3s var(--ease-out), color .3s var(--ease-out);
}
.craft-results__tab.active{
  background:linear-gradient(135deg,var(--primary),var(--primary-2));color:#fff;
}
/* altura fixa no viewport (não nos slides) — os 2 prints têm a mesma
   proporção (1414×2000, retrato), então uma altura só já cobre os dois
   sem pulo de layout ao trocar de aba; os slides ficam empilhados por
   cima um do outro (position:absolute) com crossfade de opacidade,
   mesma técnica já usada no .recursos-panel. */
.craft-results__viewport{position:relative;height:340px}
.craft-results__slide{
  position:absolute;inset:0;opacity:0;pointer-events:none;
  display:flex;align-items:center;justify-content:center;
  transition:opacity .4s var(--ease-out);
}
.craft-results__slide.active{opacity:1;pointer-events:auto}
/* .craft-results__frame encolhe pro tamanho real da imagem renderizada
   (inline-block, não o viewport inteiro) — é isso que deixa o botão de
   expandir (position:absolute) grudado no canto da imagem, em vez de
   flutuar solto no meio do espaço vazio ao redor dela quando a imagem
   (retrato, mais estreita que o card) não preenche a largura toda. */
.craft-results__frame{position:relative;display:inline-block;max-height:100%}
.craft-results__frame img{
  display:block;max-height:340px;max-width:100%;width:auto;height:auto;
  border-radius:12px;box-shadow:0 20px 44px -20px rgba(0,0,0,.55);
}
.craft-results__expand{
  position:absolute;top:8px;right:8px;
  width:32px;height:32px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(5,7,13,.62);border:1px solid rgba(255,255,255,.18);
  color:#fff;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  cursor:pointer;transition:background-color .25s var(--ease-out);
}
.craft-results__expand:hover{background:rgba(13,110,233,.65)}
.craft-results__expand svg{width:15px;height:15px}

/* lightbox de tela cheia pros 2 resultados — pedido explícito do
   usuário ("faça uma funcionalidade para visualizar o resultado em tela
   cheia"), já que o carrossel acima é deliberadamente pequeno demais
   pra ler o conteúdo dos relatórios. Mesma receita de overlay fixed +
   backdrop-filter isolado num elemento próprio (.craft-lightbox__backdrop,
   não o .craft-lightbox direto) já usada no .founder-modal — evita o bug
   de containing-block já documentado no projeto (um ancestral com
   filter/backdrop-filter vira containing block de descendentes position:
   fixed/absolute; aqui não há nenhum descendente fixed, mas a convenção
   foi mantida por segurança e consistência). initCraftResults() (main.js)
   troca o src/alt da <img> pro clicado antes de abrir. */
.craft-lightbox{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:center;justify-content:center;
  padding:24px;
  opacity:0;visibility:hidden;
  transition:opacity .35s var(--ease-out), visibility .35s;
}
.craft-lightbox.is-open{opacity:1;visibility:visible}
.craft-lightbox__backdrop{
  position:absolute;inset:0;
  background:rgba(3,5,10,.86);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
.craft-lightbox__close{
  position:absolute;top:20px;right:20px;z-index:2;
  width:42px;height:42px;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);
  color:#fff;transition:background-color .25s var(--ease-out);
}
.craft-lightbox__close:hover{background:rgba(255,255,255,.18)}
.craft-lightbox__close svg{width:18px;height:18px}
/* .craft-lightbox__stage carrega a animação de entrada (fade+scale) —
   precisou sair do <img> pra não brigar com o transform de zoom/pan que
   initCraftResults() (main.js) escreve direto no style do <img> via JS;
   as duas coisas mexendo na mesma propriedade transform, uma por classe
   CSS e outra por JS, se cancelariam. overflow:hidden aqui é o que evita
   a imagem "vazar" pra fora da área visível quando ampliada. */
.craft-lightbox__stage{
  position:relative;z-index:1;
  max-width:min(720px,90vw);max-height:88vh;
  overflow:hidden;border-radius:16px;
  display:flex;align-items:center;justify-content:center;
  transform:translateY(16px) scale(.97);opacity:0;
  transition:transform .4s var(--ease-out), opacity .4s var(--ease-out);
}
.craft-lightbox.is-open .craft-lightbox__stage{transform:translateY(0) scale(1);opacity:1}
.craft-lightbox__img{
  max-width:100%;max-height:88vh;width:auto;height:auto;
  border-radius:16px;box-shadow:0 40px 100px -30px rgba(0,0,0,.7);
  cursor:zoom-in;touch-action:none;-webkit-user-select:none;user-select:none;
  -webkit-user-drag:none;
  transition:transform .2s var(--ease-out);
}
/* aplicadas via JS (initCraftResults()) conforme o estado de zoom —
   is-zoomed troca o cursor pra "mão aberta" (dá pra arrastar), is-
   dragging desliga a transition durante o arrasto de verdade (senão o
   movimento fica com lag, brigando com o easing pensado só pro clique
   nos botões +/-). */
.craft-lightbox__img.is-zoomed{cursor:grab}
.craft-lightbox__img.is-dragging{cursor:grabbing;transition:none}
/* toolbar de zoom — pill flutuante centralizada embaixo, mesma
   linguagem visual (vidro translúcido + blur) do .craft-results__expand
   e do próprio .craft-lightbox__close. */
.craft-lightbox__zoom{
  position:absolute;left:50%;bottom:24px;z-index:2;
  transform:translateX(-50%);
  display:flex;gap:8px;padding:6px;border-radius:999px;
  background:rgba(5,7,13,.62);border:1px solid rgba(255,255,255,.18);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.craft-lightbox__zoom-btn{
  width:36px;height:36px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  color:#fff;font-size:19px;font-weight:600;line-height:1;
  cursor:pointer;transition:background-color .25s var(--ease-out);
}
.craft-lightbox__zoom-btn:hover{background:rgba(13,110,233,.65)}
@media (max-width:480px){
  .craft-results__viewport{height:280px}
  .craft-results__frame img{max-height:280px}
}

/* ========================================================
   SUPER APP — moldura de celular (componente genérico)
   ======================================================== */
/* emoldura os vídeos reais do Super App (assets/video/superApp-*.webm,
   720×1080, gravações verticais de tela) como se fossem a tela de um
   celular — os dois vídeos já são "screen recordings" no formato 9:16,
   então um frame de telefone é o encaixe mais direto, sem crop nem
   distorção de aspect-ratio. Genérico o bastante (não tem nada de
   "hero" nem "demo" no nome) pra reaproveitar nas duas seções que usam
   vídeo nesta página. */
.phone-frame{
  position:relative;
  width:100%;max-width:280px;margin:0 auto;
  aspect-ratio:9/16;
  border-radius:38px;
  background:#000;
  border:6px solid #161b26;
  box-shadow:0 30px 70px -24px rgba(0,0,0,.65), 0 0 0 1px rgba(255,255,255,.06);
  overflow:hidden;
}
.phone-frame::before{
  content:"";position:absolute;top:10px;left:50%;transform:translateX(-50%);
  width:34%;height:16px;border-radius:10px;
  background:#161b26;z-index:2;
}
.phone-frame video,.phone-frame img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.phone-frame--lg{max-width:320px}

/* ========================================================
   GESTÃO — moldura de notebook (componente genérico)
   ======================================================== */
/* emoldura os vídeos reais dos 3 módulos de Gestão (assets/video/
   modulo_{operacional,frotas,administrativo}.webm, 1920×1080, gravações
   de tela do ERP rodando no navegador) como se fossem a tela de um
   notebook — mesma lógica do .phone-frame acima (moldura escura +
   sombra), só que pro formato 16:9/paisagem desses vídeos, que são
   telas de desktop, não recordings de celular. `aspect-ratio:16/9`
   bate exato com a resolução de origem, sem crop.
   Segunda versão — a primeira (só uma borda fina + uma barrinha embaixo)
   não lia como notebook de verdade, reportado pelo usuário. Reforçada com
   3 pistas visuais que a primeira não tinha: (1) uma linha de "dobradiça"
   entre tela e base, separando as duas peças; (2) a base **mais larga que
   a tela** (`width:112%`, centralizada com margin negativa) via
   `clip-path` trapezoidal — um notebook visto de frente tem a base do
   teclado alargando/apoiando por baixo da tela, não alinhada borda-a-borda
   com ela; (3) gradiente na base simulando luz batendo numa superfície de
   metal/plástico, em vez de uma cor sólida chapada. */
.notebook-frame{width:100%;max-width:760px;margin:0 auto}
.notebook-frame__screen{
  position:relative;
  aspect-ratio:16/9;
  background:#000;
  border:12px solid #1b202b;
  border-radius:12px 12px 3px 3px;
  overflow:hidden;
  box-shadow:0 30px 70px -24px rgba(0,0,0,.65);
}
/* "câmera" do notebook — mesmo papel do notch do .phone-frame, só que
   um ponto único centralizado (webcam), não uma barra. */
.notebook-frame__cam{
  position:absolute;top:4px;left:50%;transform:translateX(-50%);
  width:5px;height:5px;border-radius:50%;
  background:#3a4152;z-index:2;
}
.notebook-frame__screen video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
/* linha de dobradiça — separa visualmente tela e base, reforçando que
   são duas peças articuladas, não um bloco único. */
.notebook-frame__hinge{
  height:5px;
  background:linear-gradient(180deg,#0d0f14,#1b202b);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6);
}
/* "base"/teclado — deliberadamente mais larga que a tela (112%,
   centralizada) e em trapézio (mais estreita no topo, mais larga embaixo)
   via clip-path, imitando a perspectiva de uma base de notebook vista de
   frente. Recorte central simula o vão de abertura da tampa. Ainda não
   tenta desenhar um teclado de verdade — só o volume/silhueta certos. */
.notebook-frame__base{
  position:relative;
  width:112%;margin-left:-6%;
  height:22px;
  background:linear-gradient(180deg,#2b323e 0%,#181d26 55%,#0c0e13 100%);
  clip-path:polygon(3% 0, 97% 0, 100% 100%, 0% 100%);
  border-radius:0 0 10px 10px;
  box-shadow:0 14px 24px -8px rgba(0,0,0,.6);
}
.notebook-frame__base::before{
  content:"";position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:72px;height:8px;border-radius:0 0 8px 8px;
  background:#05070d;
}

/* seção "Veja em ação" — texto de um lado, celular com o vídeo
   instrucional do outro. Reaproveita o mesmo grid 2 colunas do hero
   (`.hero__grid`/`.hero__left`/`.hero__right` já existem), mas essa
   seção não é um `.page-header`, então precisa do próprio wrapper de
   grid — `.app-demo__grid` copia só o `display:grid` necessário, sem
   herdar nada específico de hero. */
.app-demo__grid{
  display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center;
}
@media (max-width:900px){
  .app-demo__grid{grid-template-columns:1fr;gap:40px}
}

.form-submit:hover .arrow{transform:translateX(4px)}
