/*!
 * Infinity Ventiladores – Tech UI (microefeitos "tech", CSS puro + /static/js/fx/tech-ui.js)
 * Inspirado/adaptado de React Bits (https://reactbits.dev) – licença MIT + Commons Clause
 * Copyright (c) 2026 David Haz. Aviso de licença completo no topo de /static/js/fx/tech-ui.js.
 * Carregue DEPOIS de site.css. Elementos decorativos são abstratos (luz, linhas, cantos):
 * nada aqui desenha produto e nada é aplicado sobre fotos (efeitos ficam atrás do conteúdo).
 */

/* ------------------------------------------------ fonte mono (local) */
/* um só peso (500): textos mono em 400 usam a mesma face (um arquivo a menos para baixar) */
@font-face {
  font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(/static/fonts/jetbrains-mono-latin-500-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --fx-ease: cubic-bezier(.2, .7, .2, 1);
  --fx-mono: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Inter', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --fx-cyan: #24b6cd;
}

.fx-sr { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* ------------------------------------------------ [data-reveal-stagger] – filhos entram em sequência
   Sem JS (ou com erro) nada fica escondido: as regras só valem com html.fx-js. */
@media (prefers-reduced-motion: no-preference) {
  html.fx-js [data-reveal-stagger]:not(.is-in) > * { opacity: 0; translate: 0 var(--fx-dist, 18px); }
  html.fx-js [data-reveal-stagger].is-in:not(.is-done) > * {
    transition: opacity .6s var(--fx-ease) calc(var(--fx-i, 0) * var(--fx-step, 90ms)),
                translate .75s var(--fx-ease) calc(var(--fx-i, 0) * var(--fx-step, 90ms));
  }
}

/* ------------------------------------------------ [data-decrypt] / [data-countup] */
.is-decrypting { font-kerning: none; }
[data-countup] { font-variant-numeric: tabular-nums; }
.fx-count-vis { display: inline-block; text-align: end; white-space: nowrap; }

/* ------------------------------------------------ [data-spotlight] – brilho que segue o cursor (SpotlightCard)
   O brilho fica ATRÁS do conteúdo (z-index -1 dentro do próprio cartão); a borda luminosa é só um anel de 1px. */
:where([data-spotlight]) { position: relative; isolation: isolate; }
[data-spotlight] { --mx: 50%; --my: 50%; }
[data-spotlight]::before,
[data-spotlight]::after { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .45s ease; }
[data-spotlight]::before {
  z-index: -1;
  background: radial-gradient(var(--spot-size, 380px) circle at var(--mx) var(--my), var(--spot-color, rgba(36, 182, 205, .16)), transparent 70%);
}
[data-spotlight]::after {
  padding: var(--spot-ring-w, 1px);
  background: radial-gradient(var(--spot-ring-size, 240px) circle at var(--mx) var(--my), var(--spot-ring, rgba(36, 182, 205, .75)), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
@media (hover: hover) {
  [data-spotlight]:hover::before, [data-spotlight]:hover::after { opacity: 1; }
}
[data-spotlight]:focus-within::before, [data-spotlight]:focus-within::after { opacity: 1; }
.on-dark[data-spotlight], .on-dark [data-spotlight] { --spot-color: rgba(36, 182, 205, .2); --spot-ring: rgba(127, 211, 234, .8); }

/* ------------------------------------------------ [data-tilt] – inclinação 3D + reflexo especular (TiltedCard) */
:where([data-tilt]) { position: relative; }
[data-tilt].is-tilting { will-change: transform; }
[data-tilt]:not([data-spotlight]):not([data-tilt-glare="false"])::after {
  content: ''; position: absolute; inset: 0; z-index: 3; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 50%), var(--tilt-glare, rgba(255, 255, 255, .16)), transparent 60%);
  opacity: var(--glare, 0); transition: opacity .35s ease;
}

/* ------------------------------------------------ [data-velocity-marquee] – faixa infinita (ScrollVelocity)
   Sem JS / movimento reduzido: faixa estática com rolagem horizontal (todo o conteúdo acessível). */
[data-velocity-marquee] {
  --vm-gap: 2.5rem; --vm-fade: 56px;
  display: flex; align-items: center; gap: var(--vm-gap); max-width: 100%; min-width: 0;
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scrollbar-width: thin; scrollbar-color: rgba(143, 227, 240, .35) transparent;
  white-space: nowrap;
}
[data-velocity-marquee]::-webkit-scrollbar { height: 4px; }
[data-velocity-marquee]::-webkit-scrollbar-thumb { border-radius: 4px; background: rgba(143, 227, 240, .35); }
/* com botão de pausa: altura do botão reservada desde o HTML (montar não muda o tamanho da faixa) */
[data-velocity-marquee][data-velocity-pause-button] { min-height: 44px; }
:where([data-velocity-marquee]) { position: relative; }
[data-velocity-marquee] > * { flex: none; }
/* montado: o hospedeiro continua o mesmo contêiner de rolagem (overflow igual antes e depois).
   Trocar para overflow: visible fazia o Chrome registrar um "salto" de layout enorme (CLS ~0,55);
   nada transborda, pois .vm-view já corta a trilha. */
.vm-view {
  width: 100%; min-width: 0; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--vm-fade), #000 calc(100% - var(--vm-fade)), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 var(--vm-fade), #000 calc(100% - var(--vm-fade)), transparent);
}
.vm-track { display: flex; width: max-content; will-change: transform; }
.vm-group { display: flex; flex: none; align-items: center; gap: var(--vm-gap); padding-right: var(--vm-gap); }
.vm-group > * { flex: none; }
.vm-reduced .vm-view { overflow-x: auto; } /* reduzido ligado com a faixa já montada */
.vm-reduced .vm-clone, .vm-reduced .vm-toggle { display: none; }
.vm-reduced .vm-track { transform: none !important; }
/* movimento reduzido: faixa estática quebrando em linhas (sem barra de rolagem e sem item cortado);
   pela media query vale desde a 1ª pintura, sem esperar o JS */
@media (prefers-reduced-motion: reduce) {
  [data-velocity-marquee]:not(.vm-on) { flex-wrap: wrap; justify-content: center; row-gap: 10px; overflow: visible; white-space: normal; }
}
.vm-toggle {
  position: absolute; right: 6px; top: 50%; translate: 0 -50%; z-index: 2;
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0; border-radius: 50%;
  border: 1px solid rgba(127, 211, 234, .5); background: rgba(11, 29, 47, .82); color: #fff; cursor: pointer;
}
.vm-toggle::before { content: ''; width: 10px; height: 12px; box-sizing: border-box; border-left: 3px solid currentColor; border-right: 3px solid currentColor; }
.vm-toggle[aria-pressed="true"]::before { width: 0; height: 0; margin-left: 3px; border-style: solid; border-width: 6px 0 6px 10px; border-color: transparent transparent transparent currentColor; }
.vm-toggle:hover { background: #0b1d2f; border-color: #7fd3ea; }
.vm-toggle:focus-visible { outline: 3px solid rgba(36, 182, 205, .6); outline-offset: 2px; }
/* toque: alvo de 44 px (o contorno de foco fica por dentro, a faixa corta o que passa da altura) */
@media (pointer: coarse), (max-width: 1024px) { .vm-toggle { width: 44px; height: 44px; } .vm-toggle:focus-visible { outline-offset: -4px; } }

/* ------------------------------------------------ .shiny-text – brilho que atravessa o texto (ShinyText)
   Base = cor atual a 68% (contraste AA preservado); faixa de brilho = cor cheia. */
.shiny-text { --shiny-speed: 3.2s; --shiny-spread: 120deg; }
@supports (color: color-mix(in srgb, red 50%, blue)) and ((-webkit-background-clip: text) or (background-clip: text)) {
  .shiny-text {
    --shiny-color: color-mix(in srgb, currentColor 68%, transparent);
    --shiny-shine: currentColor;
    background-image: linear-gradient(var(--shiny-spread), var(--shiny-color) 0%, var(--shiny-color) 35%, var(--shiny-shine) 50%, var(--shiny-color) 65%, var(--shiny-color) 100%);
    background-size: 200% auto; background-position: 150% center;
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    animation: fx-shine var(--shiny-speed) linear infinite;
  }
  .shiny-text.is-cyan { --shiny-shine: #8fdcec; }
  .shiny-text.is-gold { --shiny-shine: #e7d3a4; }
}
@keyframes fx-shine { 0% { background-position: 150% center; } 75%, 100% { background-position: -50% center; } }

/* ------------------------------------------------ .gradient-text – gradiente animado (GradientText)
   Paletas com contraste AA: padrão (fundo claro), .on-dark (fundo navy), .is-gold (+ .on-dark). */
.gradient-text { --gt-1: #0d4a79; --gt-2: #1569ab; --gt-3: #1673b0; --gt-speed: 8s; color: var(--gt-2); }
.gradient-text.on-dark, .on-dark .gradient-text { --gt-1: #24b6cd; --gt-2: #8fdcec; --gt-3: #5fd0e6; }
.gradient-text.is-gold { --gt-1: #8a6a2e; --gt-2: #6f5524; --gt-3: #7d6029; }
.gradient-text.is-gold.on-dark, .on-dark .gradient-text.is-gold { --gt-1: #c9a65e; --gt-2: #e7d3a4; --gt-3: #d9bb72; }
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .gradient-text {
    background-image: linear-gradient(to right, var(--gt-1), var(--gt-2), var(--gt-3), var(--gt-1));
    background-size: 300% 100%; background-position: 0% 50%;
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    animation: fx-gradient var(--gt-speed) ease-in-out infinite alternate;
  }
}
@keyframes fx-gradient { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }

/* ------------------------------------------------ .star-border – luz orbitando a borda (StarBorder)
   Duas "estrelas" opostas giram pelo contorno (conic-gradient + máscara), em qualquer elemento com border-radius. */
@property --sb-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.star-border { --sb-color: #24b6cd; --sb-head: #e6f8fc; --sb-speed: 6s; --sb-width: 1.5px; }
:where(.star-border) { position: relative; isolation: isolate; }
.star-border::before {
  content: ''; position: absolute; inset: var(--sb-inset, -1px); z-index: 1; border-radius: inherit; padding: var(--sb-width); pointer-events: none;
  background: repeating-conic-gradient(from var(--sb-angle), transparent 0% 28%, var(--sb-color) 45%, var(--sb-head) 49%, transparent 50%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  animation: fx-orbit var(--sb-speed) linear infinite;
}
.star-border.is-gold { --sb-color: #c9a65e; --sb-head: #f7f0e2; }
@keyframes fx-orbit { to { --sb-angle: 360deg; } }

/* ------------------------------------------------ .hud-frame – colchetes nos 4 cantos (camadas de fundo, sem pseudo-elementos)
   Substitui background-image do elemento; para manter um gradiente próprio use --hud-under. */
.hud-frame {
  --hud-c: rgba(36, 182, 205, .8); --hud-len: 14px; --hud-w: 1.5px; --hud-in: 8px;
  background-image:
    linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0),
    linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0), linear-gradient(var(--hud-c) 0 0),
    var(--hud-under, none);
  background-repeat: no-repeat;
  background-size:
    var(--hud-len) var(--hud-w), var(--hud-w) var(--hud-len), var(--hud-len) var(--hud-w), var(--hud-w) var(--hud-len),
    var(--hud-len) var(--hud-w), var(--hud-w) var(--hud-len), var(--hud-len) var(--hud-w), var(--hud-w) var(--hud-len),
    100% 100%;
  background-position:
    left var(--hud-in) top var(--hud-in), left var(--hud-in) top var(--hud-in),
    right var(--hud-in) top var(--hud-in), right var(--hud-in) top var(--hud-in),
    left var(--hud-in) bottom var(--hud-in), left var(--hud-in) bottom var(--hud-in),
    right var(--hud-in) bottom var(--hud-in), right var(--hud-in) bottom var(--hud-in),
    0 0;
}
.hud-frame.is-gold { --hud-c: rgba(201, 166, 94, .85); }
.hud-frame.is-subtle { --hud-c: rgba(21, 105, 171, .45); }

/* ------------------------------------------------ .scanlines – linhas horizontais sutis (atrás do conteúdo)
   .is-animated adiciona uma faixa de varredura lenta; .on-light para fundos claros. Não use sobre fotos. */
:where(.scanlines) { position: relative; isolation: isolate; }
.scanlines::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: repeating-linear-gradient(180deg, var(--scan-c, rgba(255, 255, 255, .045)) 0 1px, transparent 1px var(--scan-gap, 4px));
}
.scanlines.on-light { --scan-c: rgba(12, 32, 51, .035); --scan-band: rgba(21, 105, 171, .05); }
.scanlines.is-animated::before {
  background-image:
    linear-gradient(180deg, transparent, var(--scan-band, rgba(36, 182, 205, .07)), transparent),
    repeating-linear-gradient(180deg, var(--scan-c, rgba(255, 255, 255, .045)) 0 1px, transparent 1px var(--scan-gap, 4px));
  background-size: 100% 28%, auto; background-repeat: no-repeat, repeat;
  animation: fx-scan 9s linear infinite;
}
@keyframes fx-scan { from { background-position: 0 -40%, 0 0; } to { background-position: 0 140%, 0 0; } }

/* ------------------------------------------------ .mono-label – rótulo técnico */
.mono-label {
  display: inline-flex; align-items: center; gap: .6em;
  font: 500 .75rem/1.35 var(--fx-mono); letter-spacing: .14em; text-transform: uppercase; font-variant-numeric: tabular-nums;
  color: var(--mono-c, #1569ab);
}
.mono-label.on-dark { --mono-c: #7fd3ea; }
.mono-label.is-muted { --mono-c: #5b6d80; }
.mono-label.is-muted.on-dark { --mono-c: #a9bccd; }
.mono-label.is-gold { --mono-c: #8a6a2e; }
.mono-label.is-gold.on-dark { --mono-c: #e7d3a4; }
.mono-label.has-dot::before { content: ''; flex: none; width: .5em; height: .5em; border-radius: 50%; background: currentColor; animation: fx-ping 2.4s var(--fx-ease) infinite; }
@keyframes fx-ping { 0% { box-shadow: 0 0 0 0 currentColor; } 70%, 100% { box-shadow: 0 0 0 .55em transparent; } }
.mono { font-family: var(--fx-mono); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------ pausa fora da tela (classe pelo JS), com a aba oculta
   e com "Pausar animações" (html.fx-paused, TechUI.pause) */
.fx-off, .fx-off::before, .fx-off::after,
html:is(.fx-tab-hidden, .fx-paused) :is(.shiny-text, .gradient-text),
html:is(.fx-tab-hidden, .fx-paused) :is(.star-border, .scanlines, .mono-label)::before { animation-play-state: paused !important; }

/* ------------------------------------------------ movimento reduzido: tudo estático */
@media (prefers-reduced-motion: reduce) {
  .shiny-text, .gradient-text, .star-border::before, .scanlines::before, .mono-label.has-dot::before { animation: none !important; }
  .shiny-text { background: none; -webkit-text-fill-color: currentColor; }
  [data-spotlight]::before, [data-spotlight]::after, [data-tilt]::after { transition: none; }
  .vm-track { transform: none !important; }
}

/* ------------------------------------------------ alto contraste do Windows */
@media (forced-colors: active) {
  .shiny-text, .gradient-text { background: none; -webkit-text-fill-color: currentColor; }
  .star-border::before, .scanlines::before, [data-spotlight]::before, [data-spotlight]::after, [data-tilt]::after { display: none; }
  .hud-frame { background-image: none; }
}
