first-commit
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run

This commit is contained in:
Zakaria
2026-05-04 14:58:14 -04:00
commit a46764fb1b
1210 changed files with 233231 additions and 0 deletions
@@ -0,0 +1,138 @@
/* html-ppt :: animations.css
* Apply by adding class="anim-<name>" or data-anim="<name>".
* Durations are deliberately snappy; tweak --anim-dur per element.
*/
:root{--anim-dur:.7s;--anim-ease:cubic-bezier(.4,0,.2,1)}
/* ---------- FADE DIRECTIONALS ---------- */
@keyframes kf-fade-up{from{opacity:0;transform:translateY(32px)}to{opacity:1;transform:none}}
@keyframes kf-fade-down{from{opacity:0;transform:translateY(-32px)}to{opacity:1;transform:none}}
@keyframes kf-fade-left{from{opacity:0;transform:translateX(-40px)}to{opacity:1;transform:none}}
@keyframes kf-fade-right{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}
.anim-fade-up{animation:kf-fade-up var(--anim-dur) var(--anim-ease) both}
.anim-fade-down{animation:kf-fade-down var(--anim-dur) var(--anim-ease) both}
.anim-fade-left{animation:kf-fade-left var(--anim-dur) var(--anim-ease) both}
.anim-fade-right{animation:kf-fade-right var(--anim-dur) var(--anim-ease) both}
/* ---------- RISE / DROP / ZOOM / BLUR / GLITCH ---------- */
@keyframes kf-rise{from{opacity:0;transform:translateY(60px) scale(.97);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
@keyframes kf-drop{from{opacity:0;transform:translateY(-60px) scale(.97)}to{opacity:1;transform:none}}
@keyframes kf-zoom{0%{opacity:0;transform:scale(.6)}60%{transform:scale(1.04)}100%{opacity:1;transform:scale(1)}}
@keyframes kf-blur{from{opacity:0;filter:blur(18px)}to{opacity:1;filter:none}}
@keyframes kf-glitch{0%{opacity:0;transform:translateX(0);clip-path:inset(0 0 0 0)}
20%{opacity:1;transform:translateX(-6px);clip-path:inset(20% 0 30% 0)}
40%{transform:translateX(4px);clip-path:inset(50% 0 10% 0)}
60%{transform:translateX(-3px);clip-path:inset(10% 0 60% 0)}
80%{transform:translateX(2px);clip-path:inset(0 0 0 0)}
100%{opacity:1;transform:none}}
.anim-rise-in{animation:kf-rise .9s var(--anim-ease) both}
.anim-drop-in{animation:kf-drop .8s var(--anim-ease) both}
.anim-zoom-pop{animation:kf-zoom .7s cubic-bezier(.22,1.3,.36,1) both}
.anim-blur-in{animation:kf-blur .8s var(--anim-ease) both}
.anim-glitch-in{animation:kf-glitch .8s steps(5,end) both}
/* ---------- TYPEWRITER ---------- */
.anim-typewriter{display:inline-block;overflow:hidden;white-space:nowrap;border-right:2px solid currentColor;
width:0;animation:kf-type 2.4s steps(40,end) forwards, kf-caret 1s step-end infinite}
@keyframes kf-type{to{width:100%}}
@keyframes kf-caret{50%{border-color:transparent}}
/* ---------- GLOW / SHIMMER / GRADIENT-FLOW ---------- */
@keyframes kf-neon{0%,100%{text-shadow:0 0 8px var(--accent),0 0 20px var(--accent)}
50%{text-shadow:0 0 16px var(--accent),0 0 40px var(--accent),0 0 80px var(--accent)}}
.anim-neon-glow{animation:kf-neon 2s ease-in-out infinite}
.anim-shimmer-sweep{position:relative;overflow:hidden}
.anim-shimmer-sweep::after{content:"";position:absolute;inset:0;
background:linear-gradient(110deg,transparent 40%,rgba(255,255,255,.55) 50%,transparent 60%);
transform:translateX(-100%);animation:kf-shimmer 2.4s var(--anim-ease) infinite}
@keyframes kf-shimmer{to{transform:translateX(100%)}}
.anim-gradient-flow{background:linear-gradient(90deg,var(--accent),var(--accent-2,var(--accent)),var(--accent-3,var(--accent)),var(--accent));
background-size:300% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;
animation:kf-gradflow 4s linear infinite}
@keyframes kf-gradflow{to{background-position:300% 0}}
/* ---------- STAGGER LIST ---------- */
.anim-stagger-list > *{opacity:0;animation:kf-rise .65s var(--anim-ease) both}
.anim-stagger-list > *:nth-child(1){animation-delay:.05s}
.anim-stagger-list > *:nth-child(2){animation-delay:.15s}
.anim-stagger-list > *:nth-child(3){animation-delay:.25s}
.anim-stagger-list > *:nth-child(4){animation-delay:.35s}
.anim-stagger-list > *:nth-child(5){animation-delay:.45s}
.anim-stagger-list > *:nth-child(6){animation-delay:.55s}
.anim-stagger-list > *:nth-child(7){animation-delay:.65s}
.anim-stagger-list > *:nth-child(8){animation-delay:.75s}
.anim-stagger-list > *:nth-child(n+9){animation-delay:.85s}
/* ---------- COUNTER-UP (JS-driven, marker class only) ---------- */
.counter{font-variant-numeric:tabular-nums}
/* ---------- SVG PATH DRAW ---------- */
.anim-path-draw path,.anim-path-draw line,.anim-path-draw polyline,.anim-path-draw circle,.anim-path-draw rect{
stroke-dasharray:1000;stroke-dashoffset:1000;animation:kf-draw 2s var(--anim-ease) forwards}
@keyframes kf-draw{to{stroke-dashoffset:0}}
/* ---------- PARALLAX TILT (hover) ---------- */
.anim-parallax-tilt{transform-style:preserve-3d;transition:transform .4s var(--anim-ease)}
.anim-parallax-tilt:hover{transform:perspective(900px) rotateX(6deg) rotateY(-8deg) translateZ(10px)}
/* ---------- CARD FLIP 3D ---------- */
@keyframes kf-flip{from{transform:perspective(1200px) rotateY(-90deg);opacity:0}
to{transform:perspective(1200px) rotateY(0);opacity:1}}
.anim-card-flip-3d{animation:kf-flip .9s var(--anim-ease) both;transform-style:preserve-3d;backface-visibility:hidden}
/* ---------- CUBE ROTATE 3D ---------- */
@keyframes kf-cube{from{transform:perspective(1200px) rotateX(20deg) rotateY(-90deg) translateZ(-200px);opacity:0}
to{transform:perspective(1200px) rotateX(0) rotateY(0) translateZ(0);opacity:1}}
.anim-cube-rotate-3d{animation:kf-cube 1s var(--anim-ease) both}
/* ---------- PAGE TURN 3D ---------- */
@keyframes kf-pageturn{from{transform:perspective(1600px) rotateY(-85deg);transform-origin:left center;opacity:0}
to{transform:perspective(1600px) rotateY(0);opacity:1}}
.anim-page-turn-3d{animation:kf-pageturn 1s var(--anim-ease) both;transform-origin:left center}
/* ---------- PERSPECTIVE ZOOM ---------- */
@keyframes kf-pzoom{from{opacity:0;transform:perspective(1400px) translateZ(-400px) rotateX(12deg)}
to{opacity:1;transform:none}}
.anim-perspective-zoom{animation:kf-pzoom 1s var(--anim-ease) both}
/* ---------- MARQUEE SCROLL ---------- */
.anim-marquee-scroll{display:flex;gap:48px;white-space:nowrap;animation:kf-marquee 20s linear infinite}
@keyframes kf-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* ---------- KEN BURNS ---------- */
@keyframes kf-kenburns{0%{transform:scale(1) translate(0,0)}100%{transform:scale(1.15) translate(-2%,-1%)}}
.anim-kenburns{animation:kf-kenburns 14s ease-in-out infinite alternate}
/* ---------- CONFETTI BURST (pseudo — pure CSS sparkles) ---------- */
.anim-confetti-burst{position:relative}
.anim-confetti-burst::before,.anim-confetti-burst::after{
content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;
background:var(--accent);box-shadow:
20px -30px 0 var(--accent-2,var(--accent)),-25px -20px 0 var(--accent-3,var(--accent)),
30px 20px 0 var(--good,#1aaf6c),-30px 25px 0 var(--warn,#f5a524),
40px -10px 0 var(--bad,#e0445a),-45px 0 0 var(--accent),
10px 40px 0 var(--accent-2,var(--accent)),-15px -40px 0 var(--accent-3,var(--accent));
opacity:0;animation:kf-confetti 1.2s var(--anim-ease) forwards}
.anim-confetti-burst::after{animation-delay:.15s;transform:rotate(45deg)}
@keyframes kf-confetti{0%{opacity:0;transform:scale(.2)}30%{opacity:1}100%{opacity:0;transform:scale(2.2)}}
/* ---------- SPOTLIGHT ---------- */
@keyframes kf-spot{0%{clip-path:circle(0% at 50% 50%)}100%{clip-path:circle(140% at 50% 50%)}}
.anim-spotlight{animation:kf-spot 1.1s var(--anim-ease) both}
/* ---------- MORPH SHAPE (SVG) ---------- */
.anim-morph-shape path{animation:kf-morph 6s ease-in-out infinite alternate}
@keyframes kf-morph{0%{d:path("M60,120 Q120,20 180,120 T300,120")}
100%{d:path("M60,120 Q120,220 180,120 T300,120")}}
/* ---------- RIPPLE REVEAL ---------- */
@keyframes kf-ripple{0%{clip-path:circle(0% at 20% 80%);opacity:.4}
100%{clip-path:circle(160% at 20% 80%);opacity:1}}
.anim-ripple-reveal{animation:kf-ripple 1.2s var(--anim-ease) both}
/* reduced motion */
@media (prefers-reduced-motion: reduce){
[class*="anim-"]{animation:none!important;transition:none!important}
}
@@ -0,0 +1,99 @@
/* html-ppt :: fx-runtime.js
* Canvas FX autoloader + lifecycle manager.
* - Dynamically loads all fx modules listed in FX_LIST
* - Initializes [data-fx] elements when their slide becomes active
* - Calls handle.stop() when the slide leaves
*/
(function(){
'use strict';
const FX_LIST = [
'_util',
'particle-burst','confetti-cannon','firework','starfield','matrix-rain',
'knowledge-graph','neural-net','constellation','orbit-ring','galaxy-swirl',
'word-cascade','letter-explode','chain-react','magnetic-field','data-stream',
'gradient-blob','sparkle-trail','shockwave','typewriter-multi','counter-explosion'
];
// Resolve base path of this script so it works from any page location.
const myScript = document.currentScript || (function(){
const all = document.getElementsByTagName('script');
for (const s of all){ if (s.src && s.src.indexOf('fx-runtime.js')>-1) return s; }
return null;
})();
const base = myScript ? myScript.src.replace(/fx-runtime\.js.*$/, 'fx/') : 'assets/animations/fx/';
let loaded = 0;
const total = FX_LIST.length;
const ready = new Promise((resolve) => {
if (!total) return resolve();
FX_LIST.forEach((name) => {
const s = document.createElement('script');
s.src = base + name + '.js';
s.async = false;
s.onload = s.onerror = () => { if (++loaded >= total) resolve(); };
document.head.appendChild(s);
});
});
window.__hpxActive = window.__hpxActive || new Map();
function initFxIn(root){
if (!window.HPX) return;
const els = root.querySelectorAll('[data-fx]');
els.forEach((el) => {
if (window.__hpxActive.has(el)) return;
const name = el.getAttribute('data-fx');
const fn = window.HPX[name];
if (typeof fn !== 'function') return;
try {
const handle = fn(el, {}) || { stop(){} };
window.__hpxActive.set(el, handle);
} catch(e){ console.warn('[hpx-fx]', name, e); }
});
}
function stopFxIn(root){
const els = root.querySelectorAll('[data-fx]');
els.forEach((el) => {
const h = window.__hpxActive.get(el);
if (h && typeof h.stop === 'function'){
try{ h.stop(); }catch(e){}
}
window.__hpxActive.delete(el);
});
}
function reinitFxIn(root){
stopFxIn(root);
initFxIn(root);
}
window.__hpxReinit = reinitFxIn;
function boot(){
ready.then(() => {
const active = document.querySelector('.slide.is-active') || document.querySelector('.slide');
if (active) initFxIn(active);
// Watch all slides for class changes
const slides = document.querySelectorAll('.slide');
slides.forEach((sl) => {
const mo = new MutationObserver((muts) => {
for (const m of muts){
if (m.attributeName === 'class'){
if (sl.classList.contains('is-active')) initFxIn(sl);
else stopFxIn(sl);
}
}
});
mo.observe(sl, { attributes: true, attributeFilter: ['class'] });
});
});
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', boot);
} else {
boot();
}
})();
@@ -0,0 +1,63 @@
/* html-ppt fx :: shared helpers */
(function(){
window.HPX = window.HPX || {};
const U = window.HPX._u = {};
U.css = (el, name, fb) => {
const v = getComputedStyle(el).getPropertyValue(name).trim();
return v || fb;
};
U.accent = (el, fb) => U.css(el, '--accent', fb || '#7c5cff');
U.accent2 = (el, fb) => U.css(el, '--accent-2', fb || '#22d3ee');
U.text = (el, fb) => U.css(el, '--text-1', fb || '#eaeaf2');
U.palette = (el) => [
U.accent(el, '#7c5cff'),
U.accent2(el, '#22d3ee'),
U.css(el, '--ok', '#22c55e'),
U.css(el, '--warn', '#f59e0b'),
U.css(el, '--danger', '#ef4444'),
];
U.canvas = (el) => {
if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
const c = document.createElement('canvas');
c.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;pointer-events:none;display:block;';
el.appendChild(c);
const ctx = c.getContext('2d');
let w = 0, h = 0, dpr = Math.max(1, Math.min(2, window.devicePixelRatio||1));
const fit = () => {
const r = el.getBoundingClientRect();
w = Math.max(1, r.width|0);
h = Math.max(1, r.height|0);
c.width = (w*dpr)|0;
c.height = (h*dpr)|0;
ctx.setTransform(dpr,0,0,dpr,0,0);
};
fit();
const ro = new ResizeObserver(fit);
ro.observe(el);
return {
c, ctx,
get w(){return w;}, get h(){return h;}, get dpr(){return dpr;},
destroy(){
try{ro.disconnect();}catch(e){}
if (c.parentNode) c.parentNode.removeChild(c);
}
};
};
U.loop = (fn) => {
let raf = 0, stopped = false, t0 = performance.now();
const tick = (t) => {
if (stopped) return;
fn((t - t0)/1000);
raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
return () => { stopped = true; cancelAnimationFrame(raf); };
};
U.rand = (a,b) => a + Math.random()*(b-a);
})();
@@ -0,0 +1,41 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['chain-react'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
const N = 8;
const stop = U.loop((t) => {
ctx.clearRect(0,0,k.w,k.h);
const cy = k.h/2;
const pad = 60;
const dx = (k.w - pad*2)/(N-1);
const period = 2.4;
const phase = (t % period) / period; // 0..1
for (let i=0;i<N;i++){
const x = pad + i*dx;
const my = i/(N-1);
const d = Math.abs(phase - my);
const pulse = Math.max(0, 1 - d*6);
const r = 18 + pulse*18;
// glow
const g = ctx.createRadialGradient(x,cy,0,x,cy,r*2);
g.addColorStop(0, `rgba(124,92,255,${0.4*pulse})`);
g.addColorStop(1, 'rgba(0,0,0,0)');
ctx.fillStyle = g;
ctx.fillRect(x-r*2, cy-r*2, r*4, r*4);
// circle
ctx.fillStyle = pulse>0.1 ? ac2 : ac;
ctx.beginPath(); ctx.arc(x,cy,r,0,Math.PI*2); ctx.fill();
ctx.strokeStyle='rgba(255,255,255,0.4)'; ctx.lineWidth=2;
ctx.stroke();
// connectors
if (i<N-1){
ctx.strokeStyle='rgba(200,200,230,0.3)'; ctx.lineWidth=2;
ctx.beginPath(); ctx.moveTo(x+r,cy); ctx.lineTo(x+dx-r,cy); ctx.stroke();
}
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,49 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['confetti-cannon'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
let parts = [];
const fire = () => {
for (let side=0; side<2; side++){
const x0 = side===0 ? 20 : k.w-20;
const y0 = k.h - 20;
for (let i=0;i<40;i++){
const a = side===0 ? U.rand(-Math.PI*0.7, -Math.PI*0.4) : U.rand(-Math.PI*0.6, -Math.PI*0.3) - Math.PI/2 - Math.PI/6;
const spd = U.rand(300, 520);
parts.push({
x: x0, y: y0,
vx: Math.cos(a)*spd, vy: Math.sin(a)*spd,
w: U.rand(6,12), h: U.rand(3,7),
rot: Math.random()*Math.PI, vr: U.rand(-6,6),
c: pal[(Math.random()*pal.length)|0],
life: 1
});
}
}
};
fire();
let last = 0;
const stop = U.loop((t) => {
ctx.clearRect(0,0,k.w,k.h);
if (t - last > 3) { fire(); last = t; }
const dt = 1/60;
parts = parts.filter(p => p.life > 0 && p.y < k.h+40);
for (const p of parts){
p.vy += 520*dt;
p.x += p.vx*dt; p.y += p.vy*dt;
p.rot += p.vr*dt;
p.life -= 0.006;
ctx.save();
ctx.translate(p.x, p.y); ctx.rotate(p.rot);
ctx.globalAlpha = Math.max(0, p.life);
ctx.fillStyle = p.c;
ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
ctx.restore();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,44 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['constellation'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const ac = U.accent(el,'#9fb4ff');
const N = 70;
let pts = [];
const seed = () => {
pts = Array.from({length:N}, () => ({
x: Math.random()*k.w, y: Math.random()*k.h,
vx: U.rand(-0.3,0.3), vy: U.rand(-0.3,0.3)
}));
};
seed();
let lw=k.w, lh=k.h;
const stop = U.loop(() => {
if (k.w!==lw||k.h!==lh){ seed(); lw=k.w; lh=k.h; }
ctx.clearRect(0,0,k.w,k.h);
for (const p of pts){
p.x += p.vx; p.y += p.vy;
if (p.x<0||p.x>k.w) p.vx*=-1;
if (p.y<0||p.y>k.h) p.vy*=-1;
}
for (let i=0;i<N;i++){
for (let j=i+1;j<N;j++){
const a=pts[i], b=pts[j];
const d = Math.hypot(a.x-b.x, a.y-b.y);
if (d < 150){
ctx.globalAlpha = 1 - d/150;
ctx.strokeStyle = ac; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
}
}
}
ctx.globalAlpha = 1;
ctx.fillStyle = ac;
for (const p of pts){
ctx.beginPath(); ctx.arc(p.x,p.y,1.8,0,Math.PI*2); ctx.fill();
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,58 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['counter-explosion'] = function(el){
const U = window.HPX._u;
if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
const target = parseInt(el.getAttribute('data-fx-to') || '2400', 10);
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
// number overlay
const num = document.createElement('div');
num.style.cssText = 'position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font:900 120px system-ui,sans-serif;color:var(--text-1,#fff);pointer-events:none;text-shadow:0 4px 40px rgba(124,92,255,0.5);';
num.textContent = '0';
el.appendChild(num);
let parts = [];
let state = 'count'; // count | burst | hold
let stateT = 0;
let value = 0;
let cycle = 0;
const burst = () => {
const cx = k.w/2, cy = k.h/2;
for (let i=0;i<120;i++){
const a = Math.random()*Math.PI*2;
const s = U.rand(120, 400);
parts.push({x:cx,y:cy,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,r:U.rand(2,5),c:pal[(Math.random()*pal.length)|0]});
}
};
const stop = U.loop(() => {
ctx.clearRect(0,0,k.w,k.h);
const dt = 1/60;
stateT += dt;
if (state === 'count'){
const dur = 2.2;
const p = Math.min(1, stateT/dur);
const eased = 1 - Math.pow(1-p,3);
value = Math.round(target*eased);
num.textContent = value.toLocaleString();
if (p >= 1){ state='burst'; stateT=0; burst(); }
} else if (state === 'burst'){
if (stateT > 0.05 && stateT < 0.3 && parts.length < 200) {}
if (stateT > 2.5){ state='hold'; stateT=0; }
} else if (state === 'hold'){
if (stateT > 1.5){
state='count'; stateT=0; value=0; num.textContent='0'; cycle++;
}
}
parts = parts.filter(p => p.life > 0);
for (const p of parts){
p.vy += 260*dt; p.vx *= 0.985; p.vy *= 0.985;
p.x += p.vx*dt; p.y += p.vy*dt; p.life -= 0.01;
ctx.globalAlpha = Math.max(0,p.life);
ctx.fillStyle = p.c;
ctx.beginPath(); ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); if (num.parentNode) num.parentNode.removeChild(num); } };
};
})();
@@ -0,0 +1,45 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['data-stream'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const ac = U.accent(el,'#22d3ee'), ac2 = U.accent2(el,'#7c5cff');
const rows = [];
const rh = 22;
const genRow = (y) => ({
y, dir: Math.random()<0.5?-1:1,
speed: U.rand(30, 90),
offset: Math.random()*2000,
text: Array.from({length:120}, () => {
const r = Math.random();
if (r<0.3) return Math.random()<0.5?'0':'1';
if (r<0.6) return '0x' + Math.floor(Math.random()*256).toString(16).padStart(2,'0');
return Math.random().toString(16).slice(2,6);
}).join(' ')
});
const init = () => {
rows.length = 0;
const n = Math.ceil(k.h/rh);
for (let i=0;i<n;i++) rows.push(genRow(i*rh + rh*0.7));
};
init();
let lh = k.h;
const stop = U.loop((t) => {
if (k.h!==lh){ init(); lh=k.h; }
ctx.fillStyle = 'rgba(5,8,14,0.35)';
ctx.fillRect(0,0,k.w,k.h);
ctx.font = '13px ui-monospace,Menlo,monospace';
for (let i=0;i<rows.length;i++){
const r = rows[i];
const x = r.dir>0
? ((t*r.speed + r.offset) % (k.w+400)) - 400
: k.w - (((t*r.speed + r.offset) % (k.w+400)) - 400);
ctx.fillStyle = (i%3===0)?ac:ac2;
ctx.globalAlpha = 0.65 + (i%2)*0.3;
ctx.fillText(r.text, x, r.y);
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,51 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['firework'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
let rockets = [], sparks = [];
const launch = () => {
rockets.push({
x: U.rand(k.w*0.2, k.w*0.8), y: k.h+10,
vx: U.rand(-30,30), vy: U.rand(-520,-380),
tgtY: U.rand(k.h*0.15, k.h*0.45),
c: pal[(Math.random()*pal.length)|0]
});
};
const burst = (x, y, c) => {
const n = 70;
for (let i=0;i<n;i++){
const a = Math.random()*Math.PI*2;
const s = U.rand(60, 240);
sparks.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,c});
}
};
let last = -1;
const stop = U.loop((t) => {
ctx.fillStyle = 'rgba(0,0,0,0.18)';
ctx.fillRect(0,0,k.w,k.h);
if (t - last > 0.7) { launch(); last = t; }
const dt = 1/60;
rockets = rockets.filter(r => {
r.x += r.vx*dt; r.y += r.vy*dt; r.vy += 260*dt;
ctx.fillStyle = r.c;
ctx.beginPath(); ctx.arc(r.x, r.y, 2.5, 0, Math.PI*2); ctx.fill();
if (r.y <= r.tgtY || r.vy >= 0) { burst(r.x, r.y, r.c); return false; }
return true;
});
sparks = sparks.filter(p => p.life > 0);
for (const p of sparks){
p.vy += 90*dt;
p.vx *= 0.98; p.vy *= 0.98;
p.x += p.vx*dt; p.y += p.vy*dt;
p.life -= 0.012;
ctx.globalAlpha = Math.max(0, p.life);
ctx.fillStyle = p.c;
ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,33 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['galaxy-swirl'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const N = 800;
const parts = Array.from({length:N}, (_,i) => {
const arm = i%3;
const t = Math.random();
const r = t*180 + 8;
const base = (arm/3)*Math.PI*2;
return { r, a: base + Math.log(r+1)*1.6 + U.rand(-0.2,0.2),
c: pal[arm%pal.length],
s: U.rand(0.8, 2.2) };
});
const stop = U.loop((t) => {
ctx.fillStyle = 'rgba(0,0,0,0.15)';
ctx.fillRect(0,0,k.w,k.h);
const cx=k.w/2, cy=k.h/2;
for (const p of parts){
const a = p.a + t*0.15;
const x = cx + Math.cos(a)*p.r;
const y = cy + Math.sin(a)*p.r*0.7;
ctx.fillStyle = p.c;
ctx.globalAlpha = 0.7;
ctx.beginPath(); ctx.arc(x,y,p.s,0,Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,39 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['gradient-blob'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const blobs = Array.from({length:4}, (_,i) => ({
x: U.rand(0,1), y: U.rand(0,1),
vx: U.rand(-0.08,0.08), vy: U.rand(-0.08,0.08),
r: U.rand(180,320),
c: pal[i%pal.length]
}));
const hex2rgb = (h) => {
const m = h.replace('#','').match(/.{2}/g);
if (!m) return [124,92,255];
return m.map(x=>parseInt(x,16));
};
const stop = U.loop((t) => {
ctx.fillStyle = 'rgba(10,12,22,0.2)';
ctx.fillRect(0,0,k.w,k.h);
ctx.globalCompositeOperation = 'lighter';
for (const b of blobs){
b.x += b.vx*0.01; b.y += b.vy*0.01;
if (b.x<0||b.x>1) b.vx*=-1;
if (b.y<0||b.y>1) b.vy*=-1;
const px = b.x*k.w, py = b.y*k.h;
const r = b.r + Math.sin(t*0.8 + b.x*6)*30;
const [R,G,B] = hex2rgb(b.c);
const grad = ctx.createRadialGradient(px,py,0,px,py,r);
grad.addColorStop(0, `rgba(${R},${G},${B},0.55)`);
grad.addColorStop(1, `rgba(${R},${G},${B},0)`);
ctx.fillStyle = grad;
ctx.beginPath(); ctx.arc(px,py,r,0,Math.PI*2); ctx.fill();
}
ctx.globalCompositeOperation = 'source-over';
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,69 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['knowledge-graph'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const tx = U.text(el, '#e7e7ef');
const labels = ['AI','ML','LLM','Graph','Node','Edge','Claude','GPT','RAG','Vector',
'Embed','Neural','Agent','Tool','Memory','Logic','Data','Train','Infer','Token',
'Prompt','Chain','Plan','Skill','Cloud','Edge','GPU','Code','Task','Flow'];
const N = 28;
const nodes = Array.from({length:N}, (_,i) => ({
x: U.rand(40, 300), y: U.rand(40, 200),
vx: 0, vy: 0, label: labels[i%labels.length],
c: pal[i%pal.length]
}));
const edges = [];
const made = new Set();
while (edges.length < 50){
const a = (Math.random()*N)|0, b = (Math.random()*N)|0;
if (a===b) continue;
const key = a<b ? a+'-'+b : b+'-'+a;
if (made.has(key)) continue;
made.add(key); edges.push([a,b]);
}
const stop = U.loop(() => {
// physics
for (let i=0;i<N;i++){
for (let j=i+1;j<N;j++){
const a=nodes[i], b=nodes[j];
const dx=b.x-a.x, dy=b.y-a.y;
let d2=dx*dx+dy*dy; if (d2<1) d2=1;
const d=Math.sqrt(d2);
const f=1600/d2;
const fx=(dx/d)*f, fy=(dy/d)*f;
a.vx-=fx; a.vy-=fy; b.vx+=fx; b.vy+=fy;
}
}
for (const [i,j] of edges){
const a=nodes[i], b=nodes[j];
const dx=b.x-a.x, dy=b.y-a.y, d=Math.hypot(dx,dy)||1;
const f=(d-90)*0.008;
const fx=(dx/d)*f, fy=(dy/d)*f;
a.vx+=fx; a.vy+=fy; b.vx-=fx; b.vy-=fy;
}
const cx=k.w/2, cy=k.h/2;
for (const n of nodes){
n.vx += (cx-n.x)*0.002;
n.vy += (cy-n.y)*0.002;
n.vx *= 0.85; n.vy *= 0.85;
n.x += n.vx; n.y += n.vy;
}
ctx.clearRect(0,0,k.w,k.h);
ctx.strokeStyle = 'rgba(180,180,220,0.25)'; ctx.lineWidth=1;
for (const [i,j] of edges){
const a=nodes[i], b=nodes[j];
ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
}
ctx.font='11px system-ui,sans-serif'; ctx.textAlign='center'; ctx.textBaseline='middle';
for (const n of nodes){
ctx.fillStyle = n.c;
ctx.beginPath(); ctx.arc(n.x,n.y,7,0,Math.PI*2); ctx.fill();
ctx.fillStyle = tx;
ctx.fillText(n.label, n.x, n.y-14);
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,50 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['letter-explode'] = function(el){
const U = window.HPX._u;
if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
const src = el.querySelector('[data-fx-text]') || el;
const text = (el.getAttribute('data-fx-text-value') || src.textContent || 'EXPLODE').trim();
// Build a container, hide source text
const wrap = document.createElement('div');
wrap.style.cssText = 'position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;';
const inner = document.createElement('div');
inner.style.cssText = 'font-size:64px;font-weight:900;letter-spacing:0.02em;color:var(--text-1,#fff);white-space:nowrap;';
wrap.appendChild(inner);
el.appendChild(wrap);
const spans = [];
for (const ch of text){
const s = document.createElement('span');
s.textContent = ch === ' ' ? '\u00A0' : ch;
s.style.display='inline-block';
s.style.transform='translate(0,0)';
s.style.transition='transform 900ms cubic-bezier(.2,.9,.3,1), opacity 900ms';
s.style.opacity='0';
inner.appendChild(s);
spans.push(s);
}
let stopped = false;
const run = () => {
if (stopped) return;
spans.forEach((s,i) => {
const dx = U.rand(-400, 400), dy = U.rand(-300, 300);
s.style.transition='none';
s.style.transform=`translate(${dx}px,${dy}px) rotate(${U.rand(-180,180)}deg)`;
s.style.opacity='0';
});
// force reflow
void inner.offsetWidth;
spans.forEach((s,i) => {
setTimeout(() => {
if (stopped) return;
s.style.transition='transform 900ms cubic-bezier(.2,.9,.3,1), opacity 900ms';
s.style.transform='translate(0,0) rotate(0deg)';
s.style.opacity='1';
}, i*35);
});
};
run();
const iv = setInterval(run, 4500);
return { stop(){ stopped=true; clearInterval(iv); if (wrap.parentNode) wrap.parentNode.removeChild(wrap); } };
};
})();
@@ -0,0 +1,40 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['magnetic-field'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const N = 60;
const parts = Array.from({length:N}, (_,i) => ({
phase: Math.random()*Math.PI*2,
freq: U.rand(0.4, 1.2),
amp: U.rand(30, 90),
y0: U.rand(0.15, 0.85),
c: pal[i%pal.length],
trail: []
}));
const stop = U.loop((t) => {
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.fillRect(0,0,k.w,k.h);
for (const p of parts){
const x = ((t*80 + p.phase*50) % (k.w+100)) - 50;
const y = k.h*p.y0 + Math.sin(x*0.02 + p.phase + t*p.freq)*p.amp;
p.trail.push([x,y]);
if (p.trail.length > 18) p.trail.shift();
ctx.strokeStyle = p.c;
ctx.lineWidth = 2;
ctx.beginPath();
for (let i=0;i<p.trail.length;i++){
const [tx,ty] = p.trail[i];
if (i===0) ctx.moveTo(tx,ty); else ctx.lineTo(tx,ty);
}
ctx.globalAlpha = 0.7;
ctx.stroke();
ctx.globalAlpha = 1;
ctx.fillStyle = p.c;
ctx.beginPath(); ctx.arc(x,y,2.5,0,Math.PI*2); ctx.fill();
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,33 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['matrix-rain'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const glyphs = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ0123456789ABCDEF'.split('');
const fs = 16;
let cols = 0, drops = [];
const init = () => {
cols = Math.ceil(k.w/fs);
drops = Array.from({length:cols}, () => U.rand(-20, 0));
};
init();
let lw = k.w, lh = k.h;
const stop = U.loop(() => {
if (k.w!==lw || k.h!==lh){ init(); lw=k.w; lh=k.h; }
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.fillRect(0,0,k.w,k.h);
ctx.font = fs+'px monospace';
for (let i=0;i<cols;i++){
const ch = glyphs[(Math.random()*glyphs.length)|0];
const x = i*fs, y = drops[i]*fs;
ctx.fillStyle = '#9fffc9';
ctx.fillText(ch, x, y);
ctx.fillStyle = '#00ff6a';
ctx.fillText(ch, x, y - fs);
drops[i] += 1;
if (y > k.h && Math.random() > 0.975) drops[i] = 0;
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,75 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['neural-net'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
const layers = [4,6,6,3];
let nodes = [], edges = [], pulses = [];
const layout = () => {
nodes = [];
const pad = 40;
const cw = k.w - pad*2, ch = k.h - pad*2;
for (let L=0; L<layers.length; L++){
const x = pad + (cw * L / (layers.length-1));
const n = layers[L];
for (let i=0;i<n;i++){
const y = pad + (ch * (i+0.5) / n);
nodes.push({x,y,L,i});
}
}
edges = [];
for (let L=0; L<layers.length-1; L++){
const a = nodes.filter(n=>n.L===L), b = nodes.filter(n=>n.L===L+1);
for (const x of a) for (const y of b) edges.push([nodes.indexOf(x),nodes.indexOf(y)]);
}
};
layout();
let lw=k.w, lh=k.h, last=0;
const stop = U.loop((t) => {
if (k.w!==lw||k.h!==lh){ layout(); lw=k.w; lh=k.h; }
ctx.clearRect(0,0,k.w,k.h);
ctx.strokeStyle = 'rgba(160,160,200,0.22)'; ctx.lineWidth=1;
for (const [i,j] of edges){
const a=nodes[i], b=nodes[j];
ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
}
if (t - last > 0.25){
last = t;
const starts = nodes.filter(n=>n.L===0);
const s = starts[(Math.random()*starts.length)|0];
pulses.push({node:s, L:0, t:0});
}
pulses = pulses.filter(p => p.L < layers.length-1);
for (const p of pulses){
p.t += 0.03;
if (p.t >= 1){
const next = nodes.filter(n=>n.L===p.L+1);
p.node2 = next[(Math.random()*next.length)|0];
if (!p._started){ p._started = true; }
}
}
// animate progression
for (const p of pulses){
if (!p.target){
const next = nodes.filter(n=>n.L===p.L+1);
p.target = next[(Math.random()*next.length)|0];
}
p.t += 0.04;
const a = p.node, b = p.target;
const x = a.x + (b.x-a.x)*Math.min(1,p.t);
const y = a.y + (b.y-a.y)*Math.min(1,p.t);
ctx.fillStyle = ac2;
ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
if (p.t >= 1){ p.node = b; p.target=null; p.L++; p.t=0; }
}
for (const n of nodes){
ctx.fillStyle = ac;
ctx.beginPath(); ctx.arc(n.x,n.y,6,0,Math.PI*2); ctx.fill();
ctx.strokeStyle = ac2; ctx.lineWidth=1.5;
ctx.beginPath(); ctx.arc(n.x,n.y,8,0,Math.PI*2); ctx.stroke();
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,38 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['orbit-ring'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const rings = [
{r:40, n:3, sp:1.2, c:pal[0]},
{r:75, n:5, sp:0.8, c:pal[1]},
{r:110, n:8, sp:-0.6, c:pal[2]},
{r:145, n:12, sp:0.4, c:pal[3]},
{r:180, n:16, sp:-0.3, c:pal[4]}
];
const stop = U.loop((t) => {
ctx.clearRect(0,0,k.w,k.h);
const cx=k.w/2, cy=k.h/2;
// radial glow
const g = ctx.createRadialGradient(cx,cy,0,cx,cy,210);
g.addColorStop(0,'rgba(124,92,255,0.25)');
g.addColorStop(1,'rgba(0,0,0,0)');
ctx.fillStyle = g; ctx.fillRect(0,0,k.w,k.h);
for (const R of rings){
ctx.strokeStyle = 'rgba(200,200,230,0.2)'; ctx.lineWidth=1;
ctx.beginPath(); ctx.arc(cx,cy,R.r,0,Math.PI*2); ctx.stroke();
for (let i=0;i<R.n;i++){
const a = (i/R.n)*Math.PI*2 + t*R.sp;
const x = cx + Math.cos(a)*R.r;
const y = cy + Math.sin(a)*R.r;
ctx.fillStyle = R.c;
ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
}
}
ctx.fillStyle = '#fff';
ctx.beginPath(); ctx.arc(cx,cy,5,0,Math.PI*2); ctx.fill();
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,42 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['particle-burst'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
let parts = [];
const spawn = () => {
const cx = k.w/2, cy = k.h/2;
const n = 90;
for (let i=0;i<n;i++){
const a = Math.random()*Math.PI*2;
const s = U.rand(80, 260);
parts.push({
x: cx, y: cy,
vx: Math.cos(a)*s, vy: Math.sin(a)*s,
life: 1, r: U.rand(2,5),
c: pal[(Math.random()*pal.length)|0]
});
}
};
spawn();
let lastSpawn = 0;
const stop = U.loop((t) => {
ctx.clearRect(0,0,k.w,k.h);
if (t - lastSpawn > 2.5) { spawn(); lastSpawn = t; }
const dt = 1/60;
parts = parts.filter(p => p.life > 0);
for (const p of parts){
p.vy += 220*dt;
p.vx *= 0.985; p.vy *= 0.985;
p.x += p.vx*dt; p.y += p.vy*dt;
p.life -= 0.012;
ctx.globalAlpha = Math.max(0, p.life);
ctx.fillStyle = p.c;
ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,39 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['shockwave'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
let waves = [];
let last = -1;
const stop = U.loop((t) => {
ctx.fillStyle = 'rgba(0,0,0,0.12)';
ctx.fillRect(0,0,k.w,k.h);
if (t - last > 0.6){ last = t; waves.push({t:0}); }
const cx=k.w/2, cy=k.h/2;
const max = Math.hypot(k.w,k.h)/2;
waves = waves.filter(w => w.t < 1);
for (const w of waves){
w.t += 0.012;
const r = w.t * max;
const alpha = 1 - w.t;
ctx.strokeStyle = w.t<0.5?ac2:ac;
ctx.globalAlpha = alpha;
ctx.lineWidth = 3 + (1-w.t)*3;
ctx.beginPath(); ctx.arc(cx,cy,r,0,Math.PI*2); ctx.stroke();
ctx.strokeStyle = '#fff';
ctx.lineWidth = 1;
ctx.globalAlpha = alpha*0.4;
ctx.beginPath(); ctx.arc(cx,cy,r*0.92,0,Math.PI*2); ctx.stroke();
}
ctx.globalAlpha = 1;
// core
const g = ctx.createRadialGradient(cx,cy,0,cx,cy,40);
g.addColorStop(0,'rgba(255,255,255,0.9)');
g.addColorStop(1,'rgba(124,92,255,0)');
ctx.fillStyle = g;
ctx.beginPath(); ctx.arc(cx,cy,40,0,Math.PI*2); ctx.fill();
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,62 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['sparkle-trail'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
k.c.style.pointerEvents = 'none';
el.style.cursor = 'crosshair';
const pal = U.palette(el);
let sparks = [];
const onMove = (e) => {
const r = el.getBoundingClientRect();
const x = e.clientX - r.left, y = e.clientY - r.top;
for (let i=0;i<3;i++){
sparks.push({
x, y,
vx: U.rand(-60,60), vy: U.rand(-80,20),
life: 1, c: pal[(Math.random()*pal.length)|0],
r: U.rand(1.5,3.5)
});
}
};
// auto-wiggle if no mouse moves
let auto = true, autoT = 0;
const onAny = () => { auto = false; };
el.addEventListener('pointermove', onMove);
el.addEventListener('pointerenter', onAny);
const stop = U.loop(() => {
ctx.fillStyle = 'rgba(0,0,0,0.15)';
ctx.fillRect(0,0,k.w,k.h);
if (auto){
autoT += 0.04;
const x = k.w/2 + Math.cos(autoT)*k.w*0.3;
const y = k.h/2 + Math.sin(autoT*1.3)*k.h*0.3;
for (let i=0;i<3;i++){
sparks.push({
x, y,
vx: U.rand(-60,60), vy: U.rand(-80,20),
life: 1, c: pal[(Math.random()*pal.length)|0],
r: U.rand(1.5,3.5)
});
}
}
const dt = 1/60;
sparks = sparks.filter(s => s.life > 0);
for (const s of sparks){
s.vy += 160*dt;
s.x += s.vx*dt; s.y += s.vy*dt;
s.life -= 0.018;
ctx.globalAlpha = Math.max(0, s.life);
ctx.fillStyle = s.c;
ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){
el.removeEventListener('pointermove', onMove);
el.removeEventListener('pointerenter', onAny);
el.style.cursor = '';
stop(); k.destroy();
}};
};
})();
@@ -0,0 +1,30 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['starfield'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const tx = U.text(el, '#ffffff');
const N = 260;
const stars = Array.from({length:N}, () => ({
x: U.rand(-1,1), y: U.rand(-1,1), z: Math.random()
}));
const stop = U.loop(() => {
ctx.fillStyle = 'rgba(0,0,0,0.25)';
ctx.fillRect(0,0,k.w,k.h);
const cx = k.w/2, cy = k.h/2;
for (const s of stars){
s.z -= 0.006;
if (s.z <= 0.02) { s.x = U.rand(-1,1); s.y = U.rand(-1,1); s.z = 1; }
const px = cx + (s.x/s.z)*cx;
const py = cy + (s.y/s.z)*cy;
if (px<0||py<0||px>k.w||py>k.h) continue;
const r = (1-s.z)*2.4;
ctx.globalAlpha = 1-s.z;
ctx.fillStyle = tx;
ctx.beginPath(); ctx.arc(px,py,r,0,Math.PI*2); ctx.fill();
}
ctx.globalAlpha = 1;
});
return { stop(){ stop(); k.destroy(); } };
};
})();
@@ -0,0 +1,51 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['typewriter-multi'] = function(el){
if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
const lines = [
(el.getAttribute('data-fx-line1') || '> initializing knowledge graph...'),
(el.getAttribute('data-fx-line2') || '> loading 28 concept nodes'),
(el.getAttribute('data-fx-line3') || '> agent ready. awaiting prompt_'),
];
const wrap = document.createElement('div');
wrap.style.cssText = 'position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:14px;padding:32px 48px;font:600 22px ui-monospace,Menlo,monospace;color:var(--text-1,#e7e7ef);';
el.appendChild(wrap);
const rows = lines.map((txt) => {
const row = document.createElement('div');
row.style.cssText = 'white-space:pre;display:flex;align-items:center;';
const span = document.createElement('span'); span.textContent = '';
const cur = document.createElement('span');
cur.textContent = '\u2588';
cur.style.cssText = 'display:inline-block;margin-left:2px;color:var(--accent,#22d3ee);animation:hpxBlink 1s steps(2) infinite;';
row.appendChild(span); row.appendChild(cur);
wrap.appendChild(row);
return {row, span, txt, i:0};
});
// inject blink keyframes once
if (!document.getElementById('hpx-blink-kf')){
const st = document.createElement('style');
st.id = 'hpx-blink-kf';
st.textContent = '@keyframes hpxBlink{50%{opacity:0}}';
document.head.appendChild(st);
}
let stopped = false;
const speeds = [55, 70, 45];
rows.forEach((r, idx) => {
const tick = () => {
if (stopped) return;
if (r.i < r.txt.length){
r.span.textContent += r.txt[r.i++];
setTimeout(tick, speeds[idx]);
} else {
setTimeout(() => {
if (stopped) return;
r.i = 0; r.span.textContent = '';
tick();
}, 2200);
}
};
setTimeout(tick, idx*400);
});
return { stop(){ stopped = true; if (wrap.parentNode) wrap.parentNode.removeChild(wrap); } };
};
})();
@@ -0,0 +1,47 @@
(function(){
window.HPX = window.HPX || {};
window.HPX['word-cascade'] = function(el){
const U = window.HPX._u;
const k = U.canvas(el), ctx = k.ctx;
const pal = U.palette(el);
const WORDS = ['AI','知识','Graph','Claude','LLM','Agent','Vector','RAG','Token','神经',
'Prompt','Chain','Skill','Code','Cloud','GPU','Flow','推理','Data','Model'];
let items = [];
let last = -1;
let piles = {}; // column -> stack height
const stop = U.loop((t) => {
ctx.clearRect(0,0,k.w,k.h);
if (t - last > 0.18){
last = t;
const w = WORDS[(Math.random()*WORDS.length)|0];
items.push({
text: w, x: U.rand(40, k.w-40), y: -20,
vy: 0, c: pal[(Math.random()*pal.length)|0],
size: U.rand(16,26), landed: false
});
}
ctx.textAlign='center'; ctx.textBaseline='middle';
for (const it of items){
if (!it.landed){
it.vy += 0.4;
it.y += it.vy;
const col = Math.round(it.x/60);
const floor = k.h - (piles[col]||0) - it.size*0.6;
if (it.y >= floor){
it.y = floor; it.landed = true;
piles[col] = (piles[col]||0) + it.size*1.1;
if ((piles[col]||0) > k.h*0.8) piles[col] = 0; // reset if too high
}
}
ctx.fillStyle = it.c;
ctx.font = `700 ${it.size}px system-ui,sans-serif`;
ctx.fillText(it.text, it.x, it.y);
}
// prune old landed
if (items.length > 120){
items = items.filter(i => !i.landed).concat(items.filter(i=>i.landed).slice(-60));
}
});
return { stop(){ stop(); k.destroy(); } };
};
})();