/* =============================================================================
 * CAMADA DE EFEITOS — linhas, fios e bolinhas
 * =============================================================================
 * Porte do kit de referencia (`New folder/index.html`) para a identidade da
 * GUIDSE. Uma camada SO, compartilhada pelas quatro paginas: se cada equipe
 * escrevesse o proprio brilho, o site teria quatro brilhos parecidos, que e
 * pior que ter um so.
 *
 * -----------------------------------------------------------------------------
 * OS TOKENS — e a correcao que o dono pediu
 * -----------------------------------------------------------------------------
 * A referencia usa um nucleo QUASE BRANCO (`--fx-core:#eafff5`) e escreve, com
 * todas as letras, "NUNCA #fff puro" e "se o nucleo for da mesma cor do halo,
 * parece adesivo".
 *
 * O dono pediu o oposto: "a bolinha branca deve ser verde".
 *
 * Os dois estao certos, e da para atender os dois. O que faz o nucleo ler como
 * "quente" nao e ser BRANCO — e ser MAIS CLARO que o halo. A paleta da GUIDSE
 * ja tem esse par pronto:
 *
 *     halo/glow  --gs-primary       #00c589   (verde da marca)
 *     nucleo     --gs-mint          #45e8c8   (o mesmo verde, mais claro)
 *
 * Luminancia relativa: 0,417 contra 0,631 — o mint e 51% mais luminoso. Isso
 * basta para o centro parecer aceso, e a bolinha le como VERDE, nao branca.
 * Nenhum pixel branco entra.
 *
 * ⚠️ Se um dia alguem trocar `--fx-core` por branco "para dar mais brilho", o
 * pedido do dono some. O brilho vem das TRES CAMADAS, nao da cor do nucleo.
 * -------------------------------------------------------------------------- */

:root {
  --fx: var(--gs-primary);
  --fx-core: var(--gs-mint);
  --fx-deep: var(--gs-primary-deep);

  /* A cor do FURO do anel. Nao e decoracao: o furo e fundo pintado, entao ele
   * tem de valer a superficie em que o conector esta pousado. Sobrescreva numa
   * secao clara e o anel acompanha, sem reescrever regra. */
  --fx-surface: var(--gs-core-black);

  /* A cor do estado apagado. Existe como variavel porque `idle` e o estado em
   * que o conector FICA se o JavaScript nao rodar — e um fio invisivel no
   * repouso e pior que um fio apagado. */
  --fx-off: var(--gs-border-strong-dark);
}

/* SUPERFICIE CLARA.
 *
 * Achado da equipe do /white-label, e e um defeito de verdade: o sistema
 * inteiro pressupoe fundo escuro (luz e aditiva — a propria referencia diz que
 * "o brilho so existe sobre fundo escuro"). Mas metade das secoes deste site e
 * clara, e ali o anel virava um disco PRETO sobre cartao branco.
 *
 * Ponha `.fx-on-light` na secao clara. O furo passa a valer a superficie, o
 * apagado escurece em vez de clarear, e o nucleo desce para o verde profundo —
 * mint sobre branco mede 1,5:1 e desaparece. */
.fx-on-light {
  --fx-surface: var(--gs-surface);
  --fx-off: var(--gs-border-strong);
  --fx-core: var(--gs-primary-deep);
}

/* As opacidades 0,10 / 0,40 foram calibradas para luz ADITIVA sobre preto. Em
 * branco elas quase nao somam, e a pilha de tres camadas colapsa visualmente
 * num traco unico de 2px — a equipe do /platform mediu #00c589 a 2,3:1 sobre
 * branco.
 *
 * Em fundo claro o efeito nao e luz, e TINTA: as camadas precisam de mais corpo
 * para ainda lerem como halo. Nao e o mesmo visual do escuro, e nem deveria
 * ser — brilho sobre branco vira borrao sujo, como a propria referencia avisa. */
.fx-on-light .fx-halo {
  opacity: 0.22;
}

.fx-on-light .fx-glow {
  opacity: 0.6;
}

