/* fx-web.css: efeitos de site da sitesenior (portados do fx-site do edit-machine, agora movidos por scroll/hover/tempo).
   Trocar as cores em :root pelas da marca. Movimento: fx-web.js. Cardápio: references/efeitos-web.md */
:root { --fx-brand: #FF8A1F; --fx-brand-2: #7b5cff; --fx-light: rgba(255,255,255,.22); }

/* Entrada e saída de texto (regra da casa). JS põe .is-in ao entrar e .is-out quando o leitor já passou */
.fx-io { transition: opacity .5s cubic-bezier(0.33,1,0.68,1), transform .6s cubic-bezier(0.33,1,0.68,1), filter .5s; }
.fx-on .fx-io:not(.is-in) { opacity: 0; transform: translateY(32px); } /* .fx-on: sem JS o texto continua visível */
.fx-io.is-out { opacity: .2; transform: translateY(-24px); filter: blur(3px);
  transition-timing-function: cubic-bezier(0.11,0,0.5,0); transition-duration: .45s; }
/* data-fx-split: cada palavra/linha numa máscara */
.fx-w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .12em; margin-bottom: -.12em; /* não corta g j p */ padding-inline: .08em; margin-inline: -.08em; /* nem a última letra em título com tracking negativo */ }
.fx-w > span { display: inline-block; transform: translateY(105%); transition: transform .6s cubic-bezier(0.33,1,0.68,1); transition-delay: var(--d, 0ms); }
.fx-on .fx-io[data-fx-split]:not(.is-in) { opacity: 1; transform: none; }
.fx-io.is-in .fx-w > span { transform: none; }
/* data-fx-split="letras": letras caindo girando. Só título curto; acima de 32 caracteres o JS cai pra palavra */
.fx-pal { display: inline-block; white-space: nowrap; }
.fx-l { display: inline-block; opacity: 0; transform: translateY(-.8em) rotate(var(--r, 0deg));
  transition: transform .7s cubic-bezier(0.16,1,0.3,1), opacity .25s linear; transition-delay: var(--d, 0ms); }
.fx-io.is-in .fx-l { opacity: 1; transform: none; }

/* Spotlight (Aceternity): luz segue o mouse no card. card com position:relative + overflow:hidden */
.fx-spot { position: relative; overflow: hidden; --sx: 50%; --sy: -20%; }
.fx-spot::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; opacity: 0; transition: opacity .3s;
  background: radial-gradient(420px circle at var(--sx) var(--sy), var(--fx-light), transparent 60%); }
.fx-spot:hover::after { opacity: 1; }

