/* ── RESET & BASE ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* scroll-behavior removed: JS animation loop handles all smooth transitions */

/* O <style> inline no <head> do index.html (crítico, evita flash antes deste
   arquivo carregar) pinta html E body de #030810 — de propósito, porque a
   primeira coisa que a visita vê é a splash/globo, que continua escura. Uma
   vez que ESTE arquivo carrega, ele precisa vencer a herança pro <html> nos
   trechos claros da página (fora da cena); sem esta regra, sobrava o
   #030810 do crítico atrás de qualquer camada transparente, mesmo com o
   body já claro — achado em captura, 14/08. */
html {
  background-color: #0d2847;
}

/* Pedido do fundador (14/08): o fundo azul-escuro→azul-claro é ÚNICO em todo
   o site — começa já na tela de escolha de idioma (#splash) e continua igual
   no resto da página. `fixed` prende a imagem à JANELA, não ao documento: ela
   nunca se move ou "reaparece" ao rolar, é sempre o mesmo quadro parado atrás
   de tudo. Pedido do fundador (15/08): tirar a malha de grade de 26px que
   ficava por cima do gradiente e não deixar o tom claro chegar perto do
   branco — o gradiente sozinho vai de #0d2847 a #5a8fc2, um azul ainda
   bem saturado, não pastel. */
body {
  font-family: 'Plus Jakarta Sans', sans-serif;
  background-color: #5a8fc2;
  background-image: linear-gradient(180deg, #0d2847 0%, #3d6fa8 20%, #5a8fc2 55%);
  background-size: 100% 100vh;
  background-attachment: fixed;
  color: #122845;
  overflow-x: hidden;
}

/* ══════════════════════════════════════════════════════
   SPLASH SCREEN
══════════════════════════════════════════════════════ */
#splash {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background-color: #5a8fc2;
  background-image: linear-gradient(180deg, #0d2847 0%, #3d6fa8 20%, #5a8fc2 55%);
  background-size: 100% 100vh;
  display: flex;
  align-items: stretch;
  transition: opacity 0.9s ease;
}

#splash.fade-out {
  opacity: 0;
  pointer-events: none;
}

/* ── O globo parado (data-globe="hold") ──
   Pedido do fundador (11/08): "ao clicar no idioma o globo ainda é esférico e
   só para de rodar na região escolhida, e aparece o sobre nós à esquerda dele
   e o propósito à direita".

   O #splash deixa de ser uma cortina e vira o HOSPEDEIRO do globo: ele
   continua de pé, opaco, com o canvas dentro — mas rebaixado para o z-index 2,
   entre o #scene-canvas (1) e o conteúdo de borda dos atos (3), para o "Sobre
   Nós"/"Nosso propósito" ficarem POR CIMA da esfera. Sem ponteiro, porque
   dali em diante ninguém mais clica no globo (o menu de idiomas já foi), e
   uma camada fixa cobrindo a tela inteira engoliria os cliques da navbar.

   A opacidade passa a ser escrita quadro a quadro por applyGlobeDescent()
   (js/main.js) a partir do progresso do scroll — daí `transition: none`: uma
   transição de 0,9s brigando com uma escrita por quadro dá exatamente o
   arrasto que faz o crossfade ficar atrás da rolagem. */
html[data-globe="hold"] #splash {
  z-index: 2;
  pointer-events: none;
  transition: none;
}

/* ── Link direto para um caso (?destino=act-wind) ──
   Achado em captura (29/08), na mesma família do defeito do logo: abrir o link
   compartilhável de um caso montava a cena JÁ dentro dele (montaHub lê
   ?destino= no mount) e depois pousava o globo por cima — o #splash rebaixado
   está no z-index 2, o canvas da cena no 1. O visitante recebia o caso da
   Bahia desenhado POR BAIXO de uma esfera, exatamente a mesma tela quebrada
   que o logo produzia por outro caminho.

   Com um caso aberto o globo não é o quadro, o caso é: o #splash sai. Só
   `[data-globe="hold"]`, nunca durante o voo — ali o splash ainda é a cortina
   que cobre a troca, e escondê-lo faria o globo sumir no meio do giro. E é
   reversível por construção: a seta "voltar ao mapa" apaga data-destino, o
   splash volta com o globo, que é justamente o que existe no scrollY de volta. */
html[data-globe="hold"][data-destino] #splash {
  display: none;
}
/* A UI do splash (logo, tagline, botões de idioma, parceiros) sai; o globo
   fica. Separar as duas coisas é a mudança estrutural desta rodada — antes,
   esconder o splash e matar o globo eram a mesma linha de código. */
html[data-globe="hold"] #splash-ui {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}

/* Globe canvas fills full splash background */
#globe-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

/* UI panel — right side */
#splash-ui {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  margin-left: auto;
  width: 46%;
  min-width: 320px;
  padding: 3rem 5% 3rem 3%;
}

#splash-logo {
  width: min(300px, 85%);
  height: auto;
  filter: drop-shadow(0 0 32px rgba(77, 184, 255, 0.28));
}

#splash-tagline {
  font-size: 0.85rem;
  /* Pedido do fundador (15/08): "quase não dá para ver" — era peso 300 e
     azul-marinho escuro (rgba(18,40,69,.55)), pensado para pousar sobre um
     fundo quase branco que a splash não tem mais. Peso 700 + branco-azulado
     claro, mesma dupla que resolveu o mesmo problema no resto do site. */
  font-weight: 700;
  color: rgba(231, 241, 255, 0.92);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
}

#lang-selector {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  width: 100%;
  max-width: 280px;
}

#lang-prompt {
  font-size: 0.72rem;
  /* Mesmo achado do #splash-tagline: azul escuro (rgba(28,127,196)) sobre o
     topo escuro do gradiente da splash quase não aparecia. */
  color: rgba(190, 220, 255, 0.85);
  text-align: center;
  letter-spacing: 0.06em;
  line-height: 1.5;
}

#lang-buttons {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
}

.lang-btn {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 0.8rem;
  padding: 0.9rem 1.4rem;
  background: rgba(6, 14, 34, 0.88);
  border: 1px solid rgba(77, 184, 255, 0.30);
  border-radius: 10px;
  color: #fff;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background 0.2s, border-color 0.2s, transform 0.15s;
  width: 100%;
  backdrop-filter: blur(4px);
}

.lang-btn:hover {
  background: rgba(10, 22, 50, 0.95);
  border-color: rgba(77, 184, 255, 0.55);
  transform: translateX(5px);
}

.lang-code {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: #4db8ff;
}

.lang-name {
  font-weight: 500;
}

.lang-city {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.72);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* ── SPLASH PARTNERS ── */
#splash-partners {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: center;
  margin-top: 0.5rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(77, 184, 255, 0.22);
  width: 100%;
  max-width: 400px;
}

.splash-partners-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.splash-partners-label {
  font-size: 0.6rem;
  font-weight: 500;
  color: rgba(190, 220, 255, 0.8);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.splash-partners-logos {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  flex-wrap: nowrap;
}

/* Pedido do fundador (15/08): "quero que eles sempre sejam nítidos e não
   fique interagindo com o mouse ao passar o mouse" — eram opacity:0.7 em
   repouso e só nitidos no :hover; agora sempre nítidos, sem estado de hover
   para a opacidade mudar. */
.splash-partners-logos img {
  height: 56px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  opacity: 1;
  border-radius: 4px;
}

/* ── NAVBAR ── */
#navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 2rem;
  background: rgba(10, 20, 40, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255,255,255,0.08);
  z-index: 1000;
}

#logo {
  height: clamp(30px, 6px + 2.4vw, 40px);
  width: auto;
  object-fit: contain;
  cursor: pointer;
  transition: opacity 0.2s;
}

#logo:hover {
  opacity: 0.80;
}

/* gap/font-size em clamp(): entre o corte estreito (900px, ver BREAKPOINT em
   js/main.js) e telas largas confortáveis, os 7 links + o logo (~207px)
   não cabiam no espaço disponível — o texto vazava para fora da viewport
   sem quebrar linha (achado 21/08, notebook de tela menor: "Prêmios e
   Projetos" cortado na borda, "Contatos" invisível). Encolher suavemente
   com a largura, em vez de um corte fixo, evita recriar o mesmo problema
   em qualquer resolução intermediária que não testamos. */
/* ── O menu do topo ──
   Relato do fundador (29/08): "as divisórias de cada subseção do 'Sobre nós',
   'Por que nós' etc precisam estar escritas de uma forma mais bonita e com
   divisões na parte de cima, pois parece texto normal, não parece clicável".
   Ele está certo: eram sete palavras soltas, separadas só por espaço em
   branco, sem nada dizendo onde termina um item e começa o outro, e a única
   resposta ao ponteiro era a cor mudar.

   Três coisas resolvem isso sem transformar a barra num painel de botões:
   um filete vertical ENTRE os itens (a divisória pedida), um sublinhado que
   cresce no hover/foco, e a seção em que o visitante está de fato marcada
   (aria-current, escrito por js/main.js). O gap vira variável porque a
   divisória precisa cair exatamente no meio dele. */
#nav-links {
  --nav-gap: clamp(0.5rem, -0.92rem + 2.52vw, 1.6rem);
  display: flex;
  align-items: stretch;
  gap: var(--nav-gap);
}

/* Narrow-screen navigation ships in the same DOM; it stays off above the
   breakpoint, where #nav-links is the real menu. */
#hamburger,
#nav-overlay,
#awards-timeline {
  display: none;
}

#nav-links a {
  position: relative;
  color: rgba(255,255,255,0.78);
  text-decoration: none;
  font-size: clamp(0.66rem, 0.454rem + 0.366vw, 0.82rem);
  font-weight: 500;
  letter-spacing: 0.045em;
  /* O padding é o que dá ao sublinhado um lugar para morar sem encostar na
     palavra, e ao filete uma altura de referência. */
  padding: 0.42rem 0 0.38rem;
  transition: color 0.2s;
  white-space: nowrap;
}

/* A DIVISÓRIA. `a + a` e não `::after` em todos: assim nunca sobra um filete
   pendurado depois do último item. Fica no meio do gap (metade dele, para a
   esquerda) para não parecer colada em nenhuma das duas palavras. */
#nav-links a + a::before {
  content: '';
  position: absolute;
  left: calc(var(--nav-gap) / -2);
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 0.95em;
  background: rgba(255,255,255,0.20);
  pointer-events: none;
}

/* O SUBLINHADO. Cresce da esquerda, no amarelo da marca — o mesmo do
   #scroll-hint e dos rótulos numerados do manifesto, não o azul de link que
   estava aqui e não aparece em nenhum outro lugar do site. */
#nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: #F5C200;
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.24s ease, opacity 0.24s ease;
}

#nav-links a:hover,
#nav-links a:focus-visible {
  color: #fff;
}

#nav-links a:hover::after,
#nav-links a:focus-visible::after {
  opacity: 1;
  transform: scaleX(1);
}

/* A seção em que o visitante ESTÁ. Escrita por js/main.js a cada rolagem —
   uma barra que só reage ao ponteiro diz "isto é clicável"; uma que também diz
   onde você está vira navegação de verdade. Mais apagada que o hover de
   propósito: é informação, não convite. */
#nav-links a[aria-current="true"] {
  color: #ffd34d;
}
#nav-links a[aria-current="true"]::after {
  opacity: 0.55;
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  #nav-links a::after { transition: none; }
}

/* ── MAP BACKGROUND ── */
#map-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
}

/* Remove MapLibre default controls */
.maplibregl-control-container { display: none; }

/* ── SCROLL CONTAINER ── */
#scroll-container {
  position: relative;
  z-index: 10;
  pointer-events: none; /* let map receive no events */
}

.stage {
  height: 200vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px 2rem 2rem 2rem; /* top pad = navbar height */
  pointer-events: none;
}

/* ── SCENE (atrás de ?scene=1) ──
   O canvas fica fixo atrás de tudo; só o handle da régua (tarefa posterior)
   recebe ponteiro, por isso pointer-events:none aqui. */
#scene-canvas {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1;
  pointer-events: none;
}

/* A cena nasce desligada: sem data-scene no <html>, os três atos não existem
   para efeitos de layout — senão o documento padrão ganharia 900vh de nada.
   O canvas some junto: sem mount(), ele fica com o tamanho padrão do elemento
   (300x150) esticado por CSS, o que é sinalizado como fora de escala. */
html:not([data-scene]) .act,
html:not([data-scene]) #scene-canvas {
  display: none;
}

/* E com a cena LIGADA, a câmera antiga sai da frente — mas o resto do
   documento (Tarefa 11) sobrevive depois do ato 2. A câmera do maplibre, a
   malha WRF e o overlay escuro eram todos amarrados ao voo antigo; sem ele
   rodando (ver js/main.js: startMain() nunca agenda animationLoop quando
   cenaLigada), eles ficariam parados num estado arbitrário — melhor
   escondidos. #scroll-container NÃO entra mais nesta lista: é onde moram
   os cards que sobrevivem em texto (why, produtos, equipe, prêmios,
   parceiros, compromisso, contatos) — escondê-lo apagava a página inteira
   depois da cena, não só a câmera. */
html[data-scene] #map-bg,
html[data-scene] #wrf-grid,
html[data-scene] #dark-overlay,
html[data-scene] #map-attrib,
html[data-scene] #map-toggle {
  display: none !important;
}

/* ── A dica de rolagem DENTRO da cena ──
   Até 29/08 o #scroll-hint estava nesta lista de "não existe na cena", e o
   resultado é que quem escolhia o idioma pousava no globo sem nada dizendo que
   havia site abaixo — a tela simplesmente parava. O botão .next-section-btn,
   que assume esse papel no resto da página, é justamente o que NÃO aparece
   aqui: ele só liga quando o mapa de pilotos está pronto (ver o gate em
   js/main.js), várias telas depois.

   Então o hint volta, mas com escopo estreito: só no beat do globo parado, só
   até o primeiro rolar (js/main.js escreve e apaga `data-dica-rolagem`), e
   nunca com um caso aberto. Assim ele nunca divide o canto inferior direito
   com a seta de próxima seção — os dois continuam sem se encontrar.

   O seletor precisa passar por #splash porque a regra genérica
   `#splash:not(.fade-out) ~ #scroll-hint { opacity: 0 }` (mais abaixo) tem
   dois ids: na cena o splash NUNCA ganha .fade-out — ele fica de pé como
   hospedeiro do canvas do globo —, então sem empatar os ids esta regra perdia
   por especificidade e o hint ficava invisível. */
html[data-scene] #scroll-hint { display: none; }
html[data-scene][data-dica-rolagem="1"]:not([data-destino]) #splash ~ #scroll-hint {
  display: flex;
  opacity: 0.8;
  animation: scroll-hint-entra 0.7s ease both;
}
/* A entrada anima SÓ a opacidade: o translateX(-50%) abaixo é o que centra o V,
   e um `transform` na keyframe o sobrescreveria — o V nasceria meia largura à
   direita e escorregaria para o lugar, que lê como defeito de layout. */
@keyframes scroll-hint-entra {
  from { opacity: 0; }
  to   { opacity: 0.8; }
}

/* ── A forma da dica dentro da cena ──
   Pedido do fundador (29/08, 2ª rodada): "em vez de um 'role para baixo' na
   esquerda, uma seta para baixo em formato de V bem grande, centralizada e
   embaixo do globo, embaixo do 'O modelo global de hoje | METENERGY'".

   Então some tudo o que fazia dela uma pílula de canto — caixa, borda, blur,
   sombra e a própria palavra. O que fica é o gesto: um V grande no eixo do
   olhar, logo abaixo da linha de rótulos que fecha o globo. Traço fino
   (stroke-width 1.4 contra os 2 do atributo no SVG) porque a mesma espessura
   que dá corpo a um ícone de 14px vira um bloco pesado a 56px.

   A palavra sai do desenho e não da árvore: o contêiner é aria-hidden, então
   ela nunca foi lida em voz alta — mas continua traduzida e no HTML, e é o
   que a forma legada (?legacy=1) mostra. */
html[data-scene] #scroll-hint {
  /* O deslocamento vertical mora no transform, e não em `bottom`, porque o V
     é pequeno dentro de um quadro grande: a polyline ocupa a faixa central do
     viewBox, então sobram ~40px de caixa vazia embaixo do desenho. Empurrar
     por `bottom` negativo funcionaria, mas deixa o elemento oficialmente fora
     da viewport — aqui a caixa continua inteira dentro e só o desenho desce. */
  bottom: 0.4rem;
  right: auto;
  left: 50%;
  transform: translate(-50%, 18px);
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-scene] #scroll-hint [data-i18n="scroll_hint"] { display: none; }
/* O tamanho é do QUADRO, não do traço: no viewBox de 24 o V ocupa só a metade
   central da largura e um quarto da altura (polyline 6,9 → 12,15 → 18,9), então
   um svg de 56px desenhava um V de 28x14 — "bem grande" pedia o dobro. A
   espessura anda no sentido contrário: stroke-width é medida no viewBox, então
   escalar o quadro engrossa o traço junto, e 0,8 aqui dá os ~4px que mantêm o V
   leve em vez de blocado. */
html[data-scene] #scroll-hint svg {
  width: 120px;
  height: 120px;
  stroke-width: 0.8;
  /* Mais LARGO que alto (29/08, 3ª rodada). O V do ícone é simétrico; abrindo
     o ângulo ele deixa de parecer um chevron de menu e passa a apontar para
     baixo com mais autoridade. O scaleX viaja dentro da keyframe porque a
     animação de pulo também escreve `transform` — duas regras disputando a
     mesma propriedade e a última a ser aplicada apaga a outra, que foi como o
     V nasceu sem largura na primeira tentativa. */
  animation-name: scroll-hint-bounce-largo;
}
@keyframes scroll-hint-bounce-largo {
  0%, 100% { transform: translateY(0)   scaleX(1.35); opacity: 0.65; }
  50%      { transform: translateY(6px) scaleX(1.35); opacity: 1; }
}
@media (max-width: 900px) {
  html[data-scene] #scroll-hint svg { width: 90px; height: 90px; }
}
/* #scroll-hint já some em telas estreitas por outra regra (bloco "NARROW
   SCREENS" mais abaixo, <= 900px) — o mesmo canto fica livre lá também, e
   .next-section-btn assume os dois papéis: convite a rolar E navegação com
   o nome da seção. Em telas largas SEM a cena (?legacy=1) o botão novo
   nunca liga (guarda NARROW||cenaLigada em main.js) e o #scroll-hint
   genérico continua sozinho, sem concorrência. */
/* #map-bg entrou nesta lista depois de o fundador relatar "o fundo está com
   relevo e está errado". A cena pinta o próprio fundo escuro por cima do mapa,
   então em condição normal o relevo não aparece — mas ele continuava VIVO por
   baixo, custando tiles e bateria, e bastava a cena não desenhar (falha ao
   montar, um quadro antes do primeiro draw) para o relevo aparecer sozinho, sem
   conteúdo nenhum em cima, porque a narrativa antiga já tinha sido escondida.
   Esconder o mapa junto torna esse estado impossível. */

/* ── Tarefa 11 (via flag, não via exclusão): #scroll-container vira
   documento parado, do jeito que o `@media (max-width: 900px)` já faz para
   o telefone — mesmo mecanismo (posição estática, opacidade forçada),
   porque main.js nunca escreve opacity/transform inline quando cenaLigada
   (o loop de animação antigo nem é agendado). Larguras ficam as do modo
   largo (a base do arquivo já dá 1100-1300px de cartão); só o
   comportamento de "documento parado" é emprestado do estreito. */
html[data-scene] #scroll-container { pointer-events: auto; }

/* #about é a Stage 0 original — o mesmo texto que o ato de abertura mostra
   em DOM de borda (.act-open-about, ver index.html #act-open; o segundo card
   que dobrava #about, .act-open-info, saiu em 13/08 a pedido do fundador).
   Com a cena ligada o cartão duplicava o mesmo texto duas vezes na mesma
   rolagem (achado do fundador, 11/08); a seção continua no documento
   (ver comentário em index.html) só para telas estreitas, que nunca
   chegam aqui porque nunca ganham data-scene. */