/* =============================================================================
 * A REGRA DAS TRES CAMADAS
 * =============================================================================
 * Todo traco luminoso e o MESMO path desenhado tres vezes. A referencia insiste
 * nisso e tem razao: uma linha so com blur, ou so com opacidade, sempre parece
 * amadora — falta o degrade entre a atmosfera e o filamento.
 *
 *     camada   largura   opacidade   blur
 *     halo     16        0.10        7px
 *     glow     5         0.40        2.5px
 *     core     2         0.95        —
 *
 * `stroke-linecap: round` em todas: ponta quadrada mata o efeito.
 * -------------------------------------------------------------------------- */

.fx-halo,
.fx-glow,
.fx-core {
  fill: none;
  stroke-linecap: round;
}

.fx-halo {
  stroke: var(--fx);
  stroke-width: 16;
  opacity: 0.1;
  filter: blur(7px);
}

.fx-glow {
  stroke: var(--fx);
  stroke-width: 5;
  opacity: 0.4;
  filter: blur(2.5px);
}

.fx-core {
  stroke: var(--fx);
  stroke-width: 2;
  opacity: 0.95;
}

/* A bolinha. VERDE, por ordem do dono — mint no preenchimento, primary nas duas
 * sombras. O drop-shadow duplo (perto + longe) e o que da o halo sem precisar
 * de um segundo elemento. */
.fx-bead {
  fill: var(--fx-core);
  filter: drop-shadow(0 0 5px var(--fx)) drop-shadow(0 0 13px var(--fx));
}

/* Grupo de luz: `screen` faz cruzamento de linha SOMAR em vez de uma cobrir a
 * outra. Sem isso, duas linhas que se cruzam ficam com um degrau visivel. */
.fx-layer {
  mix-blend-mode: screen;
}

/* =============================================================================
 * PORTAS (os "donuts")
 * =============================================================================
 * O furo do anel nao e furo: e o fundo pintado. Por isso o `fill` e a cor da
 * superficie, e nao `none` — com `none` a linha que passa por tras apareceria
 * dentro do anel.
 * -------------------------------------------------------------------------- */

.fx-port-halo {
  fill: var(--fx);
  opacity: 0.22;
  filter: blur(6px);
}

.fx-port {
  fill: var(--fx-surface);
  stroke: var(--fx);
  stroke-width: 3.4;
  filter: drop-shadow(0 0 4px var(--fx))
          drop-shadow(0 0 14px color-mix(in srgb, var(--fx) 53%, transparent));
}

/* =============================================================================
 * FLUXO ANIMADO — o "running"
 * =============================================================================
 * Tres animacoes independentes que se somam: tracejado marchando, pulso
 * viajando, e o estado que liga/desliga tudo.
 *
 * ⚠️ O OFFSET TEM DE SER A SOMA EXATA DO PADRAO. `stroke-dasharray: 7 11` soma
 * 18, entao o keyframe anda -18. Um pixel a mais e o laco SALTA a cada volta —
 * e o tipo de defeito que ninguem sabe nomear mas todo mundo percebe.
 * -------------------------------------------------------------------------- */

[data-fx-flow="running"] .fx-core {
  stroke-dasharray: 7 11;
  animation: fx-march 0.85s linear infinite;
}

@keyframes fx-march {
  to { stroke-dashoffset: -18; }   /* 7 + 11 */
}

.fx-pulses {
  transition: opacity 0.35s;
}

/* O pulso e a bolinha verde viajando. Mesma regra do bead: mint no centro,
 * primary nas sombras. */
.fx-pulse {
  fill: var(--fx-core);
  filter: drop-shadow(0 0 6px var(--fx)) drop-shadow(0 0 16px var(--fx));
}

/* PARADO NAO ANIMA. A referencia e categorica e ela esta certa: "movimento so
 * quando algo esta de fato acontecendo — animacao em estado parado mente pro
 * usuario". Num site institucional isso vale ainda mais: nao ha job rodando,
 * entao o fluxo so anda quando esta na tela, e para quando sai. */
[data-fx-flow]:not([data-fx-flow="running"]) .fx-core {
  animation: none;
  stroke-dasharray: none;
  opacity: 0.7;
}

[data-fx-flow]:not([data-fx-flow="running"]) .fx-pulses {
  opacity: 0;
}

