Download static/script.js from Juek/Rank_Noir: direct link, hf CLI and curl.
- Browser
- Download file 8.64 kB
-
https://huggingface.co/spaces/Juek/Rank_Noir/resolve/main/static/script.js
- Command line
-
hf download hf://spaces/Juek/Rank_Noir/static/script.js
-
curl -L -o script.js https://huggingface.co/spaces/Juek/Rank_Noir/resolve/main/static/script.js
8.64 kB
| /* ββββββββββββββββββββββββββββββββββββββ | |
| RANKNOIR β script.js | |
| TensorStax-style interactions | |
| ββββββββββββββββββββββββββββββββββββββ */ | |
| // ββ Canvas Background ββ | |
| (function() { | |
| const canvas = document.getElementById('bgCanvas'); | |
| if (!canvas) return; | |
| const ctx = canvas.getContext('2d'); | |
| let W, H, particles; | |
| function resize() { W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; } | |
| function mkP() { | |
| return { | |
| x: Math.random() * W, y: Math.random() * H, | |
| size: Math.random() * 1.2 + 0.3, | |
| vx: (Math.random() - 0.5) * 0.25, | |
| vy: (Math.random() - 0.5) * 0.25, | |
| op: Math.random() * 0.5 + 0.1, | |
| color: ['#5a4fcf','#3b7dd8','#e8532a','rgba(90,79,207,0.8)'][Math.floor(Math.random() * 4)] | |
| }; | |
| } | |
| function init() { particles = Array.from({length: 50}, mkP); } | |
| function draw() { | |
| ctx.clearRect(0, 0, W, H); | |
| particles.forEach(p => { | |
| ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); | |
| ctx.fillStyle = p.color; ctx.globalAlpha = p.op; ctx.fill(); ctx.globalAlpha = 1; | |
| p.x += p.vx; p.y += p.vy; | |
| if (p.x < 0) p.x = W; if (p.x > W) p.x = 0; | |
| if (p.y < 0) p.y = H; if (p.y > H) p.y = 0; | |
| }); | |
| // Subtle connections | |
| for (let i = 0; i < particles.length; i++) { | |
| for (let j = i+1; j < particles.length; j++) { | |
| const dx = particles[i].x - particles[j].x, dy = particles[i].y - particles[j].y; | |
| const d = Math.sqrt(dx*dx + dy*dy); | |
| if (d < 110) { | |
| ctx.beginPath(); ctx.moveTo(particles[i].x, particles[i].y); ctx.lineTo(particles[j].x, particles[j].y); | |
| ctx.strokeStyle = 'rgba(90,79,207,0.06)'; ctx.globalAlpha = (1 - d/110) * 0.25; ctx.lineWidth = 0.5; ctx.stroke(); ctx.globalAlpha = 1; | |
| } | |
| } | |
| } | |
| requestAnimationFrame(draw); | |
| } | |
| resize(); init(); draw(); | |
| window.addEventListener('resize', () => { resize(); init(); }, { passive: true }); | |
| })(); | |
| // ββ Navbar ββ | |
| const navbar = document.getElementById('navbar'); | |
| window.addEventListener('scroll', () => { | |
| navbar.classList.toggle('scrolled', window.scrollY > 40); | |
| }, { passive: true }); | |
| // ββ Hamburger ββ | |
| const hamburger = document.getElementById('hamburger'); | |
| const mobileMenu = document.getElementById('mobileMenu'); | |
| hamburger.addEventListener('click', () => { | |
| const open = mobileMenu.classList.toggle('open'); | |
| const s = hamburger.querySelectorAll('span'); | |
| s[0].style.transform = open ? 'translateY(6.5px) rotate(45deg)' : ''; | |
| s[1].style.opacity = open ? '0' : ''; | |
| s[2].style.transform = open ? 'translateY(-6.5px) rotate(-45deg)' : ''; | |
| }); | |
| mobileMenu.querySelectorAll('a').forEach(a => a.addEventListener('click', () => { | |
| mobileMenu.classList.remove('open'); | |
| hamburger.querySelectorAll('span').forEach(s => { s.style.transform = ''; s.style.opacity = ''; }); | |
| })); | |
| // ββ Blob parallax ββ | |
| const blobs = document.querySelectorAll('.blob'); | |
| window.addEventListener('scroll', () => { | |
| const y = window.scrollY; | |
| blobs.forEach((b, i) => { | |
| const spd = 0.05 + i * 0.015; | |
| const dir = i % 2 === 0 ? 1 : -1; | |
| b.style.transform = `translateY(${y * spd * dir}px)`; | |
| }); | |
| }, { passive: true }); | |
| // ββ Scroll Reveal ββ | |
| function setupReveal() { | |
| const sels = [ | |
| '.step-block', '.feat-card', '.gs-card', '.sec-badge', | |
| '.faq-item', '.section-title', '.section-sub', | |
| '.step-h2', '.step-p', '.ui-card', | |
| '.feat-os-card', '.security-wrap', '.cta-h2', | |
| '.logo-badge', '.trust-label', '.trust-sub' | |
| ]; | |
| document.querySelectorAll(sels.join(',')).forEach(el => { | |
| if (el.closest('.hero')) return; | |
| el.classList.add('reveal'); | |
| }); | |
| const obs = new IntersectionObserver(entries => { | |
| entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('visible'); obs.unobserve(e.target); }}); | |
| }, { threshold: 0.08, rootMargin: '0px 0px -40px 0px' }); | |
| document.querySelectorAll('.reveal').forEach(el => obs.observe(el)); | |
| // Stagger cards | |
| ['feat-card', 'gs-card', 'sec-badge'].forEach(cls => { | |
| document.querySelectorAll('.' + cls).forEach((el, i) => { el.style.transitionDelay = `${i * 80}ms`; }); | |
| }); | |
| document.querySelectorAll('.step-block').forEach((el, i) => { el.style.transitionDelay = `${i * 60}ms`; }); | |
| } | |
| setupReveal(); | |
| // ββ FAQ ββ | |
| document.querySelectorAll('.faq-q').forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| const isOpen = btn.getAttribute('aria-expanded') === 'true'; | |
| document.querySelectorAll('.faq-q').forEach(b => { b.setAttribute('aria-expanded', 'false'); b.nextElementSibling.classList.remove('open'); }); | |
| if (!isOpen) { btn.setAttribute('aria-expanded', 'true'); btn.nextElementSibling.classList.add('open'); } | |
| }); | |
| }); | |
| // ββ Form ββ | |
| function handleSubmit(e) { | |
| e.preventDefault(); | |
| const input = e.target.querySelector('.email-input'); | |
| const btn = e.target.querySelector('button[type="submit"]'); | |
| if (!input.value.trim()) return; | |
| const orig = btn.innerHTML; | |
| btn.innerHTML = 'β You\'re on the list!'; | |
| btn.style.background = '#2d8a4e'; | |
| btn.style.animation = 'none'; | |
| input.disabled = btn.disabled = true; | |
| setTimeout(() => { | |
| btn.innerHTML = orig; btn.style.background = btn.style.animation = ''; | |
| input.disabled = btn.disabled = false; input.value = ''; | |
| }, 4000); | |
| } | |
| // ββ Score counter ββ | |
| function animCount(el, from, to, dur = 1400) { | |
| const start = performance.now(); | |
| (function tick(t) { | |
| const p = Math.min((t - start) / dur, 1), e = 1 - Math.pow(1 - p, 3); | |
| el.textContent = Math.round(from + (to - from) * e); | |
| if (p < 1) requestAnimationFrame(tick); | |
| })(start); | |
| } | |
| const after = document.querySelector('.vsn.gold'), before = document.querySelector('.vscore.before .vsn'); | |
| let counted = false; | |
| if (after && before) { | |
| new IntersectionObserver(([entry]) => { | |
| if (entry.isIntersecting && !counted) { counted = true; animCount(before, 0, 42, 1000); animCount(after, 0, 92, 1600); } | |
| }, { threshold: 0.5 }).observe(after); | |
| } | |
| // ββ Progress bar animate ββ | |
| const progressBar = document.querySelector('.uic-progress-bar'); | |
| if (progressBar) { | |
| new IntersectionObserver(([e]) => { | |
| if (e.isIntersecting) { progressBar.style.width = '72%'; } | |
| }, { threshold: 0.4 }).observe(progressBar); | |
| } | |
| // ββ Active nav ββ | |
| const sections = document.querySelectorAll('section[id]'); | |
| const navItems = document.querySelectorAll('.nav-item'); | |
| new IntersectionObserver(entries => { | |
| entries.forEach(e => { | |
| if (e.isIntersecting) { | |
| const id = e.target.id; | |
| navItems.forEach(a => { | |
| a.style.color = a.getAttribute('href') === `#${id}` ? 'var(--white)' : ''; | |
| }); | |
| } | |
| }); | |
| }, { threshold: 0.4 }).observe(document.querySelector('section[id]') || document.body); | |
| // ββ Cursor glow ββ | |
| const glow = document.createElement('div'); | |
| Object.assign(glow.style, { | |
| position:'fixed',width:'250px',height:'250px',borderRadius:'50%',pointerEvents:'none', | |
| zIndex:'9999',background:'radial-gradient(circle,rgba(90,79,207,0.06) 0%,transparent 70%)', | |
| transform:'translate(-50%,-50%)',transition:'opacity 0.3s',opacity:'0' | |
| }); | |
| document.body.appendChild(glow); | |
| let mx=0, my=0, gx=0, gy=0, glowActive=false; | |
| document.addEventListener('mousemove', e => { mx=e.clientX; my=e.clientY; if(!glowActive){glowActive=true;glow.style.opacity='1';loop();} }); | |
| document.addEventListener('mouseleave', () => { glow.style.opacity='0'; glowActive=false; }); | |
| function loop() { | |
| if(!glowActive) return; | |
| gx+=(mx-gx)*0.09; gy+=(my-gy)*0.09; | |
| glow.style.left=gx+'px'; glow.style.top=gy+'px'; | |
| requestAnimationFrame(loop); | |
| } | |
| async function pollStream() { | |
| console.log("π pollStream started"); | |
| const interval = setInterval(async () => { | |
| try { | |
| const res = await fetch("/stream"); | |
| const data = await res.json(); | |
| console.log("π‘ /stream response:", data); | |
| if (data.url) { | |
| clearInterval(interval); | |
| const frame = document.getElementById("agentFrame"); | |
| if (!frame) return; | |
| frame.src = data.url; // set once, iframe handles it natively | |
| document.getElementById("agentLoader")?.remove(); | |
| console.log("π₯ Stream live!"); | |
| } | |
| } catch (e) { | |
| console.error("β Polling error:", e); | |
| } | |
| }, 2000); | |
| } | |