354 lines
17 KiB
HTML
354 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr" data-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Vela — Votre serveur privé, prêt à l'emploi</title>
|
|
<style>
|
|
* { margin:0; padding:0; box-sizing:border-box; }
|
|
|
|
:root {
|
|
--bg: #050505;
|
|
--bg2: #0a0a0a;
|
|
--surface: #111111;
|
|
--border: #222222;
|
|
--text: #ffffff;
|
|
--muted: #888888;
|
|
--accent: #3b82f6;
|
|
--accent-hover: #2563eb;
|
|
--green: #22c55e;
|
|
--radius: 12px;
|
|
}
|
|
|
|
[data-theme="light"] {
|
|
--bg: #fafafa;
|
|
--bg2: #f0f0f0;
|
|
--surface: #ffffff;
|
|
--border: #e0e0e0;
|
|
--text: #111111;
|
|
--muted: #666666;
|
|
--accent: #3b82f6;
|
|
--accent-hover: #2563eb;
|
|
--green: #16a34a;
|
|
}
|
|
|
|
body {
|
|
font-family: Inter, system-ui, -apple-system, sans-serif;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
line-height: 1.6;
|
|
transition: background .2s, color .2s;
|
|
}
|
|
|
|
.container { max-width:1100px; margin:0 auto; padding:0 24px; }
|
|
|
|
/* Nav */
|
|
nav {
|
|
display:flex; align-items:center; justify-content:space-between;
|
|
padding:16px 24px; max-width:1100px; margin:0 auto;
|
|
border-bottom:1px solid var(--border);
|
|
}
|
|
nav .logo { font-size:20px; font-weight:700; color:var(--text); text-decoration:none; }
|
|
nav .nav-links { display:flex; gap:20px; align-items:center; }
|
|
nav a { color:var(--muted); text-decoration:none; font-size:14px; transition:color .15s; }
|
|
nav a:hover { color:var(--text); }
|
|
.lang-btn, .theme-btn {
|
|
background:none; border:1px solid var(--border); color:var(--muted);
|
|
padding:6px 12px; border-radius:6px; cursor:pointer; font-size:13px;
|
|
transition:all .15s;
|
|
}
|
|
.lang-btn:hover, .theme-btn:hover { color:var(--text); border-color:var(--accent); }
|
|
|
|
/* Sections */
|
|
section { padding:80px 0; }
|
|
.hero { text-align:center; padding:100px 0 80px; }
|
|
.hero h1 { font-size:clamp(32px,5vw,56px); font-weight:800; line-height:1.1; margin-bottom:20px; letter-spacing:-1px; }
|
|
.hero p { font-size:18px; color:var(--muted); max-width:600px; margin:0 auto 32px; }
|
|
.btn { display:inline-block; padding:14px 28px; border-radius:8px; font-size:15px; font-weight:600; text-decoration:none; cursor:pointer; border:none; transition:all .15s; }
|
|
.btn-primary { background:var(--accent); color:#fff; } .btn-primary:hover { background:var(--accent-hover); transform:translateY(-1px); }
|
|
.btn-ghost { background:transparent; color:var(--text); border:1px solid var(--border); margin-left:12px; }
|
|
.btn-ghost:hover { border-color:var(--accent); }
|
|
|
|
h2 { font-size:32px; font-weight:700; text-align:center; margin-bottom:16px; letter-spacing:-.5px; }
|
|
.section-sub { text-align:center; color:var(--muted); font-size:16px; margin-bottom:48px; max-width:600px; margin-left:auto; margin-right:auto; }
|
|
|
|
/* Pricing */
|
|
.pricing-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:20px; }
|
|
.pricing-card {
|
|
background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
|
|
padding:28px; text-align:center; transition:border-color .2s;
|
|
}
|
|
.pricing-card:hover { border-color:var(--accent); }
|
|
.pricing-card h3 { font-size:20px; margin-bottom:4px; }
|
|
.pricing-card .price { font-size:32px; font-weight:800; margin:12px 0; color:var(--accent); }
|
|
.pricing-card .price small { font-size:14px; font-weight:400; color:var(--muted); }
|
|
.pricing-card .desc { color:var(--muted); font-size:14px; margin-bottom:16px; min-height:40px; }
|
|
.pricing-card .specs { text-align:left; font-size:13px; color:var(--muted); margin-bottom:20px; }
|
|
.pricing-card .specs li { padding:4px 0; list-style:none; }
|
|
.pricing-card .specs li::before { content:"✓ "; color:var(--green); }
|
|
|
|
/* Why */
|
|
.reasons { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:24px; }
|
|
.reason { text-align:center; padding:24px; }
|
|
.reason .icon { font-size:36px; margin-bottom:12px; }
|
|
.reason h4 { font-size:16px; margin-bottom:8px; }
|
|
.reason p { font-size:14px; color:var(--muted); }
|
|
|
|
/* Steps */
|
|
.steps { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:32px; text-align:center; }
|
|
.step .num { width:48px; height:48px; background:var(--accent); color:#fff; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; font-size:20px; font-weight:700; margin-bottom:16px; }
|
|
.step h4 { font-size:16px; margin-bottom:6px; }
|
|
.step p { font-size:14px; color:var(--muted); }
|
|
|
|
/* CTA */
|
|
.cta { text-align:center; background:var(--surface); border-radius:var(--radius); padding:60px 24px; margin-bottom:80px; }
|
|
.cta h2 { margin-bottom:8px; }
|
|
.cta p { color:var(--muted); margin-bottom:24px; }
|
|
|
|
/* Footer */
|
|
footer { border-top:1px solid var(--border); padding:24px; text-align:center; color:var(--muted); font-size:13px; }
|
|
footer .tagline { font-size:15px; color:var(--text); margin-bottom:8px; font-weight:600; }
|
|
|
|
/* Responsive */
|
|
@media (max-width:640px) {
|
|
section { padding:48px 0; }
|
|
.hero { padding:60px 0 48px; }
|
|
nav .nav-links { gap:10px; }
|
|
nav a.hide-mobile { display:none; }
|
|
}
|
|
|
|
[lang="en"] .fr { display:none; }
|
|
[lang="fr"] .en { display:none; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<nav>
|
|
<a href="/" class="logo">Vela</a>
|
|
<div class="nav-links">
|
|
<a href="#pricing" class="hide-mobile"><span class="fr">Offres</span><span class="en">Pricing</span></a>
|
|
<a href="#how" class="hide-mobile"><span class="fr">Comment ça marche</span><span class="en">How it works</span></a>
|
|
<button class="lang-btn" onclick="toggleLang()" id="langBtn">EN</button>
|
|
<button class="theme-btn" onclick="toggleTheme()" id="themeBtn">☀️</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- HERO -->
|
|
<section class="hero">
|
|
<div class="container">
|
|
<h1><span class="fr">Vos données.<br>Chez vous.</span><span class="en">Your data.<br>At home.</span></h1>
|
|
<p><span class="fr">Vous prenez une photo. Vous rentrez. Elle est déjà là. Reconnaissance de visages, recherche intelligente, sauvegardes — tout tourne chez vous, pas dans le cloud de Google.</span><span class="en">You take a photo. You get home. It's already there. Face recognition, smart search, backups — all runs at home, not on Google's cloud.</span></p>
|
|
<a href="#pricing" class="btn btn-primary"><span class="fr">Voir les offres</span><span class="en">See plans</span></a>
|
|
<a href="https://wa.me/212725569519" class="btn btn-ghost"><span class="fr">WhatsApp</span><span class="en">WhatsApp</span></a>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- PROBLEM -->
|
|
<section style="background:var(--bg2);">
|
|
<div class="container">
|
|
<h2><span class="fr">Vous connaissez ça ?</span><span class="en">Sound familiar?</span></h2>
|
|
<div class="reasons">
|
|
<div class="reason">
|
|
<div class="icon">📱</div>
|
|
<h4 class="fr">Stockage plein</h4><h4 class="en">Storage full</h4>
|
|
<p class="fr">Google Photos ou iCloud vous demandent de payer chaque mois.</p>
|
|
<p class="en">Google Photos or iCloud asks you to pay every month.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon">💸</div>
|
|
<h4 class="fr">Abonnements qui s'accumulent</h4><h4 class="en">Subscriptions pile up</h4>
|
|
<p class="fr">Google One, iCloud, Dropbox... chaque mois, ça monte.</p>
|
|
<p class="en">Google One, iCloud, Dropbox... it adds up every month.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon">🔒</div>
|
|
<h4 class="fr">Vos données chez les autres</h4><h4 class="en">Your data on their servers</h4>
|
|
<p class="fr">Vos photos de famille sont sur les serveurs de Google.</p>
|
|
<p class="en">Your family photos live on Google's servers.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon">😰</div>
|
|
<h4 class="fr">Pas de vraie sauvegarde</h4><h4 class="en">No real backup</h4>
|
|
<p class="fr">Si votre téléphone tombe, où sont vos fichiers ?</p>
|
|
<p class="en">If your phone breaks, where are your files?</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SOLUTION -->
|
|
<section>
|
|
<div class="container">
|
|
<h2><span class="fr">La solution Vela</span><span class="en">The Vela solution</span></h2>
|
|
<p class="section-sub"><span class="fr">Un petit boîtier chez vous. Tout votre monde numérique, en sécurité, sans abonnement.</span><span class="en">A small box in your home. Your entire digital world, safe, no subscription.</span></p>
|
|
<div class="reasons">
|
|
<div class="reason">
|
|
<div class="icon"><img src="/static/immich-logo.svg" alt="Immich" style="height:40px;"></div>
|
|
<h4>Immich</h4>
|
|
<p class="fr">Vous prenez une photo. Vous rentrez chez vous. Elle est déjà sur votre Vela. Reconnaissance de visages, recherche par texte ("chien à la plage") — tout est privé, rien ne part chez Google.</p>
|
|
<p class="en">You take a photo. You get home. It's already on your Vela. Face recognition, text search ("dog at the beach") — all private, nothing goes to Google.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon"><img src="/static/nextcloud-logo.svg" alt="Nextcloud" style="height:36px;"></div>
|
|
<h4>Nextcloud</h4>
|
|
<p class="fr">Vos fichiers, vos documents, votre calendrier. Tout se synchronise tout seul entre votre téléphone et votre Vela.</p>
|
|
<p class="en">Your files, documents, calendar. Everything syncs by itself between your phone and your Vela.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon">💾</div>
|
|
<h4 class="fr">Sauvegarde automatique</h4><h4 class="en">Auto backup</h4>
|
|
<p class="fr">Vos données sont sauvegardées automatiquement. Plus jamais de panique.</p>
|
|
<p class="en">Your data is backed up automatically. No more panic.</p>
|
|
</div>
|
|
<div class="reason">
|
|
<div class="icon">🇲🇦</div>
|
|
<h4 class="fr">Installé à Casablanca</h4><h4 class="en">Installed in Casablanca</h4>
|
|
<p class="fr">On vient chez vous, on installe, on configure. Vous n'avez rien à faire.</p>
|
|
<p class="en">We come to your home, install, configure. You do nothing.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- PRICING -->
|
|
<section id="pricing" style="background:var(--bg2);">
|
|
<div class="container">
|
|
<h2><span class="fr">Choisissez votre Vela</span><span class="en">Choose your Vela</span></h2>
|
|
<p class="section-sub"><span class="fr">Prix unique. Pas d'abonnement. Installation incluse.</span><span class="en">One-time price. No subscription. Installation included.</span></p>
|
|
<div class="pricing-grid" id="pricingGrid">
|
|
<div class="pricing-card"><p style="color:var(--muted);">Chargement...</p></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- HOW IT WORKS -->
|
|
<section id="how">
|
|
<div class="container">
|
|
<h2><span class="fr">Comment ça marche</span><span class="en">How it works</span></h2>
|
|
<p class="section-sub"><span class="fr">Simple, rapide, sans stress.</span><span class="en">Simple, fast, stress-free.</span></p>
|
|
<div class="steps">
|
|
<div class="step">
|
|
<div class="num">1</div>
|
|
<h4 class="fr">Vous choisissez</h4><h4 class="en">You choose</h4>
|
|
<p class="fr">Un modèle Vela adapté à vos besoins.</p>
|
|
<p class="en">A Vela model that fits your needs.</p>
|
|
</div>
|
|
<div class="step">
|
|
<div class="num">2</div>
|
|
<h4 class="fr">On installe</h4><h4 class="en">We install</h4>
|
|
<p class="fr">On vient chez vous, on branche, on configure tout.</p>
|
|
<p class="en">We come to your home, plug in, configure everything.</p>
|
|
</div>
|
|
<div class="step">
|
|
<div class="num">3</div>
|
|
<h4 class="fr">Vous profitez</h4><h4 class="en">You enjoy</h4>
|
|
<p class="fr">Vos photos, fichiers, sauvegardes — tout est là, chez vous.</p>
|
|
<p class="en">Your photos, files, backups — all there, at home.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- CTA -->
|
|
<section>
|
|
<div class="container">
|
|
<div class="cta">
|
|
<h2><span class="fr">Prêt à récupérer vos données ?</span><span class="en">Ready to take back your data?</span></h2>
|
|
<p><span class="fr">Un Vela chez vous, c'est la tranquillité. Contactez-nous.</span><span class="en">A Vela at home means peace of mind. Contact us.</span></p>
|
|
<a href="https://wa.me/212725569519" class="btn btn-primary"><span class="fr">Discutons sur WhatsApp</span><span class="en">Chat on WhatsApp</span></a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<footer>
|
|
<div class="tagline"><span class="fr">Vos données. Chez vous.</span><span class="en">Your data. At home.</span></div>
|
|
<div>Vela © 2026 · <a href="/admin" style="color:var(--muted);text-decoration:none;opacity:0.3;font-size:12px;">Admin</a></div>
|
|
</footer>
|
|
|
|
<script>
|
|
// ── Theme ──
|
|
function getTheme() { return localStorage.getItem('vela_theme') || 'dark'; }
|
|
function setTheme(t) {
|
|
document.documentElement.setAttribute('data-theme', t);
|
|
document.getElementById('themeBtn').textContent = t === 'light' ? '🌙' : '☀️';
|
|
localStorage.setItem('vela_theme', t);
|
|
}
|
|
function toggleTheme() { setTheme(getTheme() === 'dark' ? 'light' : 'dark'); }
|
|
setTheme(getTheme());
|
|
|
|
// ── Language ──
|
|
function getLang() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const urlLang = params.get('lang');
|
|
if (urlLang === 'fr' || urlLang === 'en') { localStorage.setItem('vela_lang', urlLang); return urlLang; }
|
|
return localStorage.getItem('vela_lang') || 'fr';
|
|
}
|
|
function setLang(l) {
|
|
document.documentElement.setAttribute('lang', l);
|
|
document.getElementById('langBtn').textContent = l === 'fr' ? 'EN' : 'FR';
|
|
localStorage.setItem('vela_lang', l);
|
|
// Update URL
|
|
const url = new URL(window.location);
|
|
url.searchParams.set('lang', l);
|
|
window.history.replaceState({}, '', url);
|
|
}
|
|
function toggleLang() { setLang(getLang() === 'fr' ? 'en' : 'fr'); }
|
|
setLang(getLang());
|
|
// Redirect from clean URL to ?lang= if no param
|
|
if (!window.location.search.includes('lang=') && getLang() === 'en') {
|
|
const url = new URL(window.location);
|
|
url.searchParams.set('lang', 'en');
|
|
window.history.replaceState({}, '', url);
|
|
}
|
|
|
|
// ── Pricing ──
|
|
async function loadPricing() {
|
|
try {
|
|
const r = await fetch('/api/public/pricing');
|
|
const tiers = await r.json();
|
|
const grid = document.getElementById('pricingGrid');
|
|
const specs = {
|
|
fr: {
|
|
"Rif": ["Mini PC", "512 Go SSD", "8 Go RAM", "Immich + Nextcloud", "Installation incluse"],
|
|
"Rif+": ["Mini PC", "512 Go SSD", "8 Go RAM", "Immich + Nextcloud", '<a href="/backup?lang=fr" style="color:var(--green);">+ Sauvegarde automatique 1 To</a>', "Installation incluse"],
|
|
"Atlas": ["Mini PC", "1 To SSD", "16 Go RAM", "Immich + Nextcloud", "Installation incluse"],
|
|
"Atlas+": ["Mini PC", "1 To SSD", "16 Go RAM", "Immich + Nextcloud", '<a href="/backup?lang=fr" style="color:var(--green);">+ Sauvegarde redondante 1 To</a>', "Installation incluse"]
|
|
},
|
|
en: {
|
|
"Rif": ["Mini PC", "512 GB SSD", "8 GB RAM", "Immich + Nextcloud", "Installation included"],
|
|
"Rif+": ["Mini PC", "512 GB SSD", "8 GB RAM", "Immich + Nextcloud", '<a href="/backup?lang=en" style="color:var(--green);">+ Auto backup 1 TB</a>', "Installation included"],
|
|
"Atlas": ["Mini PC", "1 TB SSD", "16 GB RAM", "Immich + Nextcloud", "Installation included"],
|
|
"Atlas+": ["Mini PC", "1 TB SSD", "16 GB RAM", "Immich + Nextcloud", '<a href="/backup?lang=en" style="color:var(--green);">+ Redundant backup 1 TB</a>', "Installation included"]
|
|
}
|
|
};
|
|
const desc = {
|
|
fr: {
|
|
"Rif": "Pour démarrer avec vos photos et fichiers.",
|
|
"Rif+": "Le meilleur rapport qualité-prix avec sauvegarde.",
|
|
"Atlas": "Plus de stockage et de puissance.",
|
|
"Atlas+": "La formule complète, sauvegarde redondante."
|
|
},
|
|
en: {
|
|
"Rif": "Start with your photos and files.",
|
|
"Rif+": "Best value with backup included.",
|
|
"Atlas": "More storage and power.",
|
|
"Atlas+": "The full package, redundant backup."
|
|
}
|
|
};
|
|
const lang = getLang();
|
|
grid.innerHTML = tiers.map(t => `
|
|
<div class="pricing-card">
|
|
<h3>${t.name}</h3>
|
|
<div class="price">${Number(t.sell_price).toLocaleString('fr-MA')} <small>MAD</small></div>
|
|
<div class="desc">${(desc[lang]||desc.fr)[t.name] || t.description || ''}</div>
|
|
<ul class="specs">${(specs[lang]||specs.fr)[t.name]?.map(s => `<li>${s}</li>`).join('') || ''}</ul>
|
|
<a href="https://wa.me/212725569519" class="btn btn-primary" style="width:100%;text-align:center;">${lang==='fr'?'Commander':'Order'}</a>
|
|
</div>
|
|
`).join('');
|
|
} catch(e) { document.getElementById('pricingGrid').innerHTML = '<p style="color:var(--muted);text-align:center;">Pricing unavailable</p>'; }
|
|
}
|
|
loadPricing();
|
|
</script>
|
|
</body>
|
|
</html>
|