/* Estado apagado: troca as VARIAVEIS, nao as regras. Cinza da propria paleta,
 * nunca um cinza novo. */
/* O APAGADO CONTINUA VERDE.
 *
 * A primeira versao punha `--fx-core: var(--fx-off)`, e sobre fundo escuro o
 * `--fx-off` e branco a 38% — ou seja, a bolinha APAGADA ficava esbranquicada.
 * O dono disse "a bolinha branca deve ser verde" e nao abriu excecao para o
 * estado off; nao cabe a mim abrir.
 *
 * Achado pela equipe do /solutions. O fio pode empalidecer (ele e estrutura),
 * mas o nucleo permanece na familia do verde, so escurecido: `color-mix` a 45%
 * sobre transparente da um verde visivelmente desligado, sem virar cinza e sem
 * virar branco. */
[data-fx-flow="idle"] {
  --fx: var(--fx-off);
  --fx-core: color-mix(in srgb, var(--gs-primary) 45%, transparent);
}

[data-fx-flow="idle"] .fx-halo,
[data-fx-flow="idle"] .fx-glow {
  opacity: 0.05;
}

/* =============================================================================
 * CAPILARIDADE — os fios com bolinhas
 * =============================================================================
 * O dono foi especifico: gostou dos "fios capilares" e das bolinhas, e
 * desconfiou do BURST inteiro ("talvez o burst nao caia bem"). Ele esta certo.
 *
 * O burst da referencia e um leque de 34 tracos saindo de um nucleo aceso, com
 * um `core-glow` pulsando por cima. Naquele contexto — demo de efeito, tela
 * cheia, fundo roxo — funciona. Num site institucional ele compete com o
 * conteudo: o olho vai para o ponto de luz, nao para o titulo.
 *
 * Entao o que entra aqui e o TECIDO, sem o nucleo:
 *   - os fios continuam sendo curvas quadraticas com controle na PERPENDICULAR
 *     (e isso que faz leque penteado em vez de estrela);
 *   - continuam nascendo opacos e morrendo transparentes;
 *   - as bolinhas continuam percorrendo o mesmo path;
 *   - NAO ha ponto de origem aceso, NAO ha `core-glow` pulsando, e a opacidade
 *     geral cai para um terco.
 *
 * Resultado: textura de fundo que se percebe sem se olhar. Se o dono quiser o
 * burst completo em algum lugar, e ligar `data-fx-burst="full"` — a marcacao
 * ja suporta, e a regra esta abaixo.
 * -------------------------------------------------------------------------- */

/* ⚠️ O CAMPO PRECISA DE UM HOSPEDEIRO. Ponha `.fx-host` na seção que o contém.
 *
 * Sem isso o campo TAPA O TEXTO, e de um jeito que parece bug de layout: ele é
 * `position:absolute`, e elemento posicionado pinta acima de qualquer irmão NÃO
 * posicionado, mesmo com `z-index:0`. O título e os botões da seção somem atrás
 * de uma teia de fios e ninguém entende por quê.
 *
 * Achado pela equipe do /resources, que teve de escrever o remendo à mão. O
 * remendo é o certo — errado era cada página ter de descobrir isso sozinha.
 *
 * `isolation: isolate` fecha um contexto de empilhamento próprio: o
 * `mix-blend-mode: screen` das camadas passa a somar luz só com o fundo DESTA
 * seção, e não com o que estiver atrás dela na página. */
.fx-host {
  position: relative;
  isolation: isolate;
}

/* ⚠️ EMPURRA O CAMPO PARA TRAS, NAO O CONTEUDO PARA A FRENTE.
 *
 * A primeira versao subia os irmaos: `.fx-host > :not(.fx-field) { position:
 * relative; z-index: 1 }`. Funcionava no caso simples e QUEBRAVA o herói do
 * /platform — medido a 1600x900: a secao crescia de 618 para 918px, a
 * decoracao de brilho radial saía de `absolute z:-1` para `relative z:1` e
 * passava a pintar um circulo borrado de 300px POR CIMA do h1, e a grade de
 * pontos colapsava para altura zero.
 *
 * A causa e especificidade: `.fx-host > :not(.fx-field)` vale (0,2,0) e vence
 * as utilitarias `.absolute` e `.z-[-1]` do Tailwind, que estavam ali de
 * proposito. Uma regra do sistema nao pode desautorizar o posicionamento que a
 * pagina declarou.
 *
 * Como `.fx-host` ja isola o contexto, mandar o CAMPO para tras chega no mesmo
 * lugar e nao toca em irmao nenhum. Achado e solucao da equipe do /platform. */