html[data-scene] #about {
  display: none !important;
}

html[data-scene] .stage {
  height: auto;
  display: block;
  padding: 2.4rem 2rem 0;
}

html[data-scene] .text-box {
  position: static !important;
  transform: none !important;
  opacity: 1 !important;
  visibility: visible !important;
  filter: none !important;
  pointer-events: auto !important;
  margin: 0 auto 3rem;
}

/* ── #why: só o que não tem lugar no canvas sobrevive (Tarefa 11 §2) ──
   A régua, os dois campos e a malha já são a cena; o gráfico de 48 h é
   série de tempo (não campo — não tem onde pousar no mapa), então ele e as
   métricas continuam como prova em texto, indexável, abaixo da cena. O
   regime de chuva (#why-act-extreme) e os rótulos/legendas dos painéis
   espaciais somem inteiros: não é numero novo nem duplicado, é o mesmo
   numero que a faixa de métricas da cena (Tarefa 8b) já mostra durante o
   ato. Escondido por CSS, não apagado — ?legacy=1 mostra tudo de novo. */
html[data-scene] .why-act#why-act-extreme,
html[data-scene] .why-dots,
html[data-scene] .why-regime,
html[data-scene] .wf-head,
html[data-scene] .wf-maps,
html[data-scene] .wf-note {
  display: none !important;
}

html[data-scene] .why-act {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* Sem .wf-maps, wf-body ficava com uma coluna "auto" vazia e o gráfico de
   48h encolhido nela — a mesma correção que o estreito já faz por outro
   motivo (a coluna não cabia), aqui porque a coluna não existe mais. */
html[data-scene] .wf-body { grid-template-columns: 1fr; }

/* ── Prêmios: as LÂMPADAS voltaram (13/08) ───────────────────────────────
   Pedido do fundador: "no Prêmios e Projetos deixar como o original, a linha
   com as lâmpadas".

   Elas tinham sido substituídas por uma timeline em DOM porque o canvas
   precisava do loop de animação antigo para acender — e esse loop não roda com
   a cena ligada. A correção não foi trazer o loop inteiro de volta (ele move a
   câmera do maplibre, a malha WRF e o overlay, coisas que a cena substituiu):
   é um redesenho próprio, disparado por rolagem, resize e hover, em
   js/main.js. Ver iniciaPremiosNaCena().

   Com isso, o modo cena volta a usar o MESMO layout do original — seção alta,
   sticky, canvas em cima — e a timeline em DOM fica só para o telefone. */

/* A timeline em DOM dos prêmios ficou SÓ para o telefone (13/08): com as
   lâmpadas de volta no modo cena, manter as duas ligadas desenhava uma por
   cima da outra — foi o que a captura mostrou. */

.act {
  height: 300vh;
  position: relative;
}

/* #act-open é mais alto que os outros dois atos — pedido do fundador
   (verbatim, 11/08, 2ª rodada): "deixe por mais tempo" o manifesto de
   "sobre nós" (.about-manifest) legível. sectionProgress() (js/scene/
   progress.mjs) mede o progresso de CADA seção contra a própria altura, não
   contra uma constante global — então esticar só este ato dá mais pixels de
   rolagem reais ao platô do manifesto (ABOUT_HOLD_END em scene.mjs) sem
   mexer no ritmo dos outros dois atos nem em ACT_LANDING_FRACTION (que já é
   uma fração, não um pixel). Verificado: tests/section-nav.test.mjs não
   depende de 300vh (usa alturas passadas por parâmetro). */
/* 380vh → 460vh (11/08, abertura com o globo parado): a seção passou a
   carregar uma fase a mais. Os primeiros 30% do curso (DESCENT_END em
   js/scene/opening.mjs) são a descida do globo esférico até o quadro largo da
   cena plana; só os 70% restantes são o voo plano que já existia. Sem esticar
   a seção, o voo plano perderia quase um terço dos pixels de rolagem que já
   estavam medidos — 0,70 × 460vh − 100vh ≈ 0,70 × 360vh = 252vh, contra os
   280vh que ele tinha antes. Continua não havendo constante de altura em
   nenhum lugar: sectionProgress() mede cada seção contra a própria altura. */
#act-open {
  height: 700vh;
}



.act-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
}

/* ── Conteúdo de borda (Tarefa 8b) ──
   "As informações contidas ao redor da centralização do mapa" — a cena sem
   isto desenha certo e não diz nada: sem rótulo de painel, sem métrica, sem
   handle visível. Tudo aqui é DOM fixo sobre o canvas (z-index acima de 1);
   scene.mjs liga ".act-on" no elemento do ato ativo e escreve a custom
   property --ruler a cada quadro para os dois rótulos de borda acompanharem
   o arrasto sem re-renderizar CSS nenhum — só a variável muda. */
.act-border {
  position: fixed;
  z-index: 3;
  display: none;
  pointer-events: none;
  /* Pedido do fundador (15/08): "literalmente todos os cards" com o mesmo
     fundo escuro — a família inteira de cards da cena (.act-header,
     .act-metrics, .act-side-card, .act-rain-chart, etc.) usava vidro
     BRANCO com texto escuro (#122845) e um glow branco só para segurar
     contraste contra aquele branco. Com os cards virando vidro escuro
     (mesmo tom de .about-manifest/.hub-pin), o texto vira claro e o glow
     branco não faz mais sentido — cada card escuro já basta como fundo. */
  color: #e7f1ff;
  text-shadow: none;
  font-family: 'Plus Jakarta Sans', sans-serif;
}
.act-border.act-on { display: block; }

/* O cabeçalho do ato ganhou fundo (12/08). Só o text-shadow herdado de
   .act-border não bastava: o rótulo de demonstração em alemão tem quase o
   dobro do comprimento do português, quebra em duas linhas e cai justamente
   em cima do contorno do país — em captura ficava ilegível. Mesma família de
   vidro escuro do resto da cena, sem moldura, porque isto é uma legenda e não
   um card. */
.act-header {
  top: 96px;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(90vw, 640px);
  padding: 0.4rem 0.9rem;
  border-radius: 3px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(4px);
  text-align: center;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  opacity: 0.9;
}

