Copy-ava-testing / about.html
Testing347's picture
Update about.html
f124ceb verified
<!-- SILENTPATTERN FINAL BUILD: 2025-12-15 | pages: 10 | features: hash-deep-linking, lab-navigator, access-modal, form-validation, lab-file-interface -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>SILENTPATTERN — About</title>
<!-- Tailwind -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Three.js + Vanta -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
<!-- Icons + Font -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap">
<style>
body { font-family: 'Inter', sans-serif; }
.gradient-text {
background: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.aura {
background:
radial-gradient(circle at 25% 20%, rgba(99,102,241,0.22), transparent 44%),
radial-gradient(circle at 80% 75%, rgba(236,72,153,0.12), transparent 50%),
radial-gradient(circle at 55% 45%, rgba(139,92,246,0.10), transparent 60%);
}
.focus-ring:focus { outline: none; box-shadow: 0 0 0 2px rgba(99,102,241,0.65); }
.modal { transition: opacity 0.3s ease, transform 0.3s ease; }
.modal-hidden { opacity: 0; transform: translateY(20px); pointer-events: none; }
.modal-visible { opacity: 1; transform: translateY(0); }
.thin-scroll {
scrollbar-width: thin;
scrollbar-color: #4f46e5 #1e1b4b;
}
.thin-scroll::-webkit-scrollbar { width: 6px; }
.thin-scroll::-webkit-scrollbar-track { background: #1e1b4b; }
.thin-scroll::-webkit-scrollbar-thumb { background-color: #4f46e5; border-radius: 3px; }
.conscious-element { transition: all 0.28s ease; }
.conscious-element:hover { transform: translateY(-2px); }
/* Active states */
.lab-node.active {
border-color: rgba(99,102,241,0.55) !important;
box-shadow: 0 0 0 1px rgba(99,102,241,0.22), 0 0 28px rgba(99,102,241,0.08);
transform: translateY(-1px);
}
</style>
</head>
<body class="bg-black text-white overflow-x-hidden">
<!-- Animated background -->
<div id="vanta-bg" class="fixed top-0 left-0 w-full h-full z-0"></div>
<!-- Minimal top bar -->
<nav class="relative z-10 py-6 px-8 flex justify-between items-center backdrop-blur-sm">
<a href="index.html" class="flex items-center space-x-2">
<div class="w-8 h-8 rounded-full bg-indigo-600 flex items-center justify-center">
<div class="w-2 h-2 rounded-full bg-white animate-pulse"></div>
</div>
<span class="text-xl font-semibold">SILENTPATTERN</span>
</a>
<div class="flex items-center space-x-3">
<button id="lab-nav-btn"
class="w-10 h-10 rounded-full border border-indigo-500/40 bg-gray-900/20 hover:bg-gray-900/40 backdrop-blur-sm transition flex items-center justify-center focus-ring"
aria-label="Open Lab Navigator" title="Lab Navigator">
<i class="fas fa-asterisk text-indigo-300 text-sm"></i>
</button>
<button id="access-btn"
class="px-6 py-2 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full hover:opacity-90 transition focus-ring">
Access
</button>
</div>
</nav>
<!-- ABOUT: PRESENTED AS A LAB FILE -->
<section class="relative z-10 px-6 pt-14 pb-16">
<div class="max-w-6xl mx-auto">
<div class="grid grid-cols-1 lg:grid-cols-5 gap-6">
<!-- LEFT: "File Header" + Mission -->
<div class="lg:col-span-3 rounded-2xl border border-gray-800 bg-gray-900/20 overflow-hidden aura">
<div class="px-6 py-5 border-b border-gray-800/60 flex items-start justify-between gap-6">
<div>
<div class="inline-flex items-center gap-3 px-4 py-2 rounded-full border border-gray-800 bg-gray-900/20 backdrop-blur-sm">
<span class="w-2 h-2 rounded-full bg-indigo-400 animate-pulse"></span>
<span class="text-xs text-gray-300 tracking-widest uppercase">Lab File</span>
<span class="text-xs text-gray-500">ABOUT.md</span>
</div>
<h1 class="mt-6 text-3xl md:text-6xl font-bold leading-tight">
<span class="gradient-text">SILENTPATTERN</span><br>
An AI lab oriented toward general systems
</h1>
<p class="mt-4 text-gray-300 text-lg md:text-xl max-w-3xl">
SILENTPATTERN is built as a research interface, not a marketing site. We publish conservative claims, prioritize reproducibility, and scale capabilities only when evidence supports it.
</p>
</div>
<div class="text-xs px-2.5 py-1 rounded-full border border-indigo-500/30 text-indigo-200 bg-indigo-900/15 self-start">
PUBLIC
</div>
</div>
<div class="p-6 space-y-6">
<div class="rounded-2xl border border-gray-800 bg-black/20 p-5">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Mission</div>
<div class="text-sm text-gray-300 leading-relaxed">
Advance toward AGI and, eventually, superintelligence by building systems that can reason, experiment, and improve—while preserving governance, auditability, and alignment constraints. The lab's identity is methodological: evidence first, iteration always.
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="rounded-2xl border border-gray-800 bg-gray-900/30 p-5 conscious-element">
<div class="text-sm font-semibold text-gray-100">What "progress" means here</div>
<div class="text-sm text-gray-300 mt-2">
Not hype. Measurable capability gains validated by protocols, baselines, and repeatability.
</div>
</div>
<div class="rounded-2xl border border-gray-800 bg-gray-900/30 p-5 conscious-element">
<div class="text-sm font-semibold text-gray-100">What "prestige" means here</div>
<div class="text-sm text-gray-300 mt-2">
Discipline: clean evaluations, honest uncertainty, and claims proportional to evidence.
</div>
</div>
<div class="rounded-2xl border border-gray-800 bg-gray-900/30 p-5 conscious-element">
<div class="text-sm font-semibold text-gray-100">What the website is</div>
<div class="text-sm text-gray-300 mt-2">
A lab console. Modules are dossiers. Navigation stays minimal to protect the interface aesthetic.
</div>
</div>
<div class="rounded-2xl border border-gray-800 bg-gray-900/30 p-5 conscious-element">
<div class="text-sm font-semibold text-gray-100">What the website is not</div>
<div class="text-sm text-gray-300 mt-2">
Not a claim factory. Not a generic SaaS landing page. Not a "busy top menu."
</div>
</div>
</div>
<div class="rounded-2xl border border-gray-800 bg-black/20 p-5">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Stance on AGI and Superintelligence</div>
<div class="text-sm text-gray-300 leading-relaxed space-y-3">
<p>
We treat AGI as an engineering and scientific frontier: general problem-solving, robust transfer, and the ability to build and validate hypotheses. Superintelligence is approached as a trajectory, not a marketing label.
</p>
<p class="text-gray-400">
Public statements remain conservative. Internally, the lab is oriented toward capability growth alongside governance: constraints, logs, human oversight where appropriate, and "fail-closed" behavior for agents.
</p>
</div>
</div>
</div>
</div>
<!-- RIGHT: "Evaluation Doctrine" panel -->
<div class="lg:col-span-2 rounded-2xl border border-gray-800 bg-gray-900/30 overflow-hidden">
<div class="px-6 py-5 border-b border-gray-800/60">
<div class="text-lg font-semibold text-gray-100">Evaluation Doctrine</div>
<div class="text-xs text-gray-500 mt-1">How SILENTPATTERN protects itself from its own ambitions.</div>
</div>
<div class="p-6 space-y-5 thin-scroll max-h-[840px] overflow-auto">
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Rule 1: Protocol before Results</div>
<div class="text-sm text-gray-300">
Define datasets, splits, baselines, and metrics first. If the protocol is weak, results do not count.
</div>
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Rule 2: Claims scale with Evidence</div>
<div class="text-sm text-gray-300">
Public language remains bounded: "concept," "prototype," "validated," with explicit assumptions and limitations.
</div>
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Rule 3: Uncertainty is a first-class output</div>
<div class="text-sm text-gray-300">
Calibration, confidence, and failure modes are included in reports; no "high accuracy" statements without replicated benchmarks.
</div>
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Rule 4: Agents are governed</div>
<div class="text-sm text-gray-300">
"AI employees" are scoped by permissions, logged actions, approval gates, and verification layers. The system must fail closed.
</div>
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Rule 5: Reproducibility is a feature</div>
<div class="text-sm text-gray-300">
Every result should be repeatable: same code, same seeds, same data lineage, same output checks.
</div>
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Public-facing positioning</div>
<div class="text-sm text-gray-300">
Programs are introduced as dossiers with maturity levels and evidence capsules. The interface communicates seriousness without overpromising.
</div>
</div>
<div class="flex flex-col gap-3">
<button id="open-programs"
class="px-5 py-3 rounded-xl bg-gradient-to-r from-indigo-600 to-purple-600 hover:opacity-90 transition focus-ring">
Open Programs
</button>
<button id="open-console"
class="px-5 py-3 rounded-xl border border-gray-700 bg-gray-900/20 hover:bg-gray-900/35 transition focus-ring">
Open Console
</button>
</div>
<div class="text-xs text-gray-500">
Last updated: <span class="text-gray-300"></span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Minimal Footer -->
<footer class="relative z-10 px-6 pb-10">
<div class="max-w-6xl mx-auto border-t border-gray-800/60 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
<div class="text-sm text-gray-500">© 2025 SILENTPATTERN. All rights reserved.</div>
<div class="text-sm text-gray-500 flex gap-6">
<a href="research.html" class="hover:text-indigo-400 transition">Research</a>
<a href="privacy.html" class="hover:text-indigo-400 transition">Privacy</a>
<a href="terms.html" class="hover:text-indigo-400 transition">Terms</a>
<a href="contact.html" class="hover:text-indigo-400 transition">Contact</a>
</div>
</div>
</footer>
<!-- ACCESS MODAL -->
<div id="access-modal"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm modal modal-hidden"
role="dialog" aria-modal="true" aria-labelledby="access-modal-title" tabindex="-1">
<div class="bg-gray-900/90 border border-gray-800 rounded-xl max-w-md w-full mx-4 relative overflow-hidden">
<div class="absolute inset-x-0 top-0 h-1 bg-gradient-to-r from-indigo-600 to-purple-600"></div>
<div class="p-6">
<div class="flex justify-between items-start mb-6">
<div>
<h3 class="text-xl font-bold" id="access-modal-title">Request Access</h3>
<p class="text-gray-400 mt-1">Curated access for research and evaluation</p>
</div>
<button id="close-access-modal" class="text-gray-400 hover:text-white focus-ring" aria-label="Close">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Inline feedback -->
<div id="access-feedback"
class="hidden mb-4 rounded-lg border border-gray-800 bg-black/25 px-4 py-3 text-sm"
role="status" aria-live="polite"></div>
<form id="access-form" class="space-y-4" novalidate>
<div>
<label for="name" class="block text-sm font-medium mb-1">Full Name</label>
<input type="text" id="name" class="w-full bg-gray-800/50 border border-gray-700 rounded-lg px-4 py-2 focus-ring" autocomplete="name">
<p id="name-error" class="hidden mt-1 text-xs text-red-300">Please enter your full name.</p>
</div>
<div>
<label for="email" class="block text-sm font-medium mb-1">Email</label>
<input type="email" id="email" class="w-full bg-gray-800/50 border border-gray-700 rounded-lg px-4 py-2 focus-ring" autocomplete="email">
<p id="email-error" class="hidden mt-1 text-xs text-red-300">Please enter a valid email address.</p>
</div>
<div>
<label for="institution" class="block text-sm font-medium mb-1">Institution/Organization</label>
<input type="text" id="institution" class="w-full bg-gray-800/50 border border-gray-700 rounded-lg px-4 py-2 focus-ring" autocomplete="organization">
<p id="institution-error" class="hidden mt-1 text-xs text-red-300">Please enter your institution/organization.</p>
</div>
<div>
<label for="purpose" class="block text-sm font-medium mb-1">Purpose</label>
<select id="purpose" class="w-full bg-gray-800/50 border border-gray-700 rounded-lg px-4 py-2 focus-ring">
<option value="">Select a purpose</option>
<option value="research">Academic / Independent Research</option>
<option value="development">Engineering / Product Evaluation</option>
<option value="partnership">Partnership</option>
<option value="other">Other</option>
</select>
<p id="purpose-error" class="hidden mt-1 text-xs text-red-300">Please select a purpose.</p>
</div>
<div class="pt-2">
<button type="submit" class="w-full py-3 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-lg hover:opacity-90 transition focus-ring">
Submit Request
</button>
</div>
</form>
</div>
</div>
</div>
<!-- LAB NAVIGATOR -->
<div id="lab-navigator"
class="fixed inset-0 z-[60] bg-black/80 backdrop-blur-md modal modal-hidden"
role="dialog" aria-modal="true" aria-label="Lab Navigator" tabindex="-1">
<div class="absolute inset-0" data-lab-close="true"></div>
<div class="relative w-full h-full flex items-center justify-center p-6">
<div class="w-full max-w-6xl mx-auto grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="relative rounded-2xl border border-gray-800 bg-gray-900/20 overflow-hidden">
<div class="flex items-center justify-between px-5 py-4 border-b border-gray-800/60">
<div class="flex items-center space-x-3">
<div class="w-7 h-7 rounded-full bg-indigo-600 flex items-center justify-center">
<div class="w-1.5 h-1.5 rounded-full bg-white animate-pulse"></div>
</div>
<div>
<div class="text-sm text-gray-300 tracking-wide">SILENTPATTERN</div>
<div class="text-xs text-gray-500">Lab Navigator</div>
</div>
</div>
<button id="lab-nav-close"
class="w-9 h-9 rounded-full border border-gray-800 bg-gray-900/30 hover:bg-gray-900/50 transition flex items-center justify-center focus-ring"
aria-label="Close Lab Navigator">
<i class="fas fa-times text-gray-300 text-sm"></i>
</button>
</div>
<div class="relative p-6 min-h-[420px]">
<div class="absolute inset-0 opacity-70 pointer-events-none"
style="background: radial-gradient(circle at 30% 20%, rgba(99,102,241,0.18), transparent 45%),
radial-gradient(circle at 70% 70%, rgba(236,72,153,0.10), transparent 50%);"></div>
<div class="relative grid grid-cols-1 sm:grid-cols-2 gap-3">
<button class="lab-node text-left rounded-xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/50 hover:bg-gray-900/45 transition p-4 focus-ring"
data-dossier="start" aria-current="false">
<div class="text-sm text-gray-200 font-medium">Start Here</div>
<div class="text-xs text-gray-500 mt-1">Entry interface</div>
</button>
<button class="lab-node text-left rounded-xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/50 hover:bg-gray-900/45 transition p-4 focus-ring"
data-dossier="programs" aria-current="false">
<div class="text-sm text-gray-200 font-medium">Programs</div>
<div class="text-xs text-gray-500 mt-1">Program Bay</div>
</button>
<button class="lab-node text-left rounded-xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/50 hover:bg-gray-900/45 transition p-4 focus-ring"
data-dossier="console" aria-current="false">
<div class="text-sm text-gray-200 font-medium">Console</div>
<div class="text-xs text-gray-500 mt-1">Controlled chat</div>
</button>
<button class="lab-node text-left rounded-xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/50 hover:bg-gray-900/45 transition p-4 focus-ring"
data-dossier="research" aria-current="false">
<div class="text-sm text-gray-200 font-medium">Research</div>
<div class="text-xs text-gray-500 mt-1">Notes and briefs</div>
</button>
<button class="lab-node text-left rounded-xl border border-gray-800 bg-gray-900/30 hover:border-indigo-500/50 hover:bg-gray-900/45 transition p-4 focus-ring sm:col-span-2"
data-dossier="access" aria-current="false">
<div class="text-sm text-gray-200 font-medium">Access</div>
<div class="text-xs text-gray-500 mt-1">Curated entry</div>
</button>
</div>
<div class="relative mt-6 text-xs text-gray-500">
Tip: Press <span class="text-gray-300">Esc</span> to close.
</div>
</div>
</div>
<div class="relative rounded-2xl border border-gray-800 bg-gray-900/30 overflow-hidden">
<div class="px-6 py-5 border-b border-gray-800/60">
<div class="flex items-start justify-between gap-4">
<div>
<div id="dossier-title" class="text-lg font-semibold text-gray-100">Lab Dossier</div>
<div id="dossier-subtitle" class="text-xs text-gray-500 mt-1">Select a node to load details.</div>
</div>
<div id="dossier-status"
class="text-xs px-2.5 py-1 rounded-full border border-indigo-500/30 text-indigo-200 bg-indigo-900/15">
READY
</div>
</div>
</div>
<div class="p-6 space-y-5 max-h-[560px] overflow-auto thin-scroll">
<div id="dossier-body" class="text-sm text-gray-300 leading-relaxed">
This interface reveals SILENTPATTERN as a set of research programs and operational systems.
The public layer is minimal by design; depth is opened intentionally.
</div>
<div class="rounded-xl border border-gray-800 bg-black/20 p-4">
<div class="text-xs text-gray-400 uppercase tracking-wider mb-2">Evidence Capsule</div>
<ul id="dossier-evidence" class="text-sm text-gray-300 space-y-1">
<li class="text-gray-500">No dossier selected.</li>
</ul>
</div>
<div class="flex flex-col sm:flex-row gap-3">
<button id="dossier-primary"
class="flex-1 px-5 py-3 rounded-xl bg-gradient-to-r from-indigo-600 to-purple-600 hover:opacity-90 transition focus-ring">
Open
</button>
<button id="dossier-secondary"
class="flex-1 px-5 py-3 rounded-xl border border-gray-700 bg-gray-900/20 hover:bg-gray-900/35 transition focus-ring">
View Note
</button>
</div>
<div id="dossier-meta" class="text-xs text-gray-500">
Last updated: <span class="text-gray-300"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Site-wide configuration
const CONFIG = {
MODAL_HASHES: new Set(['lab', 'access'])
};
/* -------------------------------------------------------------
UTILITY FUNCTIONS (consistent with other pages)
------------------------------------------------------------- */
function escapeHtml(str) {
return String(str)
.replaceAll('&', '&amp;')
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;')
.replaceAll('"', '&quot;')
.replaceAll("'", '&#039;');
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function currentHashKey() {
const h = (window.location.hash || '').replace('#', '').trim();
return h;
}
function setHash(key, replace = false) {
if (!key) return;
if (window.location.hash.replace('#', '') === key) return;
if (replace) {
history.replaceState(null, '', '#' + key);
} else {
history.pushState(null, '', '#' + key);
}
}
function clearHashIf(key) {
const h = currentHashKey();
if (!h) return;
if (!key || h === key) {
history.replaceState(null, '', window.location.pathname + window.location.search);
}
}
/* -------------------------------------------------------------
MODAL HELPERS (consistent with other pages)
------------------------------------------------------------- */
function trapFocus(modal) {
const focusable = modal.querySelectorAll('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
if (!focusable.length) return;
const first = focusable[0];
const last = focusable[focusable.length - 1];
function handler(e) {
if (e.key === 'Tab') {
if (e.shiftKey) {
if (document.activeElement === first) { e.preventDefault(); last.focus(); }
} else {
if (document.activeElement === last) { e.preventDefault(); first.focus(); }
}
}
}
modal.addEventListener('keydown', handler);
modal._focusHandler = handler;
}
function untrapFocus(modal) {
if (modal._focusHandler) {
modal.removeEventListener('keydown', modal._focusHandler);
delete modal._focusHandler;
}
}
const toggleModal = (modal, show) => {
if (show) {
modal.classList.remove('modal-hidden');
modal.classList.add('modal-visible');
document.body.style.overflow = 'hidden';
setTimeout(() => { modal.focus(); trapFocus(modal); }, 0);
} else {
modal.classList.remove('modal-visible');
modal.classList.add('modal-hidden');
document.body.style.overflow = '';
untrapFocus(modal);
}
};
/* -------------------------------------------------------------
VANTA BACKGROUND
------------------------------------------------------------- */
let vantaEffect = null;
try {
if (window.VANTA && typeof VANTA.NET === 'function') {
vantaEffect = VANTA.NET({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x4f46e5,
backgroundColor: 0x020617,
points: 12.00,
maxDistance: 20.00,
spacing: 15.00
});
}
} catch (e) {
console.warn('Vanta background failed to initialize:', e);
vantaEffect = null;
}
window.addEventListener('resize', () => {
if (vantaEffect && typeof vantaEffect.resize === 'function') {
vantaEffect.resize();
}
});
/* -------------------------------------------------------------
ACCESS MODAL
------------------------------------------------------------- */
const accessModal = document.getElementById('access-modal');
const accessBtn = document.getElementById('access-btn');
const closeAccessModal = document.getElementById('close-access-modal');
const accessForm = document.getElementById('access-form');
const accessFeedback = document.getElementById('access-feedback');
const nameEl = document.getElementById('name');
const emailEl = document.getElementById('email');
const institutionEl = document.getElementById('institution');
const purposeEl = document.getElementById('purpose');
const nameErr = document.getElementById('name-error');
const emailErr = document.getElementById('email-error');
const institutionErr = document.getElementById('institution-error');
const purposeErr = document.getElementById('purpose-error');
function setAccessFeedback(kind, text) {
if (!accessFeedback) return;
accessFeedback.classList.remove('hidden');
accessFeedback.classList.remove('border-red-500/30', 'bg-red-900/10', 'text-red-200');
accessFeedback.classList.remove('border-emerald-500/30', 'bg-emerald-900/10', 'text-emerald-200');
accessFeedback.classList.remove('border-indigo-500/30', 'bg-indigo-900/10', 'text-indigo-200');
if (kind === 'error') {
accessFeedback.classList.add('border-red-500/30', 'bg-red-900/10', 'text-red-200');
} else if (kind === 'success') {
accessFeedback.classList.add('border-emerald-500/30', 'bg-emerald-900/10', 'text-emerald-200');
} else {
accessFeedback.classList.add('border-indigo-500/30', 'bg-indigo-900/10', 'text-indigo-200');
}
accessFeedback.textContent = text;
}
function hideAccessFeedback() {
if (!accessFeedback) return;
accessFeedback.textContent = '';
accessFeedback.classList.add('hidden');
accessFeedback.classList.remove(
'border-red-500/30','bg-red-900/10','text-red-200',
'border-emerald-500/30','bg-emerald-900/10','text-emerald-200',
'border-indigo-500/30','bg-indigo-900/10','text-indigo-200'
);
}
function setFieldError(inputEl, errorEl, isError) {
if (!inputEl || !errorEl) return;
if (isError) {
errorEl.classList.remove('hidden');
inputEl.setAttribute('aria-invalid', 'true');
inputEl.classList.add('border-red-500/60');
} else {
errorEl.classList.add('hidden');
inputEl.removeAttribute('aria-invalid');
inputEl.classList.remove('border-red-500/60');
}
}
function resetAccessErrors() {
hideAccessFeedback();
setFieldError(nameEl, nameErr, false);
setFieldError(emailEl, emailErr, false);
setFieldError(institutionEl, institutionErr, false);
setFieldError(purposeEl, purposeErr, false);
}
function openAccessModal(setHashFlag = true) {
resetAccessErrors();
toggleModal(accessModal, true);
if (setHashFlag) setHash('access');
setTimeout(() => nameEl && nameEl.focus(), 80);
}
function closeAccessModal(clearHashFlag = true) {
toggleModal(accessModal, false);
if (clearHashFlag) clearHashIf('access');
}
accessBtn.addEventListener('click', () => openAccessModal(true));
if (closeAccessModal) closeAccessModal.addEventListener('click', () => closeAccessModal(true));
if (accessModal) {
accessModal.addEventListener('click', (e) => {
if (e.target === accessModal) closeAccessModal(true);
});
}
if (accessForm) {
// Clear per-field errors on input
[nameEl, emailEl, institutionEl, purposeEl].forEach(el => {
if (!el) return;
el.addEventListener('input', () => {
if (el === nameEl) setFieldError(nameEl, nameErr, !nameEl.value.trim());
if (el === emailEl) setFieldError(emailEl, emailErr, !isValidEmail(emailEl.value.trim()));
if (el === institutionEl) setFieldError(institutionEl, institutionErr, !institutionEl.value.trim());
if (el === purposeEl) setFieldError(purposeEl, purposeErr, !purposeEl.value);
});
el.addEventListener('change', () => el.dispatchEvent(new Event('input')));
});
accessForm.addEventListener('submit', (e) => {
e.preventDefault();
resetAccessErrors();
const name = (nameEl?.value || '').trim();
const email = (emailEl?.value || '').trim();
const institution = (institutionEl?.value || '').trim();
const purpose = (purposeEl?.value || '').trim();
let ok = true;
if (!name) { setFieldError(nameEl, nameErr, true); ok = false; }
if (!email || !isValidEmail(email)) { setFieldError(emailEl, emailErr, true); ok = false; }
if (!institution) { setFieldError(institutionEl, institutionErr, true); ok = false; }
if (!purpose) { setFieldError(purposeEl, purposeErr, true); ok = false; }
if (!ok) {
setAccessFeedback('error', 'Please correct the highlighted fields and resubmit.');
return;
}
setAccessFeedback('success', 'Request received. You will be contacted after review.');
accessForm.reset();
});
}
/* -------------------------------------------------------------
LAB NAVIGATOR
------------------------------------------------------------- */
const labNav = document.getElementById('lab-navigator');
const labNavBtn = document.getElementById('lab-nav-btn');
const labNavClose = document.getElementById('lab-nav-close');
const DOSSIERS = {
start: {
title: "Start Here",
subtitle: "Entry interface",
status: "ACTIVE",
body: "Return to the main interface.",
evidence: ["Public entry layer", "Programs as dossiers", "Console for controlled interaction"],
primary: { label: "Go to Index", action: () => { window.location.href = "index.html"; } },
secondary: { label: "Programs", action: () => { window.location.href = "capabilities.html"; } },
updated: "—"
},
programs: {
title: "Programs",
subtitle: "Program Bay",
status: "ACTIVE",
body: "Program Bay: MCAP, CHAI, Quantum Lambda, AI Scientist, Agentic Workforce.",
evidence: ["Dossiers with maturity levels", "Evidence capsules", "Access gates"],
primary: { label: "Open Programs", action: () => { window.location.href = "capabilities.html"; } },
secondary: { label: "Console", action: () => { window.location.href = "chat.html"; } },
updated: "—"
},
console: {
title: "Console",
subtitle: "Controlled chat",
status: "DRAFT",
body: "Controlled chat with exportable transcripts. Model access must remain server-side.",
evidence: ["No client-side secrets", "Audit-ready transcripts", "Fail-closed behaviors"],
primary: { label: "Open Console", action: () => { window.location.href = "chat.html"; } },
secondary: { label: "Research", action: () => { window.location.href = "research.html"; } },
updated: "—"
},
research: {
title: "Research",
subtitle: "Notes and briefs",
status: "DRAFT",
body: "Technical notes, evaluation methodology, and changelogs.",
evidence: ["Evaluation philosophy", "Benchmarks + baselines", "Limitations and failure modes"],
primary: { label: "Open Research", action: () => { window.location.href = "research.html"; } },
secondary: { label: "Contact", action: () => { window.location.href = "contact.html"; } },
updated: "—"
},
access: {
title: "Access",
subtitle: "Curated entry",
status: "ACTIVE",
body: "Request access for controlled demos and evaluation workflows.",
evidence: ["Application-based", "Segmented by intent", "Controlled demos"],
primary: { label: "Request Access", action: () => { closeLabNav(true); openAccessModal(true); } },
secondary: { label: "Contact", action: () => { window.location.href = "contact.html"; } },
updated: "—"
}
};
const dossierTitle = document.getElementById('dossier-title');
const dossierSubtitle = document.getElementById('dossier-subtitle');
const dossierStatus = document.getElementById('dossier-status');
const dossierBody = document.getElementById('dossier-body');
const dossierEvidence = document.getElementById('dossier-evidence');
const dossierPrimary = document.getElementById('dossier-primary');
const dossierSecondary = document.getElementById('dossier-secondary');
const dossierMeta = document.getElementById('dossier-meta');
function setActiveLabNode(key) {
document.querySelectorAll('.lab-node').forEach(btn => {
const isActive = btn.getAttribute('data-dossier') === key;
btn.classList.toggle('active', isActive);
btn.setAttribute('aria-current', isActive ? 'true' : 'false');
});
}
function renderDossier(key) {
const d = DOSSIERS[key];
if (!d) return;
setActiveLabNode(key);
dossierTitle.textContent = d.title;
dossierSubtitle.textContent = d.subtitle;
dossierStatus.textContent = d.status;
dossierBody.textContent = d.body;
dossierEvidence.innerHTML = "";
d.evidence.forEach(item => {
const li = document.createElement('li');
li.textContent = item;
dossierEvidence.appendChild(li);
});
dossierPrimary.textContent = d.primary.label;
dossierPrimary.onclick = d.primary.action;
dossierSecondary.textContent = d.secondary.label;
dossierSecondary.onclick = d.secondary.action;
dossierMeta.innerHTML = `Last updated: <span class="text-gray-300">${d.updated}</span>`;
}
function openLabNav(setHashFlag = true) {
toggleModal(labNav, true);
if (setHashFlag) setHash('lab');
setTimeout(() => labNav.focus(), 0);
// Ensure a stable default selection when opened
const alreadyActive = document.querySelector('.lab-node.active');
if (!alreadyActive) renderDossier('start');
}
function closeLabNav(clearHashFlag = true) {
toggleModal(labNav, false);
if (clearHashFlag) clearHashIf('lab');
}
labNavBtn.addEventListener('click', () => openLabNav(true));
labNavClose.addEventListener('click', () => closeLabNav(true));
labNav.addEventListener('click', (e) => {
const shouldClose = e.target && e.target.getAttribute('data-lab-close') === 'true';
if (shouldClose) closeLabNav(true);
});
document.querySelectorAll('.lab-node').forEach(btn => {
btn.addEventListener('click', () => {
const key = btn.getAttribute('data-dossier');
renderDossier(key);
// Apply navigation actions
if (key === 'start') window.location.href = "index.html";
if (key === 'programs') window.location.href = "capabilities.html";
if (key === 'console') window.location.href = "chat.html";
if (key === 'research') window.location.href = "research.html";
if (key === 'access') { closeLabNav(true); openAccessModal(true); }
});
});
/* -------------------------------------------------------------
QUICK LINKS
------------------------------------------------------------- */
document.getElementById('open-programs').addEventListener('click', () => {
window.location.href = "capabilities.html";
});
document.getElementById('open-console').addEventListener('click', () => {
window.location.href = "chat.html";
});
/* -------------------------------------------------------------
HASH ROUTER: handle modal hashes
------------------------------------------------------------- */
function applyHashState() {
const key = currentHashKey();
if (CONFIG.MODAL_HASHES.has(key)) {
if (key === 'lab') openLabNav(false);
if (key === 'access') openAccessModal(false);
}
}
window.addEventListener('hashchange', applyHashState);
applyHashState(); // Initial load
/* -------------------------------------------------------------
GLOBAL ESC BEHAVIOR
------------------------------------------------------------- */
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
if (labNav && !labNav.classList.contains('modal-hidden')) closeLabNav(true);
if (accessModal && !accessModal.classList.contains('modal-hidden')) closeAccessModal(true);
}
});
// Initial dossier render
renderDossier('start');
</script>
</body>
</html>