.fx-host > .fx-field {
  z-index: -1;
}

.fx-field {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* O CINTILAR E CSS, E `pauseAnimations()` NAO O ALCANCA.
 *
 * O relogio do SVG para o SMIL — as bolinhas que viajam. As bolinhas PARADAS
 * cintilam por `@keyframes`, que e CSS, e seguiam piscando com o campo pausado
 * e fora da tela. Achado pela equipe do /platform: nove delas apareciam em
 * toda amostra de rolagem.
 *
 * O observador agora carimba `data-fx-visible` no campo, e o CSS desliga o
 * cintilar quando ele nao esta. */
[data-fx-field][data-fx-visible="false"] .fx-twinkle {
  animation-play-state: paused;
}

.fx-field svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* O tecido, contido: um terco da intensidade do demo. */
.fx-field-layer {
  mix-blend-mode: screen;
  opacity: 0.34;
}

.fx-thread {
  fill: none;
  stroke: url(#fxFade);
  stroke-linecap: round;
}

.fx-dot {
  fill: var(--fx-core);
}

.fx-dot-dim {
  fill: var(--fx);
}

/* Cintilar dessincronizado: o `animation-delay` negativo por elemento vem do
 * JS, para as bolinhas nunca piscarem em bloco. */
.fx-twinkle {
  animation: fx-twinkle 3.2s ease-in-out infinite;
}

@keyframes fx-twinkle {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}

/* O burst COMPLETO, com nucleo aceso — desligado por padrao. So existe para o
 * dono poder ligar num lugar especifico e ver. Nao use em duas telas. */
[data-fx-burst="full"] .fx-field-layer {
  opacity: 0.85;
}

[data-fx-burst="full"] .fx-core-glow {
  display: block;
}

.fx-core-glow {
  display: none;
  position: absolute;
  width: 36%;
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%);
  mix-blend-mode: screen;
  filter: blur(2px);
  background: radial-gradient(circle,
    var(--gs-mint) 0%,
    var(--fx-core) 16%,
    var(--fx) 30%,
    color-mix(in srgb, var(--fx) 33%, transparent) 48%,
    transparent 68%);
  animation: fx-breathe 4.6s ease-in-out infinite;
}

@keyframes fx-breathe {
  0%, 100% { opacity: 0.85; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;    transform: translate(-50%, -50%) scale(1.08); }
}

/* =============================================================================
 * MOVIMENTO REDUZIDO
 * =============================================================================
 * Nao basta parar a animacao: um tracejado congelado no meio da marcha fica
 * com o padrao cortado em lugar arbitrario. Aqui ele volta a ser linha inteira,
 * que e o estado de repouso correto.
 * -------------------------------------------------------------------------- */

/* ⚠️ ESTE BLOCO SOZINHO NAO BASTA, e e importante saber por que.
 *
 * As bolinhas que viajam pelos fios sao SMIL (`<animateMotion>`), e **CSS nao
 * para SMIL**. Nem `animation: none`, nem este media query, nem `display` num
 * ancestral interrompem um `animateMotion` — ele continua andando e continua
 * custando frame. A unica alavanca e o DOM do SVG: `svg.pauseAnimations()`,
 * que o `efeitos.js` chama.
 *
 * O que fica aqui e o que E CSS: o cintilar, o respiro do nucleo, a marcha do
 * tracejado e os pulsos. Achado pela equipe do /white-label, medindo — nao era
 * teoria: 28 bolinhas seguiam viajando com movimento reduzido ligado. */
@media (prefers-reduced-motion: reduce) {
  .fx-twinkle,
  .fx-core-glow,
  [data-fx-flow="running"] .fx-core {
    animation: none !important;
  }

  [data-fx-flow="running"] .fx-core {
    stroke-dasharray: none;
  }

  .fx-pulses {
    opacity: 0;
  }
}
