562 lines
56 KiB
HTML
562 lines
56 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>vault1984 — Hosted</title>
|
||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<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">
|
||
<link rel="stylesheet" href="/tailwind.min.css">
|
||
<style>
|
||
*{box-sizing:border-box}
|
||
body{background:#0A1628;color:#f1f5f9;font-family:Inter,sans-serif;margin:0}
|
||
.label{font-family:"JetBrains Mono",monospace;font-size:0.7rem;font-weight:500;letter-spacing:0.12em;text-transform:uppercase}
|
||
.card{border-radius:1rem;border:1px solid rgba(255,255,255,0.06)}
|
||
.card-hover{transition:transform 0.2s,box-shadow 0.2s}
|
||
.card-hover:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,0.3)}
|
||
.vaultname{font-family:"JetBrains Mono",monospace;font-weight:700;color:#f1f5f9}
|
||
.vaultname .n{color:#22C55E}
|
||
hr.div{border:none;border-top:1px solid rgba(255,255,255,0.06);margin:0}
|
||
@keyframes hostedPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:0.3;transform:scale(1.8)}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="fixed top-0 w-full z-50 bg-navy/80 backdrop-blur-md border-b border-white/5">
|
||
<div class="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
|
||
<a href="/" class="font-mono font-bold text-3xl text-white tracking-tight leading-none">vault<span class="text-accent font-mono">1984</span></a>
|
||
<div class="hidden md:flex items-center gap-6 text-sm">
|
||
<a href="https://github.com/johanjongsma/vault1984" target="_blank" rel="noopener" class="text-gray-400 hover:text-white transition-colors">GitHub</a>
|
||
<a href="/hosted" class="font-semibold transition-colors flex items-center gap-1.5" style="color:#D4AF37"><span style="display:inline-block;width:6px;height:6px;border-radius:50%;background:#D4AF37;animation:hostedPulse 2s ease-in-out infinite"></span>Hosted</a>
|
||
<a href="/install.html" class="text-gray-400 hover:text-white transition-colors">Self-host</a>
|
||
<a href="#" class="border border-gray-600 text-gray-300 hover:border-gray-400 hover:text-white px-4 py-1.5 rounded-lg transition-colors text-sm">Sign in</a>
|
||
<a href="/hosted" class="bg-accent hover:bg-accent-hover text-black font-medium px-4 py-1.5 rounded-lg transition-colors text-sm">Get hosted — $12/yr</a>
|
||
</div>
|
||
<button id="mobile-menu-btn" class="md:hidden text-gray-400">
|
||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
|
||
</button>
|
||
</div>
|
||
<div id="mobile-menu" class="hidden md:hidden border-t border-white/5 bg-navy/95 backdrop-blur-md">
|
||
<div class="px-6 py-4 space-y-3">
|
||
<a href="https://github.com/johanjongsma/vault1984" target="_blank" rel="noopener" class="block text-gray-400 hover:text-white">GitHub</a>
|
||
<a href="/hosted" class="block font-semibold" style="color:#D4AF37">✦ Hosted</a>
|
||
<a href="/install.html" class="block text-gray-400 hover:text-white">Self-host</a>
|
||
<a href="#" class="block text-gray-400 hover:text-white">Sign in</a>
|
||
<a href="/pricing.html" class="block bg-accent hover:bg-accent-hover text-black font-medium px-4 py-2 rounded-lg text-center">Get hosted — $12/yr</a>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- Hero -->
|
||
<div style="padding-top:100px;padding-bottom:2.5rem;text-align:center;max-width:1100px;margin:0 auto;padding-left:2rem;padding-right:2rem">
|
||
<p style="font-family:'JetBrains Mono',monospace;font-size:0.875rem;font-weight:700;margin-bottom:1rem;letter-spacing:0.02em">vault<span style="color:#22C55E">1984</span> <span style="color:#94a3b8;font-weight:400">hosted</span></p>
|
||
<h1 style="font-size:clamp(2rem,5vw,3.5rem);font-weight:800;color:#fff;margin:0 0 1rem;line-height:1.1">Your vault. Wherever you want it.</h1>
|
||
<p style="color:#94a3b8;font-size:1.125rem;margin:0">We run it. You own it. Pick your region — your data stays there.</p>
|
||
</div>
|
||
|
||
<!-- Map -->
|
||
<div style="max-width:1100px;margin:0 auto;padding:0 2rem 2rem">
|
||
<div style="border-radius:1rem;overflow:hidden;border:1px solid rgba(255,255,255,0.06)">
|
||
<svg id="worldmap" viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg" style="display:block;width:100%;background:#0a1628">
|
||
<image href="/worldmap.svg" x="0" y="0" width="1000" height="460"/>
|
||
<circle cx="284.7" cy="143.8" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.00s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.00s" repeatCount="indefinite"/></circle>
|
||
<circle cx="284.7" cy="143.8" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.80s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="0.80s" repeatCount="indefinite"/></circle>
|
||
<circle cx="284.7" cy="143.8" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="284.7" y="155.8" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Washington D.C.</text>
|
||
<circle cx="160.0" cy="143.1" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.08s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.08s" repeatCount="indefinite"/></circle>
|
||
<circle cx="160.0" cy="143.1" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.88s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="0.88s" repeatCount="indefinite"/></circle>
|
||
<circle cx="160.0" cy="143.1" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="160.0" y="135.1" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">San Francisco</text>
|
||
<circle cx="295.6" cy="122.8" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.16s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.16s" repeatCount="indefinite"/></circle>
|
||
<circle cx="295.6" cy="122.8" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.96s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="0.96s" repeatCount="indefinite"/></circle>
|
||
<circle cx="295.6" cy="122.8" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="295.6" y="114.8" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Montréal</text>
|
||
<circle cx="224.7" cy="187.0" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.24s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.24s" repeatCount="indefinite"/></circle>
|
||
<circle cx="224.7" cy="187.0" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.04s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.04s" repeatCount="indefinite"/></circle>
|
||
<circle cx="224.7" cy="187.0" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="224.7" y="199.0" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Mexico City</text>
|
||
<circle cx="294.2" cy="219.7" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.32s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.32s" repeatCount="indefinite"/></circle>
|
||
<circle cx="294.2" cy="219.7" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.12s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.12s" repeatCount="indefinite"/></circle>
|
||
<circle cx="294.2" cy="219.7" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="294.2" y="231.7" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Bogotá</text>
|
||
<circle cx="370.6" cy="282.7" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.40s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.40s" repeatCount="indefinite"/></circle>
|
||
<circle cx="370.6" cy="282.7" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.20s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.20s" repeatCount="indefinite"/></circle>
|
||
<circle cx="370.6" cy="282.7" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="370.6" y="294.7" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">São Paulo</text>
|
||
<circle cx="303.9" cy="306.0" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.48s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.48s" repeatCount="indefinite"/></circle>
|
||
<circle cx="303.9" cy="306.0" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.28s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.28s" repeatCount="indefinite"/></circle>
|
||
<circle cx="303.9" cy="306.0" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="303.9" y="318.0" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Santiago</text>
|
||
<circle cx="499.7" cy="106.0" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.56s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.56s" repeatCount="indefinite"/></circle>
|
||
<circle cx="499.7" cy="106.0" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.36s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.36s" repeatCount="indefinite"/></circle>
|
||
<circle cx="499.7" cy="106.0" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="499.7" y="98.0" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">London</text>
|
||
<circle cx="523.6" cy="117.6" r="5" fill="none" stroke="#D4AF37" stroke-width="2"><animate attributeName="r" values="5;18;5" dur="2.4s" begin="0.64s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.64s" repeatCount="indefinite"/></circle>
|
||
<circle cx="523.6" cy="117.6" r="5" fill="none" stroke="#D4AF37" stroke-width="1.5"><animate attributeName="r" values="5;18;5" dur="2.4s" begin="1.44s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.44s" repeatCount="indefinite"/></circle>
|
||
<circle cx="523.6" cy="117.6" r="6" fill="#D4AF37" stroke="#0a1628" stroke-width="2"/>
|
||
<circle cx="523.6" cy="117.6" r="3" fill="#0a1628"/>
|
||
<text x="523.6" y="109.6" font-family="Inter,sans-serif" font-size="8.5" fill="#D4AF37" text-anchor="middle" opacity="0.85">Zürich</text>
|
||
<circle cx="489.7" cy="136.4" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.72s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.72s" repeatCount="indefinite"/></circle>
|
||
<circle cx="489.7" cy="136.4" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.52s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.52s" repeatCount="indefinite"/></circle>
|
||
<circle cx="489.7" cy="136.4" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="489.7" y="128.4" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Madrid</text>
|
||
<circle cx="550.3" cy="82.1" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.80s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.80s" repeatCount="indefinite"/></circle>
|
||
<circle cx="550.3" cy="82.1" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.60s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.60s" repeatCount="indefinite"/></circle>
|
||
<circle cx="550.3" cy="82.1" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="550.3" y="74.1" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Stockholm</text>
|
||
<circle cx="580.3" cy="134.8" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.88s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.88s" repeatCount="indefinite"/></circle>
|
||
<circle cx="580.3" cy="134.8" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.68s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.68s" repeatCount="indefinite"/></circle>
|
||
<circle cx="580.3" cy="134.8" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="580.3" y="126.8" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Istanbul</text>
|
||
<circle cx="653.6" cy="173.6" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="0.96s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="0.96s" repeatCount="indefinite"/></circle>
|
||
<circle cx="653.6" cy="173.6" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.76s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.76s" repeatCount="indefinite"/></circle>
|
||
<circle cx="653.6" cy="173.6" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="653.6" y="165.6" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Dubai</text>
|
||
<circle cx="509.4" cy="215.7" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.04s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.04s" repeatCount="indefinite"/></circle>
|
||
<circle cx="509.4" cy="215.7" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.84s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.84s" repeatCount="indefinite"/></circle>
|
||
<circle cx="509.4" cy="215.7" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="509.4" y="227.7" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Lagos</text>
|
||
<circle cx="602.2" cy="232.8" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.12s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.12s" repeatCount="indefinite"/></circle>
|
||
<circle cx="602.2" cy="232.8" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.92s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="1.92s" repeatCount="indefinite"/></circle>
|
||
<circle cx="602.2" cy="232.8" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="602.2" y="244.8" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Nairobi</text>
|
||
<circle cx="551.1" cy="307.2" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.20s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.20s" repeatCount="indefinite"/></circle>
|
||
<circle cx="551.1" cy="307.2" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.00s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.00s" repeatCount="indefinite"/></circle>
|
||
<circle cx="551.1" cy="307.2" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="551.1" y="319.2" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Cape Town</text>
|
||
<circle cx="702.5" cy="187.7" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.28s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.28s" repeatCount="indefinite"/></circle>
|
||
<circle cx="702.5" cy="187.7" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.08s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.08s" repeatCount="indefinite"/></circle>
|
||
<circle cx="702.5" cy="187.7" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="702.5" y="179.7" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Mumbai</text>
|
||
<circle cx="788.3" cy="227.2" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.36s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.36s" repeatCount="indefinite"/></circle>
|
||
<circle cx="788.3" cy="227.2" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.16s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.16s" repeatCount="indefinite"/></circle>
|
||
<circle cx="788.3" cy="227.2" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="788.3" y="239.2" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Singapore</text>
|
||
<circle cx="920.0" cy="307.2" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.44s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.44s" repeatCount="indefinite"/></circle>
|
||
<circle cx="920.0" cy="307.2" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.24s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.24s" repeatCount="indefinite"/></circle>
|
||
<circle cx="920.0" cy="307.2" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="920.0" y="319.2" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Sydney</text>
|
||
<circle cx="888.1" cy="148.3" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.52s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.52s" repeatCount="indefinite"/></circle>
|
||
<circle cx="888.1" cy="148.3" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.32s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.32s" repeatCount="indefinite"/></circle>
|
||
<circle cx="888.1" cy="148.3" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="888.1" y="140.3" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Tokyo</text>
|
||
<circle cx="852.5" cy="143.6" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.60s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.60s" repeatCount="indefinite"/></circle>
|
||
<circle cx="852.5" cy="143.6" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.40s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.40s" repeatCount="indefinite"/></circle>
|
||
<circle cx="852.5" cy="143.6" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="852.5" y="135.6" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Seoul</text>
|
||
<circle cx="817.2" cy="180.3" r="4" fill="none" stroke="#22C55E" stroke-width="1.5"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="1.68s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.6;0;0.6" dur="2.4s" begin="1.68s" repeatCount="indefinite"/></circle>
|
||
<circle cx="817.2" cy="180.3" r="4" fill="none" stroke="#22C55E" stroke-width="1"><animate attributeName="r" values="4;13;4" dur="2.4s" begin="2.48s" repeatCount="indefinite"/><animate attributeName="stroke-opacity" values="0.4;0;0.4" dur="2.4s" begin="2.48s" repeatCount="indefinite"/></circle>
|
||
<circle cx="817.2" cy="180.3" r="4.5" fill="#22C55E" stroke="#0a1628" stroke-width="1.5"/>
|
||
<text x="817.2" y="172.3" font-family="Inter,sans-serif" font-size="8.5" fill="#6ee7a0" text-anchor="middle" opacity="0.85">Hong Kong</text>
|
||
</svg>
|
||
</div>
|
||
<div style="height:1rem"></div>
|
||
<div id="dc-grid" style="display:flex;gap:12px;width:100%;margin-bottom:2.5rem">
|
||
<!-- Self-hosted -->
|
||
<div class="rounded-xl p-4 text-center card-hover" style="background:#1f0a0a;border:1px solid rgba(239,68,68,0.35);flex:1;min-width:0">
|
||
<div class="text-2xl mb-1.5">🖥️</div>
|
||
<div class="text-white font-semibold text-sm">Self-hosted</div>
|
||
<div class="text-gray-500 text-xs mb-2">Your machine. Your rules.</div>
|
||
<div class="flex items-center justify-center gap-1.5 text-xs mb-3" style="color:#EF4444"><span class="w-1.5 h-1.5 rounded-full inline-block" style="background:#EF4444"></span>Free forever</div>
|
||
<a href="/install" class="block w-full text-center text-xs font-semibold py-1.5 px-3 rounded-lg transition-colors" style="background:rgba(239,68,68,0.15);color:#EF4444;border:1px solid rgba(239,68,68,0.3)" onmouseover="this.style.background='rgba(239,68,68,0.25)'" onmouseout="this.style.background='rgba(239,68,68,0.15)'">Download now →</a>
|
||
</div>
|
||
<!-- Zürich HQ -->
|
||
<div class="rounded-xl p-4 text-center card-hover" style="background:#3d2e00;border:1px solid rgba(212,175,55,0.5);flex:1;min-width:0">
|
||
<div class="text-2xl mb-1.5">🇨🇭</div>
|
||
<div class="text-white font-semibold text-sm">Zürich, Switzerland</div>
|
||
<div class="text-gray-500 text-xs mb-2">Capital of Privacy</div>
|
||
<div class="flex items-center justify-center gap-1.5 text-xs mb-3" style="color:#D4AF37"><span class="w-1.5 h-1.5 rounded-full inline-block" style="background:#D4AF37"></span>Headquarters</div>
|
||
<a href="/signup?region=eu-central-2" class="block w-full text-center text-xs font-semibold py-1.5 px-3 rounded-lg transition-colors" style="background:rgba(212,175,55,0.15);color:#D4AF37;border:1px solid rgba(212,175,55,0.3)" onmouseover="this.style.background='rgba(212,175,55,0.25)'" onmouseout="this.style.background='rgba(212,175,55,0.15)'">Buy now →</a>
|
||
</div>
|
||
<!-- Closest POP — populated by JS -->
|
||
<div id="closest-pop" class="rounded-xl p-4 text-center card-hover" style="background:#0d1f10;border:1px solid rgba(34,197,94,0.25);flex:1;min-width:0">
|
||
<div class="text-2xl mb-1.5">📍</div>
|
||
<div id="closest-name" class="text-white font-semibold text-sm">Nearest region</div>
|
||
<div id="closest-sub" class="text-gray-500 text-xs mb-2">Locating you…</div>
|
||
<div class="flex items-center justify-center gap-1.5 text-xs mb-3 text-accent"><span class="w-1.5 h-1.5 rounded-full bg-accent inline-block"></span>Closest to you</div>
|
||
<a id="closest-buy" href="/signup" class="block w-full text-center text-xs font-semibold py-1.5 px-3 rounded-lg transition-colors" style="background:rgba(34,197,94,0.15);color:#22C55E;border:1px solid rgba(34,197,94,0.3)" onmouseover="this.style.background='rgba(34,197,94,0.25)'" onmouseout="this.style.background='rgba(34,197,94,0.15)'">Buy now →</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<hr class="div">
|
||
|
||
<!-- Why it matters -->
|
||
<div style="max-width:1100px;margin:0 auto;padding:3.5rem 2rem">
|
||
|
||
<div style="margin-bottom:3.5rem">
|
||
<p class="label" style="color:#64748b;margin-bottom:0.75rem">The problem</p>
|
||
<h2 style="font-size:clamp(1.5rem,3vw,2.25rem);font-weight:700;color:#fff;margin:0 0 1rem;line-height:1.2">Your AI assistant needs your credentials.<br>That changes everything.</h2>
|
||
<p style="color:#94a3b8;font-size:1.0625rem;line-height:1.75;max-width:680px;margin:0">A password manager that blocks AI agents is useless in 2025. But one that hands them everything is a liability. The question is: how do you give Claude access to your GitHub token without giving it access to your bank password?</p>
|
||
</div>
|
||
|
||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1.25rem;margin-bottom:3.5rem">
|
||
<div class="card" style="background:#0a1a0a;padding:1.75rem">
|
||
<p class="label" style="color:#22C55E;margin-bottom:0.75rem">Sealed fields</p>
|
||
<h3 style="font-size:1.2rem;font-weight:700;color:#fff;margin:0 0 0.875rem">Only you. Only in person.</h3>
|
||
<p style="color:#94a3b8;line-height:1.7;font-size:0.9375rem;margin:0">Passwords and private notes are encrypted on your device with a key derived from your fingerprint or hardware token. We store a locked box. No key ever reaches our servers — not a court order, not your AI assistant. Sealed fields require your physical presence to unlock.</p>
|
||
</div>
|
||
<div class="card" style="background:#0a1220;padding:1.75rem">
|
||
<p class="label" style="color:#64748b;margin-bottom:0.75rem">Agent fields</p>
|
||
<h3 style="font-size:1.2rem;font-weight:700;color:#fff;margin:0 0 0.875rem">Your AI, scoped and controlled.</h3>
|
||
<p style="color:#94a3b8;line-height:1.7;font-size:0.9375rem;margin:0">Fields you designate as agent-accessible are encrypted on our servers. You issue scoped tokens — Claude gets your GitHub token, nothing else. Revoke at any time. The agent never touches sealed fields, no matter what.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<p class="label" style="color:#D4AF37;margin-bottom:0.75rem">Why Zürich</p>
|
||
<h2 style="font-size:clamp(1.5rem,3vw,2.25rem);font-weight:700;color:#fff;margin:0 0 1rem;line-height:1.2">Sealed fields: jurisdiction irrelevant.<br>Agent fields: it isn’t.</h2>
|
||
<p style="color:#94a3b8;font-size:1.0625rem;line-height:1.75;max-width:680px;margin:0 0 1.75rem">Sealed fields are protected by math — where the server sits doesn’t matter. But agent fields live on a server in a jurisdiction. A US server is subject to the CLOUD Act. Zürich, Switzerland is subject to Swiss law — which does not cooperate with foreign government data requests. No backdoors. Both layers protected.</p>
|
||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem">
|
||
<div class="card" style="background:#0d1627;padding:1.25rem">
|
||
<p class="label" style="color:#64748b;margin-bottom:0.5rem">Self-hosted · US</p>
|
||
<p style="color:#cbd5e1;font-size:0.875rem;line-height:1.65;margin:0">Your server, your rules — until a court says otherwise. CLOUD Act applies to US persons regardless of encryption.</p>
|
||
</div>
|
||
<div class="card" style="background:#0a1220;padding:1.25rem">
|
||
<p class="label" style="color:#64748b;margin-bottom:0.5rem">Self-hosted · anywhere</p>
|
||
<p style="color:#cbd5e1;font-size:0.875rem;line-height:1.65;margin:0">Full control. Your infrastructure, your jurisdiction. The right choice if you know what you’re doing.</p>
|
||
</div>
|
||
<div style="border-radius:1rem;border:1px solid rgba(212,175,55,0.3);background:#2a1f00;padding:1.25rem">
|
||
<p class="label" style="color:#D4AF37;margin-bottom:0.5rem">Hosted · Zürich, Switzerland</p>
|
||
<p style="color:#cbd5e1;font-size:0.875rem;line-height:1.65;margin:0">Swiss law. Swiss courts. Capital of Privacy. No CLOUD Act. No backdoors. We handle the infrastructure — you get the protection.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<hr class="div">
|
||
|
||
<!-- Access Methods -->
|
||
<section class="py-8 border-t border-white/5">
|
||
<div class="max-w-7xl mx-auto px-6 text-center">
|
||
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">Your agent and you — same vault, right access</h2>
|
||
<p class="text-gray-400 max-w-2xl mx-auto mb-14">Four ways in. Each one designed for a different context. All pointing at the same encrypted store.</p>
|
||
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-6 text-left">
|
||
<div class="bg-navy-light rounded-xl p-6 border border-white/5">
|
||
<div class="font-mono text-accent font-bold text-lg mb-2">MCP</div>
|
||
<div class="text-sm font-semibold text-white mb-2">For AI agents</div>
|
||
<p class="text-gray-400 text-sm leading-relaxed">Claude, GPT, or any MCP-compatible agent can search credentials, fetch API keys, and generate 2FA codes — scoped to exactly what you allow.</p>
|
||
</div>
|
||
<div class="bg-navy-light rounded-xl p-6 border border-white/5">
|
||
<div class="font-mono text-accent font-bold text-lg mb-2">Extension</div>
|
||
<div class="text-sm font-semibold text-white mb-2">For humans in a browser</div>
|
||
<p class="text-gray-400 text-sm leading-relaxed">Autofill passwords, generate 2FA codes inline, and unlock L2 fields with Touch ID — without leaving the page you're on.</p>
|
||
</div>
|
||
<div class="bg-navy-light rounded-xl p-6 border border-white/5">
|
||
<div class="font-mono text-accent font-bold text-lg mb-2">CLI</div>
|
||
<div class="text-sm font-semibold text-white mb-2">For terminal workflows</div>
|
||
<p class="text-gray-400 text-sm leading-relaxed">Pipe credentials directly into scripts and CI pipelines. <span class="font-mono text-gray-300 text-xs">vault get github.token</span> — done.</p>
|
||
</div>
|
||
<div class="bg-navy-light rounded-xl p-6 border border-white/5">
|
||
<div class="font-mono text-accent font-bold text-lg mb-2">API</div>
|
||
<div class="text-sm font-semibold text-white mb-2">For everything else</div>
|
||
<p class="text-gray-400 text-sm leading-relaxed">REST API with scoped tokens. Give your deployment pipeline read access to staging keys. Nothing else.</p>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Complaints Wall -->
|
||
<section class="py-24 bg-navy">
|
||
<div class="max-w-7xl mx-auto px-6">
|
||
<div class="text-center mb-16">
|
||
<p class="text-green-400 text-xs font-mono uppercase tracking-widest mb-4">The competition</p>
|
||
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">We listened. And addressed them all.</h2>
|
||
<p class="text-gray-400 max-w-2xl mx-auto">Real complaints from real users — about 1Password, Bitwarden, and LastPass. Pulled from forums, GitHub issues, and Hacker News. Not cherry-picked from our own users.</p>
|
||
</div>
|
||
|
||
<!-- Complaint cards — masonry-style grid -->
|
||
<div class="columns-1 md:columns-2 lg:columns-3 gap-6 space-y-6">
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">1PASSWORD — Community Forum</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"The web extensions are laughably bad at this point. This has been going on for months. They either won't fill, wont' unlock, or just plain won't do anything (even clicking extension icon). It's so bad"</p>
|
||
<a href="https://www.1password.community/discussions/1password/constantly-being-asked-to-unlock-with-password/90511" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— notnotjake, April 2024 ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: No desktop app dependency. The extension talks directly to the local vault binary — no IPC, no sync, no unlock chains.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">BITWARDEN — GitHub Issues</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"Every single website loads slower. From Google, up to social media websites like Reddit, Instagram, X up to websites like example.com. Even scrolling and animation stutters sometimes. javascript heavy websites like X, Instagram, Reddit etc. become extremely sluggish when interacting with buttons. So for me the Bitwarden browser extension is unusable. It interferes with my browsing experience like malware."</p>
|
||
<a href="https://github.com/bitwarden/clients/issues/11077" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— julianw1011, 2024 ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: Zero content scripts. The extension injects nothing into pages — it fills via the browser autofill API only when you ask.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">LASTPASS — Hacker News</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"The fact they're drip-feeding how bad this breach actually was is terrible enough... Personally I'm never touching them again."</p>
|
||
<a href="https://news.ycombinator.com/item?id=34516275" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— intunderflow, January 2023 ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: Self-host or use hosted with L2 encryption — we mathematically cannot read your private fields. No vault data to breach.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">1PASSWORD — Community Forum</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"Since doing so, it asks me to enter my password every 10 minutes or so in the chrome extension"</p>
|
||
<a href="https://www.1password.community/discussions/1password/why-does-the-chrome-extension-keep-asking-for-my-password-every-10-mins-rather-t/74253" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— Anonymous (Former Member), November 2022 ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: WebAuthn-first. Touch ID is the primary unlock. Session lives locally — no server-side expiry forcing re-auth.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">BITWARDEN — Community Forums</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"the password not only auto-filled in the password field, but also auto-filled in reddit's search box!"</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic mt-2">"if autofill has the propensity at times to put an entire password in plain text in a random field, autofill seems like more risk than it's worth."</p>
|
||
<a href="https://community.bitwarden.com/t/auto-fill-is-pasting-password-in-website-search-box/44045" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— xru1nib5 ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: LLM field mapping. The extension reads the form, asks the model which field is which — fills by intent, not by CSS selector.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="break-inside-avoid rounded-xl bg-navy-light border border-red-500/10 p-6 mb-6">
|
||
<p class="text-red-400 text-xs font-mono mb-3">BITWARDEN — Community Forums</p>
|
||
<p class="text-gray-300 text-sm leading-relaxed italic">"Bitwarden REFUSES to autofill the actual password saved for a given site or app...and instead fills an old password. It simply substitutes the OLD password for the new one that is plainly saved in the vault."</p>
|
||
<a href="https://community.bitwarden.com/t/autofill-is-wrong-saved-password-is-right/32090" target="_blank" rel="noopener" class="text-gray-600 text-xs mt-2 block hover:text-gray-400 transition-colors">— gentlezacharias ↗</a>
|
||
<div class="mt-4 pt-4 border-t border-gray-700">
|
||
<p class="text-green-400 text-xs">✓ vault<span class="text-accent font-mono">1984</span>: LLM field mapping matches by intent. Entries are indexed by URL — the right credential for the right site, every time.</p>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<p class="text-center text-gray-500 text-sm mt-12">All quotes verbatim from public posts. URLs verified. <a href="/sources" class="text-gray-400 underline hover:text-white">View sources →</a></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Pricing -->
|
||
<section id="pricing" class="py-20 border-t border-white/5">
|
||
<div class="max-w-7xl mx-auto px-6">
|
||
<h2 class="text-3xl md:text-4xl font-bold text-white text-center mb-4">Pricing</h2>
|
||
<p class="text-gray-400 text-center mb-14 max-w-2xl mx-auto">No tiers. No per-seat. No "contact sales." Two options.</p>
|
||
<div class="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
||
<!-- Self-hosted -->
|
||
<div class="bg-navy-light rounded-xl p-8 border border-white/5 card-hover">
|
||
<h3 class="text-xl font-bold text-white mb-1">Self-hosted</h3>
|
||
<div class="text-3xl font-bold text-white mb-1">Free</div>
|
||
<p class="text-gray-500 text-sm mb-6">Forever. MIT license.</p>
|
||
<p class="text-gray-400 text-sm mb-8">One binary, your machine, your data. Full source on GitHub.</p>
|
||
<ul class="space-y-3 mb-8">
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
All features included
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Sealed & Agent fields
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
MCP server
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Browser extension
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Unlimited entries
|
||
</li>
|
||
</ul>
|
||
<a href="/install.html" class="block text-center border border-gray-600 text-gray-300 hover:border-accent hover:text-white font-medium px-6 py-3 rounded-lg transition-colors">Self-host guide →</a>
|
||
</div>
|
||
|
||
<!-- Hosted -->
|
||
<div class="bg-navy-light rounded-xl p-8 border border-accent/30 card-hover relative">
|
||
<div class="absolute -top-3 right-6 bg-accent text-black text-xs font-semibold px-3 py-1 rounded-full">Recommended</div>
|
||
<h3 class="text-xl font-bold text-white mb-1">Hosted</h3>
|
||
<div class="text-3xl font-bold text-white mb-1">$12<span class="text-lg font-normal text-gray-400">/year</span></div>
|
||
<p class="text-gray-500 text-sm mb-6">We manage it. You use it.</p>
|
||
<p class="text-gray-400 text-sm mb-8">22 regions across every continent. Pick yours at signup.</p>
|
||
<ul class="space-y-3 mb-8">
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Everything in self-hosted
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Managed backups
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Multi-region deployment
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Uptime monitoring
|
||
</li>
|
||
<li class="flex items-center gap-3 text-sm text-gray-300">
|
||
<svg class="w-4 h-4 text-accent flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
|
||
Automatic updates
|
||
</li>
|
||
</ul>
|
||
<a href="#" class="block text-center bg-accent hover:bg-accent-hover text-black font-semibold px-6 py-3 rounded-lg transition-colors">Get started — $12/yr</a>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<footer class="border-t border-white/5 py-12">
|
||
<div class="max-w-7xl mx-auto px-6 flex flex-col md:flex-row items-center justify-between gap-6">
|
||
<div class="flex items-center gap-6">
|
||
<a href="/" class="font-mono font-semibold text-lg text-white tracking-tight leading-none">vault<span class="text-accent font-mono">1984</span></a>
|
||
<div class="flex items-center gap-4 text-sm text-gray-500">
|
||
<a href="#" class="hover:text-gray-300 transition-colors">GitHub</a>
|
||
<a href="#" class="hover:text-gray-300 transition-colors">Discord</a>
|
||
<a href="#" class="hover:text-gray-300 transition-colors">X</a>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center gap-6 text-sm text-gray-500">
|
||
<a href="/privacy.html" class="hover:text-gray-300 transition-colors">Privacy</a>
|
||
<a href="/terms.html" class="hover:text-gray-300 transition-colors">Terms</a>
|
||
<span>MIT License</span>
|
||
</div>
|
||
</div>
|
||
<div class="max-w-7xl mx-auto px-6 mt-8 text-center text-xs text-gray-600">
|
||
Built for humans with AI assistants.
|
||
</div>
|
||
</footer>
|
||
|
||
|
||
|
||
<script>
|
||
(function() {
|
||
const W = 1000, H = 460;
|
||
function project(lon, lat) {
|
||
const latR = Math.min(Math.abs(lat), 85) * Math.PI / 180 * (lat < 0 ? -1 : 1);
|
||
const miller = 1.25 * Math.log(Math.tan(Math.PI/4 + 0.4*latR));
|
||
const maxMiller = 1.25 * Math.log(Math.tan(Math.PI/4 + 0.4*80*Math.PI/180));
|
||
const x = (lon + 180) / 360 * W;
|
||
const y = H/2 - (miller / (2*maxMiller)) * H;
|
||
return [Math.round(x*10)/10, Math.round(y*10)/10];
|
||
}
|
||
|
||
function addVisitorDot(lat, lon, city) {
|
||
const svg = document.getElementById('worldmap');
|
||
if (!svg) return;
|
||
const [x, y] = project(lon, lat);
|
||
const ns = 'http://www.w3.org/2000/svg';
|
||
|
||
// Pulse ring
|
||
const ring = document.createElementNS(ns, 'circle');
|
||
ring.setAttribute('cx', x); ring.setAttribute('cy', y);
|
||
ring.setAttribute('r', '3'); ring.setAttribute('fill', 'none');
|
||
ring.setAttribute('stroke', '#EF4444'); ring.setAttribute('stroke-width', '1.5');
|
||
const a1 = document.createElementNS(ns, 'animate');
|
||
a1.setAttribute('attributeName', 'r'); a1.setAttribute('values', '3;16;3');
|
||
a1.setAttribute('dur', '2s'); a1.setAttribute('repeatCount', 'indefinite');
|
||
const a2 = document.createElementNS(ns, 'animate');
|
||
a2.setAttribute('attributeName', 'stroke-opacity'); a2.setAttribute('values', '0.8;0;0.8');
|
||
a2.setAttribute('dur', '2s'); a2.setAttribute('repeatCount', 'indefinite');
|
||
ring.appendChild(a1); ring.appendChild(a2);
|
||
|
||
// Dot
|
||
const dot = document.createElementNS(ns, 'circle');
|
||
dot.setAttribute('cx', x); dot.setAttribute('cy', y);
|
||
dot.setAttribute('r', '4'); dot.setAttribute('fill', '#EF4444');
|
||
dot.setAttribute('stroke', '#0a1628'); dot.setAttribute('stroke-width', '1.5');
|
||
|
||
// Label
|
||
const label = document.createElementNS(ns, 'text');
|
||
label.setAttribute('x', x); label.setAttribute('y', y + 15);
|
||
label.setAttribute('font-family', 'Inter,sans-serif');
|
||
label.setAttribute('font-size', '10');
|
||
label.setAttribute('fill', '#EF4444');
|
||
label.setAttribute('text-anchor', 'middle');
|
||
label.setAttribute('font-weight', '500');
|
||
label.textContent = city || 'You';
|
||
|
||
svg.appendChild(ring);
|
||
svg.appendChild(dot);
|
||
svg.appendChild(label);
|
||
}
|
||
|
||
const POPS = [
|
||
{name:"Washington D.C.", region:"us-east-1", lat:37.5, lon:-77.5},
|
||
{name:"San Francisco", region:"us-west-1", lat:37.8, lon:-122.4},
|
||
{name:"Montréal", region:"ca-central-1", lat:45.5, lon:-73.6},
|
||
{name:"Mexico City", region:"mx-central-1", lat:19.4, lon:-99.1},
|
||
{name:"Bogotá", region:"sa-bogota", lat:4.7, lon:-74.1},
|
||
{name:"São Paulo", region:"sa-east-1", lat:-23.6, lon:-46.6},
|
||
{name:"Santiago", region:"sa-west-1", lat:-33.4, lon:-70.6},
|
||
{name:"London", region:"eu-west-2", lat:51.5, lon:-0.1},
|
||
{name:"Zürich", region:"eu-central-2", lat:47.4, lon:8.5},
|
||
{name:"Madrid", region:"eu-south-2", lat:40.4, lon:-3.7},
|
||
{name:"Stockholm", region:"eu-north-1", lat:59.3, lon:18.1},
|
||
{name:"Istanbul", region:"tr-west-1", lat:41.0, lon:28.9},
|
||
{name:"Dubai", region:"me-central-1", lat:25.2, lon:55.3},
|
||
{name:"Lagos", region:"af-west-1", lat:6.5, lon:3.4},
|
||
{name:"Nairobi", region:"af-east-1", lat:-1.3, lon:36.8},
|
||
{name:"Cape Town", region:"af-south-1", lat:-33.9, lon:18.4},
|
||
{name:"Mumbai", region:"ap-south-1", lat:19.1, lon:72.9},
|
||
{name:"Singapore", region:"ap-southeast-1", lat:1.3, lon:103.8},
|
||
{name:"Sydney", region:"ap-southeast-2", lat:-33.9, lon:151.2},
|
||
{name:"Tokyo", region:"ap-northeast-1", lat:35.7, lon:139.7},
|
||
{name:"Seoul", region:"ap-northeast-2", lat:37.6, lon:126.9},
|
||
{name:"Hong Kong", region:"ap-east-1", lat:22.3, lon:114.2},
|
||
];
|
||
|
||
function findClosestPop(lat, lon) {
|
||
return POPS.reduce((best, p) => {
|
||
const d = (lat-p.lat)**2 + (lon-p.lon)**2;
|
||
const bd = (lat-best.lat)**2 + (lon-best.lon)**2;
|
||
return d < bd ? p : best;
|
||
});
|
||
}
|
||
|
||
function handleGeoData(d) {
|
||
if (!d.latitude || !d.longitude) return;
|
||
addVisitorDot(d.latitude, d.longitude, d.city || 'You');
|
||
|
||
const closest = findClosestPop(d.latitude, d.longitude);
|
||
const nameEl = document.getElementById('closest-name');
|
||
const subEl = document.getElementById('closest-sub');
|
||
const buyEl = document.getElementById('closest-buy');
|
||
if (nameEl) nameEl.textContent = closest.name;
|
||
if (subEl) subEl.textContent = d.city ? `~${d.city}` : 'Your region';
|
||
if (buyEl) buyEl.href = `/signup?region=${closest.region}`;
|
||
}
|
||
|
||
// Ask browser geolocation first (accurate, triggers permission prompt)
|
||
// Fall back to server-side IP lookup if denied or unavailable
|
||
function tryIPGeo() {
|
||
fetch('/geo')
|
||
.then(r => r.json())
|
||
.then(d => { if (d.latitude) handleGeoData(d); })
|
||
.catch(() => {});
|
||
}
|
||
|
||
if (navigator.geolocation) {
|
||
navigator.geolocation.getCurrentPosition(
|
||
pos => {
|
||
handleGeoData({
|
||
latitude: pos.coords.latitude,
|
||
longitude: pos.coords.longitude,
|
||
city: '', region: '', country_name: '', country_code: ''
|
||
});
|
||
},
|
||
() => tryIPGeo() // denied — fall back to IP
|
||
);
|
||
} else {
|
||
tryIPGeo();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
</html> |