.act-edge {
  top: 50%;
  transform: translateY(-50%);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.act-edge--left  { right: calc((1 - var(--ruler, 0.5)) * 100vw + 28px); text-align: right; }
.act-edge--right { left:  calc(var(--ruler, 0.5) * 100vw + 28px); text-align: left; }

/* Seletor ERA5/IMERG (18/08, reposicionado 19/08). Posição fixa (não segue a
   régua como .act-edge--left): é um controle, não uma legenda do campo, e
   perseguir o arrasto o deixaria embaixo do dedo/cursor de quem está
   arrastando. .act-border trava pointer-events:none — reaberto aqui porque
   isto é um controle de verdade, mesma exceção que .pino-ponto usa.
   À DIREITA, não à esquerda: o canto superior esquerdo já é do botão
   "Voltar ao mapa" (#hub-voltar) — os dois ficavam colados (achado do
   fundador, 19/08). Nada mora no canto superior direito nesta altura
   (.act-side-card--right só desce para top:38%), então o seletor tem o
   canto só para ele. */
/* Rótulo em linha própria, em cima dos botões (19/08, 5ª rodada) — pedido do
   fundador: na mesma linha dos botões, com o mesmo espaçamento, "Comparativo"
   lia como um terceiro botão em vez de título dos outros dois. Por isso o
   contêiner virou coluna (não mais um pill só, que não faz sentido numa
   caixa de duas linhas) e só .rain-product-toggle-buttons, por dentro,
   continua com o border-radius total de pílula. */
.rain-product-toggle {
  top: 96px;
  right: 16px;
  display: none;
  flex-direction: column;
  gap: 3px;
  padding: 6px 7px;
  border-radius: 14px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(4px);
  pointer-events: auto;
}
.rain-product-toggle.act-on { display: flex; }
.rain-product-toggle-label {
  padding: 0 0.3rem;
  color: rgba(231, 241, 255, 0.55);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
}
.rain-product-toggle-buttons {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
}
.rain-product-toggle-btn {
  padding: 0.3rem 0.75rem;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: rgba(231, 241, 255, 0.6);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.rain-product-toggle-btn--on {
  background: #1c7fc4;
  color: #e7f1ff;
}
.rain-product-toggle-btn:not(.rain-product-toggle-btn--on):hover {
  background: rgba(231, 241, 255, 0.12);
  color: #e7f1ff;
}

/* Legenda do contorno de elevação (ato vento) — mesma coluna do rótulo
   METENERGY à direita da régua, uma linha abaixo, menor e mais apagada:
   é contexto, não o argumento do painel. */
.act-terrain-caption {
  top: calc(50% + 24px);
  left: calc(var(--ruler, 0.5) * 100vw + 28px);
  transform: translateY(-50%);
  max-width: 220px;
  font-size: 11px;
  font-weight: 400;
  opacity: 0.7;
}

/* Faixa de métricas do ato de vento. Reprojetada em 12/08 (fundador: "acredito
   que dá para melhorar o layout dos cards de cada evento analisado").
   Era uma linha corrida de quatro pares rótulo+número, tudo no mesmo corpo e
   separado só por espaço: quatro números que precisam ser COMPARADOS dois a
   dois viravam uma frase longa, e em captura o olho não achava onde começava
   cada métrica. Agora cada uma é uma célula com o rótulo por cima e o par por
   baixo, separadas por um filete — a comparação passa a ser vertical dentro da
   célula e a leitura horizontal entre células. Mesma moldura de instrumento das
   colunas da abertura (contorno azul de 1px, raio 3px), para o site inteiro ler
   como um sistema só. */
/* Pedido do fundador (13/08): empilhadas no canto direito, não em linha no
   rodapé — a faixa horizontal de 4 células dividia o rodapé com a colorbar e
   não sobrava largura para nenhuma das duas. Empilhada, a coluna cabe num
   canto e a colorbar (abaixo) fica livre para crescer. */
.act-metrics {
  left: auto;
  right: 28px;
  /* Topo, não rodapé: embaixo a coluna de 4 itens (mais alta que a antiga
     linha única) colidia com o next-section-btn, que também mora no canto
     inferior direito (z-index 9999) — a "redução de erro" ficava atrás do
     botão. Achado em captura. */
  top: 96px;
  bottom: auto;
  transform: none;
  display: none; /* .act-on troca para flex, não block — ver regra abaixo */
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  /* 172 -> 210: as barras (19/08) precisam de espaço pra trilha + número no
     fim; em 172px o número quebrava linha ou a trilha ficava curta demais
     pra ler comprimento. */
  width: 210px;
  padding: 0.15rem 0.3rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  background: rgba(10, 20, 40, 0.92);
  backdrop-filter: blur(6px);
  font-size: 13px;
  font-weight: 500;
}
.act-metrics.act-on { display: flex; }
/* grid e não flex-row: o rótulo ocupa a linha inteira e o PAR fica numa
   linha só embaixo dele. Empilhar os três (nosso, ×, deles) foi a 1ª versão e
   em captura lia como fração — o "×" no meio de dois números um sobre o outro
   é uma barra de divisão para qualquer olho. A comparação tem de ser
   horizontal; o que é vertical é a relação entre rótulo e valores — e agora
   também a relação entre uma métrica e a próxima (border-top, não -left). */
.act-metric {
  display: grid;
  grid-template-columns: auto auto auto;
  justify-content: center;
  align-items: baseline;
  column-gap: 0.1rem;
  row-gap: 0.34rem;
  padding: 0.5rem 0.3rem;
  border-top: 1px solid rgba(77, 184, 255, 0.16);
}
.act-metric-label { grid-column: 1 / -1; justify-self: center; }
.act-metrics-legend {
  display: flex;
  justify-content: center;
  gap: 0.7rem;
  padding: 0.45rem 0.3rem 0.4rem;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: rgba(231, 241, 255, 0.75);
}
.act-metrics-legend-item { display: inline-flex; align-items: center; gap: 0.3rem; }
.act-metrics-legend-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.act-metrics-legend-dot--good { background: #4db8ff; }
.act-metrics-legend-dot--bad  { background: #ff9d7a; }
/* A síntese tem um número só, não um par. */
.act-metric-hero { grid-template-columns: auto; }
.act-metric:first-child { border-top: none; }
.act-metric-label {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  opacity: 0.62;
  margin: 0;
}
.act-metric .act-bad  { color: #ff9d7a; font-weight: 700; font-size: 15px; }
.act-metric .act-good { color: #4db8ff; font-weight: 700; font-size: 15px; }
.act-metric .act-vs   { opacity: 0.45; margin: 0 0.4rem; font-weight: 400; }
/* Barras horizontais (19/08) — ver comentário grande no HTML sobre por que
   cada métrica normaliza no PRÓPRIO par, não num eixo comum. */
.act-metric-bars {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  width: 100%;
}
.act-metric-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.act-metric-bar-track {
  position: relative;
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}
.act-metric-bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: 3px;
  /* Nasce achatada e cresce até a largura já escrita no style inline (HTML)
     — mesma ideia da barra de progresso do scroll, sem depender de mais
     nada carregar antes de animar. */
  animation: act-metric-bar-cresce 0.6s ease-out both;
}
@keyframes act-metric-bar-cresce { from { transform: scaleX(0); transform-origin: left; } }
.act-metric-bar--good .act-metric-bar-fill { background: #4db8ff; }
.act-metric-bar--bad  .act-metric-bar-fill { background: #ff9d7a; }
.act-metric-bar strong {
  min-width: 34px;
  text-align: right;
  font-size: 12px;
  font-weight: 700;
}
/* A métrica-síntese ganha o amarelo do logo e um pouco mais de corpo: é a
   única das quatro que não é um par comparado, é o resultado. */
.act-metric-hero { border-top-color: rgba(255, 211, 77, 0.38); }
.act-metric-hero .act-metric-label { color: rgba(255, 211, 77, 0.9); opacity: 1; }
.act-metric-hero strong { color: #F5C200; font-weight: 700; font-size: 17px; }

/* Cards laterais do ato de chuva (Tarefa 8b, 3ª rodada de feedback do
   fundador, 10/08) — mesma família visual do act-metrics (vidro escuro,
   blur), mas ancorados nas bordas esquerda/direita em vez do rodapé, porque
   cada card pertence a um dos dois painéis (esquerda=ERA5, direita=METENERGY
   — mesma geografia que os rótulos de borda e a régua já usam). Fixos na
   viewport (herdam position:fixed de .act-border) e verticalmente
   centrados, para nunca competir com o cabeçalho (top) nem colidir com a
   régua central. */
.act-side-card {
  top: 50%;
  transform: translateY(-50%);
  width: 258px;
  max-width: 26vw;
  padding: 1rem 1.15rem 1.05rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  background: rgba(10, 20, 40, 0.92);
  backdrop-filter: blur(6px);
  font-size: 13px;
  line-height: 1.5;
}
/* Mesmo colchete de canto das colunas da abertura, e amarelo no canto por onde
   a leitura entra — o card do painel esquerdo abre em cima à esquerda, o do
   direito em baixo à direita. É o que faz os dois cards, a faixa de métricas e
   o "Sobre Nós" lerem como o mesmo instrumento em vez de três caixas de vidro
   escuro parecidas. */
/* Os dois cards saem do centro em direções opostas, o mesmo tanto (12 pontos
   percentuais da altura para cada lado). Pedido do fundador (12/08): "a
   informação ERA5 descer mais e espelhar com o card da info da Metenergy à
   direita, subindo o mesmo tanto que o card do ERA5 desceu".
   O ganho não é só de ritmo: os dois estavam centrados na mesma altura em que
   ficam os rótulos da régua e o anel de arraste, e o meio da tela — que é onde
   a comparação de fato acontece — vivia disputado. Saindo em espelho, o eixo
   central fica livre e os dois cards continuam lendo como par.
   `top` aqui é o CENTRO do card, porque translateY(-50%) continua valendo. */
.act-side-card--left {
  left: 28px;
  /* Pedido do fundador (19/08, 5ª rodada): "o gráfico do pluviômetro ficou
     meio esmagado com o card do ERA5 x IMERG" — era 68% (antes disso 62%).
     O card do gráfico cresceu (canvas 154→190px, 4ª linha de legenda do
     IMERG) sem este descer junto, e os dois passaram a brigar pelo mesmo
     espaço vertical. */
  top: 78%;
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 14px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 14px,
    linear-gradient(rgba(10, 20, 40, 0.92), rgba(10, 20, 40, 0.92));
}
.act-side-card--right {
  right: 28px;
  top: 38%;
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 14px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 2px 14px,
    linear-gradient(rgba(10, 20, 40, 0.92), rgba(10, 20, 40, 0.92));
}
.act-side-card-label {
  margin: 0 0 0.55rem;
  padding-bottom: 0.45rem;
  border-bottom: 1px solid rgba(77, 184, 255, 0.22);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(120, 200, 255, 0.9);
}
.act-side-card-stat { margin: 0 0 0.55rem; font-weight: 500; font-size: 14px; }
.act-side-card-stat .act-bad  { color: #ff9d7a; font-weight: 700; }
.act-side-card-stat .act-good { color: #4db8ff; font-weight: 700; }
/* ERA5/IMERG sempre visíveis (19/08) — a linha ativa (o produto pintado no
   mapa agora, marcada em scene.mjs via rain-stat--active) fica no brilho
   normal; a outra apaga um pouco, o bastante pra ler "isto não é o que está
   na tela agora" sem sumir. Ambas legíveis o tempo todo — a diferença é só
   ênfase, nunca esconde nenhum número. */
.act-side-card-stat[data-product] { font-size: 13px; opacity: 0.5; transition: opacity 0.2s ease; }
.act-side-card-stat[data-product].rain-stat--active { opacity: 1; }
.act-side-card-note { margin: 0; opacity: 0.85; font-size: 12px; }
.act-side-card-note--dim { margin-top: 0.35rem; opacity: 0.62; font-size: 11px; }

/* Argumento novo do ato de chuva (pedido do fundador, 11/08, 3ª rodada):
   "caso sua empresa tenha alguma inteligencia de dados... o dado de baixa
   resolução... suja o histórico". Não é amarrado a Barra do Una (sem
   número que não esteja já no site) — por isso NÃO leva act-local-only:
   aparece em pt e também em en/de (modo demonstração), sem violar o
   guardrail do campo viajante (js/scene/act-rain-i18n.mjs). O rodapé deste
   ato está livre (só o ato de vento usa .act-metrics no rodapé) — ancorado
   embaixo, centralizado, mesma família de vidro escuro dos cards laterais,
   para não competir com eles (que ficam nas bordas, verticalmente
   centrados) nem com a régua. */
/* Mesma moldura de instrumento dos cards laterais e da faixa de métricas do
   ato de vento — era o único card da cena que ainda usava o vidro arredondado
   antigo, e ficar sozinho nesse estilo fazia parecer que ele pertencia a outra
   página. Colchete amarelo nos dois cantos aqui, e não em um só: este card é
   centrado, não tem lado por onde a leitura entre. */
/* 13/08 — pedido do fundador: "o card 'impacto no seu histórico de dados' deve
   estar escrito menor, abaixo do card da resolução METENERGY". Ele saiu do
   rodapé central (onde competia com a régua e com a legenda do campo) e virou
   uma nota SUBORDINADA ao card da direita: mesma coluna, mesma largura, logo
   abaixo dele. É a leitura certa — ele não é um terceiro argumento, é a
   consequência do que o card de cima acabou de mostrar. */
.act-rain-argument {
  right: 28px;
  /* O card da direita tem o CENTRO em 38% (ele é translateY(-50%)) e ~120px
     de altura, então a borda de baixo dele cai por volta de 38% + 60px. Este
     começa 18px abaixo disso. Mesma largura, para os dois lerem como uma
     coluna só — que é o que eles são agora: afirmação e consequência. */
  top: calc(38% + 78px);
  width: 258px;
  max-width: 26vw;
  padding: 0.7rem 0.9rem 0.75rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 14px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 14px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 14px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 2px 14px,
    linear-gradient(rgba(10, 20, 40, 0.92), rgba(10, 20, 40, 0.92));
  backdrop-filter: blur(6px);
  text-align: left;
  opacity: var(--rain-arg-fade, 1);
}
.act-rain-argument-label {
  display: block;
  margin: 0 0 0.3rem;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(77, 184, 255, 0.85);
}
.act-rain-argument-body { margin: 0; font-size: 10.5px; line-height: 1.45; opacity: 0.82; }


/* Gráfico do acumulado do evento (12/08) — alto à esquerda, ligado por uma
   linha puxada ao pino do pluviômetro no mapa (o traço é desenhado no canvas
   da cena, ver drawGaugeCallout em scene.mjs: linha e pino vivem no mesmo
   espaço de coordenadas que o mapa, então não podem sair de registro).
   Altura contida de propósito: abaixo dele, na mesma coluna, fica o card
   lateral do ERA5, que em 1366x768 começa por volta de y=290. */
.act-rain-chart {
  /* top/left não são mais fixos: posicionaPinoDoPluviometro (scene.mjs) ancora
     o card logo abaixo do pino do pluviômetro a cada quadro — pedido do
     fundador (15/08), "o gráfico aparece logo abaixo da parte escrita". Em
     telas baixas ele pode alcançar a colorbar (.act-cbar) que mora no mesmo
     canto — z-index mais alto garante que ele sempre pinta por cima dela em
     vez de entrelaçar (o card aberto é a informação ativa no momento). */
  z-index: 5;
  width: 372px;
  max-width: 33vw;
  padding: 0.75rem 0.85rem 0.7rem;
  border: 1px solid rgba(77, 184, 255, 0.26);
  border-radius: 3px;
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 14px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 14px,
    linear-gradient(rgba(10, 20, 40, 0.92), rgba(10, 20, 40, 0.92));
  backdrop-filter: blur(6px);
  /* Pedido do fundador (16/08): "o gráfico deve ir surgindo com um certo
     alpha e não de uma vez" — era display:none/block (ver a regra de
     data-pluviometro logo abaixo), e display não anima. Opacity sim. */
  opacity: 0;
  transition: opacity 0.5s ease;
}
.act-rain-chart.act-on { display: block; }
html[data-scene][data-pluviometro] .act-rain-chart { opacity: 1; }
.act-rain-chart-title {
  margin: 0 0 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid rgba(77, 184, 255, 0.22);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(120, 200, 255, 0.9);
}
/* 154 -> 190: a 4ª faixa (IMERG, 18/08) dividiu a mesma altura em 4 em vez de
   3 — sem crescer, cada faixa perdia ~1/4 da altura e as barras pequenas
   (ERA5/IMERG, que É o argumento do quadro: teto comum mostrando o quanto são
   menores) ficavam ilegíveis. */
.act-rain-chart-canvas { display: block; width: 100%; height: 190px; }
.act-rain-chart-legend {
  margin: 0.55rem 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
}
/* O traço de cada chave repete a cor e o estilo da curva — inclusive o
   tracejado do observado, que é linha de referência e não série. */
.act-rain-chart-key {
  position: relative;
  padding-left: 1.5rem;
  font-size: 10.5px;
  line-height: 1.35;
  opacity: 0.86;
}
.act-rain-chart-key::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 1.05rem;
  height: 2px;
}
/* Sólida, não mais tracejada: com a série do CEMADEN extraída, o observado
   virou curva e o tracejado (convenção de "alvo", não de "série") passou a
   dizer a coisa errada. Mais grosso que as outras duas porque é a referência. */
.act-rain-chart-key--obs::before { background: #e7f1ff; height: 2.5px; }
.act-rain-chart-key--metn::before { background: #d99e00; }
.act-rain-chart-key--era5::before { background: #1c7fc4; }
.act-rain-chart-key--imerg::before { background: #3ec28f; }
.act-rain-chart-foot {
  margin: 0.5rem 0 0;
  font-size: 9.5px;
  letter-spacing: 0.04em;
  opacity: 0.55;
}

/* Telas baixas: o gráfico e o card do ERA5 dividem a mesma coluna esquerda, e
   em 1366x768 eles se sobrepunham — a legenda do gráfico ficava escondida atrás
   do card e o colchete do card por cima do gráfico (verificado em captura).
   O ajuste é do gráfico: ele sobe e encolhe.
   O empurrão do card do ERA5 (19/08, 5ª rodada) voltou a existir aqui — a
   simetria com o card da METENERGY (right, que não mudou) já não era
   perfeita na regra base depois do card do gráfico crescer, e nesta faixa
   mais apertada o esmagamento é pior, não menor.
   O rodapé do gráfico ("passo horário") NÃO some aqui: é a única declaração de
   que a série é horária, e o pedido original falava em semi-horária. */
@media (max-height: 820px) {
  .act-rain-chart { top: 84px; padding: 0.6rem 0.75rem 0.55rem; }
  .act-rain-chart-canvas { height: 134px; }
  .act-rain-chart-legend { gap: 0.1rem; }
  .act-rain-chart-key { font-size: 10px; }
  .act-side-card--left  { top: 66%; }
  .act-side-card--right { top: 43%; }
  /* Mesmo alívio do gráfico de chuva, aqui pro de vento (19/08): 560px não
     cabe inteiro numa tela de 768px de altura junto com o cabeçalho e as
     métricas abaixo do canvas. */
  .act-wind-curvas { top: 84px; padding: 0.6rem 0.75rem 0.55rem; }
  #act-wind-curvas-canvas { height: 380px; }
}

/* Rótulos das duas metades do globo (12/08). Ficam logo abaixo da esfera,
   um de cada lado da costura, e somem junto com o texto de abertura porque
   pertencem ao mesmo quadro. bottom fixo em vez de deslocamento a partir do
   centro: o raio da esfera é min(largura, altura)·0,36, então a base dela
   acompanha a altura da tela e um bottom constante mantém a mesma folga em
   768, 900 e 1080 — verificado em captura nas três. */
.act-globe-side {
  bottom: 92px;
  margin: 0;
  /* Amarrado ao MESMO fade das duas colunas. Sem isto eles ficavam ligados o
     ato inteiro: o globo saía, a câmera descia para o mapa plano, e os dois
     rótulos continuavam lá no rodapé — por cima do mapa comparativo e por
     cima da cartela do caso, que é o que o fundador viu como "deu uma
     bugada". Eles descrevem as METADES DA ESFERA; sem esfera não têm assunto. */
  opacity: var(--about-fade, 0);
  max-width: 30vw;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.act-globe-side--left {
  right: calc(50% + 26px);
  text-align: right;
  color: rgba(18, 40, 69, 0.62);
}
/* O nosso lado é o que ganha cor: azul do logo, com um traço amarelo curto
   antes do texto. É a mesma gramática do resto da cena — o lado da Metenergy
   é sempre o que carrega a marca. */
.act-globe-side--right {
  left: calc(50% + 26px);
  text-align: left;
  /* Pedido do fundador (15/08): o azul do logo (rgba(28,127,196)) sumia
     contra o cinturão de ciclones — trocado por amarelo sólido. Pedido do
     fundador (16/08): o contorno preto que veio junto ficou ruim — amarelo
     sem contorno. */
  color: #ffd34d;
  padding-left: 0.7rem;
  background: linear-gradient(rgba(255, 211, 77, 0.95), rgba(255, 211, 77, 0.95))
    no-repeat left center / 3px 11px;
}
.act-globe-side.act-on { display: block; }


/* Escala de cor dos dois atos. Canto inferior esquerdo — o único que fica
   livre nos dois: o ato da chuva tem cards nas laterais (centrados) e o card
   de argumento no rodapé central; o do vento tem a faixa de métricas no
   rodapé central. Vertical, com o máximo em cima, que é a convenção de escala
   vertical que os painéis do estudo de caso já usam.

   display/visibility em vez de display:none (o padrão de .act-border): um
   canvas sem caixa tem clientWidth 0 e drawColorBar desiste, então a barra
   nunca seria desenhada se o elemento nascesse com display:none. Com
   visibility ela tem layout desde o início e o pipeline de canvas do main.js
   a desenha junto com as outras duas. */
.act-cbar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  /* Pedido do fundador (16/08): a colorbar do caso de chuva foi para a
     direita — a esquerda já carrega o pino do pluviômetro, o card do ERA5 e
     o gráfico que abre embaixo do pino, e a colorbar entrava na fila. O caso
     de vento (.act-cbar--linha, embaixo, centralizada) não usa esta posição,
     então não é afetado. */
  right: 28px;
  left: auto;
  bottom: 28px;
  padding: 0.65rem 0.55rem 0.6rem;
  border: 1px solid rgba(77, 184, 255, 0.32);
  border-radius: 3px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(6px);
  font-size: 0.58rem;
  color: rgba(231, 241, 255, 0.85);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.25s ease;
}
/* display:flex REPETIDO aqui de propósito: `.act-border.act-on { display:
   block }` tem duas classes de especificidade e vencia o `display:flex` da
   regra base, desmanchando a coluna — em captura os três rótulos apareciam
   amontoados numa linha só no pé da barra. */
.act-cbar.act-on { display: flex; visibility: visible; opacity: 1; }
.act-cbar-canvas { width: 12px; height: 118px; }

/* A barra DEITADA (13/08). Rodapé centrado, onde o campo não chega: a versão
   em pé morava na lateral e os números caíam por cima do mapa. */
.act-cbar--linha {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  left: 50%;
  right: auto;
  bottom: 84px;
  transform: translateX(-50%);
  padding: 0.4rem 0.7rem;
}
/* Mais larga desde que .act-metrics saiu do rodapé para o canto direito
   (13/08) — a faixa deixou de disputar espaço com a coluna de métricas. */
.act-cbar--linha .act-cbar-canvas { width: 320px; height: 9px; }
.act-cbar-unit { opacity: 0.7; }

/* Cartela do caso — o interlúdio entre o "Sobre Nós" e o caso de tempestade
   (pedido do fundador, 12/08). Rodapé centrado, exatamente onde o card de
   argumento do ato da chuva vai aparecer em seguida: a cartela ocupa o lugar,
   o caso começa, e o lugar continua ocupado — a passagem não tem buraco.
   Mesma moldura de instrumento do resto da cena, com os dois colchetes em
   amarelo porque este bloco é centrado e não tem lado por onde a leitura
   entre. --slate-fade é escrito por drawActOpen a cada quadro. */
.act-open-slate {
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  width: min(92vw, 620px);
  padding: 1rem 1.5rem 1.15rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 16px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 16px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 16px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 2px 16px,
    linear-gradient(rgba(10, 20, 40, 0.92), rgba(10, 20, 40, 0.92));
  backdrop-filter: blur(6px);
  text-align: center;
  opacity: var(--slate-fade, 0);
}
.act-open-slate.act-on { display: block; }
/* A cartela 02 é a mesma peça, só que dirigida por outra variável — ela vive
   no ato da chuva, não no da abertura. */
.act-open-slate--2 { opacity: var(--slate2-fade, 0); }
/* O "01 / 02" não é enfeite: é a preparação. Dizer que existem dois casos,
   antes do primeiro, é o que transforma uma tela técnica solta numa sequência
   que o leitor sabe onde começa e onde acaba. */
.act-open-slate-eyebrow {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.8rem;
  margin: 0 0 0.7rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(77, 184, 255, 0.32);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 211, 77, 0.92);
}
.act-open-slate-eyebrow::after {
  content: attr(data-index);
  font-family: 'Courier New', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
  color: rgba(120, 200, 255, 0.75);
}
.act-open-slate-title {
  margin: 0 0 0.5rem;
  font-family: 'Space Grotesk', 'Plus Jakarta Sans', sans-serif;
  font-size: clamp(1.05rem, 1.35vw, 1.4rem);
  font-weight: 600;
  line-height: 1.3;
  color: #e7f1ff;
}
.act-open-slate-line {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: rgba(231, 241, 255, 0.85);
  opacity: 0.92;
}
/* Só uma das duas linhas existe por idioma — a regra do campo viajante
   (js/scene/act-rain-i18n.mjs) decide qual, e syncActDom liga a classe. Sem
   isto as duas ocupariam espaço mesmo invisíveis. */
.act-open-slate .act-local-only,
.act-open-slate .act-demo-only { display: none; }
.act-open-slate .act-local-only.act-on,
.act-open-slate .act-demo-only.act-on { display: block; }

/* "Sobre nós" da abertura — 3ª reprojeção (pedido do fundador, verbatim,
   11/08, 4ª rodada): "sobre nós a esquerda [...] nosso propósito a
   direita". Duas colunas agora em vez de um bloco só, ancoradas nas
   laterais como .act-side-card (fixed, centralizado verticalmente, 28px da
   borda) — o mesmo padrão do ato de chuva, reaproveitado aqui pela 1ª vez.
   O pino do caso e a malha caem perto do centro do quadro (CASE_PIN,
   scene.mjs) durante o platô de leitura; laterais deixam o centro livre
   para o mapa (verificado em captura, VW=1440/1366/1920 — se o mapa virar
   tira nas larguras estreitas, a largura das colunas cai antes de mexer na
   posição). de/en mostram o país inteiro nesse mesmo trecho do voo
   (WIDE_FACTOR ainda dominante, ver scene.mjs) — mesma posição lateral
   serve, o quadro largo tem sobra nos dois lados nesses idiomas. */
.act-open-about {
  /* Banda vertical FIXA, em vez de uma caixa que abraça o próprio texto e é
     centrada em top:50%. Achado do fundador (12/08): "os textos não estão
     muito bem organizados e preenchidos, parecem meio espremidos por conta de
     não estar centralizado".
     O diagnóstico dele está certo e a causa era esta: as duas colunas tinham
     alturas DIFERENTES (o "Sobre Nós" é um parágrafo de quatro frases, o
     "Nosso propósito" tem metade disso), e duas caixas de alturas diferentes
     centradas no mesmo eixo não leem como par — leem como duas coisas soltas,
     e a mais cheia parece apertada ao lado da mais vazia. Com topo e base
     iguais e o conteúdo centrado DENTRO, as duas viram uma composição só e a
     folga sobra igual dos dois lados.
     14vh de margem: em 900 px de altura sobram 630 px de banda para ~525 px de
     conteúdo na coluna mais cheia; em 768 px, 538 para ~505. Verificado em
     captura nas três alturas. */
  top: 14vh;
  bottom: 14vh;
  transform: none;
  /* 1ª tentativa (280/27vw/380px) estourava a viewport verticalmente: a 380px
     de largura, o parágrafo do propósito (~350 caracteres, fonte grande)
     quebrava em ~20 linhas e vazava por cima E por baixo da tela inteira —
     "Nosso propósito" nem aparecia, cortado acima do topo (verificado em
     captura, VW=1440 VH=900). Alargado para 460px de teto — com a fonte
     também reduzida (.about-manifest-purpose abaixo), o bloco volta a caber
     inteiro entre topo e rodapé nas alturas testadas (768/900/1080). */
  /* 30vw/460px → 24vw/380px (11/08, abertura com o globo parado): as duas
     colunas passaram a flanquear a ESFERA, não o mapa plano. O mapa aceitava
     ser espremido nas laterais; o globo não — ele é o argumento agora, e uma
     esfera coberta pelos dois lados deixa de ser um objeto.
     A conta, em 1440x900: o globo tem raio min(W,H)·0,36 = 324 px, logo 648 px
     de diâmetro, centrado. Duas colunas de 24vw = 345 px mais 28 px de margem
     de cada lado deixam 1440 − 2·(345+28) = 694 px livres no meio — 46 px de
     folga sobre o diâmetro. Em 1366x768 sobram 654 px para 553 px de esfera;
     em 1920x1080, 1104 px para 778 px. Verificado em captura nas três. */
  width: clamp(280px, 24vw, 380px);
  max-width: 34vw;
  opacity: var(--about-fade, 0);
}
.act-open-about--who {
  left: 28px;
  right: auto;
  text-align: left;
}
.act-open-about--purpose {
  right: 28px;
  left: auto;
  text-align: right;
}
/* Rótulo dos cinturões de ciclones — logo abaixo da esfera, centrado. Peso
   deliberadamente pequeno: é uma ressalva, não uma legenda de painel (uma
   legenda daria ao campo o status de dado, que é exatamente o que a ressalva
   existe para negar). Sem cor de escala, sem unidade, sem número. Segue a
   mesma opacidade das duas colunas: é o mesmo quadro. */
.act-open-ambient {
  left: 50%;
  bottom: 56px;
  transform: translateX(-50%);
  margin: 0;
  max-width: 46vw;
  text-align: center;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: rgba(150, 200, 245, 0.62);
  opacity: var(--about-fade, 0);
}
.act-open-ambient.act-on { display: block; }

/* flex, não block: a caixa interna precisa PREENCHER a banda para as duas
   colunas terminarem com a mesma altura (ver comentário acima). */
.act-open-about.act-on { display: flex; }
.act-open-about .about-manifest {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Beat do diferencial — ocupa exatamente a mesma banda e a mesma largura das
   duas colunas do "Sobre Nós"/"Nosso propósito", porque é o que ele substitui.
   Herda a moldura de instrumento inteira (.about-manifest lá dentro), então a
   troca lê como a MESMA caixa mudando de conteúdo, e não como dois blocos
   diferentes se revezando. --diff-fade é escrito por drawActOpen a cada
   quadro, espelhado com --about-fade. */
.act-open-diff {
  top: 14vh;
  bottom: 14vh;
  transform: none;
  width: clamp(280px, 24vw, 380px);
  max-width: 34vw;
  opacity: var(--diff-fade, 0);
}
.act-open-diff--left  { left: 28px; right: auto; text-align: left; }
.act-open-diff--right { right: 28px; left: auto; text-align: right; }
.act-open-diff.act-on { display: flex; }
.act-open-diff .about-manifest {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ── 13/08: as duas caixas de um lado, os diferenciais do outro ─────────
   Pedido do fundador: "a caixa do relevo e da vegetação e características de
   solo estejam do mesmo lado na esquerda com descritivos mínimos [...] e do
   lado direito colocaremos as nossas características".

   As duas colunas viram pilhas verticais. A da esquerda empilha as duas caixas
   3D; a da direita, três afirmações, cada uma com seu objeto 3D pequeno. */
.act-open-diff {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  /* Pedido do fundador (15/08): estas duas colunas ficavam sem fundo próprio
     — texto escuro (#122845, pensado para pousar sobre o mar claro que a
     cena tinha antes de virar azul-marinho no topo) direto sobre o céu
     escuro da cena, só legível por causa do text-shadow branco herdado de
     .act-border. Removido o shadow (ver .about-manifest-eyebrow), então
     ganham o mesmo cartão sólido + colchetes de canto que "Sobre Nós"/
     "Nosso propósito" já usam (.about-manifest), e o texto interno vira
     claro (ver .act-diff-title/.act-diff-body/.edge-titulo/.edge-corpo). */
  padding: 1.2rem 1.4rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  background:
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
  backdrop-filter: blur(6px);
}
.act-open-diff.act-on { display: flex; }
/* O colchete de canto amarelo do lado por onde a leitura começa — mesma
   convenção de .about-manifest--who/--purpose. */
.act-open-diff--left {
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
}
.act-open-diff--right {
  background:
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
}
/* A coluna da direita é mais larga: ela carrega texto em três blocos, e no
   teto de 380px as frases quebravam em quatro linhas cada. */
.act-open-diff--right { width: clamp(300px, 27vw, 430px); }

.diff-caixa { display: flex; flex-direction: column; }
/* Empilhadas, cada canvas fica com pouco mais de um terço da coluna. A
   proporção 3:2 do canvas (ver .act-diff-canvas) já tinha sido medida para o
   objeto — o que muda aqui é só quanto espaço cada uma recebe. */
.act-open-diff--left .act-diff-canvas { margin: 0.1rem 0 0.35rem; }
.act-open-diff--left .act-diff-title { font-size: 1rem; margin-bottom: 0.2rem; }
.act-open-diff--left .act-diff-body { font-size: 11.5px; line-height: 1.45; }
/* Mesma banda de altura fixa do "Sobre Nós"/"Nosso propósito" ao lado
   (.act-open-diff herda top/bottom:14vh de .act-open-about, ver acima) — e o
   mesmo defeito: duas caixas empilhadas (relevo + vegetação), cada uma com
   canvas + título + corpo em tamanho fixo, não cabem na banda quando a
   altura da viewport é curta (achado por captura, 24/08, VW=1000 VH=650: a
   segunda caixa vaza ~12px pelo rodapé). Encolhe as margens do canvas e o
   corpo do texto só aqui — o suficiente pra caber, sem mexer na coluna da
   direita (.act-open-diff--right), que já cabia. */
@media (max-height: 700px) {
  .act-open-diff--left .act-diff-canvas { margin: 0.05rem 0 0.2rem; }
  .act-open-diff--left .act-diff-title { font-size: 0.92rem; margin-bottom: 0.1rem; }
  .act-open-diff--left .act-diff-body { font-size: 10.5px; line-height: 1.3; }
  .act-open-diff { gap: 0.3rem; padding: 0.85rem 1rem; }
}
/* Ainda mais curto (janela pequena/DevTools aberto): o passo acima sozinho
   ainda deixava ~13px de sobra em VH=600 (verificado em captura). */
@media (max-height: 640px) {
  .act-open-diff--left .act-diff-canvas { margin: 0 0 0.08rem; }
  .act-open-diff--left .act-diff-title { font-size: 0.85rem; }
  .act-open-diff--left .act-diff-body { font-size: 9.5px; line-height: 1.2; }
}

/* Os três diferenciais. Objeto à esquerda do texto, sempre — mesmo na coluna
   alinhada à direita: o olho lê o par "símbolo + frase" na mesma ordem, e
   espelhar isso faria as três linhas parecerem três layouts diferentes. */
.edge-item {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  text-align: left;
  padding: 0.5rem 0;
}
/* 108px e não 84: a nuvem passou a ter processadores dentro e um banco
   embaixo (13/08), e a 84px os pinos do chip viravam um borrão cinza. É o
   objeto mais detalhado dos três que manda no tamanho dos três — eles têm de
   ficar do mesmo tamanho, senão a lista lê como três layouts. */
.edge-canvas {
  flex: 0 0 auto;
  width: 108px;
  height: 108px;
  display: block;
}
.edge-texto { min-width: 0; }
.edge-titulo {
  margin: 0 0 0.2rem;
  font-family: 'Space Grotesk', 'Plus Jakarta Sans', sans-serif;
  font-size: 0.95rem;
  font-weight: 700;
  color: #e7f1ff;
}
.edge-corpo {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: rgba(231, 241, 255, 0.85);
  opacity: 0.9;
}
/* A caixa 3D. Quadrada: ela gira, e uma caixa não quadrada mudaria de tamanho
   aparente conforme o giro — o olho leria isso como a caixa crescendo, não
   girando. */
.act-diff-canvas {
  display: block;
  width: 100%;
  /* 3:2 e não 1:1. O objeto é uma laje larga e baixa vista de cima; num quadro
     quadrado ele ocupava a faixa do meio e sobrava vazio em cima e embaixo.
     Encher o quadrado exigiria ou cortar os cantos no giro, ou esticar a
     projeção — e esticar deforma o terreno. Mudar o quadro é o barato. */
  aspect-ratio: 3 / 2;
  margin: 0.2rem 0 0.6rem;
}
.act-diff-title {
  margin: 0 0 0.35rem;
  font-family: 'Space Grotesk', 'Plus Jakarta Sans', sans-serif;
  font-size: 1.15rem;
  font-weight: 600;
  color: #e7f1ff;
}
.act-diff-body {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(231, 241, 255, 0.85);
  opacity: 0.9;
}

/* Scrim: não é caixa — é um gradiente radial ancorado no canto onde o texto
   mora, bem mais escuro perto do texto e transparente a ~70% da distância,
   sem borda nem raio. Existe só para segurar contraste sobre o mar mais
   claro/a malha de 25 km; sozinho o text-shadow (herdado de .act-border)
   não bastava em captura com o mar iluminado pelo estilo "streets" do
   toggle de mapa. */
/* Contorno azul — pedido do fundador (11/08, 3ª rodada): "deveria seguir o
   layout com azul, com contorno azuis". Tensão com o pedido anterior ("sem
   caixa nenhuma", ver comentário grande acima): a diferença é contorno vs.
   moldura — 1px, quase transparente (0.22 de opacidade), SEM fundo opaco
   (o scrim ::before continua sendo o único "fundo", e ele já existia). Se
   isto ler como caixa de novo em captura, a opacidade cai, não sobe.
   #4db8ff é o azul de título já usado no resto do site (splash, nav,
   domain-label) — aqui vira também o contorno, não só o texto. */
.about-manifest {
  position: relative;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 3px;
  padding: 1.5rem 1.8rem;
  /* Pedido do fundador (11/08, 5ª rodada): "contornos melhores, mais
     features visuais nos textos não só uma caixa de texto [...] talvez
     colocar mais features na borda deixar mais futurista". Registro de
     instrumento/HUD (console de radar), não "adesivo sci-fi" — restrito a
     DOIS traços diagonais (canto onde a leitura começa e canto onde ela
     termina), não os quatro: quatro cantos com o mesmo peso do contorno
     de 1px já existente lia como moldura genérica de novo em captura.
     Pura background (sem DOM novo): dois "L"s de 2px, dentro do padding,
     nunca sobre o texto. Raio caiu de 6px para 3px — cantos quase retos
     é o que deixa um traço reto ler como acabamento, não ruído, contra
     um raio maior (achado em captura). */
  background:
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
  backdrop-filter: blur(6px);
}
/* Dos dois colchetes de canto, o do lado por onde a leitura entra vira
   amarelo — esquerda na coluna "Sobre Nós", direita na "Nosso propósito",
   acompanhando o alinhamento de cada uma. Só um dos dois: os dois amarelos
   virariam moldura, que é o que a rodada de 11/08 já tinha removido. */
.about-manifest--who {
  background:
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
}
.about-manifest--purpose {
  background:
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 15px 2px,
    linear-gradient(rgba(77, 184, 255, 0.62), rgba(77, 184, 255, 0.62)) no-repeat top left / 2px 15px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 15px 2px,
    linear-gradient(rgba(255, 211, 77, 0.9), rgba(255, 211, 77, 0.9)) no-repeat bottom right / 2px 15px,
    linear-gradient(rgba(10, 20, 40, 0.97), rgba(10, 20, 40, 0.97));
}

/* O scrim radial que existia aqui (rodada de 13-14/08) segurava contraste
   contra o globo quando esta caixa não tinha fundo próprio. Pedido do
   fundador (14/08): a caixa agora tem fundo sólido azul-marinho — o scrim
   ficou redundante e, pior, vazava um halo claro para FORA da caixa (o
   inset negativo é maior que a própria caixa). Removido. */
/* Borda de topo em gradiente, mais clara no canto de onde a leitura começa
   (esquerda na coluna "Sobre Nós", direita na "Nosso propósito" — mesmo
   canto que os text-align já usam) e apagando para o outro lado: "um
   contorno que não é uniforme" sem tocar o contorno de 1px existente (que
   já foi medido e aprovado numa rodada anterior — este é aditivo, não
   substitui). */
.about-manifest::after {
  content: '';
  position: absolute;
  top: -1px; left: -1px; right: -1px;
  height: 2px;
  background: linear-gradient(to right, rgba(120, 205, 255, 0.95), rgba(120, 205, 255, 0) 65%);
  pointer-events: none;
}
.about-manifest--purpose::after {
  background: linear-gradient(to left, rgba(120, 205, 255, 0.95), rgba(120, 205, 255, 0) 65%);
}
/* Régua fina + índice monoespaçado — mesmo pedido do fundador acima ("mais
   features nos textos"), agora no rótulo em vez da caixa. attr(data-index)
   lê "01"/"02" do HTML (about-manifest--who/--purpose, ver index.html):
   número de coluna, não coordenada geográfica — verdadeiro por construção,
   sem precisar ligar isto ao frame da câmera em scene.mjs (mais estado
   entre dois módulos que já não se importam um ao outro, ver comentário de
   flightHasLanded() em scene.mjs — trade-off decidido: simplicidade > mais
   um dado "real" que pouco acrescenta ao lado de "Sobre Nós"/"Nosso
   propósito"). */
.about-manifest-eyebrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.7rem;
  margin-bottom: 1.1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(77, 184, 255, 0.28);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: rgba(77, 184, 255, 0.85);
  text-transform: uppercase;
  /* Sem isto herdava o text-shadow branco de .act-border (o pai
     .act-open-about--who) — "Sobre Nós" e o índice "01" (mesmo elemento,
     ::after) ficavam com um halo branco que "Nosso propósito" não tinha,
     porque .about-manifest-eyebrow--purpose já sobrescrevia o seu próprio
     text-shadow (achado do fundador, 15/08: "deixe como o propósito, só em
     azul normal"). */
  text-shadow: none;
}
.about-manifest-eyebrow::after {
  content: attr(data-index);
  flex: none;
  font-family: 'Courier New', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
  /* Amarelo do logo. Pedido do fundador (12/08): "colocar alguns pequenos
     detalhes em amarelo e azul, que é a cor do logo da Metenergy". O índice
     é o lugar certo para o primeiro deles — é dado de instrumento, não texto,
     então a cor lê como marcação e não como ênfase de leitura. */
  color: rgba(255, 211, 77, 0.78);
}
/* Um traço amarelo curto onde a leitura COMEÇA, por cima da régua azul do
   cabeçalho: à esquerda na coluna "Sobre Nós", à direita na "Nosso propósito",
   acompanhando o text-align de cada uma. É o segundo detalhe, e é aditivo — a
   régua azul de 1px continua exatamente onde estava. */
.about-manifest-eyebrow {
  background:
    linear-gradient(rgba(255, 211, 77, 0.85), rgba(255, 211, 77, 0.85))
    no-repeat left bottom / 34px 1px;
}
.about-manifest-eyebrow--purpose {
  background-position: right bottom;
}
/* "Nosso propósito" tinha aqui um contorno azul + text-shadow próprios
   (-webkit-text-stroke + glow) que "Sobre Nós" nunca teve — pedido do
   fundador (19/08): "está com um sombreamento branco, quero que seja a
   mesma fonte e formato do texto Sobre Nós". Removido: agora as duas
   etiquetas herdam só a base (.about-manifest-eyebrow, text-shadow:none,
   sem stroke) e diferem apenas na posição do traço amarelo embaixo (regra
   --purpose logo acima, que continua). */
/* "Sobre nós" (esquerda) — pedido do fundador (11/08, 4ª rodada): "mais
   descritivo" e "sem ser letra branca". O corpo cresceu de 1 frase para 4
   (ver index.html/report da tarefa) — testado com o mesmo contorno azul do
   parágrafo da direita (-webkit-text-stroke) e DESCARTADO: em Plus Jakarta
   Sans no tamanho de corpo (1.05rem) o traço de 0,4px virava serrilhado/
   borrão em volta de cada letra (verificado em captura, VW=1440 e VW=390 —
   pior ainda no menor). Mantido só o tingimento azul-claro do preenchimento
   e um glow suave (mesma cor do contorno, sem o -stroke): "não mais branco
   puro", mas legível numa frase de 4 sentenças. Ver nota grande em
   .about-manifest-purpose sobre por que o parágrafo maior aguenta o
   contorno e este não. */
.about-manifest-who {
  margin: 0;
  /* Era um rem fixo (1.02rem) — a banda que segura este texto é uma altura
     FIXA em vh (.act-open-about, top/bottom:14vh) e a largura da coluna
     também encolhe com a viewport (clamp(280px,24vw,380px)). Com fonte fixa,
     janelas mais estreitas quebram o parágrafo em mais linhas e janelas mais
     baixas sobram menos altura pra essas linhas — os dois efeitos se somam, e
     abaixo de ~1280×720 (notebook comum) o texto passa do fundo da caixa
     (achado por captura, 24/08, VW=1100..1200 VH=700..750: as últimas 1-2
     linhas caem fora do card). `vmin` reage aos dois eixos ao mesmo tempo. */
  font-size: clamp(0.82rem, 0.27rem + 1.33vmin, 1.02rem);
  line-height: 1.55;
  font-weight: 400;
  /* Pedido do fundador (14/08): a caixa .about-manifest ganhou fundo
     azul-marinho sólido de volta (mesmo tom dos outros cards) — texto volta a
     ser claro, sem sombra (o fundo já é opaco e uniforme, não precisa mais
     segurar contraste contra o globo por trás). */
  color: #c3dfff;
  text-shadow: none;
  opacity: 0.96;
}
/* O manifesto — "Nosso propósito", pedido do fundador (verbatim, 11/08, 4ª
   rodada): "letra mais bonita com bordas em azul meio futurista mais
   avançada", explicitamente contra a letra branca lisa que havia antes.
   Space Grotesk substitui a Fraunces (ver index.html <head>) — geométrica e
   de traço técnico, onde um contorno fino lê como acabamento, não como
   ruído (a Fraunces, serifada e mais fina nos terminais, não sustentava o
   mesmo contorno sem virar borrão — não testado a fundo porque a troca de
   fonte resolveu o problema de raiz). O tratamento é em camadas, não um
   truque só:
     1) preenchimento com leve tinta azul (não mais #f4f8ff quase-branco);
     2) -webkit-text-stroke fino (0,5px) na mesma cor de contorno do resto
        do bloco (rgba do azul de título, ver .about-manifest border);
     3) glow curto (10px) mais um text-shadow escuro apertado (3px) por
        baixo — o escuro é o que segura contraste sobre o mar/a malha
        clara, o glow é só o acento "futurista"; sem o escuro, o texto some
        no fundo claro do mapa em modo "streets" (verificado em captura).
   Tamanho e entrelinha generosos como antes — "escrita mais bonita" pedia
   respiro, não densidade de card. Verificado em captura a 1,15rem (mínimo
   do clamp, tela baixa) e 1,85rem (máximo, 1920): o contorno lê nos dois,
   não vira mancha em nenhum. */
/* Rótulos "Quem somos" / "Nosso propósito" — só sobrevivem na versão
   estreita (.about-mini-manifest, telas <900px, ver index.html #about):
   no desktop a coluna esquerda usa about-manifest-eyebrow ("Sobre Nós") e a
   direita usa about-manifest-eyebrow--purpose ("Nosso propósito") como
   cabeçalho único da coluna — não precisa mais do rótulo interno "Quem
   somos" empilhado, porque cada coluna já é um bloco visualmente separado
   do outro. Na tela estreita os dois blocos continuam empilhados dentro do
   mesmo cartão (#box-about), então o rótulo interno ainda separa os dois
   textos por escrito. */
/* Tela estreita (.about-mini-manifest, <900px) nunca ganha a caixa
   .about-manifest (decisão de rodada anterior: sem mapa, sem "caixa dentro
   de caixa" — ver comentário grande abaixo). O mesmo pedido de "mais
   features" ainda vale aqui, só que só no rótulo (régua+índice, mesma
   técnica de .about-manifest-eyebrow acima) — nada de cantos/gradiente de
   borda, que dependeriam de uma caixa que este layout deliberadamente não
   tem. */
.about-manifest-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin: 0 0 0.4rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid rgba(77, 184, 255, 0.24);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(140, 205, 255, 0.85);
  opacity: 1;
}
.about-manifest-label::after {
  content: attr(data-index);
  flex: none;
  font-family: 'Courier New', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
  color: rgba(120, 200, 255, 0.5);
}
.about-manifest-label--purpose { margin-top: 1.6rem; }
/* 13/08 — pedido do fundador: "a fonte e tipo de letra do sobre nós ficou boa
   mas a do propósito não está boa, quero que a do propósito seja a mesma fonte
   e tipo de letra do sobre nós".
   Então esta regra passou a ser a MESMA tipografia de .about-manifest-who:
   mesma família (a do corpo), mesmo peso, mesmo corpo, mesma entrelinha, mesma
   tinta. Saíram as três coisas que a faziam ler como outra letra: a família
   Space Grotesk, o peso 500 e — principalmente — o -webkit-text-stroke, que
   engrossa o traço e é o que dava a ela aquele aspecto de fonte diferente.
   O que NÃO mudou é o alinhamento à direita: isso é posição da coluna, não
   tipo de letra, e é o que mantém as duas colunas espelhadas em volta do
   globo. */
.about-manifest-purpose {
  margin: 0.5rem 0 0;
  /* Mesmo raciocínio/achado de .about-manifest-who acima — vmin em vez de
     rem fixo, pra caber na banda de 14vh quando a viewport é estreita e
     baixa ao mesmo tempo. */
  font-size: clamp(0.82rem, 0.27rem + 1.33vmin, 1.02rem);
  line-height: 1.55;
  font-weight: 400;
  color: #f4f8ff;
  text-shadow: none;
  opacity: 0.96;
  text-wrap: pretty;
}
/* Fatos institucionais — antes 2 dos 4 cards (financiamento/validação,
   operação); agora uma linha só, subordinada ao manifesto (pedido do
   fundador: o propósito é o centro, o resto é apoio). Tipografia de dado,
   não de prosa — Plus Jakarta Sans pequena e apagada. */
/* Logos — mesmos arquivos que #splash-partners já usa, fileira única e
   discreta no fim (pedido do fundador, rodada de 11/08: logo em vez de
   nomear por extenso). Opacidade baixa: aqui é crédito, não destaque. */

/* Telas baixas (1366×768 é o notebook mais comum abaixo de 900px de altura):
   as duas colunas agora ficam centralizadas verticalmente (top:50%, ver
   .act-open-about acima), não mais ancoradas por bottom — sobra menos
   altura livre para um parágrafo grande, então o tamanho do texto e o
   padding ainda encolhem aqui (verificado em captura, VW=1366 VH=768).
   Precisa vir DEPOIS das regras base de mesma especificidade acima
   (.about-manifest-purpose etc.) — media query não dá prioridade de
   cascata sozinha, a ordem no arquivo é quem decide entre duas regras de
   mesma especificidade, então uma cópia mais cedo no arquivo perdia mesmo
   dentro do @media. */
@media (max-height: 820px) {
  /* Até 24/08 esta regra AUMENTAVA a fonte do propósito pra até 1.5rem
     (clamp(1.1rem,1.5vw,1.5rem)) — resto de um design anterior (Space
     Grotesk + contorno), de antes da tipografia de "Nosso propósito" virar
     igual à de "Sobre Nós" (13/08, ver comentário grande acima de
     .about-manifest-purpose). Ficou esquecida aqui e piorava o estouro do
     card exatamente na condição que este media query cobre (tela baixa):
     texto MAIOR com MENOS altura disponível. .about-manifest-who/-purpose
     agora usam clamp em vmin (reage a largura E altura), então este bloco
     não precisa mais fixar tamanho de fonte — só o padding/espaçamento. */
  .about-manifest { padding: 1.1rem 1.3rem; }
  .about-manifest-eyebrow { margin-bottom: 0.7rem; }
  .about-manifest-label--purpose { margin-top: 1rem; }
  }

/* Mesmas chaves i18n do manifesto, em fluxo normal — telas estreitas nunca
   carregam a cena (ver comentário em index.html #about), então não têm mapa
   nenhum para o texto pousar em cima; aqui ele volta a viver dentro do
   cartão que #about já é (#box-about), sem scrim (não precisa: o cartão já
   tem fundo). Sem grid de cards, mesma razão do desktop: caixa dentro de
   caixa não era o que o fundador pediu, nem aqui. */
.about-mini-eyebrow {
  display: block;
  margin-top: 1.6rem;
  margin-bottom: 0.9rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: rgba(77, 184, 255, 0.85);
  text-transform: uppercase;
}
/* Só aqui: .about-manifest-who/.about-manifest-purpose também são usadas
   direto sobre a cena (globo, act-open, index.html ~L407-413), fora de
   escopo do fundo claro — a regra base delas (mais abaixo neste arquivo)
   fica intocada. Esta sobrescrita vale só dentro de .about-mini-manifest,
   o fallback estreito sem cena. */
.about-mini-manifest .about-manifest-purpose {
  font-size: clamp(1.05rem, 4vw, 1.35rem);
}
.about-mini-manifest .about-manifest-who,
.about-mini-manifest .about-manifest-purpose {
  color: rgba(214, 232, 255, 0.85);
  text-shadow: none;
}
/* Achado ao editar este bloco (11/08, 3ª rodada): a regra abaixo estava com
   o seletor ".about-mini-manifest" solto, sem chaves, seguido do comentário
   e de ".awards-section {...}" — CSS ignora comentários mas não a quebra de
   linha, então isso virava o seletor combinado
   ".about-mini-manifest .awards-section", que nunca casa com nada no DOM
   (awards-section não fica dentro do manifesto). height:500vh/pointer-
   events:all nunca aplicavam; a regra real (que sustenta a seção) é a
   segunda ".awards-section" mais abaixo neste arquivo — corrigido de
   passagem. Já que #box-about já é a moldura na tela estreita,
   o contorno azul aqui é só uma régua fina no topo (não outra caixa
   aninhada dentro do cartão que já existe). */
.about-mini-manifest {
  border-top: 1px solid rgba(77, 184, 255, 0.28);
  padding-top: 1.1rem;
}

/* Awards section: a fundacao esta sempre completa (sem crescer com o
   scroll); a altura extra e so um respiro de entrada antes do sticky
   soltar para a proxima secao. Era 500vh quando a corda crescia com o
   progresso do scroll — pedido do fundador (13/08): "ao inves de ficar
   descendo para aparecer a linha crescendo ja deixe a linha completa e
   so passar o mouse nas lampadas ja vai surgindo". */
.awards-section {
  height: 160vh;
  pointer-events: all;
}

/* ══════════════════════════════════════════════════════════
   RESOLUTION LADDER — rain field, legend, attribution
   ══════════════════════════════════════════════════════════ */

/* Rain field overlay.
   The source PNGs are contour plots on opaque white with no alpha channel;
   keyOutWhite() in main.js derives transparency from distance-to-white at load
   time, so by the time it reaches this canvas it composites normally. */
#rain-canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s ease;
}

#res-legend {
  position: fixed;
  left: 50%;
  bottom: 1.6rem;
  transform: translateX(-50%) translateY(10px);
  z-index: 6;
  max-width: min(880px, 92vw);
  padding: 0.7rem 1.1rem 0.75rem;
  border-radius: 14px;
  background: rgba(8, 20, 32, 0.78);
  border: 1px solid rgba(120, 200, 255, 0.20);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #eaf4ff;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease, transform 0.45s ease, visibility 0.45s;
  pointer-events: none;
  text-wrap: pretty;
}

#res-legend.visible {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.rl-event {
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(180, 215, 245, 0.7);
  text-align: center;
  margin-bottom: 0.5rem;
}

/* The three rungs sit side by side so the ladder itself is legible: you can
   see which product you are on and what is still coming. */
.rl-ladder {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}

.rl-rung {
  padding: 0.45rem 0.6rem 0.5rem;
  border-radius: 9px;
  border: 1px solid transparent;
  background: rgba(255, 255, 255, 0.03);
  opacity: 0.42;
  transition: opacity 0.4s ease, background 0.4s ease, border-color 0.4s ease;
}

.rl-rung.active {
  opacity: 1;
  background: rgba(70, 150, 220, 0.16);
  border-color: rgba(127, 212, 255, 0.42);
}

.rl-rung-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
}

.rl-name {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.rl-res {
  font-size: 0.66rem;
  font-weight: 600;
  color: #7fd4ff;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rl-bar {
  position: relative;
  height: 4px;
  margin: 0.4rem 0 0.35rem;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}

.rl-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: 3px;
  transition: width 0.7s ease;
}

.rl-rung .rl-fill        { background: linear-gradient(90deg, #6a5a8f, #a07fc4); }
.rl-rung.best .rl-fill   { background: linear-gradient(90deg, #2f7fd4, #7fd4ff); }

.rl-value {
  font-size: 0.72rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rl-note {
  margin-top: 0.5rem;
  padding-top: 0.45rem;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  font-size: 0.62rem;
  line-height: 1.35;
  color: rgba(175, 205, 230, 0.62);
  text-align: center;
}

/* Case invite — same slot as the legend, for the corridors without a field. */
.case-invite {
  position: fixed;
  left: 50%;
  bottom: 1.6rem;
  transform: translateX(-50%) translateY(10px);
  z-index: 6;
  max-width: min(620px, 92vw);
  padding: 0.8rem 1.3rem 0.9rem;
  border-radius: 14px;
  background: rgba(8, 20, 32, 0.78);
  border: 1px solid rgba(120, 200, 255, 0.20);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #eaf4ff;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease, transform 0.45s ease, visibility 0.45s;
  pointer-events: none;
  text-wrap: pretty;
}

.case-invite.visible {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.ci-headline {
  font-size: 0.86rem;
  line-height: 1.2;
}

.ci-headline strong {
  font-size: 1.55rem;
  font-weight: 700;
  color: #7fd4ff;
  font-variant-numeric: tabular-nums;
  margin-right: 0.3rem;
}

.ci-sub {
  margin-top: 0.4rem;
  font-size: 0.72rem;
  line-height: 1.4;
  color: rgba(190, 220, 245, 0.78);
}

.ci-link {
  display: inline-block;
  margin-top: 0.7rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: #7fd4ff;
  text-decoration: none;
  border-bottom: 1px solid rgba(127, 212, 255, 0.35);
  padding-bottom: 1px;
  transition: color 0.2s, border-color 0.2s;
}

.ci-link:hover {
  color: #b9e6ff;
  border-color: rgba(185, 230, 255, 0.7);
}

/* Tile attribution — required by Esri and CARTO terms on a commercial site. */
#map-attrib {
  position: fixed;
  right: 0.5rem;
  bottom: 0.35rem;
  z-index: 6;
  font-size: 0.6rem;
  line-height: 1.3;
  color: rgba(230, 240, 250, 0.55);
  background: rgba(0, 0, 0, 0.32);
  padding: 0.14rem 0.5rem;
  border-radius: 5px;
  pointer-events: none;
  max-width: 46vw;
  text-align: right;
}

/* ── WRF GRID ── */
#wrf-grid {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 2;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.5s ease;
}

#wrf-grid line, #wrf-grid rect {
  stroke: rgba(100, 200, 255, 0.35);
  stroke-width: 1;
  fill: none;
}

/* Domain border (outer box) */
#wrf-grid .domain-border {
  stroke: rgba(100, 200, 255, 0.7);
  stroke-width: 2;
  stroke-dasharray: 6 3;
}

/* ── TEXT BOXES (card layout) ── */
.text-box {
  /* Fixed to the centre of the VISIBLE area — the navbar owns the top 64px, so
     centring on the raw viewport pushed tall cards up behind it on short
     screens and clipped their titles. */
  position: fixed;
  top: calc(50% + 32px);
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 20;
  will-change: opacity, transform;  /* GPU layer — prevents repaint on every frame */

  /* Split layout: image left | content right */
  display: grid;
  grid-template-columns: 42% 58%;

  width: min(90vw, 1100px);
  min-height: min(62vh, 560px);

  background: rgba(6, 14, 34, 0.88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-radius: 14px;
  overflow: hidden; /* clips card-image to border-radius */
  color: #fff;

  opacity: 0;
  pointer-events: none;

  /* Nested WRF domain rings (box-shadow survives overflow:hidden) */
  box-shadow:
    0 0 0 1px  rgba(77, 184, 255, 0.25),   /* card edge */
    0 0 0 13px rgba(77, 184, 255, 0.07),   /* D+1 ring  */
    0 0 0 26px rgba(77, 184, 255, 0.03),   /* D+2 ring  */
    0 24px 64px rgba(0, 0, 0, 0.55);       /* depth shadow */
}

/* ── Card image panel ── */
.card-image {
  background-size: cover;
  background-position: center;
  position: relative;
  min-height: 340px;
}

/* Blue-teal color overlay — forces site palette over any photo */
.card-image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    145deg,
    rgba(2, 20, 55, 0.72) 0%,
    rgba(8, 45, 90, 0.45) 50%,
    rgba(4, 30, 65, 0.25) 100%
  );
}

/* Thin separator line between image and content */
.card-image::before {
  content: '';
  position: absolute;
  top: 0; right: 0;
  width: 1px; height: 100%;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(77, 184, 255, 0.30) 30%,
    rgba(77, 184, 255, 0.30) 70%,
    transparent
  );
  z-index: 1;
}

/* ── Card text content panel ── */
.card-content {
  padding: 2.8rem 3rem 2.8rem 2.8rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
}

/* #box-dataviz (Estudo de Caso e Ferramentas) tinha mais conteúdo que os
   outros cards .text-box (título + corpo + botão + os 3 links de caso) e,
   sem altura própria, crescia além do min-height padrão de 560px — ficando
   visivelmente maior que "Sobre Nós"/"Terreno"/etc. Pedido do fundador
   (19/08): "por enquanto vamos só colocar o card do tamanho padrão dos
   outros cards acima". max-height trava no mesmo teto que os outros já
   respeitam (min(62vh,560px) da regra base); overflow-y:auto no conteúdo
   deixa o excesso rolar dentro do card em vez de estourar a caixa — solução
   de interim, não o redesenho fino que este card ainda vai precisar.
   Largura (19/08, achado seguinte): #box-dataviz ficou na .text-box base
   (min(90vw,1100px)) enquanto os vizinhos de verdade agora — Aplicações e
   Nossa Equipe, desde a reordenação — usam .products-box/.team-box
   (min(98vw,1300px)). Mesma largura dos dois. */
#box-dataviz { max-height: min(62vh, 560px); width: min(98vw, 1300px); }
#box-dataviz .card-content { overflow-y: auto; }

/* Domain label – sits above the title */
.domain-label {
  display: inline-block;
  margin-bottom: 0.8rem;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: rgba(77, 184, 255, 0.70);
  text-transform: uppercase;
  pointer-events: none;
}

.card-content h2 {
  font-size: 2rem;
  font-weight: 700;
  color: #4db8ff;
  margin-bottom: 1.2rem;
  letter-spacing: 0.02em;
  line-height: 1.2;
}

.card-content p, .card-content li {
  font-size: 1rem;
  line-height: 1.85;
  color: rgba(255, 255, 255, 0.82);
}

.card-content ul {
  padding-left: 1.4rem;
}

.card-content li {
  margin-bottom: 0.55rem;
}

.cta-btn {
  display: inline-block;
  margin-top: 1.2rem;
  padding: 0.6rem 1.4rem;
  background: #4db8ff;
  color: #0d1117;
  border-radius: 6px;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  pointer-events: all;
  transition: background 0.2s;
}

.cta-btn:hover { background: #7acfff; }

/* ── Yellow CTA variant (used on Case Study & Tools card) ── */
.cta-btn.cta-yellow {
  background: #F5C200;
  color: #0a1428;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.cta-btn.cta-yellow:hover { background: #ffd32a; }
.cta-btn.cta-yellow svg { width: 15px; height: 15px; flex-shrink: 0; }

/* ── Secondary CTA — yellow, same palette as primary yellow button ── */
.cta-btn-secondary {
  display: inline-block;
  margin-top: 0.8rem;
  padding: 0.5rem 1.2rem;
  background: #F5C200;
  color: #0a1428;
  border-radius: 6px;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.85rem;
  pointer-events: all;
  transition: background 0.2s;
}
.cta-btn-secondary:hover { background: #ffd32a; }

/* ── Case study sub-section inside card ── */
.case-study-block {
  margin-top: 1.4rem;
  padding-top: 1.2rem;
  border-top: 1px solid rgba(77,184,255,0.12);
}
.case-study-block p {
  font-size: 0.88rem;
  line-height: 1.70;
  color: rgba(255,255,255,0.60);
  margin-bottom: 0;
}


/* ── DARK OVERLAY ── */
#dark-overlay {
  position: fixed;
  inset: 0;
  background: #050c1a;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s;
}

/* ── AWARDS SECTION – String of Lights ── */
.awards-section {
  position: relative;
  z-index: 15;
}

.awards-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

#awards-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

#awards-hitboxes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.awards-hitbox {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  cursor: pointer;
}

.awards-hitbox.visible {
  pointer-events: all;
}

.awards-heading {
  position: absolute;
  top: 5rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: 1.55rem;
  font-weight: 700;
  color: #4db8ff;
  letter-spacing: 0.03em;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.8s ease;
  white-space: nowrap;
  text-align: center;
  z-index: 2;
}

.awards-heading.visible { opacity: 1; }

#awards-panel {
  position: absolute;
  top: 55%;           /* overridden by JS to sit just below rope */
  left: 50%;
  transform: translateX(-50%);
  width: min(90vw, 820px);
  z-index: 3;
  background: rgba(5, 13, 36, 0.95);
  border: 1px solid rgba(77,184,255,0.20);
  border-radius: 14px;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height 0.45s cubic-bezier(0.22,1,0.36,1), opacity 0.35s ease;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

#awards-panel.is-visible {
  max-height: 340px;
  opacity: 1;
}

#awards-panel-inner {
  padding: 1.4rem 2.2rem 1.8rem;
}

.awards-panel-date {
  font-size: 0.82rem;
  font-weight: 700;
  color: #F5C200;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.awards-trl {
  font-size: 0.72rem;
  font-weight: 600;
  color: #4db8ff;
  background: rgba(77,184,255,0.10);
  border: 1px solid rgba(77,184,255,0.28);
  border-radius: 4px;
  padding: 0.15rem 0.5rem;
  letter-spacing: 0.06em;
}

.awards-panel-items {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.42rem;
}

.awards-panel-items li {
  font-size: 0.88rem;
  color: rgba(185, 215, 255, 0.88);
  line-height: 1.55;
  padding-left: 1.1rem;
  position: relative;
}

.awards-panel-items li::before {
  content: '·';
  position: absolute;
  left: 0;
  color: #F5C200;
  font-weight: 700;
}

/* ── NOSSO COMPROMISSO ── */
.commitment-section {
  position: relative;
  z-index: 15;
  background-color: #5a8fc2;
  background-image: linear-gradient(180deg, #0d2847 0%, #3d6fa8 20%, #5a8fc2 55%);
  background-size: 100% 100vh;
  background-attachment: fixed;
  padding: 5rem 2rem 6rem;
  pointer-events: all;
}

.commitment-content {
  max-width: 960px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.2rem;
  text-align: center;
}

.commitment-content h2 {
  font-size: 1.75rem;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.02em;
  margin-bottom: 0.4rem;
  text-shadow: 0 1px 4px rgba(0,0,0,0.35);
}

.commitment-headline {
  font-size: 1.12rem;
  font-weight: 600;
  color: #ffd66b;
  line-height: 1.45;
  max-width: 720px;
  text-shadow: 0 1px 4px rgba(0,0,0,0.35);
}

.commitment-ods-text {
  font-size: 0.92rem;
  color: rgba(255,255,255,0.78);
  line-height: 1.65;
  max-width: 620px;
  text-shadow: 0 1px 4px rgba(0,0,0,0.35);
}

.commitment-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  width: 100%;
  max-width: 820px;
  margin-top: 2rem;
}

.commitment-tile {
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  background: #ffffff;
  border: 1px solid rgba(77,184,255,0.22);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Sem transition e sem :hover desde 13/08 — pedido do fundador: "na parte de
     Nosso Compromisso não precisa deixar animado os cards de ODS". Os selos da
     ONU são um selo: eles não são clicáveis nem levam a lugar nenhum, e um
     card que cresce sob o mouse promete uma ação que não existe. */
}

.commitment-tile img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 0.3rem;
}

.commitment-tile--logo {
  background: #ffffff;
}

.commitment-tile--logo img {
  padding: 1rem;
}

@media (max-width: 600px) {
  .commitment-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── PARTNERS / ECOSSISTEMA ── */
.partners-section {
  position: relative;
  z-index: 15;
  background-color: #5a8fc2;
  background-image: linear-gradient(180deg, #0d2847 0%, #3d6fa8 20%, #5a8fc2 55%);
  background-size: 100% 100vh;
  background-attachment: fixed;
  padding: 3rem 2rem 4rem;
  pointer-events: all;
  border-top: 1px solid rgba(77, 184, 255, 0.18);
}

.partners-content {
  max-width: 800px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
  /* Pedido do fundador (15/08): "um fundo levemente mais escuro nesta parte
     em especial só para aparecer melhor os logos" — o azul médio da cena por
     trás é claro o bastante pra competir com os próprios logos (vários já
     vêm em caixa branca). Um painel translúcido escuro só aqui, sem mexer no
     gradiente do resto da página. */
  padding: 2rem 2.5rem;
  background: rgba(5, 12, 28, 0.28);
  border-radius: 16px;
}

.partners-group {
  text-align: center;
}

.partners-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: rgba(190, 220, 255, 0.85);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 1.2rem;
}

.partners-logos {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  flex-wrap: wrap;
}

.partner-logo {
  height: 56px;
  width: auto;
  max-width: 175px;
  object-fit: contain;
  filter: none;
  opacity: 1;
  border: 1px solid rgba(20,60,110,0.10);
  box-shadow: 0 2px 8px rgba(20,40,70,0.06);
  border-radius: 6px;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

.partner-logo:hover {
  border-color: rgba(77, 184, 255, 0.35);
}

@media (max-width: 600px) {
  .partners-logos { gap: 1.5rem; }
  .partner-logo { height: 38px; max-width: 120px; }
  .partners-section { padding: 2rem 1rem 3rem; }
}

/* ── MAP STYLE TOGGLE ── */
#map-toggle {
  position: fixed;
  bottom: 1.4rem;
  right: 1.4rem;
  z-index: 500;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.85rem 0.45rem 0.65rem;
  background: rgba(6, 14, 34, 0.72);
  border: 1px solid rgba(77, 184, 255, 0.28);
  border-radius: 999px;
  color: rgba(160, 200, 245, 0.88);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
#map-toggle:hover {
  background: rgba(10, 25, 65, 0.88);
  border-color: rgba(77, 184, 255, 0.55);
  color: #fff;
}
#map-toggle svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* ── FIND US SECTION ── */
.contacts-section {
  position: relative;
  z-index: 15;
  background-color: #5a8fc2;
  background-image: linear-gradient(180deg, #0d2847 0%, #3d6fa8 20%, #5a8fc2 55%);
  background-size: 100% 100vh;
  background-attachment: fixed;
  padding: 5rem 2rem 6rem;
  pointer-events: all;
}

.findus-content {
  max-width: 960px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.4rem;
  text-align: center;
}

.findus-content h2 {
  font-size: 1.75rem;
  font-weight: 700;
  color: #4db8ff;
  letter-spacing: 0.02em;
}

.findus-event-card {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.4rem;
  align-items: center;
}

.findus-map {
  height: 340px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(77,184,255,0.22);
}

.findus-info {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.findus-event-name {
  font-size: 1.55rem;
  font-weight: 700;
  color: #F5C200;
  letter-spacing: 0.01em;
}

.findus-event-text {
  font-size: 1rem;
  color: rgba(185, 215, 255, 0.85);
  line-height: 1.7;
}

.findus-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.findus-badge {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  border: 1px solid rgba(77,184,255,0.30);
  color: rgba(185,215,255,0.88);
  background: rgba(77,184,255,0.08);
}

.findus-badge--yellow {
  border-color: rgba(245,194,0,0.35);
  color: #F5C200;
  background: rgba(245,194,0,0.08);
}

.findus-marker {
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 768px) {
  .findus-event-card { grid-template-columns: 1fr; }
  .findus-map { height: 240px; }
  .findus-info { text-align: center; }
  .findus-badges { justify-content: center; }
}

/* Grid de cards da equipe */
.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 2rem;
}

/* Card individual */
.team-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 2rem 1.5rem 1.8rem;
  background: rgba(10, 25, 60, 0.60);
  border: 1px solid rgba(77, 184, 255, 0.15);
  border-radius: 16px;
  transition: border-color 0.25s, transform 0.25s;
}

.team-card:hover {
  border-color: rgba(77, 184, 255, 0.40);
  transform: translateY(-4px);
}

/* Avatar circular */
.team-avatar {
  position: relative;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(77, 184, 255, 0.40);
  background: rgba(8, 25, 65, 0.9);
  margin-bottom: 1.2rem;
  flex-shrink: 0;
}

.team-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Iniciais — visíveis quando a foto não carrega */
.team-avatar .initials {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  font-weight: 700;
  color: rgba(77, 184, 255, 0.60);
  letter-spacing: 0.05em;
}

/* Nome e cargo */
.member-name {
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  margin-bottom: 0.3rem;
}

.member-role {
  font-size: 0.8rem;
  color: rgba(77, 184, 255, 0.65);
  letter-spacing: 0.04em;
  margin-bottom: 1.4rem;
}

/* Links de contato (ícones) */
.member-links {
  display: flex;
  gap: 0.9rem;
  margin-top: auto;
}

.member-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: rgba(77, 184, 255, 0.08);
  border: 1px solid rgba(77, 184, 255, 0.20);
  color: rgba(77, 184, 255, 0.70);
  text-decoration: none;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
  pointer-events: all;
}

.member-link:hover {
  background: rgba(77, 184, 255, 0.18);
  color: #4db8ff;
  border-color: rgba(77, 184, 255, 0.45);
}

.member-link svg {
  width: 16px;
  height: 16px;
}

/* ══════════════════════════════════════════════════════
   WHY CHOOSE US — comparison table card
══════════════════════════════════════════════════════ */

/*
 * Larger card; override standard 42/58 split; disable backdrop-filter
 * (cells have opaque bg so blur is unnecessary and expensive during animation)
 */
.why-box {
  /* Denser than any other card, and the camera passes over bright terrain here:
     at the shared 0.70 opacity the charts and figures washed out. */
  background: rgba(0, 0, 0, 0.88);
  grid-template-columns: 1fr;
  width: min(98vw, 1300px);
  min-height: 0;
  padding: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.why-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
}

/* Title styled like card-content h2 */
.why-title {
  font-size: 1.55rem;
  font-weight: 700;
  color: #4db8ff;
  letter-spacing: 0.02em;
  line-height: 1.2;
  padding: 1.4rem 2.2rem 0.5rem;
  flex-shrink: 0;
}

/* Os dois numeros conviviam sem rotulo e o leitor perguntava "afinal, 92% ou
   50%?". A ponte responde antes de a duvida nascer. */
.why-bridge {
  margin: 0;
  padding: 0 2.2rem 1.1rem;
  font-size: 0.92rem;
  line-height: 1.45;
  color: rgba(214, 232, 255, 0.80);
  border-bottom: 1px solid rgba(77,184,255,0.15);
  flex-shrink: 0;
}

/* ── Rotulo de regime, um por ato ── */
.why-regime {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 0.55rem;
  margin: 0;
  padding: 0.9rem 2.2rem 0;
}

.why-regime-when {
  font-size: 0.95rem;
  font-weight: 700;
  color: #122845;
  letter-spacing: 0.01em;
}

.why-regime-claim {
  font-size: 0.88rem;
  color: rgba(18, 40, 69, 0.82);
}

.why-regime-claim::before,
.why-regime-tie::before {
  content: '— ';
  color: rgba(18, 40, 69, 0.45);
}

.why-regime-tie {
  font-size: 0.78rem;
  font-style: italic;
  color: rgba(18, 40, 69, 0.62);
}

/*
 * CSS Grid: ROW-MAJOR source order  (label | mkt | us) × 6 rows
 * Column order = labels | Mercado Atual | Nossa Solução
 */
.why-table {
  display: grid;
  grid-template-columns: 22% 39% 39%;
  isolation: isolate;   /* new stacking context → stops children from leaking into parent blur */
}

/* ── Base cell ── */
.wt-cell {
  display: flex;
  align-items: center;
  padding: 0.80rem 1.15rem;
  font-size: 0.83rem;
  line-height: 1.50;
  border-bottom: 1px solid rgba(77,184,255,0.07);
}

/* ── Column 1 — labels (centred, no colon) ── */
.wt-label {
  background: rgba(4, 20, 58, 0.90);
  color: rgba(155, 200, 255, 0.72);
  font-weight: 600;
  font-size: 0.77rem;
  text-align: center;
  justify-content: center;
}

/* ── Column 2 — Mercado Atual (medium navy) ── */
.wt-mkt {
  background: rgba(7, 35, 90, 0.82);
  color: rgba(185, 215, 255, 0.78);
  border-bottom: 1px solid rgba(60,110,200,0.10);
}

/* ── Column 3 — Nossa Solução (deep navy, Metenergy yellow text) ── */
.wt-us {
  background: rgba(2, 10, 38, 0.98);
  color: #F5C200;
  border-bottom: 1px solid rgba(77,184,255,0.10);
}

/* ── Header row ── */
.wt-head {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  justify-content: center;
  text-align: center;
  min-height: 44px;
  padding: 0.60rem 0.7rem;
}

.wt-label.wt-head { color: transparent;           background: rgba(3,15,45,0.85); }
.wt-mkt.wt-head   { color: rgba(140,190,255,0.88); background: rgba(5,28,75,0.92); border-bottom: 1px solid rgba(60,120,220,0.22); }
.wt-us.wt-head    { color: #F5C200;               background: rgba(2,8,32,1);     border-bottom: 1.5px solid rgba(245,194,0,0.30); }

/* ── Resolution rows ── */
.wt-res     { justify-content: center; text-align: center; font-size: 0.88rem; font-weight: 600; }
.wt-mkt.wt-res { color: rgba(150,195,255,0.82); }
.wt-us.wt-res  { color: #F5C200; }

/* ── Last row: big KM + image overlay ── */
.wt-res-big {
  font-size: 1.60rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0;
  min-height: 155px;
  position: relative;
  overflow: hidden;
}

.km-text {
  position: relative;
  z-index: 1;
  /* JS drives opacity to cross-fade text → image */
}

.wt-fig {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;          /* JS drives opacity */
  z-index: 2;
  pointer-events: none;
}

.wt-mkt.wt-res-big { color: rgba(150,200,255,0.85); }
.wt-us.wt-res-big  { color: #F5C200; }


/* ══════════════════════════════════════════════════════
   PRODUCTS — 3-card hover layout
══════════════════════════════════════════════════════ */

.products-box {
  grid-template-columns: 1fr;
  width: min(98vw, 1300px);
  min-height: 0;
  padding: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.products-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.products-kicker {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #F5C200;
  padding: 1.6rem 2.2rem 0;
  flex-shrink: 0;
}

.products-title {
  font-size: 1.7rem;
  font-weight: 800;
  color: #4db8ff;
  letter-spacing: 0.01em;
  line-height: 1.2;
  padding: 0.5rem 2.2rem 1.1rem;
  border-bottom: 1px solid rgba(77,184,255,0.15);
  flex-shrink: 0;
}

.prod-grid {
  display: flex;
  gap: 1.6rem;
  padding: 2rem 2.2rem 2.4rem;
  pointer-events: all;
}

.prod-card {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid rgba(77,184,255,0.18);
  border-radius: 18px;
  min-height: 340px;
  background-color: rgba(255,255,255,0.025);
  background-size: cover;
  background-position: center;
  cursor: default;
  transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
  pointer-events: all;
}

.prod-card:hover {
  transform: translateY(-4px);
  border-color: rgba(77,184,255,0.45);
  box-shadow: 0 14px 30px rgba(0,0,0,0.35), 0 0 0 1px rgba(77,184,255,0.12);
}

/* ── Card 3: fundo dividido na diagonal (solar + plantação) ── */
.prod-card-split-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
}

.prod-card-split-b {
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.prod-card-body-panel {
  position: relative;
  margin-top: auto;
  padding: 1.7rem 1.6rem 1.8rem;
  background: linear-gradient(180deg, transparent, rgba(6,9,14,0.55) 30%, rgba(6,9,14,0.94) 75%);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.prod-card-title {
  font-size: 1.18rem;
  font-weight: 700;
  color: #fff;
  line-height: 1.3;
  text-shadow: 0 1px 8px rgba(0,0,0,0.5);
}

.prod-card-body {
  font-size: 0.93rem;
  line-height: 1.65;
  color: rgba(255,255,255,0.86);
}

@media (max-width: 900px) {
  .products-box { width: 98vw; }
  .prod-grid    { flex-direction: column; padding: 1.4rem 1.6rem 1.8rem; gap: 1.2rem; }
}

/* ── CTA intermediario, no fim da prova ── */
.why-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  padding: 0 2.2rem 1.4rem;
}

.why-cta-text {
  font-size: 0.88rem;
  color: rgba(214, 232, 255, 0.85);
}

.why-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 1.1rem;
  border: none;
  border-radius: 999px;
  background: #f5c200;
  color: #0b1220;
  font-size: 0.84rem;
  font-weight: 700;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: filter 0.2s ease;
}

.why-cta-btn:hover { filter: brightness(1.08); }

/* Pedido do fundador (14/08): os cards de conteúdo (Por que nós, Produtos,
   Estudo de Caso, Equipe, Contatos) voltam para o azul-marinho da navbar —
   só o FUNDO da página (grid) e a cena continuam claros. O bloco que clareava
   .why-box/.why-title/.why-bridge/.why-cta-text/.wf-*/.ws-* (13-14/08) foi
   removido; as regras-base logo abaixo, no tema escuro original, voltam a
   valer sozinhas. */

/* O card da prova e o mais alto do site e cresce com o CTA no fim. Num laptop
   de 768 px de altura ele encostava na navbar em cima e cortava o CTA embaixo —
   exatamente a linha que o card existe para justificar. Os mapas ja escalam com
   a altura (min(600px, 60vh)); o que sobra e respiro vertical de texto. */
@media (min-width: 901px) and (max-height: 850px) {
  .why-title  { font-size: 1.3rem; padding: 0.85rem 2.2rem 0.3rem; }
  .why-bridge { font-size: 0.85rem; padding: 0 2.2rem 0.7rem; }
  .why-regime { padding: 0.6rem 2.2rem 0; }
  .wf-head    { padding: 0.7rem 2.2rem 0.4rem; }
  .why-strip  { padding: 0.6rem 2.2rem 0.7rem; }
  .why-cta    { padding: 0 2.2rem 0.85rem; }
  .why-dots   { padding: 0.4rem 2.2rem 0.1rem; }
}

/* ── Citation ── */
.why-citation {
  padding: 0.50rem 1.4rem;
  font-size: 0.54rem;
  color: rgba(255,255,255,0.28);
  line-height: 1.5;
  border-top: 1px solid rgba(77,184,255,0.08);
  text-align: center;
}
.why-citation em { font-style: italic; }

/* ── Responsive ── */
@media (max-width: 900px) {
  /* max-height: 82vh + overflow-y: auto sobrou da epoca em que a Why era uma
     tabela: no telefone ela virava uma janelinha rolavel DENTRO da pagina, e o
     regime do extremo (92,2% x 46,8%) ficava fora da vista de quem so rola a
     pagina. Em tela estreita a pagina e um documento — o card cresce. */
  .why-box   { width: 98vw; }
  .why-table { grid-template-columns: 25% 37.5% 37.5%; }
  .wt-cell   { font-size: 0.73rem; padding: 0.65rem 0.80rem; }
  .wt-res-big { min-height: 110px; font-size: 1.2rem; }
  .why-title  { font-size: 1.25rem; padding: 1rem 1.4rem 0.4rem; }
  .why-bridge { font-size: 0.86rem; padding: 0 1.4rem 0.9rem; }
  .why-regime { padding: 0.9rem 1.4rem 0; }
  .why-cta    { padding: 0 1.4rem 1.4rem; }
}

/* ══════════════════════════════════════════════════════
   OUR TEAM — circular profiles + expandable details panel
══════════════════════════════════════════════════════ */

.team-box {
  grid-template-columns: 1fr;
  width: min(98vw, 1300px);
  min-height: 0;
  padding: 0;
}

.team-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.team-section-title {
  font-size: 1.55rem;
  font-weight: 700;
  color: #4db8ff;
  letter-spacing: 0.02em;
  line-height: 1.2;
  padding: 1.4rem 2.2rem 1.1rem;
  border-bottom: 1px solid rgba(77,184,255,0.15);
  flex-shrink: 0;
}

.team-profiles {
  display: flex;
  justify-content: space-around;
  padding: 2rem 2.4rem 1.6rem;
  gap: 1rem;
  pointer-events: all;
}

.team-profile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  flex: 1;
  max-width: 170px;
  cursor: default;
}

/* ── Role badge above avatar ── */
.team-role-badge {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #F5C200;
  text-transform: uppercase;
  text-align: center;
  min-height: 1.1em; /* keeps alignment even if empty */
}

/* ── Circular avatar ── */
.team-avatar-circle {
  width: 173px;
  height: 173px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(77,184,255,0.28);
  background: rgba(8,25,65,0.90);
  transition: border-color 0.28s ease, box-shadow 0.28s ease;
  flex-shrink: 0;
}

.team-avatar-circle img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.team-profile.is-active .team-avatar-circle,
.team-profile:hover .team-avatar-circle {
  border-color: #F5C200;
  box-shadow: 0 0 0 3px rgba(245,194,0,0.18);
}

/* ── Name + LinkedIn row ── */
.team-profile-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
}

.team-member-name {
  font-size: 1.45rem;
  font-weight: 600;
  color: rgba(255,255,255,0.88);
  text-align: center;
  line-height: 1.3;
}

.team-linkedin-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: rgba(77,184,255,0.08);
  border: 1px solid rgba(77,184,255,0.22);
  color: rgba(77,184,255,0.68);
  text-decoration: none;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
  pointer-events: all;
}

.team-linkedin-btn:hover {
  background: rgba(77,184,255,0.18);
  color: #4db8ff;
  border-color: rgba(77,184,255,0.50);
}

.team-linkedin-btn svg { width: 13px; height: 13px; }

/* ── Expandable details panel — slides down on hover, stays open ── */
.team-details-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.45s cubic-bezier(0.22,1,0.36,1),
              border-top-color 0.3s ease;
  border-top: 1px solid transparent;
}

.team-details-panel.is-open {
  /* Pedido do fundador (15/08): currículo "bem mais rico" — três parágrafos
     por pessoa não cabem nos 240px antigos (pensados para uma linha de
     credenciais curtas). max-height alto o bastante para a maioria das telas
     e overflow-y:auto no conteúdo cobre o resto sem cortar texto. */
  max-height: min(70vh, 640px);
  border-top-color: rgba(77,184,255,0.15);
}

.team-details-content {
  padding: 1.1rem 2.4rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  overflow-y: auto;
  max-height: min(70vh, 640px);
}

.team-specialty {
  font-size: 1.09rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #F5C200;
  text-transform: uppercase;
}

.team-bio {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.8rem;
}

.team-bio-line {
  /* Pedido do fundador (15/08): "diminua um pouco o tamanho da fonte" —
     era 1.41rem, pensado só para credenciais de uma linha. */
  font-size: 1.05rem;
  color: rgba(185,215,255,0.80);
  white-space: nowrap;
}

/* ── Currículo rico (15/08): três seções por pessoa em vez de credenciais
   soltas — Formação acadêmica / Experiência profissional / Papel na
   Metenergy, cada uma com título curto e um parágrafo. */
.team-bio-section {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  max-width: 880px;
}
.team-bio-section-title {
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #4db8ff;
}
.team-bio-section-text {
  font-size: 0.92rem;
  line-height: 1.55;
  color: rgba(210,228,255,0.86);
}

@media (max-width: 900px) {
  .team-box      { width: 98vw; }
  .team-profiles { flex-wrap: wrap; justify-content: center; padding: 1.6rem 1.4rem 1.2rem; }
  .team-profile  { max-width: 180px; }
  .team-avatar-circle { width: 120px; height: 120px; }
  .team-role-badge { font-size: 0.72rem; }
  .team-member-name { font-size: 1rem; }
  .team-bio-line { font-size: 1rem; white-space: normal; }
}

/* ══════════════════════════════════════════════════════
   SCROLL HINT (appears after language selection)
══════════════════════════════════════════════════════ */
/* A pílula do canto é a forma LEGADA (?legacy=1 e telas estreitas). Dentro da
   cena ela vira outra coisa — ver "A dica de rolagem DENTRO da cena" lá em
   cima, onde o mesmo elemento é redesenhado como um V grande e centrado. */
#scroll-hint {
  position: fixed;
  bottom: 4.4rem;
  right: 1.4rem;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4rem 0.45rem 0.3rem;
  border-radius: 16px;
  color: rgba(245, 194, 0, 0.78);
  font-size: 0.52rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  background: rgba(3, 8, 22, 0.45);
  border: 1px solid rgba(245, 194, 0, 0.22);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.22);
  opacity: 0.8;
  pointer-events: none;
  transition: opacity 0.5s ease;
}
#scroll-hint [data-i18n="scroll_hint"] {
  display: block;
  max-width: min-content;
  white-space: normal;
  word-break: normal;
  overflow-wrap: normal;
}

/* Hide during splash */
#splash:not(.fade-out) ~ #scroll-hint { opacity: 0; }
/* Hide when JS flags end of page */
#scroll-hint.at-end { opacity: 0; }

#scroll-hint svg {
  width: 14px;
  height: 14px;
  animation: scroll-hint-bounce 1.8s ease-in-out infinite;
}

@keyframes scroll-hint-bounce {
  0%, 100% { transform: translateY(0);   opacity: 0.65; }
  50%      { transform: translateY(4px); opacity: 1; }
}

@media (max-width: 600px) {
  #scroll-hint {
    bottom: 4rem;
    right: 0.7rem;
    font-size: 0.5rem;
    letter-spacing: 0.1em;
    padding: 0.35rem 0.4rem 0.28rem;
  }
  #scroll-hint svg { width: 12px; height: 12px; }
}

