Deploy IntelligenceLab website
Browse files- .gitattributes +3 -0
- README.md +5 -5
- app.js +737 -0
- assets/examples/astro-detail.webp +3 -0
- assets/examples/astro-thumb.webp +0 -0
- assets/examples/blender-detail.webp +0 -0
- assets/examples/blender-thumb.webp +0 -0
- assets/examples/color-detail.webp +3 -0
- assets/examples/color-thumb.webp +0 -0
- assets/examples/container-detail.webp +0 -0
- assets/examples/container-thumb.webp +0 -0
- assets/examples/drc-detail.webp +0 -0
- assets/examples/drc-thumb.webp +0 -0
- assets/examples/foam-detail.webp +0 -0
- assets/examples/foam-thumb.webp +0 -0
- assets/examples/micro-detail.webp +3 -0
- assets/examples/micro-thumb.webp +0 -0
- assets/examples/ocr-detail.webp +0 -0
- assets/examples/ocr-thumb.webp +0 -0
- assets/examples/robot-detail.webp +0 -0
- assets/examples/robot-thumb.webp +0 -0
- assets/examples/stl-detail.webp +0 -0
- assets/examples/stl-thumb.webp +0 -0
- assets/examples/visuals.js +0 -0
- index.html +898 -17
- live.js +810 -0
- styles.css +891 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
assets/examples/astro-detail.webp filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
assets/examples/color-detail.webp filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
assets/examples/micro-detail.webp filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
colorTo: purple
|
| 6 |
sdk: static
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
| 1 |
---
|
| 2 |
+
title: IntelligenceLab
|
| 3 |
+
colorFrom: green
|
| 4 |
+
colorTo: indigo
|
|
|
|
| 5 |
sdk: static
|
| 6 |
+
app_file: index.html
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
+
IntelligenceLab website: verified terminal, coding, and multimodal training data for agents. Static site (`index.html`, `styles.css`, `app.js`, `live.js`, `assets/`).
|
app.js
ADDED
|
@@ -0,0 +1,737 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(() => {
|
| 2 |
+
'use strict';
|
| 3 |
+
|
| 4 |
+
// Where "Email us" and "Contact" links send inquiries. Replace before publishing.
|
| 5 |
+
const CONTACT_EMAIL = 'contact@example.com';
|
| 6 |
+
|
| 7 |
+
const $ = (sel, root = document) => root.querySelector(sel);
|
| 8 |
+
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
|
| 9 |
+
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
| 10 |
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
| 11 |
+
const rand = (lo, hi) => lo + Math.random() * (hi - lo);
|
| 12 |
+
|
| 13 |
+
function initContact() {
|
| 14 |
+
$$('[data-contact]').forEach((link) => {
|
| 15 |
+
const subject = encodeURIComponent(link.dataset.subject || 'Hello');
|
| 16 |
+
link.href = `mailto:${CONTACT_EMAIL}?subject=${subject}`;
|
| 17 |
+
});
|
| 18 |
+
$$('[data-year]').forEach((el) => {
|
| 19 |
+
el.textContent = String(new Date().getFullYear());
|
| 20 |
+
});
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
function initNav() {
|
| 24 |
+
const nav = $('.nav');
|
| 25 |
+
const onScroll = () => nav.classList.toggle('is-scrolled', window.scrollY > 8);
|
| 26 |
+
onScroll();
|
| 27 |
+
window.addEventListener('scroll', onScroll, { passive: true });
|
| 28 |
+
|
| 29 |
+
const toggle = $('.nav-toggle');
|
| 30 |
+
const menu = $('#mobile-menu');
|
| 31 |
+
const setOpen = (open) => {
|
| 32 |
+
toggle.setAttribute('aria-expanded', String(open));
|
| 33 |
+
toggle.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
|
| 34 |
+
menu.hidden = !open;
|
| 35 |
+
document.body.classList.toggle('menu-open', open);
|
| 36 |
+
};
|
| 37 |
+
toggle.addEventListener('click', () => setOpen(toggle.getAttribute('aria-expanded') !== 'true'));
|
| 38 |
+
$$('a', menu).forEach((a) => a.addEventListener('click', () => setOpen(false)));
|
| 39 |
+
window.addEventListener('keydown', (e) => {
|
| 40 |
+
if (e.key === 'Escape') setOpen(false);
|
| 41 |
+
});
|
| 42 |
+
window.matchMedia('(min-width: 1101px)').addEventListener('change', (e) => {
|
| 43 |
+
if (e.matches) setOpen(false);
|
| 44 |
+
});
|
| 45 |
+
|
| 46 |
+
if (!('IntersectionObserver' in window)) return;
|
| 47 |
+
const links = new Map($$('.nav-links a').map((a) => [a.getAttribute('href').slice(1), a]));
|
| 48 |
+
const observer = new IntersectionObserver((entries) => {
|
| 49 |
+
entries.forEach((entry) => {
|
| 50 |
+
if (!entry.isIntersecting) return;
|
| 51 |
+
links.forEach((a) => a.classList.remove('is-active'));
|
| 52 |
+
const active = links.get(entry.target.id);
|
| 53 |
+
if (active) active.classList.add('is-active');
|
| 54 |
+
});
|
| 55 |
+
}, { rootMargin: '-45% 0px -50% 0px' });
|
| 56 |
+
$$('main > section[id]').forEach((section) => observer.observe(section));
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
function initReveal() {
|
| 60 |
+
const items = $$('.reveal');
|
| 61 |
+
if (reduceMotion || !('IntersectionObserver' in window)) {
|
| 62 |
+
items.forEach((el) => el.classList.add('is-visible'));
|
| 63 |
+
return;
|
| 64 |
+
}
|
| 65 |
+
const observer = new IntersectionObserver((entries) => {
|
| 66 |
+
entries.forEach((entry) => {
|
| 67 |
+
if (!entry.isIntersecting) return;
|
| 68 |
+
entry.target.classList.add('is-visible');
|
| 69 |
+
observer.unobserve(entry.target);
|
| 70 |
+
});
|
| 71 |
+
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.12 });
|
| 72 |
+
items.forEach((el) => observer.observe(el));
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
function initTabs() {
|
| 76 |
+
const tabs = $$('[role="tab"]');
|
| 77 |
+
if (!tabs.length) return;
|
| 78 |
+
const panels = tabs.map((tab) => document.getElementById(tab.getAttribute('aria-controls')));
|
| 79 |
+
|
| 80 |
+
const select = (index, focus) => {
|
| 81 |
+
tabs.forEach((tab, i) => {
|
| 82 |
+
const on = i === index;
|
| 83 |
+
tab.setAttribute('aria-selected', String(on));
|
| 84 |
+
tab.tabIndex = on ? 0 : -1;
|
| 85 |
+
panels[i].hidden = !on;
|
| 86 |
+
panels[i].classList.toggle('is-active', on);
|
| 87 |
+
});
|
| 88 |
+
if (focus) tabs[index].focus();
|
| 89 |
+
tabs[index].scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: reduceMotion ? 'auto' : 'smooth' });
|
| 90 |
+
};
|
| 91 |
+
|
| 92 |
+
tabs.forEach((tab, i) => {
|
| 93 |
+
tab.addEventListener('click', () => select(i, false));
|
| 94 |
+
tab.addEventListener('keydown', (e) => {
|
| 95 |
+
const keys = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 };
|
| 96 |
+
if (e.key in keys) {
|
| 97 |
+
e.preventDefault();
|
| 98 |
+
select((i + keys[e.key] + tabs.length) % tabs.length, true);
|
| 99 |
+
} else if (e.key === 'Home' || e.key === 'End') {
|
| 100 |
+
e.preventDefault();
|
| 101 |
+
select(e.key === 'Home' ? 0 : tabs.length - 1, true);
|
| 102 |
+
}
|
| 103 |
+
});
|
| 104 |
+
});
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
function initExamples() {
|
| 108 |
+
const grid = $('#ex-grid');
|
| 109 |
+
const modal = $('#ex-modal');
|
| 110 |
+
const source = $('#examples-data');
|
| 111 |
+
if (!grid || !modal || !source) return;
|
| 112 |
+
let examples;
|
| 113 |
+
try {
|
| 114 |
+
examples = JSON.parse(source.textContent);
|
| 115 |
+
} catch (err) {
|
| 116 |
+
return;
|
| 117 |
+
}
|
| 118 |
+
const cards = $$('.ex-card', grid);
|
| 119 |
+
|
| 120 |
+
const more = $('#ex-more');
|
| 121 |
+
const extras = cards.filter((card) => card.classList.contains('is-extra'));
|
| 122 |
+
if (more) {
|
| 123 |
+
if (!extras.length) more.hidden = true;
|
| 124 |
+
more.textContent = `Show ${extras.length} more examples`;
|
| 125 |
+
more.addEventListener('click', () => {
|
| 126 |
+
grid.classList.add('show-all');
|
| 127 |
+
more.setAttribute('aria-expanded', 'true');
|
| 128 |
+
if (extras[0]) extras[0].focus({ preventScroll: true });
|
| 129 |
+
});
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
const sheet = $('.ex-sheet', modal);
|
| 133 |
+
const closeButton = $('.icon-btn[data-ex-close]', modal);
|
| 134 |
+
const field = (id) => document.getElementById(id);
|
| 135 |
+
const fields = {
|
| 136 |
+
domain: field('exm-domain'),
|
| 137 |
+
title: field('exm-title'),
|
| 138 |
+
tracks: field('exm-tracks'),
|
| 139 |
+
img: field('exm-img'),
|
| 140 |
+
desc: field('exm-desc'),
|
| 141 |
+
software: field('exm-software'),
|
| 142 |
+
artifacts: field('exm-artifacts'),
|
| 143 |
+
axes: field('exm-axes'),
|
| 144 |
+
outputs: field('exm-outputs'),
|
| 145 |
+
cta: field('exm-cta'),
|
| 146 |
+
live: field('exm-live'),
|
| 147 |
+
};
|
| 148 |
+
let current = 0;
|
| 149 |
+
let lastFocus = null;
|
| 150 |
+
let liveView = null;
|
| 151 |
+
|
| 152 |
+
const mountLive = (ex) => {
|
| 153 |
+
if (liveView) {
|
| 154 |
+
liveView.dispose();
|
| 155 |
+
liveView = null;
|
| 156 |
+
}
|
| 157 |
+
const live = window.ILLive;
|
| 158 |
+
if (!fields.live || !live || !live.ready) {
|
| 159 |
+
if (fields.live) fields.live.hidden = true;
|
| 160 |
+
return;
|
| 161 |
+
}
|
| 162 |
+
fields.live.hidden = false;
|
| 163 |
+
fields.live.style.setProperty('--dc', ex.color);
|
| 164 |
+
liveView = live.mount(fields.live, ex.kind, { color: ex.color, hero: true });
|
| 165 |
+
if (!liveView) fields.live.hidden = true;
|
| 166 |
+
};
|
| 167 |
+
|
| 168 |
+
const listItems = (ul, items) => {
|
| 169 |
+
ul.replaceChildren(...items.map(({ text, cls }) => {
|
| 170 |
+
const li = document.createElement('li');
|
| 171 |
+
li.textContent = text;
|
| 172 |
+
if (cls) li.className = cls;
|
| 173 |
+
return li;
|
| 174 |
+
}));
|
| 175 |
+
};
|
| 176 |
+
const plain = (items) => items.map((text) => ({ text }));
|
| 177 |
+
|
| 178 |
+
const render = (index) => {
|
| 179 |
+
current = (index + examples.length) % examples.length;
|
| 180 |
+
const ex = examples[current];
|
| 181 |
+
sheet.style.setProperty('--dc', ex.color);
|
| 182 |
+
fields.domain.textContent = ex.domain;
|
| 183 |
+
fields.title.textContent = ex.title;
|
| 184 |
+
const tracks = ex.tracks.map((t) => ({ text: t, cls: `trk trk-${t.toLowerCase()}` }));
|
| 185 |
+
if (ex.modality) tracks.push({ text: ex.modality, cls: 'trk trk-mod' });
|
| 186 |
+
listItems(fields.tracks, tracks);
|
| 187 |
+
fields.img.src = ex.img;
|
| 188 |
+
fields.img.alt = ex.alt;
|
| 189 |
+
fields.desc.textContent = ex.description;
|
| 190 |
+
listItems(fields.software, plain(ex.software));
|
| 191 |
+
listItems(fields.artifacts, plain(ex.artifacts));
|
| 192 |
+
listItems(fields.axes, plain(ex.axes));
|
| 193 |
+
listItems(fields.outputs, plain(ex.outputs));
|
| 194 |
+
fields.cta.href = `mailto:${CONTACT_EMAIL}?subject=${encodeURIComponent(`Sample request: ${ex.title}`)}`;
|
| 195 |
+
sheet.scrollTop = 0;
|
| 196 |
+
if (!modal.hidden) mountLive(ex);
|
| 197 |
+
};
|
| 198 |
+
|
| 199 |
+
const open = (index) => {
|
| 200 |
+
lastFocus = document.activeElement;
|
| 201 |
+
render(index);
|
| 202 |
+
modal.hidden = false;
|
| 203 |
+
mountLive(examples[current]);
|
| 204 |
+
document.body.classList.add('modal-open');
|
| 205 |
+
closeButton.focus();
|
| 206 |
+
};
|
| 207 |
+
const close = () => {
|
| 208 |
+
modal.hidden = true;
|
| 209 |
+
if (liveView) {
|
| 210 |
+
liveView.dispose();
|
| 211 |
+
liveView = null;
|
| 212 |
+
}
|
| 213 |
+
document.body.classList.remove('modal-open');
|
| 214 |
+
if (lastFocus) lastFocus.focus({ preventScroll: true });
|
| 215 |
+
};
|
| 216 |
+
document.addEventListener('il-live-ready', () => {
|
| 217 |
+
if (!modal.hidden) mountLive(examples[current]);
|
| 218 |
+
});
|
| 219 |
+
|
| 220 |
+
cards.forEach((card) => {
|
| 221 |
+
const index = Number(card.dataset.index);
|
| 222 |
+
card.addEventListener('click', () => open(index));
|
| 223 |
+
card.addEventListener('keydown', (e) => {
|
| 224 |
+
if (e.key === 'Enter' || e.key === ' ') {
|
| 225 |
+
e.preventDefault();
|
| 226 |
+
open(index);
|
| 227 |
+
}
|
| 228 |
+
});
|
| 229 |
+
});
|
| 230 |
+
$$('[data-ex-close]', modal).forEach((el) => el.addEventListener('click', close));
|
| 231 |
+
$('[data-ex-prev]', modal).addEventListener('click', () => render(current - 1));
|
| 232 |
+
$('[data-ex-next]', modal).addEventListener('click', () => render(current + 1));
|
| 233 |
+
|
| 234 |
+
document.addEventListener('keydown', (e) => {
|
| 235 |
+
if (modal.hidden) return;
|
| 236 |
+
if (e.key === 'Escape') {
|
| 237 |
+
e.preventDefault();
|
| 238 |
+
close();
|
| 239 |
+
} else if (e.key === 'ArrowRight') {
|
| 240 |
+
render(current + 1);
|
| 241 |
+
} else if (e.key === 'ArrowLeft') {
|
| 242 |
+
render(current - 1);
|
| 243 |
+
} else if (e.key === 'Tab') {
|
| 244 |
+
const focusables = $$('button, a[href]', sheet);
|
| 245 |
+
const first = focusables[0];
|
| 246 |
+
const last = focusables[focusables.length - 1];
|
| 247 |
+
if (e.shiftKey && document.activeElement === first) {
|
| 248 |
+
e.preventDefault();
|
| 249 |
+
last.focus();
|
| 250 |
+
} else if (!e.shiftKey && document.activeElement === last) {
|
| 251 |
+
e.preventDefault();
|
| 252 |
+
first.focus();
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
});
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
function initWaves() {
|
| 259 |
+
$$('path[data-wave]').forEach((path) => {
|
| 260 |
+
const [amp, decay, freq, phase] = path.dataset.wave.split(/\s+/).map(Number);
|
| 261 |
+
const points = [];
|
| 262 |
+
for (let i = 0; i <= 120; i += 1) {
|
| 263 |
+
const t = (3 * i) / 120;
|
| 264 |
+
const x = 40 + (296 * i) / 120;
|
| 265 |
+
const y = 104 - amp * Math.exp(-decay * t) * Math.cos(freq * t + phase);
|
| 266 |
+
points.push(`${x.toFixed(1)},${y.toFixed(1)}`);
|
| 267 |
+
}
|
| 268 |
+
path.setAttribute('d', `M${points.join('L')}`);
|
| 269 |
+
if (path.classList.contains('wave-recon')) path.setAttribute('pathLength', '1');
|
| 270 |
+
});
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
function initLadder() {
|
| 274 |
+
const svg = $('#ladder-chart');
|
| 275 |
+
const slider = $('#ladder-strength');
|
| 276 |
+
const readout = $('#ladder-readout');
|
| 277 |
+
const label = $('#ladder-strength-label');
|
| 278 |
+
if (!svg || !slider || !readout || !label) return;
|
| 279 |
+
|
| 280 |
+
const NS = 'http://www.w3.org/2000/svg';
|
| 281 |
+
// Reference-solver measurements (pass@4) by synthesis round.
|
| 282 |
+
const ANCHORS = [[1, 0.9], [6, 0.2], [15, 0.025]];
|
| 283 |
+
const ROUNDS = 15;
|
| 284 |
+
const LOW = 0.1;
|
| 285 |
+
const HIGH = 0.5;
|
| 286 |
+
const logit = (p) => Math.log(p / (1 - p));
|
| 287 |
+
const sigmoid = (z) => 1 / (1 + Math.exp(-z));
|
| 288 |
+
const baseLogit = (r) => {
|
| 289 |
+
for (let i = 0; i < ANCHORS.length - 1; i += 1) {
|
| 290 |
+
const [r0, p0] = ANCHORS[i];
|
| 291 |
+
const [r1, p1] = ANCHORS[i + 1];
|
| 292 |
+
if (r <= r1) return logit(p0) + ((r - r0) / (r1 - r0)) * (logit(p1) - logit(p0));
|
| 293 |
+
}
|
| 294 |
+
return logit(ANCHORS[ANCHORS.length - 1][1]);
|
| 295 |
+
};
|
| 296 |
+
|
| 297 |
+
const W = 640;
|
| 298 |
+
const H = 330;
|
| 299 |
+
const m = { l: 46, r: 14, t: 18, b: 46 };
|
| 300 |
+
const pw = W - m.l - m.r;
|
| 301 |
+
const ph = H - m.t - m.b;
|
| 302 |
+
const xOf = (r) => m.l + ((r - 0.5) / ROUNDS) * pw;
|
| 303 |
+
const yOf = (p) => m.t + (1 - p) * ph;
|
| 304 |
+
const barW = (pw / ROUNDS) * 0.6;
|
| 305 |
+
svg.setAttribute('viewBox', `0 0 ${W} ${H}`);
|
| 306 |
+
|
| 307 |
+
const add = (tag, attrs, text) => {
|
| 308 |
+
const node = document.createElementNS(NS, tag);
|
| 309 |
+
Object.entries(attrs).forEach(([k, v]) => node.setAttribute(k, String(v)));
|
| 310 |
+
if (text != null) node.textContent = text;
|
| 311 |
+
svg.appendChild(node);
|
| 312 |
+
return node;
|
| 313 |
+
};
|
| 314 |
+
|
| 315 |
+
[0, 0.25, 0.5, 0.75, 1].forEach((v) => {
|
| 316 |
+
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(v), y2: yOf(v), class: 'grid' });
|
| 317 |
+
add('text', { x: m.l - 10, y: yOf(v) + 4, class: 'tick', 'text-anchor': 'end' }, `${v * 100}%`);
|
| 318 |
+
});
|
| 319 |
+
add('rect', { x: m.l, y: yOf(HIGH), width: pw, height: yOf(LOW) - yOf(HIGH), class: 'zone' });
|
| 320 |
+
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(HIGH), y2: yOf(HIGH), class: 'zone-edge' });
|
| 321 |
+
add('line', { x1: m.l, x2: m.l + pw, y1: yOf(LOW), y2: yOf(LOW), class: 'zone-edge' });
|
| 322 |
+
|
| 323 |
+
const bars = [];
|
| 324 |
+
for (let r = 1; r <= ROUNDS; r += 1) {
|
| 325 |
+
bars.push(add('rect', { x: xOf(r) - barW / 2, y: yOf(0), width: barW, height: 0, rx: 3, class: 'bar' }));
|
| 326 |
+
add('text', { x: xOf(r), y: H - m.b + 18, class: 'tick', 'text-anchor': 'middle' }, String(r));
|
| 327 |
+
}
|
| 328 |
+
add('text', { x: m.l + pw / 2, y: H - 6, class: 'axis-label', 'text-anchor': 'middle' }, 'Synthesis round (harder →)');
|
| 329 |
+
|
| 330 |
+
let d = '';
|
| 331 |
+
for (let r = 1; r <= ROUNDS + 1e-9; r += 0.2) {
|
| 332 |
+
d += `${d ? 'L' : 'M'}${xOf(r).toFixed(1)},${yOf(sigmoid(baseLogit(r))).toFixed(1)}`;
|
| 333 |
+
}
|
| 334 |
+
add('path', { d, class: 'ref-line' });
|
| 335 |
+
ANCHORS.forEach(([r, p]) => {
|
| 336 |
+
add('circle', { cx: xOf(r), cy: yOf(p), r: 5, class: 'anchor' });
|
| 337 |
+
const lastRound = r === ROUNDS;
|
| 338 |
+
add('text', {
|
| 339 |
+
x: xOf(r) + (lastRound ? -10 : 10),
|
| 340 |
+
y: yOf(p) - 10,
|
| 341 |
+
class: 'anchor-label',
|
| 342 |
+
'text-anchor': lastRound ? 'end' : 'start',
|
| 343 |
+
}, `${+(p * 100).toFixed(1)}%`);
|
| 344 |
+
});
|
| 345 |
+
|
| 346 |
+
const current = bars.map(() => 0);
|
| 347 |
+
let target = bars.map(() => 0);
|
| 348 |
+
let frame = 0;
|
| 349 |
+
let started = false;
|
| 350 |
+
|
| 351 |
+
const drawBars = (values) => {
|
| 352 |
+
values.forEach((p, i) => {
|
| 353 |
+
const top = yOf(p);
|
| 354 |
+
bars[i].setAttribute('y', top.toFixed(2));
|
| 355 |
+
bars[i].setAttribute('height', Math.max(0, yOf(0) - top).toFixed(2));
|
| 356 |
+
});
|
| 357 |
+
};
|
| 358 |
+
const tick = () => {
|
| 359 |
+
let moving = false;
|
| 360 |
+
for (let i = 0; i < current.length; i += 1) {
|
| 361 |
+
const delta = target[i] - current[i];
|
| 362 |
+
if (Math.abs(delta) > 0.0005) {
|
| 363 |
+
current[i] += delta * 0.2;
|
| 364 |
+
moving = true;
|
| 365 |
+
} else {
|
| 366 |
+
current[i] = target[i];
|
| 367 |
+
}
|
| 368 |
+
}
|
| 369 |
+
drawBars(current);
|
| 370 |
+
frame = moving ? requestAnimationFrame(tick) : 0;
|
| 371 |
+
};
|
| 372 |
+
const kick = () => {
|
| 373 |
+
if (reduceMotion) {
|
| 374 |
+
target.forEach((p, i) => { current[i] = p; });
|
| 375 |
+
drawBars(current);
|
| 376 |
+
} else if (!frame) {
|
| 377 |
+
frame = requestAnimationFrame(tick);
|
| 378 |
+
}
|
| 379 |
+
};
|
| 380 |
+
|
| 381 |
+
const update = () => {
|
| 382 |
+
const shift = Number(slider.value);
|
| 383 |
+
target = bars.map((_, i) => sigmoid(baseLogit(i + 1) + shift));
|
| 384 |
+
const zone = [];
|
| 385 |
+
target.forEach((p, i) => {
|
| 386 |
+
const inZone = p >= LOW && p <= HIGH;
|
| 387 |
+
bars[i].classList.toggle('in-zone', inZone);
|
| 388 |
+
if (inZone) zone.push(i + 1);
|
| 389 |
+
});
|
| 390 |
+
if (Math.abs(shift) < 0.05) label.textContent = 'Reference solver';
|
| 391 |
+
else label.textContent = shift > 0 ? 'Stronger than reference' : 'Weaker than reference';
|
| 392 |
+
|
| 393 |
+
if (zone.length) {
|
| 394 |
+
const span = zone.length === 1 ? `round ${zone[0]}` : `rounds ${zone[0]}–${zone[zone.length - 1]}`;
|
| 395 |
+
readout.innerHTML = `Next batch: <strong>${span}</strong>, where this model succeeds 10–50% of the time.`;
|
| 396 |
+
} else if (target[ROUNDS - 1] > HIGH) {
|
| 397 |
+
readout.innerHTML = 'This model has outgrown the ladder: <strong>we synthesize further rounds</strong>.';
|
| 398 |
+
} else {
|
| 399 |
+
readout.innerHTML = '<strong>Start with warm-up tiers</strong> and calibrate upward.';
|
| 400 |
+
}
|
| 401 |
+
if (started) kick();
|
| 402 |
+
};
|
| 403 |
+
|
| 404 |
+
slider.addEventListener('input', update);
|
| 405 |
+
update();
|
| 406 |
+
|
| 407 |
+
const begin = () => {
|
| 408 |
+
started = true;
|
| 409 |
+
kick();
|
| 410 |
+
};
|
| 411 |
+
if (reduceMotion || !('IntersectionObserver' in window)) {
|
| 412 |
+
begin();
|
| 413 |
+
} else {
|
| 414 |
+
const observer = new IntersectionObserver((entries) => {
|
| 415 |
+
if (!entries.some((entry) => entry.isIntersecting)) return;
|
| 416 |
+
observer.disconnect();
|
| 417 |
+
begin();
|
| 418 |
+
}, { threshold: 0.3 });
|
| 419 |
+
observer.observe(svg);
|
| 420 |
+
}
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
function initHero() {
|
| 424 |
+
const hero = $('.hero');
|
| 425 |
+
const canvas = hero && $('.hero-canvas', hero);
|
| 426 |
+
if (!canvas || !canvas.getContext) return;
|
| 427 |
+
const ctx = canvas.getContext('2d');
|
| 428 |
+
const copy = $('.hero-copy', hero);
|
| 429 |
+
const badges = $$('.tier-badges li', hero);
|
| 430 |
+
|
| 431 |
+
const TIER_RGB = [[20, 184, 138], [13, 165, 160], [37, 140, 214], [88, 101, 226], [124, 92, 220]];
|
| 432 |
+
const IDLE_RGB = [100, 116, 139];
|
| 433 |
+
const REJECT_RGB = [242, 107, 91];
|
| 434 |
+
const GATE_LABELS = ['Execute', 'Verify', 'Audit'];
|
| 435 |
+
const REJECT_RATE = [0.14, 0.1, 0.06];
|
| 436 |
+
|
| 437 |
+
let W = 0;
|
| 438 |
+
let H = 0;
|
| 439 |
+
let copyRight = 0;
|
| 440 |
+
let flowMode = true;
|
| 441 |
+
let gates = [];
|
| 442 |
+
let targets = [];
|
| 443 |
+
const particles = [];
|
| 444 |
+
let raf = 0;
|
| 445 |
+
let last = 0;
|
| 446 |
+
let onScreen = true;
|
| 447 |
+
const mouse = { x: -1e4, y: -1e4 };
|
| 448 |
+
const glowing = new Set();
|
| 449 |
+
|
| 450 |
+
const smooth = (k) => k * k * (3 - 2 * k);
|
| 451 |
+
|
| 452 |
+
function spawn(scatter) {
|
| 453 |
+
const x = scatter ? rand(-40, W) : rand(-90, -10);
|
| 454 |
+
let y;
|
| 455 |
+
let tier;
|
| 456 |
+
if (flowMode || !targets.length) {
|
| 457 |
+
y = rand(H * 0.08, H * 0.92);
|
| 458 |
+
tier = Math.floor(Math.random() * TIER_RGB.length);
|
| 459 |
+
} else {
|
| 460 |
+
// Lanes start near the badge they feed, so streams fan in instead of crossing.
|
| 461 |
+
const top = targets[0].y;
|
| 462 |
+
const bottom = targets[targets.length - 1].y;
|
| 463 |
+
y = clamp(rand(top - 90, bottom + 90), H * 0.06, H * 0.94);
|
| 464 |
+
const slot = ((y - top) / (bottom - top)) * (targets.length - 1) + rand(-0.6, 0.6);
|
| 465 |
+
tier = clamp(Math.round(slot), 0, targets.length - 1);
|
| 466 |
+
}
|
| 467 |
+
return {
|
| 468 |
+
x, y, px: x, py: y, baseY: y,
|
| 469 |
+
speed: rand(0.45, 1.05),
|
| 470 |
+
phase: rand(0, Math.PI * 2),
|
| 471 |
+
amp: rand(4, 16),
|
| 472 |
+
tier,
|
| 473 |
+
gate: 0,
|
| 474 |
+
rejected: false,
|
| 475 |
+
alpha: 1,
|
| 476 |
+
size: rand(1, 2.3),
|
| 477 |
+
};
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
function measure() {
|
| 481 |
+
const rect = hero.getBoundingClientRect();
|
| 482 |
+
W = rect.width;
|
| 483 |
+
H = rect.height;
|
| 484 |
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
| 485 |
+
canvas.width = Math.round(W * dpr);
|
| 486 |
+
canvas.height = Math.round(H * dpr);
|
| 487 |
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
| 488 |
+
copyRight = copy ? copy.getBoundingClientRect().right - rect.left : W * 0.5;
|
| 489 |
+
targets = badges.map((badge) => {
|
| 490 |
+
const r = badge.getBoundingClientRect();
|
| 491 |
+
return { x: r.left - rect.left - 6, y: r.top - rect.top + r.height / 2, ok: r.width > 0 };
|
| 492 |
+
});
|
| 493 |
+
flowMode = !(targets.length && targets.every((t) => t.ok));
|
| 494 |
+
gates = [];
|
| 495 |
+
if (!flowMode) {
|
| 496 |
+
const start = copyRight + 56;
|
| 497 |
+
const end = Math.min(...targets.map((t) => t.x)) - 60;
|
| 498 |
+
if (end - start > 200) {
|
| 499 |
+
gates = GATE_LABELS.map((_, i) => start + ((end - start) * i) / (GATE_LABELS.length - 1));
|
| 500 |
+
} else {
|
| 501 |
+
flowMode = true;
|
| 502 |
+
}
|
| 503 |
+
}
|
| 504 |
+
const count = Math.round(clamp((W * H) / (flowMode ? 4200 : 1500), 110, 760));
|
| 505 |
+
while (particles.length < count) particles.push(spawn(true));
|
| 506 |
+
particles.length = count;
|
| 507 |
+
particles.forEach((p) => {
|
| 508 |
+
if (p.baseY > H || p.y > H) Object.assign(p, spawn(true));
|
| 509 |
+
});
|
| 510 |
+
}
|
| 511 |
+
|
| 512 |
+
function arrive(i) {
|
| 513 |
+
if (glowing.has(i) || Math.random() > 0.05) return;
|
| 514 |
+
const badge = badges[i];
|
| 515 |
+
if (!badge) return;
|
| 516 |
+
glowing.add(i);
|
| 517 |
+
badge.classList.add('glow');
|
| 518 |
+
setTimeout(() => {
|
| 519 |
+
badge.classList.remove('glow');
|
| 520 |
+
glowing.delete(i);
|
| 521 |
+
}, 700);
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
function update(p, dt, t) {
|
| 525 |
+
p.px = p.x;
|
| 526 |
+
p.py = p.y;
|
| 527 |
+
if (p.rejected) {
|
| 528 |
+
p.x += p.speed * 0.45 * dt;
|
| 529 |
+
p.y += 0.8 * dt;
|
| 530 |
+
p.alpha -= 0.024 * dt;
|
| 531 |
+
if (p.alpha <= 0) Object.assign(p, spawn(false));
|
| 532 |
+
return;
|
| 533 |
+
}
|
| 534 |
+
while (p.gate < gates.length && p.x >= gates[p.gate]) {
|
| 535 |
+
if (Math.random() < REJECT_RATE[p.gate]) {
|
| 536 |
+
p.rejected = true;
|
| 537 |
+
return;
|
| 538 |
+
}
|
| 539 |
+
p.gate += 1;
|
| 540 |
+
}
|
| 541 |
+
const target = flowMode ? null : targets[p.tier];
|
| 542 |
+
let k = 0;
|
| 543 |
+
let laneY = p.baseY;
|
| 544 |
+
if (target) {
|
| 545 |
+
const x0 = gates[0] - 80;
|
| 546 |
+
k = clamp((p.x - x0) / (target.x - x0), 0, 1);
|
| 547 |
+
laneY = p.baseY + (target.y - p.baseY) * smooth(k);
|
| 548 |
+
}
|
| 549 |
+
const wave = Math.sin(t * 0.0011 + p.phase + p.x * 0.0045) * p.amp * (1 - 0.9 * k);
|
| 550 |
+
p.x += p.speed * (0.8 + W / 1800) * dt;
|
| 551 |
+
p.y += (laneY + wave - p.y) * Math.min(1, 0.085 * dt);
|
| 552 |
+
|
| 553 |
+
const dx = p.x - mouse.x;
|
| 554 |
+
const dy = p.y - mouse.y;
|
| 555 |
+
const d2 = dx * dx + dy * dy;
|
| 556 |
+
if (d2 < 14400) {
|
| 557 |
+
const dist = Math.sqrt(d2) || 1;
|
| 558 |
+
const force = (1 - dist / 120) * 2.4 * dt;
|
| 559 |
+
p.x += (dx / dist) * force * 0.35;
|
| 560 |
+
p.y += (dy / dist) * force;
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
if (target && p.x >= target.x) {
|
| 564 |
+
arrive(p.tier);
|
| 565 |
+
Object.assign(p, spawn(false));
|
| 566 |
+
} else if (p.x > W + 24) {
|
| 567 |
+
Object.assign(p, spawn(false));
|
| 568 |
+
}
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
function roundRect(x, y, w, h, r) {
|
| 572 |
+
ctx.beginPath();
|
| 573 |
+
if (ctx.roundRect) {
|
| 574 |
+
ctx.roundRect(x, y, w, h, r);
|
| 575 |
+
return;
|
| 576 |
+
}
|
| 577 |
+
ctx.moveTo(x + r, y);
|
| 578 |
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
| 579 |
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
| 580 |
+
ctx.arcTo(x, y + h, x, y, r);
|
| 581 |
+
ctx.arcTo(x, y, x + w, y, r);
|
| 582 |
+
ctx.closePath();
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
function drawGates() {
|
| 586 |
+
const top = H * 0.16;
|
| 587 |
+
const bottom = H * 0.86;
|
| 588 |
+
ctx.save();
|
| 589 |
+
ctx.font = '600 11px Inter, ui-sans-serif, system-ui, sans-serif';
|
| 590 |
+
ctx.textAlign = 'center';
|
| 591 |
+
ctx.textBaseline = 'middle';
|
| 592 |
+
gates.forEach((gx, i) => {
|
| 593 |
+
const grad = ctx.createLinearGradient(0, top, 0, bottom);
|
| 594 |
+
grad.addColorStop(0, 'rgba(15,23,42,0)');
|
| 595 |
+
grad.addColorStop(0.5, 'rgba(15,23,42,0.18)');
|
| 596 |
+
grad.addColorStop(1, 'rgba(15,23,42,0)');
|
| 597 |
+
ctx.strokeStyle = grad;
|
| 598 |
+
ctx.lineWidth = 1;
|
| 599 |
+
ctx.setLineDash([3, 6]);
|
| 600 |
+
ctx.beginPath();
|
| 601 |
+
ctx.moveTo(gx, top);
|
| 602 |
+
ctx.lineTo(gx, bottom);
|
| 603 |
+
ctx.stroke();
|
| 604 |
+
ctx.setLineDash([]);
|
| 605 |
+
|
| 606 |
+
const text = GATE_LABELS[i];
|
| 607 |
+
const w = ctx.measureText(text).width + 22;
|
| 608 |
+
const h = 24;
|
| 609 |
+
const y = top - 16;
|
| 610 |
+
ctx.fillStyle = 'rgba(255,255,255,0.92)';
|
| 611 |
+
ctx.strokeStyle = 'rgba(15,23,42,0.12)';
|
| 612 |
+
roundRect(gx - w / 2, y - h / 2, w, h, 12);
|
| 613 |
+
ctx.fill();
|
| 614 |
+
ctx.stroke();
|
| 615 |
+
ctx.fillStyle = '#334155';
|
| 616 |
+
ctx.fillText(text, gx, y + 0.5);
|
| 617 |
+
});
|
| 618 |
+
ctx.restore();
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
function drawBadgeGlow() {
|
| 622 |
+
targets.forEach((t, i) => {
|
| 623 |
+
const [r, g, b] = TIER_RGB[i];
|
| 624 |
+
const glow = ctx.createRadialGradient(t.x, t.y, 0, t.x, t.y, 72);
|
| 625 |
+
glow.addColorStop(0, `rgba(${r},${g},${b},0.18)`);
|
| 626 |
+
glow.addColorStop(1, `rgba(${r},${g},${b},0)`);
|
| 627 |
+
ctx.fillStyle = glow;
|
| 628 |
+
ctx.fillRect(t.x - 72, t.y - 72, 144, 144);
|
| 629 |
+
});
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
function draw() {
|
| 633 |
+
ctx.clearRect(0, 0, W, H);
|
| 634 |
+
if (gates.length) {
|
| 635 |
+
drawGates();
|
| 636 |
+
drawBadgeGlow();
|
| 637 |
+
}
|
| 638 |
+
ctx.lineCap = 'round';
|
| 639 |
+
for (const p of particles) {
|
| 640 |
+
let rgb;
|
| 641 |
+
let a;
|
| 642 |
+
if (p.rejected) {
|
| 643 |
+
rgb = REJECT_RGB;
|
| 644 |
+
a = 0.75 * p.alpha;
|
| 645 |
+
} else if (flowMode) {
|
| 646 |
+
rgb = TIER_RGB[p.tier];
|
| 647 |
+
a = 0.4;
|
| 648 |
+
} else if (p.gate === 0) {
|
| 649 |
+
rgb = IDLE_RGB;
|
| 650 |
+
a = p.x < copyRight ? 0.2 : 0.36;
|
| 651 |
+
} else {
|
| 652 |
+
rgb = TIER_RGB[p.tier];
|
| 653 |
+
a = 0.5 + 0.15 * p.gate;
|
| 654 |
+
}
|
| 655 |
+
let sx = (p.x - p.px) * 3;
|
| 656 |
+
let sy = (p.y - p.py) * 3;
|
| 657 |
+
const len = Math.hypot(sx, sy);
|
| 658 |
+
if (len > 16) {
|
| 659 |
+
sx *= 16 / len;
|
| 660 |
+
sy *= 16 / len;
|
| 661 |
+
}
|
| 662 |
+
ctx.strokeStyle = `rgba(${rgb[0]},${rgb[1]},${rgb[2]},${a.toFixed(3)})`;
|
| 663 |
+
ctx.lineWidth = p.size;
|
| 664 |
+
ctx.beginPath();
|
| 665 |
+
ctx.moveTo(p.x - sx, p.y - sy);
|
| 666 |
+
ctx.lineTo(p.x + 0.01, p.y);
|
| 667 |
+
ctx.stroke();
|
| 668 |
+
}
|
| 669 |
+
}
|
| 670 |
+
|
| 671 |
+
function loop(now) {
|
| 672 |
+
const dt = clamp((now - last) / 16.67, 0.2, 3);
|
| 673 |
+
last = now;
|
| 674 |
+
for (const p of particles) update(p, dt, now);
|
| 675 |
+
draw();
|
| 676 |
+
raf = requestAnimationFrame(loop);
|
| 677 |
+
}
|
| 678 |
+
const start = () => {
|
| 679 |
+
if (raf || reduceMotion || !onScreen || document.hidden) return;
|
| 680 |
+
last = performance.now();
|
| 681 |
+
raf = requestAnimationFrame(loop);
|
| 682 |
+
};
|
| 683 |
+
const stop = () => {
|
| 684 |
+
if (raf) cancelAnimationFrame(raf);
|
| 685 |
+
raf = 0;
|
| 686 |
+
};
|
| 687 |
+
const renderStill = () => {
|
| 688 |
+
for (let i = 0; i < 260; i += 1) particles.forEach((p) => update(p, 1, i * 16));
|
| 689 |
+
draw();
|
| 690 |
+
};
|
| 691 |
+
|
| 692 |
+
measure();
|
| 693 |
+
if (reduceMotion) renderStill();
|
| 694 |
+
else start();
|
| 695 |
+
|
| 696 |
+
let resizeTimer = 0;
|
| 697 |
+
window.addEventListener('resize', () => {
|
| 698 |
+
clearTimeout(resizeTimer);
|
| 699 |
+
resizeTimer = setTimeout(() => {
|
| 700 |
+
measure();
|
| 701 |
+
if (reduceMotion) renderStill();
|
| 702 |
+
}, 120);
|
| 703 |
+
});
|
| 704 |
+
if (document.fonts && document.fonts.ready) {
|
| 705 |
+
document.fonts.ready.then(() => {
|
| 706 |
+
measure();
|
| 707 |
+
if (reduceMotion) renderStill();
|
| 708 |
+
});
|
| 709 |
+
}
|
| 710 |
+
hero.addEventListener('pointermove', (e) => {
|
| 711 |
+
const r = hero.getBoundingClientRect();
|
| 712 |
+
mouse.x = e.clientX - r.left;
|
| 713 |
+
mouse.y = e.clientY - r.top;
|
| 714 |
+
});
|
| 715 |
+
hero.addEventListener('pointerleave', () => {
|
| 716 |
+
mouse.x = -1e4;
|
| 717 |
+
mouse.y = -1e4;
|
| 718 |
+
});
|
| 719 |
+
if ('IntersectionObserver' in window) {
|
| 720 |
+
new IntersectionObserver((entries) => {
|
| 721 |
+
onScreen = entries.some((entry) => entry.isIntersecting);
|
| 722 |
+
if (onScreen) start();
|
| 723 |
+
else stop();
|
| 724 |
+
}).observe(hero);
|
| 725 |
+
}
|
| 726 |
+
document.addEventListener('visibilitychange', () => (document.hidden ? stop() : start()));
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
initContact();
|
| 730 |
+
initNav();
|
| 731 |
+
initReveal();
|
| 732 |
+
initTabs();
|
| 733 |
+
initExamples();
|
| 734 |
+
initWaves();
|
| 735 |
+
initLadder();
|
| 736 |
+
initHero();
|
| 737 |
+
})();
|
assets/examples/astro-detail.webp
ADDED
|
Git LFS Details
|
assets/examples/astro-thumb.webp
ADDED
|
|
assets/examples/blender-detail.webp
ADDED
|
assets/examples/blender-thumb.webp
ADDED
|
|
assets/examples/color-detail.webp
ADDED
|
Git LFS Details
|
assets/examples/color-thumb.webp
ADDED
|
|
assets/examples/container-detail.webp
ADDED
|
assets/examples/container-thumb.webp
ADDED
|
|
assets/examples/drc-detail.webp
ADDED
|
assets/examples/drc-thumb.webp
ADDED
|
|
assets/examples/foam-detail.webp
ADDED
|
assets/examples/foam-thumb.webp
ADDED
|
|
assets/examples/micro-detail.webp
ADDED
|
Git LFS Details
|
assets/examples/micro-thumb.webp
ADDED
|
|
assets/examples/ocr-detail.webp
ADDED
|
assets/examples/ocr-thumb.webp
ADDED
|
|
assets/examples/robot-detail.webp
ADDED
|
assets/examples/robot-thumb.webp
ADDED
|
|
assets/examples/stl-detail.webp
ADDED
|
assets/examples/stl-thumb.webp
ADDED
|
|
assets/examples/visuals.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
index.html
CHANGED
|
@@ -1,19 +1,900 @@
|
|
| 1 |
<!doctype html>
|
| 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">
|
| 6 |
+
<title>IntelligenceLab · Verified training environments for frontier agents</title>
|
| 7 |
+
<meta name="description" content="Verified, difficulty-calibrated training environments for terminal, scientific, CAD, web, and visual-to-code agents. Every task ships with a reference solution and an executable verifier.">
|
| 8 |
+
<meta property="og:type" content="website">
|
| 9 |
+
<meta property="og:title" content="IntelligenceLab · Verified training environments for frontier agents">
|
| 10 |
+
<meta property="og:description" content="Long-horizon agent tasks that prove themselves: executed, verified, and calibrated before they reach you.">
|
| 11 |
+
<meta name="theme-color" content="#f6f7f4">
|
| 12 |
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%2310b981'/%3E%3Cstop offset='1' stop-color='%236366f1'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='32' height='32' rx='8' fill='url(%23g)'/%3E%3Cpath d='M7 23h5v-5h5v-5h5' fill='none' stroke='white' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M19.6 9.4l2.2 2.2 4.2-4.4' fill='none' stroke='white' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E">
|
| 13 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 14 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 15 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
| 16 |
+
<link rel="stylesheet" href="styles.css">
|
| 17 |
+
<script>document.documentElement.classList.add('js');</script>
|
| 18 |
+
</head>
|
| 19 |
+
<body>
|
| 20 |
+
<a class="skip-link" href="#main">Skip to content</a>
|
| 21 |
+
|
| 22 |
+
<header class="nav">
|
| 23 |
+
<div class="container nav-inner">
|
| 24 |
+
<a class="brand" href="#top" aria-label="IntelligenceLab home">
|
| 25 |
+
<svg class="brand-mark" viewBox="0 0 32 32" aria-hidden="true">
|
| 26 |
+
<defs>
|
| 27 |
+
<linearGradient id="brand-grad" x1="0" y1="0" x2="1" y2="1">
|
| 28 |
+
<stop offset="0" stop-color="#10b981"/>
|
| 29 |
+
<stop offset="1" stop-color="#6366f1"/>
|
| 30 |
+
</linearGradient>
|
| 31 |
+
</defs>
|
| 32 |
+
<rect width="32" height="32" rx="8" fill="url(#brand-grad)"/>
|
| 33 |
+
<path d="M7 23h5v-5h5v-5h5" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
|
| 34 |
+
<path d="M19.6 9.4l2.2 2.2 4.2-4.4" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
|
| 35 |
+
</svg>
|
| 36 |
+
<span>IntelligenceLab</span>
|
| 37 |
+
</a>
|
| 38 |
+
<nav class="nav-links" aria-label="Primary">
|
| 39 |
+
<a href="#offerings">What we provide</a>
|
| 40 |
+
<a href="#examples">Examples</a>
|
| 41 |
+
<a href="#pipeline">How it works</a>
|
| 42 |
+
<a href="#trajectories">Trajectories</a>
|
| 43 |
+
<a href="#research">Research</a>
|
| 44 |
+
</nav>
|
| 45 |
+
<div class="nav-cta">
|
| 46 |
+
<a class="btn btn-dark btn-sm" href="#contact">Start a pilot</a>
|
| 47 |
+
<button class="nav-toggle" type="button" aria-label="Open menu" aria-expanded="false" aria-controls="mobile-menu">
|
| 48 |
+
<span></span><span></span>
|
| 49 |
+
</button>
|
| 50 |
+
</div>
|
| 51 |
+
</div>
|
| 52 |
+
<div class="mobile-menu" id="mobile-menu" hidden>
|
| 53 |
+
<a href="#offerings">What we provide</a>
|
| 54 |
+
<a href="#examples">Examples</a>
|
| 55 |
+
<a href="#pipeline">How it works</a>
|
| 56 |
+
<a href="#trajectories">Trajectories</a>
|
| 57 |
+
<a href="#research">Research</a>
|
| 58 |
+
<a class="btn btn-dark" href="#contact">Start a pilot</a>
|
| 59 |
+
</div>
|
| 60 |
+
</header>
|
| 61 |
+
|
| 62 |
+
<main id="main">
|
| 63 |
+
<section class="hero" id="top" aria-labelledby="hero-title">
|
| 64 |
+
<canvas class="hero-canvas" aria-hidden="true"></canvas>
|
| 65 |
+
<div class="hero-glow" aria-hidden="true"></div>
|
| 66 |
+
<div class="container hero-inner">
|
| 67 |
+
<div class="hero-copy">
|
| 68 |
+
<p class="eyebrow"><span class="pulse-dot" aria-hidden="true"></span>Terminal · Coding · Multimodal</p>
|
| 69 |
+
<h1 id="hero-title">Agent training data that <mark>proves itself</mark>.</h1>
|
| 70 |
+
<p class="lede">We provide terminal, coding, and multimodal training data for agents. Every task ships with its own reference solution and executable verifier, and every trajectory is verified and rewritten into one consistent harness, calibrated to the difficulty your model needs next.</p>
|
| 71 |
+
<div class="hero-actions">
|
| 72 |
+
<a class="btn btn-dark" href="#contact">Start a pilot
|
| 73 |
+
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h11m-4-4 4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 74 |
+
</a>
|
| 75 |
+
<a class="btn btn-ghost" href="#examples">See examples</a>
|
| 76 |
+
</div>
|
| 77 |
+
<ul class="hero-proof">
|
| 78 |
+
<li><svg viewBox="0 0 20 20" aria-hidden="true"><path d="m5 10.5 3 3 7-7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>Verified by execution</li>
|
| 79 |
+
<li><svg viewBox="0 0 20 20" aria-hidden="true"><path d="m5 10.5 3 3 7-7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>Calibrated to your checkpoint</li>
|
| 80 |
+
<li><svg viewBox="0 0 20 20" aria-hidden="true"><path d="m5 10.5 3 3 7-7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>Fresh every month</li>
|
| 81 |
+
</ul>
|
| 82 |
+
</div>
|
| 83 |
+
</div>
|
| 84 |
+
<ol class="tier-badges" aria-label="Difficulty tiers">
|
| 85 |
+
<li style="--tier:#14b88a"><span class="tier-num">T1</span>Warm-up</li>
|
| 86 |
+
<li style="--tier:#0da5a0"><span class="tier-num">T2</span>Core</li>
|
| 87 |
+
<li style="--tier:#258cd6"><span class="tier-num">T3</span>Hard</li>
|
| 88 |
+
<li style="--tier:#5865e2"><span class="tier-num">T4</span>Expert</li>
|
| 89 |
+
<li style="--tier:#7c5cdc"><span class="tier-num">T5</span>Frontier</li>
|
| 90 |
+
</ol>
|
| 91 |
+
</section>
|
| 92 |
+
|
| 93 |
+
<section class="marquee" aria-label="Software and formats our tasks run on">
|
| 94 |
+
<p class="marquee-title">Tasks run on the software practitioners actually use</p>
|
| 95 |
+
<div class="marquee-track">
|
| 96 |
+
<ul>
|
| 97 |
+
<li>CadQuery</li><li>OpenSCAD</li><li>FreeCAD</li><li>KiCad</li><li>Blender</li><li>OpenFOAM</li><li>MuJoCo</li><li>URDF</li><li>Tesseract</li><li>Coq</li><li>CMake</li><li>Git</li><li>Docker</li><li>Nuxt</li><li>Vue</li><li>Flask</li><li>SQLite</li><li>STEP</li>
|
| 98 |
+
</ul>
|
| 99 |
+
<ul aria-hidden="true">
|
| 100 |
+
<li>CadQuery</li><li>OpenSCAD</li><li>FreeCAD</li><li>KiCad</li><li>Blender</li><li>OpenFOAM</li><li>MuJoCo</li><li>URDF</li><li>Tesseract</li><li>Coq</li><li>CMake</li><li>Git</li><li>Docker</li><li>Nuxt</li><li>Vue</li><li>Flask</li><li>SQLite</li><li>STEP</li>
|
| 101 |
+
</ul>
|
| 102 |
+
</div>
|
| 103 |
+
</section>
|
| 104 |
+
|
| 105 |
+
<section class="section" id="offerings" aria-labelledby="offer-title">
|
| 106 |
+
<div class="container">
|
| 107 |
+
<div class="section-head reveal">
|
| 108 |
+
<p class="kicker">What we provide</p>
|
| 109 |
+
<h2 id="offer-title">Terminal, coding, and multimodal data.</h2>
|
| 110 |
+
<p class="sub">Terminal work is coding work: to finish a terminal task, the agent writes, runs, tests, and debugs real programs. The same verified environments extend to visual inputs, from engineering drawings to rendered pages.</p>
|
| 111 |
+
</div>
|
| 112 |
+
<div class="offer-grid">
|
| 113 |
+
<article class="offer-card reveal">
|
| 114 |
+
<div class="offer-top offer-terminal" aria-hidden="true">
|
| 115 |
+
<span><b>$</b> make -C services/ingest</span>
|
| 116 |
+
<span class="dim"> built ingest-worker</span>
|
| 117 |
+
<span><b>$</b> ./bin/migrate --apply v15.yaml</span>
|
| 118 |
+
<span><b>$</b> ./bin/replay --since 02:00</span>
|
| 119 |
+
<span class="ok">✓ end state verified</span>
|
| 120 |
+
</div>
|
| 121 |
+
<h3>Terminal</h3>
|
| 122 |
+
<p>Long-horizon command-line work across real tools, services, builds, and data: hundreds of commands toward one verified end state.</p>
|
| 123 |
+
<ul class="offer-list">
|
| 124 |
+
<li>Ops, data, build & release workflows</li>
|
| 125 |
+
<li>Scientific & engineering toolchains</li>
|
| 126 |
+
<li>RL environments with executable verifiers</li>
|
| 127 |
+
</ul>
|
| 128 |
+
</article>
|
| 129 |
+
<article class="offer-card reveal">
|
| 130 |
+
<div class="offer-top offer-code" aria-hidden="true">
|
| 131 |
+
<span><i class="c-k">def</i> reconstruct(scenario):</span>
|
| 132 |
+
<span> duct = sweep(scenario[<i class="c-s">"inlet_size"</i>],</span>
|
| 133 |
+
<span> scenario[<i class="c-s">"outlet_size"</i>],</span>
|
| 134 |
+
<span> bend=scenario[<i class="c-s">"bend_angle"</i>])</span>
|
| 135 |
+
<span> <i class="c-k">return</i> add_ribs(duct, scenario[<i class="c-s">"rib_count"</i>])</span>
|
| 136 |
+
</div>
|
| 137 |
+
<h3>Coding</h3>
|
| 138 |
+
<p>Every terminal task is a coding task. Agents write, test, and debug real programs, from rebuilding scientific software to shipping full-stack apps.</p>
|
| 139 |
+
<ul class="offer-list">
|
| 140 |
+
<li>Software reconstruction from real program behavior</li>
|
| 141 |
+
<li>Repository repair & feature work</li>
|
| 142 |
+
<li>Full-stack apps verified in a browser</li>
|
| 143 |
+
</ul>
|
| 144 |
+
</article>
|
| 145 |
+
<article class="offer-card reveal">
|
| 146 |
+
<div class="offer-top offer-visual" aria-hidden="true">
|
| 147 |
+
<img src="assets/examples/stl-thumb.webp" alt="" width="740" height="394" loading="lazy">
|
| 148 |
+
</div>
|
| 149 |
+
<h3>Multimodal</h3>
|
| 150 |
+
<p>Visual inputs, code outputs: engineering drawings, renders, screenshots, meshes, and scientific images.</p>
|
| 151 |
+
<ul class="offer-list">
|
| 152 |
+
<li>CAD from engineering drawings</li>
|
| 153 |
+
<li>Web pages and apps from designs</li>
|
| 154 |
+
<li>Charts, SVG & documents to code</li>
|
| 155 |
+
</ul>
|
| 156 |
+
</article>
|
| 157 |
+
</div>
|
| 158 |
+
<div class="offer-band reveal">
|
| 159 |
+
<span>Every task ships with</span>
|
| 160 |
+
<ul>
|
| 161 |
+
<li>Reference solution</li>
|
| 162 |
+
<li>Executable verifier</li>
|
| 163 |
+
<li>Difficulty tier</li>
|
| 164 |
+
<li>Harness-consistent trajectories</li>
|
| 165 |
+
</ul>
|
| 166 |
+
</div>
|
| 167 |
+
</div>
|
| 168 |
+
</section>
|
| 169 |
+
|
| 170 |
+
<section class="section section-tint" id="examples" aria-labelledby="ex-title">
|
| 171 |
+
<div class="container">
|
| 172 |
+
<div class="section-head reveal">
|
| 173 |
+
<p class="kicker">Examples</p>
|
| 174 |
+
<h2 id="ex-title">Watch real software run. Rebuild its behavior.</h2>
|
| 175 |
+
<p class="sub">A sample of our software-reconstruction tasks. The agent sees public runs of real scientific and engineering software, writes a program that reproduces it, and is graded on hidden configurations it never saw. Every visual is rendered from the task's own files.</p>
|
| 176 |
+
</div>
|
| 177 |
+
<div class="ex-grid" id="ex-grid">
|
| 178 |
+
<!--EXAMPLES_CARDS:START-->
|
| 179 |
+
<article class="ex-card reveal" data-index="0" data-kind="stl" tabindex="0" role="button" aria-label="Open example: OpenSCAD / BOSL2 parametric fan duct" style="--dc:#7c3aed">
|
| 180 |
+
<div class="ex-thumb"><img src="assets/examples/stl-thumb.webp" alt="Rendered fan-duct mesh from a public OpenSCAD run" width="740" height="394" loading="lazy"></div>
|
| 181 |
+
<div class="ex-card-body">
|
| 182 |
+
<p class="ex-card-domain">Spatial, Visual & 3D</p>
|
| 183 |
+
<h3>OpenSCAD / BOSL2 parametric fan duct</h3>
|
| 184 |
+
<p>Regenerate a swept fan-duct mount STL whose inlet size, outlet size, bend angle, and rib count change the geometry.</p>
|
| 185 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">3D mesh</li></ul>
|
| 186 |
+
<ul class="ex-sw"><li>OpenSCAD</li><li>BOSL2</li></ul>
|
| 187 |
+
</div>
|
| 188 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 189 |
+
</article>
|
| 190 |
+
<article class="ex-card reveal" data-index="1" data-kind="foam" tabindex="0" role="button" aria-label="Open example: OpenFOAM 2-D dam-break CFD" style="--dc:#0891b2">
|
| 191 |
+
<div class="ex-thumb"><img src="assets/examples/foam-thumb.webp" alt="OpenFOAM dam-break mesh drawn from the public polyMesh" width="740" height="394" loading="lazy"></div>
|
| 192 |
+
<div class="ex-card-body">
|
| 193 |
+
<p class="ex-card-domain">Physical & Engineering Simulation</p>
|
| 194 |
+
<h3>OpenFOAM 2-D dam-break CFD</h3>
|
| 195 |
+
<p>Reconstruct a 2-D dam-break CFD workflow across water height, mesh, gravity, and simulation time.</p>
|
| 196 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">CFD mesh</li></ul>
|
| 197 |
+
<ul class="ex-sw"><li>OpenFOAM</li></ul>
|
| 198 |
+
</div>
|
| 199 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 200 |
+
</article>
|
| 201 |
+
<article class="ex-card reveal" data-index="2" data-kind="drc" tabindex="0" role="button" aria-label="Open example: KiCad LED-matrix driver PCB" style="--dc:#7c3aed">
|
| 202 |
+
<div class="ex-thumb"><img src="assets/examples/drc-thumb.webp" alt="KiCad board with design-rule findings plotted at their positions" width="740" height="394" loading="lazy"></div>
|
| 203 |
+
<div class="ex-card-body">
|
| 204 |
+
<p class="ex-card-domain">Spatial, Visual & 3D</p>
|
| 205 |
+
<h3>KiCad LED-matrix driver PCB</h3>
|
| 206 |
+
<p>Reconstruct LED-matrix driver board outputs (DRC report and project files) under row, column, driver, and routing interventions.</p>
|
| 207 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">PCB layout</li></ul>
|
| 208 |
+
<ul class="ex-sw"><li>KiCad</li></ul>
|
| 209 |
+
</div>
|
| 210 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 211 |
+
</article>
|
| 212 |
+
<article class="ex-card reveal" data-index="3" data-kind="container" tabindex="0" role="button" aria-label="Open example: Container SBOM and supply-chain attestation" style="--dc:#2563eb">
|
| 213 |
+
<div class="ex-thumb"><img src="assets/examples/container-thumb.webp" alt="Container image layers and attestation from a public run" width="740" height="394" loading="lazy"></div>
|
| 214 |
+
<div class="ex-card-body">
|
| 215 |
+
<p class="ex-card-domain">Software & Formal Systems</p>
|
| 216 |
+
<h3>Container SBOM and supply-chain attestation</h3>
|
| 217 |
+
<p>Infer coupled container base-image, package-set, label, entrypoint, and SBOM-scope behavior.</p>
|
| 218 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li></ul>
|
| 219 |
+
<ul class="ex-sw"><li>Hadolint</li><li>Syft</li><li>Skopeo</li></ul>
|
| 220 |
+
</div>
|
| 221 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 222 |
+
</article>
|
| 223 |
+
<article class="ex-card reveal" data-index="4" data-kind="blender" tabindex="0" role="button" aria-label="Open example: Blender cloth flag scene" style="--dc:#7c3aed">
|
| 224 |
+
<div class="ex-thumb"><img src="assets/examples/blender-thumb.webp" alt="Blender cloth scene rotation dial across public scenarios" width="740" height="394" loading="lazy"></div>
|
| 225 |
+
<div class="ex-card-body">
|
| 226 |
+
<p class="ex-card-domain">Spatial, Visual & 3D</p>
|
| 227 |
+
<h3>Blender cloth flag scene</h3>
|
| 228 |
+
<p>Reconstruct cloth-scene behavior under wind, pin-group, frame, and subdivision interventions.</p>
|
| 229 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">3D scene</li></ul>
|
| 230 |
+
<ul class="ex-sw"><li>Blender</li></ul>
|
| 231 |
+
</div>
|
| 232 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 233 |
+
</article>
|
| 234 |
+
<article class="ex-card reveal" data-index="5" data-kind="robot" tabindex="0" role="button" aria-label="Open example: MuJoCo / URDF mass-inertia repair" style="--dc:#0891b2">
|
| 235 |
+
<div class="ex-thumb"><img src="assets/examples/robot-thumb.webp" alt="MuJoCo joint-position trajectories across public scenarios" width="740" height="394" loading="lazy"></div>
|
| 236 |
+
<div class="ex-card-body">
|
| 237 |
+
<p class="ex-card-domain">Physical & Engineering Simulation</p>
|
| 238 |
+
<h3>MuJoCo / URDF mass-inertia repair</h3>
|
| 239 |
+
<p>Infer robot state and trajectory behavior under actuator, collision, pose, joint-limit, and target interventions.</p>
|
| 240 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li></ul>
|
| 241 |
+
<ul class="ex-sw"><li>MuJoCo</li><li>URDF/MJCF tooling</li></ul>
|
| 242 |
+
</div>
|
| 243 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 244 |
+
</article>
|
| 245 |
+
<article class="ex-card reveal is-extra" data-index="6" data-kind="micro" tabindex="0" role="button" aria-label="Open example: Microscopy cell segmentation and counting" style="--dc:#16a34a">
|
| 246 |
+
<div class="ex-thumb"><img src="assets/examples/micro-thumb.webp" alt="Microscopy label masks from public runs" width="740" height="394" loading="lazy"></div>
|
| 247 |
+
<div class="ex-card-body">
|
| 248 |
+
<p class="ex-card-domain">Life & Molecular Sciences</p>
|
| 249 |
+
<h3>Microscopy cell segmentation and counting</h3>
|
| 250 |
+
<p>Reconstruct cell segmentation and measurement behavior across channel, illumination, threshold, object size, and measurement feature.</p>
|
| 251 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">Microscopy images</li></ul>
|
| 252 |
+
<ul class="ex-sw"><li>CellProfiler</li><li>scikit-image</li><li>Bio-Formats</li></ul>
|
| 253 |
+
</div>
|
| 254 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 255 |
+
</article>
|
| 256 |
+
<article class="ex-card reveal is-extra" data-index="7" data-kind="astro" tabindex="0" role="button" aria-label="Open example: Astronomy FITS/WCS cutout and photometry" style="--dc:#db2777">
|
| 257 |
+
<div class="ex-thumb"><img src="assets/examples/astro-thumb.webp" alt="Astronomy FITS cutouts from public runs" width="740" height="394" loading="lazy"></div>
|
| 258 |
+
<div class="ex-card-body">
|
| 259 |
+
<p class="ex-card-domain">Earth & Space Sciences</p>
|
| 260 |
+
<h3>Astronomy FITS/WCS cutout and photometry</h3>
|
| 261 |
+
<p>Reconstruct FITS/WCS cutout and photometry behavior under aperture, background, clipping, threshold, and coordinate-frame interventions.</p>
|
| 262 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">FITS images</li></ul>
|
| 263 |
+
<ul class="ex-sw"><li>Astropy</li><li>Photutils</li></ul>
|
| 264 |
+
</div>
|
| 265 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 266 |
+
</article>
|
| 267 |
+
<article class="ex-card reveal is-extra" data-index="8" data-kind="ocr" tabindex="0" role="button" aria-label="Open example: Tesseract table-image OCR" style="--dc:#d97706">
|
| 268 |
+
<div class="ex-thumb"><img src="assets/examples/ocr-thumb.webp" alt="OCR page preview from a public run" width="740" height="394" loading="lazy"></div>
|
| 269 |
+
<div class="ex-card-body">
|
| 270 |
+
<p class="ex-card-domain">Data & Document Workflows</p>
|
| 271 |
+
<h3>Tesseract table-image OCR</h3>
|
| 272 |
+
<p>Reconstruct how DPI, font, language, metadata, and page range affect OCR behavior.</p>
|
| 273 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">Document images</li></ul>
|
| 274 |
+
<ul class="ex-sw"><li>Pandoc</li><li>Poppler</li><li>Tesseract</li><li>QPDF</li></ul>
|
| 275 |
+
</div>
|
| 276 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 277 |
+
</article>
|
| 278 |
+
<article class="ex-card reveal is-extra" data-index="9" data-kind="color" tabindex="0" role="button" aria-label="Open example: Color-space and tone-curve pipeline" style="--dc:#7c3aed">
|
| 279 |
+
<div class="ex-thumb"><img src="assets/examples/color-thumb.webp" alt="Color-pipeline previews from public runs" width="740" height="394" loading="lazy"></div>
|
| 280 |
+
<div class="ex-card-body">
|
| 281 |
+
<p class="ex-card-domain">Spatial, Visual & 3D</p>
|
| 282 |
+
<h3>Color-space and tone-curve pipeline</h3>
|
| 283 |
+
<p>Infer a color pipeline across color space, white point, tone curve, demosaicing, and compression quality.</p>
|
| 284 |
+
<ul class="ex-card-tracks"><li class="trk trk-terminal">Terminal</li><li class="trk trk-coding">Coding</li><li class="trk trk-multimodal">Multimodal</li><li class="trk trk-mod">Images</li></ul>
|
| 285 |
+
<ul class="ex-sw"><li>colour-science</li><li>ImageMagick</li><li>scikit-image</li></ul>
|
| 286 |
+
</div>
|
| 287 |
+
<span class="ex-open" aria-hidden="true">Explore ↗</span>
|
| 288 |
+
</article>
|
| 289 |
+
<!--EXAMPLES_CARDS:END-->
|
| 290 |
+
</div>
|
| 291 |
+
<div class="ex-more">
|
| 292 |
+
<button class="btn btn-ghost" id="ex-more" type="button" aria-expanded="false">Show more examples</button>
|
| 293 |
+
</div>
|
| 294 |
+
</div>
|
| 295 |
+
</section>
|
| 296 |
+
|
| 297 |
+
<section class="section" id="why" aria-labelledby="why-title">
|
| 298 |
+
<div class="container">
|
| 299 |
+
<div class="section-head reveal">
|
| 300 |
+
<p class="kicker">Why verified synthesis</p>
|
| 301 |
+
<h2 id="why-title">Scale without losing the proof.</h2>
|
| 302 |
+
<p class="sub">Hand-written environments are slow to produce. Prompted generation is fast, but a task can look perfect and be silently broken. We generate aggressively and then try to break every task, so only environments that survive the gates ship.</p>
|
| 303 |
+
</div>
|
| 304 |
+
<div class="grid-4">
|
| 305 |
+
<article class="value-card reveal">
|
| 306 |
+
<div class="icon-tile"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3 4.5 6v5.5c0 4.6 3.1 8.2 7.5 9.5 4.4-1.3 7.5-4.9 7.5-9.5V6L12 3Z" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><path d="m8.8 12.2 2.3 2.3 4.3-4.6" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
|
| 307 |
+
<h3>Verified by execution</h3>
|
| 308 |
+
<p>A task is accepted only if its reference solution passes in a fresh sandbox, a do-nothing agent fails, and every check is stated in the instruction.</p>
|
| 309 |
+
</article>
|
| 310 |
+
<article class="value-card reveal">
|
| 311 |
+
<div class="icon-tile"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 19h4v-4h4v-4h4V7h4" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/><circle cx="20" cy="7" r="1.6" fill="currentColor"/></svg></div>
|
| 312 |
+
<h3>Difficulty you can dial</h3>
|
| 313 |
+
<p>Tasks grow harder round by round. Every task carries a measured tier, so you train on a curriculum instead of a pile.</p>
|
| 314 |
+
</article>
|
| 315 |
+
<article class="value-card reveal">
|
| 316 |
+
<div class="icon-tile"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 12a8 8 0 1 1-2.3-5.6M20 4v4.5h-4.5" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
|
| 317 |
+
<h3>Fresh every month</h3>
|
| 318 |
+
<p>New, never-published environments each cycle, synthesized for you and audited against public benchmark test sets before delivery.</p>
|
| 319 |
+
</article>
|
| 320 |
+
<article class="value-card reveal">
|
| 321 |
+
<div class="icon-tile"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h5c2 0 3 1 4.5 3S16 12 19 12M4 12h15M4 18h5c2 0 3-1 4.5-3S16 12 19 12" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/><circle cx="19.5" cy="12" r="1.6" fill="currentColor"/></svg></div>
|
| 322 |
+
<h3>One consistent harness</h3>
|
| 323 |
+
<p>Passing runs from many harnesses are rewritten into the single harness your model trains and runs under, so it learns the skill, not the scaffolding.</p>
|
| 324 |
+
</article>
|
| 325 |
+
</div>
|
| 326 |
+
</div>
|
| 327 |
+
</section>
|
| 328 |
+
|
| 329 |
+
<section class="section section-tint" id="capabilities" aria-labelledby="cap-title">
|
| 330 |
+
<div class="container">
|
| 331 |
+
<div class="section-head reveal">
|
| 332 |
+
<p class="kicker">Capabilities</p>
|
| 333 |
+
<h2 id="cap-title">Six task families. One standard of proof.</h2>
|
| 334 |
+
<p class="sub">Each family pairs what the model sees with what it must produce and how we check it. Pick one, or combine them into a single training mix.</p>
|
| 335 |
+
</div>
|
| 336 |
+
|
| 337 |
+
<div class="tabs reveal">
|
| 338 |
+
<div class="tab-list" role="tablist" aria-label="Task families">
|
| 339 |
+
<button class="tab" role="tab" id="tab-terminal" aria-controls="panel-terminal" aria-selected="true">
|
| 340 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4.5" width="18" height="15" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.7"/><path d="m7 10 3 2.5L7 15m5 0h5" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
| 341 |
+
<span>Terminal & coding agents</span>
|
| 342 |
+
</button>
|
| 343 |
+
<button class="tab" role="tab" id="tab-science" aria-controls="panel-science" aria-selected="false" tabindex="-1">
|
| 344 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9.5 3.5h5M10.5 3.5v6L5 19a1.5 1.5 0 0 0 1.3 2.2h11.4A1.5 1.5 0 0 0 19 19l-5.5-9.5v-6" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/><path d="M7.5 15h9" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg></span>
|
| 345 |
+
<span>Scientific software reconstruction</span>
|
| 346 |
+
</button>
|
| 347 |
+
<button class="tab" role="tab" id="tab-cad" aria-controls="panel-cad" aria-selected="false" tabindex="-1">
|
| 348 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m12 3 8 4.5v9L12 21l-8-4.5v-9L12 3Z" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><path d="m4 7.5 8 4.5 8-4.5M12 12v9" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg></span>
|
| 349 |
+
<span>CAD from engineering drawings</span>
|
| 350 |
+
</button>
|
| 351 |
+
<button class="tab" role="tab" id="tab-web" aria-controls="panel-web" aria-selected="false" tabindex="-1">
|
| 352 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.7"/><path d="M3 8.5h18M7 13h4m-4 3h7" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg></span>
|
| 353 |
+
<span>Web & full-stack applications</span>
|
| 354 |
+
</button>
|
| 355 |
+
<button class="tab" role="tab" id="tab-visual" aria-controls="panel-visual" aria-selected="false" tabindex="-1">
|
| 356 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V10m5 10V5m5 15v-7m5 7V8" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg></span>
|
| 357 |
+
<span>Visual-to-code</span>
|
| 358 |
+
</button>
|
| 359 |
+
<button class="tab" role="tab" id="tab-swe" aria-controls="panel-swe" aria-selected="false" tabindex="-1">
|
| 360 |
+
<span class="tab-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m8.5 8-4 4 4 4m7-8 4 4-4 4M13.5 5l-3 14" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
| 361 |
+
<span>Multimodal software engineering</span>
|
| 362 |
+
</button>
|
| 363 |
+
</div>
|
| 364 |
+
|
| 365 |
+
<div class="tab-panels">
|
| 366 |
+
<div class="tab-panel is-active" role="tabpanel" id="panel-terminal" aria-labelledby="tab-terminal" tabindex="0">
|
| 367 |
+
<div class="panel-copy">
|
| 368 |
+
<h3>Terminal & coding agents</h3>
|
| 369 |
+
<p>Multi-hour workflows where the agent explores a real environment, writes and runs programs, and checks its own work. Terminal tasks are coding tasks.</p>
|
| 370 |
+
<dl class="spec">
|
| 371 |
+
<div><dt>Model sees</dt><dd>A live workspace, an instruction, and the tools a practitioner would reach for.</dd></div>
|
| 372 |
+
<div><dt>Model produces</dt><dd>Working code and a verified end state after hundreds of commands: rebuilt programs, migrated services, repaired builds.</dd></div>
|
| 373 |
+
<div><dt>We verify</dt><dd>Artifacts and system state, with checks that reject placeholders, hard-coded outputs, and skipped steps.</dd></div>
|
| 374 |
+
</dl>
|
| 375 |
+
</div>
|
| 376 |
+
<div class="panel-visual">
|
| 377 |
+
<div class="mock mock-terminal">
|
| 378 |
+
<div class="mock-bar dark"><i></i><i></i><i></i><em>agent@sandbox:/app</em></div>
|
| 379 |
+
<pre class="term"><code><span class="t-line" style="--i:0"><b>$</b> jq -c .axes_to_vary observations/manifest.json</span>
|
| 380 |
+
<span class="t-line t-dim" style="--i:1">["inlet_size","outlet_size","bend_angle","rib_count"]</span>
|
| 381 |
+
<span class="t-line" style="--i:2"><b>$</b> ls /tmp/obs/public_1/native</span>
|
| 382 |
+
<span class="t-line t-dim" style="--i:3">metrics.json product.stl</span>
|
| 383 |
+
<span class="t-line" style="--i:4"><b>$</b> jq -c .parameters /tmp/obs/public_1/scenario.json</span>
|
| 384 |
+
<span class="t-line t-dim" style="--i:5">{"bend_angle":238,"inlet_size":11.15,"rib_count":5}</span>
|
| 385 |
+
<span class="t-line" style="--i:6"><b>$</b> python3 workspace/reconstruct.py < hidden.json</span>
|
| 386 |
+
<span class="t-line t-verify" style="--i:7">verifier ▸ hidden configurations vs. real OpenSCAD</span>
|
| 387 |
+
<span class="t-line t-ok" style="--i:8">✓ geometry matches on every hidden scenario</span></code></pre>
|
| 388 |
+
</div>
|
| 389 |
+
</div>
|
| 390 |
+
</div>
|
| 391 |
+
|
| 392 |
+
<div class="tab-panel" role="tabpanel" id="panel-science" aria-labelledby="tab-science" tabindex="0" hidden>
|
| 393 |
+
<div class="panel-copy">
|
| 394 |
+
<h3>Scientific software reconstruction</h3>
|
| 395 |
+
<p>Real scientific and engineering software becomes the reference solution. The model sees how it behaves and must rebuild that behavior without its source.</p>
|
| 396 |
+
<dl class="spec">
|
| 397 |
+
<div><dt>Model sees</dt><dd>Public runs of real software: parameters plus native outputs such as tables, meshes, waveforms, images, and sequences.</dd></div>
|
| 398 |
+
<div><dt>Model produces</dt><dd>An editable program that reproduces the software's behavior across its inputs.</dd></div>
|
| 399 |
+
<div><dt>We verify</dt><dd>On hidden configurations the model never saw, with domain-aware comparison, so replaying public outputs never passes.</dd></div>
|
| 400 |
+
</dl>
|
| 401 |
+
<ul class="chip-row" aria-label="Domains">
|
| 402 |
+
<li>Physical & engineering simulation</li><li>Life & molecular science</li><li>Earth & space</li><li>Spatial & 3D</li><li>Data & documents</li><li>Software & formal systems</li>
|
| 403 |
+
</ul>
|
| 404 |
+
</div>
|
| 405 |
+
<div class="panel-visual">
|
| 406 |
+
<div class="mock mock-plot">
|
| 407 |
+
<div class="mock-bar"><i></i><i></i><i></i><em>public runs vs hidden configuration</em></div>
|
| 408 |
+
<svg viewBox="0 0 360 210" role="img" aria-label="Two public runs and a hidden configuration matched by the reconstructed program">
|
| 409 |
+
<line x1="36" y1="186" x2="340" y2="186" class="axis"/>
|
| 410 |
+
<line x1="36" y1="22" x2="36" y2="186" class="axis"/>
|
| 411 |
+
<path class="wave wave-a" data-wave="58 0.9 6 0"/>
|
| 412 |
+
<path class="wave wave-b" data-wave="44 0.7 8 0.4"/>
|
| 413 |
+
<path class="wave wave-hidden" data-wave="66 0.5 10 0.9"/>
|
| 414 |
+
<path class="wave wave-recon" data-wave="66 0.5 10 0.9"/>
|
| 415 |
+
<g class="legend">
|
| 416 |
+
<rect x="210" y="16" width="10" height="3" rx="1.5" class="lg-a"/><text x="226" y="20">public · gain 0.4</text>
|
| 417 |
+
<rect x="210" y="30" width="10" height="3" rx="1.5" class="lg-b"/><text x="226" y="34">public · gain 0.8</text>
|
| 418 |
+
<rect x="210" y="44" width="10" height="3" rx="1.5" class="lg-h"/><text x="226" y="48">hidden · gain 1.3</text>
|
| 419 |
+
</g>
|
| 420 |
+
</svg>
|
| 421 |
+
<span class="mock-chip ok">✓ hidden configuration reproduced</span>
|
| 422 |
+
</div>
|
| 423 |
+
</div>
|
| 424 |
+
</div>
|
| 425 |
+
|
| 426 |
+
<div class="tab-panel" role="tabpanel" id="panel-cad" aria-labelledby="tab-cad" tabindex="0" hidden>
|
| 427 |
+
<div class="panel-copy">
|
| 428 |
+
<h3>CAD from engineering drawings</h3>
|
| 429 |
+
<p>Turn a dimensioned drawing or multi-view renders into parametric CAD code that builds the right solid.</p>
|
| 430 |
+
<dl class="spec">
|
| 431 |
+
<div><dt>Model sees</dt><dd>An engineering drawing or multi-view renders, with as much or as little supplied dimensioning as the tier calls for.</dd></div>
|
| 432 |
+
<div><dt>Model produces</dt><dd>A CadQuery, OpenSCAD, or FreeCAD program and the watertight solid it builds.</dd></div>
|
| 433 |
+
<div><dt>We verify</dt><dd>Geometry, not code: a fresh rebuild is compared on bounds, volume, surface area, and probes inside every hole and profile.</dd></div>
|
| 434 |
+
</dl>
|
| 435 |
+
</div>
|
| 436 |
+
<div class="panel-visual">
|
| 437 |
+
<div class="mock mock-cad">
|
| 438 |
+
<svg viewBox="0 0 360 230" role="img" aria-label="Engineering drawing of an L-bracket with dimensions and a section view">
|
| 439 |
+
<defs>
|
| 440 |
+
<pattern id="hatch" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" class="hatch-line"/></pattern>
|
| 441 |
+
<marker id="arr" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto-start-reverse" markerUnits="userSpaceOnUse"><path d="M0 0 8 4 0 8z" class="arrow"/></marker>
|
| 442 |
+
</defs>
|
| 443 |
+
<rect x="0.5" y="0.5" width="359" height="229" rx="10" class="paper"/>
|
| 444 |
+
<path class="draw part" pathLength="1" d="M40 52H170V84H96V182H40Z"/>
|
| 445 |
+
<circle class="draw part" pathLength="1" cx="68" cy="150" r="11"/>
|
| 446 |
+
<circle class="draw part" pathLength="1" cx="140" cy="68" r="7"/>
|
| 447 |
+
<path class="center" d="M52 150h32M68 134v32M128 68h24M140 56v24"/>
|
| 448 |
+
<path class="dim" d="M40 48V30M170 48V30M36 52H18M36 182H18"/>
|
| 449 |
+
<line class="dim" x1="40" y1="36" x2="170" y2="36" marker-start="url(#arr)" marker-end="url(#arr)"/>
|
| 450 |
+
<line class="dim" x1="24" y1="52" x2="24" y2="182" marker-start="url(#arr)" marker-end="url(#arr)"/>
|
| 451 |
+
<text x="105" y="30" class="dim-text" text-anchor="middle">130</text>
|
| 452 |
+
<text x="16" y="120" class="dim-text" text-anchor="middle" transform="rotate(-90 16 120)">130</text>
|
| 453 |
+
<path class="dim" d="M76 142 104 124H130"/>
|
| 454 |
+
<text x="106" y="119" class="dim-text">Ø22 THRU</text>
|
| 455 |
+
<rect x="214" y="52" width="38" height="130" class="cad-section"/>
|
| 456 |
+
<path class="hidden-line" d="M214 139h38M214 161h38"/>
|
| 457 |
+
<text x="233" y="200" class="label" text-anchor="middle">SECTION A–A</text>
|
| 458 |
+
<g class="title-block">
|
| 459 |
+
<rect x="270" y="150" width="78" height="66" rx="3"/>
|
| 460 |
+
<path d="M270 172h78M270 194h78M309 194v22"/>
|
| 461 |
+
<text x="309" y="165" text-anchor="middle">BRACKET</text>
|
| 462 |
+
<text x="309" y="187" text-anchor="middle">mm · 1:2</text>
|
| 463 |
+
<text x="289" y="209" text-anchor="middle">REV B</text>
|
| 464 |
+
<text x="328" y="209" text-anchor="middle">A3</text>
|
| 465 |
+
</g>
|
| 466 |
+
</svg>
|
| 467 |
+
<span class="mock-chip ok">✓ rebuilt solid matches geometry</span>
|
| 468 |
+
</div>
|
| 469 |
+
</div>
|
| 470 |
+
</div>
|
| 471 |
+
|
| 472 |
+
<div class="tab-panel" role="tabpanel" id="panel-web" aria-labelledby="tab-web" tabindex="0" hidden>
|
| 473 |
+
<div class="panel-copy">
|
| 474 |
+
<h3>Web & full-stack applications</h3>
|
| 475 |
+
<p>From a design, a specification, or a legacy desktop app to a running web product with real persistence.</p>
|
| 476 |
+
<dl class="spec">
|
| 477 |
+
<div><dt>Model sees</dt><dd>Requirements, design references, legacy applications, or an existing codebase.</dd></div>
|
| 478 |
+
<div><dt>Model produces</dt><dd>Running frontends and full-stack services: routes, APIs, state, and storage.</dd></div>
|
| 479 |
+
<div><dt>We verify</dt><dd>Headless-browser tests across routes and viewports, API contracts, restart persistence, and rendered-page comparison against the design.</dd></div>
|
| 480 |
+
</dl>
|
| 481 |
+
</div>
|
| 482 |
+
<div class="panel-visual">
|
| 483 |
+
<div class="mock mock-browser">
|
| 484 |
+
<div class="mock-bar"><i></i><i></i><i></i><span class="url">localhost:8080/dispatch</span></div>
|
| 485 |
+
<div class="browser-body">
|
| 486 |
+
<div class="sk-head"><span class="sk-logo"></span><span class="sk-pill"></span><span class="sk-pill"></span><span class="sk-pill short"></span></div>
|
| 487 |
+
<div class="sk-grid">
|
| 488 |
+
<div class="sk-side"><span></span><span></span><span></span><span class="short"></span></div>
|
| 489 |
+
<div class="sk-main">
|
| 490 |
+
<div class="sk-row head"></div><div class="sk-row"></div><div class="sk-row"></div><div class="sk-row"></div><div class="sk-row short"></div>
|
| 491 |
+
</div>
|
| 492 |
+
</div>
|
| 493 |
+
<ul class="checklist">
|
| 494 |
+
<li>All routes render at mobile and desktop widths</li>
|
| 495 |
+
<li>API contract and validation rules hold</li>
|
| 496 |
+
<li>State survives a full restart</li>
|
| 497 |
+
<li>Rendered page matches the design</li>
|
| 498 |
+
</ul>
|
| 499 |
+
</div>
|
| 500 |
+
</div>
|
| 501 |
+
</div>
|
| 502 |
+
</div>
|
| 503 |
+
|
| 504 |
+
<div class="tab-panel" role="tabpanel" id="panel-visual" aria-labelledby="tab-visual" tabindex="0" hidden>
|
| 505 |
+
<div class="panel-copy">
|
| 506 |
+
<h3>Visual-to-code</h3>
|
| 507 |
+
<p>Charts, diagrams, vector graphics, and documents rebuilt as code that re-renders them, and keeps working when the data changes.</p>
|
| 508 |
+
<dl class="spec">
|
| 509 |
+
<div><dt>Model sees</dt><dd>A chart, diagram, SVG, or document page, optionally with the underlying data.</dd></div>
|
| 510 |
+
<div><dt>Model produces</dt><dd>Plotting code, SVG, or LaTeX that regenerates the image.</dd></div>
|
| 511 |
+
<div><dt>We verify</dt><dd>Re-render and compare structure and pixels, then re-run on hidden data variations so that copying one image never passes.</dd></div>
|
| 512 |
+
</dl>
|
| 513 |
+
</div>
|
| 514 |
+
<div class="panel-visual">
|
| 515 |
+
<div class="mock mock-split">
|
| 516 |
+
<div class="split-chart">
|
| 517 |
+
<svg viewBox="0 0 200 150" role="img" aria-label="Bar chart with a trend line">
|
| 518 |
+
<line x1="18" y1="132" x2="192" y2="132" class="axis"/>
|
| 519 |
+
<rect x="28" y="88" width="18" height="44" rx="3" class="bar-a"/>
|
| 520 |
+
<rect x="56" y="70" width="18" height="62" rx="3" class="bar-a"/>
|
| 521 |
+
<rect x="84" y="78" width="18" height="54" rx="3" class="bar-a"/>
|
| 522 |
+
<rect x="112" y="52" width="18" height="80" rx="3" class="bar-b"/>
|
| 523 |
+
<rect x="140" y="40" width="18" height="92" rx="3" class="bar-b"/>
|
| 524 |
+
<rect x="168" y="26" width="18" height="106" rx="3" class="bar-b"/>
|
| 525 |
+
<path d="M37 80 65 64 93 70 121 44 149 32 177 18" class="trend"/>
|
| 526 |
+
</svg>
|
| 527 |
+
</div>
|
| 528 |
+
<pre class="split-code"><code><span class="c-k">import</span> matplotlib.pyplot <span class="c-k">as</span> plt
|
| 529 |
+
fig, ax = plt.subplots()
|
| 530 |
+
ax.bar(q, revenue, color=c)
|
| 531 |
+
ax.plot(q, trend, marker=<span class="c-s">"o"</span>)
|
| 532 |
+
ax.set_ylim(<span class="c-n">0</span>, <span class="c-n">120</span>)
|
| 533 |
+
fig.savefig(out, dpi=<span class="c-n">200</span>)</code></pre>
|
| 534 |
+
<span class="mock-chip ok">✓ re-render match · ✓ hidden data variant</span>
|
| 535 |
+
</div>
|
| 536 |
+
</div>
|
| 537 |
+
</div>
|
| 538 |
+
|
| 539 |
+
<div class="tab-panel" role="tabpanel" id="panel-swe" aria-labelledby="tab-swe" tabindex="0" hidden>
|
| 540 |
+
<div class="panel-copy">
|
| 541 |
+
<h3>Multimodal software engineering</h3>
|
| 542 |
+
<p>Fix what users can see. Visual bug reports inside real repositories, resolved with patches that hold up in a browser.</p>
|
| 543 |
+
<dl class="spec">
|
| 544 |
+
<div><dt>Model sees</dt><dd>Bug reports with screenshots and screen recordings, plus the full repository.</dd></div>
|
| 545 |
+
<div><dt>Model produces</dt><dd>A patch that fixes the visible behavior without breaking anything else.</dd></div>
|
| 546 |
+
<div><dt>We verify</dt><dd>UI-level tests in a real browser, render diffs, and the project's regression suite.</dd></div>
|
| 547 |
+
</dl>
|
| 548 |
+
</div>
|
| 549 |
+
<div class="panel-visual">
|
| 550 |
+
<div class="mock mock-issue">
|
| 551 |
+
<div class="issue-head"><span class="issue-dot"></span><strong>Menu clips under the hero on narrow screens</strong></div>
|
| 552 |
+
<div class="issue-shot" aria-hidden="true"><span class="shot-nav"></span><span class="shot-menu"></span><span class="shot-hero"></span></div>
|
| 553 |
+
<pre class="diff"><code><span class="d-h">@@ components/NavMenu.vue</span>
|
| 554 |
+
<span class="d-del">- .menu { overflow: hidden; }</span>
|
| 555 |
+
<span class="d-add">+ .menu { overflow: visible; }</span>
|
| 556 |
+
<span class="d-add">+ .menu { z-index: 40; }</span></code></pre>
|
| 557 |
+
<span class="mock-chip ok">✓ UI tests pass · ✓ render diff clean</span>
|
| 558 |
+
</div>
|
| 559 |
+
</div>
|
| 560 |
+
</div>
|
| 561 |
+
</div>
|
| 562 |
+
</div>
|
| 563 |
+
</div>
|
| 564 |
+
</section>
|
| 565 |
+
|
| 566 |
+
<section class="section section-dark" id="pipeline" aria-labelledby="pipe-title">
|
| 567 |
+
<div class="container">
|
| 568 |
+
<div class="section-head reveal">
|
| 569 |
+
<p class="kicker">How it works</p>
|
| 570 |
+
<h2 id="pipe-title">Generate aggressively. Then try to break every task.</h2>
|
| 571 |
+
<p class="sub">Generation is the cheap part. The value is in the gates: a task reaches you only after it survives all of them.</p>
|
| 572 |
+
</div>
|
| 573 |
+
<ol class="pipeline reveal">
|
| 574 |
+
<li style="--d:0">
|
| 575 |
+
<span class="step-dot">1</span>
|
| 576 |
+
<h3>Seed</h3>
|
| 577 |
+
<p>Licensed or authored seed tasks and real software workflows. Never benchmark test sets.</p>
|
| 578 |
+
</li>
|
| 579 |
+
<li style="--d:1">
|
| 580 |
+
<span class="step-dot">2</span>
|
| 581 |
+
<h3>Extend</h3>
|
| 582 |
+
<p>Rewrite operators add tools, services, data, and failure modes. Solution, environment, verifier, and instruction change together.</p>
|
| 583 |
+
</li>
|
| 584 |
+
<li style="--d:2">
|
| 585 |
+
<span class="step-dot">3</span>
|
| 586 |
+
<h3>Verify</h3>
|
| 587 |
+
<p>Fresh-sandbox build. The reference must pass, a do-nothing agent must fail, and every verifier check must be stated in the instruction.</p>
|
| 588 |
+
</li>
|
| 589 |
+
<li style="--d:3">
|
| 590 |
+
<span class="step-dot">4</span>
|
| 591 |
+
<h3>Calibrate</h3>
|
| 592 |
+
<p>Measure pass rates with reference solvers or your checkpoint, and assign every task a difficulty tier.</p>
|
| 593 |
+
</li>
|
| 594 |
+
<li style="--d:4">
|
| 595 |
+
<span class="step-dot">5</span>
|
| 596 |
+
<h3>Deliver</h3>
|
| 597 |
+
<p>Environments, verified trajectories, and a calibration and integrity report for every batch.</p>
|
| 598 |
+
</li>
|
| 599 |
+
</ol>
|
| 600 |
+
<ul class="gate-row reveal" aria-label="Acceptance gates">
|
| 601 |
+
<li>Reference solution passes</li>
|
| 602 |
+
<li>No-op agent fails</li>
|
| 603 |
+
<li>Replay shortcuts fail</li>
|
| 604 |
+
<li>Instruction ↔ verifier consistency</li>
|
| 605 |
+
<li>Leakage & overlap audit</li>
|
| 606 |
+
<li>Sampled human review</li>
|
| 607 |
+
</ul>
|
| 608 |
+
</div>
|
| 609 |
+
</section>
|
| 610 |
+
|
| 611 |
+
<section class="section" id="trajectories" aria-labelledby="traj-title">
|
| 612 |
+
<div class="container traj-grid">
|
| 613 |
+
<div class="traj-copy reveal">
|
| 614 |
+
<p class="kicker">Trajectory scaling</p>
|
| 615 |
+
<h2 id="traj-title">More passing trajectories. One consistent harness.</h2>
|
| 616 |
+
<p class="sub">Hard tasks get solved in different ways under different harnesses, and raw trajectories carry each harness's scaffolding with them. We pool successes across harnesses, then rewrite each one into the single harness your model trains and runs under, so it learns the skill, not the scaffolding.</p>
|
| 617 |
+
<ol class="traj-steps">
|
| 618 |
+
<li><strong>Discover.</strong> Several harnesses attack the same tasks and solve ones no single harness can.</li>
|
| 619 |
+
<li><strong>Plan.</strong> Each success becomes a runbook: end state, milestones, checks, and recovery steps, never the finished answer.</li>
|
| 620 |
+
<li><strong>Screen.</strong> A critic rejects runbooks that leak the verifier or the solution and asks for revisions.</li>
|
| 621 |
+
<li><strong>Re-execute.</strong> The task is solved again in a fresh sandbox under one consistent harness. Only passing, leak-free runs are kept.</li>
|
| 622 |
+
</ol>
|
| 623 |
+
</div>
|
| 624 |
+
<div class="traj-visual reveal">
|
| 625 |
+
<svg class="traj-diagram" viewBox="0 0 640 300" role="img" aria-label="Successes from three harnesses are distilled into runbooks, screened by a critic, and re-executed into many verified trajectories under one harness">
|
| 626 |
+
<defs>
|
| 627 |
+
<marker id="tarrow" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto" markerUnits="userSpaceOnUse"><path d="M0 0 8 4 0 8z" class="t-arrow"/></marker>
|
| 628 |
+
</defs>
|
| 629 |
+
<text x="0" y="22" class="t-stage">Discover</text>
|
| 630 |
+
<text x="232" y="22" class="t-stage">Rewrite</text>
|
| 631 |
+
<text x="560" y="22" class="t-stage">Train</text>
|
| 632 |
+
<g class="t-src">
|
| 633 |
+
<circle cx="138" cy="70" r="5" class="src-a"/><text x="126" y="74" text-anchor="end">General loop</text>
|
| 634 |
+
<circle cx="138" cy="150" r="5" class="src-b"/><text x="126" y="154" text-anchor="end">Stateful workflow</text>
|
| 635 |
+
<circle cx="138" cy="230" r="5" class="src-c"/><text x="126" y="234" text-anchor="end">Self-reflect & retry</text>
|
| 636 |
+
</g>
|
| 637 |
+
<path class="t-lane lane-a" d="M144 70C186 70 198 150 230 150"/>
|
| 638 |
+
<path class="t-lane lane-b" d="M144 150H230"/>
|
| 639 |
+
<path class="t-lane lane-c" d="M144 230C186 230 198 150 230 150"/>
|
| 640 |
+
<g class="t-node"><rect x="232" y="126" width="88" height="48" rx="12"/><text x="276" y="147" text-anchor="middle">Runbook</text><text x="276" y="163" text-anchor="middle" class="t-sub">planner</text></g>
|
| 641 |
+
<g class="t-node"><rect x="340" y="126" width="88" height="48" rx="12"/><text x="384" y="147" text-anchor="middle">Critic</text><text x="384" y="163" text-anchor="middle" class="t-sub">leak screen</text></g>
|
| 642 |
+
<g class="t-node t-node-strong"><rect x="448" y="126" width="96" height="48" rx="12"/><text x="496" y="147" text-anchor="middle">Re-execute</text><text x="496" y="163" text-anchor="middle" class="t-sub">fresh sandbox</text></g>
|
| 643 |
+
<path class="t-link" d="M320 150H336" marker-end="url(#tarrow)"/>
|
| 644 |
+
<path class="t-link" d="M428 150H444" marker-end="url(#tarrow)"/>
|
| 645 |
+
<path class="t-revise" d="M384 124C384 92 276 92 276 122" marker-end="url(#tarrow)"/>
|
| 646 |
+
<text x="330" y="88" text-anchor="middle" class="t-sub">revise</text>
|
| 647 |
+
<path class="t-out" d="M544 150C576 150 584 86 616 86"/>
|
| 648 |
+
<path class="t-out" d="M544 150C576 150 584 118 616 118"/>
|
| 649 |
+
<path class="t-out" d="M544 150H616"/>
|
| 650 |
+
<path class="t-out" d="M544 150C576 150 584 182 616 182"/>
|
| 651 |
+
<path class="t-out" d="M544 150C576 150 584 214 616 214"/>
|
| 652 |
+
<g class="t-ok"><circle cx="622" cy="86" r="5"/><circle cx="622" cy="118" r="5"/><circle cx="622" cy="150" r="5"/><circle cx="622" cy="182" r="5"/><circle cx="622" cy="214" r="5"/></g>
|
| 653 |
+
<text x="582" y="252" text-anchor="middle" class="t-sub">verified runs,</text>
|
| 654 |
+
<text x="582" y="268" text-anchor="middle" class="t-sub">one harness</text>
|
| 655 |
+
</svg>
|
| 656 |
+
<dl class="traj-metrics">
|
| 657 |
+
<div><dt>+34%</dt><dd>more tasks solved by pooling harnesses than by the best single harness</dd></div>
|
| 658 |
+
<div><dt>5.5×</dt><dd>verified training trajectories per successful source run</dd></div>
|
| 659 |
+
<div><dt>57% → 74%</dt><dd>Terminal-Bench 2 pass@3 after training on rewritten trajectories</dd></div>
|
| 660 |
+
<div><dt>+20.8 pts</dt><dd>over fine-tuning directly on the raw successes (Terminal-Bench 2)</dd></div>
|
| 661 |
+
</dl>
|
| 662 |
+
</div>
|
| 663 |
+
</div>
|
| 664 |
+
</section>
|
| 665 |
+
|
| 666 |
+
<section class="section section-tint" id="difficulty" aria-labelledby="diff-title">
|
| 667 |
+
<div class="container diff-grid">
|
| 668 |
+
<div class="diff-copy reveal">
|
| 669 |
+
<p class="kicker">Calibrated difficulty</p>
|
| 670 |
+
<h2 id="diff-title">A curriculum, not a pile.</h2>
|
| 671 |
+
<p class="sub">Each synthesis round makes tasks measurably harder: longer solutions, more tools, more checks. In our runs, a fixed strong solver went from solving 90% of first-round tasks to 2.5% by round fifteen, with no ceiling in sight.</p>
|
| 672 |
+
<p class="sub">We measure your checkpoint on every tier and ship the band where it succeeds sometimes, but not yet reliably. As your model improves, the band moves up with it.</p>
|
| 673 |
+
<div class="slider-card">
|
| 674 |
+
<label for="ladder-strength">Where is your model today?</label>
|
| 675 |
+
<input id="ladder-strength" type="range" min="-3" max="4" step="0.1" value="0" aria-describedby="ladder-readout">
|
| 676 |
+
<div class="slider-ends"><span>Weaker</span><span id="ladder-strength-label">Reference solver</span><span>Stronger</span></div>
|
| 677 |
+
<p class="readout" id="ladder-readout" aria-live="polite"></p>
|
| 678 |
+
</div>
|
| 679 |
+
</div>
|
| 680 |
+
<figure class="chart-card reveal">
|
| 681 |
+
<svg id="ladder-chart" role="img" aria-label="Success rate by synthesis round, with the learning zone between 10 and 50 percent highlighted"></svg>
|
| 682 |
+
<figcaption>
|
| 683 |
+
<span class="legend-item"><i class="lg-zone"></i>Learning zone (10–50% success)</span>
|
| 684 |
+
<span class="legend-item"><i class="lg-bar"></i>Your model (modeled)</span>
|
| 685 |
+
<span class="legend-item"><i class="lg-line"></i>Reference solver</span>
|
| 686 |
+
<span class="legend-item"><i class="lg-dot"></i>Measured reference results (pass@4)</span>
|
| 687 |
+
<span class="note">Illustrative: the curve interpolates measured reference-solver results. Moving the slider shows how the recommended band shifts.</span>
|
| 688 |
+
</figcaption>
|
| 689 |
+
</figure>
|
| 690 |
+
</div>
|
| 691 |
+
</section>
|
| 692 |
+
|
| 693 |
+
<section class="section" id="deliverables" aria-labelledby="deliv-title">
|
| 694 |
+
<div class="container">
|
| 695 |
+
<div class="section-head reveal">
|
| 696 |
+
<p class="kicker">Deliverables</p>
|
| 697 |
+
<h2 id="deliv-title">Everything you need to train on it tomorrow.</h2>
|
| 698 |
+
<p class="sub">Delivered in a reproducible, container-first format that drops into SFT and RL pipelines, with adapters for your stack on request.</p>
|
| 699 |
+
</div>
|
| 700 |
+
<div class="deliv-grid">
|
| 701 |
+
<article class="deliv-card reveal">
|
| 702 |
+
<h3>RL environments</h3>
|
| 703 |
+
<p>Self-contained Docker environments with instruction, executable verifier, reference solution, and metadata, in Harbor task format.</p>
|
| 704 |
+
</article>
|
| 705 |
+
<article class="deliv-card reveal">
|
| 706 |
+
<h3>Verified trajectories</h3>
|
| 707 |
+
<p>Agent runs kept only when they pass the hidden checks, rewritten into one consistent harness, and exported as chat-format JSONL for fine-tuning.</p>
|
| 708 |
+
</article>
|
| 709 |
+
<article class="deliv-card reveal">
|
| 710 |
+
<h3>Calibration report</h3>
|
| 711 |
+
<p>Tier and measured pass rate for every task, against reference solvers or your own checkpoint.</p>
|
| 712 |
+
</article>
|
| 713 |
+
<article class="deliv-card reveal">
|
| 714 |
+
<h3>Integrity report & data card</h3>
|
| 715 |
+
<p>Overlap audit against public benchmark test sets, shortcut controls, and sampled human review, plus the domains, tools, licenses, and known limitations of every batch.</p>
|
| 716 |
+
</article>
|
| 717 |
+
<article class="deliv-card tree-card reveal" aria-label="Example environment bundle">
|
| 718 |
+
<pre class="tree"><code><span class="tr-dir">task/</span>
|
| 719 |
+
├── instruction.md <span class="tr-c"># what the agent sees</span>
|
| 720 |
+
├── task.toml <span class="tr-c"># tier, tags, timeouts</span>
|
| 721 |
+
├── environment/
|
| 722 |
+
│ └── Dockerfile <span class="tr-c"># fresh, pinned sandbox</span>
|
| 723 |
+
├── solution/
|
| 724 |
+
│ └── solve.sh <span class="tr-c"># reference solution</span>
|
| 725 |
+
└── tests/
|
| 726 |
+
└── test_state.py <span class="tr-c"># executable verifier</span>
|
| 727 |
+
<span class="tr-dir">trajectories.jsonl</span> <span class="tr-c"># verified agent runs</span>
|
| 728 |
+
<span class="tr-dir">report.json</span> <span class="tr-c"># calibration + audit</span></code></pre>
|
| 729 |
+
</article>
|
| 730 |
+
</div>
|
| 731 |
+
</div>
|
| 732 |
+
</section>
|
| 733 |
+
|
| 734 |
+
<section class="section section-tint" id="benchmarks" aria-labelledby="bench-title">
|
| 735 |
+
<div class="container">
|
| 736 |
+
<div class="section-head reveal">
|
| 737 |
+
<p class="kicker">Alignment</p>
|
| 738 |
+
<h2 id="bench-title">Built for the skills frontier evaluations measure.</h2>
|
| 739 |
+
<p class="sub">We train skills, not test items. No benchmark test data is used, copied, or derived, and every batch ships with an overlap audit.</p>
|
| 740 |
+
</div>
|
| 741 |
+
<div class="bench-grid">
|
| 742 |
+
<div class="bench-group reveal">
|
| 743 |
+
<h3>Terminal & long-horizon agents</h3>
|
| 744 |
+
<ul class="chip-row"><li>Terminal-Bench 2</li><li>Terminal-Bench 4</li><li>Terminal-Bench Hard</li><li>Long-Horizon Terminal-Bench</li></ul>
|
| 745 |
+
</div>
|
| 746 |
+
<div class="bench-group reveal">
|
| 747 |
+
<h3>Multimodal SWE & web</h3>
|
| 748 |
+
<ul class="chip-row"><li>SWE-bench Multimodal</li><li>Vision2Web</li><li>Interaction2Code</li><li>Design2Code</li></ul>
|
| 749 |
+
</div>
|
| 750 |
+
<div class="bench-group reveal">
|
| 751 |
+
<h3>CAD & visual-to-code</h3>
|
| 752 |
+
<ul class="chip-row"><li>BenchCAD</li><li>Chart2Code</li><li>Image2Struct</li><li>MMSVGBench</li></ul>
|
| 753 |
+
</div>
|
| 754 |
+
</div>
|
| 755 |
+
</div>
|
| 756 |
+
</section>
|
| 757 |
+
|
| 758 |
+
<section class="section" id="research" aria-labelledby="research-title">
|
| 759 |
+
<div class="container">
|
| 760 |
+
<div class="section-head reveal">
|
| 761 |
+
<p class="kicker">Research</p>
|
| 762 |
+
<h2 id="research-title">Proven in our research.</h2>
|
| 763 |
+
<p class="sub">Each method is measured across multiple seeds and against matched-budget baselines.</p>
|
| 764 |
+
</div>
|
| 765 |
+
<div class="research-grid">
|
| 766 |
+
<article class="paper-card reveal">
|
| 767 |
+
<p class="paper-tag">Scientific software</p>
|
| 768 |
+
<h3>Software-in-the-loop reconstruction</h3>
|
| 769 |
+
<p>Existing scientific software becomes both the reference solution and the source of hidden test cases, so verification scales with the software rather than with authoring effort.</p>
|
| 770 |
+
<dl class="metrics">
|
| 771 |
+
<div><dt>+5.6 pts</dt><dd>Terminal-Bench 2 after fine-tuning (47.9% → 53.6%, three seeds)</dd></div>
|
| 772 |
+
<div><dt>#1 of 5</dt><dd>training corpora at a matched token budget, on all four evaluations</dd></div>
|
| 773 |
+
<div><dt>98%</dt><dd>verifier agreement with blinded human review</dd></div>
|
| 774 |
+
</dl>
|
| 775 |
+
</article>
|
| 776 |
+
<article class="paper-card reveal">
|
| 777 |
+
<p class="paper-tag">Task difficulty</p>
|
| 778 |
+
<h3>Recursive verified synthesis</h3>
|
| 779 |
+
<p>Accepted tasks seed the next round. Each round extends the solution, verifier, and instruction together and re-validates the whole task in a fresh sandbox, with no human authoring in the loop.</p>
|
| 780 |
+
<dl class="metrics">
|
| 781 |
+
<div><dt>+10 pts</dt><dd>best fine-tuning gain across Terminal-Bench 2, Terminal-Bench Hard, and LHTB</dd></div>
|
| 782 |
+
<div><dt>+41%</dt><dd>relative gain on Terminal-Bench Hard with agentic PPO</dd></div>
|
| 783 |
+
<div><dt>36×</dt><dd>drop in fixed-solver success from round 1 to 15 (90% → 2.5%), no ceiling observed</dd></div>
|
| 784 |
+
</dl>
|
| 785 |
+
</article>
|
| 786 |
+
<article class="paper-card reveal">
|
| 787 |
+
<p class="paper-tag">Trajectory scaling</p>
|
| 788 |
+
<h3>Recursive self-rewrite</h3>
|
| 789 |
+
<p>Successes discovered under diverse harnesses are rewritten by the same base model into one general harness, with leakage screening and fresh-sandbox re-execution.</p>
|
| 790 |
+
<dl class="metrics">
|
| 791 |
+
<div><dt>74.2%</dt><dd>Terminal-Bench 2 pass@3, up from 57.0%</dd></div>
|
| 792 |
+
<div><dt>6×</dt><dd>Terminal-Bench 4 pass@3, from 1.5% to 9.1%</dd></div>
|
| 793 |
+
<div><dt>+20.8 pts</dt><dd>over direct fine-tuning on the same successes</dd></div>
|
| 794 |
+
</dl>
|
| 795 |
+
</article>
|
| 796 |
+
</div>
|
| 797 |
+
</div>
|
| 798 |
+
</section>
|
| 799 |
+
|
| 800 |
+
<section class="section section-tint" id="engage" aria-labelledby="engage-title">
|
| 801 |
+
<div class="container">
|
| 802 |
+
<div class="section-head reveal">
|
| 803 |
+
<p class="kicker">Working together</p>
|
| 804 |
+
<h2 id="engage-title">Start small. Scale every month.</h2>
|
| 805 |
+
</div>
|
| 806 |
+
<div class="engage-grid">
|
| 807 |
+
<article class="engage-card reveal">
|
| 808 |
+
<span class="engage-num">01</span>
|
| 809 |
+
<h3>Pilot</h3>
|
| 810 |
+
<p>A calibrated sample batch in your format, measured on your checkpoint, for the task families that matter most to you.</p>
|
| 811 |
+
</article>
|
| 812 |
+
<article class="engage-card reveal">
|
| 813 |
+
<span class="engage-num">02</span>
|
| 814 |
+
<h3>Monthly refresh</h3>
|
| 815 |
+
<p>Fresh, never-published environments every month at the tiers you choose. Difficulty moves up as your model improves.</p>
|
| 816 |
+
</article>
|
| 817 |
+
<article class="engage-card reveal">
|
| 818 |
+
<span class="engage-num">03</span>
|
| 819 |
+
<h3>Custom & exclusive</h3>
|
| 820 |
+
<p>New domains, software stacks, and modalities built for your team alone, on your timeline.</p>
|
| 821 |
+
</article>
|
| 822 |
+
</div>
|
| 823 |
+
</div>
|
| 824 |
+
</section>
|
| 825 |
+
|
| 826 |
+
<section class="cta" id="contact" aria-labelledby="cta-title">
|
| 827 |
+
<div class="container cta-inner reveal">
|
| 828 |
+
<h2 id="cta-title">Tell us what your next checkpoint needs to learn.</h2>
|
| 829 |
+
<p>We'll come back with a pilot plan: task families, difficulty tiers, delivery format, and a calibration run on your model.</p>
|
| 830 |
+
<div class="hero-actions center">
|
| 831 |
+
<a class="btn btn-light" data-contact data-subject="Pilot inquiry" href="#contact">Email us
|
| 832 |
+
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h11m-4-4 4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 833 |
+
</a>
|
| 834 |
+
<a class="btn btn-outline-light" href="#capabilities">Explore capabilities</a>
|
| 835 |
+
</div>
|
| 836 |
+
</div>
|
| 837 |
+
</section>
|
| 838 |
+
</main>
|
| 839 |
+
|
| 840 |
+
<footer class="footer">
|
| 841 |
+
<div class="container footer-inner">
|
| 842 |
+
<a class="brand" href="#top" aria-label="IntelligenceLab home">
|
| 843 |
+
<svg class="brand-mark" viewBox="0 0 32 32" aria-hidden="true">
|
| 844 |
+
<rect width="32" height="32" rx="8" fill="url(#brand-grad)"/>
|
| 845 |
+
<path d="M7 23h5v-5h5v-5h5" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
|
| 846 |
+
<path d="M19.6 9.4l2.2 2.2 4.2-4.4" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
|
| 847 |
+
</svg>
|
| 848 |
+
<span>IntelligenceLab</span>
|
| 849 |
+
</a>
|
| 850 |
+
<nav class="footer-links" aria-label="Footer">
|
| 851 |
+
<a href="#examples">Examples</a>
|
| 852 |
+
<a href="#trajectories">Trajectories</a>
|
| 853 |
+
<a href="#research">Research</a>
|
| 854 |
+
<a data-contact data-subject="Hello" href="#contact">Contact</a>
|
| 855 |
+
</nav>
|
| 856 |
+
<p class="footer-note">© <span data-year>2026</span> IntelligenceLab. Benchmark names belong to their respective authors and are listed for skill alignment only.</p>
|
| 857 |
+
</div>
|
| 858 |
+
</footer>
|
| 859 |
+
|
| 860 |
+
<div class="ex-modal" id="ex-modal" hidden>
|
| 861 |
+
<div class="ex-backdrop" data-ex-close></div>
|
| 862 |
+
<div class="ex-sheet" role="dialog" aria-modal="true" aria-labelledby="exm-title">
|
| 863 |
+
<header class="ex-head">
|
| 864 |
+
<div>
|
| 865 |
+
<p class="ex-domain" id="exm-domain"></p>
|
| 866 |
+
<h3 id="exm-title"></h3>
|
| 867 |
+
<ul class="ex-tracks" id="exm-tracks"></ul>
|
| 868 |
+
</div>
|
| 869 |
+
<div class="ex-nav">
|
| 870 |
+
<button class="icon-btn" type="button" data-ex-prev aria-label="Previous example">←</button>
|
| 871 |
+
<button class="icon-btn" type="button" data-ex-next aria-label="Next example">→</button>
|
| 872 |
+
<button class="icon-btn" type="button" data-ex-close aria-label="Close">✕</button>
|
| 873 |
+
</div>
|
| 874 |
+
</header>
|
| 875 |
+
<div class="ex-body">
|
| 876 |
+
<figure class="ex-figure">
|
| 877 |
+
<div class="ex-live-hero" id="exm-live" aria-hidden="true" hidden></div>
|
| 878 |
+
<figcaption class="ex-evidence-label">Evidence from the task's public runs</figcaption>
|
| 879 |
+
<img id="exm-img" alt="" width="1600" height="939">
|
| 880 |
+
</figure>
|
| 881 |
+
<p class="ex-desc" id="exm-desc"></p>
|
| 882 |
+
<div class="ex-facts">
|
| 883 |
+
<div><h4>Software</h4><ul id="exm-software"></ul></div>
|
| 884 |
+
<div><h4>Agent observes</h4><ul id="exm-artifacts"></ul></div>
|
| 885 |
+
<div><h4>Hidden interventions</h4><ul id="exm-axes"></ul></div>
|
| 886 |
+
<div><h4>Graded on</h4><ul id="exm-outputs"></ul></div>
|
| 887 |
+
</div>
|
| 888 |
+
<p class="ex-how">The agent sees public runs of the real software and writes a program that reproduces it. That program is then run on hidden configurations of these parameters and must match the software's outputs, field by field.</p>
|
| 889 |
+
<a class="btn btn-dark" id="exm-cta" data-contact data-subject="Sample request" href="#contact">Request the full sample
|
| 890 |
+
<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h11m-4-4 4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
| 891 |
+
</a>
|
| 892 |
+
</div>
|
| 893 |
+
</div>
|
| 894 |
+
</div>
|
| 895 |
+
|
| 896 |
+
<script type="application/json" id="examples-data">[{"kind": "stl", "title": "OpenSCAD / BOSL2 parametric fan duct", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Regenerate a swept fan-duct mount STL whose inlet size, outlet size, bend angle, and rib count change the geometry.", "software": ["OpenSCAD", "BOSL2"], "artifacts": ["STL mesh", "geometry metrics JSON"], "axes": ["inlet size", "outlet size", "bend angle", "rib count"], "outputs": ["bounding box", "volume", "surface area", "connected components", "sampled surface distance"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D mesh", "img": "assets/examples/stl-detail.webp", "alt": "Rendered fan-duct mesh from a public OpenSCAD run"}, {"kind": "foam", "title": "OpenFOAM 2-D dam-break CFD", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Reconstruct a 2-D dam-break CFD workflow across water height, mesh, gravity, and simulation time.", "software": ["OpenFOAM"], "artifacts": ["blockMesh log", "polyMesh", "initial field files", "case dictionaries"], "axes": ["water height", "mesh", "gravity", "time"], "outputs": ["mesh statistics", "field summaries", "residual/probe behavior"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "CFD mesh", "img": "assets/examples/foam-detail.webp", "alt": "OpenFOAM dam-break mesh drawn from the public polyMesh"}, {"kind": "drc", "title": "KiCad LED-matrix driver PCB", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct LED-matrix driver board outputs (DRC report and project files) under row, column, driver, and routing interventions.", "software": ["KiCad"], "artifacts": ["DRC report", "project file list"], "axes": ["rows", "cols", "driver", "routing"], "outputs": ["DRC report summary", "project file inventory"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "PCB layout", "img": "assets/examples/drc-detail.webp", "alt": "KiCad board with design-rule findings plotted at their positions"}, {"kind": "container", "title": "Container SBOM and supply-chain attestation", "domain": "Software & Formal Systems", "color": "#2563eb", "description": "Infer coupled container base-image, package-set, label, entrypoint, and SBOM-scope behavior.", "software": ["Hadolint", "Syft", "Skopeo"], "artifacts": ["Dockerfile", "in-toto attestation", "SPDX SBOM"], "axes": ["base image", "entrypoint", "labels", "package set", "SBOM scope"], "outputs": ["attestation", "base", "layer count", "merkle", "vuln budget"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/container-detail.webp", "alt": "Container image layers and attestation from a public run"}, {"kind": "blender", "title": "Blender cloth flag scene", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Reconstruct cloth-scene behavior under wind, pin-group, frame, and subdivision interventions.", "software": ["Blender"], "artifacts": ["scene graph JSON"], "axes": ["wind strength", "pin group", "frame", "cloth subdiv"], "outputs": ["evaluated objects", "frame", "materials", "node groups", "object counts", "rotation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "3D scene", "img": "assets/examples/blender-detail.webp", "alt": "Blender cloth scene rotation dial across public scenarios"}, {"kind": "robot", "title": "MuJoCo / URDF mass-inertia repair", "domain": "Physical & Engineering Simulation", "color": "#0891b2", "description": "Infer robot state and trajectory behavior under actuator, collision, pose, joint-limit, and target interventions.", "software": ["MuJoCo", "URDF/MJCF tooling"], "artifacts": ["URDF model", "trajectory CSV", "control summary"], "axes": ["actuator gain", "collision margin", "initial pose", "joint limit", "trajectory target"], "outputs": ["gain", "nq", "nv", "qpos", "qvel"], "tracks": ["Terminal", "Coding"], "modality": "", "img": "assets/examples/robot-detail.webp", "alt": "MuJoCo joint-position trajectories across public scenarios"}, {"kind": "micro", "title": "Microscopy cell segmentation and counting", "domain": "Life & Molecular Sciences", "color": "#16a34a", "description": "Reconstruct cell segmentation and measurement behavior across channel, illumination, threshold, object size, and measurement feature.", "software": ["CellProfiler", "scikit-image", "Bio-Formats"], "artifacts": ["label-mask image", "object-measurements CSV"], "axes": ["channel selection", "illumination correction", "measurement feature", "object size range", "threshold method"], "outputs": ["object count", "area sum", "eccentricity sum", "threshold", "minimum size"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Microscopy images", "img": "assets/examples/micro-detail.webp", "alt": "Microscopy label masks from public runs"}, {"kind": "astro", "title": "Astronomy FITS/WCS cutout and photometry", "domain": "Earth & Space Sciences", "color": "#db2777", "description": "Reconstruct FITS/WCS cutout and photometry behavior under aperture, background, clipping, threshold, and coordinate-frame interventions.", "software": ["Astropy", "Photutils"], "artifacts": ["FITS image", "photometry catalog CSV"], "axes": ["aperture radius", "background model", "sigma clip", "source threshold", "WCS frame"], "outputs": ["flux", "coordinate frame", "median", "shape", "standard deviation"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "FITS images", "img": "assets/examples/astro-detail.webp", "alt": "Astronomy FITS cutouts from public runs"}, {"kind": "ocr", "title": "Tesseract table-image OCR", "domain": "Data & Document Workflows", "color": "#d97706", "description": "Reconstruct how DPI, font, language, metadata, and page range affect OCR behavior.", "software": ["Pandoc", "Poppler", "Tesseract", "QPDF"], "artifacts": ["OCR summary JSON", "page-preview image"], "axes": ["DPI", "font", "language", "metadata", "page range"], "outputs": ["ink", "line count", "page size", "text digest", "text length"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Document images", "img": "assets/examples/ocr-detail.webp", "alt": "OCR page preview from a public run"}, {"kind": "color", "title": "Color-space and tone-curve pipeline", "domain": "Spatial, Visual & 3D", "color": "#7c3aed", "description": "Infer a color pipeline across color space, white point, tone curve, demosaicing, and compression quality.", "software": ["colour-science", "ImageMagick", "scikit-image"], "artifacts": ["color measurements JSON", "PPM preview"], "axes": ["color space", "white point", "tone curve", "demosaic method", "compression quality"], "outputs": ["mean color", "image shape", "XYZ tristimulus values"], "tracks": ["Terminal", "Coding", "Multimodal"], "modality": "Images", "img": "assets/examples/color-detail.webp", "alt": "Color-pipeline previews from public runs"}]</script>
|
| 897 |
+
<script src="app.js" defer></script>
|
| 898 |
+
<script src="live.js" defer></script>
|
| 899 |
+
</body>
|
| 900 |
</html>
|
live.js
ADDED
|
@@ -0,0 +1,810 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(() => {
|
| 2 |
+
'use strict';
|
| 3 |
+
|
| 4 |
+
const REDUCE = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
| 5 |
+
const SC = ['#0d9488', '#2563eb', '#7c3aed', '#db2777', '#d97706', '#059669'];
|
| 6 |
+
const DRC = ['#fbbf24', '#2dd4bf', '#f472b6', '#60a5fa', '#a78bfa', '#34d399', '#fb7185', '#22d3ee'];
|
| 7 |
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
| 8 |
+
const easeOut = (t) => 1 - Math.pow(1 - clamp(t, 0, 1), 3);
|
| 9 |
+
const easeInOut = (t) => {
|
| 10 |
+
const x = clamp(t, 0, 1);
|
| 11 |
+
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
| 12 |
+
};
|
| 13 |
+
const fmt = (n) => n.toLocaleString('en-US');
|
| 14 |
+
const hexRgb = (h) => [1, 3, 5].map((i) => parseInt(h.slice(i, i + 2), 16));
|
| 15 |
+
|
| 16 |
+
function decode(b64, Type) {
|
| 17 |
+
const bin = atob(b64);
|
| 18 |
+
const u8 = new Uint8Array(bin.length);
|
| 19 |
+
for (let i = 0; i < bin.length; i += 1) u8[i] = bin.charCodeAt(i);
|
| 20 |
+
return new Type(u8.buffer);
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
function make(tag, cls, parent, text) {
|
| 24 |
+
const node = document.createElement(tag);
|
| 25 |
+
if (cls) node.className = cls;
|
| 26 |
+
if (text != null) node.textContent = text;
|
| 27 |
+
if (parent) parent.appendChild(node);
|
| 28 |
+
return node;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// One animation loop drives every visible view.
|
| 32 |
+
const active = new Set();
|
| 33 |
+
let raf = 0;
|
| 34 |
+
function loop(now) {
|
| 35 |
+
active.forEach((view) => { if (view.ready) view.render(now); });
|
| 36 |
+
raf = active.size && !document.hidden ? requestAnimationFrame(loop) : 0;
|
| 37 |
+
}
|
| 38 |
+
function wake() {
|
| 39 |
+
if (!raf && active.size && !document.hidden) raf = requestAnimationFrame(loop);
|
| 40 |
+
}
|
| 41 |
+
document.addEventListener('visibilitychange', () => {
|
| 42 |
+
if (document.hidden) {
|
| 43 |
+
cancelAnimationFrame(raf);
|
| 44 |
+
raf = 0;
|
| 45 |
+
} else {
|
| 46 |
+
wake();
|
| 47 |
+
}
|
| 48 |
+
});
|
| 49 |
+
|
| 50 |
+
class View {
|
| 51 |
+
constructor(box, { canvas = true, hero = false } = {}) {
|
| 52 |
+
this.box = box;
|
| 53 |
+
this.hero = hero;
|
| 54 |
+
this.t0 = performance.now() - (REDUCE ? 600000 : 0);
|
| 55 |
+
this.w = 1;
|
| 56 |
+
this.h = 1;
|
| 57 |
+
if (canvas) {
|
| 58 |
+
this.canvas = make('canvas', 'lv-canvas', box);
|
| 59 |
+
this.ctx = this.canvas.getContext('2d');
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
start() {
|
| 64 |
+
this.ro = new ResizeObserver(() => this.resize());
|
| 65 |
+
this.ro.observe(this.box);
|
| 66 |
+
this.io = new IntersectionObserver((entries) => {
|
| 67 |
+
if (!REDUCE && entries.some((e) => e.isIntersecting)) {
|
| 68 |
+
active.add(this);
|
| 69 |
+
wake();
|
| 70 |
+
} else {
|
| 71 |
+
active.delete(this);
|
| 72 |
+
}
|
| 73 |
+
}, { rootMargin: '60px' });
|
| 74 |
+
this.io.observe(this.box);
|
| 75 |
+
this.resize();
|
| 76 |
+
return this;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
resize() {
|
| 80 |
+
const r = this.box.getBoundingClientRect();
|
| 81 |
+
this.w = Math.max(1, r.width);
|
| 82 |
+
this.h = Math.max(1, r.height);
|
| 83 |
+
if (this.canvas) {
|
| 84 |
+
const dpr = Math.min(2, window.devicePixelRatio || 1);
|
| 85 |
+
const W = Math.round(this.w * dpr);
|
| 86 |
+
const H = Math.round(this.h * dpr);
|
| 87 |
+
if (this.canvas.width !== W || this.canvas.height !== H) {
|
| 88 |
+
this.canvas.width = W;
|
| 89 |
+
this.canvas.height = H;
|
| 90 |
+
}
|
| 91 |
+
this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
| 92 |
+
}
|
| 93 |
+
if (this.w < 8 || this.h < 8) return;
|
| 94 |
+
this.layout();
|
| 95 |
+
this.ready = true;
|
| 96 |
+
this.render(performance.now());
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
layout() {}
|
| 100 |
+
|
| 101 |
+
render() {}
|
| 102 |
+
|
| 103 |
+
elapsed(now) {
|
| 104 |
+
return now - this.t0;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
caption(text) {
|
| 108 |
+
if (!this.cap) this.cap = make('span', 'lv-cap', this.box);
|
| 109 |
+
if (this.cap.textContent !== text) this.cap.textContent = text;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
dispose() {
|
| 113 |
+
active.delete(this);
|
| 114 |
+
if (this.io) this.io.disconnect();
|
| 115 |
+
if (this.ro) this.ro.disconnect();
|
| 116 |
+
this.box.replaceChildren();
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
// OpenSCAD meshes: rotate, alternating public runs at one shared scale.
|
| 121 |
+
class MeshLive extends View {
|
| 122 |
+
constructor(box, v, opts) {
|
| 123 |
+
super(box, opts);
|
| 124 |
+
this.base = hexRgb(opts.color || '#7c3aed');
|
| 125 |
+
this.meshes = v.meshes.map((m) => {
|
| 126 |
+
const T = decode(m.tris, Float32Array);
|
| 127 |
+
const mn = [Infinity, Infinity, Infinity];
|
| 128 |
+
const mx = [-Infinity, -Infinity, -Infinity];
|
| 129 |
+
for (let i = 0; i < T.length; i += 3) {
|
| 130 |
+
for (let k = 0; k < 3; k += 1) {
|
| 131 |
+
const x = T[i + k];
|
| 132 |
+
if (x < mn[k]) mn[k] = x;
|
| 133 |
+
if (x > mx[k]) mx[k] = x;
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
return {
|
| 137 |
+
id: m.id,
|
| 138 |
+
T,
|
| 139 |
+
n: T.length / 9,
|
| 140 |
+
ctr: [0, 1, 2].map((k) => (mn[k] + mx[k]) / 2),
|
| 141 |
+
rad: Math.hypot(mx[0] - mn[0], mx[1] - mn[1], mx[2] - mn[2]) / 2 || 1,
|
| 142 |
+
};
|
| 143 |
+
});
|
| 144 |
+
this.rad = Math.max(...this.meshes.map((m) => m.rad));
|
| 145 |
+
const maxN = Math.max(...this.meshes.map((m) => m.n));
|
| 146 |
+
this.tmp = new Float32Array(9);
|
| 147 |
+
this.depth = new Float32Array(maxN);
|
| 148 |
+
this.order = new Uint32Array(maxN);
|
| 149 |
+
this.pts = new Float32Array(maxN * 6);
|
| 150 |
+
this.col = new Array(maxN);
|
| 151 |
+
this.cycle = 6500;
|
| 152 |
+
this.start();
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
render(now) {
|
| 156 |
+
const { ctx, w, h, tmp, pts, depth, order } = this;
|
| 157 |
+
const t = this.elapsed(now);
|
| 158 |
+
const mesh = this.meshes[Math.floor(t / this.cycle) % this.meshes.length];
|
| 159 |
+
const ph = (t % this.cycle) / this.cycle;
|
| 160 |
+
const alpha = REDUCE ? 1 : clamp(Math.min(ph, 1 - ph) / 0.07, 0, 1);
|
| 161 |
+
ctx.clearRect(0, 0, w, h);
|
| 162 |
+
|
| 163 |
+
const m = Math.min(w, h);
|
| 164 |
+
const ox = w / 2;
|
| 165 |
+
const oy = h / 2;
|
| 166 |
+
const shadow = ctx.createRadialGradient(ox, oy + h * 0.33, 0, ox, oy + h * 0.33, m * 0.45);
|
| 167 |
+
shadow.addColorStop(0, 'rgba(15,23,42,.24)');
|
| 168 |
+
shadow.addColorStop(1, 'rgba(15,23,42,0)');
|
| 169 |
+
ctx.fillStyle = shadow;
|
| 170 |
+
ctx.beginPath();
|
| 171 |
+
ctx.ellipse(ox, oy + h * 0.33, m * 0.45, m * 0.07, 0, 0, Math.PI * 2);
|
| 172 |
+
ctx.fill();
|
| 173 |
+
|
| 174 |
+
const s = (m * 0.5) / this.rad;
|
| 175 |
+
const yaw = -0.75 + t * 0.00045;
|
| 176 |
+
const cy = Math.cos(yaw);
|
| 177 |
+
const sy = Math.sin(yaw);
|
| 178 |
+
const cp = Math.cos(0.42);
|
| 179 |
+
const sp = Math.sin(0.42);
|
| 180 |
+
const [mx, my, mz] = mesh.ctr;
|
| 181 |
+
let lx = -0.45;
|
| 182 |
+
let ly = -0.72;
|
| 183 |
+
let lz = 0.55;
|
| 184 |
+
const ll = Math.hypot(lx, ly, lz);
|
| 185 |
+
lx /= ll; ly /= ll; lz /= ll;
|
| 186 |
+
let hx = lx;
|
| 187 |
+
let hy = ly - 1;
|
| 188 |
+
let hz = lz;
|
| 189 |
+
const hl = Math.hypot(hx, hy, hz);
|
| 190 |
+
hx /= hl; hy /= hl; hz /= hl;
|
| 191 |
+
const [br, bg, bb] = this.base;
|
| 192 |
+
const { T, n } = mesh;
|
| 193 |
+
|
| 194 |
+
for (let f = 0; f < n; f += 1) {
|
| 195 |
+
const b = f * 9;
|
| 196 |
+
for (let k = 0; k < 3; k += 1) {
|
| 197 |
+
const x = T[b + 3 * k] - mx;
|
| 198 |
+
const y = T[b + 3 * k + 1] - my;
|
| 199 |
+
const z = T[b + 3 * k + 2] - mz;
|
| 200 |
+
const x1 = x * cy - y * sy;
|
| 201 |
+
const y1 = x * sy + y * cy;
|
| 202 |
+
tmp[3 * k] = x1;
|
| 203 |
+
tmp[3 * k + 1] = y1 * cp - z * sp;
|
| 204 |
+
tmp[3 * k + 2] = y1 * sp + z * cp;
|
| 205 |
+
}
|
| 206 |
+
const ux = tmp[3] - tmp[0];
|
| 207 |
+
const uy = tmp[4] - tmp[1];
|
| 208 |
+
const uz = tmp[5] - tmp[2];
|
| 209 |
+
const vx = tmp[6] - tmp[0];
|
| 210 |
+
const vy = tmp[7] - tmp[1];
|
| 211 |
+
const vz = tmp[8] - tmp[2];
|
| 212 |
+
let nx = uy * vz - uz * vy;
|
| 213 |
+
let ny = uz * vx - ux * vz;
|
| 214 |
+
let nz = ux * vy - uy * vx;
|
| 215 |
+
const nl = Math.hypot(nx, ny, nz) || 1;
|
| 216 |
+
nx /= nl; ny /= nl; nz /= nl;
|
| 217 |
+
if (ny > 0) { nx = -nx; ny = -ny; nz = -nz; }
|
| 218 |
+
const dif = Math.max(0, nx * lx + ny * ly + nz * lz);
|
| 219 |
+
const spec = Math.pow(Math.max(0, nx * hx + ny * hy + nz * hz), 30) * 140;
|
| 220 |
+
const k = 0.2 + 0.8 * dif;
|
| 221 |
+
this.col[f] = `rgb(${Math.min(255, br * k + spec) | 0},${Math.min(255, bg * k + spec) | 0},${Math.min(255, bb * k + spec) | 0})`;
|
| 222 |
+
depth[f] = tmp[1] + tmp[4] + tmp[7];
|
| 223 |
+
const o = f * 6;
|
| 224 |
+
pts[o] = ox + tmp[0] * s;
|
| 225 |
+
pts[o + 1] = oy - tmp[2] * s;
|
| 226 |
+
pts[o + 2] = ox + tmp[3] * s;
|
| 227 |
+
pts[o + 3] = oy - tmp[5] * s;
|
| 228 |
+
pts[o + 4] = ox + tmp[6] * s;
|
| 229 |
+
pts[o + 5] = oy - tmp[8] * s;
|
| 230 |
+
order[f] = f;
|
| 231 |
+
}
|
| 232 |
+
const sorted = order.subarray(0, n).sort((p, q) => depth[q] - depth[p]);
|
| 233 |
+
ctx.globalAlpha = alpha;
|
| 234 |
+
ctx.lineJoin = 'round';
|
| 235 |
+
ctx.lineWidth = 0.6;
|
| 236 |
+
for (let j = 0; j < n; j += 1) {
|
| 237 |
+
const f = sorted[j];
|
| 238 |
+
const o = f * 6;
|
| 239 |
+
ctx.beginPath();
|
| 240 |
+
ctx.moveTo(pts[o], pts[o + 1]);
|
| 241 |
+
ctx.lineTo(pts[o + 2], pts[o + 3]);
|
| 242 |
+
ctx.lineTo(pts[o + 4], pts[o + 5]);
|
| 243 |
+
ctx.closePath();
|
| 244 |
+
ctx.fillStyle = this.col[f];
|
| 245 |
+
ctx.strokeStyle = this.col[f];
|
| 246 |
+
ctx.fill();
|
| 247 |
+
ctx.stroke();
|
| 248 |
+
}
|
| 249 |
+
ctx.globalAlpha = 1;
|
| 250 |
+
this.caption(`${mesh.id} · ${fmt(mesh.n)} facets`);
|
| 251 |
+
}
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
// OpenFOAM: the mesh draws in, then tracer particles flow inlet to outlet.
|
| 255 |
+
class FoamLive extends View {
|
| 256 |
+
constructor(box, v, opts) {
|
| 257 |
+
super(box, opts);
|
| 258 |
+
this.P = decode(v.points, Float32Array);
|
| 259 |
+
this.Q = decode(v.quads, Uint16Array);
|
| 260 |
+
const pal = { inlet: '#2563eb', outlet: '#d97706' };
|
| 261 |
+
this.patches = v.patches.map((p) => ({
|
| 262 |
+
E: decode(p.edges, Uint16Array),
|
| 263 |
+
color: pal[p.name] || (p.type === 'wall' ? '#1e293b' : '#db2777'),
|
| 264 |
+
}));
|
| 265 |
+
let x0 = Infinity;
|
| 266 |
+
let x1 = -Infinity;
|
| 267 |
+
let y0 = Infinity;
|
| 268 |
+
let y1 = -Infinity;
|
| 269 |
+
for (let i = 0; i < this.P.length; i += 2) {
|
| 270 |
+
const x = this.P[i];
|
| 271 |
+
const y = this.P[i + 1];
|
| 272 |
+
if (x < x0) x0 = x;
|
| 273 |
+
if (x > x1) x1 = x;
|
| 274 |
+
if (y < y0) y0 = y;
|
| 275 |
+
if (y > y1) y1 = y;
|
| 276 |
+
}
|
| 277 |
+
this.bb = [x0, y0, x1, y1];
|
| 278 |
+
|
| 279 |
+
const bins = 160;
|
| 280 |
+
const lo = new Float32Array(bins).fill(Infinity);
|
| 281 |
+
const hi = new Float32Array(bins).fill(-Infinity);
|
| 282 |
+
for (let i = 0; i < this.P.length; i += 2) {
|
| 283 |
+
const b = clamp(Math.round(((this.P[i] - x0) / (x1 - x0)) * (bins - 1)), 0, bins - 1);
|
| 284 |
+
lo[b] = Math.min(lo[b], this.P[i + 1]);
|
| 285 |
+
hi[b] = Math.max(hi[b], this.P[i + 1]);
|
| 286 |
+
}
|
| 287 |
+
for (let b = 1; b < bins; b += 1) {
|
| 288 |
+
if (!Number.isFinite(lo[b])) { lo[b] = lo[b - 1]; hi[b] = hi[b - 1]; }
|
| 289 |
+
}
|
| 290 |
+
this.bins = bins;
|
| 291 |
+
this.lo = lo;
|
| 292 |
+
this.hi = hi;
|
| 293 |
+
this.maxSpan = Math.max(...Array.from(hi, (v2, b) => v2 - lo[b]));
|
| 294 |
+
this.cells = v.n_cells;
|
| 295 |
+
this.off = document.createElement('canvas');
|
| 296 |
+
this.parts = Array.from({ length: opts.hero ? 280 : 120 }, () => this.spawn(true));
|
| 297 |
+
this.last = 0;
|
| 298 |
+
this.start();
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
spawn(scatter) {
|
| 302 |
+
return { f: scatter ? Math.random() : -Math.random() * 0.04, u: 0.05 + Math.random() * 0.9, v: 0.7 + Math.random() * 0.6, ph: Math.random() * 6.3 };
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
layout() {
|
| 306 |
+
const dpr = Math.min(2, window.devicePixelRatio || 1);
|
| 307 |
+
const pad = this.hero ? 30 : 14;
|
| 308 |
+
const [x0, y0, x1, y1] = this.bb;
|
| 309 |
+
this.s = Math.min((this.w - 2 * pad) / (x1 - x0), (this.h - 2 * pad) / (y1 - y0));
|
| 310 |
+
this.ox = this.w / 2 - ((x0 + x1) / 2) * this.s;
|
| 311 |
+
this.oy = this.h / 2 + ((y0 + y1) / 2) * this.s;
|
| 312 |
+
const off = this.off;
|
| 313 |
+
off.width = Math.round(this.w * dpr);
|
| 314 |
+
off.height = Math.round(this.h * dpr);
|
| 315 |
+
const c = off.getContext('2d');
|
| 316 |
+
c.setTransform(dpr, 0, 0, dpr, 0, 0);
|
| 317 |
+
c.clearRect(0, 0, this.w, this.h);
|
| 318 |
+
const { P, Q } = this;
|
| 319 |
+
const X = (x) => this.ox + x * this.s;
|
| 320 |
+
const Y = (y) => this.oy - y * this.s;
|
| 321 |
+
c.lineWidth = 0.45;
|
| 322 |
+
c.strokeStyle = 'rgba(5,150,105,.5)';
|
| 323 |
+
c.beginPath();
|
| 324 |
+
for (let q = 0; q < Q.length; q += 4) {
|
| 325 |
+
c.moveTo(X(P[2 * Q[q]]), Y(P[2 * Q[q] + 1]));
|
| 326 |
+
for (let k = 1; k < 4; k += 1) c.lineTo(X(P[2 * Q[q + k]]), Y(P[2 * Q[q + k] + 1]));
|
| 327 |
+
c.closePath();
|
| 328 |
+
}
|
| 329 |
+
c.stroke();
|
| 330 |
+
c.lineWidth = this.hero ? 2.4 : 1.6;
|
| 331 |
+
for (const p of this.patches) {
|
| 332 |
+
c.strokeStyle = p.color;
|
| 333 |
+
c.beginPath();
|
| 334 |
+
for (let e = 0; e < p.E.length; e += 2) {
|
| 335 |
+
c.moveTo(X(P[2 * p.E[e]]), Y(P[2 * p.E[e] + 1]));
|
| 336 |
+
c.lineTo(X(P[2 * p.E[e + 1]]), Y(P[2 * p.E[e + 1] + 1]));
|
| 337 |
+
}
|
| 338 |
+
c.stroke();
|
| 339 |
+
}
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
at(p) {
|
| 343 |
+
const [x0, , x1] = this.bb;
|
| 344 |
+
const b = clamp(Math.round(clamp(p.f, 0, 1) * (this.bins - 1)), 0, this.bins - 1);
|
| 345 |
+
const span = this.hi[b] - this.lo[b];
|
| 346 |
+
const y = this.lo[b] + span * (0.04 + 0.92 * p.u);
|
| 347 |
+
return { x: this.ox + (x0 + clamp(p.f, 0, 1) * (x1 - x0)) * this.s, y: this.oy - y * this.s, span };
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
render(now) {
|
| 351 |
+
const { ctx, w, h } = this;
|
| 352 |
+
const t = this.elapsed(now);
|
| 353 |
+
const dt = clamp(now - (this.last || now), 0, 48);
|
| 354 |
+
this.last = now;
|
| 355 |
+
ctx.clearRect(0, 0, w, h);
|
| 356 |
+
const reveal = REDUCE ? 1 : easeOut(t / 1500);
|
| 357 |
+
ctx.save();
|
| 358 |
+
ctx.beginPath();
|
| 359 |
+
ctx.rect(0, 0, w * reveal, h);
|
| 360 |
+
ctx.clip();
|
| 361 |
+
ctx.drawImage(this.off, 0, 0, w, h);
|
| 362 |
+
ctx.restore();
|
| 363 |
+
this.caption(`${fmt(this.cells)} cells`);
|
| 364 |
+
if (reveal < 1) return;
|
| 365 |
+
|
| 366 |
+
ctx.lineCap = 'round';
|
| 367 |
+
ctx.lineWidth = this.hero ? 1.8 : 1.4;
|
| 368 |
+
for (const p of this.parts) {
|
| 369 |
+
const a = this.at(p);
|
| 370 |
+
const speed = 0.00007 * p.v * (this.maxSpan / Math.max(a.span, 1e-6)) ** 0.7;
|
| 371 |
+
p.f += speed * dt;
|
| 372 |
+
if (p.f > 1) Object.assign(p, this.spawn(false));
|
| 373 |
+
const b = this.at(p);
|
| 374 |
+
const wobble = Math.sin(t * 0.002 + p.ph) * 0.6;
|
| 375 |
+
const len = clamp((b.x - a.x) * 5, 2, 14);
|
| 376 |
+
ctx.strokeStyle = 'rgba(14,165,233,.75)';
|
| 377 |
+
ctx.beginPath();
|
| 378 |
+
ctx.moveTo(b.x - len, b.y + wobble);
|
| 379 |
+
ctx.lineTo(b.x, b.y + wobble);
|
| 380 |
+
ctx.stroke();
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
// KiCad: a design-rule scan sweeps the board and lights up each finding.
|
| 386 |
+
class DrcLive extends View {
|
| 387 |
+
constructor(box, v, opts) {
|
| 388 |
+
super(box, opts);
|
| 389 |
+
this.dots = v.dots;
|
| 390 |
+
let x0 = Infinity;
|
| 391 |
+
let x1 = -Infinity;
|
| 392 |
+
let y0 = Infinity;
|
| 393 |
+
let y1 = -Infinity;
|
| 394 |
+
for (const [x, y] of this.dots) {
|
| 395 |
+
x0 = Math.min(x0, x); x1 = Math.max(x1, x);
|
| 396 |
+
y0 = Math.min(y0, y); y1 = Math.max(y1, y);
|
| 397 |
+
}
|
| 398 |
+
const pad = 14;
|
| 399 |
+
this.bb = [x0 - pad, y0 - pad, x1 + pad, y1 + pad];
|
| 400 |
+
this.sweepMs = 3200;
|
| 401 |
+
this.cycle = 4600;
|
| 402 |
+
this.start();
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
layout() {
|
| 406 |
+
const margin = this.hero ? 26 : 12;
|
| 407 |
+
const [x0, y0, x1, y1] = this.bb;
|
| 408 |
+
this.s = Math.min((this.w - 2 * margin) / (x1 - x0), (this.h - 2 * margin) / (y1 - y0));
|
| 409 |
+
this.bw = (x1 - x0) * this.s;
|
| 410 |
+
this.bh = (y1 - y0) * this.s;
|
| 411 |
+
this.bx = (this.w - this.bw) / 2;
|
| 412 |
+
this.by = (this.h - this.bh) / 2;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
render(now) {
|
| 416 |
+
const { ctx, w, h, s, bx, by, bw, bh } = this;
|
| 417 |
+
const [x0, y0] = this.bb;
|
| 418 |
+
const t = this.elapsed(now) % this.cycle;
|
| 419 |
+
const sweep = REDUCE ? 1.2 : t / this.sweepMs;
|
| 420 |
+
const beam = bx + sweep * bw;
|
| 421 |
+
ctx.clearRect(0, 0, w, h);
|
| 422 |
+
|
| 423 |
+
ctx.save();
|
| 424 |
+
ctx.beginPath();
|
| 425 |
+
if (ctx.roundRect) ctx.roundRect(bx, by, bw, bh, 8);
|
| 426 |
+
else ctx.rect(bx, by, bw, bh);
|
| 427 |
+
ctx.fillStyle = '#05271f';
|
| 428 |
+
ctx.fill();
|
| 429 |
+
ctx.strokeStyle = 'rgba(52,211,153,.5)';
|
| 430 |
+
ctx.lineWidth = 1;
|
| 431 |
+
ctx.stroke();
|
| 432 |
+
ctx.clip();
|
| 433 |
+
ctx.strokeStyle = 'rgba(94,234,212,.1)';
|
| 434 |
+
ctx.lineWidth = 0.6;
|
| 435 |
+
ctx.beginPath();
|
| 436 |
+
const step = 10 * s;
|
| 437 |
+
for (let gx = bx; gx < bx + bw; gx += step) { ctx.moveTo(gx, by); ctx.lineTo(gx, by + bh); }
|
| 438 |
+
for (let gy = by; gy < by + bh; gy += step) { ctx.moveTo(bx, gy); ctx.lineTo(bx + bw, gy); }
|
| 439 |
+
ctx.stroke();
|
| 440 |
+
if (sweep <= 1) {
|
| 441 |
+
const band = ctx.createLinearGradient(beam - 46, 0, beam + 6, 0);
|
| 442 |
+
band.addColorStop(0, 'rgba(45,212,191,0)');
|
| 443 |
+
band.addColorStop(1, 'rgba(45,212,191,.28)');
|
| 444 |
+
ctx.fillStyle = band;
|
| 445 |
+
ctx.fillRect(beam - 46, by, 52, bh);
|
| 446 |
+
ctx.fillStyle = 'rgba(153,246,228,.9)';
|
| 447 |
+
ctx.fillRect(beam, by, 1.5, bh);
|
| 448 |
+
}
|
| 449 |
+
ctx.restore();
|
| 450 |
+
|
| 451 |
+
let found = 0;
|
| 452 |
+
const r = this.hero ? 3.4 : 2.6;
|
| 453 |
+
for (const [x, y, g] of this.dots) {
|
| 454 |
+
const px = bx + (x - x0) * s;
|
| 455 |
+
const py = by + (y - y0) * s;
|
| 456 |
+
const color = DRC[g % DRC.length];
|
| 457 |
+
const passed = px <= beam;
|
| 458 |
+
if (passed) found += 1;
|
| 459 |
+
ctx.globalAlpha = passed ? 1 : 0.22;
|
| 460 |
+
ctx.fillStyle = color;
|
| 461 |
+
ctx.beginPath();
|
| 462 |
+
ctx.arc(px, py, r, 0, Math.PI * 2);
|
| 463 |
+
ctx.fill();
|
| 464 |
+
const since = ((beam - px) / bw) * this.sweepMs;
|
| 465 |
+
if (passed && since < 700 && sweep <= 1) {
|
| 466 |
+
const k = since / 700;
|
| 467 |
+
ctx.globalAlpha = 1 - k;
|
| 468 |
+
ctx.strokeStyle = color;
|
| 469 |
+
ctx.lineWidth = 1.4;
|
| 470 |
+
ctx.beginPath();
|
| 471 |
+
ctx.arc(px, py, r + 2 + k * 9, 0, Math.PI * 2);
|
| 472 |
+
ctx.stroke();
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
ctx.globalAlpha = 1;
|
| 476 |
+
this.caption(`DRC scan · ${found} findings`);
|
| 477 |
+
}
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
// Container: layers build bottom-up, then the attestation is written.
|
| 481 |
+
class ContainerLive extends View {
|
| 482 |
+
constructor(box, v, opts) {
|
| 483 |
+
super(box, { ...opts, canvas: false });
|
| 484 |
+
this.sc = v.scenarios;
|
| 485 |
+
const wrap = make('div', 'lv-container', box);
|
| 486 |
+
this.code = make('div', 'lv-code', wrap);
|
| 487 |
+
this.stack = make('div', 'lv-stack', wrap);
|
| 488 |
+
this.hash = make('div', 'lv-hash', wrap);
|
| 489 |
+
this.layers = [];
|
| 490 |
+
this.idx = -1;
|
| 491 |
+
this.cycle = 3800;
|
| 492 |
+
this.start();
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
render(now) {
|
| 496 |
+
const t = this.elapsed(now);
|
| 497 |
+
const idx = REDUCE ? 0 : Math.floor(t / this.cycle) % this.sc.length;
|
| 498 |
+
const lt = REDUCE ? this.cycle : t % this.cycle;
|
| 499 |
+
const sc = this.sc[idx];
|
| 500 |
+
if (idx !== this.idx) {
|
| 501 |
+
this.idx = idx;
|
| 502 |
+
this.code.textContent = `FROM ${sc.base} · ${sc.id}`;
|
| 503 |
+
this.layers = Array.from({ length: sc.layers }, (_, k) => {
|
| 504 |
+
const el = make('div', 'lv-layer', null, k === sc.layers - 1 ? `L1 · base ${sc.base}` : `L${sc.layers - k}`);
|
| 505 |
+
el.style.setProperty('--k', String(k));
|
| 506 |
+
return el;
|
| 507 |
+
});
|
| 508 |
+
this.stack.replaceChildren(...this.layers);
|
| 509 |
+
}
|
| 510 |
+
const n = this.layers.length;
|
| 511 |
+
this.layers.forEach((el, k) => el.classList.toggle('on', lt > 180 + (n - 1 - k) * 260));
|
| 512 |
+
const typeStart = 180 + n * 260 + 120;
|
| 513 |
+
const chars = clamp(Math.floor((lt - typeStart) / 42), 0, sc.attestation.length);
|
| 514 |
+
const cursor = chars > 0 && chars < sc.attestation.length ? '▍' : '';
|
| 515 |
+
const text = `attestation ${sc.attestation.slice(0, chars)}${cursor}`;
|
| 516 |
+
if (this.hash.textContent !== text) this.hash.textContent = text;
|
| 517 |
+
this.box.classList.toggle('lv-fade', !REDUCE && lt > this.cycle - 320);
|
| 518 |
+
}
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
// Blender: rotation dial sweeps out to each scenario's evaluated rotation.
|
| 522 |
+
class DialLive extends View {
|
| 523 |
+
constructor(box, v, opts) {
|
| 524 |
+
super(box, opts);
|
| 525 |
+
this.scenes = v.scenes;
|
| 526 |
+
this.cycle = 4800;
|
| 527 |
+
this.start();
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
render(now) {
|
| 531 |
+
const { ctx, w, h } = this;
|
| 532 |
+
const t = this.elapsed(now) % this.cycle;
|
| 533 |
+
ctx.clearRect(0, 0, w, h);
|
| 534 |
+
const cx = w / 2;
|
| 535 |
+
const cy = h / 2 - (this.hero ? 0 : 8);
|
| 536 |
+
const R = Math.min(w, h) * (this.hero ? 0.3 : 0.32);
|
| 537 |
+
ctx.fillStyle = 'rgba(255,255,255,.92)';
|
| 538 |
+
ctx.strokeStyle = 'rgba(100,116,139,.35)';
|
| 539 |
+
ctx.lineWidth = 1.2;
|
| 540 |
+
ctx.beginPath();
|
| 541 |
+
ctx.arc(cx, cy, R, 0, Math.PI * 2);
|
| 542 |
+
ctx.fill();
|
| 543 |
+
ctx.stroke();
|
| 544 |
+
ctx.strokeStyle = 'rgba(100,116,139,.45)';
|
| 545 |
+
for (let k = 0; k < 36; k += 1) {
|
| 546 |
+
const a = (k / 36) * Math.PI * 2;
|
| 547 |
+
const r1 = R - (k % 9 === 0 ? 10 : 5);
|
| 548 |
+
ctx.lineWidth = k % 9 === 0 ? 1.4 : 0.9;
|
| 549 |
+
ctx.beginPath();
|
| 550 |
+
ctx.moveTo(cx + R * Math.cos(a), cy - R * Math.sin(a));
|
| 551 |
+
ctx.lineTo(cx + r1 * Math.cos(a), cy - r1 * Math.sin(a));
|
| 552 |
+
ctx.stroke();
|
| 553 |
+
}
|
| 554 |
+
this.scenes.forEach((sc, i) => {
|
| 555 |
+
const local = t - i * 220;
|
| 556 |
+
let k;
|
| 557 |
+
if (REDUCE) k = 1;
|
| 558 |
+
else if (local < 1400) k = easeInOut(local / 1400);
|
| 559 |
+
else if (local < 3700) k = 1;
|
| 560 |
+
else k = 1 - easeInOut((local - 3700) / 800);
|
| 561 |
+
const a = sc.rotation_z * clamp(k, 0, 1);
|
| 562 |
+
const color = SC[i % SC.length];
|
| 563 |
+
ctx.strokeStyle = color;
|
| 564 |
+
ctx.lineCap = 'round';
|
| 565 |
+
ctx.lineWidth = 3;
|
| 566 |
+
ctx.globalAlpha = 0.85;
|
| 567 |
+
ctx.beginPath();
|
| 568 |
+
ctx.arc(cx, cy, R + 8 + i * 7, 0, -a, true);
|
| 569 |
+
ctx.stroke();
|
| 570 |
+
ctx.globalAlpha = 1;
|
| 571 |
+
const tip = R - 16;
|
| 572 |
+
ctx.lineWidth = 3.2;
|
| 573 |
+
ctx.beginPath();
|
| 574 |
+
ctx.moveTo(cx, cy);
|
| 575 |
+
ctx.lineTo(cx + tip * Math.cos(a), cy - tip * Math.sin(a));
|
| 576 |
+
ctx.stroke();
|
| 577 |
+
ctx.fillStyle = color;
|
| 578 |
+
ctx.beginPath();
|
| 579 |
+
ctx.arc(cx + tip * Math.cos(a), cy - tip * Math.sin(a), 5, 0, Math.PI * 2);
|
| 580 |
+
ctx.fill();
|
| 581 |
+
});
|
| 582 |
+
ctx.fillStyle = '#0f172a';
|
| 583 |
+
ctx.beginPath();
|
| 584 |
+
ctx.arc(cx, cy, 6, 0, Math.PI * 2);
|
| 585 |
+
ctx.fill();
|
| 586 |
+
this.caption(`rotation_z ${this.scenes.map((sc) => sc.rotation_z).join(' · ')} rad`);
|
| 587 |
+
}
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
// MuJoCo: joint-position trajectories draw in across every public scenario.
|
| 591 |
+
class LinesLive extends View {
|
| 592 |
+
constructor(box, v, opts) {
|
| 593 |
+
super(box, opts);
|
| 594 |
+
this.series = v.series;
|
| 595 |
+
const xs = this.series.flatMap((sr) => sr.step);
|
| 596 |
+
const ys = this.series.flatMap((sr) => sr.qpos);
|
| 597 |
+
this.x0 = Math.min(...xs);
|
| 598 |
+
this.x1 = Math.max(...xs);
|
| 599 |
+
let y0 = Math.min(...ys);
|
| 600 |
+
let y1 = Math.max(...ys);
|
| 601 |
+
const pad = (y1 - y0) * 0.1 || 1;
|
| 602 |
+
this.y0 = y0 - pad;
|
| 603 |
+
this.y1 = y1 + pad;
|
| 604 |
+
this.cycle = 5200;
|
| 605 |
+
this.start();
|
| 606 |
+
}
|
| 607 |
+
|
| 608 |
+
render(now) {
|
| 609 |
+
const { ctx, w, h } = this;
|
| 610 |
+
const t = this.elapsed(now) % this.cycle;
|
| 611 |
+
const p = REDUCE ? 1 : easeInOut(t / 2600);
|
| 612 |
+
const fade = REDUCE || t < this.cycle - 500 ? 1 : (this.cycle - t) / 500;
|
| 613 |
+
ctx.clearRect(0, 0, w, h);
|
| 614 |
+
const L = this.hero ? 40 : 22;
|
| 615 |
+
const Rm = this.hero ? 30 : 22;
|
| 616 |
+
const T = this.hero ? 30 : 22;
|
| 617 |
+
const B = this.hero ? 34 : 24;
|
| 618 |
+
const X = (v) => L + ((v - this.x0) / ((this.x1 - this.x0) || 1)) * (w - L - Rm);
|
| 619 |
+
const Y = (v) => T + (1 - (v - this.y0) / (this.y1 - this.y0)) * (h - T - B);
|
| 620 |
+
ctx.strokeStyle = 'rgba(148,163,184,.25)';
|
| 621 |
+
ctx.lineWidth = 1;
|
| 622 |
+
for (let k = 0; k <= 3; k += 1) {
|
| 623 |
+
const y = T + (k / 3) * (h - T - B);
|
| 624 |
+
ctx.beginPath();
|
| 625 |
+
ctx.moveTo(L, y);
|
| 626 |
+
ctx.lineTo(w - Rm, y);
|
| 627 |
+
ctx.stroke();
|
| 628 |
+
}
|
| 629 |
+
const cursorX = L + p * (w - L - Rm);
|
| 630 |
+
ctx.strokeStyle = 'rgba(15,23,42,.12)';
|
| 631 |
+
ctx.setLineDash([3, 4]);
|
| 632 |
+
ctx.beginPath();
|
| 633 |
+
ctx.moveTo(cursorX, T - 6);
|
| 634 |
+
ctx.lineTo(cursorX, h - B + 6);
|
| 635 |
+
ctx.stroke();
|
| 636 |
+
ctx.setLineDash([]);
|
| 637 |
+
ctx.globalAlpha = fade;
|
| 638 |
+
ctx.lineCap = 'round';
|
| 639 |
+
ctx.lineJoin = 'round';
|
| 640 |
+
this.series.forEach((sr, i) => {
|
| 641 |
+
const n = sr.step.length - 1;
|
| 642 |
+
const reach = p * n;
|
| 643 |
+
const color = SC[i % SC.length];
|
| 644 |
+
ctx.strokeStyle = color;
|
| 645 |
+
ctx.lineWidth = this.hero ? 2.8 : 2.2;
|
| 646 |
+
ctx.beginPath();
|
| 647 |
+
let hx = X(sr.step[0]);
|
| 648 |
+
let hy = Y(sr.qpos[0]);
|
| 649 |
+
ctx.moveTo(hx, hy);
|
| 650 |
+
for (let j = 1; j <= n; j += 1) {
|
| 651 |
+
if (j <= reach) {
|
| 652 |
+
hx = X(sr.step[j]);
|
| 653 |
+
hy = Y(sr.qpos[j]);
|
| 654 |
+
ctx.lineTo(hx, hy);
|
| 655 |
+
} else {
|
| 656 |
+
const f = reach - (j - 1);
|
| 657 |
+
if (f > 0) {
|
| 658 |
+
hx = X(sr.step[j - 1]) + (X(sr.step[j]) - X(sr.step[j - 1])) * f;
|
| 659 |
+
hy = Y(sr.qpos[j - 1]) + (Y(sr.qpos[j]) - Y(sr.qpos[j - 1])) * f;
|
| 660 |
+
ctx.lineTo(hx, hy);
|
| 661 |
+
}
|
| 662 |
+
break;
|
| 663 |
+
}
|
| 664 |
+
}
|
| 665 |
+
ctx.stroke();
|
| 666 |
+
ctx.fillStyle = color;
|
| 667 |
+
ctx.beginPath();
|
| 668 |
+
ctx.arc(hx, hy, this.hero ? 4.2 : 3.2, 0, Math.PI * 2);
|
| 669 |
+
ctx.fill();
|
| 670 |
+
});
|
| 671 |
+
ctx.globalAlpha = 1;
|
| 672 |
+
this.caption(`qpos over the trajectory · ${this.series.length} public scenarios`);
|
| 673 |
+
}
|
| 674 |
+
}
|
| 675 |
+
|
| 676 |
+
// Image tasks: public outputs cycle with a scan line or photometry aperture.
|
| 677 |
+
class ImagesLive extends View {
|
| 678 |
+
constructor(box, v, opts, mode) {
|
| 679 |
+
super(box, { ...opts, canvas: false });
|
| 680 |
+
this.mode = mode;
|
| 681 |
+
this.images = v.images;
|
| 682 |
+
this.wrap = make('div', `lv-images lv-${mode}`, box);
|
| 683 |
+
const slots = { micro: 3, astro: 4, ocr: 1, color: 6 }[mode];
|
| 684 |
+
this.slots = Array.from({ length: slots }, (_, j) => {
|
| 685 |
+
const cell = make('div', 'lv-cell', this.wrap);
|
| 686 |
+
const a = make('img', 'on', cell);
|
| 687 |
+
const b = make('img', '', cell);
|
| 688 |
+
[a, b].forEach((img) => { img.alt = ''; img.decoding = 'async'; });
|
| 689 |
+
const first = this.images[j % this.images.length];
|
| 690 |
+
a.src = first.src;
|
| 691 |
+
if (mode === 'astro') make('span', 'lv-aperture', cell);
|
| 692 |
+
if (mode === 'ocr' || mode === 'micro') make('span', 'lv-scan', cell);
|
| 693 |
+
if (mode === 'color') {
|
| 694 |
+
const sw = make('span', 'lv-swatch', cell);
|
| 695 |
+
sw.style.background = first.m;
|
| 696 |
+
}
|
| 697 |
+
return { cell, layers: [a, b], front: 0, idx: j % this.images.length };
|
| 698 |
+
});
|
| 699 |
+
this.period = mode === 'ocr' ? 3200 : 2600;
|
| 700 |
+
this.start();
|
| 701 |
+
}
|
| 702 |
+
|
| 703 |
+
show(slot, idx) {
|
| 704 |
+
if (slot.idx === idx) return;
|
| 705 |
+
slot.idx = idx;
|
| 706 |
+
const back = slot.layers[1 - slot.front];
|
| 707 |
+
back.src = this.images[idx].src;
|
| 708 |
+
back.classList.add('on');
|
| 709 |
+
slot.layers[slot.front].classList.remove('on');
|
| 710 |
+
slot.front = 1 - slot.front;
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
+
render(now) {
|
| 714 |
+
const t = this.elapsed(now);
|
| 715 |
+
const n = this.images.length;
|
| 716 |
+
if (this.mode === 'color') {
|
| 717 |
+
const hot = REDUCE ? 0 : Math.floor(t / 900) % n;
|
| 718 |
+
this.slots.forEach((slot, j) => slot.cell.classList.toggle('hot', j === hot));
|
| 719 |
+
const im = this.images[hot];
|
| 720 |
+
this.caption(`${im.id} · mean swatch ${im.m}`);
|
| 721 |
+
return;
|
| 722 |
+
}
|
| 723 |
+
this.slots.forEach((slot, j) => {
|
| 724 |
+
const step = REDUCE ? 0 : Math.floor((t + j * 450) / this.period);
|
| 725 |
+
this.show(slot, (j + step) % n);
|
| 726 |
+
});
|
| 727 |
+
const im = this.images[this.slots[0].idx];
|
| 728 |
+
if (this.mode === 'ocr') this.caption(`${im.id} · ${im.m} text lines`);
|
| 729 |
+
else if (this.mode === 'micro') this.caption(`${im.id} · ${im.m} objects segmented`);
|
| 730 |
+
else this.caption(`${im.id} · flux ${im.m.toFixed(1)}`);
|
| 731 |
+
}
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
const RENDERERS = {
|
| 735 |
+
stl: (box, v, o) => new MeshLive(box, v, o),
|
| 736 |
+
foam: (box, v, o) => new FoamLive(box, v, o),
|
| 737 |
+
drc: (box, v, o) => new DrcLive(box, v, o),
|
| 738 |
+
container: (box, v, o) => new ContainerLive(box, v, o),
|
| 739 |
+
blender: (box, v, o) => new DialLive(box, v, o),
|
| 740 |
+
robot: (box, v, o) => new LinesLive(box, v, o),
|
| 741 |
+
micro: (box, v, o) => new ImagesLive(box, v, o, 'micro'),
|
| 742 |
+
astro: (box, v, o) => new ImagesLive(box, v, o, 'astro'),
|
| 743 |
+
ocr: (box, v, o) => new ImagesLive(box, v, o, 'ocr'),
|
| 744 |
+
color: (box, v, o) => new ImagesLive(box, v, o, 'color'),
|
| 745 |
+
};
|
| 746 |
+
|
| 747 |
+
function mount(box, kind, opts = {}) {
|
| 748 |
+
const data = window.IL_VISUALS && window.IL_VISUALS[kind];
|
| 749 |
+
const build = RENDERERS[kind];
|
| 750 |
+
if (!data || !build) return null;
|
| 751 |
+
box.dataset.kind = kind;
|
| 752 |
+
try {
|
| 753 |
+
return build(box, data, opts);
|
| 754 |
+
} catch (err) {
|
| 755 |
+
box.replaceChildren();
|
| 756 |
+
console.error(`live preview failed for ${kind}`, err);
|
| 757 |
+
return null;
|
| 758 |
+
}
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
function mountCards() {
|
| 762 |
+
document.querySelectorAll('.ex-card[data-kind]').forEach((card) => {
|
| 763 |
+
const thumb = card.querySelector('.ex-thumb');
|
| 764 |
+
if (!thumb || thumb.querySelector('.ex-live')) return;
|
| 765 |
+
const box = make('div', 'ex-live', thumb);
|
| 766 |
+
box.setAttribute('aria-hidden', 'true');
|
| 767 |
+
const color = getComputedStyle(card).getPropertyValue('--dc').trim();
|
| 768 |
+
if (mount(box, card.dataset.kind, { color })) {
|
| 769 |
+
requestAnimationFrame(() => thumb.classList.add('is-live'));
|
| 770 |
+
} else {
|
| 771 |
+
box.remove();
|
| 772 |
+
}
|
| 773 |
+
});
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
function loadData() {
|
| 777 |
+
if (window.IL_VISUALS) return Promise.resolve();
|
| 778 |
+
return new Promise((resolve, reject) => {
|
| 779 |
+
const script = document.createElement('script');
|
| 780 |
+
script.src = 'assets/examples/visuals.js';
|
| 781 |
+
script.async = true;
|
| 782 |
+
script.onload = resolve;
|
| 783 |
+
script.onerror = reject;
|
| 784 |
+
document.head.appendChild(script);
|
| 785 |
+
});
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
const api = { ready: false, mount };
|
| 789 |
+
window.ILLive = api;
|
| 790 |
+
|
| 791 |
+
const section = document.getElementById('examples');
|
| 792 |
+
if (!section) return;
|
| 793 |
+
const go = () => loadData()
|
| 794 |
+
.then(() => {
|
| 795 |
+
api.ready = true;
|
| 796 |
+
mountCards();
|
| 797 |
+
document.dispatchEvent(new CustomEvent('il-live-ready'));
|
| 798 |
+
})
|
| 799 |
+
.catch(() => {});
|
| 800 |
+
if (!('IntersectionObserver' in window)) {
|
| 801 |
+
go();
|
| 802 |
+
} else {
|
| 803 |
+
const io = new IntersectionObserver((entries) => {
|
| 804 |
+
if (!entries.some((e) => e.isIntersecting)) return;
|
| 805 |
+
io.disconnect();
|
| 806 |
+
go();
|
| 807 |
+
}, { rootMargin: '900px 0px' });
|
| 808 |
+
io.observe(section);
|
| 809 |
+
}
|
| 810 |
+
})();
|
styles.css
ADDED
|
@@ -0,0 +1,891 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root {
|
| 2 |
+
--bg: #f6f7f4;
|
| 3 |
+
--surface: #ffffff;
|
| 4 |
+
--tint: #eef3f0;
|
| 5 |
+
--tint-2: #f3f6f4;
|
| 6 |
+
--ink: #0b1220;
|
| 7 |
+
--ink-2: #2b3648;
|
| 8 |
+
--muted: #5f6b7d;
|
| 9 |
+
--line: #e2e7e3;
|
| 10 |
+
--accent: #10b981;
|
| 11 |
+
--accent-deep: #047857;
|
| 12 |
+
--accent-soft: rgba(16, 185, 129, 0.12);
|
| 13 |
+
--indigo: #6366f1;
|
| 14 |
+
--violet: #7c5cdc;
|
| 15 |
+
--dark: #0a0f1a;
|
| 16 |
+
--radius: 18px;
|
| 17 |
+
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05);
|
| 18 |
+
--shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 12px 32px -12px rgba(15, 23, 42, 0.12);
|
| 19 |
+
--shadow-lg: 0 24px 60px -24px rgba(15, 23, 42, 0.32);
|
| 20 |
+
--font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
| 21 |
+
--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
| 22 |
+
--ease: cubic-bezier(0.2, 0.7, 0.2, 1);
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
*, *::before, *::after { box-sizing: border-box; }
|
| 26 |
+
|
| 27 |
+
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
|
| 28 |
+
|
| 29 |
+
body {
|
| 30 |
+
margin: 0;
|
| 31 |
+
font-family: var(--font);
|
| 32 |
+
font-size: 16px;
|
| 33 |
+
line-height: 1.6;
|
| 34 |
+
color: var(--ink);
|
| 35 |
+
background: var(--bg);
|
| 36 |
+
-webkit-font-smoothing: antialiased;
|
| 37 |
+
text-rendering: optimizeLegibility;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
body.menu-open { overflow: hidden; }
|
| 41 |
+
|
| 42 |
+
img, svg { display: block; max-width: 100%; }
|
| 43 |
+
a { color: inherit; text-decoration: none; }
|
| 44 |
+
h1, h2, h3 { margin: 0; line-height: 1.22; }
|
| 45 |
+
p { margin: 0; }
|
| 46 |
+
|
| 47 |
+
.container { width: min(1200px, 100% - 48px); margin-inline: auto; }
|
| 48 |
+
|
| 49 |
+
section[id] { scroll-margin-top: 72px; }
|
| 50 |
+
|
| 51 |
+
.skip-link {
|
| 52 |
+
position: absolute;
|
| 53 |
+
left: 16px;
|
| 54 |
+
top: -48px;
|
| 55 |
+
z-index: 100;
|
| 56 |
+
padding: 10px 14px;
|
| 57 |
+
border-radius: 10px;
|
| 58 |
+
background: var(--ink);
|
| 59 |
+
color: #fff;
|
| 60 |
+
font-weight: 600;
|
| 61 |
+
}
|
| 62 |
+
.skip-link:focus { top: 12px; }
|
| 63 |
+
|
| 64 |
+
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
|
| 65 |
+
|
| 66 |
+
/* Buttons */
|
| 67 |
+
.btn {
|
| 68 |
+
display: inline-flex;
|
| 69 |
+
align-items: center;
|
| 70 |
+
justify-content: center;
|
| 71 |
+
gap: 8px;
|
| 72 |
+
height: 46px;
|
| 73 |
+
padding: 0 22px;
|
| 74 |
+
border-radius: 999px;
|
| 75 |
+
border: 1px solid transparent;
|
| 76 |
+
font: 600 15px/1 var(--font);
|
| 77 |
+
letter-spacing: -0.005em;
|
| 78 |
+
cursor: pointer;
|
| 79 |
+
transition: transform 0.2s var(--ease), background-color 0.2s, box-shadow 0.2s, border-color 0.2s;
|
| 80 |
+
}
|
| 81 |
+
.btn svg { width: 18px; height: 18px; transition: transform 0.2s var(--ease); }
|
| 82 |
+
.btn:hover svg { transform: translateX(2px); }
|
| 83 |
+
.btn:hover { transform: translateY(-1px); }
|
| 84 |
+
.btn-sm { height: 38px; padding: 0 16px; font-size: 14px; }
|
| 85 |
+
.btn-dark { background: var(--ink); color: #fff; box-shadow: 0 8px 20px -10px rgba(11, 18, 32, 0.6); }
|
| 86 |
+
.btn-dark:hover { background: #1b2538; }
|
| 87 |
+
.btn-ghost { background: rgba(255, 255, 255, 0.75); border-color: var(--line); color: var(--ink); }
|
| 88 |
+
.btn-ghost:hover { border-color: #c9d2cc; background: #fff; }
|
| 89 |
+
.btn-light { background: #fff; color: var(--ink); }
|
| 90 |
+
.btn-light:hover { box-shadow: 0 10px 30px -10px rgba(16, 185, 129, 0.6); }
|
| 91 |
+
.btn-outline-light { border-color: rgba(255, 255, 255, 0.28); color: #fff; }
|
| 92 |
+
.btn-outline-light:hover { border-color: rgba(255, 255, 255, 0.6); }
|
| 93 |
+
|
| 94 |
+
/* Navigation */
|
| 95 |
+
.nav {
|
| 96 |
+
position: sticky;
|
| 97 |
+
top: 0;
|
| 98 |
+
z-index: 50;
|
| 99 |
+
background: rgba(246, 247, 244, 0.78);
|
| 100 |
+
-webkit-backdrop-filter: saturate(1.5) blur(14px);
|
| 101 |
+
backdrop-filter: saturate(1.5) blur(14px);
|
| 102 |
+
border-bottom: 1px solid transparent;
|
| 103 |
+
transition: border-color 0.25s, box-shadow 0.25s;
|
| 104 |
+
}
|
| 105 |
+
.nav.is-scrolled { border-bottom-color: var(--line); box-shadow: 0 8px 24px -18px rgba(15, 23, 42, 0.35); }
|
| 106 |
+
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 66px; gap: 24px; }
|
| 107 |
+
.brand { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
|
| 108 |
+
.brand-mark { width: 30px; height: 30px; flex: none; }
|
| 109 |
+
.nav-links { display: flex; gap: 30px; font-size: 14.5px; font-weight: 500; color: var(--ink-2); }
|
| 110 |
+
.nav-links a { position: relative; padding: 6px 0; transition: color 0.2s; }
|
| 111 |
+
.nav-links a::after {
|
| 112 |
+
content: "";
|
| 113 |
+
position: absolute;
|
| 114 |
+
left: 0;
|
| 115 |
+
right: 0;
|
| 116 |
+
bottom: 0;
|
| 117 |
+
height: 2px;
|
| 118 |
+
border-radius: 2px;
|
| 119 |
+
background: var(--accent);
|
| 120 |
+
transform: scaleX(0);
|
| 121 |
+
transition: transform 0.25s var(--ease);
|
| 122 |
+
}
|
| 123 |
+
.nav-links a:hover, .nav-links a.is-active { color: var(--ink); }
|
| 124 |
+
.nav-links a.is-active::after { transform: scaleX(1); }
|
| 125 |
+
.nav-cta { display: flex; align-items: center; gap: 10px; }
|
| 126 |
+
.nav-toggle {
|
| 127 |
+
display: none;
|
| 128 |
+
width: 40px;
|
| 129 |
+
height: 40px;
|
| 130 |
+
border-radius: 12px;
|
| 131 |
+
border: 1px solid var(--line);
|
| 132 |
+
background: #fff;
|
| 133 |
+
cursor: pointer;
|
| 134 |
+
flex-direction: column;
|
| 135 |
+
align-items: center;
|
| 136 |
+
justify-content: center;
|
| 137 |
+
gap: 5px;
|
| 138 |
+
}
|
| 139 |
+
.nav-toggle span { width: 16px; height: 2px; border-radius: 2px; background: var(--ink); transition: transform 0.25s var(--ease); }
|
| 140 |
+
.nav-toggle[aria-expanded="true"] span:first-child { transform: translateY(3.5px) rotate(45deg); }
|
| 141 |
+
.nav-toggle[aria-expanded="true"] span:last-child { transform: translateY(-3.5px) rotate(-45deg); }
|
| 142 |
+
.mobile-menu {
|
| 143 |
+
display: grid;
|
| 144 |
+
gap: 4px;
|
| 145 |
+
padding: 12px 24px 24px;
|
| 146 |
+
border-top: 1px solid var(--line);
|
| 147 |
+
background: var(--bg);
|
| 148 |
+
}
|
| 149 |
+
.mobile-menu[hidden] { display: none; }
|
| 150 |
+
.mobile-menu a:not(.btn) { padding: 12px 4px; font-size: 17px; font-weight: 600; border-bottom: 1px solid var(--line); }
|
| 151 |
+
.mobile-menu .btn { margin-top: 14px; }
|
| 152 |
+
|
| 153 |
+
/* Hero */
|
| 154 |
+
.hero {
|
| 155 |
+
position: relative;
|
| 156 |
+
isolation: isolate;
|
| 157 |
+
overflow: hidden;
|
| 158 |
+
display: flex;
|
| 159 |
+
align-items: center;
|
| 160 |
+
min-height: clamp(640px, 88vh, 840px);
|
| 161 |
+
}
|
| 162 |
+
.hero::before {
|
| 163 |
+
content: "";
|
| 164 |
+
position: absolute;
|
| 165 |
+
inset: 0;
|
| 166 |
+
z-index: -3;
|
| 167 |
+
background-image:
|
| 168 |
+
linear-gradient(rgba(15, 23, 42, 0.045) 1px, transparent 1px),
|
| 169 |
+
linear-gradient(90deg, rgba(15, 23, 42, 0.045) 1px, transparent 1px);
|
| 170 |
+
background-size: 56px 56px;
|
| 171 |
+
-webkit-mask-image: radial-gradient(75% 65% at 45% 45%, #000 35%, transparent 100%);
|
| 172 |
+
mask-image: radial-gradient(75% 65% at 45% 45%, #000 35%, transparent 100%);
|
| 173 |
+
}
|
| 174 |
+
.hero-glow {
|
| 175 |
+
position: absolute;
|
| 176 |
+
inset: 0;
|
| 177 |
+
z-index: -2;
|
| 178 |
+
background:
|
| 179 |
+
radial-gradient(38% 48% at 14% 28%, rgba(16, 185, 129, 0.17), transparent 70%),
|
| 180 |
+
radial-gradient(34% 44% at 84% 36%, rgba(99, 102, 241, 0.15), transparent 70%),
|
| 181 |
+
radial-gradient(30% 34% at 52% 96%, rgba(20, 184, 166, 0.12), transparent 70%);
|
| 182 |
+
}
|
| 183 |
+
.hero-canvas { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; }
|
| 184 |
+
.hero-inner { position: relative; }
|
| 185 |
+
.hero-copy { max-width: 610px; padding: 64px 0 80px; }
|
| 186 |
+
|
| 187 |
+
.eyebrow {
|
| 188 |
+
display: inline-flex;
|
| 189 |
+
align-items: center;
|
| 190 |
+
gap: 10px;
|
| 191 |
+
padding: 7px 14px 7px 10px;
|
| 192 |
+
border-radius: 999px;
|
| 193 |
+
background: rgba(255, 255, 255, 0.75);
|
| 194 |
+
border: 1px solid var(--line);
|
| 195 |
+
font-size: 12.5px;
|
| 196 |
+
font-weight: 600;
|
| 197 |
+
letter-spacing: 0.06em;
|
| 198 |
+
text-transform: uppercase;
|
| 199 |
+
color: var(--accent-deep);
|
| 200 |
+
box-shadow: var(--shadow-sm);
|
| 201 |
+
}
|
| 202 |
+
.pulse-dot {
|
| 203 |
+
width: 8px;
|
| 204 |
+
height: 8px;
|
| 205 |
+
border-radius: 50%;
|
| 206 |
+
background: var(--accent);
|
| 207 |
+
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5);
|
| 208 |
+
animation: ping 2.2s infinite;
|
| 209 |
+
}
|
| 210 |
+
@keyframes ping {
|
| 211 |
+
0% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.45); }
|
| 212 |
+
70% { box-shadow: 0 0 0 9px rgba(16, 185, 129, 0); }
|
| 213 |
+
100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
.hero h1 {
|
| 217 |
+
margin: 22px 0 22px;
|
| 218 |
+
font-size: clamp(42px, 5.7vw, 72px);
|
| 219 |
+
line-height: 1.02;
|
| 220 |
+
font-weight: 800;
|
| 221 |
+
letter-spacing: -0.04em;
|
| 222 |
+
}
|
| 223 |
+
.hero h1 mark {
|
| 224 |
+
color: inherit;
|
| 225 |
+
background: linear-gradient(transparent 56%, rgba(16, 185, 129, 0.3) 56%, rgba(16, 185, 129, 0.3) 92%, transparent 92%);
|
| 226 |
+
padding: 0 0.06em;
|
| 227 |
+
}
|
| 228 |
+
.lede { font-size: clamp(17px, 1.45vw, 19.5px); line-height: 1.6; color: var(--ink-2); max-width: 570px; }
|
| 229 |
+
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
|
| 230 |
+
.hero-actions.center { justify-content: center; }
|
| 231 |
+
.hero-proof { display: flex; flex-wrap: wrap; gap: 10px 22px; margin: 30px 0 0; padding: 0; list-style: none; font-size: 14px; font-weight: 500; color: var(--ink-2); }
|
| 232 |
+
.hero-proof li { display: inline-flex; align-items: center; gap: 7px; }
|
| 233 |
+
.hero-proof svg { width: 18px; height: 18px; color: var(--accent); }
|
| 234 |
+
|
| 235 |
+
.tier-badges {
|
| 236 |
+
position: absolute;
|
| 237 |
+
top: 50%;
|
| 238 |
+
right: max(24px, calc((100% - 1200px) / 2));
|
| 239 |
+
z-index: 2;
|
| 240 |
+
display: grid;
|
| 241 |
+
gap: clamp(20px, 4.4vh, 40px);
|
| 242 |
+
margin: 0;
|
| 243 |
+
padding: 0;
|
| 244 |
+
list-style: none;
|
| 245 |
+
transform: translateY(-50%);
|
| 246 |
+
}
|
| 247 |
+
.tier-badges li {
|
| 248 |
+
display: flex;
|
| 249 |
+
align-items: center;
|
| 250 |
+
gap: 10px;
|
| 251 |
+
min-width: 150px;
|
| 252 |
+
padding: 8px 14px 8px 8px;
|
| 253 |
+
border-radius: 12px;
|
| 254 |
+
border: 1px solid var(--line);
|
| 255 |
+
background: rgba(255, 255, 255, 0.9);
|
| 256 |
+
font-size: 13.5px;
|
| 257 |
+
font-weight: 600;
|
| 258 |
+
box-shadow: 0 6px 18px -10px rgba(15, 23, 42, 0.3);
|
| 259 |
+
transition: transform 0.35s var(--ease), box-shadow 0.35s, border-color 0.35s;
|
| 260 |
+
}
|
| 261 |
+
.tier-badges li.glow { transform: translateX(-4px); border-color: color-mix(in srgb, var(--tier) 45%, white); box-shadow: 0 10px 26px -12px color-mix(in srgb, var(--tier) 70%, transparent); }
|
| 262 |
+
.tier-num {
|
| 263 |
+
display: grid;
|
| 264 |
+
place-items: center;
|
| 265 |
+
width: 30px;
|
| 266 |
+
height: 24px;
|
| 267 |
+
border-radius: 7px;
|
| 268 |
+
background: var(--tier);
|
| 269 |
+
color: #fff;
|
| 270 |
+
font: 700 11px/1 var(--mono);
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
/* Marquee */
|
| 274 |
+
.marquee { padding: 26px 0 30px; border-block: 1px solid var(--line); background: rgba(255, 255, 255, 0.55); }
|
| 275 |
+
.marquee-title { text-align: center; font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; }
|
| 276 |
+
.marquee-track {
|
| 277 |
+
display: flex;
|
| 278 |
+
overflow: hidden;
|
| 279 |
+
-webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
|
| 280 |
+
mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
|
| 281 |
+
}
|
| 282 |
+
.marquee-track ul {
|
| 283 |
+
display: flex;
|
| 284 |
+
flex: none;
|
| 285 |
+
gap: 52px;
|
| 286 |
+
margin: 0;
|
| 287 |
+
padding: 0 52px 0 0;
|
| 288 |
+
list-style: none;
|
| 289 |
+
animation: marquee 46s linear infinite;
|
| 290 |
+
}
|
| 291 |
+
.marquee-track li { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; color: #8c97a6; white-space: nowrap; }
|
| 292 |
+
@keyframes marquee { to { transform: translateX(-100%); } }
|
| 293 |
+
|
| 294 |
+
/* Sections */
|
| 295 |
+
.section { padding: clamp(80px, 10vw, 128px) 0; }
|
| 296 |
+
.section-tint { background: var(--tint); }
|
| 297 |
+
.section-head { max-width: 760px; margin-bottom: 52px; }
|
| 298 |
+
.kicker { font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-deep); margin-bottom: 14px; }
|
| 299 |
+
.section h2 { font-size: clamp(32px, 3.6vw, 48px); line-height: 1.08; font-weight: 800; letter-spacing: -0.035em; }
|
| 300 |
+
.sub { margin-top: 18px; font-size: 17.5px; color: var(--ink-2); max-width: 680px; }
|
| 301 |
+
|
| 302 |
+
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
|
| 303 |
+
.value-card {
|
| 304 |
+
padding: 28px 26px;
|
| 305 |
+
border-radius: var(--radius);
|
| 306 |
+
border: 1px solid var(--line);
|
| 307 |
+
background: var(--surface);
|
| 308 |
+
box-shadow: var(--shadow-sm);
|
| 309 |
+
transition: transform 0.3s var(--ease), box-shadow 0.3s;
|
| 310 |
+
}
|
| 311 |
+
.value-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
|
| 312 |
+
.value-card h3 { margin: 20px 0 10px; font-size: 18px; letter-spacing: -0.02em; }
|
| 313 |
+
.value-card p { font-size: 15px; color: var(--muted); }
|
| 314 |
+
.icon-tile { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 14px; background: var(--accent-soft); color: var(--accent-deep); }
|
| 315 |
+
.icon-tile svg { width: 24px; height: 24px; }
|
| 316 |
+
|
| 317 |
+
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
|
| 318 |
+
.chip-row li { padding: 6px 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--tint-2); font-size: 13px; font-weight: 500; color: var(--ink-2); }
|
| 319 |
+
|
| 320 |
+
/* Capability tabs */
|
| 321 |
+
.tabs { display: grid; grid-template-columns: 300px 1fr; gap: 28px; align-items: start; }
|
| 322 |
+
.tab-list { display: flex; flex-direction: column; gap: 6px; }
|
| 323 |
+
.tab {
|
| 324 |
+
display: flex;
|
| 325 |
+
align-items: center;
|
| 326 |
+
gap: 12px;
|
| 327 |
+
width: 100%;
|
| 328 |
+
padding: 12px 14px;
|
| 329 |
+
border: 1px solid transparent;
|
| 330 |
+
border-radius: 14px;
|
| 331 |
+
background: transparent;
|
| 332 |
+
color: var(--ink-2);
|
| 333 |
+
font: 600 15px/1.3 var(--font);
|
| 334 |
+
text-align: left;
|
| 335 |
+
cursor: pointer;
|
| 336 |
+
transition: background-color 0.2s, border-color 0.2s, box-shadow 0.2s, color 0.2s;
|
| 337 |
+
}
|
| 338 |
+
.tab:hover { background: rgba(255, 255, 255, 0.6); }
|
| 339 |
+
.tab[aria-selected="true"] { background: var(--surface); border-color: var(--line); color: var(--ink); box-shadow: var(--shadow); }
|
| 340 |
+
.tab-icon { display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 11px; background: rgba(15, 23, 42, 0.05); color: var(--muted); transition: background-color 0.2s, color 0.2s; }
|
| 341 |
+
.tab-icon svg { width: 21px; height: 21px; }
|
| 342 |
+
.tab[aria-selected="true"] .tab-icon { background: var(--accent-soft); color: var(--accent-deep); }
|
| 343 |
+
|
| 344 |
+
.tab-panels { border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); padding: 34px; }
|
| 345 |
+
.tab-panel { display: grid; grid-template-columns: 1fr 1.08fr; gap: 34px; align-items: center; }
|
| 346 |
+
.tab-panel[hidden] { display: none; }
|
| 347 |
+
.tab-panel.is-active { animation: panel-in 0.45s var(--ease); }
|
| 348 |
+
@keyframes panel-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
| 349 |
+
.panel-copy h3 { font-size: 24px; letter-spacing: -0.025em; }
|
| 350 |
+
.panel-copy > p { margin-top: 10px; color: var(--muted); font-size: 15.5px; }
|
| 351 |
+
.panel-copy .chip-row { margin-top: 18px; }
|
| 352 |
+
.spec { margin: 22px 0 0; }
|
| 353 |
+
.spec div { display: grid; grid-template-columns: 118px 1fr; gap: 14px; padding: 13px 0; border-top: 1px solid var(--line); }
|
| 354 |
+
.spec dt { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); padding-top: 2px; }
|
| 355 |
+
.spec dd { margin: 0; font-size: 15px; color: var(--ink-2); }
|
| 356 |
+
|
| 357 |
+
/* Mockups */
|
| 358 |
+
.mock { position: relative; overflow: hidden; border-radius: 16px; border: 1px solid var(--line); background: #fff; box-shadow: var(--shadow-lg); }
|
| 359 |
+
.mock-bar { display: flex; align-items: center; gap: 6px; padding: 11px 14px; border-bottom: 1px solid var(--line); background: #f7f9f8; }
|
| 360 |
+
.mock-bar i { width: 10px; height: 10px; border-radius: 50%; background: #dfe4e1; }
|
| 361 |
+
.mock-bar em { margin-left: 8px; font: 500 11.5px var(--mono); font-style: normal; color: var(--muted); }
|
| 362 |
+
.mock-bar.dark { background: #0f172a; border-color: #1e293b; }
|
| 363 |
+
.mock-bar.dark i { background: #334155; }
|
| 364 |
+
.mock-bar.dark em { color: #94a3b8; }
|
| 365 |
+
.mock-chip {
|
| 366 |
+
position: absolute;
|
| 367 |
+
right: 14px;
|
| 368 |
+
bottom: 14px;
|
| 369 |
+
padding: 7px 12px;
|
| 370 |
+
border-radius: 999px;
|
| 371 |
+
border: 1px solid #a7f3d0;
|
| 372 |
+
background: #ecfdf5;
|
| 373 |
+
color: var(--accent-deep);
|
| 374 |
+
font-size: 12px;
|
| 375 |
+
font-weight: 700;
|
| 376 |
+
box-shadow: 0 8px 18px -10px rgba(4, 120, 87, 0.5);
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
.mock-terminal { background: #0b1220; border-color: #1e293b; }
|
| 380 |
+
.term { margin: 0; padding: 18px 20px 24px; min-height: 250px; font: 12.5px/1.8 var(--mono); color: #e2e8f0; }
|
| 381 |
+
.term code { white-space: normal; }
|
| 382 |
+
.term .t-line { display: block; white-space: pre-wrap; overflow-wrap: anywhere; }
|
| 383 |
+
.js .term .t-line { opacity: 0; transform: translateY(4px); }
|
| 384 |
+
.js .is-active .term .t-line { animation: line-in 0.45s var(--ease) forwards; animation-delay: calc(var(--i) * 0.32s + 0.15s); }
|
| 385 |
+
@keyframes line-in { to { opacity: 1; transform: none; } }
|
| 386 |
+
.term b { color: #34d399; font-weight: 600; }
|
| 387 |
+
.t-dim { color: #8b9ab0; }
|
| 388 |
+
.t-verify { color: #a5b4fc; margin-top: 8px; }
|
| 389 |
+
.t-ok { color: #34d399; font-weight: 600; }
|
| 390 |
+
|
| 391 |
+
.mock-plot svg { padding: 6px 8px 40px; }
|
| 392 |
+
.mock-plot .axis, .mock-split .axis { stroke: #cfd6d2; stroke-width: 1; }
|
| 393 |
+
.wave { fill: none; stroke-width: 2; stroke-linejoin: round; }
|
| 394 |
+
.wave-a { stroke: #14b8a6; opacity: 0.85; }
|
| 395 |
+
.wave-b { stroke: #6366f1; opacity: 0.7; }
|
| 396 |
+
.wave-hidden { stroke: #7c5cdc; stroke-dasharray: 5 5; opacity: 0.85; }
|
| 397 |
+
.wave-recon { stroke: #10b981; stroke-width: 3; opacity: 0.95; }
|
| 398 |
+
.js .wave-recon { stroke-dasharray: 1; stroke-dashoffset: 1; }
|
| 399 |
+
.js .is-active .wave-recon { animation: draw 1.8s 0.5s var(--ease) forwards; }
|
| 400 |
+
.legend text { font: 500 9.5px var(--font); fill: var(--muted); }
|
| 401 |
+
.lg-a { fill: #14b8a6; }
|
| 402 |
+
.lg-b { fill: #6366f1; }
|
| 403 |
+
.lg-h { fill: #7c5cdc; }
|
| 404 |
+
@keyframes draw { to { stroke-dashoffset: 0; } }
|
| 405 |
+
|
| 406 |
+
.mock-cad { background: #fbfcfd; }
|
| 407 |
+
.mock-cad svg { padding: 10px 10px 48px; }
|
| 408 |
+
.mock-cad .paper { fill: #fbfcfd; stroke: none; }
|
| 409 |
+
.mock-cad .part { fill: rgba(16, 185, 129, 0.07); stroke: #0b1220; stroke-width: 1.8; stroke-linejoin: round; }
|
| 410 |
+
.js .mock-cad .draw { stroke-dasharray: 1; stroke-dashoffset: 1; }
|
| 411 |
+
.js .is-active .mock-cad .draw { animation: draw 1.5s var(--ease) forwards; }
|
| 412 |
+
.mock-cad .center { stroke: #94a3b8; stroke-width: 0.8; stroke-dasharray: 6 3 1 3; fill: none; }
|
| 413 |
+
.mock-cad .dim { stroke: #64748b; stroke-width: 0.9; fill: none; }
|
| 414 |
+
.mock-cad .arrow { fill: #64748b; }
|
| 415 |
+
.mock-cad .dim-text { font: 600 10px var(--mono); fill: #334155; }
|
| 416 |
+
.mock-cad .cad-section { fill: url(#hatch); stroke: #0b1220; stroke-width: 1.6; }
|
| 417 |
+
.mock-cad .hatch-line { stroke: #a3afbf; stroke-width: 1; }
|
| 418 |
+
.mock-cad .hidden-line { stroke: #0b1220; stroke-width: 1; stroke-dasharray: 4 3; fill: none; }
|
| 419 |
+
.mock-cad .label { font: 700 8.5px var(--font); letter-spacing: 0.1em; fill: #64748b; }
|
| 420 |
+
.mock-cad .title-block rect, .mock-cad .title-block path { fill: none; stroke: #9aa6b5; stroke-width: 1; }
|
| 421 |
+
.mock-cad .title-block text { font: 600 8.5px var(--mono); fill: #334155; }
|
| 422 |
+
|
| 423 |
+
.mock-browser .url { margin-left: 10px; padding: 4px 12px; border-radius: 999px; border: 1px solid var(--line); background: #fff; font: 500 11.5px var(--mono); color: var(--ink-2); }
|
| 424 |
+
.browser-body { position: relative; min-height: 292px; padding: 16px; background: linear-gradient(#fff, #f8faf9); }
|
| 425 |
+
.sk-head { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
|
| 426 |
+
.sk-logo { width: 26px; height: 26px; border-radius: 8px; background: linear-gradient(135deg, #10b981, #6366f1); }
|
| 427 |
+
.sk-pill { width: 64px; height: 10px; border-radius: 6px; background: #e3e8e5; }
|
| 428 |
+
.sk-pill.short { width: 40px; margin-left: auto; background: #0b1220; height: 22px; border-radius: 999px; }
|
| 429 |
+
.sk-grid { display: grid; grid-template-columns: 92px 1fr; gap: 14px; }
|
| 430 |
+
.sk-side { display: grid; gap: 10px; align-content: start; padding: 12px; border-radius: 12px; background: #f1f4f2; }
|
| 431 |
+
.sk-side span { height: 9px; border-radius: 5px; background: #d9e0dc; }
|
| 432 |
+
.sk-side span.short { width: 60%; }
|
| 433 |
+
.sk-main { display: grid; gap: 9px; padding: 12px; border-radius: 12px; border: 1px solid var(--line); background: #fff; }
|
| 434 |
+
.sk-row { height: 22px; border-radius: 7px; background: #f1f4f2; }
|
| 435 |
+
.sk-row.head { background: #e6f7f0; }
|
| 436 |
+
.sk-row.short { width: 70%; }
|
| 437 |
+
.checklist {
|
| 438 |
+
position: absolute;
|
| 439 |
+
right: 14px;
|
| 440 |
+
bottom: 14px;
|
| 441 |
+
display: grid;
|
| 442 |
+
gap: 7px;
|
| 443 |
+
max-width: 280px;
|
| 444 |
+
margin: 0;
|
| 445 |
+
padding: 14px 16px;
|
| 446 |
+
list-style: none;
|
| 447 |
+
border-radius: 14px;
|
| 448 |
+
border: 1px solid var(--line);
|
| 449 |
+
background: rgba(255, 255, 255, 0.96);
|
| 450 |
+
box-shadow: var(--shadow-lg);
|
| 451 |
+
font-size: 12.5px;
|
| 452 |
+
font-weight: 500;
|
| 453 |
+
color: var(--ink-2);
|
| 454 |
+
}
|
| 455 |
+
.checklist li { display: flex; gap: 8px; align-items: baseline; }
|
| 456 |
+
.checklist li::before { content: "✓"; flex: none; color: var(--accent); font-weight: 800; }
|
| 457 |
+
.js .checklist li { opacity: 0; transform: translateX(6px); }
|
| 458 |
+
.js .is-active .checklist li { animation: line-in 0.4s var(--ease) forwards; }
|
| 459 |
+
.js .is-active .checklist li:nth-child(1) { animation-delay: 0.35s; }
|
| 460 |
+
.js .is-active .checklist li:nth-child(2) { animation-delay: 0.65s; }
|
| 461 |
+
.js .is-active .checklist li:nth-child(3) { animation-delay: 0.95s; }
|
| 462 |
+
.js .is-active .checklist li:nth-child(4) { animation-delay: 1.25s; }
|
| 463 |
+
|
| 464 |
+
.mock-split { display: grid; grid-template-columns: 1fr; }
|
| 465 |
+
.split-chart { display: grid; place-items: center; padding: 18px 28px 10px; background: #fff; }
|
| 466 |
+
.split-chart svg { width: 100%; max-height: 150px; }
|
| 467 |
+
.bar-a { fill: #a7f3d0; }
|
| 468 |
+
.bar-b { fill: #10b981; }
|
| 469 |
+
.trend { fill: none; stroke: #6366f1; stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
|
| 470 |
+
.split-code { margin: 0; padding: 16px 20px 56px; background: #0b1220; color: #e2e8f0; font: 12px/1.75 var(--mono); white-space: pre-wrap; overflow: hidden; }
|
| 471 |
+
.c-k { color: #c4b5fd; }
|
| 472 |
+
.c-n { color: #fcd34d; }
|
| 473 |
+
.c-s { color: #6ee7b7; }
|
| 474 |
+
|
| 475 |
+
.mock-issue { padding-bottom: 54px; background: #fff; }
|
| 476 |
+
.issue-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--line); font-size: 13.5px; }
|
| 477 |
+
.issue-dot { width: 10px; height: 10px; flex: none; border-radius: 50%; background: #f26b5b; box-shadow: 0 0 0 4px rgba(242, 107, 91, 0.15); }
|
| 478 |
+
.issue-shot { position: relative; height: 120px; margin: 14px 16px; overflow: hidden; border-radius: 10px; border: 1px solid var(--line); background: #f7f9f8; }
|
| 479 |
+
.shot-nav { position: absolute; inset: 0 0 auto 0; height: 22px; background: #fff; border-bottom: 1px solid var(--line); }
|
| 480 |
+
.shot-menu { position: absolute; top: 14px; left: 28%; width: 34%; height: 40px; border-radius: 6px; background: #fff; border: 1px solid #f5b4ab; box-shadow: 0 6px 14px -8px rgba(242, 107, 91, 0.6); }
|
| 481 |
+
.shot-hero { position: absolute; top: 38px; left: 0; right: 0; bottom: 0; background: linear-gradient(120deg, #d1fae5, #e0e7ff); }
|
| 482 |
+
.diff { margin: 0 16px; padding: 14px 16px; border-radius: 10px; background: #0b1220; color: #cbd5e1; font: 11.5px/1.75 var(--mono); }
|
| 483 |
+
.diff code { white-space: normal; }
|
| 484 |
+
.diff span { display: block; white-space: pre-wrap; }
|
| 485 |
+
.d-h { color: #8b9ab0; }
|
| 486 |
+
.d-del { color: #fca5a5; background: rgba(239, 68, 68, 0.12); }
|
| 487 |
+
.d-add { color: #86efac; background: rgba(34, 197, 94, 0.12); }
|
| 488 |
+
|
| 489 |
+
/* Pipeline (dark) */
|
| 490 |
+
.section-dark {
|
| 491 |
+
color: #e5e7eb;
|
| 492 |
+
background:
|
| 493 |
+
radial-gradient(55% 70% at 85% 0%, rgba(99, 102, 241, 0.22), transparent 62%),
|
| 494 |
+
radial-gradient(50% 70% at 0% 100%, rgba(16, 185, 129, 0.18), transparent 62%),
|
| 495 |
+
var(--dark);
|
| 496 |
+
}
|
| 497 |
+
.section-dark h2, .section-dark h3 { color: #fff; }
|
| 498 |
+
.section-dark .kicker { color: #6ee7b7; }
|
| 499 |
+
.section-dark .sub { color: #a7b0bf; }
|
| 500 |
+
.pipeline { position: relative; display: grid; grid-template-columns: repeat(5, 1fr); gap: 24px; margin: 0; padding: 0; list-style: none; }
|
| 501 |
+
.pipeline::before, .pipeline::after {
|
| 502 |
+
content: "";
|
| 503 |
+
position: absolute;
|
| 504 |
+
top: 22px;
|
| 505 |
+
left: 22px;
|
| 506 |
+
right: calc(20% - 22px);
|
| 507 |
+
height: 2px;
|
| 508 |
+
border-radius: 2px;
|
| 509 |
+
}
|
| 510 |
+
.pipeline::before { background: rgba(255, 255, 255, 0.1); }
|
| 511 |
+
.pipeline::after {
|
| 512 |
+
background: linear-gradient(90deg, #10b981, #6366f1);
|
| 513 |
+
transform: scaleX(0);
|
| 514 |
+
transform-origin: left;
|
| 515 |
+
transition: transform 1.8s var(--ease) 0.25s;
|
| 516 |
+
}
|
| 517 |
+
.pipeline.is-visible::after { transform: scaleX(1); }
|
| 518 |
+
.pipeline li { position: relative; }
|
| 519 |
+
.step-dot {
|
| 520 |
+
position: relative;
|
| 521 |
+
z-index: 1;
|
| 522 |
+
display: grid;
|
| 523 |
+
place-items: center;
|
| 524 |
+
width: 44px;
|
| 525 |
+
height: 44px;
|
| 526 |
+
border-radius: 50%;
|
| 527 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 528 |
+
background: #111827;
|
| 529 |
+
color: #fff;
|
| 530 |
+
font: 700 15px/1 var(--mono);
|
| 531 |
+
transition: background 0.5s, box-shadow 0.5s, border-color 0.5s;
|
| 532 |
+
transition-delay: calc(var(--d) * 0.32s + 0.35s);
|
| 533 |
+
}
|
| 534 |
+
.pipeline.is-visible .step-dot { border-color: transparent; background: linear-gradient(135deg, #10b981, #6366f1); box-shadow: 0 0 0 7px rgba(16, 185, 129, 0.12); }
|
| 535 |
+
.pipeline h3 { margin: 22px 0 8px; font-size: 19px; letter-spacing: -0.02em; }
|
| 536 |
+
.pipeline p { font-size: 14.5px; color: #a7b0bf; }
|
| 537 |
+
.gate-row { display: flex; flex-wrap: wrap; gap: 10px; margin: 56px 0 0; padding: 26px 0 0; list-style: none; border-top: 1px solid rgba(255, 255, 255, 0.1); }
|
| 538 |
+
.gate-row li { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(255, 255, 255, 0.04); font-size: 13.5px; font-weight: 500; color: #d7dce4; }
|
| 539 |
+
.gate-row li::before { content: "✓"; color: #34d399; font-weight: 800; }
|
| 540 |
+
|
| 541 |
+
/* Difficulty */
|
| 542 |
+
.diff-grid { display: grid; grid-template-columns: 0.92fr 1.08fr; gap: 56px; align-items: center; }
|
| 543 |
+
.diff-copy .sub + .sub { margin-top: 14px; }
|
| 544 |
+
.slider-card { margin-top: 30px; padding: 22px 22px 20px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); }
|
| 545 |
+
.slider-card label { display: block; margin-bottom: 14px; font-weight: 700; font-size: 15px; }
|
| 546 |
+
.slider-card input[type="range"] { width: 100%; accent-color: var(--accent); cursor: pointer; }
|
| 547 |
+
.slider-ends { display: flex; justify-content: space-between; margin-top: 6px; font-size: 12.5px; color: var(--muted); }
|
| 548 |
+
#ladder-strength-label { font-weight: 700; color: var(--ink); }
|
| 549 |
+
.readout { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); font-size: 15.5px; color: var(--ink-2); }
|
| 550 |
+
.readout strong { color: var(--accent-deep); }
|
| 551 |
+
|
| 552 |
+
.chart-card { margin: 0; padding: 22px 22px 18px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); }
|
| 553 |
+
.chart-card svg { width: 100%; height: auto; }
|
| 554 |
+
.chart-card figcaption { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 12px; font-size: 12.5px; color: var(--ink-2); }
|
| 555 |
+
.legend-item { display: inline-flex; align-items: center; gap: 7px; font-weight: 500; }
|
| 556 |
+
.lg-zone { width: 16px; height: 10px; border-radius: 2px; background: rgba(16, 185, 129, 0.16); border: 1px dashed rgba(4, 120, 87, 0.5); }
|
| 557 |
+
.lg-bar { width: 12px; height: 10px; border-radius: 2px; background: var(--accent); }
|
| 558 |
+
.lg-line { width: 18px; border-top: 2px dashed var(--indigo); }
|
| 559 |
+
.lg-dot { width: 10px; height: 10px; border-radius: 50%; border: 2.5px solid var(--indigo); background: #fff; }
|
| 560 |
+
.chart-card .note { width: 100%; color: var(--muted); font-size: 12px; }
|
| 561 |
+
#ladder-chart .zone { fill: rgba(16, 185, 129, 0.09); }
|
| 562 |
+
#ladder-chart .zone-edge { stroke: rgba(4, 120, 87, 0.35); stroke-dasharray: 3 4; }
|
| 563 |
+
#ladder-chart .zone-label { font: 700 11px var(--font); fill: var(--accent-deep); }
|
| 564 |
+
#ladder-chart .grid { stroke: #e8ece9; }
|
| 565 |
+
#ladder-chart .tick { font: 500 11px var(--font); fill: #7b8794; }
|
| 566 |
+
#ladder-chart .axis-label { font: 600 11.5px var(--font); fill: var(--muted); }
|
| 567 |
+
#ladder-chart .bar { fill: #d6dde3; transition: fill 0.3s; }
|
| 568 |
+
#ladder-chart .bar.in-zone { fill: var(--accent); }
|
| 569 |
+
#ladder-chart .ref-line { fill: none; stroke: var(--indigo); stroke-width: 2; stroke-dasharray: 5 4; }
|
| 570 |
+
#ladder-chart .anchor { fill: #fff; stroke: var(--indigo); stroke-width: 2.5; }
|
| 571 |
+
#ladder-chart .anchor-label { font: 700 11px var(--font); fill: #4338ca; paint-order: stroke; stroke: #fff; stroke-width: 3px; stroke-linejoin: round; }
|
| 572 |
+
|
| 573 |
+
/* Deliverables */
|
| 574 |
+
.deliv-grid { display: grid; grid-template-columns: 1fr 1fr 1.12fr; gap: 20px; }
|
| 575 |
+
.deliv-card { padding: 26px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); transition: transform 0.3s var(--ease), box-shadow 0.3s; }
|
| 576 |
+
.deliv-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
|
| 577 |
+
.deliv-card h3 { position: relative; padding-top: 18px; font-size: 18px; letter-spacing: -0.02em; }
|
| 578 |
+
.deliv-card h3::before { content: ""; position: absolute; top: 0; left: 0; width: 30px; height: 3px; border-radius: 3px; background: linear-gradient(90deg, var(--accent), var(--indigo)); }
|
| 579 |
+
.deliv-card p { margin-top: 10px; font-size: 15px; color: var(--muted); }
|
| 580 |
+
.tree-card { grid-column: 3; grid-row: 1 / span 2; display: flex; align-items: center; padding: 0; overflow: hidden; border-color: #1e293b; background: #0b1220; }
|
| 581 |
+
.tree-card:hover { transform: none; }
|
| 582 |
+
.tree { margin: 0; padding: 24px 24px; overflow-x: auto; font: 12.5px/1.85 var(--mono); color: #cbd5e1; }
|
| 583 |
+
.tr-dir { color: #6ee7b7; font-weight: 600; }
|
| 584 |
+
.tr-c { color: #64748b; }
|
| 585 |
+
|
| 586 |
+
/* Benchmarks */
|
| 587 |
+
.bench-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
| 588 |
+
.bench-group { padding: 26px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); }
|
| 589 |
+
.bench-group h3 { margin-bottom: 16px; font-size: 16.5px; letter-spacing: -0.015em; }
|
| 590 |
+
.bench-group .chip-row li { background: #fff; font-weight: 600; }
|
| 591 |
+
|
| 592 |
+
/* Research */
|
| 593 |
+
.research-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
|
| 594 |
+
.paper-card { display: flex; flex-direction: column; padding: 28px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); }
|
| 595 |
+
.paper-tag { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 596 |
+
.paper-card h3 { margin: 10px 0 12px; font-size: 19px; line-height: 1.3; letter-spacing: -0.02em; }
|
| 597 |
+
.paper-card > p:not(.paper-tag) { color: var(--muted); font-size: 15px; }
|
| 598 |
+
.metrics { display: grid; grid-template-columns: 1fr; gap: 10px; margin: 22px 0 24px; }
|
| 599 |
+
.metrics div { display: grid; grid-template-columns: 104px 1fr; align-items: center; gap: 14px; padding: 12px 14px; border-radius: 14px; background: var(--tint); }
|
| 600 |
+
.metrics dt { font-size: 20px; font-weight: 800; letter-spacing: -0.03em; color: var(--accent-deep); line-height: 1.15; white-space: nowrap; }
|
| 601 |
+
.metrics dd { margin: 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
|
| 602 |
+
/* Engagement */
|
| 603 |
+
.engage-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
| 604 |
+
.engage-card { position: relative; overflow: hidden; padding: 30px 28px; border-radius: 22px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); transition: transform 0.3s var(--ease), box-shadow 0.3s; }
|
| 605 |
+
.engage-card::after { content: ""; position: absolute; right: -60px; top: -60px; width: 160px; height: 160px; border-radius: 50%; background: radial-gradient(circle, rgba(16, 185, 129, 0.16), transparent 70%); transition: transform 0.5s var(--ease); }
|
| 606 |
+
.engage-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
|
| 607 |
+
.engage-card:hover::after { transform: scale(1.3); }
|
| 608 |
+
.engage-num { font: 700 13px var(--mono); color: var(--accent-deep); }
|
| 609 |
+
.engage-card h3 { margin: 14px 0 10px; font-size: 22px; letter-spacing: -0.025em; }
|
| 610 |
+
.engage-card p { color: var(--muted); font-size: 15.5px; }
|
| 611 |
+
|
| 612 |
+
/* CTA + footer */
|
| 613 |
+
.cta {
|
| 614 |
+
padding: clamp(84px, 10vw, 124px) 0;
|
| 615 |
+
text-align: center;
|
| 616 |
+
color: #fff;
|
| 617 |
+
background:
|
| 618 |
+
radial-gradient(60% 110% at 50% 0%, rgba(16, 185, 129, 0.3), transparent 62%),
|
| 619 |
+
radial-gradient(45% 90% at 100% 100%, rgba(99, 102, 241, 0.32), transparent 62%),
|
| 620 |
+
var(--dark);
|
| 621 |
+
}
|
| 622 |
+
.cta h2 { max-width: 820px; margin-inline: auto; font-size: clamp(32px, 4.2vw, 52px); line-height: 1.08; font-weight: 800; letter-spacing: -0.035em; }
|
| 623 |
+
.cta p { max-width: 640px; margin: 18px auto 0; font-size: 17.5px; color: #b7c0cd; }
|
| 624 |
+
.footer { padding: 30px 0 34px; background: var(--dark); border-top: 1px solid rgba(255, 255, 255, 0.08); color: #9aa4b2; }
|
| 625 |
+
.footer-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 18px; }
|
| 626 |
+
.footer .brand { color: #fff; }
|
| 627 |
+
.footer-links { display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px; }
|
| 628 |
+
.footer-links a:hover { color: #fff; }
|
| 629 |
+
.footer-note { width: 100%; font-size: 12.5px; color: #6b7686; }
|
| 630 |
+
|
| 631 |
+
/* Offerings */
|
| 632 |
+
.offer-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
|
| 633 |
+
.offer-card { display: flex; flex-direction: column; overflow: hidden; border-radius: 22px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-sm); transition: transform 0.3s var(--ease), box-shadow 0.3s; }
|
| 634 |
+
.offer-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
|
| 635 |
+
.offer-card h3 { margin: 22px 26px 8px; font-size: 24px; letter-spacing: -0.025em; }
|
| 636 |
+
.offer-card > p { margin: 0 26px; font-size: 15.5px; color: var(--muted); }
|
| 637 |
+
.offer-top { display: grid; align-content: center; height: 176px; border-bottom: 1px solid var(--line); }
|
| 638 |
+
.offer-terminal, .offer-code { gap: 2px; padding: 18px 22px; background: #0b1220; border-color: #1e293b; color: #dbe3ee; font: 11.5px/1.7 var(--mono); white-space: pre; overflow: hidden; }
|
| 639 |
+
.offer-terminal b { color: #34d399; }
|
| 640 |
+
.offer-terminal .dim { color: #8b9ab0; }
|
| 641 |
+
.offer-terminal .ok { color: #34d399; font-weight: 600; }
|
| 642 |
+
.offer-code i { font-style: normal; }
|
| 643 |
+
.offer-visual { background: linear-gradient(180deg, #f5f3ff, #fff); }
|
| 644 |
+
.offer-visual img { width: 100%; height: 176px; object-fit: cover; }
|
| 645 |
+
.offer-list { display: grid; gap: 9px; margin: 18px 26px 26px; padding: 18px 0 0; list-style: none; border-top: 1px solid var(--line); font-size: 14.5px; font-weight: 500; color: var(--ink-2); }
|
| 646 |
+
.offer-list li { display: flex; gap: 10px; align-items: baseline; }
|
| 647 |
+
.offer-list li::before { content: "✓"; flex: none; color: var(--accent); font-weight: 800; }
|
| 648 |
+
.offer-band { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 18px; margin-top: 28px; padding: 18px 22px; border-radius: 18px; border: 1px dashed #c9d6cf; background: rgba(255, 255, 255, 0.6); }
|
| 649 |
+
.offer-band > span { font-size: 13px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 650 |
+
.offer-band ul { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
|
| 651 |
+
.offer-band li { padding: 7px 14px; border-radius: 999px; background: var(--ink); color: #fff; font-size: 13.5px; font-weight: 600; }
|
| 652 |
+
|
| 653 |
+
/* Examples */
|
| 654 |
+
.ex-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
|
| 655 |
+
.ex-card {
|
| 656 |
+
position: relative;
|
| 657 |
+
display: flex;
|
| 658 |
+
flex-direction: column;
|
| 659 |
+
overflow: hidden;
|
| 660 |
+
border-radius: 20px;
|
| 661 |
+
border: 1px solid var(--line);
|
| 662 |
+
background: var(--surface);
|
| 663 |
+
box-shadow: var(--shadow-sm);
|
| 664 |
+
cursor: pointer;
|
| 665 |
+
transition: transform 0.3s var(--ease), box-shadow 0.3s, border-color 0.3s;
|
| 666 |
+
}
|
| 667 |
+
.ex-card:hover, .ex-card:focus-visible { transform: translateY(-4px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--dc) 35%, var(--line)); }
|
| 668 |
+
.ex-card:focus-visible { outline: 2px solid var(--dc); outline-offset: 3px; }
|
| 669 |
+
.ex-card.is-extra { display: none; }
|
| 670 |
+
.ex-grid.show-all .ex-card.is-extra { display: flex; }
|
| 671 |
+
.ex-thumb { aspect-ratio: 740 / 394; overflow: hidden; border-bottom: 1px solid var(--line); background: #f7f8fb; }
|
| 672 |
+
.ex-thumb > img { width: 100%; height: 100%; object-fit: cover; }
|
| 673 |
+
.ex-card:hover .ex-thumb > img { transform: scale(1.04); }
|
| 674 |
+
.ex-card-body { display: flex; flex: 1; flex-direction: column; padding: 18px 20px 20px; }
|
| 675 |
+
.ex-card-domain { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: color-mix(in srgb, var(--dc) 80%, #0b1220); }
|
| 676 |
+
.ex-card-domain::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--dc); }
|
| 677 |
+
.ex-card h3 { margin: 8px 0 6px; font-size: 18px; letter-spacing: -0.02em; }
|
| 678 |
+
.ex-card-body > p:not(.ex-card-domain) { font-size: 14px; color: var(--muted); }
|
| 679 |
+
.ex-card-tracks { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 0; padding: 0; list-style: none; }
|
| 680 |
+
.trk { padding: 4px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; }
|
| 681 |
+
.trk-terminal { background: #0b1220; color: #fff; }
|
| 682 |
+
.trk-coding { background: rgba(99, 102, 241, 0.12); color: #4338ca; }
|
| 683 |
+
.trk-multimodal { background: var(--accent-soft); color: var(--accent-deep); }
|
| 684 |
+
.trk-mod { border: 1px solid var(--line); color: var(--ink-2); font-weight: 600; }
|
| 685 |
+
.ex-sw { display: flex; flex-wrap: wrap; gap: 6px; margin: auto 0 0; padding: 14px 0 0; list-style: none; }
|
| 686 |
+
.ex-sw li { padding: 3px 8px; border-radius: 6px; background: var(--tint-2); border: 1px solid var(--line); font: 500 11px var(--mono); color: var(--ink-2); }
|
| 687 |
+
.ex-open { position: absolute; top: 12px; right: 12px; padding: 6px 11px; border-radius: 999px; background: rgba(11, 18, 32, 0.86); color: #fff; font-size: 12px; font-weight: 700; opacity: 0; transform: translateY(-4px); transition: opacity 0.25s, transform 0.25s var(--ease); }
|
| 688 |
+
.ex-card:hover .ex-open, .ex-card:focus-visible .ex-open { opacity: 1; transform: none; }
|
| 689 |
+
.ex-more { display: flex; justify-content: center; margin-top: 30px; }
|
| 690 |
+
.ex-grid.show-all + .ex-more { display: none; }
|
| 691 |
+
|
| 692 |
+
.ex-modal { position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 24px; }
|
| 693 |
+
.ex-modal[hidden] { display: none; }
|
| 694 |
+
.ex-backdrop { position: absolute; inset: 0; background: rgba(8, 12, 22, 0.55); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); animation: fade-in 0.25s ease; }
|
| 695 |
+
.ex-sheet {
|
| 696 |
+
position: relative;
|
| 697 |
+
width: min(1080px, 100%);
|
| 698 |
+
max-height: min(92vh, 980px);
|
| 699 |
+
overflow: auto;
|
| 700 |
+
border-radius: 24px;
|
| 701 |
+
background: var(--surface);
|
| 702 |
+
box-shadow: 0 40px 120px -30px rgba(0, 0, 0, 0.55);
|
| 703 |
+
animation: sheet-in 0.35s var(--ease);
|
| 704 |
+
}
|
| 705 |
+
@keyframes fade-in { from { opacity: 0; } }
|
| 706 |
+
@keyframes sheet-in { from { opacity: 0; transform: translateY(14px) scale(0.985); } }
|
| 707 |
+
.ex-head { position: sticky; top: 0; z-index: 1; display: flex; justify-content: space-between; align-items: flex-start; gap: 18px; padding: 22px 26px 18px; border-bottom: 1px solid var(--line); background: rgba(255, 255, 255, 0.94); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
|
| 708 |
+
.ex-domain { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 700; color: color-mix(in srgb, var(--dc, #10b981) 80%, #0b1220); }
|
| 709 |
+
.ex-domain::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--dc, #10b981); }
|
| 710 |
+
.ex-head h3 { margin: 6px 0 10px; font-size: 24px; letter-spacing: -0.025em; }
|
| 711 |
+
.ex-tracks { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
|
| 712 |
+
.ex-nav { display: flex; gap: 8px; flex: none; }
|
| 713 |
+
.icon-btn { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; border: 1px solid var(--line); background: #fff; font: 600 15px/1 var(--font); color: var(--ink); cursor: pointer; transition: background-color 0.2s, border-color 0.2s; }
|
| 714 |
+
.icon-btn:hover { background: var(--tint-2); border-color: #c9d2cc; }
|
| 715 |
+
.ex-body { padding: 22px 26px 28px; }
|
| 716 |
+
.ex-figure { margin: 0; overflow: hidden; border-radius: 16px; border: 1px solid var(--line); background: #f7f8fb; }
|
| 717 |
+
.ex-figure img { width: 100%; height: auto; }
|
| 718 |
+
.ex-desc { margin-top: 18px; font-size: 16.5px; color: var(--ink-2); }
|
| 719 |
+
.ex-facts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 18px; }
|
| 720 |
+
.ex-facts > div { padding: 14px; border-radius: 14px; border: 1px solid var(--line); background: var(--tint-2); }
|
| 721 |
+
.ex-facts h4 { margin: 0 0 10px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 722 |
+
.ex-facts ul { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
|
| 723 |
+
.ex-facts li { padding: 4px 9px; border-radius: 7px; border: 1px solid var(--line); background: #fff; font: 500 11.5px var(--mono); color: var(--ink-2); }
|
| 724 |
+
.ex-how { margin: 18px 0 20px; padding-left: 14px; border-left: 3px solid var(--accent); font-size: 15px; color: var(--muted); }
|
| 725 |
+
body.modal-open { overflow: hidden; }
|
| 726 |
+
|
| 727 |
+
/* Live example previews */
|
| 728 |
+
.ex-thumb { position: relative; }
|
| 729 |
+
.ex-thumb > img { transition: opacity 0.5s ease, transform 0.6s var(--ease); }
|
| 730 |
+
.ex-thumb.is-live > img { opacity: 0; }
|
| 731 |
+
.ex-live, .ex-live-hero { overflow: hidden; background: radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--dc, #10b981) 13%, #fff) 0%, #fbfcfd 70%); }
|
| 732 |
+
.ex-live { position: absolute; inset: 0; opacity: 0; transition: opacity 0.5s ease; }
|
| 733 |
+
.ex-thumb.is-live .ex-live { opacity: 1; }
|
| 734 |
+
.ex-live-hero { position: relative; aspect-ratio: 16 / 7; border-bottom: 1px solid var(--line); }
|
| 735 |
+
.ex-live-hero[hidden] { display: none; }
|
| 736 |
+
.ex-evidence-label { padding: 12px 16px 0; font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-deep); }
|
| 737 |
+
.ex-live-hero[hidden] + .ex-evidence-label { display: none; }
|
| 738 |
+
.lv-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
|
| 739 |
+
.lv-cap { position: absolute; left: 14px; bottom: 10px; z-index: 2; font: 500 11px var(--mono); color: var(--muted); }
|
| 740 |
+
.ex-live-hero .lv-cap { left: 22px; bottom: 16px; font-size: 12px; }
|
| 741 |
+
[data-kind="drc"] .lv-cap { left: 24px; bottom: 20px; color: #a7f3d0; }
|
| 742 |
+
.ex-live-hero[data-kind="drc"] .lv-cap { left: 40px; bottom: 36px; }
|
| 743 |
+
|
| 744 |
+
.lv-container { position: absolute; inset: 0; display: grid; align-content: center; gap: 6px; width: 74%; margin: auto; transition: opacity 0.3s; }
|
| 745 |
+
.lv-fade .lv-container { opacity: 0; }
|
| 746 |
+
.lv-code { margin-bottom: 4px; font: 600 12px var(--mono); color: #0d9488; }
|
| 747 |
+
.lv-stack { display: grid; gap: 6px; }
|
| 748 |
+
.lv-layer {
|
| 749 |
+
display: flex;
|
| 750 |
+
align-items: center;
|
| 751 |
+
height: 24px;
|
| 752 |
+
margin-left: calc(var(--k) * 16px);
|
| 753 |
+
padding: 0 10px;
|
| 754 |
+
border-radius: 7px;
|
| 755 |
+
border: 1px solid rgba(37, 99, 235, 0.25);
|
| 756 |
+
background: linear-gradient(90deg, rgba(37, 99, 235, 0.16), rgba(37, 99, 235, 0.05));
|
| 757 |
+
font: 500 11px var(--mono);
|
| 758 |
+
color: var(--ink-2);
|
| 759 |
+
opacity: 0;
|
| 760 |
+
transform: translateY(-10px);
|
| 761 |
+
transition: opacity 0.35s, transform 0.35s var(--ease);
|
| 762 |
+
}
|
| 763 |
+
.lv-layer.on { opacity: 1; transform: none; }
|
| 764 |
+
.lv-hash { min-height: 1.6em; margin-top: 6px; font: 500 11px var(--mono); color: var(--muted); }
|
| 765 |
+
.ex-live-hero .lv-container { width: 54%; gap: 8px; }
|
| 766 |
+
.ex-live-hero .lv-layer { height: 34px; margin-left: calc(var(--k) * 26px); font-size: 13px; }
|
| 767 |
+
.ex-live-hero .lv-code, .ex-live-hero .lv-hash { font-size: 13.5px; }
|
| 768 |
+
|
| 769 |
+
.lv-images { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 12px; padding: 18px; }
|
| 770 |
+
.lv-cell { position: relative; overflow: hidden; border-radius: 12px; background: #e9eef2; box-shadow: 0 12px 24px -12px rgba(15, 23, 42, 0.4); }
|
| 771 |
+
.lv-cell img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; opacity: 0; transition: opacity 0.6s ease; }
|
| 772 |
+
.lv-cell img.on { opacity: 1; }
|
| 773 |
+
.lv-micro .lv-cell { width: 25%; aspect-ratio: 1; }
|
| 774 |
+
.lv-astro .lv-cell { width: 18.5%; aspect-ratio: 1; border-radius: 8px; box-shadow: 0 0 30px -6px rgba(249, 140, 10, 0.5); }
|
| 775 |
+
.lv-ocr .lv-cell { width: 84%; aspect-ratio: 237 / 82; border-radius: 8px; }
|
| 776 |
+
.lv-color { display: grid; grid-template-columns: repeat(3, auto); gap: 8px; align-content: center; justify-content: center; }
|
| 777 |
+
.lv-color .lv-cell { width: 62px; height: 62px; border-radius: 10px; transition: transform 0.35s var(--ease), box-shadow 0.35s; }
|
| 778 |
+
.lv-color .lv-cell.hot { transform: translateY(-4px) scale(1.08); box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--dc, #7c3aed), 0 14px 26px -12px rgba(15, 23, 42, 0.5); }
|
| 779 |
+
.ex-live-hero .lv-color .lv-cell { width: 92px; height: 92px; }
|
| 780 |
+
.lv-swatch { position: absolute; right: 5px; bottom: 5px; z-index: 1; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); }
|
| 781 |
+
.lv-scan { position: absolute; left: 0; right: 0; top: 0; z-index: 1; height: 2px; background: var(--dc, #10b981); box-shadow: 0 0 14px 2px var(--dc, #10b981); animation: lv-scan 2.6s ease-in-out infinite; }
|
| 782 |
+
@keyframes lv-scan { 0%, 100% { top: 0; } 50% { top: calc(100% - 2px); } }
|
| 783 |
+
.lv-aperture { position: absolute; left: 50%; top: 50%; z-index: 1; width: 40%; aspect-ratio: 1; border: 1.5px solid rgba(255, 255, 255, 0.92); border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); animation: lv-aperture 2.6s ease-in-out infinite; }
|
| 784 |
+
.lv-aperture::before, .lv-aperture::after { content: ""; position: absolute; left: 50%; top: 50%; background: rgba(255, 255, 255, 0.85); transform: translate(-50%, -50%); }
|
| 785 |
+
.lv-aperture::before { width: 140%; height: 1px; }
|
| 786 |
+
.lv-aperture::after { width: 1px; height: 140%; }
|
| 787 |
+
@keyframes lv-aperture { 0%, 100% { width: 30%; } 50% { width: 58%; } }
|
| 788 |
+
|
| 789 |
+
/* Trajectory scaling */
|
| 790 |
+
.traj-grid { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 56px; align-items: center; }
|
| 791 |
+
.traj-steps { display: grid; gap: 14px; margin: 28px 0 0; padding: 0; list-style: none; counter-reset: step; }
|
| 792 |
+
.traj-steps li { position: relative; padding-left: 46px; font-size: 15.5px; color: var(--ink-2); counter-increment: step; }
|
| 793 |
+
.traj-steps li::before {
|
| 794 |
+
content: counter(step);
|
| 795 |
+
position: absolute;
|
| 796 |
+
left: 0;
|
| 797 |
+
top: -2px;
|
| 798 |
+
display: grid;
|
| 799 |
+
place-items: center;
|
| 800 |
+
width: 30px;
|
| 801 |
+
height: 30px;
|
| 802 |
+
border-radius: 50%;
|
| 803 |
+
background: linear-gradient(135deg, var(--accent), var(--indigo));
|
| 804 |
+
color: #fff;
|
| 805 |
+
font: 700 13px/1 var(--mono);
|
| 806 |
+
}
|
| 807 |
+
.traj-steps strong { color: var(--ink); }
|
| 808 |
+
.traj-visual { padding: 26px; border-radius: 24px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow); }
|
| 809 |
+
.traj-diagram { width: 100%; height: auto; }
|
| 810 |
+
.traj-diagram text { font: 600 11.5px var(--font); fill: var(--ink-2); }
|
| 811 |
+
.traj-diagram .t-stage { font: 700 10.5px var(--font); letter-spacing: 0.1em; text-transform: uppercase; fill: var(--accent-deep); }
|
| 812 |
+
.traj-diagram .t-sub { font: 500 10px var(--mono); fill: var(--muted); }
|
| 813 |
+
.traj-diagram .src-a { fill: #14b8a6; }
|
| 814 |
+
.traj-diagram .src-b { fill: #6366f1; }
|
| 815 |
+
.traj-diagram .src-c { fill: #7c5cdc; }
|
| 816 |
+
.traj-diagram .t-lane { fill: none; stroke-width: 2.5; stroke-dasharray: 5 6; animation: flow 1.6s linear infinite; }
|
| 817 |
+
.traj-diagram .lane-a { stroke: #14b8a6; }
|
| 818 |
+
.traj-diagram .lane-b { stroke: #6366f1; }
|
| 819 |
+
.traj-diagram .lane-c { stroke: #7c5cdc; }
|
| 820 |
+
.traj-diagram .t-node rect { fill: #fff; stroke: #cfd8d3; stroke-width: 1.4; }
|
| 821 |
+
.traj-diagram .t-node-strong rect { fill: #ecfdf5; stroke: var(--accent); }
|
| 822 |
+
.traj-diagram .t-link { fill: none; stroke: #94a3b8; stroke-width: 1.6; }
|
| 823 |
+
.traj-diagram .t-revise { fill: none; stroke: #f26b5b; stroke-width: 1.4; stroke-dasharray: 3 4; }
|
| 824 |
+
.traj-diagram .t-arrow { fill: #94a3b8; }
|
| 825 |
+
.traj-diagram .t-out { fill: none; stroke: var(--accent); stroke-width: 2; stroke-dasharray: 4 5; animation: flow 1.2s linear infinite; }
|
| 826 |
+
.traj-diagram .t-ok circle { fill: var(--accent); }
|
| 827 |
+
@keyframes flow { to { stroke-dashoffset: -22; } }
|
| 828 |
+
.traj-metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin: 22px 0 0; }
|
| 829 |
+
.traj-metrics div { padding: 14px 16px; border-radius: 16px; background: var(--tint); }
|
| 830 |
+
.traj-metrics dt { font-size: 24px; font-weight: 800; letter-spacing: -0.03em; color: var(--accent-deep); white-space: nowrap; }
|
| 831 |
+
.traj-metrics dd { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
|
| 832 |
+
/* Scroll reveal */
|
| 833 |
+
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
|
| 834 |
+
.js .reveal.is-visible { opacity: 1; transform: none; }
|
| 835 |
+
.grid-4 .reveal:nth-child(2), .deliv-grid .reveal:nth-child(2), .engage-grid .reveal:nth-child(2), .bench-grid .reveal:nth-child(2), .research-grid .reveal:nth-child(2) { transition-delay: 0.08s; }
|
| 836 |
+
.grid-4 .reveal:nth-child(3), .deliv-grid .reveal:nth-child(3), .engage-grid .reveal:nth-child(3), .bench-grid .reveal:nth-child(3) { transition-delay: 0.16s; }
|
| 837 |
+
.grid-4 .reveal:nth-child(4), .deliv-grid .reveal:nth-child(4) { transition-delay: 0.24s; }
|
| 838 |
+
.deliv-grid .reveal:nth-child(5) { transition-delay: 0.32s; }
|
| 839 |
+
.deliv-grid .reveal:nth-child(6) { transition-delay: 0.4s; }
|
| 840 |
+
|
| 841 |
+
/* Responsive */
|
| 842 |
+
@media (max-width: 1100px) {
|
| 843 |
+
.nav-links { display: none; }
|
| 844 |
+
.nav-toggle { display: inline-flex; }
|
| 845 |
+
.nav-cta .btn { display: none; }
|
| 846 |
+
.tier-badges { display: none; }
|
| 847 |
+
.hero-canvas { opacity: 0.6; }
|
| 848 |
+
.grid-4 { grid-template-columns: repeat(2, 1fr); }
|
| 849 |
+
.tabs { grid-template-columns: minmax(0, 1fr); }
|
| 850 |
+
.tab-list { flex-direction: row; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
|
| 851 |
+
.tab-list::-webkit-scrollbar { display: none; }
|
| 852 |
+
.tab { width: auto; white-space: nowrap; }
|
| 853 |
+
.tab-panel { grid-template-columns: minmax(0, 1fr); }
|
| 854 |
+
.pipeline { grid-template-columns: repeat(2, 1fr); row-gap: 34px; }
|
| 855 |
+
.pipeline::before, .pipeline::after { display: none; }
|
| 856 |
+
.diff-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
|
| 857 |
+
.deliv-grid { grid-template-columns: repeat(2, 1fr); }
|
| 858 |
+
.tree-card { grid-column: 1 / -1; grid-row: auto; }
|
| 859 |
+
.bench-grid, .research-grid, .engage-grid { grid-template-columns: minmax(0, 1fr); }
|
| 860 |
+
.offer-grid { grid-template-columns: minmax(0, 1fr); max-width: 640px; }
|
| 861 |
+
.ex-grid { grid-template-columns: repeat(2, 1fr); }
|
| 862 |
+
.ex-facts { grid-template-columns: repeat(2, 1fr); }
|
| 863 |
+
.traj-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
@media (max-width: 640px) {
|
| 867 |
+
.container { width: min(1200px, 100% - 36px); }
|
| 868 |
+
.hero { min-height: auto; }
|
| 869 |
+
.hero-copy { padding: 48px 0 64px; }
|
| 870 |
+
.grid-4, .deliv-grid, .pipeline { grid-template-columns: 1fr; }
|
| 871 |
+
.tab-panels { padding: 20px; border-radius: 20px; }
|
| 872 |
+
.spec div { grid-template-columns: 1fr; gap: 4px; }
|
| 873 |
+
.metrics { grid-template-columns: 1fr; }
|
| 874 |
+
.tree { padding: 18px; font-size: 10.5px; }
|
| 875 |
+
.ex-grid, .ex-facts, .traj-metrics { grid-template-columns: 1fr; }
|
| 876 |
+
.ex-modal { padding: 10px; }
|
| 877 |
+
.ex-sheet { max-height: 100%; border-radius: 18px; }
|
| 878 |
+
.ex-head { padding: 16px 16px 14px; }
|
| 879 |
+
.ex-head h3 { font-size: 20px; }
|
| 880 |
+
.ex-body { padding: 16px; }
|
| 881 |
+
.metrics div { grid-template-columns: 88px 1fr; }
|
| 882 |
+
.traj-visual { padding: 16px; }
|
| 883 |
+
.checklist { position: static; margin-top: 14px; max-width: none; }
|
| 884 |
+
.paper-card { padding: 24px; }
|
| 885 |
+
}
|
| 886 |
+
|
| 887 |
+
@media (prefers-reduced-motion: reduce) {
|
| 888 |
+
html { scroll-behavior: auto; }
|
| 889 |
+
*, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; transition-delay: 0s !important; }
|
| 890 |
+
.marquee-track ul { animation: none; }
|
| 891 |
+
}
|