Palette (promo/, les 4 pages) — les teintes rose, verte et violette etaient trop presentes une fois etalees au tour precedent. Reduction d'environ 40 % : rose .075 -> .044, vert .058 -> .034, violet .062 -> .036, arrets intermediaires abaisses dans la meme proportion, opacite de la nappe .aurora .44 -> .32. Geometrie inchangee : meme largeur, meme position, seule l'intensite baisse. 0 conflit CSS entre les quatre pages. forge-01 — la note precedente presentait comme une contradiction a trancher le fait que le plan dise `etat: planifie` et que le CHANGELOG du 2026-07-03 dise le branding « prouve sur forge-01 ». Ce n'en etait pas une : l'hote a ete cree, puis supprime. Le plan decrit l'etat COURANT, le CHANGELOG un etat PASSE — les deux disent vrai. La preuve reste valable, simplement non rejouable tant que l'hote n'est pas recree. roles/serveur_forgejo/README.md corrige. Valide : equilibre accolades/parentheses du CSS, 0 conflit CSS, prouver.py --verifier -> CONFORME 16/16. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
748 lines
37 KiB
HTML
748 lines
37 KiB
HTML
<!doctype html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Set-OPS — La valeur · Chezlepro</title>
|
|
<meta name="description" content="Ce que Set-OPS remplace, ce qu'il coûte, ce qu'il prouve. Calculateur de coût total, tableau des équivalences SaaS, registre d'affirmations vérifiables. Infrastructure numérique souveraine sur votre propre matériel.">
|
|
<meta name="color-scheme" content="dark">
|
|
</head>
|
|
<body>
|
|
<style>
|
|
:root{
|
|
--night:#05060f; --night-2:#0a0d24; --night-3:#0e1640;
|
|
--ink:#e9ecff; --dim:#99a1c9; --dim-2:#727aa6;
|
|
--line:rgba(255,255,255,.10); --line-2:rgba(255,255,255,.06);
|
|
--panel:rgba(255,255,255,.045); --panel-2:rgba(255,255,255,.03);
|
|
--teal:#4fe3c1; --cyan:#56c2ff; --violet:#a98bff; --amber:#ffc46b;
|
|
--rose:#ff6fc4; --vert:#5cff9d; /* frange magenta + vert fluo de l'aurore */
|
|
--aurora:linear-gradient(100deg,var(--teal) 0%,var(--cyan) 46%,var(--violet) 100%);
|
|
--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Noto Sans","Helvetica Neue",Arial,sans-serif;
|
|
--mono:ui-monospace,"SF Mono","JetBrains Mono",Menlo,Consolas,"Liberation Mono",monospace;
|
|
--wrap:1140px;
|
|
}
|
|
*{box-sizing:border-box}
|
|
html{scroll-behavior:smooth}
|
|
body{
|
|
margin:0; font-family:var(--sans); color:var(--ink); line-height:1.6;
|
|
background:
|
|
radial-gradient(1200px 760px at 82% -8%,#141c4c 0%,transparent 58%),
|
|
radial-gradient(900px 620px at 8% -2%,#0e1640 0%,transparent 55%),
|
|
radial-gradient(1500px 1020px at 76% 28%,rgba(255,111,196,.044) 0%,rgba(255,111,196,.021) 44%,transparent 82%),
|
|
radial-gradient(1620px 1120px at 20% 64%,rgba(92,255,157,.034) 0%,rgba(92,255,157,.016) 46%,transparent 84%),
|
|
radial-gradient(1400px 960px at 52% 106%,rgba(169,139,255,.036) 0%,rgba(169,139,255,.017) 44%,transparent 80%),
|
|
linear-gradient(180deg,var(--night-2) 0%,var(--night) 62%) fixed;
|
|
-webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
|
|
overflow-x:hidden;
|
|
}
|
|
#sky{position:fixed;inset:0;z-index:-2;pointer-events:none}
|
|
#sky canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
|
|
.aurora{
|
|
position:fixed;left:-10%;right:-10%;top:-22%;height:74vh;z-index:-1;pointer-events:none;
|
|
filter:blur(86px) saturate(140%);opacity:.32;
|
|
background:
|
|
radial-gradient(60% 80% at 22% 50%,var(--vert) 0%,transparent 78%),
|
|
radial-gradient(40% 60% at 20% 30%,var(--teal) 0%,transparent 70%),
|
|
radial-gradient(45% 70% at 55% 20%,var(--cyan) 0%,transparent 70%),
|
|
radial-gradient(40% 65% at 82% 35%,var(--violet) 0%,transparent 70%),
|
|
radial-gradient(58% 78% at 79% 57%,var(--rose) 0%,transparent 78%);
|
|
animation:drift 24s ease-in-out infinite alternate;
|
|
}
|
|
@keyframes drift{from{transform:translate(-3%,0) scale(1)}to{transform:translate(3%,2%) scale(1.08)}}
|
|
.wrap{max-width:var(--wrap);margin-inline:auto;padding-inline:24px}
|
|
header.nav{position:sticky;top:0;z-index:20;backdrop-filter:blur(12px);
|
|
background:linear-gradient(180deg,rgba(5,6,15,.72),rgba(5,6,15,.28));
|
|
border-bottom:1px solid var(--line-2)}
|
|
.nav .wrap{display:flex;align-items:center;gap:20px;height:64px}
|
|
.brand{display:flex;align-items:center;gap:11px;font-weight:650;letter-spacing:.2px;text-decoration:none;color:var(--ink)}
|
|
.brand svg{width:30px;height:30px;flex:none}
|
|
.brand b{font-weight:750}
|
|
.nav nav{margin-left:auto;display:flex;gap:24px;align-items:center}
|
|
.nav nav a{color:var(--dim);text-decoration:none;font-size:.94rem;font-weight:500}
|
|
.nav nav a:hover{color:var(--ink)}
|
|
.nav nav a[aria-current="page"]{color:var(--ink);font-weight:640}
|
|
.nav nav a[aria-current="page"]::after{content:"";display:block;height:2px;border-radius:2px;background:var(--aurora);margin-top:3px}
|
|
.nav .cta-mini{padding:8px 16px;border-radius:999px;background:var(--aurora);color:#04121a;font-weight:700;font-size:.9rem}
|
|
.nav .cta-mini:hover{color:#04121a;filter:brightness(1.08)}
|
|
@media(max-width:860px){.nav nav a:not(.cta-mini){display:none}}
|
|
.eyebrow{font-family:var(--mono);font-size:.76rem;letter-spacing:.28em;text-transform:uppercase;color:var(--cyan);font-weight:600}
|
|
h1,h2,h3{text-wrap:balance;line-height:1.08;margin:0}
|
|
.grad{background:var(--aurora);-webkit-background-clip:text;background-clip:text;color:transparent}
|
|
p{margin:0}
|
|
.lede{color:var(--dim);font-size:1.12rem;max-width:60ch}
|
|
.hero{position:relative;padding:82px 0 60px}
|
|
.hero .eyebrow{display:block;margin-bottom:22px}
|
|
.hero h1{font-size:clamp(2.3rem,6vw,4.6rem);font-weight:800;letter-spacing:-.02em;max-width:17ch}
|
|
.hero .lede{margin-top:26px;font-size:clamp(1.05rem,1.9vw,1.26rem);max-width:64ch}
|
|
.cta-row{display:flex;flex-wrap:wrap;gap:14px;margin-top:36px}
|
|
.btn{display:inline-flex;align-items:center;gap:9px;padding:14px 24px;border-radius:999px;font-weight:700;text-decoration:none;font-size:1rem;border:1px solid transparent;transition:transform .15s ease,filter .15s ease,border-color .15s ease}
|
|
.btn-primary{background:var(--aurora);color:#04121a}
|
|
.btn-primary:hover{transform:translateY(-2px);filter:brightness(1.08)}
|
|
.btn-ghost{color:var(--ink);border-color:var(--line);background:var(--panel)}
|
|
.btn-ghost:hover{border-color:var(--cyan);transform:translateY(-2px)}
|
|
section{padding:72px 0;position:relative}
|
|
.sec-head{max-width:68ch;margin-bottom:42px}
|
|
.sec-head h2{font-size:clamp(1.75rem,3.4vw,2.6rem);font-weight:750;letter-spacing:-.015em;margin-top:14px}
|
|
.sec-head p{margin-top:16px;color:var(--dim);font-size:1.07rem}
|
|
.rule{height:1px;border:0;margin:0;background:linear-gradient(90deg,rgba(92,255,157,.28),rgba(86,194,255,.22) 34%,rgba(255,111,196,.24) 68%,transparent)}
|
|
/* ---- calculateur ---- */
|
|
.calc{display:grid;grid-template-columns:minmax(0,340px) minmax(0,1fr);gap:26px;align-items:start}
|
|
@media(max-width:900px){.calc{grid-template-columns:1fr}}
|
|
.panel{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:24px}
|
|
.panel h3{font-size:1.02rem;font-weight:700;margin-bottom:6px}
|
|
.panel .hint{color:var(--dim-2);font-size:.85rem;margin-bottom:20px}
|
|
.field{margin-bottom:20px}
|
|
.field label{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:.9rem;color:var(--dim);margin-bottom:9px}
|
|
.field label b{color:var(--ink);font-family:var(--mono);font-size:.95rem;font-weight:600}
|
|
.field input[type=range]{width:100%;accent-color:#56c2ff;height:22px;cursor:pointer}
|
|
.field .sub{font-size:.78rem;color:var(--dim-2);margin-top:5px}
|
|
.results{display:grid;gap:18px}
|
|
.verdict{background:linear-gradient(135deg,rgba(79,227,193,.11),rgba(169,139,255,.09));border:1px solid rgba(86,194,255,.3);border-radius:18px;padding:26px}
|
|
.verdict .big{font-size:clamp(1.6rem,4.2vw,2.5rem);font-weight:800;letter-spacing:-.02em;line-height:1.15}
|
|
.verdict p{color:var(--dim);margin-top:12px;font-size:.99rem;max-width:56ch}
|
|
.vs{display:grid;grid-template-columns:1fr 1fr;gap:16px}
|
|
@media(max-width:560px){.vs{grid-template-columns:1fr}}
|
|
.col{background:var(--panel-2);border:1px solid var(--line-2);border-radius:15px;padding:20px}
|
|
.col .who{font-family:var(--mono);font-size:.75rem;letter-spacing:.14em;text-transform:uppercase;color:var(--dim-2)}
|
|
.col .amt{font-size:1.85rem;font-weight:780;letter-spacing:-.02em;margin:8px 0 3px;font-variant-numeric:tabular-nums}
|
|
.col.saas .amt{color:var(--amber)}
|
|
.col.setops .amt{color:var(--teal)}
|
|
.col .per{font-size:.84rem;color:var(--dim-2)}
|
|
.lines{list-style:none;padding:0;margin:16px 0 0;display:grid;gap:7px;font-size:.87rem}
|
|
.lines li{display:flex;justify-content:space-between;gap:12px;color:var(--dim)}
|
|
.lines li span:last-child{font-family:var(--mono);color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
.lines li.zero span:last-child{color:var(--teal);font-weight:700}
|
|
.note{font-size:.87rem;color:var(--dim-2);margin-top:18px;max-width:76ch}
|
|
.note b{color:var(--dim)}
|
|
/* ---- tableau remplace ---- */
|
|
.tbl-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:16px;background:var(--panel-2)}
|
|
table{border-collapse:collapse;width:100%;min-width:640px;font-size:.94rem}
|
|
thead th{text-align:left;padding:15px 18px;font-family:var(--mono);font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;color:var(--dim-2);border-bottom:1px solid var(--line);font-weight:600;white-space:nowrap}
|
|
tbody td{padding:14px 18px;border-bottom:1px solid var(--line-2);vertical-align:top;color:var(--dim)}
|
|
tbody tr:last-child td{border-bottom:0}
|
|
tbody tr:hover{background:rgba(255,255,255,.022)}
|
|
tbody td:first-child{color:var(--ink);font-weight:640;white-space:nowrap}
|
|
tbody td.libre{color:var(--dim);font-family:var(--mono);font-size:.86rem}
|
|
.st{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:.7rem;letter-spacing:.07em;text-transform:uppercase;padding:4px 10px;border-radius:999px;white-space:nowrap;margin-left:auto;flex:none}
|
|
.st.ok{color:#7ff0d0;background:rgba(79,227,193,.12);border:1px solid rgba(79,227,193,.32)}
|
|
.st.wip{color:#ffd79a;background:rgba(255,196,107,.1);border:1px solid rgba(255,196,107,.3)}
|
|
/* ---- preuve ---- */
|
|
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:16px;margin-bottom:34px}
|
|
.stat{background:var(--panel-2);border:1px solid var(--line-2);border-radius:15px;padding:22px}
|
|
.stat .n{font-size:2rem;font-weight:800;letter-spacing:-.02em;background:var(--aurora);-webkit-background-clip:text;background-clip:text;color:transparent;font-variant-numeric:tabular-nums}
|
|
.stat .l{color:var(--dim);font-size:.9rem;margin-top:5px}
|
|
.term{background:#04050d;border:1px solid var(--line);border-radius:16px;overflow:hidden;font-family:var(--mono);font-size:.88rem}
|
|
.term .bar{display:flex;align-items:center;gap:7px;padding:11px 16px;background:rgba(255,255,255,.03);border-bottom:1px solid var(--line-2)}
|
|
.term .bar i{width:10px;height:10px;border-radius:50%;background:#2c3155;display:block}
|
|
.term .bar span{margin-left:8px;color:var(--dim-2);font-size:.78rem;letter-spacing:.05em}
|
|
.term pre{margin:0;padding:20px 18px;overflow-x:auto;line-height:1.75;color:var(--dim)}
|
|
.term .p{color:var(--violet)}
|
|
.term .c{color:var(--cyan)}
|
|
.term .g{color:var(--teal)}
|
|
.term .w{color:var(--ink)}
|
|
/* ---- colonnes génériques ---- */
|
|
.duo{display:grid;grid-template-columns:repeat(2,1fr);gap:20px}
|
|
@media(max-width:820px){.duo{grid-template-columns:1fr}}
|
|
.card{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:26px;overflow:hidden;transition:transform .2s ease,border-color .2s ease,box-shadow .2s ease}
|
|
.card:hover{transform:translateY(-3px);border-color:rgba(86,194,255,.42);box-shadow:0 18px 50px -24px rgba(86,194,255,.45)}
|
|
.card::before{content:"";position:absolute;inset:0 0 auto 0;height:2px;background:var(--aurora);opacity:.75}
|
|
.card h3{font-size:1.2rem;font-weight:720;margin-bottom:10px}
|
|
.card p{color:var(--dim);font-size:.95rem}
|
|
ul.does{list-style:none;padding:0;margin:16px 0 0;display:grid;gap:9px}
|
|
ul.does li{position:relative;padding-left:22px;color:var(--dim);font-size:.94rem}
|
|
ul.does li::before{content:"";position:absolute;left:2px;top:.62em;width:7px;height:7px;border-radius:2px;background:var(--aurora);transform:rotate(45deg)}
|
|
ul.does b{color:var(--ink);font-weight:640}
|
|
.honest{background:var(--panel-2);border:1px solid var(--line);border-left:3px solid var(--amber);border-radius:14px;padding:24px 26px}
|
|
.honest h3{font-size:1.04rem;font-weight:700;margin-bottom:12px;color:var(--amber)}
|
|
.honest ul{margin:0;padding-left:20px;display:grid;gap:10px}
|
|
.honest li{color:var(--dim);font-size:.95rem}
|
|
.honest b{color:var(--ink);font-weight:640}
|
|
.close{text-align:center;padding:88px 0 96px}
|
|
.close h2{font-size:clamp(1.9rem,4.6vw,3.1rem);font-weight:800;letter-spacing:-.02em;max-width:20ch;margin-inline:auto}
|
|
.close p{margin:20px auto 0;color:var(--dim);max-width:56ch;font-size:1.06rem}
|
|
.close .cta-row{justify-content:center}
|
|
footer{border-top:1px solid var(--line-2);padding:40px 0;color:var(--dim-2);font-size:.9rem}
|
|
footer .wrap{display:flex;flex-wrap:wrap;gap:16px 28px;align-items:center;justify-content:space-between}
|
|
footer a{color:var(--dim);text-decoration:none}
|
|
footer a:hover{color:var(--cyan)}
|
|
.reveal{opacity:0;transform:translateY(16px);transition:opacity .6s ease,transform .6s ease}
|
|
.reveal.in{opacity:1;transform:none}
|
|
@media(prefers-reduced-motion:reduce){
|
|
.reveal{opacity:1;transform:none;transition:none}
|
|
.aurora{animation:none}
|
|
html{scroll-behavior:auto}
|
|
}
|
|
</style>
|
|
|
|
<div id="sky" aria-hidden="true"><canvas></canvas></div>
|
|
<div class="aurora" aria-hidden="true"></div>
|
|
|
|
<header class="nav">
|
|
<div class="wrap">
|
|
<a class="brand" href="#top" aria-label="Set-OPS — Chezlepro">
|
|
<svg viewBox="0 0 32 32" role="img" aria-hidden="true"><defs>
|
|
<radialGradient id="sky1" cx="50%" cy="36%" r="75%"><stop offset="0%" stop-color="#10184a"/><stop offset="100%" stop-color="#05060f"/></radialGradient>
|
|
<linearGradient id="au1" x1="0" y1="1" x2="1" y2="0"><stop offset="0%" stop-color="#2ec18f"/><stop offset="45%" stop-color="#56c2ff"/><stop offset="100%" stop-color="#a98bff"/></linearGradient>
|
|
<radialGradient id="gl1" cx="50%" cy="50%" r="50%"><stop offset="0%" stop-color="#bfe9ff"/><stop offset="100%" stop-color="#bfe9ff" stop-opacity="0"/></radialGradient>
|
|
<radialGradient id="st1" cx="50%" cy="45%" r="60%"><stop offset="0%" stop-color="#fff"/><stop offset="100%" stop-color="#d6ecff"/></radialGradient>
|
|
</defs>
|
|
<circle cx="16" cy="16" r="16" fill="url(#sky1)"/>
|
|
<path d="M3 21 C 9 16, 13 23, 18 18 C 22 14, 26 17, 30 13" fill="none" stroke="url(#au1)" stroke-width="2.6" stroke-linecap="round" opacity=".85"/>
|
|
<circle cx="7" cy="9" r=".9" fill="#cfe6ff"/><circle cx="24" cy="8" r="1.1" fill="#fff"/><circle cx="26" cy="22" r=".8" fill="#bfe9ff"/><circle cx="9" cy="25" r=".7" fill="#cfe6ff"/>
|
|
<circle cx="16" cy="15" r="9" fill="url(#gl1)" opacity=".55"/>
|
|
<path d="M16 5 C 16.9 12.4, 17.6 13.1, 25 14 C 17.6 14.9, 16.9 15.6, 16 23 C 15.1 15.6, 14.4 14.9, 7 14 C 14.4 13.1, 15.1 12.4, 16 5 Z" fill="url(#st1)"/>
|
|
</svg>
|
|
<span>Set‑OPS <b>·</b> <span style="color:var(--dim);font-weight:500">Chezlepro</span></span>
|
|
</a>
|
|
<nav>
|
|
<a href="index.html">Capacités</a>
|
|
<a href="offres.html">Offres</a>
|
|
<a href="tarifs.html">Tarifs</a>
|
|
<a href="valeur.html" aria-current="page">Valeur</a>
|
|
<a class="cta-mini" href="https://chezlepro.ca/contact">Nous parler</a>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="top">
|
|
|
|
<!-- =================== HERO =================== -->
|
|
<div class="hero">
|
|
<div class="wrap">
|
|
<span class="eyebrow">Valeur · Coût total · Preuve</span>
|
|
<h1>Le nuage vous <span class="grad">loue</span> votre propre organisation.</h1>
|
|
<p class="lede">
|
|
Chaque mois, vous payez pour héberger vos courriels, vos documents, vos identités et
|
|
votre mémoire institutionnelle sur des serveurs qui ne vous appartiennent pas, sous des
|
|
lois qui ne sont pas les vôtres, à un prix que vous ne fixez pas.
|
|
Set‑OPS installe la même chose chez vous — avec du logiciel libre, sur votre
|
|
matériel — et vérifie par lui‑même qu'il tient parole.
|
|
</p>
|
|
<div class="cta-row">
|
|
<a class="btn btn-primary" href="#calcul">Faire le calcul →</a>
|
|
<a class="btn btn-ghost" href="#preuve">Voir la preuve</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="rule">
|
|
|
|
<!-- =================== CALCULATEUR =================== -->
|
|
<section id="calcul">
|
|
<div class="wrap">
|
|
<div class="sec-head reveal">
|
|
<span class="eyebrow">1 — L'arithmétique</span>
|
|
<h2>Vos chiffres, pas les nôtres.</h2>
|
|
<p>
|
|
Les hypothèses ci‑dessous sont des valeurs de départ, pas des promesses.
|
|
Remplacez‑les par votre réalité : l'addition se refait toute seule.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="calc reveal">
|
|
<div class="panel">
|
|
<h3>Votre situation</h3>
|
|
<p class="hint">Glissez les curseurs.</p>
|
|
|
|
<div class="field">
|
|
<label for="p">Personnes à desservir <b id="p-v">60</b></label>
|
|
<input type="range" id="p" min="5" max="250" step="5" value="60">
|
|
<p class="sub">Employé·es, membres et bénévoles ayant un compte.</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="s">Abonnements $/personne/mois <b id="s-v">26 $</b></label>
|
|
<input type="range" id="s" min="6" max="80" step="2" value="26">
|
|
<p class="sub">Suite bureautique, courriel, stockage, visioconférence, forge, sauvegarde — additionnés.</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="h">Matériel, achat unique <b id="h-v">9 000 $</b></label>
|
|
<input type="range" id="h" min="3000" max="40000" step="1000" value="9000">
|
|
<p class="sub">Serveurs et réseau, amortis sur 5 ans.</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="m">Mise en place, une fois <b id="m-v">15 000 $</b></label>
|
|
<input type="range" id="m" min="0" max="60000" step="1000" value="15000">
|
|
<p class="sub">Installation, migration, formation. Zéro si vous la faites vous‑même.</p>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="e">Exploitation $/mois <b id="e-v">600 $</b></label>
|
|
<input type="range" id="e" min="0" max="4000" step="50" value="600">
|
|
<p class="sub">Infogérance, ou le temps de votre propre équipe.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="results">
|
|
<div class="verdict">
|
|
<p class="big" id="verdict-big">—</p>
|
|
<p id="verdict-txt">—</p>
|
|
</div>
|
|
|
|
<div class="vs">
|
|
<div class="col saas">
|
|
<p class="who">Abonnements · 5 ans</p>
|
|
<p class="amt" id="saas-5">—</p>
|
|
<p class="per" id="saas-1">—</p>
|
|
<ul class="lines">
|
|
<li><span>Licences et sièges</span><span id="l-saas">—</span></li>
|
|
<li><span>Matériel</span><span>0 $</span></li>
|
|
<li><span>Vos données</span><span>ailleurs</span></li>
|
|
<li><span>Si les prix montent</span><span>vous payez</span></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col setops">
|
|
<p class="who">Set-OPS · 5 ans</p>
|
|
<p class="amt" id="so-5">—</p>
|
|
<p class="per" id="so-1">—</p>
|
|
<ul class="lines">
|
|
<li class="zero"><span>Licences logicielles</span><span>0 $</span></li>
|
|
<li><span>Matériel amorti</span><span id="l-hw">—</span></li>
|
|
<li><span>Mise en place</span><span id="l-mep">—</span></li>
|
|
<li><span>Exploitation</span><span id="l-ops">—</span></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="note">
|
|
<b>Ce que ce calcul ne dit pas.</b> Il compare des dollars, et les dollars sont la
|
|
plus petite partie de la question. Une migration coûte du temps et de la patience.
|
|
Un serveur chez vous demande quelqu'un pour s'en occuper. En échange, vous cessez de
|
|
louer votre propre organisation, et vous pouvez partir quand vous voulez — tout est
|
|
libre, rien n'est captif.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<hr class="rule">
|
|
|
|
<!-- =================== CE QUE ÇA REMPLACE =================== -->
|
|
<section id="remplace">
|
|
<div class="wrap">
|
|
<div class="sec-head reveal">
|
|
<span class="eyebrow">2 — L'équivalence</span>
|
|
<h2>Ligne pour ligne, ce qui sort de votre budget.</h2>
|
|
<p>
|
|
Set‑OPS n'est pas un logiciel de plus : c'est le moteur qui installe et tient à
|
|
jour une pile complète de logiciels libres, sur votre matériel. Voici ce que chaque
|
|
brique remplace — et son état réel, sans embellissement.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="tbl-scroll reveal">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Brique</th>
|
|
<th>Ce que vous louez aujourd'hui</th>
|
|
<th>Le libre qui le fait</th>
|
|
<th>État</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Identité unique</td>
|
|
<td>Entra ID, Google Workspace</td>
|
|
<td class="libre">OpenLDAP + Keycloak</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Courriel</td>
|
|
<td>Microsoft 365, Google Workspace</td>
|
|
<td class="libre">Postfix + Dovecot + rspamd</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Fichiers et bureautique</td>
|
|
<td>Dropbox, OneDrive, Google Docs</td>
|
|
<td class="libre">Nextcloud + Collabora</td>
|
|
<td><span class="st wip">En chantier</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Forge et code</td>
|
|
<td>GitHub, GitLab payant</td>
|
|
<td class="libre">Forgejo</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Site et applications web</td>
|
|
<td>Hébergeur, PaaS</td>
|
|
<td class="libre">nginx + systemd (natif)</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Base de données</td>
|
|
<td>RDS, bases infogérées</td>
|
|
<td class="libre">PostgreSQL + Redis</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Certificats et chiffrement</td>
|
|
<td>Certificats commerciaux</td>
|
|
<td class="libre">step-ca (autorité interne)</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>DNS</td>
|
|
<td>DNS infogéré</td>
|
|
<td class="libre">PowerDNS + Unbound</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Supervision et journaux</td>
|
|
<td>Datadog, New Relic</td>
|
|
<td class="libre">Prometheus + Grafana + Loki + Icinga</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Sauvegardes</td>
|
|
<td>Sauvegarde infonuagique</td>
|
|
<td class="libre">restic, hors‑nœud, chiffré</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Sécurité du parc</td>
|
|
<td>Options de sécurité facturées</td>
|
|
<td class="libre">nftables, fail2ban, AppArmor, auditd</td>
|
|
<td><span class="st ok">Éprouvé</span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<p class="note">
|
|
<b>« Éprouvé »</b> signifie déployé et vérifié sur des machines réelles, pas seulement
|
|
écrit. <b>« En chantier »</b> signifie exactement cela. Nous distinguons les deux parce
|
|
que la confusion entre les deux est le mensonge le plus courant de notre industrie.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<hr class="rule">
|
|
|
|
<!-- =================== LA PREUVE =================== -->
|
|
<section id="preuve">
|
|
<div class="wrap">
|
|
<div class="sec-head reveal">
|
|
<span class="eyebrow">3 — La différence</span>
|
|
<h2>Ne nous croyez pas. Lancez la commande.</h2>
|
|
<p>
|
|
N'importe quel fournisseur peut écrire une page comme celle‑ci. Presque aucun ne
|
|
vous donne le moyen de la contredire. Set‑OPS tient un <b>registre de ses propres
|
|
affirmations</b> — chaque phrase publique du projet y est reliée soit à une commande
|
|
qui la vérifie, soit à un aveu qu'elle n'est pas prouvée.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="stats reveal">
|
|
<div class="stat"><p class="n">51</p><p class="l">rôles d'installation, testés et documentés</p></div>
|
|
<div class="stat"><p class="n">16 / 16</p><p class="l">preuves automatiques au vert</p></div>
|
|
<div class="stat"><p class="n">54</p><p class="l">affirmations publiques tracées au registre</p></div>
|
|
<div class="stat"><p class="n">8 600</p><p class="l">lignes de documentation en français</p></div>
|
|
</div>
|
|
|
|
<div class="term reveal">
|
|
<div class="bar"><i></i><i></i><i></i><span>make prouver</span></div>
|
|
<pre><span class="p">$</span> <span class="w">make prouver</span>
|
|
|
|
<span class="c">P01</span> Lint Ansible ................................ <span class="g">OK</span>
|
|
<span class="c">P03</span> L'inventaire est bien généré depuis le plan . <span class="g">OK</span>
|
|
<span class="c">P06</span> Les registres du plan sont valides .......... <span class="g">OK</span>
|
|
<span class="c">P09</span> Flux réseau : schéma et matrice cohérents ... <span class="g">OK</span>
|
|
<span class="c">P11</span> Syntaxe des 35 playbooks .................... <span class="g">OK</span>
|
|
<span class="c">P13</span> Invariants : SSH par clé, pare-feu, licence . <span class="g">OK</span>
|
|
<span class="c">P16</span> Inventaire complet déchiffré et lu .......... <span class="g">OK</span>
|
|
|
|
<span class="g">CONFORME : 16 OK, 0 échec, 0 sauté.</span>
|
|
<span class="w">→ docs/audit/preuve-2026-07-20.md</span>
|
|
</pre>
|
|
</div>
|
|
|
|
<div class="duo reveal" style="margin-top:26px">
|
|
<div class="card">
|
|
<h3>Un rapport daté, à archiver</h3>
|
|
<p>
|
|
Chaque exécution produit une pièce justificative horodatée, versionnée avec le code.
|
|
Utilisable en conseil d'administration, en audit, en demande de subvention, ou
|
|
simplement pour dormir tranquille.
|
|
</p>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Le registre a le droit de perdre</h3>
|
|
<p>
|
|
Une affirmation qui échoue redescend au statut « non prouvée », publiquement, dans le
|
|
dépôt. C'est la seule façon qu'un tel registre ait la moindre valeur — et c'est
|
|
pourquoi le nôtre en a.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<hr class="rule">
|
|
|
|
<!-- =================== SOUVERAINETÉ =================== -->
|
|
<section id="souverainete">
|
|
<div class="wrap">
|
|
<div class="sec-head reveal">
|
|
<span class="eyebrow">4 — Ce qui ne se chiffre pas</span>
|
|
<h2>La valeur qui apparaît le jour où ça tourne mal.</h2>
|
|
</div>
|
|
|
|
<div class="duo reveal">
|
|
<div class="card">
|
|
<h3>Vos données restent où vous êtes</h3>
|
|
<ul class="does">
|
|
<li><b>Résidence réelle</b> — les disques sont dans votre local, pas dans une région infonuagique.</li>
|
|
<li><b>Aucune loi étrangère</b> ne s'applique à un serveur que personne d'autre ne détient.</li>
|
|
<li><b>Vos obligations en matière de vie privée</b> deviennent vérifiables : vous pouvez montrer la machine.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Vous pouvez partir</h3>
|
|
<ul class="does">
|
|
<li><b>Zéro licence, zéro captivité</b> — chaque composant est libre, remplaçable, documenté.</li>
|
|
<li><b>Aucune hausse de prix unilatérale</b> : personne ne peut doubler votre facture par courriel.</li>
|
|
<li><b>Aucune fonction retirée</b> parce qu'un fournisseur a changé de stratégie.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>L'infrastructure est du texte</h3>
|
|
<ul class="does">
|
|
<li><b>Tout est décrit dans des fichiers</b> lisibles, versionnés, relus comme du code.</li>
|
|
<li><b>Reconstructible</b> : la même commande rebâtit la même chose sur du matériel neuf.</li>
|
|
<li><b>Auditable par un tiers</b> — un consultant externe lit tout en une journée.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Pensé pour des organisations réelles</h3>
|
|
<ul class="does">
|
|
<li><b>En français</b>, documentation et interface comprises.</li>
|
|
<li><b>À l'échelle d'un OBNL ou d'une coop</b> — pas une machinerie d'entreprise du Fortune 500.</li>
|
|
<li><b>Exploitable par un humain seul</b>, sans intelligence artificielle, sans l'auteur.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<hr class="rule">
|
|
|
|
<!-- =================== RÉSERVES =================== -->
|
|
<section id="reserves">
|
|
<div class="wrap">
|
|
<div class="sec-head reveal">
|
|
<span class="eyebrow">5 — Honnêteté</span>
|
|
<h2>Ce que nous ne prétendons pas.</h2>
|
|
<p>
|
|
La règle du projet est écrite dans son dépôt : <i>ne jamais affirmer plus que ce qu'on
|
|
prouve.</i> Elle s'applique aussi à cette page.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="honest reveal">
|
|
<h3>Nos réserves, en clair</h3>
|
|
<ul>
|
|
<li>
|
|
<b>Ce n'est pas rentable pour tout le monde.</b> En dessous d'une certaine taille, le
|
|
calcul ci‑dessus ne bascule pas en votre faveur avant des années. À cette
|
|
échelle, on choisit Set‑OPS pour la souveraineté, pas pour l'économie — et nous
|
|
vous le dirons.
|
|
</li>
|
|
<li>
|
|
<b>Il faut quelqu'un.</b> Un serveur chez soi demande une personne responsable, à
|
|
l'interne ou sous contrat. Set‑OPS réduit énormément ce travail ; il ne le
|
|
supprime pas.
|
|
</li>
|
|
<li>
|
|
<b>Le projet repose encore sur un seul mainteneur.</b> C'est le risque principal, nous
|
|
le nommons. La documentation, les procédures et le registre de preuves existent
|
|
précisément pour que le savoir ne vive pas dans une seule tête.
|
|
</li>
|
|
<li>
|
|
<b>Une épreuve est en cours.</b> Un administrateur système indépendant, qui n'est pas
|
|
l'auteur, doit installer l'ensemble à partir de la seule documentation, sans aide et
|
|
sans IA. Le protocole est public, le résultat sera publié — <i>y compris s'il
|
|
échoue.</i>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- =================== CLOSE =================== -->
|
|
<div class="close">
|
|
<div class="wrap reveal">
|
|
<h2>Reprenez vos <span class="grad">clés</span>.</h2>
|
|
<p>
|
|
Parlons de votre organisation : ce que vous payez aujourd'hui, ce que vous hébergez,
|
|
et ce qu'il faudrait pour que tout cela vous appartienne à nouveau.
|
|
</p>
|
|
<div class="cta-row">
|
|
<a class="btn btn-primary" href="index.html">Voir toutes les capacités →</a>
|
|
<a class="btn btn-ghost" href="#calcul">Refaire le calcul</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
|
|
<footer>
|
|
<div class="wrap">
|
|
<div style="display:flex;align-items:center;gap:10px">
|
|
<svg viewBox="0 0 32 32" width="26" height="26" aria-hidden="true">
|
|
<circle cx="16" cy="16" r="16" fill="#0a0d24"/>
|
|
<path d="M3 21 C 9 16, 13 23, 18 18 C 22 14, 26 17, 30 13" fill="none" stroke="#56c2ff" stroke-width="2.4" stroke-linecap="round" opacity=".8"/>
|
|
<path d="M16 6 C 16.8 12.6, 17.4 13.2, 24 14 C 17.4 14.8, 16.8 15.4, 16 22 C 15.2 15.4, 14.6 14.8, 8 14 C 14.6 13.2, 15.2 12.6, 16 6 Z" fill="#e9ecff"/></svg>
|
|
<span>Chezlepro inc. · Saint-Bruno-de-Montarville, Québec</span>
|
|
</div>
|
|
<div><a href="index.html">Capacités</a> · <a href="offres.html">Offres</a> · <a href="tarifs.html">Tarifs</a> · <a href="valeur.html">Valeur</a></div>
|
|
<div>Set‑OPS — moteur libre, licence AGPLv3 · <a href="https://chezlepro.ca">chezlepro.ca</a></div>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
(function(){
|
|
var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
|
|
/* ---------- constellation ---------- */
|
|
var sky = document.querySelector('#sky canvas');
|
|
if(sky){
|
|
var ctx = sky.getContext('2d'), W, H, DPR, stars=[], raf;
|
|
function size(){
|
|
DPR = Math.min(window.devicePixelRatio||1, 2);
|
|
W = sky.clientWidth; H = sky.clientHeight;
|
|
sky.width = W*DPR; sky.height = H*DPR; ctx.setTransform(DPR,0,0,DPR,0,0);
|
|
var count = Math.min(120, Math.round(W*H/14000));
|
|
stars = [];
|
|
for(var i=0;i<count;i++){
|
|
stars.push({x:Math.random()*W, y:Math.random()*H,
|
|
r:Math.random()*1.3+0.3, vx:(Math.random()-.5)*0.12, vy:(Math.random()-.5)*0.12,
|
|
tw:Math.random()*Math.PI*2, ts:Math.random()*0.02+0.006});
|
|
}
|
|
}
|
|
function frame(){
|
|
ctx.clearRect(0,0,W,H);
|
|
for(var i=0;i<stars.length;i++){
|
|
var s=stars[i];
|
|
if(!reduce){ s.x+=s.vx; s.y+=s.vy; s.tw+=s.ts;
|
|
if(s.x<0)s.x+=W; if(s.x>W)s.x-=W; if(s.y<0)s.y+=H; if(s.y>H)s.y-=H; }
|
|
var a = 0.5 + Math.sin(s.tw)*0.4;
|
|
ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,6.2832);
|
|
ctx.fillStyle='rgba(207,230,255,'+a.toFixed(3)+')'; ctx.fill();
|
|
}
|
|
for(var i=0;i<stars.length;i++){
|
|
for(var j=i+1;j<stars.length;j++){
|
|
var dx=stars[i].x-stars[j].x, dy=stars[i].y-stars[j].y, d=dx*dx+dy*dy;
|
|
if(d<10000){
|
|
var o=(1-d/10000)*0.22;
|
|
ctx.strokeStyle='rgba(86,194,255,'+o.toFixed(3)+')'; ctx.lineWidth=0.6;
|
|
ctx.beginPath(); ctx.moveTo(stars[i].x,stars[i].y); ctx.lineTo(stars[j].x,stars[j].y); ctx.stroke();
|
|
}
|
|
}
|
|
}
|
|
if(!reduce) raf=requestAnimationFrame(frame);
|
|
}
|
|
size(); frame();
|
|
var to; window.addEventListener('resize',function(){ clearTimeout(to); to=setTimeout(function(){ cancelAnimationFrame(raf); size(); frame(); },180); });
|
|
document.addEventListener('visibilitychange',function(){
|
|
if(document.hidden){ cancelAnimationFrame(raf); } else if(!reduce){ raf=requestAnimationFrame(frame); }
|
|
});
|
|
}
|
|
|
|
/* ---------- calculateur de coût total ---------- */
|
|
var ANS = 5, AMORT = 5;
|
|
var f0 = new Intl.NumberFormat('fr-CA',{style:'currency',currency:'CAD',maximumFractionDigits:0});
|
|
function $(id){ return document.getElementById(id); }
|
|
function money(n){ return f0.format(Math.round(n)); }
|
|
|
|
var ids = ['p','s','h','m','e'];
|
|
function read(){
|
|
return {
|
|
p:+$('p').value, s:+$('s').value, h:+$('h').value,
|
|
m:+$('m').value, e:+$('e').value
|
|
};
|
|
}
|
|
|
|
function calc(){
|
|
var v = read();
|
|
|
|
$('p-v').textContent = v.p;
|
|
$('s-v').textContent = money(v.s);
|
|
$('h-v').textContent = money(v.h);
|
|
$('m-v').textContent = money(v.m);
|
|
$('e-v').textContent = money(v.e);
|
|
|
|
var saasAn = v.p * v.s * 12;
|
|
var saas5 = saasAn * ANS;
|
|
|
|
/* Matériel : achat initial + renouvellement au prorata des années au-delà de l'amortissement */
|
|
var hw5 = v.h * (ANS / AMORT);
|
|
var ops5 = v.e * 12 * ANS;
|
|
var so5 = v.m + hw5 + ops5;
|
|
var soAn1 = v.m + v.h + v.e * 12;
|
|
|
|
$('saas-5').textContent = money(saas5);
|
|
$('saas-1').textContent = 'soit ' + money(saasAn) + ' par année';
|
|
$('so-5').textContent = money(so5);
|
|
$('so-1').textContent = 'dont ' + money(soAn1) + ' la première année';
|
|
|
|
$('l-saas').textContent = money(saas5);
|
|
$('l-hw').textContent = money(hw5);
|
|
$('l-mep').textContent = money(v.m);
|
|
$('l-ops').textContent = money(ops5);
|
|
|
|
/* Point de bascule : première année où le cumul Set-OPS passe sous le cumul abonnements */
|
|
var bascule = 0;
|
|
for(var a=1; a<=25; a++){
|
|
var cSaas = saasAn * a;
|
|
var cSo = v.m + v.h * Math.ceil(a/AMORT) + v.e * 12 * a;
|
|
if(cSo <= cSaas){ bascule = a; break; }
|
|
}
|
|
|
|
var ecart = saas5 - so5;
|
|
var big = $('verdict-big'), txt = $('verdict-txt');
|
|
|
|
if(bascule && bascule <= ANS){
|
|
big.textContent = money(Math.abs(ecart)) + ' de moins sur 5 ans';
|
|
txt.innerHTML = 'Le point de bascule tombe dans la <b>' + bascule +
|
|
(bascule === 1 ? '<sup>re</sup>' : '<sup>e</sup>') + ' année</b> : ' +
|
|
'à partir de là, chaque mois joue en votre faveur. Et les ' + v.p +
|
|
' personnes desservies ne coûtent plus rien de plus à ajouter.';
|
|
} else if(bascule){
|
|
big.innerHTML = 'Rentable à la ' + bascule + '<sup>e</sup> année';
|
|
txt.innerHTML = 'Au‑delà de l\'horizon de 5 ans retenu ici. À cette taille, ' +
|
|
'le gain n\'est pas d\'abord monétaire : <b>c\'est le contrôle de vos données et ' +
|
|
'la liberté de partir.</b> Nous préférons vous le dire que vous le cacher.';
|
|
} else {
|
|
big.textContent = 'Pas rentable, à cette échelle';
|
|
txt.innerHTML = 'Avec ces hypothèses, l\'autohébergement ne se rembourse pas. ' +
|
|
'<b>La bonne raison de le faire devient la souveraineté, pas le budget</b> — ' +
|
|
'et c\'est une raison parfaitement valable, tant qu\'elle est choisie en connaissance de cause.';
|
|
}
|
|
}
|
|
|
|
ids.forEach(function(id){
|
|
var el = $(id);
|
|
if(el){ el.addEventListener('input', calc); }
|
|
});
|
|
calc();
|
|
|
|
/* ---------- révélations au scroll ---------- */
|
|
var els = document.querySelectorAll('.reveal');
|
|
if(reduce || !('IntersectionObserver' in window)){
|
|
els.forEach(function(e){ e.classList.add('in'); });
|
|
} else {
|
|
var io = new IntersectionObserver(function(entries){
|
|
entries.forEach(function(en){ if(en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); } });
|
|
}, {rootMargin:'0px 0px -8% 0px', threshold:0.08});
|
|
els.forEach(function(e){ io.observe(e); });
|
|
}
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|