/* ══════════════════════════════════════════════════════
   NEXT SECTION CONTROL (seta "próxima seção", pedido do fundador 11/08)
   Contorno apenas — sem preenchimento, sem o amarelo de marca. É uma
   affordance discreta para quem não quer rolar, não um CTA; por isso a cor
   é a mesma cinza-azulada apagada que os rótulos de borda dos atos usam
   (#eaf3ff em baixa opacidade), nunca #F5C200/#ffd34d. Mesmo canto que
   #scroll-hint ocupava — os dois nunca aparecem juntos (ver regras de
   esconder #scroll-hint acima). */
.next-section-btn {
  position: fixed;
  bottom: 1.6rem;
  right: 1.4rem;
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.9rem 0.5rem 1rem;
  border-radius: 999px;
  background: rgba(3, 8, 22, 0.5);
  border: 1px solid rgba(234, 243, 255, 0.28);
  color: rgba(234, 243, 255, 0.8);
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-align: right;
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.22);
  cursor: pointer;
  transition: opacity 0.35s ease, border-color 0.2s ease, transform 0.15s ease;
}
.next-section-btn:hover  { border-color: rgba(234, 243, 255, 0.5); transform: translateY(-1px); }
.next-section-btn:focus-visible { outline: 2px solid rgba(234, 243, 255, 0.6); outline-offset: 2px; }
.next-section-label { max-width: 40vw; }
.next-section-btn svg { width: 15px; height: 15px; flex: none; }

