{"id":254,"date":"2026-06-10T14:03:48","date_gmt":"2026-06-10T17:03:48","guid":{"rendered":"https:\/\/jandaiadosul.ufpr.br\/spei\/?page_id=254"},"modified":"2026-06-10T14:07:04","modified_gmt":"2026-06-10T17:07:04","slug":"index","status":"publish","type":"page","link":"https:\/\/jandaiadosul.ufpr.br\/spei\/index\/","title":{"rendered":"index"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">&lt;!DOCTYPE html&gt;<br>&lt;html lang=&#8221;pt-BR&#8221;&gt;<br>&lt;head&gt;<br>    &lt;meta charset=&#8221;UTF-8&#8243;&gt;<br>    &lt;meta name=&#8221;viewport&#8221; content=&#8221;width=device-width, initial-scale=1.0&#8243;&gt;<br>    &lt;title&gt;Nexus Inova\u00e7\u00e3o | Superf\u00edcie 3D&lt;\/title&gt;<br>    &lt;meta name=&#8221;description&#8221; content=&#8221;Superf\u00edcie 3D interativa de vidro fluido com blocos flutuantes ultra-volum\u00e9tricos de vidro cristalino 3D.&#8221;&gt;<br>    <br>    &lt;!&#8211; Google Fonts &#8211;&gt;<br>    &lt;link rel=&#8221;preconnect&#8221; href=&#8221;https:\/\/fonts.googleapis.com&#8221;&gt;<br>    &lt;link rel=&#8221;preconnect&#8221; href=&#8221;https:\/\/fonts.gstatic.com&#8221; crossorigin&gt;<br>    &lt;link href=&#8221;https:\/\/fonts.googleapis.com\/css2?family=Saira+Extra+Condensed:wght@700;800&amp;family=Plus+Jakarta+Sans:wght@300;400;500;600;700&amp;display=swap&#8221; rel=&#8221;stylesheet&#8221;&gt;<br><br>    &lt;style&gt;<br>        :root {<br>            &#8211;color-primary: #00f0ff;<br>            &#8211;color-secondary: #a855f7;<br>            &#8211;color-bg: #03030c;<br>        }<br><br>        * {<br>            box-sizing: border-box;<br>            margin: 0;<br>            padding: 0;<br>            cursor: none !important; \/* Oculta o cursor nativo em toda a p\u00e1gina *\/<br>        }<br><br>        body {<br>            background-color: var(&#8211;color-bg);<br>            background-image: radial-gradient(circle at 50% 50%, rgba(15, 7, 34, 0.6) 0%, rgba(3, 3, 12, 1) 100%), url(&#8216;https:\/\/jandaiadosul.ufpr.br\/spei\/wp-content\/uploads\/sites\/77\/2026\/06\/innovation_bg.jpg&#8217;);<br>            background-size: cover;<br>            background-position: center;<br>            background-repeat: no-repeat;<br>            min-height: 100vh;<br>            overflow: hidden;<br>            position: relative;<br>        }<br><br>        \/* Custom Cursor *\/<br>        .custom-cursor {<br>            width: 30px;<br>            height: 30px;<br>            border: 2px solid var(&#8211;color-primary);<br>            border-radius: 50%;<br>            position: fixed;<br>            transform: translate(-50%, -50%);<br>            pointer-events: none;<br>            z-index: 9999;<br>            transition: width 0.2s, height 0.2s, background-color 0.2s, border-color 0.2s;<br>            mix-blend-mode: difference;<br>        }<br><br>        .custom-cursor-dot {<br>            width: 6px;<br>            height: 6px;<br>            background-color: var(&#8211;color-primary);<br>            border-radius: 50%;<br>            position: fixed;<br>            transform: translate(-50%, -50%);<br>            pointer-events: none;<br>            z-index: 9999;<br>        }<br><br>        #webgl-canvas {<br>            position: fixed;<br>            top: 0;<br>            left: 0;<br>            width: 100%;<br>            height: 100%;<br>            z-index: 1;<br>        }<br><br>        \/* Flash de luz branca transi\u00e7\u00e3o *\/<br>        #flash-overlay {<br>            position: fixed;<br>            top: 0;<br>            left: 0;<br>            width: 100vw;<br>            height: 100vh;<br>            background-color: #ffffff;<br>            opacity: 0;<br>            pointer-events: none;<br>            z-index: 10000;<br>            transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1);<br>        }<br><br>        #flash-overlay.active {<br>            opacity: 1;<br>        }<br>    &lt;\/style&gt;<br>&lt;\/head&gt;<br>&lt;body&gt;<br><br>    &lt;!&#8211; Cursores Personalizados &#8211;&gt;<br>    &lt;div class=&#8221;custom-cursor&#8221; id=&#8221;custom-cursor&#8221;&gt;&lt;\/div&gt;<br>    &lt;div class=&#8221;custom-cursor-dot&#8221; id=&#8221;custom-cursor-dot&#8221;&gt;&lt;\/div&gt;<br><br>    &lt;!&#8211; Flash de Transi\u00e7\u00e3o &#8211;&gt;<br>    &lt;div id=&#8221;flash-overlay&#8221;&gt;&lt;\/div&gt;<br><br>    &lt;!&#8211; Canvas para renderizar a superf\u00edcie 3D &#8211;&gt;<br>    &lt;canvas id=&#8221;webgl-canvas&#8221;&gt;&lt;\/canvas&gt;<br><br>    &lt;!&#8211; Biblioteca Three.js &#8211;&gt;<br>    &lt;script src=&#8221;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js&#8221;&gt;&lt;\/script&gt;<br><br>    &lt;script&gt;<br>        \/\/ &#8212; 1. CONFIGURA\u00c7\u00c3O DO CURSOR PERSONALIZADO &#8212;<br>        const cursor = document.getElementById(&#8216;custom-cursor&#8217;);<br>        const cursorDot = document.getElementById(&#8216;custom-cursor-dot&#8217;);<br>        <br>        let mouseX = window.innerWidth \/ 2;<br>        let mouseY = window.innerHeight \/ 2;<br>        let cursorX = mouseX;<br>        let cursorY = mouseY;<br>        let dotX = mouseX;<br>        let dotY = mouseY;<br><br>        window.addEventListener(&#8216;mousemove&#8217;, (e) =&gt; {<br>            mouseX = e.clientX;<br>            mouseY = e.clientY;<br>        });<br><br>        function animateCursor() {<br>            cursorX += (mouseX &#8211; cursorX) * 0.15;<br>            cursorY += (mouseY &#8211; cursorY) * 0.15;<br>            cursor.style.left = `${cursorX}px`;<br>            cursor.style.top = `${cursorY}px`;<br><br>            dotX += (mouseX &#8211; dotX) * 0.35;<br>            dotY += (mouseY &#8211; dotY) * 0.35;<br>            cursorDot.style.left = `${dotX}px`;<br>            cursorDot.style.top = `${dotY}px`;<br><br>            requestAnimationFrame(animateCursor);<br>        }<br>        animateCursor();<br><br>        \/\/ &#8212; 2. CONFIGURA\u00c7\u00c3O DA CENA THREE.JS &#8212;<br>        const canvas = document.getElementById(&#8216;webgl-canvas&#8217;);<br>        const clock = new THREE.Clock();<br>        <br>        const mouse3D = new THREE.Vector2(0, 0);<br>        window.addEventListener(&#8216;mousemove&#8217;, (e) =&gt; {<br>            mouse3D.x = (e.clientX \/ window.innerWidth) * 2 &#8211; 1;<br>            mouse3D.y = -(e.clientY \/ window.innerHeight) * 2 + 1;<br>        });<br><br>        const scene = new THREE.Scene();<br>        const camera = new THREE.PerspectiveCamera(45, window.innerWidth \/ window.innerHeight, 0.1, 100);<br>        camera.position.z = 8;<br><br>        const renderer = new THREE.WebGLRenderer({<br>            canvas: canvas,<br>            antialias: true,<br>            alpha: true,<br>            powerPreference: &#8220;high-performance&#8221;<br>        });<br>        renderer.setSize(window.innerWidth, window.innerHeight);<br>        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));<br>        renderer.toneMapping = THREE.ACESFilmicToneMapping;<br>        renderer.toneMappingExposure = 1.2;<br><br>        \/\/ &#8212; 3. CRIANDO A TEXTURA DE FUNDO E O FALLBACK &#8212;<br>        const textureLoader = new THREE.TextureLoader();<br>        let bgTexture = null;<br>        let bgMesh = null;<br>        let glassMesh = null;<br>        let mouseLight = null;<br>        let textMeshes = [];<br>        let isTransitioning = false;<br><br>        const raycaster = new THREE.Raycaster();<br><br>        \/\/ Propor\u00e7\u00e3o de texto<br>        function getWordAspect(text) {<br>            const length = text.length;<br>            if (length &gt; 15) return 2.4; \/\/ Empreendedorismo<br>            if (length &gt; 10) return 1.9;<br>            return 1.3; \/\/ Parcerias, Inova\u00e7\u00e3o, Not\u00edcias<br>        }<br><br>        \/\/ Desenha templates de textura com fonte Saira Extra Condensed<br>        function createTextTexture(text, isHovered = false) {<br>            const canvas = document.createElement(&#8216;canvas&#8217;);<br>            canvas.width = 1024;<br>            canvas.height = 256;<br>            const ctx = canvas.getContext(&#8216;2d&#8217;);<br>            <br>            ctx.clearRect(0, 0, 1024, 256);<br>            <br>            \/\/ Fonte condensada, tamanho ligeiramente menor para maior nitidez\/refinamento<br>            ctx.font = &#8216;bold 115px &#8220;Saira Extra Condensed&#8221;, sans-serif&#8217;;<br>            ctx.textAlign = &#8216;center&#8217;;<br>            ctx.textBaseline = &#8216;middle&#8217;;<br>            <br>            \/\/ Sombra interna refrativa<br>            const shadowColor = isHovered ? &#8216;rgba(0, 240, 255, 0.25)&#8217; : &#8216;rgba(255, 255, 255, 0.1)&#8217;;<br>            ctx.fillStyle = shadowColor;<br>            ctx.fillText(text, 516, 132);<br>            <br>            \/\/ Borda do vidro<br>            ctx.strokeStyle = isHovered ? &#8216;#00f0ff&#8217; : &#8216;rgba(255, 255, 255, 0.35)&#8217;;<br>            ctx.lineWidth = 3;<br>            ctx.strokeText(text, 512, 128);<br>            <br>            \/\/ Corpo do vidro<br>            ctx.fillStyle = isHovered ? &#8216;rgba(0, 240, 255, 0.15)&#8217; : &#8216;rgba(255, 255, 255, 0.08)&#8217;;<br>            ctx.fillText(text, 512, 128);<br>            <br>            const texture = new THREE.CanvasTexture(canvas);<br>            texture.minFilter = THREE.LinearFilter;<br>            return texture;<br>        }<br><br>        function createProceduralTexture() {<br>            const canvas = document.createElement(&#8216;canvas&#8217;);<br>            canvas.width = 1024;<br>            canvas.height = 1024;<br>            const ctx = canvas.getContext(&#8216;2d&#8217;);<br><br>            const grad = ctx.createRadialGradient(512, 512, 50, 512, 512, 700);<br>            grad.addColorStop(0, &#8216;#12042b&#8217;);<br>            grad.addColorStop(0.4, &#8216;#030514&#8217;);<br>            grad.addColorStop(1, &#8216;#010103&#8217;);<br>            ctx.fillStyle = grad;<br>            ctx.fillRect(0, 0, 1024, 1024);<br><br>            ctx.strokeStyle = &#8216;rgba(0, 240, 255, 0.12)&#8217;;<br>            ctx.lineWidth = 1.5;<br>            <br>            const points = [];<br>            for (let i = 0; i &lt; 45; i++) {<br>                points.push({<br>                    x: Math.random() * 1024,<br>                    y: Math.random() * 1024,<br>                    r: Math.random() * 3 + 1,<br>                    glow: Math.random() &gt; 0.6<br>                });<br>            }<br><br>            ctx.beginPath();<br>            for (let i = 0; i &lt; points.length; i++) {<br>                for (let j = i + 1; j &lt; points.length; j++) {<br>                    const dx = points[i].x &#8211; points[j].x;<br>                    const dy = points[i].y &#8211; points[j].y;<br>                    const dist = Math.sqrt(dx*dx + dy*dy);<br>                    if (dist &lt; 260) {<br>                        ctx.moveTo(points[i].x, points[i].y);<br>                        ctx.lineTo(points[j].x, points[j].y);<br>                    }<br>                }<br>            }<br>            ctx.stroke();<br><br>            for (let i = 0; i &lt; points.length; i++) {<br>                ctx.beginPath();<br>                ctx.arc(points[i].x, points[i].y, points[i].r, 0, Math.PI * 2);<br>                ctx.fillStyle = &#8216;rgba(0, 240, 255, 0.7)&#8217;;<br>                ctx.fill();<br><br>                if (points[i].glow) {<br>                    ctx.beginPath();<br>                    ctx.arc(points[i].x, points[i].y, points[i].r * 4, 0, Math.PI * 2);<br>                    const nodeGrad = ctx.createRadialGradient(points[i].x, points[i].y, points[i].r, points[i].x, points[i].y, points[i].r * 4);<br>                    nodeGrad.addColorStop(0, &#8216;rgba(0, 240, 255, 0.3)&#8217;);<br>                    nodeGrad.addColorStop(1, &#8216;rgba(0, 240, 255, 0)&#8217;);<br>                    ctx.fillStyle = nodeGrad;<br>                    ctx.fill();<br>                }<br>            }<br><br>            const grad2 = ctx.createLinearGradient(0, 0, 1024, 1024);<br>            grad2.addColorStop(0.2, &#8216;rgba(168, 85, 247, 0.0)&#8217;);<br>            grad2.addColorStop(0.5, &#8216;rgba(168, 85, 247, 0.18)&#8217;);<br>            grad2.addColorStop(0.8, &#8216;rgba(0, 240, 255, 0.12)&#8217;);<br>            grad2.addColorStop(1, &#8216;rgba(0, 240, 255, 0.0)&#8217;);<br>            ctx.fillStyle = grad2;<br>            ctx.fillRect(0, 0, 1024, 1024);<br><br>            return new THREE.CanvasTexture(canvas);<br>        }<br><br>        \/\/ Garante carregamento da fonte antes de iniciar o Three.js<br>        document.fonts.ready.then(() =&gt; {<br>            const isLocalFile = window.location.protocol === &#8216;file:&#8217;;<br>            if (isLocalFile) {<br>                console.warn(&#8220;Servindo via file:\/\/. Usando fallback de textura procedural para evitar erros de CORS.&#8221;);<br>                const pTexture = createProceduralTexture();<br>                initScene(pTexture);<br>            } else {<br>                textureLoader.load(<br>                    &#8216;innovation_bg.png&#8217;,<br>                    (loadedTexture) =&gt; {<br>                        initScene(loadedTexture);<br>                    },<br>                    undefined,<br>                    (err) =&gt; {<br>                        console.error(&#8220;Erro ao carregar imagem, usando fallback de textura procedural.&#8221;, err);<br>                        const pTexture = createProceduralTexture();<br>                        initScene(pTexture);<br>                    }<br>                );<br>            }<br>        });<br><br>        \/\/ &#8212; 4. INICIALIZA\u00c7\u00c3O DOS ELEMENTOS DA CENA &#8212;<br>        let dirLight1, dirLight2, ambientLight;<br><br>        function initScene(texture) {<br>            bgTexture = texture;<br>            bgTexture.wrapS = THREE.ClampToEdgeWrapping;<br>            bgTexture.wrapT = THREE.ClampToEdgeWrapping;<br>            bgTexture.minFilter = THREE.LinearFilter;<br><br>            \/\/ Fundo<br>            const bgGeometry = new THREE.PlaneGeometry(60, 40);<br>            const bgMaterial = new THREE.MeshBasicMaterial({ map: bgTexture });<br>            bgMesh = new THREE.Mesh(bgGeometry, bgMaterial);<br>            bgMesh.position.z = -5;<br>            scene.add(bgMesh);<br><br>            \/\/ ILUMINA\u00c7\u00c3O<br>            ambientLight = new THREE.AmbientLight(0x0e0e22, 1.8);<br>            scene.add(ambientLight);<br><br>            dirLight1 = new THREE.DirectionalLight(0x00f0ff, 2.5);<br>            dirLight1.position.set(-8, 8, 6);<br>            scene.add(dirLight1);<br><br>            dirLight2 = new THREE.DirectionalLight(0xa855f7, 2.0);<br>            dirLight2.position.set(8, -8, 6);<br>            scene.add(dirLight2);<br><br>            mouseLight = new THREE.PointLight(0xffffff, 5.0, 18);<br>            mouseLight.position.set(0, 0, 2.5);<br>            scene.add(mouseLight);<br><br>            \/\/ Dados das palavras flutuantes<br>            \/\/ baseScale reduzido levemente para fonte menor conforme solicitado<br>            const wordsData = [<br>                { text: &#8220;Parcerias&#8221;, url: &#8220;parcerias.html&#8221;, x: -3.8, y: 1.8, z: -2, baseScale: 1.45 },<br>                { text: &#8220;Empreendedorismo&#8221;, url: &#8220;empreender.html&#8221;, x: 3.5, y: 1.6, z: -2.2, baseScale: 1.3 },<br>                { text: &#8220;Inova\u00e7\u00e3o&#8221;, url: &#8220;inovacao.html&#8221;, x: -3.4, y: -1.8, z: -2.2, baseScale: 1.5 },<br>                { text: &#8220;Not\u00edcias&#8221;, url: &#8220;noticias.html&#8221;, x: 3.8, y: -1.6, z: -2, baseScale: 1.45 }<br>            ];<br><br>            wordsData.forEach(data =&gt; {<br>                const normTex = createTextTexture(data.text, false);<br>                const hovTex = createTextTexture(data.text, true);<br>                <br>                const aspect = getWordAspect(data.text);<br>                const geometry = new THREE.PlaneGeometry(aspect * 2.2, 2.2);<br>                <br>                \/\/ Material f\u00edsico de vidro compartilhado pelas camadas da palavra<br>                const wordMaterial = new THREE.MeshPhysicalMaterial({ <br>                    map: normTex, <br>                    transparent: true,<br>                    opacity: 1.0,                <br>                    transmission: 0.92,          \/\/ Vidro puro cristalino<br>                    roughness: 0.05,             \/\/ Superf\u00edcie polida<br>                    metalness: 0.1,              <br>                    ior: 1.52,                   \/\/ IOR de vidro crown<br>                    thickness: 2.5,              \/\/ Refra\u00e7\u00e3o f\u00edsica<br>                    clearcoat: 1.0,              <br>                    clearcoatRoughness: 0.05,<br>                    emissive: new THREE.Color(0xa855f7), <br>                    emissiveIntensity: 0.4,      <br>                    depthWrite: false <br>                });<br>                <br>                \/\/ Criamos um Grupo para empilhar camadas (Volumetric Stacked Layers)<br>                const wordGroup = new THREE.Group();<br>                wordGroup.position.set(data.x, data.y, data.z);<br>                <br>                \/\/ AUMENTADO O VOLUME 3D:<br>                \/\/ Aumentamos o n\u00famero de camadas para 26 e mantivemos o espa\u00e7amento curto (0.022) <br>                \/\/ Isso cria uma extrus\u00e3o massiva de 0.572 unidades de espessura sem v\u00e3os vis\u00edveis!<br>                const layersCount = 26;      <br>                const layerSpacing = 0.022;  <br>                <br>                let frontMesh = null;<br>                for (let i = 0; i &lt; layersCount; i++) {<br>                    const layerMesh = new THREE.Mesh(geometry, wordMaterial);<br>                    layerMesh.position.z = -i * layerSpacing;<br>                    wordGroup.add(layerMesh);<br>                    <br>                    if (i === 0) {<br>                        frontMesh = layerMesh;<br>                    }<br>                }<br>                <br>                \/\/ Metadados anexados ao frontMesh<br>                frontMesh.wordGroup = wordGroup;<br>                frontMesh.wordMaterial = wordMaterial;<br>                frontMesh.targetUrl = data.url;<br>                frontMesh.normalTexture = normTex;<br>                frontMesh.hoverTexture = hovTex;<br>                frontMesh.isHovered = false;<br>                frontMesh.scaleFactor = data.baseScale;<br>                <br>                frontMesh.initialX = data.x;<br>                frontMesh.initialY = data.y;<br>                frontMesh.phase = Math.random() * Math.PI * 2;<br>                <br>                scene.add(wordGroup);<br>                textMeshes.push(frontMesh);<br>            });<br><br>            \/\/ Criar a superf\u00edcie de vidro 3D ondulada por cima dos textos<br>            const glassGeometry = new THREE.PlaneGeometry(32, 20, 95, 95);<br>            const glassMaterial = new THREE.MeshPhysicalMaterial({<br>                color: 0xffffff,<br>                transparent: true,<br>                transmission: 0.95,<br>                opacity: 1.0,<br>                roughness: 0.12,<br>                metalness: 0.05,<br>                ior: 1.5,<br>                thickness: 1.5,<br>                specularIntensity: 1.2,<br>                specularColor: 0xffffff,<br>                clearcoat: 1.0,<br>                clearcoatRoughness: 0.08,<br>                side: THREE.DoubleSide<br>            });<br><br>            glassMesh = new THREE.Mesh(glassGeometry, glassMaterial);<br>            glassMesh.position.z = 0;<br>            scene.add(glassMesh);<br><br>            resize();<br>            animate();<br>        }<br><br>        \/\/ &#8212; 5. REDIMENSIONAMENTO &#8212;<br>        function resize() {<br>            if (!bgMesh) return;<br><br>            const width = window.innerWidth;<br>            const height = window.innerHeight;<br><br>            camera.aspect = width \/ height;<br>            camera.updateProjectionMatrix();<br>            renderer.setSize(width, height);<br><br>            const distance = camera.position.z &#8211; bgMesh.position.z;<br>            const vFov = (camera.fov * Math.PI) \/ 180;<br>            const planeHeight = 2 * Math.tan(vFov \/ 2) * distance;<br>            const planeWidth = planeHeight * camera.aspect;<br><br>            bgMesh.scale.set(planeWidth \/ 60, planeHeight \/ 40, 1);<br><br>            if (bgTexture &amp;&amp; bgTexture.image) {<br>                const textureAspect = bgTexture.image.width \/ bgTexture.image.height;<br>                const screenAspect = camera.aspect;<br><br>                if (screenAspect &gt; textureAspect) {<br>                    bgTexture.repeat.set(1, textureAspect \/ screenAspect);<br>                    bgTexture.offset.set(0, (1 &#8211; textureAspect \/ screenAspect) \/ 2);<br>                } else {<br>                    bgTexture.repeat.set(screenAspect \/ textureAspect, 1);<br>                    bgTexture.offset.set((1 &#8211; screenAspect \/ textureAspect) \/ 2, 0);<br>                }<br>            }<br>        }<br>        window.addEventListener(&#8216;resize&#8217;, resize);<br><br>        \/\/ &#8212; 6. EVENTO DE CLIQUE (TRANSI\u00c7\u00c3O) &#8212;<br>        window.addEventListener(&#8216;click&#8217;, () =&gt; {<br>            if (isTransitioning) return;<br><br>            raycaster.setFromCamera(mouse3D, camera);<br>            const intersects = raycaster.intersectObjects(textMeshes);<br><br>            if (intersects.length &gt; 0) {<br>                const clickedMesh = intersects[0].object;<br>                isTransitioning = true;<br><br>                \/\/ Ativa flash branco CSS<br>                const flashOverlay = document.getElementById(&#8216;flash-overlay&#8217;);<br>                flashOverlay.classList.add(&#8216;active&#8217;);<br><br>                \/\/ Anima luzes e c\u00e2mera<br>                const startT = clock.getElapsedTime();<br>                function flashLoop() {<br>                    const elapsed = clock.getElapsedTime() &#8211; startT;<br>                    if (elapsed &lt; 0.8) {<br>                        \/\/ Explode fontes WebGL<br>                        if (mouseLight) mouseLight.intensity += 12.0;<br>                        if (dirLight1) dirLight1.intensity += 6.0;<br>                        if (dirLight2) dirLight2.intensity += 6.0;<br><br>                        \/\/ Explode o brilho emissivo do material da palavra clicada<br>                        clickedMesh.wordMaterial.emissiveIntensity += 1.5;<br>                        clickedMesh.wordMaterial.emissive.lerp(new THREE.Color(0xffffff), 0.25);<br><br>                        \/\/ Zoom na palavra<br>                        camera.position.x += (clickedMesh.wordGroup.position.x &#8211; camera.position.x) * 0.15;<br>                        camera.position.y += (clickedMesh.wordGroup.position.y &#8211; camera.position.y) * 0.15;<br>                        camera.position.z -= 0.12;<br><br>                        requestAnimationFrame(flashLoop);<br>                    }<br>                }<br>                flashLoop();<br><br>                setTimeout(() =&gt; {<br>                    window.location.href = clickedMesh.targetUrl;<br>                }, 800);<br>            }<br>        });<br><br>        \/\/ &#8212; 7. LOOP DE ANIMA\u00c7\u00c3O (RENDER) &#8212;<br>        function animate() {<br>            requestAnimationFrame(animate);<br><br>            const time = clock.getElapsedTime();<br><br>            \/\/ Interatividade do mouse na luz de ponto<br>            if (mouseLight &amp;&amp; camera &amp;&amp; !isTransitioning) {<br>                const vector = new THREE.Vector3(mouse3D.x, mouse3D.y, 0.5);<br>                vector.unproject(camera);<br>                const dir = vector.sub(camera.position).normalize();<br>                const distance = -camera.position.z \/ dir.z;<br>                const targetPos = camera.position.clone().add(dir.multiplyScalar(distance));<br><br>                mouseLight.position.x += (targetPos.x &#8211; mouseLight.position.x) * 0.12;<br>                mouseLight.position.y += (targetPos.y &#8211; mouseLight.position.y) * 0.12;<br>                mouseLight.position.z = 2.0;<br>            }<br><br>            \/\/ Raycasting para Hover<br>            if (!isTransitioning) {<br>                raycaster.setFromCamera(mouse3D, camera);<br>                const intersects = raycaster.intersectObjects(textMeshes);<br>                <br>                let hoveredObj = null;<br>                if (intersects.length &gt; 0) {<br>                    hoveredObj = intersects[0].object;<br>                }<br><br>                \/\/ Efeito no cursor personalizado<br>                if (hoveredObj) {<br>                    cursor.style.width = &#8217;60px&#8217;;<br>                    cursor.style.height = &#8217;60px&#8217;;<br>                    cursor.style.borderColor = &#8216;var(&#8211;color-secondary)&#8217;;<br>                    cursor.style.backgroundColor = &#8216;rgba(168, 85, 247, 0.12)&#8217;;<br>                } else {<br>                    cursor.style.width = &#8217;30px&#8217;;<br>                    cursor.style.height = &#8217;30px&#8217;;<br>                    cursor.style.borderColor = &#8216;var(&#8211;color-primary)&#8217;;<br>                    cursor.style.backgroundColor = &#8216;transparent&#8217;;<br>                }<br><br>                \/\/ Interpola\u00e7\u00e3o suave para o material f\u00edsico de vidro dos textos (Lerp)<br>                textMeshes.forEach(mesh =&gt; {<br>                    if (mesh === hoveredObj) {<br>                        mesh.isHovered = true;<br>                        mesh.wordMaterial.map = mesh.hoverTexture;<br>                        <br>                        \/\/ Valores Alvo para Hover<br>                        mesh.targetEmissiveIntensity = 1.4;      <br>                        mesh.targetEmissiveColor = new THREE.Color(0x00f0ff); \/\/ Vidro ciano el\u00e9trico<br>                        mesh.targetScale = mesh.scaleFactor * 1.12;<br>                        mesh.wordMaterial.roughness = 0.02;          <br>                    } else {<br>                        mesh.isHovered = false;<br>                        mesh.wordMaterial.map = mesh.normalTexture;<br><br>                        \/\/ Valores Alvo Padr\u00e3o (Vidro cristalino lil\u00e1s discreto)<br>                        mesh.targetEmissiveIntensity = 0.4;<br>                        mesh.targetEmissiveColor = new THREE.Color(0xa855f7);<br>                        mesh.targetScale = mesh.scaleFactor;<br>                        mesh.wordMaterial.roughness = 0.05;          <br>                    }<br><br>                    \/\/ Aplica interpola\u00e7\u00e3o linear suave no material da palavra<br>                    mesh.wordMaterial.emissiveIntensity += (mesh.targetEmissiveIntensity &#8211; mesh.wordMaterial.emissiveIntensity) * 0.15;<br>                    mesh.wordMaterial.emissive.lerp(mesh.targetEmissiveColor, 0.15);<br>                    mesh.wordMaterial.needsUpdate = true;<br><br>                    \/\/ Escala do grupo<br>                    const group = mesh.wordGroup;<br>                    const s = group.scale.x + (mesh.targetScale &#8211; group.scale.x) * 0.15;<br>                    group.scale.set(s, s, 1);<br>                });<br>            }<br><br>            \/\/ Flutua\u00e7\u00e3o 3D e rota\u00e7\u00e3o reativa direcionada ao cursor (Acentua a profundidade das laterais do vidro)<br>            textMeshes.forEach(mesh =&gt; {<br>                const group = mesh.wordGroup;<br>                <br>                group.position.y = mesh.initialY + Math.sin(time * 0.8 + mesh.phase) * 0.15;<br>                group.position.x = mesh.initialX + Math.cos(time * 0.4 + mesh.phase) * 0.1;<br>                group.rotation.z = Math.sin(time * 0.3 + mesh.phase) * 0.04;<br>                <br>                if (!isTransitioning) {<br>                    \/\/ Limites de rota\u00e7\u00e3o aumentados ligeiramente para enfatizar a espessura de 26 camadas<br>                    group.rotation.y = Math.sin(time * 0.1 + mesh.phase) * 0.05 + mouse3D.x * 0.32;<br>                    group.rotation.x = mouse3D.y * 0.25;<br>                }<br>            });<br><br>            \/\/ Deforma a malha de vidro frontal para gerar refra\u00e7\u00f5es<br>            if (glassMesh) {<br>                const geometry = glassMesh.geometry;<br>                const position = geometry.attributes.position;<br>                <br>                for (let i = 0; i &lt; position.count; i++) {<br>                    const x = position.getX(i);<br>                    const y = position.getY(i);<br><br>                    const z1 = Math.sin(x * 0.2 + time * 0.7) * Math.cos(y * 0.2 + time * 0.7) * 0.45;<br>                    const z2 = Math.sin(x * 0.45 &#8211; time * 0.5) * Math.cos(y * 0.35 + time * 0.4) * 0.2;<br>                    const z3 = Math.cos(x * 0.1 + y * 0.1 + time * 0.3) * 0.3;<br><br>                    const dx = x &#8211; mouseLight.position.x;<br>                    const dy = y &#8211; mouseLight.position.y;<br>                    const dist = Math.sqrt(dx * dx + dy * dy);<br>                    const mouseGlowEffect = Math.sin(dist * 0.7 &#8211; time * 2.5) * Math.exp(-dist * 0.12) * 0.35;<br><br>                    position.setZ(i, z1 + z2 + z3 + mouseGlowEffect);<br>                }<br><br>                geometry.computeVertexNormals();<br>                position.needsUpdate = true;<br><br>                glassMesh.rotation.y = Math.sin(time * 0.05) * 0.04;<br>                glassMesh.rotation.x = Math.cos(time * 0.05) * 0.02;<br>            }<br><br>            renderer.render(scene, camera);<br>        }<br>    &lt;\/script&gt;<br>&lt;\/body&gt;<br>&lt;\/html&gt;<br><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&lt;!DOCTYPE html&gt;&lt;html lang=&#8221;pt-BR&#8221;&gt;&lt;head&gt; &lt;meta charset=&#8221;UTF-8&#8243;&gt; &lt;meta name=&#8221;viewport&#8221; content=&#8221;width=device-width, initial-scale=1.0&#8243;&gt; &lt;title&gt;Nexus Inova\u00e7\u00e3o | Superf\u00edcie 3D&lt;\/title&gt; &lt;meta name=&#8221;description&#8221; content=&#8221;Superf\u00edcie 3D interativa de vidro fluido com blocos flutuantes ultra-volum\u00e9tricos de vidro cristalino 3D.&#8221;&gt; &lt;!&#8211; Google Fonts &#8211;&gt; &lt;link rel=&#8221;preconnect&#8221; href=&#8221;https:\/\/fonts.googleapis.com&#8221;&gt; &lt;link rel=&#8221;preconnect&#8221; href=&#8221;https:\/\/fonts.gstatic.com&#8221; crossorigin&gt; &lt;link href=&#8221;https:\/\/fonts.googleapis.com\/css2?family=Saira+Extra+Condensed:wght@700;800&amp;family=Plus+Jakarta+Sans:wght@300;400;500;600;700&amp;display=swap&#8221; rel=&#8221;stylesheet&#8221;&gt; &lt;style&gt; :root { &#8211;color-primary: #00f0ff; &#8211;color-secondary: #a855f7; &#8211;color-bg: #03030c; } * [&hellip;]<\/p>\n","protected":false},"author":3605,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-254","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/pages\/254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/users\/3605"}],"replies":[{"embeddable":true,"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/comments?post=254"}],"version-history":[{"count":3,"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/pages\/254\/revisions"}],"predecessor-version":[{"id":263,"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/pages\/254\/revisions\/263"}],"wp:attachment":[{"href":"https:\/\/jandaiadosul.ufpr.br\/spei\/wp-json\/wp\/v2\/media?parent=254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}