/* Border beam (Magic UI): cometa de luz girando na borda */
@property --ba { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.fx-beam { position: relative; --bw: 2px; }
.fx-beam::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: var(--bw); pointer-events: none; z-index: 2;
  background: conic-gradient(from var(--ba), transparent 0 70%, var(--fx-brand) 88%, #fff 92%, transparent 94%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude;
  animation: fx-beam 6s linear infinite; }
@keyframes fx-beam { to { --ba: 360deg; } }

/* Aurora text: gradiente escorrendo dentro das letras. Só frase-assinatura, nunca texto corrido */
.fx-aurora { background: linear-gradient(100deg, var(--fx-brand), #ffd166, var(--fx-brand-2), #19d3f0, var(--fx-brand)) 0 50% / 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent; animation: fx-aurora 8s linear infinite; }
@keyframes fx-aurora { to { background-position: 300% 50%; } }

/* Shimmer: brilho atravessa o botão no hover e uma vez a cada 5 s */
.fx-shimmer { position: relative; overflow: clip; }
.fx-shimmer::after { content: ""; position: absolute; top: -20%; bottom: -20%; width: 40%; left: -60%; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.55), transparent); transform: skewX(-18deg); animation: fx-shimmer 5s cubic-bezier(0.65,0,0.35,1) infinite; }
.fx-shimmer:hover::after { animation-duration: .9s; }
@keyframes fx-shimmer { 0%, 80% { translate: 0 0; } 100% { translate: 550% 0; } } /* 550% da própria largura = atravessa o botão, sem refazer layout */

/* Marquee: janela .fx-marquee > trilha .fx-track (JS duplica o conteúdo). Pausa no hover */
.fx-marquee { overflow: hidden; -webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.fx-track { display: flex; gap: 28px; width: max-content; white-space: nowrap; animation: fx-marquee var(--dur, 30s) linear infinite; }
.fx-track > * { flex: none; }
.fx-marquee:hover .fx-track { animation-play-state: paused; }
@keyframes fx-marquee { to { transform: translateX(calc(-50% - 14px)); } }

/* Odômetro / Number Flow (Details): <span class="fx-odo" data-to="1250" data-format="pt">0</span> */
.fx-odo { display: inline-flex; font-variant-numeric: tabular-nums; line-height: 1; }
.fx-odo-c { display: inline-block; height: 1em; overflow: hidden; }
.fx-odo-s { display: flex; flex-direction: column; transition: transform 1.1s cubic-bezier(0.16,1,0.3,1); transition-delay: var(--d, 0ms); }
.fx-odo-s b { display: block; height: 1em; font-weight: inherit; }

/* Card 3D: pai .fx-persp, card .fx-tilt. Só em mouse (JS ignora toque) */
.fx-persp { perspective: 1200px; }
.fx-tilt { position: relative; transform-style: preserve-3d; --gx: 50%; transition: transform .5s cubic-bezier(0.33,1,0.68,1); }
.fx-tilt::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(115deg, transparent calc(var(--gx) - 25%), rgba(255,255,255,.14) var(--gx), transparent calc(var(--gx) + 25%)); }

/* Animated beam (Magic UI): <path class="fx-wire"> + mesmo d em <path class="fx-pulse" pathLength="1"> */
.fx-wire { fill: none; stroke: rgba(127,127,127,.25); stroke-width: 2; }
.fx-pulse { fill: none; stroke: var(--fx-brand); stroke-width: 3; stroke-linecap: round; stroke-dasharray: .2 1.2; stroke-dashoffset: .2;
  filter: drop-shadow(0 0 6px var(--fx-brand)); animation: fx-pulse 2.6s cubic-bezier(0.65,0,0.35,1) infinite; animation-delay: var(--d, 0s); }
@keyframes fx-pulse { to { stroke-dashoffset: -1; } }

/* Text reveal por varredura ligada ao scroll: JS anima --rv de -20% a 120% */
.fx-reveal { --rv: -20%; -webkit-mask: linear-gradient(90deg, #000 calc(var(--rv) - 10%), rgba(0,0,0,.15) calc(var(--rv) + 10%)); mask: linear-gradient(90deg, #000 calc(var(--rv) - 10%), rgba(0,0,0,.15) calc(var(--rv) + 10%)); }

/* Progressive blur (Details Vault): estático, colocar por cima da borda de lista/tela (top/bottom:0) */
.fx-pblur { position: absolute; left: 0; right: 0; height: 160px; pointer-events: none; }
.fx-pblur > i { position: absolute; inset: 0; }
.fx-pblur > i:nth-child(1) { backdrop-filter: blur(2px);  -webkit-mask: linear-gradient(transparent 0%, #000 25%); mask: linear-gradient(transparent 0%, #000 25%); }
.fx-pblur > i:nth-child(2) { backdrop-filter: blur(6px);  -webkit-mask: linear-gradient(transparent 25%, #000 55%); mask: linear-gradient(transparent 25%, #000 55%); }
.fx-pblur > i:nth-child(3) { backdrop-filter: blur(14px); -webkit-mask: linear-gradient(transparent 55%, #000 90%); mask: linear-gradient(transparent 55%, #000 90%); }

/* Meteoros: host position:relative overflow:hidden com data-fx-meteors="12" */
.fx-meteor { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #fff; box-shadow: 0 0 8px 2px rgba(255,255,255,.5);
  animation: fx-meteor var(--life, 3s) linear infinite; animation-delay: var(--d, 0s); opacity: 0; }
.fx-meteor::after { content: ""; position: absolute; top: 0; left: 1px; width: 160px; height: 1px; transform-origin: 0 50%; transform: rotate(-45deg);
  background: linear-gradient(90deg, rgba(255,255,255,.6), transparent); }
@keyframes fx-meteor { 0% { opacity: 0; transform: translate(0,0); } 8% { opacity: 1; } 70% { opacity: 1; } 100% { opacity: 0; transform: translate(-600px, 600px); } }

/* Shader de fundo: <canvas class="fx-shader" data-fx-shader="#id-do-script-glsl"> */
.fx-shader { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ===== DOBRAS: tudo lê --p (0 a 1), escrito pelo motor data-fx-scrub do JS. Sem JS, --p assume 1 e fica tudo aberto ===== */
/* Abertura da dobra. Pôr num filho e deixar no pai o fundo da seção anterior, senão aparece o fundo do body */
.fx-d-clip { clip-path: inset(calc((1 - var(--p, 1)) * 14%) calc((1 - var(--p, 1)) * 8%) round calc((1 - var(--p, 1)) * 32px)); }
.fx-d-circulo { clip-path: circle(calc(var(--p, 1) * 150%) at var(--ox, 50%) var(--oy, 100%)); }
.fx-d-diagonal { clip-path: polygon(0 calc((1 - var(--p, 1)) * 100%), 100% calc((1 - var(--p, 1)) * 40%), 100% 100%, 0 100%); }
.fx-d-cortina { -webkit-mask: repeating-linear-gradient(90deg, #000 0 calc(var(--p, 1) * 12.5%), transparent calc(var(--p, 1) * 12.5%) 12.5%); mask: repeating-linear-gradient(90deg, #000 0 calc(var(--p, 1) * 12.5%), transparent calc(var(--p, 1) * 12.5%) 12.5%); }
/* Base curva: a seção sai com a base arredondando por cima da próxima. Modo cruza */
.fx-d-curva { position: relative; z-index: 1; --c: calc(clamp(0, var(--p, 0) * 2 - 1, 1) * 9vw); border-radius: 0 0 50% 50% / 0 0 var(--c) var(--c); }
.fx-d-curva + * { margin-top: -9vw; padding-top: 9vw; }

/* Painéis empilhando: .fx-pilha > .fx-painel[data-fx-scrub="sai"] > .fx-painel-in. Painel alto rola inteiro antes de parar (JS ajusta o top). Ancestral sem overflow:hidden */
.fx-painel { position: sticky; top: var(--t, 0); overflow: clip; }
.fx-painel + .fx-painel { border-radius: 28px 28px 0 0; }
.fx-painel-in { position: relative; transform-origin: 50% 0; transform: scale(calc(1 - var(--p, 0) * .05)); }
.fx-painel-in::after { content: ""; position: absolute; inset: 0; background: #000; opacity: calc(var(--p, 0) * .45); pointer-events: none; }

/* Mergulho: .fx-mergulho[data-fx-scrub="pin"] > .fx-mergulho-palco > (.fx-mergulho-janela > img|video) + .fx-mergulho-txt. Rolagem natural, sem sequestro */
.fx-on .fx-mergulho { height: 220svh; }
.fx-mergulho-palco { display: grid; place-items: center; min-height: 100svh; overflow: hidden; }
.fx-on .fx-mergulho-palco { position: sticky; top: 0; height: 100svh; }
.fx-mergulho-palco > * { grid-area: 1 / 1; }
.fx-mergulho-janela { width: 100%; height: 100%; clip-path: inset(calc((1 - var(--p, 1)) * 32%) calc((1 - var(--p, 1)) * 34%) round calc((1 - var(--p, 1)) * 28px)); }
.fx-mergulho-janela > * { display: block; width: 100%; height: 100%; object-fit: cover; transform: scale(calc(1.18 - var(--p, 1) * .18)); }
.fx-mergulho-txt { position: relative; opacity: clamp(0, calc(var(--p, 1) * 3 - 2), 1); text-align: center; }

/* Cena em passos: .fx-cena[data-fx-passos] > .fx-cena-palco > [data-passo]. Cada passo ocupa uma tela de rolagem. Sem JS vira lista normal */
.fx-on .fx-cena { height: calc(var(--n, 3) * 100svh); }
.fx-on .fx-cena-palco { position: sticky; top: 0; height: 100svh; overflow: hidden; display: grid; place-items: center; }
.fx-on .fx-cena-palco > [data-passo] { grid-area: 1 / 1; opacity: 0; transform: translateY(28px); transition: opacity .3s cubic-bezier(0.65,0,0.35,1), transform .55s cubic-bezier(0.33,1,0.68,1); }
.fx-on .fx-cena-palco > [data-passo].is-on { opacity: 1; transform: none; }

/* Troca de tema: data-fx-tema="#fundo|#texto" nas seções (seção sem fundo próprio) */
.fx-tema-on body { background: var(--fx-bg); color: var(--fx-fg); transition: background-color .6s cubic-bezier(0.65,0,0.35,1), color .6s cubic-bezier(0.65,0,0.35,1); }

/* Traço desenhando com a rolagem: <path pathLength="1" class="fx-draw" data-fx-scrub="entra"> */
.fx-on .fx-draw { fill: none; stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--p, 0)); }

/* Faixa correndo com a rolagem: janela .fx-faixa (fullbleed, sem barra lateral), filho .fx-corre[data-fx-scrub="cruza"] com --corre:-20vw */
.fx-faixa { overflow: clip; }
.fx-corre { width: max-content; translate: calc((var(--p, .5) - .5) * var(--corre, -20vw)) 0; }

/* Parágrafo que acende palavra a palavra: data-fx-acende. Bom em texto centralizado, onde .fx-reveal corta estranho */
.fx-acende > span { opacity: calc(.18 + .82 * clamp(0, calc(var(--p, 1) * var(--n) - var(--i)), 1)); }

/* Palavra que troca: <span data-fx-troca="uma|outra">. A largura é a da palavra mais longa, então nada pula */
[data-fx-troca] { display: inline-grid; justify-items: center; }
.fx-troca-w { grid-area: 1 / 1; white-space: nowrap; opacity: 0; transform: translateY(.5em); transition: opacity .25s linear, transform .5s cubic-bezier(0.33,1,0.68,1); }
.fx-troca-w.is-on { opacity: 1; transform: none; }

/* Marca-texto que passa quando entra na tela: <span class="fx-marca" data-fx-ver> */
.fx-marca { background: linear-gradient(var(--fx-brand), var(--fx-brand)) 50% 88% / 100% .32em no-repeat; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.fx-on .fx-marca { background-size: 0 .32em; transition: background-size .7s cubic-bezier(0.33,1,0.68,1); }
.fx-on .fx-marca.is-in { background-size: 100% .32em; }

/* Botão magnético: .fx-mag. Usa translate pra não brigar com transform de outro efeito */
.fx-mag { transition: translate .45s cubic-bezier(0.16,1,0.3,1); }

/* Menu suspenso animado: <details class="fx-acc" name="grupo">. Navegador sem suporte abre sem animar, e continua funcionando */
.fx-acc > summary { cursor: pointer; list-style: none; }
.fx-acc > summary::-webkit-details-marker { display: none; }
@supports (interpolate-size: allow-keywords) {
  .fx-acc { interpolate-size: allow-keywords; }
  .fx-acc::details-content { height: 0; overflow: clip; transition: height .4s cubic-bezier(0.33,1,0.68,1), content-visibility .4s allow-discrete; }
  .fx-acc[open]::details-content { height: auto; }
}

/* Letreiro que preenche a régua: <div><span data-fx-fit>PALAVRA</span></div> */
[data-fx-fit] { display: inline-block; white-space: nowrap; line-height: .95; }

@media (prefers-reduced-motion: reduce) {
  .fx-io, .fx-io.is-out, .fx-w > span, .fx-l, .fx-troca-w { transition: opacity .2s !important; transform: none !important; filter: none !important; }
  .fx-beam::before, .fx-aurora, .fx-shimmer::after, .fx-track, .fx-pulse, .fx-meteor { animation: none !important; }
  .fx-corre, .fx-mag { translate: none !important; }
  .fx-painel-in, .fx-mergulho-janela > * { transform: none !important; }
  .fx-on .fx-marca, .fx-acc::details-content, .fx-tema-on body { transition: none !important; }
}
