235 lines
9.5 KiB
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>
|