zli12321's picture
Deploy IntelligenceLab website
87008d1 verified
Raw History Blame Contribute Delete
25.2 kB
(() => {
'use strict';
// Where "Email us" and "Contact" links send inquiries. Replace before publishing.
const CONTACT_EMAIL = 'contact@example.com';
const $ = (sel, root = document) => root.querySelector(sel);
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
const rand = (lo, hi) => lo + Math.random() * (hi - lo);
function initContact() {
$$('[data-contact]').forEach((link) => {
const subject = encodeURIComponent(link.dataset.subject || 'Hello');
link.href = `mailto:${CONTACT_EMAIL}?subject=${subject}`;
});
$$('[data-year]').forEach((el) => {
el.textContent = String(new Date().getFullYear());
});
}
function initNav() {
const nav = $('.nav');
const onScroll = () => nav.classList.toggle('is-scrolled', window.scrollY > 8);
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
const toggle = $('.nav-toggle');
const menu = $('#mobile-menu');
const setOpen = (open) => {
toggle.setAttribute('aria-expanded', String(open));
toggle.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
menu.hidden = !open;
document.body.classList.toggle('menu-open', open);
};
toggle.addEventListener('click', () => setOpen(toggle.getAttribute('aria-expanded') !== 'true'));
$$('a', menu).forEach((a) => a.addEventListener('click', () => setOpen(false)));
window.addEventListener('keydown', (e) => {
if (e.key === 'Escape') setOpen(false);
});
window.matchMedia('(min-width: 1101px)').addEventListener('change', (e) => {
if (e.matches) setOpen(false);
});
if (!('IntersectionObserver' in window)) return;
const links = new Map($$('.nav-links a').map((a) => [a.getAttribute('href').slice(1), a]));
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
links.forEach((a) => a.classList.remove('is-active'));
const active = links.get(entry.target.dataset.nav || entry.target.id);
if (active) active.classList.add('is-active');
});
}, { rootMargin: '-45% 0px -50% 0px' });
$$('main > section[id]').forEach((section) => observer.observe(section));
}
function initReveal() {
const items = $$('.reveal');
if (reduceMotion || !('IntersectionObserver' in window)) {
items.forEach((el) => el.classList.add('is-visible'));
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
});
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.12 });
items.forEach((el) => observer.observe(el));
}
function initTabs() {
const tabs = $$('[role="tab"]');
if (!tabs.length) return;
const panels = tabs.map((tab) => document.getElementById(tab.getAttribute('aria-controls')));
const select = (index, focus) => {
tabs.forEach((tab, i) => {
const on = i === index;
tab.setAttribute('aria-selected', String(on));
tab.tabIndex = on ? 0 : -1;
panels[i].hidden = !on;
panels[i].classList.toggle('is-active', on);
});
if (focus) tabs[index].focus();
tabs[index].scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: reduceMotion ? 'auto' : 'smooth' });
};
tabs.forEach((tab, i) => {
tab.addEventListener('click', () => select(i, false));
tab.addEventListener('keydown', (e) => {
const keys = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 };
if (e.key in keys) {
e.preventDefault();
select((i + keys[e.key] + tabs.length) % tabs.length, true);
} else if (e.key === 'Home' || e.key === 'End') {
e.preventDefault();
select(e.key === 'Home' ? 0 : tabs.length - 1, true);
}
});
});
}
function initExamples() {
const grid = $('#ex-grid');
const modal = $('#ex-modal');
const source = $('#examples-data');
if (!grid || !modal || !source) return;
let examples;
try {
examples = JSON.parse(source.textContent);
} catch (err) {
return;
}
const cards = $$('.ex-card', grid);
const more = $('#ex-more');
const extras = cards.filter((card) => card.classList.contains('is-extra'));
if (more) {
if (!extras.length) more.hidden = true;
more.textContent = `Show ${extras.length} more examples`;
more.addEventListener('click', () => {
grid.classList.add('show-all');
more.setAttribute('aria-expanded', 'true');
if (extras[0]) extras[0].focus({ preventScroll: true });
});
}
const sheet = $('.ex-sheet', modal);
const closeButton = $('.icon-btn[data-ex-close]', modal);
const field = (id) => document.getElementById(id);
const fields = {
domain: field('exm-domain'),
title: field('exm-title'),
tracks: field('exm-tracks'),
img: field('exm-img'),
desc: field('exm-desc'),
software: field('exm-software'),
artifacts: field('exm-artifacts'),
axes: field('exm-axes'),
outputs: field('exm-outputs'),
cta: field('exm-cta'),
live: field('exm-live'),
};
let current = 0;
let lastFocus = null;
let liveView = null;
const mountLive = (ex) => {
if (liveView) {
liveView.dispose();
liveView = null;
}
const live = window.ILLive;
if (!fields.live || !live || !live.ready) {
if (fields.live) fields.live.hidden = true;
return;
}
fields.live.hidden = false;
fields.live.style.setProperty('--dc', ex.color);
liveView = live.mount(fields.live, ex.kind, { color: ex.color, hero: true });
if (!liveView) fields.live.hidden = true;
};
const listItems = (ul, items) => {
ul.replaceChildren(...items.map(({ text, cls }) => {
const li = document.createElement('li');
li.textContent = text;
if (cls) li.className = cls;
return li;
}));
};
const plain = (items) => items.map((text) => ({ text }));
const render = (index) => {
current = (index + examples.length) % examples.length;
const ex = examples[current];
sheet.style.setProperty('--dc', ex.color);
fields.domain.textContent = ex.domain;
fields.title.textContent = ex.title;
const tracks = ex.tracks.map((t) => ({ text: t, cls: `trk trk-${t.toLowerCase()}` }));
if (ex.modality) tracks.push({ text: ex.modality, cls: 'trk trk-mod' });
listItems(fields.tracks, tracks);
fields.img.src = ex.img;
fields.img.alt = ex.alt;
fields.desc.textContent = ex.description;
listItems(fields.software, plain(ex.software));
listItems(fields.artifacts, plain(ex.artifacts));
listItems(fields.axes, plain(ex.axes));
listItems(fields.outputs, plain(ex.outputs));
fields.cta.href = `mailto:${CONTACT_EMAIL}?subject=${encodeURIComponent(`Sample request: ${ex.title}`)}`;
sheet.scrollTop = 0;
if (!modal.hidden) mountLive(ex);
};
const open = (index) => {
lastFocus = document.activeElement;
render(index);
modal.hidden = false;
mountLive(examples[current]);
document.body.classList.add('modal-open');
closeButton.focus();
};
const close = () => {
modal.hidden = true;
if (liveView) {
liveView.dispose();
liveView = null;
}
document.body.classList.remove('modal-open');
if (lastFocus) lastFocus.focus({ preventScroll: true });
};
document.addEventListener('il-live-ready', () => {
if (!modal.hidden) mountLive(examples[current]);
});
cards.forEach((card) => {
const index = Number(card.dataset.index);
card.addEventListener('click', () => open(index));
card.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
open(index);
}
});
});
$$('[data-ex-close]', modal).forEach((el) => el.addEventListener('click', close));
$('[data-ex-prev]', modal).addEventListener('click', () => render(current - 1));
$('[data-ex-next]', modal).addEventListener('click', () => render(current + 1));
document.addEventListener('keydown', (e) => {
if (modal.hidden) return;
if (e.key === 'Escape') {
e.preventDefault();
close();
} else if (e.key === 'ArrowRight') {
render(current + 1);
} else if (e.key === 'ArrowLeft') {
render(current - 1);
} else if (e.key === 'Tab') {
const focusables = $$('button, a[href]', sheet);
const first = focusables[0];
const last = focusables[focusables.length - 1];
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
}
function initWaves() {
$$('path[data-wave]').forEach((path) => {
const [amp, decay, freq, phase] = path.dataset.wave.split(/\s+/).map(Number);
const points = [];
for (let i = 0; i <= 120; i += 1) {
const t = (3 * i) / 120;
const x = 40 + (296 * i) / 120;
const y = 104 - amp * Math.exp(-decay * t) * Math.cos(freq * t + phase);
points.push(`${x.toFixed(1)},${y.toFixed(1)}`);
}
path.setAttribute('d', `M${points.join('L')}`);
if (path.classList.contains('wave-recon')) path.setAttribute('pathLength', '1');
});
}
function initLadder() {
const svg = $('#ladder-chart');
const slider = $('#ladder-strength');
const readout = $('#ladder-readout');
const label = $('#ladder-strength-label');
if (!svg || !slider || !readout || !label) return;
const NS = 'http://www.w3.org/2000/svg';
// Reference-solver measurements (pass@4) by synthesis round.
const ANCHORS = [[1, 0.9], [6, 0.2], [15, 0.025]];
const ROUNDS = 15;
const LOW = 0.1;
const HIGH = 0.5;
const logit = (p) => Math.log(p / (1 - p));
const sigmoid = (z) => 1 / (1 + Math.exp(-z));
const baseLogit = (r) => {
for (let i = 0; i < ANCHORS.length - 1; i += 1) {
const [r0, p0] = ANCHORS[i];
const [r1, p1] = ANCHORS[i + 1];
if (r <= r1) return logit(p0) + ((r - r0) / (r1 - r0)) * (logit(p1) - logit(p0));
}
return logit(ANCHORS[ANCHORS.length - 1][1]);
};
const W = 640;
const H = 330;
const m = { l: 46, r: 14, t: 18, b: 46 };
const pw = W - m.l - m.r;
const ph = H - m.t - m.b;
const xOf = (r) => m.l + ((r - 0.5) / ROUNDS) * pw;
const yOf = (p) => m.t + (1 - p) * ph;
const barW = (pw / ROUNDS) * 0.6;
svg.setAttribute('viewBox', `0 0 ${W} ${H}`);
const add = (tag, attrs, text) => {
const node = document.createElementNS(NS, tag);
Object.entries(attrs).forEach(([k, v]) => node.setAttribute(k, String(v)));
if (text != null) node.textContent = text;
svg.appendChild(node);
return node;
};
[0, 0.25, 0.5, 0.75, 1].forEach((v) => {
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(v), y2: yOf(v), class: 'grid' });
add('text', { x: m.l - 10, y: yOf(v) + 4, class: 'tick', 'text-anchor': 'end' }, `${v * 100}%`);
});
add('rect', { x: m.l, y: yOf(HIGH), width: pw, height: yOf(LOW) - yOf(HIGH), class: 'zone' });
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(HIGH), y2: yOf(HIGH), class: 'zone-edge' });
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(LOW), y2: yOf(LOW), class: 'zone-edge' });
const bars = [];
for (let r = 1; r <= ROUNDS; r += 1) {
bars.push(add('rect', { x: xOf(r) - barW / 2, y: yOf(0), width: barW, height: 0, rx: 3, class: 'bar' }));
add('text', { x: xOf(r), y: H - m.b + 18, class: 'tick', 'text-anchor': 'middle' }, String(r));
}
add('text', { x: m.l + pw / 2, y: H - 6, class: 'axis-label', 'text-anchor': 'middle' }, 'Synthesis round (harder →)');
let d = '';
for (let r = 1; r <= ROUNDS + 1e-9; r += 0.2) {
d += `${d ? 'L' : 'M'}${xOf(r).toFixed(1)},${yOf(sigmoid(baseLogit(r))).toFixed(1)}`;
}
add('path', { d, class: 'ref-line' });
ANCHORS.forEach(([r, p]) => {
add('circle', { cx: xOf(r), cy: yOf(p), r: 5, class: 'anchor' });
const lastRound = r === ROUNDS;
add('text', {
x: xOf(r) + (lastRound ? -10 : 10),
y: yOf(p) - 10,
class: 'anchor-label',
'text-anchor': lastRound ? 'end' : 'start',
}, `${+(p * 100).toFixed(1)}%`);
});
const current = bars.map(() => 0);
let target = bars.map(() => 0);
let frame = 0;
let started = false;
const drawBars = (values) => {
values.forEach((p, i) => {
const top = yOf(p);
bars[i].setAttribute('y', top.toFixed(2));
bars[i].setAttribute('height', Math.max(0, yOf(0) - top).toFixed(2));
});
};
const tick = () => {
let moving = false;
for (let i = 0; i < current.length; i += 1) {
const delta = target[i] - current[i];
if (Math.abs(delta) > 0.0005) {
current[i] += delta * 0.2;
moving = true;
} else {
current[i] = target[i];
}
}
drawBars(current);
frame = moving ? requestAnimationFrame(tick) : 0;
};
const kick = () => {
if (reduceMotion) {
target.forEach((p, i) => { current[i] = p; });
drawBars(current);
} else if (!frame) {
frame = requestAnimationFrame(tick);
}
};
const update = () => {
const shift = Number(slider.value);
target = bars.map((_, i) => sigmoid(baseLogit(i + 1) + shift));
const zone = [];
target.forEach((p, i) => {
const inZone = p >= LOW && p <= HIGH;
bars[i].classList.toggle('in-zone', inZone);
if (inZone) zone.push(i + 1);
});
if (Math.abs(shift) < 0.05) label.textContent = 'Reference solver';
else label.textContent = shift > 0 ? 'Stronger than reference' : 'Weaker than reference';
if (zone.length) {
const span = zone.length === 1 ? `round ${zone[0]}` : `rounds ${zone[0]}–${zone[zone.length - 1]}`;
readout.innerHTML = `Next batch: <strong>${span}</strong>, where this model succeeds 10–50% of the time.`;
} else if (target[ROUNDS - 1] > HIGH) {
readout.innerHTML = 'This model has outgrown the ladder: <strong>we synthesize further rounds</strong>.';
} else {
readout.innerHTML = '<strong>Start with warm-up tiers</strong> and calibrate upward.';
}
if (started) kick();
};
slider.addEventListener('input', update);
update();
const begin = () => {
started = true;
kick();
};
if (reduceMotion || !('IntersectionObserver' in window)) {
begin();
} else {
const observer = new IntersectionObserver((entries) => {
if (!entries.some((entry) => entry.isIntersecting)) return;
observer.disconnect();
begin();
}, { threshold: 0.3 });
observer.observe(svg);
}
}
function initHero() {
const hero = $('.hero');
const canvas = hero && $('.hero-canvas', hero);
if (!canvas || !canvas.getContext) return;
const ctx = canvas.getContext('2d');
const copy = $('.hero-copy', hero);
const badges = $$('.tier-badges li', hero);
const TIER_RGB = [[20, 184, 138], [13, 165, 160], [37, 140, 214], [88, 101, 226], [124, 92, 220]];
const IDLE_RGB = [100, 116, 139];
const REJECT_RGB = [242, 107, 91];
const GATE_LABELS = ['Execute', 'Verify', 'Audit'];
const REJECT_RATE = [0.14, 0.1, 0.06];
let W = 0;
let H = 0;
let copyRight = 0;
let flowMode = true;
let gates = [];
let targets = [];
const particles = [];
let raf = 0;
let last = 0;
let onScreen = true;
const mouse = { x: -1e4, y: -1e4 };
const glowing = new Set();
const smooth = (k) => k * k * (3 - 2 * k);
function spawn(scatter) {
const x = scatter ? rand(-40, W) : rand(-90, -10);
let y;
let tier;
if (flowMode || !targets.length) {
y = rand(H * 0.08, H * 0.92);
tier = Math.floor(Math.random() * TIER_RGB.length);
} else {
// Lanes start near the badge they feed, so streams fan in instead of crossing.
const top = targets[0].y;
const bottom = targets[targets.length - 1].y;
y = clamp(rand(top - 90, bottom + 90), H * 0.06, H * 0.94);
const slot = ((y - top) / (bottom - top)) * (targets.length - 1) + rand(-0.6, 0.6);
tier = clamp(Math.round(slot), 0, targets.length - 1);
}
return {
x, y, px: x, py: y, baseY: y,
speed: rand(0.45, 1.05),
phase: rand(0, Math.PI * 2),
amp: rand(4, 16),
tier,
gate: 0,
rejected: false,
alpha: 1,
size: rand(1, 2.3),
};
}
function measure() {
const rect = hero.getBoundingClientRect();
W = rect.width;
H = rect.height;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = Math.round(W * dpr);
canvas.height = Math.round(H * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
copyRight = copy ? copy.getBoundingClientRect().right - rect.left : W * 0.5;
targets = badges.map((badge) => {
const r = badge.getBoundingClientRect();
return { x: r.left - rect.left - 6, y: r.top - rect.top + r.height / 2, ok: r.width > 0 };
});
flowMode = !(targets.length && targets.every((t) => t.ok));
gates = [];
if (!flowMode) {
const start = copyRight + 56;
const end = Math.min(...targets.map((t) => t.x)) - 60;
if (end - start > 200) {
gates = GATE_LABELS.map((_, i) => start + ((end - start) * i) / (GATE_LABELS.length - 1));
} else {
flowMode = true;
}
}
const count = Math.round(clamp((W * H) / (flowMode ? 4200 : 1500), 110, 760));
while (particles.length < count) particles.push(spawn(true));
particles.length = count;
particles.forEach((p) => {
if (p.baseY > H || p.y > H) Object.assign(p, spawn(true));
});
}
function arrive(i) {
if (glowing.has(i) || Math.random() > 0.05) return;
const badge = badges[i];
if (!badge) return;
glowing.add(i);
badge.classList.add('glow');
setTimeout(() => {
badge.classList.remove('glow');
glowing.delete(i);
}, 700);
}
function update(p, dt, t) {
p.px = p.x;
p.py = p.y;
if (p.rejected) {
p.x += p.speed * 0.45 * dt;
p.y += 0.8 * dt;
p.alpha -= 0.024 * dt;
if (p.alpha <= 0) Object.assign(p, spawn(false));
return;
}
while (p.gate < gates.length && p.x >= gates[p.gate]) {
if (Math.random() < REJECT_RATE[p.gate]) {
p.rejected = true;
return;
}
p.gate += 1;
}
const target = flowMode ? null : targets[p.tier];
let k = 0;
let laneY = p.baseY;
if (target) {
const x0 = gates[0] - 80;
k = clamp((p.x - x0) / (target.x - x0), 0, 1);
laneY = p.baseY + (target.y - p.baseY) * smooth(k);
}
const wave = Math.sin(t * 0.0011 + p.phase + p.x * 0.0045) * p.amp * (1 - 0.9 * k);
p.x += p.speed * (0.8 + W / 1800) * dt;
p.y += (laneY + wave - p.y) * Math.min(1, 0.085 * dt);
const dx = p.x - mouse.x;
const dy = p.y - mouse.y;
const d2 = dx * dx + dy * dy;
if (d2 < 14400) {
const dist = Math.sqrt(d2) || 1;
const force = (1 - dist / 120) * 2.4 * dt;
p.x += (dx / dist) * force * 0.35;
p.y += (dy / dist) * force;
}
if (target && p.x >= target.x) {
arrive(p.tier);
Object.assign(p, spawn(false));
} else if (p.x > W + 24) {
Object.assign(p, spawn(false));
}
}
function roundRect(x, y, w, h, r) {
ctx.beginPath();
if (ctx.roundRect) {
ctx.roundRect(x, y, w, h, r);
return;
}
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
function drawGates() {
const top = H * 0.16;
const bottom = H * 0.86;
ctx.save();
ctx.font = '600 11px Inter, ui-sans-serif, system-ui, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
gates.forEach((gx, i) => {
const grad = ctx.createLinearGradient(0, top, 0, bottom);
grad.addColorStop(0, 'rgba(15,23,42,0)');
grad.addColorStop(0.5, 'rgba(15,23,42,0.18)');
grad.addColorStop(1, 'rgba(15,23,42,0)');
ctx.strokeStyle = grad;
ctx.lineWidth = 1;
ctx.setLineDash([3, 6]);
ctx.beginPath();
ctx.moveTo(gx, top);
ctx.lineTo(gx, bottom);
ctx.stroke();
ctx.setLineDash([]);
const text = GATE_LABELS[i];
const w = ctx.measureText(text).width + 22;
const h = 24;
const y = top - 16;
ctx.fillStyle = 'rgba(255,255,255,0.92)';
ctx.strokeStyle = 'rgba(15,23,42,0.12)';
roundRect(gx - w / 2, y - h / 2, w, h, 12);
ctx.fill();
ctx.stroke();
ctx.fillStyle = '#334155';
ctx.fillText(text, gx, y + 0.5);
});
ctx.restore();
}
function drawBadgeGlow() {
targets.forEach((t, i) => {
const [r, g, b] = TIER_RGB[i];
const glow = ctx.createRadialGradient(t.x, t.y, 0, t.x, t.y, 72);
glow.addColorStop(0, `rgba(${r},${g},${b},0.18)`);
glow.addColorStop(1, `rgba(${r},${g},${b},0)`);
ctx.fillStyle = glow;
ctx.fillRect(t.x - 72, t.y - 72, 144, 144);
});
}
function draw() {
ctx.clearRect(0, 0, W, H);
if (gates.length) {
drawGates();
drawBadgeGlow();
}
ctx.lineCap = 'round';
for (const p of particles) {
let rgb;
let a;
if (p.rejected) {
rgb = REJECT_RGB;
a = 0.75 * p.alpha;
} else if (flowMode) {
rgb = TIER_RGB[p.tier];
a = 0.4;
} else if (p.gate === 0) {
rgb = IDLE_RGB;
a = p.x < copyRight ? 0.2 : 0.36;
} else {
rgb = TIER_RGB[p.tier];
a = 0.5 + 0.15 * p.gate;
}
let sx = (p.x - p.px) * 3;
let sy = (p.y - p.py) * 3;
const len = Math.hypot(sx, sy);
if (len > 16) {
sx *= 16 / len;
sy *= 16 / len;
}
ctx.strokeStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${a.toFixed(3)})`;
ctx.lineWidth = p.size;
ctx.beginPath();
ctx.moveTo(p.x - sx, p.y - sy);
ctx.lineTo(p.x + 0.01, p.y);
ctx.stroke();
}
}
function loop(now) {
const dt = clamp((now - last) / 16.67, 0.2, 3);
last = now;
for (const p of particles) update(p, dt, now);
draw();
raf = requestAnimationFrame(loop);
}
const start = () => {
if (raf || reduceMotion || !onScreen || document.hidden) return;
last = performance.now();
raf = requestAnimationFrame(loop);
};
const stop = () => {
if (raf) cancelAnimationFrame(raf);
raf = 0;
};
const renderStill = () => {
for (let i = 0; i < 260; i += 1) particles.forEach((p) => update(p, 1, i * 16));
draw();
};
measure();
if (reduceMotion) renderStill();
else start();
let resizeTimer = 0;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
measure();
if (reduceMotion) renderStill();
}, 120);
});
if (document.fonts && document.fonts.ready) {
document.fonts.ready.then(() => {
measure();
if (reduceMotion) renderStill();
});
}
hero.addEventListener('pointermove', (e) => {
const r = hero.getBoundingClientRect();
mouse.x = e.clientX - r.left;
mouse.y = e.clientY - r.top;
});
hero.addEventListener('pointerleave', () => {
mouse.x = -1e4;
mouse.y = -1e4;
});
if ('IntersectionObserver' in window) {
new IntersectionObserver((entries) => {
onScreen = entries.some((entry) => entry.isIntersecting);
if (onScreen) start();
else stop();
}).observe(hero);
}
document.addEventListener('visibilitychange', () => (document.hidden ? stop() : start()));
}
initContact();
initNav();
initReveal();
initTabs();
initExamples();
initWaves();
initLadder();
initHero();
})();