/* Some sozinho na última seção (js/main.js liga/tira esta classe — um
   botão prometendo "próxima" que não leva a lugar nenhum é pior que
   nenhum botão). */
.next-section-btn.is-hidden { opacity: 0; pointer-events: none; }

@media (max-width: 600px) {
  .next-section-btn {
    bottom: 1rem;
    right: 0.7rem;
    font-size: 0.6rem;
    padding: 0.4rem 0.7rem 0.4rem 0.8rem;
  }
  .next-section-label { max-width: 46vw; }
  .next-section-btn svg { width: 13px; height: 13px; }
}

/* ── TOP GRADIENT (helps navbar readability) ── */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 120px;
  background: linear-gradient(to bottom, rgba(10,20,40,0.6) 0%, transparent 100%);
  z-index: 5;
  pointer-events: none;
}

/* ── RESPONSIVE ── */
@media (max-width: 900px) {
  #nav-links {
    gap: 1rem;
  }

  #nav-links a {
    font-size: 0.75rem;
  }
}

@media (max-width: 768px) {
  #logo {
    height: 32px;
  }

  .stage {
    justify-content: center;
    padding: 64px 1rem 1rem;
  }

  /* Stack card vertically on mobile: image on top, text below */
  .text-box {
    grid-template-columns: 1fr;
    grid-template-rows: 200px 1fr;
    width: 94vw;
    min-height: unset;
  }

  .card-image {
    min-height: unset;
  }

  /* Hide the vertical separator on mobile */
  .card-image::before { display: none; }

  .card-content {
    padding: 1.8rem 1.8rem;
  }

  .card-content h2 {
    font-size: 1.5rem;
  }

  .team-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .about-mini-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  #nav-links {
    display: none;
  }

  .team-grid {
    grid-template-columns: 1fr;
  }

  /* Splash: full-width UI panel on small screens */
  #splash-ui {
    width: 100%;
    background: rgba(3, 8, 22, 0.88);
    padding: 3rem 2rem;
  }
}

