/* ═══════════════════════════════════════════════════════════════════
Brand: PoligusMark, PoligusLogo, IconSet, CinematicBackdrop, Particles
═══════════════════════════════════════════════════════════════════ */
/* ── PREMIUM ICON SET (stroke-based SVGs replacing all emojis) ────── */
const Icon = ({ name, size = 22, stroke = 1.5, color = "currentColor" }) => {
const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
const paths = {
bolt: <>>,
chart: <>>,
target: <>>,
rocket: <>>,
search: <>>,
layers: <>>,
gear: <>>,
handshake: <>>,
shield: <>>,
chat: <>>,
site: <>>,
dashboard: <>>,
megaphone: <>>,
repeat: <>>,
cpu: <>>,
sparkle: <>>,
arrowRight: <>>,
check: <>>,
plus: <>>,
calendar: <>>,
mic: <>>,
whatsapp: ,
};
return ;
};
const WhatsAppIcon = ({ size = 20 }) => ;
/* ── CINEMATIC CIRCUIT BACKDROP — full SVG, animated data pulses ──── */
const CircuitBackdrop = ({ size = 520, opacity = 1 }) => {
const id = React.useId();
const V = 800;
return (
);
};
/* ── PCB SHEET BACKDROP — full-width, scrolls behind hero ────────── */
const PcbSheet = ({ opacity = 0.7 }) => {
const id = React.useId();
return (
);
};
/* ── REAL-TIME 3D POLIGUS SPHERE (Three.js / WebGL) ──────────────────
Núcleo geodésico facetado (facetas em gradiente da marca), arestas
incandescentes, atmosfera fresnel, nós que pulsam, partículas de
dados em órbita. Reage ao ponteiro e ao scroll. Faz fallback para
a imagem da marca quando WebGL não está disponível. */
function makeGlowTexture(THREE, soft) {
var s = 128, c = document.createElement("canvas"); c.width = c.height = s;
var ctx = c.getContext("2d");
var g = ctx.createRadialGradient(s/2, s/2, 0, s/2, s/2, s/2);
if (soft) {
g.addColorStop(0, "rgba(220,240,255,0.55)");
g.addColorStop(0.16, "rgba(150,210,255,0.26)");
g.addColorStop(0.42, "rgba(125,211,255,0.07)");
g.addColorStop(1, "rgba(125,211,255,0)");
} else {
g.addColorStop(0, "rgba(255,255,255,1)");
g.addColorStop(0.25, "rgba(190,235,255,0.7)");
g.addColorStop(0.55, "rgba(125,211,255,0.25)");
g.addColorStop(1, "rgba(125,211,255,0)");
}
ctx.fillStyle = g; ctx.fillRect(0, 0, s, s);
var tex = new THREE.CanvasTexture(c);
tex.minFilter = THREE.LinearFilter;
return tex;
}
function createPoligusSphere(container, opts) {
opts = opts || {};
var THREE = window.THREE;
if (!THREE || !container) return null;
var detail = opts.detail != null ? opts.detail : 1;
var reduced = !!opts.reduced;
var renderer;
try {
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, powerPreference: "high-performance" });
} catch (e) { return null; }
if (!renderer || !renderer.getContext()) return null;
renderer.setClearColor(0x000000, 0);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
var cv = renderer.domElement;
cv.style.width = "100%"; cv.style.height = "100%"; cv.style.display = "block"; cv.style.cursor = "grab";
container.appendChild(cv);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(42, 1, 0.1, 100);
camera.position.set(0, 0, 4.7);
var root = new THREE.Group(); // tilt by input + scroll
var spin = new THREE.Group(); // continuous auto-spin
root.add(spin); scene.add(root);
var R = 1.5;
var BLUE = new THREE.Color(0x2B7BFF), CYAN = new THREE.Color(0xA8E4FF),
DEEP = new THREE.Color(0x0E2A6B), VIOLET = new THREE.Color(0x8C5BFF);
/* faceted gem — gem-like facets in the brand gradient */
var baseGeo = new THREE.IcosahedronGeometry(R, detail);
var gemGeo = baseGeo.index ? baseGeo.toNonIndexed() : baseGeo.clone();
var posAttr = gemGeo.getAttribute("position");
var nFaces = posAttr.count / 3;
var colArr = new Float32Array(posAttr.count * 3);
var a = new THREE.Vector3(), b = new THREE.Vector3(), cc = new THREE.Vector3(), cen = new THREE.Vector3(), col = new THREE.Color();
for (var f = 0; f < nFaces; f++) {
var i0 = f * 3;
a.fromBufferAttribute(posAttr, i0); b.fromBufferAttribute(posAttr, i0 + 1); cc.fromBufferAttribute(posAttr, i0 + 2);
cen.copy(a).add(b).add(cc).multiplyScalar(1 / 3);
var t = (cen.y / R) * 0.5 + 0.5;
var az = (Math.atan2(cen.z, cen.x) / Math.PI) * 0.5 + 0.5;
if (t < 0.5) col.copy(DEEP).lerp(BLUE, t * 2);
else col.copy(BLUE).lerp(CYAN, (t - 0.5) * 2);
col.lerp(VIOLET, az * 0.26);
var r = (Math.sin(f * 127.1 + 311.7) * 43758.5453); r = r - Math.floor(r);
col.multiplyScalar(0.8 + r * 0.45);
for (var k = 0; k < 3; k++) { colArr[(i0 + k) * 3] = col.r; colArr[(i0 + k) * 3 + 1] = col.g; colArr[(i0 + k) * 3 + 2] = col.b; }
}
gemGeo.setAttribute("color", new THREE.BufferAttribute(colArr, 3));
gemGeo.computeVertexNormals();
var gemMat = new THREE.MeshStandardMaterial({
vertexColors: true, flatShading: true, metalness: 0.85, roughness: 0.32,
emissive: new THREE.Color(0x0a1a44), emissiveIntensity: 0.5
});
var gem = new THREE.Mesh(gemGeo, gemMat); spin.add(gem);
/* glowing wireframe */
var edges = new THREE.EdgesGeometry(baseGeo, 1);
var edgeMat = new THREE.LineBasicMaterial({ color: 0x9fe6ff, transparent: true, opacity: 0.32, blending: THREE.AdditiveBlending });
var wire = new THREE.LineSegments(edges, edgeMat); wire.scale.setScalar(1.006); spin.add(wire);
/* glow texture (shared with orbiting particles) */
var nodeTex = makeGlowTexture(THREE);
/* fresnel atmosphere */
var atmMat = new THREE.ShaderMaterial({
transparent: true, blending: THREE.AdditiveBlending, side: THREE.BackSide, depthWrite: false,
uniforms: { uColor: { value: new THREE.Color(0x4aa8ff) }, uPower: { value: 3.6 }, uIntensity: { value: 0.72 } },
vertexShader: "varying vec3 vN; varying vec3 vP; void main(){ vN=normalize(normalMatrix*normal); vec4 mv=modelViewMatrix*vec4(position,1.0); vP=mv.xyz; gl_Position=projectionMatrix*mv; }",
fragmentShader: "varying vec3 vN; varying vec3 vP; uniform vec3 uColor; uniform float uPower; uniform float uIntensity; void main(){ vec3 v=normalize(-vP); float fr=pow(1.0-max(dot(vN,v),0.0),uPower); gl_FragColor=vec4(uColor*fr*uIntensity, fr); }"
});
var atm = new THREE.Mesh(new THREE.SphereGeometry(R * 1.06, 48, 48), atmMat); root.add(atm);
/* soft bloom halo */
var haloMat = new THREE.SpriteMaterial({ map: makeGlowTexture(THREE, 0.5), color: 0x3A8BFF, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, opacity: 0.16 });
var halo = new THREE.Sprite(haloMat); halo.scale.setScalar(R * 2.0); scene.add(halo);
/* orbiting data particles */
var pCount = reduced ? 60 : 150;
var pGeo = new THREE.BufferGeometry(); var pPos = new Float32Array(pCount * 3);
for (var i = 0; i < pCount; i++) {
var rr = R * (1.12 + Math.random() * 0.55);
var th = Math.random() * Math.PI * 2, ph = Math.acos(2 * Math.random() - 1);
pPos[i*3] = rr * Math.sin(ph) * Math.cos(th);
pPos[i*3+1] = rr * Math.cos(ph) * 0.62;
pPos[i*3+2] = rr * Math.sin(ph) * Math.sin(th);
}
pGeo.setAttribute("position", new THREE.BufferAttribute(pPos, 3));
var pMat = new THREE.PointsMaterial({ size: 0.05, map: nodeTex, transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, color: 0x7DD3FF, opacity: 0.8 });
var parts = new THREE.Points(pGeo, pMat); root.add(parts);
/* lights */
scene.add(new THREE.AmbientLight(0x2a4a86, 1.05));
var key = new THREE.DirectionalLight(0xBFEAFF, 2.4); key.position.set(2.5, 3, 2.5); scene.add(key);
var rim = new THREE.DirectionalLight(0x2B7BFF, 1.8); rim.position.set(-3, -1.5, -2); scene.add(rim);
var fill = new THREE.PointLight(0x8C5BFF, 1.3, 14); fill.position.set(-1.5, 1.5, 3); scene.add(fill);
/* interaction */
var tx = 0, ty = 0, cx = 0, cy = 0, hover = 0, hoverT = 0;
/* drag state (mouse + touch) with momentum */
var dragging = false, lastX = 0, lastY = 0;
var velY = 0, velX = 0; // angular velocity carried after release
var manualTiltX = 0; // accumulated vertical tilt from drag
function clampTilt(v) { return v < -0.7 ? -0.7 : (v > 0.7 ? 0.7 : v); }
function onMove(e) {
var r = container.getBoundingClientRect();
var mx = (e.clientX - r.left) / r.width, my = (e.clientY - r.top) / r.height;
tx = (my - 0.5) * 0.9; ty = (mx - 0.5) * 1.4;
}
function onEnter() { hoverT = 1; }
function onLeave() { hoverT = 0; tx *= 0.3; ty *= 0.3; }
function dragStart(x, y) { dragging = true; lastX = x; lastY = y; velY = 0; velX = 0; hoverT = 1; }
function dragMove(x, y) {
if (!dragging) return;
var dx = x - lastX, dy = y - lastY;
lastX = x; lastY = y;
velY = dx * 0.009;
velX = dy * 0.006;
spin.rotation.y += velY; // 1:1 response while dragging
manualTiltX = clampTilt(manualTiltX + velX);
}
function dragEnd() { dragging = false; hoverT = 0; }
function onTouchStart(e) { if (e.touches && e.touches[0]) dragStart(e.touches[0].clientX, e.touches[0].clientY); }
function onTouchMove(e) {
if (e.touches && e.touches[0]) {
if (dragging && e.cancelable) e.preventDefault(); // gira a esfera sem rolar a página
dragMove(e.touches[0].clientX, e.touches[0].clientY);
}
}
window.addEventListener("mousemove", onMove, { passive: true });
container.addEventListener("mouseenter", onEnter);
container.addEventListener("mouseleave", onLeave);
container.addEventListener("touchstart", onTouchStart, { passive: true });
container.addEventListener("touchmove", onTouchMove, { passive: false });
container.addEventListener("touchend", dragEnd, { passive: true });
container.addEventListener("touchcancel", dragEnd, { passive: true });
function resize() {
var w = container.clientWidth || 1, h = container.clientHeight || 1;
renderer.setSize(w, h, false);
camera.aspect = w / h; camera.updateProjectionMatrix();
}
var ro = (typeof ResizeObserver !== "undefined") ? new ResizeObserver(resize) : null;
if (ro) ro.observe(container); else window.addEventListener("resize", resize);
resize();
var raf = 0, t0 = performance.now();
var isTouch = (typeof window !== "undefined") && (("ontouchstart" in window) || ((navigator.maxTouchPoints || 0) > 0));
var baseSpeed = reduced ? 0.02 : (isTouch ? 0.30 : 0.14);
function frame(now) {
raf = requestAnimationFrame(frame);
if (container.clientWidth === 0 || container.clientHeight === 0) return;
var dt = Math.min((now - t0) / 1000, 0.05); t0 = now;
var ts = now * 0.001;
hover += (hoverT - hover) * Math.min(dt * 6, 1);
cx += (tx - cx) * Math.min(dt * 4, 1);
cy += (ty - cy) * Math.min(dt * 4, 1);
var scroll = (window.scrollY || 0) * 0.0006;
/* momentum after releasing the drag */
if (!dragging) {
if (velY * velY + velX * velX > 1e-8) {
spin.rotation.y += velY; velY *= 0.94;
manualTiltX = clampTilt(manualTiltX + velX); velX *= 0.94;
}
manualTiltX *= 0.985; // slowly recenter the vertical tilt
}
spin.rotation.y += dt * (baseSpeed + hover * 0.28);
spin.rotation.x = Math.sin(ts * 0.2) * 0.05;
root.rotation.x = cx + scroll * 0.4 + manualTiltX;
root.rotation.y = cy * 0.6;
edgeMat.opacity = 0.26 + Math.sin(ts * 1.3) * 0.06 + hover * 0.18;
haloMat.opacity = 0.13 + Math.sin(ts * 1.1) * 0.04 + hover * 0.08;
gemMat.emissiveIntensity = 0.45 + Math.sin(ts * 1.5) * 0.08 + hover * 0.18;
parts.rotation.y -= dt * 0.05; parts.rotation.x = Math.sin(ts * 0.15) * 0.1;
renderer.render(scene, camera);
}
raf = requestAnimationFrame(frame);
return {
destroy: function () {
cancelAnimationFrame(raf);
window.removeEventListener("mousemove", onMove);
container.removeEventListener("mouseenter", onEnter);
container.removeEventListener("mouseleave", onLeave);
container.removeEventListener("touchstart", onTouchStart);
container.removeEventListener("touchmove", onTouchMove);
container.removeEventListener("touchend", dragEnd);
container.removeEventListener("touchcancel", dragEnd);
if (ro) ro.disconnect(); else window.removeEventListener("resize", resize);
[gemGeo, baseGeo, edges, pGeo, atm.geometry, nodeTex, haloMat.map].forEach(function (o) { try { o && o.dispose && o.dispose(); } catch (_) {} });
[gemMat, edgeMat, atmMat, pMat, haloMat].forEach(function (m) { try { m && m.dispose && m.dispose(); } catch (_) {} });
try { renderer.dispose(); } catch (_) {}
if (cv && cv.parentNode) cv.parentNode.removeChild(cv);
}
};
}
/* ── POLIGUS LOGO (3D-feeling sphere with rotating energy rings) ────── */
const PoligusMark = ({ size = 56, animated = false, glow = true }) => (
);
/* ── POLIGUS SPHERE 3D (React wrapper around the WebGL engine) ── */
const PoligusSphere3D = ({ size = 320, detail = 1, className = "", style = {} }) => {
const ref = React.useRef(null);
const [failed, setFailed] = React.useState(false);
React.useEffect(() => {
if (!ref.current) return;
if (typeof window === "undefined" || !window.THREE || !window.createPoligusSphere) { setFailed(true); return; }
const reduced = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches);
let inst = null, cancelled = false, raf1 = 0, raf2 = 0, to = 0;
const start = () => {
if (cancelled || !ref.current) return;
try { inst = window.createPoligusSphere(ref.current, { detail, reduced }); } catch (e) { inst = null; }
if (!inst) setFailed(true);
};
// defer heavy WebGL build so the hero text paints + reveals fire first
to = setTimeout(() => { raf1 = requestAnimationFrame(() => { raf2 = requestAnimationFrame(start); }); }, 90);
return () => {
cancelled = true; clearTimeout(to); cancelAnimationFrame(raf1); cancelAnimationFrame(raf2);
if (inst) { try { inst.destroy(); } catch (e) {} }
};
}, [detail]);
if (failed) {
return (
);
}
return ;
};
/* ── POLIGUS WORDMARK (premium tracking, gradient blend) ────────────── */
const PoligusLogo = ({ height = 44 }) => {
const sphereSize = height;
const titleSize = Math.round(height * 0.62);
const subSize = Math.round(height * 0.205);
return (
Poligus
IA · PARA · WHATSAPP
);
};
/* ── Particles (small drifting dots) ─────────────────────────────── */
const Particles = ({ density = 22 }) => {
const particles = React.useMemo(() => Array.from({ length: density }, (_, i) => ({
id: i, x: Math.random() * 100, size: Math.random() * 2.5 + 0.8,
delay: Math.random() * 8, duration: Math.random() * 6 + 7,
opacity: Math.random() * 0.45 + 0.18,
color: Math.random() > 0.7 ? "#A8E4FF" : "#7DD3FF",
})), [density]);
return (
{particles.map(p => (
))}
);
};
/* ── Ambient orbs (drifting blurred color clouds) ────────────────── */
const AmbientOrbs = ({ palette = "cool" }) => {
const orbs = palette === "warm"
? [{ color: "rgba(140,91,255,0.18)", x: "8%", y: "20%", size: 520 }, { color: "rgba(43,123,255,0.14)", x: "78%", y: "62%", size: 420 }]
: [{ color: "rgba(125,211,255,0.16)", x: "10%", y: "16%", size: 560 }, { color: "rgba(43,123,255,0.14)", x: "82%", y: "70%", size: 460 }, { color: "rgba(140,91,255,0.10)", x: "55%", y: "45%", size: 380 }];
return (
<>
{orbs.map((o, i) => (
))}
>
);
};
/* ── Aurora / gradient mesh (fundo premium, substitui partículas) ── */
const Aurora = () => (
);
Object.assign(window, { Icon, PoligusMark, PoligusSphere3D, createPoligusSphere, makeGlowTexture, PoligusLogo, Particles, WhatsAppIcon, CircuitBackdrop, PcbSheet, AmbientOrbs, Aurora });