/* Abertura do site: assinatura, intro, hero e mapa animado. Trechos trazidos de ../assets/css/styles.css, backup-v6 e map-camera.css (gerado por tools/build-map.js). */
/* ---------- assinatura oficial (SVG do hero-preview) ---------- */
/* Ícone = PNG oficial embutido via <image>; wordmark, ponto e legenda = vetores do arquivo fornecido. */
.vad-logo svg { display: block; width: 100%; height: auto; overflow: visible; }
.vlogo-st0, .vlogo-st1, .vlogo-st2 { fill: #fff; }
.vlogo-st0, .vlogo-st2 { stroke: #fff; stroke-miterlimit: 10; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
.vlogo-st0 { font-size: 16.25px; font-style: italic; stroke-width: 0.25px; }
.vlogo-st2 { font-size: 22.39px; }
.vlogo-st3 { fill: #e63823; }
.vfrase-base { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 39.24px; stroke-miterlimit: 10; }
.vfrase-st1 { fill: #ee782b; stroke: #ee782b; }
.vfrase-st2, .vfrase-st3 { fill: #fff; stroke: #fff; stroke-width: 0.75px; }
.vfrase-st4 { fill: #e43228; stroke: #e43228; }

/* entrada das partes da assinatura, como no preview: ícone, wordmark, ponto, legenda */
.js .vad-logo .vlogo-part {
  opacity: 0; transform-box: fill-box; transform-origin: center;
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}
.js .vad-logo .vlogo-part-icon { transform: scale(0.85) translateY(-6px); }
.js .vad-logo .vlogo-part-wordmark { transform: translateX(10px); transition-delay: 0.14s; }
.js .vad-logo .vlogo-part-dot {
  transform: scale(0); transition-delay: 0.34s;
  transition-duration: 0.5s; transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
}
.js .vad-logo .vlogo-part-caption { transform: translateY(8px); transition-delay: 0.42s; }
.js .vad-logo.is-loaded .vlogo-part { opacity: 1; transform: none; }

/* ---------- intro ---------- */
/* Reconstrução vetorial do motion de referência (referencias/Vale do aço digital motion intro.mp4),
   só o trecho Vale do Aço Digital: 0,00–3,27 s do vídeo + o ponto final (4,30–4,60 s do vídeo, antecipado).
   Os tempos abaixo são os observados no vídeo; tudo dispara com .is-playing. */
.intro { display: none; }
.intro-on .intro {
  position: fixed; inset: 0; z-index: 200; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(60% 48% at 62% 56%, #1b232b 0%, rgba(27, 35, 43, 0) 72%), #070d15;
  transition: opacity 0.55s var(--ease), visibility 0s 0.55s;
}
.intro-lock, .intro-lock body { overflow: hidden; }
.intro.is-leaving { opacity: 0; visibility: hidden; pointer-events: none; }
.intro__stage { width: min(78vw, 460px); }
@media (max-width: 600px) { .intro__stage { width: 84vw; } } /* celular em pé: a assinatura final ganha corpo */
.intro__mark { display: block; width: 100%; height: auto; overflow: visible; }

/* --zk (abertura.js) encolhe a aproximação onde o ícone a 5× não cabe na tela: escala = 1 + (s − 1) × --zk */
.im-cam { transform-origin: 104.6px 72.7px; transform: translate(79.5px, 0) scale(calc(1 + 4 * var(--zk, 1))); }
.im-lines path, .im-trace, .im-outline path, .im-sweep { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* sem vector-effect: non-scaling-stroke — no Chromium ele força repintura a cada quadro do zoom e, combinado a
   pathLength + dasharray, chegou a travar a pintura. As espessuras estão em unidades do viewBox: as linhas afinam
   junto com o zoom-out, como no vídeo de referência. Nenhum traço pode ficar abaixo de ~1px de tela: linhas
   sub-pixel (hairline) travaram a pintura em palcos estreitos — por isso o reforço em telas pequenas mais abaixo. */
.im-lines path { stroke: #f39a1f; stroke-width: 0.85px; opacity: 0; }
.im-lines path:nth-child(4n + 1), .im-lines path:nth-child(4n + 2) { stroke: #e9801b; }
.im-trace { stroke: #f08a1d; stroke-width: 0.34px; opacity: 0; } /* ≈2px de tela com a câmera em ~4,6× */
.im-trace--spark { stroke: #f7a823; stroke-dasharray: 0.05 1.4; stroke-dashoffset: 0.06; }
.im-trace--diag { stroke: #e8352a; stroke-dasharray: 0.2 1.4; stroke-dashoffset: 0.21; }
.im-trace--stem, .im-trace--arc { stroke-dasharray: 1; stroke-dashoffset: 1; }
.im-sweep { stroke: #fff3dc; stroke-width: 0.9px; stroke-dasharray: 0.14 1.4; stroke-dashoffset: 0.15; opacity: 0; }
.im-outline path { stroke: #f08a1d; stroke-width: 1px; }
@media (max-width: 600px) {
  .im-lines path { stroke-width: 1.3px; }
  .im-outline path { stroke-width: 1.4px; }
  .im-trace { stroke-width: 0.5px; }
  .im-sweep { stroke-width: 1.2px; }
}
.im-outline, .im-fill, .im-glow, .im-official, .im-word { opacity: 0; }
.im-word { fill: #fff; }
.im-dot { fill: #e63823; transform-box: fill-box; transform-origin: center; transform: scale(0); }

.intro.is-playing .im-cam { animation: im-cam 2.63s linear both; }
.intro.is-playing .im-trace--spark { animation: im-spark 0.32s linear 0.1s both; }
.intro.is-playing .im-trace--diag { animation: im-diag 0.28s linear 0.3s both; }
.intro.is-playing .im-trace--stem { animation: im-draw 0.22s ease-in-out 0.43s both, im-hide 0.3s linear 1.05s forwards; }
.intro.is-playing .im-trace--arc { animation: im-draw 0.29s ease-in-out 0.63s both, im-hide 0.3s linear 1.05s forwards; }
.intro.is-playing .im-lines path { animation: im-line-in 0.35s ease-out calc(0.9s + var(--i) * 0.05s) both, im-hide 0.16s linear 2.67s forwards; }
.intro.is-playing .im-sweep { animation: im-sweep 0.5s ease-in-out 2s both; }
.intro.is-playing .im-word { animation: im-word 0.27s linear 2.55s both; }
.intro.is-playing .im-outline { animation: im-outline 0.45s linear 2.63s both; }
.intro.is-playing .im-fill { animation: im-fill 0.27s linear 2.7s both; }
.intro.is-playing .im-glow { animation: im-show 0.4s ease-out 2.75s both; }
.intro.is-playing .im-official { animation: im-show 0.3s linear 3s both; }
.intro.is-playing .im-dot { animation: im-dot 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) 3.15s both; }

/* câmera: close extremo nos traços → zoom-out contínuo → desliza para a posição da assinatura */
@keyframes im-cam {
  0% { transform: translate(79.5px, 0) scale(calc(1 + 4 * var(--zk, 1))); }
  34% { transform: translate(79.5px, 0) scale(calc(1 + 3.3 * var(--zk, 1))); animation-timing-function: cubic-bezier(0.2, 0.6, 0.3, 1); }
  61% { transform: translate(79.5px, 0) scale(calc(1 + 1.9 * var(--zk, 1))); animation-timing-function: linear; }
  88.6% { transform: translate(79.5px, 0) scale(calc(1 + 1.2 * var(--zk, 1))); animation-timing-function: cubic-bezier(0.6, 0, 0.2, 1); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes im-spark { 0% { stroke-dashoffset: 0.06; opacity: 1; } 90% { opacity: 1; } 100% { stroke-dashoffset: -0.62; opacity: 0; } }
@keyframes im-diag { 0% { stroke-dashoffset: 0.21; opacity: 1; } 90% { opacity: 1; } 100% { stroke-dashoffset: -1.02; opacity: 0; } }
@keyframes im-draw { 0% { stroke-dashoffset: 1; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 1; } }
@keyframes im-line-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes im-hide { to { opacity: 0; } }
@keyframes im-show { from { opacity: 0; } to { opacity: 1; } }
@keyframes im-sweep { 0% { stroke-dashoffset: 0.15; opacity: 0; } 12%, 85% { opacity: 0.95; } 100% { stroke-dashoffset: -1.02; opacity: 0; } }
@keyframes im-word { 0% { opacity: 0; } 40% { opacity: 0.45; } 100% { opacity: 1; } }
@keyframes im-outline { 0% { opacity: 0; } 20%, 64% { opacity: 1; } 100% { opacity: 0; } }
@keyframes im-fill { 0% { opacity: 0; } 37% { opacity: 0.45; } 100% { opacity: 1; } }
@keyframes im-dot { 0% { transform: scale(0); fill: #f08a1d; } 100% { transform: scale(1); fill: #e63823; } }

/* ---------- hero (composição do hero-preview) ---------- */
/* Scrub (html.hero-scrub, mouse e toque): 280vh desktop / 240vh tela estreita, sticky. Play (toque que não acompanha o seek), sem JS,
   reduced motion, economia de dados ou vídeo com falha: 100svh em fluxo normal. O preview usava 560/320vh; o percurso foi encurtado. */
.hero { --hero-bg: #251404; position: relative; height: 100vh; height: 100svh; background: var(--hero-bg); color: #fff; }
.hero-scrub .hero { height: 280vh; }
.hero__sticky { position: relative; height: 100vh; height: 100svh; overflow: hidden; background: var(--hero-bg); }
.hero-scrub .hero__sticky { position: sticky; top: 0; }
/* palco pinado na altura do viewport GRANDE: no celular a barra de endereço recolhe ao rolar e um palco de 100svh deixava uma
   faixa do fundo aparecendo embaixo do vídeo. O que fica ancorado na base (frase e indicação de rolagem) sobe a diferença
   (--barra) e nasce visível com a barra aberta. No desktop lvh = svh e nada muda. */
@supports (height: 100lvh) {
  .hero-scrub .hero__sticky { height: 100lvh; --barra: calc(100lvh - 100svh); }
}
.hero__video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: var(--hero-bg);
}
/* quadro final por cima do vídeo: só aparece (abertura.js) enquanto o vídeo não tem quadro para mostrar */
.hero__alt {
  position: absolute; inset: 0; pointer-events: none; opacity: 0; visibility: hidden;
  background: var(--hero-bg) url("../img/hero-poster-fim.jpg") center / cover no-repeat;
}
/* dissolução para o fundo do hero: mesmo resultado da antiga máscara (40% → 100%), mas como camada própria animada só por
   opacity — o <video> fica sem mask e o navegador o compõe pelo caminho barato. Sem JS/estático: opacidade 1 (quadro final). */
.hero__fade {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to bottom, rgba(37, 20, 4, 0) 40%, var(--hero-bg) 100%);
}
.js .hero.is-scrub .hero__fade, .js .hero.is-play .hero__fade { opacity: 0; visibility: hidden; }
.hero__shade {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(20, 9, 2, 0.55) 0%, rgba(20, 9, 2, 0) 22%),
    linear-gradient(to top, rgba(20, 9, 2, 0.72) 0%, rgba(20, 9, 2, 0) 46%);
}
.hero__logo {
  position: absolute; z-index: 3; top: clamp(16px, 3vh, 32px); left: 50%; transform: translateX(-50%);
  width: clamp(120px, 14vw, 190px);
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, 0.45));
}
.hero__loading { position: absolute; inset: 0; z-index: 4; background: var(--hero-bg); display: none; }

.hero__start {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: clamp(28px, 7vh, 72px);
  width: 100%; max-width: calc(var(--wrap) + var(--gutter) * 2); margin-inline: auto; padding-inline: var(--gutter);
  display: none;
}
.js .hero.is-scrub .hero__start, .js .hero.is-play .hero__start { display: block; } /* só com o modo decidido: antes disso o hero mostra o quadro final */
/* sem frase de abertura: o bloco inicial guarda só a indicação de rolagem, e o escurecimento que dava leitura ao texto saiu junto */
.hero__lead { margin-top: 16px; max-width: 26em; font-size: clamp(1.02rem, 0.95rem + 0.4vw, 1.25rem); line-height: 1.5; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.5); }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; margin-top: 24px; }
.hero__actions--end { justify-content: center; margin-top: clamp(18px, 3vh, 30px); }
.link-arrow--light { color: #fff; text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5); background-image: linear-gradient(var(--orange), var(--orange)); }
.hero__hint {
  display: flex; align-items: center; gap: 10px; margin-top: clamp(20px, 4vh, 40px);
  font-family: var(--font-title); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
}
.hero__hint span { width: 1px; height: 28px; background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff); }

.hero__end {
  position: absolute; z-index: 2; left: 50%; bottom: 8vh; transform: translateX(-50%);
  width: min(100% - var(--gutter) * 2, 640px); text-align: center;
}
.hero__phrase { width: min(100%, clamp(340px, 48vw, 640px)); margin-inline: auto; filter: drop-shadow(0 2px 14px rgba(0, 0, 0, 0.55)); }
.hero__phrase svg { display: block; width: 100%; height: auto; overflow: visible; }
/* frase final: entra por tempo quando a personagem se vira (main.js liga .is-on). Cada linha sobe e firma em sequência,
   os botões vêm depois; na volta tudo sai junto e rápido. Sem JS / modo estático: a frase já está no lugar. */
.js .hero.is-scrub .hero__end, .js .hero.is-play .hero__end { visibility: hidden; transition: visibility 0s 0.45s; }
.js .hero.is-scrub .hero__end.is-on, .js .hero.is-play .hero__end.is-on { visibility: visible; transition: visibility 0s; }
.js .hero.is-scrub .vfrase-row, .js .hero.is-play .vfrase-row,
.js .hero.is-scrub .hero__actions--end, .js .hero.is-play .hero__actions--end {
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.js .hero.is-scrub .hero__actions--end, .js .hero.is-play .hero__actions--end { transform: translateY(10px); }
.js .hero .hero__end.is-on .vfrase-row {
  opacity: 1; transform: none;
  transition: opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1) calc(var(--r, 0) * 0.16s), transform 1.4s cubic-bezier(0.16, 1, 0.3, 1) calc(var(--r, 0) * 0.16s);
}
.js .hero .hero__end.is-on .hero__actions--end {
  opacity: 1; transform: none;
  transition: opacity 0.9s ease 0.55s, transform 1.1s cubic-bezier(0.16, 1, 0.3, 1) 0.55s;
}
/* controle da reprodução nativa (toque): abaixo do cabeçalho, 44px de alvo */
.hero__play {
  position: absolute; z-index: 3; left: var(--gutter); top: calc(var(--header-h) + 10px);
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 14px 8px 12px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.4); border-radius: var(--radius); background: rgba(20, 9, 2, 0.5); color: #fff;
  font-family: var(--font-title); font-size: 0.76rem; font-weight: 600;
}
.hero__play[hidden] { display: none; }
.hero__play:focus-visible { outline-color: var(--amber); }
.hero__play-icon { width: 0; height: 0; border-block: 6px solid transparent; border-left: 10px solid currentColor; }
.hero__play[data-state="playing"] .hero__play-icon { width: 10px; height: 12px; border: 0; border-inline: 3px solid currentColor; }
/* sem suporte ao vídeo (ou reduced motion via JS): quadro final, 100vh, fluxo normal */
.js .hero.is-static { height: 100vh; height: 100svh; }
.js .hero.is-static .hero__sticky { position: relative; }
.js .hero.is-static .hero__start { display: none; }

/* sem JS o cabeçalho fica no fluxo acima do hero: desconta sua altura para o CTA caber na primeira dobra */
@media (min-width: 940px) {
  .no-js .hero, .no-js .hero__sticky { height: calc(100vh - var(--header-h)); height: calc(100svh - var(--header-h)); }
}

/* ---------- redes vetoriais ---------- */
svg.net { width: 100%; height: auto; overflow: visible; }

/* ---------- mapa ---------- */
/* Só o mapa regional: os municípios do Vale do Aço e a teia de conexões, sem quadro. Em 07/10/2026 saíram a aproximação
   Brasil → Minas → Vale e, do HTML, os contornos do país, dos estados e de Minas. As camadas continuam na projeção do mapa do Brasil
   (gerada por tools/build-map.js): por isso o grupo-câmera leva o enquadramento final (--cam-end) e tudo que tem tamanho de tela —
   espessuras, nós e núcleo — é multiplicado pelo inverso dessa escala (--inv-end). O brilho quente foi aprovado só para este mapa. */
.net--map { --cam-end: translate(-14213.77px, -11577.4px) scale(30.3663); --inv-end: 0.03293; }
.map__cam { transform-origin: 0 0; transform: var(--cam-end); }
/* sem vector-effect: non-scaling-stroke — em paths grandes ele travou a pintura do Chromium; --inv-end compensa a espessura */
.map__mun { stroke-linejoin: round; fill: rgba(255, 122, 26, 0.07); stroke: rgba(255, 196, 140, 0.42); stroke-width: calc(1px * var(--inv-end)); }
.map__mun--rm { fill: rgba(255, 122, 26, 0.2); stroke: var(--orange); stroke-width: calc(1.4px * var(--inv-end)); }

/* núcleo da teia: escala inversa da câmera em torno da coordenada real → tamanho de tela constante */
.origin { transform-origin: var(--x) var(--y); transform: scale(var(--inv-end)); }
.origin__halo, .origin__echo { transform-box: fill-box; transform-origin: center; }
.origin__dot { fill: #fff1d6; stroke: var(--red); stroke-width: 2.5; }
.origin__echo { fill: none; stroke: var(--amber); stroke-width: 1.5; opacity: 0; }

/* teia regional: fios do núcleo (Ipatinga) aos municípios + malha secundária entre vizinhos.
   Espessuras multiplicadas pelo inverso da escala final (~26×) para terem 1–6 px de tela, nunca manchas. */
.link__glow, .link__line, .link__pulse, .mesh { fill: none; stroke-linecap: round; }
.mesh { stroke: var(--orange); stroke-opacity: 0.4; stroke-width: calc(1px * var(--inv-end)); }
.link__glow { stroke: var(--orange); stroke-width: calc(6px * var(--inv-end)); opacity: 0.16; }
.link__line { stroke: #ffc46b; stroke-width: calc(1.4px * var(--inv-end)); opacity: 0.95; stroke-dasharray: 1; stroke-dashoffset: 0; }
.link__pulse { stroke: #fff1d6; stroke-width: calc(2.6px * var(--inv-end)); stroke-dasharray: 0.09 1.4; stroke-dashoffset: 0.11; opacity: 0; }
.mnode { transform-origin: var(--x) var(--y); transform: scale(var(--inv-end)); }
.mnode__halo { transform-box: fill-box; transform-origin: center; }
.mnode__core { fill: #fff1d6; }
/* antes de chegar à tela (com JS e movimento permitido) o mapa espera apagado; sem JS ou com movimento reduzido ele já está
   completo, com a teia inteira desenhada */
@media (prefers-reduced-motion: no-preference) {
  .js .net--map:not(.is-live) .map__regional, .js .net--map:not(.is-live) .origin { opacity: 0; }
}

/* entrada: toca uma vez quando o mapa chega à tela (abertura.js liga .is-live com 35% dele à vista); tempos em segundos.
   municípios 0–0,9 · núcleo metropolitano 0,25 · ponto de origem 0,6 · nós 0,7–1,5 · teia a partir de 0,8, em loop de 6 s */
.js .net--map.is-live .map__mun { animation: im-show 0.9s cubic-bezier(0.16, 1, 0.3, 1) both; }
.js .net--map.is-live .map__mun--rm { animation-delay: 0.25s; }
.js .net--map.is-live .origin { animation: mo-in 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.6s both; }
.js .net--map.is-live .origin__echo { animation: mo-echo 3s ease-out 1.1s infinite; }
.js .net--map.is-live .origin__halo { animation: mo-halo 3s ease-in-out 1.1s infinite; }
.js .net--map.is-live .map__links { animation: im-show 0.8s ease-out 0.8s both; }
.js .net--map.is-live .mesh { animation: ml-mesh 6s ease-in-out 1.1s infinite both; }
.js .net--map.is-live .mnode { animation: mn-in 0.5s ease-out calc(0.7s + var(--i) * 0.1s) both; }
.js .net--map.is-live .mnode__halo { animation: mn-halo 6s ease-in-out calc(1.1s + var(--i) * 0.4s) infinite both; }
.js .net--map.is-live .link__line { animation: ml-line 6s linear calc(1.1s + var(--i) * 0.4s) infinite both; }
.js .net--map.is-live .link__glow { animation: ml-glow 6s linear calc(1.1s + var(--i) * 0.4s) infinite both; }
.js .net--map.is-live .link__pulse { animation: ml-pulse 6s linear calc(1.1s + var(--i) * 0.4s) infinite both; }

@keyframes mo-in { from { opacity: 0; transform: scale(calc(var(--inv-end) * 0.4)); } to { opacity: 1; transform: scale(var(--inv-end)); } }
@keyframes mo-echo { 0% { transform: scale(1); opacity: 0.9; } 60%, 100% { transform: scale(3.2); opacity: 0; } }
@keyframes mo-halo { 0%, 100% { transform: scale(0.85); opacity: 0.75; } 50% { transform: scale(1.12); opacity: 1; } }
@keyframes mn-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes mn-halo { 0%, 44% { transform: scale(0.6); opacity: 0.5; } 56% { transform: scale(1.35); opacity: 1; } 72%, 100% { transform: scale(0.6); opacity: 0.5; } }
@keyframes ml-mesh { 0%, 30% { stroke-opacity: 0.12; } 55%, 80% { stroke-opacity: 0.5; } 100% { stroke-opacity: 0.12; } }
@keyframes ml-line { 0% { stroke-dashoffset: 1; opacity: 0; } 4% { stroke-dashoffset: 1; opacity: 0.95; animation-timing-function: ease-in-out; } 34%, 82% { stroke-dashoffset: 0; opacity: 0.95; } 96%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes ml-glow { 0%, 30% { opacity: 0; } 40%, 82% { opacity: 0.2; } 96%, 100% { opacity: 0; } }
@keyframes ml-pulse { 0%, 36% { stroke-dashoffset: 0.1; opacity: 0; } 38% { stroke-dashoffset: 0.1; opacity: 1; animation-timing-function: ease-in-out; } 54% { stroke-dashoffset: -1.02; opacity: 1; } 56%, 100% { stroke-dashoffset: -1.02; opacity: 0; } }

.key--note { background: transparent; box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.55); }

/* pausa fora da tela / aba oculta: o relógio congela, não reinicia */
/* (* não alcança pseudo-elementos: o eco do núcleo da rede, .rede__hub::after, seguia animando fora da tela) */
.js .net.is-paused, .js .net.is-paused *, .js .net.is-paused *::before, .js .net.is-paused *::after,
.js.is-hidden .net, .js.is-hidden .net *, .js.is-hidden .net *::before, .js.is-hidden .net *::after { animation-play-state: paused !important; }
/* enquanto a página rola (site.js liga .rolando e desliga quando o parallax assenta) os loops das conexões esperam: cada
   quadro deles repinta o mapa inteiro, e junto com a rolagem isso passava do tempo de um quadro. A entrada (uma vez só)
   segue tocando; o relógio dos loops congela e continua do mesmo ponto. */
.js.rolando .net--map :is(.mesh, .mnode__halo, .link__line, .link__glow, .link__pulse, .origin__echo, .origin__halo) { animation-play-state: paused !important; }
/* pausa pedida pela pessoa: volta à composição estática completa */
.js.motion-off .net, .js.motion-off .net *, .js.motion-off .net *::before, .js.motion-off .net *::after { animation: none !important; }


@media (max-width: 768px) {
  .hero-scrub .hero { height: 240vh; }
}
@media (prefers-reduced-motion: reduce) {
  .js .net, .js .net * { animation: none !important; }
  .js .hero, .hero-scrub .hero { height: 100vh; height: 100svh; }
  .js .hero__sticky, .hero-scrub .hero__sticky { position: relative; }
  .js .hero__start { display: none; }
  .js .hero .hero__fade { opacity: 1; visibility: visible; }
  .hero__play { display: none; }
}
@media print { .intro { display: none !important; } }