@media (max-width: 600px) {
  #splash-ui {
    width: 100%;
    min-width: unset;
  }
}

/* ══════════════════════════════════════════════════════════
   REDUCED MOTION
   The whole homepage is a scroll-driven camera move, which is exactly the
   pattern that triggers motion sickness. Under this query the narrative still
   works — the rain field and legend remain fully legible — but the parallax,
   the vignette and every non-essential transition are gone.
   ══════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  #rain-canvas,
  #res-legend,
  #wrf-grid,
  .text-box {
    transition-duration: 0.01ms !important;
  }

  .text-box {
    /* Parallax recede is disabled in JS; neutralise any residual blur here. */
    filter: none !important;
  }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ══════════════════════════════════════════════════════════
   WHY — EVENT COMPARISON
   Replaces the old 4-row table and the borrowed Andes figures with the
   company's own event: the same storm, the same region, seen through a 25 km
   product and through the 900 m model.
   ══════════════════════════════════════════════════════════ */

.why-cmp {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)) minmax(0, 0.92fr) auto;
  gap: 1.15rem;
  padding: 1.1rem 2.2rem 0.4rem;
  align-items: start;
}

.wc-panel {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  min-width: 0;
  width: min(100%, 32vh);
  margin-inline: auto;
}

.wc-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.wc-name {
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: #122845;
  white-space: nowrap;
}

