clavitor/clavitor.ai/test-index.html

235 lines
9.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clavitor — Test Page</title>
<link rel="stylesheet" href="/clavitor.css">
<style>
/* Inline the fonts for testing */
@font-face {
font-family: 'IBM Plex Sans';
font-style: normal;
font-weight: 400 700;
font-display: swap;
src: url('https://fonts.gstatic.com/s/ibmplexsans/v19/zYXzKVElJtQ_m--A1PHz_MlYGHbM.woff2') format('woff2');
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 100 800;
font-display: swap;
src: url('https://fonts.gstatic.com/s/jetbrainsmono/v18/tDbY2o-flE3B8wJ47L-j6pEsKTZbBr8M.woff2') format('woff2');
}
</style>
</head>
<body>
<nav class="nav">
<div class="container nav-inner">
<a href="/" class="nav-logo"><span class="logo-lockup logo-lockup-nav"><span class="logo-lockup-square"></span><span class="logo-lockup-text"><span class="logo-lockup-wordmark">CLAVITOR</span><span class="logo-lockup-tagline">Black-box credential issuance</span></span></span></a>
<button class="nav-hamburger" onclick="document.querySelector('.nav-links').classList.toggle('open')"><span></span><span></span><span></span></button>
<div class="nav-links">
<a href="/hosted" class="nav-link">Hosted</a>
<div class="nav-dropdown">
<span class="nav-link nav-dropdown-trigger">Product</span>
<div class="nav-dropdown-menu">
<a href="/upgrade" class="nav-dropdown-item">Upgrade</a>
<a href="/developers" class="nav-dropdown-item">Developers</a>
<a href="/install" class="nav-dropdown-item">Self-host</a>
</div>
</div>
<div class="nav-dropdown">
<span class="nav-link nav-dropdown-trigger">Network</span>
<div class="nav-dropdown-menu">
<a href="/status" class="nav-dropdown-item">Status</a>
<a href="/glass" class="nav-dropdown-item">Looking Glass</a>
</div>
</div>
<a href="/pricing" class="nav-link active">Pricing</a>
<div class="nav-dropdown nav-dropdown--language">
<span class="nav-link nav-dropdown-trigger" id="languageTrigger">🇺🇸 EN</span>
<div class="nav-dropdown-menu nav-dropdown-menu--right">
<a href="/" class="nav-dropdown-item active" data-lang="en">🇺🇸 English</a>
<a href="/de" class="nav-dropdown-item" data-lang="de">🇩🇪 Deutsch</a>
</div>
</div>
<div class="nav-dropdown nav-dropdown--currency">
<span class="nav-link nav-dropdown-trigger" id="currencyTrigger">$ USD</span>
<div class="nav-dropdown-menu nav-dropdown-menu--right" id="currencyMenu">
<!-- Currency options loaded dynamically from /api/currencies -->
<a href="#" class="nav-dropdown-item active" data-currency="USD">$ USD</a>
<a href="#" class="nav-dropdown-item" data-currency="EUR">€ EUR</a>
</div>
</div>
<a href="#" class="nav-link btn btn-ghost">Sign in</a>
<a href="/hosted" class="btn btn-primary">Get hosted — $12/yr</a>
</div>
</div>
</nav>
<div class="hero container">
<p class="label accent mb-3">Simple pricing</p>
<h1 class="mb-4">No tiers. No per-seat. No surprises.</h1>
<p class="lead">Two options — both get every feature.</p>
</div>
<hr class="divider">
<div class="section container">
<div class="grid-2 price-grid">
<div class="price-card">
<p class="label mb-4">Self-hosted</p>
<div class="price-amount mb-2">Free</div>
<p class="mb-6">Forever. Elastic License 2.0. No strings.</p>
<a href="/install" class="btn btn-ghost btn-block mb-8">Self-host guide →</a>
<p class="label mb-4">What you get</p>
<ul class="checklist"><li>Three-tier encryption</li><li>WebAuthn PRF</li><li>CLI for AI agents</li></ul>
</div>
<div class="price-card featured">
<span class="badge recommended price-badge">Recommended</span>
<p class="label accent mb-4">Hosted</p>
<div class="price-amount mb-2">$12<span class="price-period">/year</span></div>
<p class="mb-6">7-day free trial. Cancel anytime.</p>
<a href="/signup" class="btn btn-primary btn-block mb-8">Get started</a>
<p class="label accent mb-4">Everything in self-hosted, plus</p>
<ul class="checklist"><li>Managed infrastructure</li><li>Daily encrypted backups</li><li>4 regions across every continent</li></ul>
</div>
</div>
</div>
<hr class="divider">
<div class="section container prose-width">
<p class="label mb-6 text-center">Common questions</p>
<h2 class="mb-8 text-center">FAQ</h2>
<div class="prose">
<h3>Why so cheap?</h3>
<p>AI agents are everywhere — and so are the security risks. We set a price that's within reach for everyone.</p>
<h3>Will my price go up?</h3>
<p><strong>Never.</strong> Your price is locked for life. Pay $12/yr today, pay $12/yr in 2035.</p>
<h3>Does self-hosted get every feature?</h3>
<p>Yes. Every feature ships in both versions.</p>
</div>
</div>
<footer class="footer">
<div class="container">
<div class="footer-inner">
<div>© 2025 clavitor</div>
<div class="footer-links">
<a href="/privacy">Privacy</a>
<a href="/terms">Terms</a>
</div>
</div>
</div>
</footer>
<script>
// Toggle dropdown menus
document.querySelectorAll('.nav-dropdown-trigger').forEach(t=>t.addEventListener('click',()=>t.parentElement.classList.toggle('open')));
// Language selector state management
document.querySelectorAll('.nav-dropdown--language .nav-dropdown-item').forEach(item => {
item.addEventListener('click', (e) => {
e.preventDefault();
const lang = item.getAttribute('data-lang');
const flag = item.textContent.trim().split(' ')[0];
document.getElementById('languageTrigger').textContent = flag + ' ' + lang.toUpperCase();
document.querySelectorAll('.nav-dropdown--language .nav-dropdown-item').forEach(i => i.classList.remove('active'));
item.classList.add('active');
});
});
// Currency selector - fetch from API and render with sections
async function loadCurrencies() {
const menu = document.getElementById('currencyMenu');
const trigger = document.getElementById('currencyTrigger');
try {
const response = await fetch('/api/currencies');
if (!response.ok) throw new Error('ERR-CURRENCY-001: Failed to load currencies');
const data = await response.json();
// Clear existing content
menu.innerHTML = '';
// Render "Popular" section
if (data.top && data.top.length > 0) {
const popularHeader = document.createElement('div');
popularHeader.className = 'dropdown-section';
popularHeader.textContent = 'Popular';
menu.appendChild(popularHeader);
data.top.forEach(currency => {
const item = createCurrencyItem(currency, trigger);
menu.appendChild(item);
});
}
// Divider between sections
if (data.all && data.all.length > 0 && data.top && data.top.length > 0) {
const divider = document.createElement('div');
divider.className = 'dropdown-divider';
menu.appendChild(divider);
}
// Render "All Currencies" section
if (data.all && data.all.length > 0) {
const allHeader = document.createElement('div');
allHeader.className = 'dropdown-section';
allHeader.textContent = 'All Currencies';
menu.appendChild(allHeader);
data.all.forEach(currency => {
const item = createCurrencyItem(currency, trigger);
menu.appendChild(item);
});
}
} catch (err) {
// ERR-CURRENCY-002: API unavailable - keep default fallback options
console.error('ERR-CURRENCY-002: Currency API unavailable, using defaults');
}
}
function createCurrencyItem(currency, trigger) {
const item = document.createElement('a');
item.href = '#';
item.className = 'nav-dropdown-item';
item.setAttribute('data-currency', currency.code);
item.textContent = (currency.symbol || '$') + ' ' + currency.code;
// Set active state based on current selection
const currentText = trigger.textContent.trim();
if (currentText.includes(currency.code)) {
item.classList.add('active');
}
item.addEventListener('click', (e) => {
e.preventDefault();
const code = item.getAttribute('data-currency');
const symbol = currency.symbol || '$';
trigger.textContent = symbol + ' ' + code;
// Update active state
document.querySelectorAll('.nav-dropdown--currency .nav-dropdown-item').forEach(i => i.classList.remove('active'));
item.classList.add('active');
// Store preference
localStorage.setItem('preferredCurrency', code);
});
return item;
}
// Load currencies on page load
loadCurrencies();
</script>
</body>
</html>