Download core/tools/sky.template.html from playn4/playnfrontierAI: direct link, hf CLI and curl.
- Browser
- Download file 8.91 kB
-
https://huggingface.co/playn4/playnfrontierAI/resolve/main/core/tools/sky.template.html
- Command line
-
hf download hf://playn4/playnfrontierAI/core/tools/sky.template.html
-
curl -L -o sky.template.html https://huggingface.co/playn4/playnfrontierAI/resolve/main/core/tools/sky.template.html
8.91 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>the memory sky — OMN seen from inside</title> | |
| <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='88'>✦</text></svg>"> | |
| <style> | |
| html,body{margin:0;height:100%;background:#03050c;overflow:hidden; | |
| font-family:Georgia,'Times New Roman',serif;} | |
| canvas{position:fixed;inset:0;width:100%;height:100%;cursor:crosshair;} | |
| #tip{position:fixed;pointer-events:none;opacity:0;transition:opacity .25s ease; | |
| background:rgba(6,10,20,.88);border:1px solid rgba(255,217,160,.25);border-radius:6px; | |
| padding:7px 11px;color:#F2E3C8;font-size:13px;line-height:1.5;max-width:280px; | |
| box-shadow:0 0 24px rgba(255,217,160,.08);} | |
| #tip .t{font-variant:small-caps;letter-spacing:.08em;color:#FFD9A0;} | |
| #tip .m{opacity:.62;font-size:11px;} | |
| #cap{position:fixed;left:50%;top:4.5vh;transform:translateX(-50%);text-align:center; | |
| pointer-events:none;color:#C9D6F2;opacity:.6;} | |
| #cap .a{font-variant:small-caps;letter-spacing:.34em;font-size:clamp(13px,1.5vw,19px);} | |
| #cap .b{font-style:italic;opacity:.6;font-size:clamp(10px,1.1vw,13px);margin-top:.5vh;} | |
| #foot{position:fixed;left:50%;bottom:3.2vh;transform:translateX(-50%);pointer-events:none; | |
| color:#C9D6F2;opacity:.34;font-size:12px;letter-spacing:.18em;font-variant:small-caps;} | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="sky"></canvas> | |
| <div id="cap"><div class="a">the memory sky</div><div class="b">OMN canon, seen from inside</div></div> | |
| <div id="foot">hover a star · click to send a thought</div> | |
| <div id="tip"></div> | |
| <script> | |
| ; | |
| window.__errs=[];window.onerror=(m,s,l)=>{__errs.push(m+" @"+l);}; | |
| const GRAPH=__GRAPH_DATA__; | |
| const $=s=>document.querySelector(s); | |
| const cv=$("#sky"),ctx=cv.getContext("2d"),tip=$("#tip"); | |
| const DPR=Math.min(devicePixelRatio||1,1.5); | |
| let W=0,H=0; | |
| function resize(){W=innerWidth;H=innerHeight;cv.width=W*DPR;cv.height=H*DPR;ctx.setTransform(DPR,0,0,DPR,0,0);} | |
| addEventListener("resize",resize);resize(); | |
| /* palette by group */ | |
| const STYLE={ | |
| facts: {c:"255,217,160", r:5.2, glow:22}, | |
| projects:{c:"232,184,122", r:4.6, glow:18}, | |
| decisions:{c:"159,184,232", r:3.4, glow:13}, | |
| root: {c:"201,214,242", r:4.0, glow:15}, | |
| }; | |
| const group=n=>n.id.includes("/")?n.id.split("/")[0]:"root"; | |
| const deg={};GRAPH.links.forEach(l=>{deg[l.s]=(deg[l.s]||0)+1;deg[l.t]=(deg[l.t]||0)+1;}); | |
| /* deterministic scatter: golden-angle rings by group */ | |
| const RING={facts:.16,projects:.30,decisions:.44,root:.24}; | |
| let seed=42;const rnd=()=>{seed=(seed*1103515245+12345)&0x7fffffff;return seed/0x7fffffff;}; | |
| const GA=Math.PI*(3-Math.sqrt(5)); | |
| const ringN={facts:0,projects:0,decisions:0,root:0}; | |
| const nodes=GRAPH.nodes.map((n,i)=>{ | |
| const g=group(n),k=ringN[g]++,R=RING[g]; | |
| const a=k*GA+ (g==="decisions"? .5:0), r=R*Math.min(W,H)*(.75+.35*rnd()); | |
| return{...n,g,deg:deg[n.id]||0, | |
| x:W/2+Math.cos(a)*r, y:H/2+Math.sin(a)*r*.82, | |
| vx:0,vy:0, ph:rnd()*6.28, tw:.4+rnd()*.9, sz:1+ .28*(n.deg||0)}; | |
| }); | |
| /* background starfield + nebulae (static, generated once) */ | |
| const BG=Array.from({length:260},()=>({x:Math.random(),y:Math.random(), | |
| r:.3+Math.random()*1.1, a:.15+Math.random()*.5, ph:Math.random()*6.28, sp:.3+Math.random()})); | |
| const NEB=[ | |
| {x:.24,y:.30,r:.42,c:"255,190,120"},{x:.72,y:.62,r:.5,c:"120,150,255"},{x:.55,y:.18,r:.3,c:"255,140,90"}]; | |
| /* links adjacency for thought-pulses */ | |
| const adj={};GRAPH.links.forEach((l,i)=>{(adj[l.s]=adj[l.s]||[]).push(l.t);(adj[l.t]=adj[l.t]||[]).push(l.s);}); | |
| const pulses=[]; // {id, t0} | |
| const shoots=[]; // shooting stars | |
| let mouse={x:.5,y:.5,px:null,py:null},hover=null,nextShoot=performance.now()+9000; | |
| function physics(t,dt){ | |
| for(let i=0;i<nodes.length;i++){const n=nodes[i]; | |
| let fx=0,fy=0; | |
| for(let j=0;j<nodes.length;j++){if(i===j)continue;const o=nodes[j]; | |
| let dx=n.x-o.x,dy=n.y-o.y,d2=dx*dx+dy*dy+40; | |
| if(d2<92000){const f=1900/d2;fx+=dx*f;fy+=dy*f;}} | |
| fx+=(W/2-n.x)*.0006; fy+=(H/2-n.y)*.0006; // gravity to heart | |
| fx+=Math.sin(t*.33+n.ph)*.05; fy+=Math.cos(t*.27+n.ph)*.05; // the wander | |
| n.vx=(n.vx+fx*dt)*.93; n.vy=(n.vy+fy*dt)*.93; | |
| } | |
| GRAPH.links.forEach(l=>{const a=nodes[GRAPH.nodes.findIndex(x=>x.id===l.s)], | |
| b=nodes[GRAPH.nodes.findIndex(x=>x.id===l.t)]; | |
| let dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1; | |
| const rest=130,f=(d-rest)*.004; | |
| a.vx+=dx/d*f;a.vy+=dy/d*f;b.vx-=dx/d*f;b.vy-=dy/d*f;}); | |
| nodes.forEach(n=>{n.x+=n.vx;n.y+=n.vy;}); | |
| } | |
| function draw(t){ | |
| ctx.clearRect(0,0,W,H); | |
| let g=ctx.createRadialGradient(W*.5,H*.46,0,W*.5,H*.46,Math.max(W,H)*.75); | |
| g.addColorStop(0,"#0a1226");g.addColorStop(.6,"#060a18");g.addColorStop(1,"#03050c"); | |
| ctx.fillStyle=g;ctx.fillRect(0,0,W,H); | |
| const ox=(mouse.x-.5)*-24, oy=(mouse.y-.5)*-16; // parallax — looking around | |
| ctx.save();ctx.translate(ox,oy); | |
| NEB.forEach(nb=>{const rg=ctx.createRadialGradient(nb.x*W,nb.y*H,0,nb.x*W,nb.y*H,nb.r*Math.min(W,H)); | |
| rg.addColorStop(0,"rgba("+nb.c+",.05)");rg.addColorStop(1,"rgba("+nb.c+",0)"); | |
| ctx.fillStyle=rg;ctx.fillRect(0,0,W,H);}); | |
| BG.forEach(s=>{const a=s.a*(.55+.45*Math.sin(t*s.sp+s.ph)); | |
| ctx.fillStyle="rgba(220,230,255,"+a+")"; | |
| ctx.beginPath();ctx.arc(s.x*W,s.y*H,s.r,0,6.283);ctx.fill();}); | |
| /* constellation lines */ | |
| GRAPH.links.forEach(l=>{ | |
| const a=nodes[GRAPH.nodes.findIndex(x=>x.id===l.s)],b=nodes[GRAPH.nodes.findIndex(x=>x.id===l.t)]; | |
| if(!a||!b)return; // never crash on a dangling thread | |
| const hot=pulses.some(p=>(p.id===l.s||p.id===l.t)&&t-p.t0<1.1); | |
| ctx.setLineDash(l.k==="supersedes"?[4,4]:[]); | |
| ctx.strokeStyle=(hot?"rgba(255,230,180,.55)":"rgba(180,200,255,"+(l.k==="supersedes"?.10:.14)+")"); | |
| ctx.lineWidth=hot?1.6:1; | |
| ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke(); | |
| ctx.setLineDash([]);}); | |
| /* stars */ | |
| let hov=null; | |
| nodes.forEach(n=>{ | |
| const S=STYLE[n.g], tw=.72+.28*Math.sin(t*n.tw+n.ph); | |
| let boost=0;const p=pulses.find(p=>p.id===n.id); | |
| if(p){const dt=t-p.t0;if(dt>0&&dt<1.2)boost=Math.exp(-dt*2.6)*2.6;} | |
| const r=(S.r+n.deg*.5+n.sz)*tw+boost*3; | |
| const gr=ctx.createRadialGradient(n.x,n.y,0,n.x,n.y,r*4+boost*10); | |
| gr.addColorStop(0,"rgba("+S.c+",.95)"); | |
| gr.addColorStop(.25,"rgba("+S.c+",.5)"); | |
| gr.addColorStop(1,"rgba("+S.c+",0)"); | |
| ctx.fillStyle=gr;ctx.beginPath();ctx.arc(n.x,n.y,r*4+boost*10,0,6.283);ctx.fill(); | |
| ctx.fillStyle="rgba(255,255,255,.96)"; | |
| ctx.beginPath();ctx.arc(n.x,n.y,Math.max(1.1,r*.42),0,6.283);ctx.fill(); | |
| if(n.stale){ctx.strokeStyle="rgba(255,120,90,.8)";ctx.lineWidth=1; | |
| ctx.beginPath();ctx.arc(n.x,n.y,r*2.6+4,0,6.283);ctx.stroke();} | |
| if(n.g==="facts"){ctx.fillStyle="rgba(255,222,170,.8)"; | |
| ctx.font="11px Georgia";ctx.textAlign="center"; | |
| ctx.fillText(n.title.split("—")[0].trim().toLowerCase(),n.x,n.y+r*4+12);} | |
| if(mouse.px!=null&&Math.hypot(mouse.px-n.x,mouse.py-n.y)<26)hov=n; | |
| }); | |
| hover=hov; | |
| /* shooting stars — a memory being written */ | |
| shoots.forEach((s,i)=>{if(t>s.t0+1.4){shoots.splice(i,1);return;} | |
| const k=(t-s.t0)/1.4, x=s.x+s.vx*k*W, y=s.y+s.vy*k*H, a=Math.sin(k*3.14); | |
| const gr=ctx.createLinearGradient(x,y,x-s.vx*90,y-s.vy*90); | |
| gr.addColorStop(0,"rgba(255,240,210,"+.85*a+")");gr.addColorStop(1,"rgba(255,240,210,0)"); | |
| ctx.strokeStyle=gr;ctx.lineWidth=1.6;ctx.beginPath();ctx.moveTo(x,y); | |
| ctx.lineTo(x-s.vx*90,y-s.vy*90);ctx.stroke();}); | |
| ctx.restore(); | |
| } | |
| let last=performance.now(); | |
| function loop(now){ | |
| const dt=Math.min(.05,(now-last)/1000);last=now;const t=now/1000; | |
| physics(t,dt); | |
| draw(t); | |
| if(now>nextShoot){shoots.push({x:Math.random()*.7+.05,y:Math.random()*.25, | |
| vx:.25+Math.random()*.3,vy:.12+Math.random()*.12,t0:t}); | |
| nextShoot=now+12000+Math.random()*16000;} | |
| if(hover){tip.style.opacity=1; | |
| tip.style.left=Math.min(W-300,hover.x+16)+"px";tip.style.top=(hover.y+14)+"px"; | |
| tip.innerHTML="<div class='t'>"+hover.title+"</div><div class='m'>"+hover.id+" · "+ | |
| hover.g+" · "+(hover.deg||0)+" links"+(hover.stale?" · ⚠STALE":"")+"</div>"; | |
| }else tip.style.opacity=0; | |
| requestAnimationFrame(loop); | |
| } | |
| addEventListener("mousemove",e=>{mouse={x:e.clientX/W,y:e.clientY/H,px:e.clientX,py:e.clientY};}); | |
| cv.addEventListener("click",e=>{ | |
| let best=null,bd=28; | |
| nodes.forEach(n=>{const d=Math.hypot(e.clientX-n.x,e.clientY-n.y);if(d<bd){bd=d;best=n;}}); | |
| if(!best)return; | |
| const seen=new Set([best.id]);let frontier=[best.id],depth=0; | |
| while(frontier.length&&depth<4){ | |
| frontier.forEach(id=>pulses.push({id,t0:performance.now()/1000+depth*.28})); | |
| frontier=frontier.flatMap(id=>adj[id]||[]).filter(id=>!seen.has(id)); | |
| frontier.forEach(id=>seen.add(id));depth++; | |
| } | |
| }); | |
| requestAnimationFrame(loop); | |
| </script> | |
| </body> | |
| </html> | |