/* ═══════════════════════════════════════════════════════════════════ 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 {paths[name] || paths.sparkle}; }; 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
); /* ── 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 = () => (