.wc-panel-us .wc-name { color: #122845; }

.wc-res {
  font-size: 0.7rem;
  font-weight: 600;
  color: rgba(18, 40, 69, 0.65);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Square frame — the domain is 2°x2°, so the canvas must not be stretched.
   The 1:1 ratio means the width cap doubles as a height cap, which is what
   keeps this card inside short laptop viewports. */
.wc-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  overflow: hidden;
  background: #eef2f8;
  border: 1px solid rgba(77, 184, 255, 0.22);
}

.wc-panel-us .wc-frame { border-color: rgba(77, 184, 255, 0.45); }

.wc-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.wc-stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.wc-mm {
  font-size: 0.76rem;
  font-weight: 500;
  color: rgba(18, 40, 69, 0.65);
  font-variant-numeric: tabular-nums;
}

.wc-pct {
  font-size: 1.28rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0.05rem 0.45rem;
  border-radius: 6px;
}

.wc-pct-bad  { color: #ffb3b3; background: rgba(200, 70, 70, 0.20); }
.wc-pct-good { color: #9fe8b6; background: rgba(50, 170, 100, 0.20); }

.wc-detail .wc-frame {
  border-style: dashed;
  border-color: rgba(255, 200, 120, 0.45);
}

.wc-zoom-note {
  font-size: 0.7rem;
  line-height: 1.3;
  color: rgba(18, 40, 69, 0.72);
  text-wrap: pretty;
}

.wc-zoom-note strong {
  font-size: 1.02rem;
  color: #8a5c00;
  font-variant-numeric: tabular-nums;
}

.wc-zoom-note strong { color: #8a5c00; }

.wc-truth {
  margin: 0.1rem 2.2rem 0;
  padding: 0.45rem 0.9rem;
  border-radius: 9px;
  background: #eef2f8;
  border: 1px solid rgba(20,60,110,0.10);
  font-size: 0.74rem;
  line-height: 1.4;
  color: rgba(18, 40, 69, 0.78);
  text-align: center;
  text-wrap: pretty;
}

.wc-truth strong {
  color: #122845;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

/* ── Compact differentiators ── */
.why-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.7rem;
  padding: 0.9rem 2.2rem 1.4rem;
}

.ws-item {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  padding-left: 0.7rem;
  border-left: 2px solid rgba(77, 184, 255, 0.28);
  min-width: 0;
}

.ws-label {
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(150, 190, 225, 0.7);
}

.ws-mkt {
  font-size: 0.7rem;
  color: rgba(190, 200, 215, 0.55);
  text-decoration: line-through;
  text-decoration-color: rgba(190, 200, 215, 0.3);
  text-wrap: pretty;
}

.ws-us {
  font-size: 0.76rem;
  font-weight: 600;
  color: #ffd66b;
  text-wrap: pretty;
}

/* ── Why: two acts (past event → 48 h ahead) ── */
/* Both acts occupy the same grid cell so the card does not jump height when
   the scroll crosses from one to the other. */
.why-acts {
  display: grid;
}

.why-act {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.5s ease, transform 0.5s ease, visibility 0.5s;
}

.why-act--on {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.why-dots {
  display: flex;
  gap: 1.1rem;
  justify-content: center;
  padding: 0.55rem 2.2rem 0.2rem;
}

.wd-dot {
  position: relative;
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(150, 190, 225, 0.42);
  padding-left: 0.85rem;
  transition: color 0.4s ease;
}

.wd-dot::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: rgba(150, 190, 225, 0.3);
  transition: background 0.4s ease, box-shadow 0.4s ease;
}

.wd-dot.wd-on { color: #7fd4ff; }
.wd-dot.wd-on::before {
  background: #7fd4ff;
  box-shadow: 0 0 8px rgba(127, 212, 255, 0.7);
}

/* ── Act 2: 48 h forecast ── */
.wf-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 2.2rem 0.6rem;
  flex-wrap: wrap;
}

.wf-titles { display: flex; flex-direction: column; gap: 0.15rem; }

.wf-title {
  font-size: 1rem;
  font-weight: 700;
  color: #122845;
}

.wf-sub {
  font-size: 0.68rem;
  color: rgba(18, 40, 69, 0.68);
}

.wf-legend { display: flex; gap: 0.9rem; flex-wrap: wrap; }

.wf-key {
  position: relative;
  font-size: 0.66rem;
  color: rgba(18, 40, 69, 0.75);
  padding-left: 1.15rem;
  white-space: nowrap;
}

.wf-key::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 14px;
  height: 0;
  margin-top: -1px;
  border-top-width: 2.5px;
  border-top-style: solid;
}

.wf-key-obs::before { border-top-color: rgba(255, 255, 255, 0.8); }
.wf-key-met::before { border-top-color: #4db8ff; border-top-width: 3px; }
.wf-key-mkt::before { border-top-color: rgba(255, 150, 100, 0.9); border-top-style: dashed; }

/* Main subject: the same wind field as a global model sees it and as we
   resolve it. Portrait frames, because the domain is 0.795 deg lon x 1.094 deg
   lat and the PNGs must not be stretched. Both images share one colour scale —
   verified by reconstructing the colorbar ramp and locating the warmest pixel
   in each: implied full scale 13.6 vs 14.0 m/s, a 3% spread. */
.wf-body {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.5rem;
  padding: 0 2.2rem;
  align-items: start;
}

.wf-maps {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 0.75rem;
  width: min(600px, 60vh);
}

.wf-map {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 0;
}

.wf-map-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
}

.wf-map-name {
  font-size: 0.76rem;
  font-weight: 700;
  color: #122845;
  white-space: nowrap;
}

.wf-map--us .wf-map-name { color: #122845; }

.wf-map-res {
  font-size: 0.64rem;
  font-weight: 600;
  color: rgba(18, 40, 69, 0.65);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.wf-map-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 1090 / 1500;
  border-radius: 9px;
  overflow: hidden;
  background: #eef2f8;
  border: 1px solid rgba(77, 184, 255, 0.22);
}

.wf-map--us .wf-map-frame { border-color: rgba(77, 184, 255, 0.45); }

.wf-map-frame canvas { display: block; width: 100%; height: 100%; }

.wf-map-peak {
  font-size: 0.64rem;
  color: rgba(18, 40, 69, 0.65);
  font-variant-numeric: tabular-nums;
}

.wf-map-peak strong { color: #122845; font-weight: 700; }
.wf-map--us .wf-map-peak strong { color: #122845; }







.wf-side { display: flex; flex-direction: column; gap: 0.5rem; }

.wf-sub-title {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(150, 190, 225, 0.7);
}

.wf-chart {
  position: relative;
  height: min(372px, 38vh);
  border-radius: 10px;
  background: rgba(4, 12, 24, 0.45);
  border: 1px solid rgba(120, 200, 255, 0.14);
  overflow: hidden;
}

#wf-canvas { display: block; width: 100%; height: 100%; }

.wf-metrics-legend {
  display: flex;
  gap: 0.9rem;
  padding-top: 0.6rem;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: rgba(231, 241, 255, 0.75);
}
.wf-metrics-legend-item { display: inline-flex; align-items: center; gap: 0.3rem; }
.wf-metrics-legend-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.wf-metrics-legend-dot--good { background: #9fe8b6; }
.wf-metrics-legend-dot--bad  { background: rgba(255, 170, 140, 0.9); }
.wf-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.7rem;
  padding: 0.7rem 0 0.2rem;
}

.wf-metric {
  display: flex;
  flex-direction: column;
  gap: 0.22rem;
  padding-left: 0.7rem;
  border-left: 2px solid rgba(77, 184, 255, 0.28);
  min-width: 0;
}

.wf-m-label {
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(150, 190, 225, 0.7);
}

.wf-m-pair {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-variant-numeric: tabular-nums;
  flex-wrap: wrap;
}

.wf-good { font-size: 0.98rem; font-weight: 700; color: #9fe8b6; }
.wf-bad  { font-size: 0.82rem; color: rgba(255, 170, 140, 0.9); }
.wf-vs   { font-size: 0.62rem; color: rgba(160, 185, 210, 0.55); }

/* Barras (19/08) — mesma ideia de .act-metric-bars, compacta pro grid de 4
   colunas deste card. Verde/salmão porque é a paleta que .wf-good/.wf-bad
   já usavam aqui (diferente do azul/laranja do card do ato — cada
   componente manteve a própria convenção de cor já estabelecida). */
.wf-m-bars { display: flex; flex-direction: column; gap: 0.22rem; }
.wf-m-bar { display: flex; align-items: center; gap: 0.3rem; }
.wf-m-bar-track {
  position: relative;
  flex: 1;
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}
.wf-m-bar-fill { position: absolute; inset: 0 auto 0 0; border-radius: 3px; }
.wf-m-bar--good .wf-m-bar-fill { background: #9fe8b6; }
.wf-m-bar--bad  .wf-m-bar-fill { background: rgba(255, 170, 140, 0.9); }
.wf-m-bar strong {
  min-width: 26px;
  text-align: right;
  font-size: 0.68rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: rgba(231, 241, 255, 0.85);
}

.wf-metric-hero { border-left-color: rgba(255, 214, 107, 0.6); }
.wf-m-hero {
  font-size: 1.45rem;
  font-weight: 700;
  color: #ffd66b;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.wf-note {
  padding: 0.55rem 2.2rem 0;
  font-size: 0.62rem;
  line-height: 1.4;
  color: rgba(165, 195, 220, 0.6);
  text-align: center;
  text-wrap: pretty;
}

/* The percentage is an accuracy figure (comparison.json: accuracy_pct); the
   bare number invited the reader to guess what it measured. */
.wc-acc {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
}

.wc-acc-label {
  font-size: 0.58rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;    /* tracking carries the label instead of weight */
  color: rgba(18, 40, 69, 0.42);
}


/* ══════════════════════════════════════════════════════════
   WHY / ACT 1 — READING KEY
   The panels carried a colour ramp, a white ring and a lattice, none of which
   were explained. A section that argues with numbers has to say what its
   colours mean.
   ══════════════════════════════════════════════════════════ */






/* (6) The conclusion, stated instead of left as arithmetic. */
.wc-takeaway {
  color: #122845;
  font-size: 0.84rem;
  margin-right: 0.35rem;
}


/* ── Vertical colour bar, to the right of the last map ──
   Drawn on a canvas rather than rotated with CSS: the source PNGs are
   horizontal, and a rotated <img> keeps its unrotated layout box, so the
   column width could not follow the map height. The canvas is sized from
   clientWidth/clientHeight like every other canvas here. */
.cbar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  align-self: stretch;
  padding-top: 1.55rem;      /* clear the panel header row */
  font-size: 0.58rem;
  color: rgba(18, 40, 69, 0.72);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cbar-canvas {
  flex: 1 1 auto;
  width: 11px;
  min-height: 40px;
  border-radius: 3px;
}

.cbar-unit {
  color: rgba(18, 40, 69, 0.55);
  letter-spacing: 0.04em;
}

.wc-key-text {
  padding: 0.1rem 2.2rem 0.3rem;
  font-size: 0.62rem;
  color: rgba(18, 40, 69, 0.68);
  text-wrap: pretty;
}

.wf-maps-note {
  grid-column: 1 / 3;
  font-size: 0.6rem;
  color: rgba(18, 40, 69, 0.62);
  text-wrap: pretty;
}

/* ══════════════════════════════════════════════════════════
   CONTACT CTA
   The page made its argument and then dead-ended: no email, no form, no
   button. This is the only exit.
   ══════════════════════════════════════════════════════════ */
.contact-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.6rem;
  margin-top: 1.6rem;
  padding: 1.5rem 1.9rem;
  border-radius: 16px;
  background: rgba(10, 20, 40, 0.85);
  border: 1px solid rgba(127, 212, 255, 0.28);
}

.cc-text { flex: 1 1 320px; min-width: 0; }

.cc-title {
  font-size: 1.22rem;
  font-weight: 700;
  color: #fff;
  margin-bottom: 0.35rem;
  text-wrap: balance;
}

.cc-body {
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(205, 225, 245, 0.85);
  max-width: 56ch;
  text-wrap: pretty;
}

.cc-actions {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-wrap: wrap;
}

.cc-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.8rem 1.5rem;
  border-radius: 10px;
  background: #F5C200;
  color: #10203a;
  font-size: 0.92rem;
  font-weight: 700;
  text-decoration: none;
  transition: background 0.2s, transform 0.15s;
}

.cc-btn svg { width: 18px; height: 18px; }

.cc-btn:hover { background: #ffd633; transform: translateY(-1px); }

.cc-btn:focus-visible,
.cc-link:focus-visible {
  outline: 2px solid #7fd4ff;
  outline-offset: 3px;
}

.cc-link {
  font-size: 0.82rem;
  color: #7fd4ff;
  text-decoration: none;
  border-bottom: 1px solid rgba(127, 212, 255, 0.35);
  padding-bottom: 1px;
}

.cc-link:hover { color: #b9e6ff; }

/* ══════════════════════════════════════════════════════════════════════════
   NARROW SCREENS  (<= 900px)
   One DOM, two behaviours. Above the breakpoint the page is a scroll-driven
   narrative: cards fixed to the viewport centre, floating over a map that
   dives. None of that survives a 390 px phone, so below it the same markup
   becomes an ordinary document — cards return to normal flow, the map and its
   grid come off, and the awards canvas gives way to a plain timeline.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {

  /* ── Chrome that only makes sense with a pointer and a tall viewport ── */
  #map-bg,
  #map-attrib,
  #wrf-grid,
  #dark-overlay,
  #scroll-hint,
  #map-toggle,
  #awards-canvas,
  #awards-hitboxes,
  #awards-panel,
  .why-dots {
    display: none !important;
  }

  /* Segunda declaracao de body dentro deste media query (achado nesta
     tarefa, mesmo padrao ja visto em .text-box/.awards-section): sem isto,
     a tela estreita inteira ficava escura por cima do fundo claro do
     Task 1. */
  body { background-color: #5a8fc2; }

  /* ── Navbar → hamburger ── */
  #navbar { padding: 0 1rem; }
  #nav-links { display: none; }

  /* As tres <span> nunca receberam regra: eram inline, altura zero, invisiveis.
     O botao existia e respondia ao toque, mas em 390 px a barra mostrava so o
     logo — quem chegava pelo telefone nao tinha navegacao nenhuma. */
  #hamburger span {
    display: block;
    width: 22px;
    height: 2px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.88);
  }

  #hamburger {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 40px;
    height: 40px;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
  }

  #nav-overlay {
    position: fixed;
    inset: 0;
    z-index: 1500;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.4rem;
    background: rgba(3, 8, 16, 0.97);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.28s ease;
  }

  /* O JS so alternava a classe `open`; ninguem nunca escreveu a regra dela, e o
     overlay ficava em opacity: 0 / pointer-events: none para sempre. Sem isto o
     menu do telefone abria e nao aparecia. */
  #nav-overlay.open {
    opacity: 1;
    pointer-events: auto;
  }

  #nav-close {
    position: absolute;
    top: 0.9rem;
    right: 1.1rem;
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.85);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
  }

  #nav-menu-links {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    gap: 0;
    width: min(320px, 78vw);
  }

  /* Mesma decisão da barra larga (ver #nav-links acima): a divisória é o que
     faz uma pilha de palavras ler como menu. Aqui ela é horizontal, entre os
     itens, e some depois do último. */
  #nav-menu-links a {
    color: rgba(255, 255, 255, 0.9);
    font-size: 1.15rem;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-decoration: none;
    padding: 0.95rem 0.4rem;
  }

  #nav-menu-links a + a {
    border-top: 1px solid rgba(255, 255, 255, 0.14);
  }

  /* ── Scroll narrative → document flow ── */
  #scroll-container { pointer-events: auto; }

  .stage {
    height: auto;
    display: block;
    padding: 1.6rem 1rem 0;
  }

  .stage[aria-hidden="true"] { display: none; }

  .text-box {
    position: static !important;
    transform: none !important;
    display: block;
    width: 100%;
    max-width: 640px;
    min-height: 0;
    margin: 0 auto 1.6rem;
    opacity: 1 !important;
    visibility: visible !important;
    filter: none !important;
    background: rgba(10, 20, 42, 0.92);
  }

  .why-box { width: 100%; max-width: 640px; }

  .card-image,
  .products-box .card-image { min-height: 190px; }

  .card-content { padding: 1.3rem 1.2rem 1.5rem; }

  /* ── Why: both acts visible, stacked; no scroll to switch between them ── */
  .why-acts { display: block; }

  .why-act {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    margin-bottom: 1.6rem;
  }

  .why-cmp {
    grid-template-columns: 1fr;
    gap: 1.1rem;
    padding: 1rem 1.1rem 0.4rem;
  }

  .wc-panel { width: 100%; max-width: 340px; }

  /* The vertical colour bar needs a tall neighbour; stacked, it lies down. */
  .cbar {
    flex-direction: row;
    align-items: center;
    width: 100%;
    max-width: 340px;
    margin: 0 auto;
    padding-top: 0;
    gap: 0.45rem;
  }

  .cbar-canvas { width: auto; height: 10px; flex: 1 1 auto; min-height: 0; }
  .cbar-hi { order: 3; }

  .wc-key-text,
  .wc-truth { padding-left: 1.1rem; padding-right: 1.1rem; margin-left: 0; margin-right: 0; }

  .why-strip {
    grid-template-columns: 1fr 1fr;
    gap: 0.8rem;
    padding: 0.9rem 1.1rem 1.2rem;
  }

  /* ── Why act 2: maps over the chart ── */
  .wf-head { padding: 1rem 1.1rem 0.5rem; }
  .wf-body { grid-template-columns: 1fr; padding: 0 1.1rem; gap: 1rem; }
  /* Lado a lado dentro de 340 px, cada campo de vento ficava com ~150 px de
     largura — o argumento e que um deles resolve o relevo e o outro nao, e a
     150 px nenhum dos dois resolve nada. Empilhados, cada um ocupa a largura
     toda, como os paineis de chuva ja faziam. Empilhar mantem a comparacao
     simultanea, que um alternador destruiria. */
  .wf-maps {
    grid-template-columns: 1fr;
    width: 100%;
    max-width: 340px;
    margin-inline: auto;
    gap: 1rem;
  }

  .wf-maps-note { grid-column: 1; }

  /* A ~150 px por painel, `white-space: nowrap` fazia o nome de um painel
     invadir o do outro: no telefone lia-se "Modelo global · GFSMETENERGY". */
  .wf-map-head { flex-wrap: wrap; gap: 0 0.4rem; }
  .wf-map-name, .wf-map-res { white-space: normal; }
  .wf-chart { height: 230px; }
  .wf-metrics { grid-template-columns: 1fr 1fr; }
  .wf-note { padding: 0.5rem 1.1rem 0; }

  /* ── Products / team ── */
  .prod-grid { grid-template-columns: 1fr; }
  .team-grid { grid-template-columns: repeat(2, 1fr); gap: 1.1rem; }

  /* ── Awards: canvas timeline → DOM timeline ── */
  .awards-section { height: auto; padding: 1.6rem 1rem 2rem; }
  .awards-sticky { position: static; height: auto; background: transparent; }

  /* Só aqui: a regra base de .awards-heading (fora deste media query) segue
     usada pela cena com canvas e continua intocada. */
  .awards-heading {
    position: static;
    opacity: 1;
    transform: none;
    font-size: 1.4rem;
    margin-bottom: 1.2rem;
    color: #122845;
  }

  #awards-timeline.timeline {
    display: block;
    position: relative;
    max-width: 640px;
    margin: 0 auto;
    padding-left: 1.2rem;
    border-left: 2px solid rgba(77, 184, 255, 0.35);
  }

  .timeline-item { margin-bottom: 1.4rem; }

  .timeline-date {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.82rem;
    font-weight: 700;
    color: #122845;
    white-space: pre-line;
    margin-bottom: 0.4rem;
  }

  .timeline-trl {
    font-size: 0.62rem;
    font-weight: 600;
    color: #8a5c00;
    border: 1px solid rgba(138, 92, 0, 0.4);
    border-radius: 5px;
    padding: 0.1rem 0.4rem;
  }

  .timeline-bullets { list-style: none; }

  .timeline-bullets li {
    position: relative;
    padding-left: 0.9rem;
    margin-bottom: 0.3rem;
    font-size: 0.84rem;
    line-height: 1.45;
    color: rgba(18, 40, 69, 0.82);
    text-wrap: pretty;
  }

  .timeline-bullets li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(77, 184, 255, 0.7);
  }

  /* ── Splash ── */
  #splash-ui {
    width: 100%;
    min-width: 0;
    padding: 2rem 1.2rem;
    background: linear-gradient(to top, rgba(3, 8, 22, 0.94) 55%, rgba(3, 8, 22, 0.6) 100%);
  }

  #splash-partners { display: none; }

  /* ── Remaining sections ── */
  .commitment-section,
  .partners-section,
  .contacts-section { padding: 1.8rem 1rem; }

  .findus-event-card { grid-template-columns: 1fr; }
  .findus-map { min-height: 220px; }
}

