Spaces:
Running
Running
Deploy neuropulse: 3D transformer visualizer + demo mode
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- README.md +29 -6
- app/index.html +0 -0
- architecture-dark.svg +109 -0
- architecture-light.svg +109 -0
- assets/app-5dUOJK1P.js +0 -0
- assets/main-D1-Ogq2V.js +61 -0
- assets/three.module-Bwi0mW4U.js +0 -0
- comparison-dark.svg +21 -0
- comparison-light.svg +21 -0
- controls-dark.svg +128 -0
- controls-light.svg +128 -0
- favicon-16.png +0 -0
- favicon-192.png +0 -0
- favicon-32.png +0 -0
- favicon-48.png +0 -0
- favicon-512.png +0 -0
- favicon-96.png +0 -0
- favicon.ico +0 -0
- favicon.svg +17 -0
- hero-dark.svg +0 -0
- hero-light.svg +0 -0
- index.html +1360 -18
- kernels-dark.svg +121 -0
- kernels-light.svg +121 -0
- layers-dark.svg +0 -0
- layers-light.svg +0 -0
- monogram-dark.svg +19 -0
- monogram-light.svg +19 -0
- og-dark.svg +41 -0
- og-light.svg +41 -0
- og.png +0 -0
- panels-dark.svg +166 -0
- panels-light.svg +166 -0
- pca-layout.json +0 -0
- preview-dark.svg +106 -0
- preview-light.svg +106 -0
- recordings/capital-01.json +0 -0
- recordings/capital-ablated-01.json +0 -0
- recordings/code-01.json +0 -0
- recordings/intro-01.json +0 -0
- reference.json +0 -0
- robots.txt +25 -0
- runlocal-dark.svg +47 -0
- runlocal-light.svg +47 -0
- scene-dark.svg +0 -0
- scene-light.svg +0 -0
- sitemap.xml +13 -0
- stack-dark.svg +108 -0
- stack-light.svg +108 -0
- stats-dark.svg +21 -0
README.md
CHANGED
|
@@ -1,10 +1,33 @@
|
|
| 1 |
---
|
| 2 |
-
title: Neuropulse
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
-
pinned:
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Neuropulse — Watch a real transformer think
|
| 3 |
+
emoji: 🧠
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: indigo
|
| 6 |
sdk: static
|
| 7 |
+
pinned: true
|
| 8 |
+
license: mit
|
| 9 |
+
short_description: Live 3D rendering of Phi-3-mini, every pixel a real tensor
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Neuropulse
|
| 13 |
+
|
| 14 |
+
A live 3D rendering of **Phi-3-mini** running as a hand-written WGSL/WebGPU
|
| 15 |
+
inference engine. Every point of light is a real tensor — attention heads, FFN
|
| 16 |
+
cells, residual norms — drawn one-to-one from the running model, not a video or
|
| 17 |
+
an animation.
|
| 18 |
+
|
| 19 |
+
## Two ways to explore
|
| 20 |
+
|
| 21 |
+
- **Start learning now — no download.** The [`?demo=1`](./app/?demo=1) path
|
| 22 |
+
replays **real runs captured live earlier** (the recordings are committed
|
| 23 |
+
tensors, always badged "RECORDED RUN"). The full UI, guided lessons, tours,
|
| 24 |
+
and ablation experiments all work with nothing to install.
|
| 25 |
+
- **Download & run live (~2 GB).** On a WebGPU-capable browser you can pull the
|
| 26 |
+
quantized weights and watch your *own* prompts run on your GPU. Close the tab
|
| 27 |
+
and the inference stops.
|
| 28 |
+
|
| 29 |
+
Canonical site: **[neuropulse.live](https://neuropulse.live)**. This Space is a
|
| 30 |
+
mirror.
|
| 31 |
+
|
| 32 |
+
Built with vanilla TypeScript + Three.js over a from-scratch WGSL Phi-3 engine.
|
| 33 |
+
No frameworks, no telemetry, no fakery.
|
app/index.html
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
architecture-dark.svg
ADDED
|
|
architecture-light.svg
ADDED
|
|
assets/app-5dUOJK1P.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
assets/main-D1-Ogq2V.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import{W as E,S as L,P as B,B as R,a as C,C as u,b as Y,A as _,c as j}from"./three.module-Bwi0mW4U.js";(function(){const r=document.getElementById("page-canvas");if(!r||window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;const p=window.innerWidth<820||/Mobi|Android|iPhone|iPad/i.test(navigator.userAgent),h=p?9e3:28e3,W=p?1.5:2,v=new E({canvas:r,antialias:!p,alpha:!0,powerPreference:"high-performance"});v.setPixelRatio(Math.min(window.devicePixelRatio,W));const w=new L,o=new B(55,1,.1,300);o.position.set(0,0,16);const l=new Float32Array(h*3),d=new Float32Array(h*3);for(let e=0;e<h;e++){const s=(Math.floor(Math.random()*32)/31-.5)*18,a=Math.pow(Math.random(),.7)*9+.5,m=Math.random()*Math.PI*2;l[e*3]=a*Math.cos(m),l[e*3+1]=s+(Math.random()-.5)*.4,l[e*3+2]=a*Math.sin(m)-4,d[e*3]=Math.random(),d[e*3+1]=Math.random(),d[e*3+2]=Math.random()}const f=new R;f.setAttribute("position",new C(l,3)),f.setAttribute("seed",new C(d,3));const c={time:{value:0},prog:{value:0},fade:{value:1},cyan:{value:new u(6220500)},cyanHot:{value:new u(58879)},violet:{value:new u(12616956)}},F=new Y({uniforms:c,transparent:!0,depthWrite:!1,blending:_,vertexShader:`
|
| 2 |
+
attribute vec3 seed;
|
| 3 |
+
uniform float time;
|
| 4 |
+
uniform float prog;
|
| 5 |
+
uniform float fade;
|
| 6 |
+
uniform vec3 cyan;
|
| 7 |
+
uniform vec3 cyanHot;
|
| 8 |
+
uniform vec3 violet;
|
| 9 |
+
varying vec3 vColor;
|
| 10 |
+
varying float vAlpha;
|
| 11 |
+
|
| 12 |
+
void main() {
|
| 13 |
+
vec3 p = position;
|
| 14 |
+
float t = time * 0.12;
|
| 15 |
+
|
| 16 |
+
// Volumetric drift (dominant in hero) fades as prog rises
|
| 17 |
+
float ph = seed.x * 6.2831;
|
| 18 |
+
float ph2 = seed.y * 6.2831;
|
| 19 |
+
float amp = 0.5 + seed.z * 1.3;
|
| 20 |
+
float volWeight = mix(1.0, 0.35, prog);
|
| 21 |
+
|
| 22 |
+
p.x += sin(t + ph) * amp * volWeight;
|
| 23 |
+
p.y += cos(t * 0.8 + ph2) * amp * 0.35 * volWeight;
|
| 24 |
+
p.z += sin(t * 0.6 + ph + seed.y * 3.0) * amp * 0.7 * volWeight;
|
| 25 |
+
|
| 26 |
+
// Leftward flow that ramps up as prog rises (mid-scroll onward)
|
| 27 |
+
float flowAmt = smoothstep(0.15, 0.85, prog);
|
| 28 |
+
float flowSpeed = (0.6 + seed.z * 1.4) * flowAmt;
|
| 29 |
+
float wrap = 36.0;
|
| 30 |
+
p.x = mod(p.x + wrap * 0.5 - time * flowSpeed, wrap) - wrap * 0.5;
|
| 31 |
+
|
| 32 |
+
vec4 mv = modelViewMatrix * vec4(p, 1.0);
|
| 33 |
+
gl_Position = projectionMatrix * mv;
|
| 34 |
+
|
| 35 |
+
// Slightly smaller points as flow tightens
|
| 36 |
+
float depth = -mv.z;
|
| 37 |
+
float baseSize = 1.0 + seed.z * 3.4;
|
| 38 |
+
gl_PointSize = baseSize * mix(1.0, 0.7, prog) * (90.0 / depth);
|
| 39 |
+
|
| 40 |
+
// Palette: mostly cyan, rare violet, rarest hot-cyan activity
|
| 41 |
+
float hot = step(0.965, seed.x);
|
| 42 |
+
float violetMix = smoothstep(0.55, 0.95, seed.y);
|
| 43 |
+
vec3 base = mix(cyan, violet, violetMix);
|
| 44 |
+
vColor = mix(base, cyanHot, hot);
|
| 45 |
+
|
| 46 |
+
// Per-point breathing + depth fade + master alpha
|
| 47 |
+
float pulse = 0.55 + 0.45 * sin(t * 2.4 + seed.x * 18.0 + seed.y * 12.0);
|
| 48 |
+
vAlpha = pulse * smoothstep(40.0, 5.0, depth) * fade;
|
| 49 |
+
}
|
| 50 |
+
`,fragmentShader:`
|
| 51 |
+
varying vec3 vColor;
|
| 52 |
+
varying float vAlpha;
|
| 53 |
+
void main() {
|
| 54 |
+
vec2 uv = gl_PointCoord - 0.5;
|
| 55 |
+
float d = length(uv);
|
| 56 |
+
if (d > 0.5) discard;
|
| 57 |
+
float fall = smoothstep(0.5, 0.0, d);
|
| 58 |
+
fall = pow(fall, 1.4);
|
| 59 |
+
gl_FragColor = vec4(vColor * (1.0 + fall * 0.6), fall * vAlpha);
|
| 60 |
+
}
|
| 61 |
+
`}),g=new j(f,F);w.add(g);function y(){const e=window.innerWidth,i=window.innerHeight;v.setSize(e,i,!1),o.aspect=e/i,o.updateProjectionMatrix()}y(),window.addEventListener("resize",y);let M=0,x=0;window.addEventListener("pointermove",e=>{M=e.clientX/window.innerWidth*2-1,x=e.clientY/window.innerHeight*2-1},{passive:!0});let t=0,b=1;function n(e,i,s){const a=Math.max(0,Math.min(1,(s-e)/(i-e)));return a*a*(3-2*a)}function A(){const e=window.scrollY,i=Math.max(1,document.documentElement.scrollHeight-window.innerHeight);t=Math.max(0,Math.min(1,e/i));const s=1-n(.04,.15,t),a=n(.15,.25,t)*(1-n(.7,.78,t)),m=n(.78,.88,t)*(1-n(.93,.98,t)),H=n(.93,1,t);b=Math.max(s,.35+(1-a)*0,m*.85,H)}A(),window.addEventListener("scroll",A,{passive:!0});let P=!0;document.addEventListener("visibilitychange",()=>{P=document.visibilityState==="visible"}),r.style.opacity="0",r.style.transition="opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1)",requestAnimationFrame(()=>{r.style.opacity="1"});let S=0;function z(){if(P){S+=1/60,c.time.value=S,c.prog.value=t,c.fade.value=b;const e=1-Math.min(1,t*4);o.position.x+=(M*.7*e-o.position.x)*.03,o.position.y+=(-x*.5*e-o.position.y)*.03,o.lookAt(0,0,0),g.rotation.y+=6e-4*(1-t*.7),v.render(w,o)}requestAnimationFrame(z)}z()})();
|
assets/three.module-Bwi0mW4U.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
comparison-dark.svg
ADDED
|
|
comparison-light.svg
ADDED
|
|
controls-dark.svg
ADDED
|
|
controls-light.svg
ADDED
|
|
favicon-16.png
ADDED
|
|
favicon-192.png
ADDED
|
|
favicon-32.png
ADDED
|
|
favicon-48.png
ADDED
|
|
favicon-512.png
ADDED
|
|
favicon-96.png
ADDED
|
|
favicon.ico
ADDED
|
|
favicon.svg
ADDED
|
|
hero-dark.svg
ADDED
|
|
hero-light.svg
ADDED
|
|
index.html
CHANGED
|
@@ -1,19 +1,1361 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>Neuropulse — Watch a real transformer think</title>
|
| 7 |
+
<meta name="description" content="A live 3D rendering of Phi-3-mini running on your GPU. Every attention head, every FFN cell, every activation — drawn one-to-one from real WebGPU tensors. The whole model runs in your tab; close it and the inference stops." />
|
| 8 |
+
<link rel="canonical" href="https://neuropulse.live/" />
|
| 9 |
+
<link rel="icon" href="./favicon.ico" sizes="any" />
|
| 10 |
+
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
|
| 11 |
+
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
| 12 |
+
<link rel="icon" type="image/png" sizes="96x96" href="./favicon-96.png" />
|
| 13 |
+
<link rel="icon" type="image/png" sizes="192x192" href="./favicon-192.png" />
|
| 14 |
+
<link rel="apple-touch-icon" sizes="192x192" href="./favicon-192.png" />
|
| 15 |
+
|
| 16 |
+
<!-- Open Graph -->
|
| 17 |
+
<meta property="og:type" content="website" />
|
| 18 |
+
<meta property="og:title" content="Neuropulse — Watch a real transformer think" />
|
| 19 |
+
<meta property="og:description" content="Live 3D rendering of Phi-3-mini running on your GPU. Strict 1:1 from real WebGPU tensors." />
|
| 20 |
+
<meta property="og:url" content="https://neuropulse.live/" />
|
| 21 |
+
<meta property="og:image" content="https://neuropulse.live/og.png" />
|
| 22 |
+
<meta name="twitter:card" content="summary_large_image" />
|
| 23 |
+
<meta name="twitter:title" content="Neuropulse — Watch a real transformer think" />
|
| 24 |
+
<meta name="twitter:description" content="Live 3D rendering of Phi-3-mini running on your GPU. Strict 1:1 from real WebGPU tensors." />
|
| 25 |
+
<meta name="twitter:image" content="https://neuropulse.live/og.png" />
|
| 26 |
+
|
| 27 |
+
<!-- Structured data: identity + cross-links to the kernel-fusion research line. -->
|
| 28 |
+
<script type="application/ld+json">
|
| 29 |
+
{
|
| 30 |
+
"@context": "https://schema.org",
|
| 31 |
+
"@graph": [
|
| 32 |
+
{
|
| 33 |
+
"@type": "WebSite",
|
| 34 |
+
"@id": "https://neuropulse.live#site",
|
| 35 |
+
"url": "https://neuropulse.live",
|
| 36 |
+
"name": "Neuropulse",
|
| 37 |
+
"description": "Live 3D rendering of Phi-3-mini running on your GPU. Every tensor drawn one-to-one from real WebGPU activations.",
|
| 38 |
+
"publisher": { "@id": "https://neuropulse.live#author" },
|
| 39 |
+
"isPartOf": {
|
| 40 |
+
"@type": "CreativeWork",
|
| 41 |
+
"name": "Kernel-fusion research line",
|
| 42 |
+
"url": "https://kernelfusion.dev"
|
| 43 |
+
}
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"@type": "Person",
|
| 47 |
+
"@id": "https://neuropulse.live#author",
|
| 48 |
+
"name": "Ahmet Baris Gunaydin",
|
| 49 |
+
"url": "https://barisgunaydin.com",
|
| 50 |
+
"sameAs": [
|
| 51 |
+
"https://barisgunaydin.com",
|
| 52 |
+
"https://kernelfusion.dev",
|
| 53 |
+
"https://gpubench.dev",
|
| 54 |
+
"https://zerotvm.com",
|
| 55 |
+
"https://webgpudna.com",
|
| 56 |
+
"https://neuropulse.live",
|
| 57 |
+
"https://webgpu-q.vercel.app",
|
| 58 |
+
"https://markview.ai",
|
| 59 |
+
"https://safenpm.dev",
|
| 60 |
+
"https://fused-lora.pages.dev",
|
| 61 |
+
"https://github.com/abgnydn",
|
| 62 |
+
"https://www.linkedin.com/in/abgnydn/"
|
| 63 |
+
]
|
| 64 |
+
}
|
| 65 |
+
]
|
| 66 |
+
}
|
| 67 |
+
</script>
|
| 68 |
+
|
| 69 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 70 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 71 |
+
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght,SOFT@9..144,300..700,30..100&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
<style>
|
| 75 |
+
:root {
|
| 76 |
+
--bg: #08060f;
|
| 77 |
+
--bg-warm: #0d0810;
|
| 78 |
+
--ink: #f4ecdf;
|
| 79 |
+
--ink-soft: #cbc1ad;
|
| 80 |
+
--ink-dim: #8a8170;
|
| 81 |
+
--ink-faint: #514a3e;
|
| 82 |
+
--rule: rgba(244, 236, 223, 0.10);
|
| 83 |
+
--cyan: #5eead4;
|
| 84 |
+
--cyan-bright: #00e5ff;
|
| 85 |
+
--violet: #c084fc;
|
| 86 |
+
--amber: #ff8c42;
|
| 87 |
+
--serif: 'Fraunces', 'Iowan Old Style', Georgia, serif;
|
| 88 |
+
--sans: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
| 89 |
+
--mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
|
| 90 |
+
|
| 91 |
+
/* ── canonical cross-site alias layer (see ~/sites-shared/tokens.css) ── */
|
| 92 |
+
--surface: var(--bg-warm);
|
| 93 |
+
--border: var(--rule);
|
| 94 |
+
--text: var(--ink);
|
| 95 |
+
--muted: var(--ink-dim);
|
| 96 |
+
--accent: var(--cyan-bright);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 100 |
+
html {
|
| 101 |
+
scroll-behavior: smooth;
|
| 102 |
+
overflow-x: clip;
|
| 103 |
+
/* bg on <html> so the fixed z-index:-1 page canvas sits above it */
|
| 104 |
+
background: var(--bg);
|
| 105 |
+
}
|
| 106 |
+
body {
|
| 107 |
+
font-family: var(--sans);
|
| 108 |
+
background: transparent;
|
| 109 |
+
color: var(--ink);
|
| 110 |
+
-webkit-font-smoothing: antialiased;
|
| 111 |
+
-moz-osx-font-smoothing: grayscale;
|
| 112 |
+
line-height: 1.6;
|
| 113 |
+
}
|
| 114 |
+
/* Full-page persistent Three.js backdrop (src/canvas.ts).
|
| 115 |
+
z-index:-1 sits above html bg, below all document content. */
|
| 116 |
+
#page-canvas {
|
| 117 |
+
position: fixed;
|
| 118 |
+
inset: 0;
|
| 119 |
+
width: 100vw;
|
| 120 |
+
height: 100vh;
|
| 121 |
+
z-index: -1;
|
| 122 |
+
pointer-events: none;
|
| 123 |
+
display: block;
|
| 124 |
+
}
|
| 125 |
+
::selection { background: var(--cyan-bright); color: #02020a; }
|
| 126 |
+
a { color: inherit; text-decoration: none; }
|
| 127 |
+
|
| 128 |
+
/* ─────────────────────────────────────────────────────────
|
| 129 |
+
HERO — type-only editorial void.
|
| 130 |
+
We deliberately do NOT show any of the real demo here. The
|
| 131 |
+
reveal is the surprise behind the CTA.
|
| 132 |
+
───────────────────────────────────────────────────────── */
|
| 133 |
+
.hero {
|
| 134 |
+
position: relative;
|
| 135 |
+
height: 100vh;
|
| 136 |
+
min-height: 700px;
|
| 137 |
+
width: 100%;
|
| 138 |
+
overflow: hidden;
|
| 139 |
+
display: flex;
|
| 140 |
+
flex-direction: column;
|
| 141 |
+
background: var(--bg);
|
| 142 |
+
}
|
| 143 |
+
/* Slow-drifting ambient gradient — subtle, hints at "something alive" */
|
| 144 |
+
.hero::before {
|
| 145 |
+
content: '';
|
| 146 |
+
position: absolute;
|
| 147 |
+
inset: -20%;
|
| 148 |
+
z-index: 0;
|
| 149 |
+
background:
|
| 150 |
+
radial-gradient(ellipse 55% 40% at 22% 30%, rgba(94, 234, 212, 0.05), transparent 60%),
|
| 151 |
+
radial-gradient(ellipse 50% 50% at 78% 70%, rgba(192, 132, 252, 0.04), transparent 60%),
|
| 152 |
+
radial-gradient(ellipse 40% 30% at 50% 92%, rgba(0, 229, 255, 0.03), transparent 60%);
|
| 153 |
+
animation: hero-drift 40s ease-in-out infinite alternate;
|
| 154 |
+
}
|
| 155 |
+
@keyframes hero-drift {
|
| 156 |
+
0% { transform: translate(0, 0) rotate(0deg) scale(1); }
|
| 157 |
+
50% { transform: translate(2%, -1.5%) rotate(1deg) scale(1.05); }
|
| 158 |
+
100% { transform: translate(-1.5%, 2%) rotate(-1deg) scale(1.02); }
|
| 159 |
+
}
|
| 160 |
+
/* The per-hero canvas is gone — #page-canvas (fixed, z:-1) now handles it
|
| 161 |
+
across the whole document. The drift gradient on .hero::before stays as
|
| 162 |
+
a subtle warm tint since the page canvas behind it is transparent. */
|
| 163 |
+
/* Film grain overlay — editorial cinematic texture */
|
| 164 |
+
.hero-grain {
|
| 165 |
+
content: '';
|
| 166 |
+
position: absolute;
|
| 167 |
+
inset: 0;
|
| 168 |
+
z-index: 2;
|
| 169 |
+
pointer-events: none;
|
| 170 |
+
opacity: 0.07;
|
| 171 |
+
mix-blend-mode: overlay;
|
| 172 |
+
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
|
| 173 |
+
}
|
| 174 |
+
/* Bottom vignette to anchor the type and lead the eye to the scroll cue */
|
| 175 |
+
.hero-vignette {
|
| 176 |
+
position: absolute;
|
| 177 |
+
inset: 0;
|
| 178 |
+
z-index: 3;
|
| 179 |
+
pointer-events: none;
|
| 180 |
+
background:
|
| 181 |
+
linear-gradient(180deg, transparent 60%, rgba(8, 6, 15, 0.85) 100%);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
/* Floating nav over the hero video */
|
| 185 |
+
.hero-nav {
|
| 186 |
+
position: relative;
|
| 187 |
+
z-index: 10;
|
| 188 |
+
display: flex;
|
| 189 |
+
justify-content: space-between;
|
| 190 |
+
align-items: center;
|
| 191 |
+
padding: 28px clamp(24px, 5vw, 64px);
|
| 192 |
+
animation: heroFadeIn 0.8s cubic-bezier(0.16,1,0.3,1) 0.1s both;
|
| 193 |
+
}
|
| 194 |
+
.logo {
|
| 195 |
+
font-family: var(--serif);
|
| 196 |
+
font-weight: 400;
|
| 197 |
+
font-size: 1.35rem;
|
| 198 |
+
letter-spacing: -0.01em;
|
| 199 |
+
font-variation-settings: "opsz" 144, "SOFT" 50;
|
| 200 |
+
}
|
| 201 |
+
.logo-neuro { color: var(--ink); }
|
| 202 |
+
.logo-pulse { color: var(--cyan-bright); font-style: italic; }
|
| 203 |
+
.nav-links {
|
| 204 |
+
display: flex;
|
| 205 |
+
gap: 32px;
|
| 206 |
+
align-items: center;
|
| 207 |
+
font-family: var(--sans);
|
| 208 |
+
font-size: 0.82rem;
|
| 209 |
+
letter-spacing: 0.04em;
|
| 210 |
+
text-transform: lowercase;
|
| 211 |
+
color: var(--ink-soft);
|
| 212 |
+
}
|
| 213 |
+
.nav-links a { transition: color 0.2s; }
|
| 214 |
+
.nav-links a:hover { color: var(--cyan-bright); }
|
| 215 |
+
.nav-star {
|
| 216 |
+
display: flex;
|
| 217 |
+
align-items: center;
|
| 218 |
+
gap: 6px;
|
| 219 |
+
padding: 6px 12px;
|
| 220 |
+
border: 1px solid rgba(244, 236, 223, 0.18);
|
| 221 |
+
border-radius: 999px;
|
| 222 |
+
background: rgba(8, 6, 15, 0.45);
|
| 223 |
+
backdrop-filter: blur(6px);
|
| 224 |
+
}
|
| 225 |
+
.nav-star svg { vertical-align: -3px; }
|
| 226 |
+
.star-count {
|
| 227 |
+
font-family: var(--mono);
|
| 228 |
+
font-size: 0.75rem;
|
| 229 |
+
color: var(--ink-soft);
|
| 230 |
+
}
|
| 231 |
+
@media (max-width: 720px) {
|
| 232 |
+
.nav-links { gap: 18px; font-size: 0.74rem; }
|
| 233 |
+
.nav-links .nav-link-hide { display: none; }
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
/* Hero text stack */
|
| 237 |
+
.hero-content {
|
| 238 |
+
position: relative;
|
| 239 |
+
z-index: 5;
|
| 240 |
+
flex: 1;
|
| 241 |
+
display: flex;
|
| 242 |
+
flex-direction: column;
|
| 243 |
+
justify-content: center;
|
| 244 |
+
padding: 0 clamp(24px, 5vw, 64px) clamp(60px, 10vh, 120px);
|
| 245 |
+
max-width: 1280px;
|
| 246 |
+
width: 100%;
|
| 247 |
+
margin: 0 auto;
|
| 248 |
+
}
|
| 249 |
+
/* Staggered entrance animations */
|
| 250 |
+
@keyframes heroFadeIn {
|
| 251 |
+
from { opacity: 0; transform: translateY(20px); }
|
| 252 |
+
to { opacity: 1; transform: translateY(0); }
|
| 253 |
+
}
|
| 254 |
+
.hero-eyebrow {
|
| 255 |
+
display: inline-flex;
|
| 256 |
+
align-items: center;
|
| 257 |
+
gap: 10px;
|
| 258 |
+
align-self: flex-start;
|
| 259 |
+
padding: 7px 14px;
|
| 260 |
+
margin-bottom: 36px;
|
| 261 |
+
border: 1px solid rgba(94, 234, 212, 0.35);
|
| 262 |
+
border-radius: 999px;
|
| 263 |
+
background: rgba(8, 6, 15, 0.55);
|
| 264 |
+
backdrop-filter: blur(8px);
|
| 265 |
+
font-family: var(--mono);
|
| 266 |
+
font-size: 0.72rem;
|
| 267 |
+
letter-spacing: 0.08em;
|
| 268 |
+
text-transform: lowercase;
|
| 269 |
+
color: var(--cyan);
|
| 270 |
+
animation: heroFadeIn 1s cubic-bezier(0.16,1,0.3,1) 0.2s both;
|
| 271 |
+
}
|
| 272 |
+
.hero-eyebrow .dot {
|
| 273 |
+
width: 7px;
|
| 274 |
+
height: 7px;
|
| 275 |
+
border-radius: 50%;
|
| 276 |
+
background: var(--cyan-bright);
|
| 277 |
+
box-shadow: 0 0 12px var(--cyan-bright);
|
| 278 |
+
animation: dot-pulse 2.4s ease-in-out infinite;
|
| 279 |
+
}
|
| 280 |
+
@keyframes dot-pulse {
|
| 281 |
+
0%, 100% { opacity: 1; transform: scale(1); }
|
| 282 |
+
50% { opacity: 0.5; transform: scale(0.85); }
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
.hero-h1 {
|
| 286 |
+
font-family: var(--serif);
|
| 287 |
+
font-weight: 300;
|
| 288 |
+
font-variation-settings: "opsz" 144, "SOFT" 30;
|
| 289 |
+
font-size: clamp(2.8rem, 8.5vw, 7rem);
|
| 290 |
+
line-height: 0.96;
|
| 291 |
+
letter-spacing: -0.035em;
|
| 292 |
+
color: var(--ink);
|
| 293 |
+
max-width: 14ch;
|
| 294 |
+
margin-bottom: 32px;
|
| 295 |
+
animation: heroFadeIn 1.2s cubic-bezier(0.16,1,0.3,1) 0.4s both;
|
| 296 |
+
}
|
| 297 |
+
.hero-h1 em {
|
| 298 |
+
font-style: italic;
|
| 299 |
+
font-weight: 300;
|
| 300 |
+
color: var(--cyan);
|
| 301 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 302 |
+
text-shadow: 0 0 40px rgba(0,229,255,0.15);
|
| 303 |
+
}
|
| 304 |
+
.hero-h1 .v {
|
| 305 |
+
color: var(--violet);
|
| 306 |
+
font-style: italic;
|
| 307 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
.hero-lede {
|
| 311 |
+
font-family: var(--serif);
|
| 312 |
+
font-weight: 300;
|
| 313 |
+
font-size: clamp(1.05rem, 1.6vw, 1.35rem);
|
| 314 |
+
line-height: 1.55;
|
| 315 |
+
color: var(--ink-soft);
|
| 316 |
+
max-width: 38rem;
|
| 317 |
+
margin-bottom: 44px;
|
| 318 |
+
animation: heroFadeIn 1.2s cubic-bezier(0.16,1,0.3,1) 0.65s both;
|
| 319 |
+
}
|
| 320 |
+
.hero-lede strong {
|
| 321 |
+
font-weight: 500;
|
| 322 |
+
color: var(--ink);
|
| 323 |
+
font-style: italic;
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
.cta-row {
|
| 327 |
+
display: flex;
|
| 328 |
+
gap: 18px;
|
| 329 |
+
flex-wrap: wrap;
|
| 330 |
+
align-items: center;
|
| 331 |
+
animation: heroFadeIn 1.2s cubic-bezier(0.16,1,0.3,1) 0.85s both;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
/* Hero stats strip — the scale numbers earn the hero, not paragraph 4 */
|
| 335 |
+
.hero-stats {
|
| 336 |
+
display: flex;
|
| 337 |
+
flex-wrap: wrap;
|
| 338 |
+
gap: 28px 48px;
|
| 339 |
+
margin-top: 56px;
|
| 340 |
+
padding-top: 28px;
|
| 341 |
+
border-top: 1px solid var(--rule);
|
| 342 |
+
max-width: 44rem;
|
| 343 |
+
animation: heroFadeIn 1.2s cubic-bezier(0.16,1,0.3,1) 1.05s both;
|
| 344 |
+
}
|
| 345 |
+
.hero-stat { display: flex; flex-direction: column; gap: 8px; }
|
| 346 |
+
.hero-stat .v {
|
| 347 |
+
font-family: var(--serif);
|
| 348 |
+
font-weight: 300;
|
| 349 |
+
font-variation-settings: "opsz" 144, "SOFT" 60;
|
| 350 |
+
font-size: 1.85rem;
|
| 351 |
+
line-height: 1;
|
| 352 |
+
letter-spacing: -0.025em;
|
| 353 |
+
color: var(--ink);
|
| 354 |
+
}
|
| 355 |
+
.hero-stat .v em {
|
| 356 |
+
font-style: italic;
|
| 357 |
+
color: var(--cyan);
|
| 358 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 359 |
+
}
|
| 360 |
+
.hero-stat .l {
|
| 361 |
+
font-family: var(--mono);
|
| 362 |
+
font-size: 0.68rem;
|
| 363 |
+
letter-spacing: 0.14em;
|
| 364 |
+
text-transform: uppercase;
|
| 365 |
+
color: var(--ink-dim);
|
| 366 |
+
}
|
| 367 |
+
@media (max-width: 560px) {
|
| 368 |
+
.hero-stats { gap: 20px 32px; margin-top: 40px; padding-top: 22px; }
|
| 369 |
+
.hero-stat .v { font-size: 1.55rem; }
|
| 370 |
+
}
|
| 371 |
+
.btn {
|
| 372 |
+
display: inline-flex;
|
| 373 |
+
align-items: center;
|
| 374 |
+
gap: 10px;
|
| 375 |
+
padding: 14px 26px;
|
| 376 |
+
font-family: var(--sans);
|
| 377 |
+
font-size: 0.92rem;
|
| 378 |
+
font-weight: 500;
|
| 379 |
+
letter-spacing: 0.005em;
|
| 380 |
+
border-radius: 4px;
|
| 381 |
+
border: 1px solid transparent;
|
| 382 |
+
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
| 383 |
+
cursor: pointer;
|
| 384 |
+
white-space: nowrap;
|
| 385 |
+
}
|
| 386 |
+
.btn-primary {
|
| 387 |
+
background: var(--ink);
|
| 388 |
+
color: #02020a;
|
| 389 |
+
border-color: var(--ink);
|
| 390 |
+
}
|
| 391 |
+
.btn-primary:hover {
|
| 392 |
+
background: var(--cyan-bright);
|
| 393 |
+
border-color: var(--cyan-bright);
|
| 394 |
+
transform: translateY(-1px);
|
| 395 |
+
box-shadow: 0 12px 32px rgba(0, 229, 255, 0.32);
|
| 396 |
+
}
|
| 397 |
+
.btn-ghost {
|
| 398 |
+
background: transparent;
|
| 399 |
+
color: var(--ink);
|
| 400 |
+
border-color: rgba(244, 236, 223, 0.32);
|
| 401 |
+
backdrop-filter: blur(6px);
|
| 402 |
+
}
|
| 403 |
+
.btn-ghost:hover {
|
| 404 |
+
border-color: var(--ink);
|
| 405 |
+
background: rgba(244, 236, 223, 0.06);
|
| 406 |
+
}
|
| 407 |
+
.btn .arrow {
|
| 408 |
+
transition: transform 0.25s;
|
| 409 |
+
}
|
| 410 |
+
.btn:hover .arrow {
|
| 411 |
+
transform: translateX(4px);
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
/* Scroll cue at the bottom of the hero */
|
| 415 |
+
.scroll-cue {
|
| 416 |
+
position: absolute;
|
| 417 |
+
z-index: 5;
|
| 418 |
+
bottom: 32px;
|
| 419 |
+
left: 50%;
|
| 420 |
+
transform: translateX(-50%);
|
| 421 |
+
display: flex;
|
| 422 |
+
flex-direction: column;
|
| 423 |
+
align-items: center;
|
| 424 |
+
gap: 12px;
|
| 425 |
+
font-family: var(--mono);
|
| 426 |
+
font-size: 0.65rem;
|
| 427 |
+
letter-spacing: 0.16em;
|
| 428 |
+
text-transform: uppercase;
|
| 429 |
+
color: var(--ink-dim);
|
| 430 |
+
}
|
| 431 |
+
.scroll-line {
|
| 432 |
+
width: 1px;
|
| 433 |
+
height: 36px;
|
| 434 |
+
background: linear-gradient(180deg, transparent, var(--ink-dim));
|
| 435 |
+
position: relative;
|
| 436 |
+
overflow: hidden;
|
| 437 |
+
}
|
| 438 |
+
.scroll-line::after {
|
| 439 |
+
content: '';
|
| 440 |
+
position: absolute;
|
| 441 |
+
top: -16px;
|
| 442 |
+
left: 0;
|
| 443 |
+
right: 0;
|
| 444 |
+
height: 16px;
|
| 445 |
+
background: var(--cyan-bright);
|
| 446 |
+
animation: scroll-fall 2.4s ease-in-out infinite;
|
| 447 |
+
}
|
| 448 |
+
@keyframes scroll-fall {
|
| 449 |
+
0% { transform: translateY(0); opacity: 0; }
|
| 450 |
+
30% { opacity: 1; }
|
| 451 |
+
100% { transform: translateY(52px); opacity: 0; }
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
/* ─────────────────────────────────────────────────────────
|
| 455 |
+
EDITORIAL — narrow column long-read
|
| 456 |
+
───────────────────────────────────────────────────────── */
|
| 457 |
+
.essay {
|
| 458 |
+
max-width: 680px;
|
| 459 |
+
margin: 0 auto;
|
| 460 |
+
padding: clamp(80px, 14vh, 160px) clamp(24px, 5vw, 32px);
|
| 461 |
+
}
|
| 462 |
+
.essay-section {
|
| 463 |
+
margin-bottom: clamp(80px, 12vh, 140px);
|
| 464 |
+
opacity: 0; transform: translateY(32px);
|
| 465 |
+
transition: opacity 0.8s cubic-bezier(0.16,1,0.3,1), transform 0.8s cubic-bezier(0.16,1,0.3,1);
|
| 466 |
+
}
|
| 467 |
+
.essay-section.visible { opacity: 1; transform: translateY(0); }
|
| 468 |
+
.essay-end {
|
| 469 |
+
opacity: 0; transform: translateY(32px);
|
| 470 |
+
transition: opacity 0.8s cubic-bezier(0.16,1,0.3,1), transform 0.8s cubic-bezier(0.16,1,0.3,1);
|
| 471 |
+
}
|
| 472 |
+
.essay-end.visible { opacity: 1; transform: translateY(0); }
|
| 473 |
+
.essay-num {
|
| 474 |
+
font-family: var(--mono);
|
| 475 |
+
font-size: 0.74rem;
|
| 476 |
+
letter-spacing: 0.18em;
|
| 477 |
+
text-transform: uppercase;
|
| 478 |
+
color: var(--cyan);
|
| 479 |
+
margin-bottom: 28px;
|
| 480 |
+
display: flex;
|
| 481 |
+
align-items: center;
|
| 482 |
+
gap: 14px;
|
| 483 |
+
}
|
| 484 |
+
.essay-num::before {
|
| 485 |
+
content: '';
|
| 486 |
+
width: 28px;
|
| 487 |
+
height: 1px;
|
| 488 |
+
background: var(--cyan);
|
| 489 |
+
}
|
| 490 |
+
.essay h2 {
|
| 491 |
+
font-family: var(--serif);
|
| 492 |
+
font-weight: 300;
|
| 493 |
+
font-variation-settings: "opsz" 144, "SOFT" 40;
|
| 494 |
+
font-size: clamp(2rem, 4.4vw, 3.4rem);
|
| 495 |
+
line-height: 1.04;
|
| 496 |
+
letter-spacing: -0.025em;
|
| 497 |
+
color: var(--ink);
|
| 498 |
+
margin-bottom: 44px;
|
| 499 |
+
max-width: 18ch;
|
| 500 |
+
}
|
| 501 |
+
.essay h2 em {
|
| 502 |
+
font-style: italic;
|
| 503 |
+
color: var(--cyan);
|
| 504 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 505 |
+
}
|
| 506 |
+
.essay p {
|
| 507 |
+
font-family: var(--serif);
|
| 508 |
+
font-weight: 300;
|
| 509 |
+
font-variation-settings: "opsz" 14, "SOFT" 40;
|
| 510 |
+
font-size: 1.18rem;
|
| 511 |
+
line-height: 1.72;
|
| 512 |
+
color: var(--ink-soft);
|
| 513 |
+
margin-bottom: 1.4em;
|
| 514 |
+
max-width: 38rem;
|
| 515 |
+
}
|
| 516 |
+
.essay p strong {
|
| 517 |
+
font-weight: 500;
|
| 518 |
+
color: var(--ink);
|
| 519 |
+
}
|
| 520 |
+
.essay p em {
|
| 521 |
+
font-style: italic;
|
| 522 |
+
color: var(--ink);
|
| 523 |
+
}
|
| 524 |
+
.essay p code, .essay p .mono {
|
| 525 |
+
font-family: var(--mono);
|
| 526 |
+
font-size: 0.92em;
|
| 527 |
+
color: var(--cyan);
|
| 528 |
+
background: rgba(94, 234, 212, 0.08);
|
| 529 |
+
padding: 1px 6px;
|
| 530 |
+
border-radius: 3px;
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
/* Drop cap on the first paragraph of section 01 */
|
| 534 |
+
.essay-section.lead p:first-of-type::first-letter {
|
| 535 |
+
font-family: var(--serif);
|
| 536 |
+
font-weight: 300;
|
| 537 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 538 |
+
font-size: 5.2em;
|
| 539 |
+
float: left;
|
| 540 |
+
line-height: 0.82;
|
| 541 |
+
margin: 0.08em 0.12em -0.05em 0;
|
| 542 |
+
color: var(--cyan);
|
| 543 |
+
font-style: italic;
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
/* Pull quote */
|
| 547 |
+
.pull {
|
| 548 |
+
font-family: var(--serif);
|
| 549 |
+
font-weight: 300;
|
| 550 |
+
font-variation-settings: "opsz" 144, "SOFT" 60;
|
| 551 |
+
font-style: italic;
|
| 552 |
+
font-size: clamp(1.4rem, 2.6vw, 2rem);
|
| 553 |
+
line-height: 1.32;
|
| 554 |
+
color: var(--ink);
|
| 555 |
+
border-left: 2px solid var(--cyan);
|
| 556 |
+
padding: 8px 0 8px 28px;
|
| 557 |
+
margin: 48px 0;
|
| 558 |
+
max-width: 36rem;
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
/* Horizontal rule between essay sections */
|
| 562 |
+
.essay-rule {
|
| 563 |
+
border: none;
|
| 564 |
+
height: 1px;
|
| 565 |
+
background: var(--rule);
|
| 566 |
+
max-width: 4rem;
|
| 567 |
+
margin: 0 0 clamp(80px, 12vh, 140px);
|
| 568 |
+
}
|
| 569 |
+
|
| 570 |
+
/* Promise — three small evidence cards inline in the essay column */
|
| 571 |
+
.evidence {
|
| 572 |
+
display: grid;
|
| 573 |
+
gap: 1px;
|
| 574 |
+
background: var(--rule);
|
| 575 |
+
border: 1px solid var(--rule);
|
| 576 |
+
margin: 48px 0 8px;
|
| 577 |
+
}
|
| 578 |
+
.evidence-row {
|
| 579 |
+
display: grid;
|
| 580 |
+
grid-template-columns: 90px 1fr;
|
| 581 |
+
background: var(--bg);
|
| 582 |
+
padding: 24px 4px 24px 0;
|
| 583 |
+
align-items: start;
|
| 584 |
+
}
|
| 585 |
+
.evidence-key {
|
| 586 |
+
font-family: var(--mono);
|
| 587 |
+
font-size: 0.72rem;
|
| 588 |
+
letter-spacing: 0.1em;
|
| 589 |
+
text-transform: uppercase;
|
| 590 |
+
color: var(--cyan);
|
| 591 |
+
padding-top: 4px;
|
| 592 |
+
}
|
| 593 |
+
.evidence-val {
|
| 594 |
+
font-family: var(--sans);
|
| 595 |
+
font-size: 0.98rem;
|
| 596 |
+
line-height: 1.55;
|
| 597 |
+
color: var(--ink);
|
| 598 |
+
}
|
| 599 |
+
.evidence-val span {
|
| 600 |
+
display: block;
|
| 601 |
+
color: var(--ink-dim);
|
| 602 |
+
font-size: 0.86rem;
|
| 603 |
+
margin-top: 4px;
|
| 604 |
+
}
|
| 605 |
+
|
| 606 |
+
/* Anatomy diagram inline */
|
| 607 |
+
.anatomy-figure {
|
| 608 |
+
margin: 48px 0;
|
| 609 |
+
text-align: center;
|
| 610 |
+
}
|
| 611 |
+
.anatomy-figure svg {
|
| 612 |
+
width: 100%;
|
| 613 |
+
max-width: 520px;
|
| 614 |
+
height: auto;
|
| 615 |
+
}
|
| 616 |
+
.anatomy-figure figcaption {
|
| 617 |
+
font-family: var(--mono);
|
| 618 |
+
font-size: 0.72rem;
|
| 619 |
+
letter-spacing: 0.08em;
|
| 620 |
+
color: var(--ink-dim);
|
| 621 |
+
margin-top: 16px;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
/* Anatomy parts list */
|
| 625 |
+
.parts-list {
|
| 626 |
+
list-style: none;
|
| 627 |
+
margin: 40px 0;
|
| 628 |
+
border-top: 1px solid var(--rule);
|
| 629 |
+
}
|
| 630 |
+
.parts-list li {
|
| 631 |
+
padding: 22px 0;
|
| 632 |
+
border-bottom: 1px solid var(--rule);
|
| 633 |
+
display: grid;
|
| 634 |
+
grid-template-columns: 1fr;
|
| 635 |
+
gap: 8px;
|
| 636 |
+
}
|
| 637 |
+
.parts-list strong {
|
| 638 |
+
font-family: var(--sans);
|
| 639 |
+
font-weight: 500;
|
| 640 |
+
font-size: 0.98rem;
|
| 641 |
+
color: var(--ink);
|
| 642 |
+
letter-spacing: -0.005em;
|
| 643 |
+
}
|
| 644 |
+
.parts-list span {
|
| 645 |
+
font-family: var(--serif);
|
| 646 |
+
font-weight: 300;
|
| 647 |
+
font-size: 1.04rem;
|
| 648 |
+
line-height: 1.6;
|
| 649 |
+
color: var(--ink-soft);
|
| 650 |
+
}
|
| 651 |
+
|
| 652 |
+
/* Validation report block */
|
| 653 |
+
.proof {
|
| 654 |
+
font-family: var(--mono);
|
| 655 |
+
font-size: 0.82rem;
|
| 656 |
+
line-height: 1.85;
|
| 657 |
+
background: #050309;
|
| 658 |
+
border: 1px solid var(--rule);
|
| 659 |
+
border-radius: 4px;
|
| 660 |
+
padding: 28px 32px;
|
| 661 |
+
margin: 40px 0;
|
| 662 |
+
color: var(--ink-soft);
|
| 663 |
+
overflow-x: auto;
|
| 664 |
+
}
|
| 665 |
+
.proof .head {
|
| 666 |
+
color: var(--cyan-bright);
|
| 667 |
+
margin-bottom: 12px;
|
| 668 |
+
font-weight: 500;
|
| 669 |
+
}
|
| 670 |
+
.proof .ok { color: #6ee7b7; }
|
| 671 |
+
.proof .label { color: var(--ink-dim); }
|
| 672 |
+
.proof .k { color: var(--violet); }
|
| 673 |
+
|
| 674 |
+
/* Stack list */
|
| 675 |
+
.stack-list {
|
| 676 |
+
list-style: none;
|
| 677 |
+
counter-reset: stack;
|
| 678 |
+
margin: 40px 0;
|
| 679 |
+
}
|
| 680 |
+
.stack-list li {
|
| 681 |
+
counter-increment: stack;
|
| 682 |
+
padding: 28px 0;
|
| 683 |
+
border-top: 1px solid var(--rule);
|
| 684 |
+
display: grid;
|
| 685 |
+
grid-template-columns: 56px 1fr;
|
| 686 |
+
gap: 16px;
|
| 687 |
+
align-items: start;
|
| 688 |
+
}
|
| 689 |
+
.stack-list li:last-child { border-bottom: 1px solid var(--rule); }
|
| 690 |
+
.stack-list li::before {
|
| 691 |
+
content: counter(stack, decimal-leading-zero);
|
| 692 |
+
font-family: var(--mono);
|
| 693 |
+
font-size: 0.78rem;
|
| 694 |
+
color: var(--cyan);
|
| 695 |
+
letter-spacing: 0.06em;
|
| 696 |
+
padding-top: 5px;
|
| 697 |
+
}
|
| 698 |
+
.stack-list strong {
|
| 699 |
+
display: block;
|
| 700 |
+
font-family: var(--sans);
|
| 701 |
+
font-weight: 500;
|
| 702 |
+
font-size: 1.02rem;
|
| 703 |
+
color: var(--ink);
|
| 704 |
+
margin-bottom: 6px;
|
| 705 |
+
}
|
| 706 |
+
.stack-list span {
|
| 707 |
+
font-family: var(--serif);
|
| 708 |
+
font-weight: 300;
|
| 709 |
+
font-size: 1.02rem;
|
| 710 |
+
line-height: 1.6;
|
| 711 |
+
color: var(--ink-soft);
|
| 712 |
+
}
|
| 713 |
+
.stack-list code {
|
| 714 |
+
font-family: var(--mono);
|
| 715 |
+
font-size: 0.86em;
|
| 716 |
+
color: var(--cyan);
|
| 717 |
+
background: rgba(94, 234, 212, 0.08);
|
| 718 |
+
padding: 1px 6px;
|
| 719 |
+
border-radius: 3px;
|
| 720 |
+
}
|
| 721 |
+
|
| 722 |
+
/* ─────────────────────────────────────────────────────────
|
| 723 |
+
"In real numbers" — full-bleed scale payoff between 04 and the CTA.
|
| 724 |
+
Breaks out of the 680px essay column because these numbers want room.
|
| 725 |
+
───────────────────────────────────────────────────────── */
|
| 726 |
+
.numbers {
|
| 727 |
+
position: relative;
|
| 728 |
+
left: 50%;
|
| 729 |
+
right: 50%;
|
| 730 |
+
width: 100vw;
|
| 731 |
+
max-width: 100vw;
|
| 732 |
+
margin-left: -50vw;
|
| 733 |
+
margin-right: -50vw;
|
| 734 |
+
margin-bottom: clamp(80px, 12vh, 140px);
|
| 735 |
+
padding: clamp(56px, 9vh, 100px) clamp(24px, 5vw, 64px);
|
| 736 |
+
background:
|
| 737 |
+
radial-gradient(ellipse 80% 40% at 50% 0%, rgba(94, 234, 212, 0.04), transparent 60%),
|
| 738 |
+
radial-gradient(ellipse 80% 40% at 50% 100%, rgba(192, 132, 252, 0.03), transparent 60%);
|
| 739 |
+
border-top: 1px solid var(--rule);
|
| 740 |
+
border-bottom: 1px solid var(--rule);
|
| 741 |
+
opacity: 0; transform: translateY(32px);
|
| 742 |
+
transition: opacity 0.8s cubic-bezier(0.16,1,0.3,1), transform 0.8s cubic-bezier(0.16,1,0.3,1);
|
| 743 |
+
}
|
| 744 |
+
.numbers.visible { opacity: 1; transform: translateY(0); }
|
| 745 |
+
.numbers-inner { max-width: 1280px; margin: 0 auto; position: relative; z-index: 2; }
|
| 746 |
+
/* Per-section numbers canvas is gone — #page-canvas's prog uniform
|
| 747 |
+
ramps up horizontal flow automatically in this region. */
|
| 748 |
+
.numbers h2 {
|
| 749 |
+
font-family: var(--serif);
|
| 750 |
+
font-weight: 300;
|
| 751 |
+
font-variation-settings: "opsz" 144, "SOFT" 40;
|
| 752 |
+
font-size: clamp(2rem, 4.4vw, 3.4rem);
|
| 753 |
+
line-height: 1.04;
|
| 754 |
+
letter-spacing: -0.025em;
|
| 755 |
+
color: var(--ink);
|
| 756 |
+
margin: 24px 0 60px;
|
| 757 |
+
max-width: 22ch;
|
| 758 |
+
}
|
| 759 |
+
.numbers h2 em {
|
| 760 |
+
font-style: italic;
|
| 761 |
+
color: var(--cyan);
|
| 762 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 763 |
+
}
|
| 764 |
+
.numbers-grid {
|
| 765 |
+
display: grid;
|
| 766 |
+
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
| 767 |
+
gap: 1px;
|
| 768 |
+
background: var(--rule);
|
| 769 |
+
border: 1px solid var(--rule);
|
| 770 |
+
}
|
| 771 |
+
.numbers-cell {
|
| 772 |
+
padding: clamp(32px, 5vh, 56px) clamp(24px, 3vw, 40px);
|
| 773 |
+
background: var(--bg);
|
| 774 |
+
display: flex;
|
| 775 |
+
flex-direction: column;
|
| 776 |
+
gap: 18px;
|
| 777 |
+
transition: background 0.35s;
|
| 778 |
+
}
|
| 779 |
+
.numbers-cell:hover { background: var(--bg-warm); }
|
| 780 |
+
.numbers-num {
|
| 781 |
+
font-family: var(--serif);
|
| 782 |
+
font-weight: 300;
|
| 783 |
+
font-variation-settings: "opsz" 144, "SOFT" 80;
|
| 784 |
+
font-size: clamp(3rem, 6.4vw, 5.2rem);
|
| 785 |
+
line-height: 0.95;
|
| 786 |
+
letter-spacing: -0.03em;
|
| 787 |
+
color: var(--ink);
|
| 788 |
+
}
|
| 789 |
+
.numbers-num em {
|
| 790 |
+
font-style: italic;
|
| 791 |
+
color: var(--cyan);
|
| 792 |
+
font-variation-settings: "opsz" 144, "SOFT" 100;
|
| 793 |
+
}
|
| 794 |
+
.numbers-label {
|
| 795 |
+
font-family: var(--mono);
|
| 796 |
+
font-size: 0.7rem;
|
| 797 |
+
letter-spacing: 0.14em;
|
| 798 |
+
text-transform: uppercase;
|
| 799 |
+
color: var(--cyan);
|
| 800 |
+
}
|
| 801 |
+
.numbers-sub {
|
| 802 |
+
font-family: var(--serif);
|
| 803 |
+
font-weight: 300;
|
| 804 |
+
font-size: 1rem;
|
| 805 |
+
line-height: 1.55;
|
| 806 |
+
color: var(--ink-soft);
|
| 807 |
+
max-width: 32ch;
|
| 808 |
+
}
|
| 809 |
+
|
| 810 |
+
/* End-of-essay closing CTA */
|
| 811 |
+
.essay-end {
|
| 812 |
+
text-align: left;
|
| 813 |
+
padding-top: 40px;
|
| 814 |
+
}
|
| 815 |
+
.essay-end h2 {
|
| 816 |
+
margin-bottom: 24px;
|
| 817 |
+
}
|
| 818 |
+
.essay-end p {
|
| 819 |
+
margin-bottom: 36px;
|
| 820 |
+
}
|
| 821 |
+
|
| 822 |
+
/* ─────────────────────────────────────────────────────────
|
| 823 |
+
FOOTER — minimal, full width
|
| 824 |
+
───────────────────────────────────────────────────────── */
|
| 825 |
+
footer {
|
| 826 |
+
border-top: 1px solid var(--rule);
|
| 827 |
+
padding: 48px clamp(24px, 5vw, 64px);
|
| 828 |
+
margin-top: 80px;
|
| 829 |
+
}
|
| 830 |
+
.footer-inner {
|
| 831 |
+
max-width: 1280px;
|
| 832 |
+
margin: 0 auto;
|
| 833 |
+
display: flex;
|
| 834 |
+
flex-direction: column;
|
| 835 |
+
gap: 28px;
|
| 836 |
+
}
|
| 837 |
+
.footer-row {
|
| 838 |
+
display: flex;
|
| 839 |
+
justify-content: space-between;
|
| 840 |
+
align-items: center;
|
| 841 |
+
flex-wrap: wrap;
|
| 842 |
+
gap: 20px;
|
| 843 |
+
}
|
| 844 |
+
.footer-credit {
|
| 845 |
+
font-family: var(--sans);
|
| 846 |
+
font-size: 0.85rem;
|
| 847 |
+
color: var(--ink-dim);
|
| 848 |
+
}
|
| 849 |
+
.footer-credit a {
|
| 850 |
+
color: var(--ink-soft);
|
| 851 |
+
transition: color 0.2s;
|
| 852 |
+
}
|
| 853 |
+
.footer-credit a:hover { color: var(--cyan-bright); }
|
| 854 |
+
.footer-links {
|
| 855 |
+
display: flex;
|
| 856 |
+
gap: 24px;
|
| 857 |
+
align-items: center;
|
| 858 |
+
font-family: var(--sans);
|
| 859 |
+
font-size: 0.82rem;
|
| 860 |
+
letter-spacing: 0.02em;
|
| 861 |
+
text-transform: lowercase;
|
| 862 |
+
color: var(--ink-soft);
|
| 863 |
+
}
|
| 864 |
+
.footer-links a { transition: color 0.2s; }
|
| 865 |
+
.footer-links a:hover { color: var(--cyan-bright); }
|
| 866 |
+
.footer-related {
|
| 867 |
+
display: flex;
|
| 868 |
+
gap: 18px;
|
| 869 |
+
align-items: center;
|
| 870 |
+
flex-wrap: wrap;
|
| 871 |
+
font-family: var(--mono);
|
| 872 |
+
font-size: 0.74rem;
|
| 873 |
+
color: var(--ink-dim);
|
| 874 |
+
}
|
| 875 |
+
.footer-related .label {
|
| 876 |
+
text-transform: uppercase;
|
| 877 |
+
letter-spacing: 0.1em;
|
| 878 |
+
color: var(--ink-faint);
|
| 879 |
+
}
|
| 880 |
+
.footer-related a {
|
| 881 |
+
color: var(--ink-soft);
|
| 882 |
+
transition: color 0.2s;
|
| 883 |
+
}
|
| 884 |
+
.footer-related a:hover { color: var(--cyan-bright); }
|
| 885 |
+
.footer-bottom {
|
| 886 |
+
font-family: var(--mono);
|
| 887 |
+
font-size: 0.7rem;
|
| 888 |
+
color: var(--ink-faint);
|
| 889 |
+
letter-spacing: 0.06em;
|
| 890 |
+
display: flex;
|
| 891 |
+
justify-content: space-between;
|
| 892 |
+
flex-wrap: wrap;
|
| 893 |
+
gap: 12px;
|
| 894 |
+
padding-top: 20px;
|
| 895 |
+
border-top: 1px solid var(--rule);
|
| 896 |
+
}
|
| 897 |
+
|
| 898 |
+
/* Responsive */
|
| 899 |
+
@media (max-width: 720px) {
|
| 900 |
+
.hero { min-height: 600px; }
|
| 901 |
+
.hero-h1 { font-size: clamp(2.4rem, 11vw, 4rem); }
|
| 902 |
+
.hero-lede { font-size: 1rem; }
|
| 903 |
+
.essay { padding: 80px 24px; }
|
| 904 |
+
.essay h2 { font-size: clamp(1.7rem, 7vw, 2.4rem); }
|
| 905 |
+
.essay p { font-size: 1.08rem; }
|
| 906 |
+
.evidence-row { grid-template-columns: 1fr; gap: 8px; padding: 20px 0; }
|
| 907 |
+
.evidence-key { padding-top: 0; }
|
| 908 |
+
.stack-list li { grid-template-columns: 40px 1fr; }
|
| 909 |
+
.scroll-cue { display: none; }
|
| 910 |
+
}
|
| 911 |
+
</style>
|
| 912 |
+
<script type="module" crossorigin src="./assets/main-D1-Ogq2V.js"></script>
|
| 913 |
+
<link rel="modulepreload" crossorigin href="./assets/three.module-Bwi0mW4U.js">
|
| 914 |
+
</head>
|
| 915 |
+
<body>
|
| 916 |
+
|
| 917 |
+
<!-- Persistent page-wide Three.js backdrop. One canvas, scroll-driven. -->
|
| 918 |
+
<canvas id="page-canvas" aria-hidden="true"></canvas>
|
| 919 |
+
|
| 920 |
+
<!-- ───────────────────────────────────────────────
|
| 921 |
+
HERO — type-only editorial void.
|
| 922 |
+
Deliberately no preview of the demo: the reveal
|
| 923 |
+
is the surprise behind the CTA. Page canvas sits
|
| 924 |
+
behind this entire section at z:-1.
|
| 925 |
+
─────────────────────────────────────────────── -->
|
| 926 |
+
<section class="hero">
|
| 927 |
+
<div class="hero-grain"></div>
|
| 928 |
+
<div class="hero-vignette"></div>
|
| 929 |
+
|
| 930 |
+
<nav class="hero-nav">
|
| 931 |
+
<a href="/" class="logo">
|
| 932 |
+
<span class="logo-neuro">neuro</span><span class="logo-pulse">pulse</span>
|
| 933 |
+
</a>
|
| 934 |
+
<div class="nav-links">
|
| 935 |
+
<a href="#essay" class="nav-link-hide">essay</a>
|
| 936 |
+
<a href="#stack" class="nav-link-hide">stack</a>
|
| 937 |
+
<a href="/app/">demo</a>
|
| 938 |
+
<a href="https://github.com/abgnydn/neuropulse" target="_blank" rel="noopener" class="nav-star">
|
| 939 |
+
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
|
| 940 |
+
<span class="star-count" id="navStarCount">·</span>
|
| 941 |
+
</a>
|
| 942 |
+
</div>
|
| 943 |
+
</nav>
|
| 944 |
+
|
| 945 |
+
<div class="hero-content">
|
| 946 |
+
<div class="hero-eyebrow">
|
| 947 |
+
<span class="dot"></span>
|
| 948 |
+
live · phi-3-mini · webgpu
|
| 949 |
+
</div>
|
| 950 |
+
<h1 class="hero-h1">
|
| 951 |
+
A real transformer, <em>laid bare.</em>
|
| 952 |
+
</h1>
|
| 953 |
+
<p class="hero-lede">
|
| 954 |
+
3.8 billion parameters. On your GPU, in your browser. Every point, every line, every pulse — a real tensor, read one-to-one. <strong>The model itself, drawn from the inside.</strong> <em>Shift-click any of the 1,024 attention heads to turn it off and watch what breaks.</em>
|
| 955 |
+
</p>
|
| 956 |
+
<div class="cta-row">
|
| 957 |
+
<a href="/app/" class="btn btn-primary">
|
| 958 |
+
Launch the demo
|
| 959 |
+
<span class="arrow">→</span>
|
| 960 |
+
</a>
|
| 961 |
+
<a href="#essay" class="btn btn-ghost">Read the essay</a>
|
| 962 |
+
</div>
|
| 963 |
+
|
| 964 |
+
<div class="hero-stats">
|
| 965 |
+
<div class="hero-stat">
|
| 966 |
+
<div class="v"><em>3.8</em>B</div>
|
| 967 |
+
<div class="l">parameters</div>
|
| 968 |
+
</div>
|
| 969 |
+
<div class="hero-stat">
|
| 970 |
+
<div class="v">292</div>
|
| 971 |
+
<div class="l">dispatches / token</div>
|
| 972 |
+
</div>
|
| 973 |
+
<div class="hero-stat">
|
| 974 |
+
<div class="v">22</div>
|
| 975 |
+
<div class="l">GPU buffers</div>
|
| 976 |
+
</div>
|
| 977 |
+
<div class="hero-stat">
|
| 978 |
+
<div class="v"><em>0</em></div>
|
| 979 |
+
<div class="l">servers</div>
|
| 980 |
+
</div>
|
| 981 |
+
</div>
|
| 982 |
+
</div>
|
| 983 |
+
|
| 984 |
+
<div class="scroll-cue">
|
| 985 |
+
<span>scroll</span>
|
| 986 |
+
<div class="scroll-line"></div>
|
| 987 |
+
</div>
|
| 988 |
+
</section>
|
| 989 |
+
|
| 990 |
+
<!-- ───────────────────────────────────────────────
|
| 991 |
+
EDITORIAL LONG-READ
|
| 992 |
+
─────────────────────────────────────────────── -->
|
| 993 |
+
<article class="essay" id="essay">
|
| 994 |
+
|
| 995 |
+
<section class="essay-section lead">
|
| 996 |
+
<div class="essay-num">01 · The Promise</div>
|
| 997 |
+
<h2>The model, <em>drawn from inside.</em></h2>
|
| 998 |
+
<p>Most "AI visualizations" online are decoration — dots pulsing to a chosen rhythm, animated metaphors built on top of static images. The model itself sits somewhere else entirely.</p>
|
| 999 |
+
<p>Neuropulse takes the opposite path. Every brightness, every line, every motion is a direct readout of a real <span class="mono">WebGPU</span> buffer mid-forward-pass. When the model thinks, you watch <em>it</em> think — the thing itself, not a representation of it.</p>
|
| 1000 |
+
<p class="pull">Strict 1:1. Every pixel a function of a real tensor.</p>
|
| 1001 |
+
<p>3.8B weights in your GPU. Attention in <span class="mono">WGSL</span>. Next-token sampled in your tab. The whole pipeline lives inside this page — close it and the inference stops with it.</p>
|
| 1002 |
+
|
| 1003 |
+
<div class="evidence">
|
| 1004 |
+
<div class="evidence-row">
|
| 1005 |
+
<div class="evidence-key">model</div>
|
| 1006 |
+
<div class="evidence-val">Phi-3-mini, q4f16_1<span>3.8B parameters · same weights Microsoft ships</span></div>
|
| 1007 |
+
</div>
|
| 1008 |
+
<div class="evidence-row">
|
| 1009 |
+
<div class="evidence-key">runtime</div>
|
| 1010 |
+
<div class="evidence-val">WebGPU compute shaders<span>13 pipelines · 22 buffers · 292 dispatches per token</span></div>
|
| 1011 |
+
</div>
|
| 1012 |
+
<div class="evidence-row">
|
| 1013 |
+
<div class="evidence-key">privacy</div>
|
| 1014 |
+
<div class="evidence-val">Your GPU only<span>zero server calls · nothing leaves your machine</span></div>
|
| 1015 |
+
</div>
|
| 1016 |
+
</div>
|
| 1017 |
+
</section>
|
| 1018 |
+
|
| 1019 |
+
<hr class="essay-rule"/>
|
| 1020 |
+
|
| 1021 |
+
<section class="essay-section">
|
| 1022 |
+
<div class="essay-num">02 · What you're watching</div>
|
| 1023 |
+
<h2>Every part of the model, <em>labeled.</em></h2>
|
| 1024 |
+
<p>The 3D scene is not a metaphor. Every glowing element maps to a specific tensor in Phi-3-mini's compute graph.</p>
|
| 1025 |
+
<p>The 3,072 points of the residual stream are laid out by PCA of the model's layer-0 <code>qkv_proj</code> weights — so dims read into attention together sit near each other. Each point's brightness is the <em>live</em> value of that residual dim on every step.</p>
|
| 1026 |
+
<p>Hover an attention head — the brightness you see <em>is</em> that head's output magnitude.</p>
|
| 1027 |
+
|
| 1028 |
+
<figure class="anatomy-figure">
|
| 1029 |
+
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
|
| 1030 |
+
<defs>
|
| 1031 |
+
<radialGradient id="anaCyan" cx="50%" cy="50%"><stop offset="0%" stop-color="#5eead4" stop-opacity="0.9"/><stop offset="100%" stop-color="#5eead4" stop-opacity="0"/></radialGradient>
|
| 1032 |
+
<radialGradient id="anaViolet" cx="50%" cy="50%"><stop offset="0%" stop-color="#c084fc" stop-opacity="0.85"/><stop offset="100%" stop-color="#c084fc" stop-opacity="0"/></radialGradient>
|
| 1033 |
+
</defs>
|
| 1034 |
+
<g stroke="rgba(94,234,212,0.18)" stroke-width="0.5">
|
| 1035 |
+
<line x1="50" y1="60" x2="350" y2="60"/>
|
| 1036 |
+
<line x1="50" y1="100" x2="350" y2="100"/>
|
| 1037 |
+
<line x1="50" y1="140" x2="350" y2="140"/>
|
| 1038 |
+
<line x1="50" y1="180" x2="350" y2="180"/>
|
| 1039 |
+
<line x1="50" y1="220" x2="350" y2="220"/>
|
| 1040 |
+
<line x1="50" y1="260" x2="350" y2="260"/>
|
| 1041 |
+
<line x1="50" y1="300" x2="350" y2="300"/>
|
| 1042 |
+
<line x1="50" y1="340" x2="350" y2="340"/>
|
| 1043 |
+
</g>
|
| 1044 |
+
<circle cx="140" cy="90" r="32" fill="url(#anaCyan)"/>
|
| 1045 |
+
<text x="68" y="55" font-family="JetBrains Mono, monospace" font-size="9" fill="#5eead4">attention heads</text>
|
| 1046 |
+
<line x1="140" y1="90" x2="92" y2="58" stroke="#5eead4" stroke-width="0.5"/>
|
| 1047 |
+
|
| 1048 |
+
<rect x="165" y="160" width="70" height="70" fill="url(#anaViolet)" rx="6"/>
|
| 1049 |
+
<text x="245" y="200" font-family="JetBrains Mono, monospace" font-size="9" fill="#c084fc">FFN slab</text>
|
| 1050 |
+
<line x1="235" y1="195" x2="245" y2="197" stroke="#c084fc" stroke-width="0.5"/>
|
| 1051 |
+
|
| 1052 |
+
<line x1="200" y1="30" x2="200" y2="370" stroke="#5eead4" stroke-opacity="0.4" stroke-width="2"/>
|
| 1053 |
+
<text x="205" y="22" font-family="JetBrains Mono, monospace" font-size="9" fill="#5eead4">residual stream</text>
|
| 1054 |
+
|
| 1055 |
+
<g>
|
| 1056 |
+
<rect x="290" y="260" width="8" height="60" fill="#5eead4" opacity="0.4"/>
|
| 1057 |
+
<rect x="302" y="260" width="8" height="60" fill="#5eead4" opacity="0.5"/>
|
| 1058 |
+
<rect x="314" y="260" width="8" height="60" fill="#5eead4" opacity="0.6"/>
|
| 1059 |
+
<rect x="326" y="260" width="8" height="60" fill="#5eead4" opacity="0.4"/>
|
| 1060 |
+
</g>
|
| 1061 |
+
<text x="278" y="340" font-family="JetBrains Mono, monospace" font-size="9" fill="#5eead4">KV cache</text>
|
| 1062 |
+
|
| 1063 |
+
<circle cx="200" cy="370" r="14" fill="#ff8c42" opacity="0.5"/>
|
| 1064 |
+
<text x="135" y="395" font-family="JetBrains Mono, monospace" font-size="9" fill="#ff8c42">LM head → next token</text>
|
| 1065 |
+
|
| 1066 |
+
<circle cx="200" cy="30" r="10" fill="#c084fc" opacity="0.7"/>
|
| 1067 |
+
</svg>
|
| 1068 |
+
<figcaption>fig. 1 — the anatomy of a single forward pass</figcaption>
|
| 1069 |
+
</figure>
|
| 1070 |
+
|
| 1071 |
+
<ul class="parts-list">
|
| 1072 |
+
<li>
|
| 1073 |
+
<strong>32 layer rings</strong>
|
| 1074 |
+
<span>Each ring is one transformer block. Brightness tracks the post-attention plus post-FFN residual norm for that layer — watch the signal build as the prompt flows upward.</span>
|
| 1075 |
+
</li>
|
| 1076 |
+
<li>
|
| 1077 |
+
<strong>32 attention heads per layer</strong>
|
| 1078 |
+
<span>Cyan heads on the outer ring. Each lights up proportional to its output magnitude. 1,024 heads in total (32 layers × 32 heads), all live.</span>
|
| 1079 |
+
</li>
|
| 1080 |
+
<li>
|
| 1081 |
+
<strong>FFN slab</strong>
|
| 1082 |
+
<span>The violet 8,192-neuron expansion. By far the largest compute budget in the model. You can see it pulse as the MLP activates.</span>
|
| 1083 |
+
</li>
|
| 1084 |
+
<li>
|
| 1085 |
+
<strong>Residual stream (3,072 dims)</strong>
|
| 1086 |
+
<span>The highway through the network. 3,072 points, one per dim, placed by PCA of the layer-0 <code>qkv_proj</code> weights so functionally related dims sit near each other. Brightness on each point is the live residual value at that dim.</span>
|
| 1087 |
+
</li>
|
| 1088 |
+
<li>
|
| 1089 |
+
<strong>KV cache strips</strong>
|
| 1090 |
+
<span>The growing memory of past tokens. Each strip is one position; height equals cache fill for that layer.</span>
|
| 1091 |
+
</li>
|
| 1092 |
+
<li>
|
| 1093 |
+
<strong>LM head</strong>
|
| 1094 |
+
<span>Final projection to 32,064 vocab logits. Softmax → next token. The live top-k distribution prints to the side panel as the model decodes.</span>
|
| 1095 |
+
</li>
|
| 1096 |
+
</ul>
|
| 1097 |
+
</section>
|
| 1098 |
+
|
| 1099 |
+
<hr class="essay-rule"/>
|
| 1100 |
+
|
| 1101 |
+
<section class="essay-section">
|
| 1102 |
+
<div class="essay-num">03 · Validation</div>
|
| 1103 |
+
<h2>Cross-checked against <em>reference Phi-3.</em></h2>
|
| 1104 |
+
<p>"Strict 1:1" is a strong claim, so it has to be falsifiable. Neuropulse ships with a built-in test suite that diffs the WebGPU implementation against a reference HuggingFace fp16 Phi-3-mini on a fixed set of prompts cached as <code>reference.json</code>. Click the <strong>wrench</strong> icon inside the demo to run it — the actual numbers from <em>your</em> GPU print to your browser console.</p>
|
| 1105 |
+
|
| 1106 |
+
<div class="proof">
|
| 1107 |
+
<div class="head">═══ What the suite checks ═══</div>
|
| 1108 |
+
<div>GPU: <span class="k">q4f16_1 Phi-3-mini</span> Reference: <span class="k">HF fp16 Phi-3-mini</span></div>
|
| 1109 |
+
<div> </div>
|
| 1110 |
+
<div><span class="label">[1]</span> <span class="ok">Tokenizer</span> — GPU input ids match HF byte-for-byte on every prompt</div>
|
| 1111 |
+
<div><span class="label">[2]</span> <span class="ok">Hidden states</span> — full 3,072-dim residual diffed at layers 0, 4, 8, 12, 16, 20, 24, 28, 31</div>
|
| 1112 |
+
<div><span class="label">[3]</span> <span class="ok">Attention (layer 31)</span> — online softmax cross-checked against an explicit-softmax reference path</div>
|
| 1113 |
+
<div><span class="label">[4]</span> <span class="ok">Logits</span> — top-k probabilities + Jensen–Shannon divergence vs HF on a 15-prompt sweep, teacher-forced for 5 steps each</div>
|
| 1114 |
+
<div><span class="label">[5]</span> <span class="ok">Long context</span> — 290-token prompt, 10 decode steps, top-1 matched against HF</div>
|
| 1115 |
+
<div><span class="label">[6]</span> <span class="ok">Sampler</span> — 5,000-sample empirical distribution vs softmax, JSD < 1e-2</div>
|
| 1116 |
+
</div>
|
| 1117 |
+
|
| 1118 |
+
<p>Expect tiny deltas at the hidden-state level — that's the cost of int4, not drift. What matters is the last line: <strong>identical top-1 tokens vs fp16 Phi-3</strong> on the test set. Re-run it on your own machine in under a minute.</p>
|
| 1119 |
+
</section>
|
| 1120 |
+
|
| 1121 |
+
<hr class="essay-rule"/>
|
| 1122 |
+
|
| 1123 |
+
<section class="essay-section">
|
| 1124 |
+
<div class="essay-num">04 · Causal Scrubbing</div>
|
| 1125 |
+
<h2>And you can <em>reach in.</em></h2>
|
| 1126 |
+
<p>Watching is the easy half. The harder, more interesting half: <strong>shift-click any of the 1,024 attention-head spheres</strong> and that head's contribution to the residual stream is zeroed before O-projection — the canonical single-head ablation from the mech-interp literature, running live on the same WebGPU context that just rendered the frame. Press <strong>Run ablated</strong> and the same prompt generates twice, side by side: once whole, once missing that one head.</p>
|
| 1127 |
+
|
| 1128 |
+
<p>Or pick a layer, run a sweep, and let it ablate every head in turn. The panel paints a strip the model itself authored — each cell colored by how much the answer moved when that head went silent. <strong>Cool tones for the heads the prompt didn't need; warm ones for the heads it leaned on.</strong> About sixty seconds buys you a layer's importance map.</p>
|
| 1129 |
+
|
| 1130 |
+
<div class="proof">
|
| 1131 |
+
<div class="head">═══ Verified ablation gradient · prompt: "Paris is the capital of" ═══</div>
|
| 1132 |
+
<div> </div>
|
| 1133 |
+
<div><span class="label">{L0}</span> <span class="ok">all heads off</span> — output barely shifts. Layer-0 attention near the embeddings is heavily redundant.</div>
|
| 1134 |
+
<div><span class="label">{L31}</span> <span class="ok">all heads off</span> — diverges at the low-certainty positions. The final layer's FFN and residual still carry the decision.</div>
|
| 1135 |
+
<div><span class="label">{L28..L31}</span> <span class="ok">stacked</span> — generation hits the stop token early. Compounded ablation bites.</div>
|
| 1136 |
+
<div><span class="label">every layer off</span> — pure FFN + residual, no token-to-token information flow. <span class="k">"-,unlintzegesenma\\. #quierudo\\i'mʔholmo<0x95>-"</span></div>
|
| 1137 |
+
</div>
|
| 1138 |
+
|
| 1139 |
+
<p>This is the same primitive that found "induction heads" and traced the circuits behind in-context learning — work that, until now, lived in Python notebooks tethered to CPUs and A100s. <strong>Here it runs in a browser tab, on your laptop, in real time, on a 3.8B-parameter model.</strong> The next thirty seconds of your life can look exactly like a mech-interp paper figure.</p>
|
| 1140 |
+
</section>
|
| 1141 |
+
|
| 1142 |
+
<hr class="essay-rule"/>
|
| 1143 |
+
|
| 1144 |
+
<section class="essay-section" id="stack">
|
| 1145 |
+
<div class="essay-num">05 · The Stack</div>
|
| 1146 |
+
<h2>How it's <em>built.</em></h2>
|
| 1147 |
+
<p>Four pieces. No frameworks for the inference path, no dependency soup, no clever tricks hiding the model from you.</p>
|
| 1148 |
+
|
| 1149 |
+
<ol class="stack-list">
|
| 1150 |
+
<li>
|
| 1151 |
+
<div>
|
| 1152 |
+
<strong>WebGPU compute & WGSL</strong>
|
| 1153 |
+
<span>13 pipelines, 22 buffers, 292 dispatches per token. Quantization: <code>q4f16_1</code>. Hand-written attention and FFN kernels.</span>
|
| 1154 |
+
</div>
|
| 1155 |
+
</li>
|
| 1156 |
+
<li>
|
| 1157 |
+
<div>
|
| 1158 |
+
<strong>MLC Phi-3-mini weights</strong>
|
| 1159 |
+
<span>The same weights as <code>mlc-ai/Phi-3-mini-4k-instruct-q4f16_1-MLC</code>, fetched directly from HuggingFace and cached in the browser's Cache API.</span>
|
| 1160 |
+
</div>
|
| 1161 |
+
</li>
|
| 1162 |
+
<li>
|
| 1163 |
+
<div>
|
| 1164 |
+
<strong>Three.js scene</strong>
|
| 1165 |
+
<span>Plain <code>WebGLRenderer</code>. No bloom, no particles, no decorative shaders. Every pixel pulls from a real tensor on every frame.</span>
|
| 1166 |
+
</div>
|
| 1167 |
+
</li>
|
| 1168 |
+
<li>
|
| 1169 |
+
<div>
|
| 1170 |
+
<strong>PCA layout from the model's own weights</strong>
|
| 1171 |
+
<span>Residual points are placed by PCA of layer 0's <code>qkv_proj.weight</code> columns; FFN points by PCA of <code>down_proj.weight</code>. Dims that get read or written together end up near each other, so the geometry is shaped by the model itself, not by hand.</span>
|
| 1172 |
+
</div>
|
| 1173 |
+
</li>
|
| 1174 |
+
</ol>
|
| 1175 |
+
</section>
|
| 1176 |
+
|
| 1177 |
+
<hr class="essay-rule"/>
|
| 1178 |
+
|
| 1179 |
+
<section class="numbers" id="numbers">
|
| 1180 |
+
<div class="numbers-inner">
|
| 1181 |
+
<div class="essay-num">06 · In real numbers</div>
|
| 1182 |
+
<h2>What it <em>actually</em> is.</h2>
|
| 1183 |
+
<div class="numbers-grid">
|
| 1184 |
+
<div class="numbers-cell">
|
| 1185 |
+
<div class="numbers-num"><em>3.8</em>B</div>
|
| 1186 |
+
<div class="numbers-label">parameters</div>
|
| 1187 |
+
<div class="numbers-sub">Phi-3-mini, q4f16_1. The same weights Microsoft ships — loaded into your GPU, not emulated.</div>
|
| 1188 |
+
</div>
|
| 1189 |
+
<div class="numbers-cell">
|
| 1190 |
+
<div class="numbers-num">1,024</div>
|
| 1191 |
+
<div class="numbers-label">attention heads, live</div>
|
| 1192 |
+
<div class="numbers-sub">32 layers × 32 heads. Every one of them drawn from its real output magnitude on every token.</div>
|
| 1193 |
+
</div>
|
| 1194 |
+
<div class="numbers-cell">
|
| 1195 |
+
<div class="numbers-num">292</div>
|
| 1196 |
+
<div class="numbers-label">dispatches / token</div>
|
| 1197 |
+
<div class="numbers-sub">13 WGSL pipelines, 22 GPU buffers. One full forward pass, in your browser tab.</div>
|
| 1198 |
+
</div>
|
| 1199 |
+
<div class="numbers-cell">
|
| 1200 |
+
<div class="numbers-num"><em>0</em></div>
|
| 1201 |
+
<div class="numbers-label">servers</div>
|
| 1202 |
+
<div class="numbers-sub">Inference begins and ends inside this tab — every weight, every kernel, every readback. Close the tab; it's gone with you.</div>
|
| 1203 |
+
</div>
|
| 1204 |
+
</div>
|
| 1205 |
+
</div>
|
| 1206 |
+
</section>
|
| 1207 |
+
|
| 1208 |
+
<section class="essay-end">
|
| 1209 |
+
<div class="essay-num">Now you</div>
|
| 1210 |
+
<h2>See it for <em>yourself.</em></h2>
|
| 1211 |
+
<p>Open Neuropulse. Feed it a prompt. Watch the model think. First load streams ~2 GB into your GPU; next visit is instant (OPFS-cached to disk).</p>
|
| 1212 |
+
<a href="/app/" class="btn btn-primary">
|
| 1213 |
+
Launch Neuropulse
|
| 1214 |
+
<span class="arrow">→</span>
|
| 1215 |
+
</a>
|
| 1216 |
+
</section>
|
| 1217 |
+
|
| 1218 |
+
</article>
|
| 1219 |
+
|
| 1220 |
+
<!-- ───────────────────────────────────────────────
|
| 1221 |
+
FOOTER
|
| 1222 |
+
─────────────────────────────────────────────── -->
|
| 1223 |
+
<footer>
|
| 1224 |
+
<div class="footer-inner">
|
| 1225 |
+
<div class="footer-row">
|
| 1226 |
+
<div class="footer-credit">
|
| 1227 |
+
<span class="logo" style="font-size:1rem"><span class="logo-neuro">neuro</span><span class="logo-pulse">pulse</span></span>
|
| 1228 |
+
by <a href="https://github.com/abgnydn" target="_blank" rel="noopener">Ahmet Barış Günaydın</a>
|
| 1229 |
+
</div>
|
| 1230 |
+
<div class="footer-links">
|
| 1231 |
+
<a href="/app/">demo</a>
|
| 1232 |
+
<a href="#essay">essay</a>
|
| 1233 |
+
<a href="https://github.com/abgnydn/neuropulse" target="_blank" rel="noopener" style="color:var(--cyan-bright)">★ star on github</a>
|
| 1234 |
+
<a href="https://www.linkedin.com/in/abgnydn/" target="_blank" rel="noopener">linkedin</a>
|
| 1235 |
+
<a href="https://barisgunaydin.com" target="_blank" rel="noopener">site</a>
|
| 1236 |
+
</div>
|
| 1237 |
+
</div>
|
| 1238 |
+
<div class="footer-related">
|
| 1239 |
+
<span class="label">More by Ahmet</span>
|
| 1240 |
+
<a href="https://kernelfusion.dev" target="_blank" rel="noopener">kernelfusion.dev</a>
|
| 1241 |
+
<a href="https://gpubench.dev" target="_blank" rel="noopener">gpubench.dev</a>
|
| 1242 |
+
<a href="https://zerotvm.com" target="_blank" rel="noopener">zerotvm.com</a>
|
| 1243 |
+
<a href="https://webgpudna.com" target="_blank" rel="noopener">webgpudna.com</a>
|
| 1244 |
+
<a href="https://webgpu-q.vercel.app" target="_blank" rel="noopener">webgpu-q.vercel.app</a>
|
| 1245 |
+
</div>
|
| 1246 |
+
<div class="footer-bottom">
|
| 1247 |
+
<div>real forward pass · built with WebGPU + Three.js · MIT licensed</div>
|
| 1248 |
+
<div>© 2026</div>
|
| 1249 |
+
</div>
|
| 1250 |
+
</div>
|
| 1251 |
+
</footer>
|
| 1252 |
+
|
| 1253 |
+
<script>
|
| 1254 |
+
// Live GitHub star count for the nav button. Cached in sessionStorage so
|
| 1255 |
+
// we don't hammer the unauthenticated GitHub API (60 req/hr limit).
|
| 1256 |
+
(function () {
|
| 1257 |
+
const el = document.getElementById('navStarCount')
|
| 1258 |
+
if (!el) return
|
| 1259 |
+
const CACHE_KEY = 'np:stars'
|
| 1260 |
+
const CACHE_TTL = 10 * 60 * 1000 // 10 minutes
|
| 1261 |
+
try {
|
| 1262 |
+
const cached = sessionStorage.getItem(CACHE_KEY)
|
| 1263 |
+
if (cached) {
|
| 1264 |
+
const { count, ts } = JSON.parse(cached)
|
| 1265 |
+
if (Date.now() - ts < CACHE_TTL && typeof count === 'number') {
|
| 1266 |
+
el.textContent = count
|
| 1267 |
+
return
|
| 1268 |
+
}
|
| 1269 |
+
}
|
| 1270 |
+
} catch {}
|
| 1271 |
+
fetch('https://api.github.com/repos/abgnydn/neuropulse')
|
| 1272 |
+
.then(r => r.ok ? r.json() : null)
|
| 1273 |
+
.then(d => {
|
| 1274 |
+
if (!d || typeof d.stargazers_count !== 'number') {
|
| 1275 |
+
// Repo is private or API failed — hide the count chip so we
|
| 1276 |
+
// don't ship a dead "·" placeholder.
|
| 1277 |
+
el.style.display = 'none'
|
| 1278 |
+
return
|
| 1279 |
+
}
|
| 1280 |
+
el.textContent = d.stargazers_count
|
| 1281 |
+
try { sessionStorage.setItem(CACHE_KEY, JSON.stringify({ count: d.stargazers_count, ts: Date.now() })) } catch {}
|
| 1282 |
+
})
|
| 1283 |
+
.catch(() => { el.style.display = 'none' })
|
| 1284 |
+
})()
|
| 1285 |
+
</script>
|
| 1286 |
+
|
| 1287 |
+
<script>
|
| 1288 |
+
// Scroll-reveal for essay sections
|
| 1289 |
+
const revealObs = new IntersectionObserver((entries) => {
|
| 1290 |
+
entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('visible'); revealObs.unobserve(e.target); } });
|
| 1291 |
+
}, { threshold: 0.15 });
|
| 1292 |
+
document.querySelectorAll('.essay-section, .essay-end, .numbers').forEach(el => revealObs.observe(el));
|
| 1293 |
+
|
| 1294 |
+
// Mobile guard — the demo needs ~2 GB of GPU memory and WebGPU, neither
|
| 1295 |
+
// of which work on phones. Intercept /app/ links on narrow screens and
|
| 1296 |
+
// show a friendly "desktop only" modal instead of crashing the browser.
|
| 1297 |
+
(function () {
|
| 1298 |
+
const IS_MOBILE = window.matchMedia('(max-width: 820px)').matches || /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent);
|
| 1299 |
+
if (!IS_MOBILE) return;
|
| 1300 |
+
|
| 1301 |
+
const modal = document.createElement('div');
|
| 1302 |
+
modal.id = 'mobileGate';
|
| 1303 |
+
modal.innerHTML = `
|
| 1304 |
+
<div class="mg-backdrop"></div>
|
| 1305 |
+
<div class="mg-card">
|
| 1306 |
+
<div class="mg-eyebrow">Desktop only</div>
|
| 1307 |
+
<h3>Neuropulse runs a real 2 GB model on your GPU.</h3>
|
| 1308 |
+
<p>Your phone browser doesn't have enough GPU memory — it will crash mid-download. Open <strong>neuropulse.live</strong> on a desktop Chrome, Edge, or Safari TP to try it.</p>
|
| 1309 |
+
<div class="mg-actions">
|
| 1310 |
+
<button class="mg-btn mg-copy" type="button">Copy link</button>
|
| 1311 |
+
<button class="mg-btn mg-dismiss" type="button">Got it</button>
|
| 1312 |
+
</div>
|
| 1313 |
+
</div>
|
| 1314 |
+
`;
|
| 1315 |
+
const css = document.createElement('style');
|
| 1316 |
+
css.textContent = `
|
| 1317 |
+
#mobileGate { position:fixed; inset:0; z-index:10000; display:none; align-items:center; justify-content:center; padding:24px; }
|
| 1318 |
+
#mobileGate.open { display:flex; }
|
| 1319 |
+
#mobileGate .mg-backdrop { position:absolute; inset:0; background:rgba(2,2,16,0.85); backdrop-filter: blur(12px); }
|
| 1320 |
+
#mobileGate .mg-card { position:relative; max-width:420px; background:#0d0d1f; border:1px solid rgba(94,234,212,0.25); border-radius:16px; padding:28px 24px; color:#f4ecdf; box-shadow:0 20px 60px rgba(0,0,0,0.6); }
|
| 1321 |
+
#mobileGate .mg-eyebrow { font-size:0.7rem; letter-spacing:0.18em; text-transform:uppercase; color:#5eead4; margin-bottom:12px; }
|
| 1322 |
+
#mobileGate h3 { font-size:1.15rem; line-height:1.35; margin:0 0 12px; font-weight:600; }
|
| 1323 |
+
#mobileGate p { font-size:0.9rem; line-height:1.55; color:#b8b4a8; margin:0 0 20px; }
|
| 1324 |
+
#mobileGate strong { color:#00e5ff; font-weight:500; }
|
| 1325 |
+
#mobileGate .mg-actions { display:flex; gap:10px; }
|
| 1326 |
+
#mobileGate .mg-btn { flex:1; padding:12px 16px; border-radius:10px; border:1px solid rgba(94,234,212,0.3); background:transparent; color:#f4ecdf; font-size:0.85rem; font-family:inherit; cursor:pointer; -webkit-tap-highlight-color:transparent; }
|
| 1327 |
+
#mobileGate .mg-copy { background:#5eead4; color:#0d0d1f; border-color:#5eead4; font-weight:600; }
|
| 1328 |
+
#mobileGate .mg-copy.copied { background:#00e5ff; }
|
| 1329 |
+
`;
|
| 1330 |
+
document.head.appendChild(css);
|
| 1331 |
+
document.body.appendChild(modal);
|
| 1332 |
+
|
| 1333 |
+
function openGate(e) {
|
| 1334 |
+
if (e) e.preventDefault();
|
| 1335 |
+
modal.classList.add('open');
|
| 1336 |
+
}
|
| 1337 |
+
function closeGate() { modal.classList.remove('open'); }
|
| 1338 |
+
|
| 1339 |
+
document.querySelectorAll('a[href="/app/"], a[href^="/app"]').forEach(a => {
|
| 1340 |
+
a.addEventListener('click', openGate);
|
| 1341 |
+
});
|
| 1342 |
+
|
| 1343 |
+
modal.querySelector('.mg-dismiss').addEventListener('click', closeGate);
|
| 1344 |
+
modal.querySelector('.mg-backdrop').addEventListener('click', closeGate);
|
| 1345 |
+
const copyBtn = modal.querySelector('.mg-copy');
|
| 1346 |
+
copyBtn.addEventListener('click', () => {
|
| 1347 |
+
const url = 'https://neuropulse.live';
|
| 1348 |
+
navigator.clipboard?.writeText(url).then(() => {
|
| 1349 |
+
copyBtn.textContent = 'Copied ✓';
|
| 1350 |
+
copyBtn.classList.add('copied');
|
| 1351 |
+
setTimeout(closeGate, 900);
|
| 1352 |
+
}).catch(() => { copyBtn.textContent = url; });
|
| 1353 |
+
});
|
| 1354 |
+
})();
|
| 1355 |
+
</script>
|
| 1356 |
+
|
| 1357 |
+
<!-- Persistent page-wide Three.js backdrop — scroll drives particle morph,
|
| 1358 |
+
readability-fade dims during essay body, brightens at hero/numbers/CTA. -->
|
| 1359 |
+
|
| 1360 |
+
</body>
|
| 1361 |
</html>
|
kernels-dark.svg
ADDED
|
|
kernels-light.svg
ADDED
|
|
layers-dark.svg
ADDED
|
|
layers-light.svg
ADDED
|
|
monogram-dark.svg
ADDED
|
|
monogram-light.svg
ADDED
|
|
og-dark.svg
ADDED
|
|
og-light.svg
ADDED
|
|
og.png
ADDED
|
panels-dark.svg
ADDED
|
|
panels-light.svg
ADDED
|
|
pca-layout.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
preview-dark.svg
ADDED
|
|
preview-light.svg
ADDED
|
|
recordings/capital-01.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
recordings/capital-ablated-01.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
recordings/code-01.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
recordings/intro-01.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
reference.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
robots.txt
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# https://neuropulse.live
|
| 2 |
+
User-agent: *
|
| 3 |
+
Allow: /
|
| 4 |
+
|
| 5 |
+
# Disallow scraping by AI training crawlers (this is a creative work)
|
| 6 |
+
User-agent: GPTBot
|
| 7 |
+
Disallow: /
|
| 8 |
+
|
| 9 |
+
User-agent: Google-Extended
|
| 10 |
+
Disallow: /
|
| 11 |
+
|
| 12 |
+
User-agent: ClaudeBot
|
| 13 |
+
Disallow: /
|
| 14 |
+
|
| 15 |
+
User-agent: CCBot
|
| 16 |
+
Disallow: /
|
| 17 |
+
|
| 18 |
+
User-agent: Bytespider
|
| 19 |
+
Disallow: /
|
| 20 |
+
|
| 21 |
+
User-agent: anthropic-ai
|
| 22 |
+
Disallow: /
|
| 23 |
+
|
| 24 |
+
Sitemap: https://neuropulse.live/sitemap.xml
|
| 25 |
+
Host: https://neuropulse.live
|
runlocal-dark.svg
ADDED
|
|
runlocal-light.svg
ADDED
|
|
scene-dark.svg
ADDED
|
|
scene-light.svg
ADDED
|
|
sitemap.xml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
| 3 |
+
<url>
|
| 4 |
+
<loc>https://neuropulse.live/</loc>
|
| 5 |
+
<changefreq>monthly</changefreq>
|
| 6 |
+
<priority>1.0</priority>
|
| 7 |
+
</url>
|
| 8 |
+
<url>
|
| 9 |
+
<loc>https://neuropulse.live/app/</loc>
|
| 10 |
+
<changefreq>monthly</changefreq>
|
| 11 |
+
<priority>0.9</priority>
|
| 12 |
+
</url>
|
| 13 |
+
</urlset>
|
stack-dark.svg
ADDED
|
|
stack-light.svg
ADDED
|
|
stats-dark.svg
ADDED
|
|