@media (max-width: 560px) {
  .team-grid { grid-template-columns: 1fr; }
  .why-strip { grid-template-columns: 1fr; }
  .wf-metrics { grid-template-columns: 1fr; }
}


/* ══════════════════════════════════════════════════════
   MAPA DE PILOTOS (13/08)
   ══════════════════════════════════════════════════════
   Camada de pins do ato 0 + a seta de voltar. Ver
   docs/superpowers/specs/2026-08-13-mapa-de-pilotos-hub-design.md */

#hub-pins {
  position: fixed;
  inset: 0;
  z-index: 6;
  /* A camada nunca intercepta: quem intercepta é o botão. Sem isto, um <div>
     de tela cheia por cima da cena comeria o scroll e o arrasto da régua. */
  pointer-events: none;
  opacity: var(--hub-fade, 0);
  transition: opacity 120ms linear;
}
/* Os pins somem quando a cena não existe e quando um CASO está aberto (a
   rolagem trava lá dentro, então o mapa não pode reaparecer por baixo).
   ⚠️ NÃO somem por causa de um destino de DOCUMENTO: no pin da sede a rolagem
   continua livre, e o visitante volta ao mapa subindo a roda — foi o bug que o
   fundador viu, "os pings somem a não ser que eu clique para o mapa". Quem
   apaga os pins fora do beat do mapa é a própria cena, escrevendo --hub-fade a
   zero quando o ato de abertura deixa de ser o ativo (ver draw() em
   js/scene/scene.mjs). */
html:not([data-scene]) #hub-pins,
html[data-travado] #hub-pins { display: none; }

.hub-pin {
  position: absolute;
  left: 0; top: 0;
  display: block;
  padding: 0.42rem 0.6rem;
  text-align: left;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 10px;
  /* Pedido do fundador (15/08): "literalmente todos os cards" com o mesmo
     fundo escuro — era o único cartão ainda branco (rgba(255,255,255,.90)),
     sobra de antes da cena virar azul-marinho no topo. Mesmo tom sólido de
     .about-manifest/.act-open-diff. */
  background: rgba(10, 20, 40, 0.92);
  backdrop-filter: blur(6px);
  color: #e7f1ff;
  cursor: pointer;
  /* Ligado só quando o mapa está de fato na tela — desenhaPins escreve
     data-ativo. Com opacidade baixa os botões continuariam clicáveis por cima
     do globo e das caixas 3D, e um clique invisível é pior que nenhum. */
  pointer-events: none;
  transition: border-color 140ms ease, transform 140ms ease, background 140ms ease;
}
#hub-pins[data-ativo] .hub-pin { pointer-events: auto; }
.hub-pin:hover,
.hub-pin:focus-visible {
  border-color: rgba(255, 211, 77, 0.85);
  background: rgba(10, 20, 40, 0.98);
  transform: translateY(-1px);
}
.hub-pin-title {
  display: block;
  /* Nunca quebra: a largura do card é escrita pelo JS, e um título em duas
     linhas empurraria o subtítulo para fora da caixa. */
  white-space: nowrap;
  font-family: 'Space Grotesk', 'Plus Jakarta Sans', sans-serif;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
}
.hub-pin-sub {
  display: block;
  margin-top: 1px;
  font-size: 10.5px;
  line-height: 1.3;
  opacity: 0.72;
}
/* O alfinete é filho do BOTÃO, mas fica lá longe, em cima da coordenada. Ele é
   position:absolute relativo ao próprio botão (desenhaPins escreve o
   deslocamento), e como é filho, clicar nele É clicar no botão — o alvo que a
   mão procura primeiro. */
.hub-pin-dot {
  position: absolute;
  width: 13px; height: 13px;
  margin: -6.5px 0 0 -6.5px;
  border-radius: 50%;
  border: 2px solid rgba(255, 211, 77, 0.95);
  background: rgba(255, 211, 77, 0.22);
  box-shadow: 0 0 12px rgba(255, 211, 77, 0.5);
}
#hub-pins[data-ativo] .hub-pin-dot { animation: hub-pulso 2.4s ease-in-out infinite; }

/* O balão da marca dentro do card do pin da sede — assinatura, não marcador.
   Alinhado à linha do título pela baseline do texto, não pelo topo da caixa. */
.hub-pin-marca {
  width: 15px;
  height: 15px;
  vertical-align: -3px;
  margin-right: 5px;
}
.hub-pin:hover .hub-pin-dot,
.hub-pin:focus-visible .hub-pin-dot { background: rgba(255, 211, 77, 0.6); }

@keyframes hub-pulso {
  0%, 100% { box-shadow: 0 0 10px rgba(255, 211, 77, 0.40); }
  50%      { box-shadow: 0 0 20px rgba(255, 211, 77, 0.85); }
}
@media (prefers-reduced-motion: reduce) {
  #hub-pins[data-ativo] .hub-pin-dot { animation: none; }
}

/* A seta de voltar: só existe dentro de um destino. */
#hub-voltar {
  display: none;
  position: fixed;
  top: 76px; left: 20px;
  z-index: 12;
  align-items: center;
  gap: 0.45rem;
  padding: 0.45rem 0.8rem 0.45rem 0.6rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 999px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(8px);
  color: #e7f1ff;
  font-size: 12.5px;
  cursor: pointer;
}
html[data-destino] #hub-voltar { display: flex; }
#hub-voltar svg { width: 15px; height: 15px; }
#hub-voltar:hover { border-color: rgba(255, 211, 77, 0.8); }

/* ── Os atos saem do caminho linear ──────────────────────────────────────
   Com o mapa fazendo as vezes de menu, os atos de chuva e vento só existem
   quando ESCOLHIDOS. Quem apenas rola vai do mapa direto para o documento.
   Mesmo mecanismo que já governa a cena desligada (display:none no .act):
   um ato escondido não ocupa layout, então não sobra buraco de 300vh. */
html[data-scene]:not([data-destino="act-rain"]) #act-rain,
html[data-scene]:not([data-destino="act-wind"]) #act-wind { display: none; }


/* ── A rolagem trava dentro de um caso (13/08) ───────────────────────────
   "Ao selecionar o caso não dá mais para descer ou subir, somente voltar para
   o mapa interativo ou ir direto para alguma aba utilizando os títulos em
   cima." O caso vira um quadro fixo; o que sobra de interação é a RÉGUA,
   arrastável, e o menu do topo.

   Só os CASOS travam. A sequência institucional (equipe, prêmios, projetos) é
   documento, e documento se lê rolando — travá-la esconderia o conteúdo.

   Sem scrollbar-gutter: reservar a calha sempre parecia a correção óbvia para
   o salto de ~15px quando a barra some, mas ela deixa a viewport 15px mais
   estreita que window.innerWidth — e o canvas do globo, que main.js dimensiona
   por innerWidth, passava a ser desenhado esticado (sinalizado pelo harness:
   "globe-canvas 1440!=1425"). O salto acontece SOB O VÉU, onde ninguém o vê;
   a distorção do globo ficaria na tela o tempo todo. */
html[data-travado], html[data-travado] body { overflow: hidden; }


/* Lista de casos do bloco "Estudo de Caso" (13/08): cada linha abre o pin
   correspondente no mapa. Empilhadas, e não em fileira: os rótulos são frases,
   não palavras, e lado a lado quebravam em três linhas cada. */
.case-lista-titulo { margin: 0 0 0.6rem; }
.case-lista { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
/* Havia aqui um `.cta-btn-secondary--fraco { opacity: 0.72 }` no botão "ver os
   casos no mapa", para rebaixá-lo em relação aos dois casos listados acima
   dele. O fundador leu o resultado como defeito, não como hierarquia (29/08):
   "está com uma cor que parece que não é clicável, um amarelo mais escuro".
   Amarelo apagado sobre card escuro não lê como "secundário", lê como
   DESABILITADO — e um botão que parece desabilitado não é uma hierarquia mais
   fraca, é um botão em que ninguém clica. Os três são o mesmo botão agora. */


/* ── O pino do pluviômetro e o gráfico sob demanda (13/08) ───────────────
   "O caso de São Sebastião está com muita informação [...] o gráfico
   comparativo pode ser interativo, com ping na posição de Barra do Una, para
   surgir quando o usuário clicar."

   O gráfico deixa de nascer aberto. Era display:none !important (o
   !important existe porque syncActDom() escreve .act-on em todo .act-border
   do ato ativo — a regra do ATO precisa perder para a regra do PINO);
   virou pointer-events:none — a opacidade (ver .act-rain-chart) já cuida da
   visibilidade, e animando opacity precisa continuar ocupando layout. */
html[data-scene]:not([data-pluviometro]) .act-rain-chart { pointer-events: none; }

#pino-pluviometro {
  position: fixed;
  z-index: 9;
  display: none;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.6rem 0.3rem 0.4rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 999px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(6px);
  color: #e7f1ff;
  font-size: 11.5px;
  cursor: pointer;
  /* Pedido do fundador (15/08): o rótulo saiu de cima do ponto (poluía o
     mapa) e foi pra fora do campo, à esquerda — posicionaPinoDoPluviometro
     (scene.mjs) já escreve o canto superior esquerdo do botão, sem precisar
     de transform pra recentrar num ponto que não é mais a âncora dele. */
}
#pino-pluviometro.act-on { display: flex; }
/* .act-border traz pointer-events:none (ela governa rótulos, não alvos), e os
   dois pinos carregam essa classe porque é ela que syncActDom varre para
   acender o texto certo por idioma. Sem esta linha o pino aparece, pulsa e
   NÃO CLICA — foi o que o fundador viu em 13/08. */
#pino-pluviometro.act-on, #pino-recurso.act-on { pointer-events: auto; }
#pino-pluviometro:hover { border-color: rgba(255, 211, 77, 0.85); }
.pino-ponto {
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 2px solid rgba(255, 211, 77, 0.95);
  background: rgba(255, 211, 77, 0.22);
  animation: hub-pulso 2.4s ease-in-out infinite;
}
html[data-pluviometro] .pino-ponto { animation: none; background: rgba(255, 211, 77, 0.7); }
@media (prefers-reduced-motion: reduce) { .pino-ponto { animation: none; } }

/* Anel de "toque aqui" nos dois pinos que CLICAM (pluviômetro e recurso do
   dia). Pedido do fundador (13/08): eles não pareciam clicáveis — o brilho do
   `.pino-ponto` já existente lê como "isto está vivo", não como "toque
   aqui". Um anel que expande e some é o idioma visual padrão de alvo de mapa
   tocável (Google Maps, Airbnb); escopado em `button.act-border` porque só os
   dois pinos que abrem painel são <button> — os de anotação da Bahia
   (.pino-vento) são <div> e não devem convidar ao clique. Some enquanto o
   painel correspondente está aberto (mesmos data-attrs que já controlam o
   toggle em scene.mjs), porque a essa altura o visitante já achou. */
button.act-border .pino-ponto { position: relative; }
button.act-border .pino-ponto::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 211, 77, 0.75);
  animation: pino-toque 2.2s ease-out infinite;
  pointer-events: none;
}
html[data-pluviometro] #pino-pluviometro .pino-ponto::after,
html[data-recurso] #pino-recurso .pino-ponto::after { animation: none; opacity: 0; }
@keyframes pino-toque {
  0%        { transform: scale(1);    opacity: 0.85; }
  75%, 100% { transform: scale(2.3);  opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  button.act-border .pino-ponto::after { animation: none; opacity: 0; }
}


/* ── Pins do caso da Bahia (13/08) ───────────────────────────────────────
   Dois de anotação (janela de manutenção) e um que abre as curvas. Os de
   anotação não clicam: eles informam, e um alvo que não leva a lugar nenhum
   frustra quem tenta. */
/* O rótulo mora FORA do campo desde 13/08, ligado por uma linha puxada
   desenhada no canvas. Por isso ele deixou de ser ancorado pelo ponto: agora a
   posição escrita por desenhaPinosDoVento já é a do canto do rótulo. */
.pino-vento, #pino-recurso {
  position: fixed;
  z-index: 9;
  display: none;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.6rem 0.3rem 0.4rem;
  border: 1px solid rgba(77, 184, 255, 0.35);
  border-radius: 999px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(6px);
  color: #e7f1ff;
  font-size: 11px;
}
.pino-vento.act-on, #pino-recurso.act-on { display: flex; }
.pino-vento { pointer-events: none; }
#pino-recurso { cursor: pointer; font-size: 11.5px; }
#pino-recurso:hover { border-color: rgba(255, 211, 77, 0.85); }
/* Indicador de clique — pedido do fundador (15/08): "menos palavras
   possível", só um sinal de que o pino abre algo. Uma seta, não texto: gira
   90° quando o painel que ela abre já está aberto (aria-expanded, escrito
   por scene.mjs), a mesma gramática de um <details> nativo. */
#pino-pluviometro::after,
#pino-recurso::after {
  content: '›';
  margin-left: 0.15rem;
  color: rgba(255, 211, 77, 0.85);
  font-weight: 700;
  transition: transform 200ms ease;
}
#pino-pluviometro[aria-expanded="true"]::after,
#pino-recurso[aria-expanded="true"]::after {
  transform: rotate(90deg);
}
.pino-vento-texto { display: flex; flex-direction: column; line-height: 1.3; }
.pino-vento-num { opacity: 0.7; font-size: 10px; }
.pino-ponto--bom { border-color: rgba(122, 214, 255, 0.95); background: rgba(122, 214, 255, 0.22); animation: none; }
.pino-ponto--ruim { border-color: rgba(255, 157, 122, 0.95); background: rgba(255, 157, 122, 0.22); animation: none; }

/* As curvas de recurso, sob demanda — mesma regra do gráfico do pluviômetro:
   a do PINO precisa vencer a do ato. */
html[data-scene]:not([data-recurso]) .act-wind-curvas { display: none !important; }
/* 140px e não 96: a seta "Voltar ao mapa" mora no canto superior esquerdo, e
   a 96 ela atravessava o título do painel (captura de 13/08). */
.act-wind-curvas {
  top: 108px;
  left: 28px;
  width: min(26vw, 340px);
  padding: 0.8rem 0.9rem 0.7rem;
  border-radius: 12px;
  background: rgba(10, 20, 40, 0.90);
  backdrop-filter: blur(8px);
}
/* 430 -> 560px (19/08, 3ª rodada): mesmo defeito voltou a ser apontado — seis
   faixas em 430px davam ~66px de altura cada, e os marcadores novos (anel de
   início de rampa + triângulo de variabilidade, ver scene.mjs) ainda
   ficavam espremidos ali dentro. A 560px cada faixa sobe pra ~92px. */
#act-wind-curvas-canvas { display: block; width: 100%; height: 560px; margin: 0.3rem 0 0.5rem; }
.curvas-legenda-linhas {
  display: flex;
  gap: 0.75rem;
  margin: 0 0 0.4rem;
  font-size: 9.5px;
  opacity: 0.75;
}
.curvas-legenda-linhas i { display: inline-block; width: 14px; height: 2px; vertical-align: middle; margin-right: 4px; }
.curvas-cabecalho {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.35rem;
  font-size: 10px;
  opacity: 0.7;
}
.curvas-legenda { white-space: nowrap; }
#act-wind-metricas { display: flex; flex-direction: column; gap: 2px; }
.curva-metrica {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 0.5rem;
  font-size: 10.5px;
}
.curva-cor { width: 8px; height: 8px; border-radius: 2px; }
.curva-nome { opacity: 0.85; }
.curva-num { font-weight: 700; font-variant-numeric: tabular-nums; }
.curva-num--boa { color: #1c7fc4; }
.curva-num--ruim { color: #ff9d7a; }


/* ── A NITIDEZ (13/08) ───────────────────────────────────────────────────
   O véu que cobria a troca saiu: ele resolvia o solavanco e não dizia nada. No
   lugar dele, o destino NASCE TRANSPARENTE e ganha nitidez — pedido do
   fundador: "ir aparecendo com certo alpha até a nitidez total dos elementos
   de cada caso".

   O canvas primeiro (o dado), os cards 120 ms depois e mais devagar: é o que
   faz a cena parecer que se MONTA, em vez de piscar inteira. O olho pousa no
   campo antes de ter texto para ler. */
/* ⚠️ transition:none no estado de ENTRADA, e não só no de chegada.
   Com a transição valendo nos dois sentidos, o elemento não some: ele COMEÇA a
   apagar, o atributo sai dois quadros depois e ele volta — medido em 835 ms, a
   opacidade estava em 1. Ir a zero é um corte; o que se anima é a volta. */
#scene-canvas { transition: opacity 420ms ease; }
html[data-entrando] #scene-canvas { opacity: 0; transition: none; }

html[data-destino] .act-border,
html[data-destino] .act-metrics,
html[data-destino] #hub-voltar { transition: opacity 520ms ease 120ms; }
html[data-entrando] .act-border,
html[data-entrando] .act-metrics,
html[data-entrando] #hub-voltar { opacity: 0 !important; transition: none !important; }

@media (prefers-reduced-motion: reduce) {
  #scene-canvas,
  html[data-destino] .act-border,
  html[data-destino] .act-metrics,
  html[data-destino] #hub-voltar { transition: none; }
}
