---
title: "L'architecture de la plateforme : ce que nous avons décidé, et ce sur quoi cela repose."
seo_title: "Architecture de la plateforme : décisions et références | SazAI"
description: "SazAI est construite : moteurs agnostiques, lignage, décisions versionées, validation avec méthode et trajectoire."
tags: [marketing]
icon: book
---

> **Conclusion : l'accélérateur est la maîtrise du substrat par l'équipe ; aucune décision ici n'est une affaire de goût : le choix est écrit, avec ce qui a été rejeté et pourquoi.** La pyramide ci-dessous est la carte ; le trou reste en dehors, énoncé.

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M24 8l16 8-16 8-16-8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 24l16 8 16-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 32l16 8 16-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## Ce qu'est SazAI

<h3 class="sub">Moteurs, composants et documentation, maîtrisés par ceux qui les ont construits</h3>

SazAI est la plateforme : le substrat d'intelligence et de preuve sur lequel les produits sont
construits. Multi-tenancy, authentification, lignage, orchestration, couche d'agents, mesurage
exact et décisions versionées, construits une fois. SazAI Corpus, le coffre et le design system sont les
produits qui en sont déjà sortis, et chacun utilise le même moteur au lieu de le reconstruire.

Les panneaux descendent par force d'ancrage, et chacun se ferme avec ses références dans un bloc déployable, pour quiconque souhaite vérifier. Les citations suivent la norme ABNT NBR 6023, 2018.

<figure class="viz" role="group" aria-label="La pyramide de cette page : quatre forces d'ancrage, de la dépendance d'exécution au positionnement, et le trou en dehors">
<div class="duo" style="grid-template-columns:auto 1fr">
<div class="mid"><svg viewBox="0 0 220 170" aria-hidden="true" style="width:200px">
<polygon points="110,10 150,50 70,50" fill="var(--hue-analysis)" opacity=".85"/>
<polygon points="64,58 156,58 176,92 44,92" fill="var(--hue-output)" opacity=".65"/>
<polygon points="38,100 182,100 198,130 22,130" fill="var(--hue-upload)" opacity=".5"/>
<polygon points="16,138 204,138 214,160 6,160" fill="var(--hue-reprocess)" opacity=".35"/>
<rect x="180" y="8" width="34" height="34" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="4 3" style="color:var(--gray)"/>
</svg></div>
<div class="side" style="text-align:left">
<b style="color:var(--hue-analysis)">dépendance d'exécution</b><span>le moteur ne tourne pas sans la norme · étape 1</span>
<b style="color:var(--hue-output);margin-top:.5rem">norme appliquée et mesurée</b><span>la loi dans le schéma, critère dans le composant, contraste par token · étapes 2 à 4</span>
<b style="color:var(--hue-upload);margin-top:.5rem">décision enregistrée</b><span>choix écrit, avec ce qui a été rejeté et pourquoi · étapes 5 et 6</span>
<b style="color:var(--hue-reprocess);margin-top:.5rem">positionnement</b><span>études avec la mise en garde attachée · étape 7</span>
<b style="color:var(--gray);margin-top:.5rem">le trou</b><span>en dehors de la pyramide, et énoncé · dernier panneau</span>
</div>
</div>
<figcaption>La force d'ancrage décide de la hauteur. Ce qui ne supporte rien reste en dehors du dessin, en tirets, avec son propre panneau.</figcaption>
</figure>

Ce n'est pas du clé en main pour quelqu'un qui arrive de l'extérieur. **L'accélérateur n'est pas le
substrat ; c'est la maîtrise du substrat par l'équipe.** Celui qui connaît les moteurs, les composants et la
documentation construit un nouveau produit SaaS à partir de ce qui existe déjà, et le reste de cette page est la mesure de combien cela raccourcit le chemin.

<figure class="viz duo" role="group" aria-label="Moteurs, composants et documentation ; la maîtrise de l'équipe au milieu ; les produits qui en sortent">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="10" y="10" width="28" height="28" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="24" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="4" x2="24" y2="10" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="38" x2="24" y2="44" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="4" y1="24" x2="10" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="38" y1="24" x2="44" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>le substrat</b>moteurs, composants, documentation</div>
<div class="mid" style="color:var(--hue-upload)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="6" y1="36" x2="40" y2="36" stroke="currentColor" stroke-width="1.5"/><path d="M34 31l6 5-6 5" fill="none" stroke="currentColor" stroke-width="1.5"/><circle cx="60" cy="36" r="14" fill="currentColor" opacity=".12" stroke="currentColor" stroke-width="1.5"/><path d="M54 36l4 4 8-8" fill="none" stroke="currentColor" stroke-width="1.5"/><line x1="80" y1="36" x2="114" y2="36" stroke="var(--hue-output)" stroke-width="1.5"/><path d="M108 31l6 5-6 5" fill="none" stroke="var(--hue-output)" stroke-width="1.5"/></svg><b>la maîtrise de l'équipe</b>c'est ce qui accélère</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="8" y="12" width="32" height="24" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="8" y1="20" x2="40" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="13" cy="16" r="1.4" fill="currentColor"/><circle cx="18" cy="16" r="1.4" fill="currentColor"/></svg><b>les produits</b>Corpus, coffre, design system</div>
</figure>

Le cadre de cette idée n'est pas nouveau, et ne vient pas de cette page : c'est le huitième des neuf
piliers avec lesquels SazAI se décrit, *plateforme avant produit*. Ce qui suit en est la preuve.

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-analysis)" name="file" size="36"></sz-icon></div>

## Le moteur dépend des normes de format pour exister

<h3 class="sub">Étape 1 · dépendance d'exécution, l'ancrage le plus fort qu'il y ait</h3>

Si la norme était fausse dans le code, le moteur ne tournerait pas. La référence n'est pas
mentionnée ; elle est dépendante, et le déterminisme en découle.

**Données et faits :**

- Espace de noms OOXML dans le moteur : 237 occurrences sur 37 formes distinctes (2026-09-01).
- Dublin Core en tant que dépendance : 22 espaces de noms. ISO 8601 : la norme la plus citée dans la base de données, 60 occurrences.
- La chaîne vérifiable : clause publiée → commentaire DDL → couche de carte → colonne. Paraphrase interdite par règle écrite ; DDL et carte portent la même clause, mot à mot.

<figure class="viz duo four" role="group" aria-label="La chaîne du déterminisme : clause publiée, commentaire DDL, couche de carte, colonne relationnelle">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="24" x2="32" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>clause publiée</b>la norme, par numéro</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><rect x="8" y="10" width="32" height="28" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="18" x2="34" y2="18" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="3 2"/><line x1="14" y1="25" x2="30" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="31" x2="30" y2="31" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>commentaire DDL</b>la même clause, mot à mot</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><circle cx="14" cy="14" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="34" cy="18" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="22" cy="34" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="17" y1="17" x2="31" y2="16" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="18" x2="20" y2="30" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>couche de carte</b>pas de paraphrase, par règle</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><rect x="8" y="8" width="32" height="32" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="20" y1="8" x2="20" y2="40" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="8" y1="20" x2="40" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>colonne relationnelle</b>existe parce que la clause existe</div>
</figure>


### Et le format suivant coûte moins cher

Le premier format était PowerPoint, et il a coûté le moteur entier : lire, mesurer, traduire,
réécrire, comparer, tout pour la première fois. Le second, le document Word, a coûté une
ordre de grandeur moins. Le troisième, la feuille de calcul, une de plus. Et le quatrième, le PDF, a coûté autant que
le troisième : la courbe s'est stabilisée. Ce n'est pas une liste de réalisations ; c'est une courbe, et
la courbe est l'argument.

<figure class="viz curve" role="group" aria-label="Coût de chaque format sur le cycle complet, sur une échelle logarithmique : le premier a coûté le moteur entier, chaque suivant une ordre de grandeur moins, et le quatrième se stabilise au même coût que le troisième">
<div class="row ooxml"><b>PPTX</b><span class="track"><span class="bar" style="width:100%"></span></span><em>le moteur entier</em></div>
<div class="row ooxml"><b>DOCX</b><span class="track"><span class="bar" style="width:46%"></span></span><em>une ordre moins</em></div>
<div class="row ooxml"><b>XLSX</b><span class="track"><span class="bar" style="width:16%"></span></span><em>une de plus</em></div>
<div class="row other"><b>PDF</b><span class="track"><span class="bar" style="width:15%"></span></span><em>se stabilise</em></div>
<figcaption>Échelle logarithmique : chaque étape est une ordre de grandeur. Le quatrième point n'est pas juste le plus petit : il est d'une nature différente, et il a coûté autant que le troisième.</figcaption>
</figure>

<p class="claim">Le <b>PDF est le premier substrat qui n'est pas Office</b> : un graphe binaire d'objets au lieu de zip plus XML. Si le moteur avait seulement amélioré PowerPoint, le quatrième format aurait coûté comme le premier. Il a coûté comme le troisième. <b>Le moteur n'est pas devenu plus rapide à PowerPoint ; il est devenu agnostique de format</b>, et les <a href="documents">quatre formats</a> tournent aujourd'hui sur la même architecture, chacun avec sa garantie déclarée. C'est pourquoi le cinquième coûtera ce que le quatrième a coûté, et c'est ce que cette page appelle accélération.</p>

<div class="bound">
<p><b>Où ceci est enregistré, énoncé avant que vous posiez la question.</b> Dans git, pas dans le journal institutionnel : la courbe repose sur des décisions datées et des commits, qui sont la source juste pour un intervalle, et c'est ce qui est vérifié dans une évaluation. Les temps absolus de chaque format vivent dans le document technique, avec la commande qui les dérive à côté.</p>
</div>
<details class="refs"><summary>Références et décisions enregistrées</summary>
<div>
<p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Lire chaque format par la norme, clause par clause ; l'heuristique a été rejetée parce qu'elle ne survit pas à un audit.</li><li>Dates en ISO 8601 dans tout le système ; métadonnées par Dublin Core.</li><li>PDF accepté comme le premier substrat non-Office, cité par sa propre norme.</li></ul><p><b>Références (ABNT NBR 6023:2018)</b></p><ul><li>ECMA INTERNATIONAL. <b>ECMA-376</b>: Office Open XML File Formats. Available at: https://ecma-international.org/publications-and-standards/standards/ecma-376/.</li><li>ISO/IEC. <b>ISO/IEC 29500</b>: Office Open XML File Formats.</li><li>ISO. <b>ISO 32000-1</b>: Portable Document Format. · ISO. <b>ISO 19005</b>: PDF/A.</li><li>ISO. <b>ISO 15836-1</b>: Dublin Core. · ISO. <b>ISO 8601</b>: Date and time.</li><li>IETF. <b>RFC 5646</b>: Tags for Identifying Languages.</li><li>MICROSOFT. <b>MS-PPTX · MS-DOCX · MS-OE376 · MS-ODRAWXML · MS-OFFCRYPTO</b>: implementation notes.</li><li>UNICODE CONSORTIUM. <b>Unicode CMap</b> specifications.</li></ul>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><circle cx="24" cy="24" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="10" cy="12" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="38" cy="10" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="12" cy="38" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="38" cy="36" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="13" y1="14" x2="20" y2="21" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="35" y1="12" x2="28" y2="21" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="36" x2="20" y2="27" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="35" y1="34" x2="28" y2="27" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## Le corps de connaissances

<h3 class="sub">Tout ce que nous avons décidé, mesuré et écrit, lié, et navigable par l'équipe et par les agents</h3>

La maîtrise de l'équipe sur le substrat a un endroit où elle vit : un coffre Obsidian qui
reflète le repository. Les décisions, la carte de données, les contrats des agents, les personas, la stratégie, les
sessions de travail : chaque note lie aux autres, et les hubs sont les portes par lesquelles une personne ou un
agent entre. C'est le même graphe que le produit livre au client dans son propre coffre, utilisé d'abord sur
nous-mêmes. Ci-dessous, le nôtre, en mouvement ; survolez un hub pour voir ce qu'il lie, et cliquez
pour l'ouvrir en entier.

<figure class="viz graph" id="vault-graph" role="group" tabindex="0" aria-label="Le graphe du coffre SazAI : les hubs de décisions, d'agents, de carte de données, de produit, de stratégie, d'opérations, de gens, de pitch et de personas, liés les uns aux autres et à leurs notes">
<div class="stage"><svg viewBox="0 0 800 520" aria-hidden="true"><g class="edges"></g><g class="nodes"></g></svg><div class="labels" aria-hidden="true"></div></div>
<figcaption>Le coffre SazAI, comme l'équipe le voit chaque jour. Chaque point est une note ; chaque ligne, un lien que quelqu'un a écrit. Les hubs ont des noms ; le reste est ce qu'ils lient. Ensemble de nœuds photographié manuellement le 2026-08-28 ; quand la dérivation automatique du coffre arrive, cette ligne sort.</figcaption>
</figure>

<div class="bound">
<p><b>Jusqu'où la carte atteint, mesuré, et c'est la partie qui vaut le plus.</b> Le graphe du coffre atteint 55 des 158 tables de la carte de données et une des cinq cartes de format ; le repository atteint 158 de 158. Une figure qui montrerait tout connecté serait la seule affirmation de cette page sans preuve derrière, sur une page dont le sujet est que nos affirmations portent des preuves. Ce qui est validé n'est pas que tout se connecte : c'est que nous savons exactement ce qui se connecte et ce qui ne le fait pas. Où la carte est silencieuse, le repository répond.</p>
</div>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-reprocess)" name="info" size="36"></sz-icon></div>

## La protection des données est conception, et la conception est vérifiée

<h3 class="sub">Étape 2 · la loi est devenue schéma, et le schéma est vérifiable</h3>

Ce que la loi demande par écrit, la base de données l'exécute par la structure. La vérification n'est pas
lire notre politique ; c'est vérifier le schéma.

**Données et faits :**

- Le stockage permanent ne porte aucun contenu de document ; le contenu vit dans une base de données séparée, sensible et effaçable.
- Isolation par tenant comme une colonne, pas comme une promesse : les tranches ne traversent jamais les tenants.
- Certification aujourd'hui : aucune. Contrôles conçus pour servir comme preuve quand elle est demandée.

<figure class="viz duo" role="group" aria-label="Deux bases de données : la permanente sans contenu, et la sensible, séparée et effaçable">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><ellipse cx="24" cy="12" rx="14" ry="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M10 12v24c0 3 6 5 14 5s14-2 14-5V12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="29" x2="28" y2="29" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>permanente</b>structure, mesurage, lignage ; contenu, jamais</div>
<div class="mid" style="color:var(--gray)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="60" y1="10" x2="60" y2="62" stroke="currentColor" stroke-width="1.5" stroke-dasharray="4 3"/></svg><b>séparation par conception</b>vérifier le schéma</div>
<div class="side" style="color:var(--hue-reprocess)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><ellipse cx="24" cy="12" rx="14" ry="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M10 12v24c0 3 6 5 14 5s14-2 14-5V12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="4 3"/><line x1="18" y1="26" x2="30" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="30" y1="26" x2="18" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>sensible</b>le contenu, véritablement effaçable</div>
</figure>

<details class="refs"><summary>Références et décisions enregistrées</summary>
<div>
<p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Protection des données par conception et par défaut comme architecture ; une couche de conformité sur une base de données partagée a été rejetée.</li><li>Le retrait s'appelle <b>withdrawal</b>, pas suppression : le mot plus fort a été rejeté parce qu'il promettait une portée que les sauvegardes ne soutiennent pas.</li></ul><p><b>Références (ABNT NBR 6023:2018)</b></p><ul><li>EUROPEAN UNION. <b>Regulation (EU) 2016/679</b> (GDPR), art. 25.</li><li>BRAZIL. <b>Law No. 13,709, of August 14, 2018</b> (LGPD).</li><li>CAVOUKIAN, Ann. <b>Privacy by Design</b>: the 7 foundational principles. Toronto: IPC, 2009.</li><li>ISO/IEC. <b>ISO/IEC 27001</b>. · OWASP FOUNDATION. Available at: https://owasp.org/.</li></ul>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-output)" name="eye" size="36"></sz-icon></div>

## L'accessibilité est mesurée, pas déclarée

<h3 class="sub">Étape 3 · une norme citée est conformité ; un nombre mesuré est conception</h3>

Le critère vit dans le composant, avec le nombre à côté du code, et le contraste est
mesuré avant qu'une couleur n'entre dans le système.

**Données et faits :**

- WCAG 2.2 AA sur 51 fichiers du design system, avec critères cités par numéro (1.4.1, 3.1) (2026-09-01).
- Contraste mesuré par token : `--hue-lineage` à 4.00:1 avec la note *guide, jamais texte* écrite dans le token lui-même ; `--text-faint` **a échoué** en mesurant 2.56:1 sur blanc, et l'échec enregistré.
- Daltonisme mesuré : le violet évalué sous deutéranopie, distance de couleur ΔE 29.1.
- Zéro décision d'architecture enregistre WCAG ; l'ancrage d'accessibilité le plus fort de la maison est invisible dans le record de décision, et l'enregistrer est un travail encore à faire.

<figure class="viz" role="group" aria-label="Trois mesures de couleur : un token approuvé comme guide, un qui a échoué, et le violet mesuré sous deutéranopie">
<div class="duo" style="grid-template-columns:1fr 1fr 1fr">
<div class="side"><div class="ev proof" style="margin:0"><span class="n">4.00:1</span><span class="t"><b>approuvé comme guide</b>avec la note <i>guide, jamais texte</i> écrite dans le token lui-même</span></div></div>
<div class="side"><div class="ev open" style="margin:0"><span class="n">2.56:1</span><span class="t"><b>échoué</b>mesuré sur blanc, et l'échec enregistré</span></div></div>
<div class="side"><div class="ev proof" style="margin:0"><span class="n">ΔE 29.1</span><span class="t"><b>deutéranopie</b>le violet mesuré sous la carence chromatique la plus courante</span></div></div>
</div>
<figcaption>Une norme citée est conformité ; un nombre mesuré est conception. Les trois nombres vivent dans les tokens, pas dans une politique.</figcaption>
</figure>

### Le design system est un produit, construit sur une norme ouverte

<h3 class="sub">Étape 4 · l'accélérateur pour les autres surfaces, en norme W3C</h3>

Le design system est un produit SazAI par ratification (2026-08-26), avec la fonction
d'accélérer les autres : les composants qui servent le marketing, le coffre et la vitrine sont
les mêmes, et ils sont norme ouverte, pas un framework propriétaire.

**Données et faits :**

- Composants construits sur W3C Custom Elements et CSS Custom Properties ; aucune dépendance framework.
- Une bibliothèque, trois surfaces servies ; thèmes clairs et sombres et skins white-label à travers le même mécanisme de token.
- Les tokens portent leurs propres mesures et notes d'utilisation (étape 3), donc la règle voyage avec la couleur.

<figure class="viz duo" role="group" aria-label="Une bibliothèque de composants servant trois surfaces">
<div class="side" style="color:var(--verb-see)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="8" y="8" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="26" y="8" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="8" y="26" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="26" y="26" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>une bibliothèque</b>composants, tokens, skins</div>
<div class="mid" style="color:var(--gray)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="10" y1="36" x2="55" y2="36" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="14" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="36" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="58" stroke="currentColor" stroke-width="1.5"/></svg><b>le même mécanisme</b>thèmes et white label par token</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="6" y="8" width="36" height="10" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="6" y="22" width="36" height="10" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="6" y="36" width="36" height="6" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>trois surfaces</b>marketing, coffre, vitrine</div>
</figure>


<details class="refs"><summary>Références et décisions enregistrées</summary>
<div><p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Critère par numéro dans le composant qui l'exécute ; la page de politique centrale a été rejetée.</li><li>Mot hors conception : texte en HTML, géométrie en SVG.</li></ul><p><b>Références (ABNT NBR 6023:2018)</b></p><ul><li>W3C. <b>WCAG 2.2</b>: Web Content Accessibility Guidelines, level AA. Recommendation, 2023. Available at: https://www.w3.org/TR/WCAG22/.</li></ul><p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Standard Web Components ; le framework propriétaire a été rejeté pour que white label ne dépende pas d'une licence de notre part.</li><li>Tenu au même standard que n'importe quelle surface : une suite qui tourne, des gardiens qui refusent au build.</li></ul><p><b>Références (ABNT NBR 6023:2018)</b></p><ul><li>W3C. <b>Custom Elements</b> (HTML Living Standard). · W3C. <b>CSS Custom Properties for Cascading Variables</b>.</li></ul></div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-analysis)" name="globe" size="36"></sz-icon></div>

## Les canaux sont capacité : API et MCP changent ce que le produit peut être

<h3 class="sub">Étape 5 · normes ouvertes à la porte, et ce qu'elles permettent</h3>

API ouvert et MCP ne sont pas de la plomberie : ce sont ce qui permet à d'autres interfaces et connexions
d'être construites sur le même substrat, sans nous dans la pièce. Un agent tiers, un tableau de bord
de votre côté, une intégration de workflow : le produit devient capable d'être ces choses parce que les canaux existent.

**Données et faits :**

- Le canal de l'agent est un serveur de ressource OAuth standard : 401 sans identifiant, découverte publiée.
- Parité en tant que contrat : **MCP ⊆ OpenAPI**, tout ce que MCP expose existe dans l'API ouvert. Un substrat, plusieurs lecteurs.
- Orchestration par un outil d'exécution de workflow durable, adopté pour ce qu'il garantit, et la garantie est mesurée : le travail mort ne laisse aucun état partiel ; la surcharge se dégrade en queue, elle ne casse pas ; rien n'échoue silencieusement.

<figure class="viz duo" role="group" aria-label="Un substrat, deux canaux, et les interfaces qu'ils permettent">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="10" y="10" width="28" height="28" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="24" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>un substrat</b>le moteur et le coffre</div>
<div class="mid" style="color:var(--hue-upload)"><svg viewBox="0 0 120 72" aria-hidden="true"><rect x="38" y="14" width="44" height="18" rx="9" stroke="currentColor" stroke-width="1.5" fill="currentColor" opacity=".12"/><rect x="38" y="40" width="44" height="18" rx="9" stroke="currentColor" stroke-width="1.5" fill="none"/><line x1="10" y1="36" x2="38" y2="24" stroke="currentColor" stroke-width="1.5"/><line x1="10" y1="36" x2="38" y2="48" stroke="currentColor" stroke-width="1.5"/><line x1="82" y1="24" x2="110" y2="16" stroke="var(--hue-output)" stroke-width="1.5"/><line x1="82" y1="48" x2="110" y2="40" stroke="var(--hue-output)" stroke-width="1.5"/><line x1="82" y1="36" x2="110" y2="60" stroke="var(--hue-output)" stroke-width="1.5"/></svg><b>API et MCP</b>MCP ⊆ OpenAPI, par contrat</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><path d="M24 6l4 12 12 4-12 4-4 12-4-12-12-4 12-4z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>ce qu'il peut être</b>agents de votre côté, tableaux de bord de votre côté, workflows de votre côté</div>
</figure>

<details class="refs"><summary>Références et décisions enregistrées</summary>
<div>
<p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Authentification et découverte par les RFCs ; une convention personnalisée a été rejetée.</li><li>Un nouveau canal n'invente pas une nouvelle surface : la règle de parité empêche MCP de devenir une seconde API.</li></ul><p><b>Références (ABNT NBR 6023:2018)</b></p><ul><li>IETF. <b>RFC 8414</b>: OAuth 2.0 Authorization Server Metadata. 2018.</li><li>IETF. <b>RFC 9728</b>: OAuth 2.0 Protected Resource Metadata. 2025.</li><li>IETF. <b>RFC 8707</b>: Resource Indicators for OAuth 2.0. 2020.</li><li>OPENAPI INITIATIVE. <b>OpenAPI Specification</b>. Available at: https://spec.openapis.org/.</li><li>ANTHROPIC. <b>Model Context Protocol</b> (MCP). Available at: https://modelcontextprotocol.io/.</li></ul>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M24 6l14 5v12c0 9-6 15-14 19-8-4-14-10-14-19V11z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M17 24l5 5 9-10" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## Comment nous validons

<h3 class="sub">Tests qui refusent, audit avec méthode, et défauts publiés à côté de ce qui a réussi</h3>

La validation a quatre couches, et l'ordre compte. **Tests :** 505 fichiers de test dans le repository,
avec la suite du design system tournant à chaque build. **Gardiens :** vérifications qui refusent au temps de build
au lieu de seulement rapporter ; un build qui viole une règle ne sort pas. **Charge :** le test du
2026-07-20, sur une réplique fidèle de production, avec 50 lectures concurrentes répondues en 0.77 s, un
travail lourd culminant à 4.71 GiB contre un plafond de 5, et des vagues de cinq et dix jobs avec zéro échec,
zéro débordement mémoire, zéro corruption. En surcharge le système entre en queue ; il ne casse pas.
**Audit interne :** rapports datés de stress, destruction et sécurité, avec un verdict par
item.

<figure class="viz duo four" role="group" aria-label="Quatre couches de validation : tests, gardiens qui refusent, audit avec méthode, défauts publiés">
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><rect x="8" y="8" width="32" height="32" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M15 24l6 6 12-12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>505 tests</b>la suite tourne à chaque build</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><path d="M8 12h32v10H8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 26h32v10H8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="30" y1="14" x2="36" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="36" y1="14" x2="30" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M28 31l3 3 5-6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>gardiens qui refusent</b>un build violé ne sort pas</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><circle cx="21" cy="21" r="11" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="29" y1="29" x2="40" y2="40" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="19" x2="26" y2="19" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="24" x2="23" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>audit avec méthode</b>stress, destruction, sécurité</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="28" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="25" x2="24" y2="29" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="31.5" r=".9" fill="currentColor"/></svg><b>défauts publiés</b>à côté de ce qui a réussi</div>
</figure>

<p class="claim">Nous ne sommes pas certifiés SOC2 ou ISO. Ce que nous avons est <b>audit interne documenté, avec une méthode déclarée et avec les défauts qu'il a trouvés publiés à côté de ceux qui ont réussi</b>. L'un de nos rapports porte, comme ses propres sections, <i>défauts trouvés</i>, <i>un faux positif que j'ai presque publié</i>, et <i>ce que je n'ai pas pu établir</i>. Un sceau est la parole d'un tiers ; une méthode déclarée, le lecteur technique juge seul. Et les décisions écrites sont conçues pour servir de preuve de contrôle quand la certification est recherchée.</p>

<div class="bound">
<p><b>Ce que cette page cite et ce qu'elle ne cite pas.</b> Ici se trouve l'existence des rapports et leur méthode. Les verdicts item par item vivent dans le document technique qui accompagne une évaluation, parce que publier la liste des sondes avec résultats au sommet de l'entonnoir donne une carte à quiconque ne devrait pas en avoir une. La phrase que le test de charge <i>n'autorise pas</i> : <i>cinquante concurrents</i>. Ce sont cinquante sièges et un travail lourd à la fois ; confondre les deux est l'erreur que cette page existe pour ne pas faire.</p>
</div>

<details class="refs"><summary>Références et décisions enregistrées</summary>
<div><p><b>Méthodologie externe déclarée pour l'axe de test : aucune.</b> Pratique forte, gardiens qui refusent au build, rapports datés ; la source de la méthode est interne, et le dire en fait partie.</p></div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="28" x2="32" y2="28" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="34" x2="26" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="15" y1="25" x2="35" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-width="2"/></svg></span></div>

## Comment nous décidons

<h3 class="sub">Décisions écrites, datées, et une supersession qui raye deux phrases et rien d'autre</h3>

Chaque décision d'architecture SazAI est un document daté, avec le contexte, l'
alternative rejetée et la raison. Il y en a 61 à la date de cette page, et le nombre figure de manière datée parce qu'il grandit ; la commande qui la dérive est dans les références de ce panneau. Ce qui en fait un reçu et pas un fichier mort est la
supersession : quand une nouvelle décision contredit une ancienne, elle énonce exactement quelle phrase de l'ancienne
cesse de valoir, et l'ancienne obtient la marque dans son propre corps, sur la phrase, pas sur le titre.

L'exemple le plus récent est d'hier. La décision 023 fixait, entre autres, le vocabulaire
que l'utilisateur nomme les capacités du produit avec. La décision 061 a supercédé **deux phrases** d'elle, toutes les deux
sur le vocabulaire, et a laissé tout sur le moteur intact, y compris la clause crue
violée qu'elle n'était pas. Trois lecteurs compétents avaient lu cette clause de la même mauvaise manière,
et la décision enregistre tous les trois noms, parce qu'une décision qui ne garde que la conclusion perd la
raison pour laquelle trois personnes l'ont mal comprise ensemble.

<figure class="viz duo" role="group" aria-label="Une ancienne décision avec deux phrases rayées et le reste intact, liée à la nouvelle décision">
<div class="side" style="color:var(--hue-reprocess)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:52px;height:52px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="28" x2="32" y2="28" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="34" x2="26" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="15" y1="25" x2="35" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-width="2"/></svg><b>l'ancienne décision</b>deux phrases rayées, le reste intact</div>
<div class="mid" style="color:var(--hue-reprocess)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="10" y1="36" x2="106" y2="36" stroke="currentColor" stroke-width="1.5"/><path d="M100 31l6 5-6 5" fill="none" stroke="currentColor" stroke-width="1.5"/><rect x="42" y="26" width="36" height="20" rx="10" fill="currentColor" opacity=".12" stroke="currentColor" stroke-width="1.5"/></svg><b>supercède</b>nomme la phrase, et juste elle</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:52px;height:52px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M18 28l4 4 8-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>la nouvelle décision</b>avec les trois noms qui l'ont mal comprise ensemble</div>
</figure>

<div class="bound">
<p><b>Un nombre que cette page ne publie pas.</b> Combien de ces 61 décisions sont <i>acceptées</i> dépend des mots que le compteur admet dans le champ d'état, et cinq compteurs compétents ont atteint cinq nombres différents cette semaine. Personne n'a eu tort : le champ n'a jamais déclaré son propre vocabulaire. Nous publions le nombre daté, avec la commande à côté ; le nombre accepté ne devient public que quand il vient avec la commande qui le produit à côté, comme les 158 tables le font déjà.</p>
</div>

### Et comment nous écrivons : un contrat interne, un pas en bas pour l'honnêteté

<h3 class="sub">Étape 6 · cohérence interne enregistrée, un pas en bas de la norme externe</h3>

Le style d'écriture, le nommage, et les conventions de la maison vivent dans un contrat versionné que les agents
citent. Son ancre est la cohérence interne avec une décision enregistrée, pas une
norme externe numérotée ; c'est un pas en bas des précédentes, et descendre prouve que la hiérarchie de cette page
s'applique même quand cela coûte quelque chose.

**Données et faits :**

- Une seule norme d'écriture, versionée par révision, citée par les décisions et par les agents comme contrat.
- Nommage et conventions de nom uniformes dans tout le système ; une norme citée n'est jamais paraphrasée.
- Formatage, lint et balayage de secrets automatisés, déclarés dans la norme avec la source à côté.

<figure class="viz" role="group" aria-label="Cohérence interne enregistrée : un pas en bas d'une norme externe, dessiné en tirets exprès">
<div class="ev open"><span class="n">cohérence interne</span><span class="t"><b>Un pas en bas, et dessiné comme ça</b>L'ancre de ce panneau est une décision enregistrée, pas une norme numérotée. Le cadre en tirets est le même que la maison utilise pour tout ce qui n'est pas un reçu, et un panneau qui descend prouve que la hiérarchie s'applique même quand cela coûte quelque chose.</span></div>
</figure>


<details class="refs"><summary>Références et décisions enregistrées</summary>
<div>
<p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul>
<li>Le compte : <code>ls docs/corpus/pptx/tech_specs/ADR | grep -c '^ADR-'</code> retourne 61 le 2026-09-01. Le nombre grandit ; la commande ne le fait pas.</li><li>Les alternatives de nommage ont été rejetées par convergence sur trois surfaces, et le rejet est enregistré avec la raison.</li></ul><p><b>Références</b></p><p>le contrat interne (`code_standards`, versioné) nomme ses propres sources ; cette
page ne le paraphrase pas.</p><p>Le contrat interne (<i>code_standards</i>, versioné) nomme ses propres sources ; cette page ne le paraphrase pas.</p>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-output)" name="check" size="36"></sz-icon></div>

## Ce qu'est un reçu, et ce qui est encore pratique

<h3 class="sub">Quatre capacités avec preuve ; trois déclarées, sans verbe au présent</h3>

Chaque capacité sur cette plateforme a été soumise à trois questions : est-ce qu'il existe une décision écrite qui
la gouverne ? est-ce qu'il existe une mesure ? ou ça fonctionne juste, sans que personne n'ait écrit pourquoi ? Ce qui passe
les deux premières, nous l'appelons <dfn data-hint="Une capacité avec une décision écrite et une mesure que quiconque peut reproduire : pas une promesse, un record.">reçu</dfn>. Le reste est pratique, et cela reste déclaré comme
direction, de la même manière que la [trajectoire](#roadmap) ci-dessous déclare ce qui n'existe pas encore. Une
page qui présente sept capacités où trois sont des reçus est plus faible qu'une qui en présente
quatre.

<figure class="viz ledger" role="group" aria-label="Quatre reçus avec leur preuve et trois pratiques déclarées comme direction">
<div class="col receipts">
<h4>Reçu</h4>
<div class="item"><b>Clé en main</b><span>4 ADRs et la recette · la courbe quatre points · la partition 158 tables, re-dérivable</span></div>
<div class="item"><b>Contrôle de queue</b><span>5 ADRs · test de charge avec zéro échec, zéro OOM, zéro corruption</span></div>
<div class="item"><b>Architecture · lignage · tenancy</b><span>avec la frontière du fournisseur déclarée comme un trou nommé</span></div>
<div class="item"><b>Versioning de décision</b><span>décisions datées, supersession chirurgicale</span></div>
</div>
<div class="col practices">
<h4>Pratique déclarée</h4>
<div class="item"><b>Versioning de schéma</b><span>direction déclarée</span></div>
<div class="item"><b>Versioning d'artefact</b><span>direction déclarée</span></div>
<div class="item"><b>Communication agent-à-agent</b><span>direction déclarée, avec modes de défaillance mesurés</span></div>
</div>
</figure>
<p class="claim">Les quatre à gauche ont quelque part où être vérifiés, et les chapitres suivants disent où. Les trois à droite sont vers lesquels la plateforme va, et aucun de leurs verbes n'est au présent.</p>

### Et le marché : études avec les mises en garde attachées

<h3 class="sub">Étape 7 · ancres où nous jouons, pas comment nous construisons</h3>

Cette étape soutient le positionnement, pas l'ingénierie, et c'est pourquoi c'est le dernier : c'est l'ancrage le plus faible de la
page, et c'est étiqueté comme tel.

**Données et faits :**

- Sept maisons : Gartner, BCG, McKinsey, Deloitte, Menlo Ventures, MIT NANDA, Stanford HAI.
- Les mises en garde construites dans les entrées elles-mêmes : préliminaire appelé préliminaire (MIT NANDA, n=52) ; republié appelé republié (Stanford/McKinsey) ; une tranche régionale appelée régionale (Deloitte, EMEA).
- Le 79% de BCG prouve l'obstacle, données non structurées non gouvernées ; cela ne prouve pas le pont.
- La recherche d'enquête auprès des cadres est perception, pas financiers audités.


<details class="refs"><summary>Références et décisions enregistrées</summary>
<div>
<p><b>Ce qui est écrit, et ce qui a été rejeté</b></p><ul><li>Plateforme avant produit ; acheter avant construire.</li><li>Sur Shadow AI, juste la forme citée : réduction par un chemin corporatif gouverné. « SazAI résout Shadow AI » a été rejeté pour n'avoir aucune mesure pour le soutenir.</li></ul><p><b>Références</b></p><p>les entrées complètes en forme ABNT NBR 6023:2018 sont dans les blocs de cette page ; des 25 dans l'
inventaire, celles consultées en ligne portent <i>Accessed on</i>, comme la norme l'exige, et le reste ne le font pas, comme la
norme le permet.</p>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><circle cx="24" cy="24" r="16" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M31 17l-4 10-10 4 4-10z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

<a id="roadmap"></a>

## Trajectoire : ce que nous construisons

La trajectoire porte les grandes directions, celles vers lesquelles la plateforme pointe et n'a pas encore construites. Quand une pièce quitte ici, elle disparaît de cette liste et apparaît sur la page pour la capacité correspondante, avec la date. Une trajectoire qui se déplace est la seule preuve de rythme qui ne peut pas être écrite avec un adjectif. Rien ci-dessous n'a expédié, et aucun item ici ne devrait peser sur votre décision aujourd'hui.
Rien sur cette page n'a expédié. Aucun item ici ne devrait peser sur votre décision aujourd'hui, et personne sur notre équipe ne devrait présenter aucun d'eux au présent. Ce qui a expédié est dans la [marche du produit](/), avec ce qu'elle garantit, et les limites de ce qui existe sont dans [confiance](trust).

## Intelligence de relecture et négociation

Comparer une version provisoire contre les révisions des parties, montrer ce que chaque côté a changé, où le risque s'est déplacé, et quel objectif le texte révèle. Le moteur de comparaison qui soutient ceci existe déjà et tourne aujourd'hui sur les versions de documents. Ce qui manque est la couche légale : comprendre qu'une clause altérée n'est pas juste un paragraphe différent.

**Pourquoi c'est sur la trajectoire et pas sur la route :** c'est la direction avec le plus grand potentiel pour créer sa propre catégorie, et c'est exactement pourquoi c'est le plus facile à vendre trop tôt. Cela n'existe pas.

## Agents spécialisés sur votre corpus

Agents avec leur propre portée, construits sur la connaissance déjà dans votre coffre : un tuteur qui enseigne à partir du matériel réel de votre entreprise, un compagnon d'adoption pour un nouveau processus, un évaluateur qui vérifie la compétence tout en citant la source qu'il a utilisée.

**Ce qui se dresse déjà en dessous :** le corpus, lignage, l'agent conversationnel, et citation de source. **Ce qui manque :** spécialisation au niveau de la tâche, avec ses propres limites et règles par agent.

## Substrat pour une flotte d'agents gouvernés

L'étape suivante de la précédente, et la plus loin portée. Chaque partie de l'entreprise alimente le coffre avec ses propres documents, et les agents que cette partie utilise déjà consultent ce coffre au moment de l'exécution, par fichier ou par protocole, pour toute question sur l'entreprise. Une source gouvernée en dessous d'une flotte entière, au lieu d'outils IA lâches que personne n'audit.

**Pourquoi c'est trajectoire et pas une promesse vague :** le mécanisme d'adoption est concret et existe déjà en partie, parce que le coffre est portable et consommable de l'extérieur. Ce qui manque est la gouvernance de flotte, et ce n'est pas construit.

## Les choses qui existent et que nous ne pouvons toujours pas vous montrer

Ce sont des lacunes de preuve, pas des caractéristiques manquantes. La capacité est là ; la preuve publique ne l'est pas, et jusqu'à ce qu'elle le soit, nous préférerions lister la lacune plutôt que de tourner autour du pot.

- **Démonstration d'exportation du coffre.** Le coffre existe et est du texte brut avec des liens ; ce qui manque est une démonstration publiée que n'importe qui peut reproduire sans nous parler. Jusqu'à alors, c'est une conversation de diligence raisonnable, pas un item de page.
- **Suffisance du record pour audit formel.** Le record existe et sert de preuve de contrôle. Que cela ferme une exigence d'audit spécifique dans votre secteur est une question que nous répondons cas par cas, pas une affirmation de page.
- **Échelle au-dessus de ce que nous avons mesuré.** Les volumes dans les centaines de milliers ou millions de documents n'ont pas été exercés. C'est un projet de dimensionnement avant c'est un achat.

## Les choses qui n'existent pas encore

Ce sont des caractéristiques manquantes, et les déposer n'importe où plus doucement vous dirait qu'elles sont là et nous ne pouvons juste pas vous les montrer. Elles ne sont pas là.

- **Vérification visuelle fidèle.** Le système mesure la structure et compte les éléments ; il ne regarde pas la page finale. Un vérificateur visuel à l'intérieur du produit n'existe pas.
- **Suppression qui atteint les copies de sauvegarde.** Aujourd'hui la suppression est complète dans les systèmes en direct et n'atteint pas les sauvegardes dans la fenêtre de rétention. Le chemin technique est défini et pas encore construit. La portée exacte est dans [confidentialité et souveraineté](privacy).
- **Supprimer le contenu et désactiver le compte, en une action à travers l'interface.** Aujourd'hui la suppression de document existe et prend les dérivés avec lui ; faire cela tout à la fois n'existe pas encore, et la fermeture est traitée sur demande. Le nom est délibéré : cela efface le contenu et désactive le compte, parce que la trace de qui a accédé au système demeure.

## Comment cette page est maintenue

Un item part d'ici quand il existe et a été mesuré, pas quand il est presque prêt. Quand il part, il entre la page de capacité avec ce qu'elle garantit et où elle s'arrête. Si vous suivez SazAI pour un moment, cette page est où le rythme se montre.

## Où la frontière passe

<h3 class="sub">Trois limites qu'un lecteur technique teste d'abord, énoncées avant le test</h3>

**La frontière du fournisseur.** Lignage suit chaque pièce de texte jusqu'à ce qu'elle quitte pour le
modèle de langage et reprenne quand elle revient. Aucune de nos tables n'enregistre ce qui s'est passé de l'autre
côté ; quiconque demande *prouver ce qu'ils ont fait avec mon texte à l'intérieur du modèle* reçoit les conditions de rétention
du fournisseur qu'il a contracté, et dans une installation de votre côté le fournisseur est votre choix. La page sur
[souveraineté](privacy) dit où cela s'arrête.

**L'exclusion de licence copyleft.** Aucune bibliothèque AGPL n'entre dans le moteur, et cela est écrit
dans le fichier de dépendance comme une décision de projet documentée. C'est un commentaire, pas une porte :
rien ne casse le build si quelqu'un l'ignore. Le dire est plus fort que de prétendre que c'est une porte, parce que
quiconque ouvre le fichier le voit en dix secondes.

**Les agents.** Ce système est construit par une équipe d'agents avec portée déclarée et une
chaîne de vérification, et la communication entre eux est pratique, pas reçu : il n'existe aucune décision écrite qui
la gouverne, et ses modes de défaillance ont été mesurés par nous cette semaine. Il siège sur le côté droit
du ledger, et c'est vers là qu'il va.

Tout ce que cette page énonce a une commande ou un document derrière, et ce qui n'en a pas est énoncé
comme direction. Si quelque chose ici ne peut pas être reproduit dans votre propre évaluation, c'est un défaut de notre côté et
nous voulons le savoir avant vous. Le produit qui est sorti de cette plateforme en premier est ce que [vous voyez quand
un document arrive](see).


### Ce que cette pyramide ne supporte pas

Une pyramide honnête dit ce qui reste en dehors d'elle.

**Données et faits :**

- Cinq références de doctrine en zéro artefacts d'ingénierie : W3C **PROV** · ZAHARIA et al., **compound AI systems** (BAIR, 2024) · XU et al., **GraphRAG** (SIGIR, 2024) · **model routing** littérature · **CommonMark/GFM**. Ils ont façonné la pensée ; aucune décision enregistrée n'en est sortie.
- Tests : pratique forte, gardiens qui refusent au build, rapports datés ; méthodologie externe déclarée : aucune. Dit en ces termes, avec aucun voisin plausible.
- Et le résultat qui supporte toute la conclusion, mesuré sur les décisions avec une alternative dans l'en-tête : dans onze de onze, ce qui a décidé était un principe d'ingénierie, pas une référence externe. La norme soutient ; le choix est le nôtre, et c'est écrit.


</div>

*Les figures mesurées le 2026-09-01 sur des ensembles qui grandissent : quiconque répète la mesure demain devrait s'attendre à des nombres plus grands, pas aux mêmes.*

<script type="module">
// IF THE #stars CANVAS EVER MORPHS INTO THIS GRAPH (Dev UX / Dev CO), REMOVE THIS FIGURE: two
// objects doing one job on one page is how a surface rots, quietly, because both look right.
// THE VAULT GRAPH, BORN AS STARS. Geometry in SVG, words in HTML. The layout is seeded, so the
// same picture renders every time; hubs are the real hubs of sazai.vault; satellites are counted
// per section, not drawn one to one. First reveal on intersection: points scatter like the
// starfield, then settle into the graph and the labels fade in. Hover lights a hub's edges;
// click (or Enter) opens the same scene full-screen; Escape closes. Reduced motion: no drift.
const fig=document.getElementById('vault-graph'); if(fig){
const svg=fig.querySelector('svg'),E=fig.querySelector('.edges'),N=fig.querySelector('.nodes'),L=fig.querySelector('.labels');
// no namespace literal: the house serves zero external references, and insertAdjacentHTML inside the <svg> inherits the SVG namespace on its own
const el=(t,a,parent)=>{parent.insertAdjacentHTML('beforeend','<'+t+' '+Object.entries(a).map(([k,v])=>k+'="'+v+'"').join(' ')+'/>');return parent.lastElementChild};
let seed=20260828; const rnd=()=>{seed=(seed*1664525+1013904223)%4294967296;return seed/4294967296};
const H=[ // real hubs of sazai.vault; n = satellites drawn, proportional, not exact
 {id:'index',l:'00-INDEX',x:400,y:250,c:'var(--dark)',r:9,n:6},
 {id:'adrs',l:'ADRs Hub',x:300,y:120,c:'var(--hue-reprocess)',r:8,n:59},
 {id:'agents',l:'Agents Hub',x:250,y:330,c:'var(--hue-analysis)',r:8,n:30},
 {id:'km',l:'Knowledge Map',x:560,y:130,c:'var(--hue-output)',r:7,n:18},
 {id:'product',l:'MOC-Product',x:600,y:300,c:'var(--hue-output)',r:7,n:26},
 {id:'strategy',l:'MOC-Strategy',x:520,y:410,c:'var(--hue-upload)',r:7,n:28},
 {id:'ops',l:'MOC-Operations',x:130,y:200,c:'var(--gray)',r:6,n:14},
 {id:'people',l:'MOC-People',x:150,y:440,c:'var(--hue-analysis)',r:6,n:10},
 {id:'pitch',l:'MOC-Pitch',x:690,y:440,c:'var(--hue-upload)',r:6,n:12},
 {id:'personas',l:'Personas',x:410,y:470,c:'var(--hue-reprocess)',r:6,n:7},
 {id:'sessions',l:'Sessions',x:700,y:200,c:'var(--gray)',r:5,n:9},
];
const X=[['index','adrs'],['index','agents'],['index','km'],['index','product'],['index','strategy'],['index','ops'],['index','people'],['index','pitch'],['index','personas'],['index','sessions'],['adrs','km'],['adrs','agents'],['agents','ops'],['agents','people'],['product','km'],['product','strategy'],['strategy','pitch'],['strategy','personas'],['pitch','personas'],['sessions','agents'],['sessions','adrs']];
const nodes=[],edges=[];
for(const h of H){const hub={...h,hub:true,sx:h.x,sy:h.y,ph:rnd()*6.28};nodes.push(hub);
  for(let i=0;i<h.n;i++){const a=rnd()*6.28,d=34+rnd()*(h.n>20?110:70);const s={id:h.id+i,x:h.x+Math.cos(a)*d,y:h.y+Math.sin(a)*d,c:h.c,r:1.6+rnd()*1.6,hub:false,of:hub,ph:rnd()*6.28};s.sx=s.x;s.sy=s.y;nodes.push(s);edges.push([hub,s]);
    if(rnd()<.12){const o=nodes[Math.floor(rnd()*nodes.length)];if(o&&o!==s)edges.push([s,o]);}}}
const byId=Object.fromEntries(nodes.filter(n=>n.hub).map(n=>[n.id,n]));
for(const [a,b] of X)edges.push([byId[a],byId[b]]);
for(const n of nodes){n.el=el('circle',{r:n.r,fill:n.c,opacity:n.hub?1:.75},N);n.el.style.color=n.c;
  n.rx=rnd()*800;n.ry=rnd()*520;n.t=0; // scatter origin, for the reveal
  if(n.hub){const sp=document.createElement('span');sp.textContent=n.l;sp.dataset.hub=n.id;L.appendChild(sp);n.lab=sp;
    n.el.classList.add('hub');n.el.dataset.hub=n.id;}}
for(const e of edges){e.el=el('line',{stroke:'var(--lightgray)','stroke-width':e[0].hub&&e[1].hub?1:.6,opacity:.55},E);}
const reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;
let t0=null,revealed=false,lit=null;
function place(){const now=performance.now();for(const n of nodes){
  const k=reduce?1:Math.min(1,(now-(t0||now))/1600),ease=1-Math.pow(1-k,3);
  const dx=reduce?0:Math.sin(now/1900+n.ph)*(n.hub?2.2:3.6),dy=reduce?0:Math.cos(now/2300+n.ph)*(n.hub?2.2:3.6);
  n.x=n.rx+(n.sx-n.rx)*ease+dx;n.y=n.ry+(n.sy-n.ry)*ease+dy;
  n.el.setAttribute('cx',n.x);n.el.setAttribute('cy',n.y);
  if(n.hub){const pulse=reduce?1:1+Math.sin(now/1400+n.ph)*.08;n.el.setAttribute('r',n.r*pulse*ease+ .5);
    n.lab.style.left=(n.x/800*100)+'%';n.lab.style.top=(n.y/520*100)+'%';}else n.el.setAttribute('r',n.r*(.4+.6*ease));}
  for(const e of edges){e.el.setAttribute('x1',e[0].x);e.el.setAttribute('y1',e[0].y);e.el.setAttribute('x2',e[1].x);e.el.setAttribute('y2',e[1].y);}
  if(!revealed&&(reduce||now-t0>1500)){revealed=true;fig.classList.add('ready');}
  if(!reduce||!revealed)requestAnimationFrame(place);}
function light(id){lit=id;fig.classList.toggle('lit',!!id);
  for(const e of edges){const on=id&&(e[0].id===id||e[1].id===id||(e[0].of&&e[0].of.id===id&&e[1].hub===false&&e[1].of===e[0].of));
    e.el.setAttribute('opacity',id?(on?1:.12):.55);e.el.setAttribute('stroke',on?byId[id].c:'var(--lightgray)');}
  for(const n of nodes){const on=!id||n.id===id||(n.of&&n.of.id===id);n.el.setAttribute('opacity',on?(n.hub?1:.85):.18);}}
fig.addEventListener('mouseover',e=>{const h=e.target.closest('[data-hub]');if(h)light(h.dataset.hub)});
fig.addEventListener('mouseout',e=>{if(e.target.closest('[data-hub]'))light(null)});
// THE EXPANDED SCENE IS A MODAL (ADR-047 A10.4 #15): the figure moves into an sz-modal beside it, inside the same
// chapter so the .chap .graph.full rules still match, and comes back on close. The dialog brings the top layer, the
// blurred page behind (A10.2) and Esc; moved BEFORE open, the figure is inside the modal, so no hole is cut for it.
const ph=document.createElement('div');let modal=null;
const restore=()=>{if(!fig.classList.contains('full'))return;fig.classList.remove('full');ph.replaceWith(fig);document.body.style.overflow='';fig.focus({preventScroll:true})};
const expand=()=>{if(!modal){modal=document.createElement('sz-modal');modal.setAttribute('size','full');modal.setAttribute('bare','');modal.setAttribute('label',fig.getAttribute('aria-label')||'');modal.addEventListener('sz-close',restore)}
  ph.style.height=fig.offsetHeight+'px';fig.replaceWith(ph);ph.after(modal);modal.appendChild(fig);fig.classList.add('full');document.body.style.overflow='hidden';modal.open();fig.focus({preventScroll:true})};
const toggle=()=>{if(fig.classList.contains('full')){modal.close();return}customElements.whenDefined('sz-modal').then(expand)};
fig.addEventListener('click',e=>{if(!e.target.closest('[data-hub]')||fig.classList.contains('full'))toggle()});
fig.addEventListener('keydown',e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();toggle()}});
// START ON SIGHT. IntersectionObserver is the primary trigger; a geometry check on load and on the
// first scroll is the fallback, so a viewport that never reports intersection (measured: an
// automated background tab delivers neither IO nor rAF) still gets the reveal on the next paint.
let started=false;const start=()=>{if(started)return;started=true;t0=performance.now();requestAnimationFrame(place)};
const inView=()=>{const r=fig.getBoundingClientRect();return r.top<innerHeight*.8&&r.bottom>innerHeight*.2};
const io=new IntersectionObserver((en)=>{if(en.some(x=>x.isIntersecting)){start();io.disconnect()}},{threshold:.35});io.observe(fig);
if(inView())start();else addEventListener('scroll',()=>{if(inView())start()},{passive:true});
}
</script>


<style>

/* CHAPTER NUMERALS, EDITORIAL. The number is the chapter's mark, not a KPI: it enters large,
   in the domain hue, beside an uppercase kicker that says what it counts. The house h2 follows
   untouched. These rules move to marketing.css (and the connectome port) when the page lands;
   they live in the body for the refine loop. */
/* ICON COLUMN (Ramés, 2026-08-28): the chapter icon sits left of the title AND its subtitle; the
   subtitle takes the old kicker voice: small, uppercase, quiet. */
/* THE ICON IS A SIBLING OF THE H2, NEVER INSIDE IT, AND THAT IS AN ANCHOR DECISION RATHER THAN
   A STYLE ONE. Quartz slugs a heading from its TEXT CONTENT, and any inline element in the
   heading contributes an empty token. Measured on a probe page, all six forms: `<sz-icon>`
   before the words gives `id="-forma-a-inline-antes"`, a `<span>` behaves identically, the icon
   AFTER the words gives a TRAILING hyphen, and the `{#explicit-id}` syntax is NOT supported
   here: it is slugged as literal text. Only a heading with no markup at all comes out clean.
   AN ANCHOR IS A URL AND A WRONG URL IS PERMANENT, so the icon leaves the heading. The visual
   is unchanged: `.ch` is zero-height and the icon is absolutely placed into the padding column
   the h2 already reserves. */
/* ============================================================================
   THE CHAPTER IS A PANEL, AND THAT ALSO RETIRES THREE MAGIC NUMBERS.

   THE DIAGNOSIS WAS AN INVERTED HIERARCHY, not a missing divider. Rendered, the page read
   heading / floating prose / CONTAINED FIGURE / floating prose: the figure carried a border,
   a fill and a blur while the chapter that owns it carried nothing, so the strongest container
   on the page was a child of the section rather than the section. Prose did not read loose so
   much as OUT-RANKED.

   Now each chapter is a real element, which fixes the ranking AND the alignment at once:

   1. THE CHAPTER IS THE SURFACE. Soft ground, hairline border, radius, generous padding.
   2. THE FIGURE GIVES BACK ITS FILL and keeps only its outline, so it reads as an object
      INSIDE the panel instead of a competing surface. The blur goes with the fill: a backdrop
      filter over a transparent box is cost with no picture.
   3. THE ICON SITS IN ITS OWN GRID COLUMN, vertically centred on the title block by the
      layout rather than by an offset. Everything before this was a magic number chasing a
      MARGIN COLLAPSE: `.ch` was a zero-height div and the h2's top margin collapsed through
      it, so the icon's 18px raise was EMERGENT, and every spacing change moved it. Measured,
      three times: padding opened a 2.4rem gap; a margin dropped it 19px; a margin on the
      previous paragraph did the same. The wrapper removes the collapse from the problem.
   ============================================================================ */
article .chap{position:relative;display:grid;grid-template-columns:3.4rem 1fr;
  gap:0 0;align-items:start;
  border:1px solid color-mix(in srgb,var(--lightgray) 85%,transparent);border-radius:14px;
  background:transparent;
  padding:1.7rem 1.9rem 1.5rem;margin:1.6rem 0}
/* THE GLASS IS A VEIL, NOT A FILTER ON THE PANEL, AND THAT IS A MEASURED CORRECTION.
   `blur(4px)` is the house's own value, read off the served page from `div.search-container`
   and `div.global-graph-outer`, the only two elements that already carry a backdrop filter.
   PUT IT ON `.chap` DIRECTLY AND THE COMPARE MODAL BREAKS: `backdrop-filter` makes the element
   a containing block for `position:fixed` DESCENDANTS, and the modal lives inside this panel.
   Measured before and after: the scrim went from the viewport (1440x757) to the panel's own box
   (788x569). So the veil goes on a pseudo-element at `z-index:-1`, which blurs what is behind
   the panel while leaving `.chap` an ordinary containing block. IT IS THE HOUSE'S OWN ANSWER
   TOO: `sz-search-field` solves the identical problem with a `.veil` behind its pill. */
article .chap::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  /* `--surface` AND NOT `--light`, MEASURED RATHER THAN CHOSEN BY NAME. In the dark theme
     `--light` resolves to #09090b, which is EXACTLY the body background: a 40% mix of the
     background over the background is the background, and the panel measured invisible on the
     rendered pixels (inside 9,9,10 against outside 9,9,11: a delta of zero). Blur cannot
     rescue it either, because a backdrop filter over a flat surface has nothing to blur: THE
     FILL IS WHAT MAKES A PANEL EXIST and the blur is only its texture. `--surface` is #18181b,
     the house's own raised colour, the one `sz-search-field` puts behind its pill. */
  background:color-mix(in srgb,var(--surface) 72%,transparent);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);pointer-events:none}
article .chap .ico-col{grid-column:1;grid-row:1 / span 2;align-self:center;
  display:flex;align-items:center;justify-content:flex-start;padding-top:.15rem}
article .chap .ico-col sz-icon,article .chap .ico-col .ico{display:inline-flex}
article .chap .ico-col .ico svg{width:36px;height:36px}
article .chap > h2{grid-column:2;grid-row:1;padding-left:0;margin:0}
article .chap > h3.sub{grid-column:2;grid-row:2;padding-left:0;margin:2px 0 0;line-height:1.15}
/* THE ANCHOR ICON WAS INFLATING THE LINE BOX, AND MY OWN CHANGE PUT IT THERE. Promoting the
   subtitle from `<p>` to `<h3>` for the SEO reading also gave it the `a[role=anchor]` Quartz
   adds to every heading: 15px tall, inline, on the baseline. Measured, the h3 box went to 26px
   for a 16px line, and that surplus is what read as too much air between title and subtitle.
   Capping the anchor to the text's own em takes the inflation out without removing the anchor,
   so the heading keeps the link it earned by being a heading. */
article .chap h2 a[role=anchor],article .chap h3.sub a[role=anchor]{
  display:inline-flex;align-items:center;height:1em;line-height:1;vertical-align:middle}
article .chap > *:not(.ico-col):not(h2):not(h3.sub){grid-column:1 / -1}
/* THE SPACE BELONGS TO THE FIRST PROSE PARAGRAPH, AND `:first-of-type` GAVE IT TO THE SUBTITLE.
   The first `<p>` inside a panel is `p.sub`, so this rule matched the subtitle instead of the
   prose: same specificity as the `.sub` rule and later in the block, so it won, and the
   subtitle inherited a 16px top margin nobody wrote for it. @rames spotted it on the rendered
   page before any probe did. Targeting the paragraph that FOLLOWS the subtitle says what was
   meant and cannot drift onto a sibling again. */
article .chap > h3.sub + p{margin-top:1rem}
article .chap > *:last-child{margin-bottom:0}
/* the figure is an object inside the panel, never a second surface */
article .chap .viz{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;
  border-color:color-mix(in srgb,var(--lightgray) 65%,transparent)}
/* ============================================================================
   HINT TEXT ON A TERM, AND THE RULE IT KEEPS: THE HOVER IS NEVER THE ONLY COPY.

   @copy-chief's rule applied literally: the explanation lives in the SENTENCE, where all three
   readers reach it (the person, the buyer's research agent, our agent reading the .md). The
   attribute is the SHORT FORM of that same sentence, so the hover adds convenience and never
   carries meaning the prose lacks. His measured reason is this page's own defect: the
   aria-label versus <text> divergence came from two copies of the same words in two encodings,
   and only one of them ever got translated.

   NO SCRIPT. Hover, keyboard focus and tap all resolve through :hover and :focus-visible, so
   there is nothing to upgrade, nothing that can trap focus, and it works before any module
   loads. `tabindex=0` makes the term reachable by keyboard and gives a tap somewhere to land.
   The term is marked as a TERM and not as a link: dotted underline, body colour, no pointer,
   because the page carries four real links and a fifth affordance that looked the same
   would lie.
   ============================================================================ */
article dfn[data-hint]{font-style:italic;position:relative;border-bottom:1px dotted var(--gray);
  cursor:help;outline:none}
article dfn[data-hint]::after{content:attr(data-hint);position:absolute;left:0;top:calc(100% + .5rem);
  z-index:30;width:min(30rem,72vw);padding:.7rem .85rem;border:1px solid var(--lightgray);
  border-radius:10px;background:var(--light);color:var(--darkgray);
  font-style:normal;font-size:var(--fs-xs,.76rem);line-height:1.45;letter-spacing:0;
  box-shadow:0 8px 24px rgb(0 0 0 / .28);opacity:0;visibility:hidden;transition:opacity .12s ease}
article dfn[data-hint]:hover::after,article dfn[data-hint]:focus-visible::after{opacity:1;visibility:visible}
article dfn[data-hint]:focus-visible{border-bottom-color:var(--secondary)}
/* THE SUBTITLE IS AN h3 AND ITS LOOK IS UNCHANGED. @sophia's SEO reading: the H2s lost their
   keywords when they became short labels, and the sentences that carry them became a styled
   paragraph with no heading weight. Promoting the element gives the weight back without moving
   a pixel: every typographic value below is the one the `<p>` already had. */
article h3.sub{font-size:var(--fs-xs,.74rem);font-weight:var(--fw-normal,400);letter-spacing:.08em;text-transform:uppercase;color:var(--gray);line-height:1.15}
/* COMPARE, in the vault's vocabulary: original, the declared relation, the edition; the button opens the component. */
article .duo .act{grid-column:1/-1;text-align:center;margin-top:.4rem}
article .duo sz-compare{display:block;height:0;overflow:hidden}
/* THE SAME BLUR THE SEARCH OVERLAY USES (Quartz .search-container: backdrop-filter blur(4px)),
   applied to the content boxes over a translucent ground so the starfield lifts them. Moves to
   marketing.css .viz when the page lands. */
article .duo.four{grid-template-columns:repeat(4,1fr)}
article .duo.strip{grid-template-columns:auto auto 1fr}
article .duo .out4{display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem}
article .duo .out4 span{display:block}
article .duo .out4 svg{width:40px;height:40px;margin:0 auto .3rem}
article .duo.four .side svg{width:44px;color:var(--hue-analysis)}
article .duo.xray .side svg{color:var(--hue-upload)}
@media (max-width:640px){article .duo.four{grid-template-columns:1fr 1fr}}
/* THE MODAL MUST BE ABOVE THE PAGE CHROME, AND THE HOUSE HAS NO LAYER SCALE TO SAY SO. Measured
   on the served page: the compare scrim is z-index 50 (sz-compare), the consent notice 60
   (sz-consent), the search field host 10000 (chrome CSS). A dialog the reader opened that
   renders UNDER the search bar is a defect; this lifts it through the part the component
   exposes for exactly that. 10001 is a magic number chasing another one, declared as such:
   the durable fix is NOT a z-scale: sz-modal already solved this in-house by building on the
   native <dialog> and its top layer, which no z-index can sit above. sz-compare following it
   onto <dialog> retires this rule; that is a component change, not a page style. */
article sz-compare::part(modal){z-index:10001}
@media (max-width:640px){article .duo.strip{grid-template-columns:1fr}article .duo .out4{grid-template-columns:1fr 1fr}}
/* THE CLOSE MIRRORS THE OPEN: one vault in the middle, two readers on the sides. Geometry only;
   every word is HTML. */
article .duo{display:grid;grid-template-columns:1fr auto 1fr;gap:1rem;align-items:center;text-align:center;font-size:var(--fs-xs,.74rem);color:var(--gray)}
article .duo svg{display:block;height:auto;margin:0 auto .3rem}
article .duo .side svg{width:56px}
article .duo .mid svg{width:96px}
article .duo b{display:block;color:var(--dark);font-size:var(--fs-sm,.86rem)}
@media (max-width:640px){article .duo{grid-template-columns:1fr}}

/* ============================================================================
   TWO OBJECTS THIS PAGE NEEDED AND `see` DID NOT.

   1. THE CURVE, ON A LOG SCALE, BECAUSE A LINEAR ONE HIDES THE ARGUMENT. The claim is one
      order of magnitude per format: 3600h, 48h, 4h, one session. Drawn linearly the last
      three bars are invisible and the fourth point, THE ONE CARRYING THE STRONGEST PROOF,
      reads as merely small. Log widths make the collapse legible, and the caption says the
      scale out loud so nobody reads it as linear.

      AND THE FOURTH ROW BREAKS THE VISUAL FAMILY ON PURPOSE. The three OOXML formats share a
      hue and a solid bar; PDF gets a different hue and an outlined bar. **THE BREAK IS THE
      ARGUMENT**: the engine did not get faster at PowerPoint, it became format-agnostic, and
      a fourth bar in the same family would have said the opposite.

   2. RECEIPT AND PRACTICE MUST NOT LOOK ALIKE, and that is a composition rule rather than a
      label. A receipt is a thing already true and carries its evidence on the same line, so
      it is solid, filled, and reads as closed. A practice is declared direction with no
      present-tense verb, so it is outlined, muted, and reads as open. A reader who never
      gets to the words should still be able to see which column is which.

   3. THE BOUNDS ARE IN THE FLOW, NOT IN SMALL PRINT. `see` had none of these. A bound that
      has to be read as a footnote is a bound that gets skipped, and both of this page's
      bounds are the kind a competent reader tests FIRST. So they sit inside the chapter, at
      the same measure as the prose, in a treatment that is quieter than the claim but not
      smaller than it.
   ============================================================================ */
article .curve{display:flex;flex-direction:column;gap:.55rem}
article .curve .row{display:grid;grid-template-columns:4.2rem 1fr 7.5rem;align-items:center;gap:.8rem}
article .curve .row b{font-size:var(--fs-sm,.86rem);color:var(--text)}
article .curve .track{display:block;height:10px;border-radius:5px;background:color-mix(in srgb,var(--lightgray) 45%,transparent)}
article .curve .bar{display:block;height:100%;border-radius:5px}
article .curve .ooxml .bar{background:var(--hue-analysis)}
article .curve .other .bar{background:transparent;border:1.5px solid var(--hue-output)}
article .curve .other b{color:var(--hue-output)}
article .curve em{font-style:normal;font-size:var(--fs-xs,.76rem);color:var(--gray);text-align:right}
article .curve .other em{color:var(--hue-output)}
article .ledger{display:grid;grid-template-columns:1fr 1fr;gap:1.4rem}
article .ledger h4{margin:0 0 .6rem;font-size:var(--fs-xs,.74rem);letter-spacing:.08em;text-transform:uppercase;font-weight:var(--fw-normal,400);color:var(--gray)}
article .ledger .item{margin-bottom:.7rem}
article .ledger .item b{display:block;font-size:var(--fs-sm,.88rem)}
article .ledger .item span{display:block;font-size:var(--fs-xs,.76rem);color:var(--gray);line-height:1.4;margin-top:.1rem}
article .ledger .receipts .item{border-left:2px solid var(--hue-output);padding-left:.7rem}
article .ledger .practices .item{border-left:2px dashed color-mix(in srgb,var(--gray) 55%,transparent);padding-left:.7rem}
article .ledger .practices .item b{color:var(--gray);font-weight:var(--fw-normal,400)}
article p.claim{margin:1rem 0 0;color:var(--text);font-size:var(--fs-sm,.95rem);line-height:1.55}
article .bound{margin:1.1rem 0 0;padding:.85rem 1rem;border-left:2px solid color-mix(in srgb,var(--gray) 40%,transparent);
  background:color-mix(in srgb,var(--surface) 45%,transparent);border-radius:0 8px 8px 0}
article .bound p{margin:0 0 .5rem;font-size:var(--fs-xs,.82rem);line-height:1.5;color:var(--gray)}
article .bound p:last-child{margin-bottom:0}
@media (max-width:640px){article .ledger{grid-template-columns:1fr}article .curve .row{grid-template-columns:3.4rem 1fr}article .curve em{grid-column:1/-1;text-align:left}}

/* THE VAULT GRAPH: born as stars, settles into the map. Geometry in SVG, words in HTML spans over
   it; `.stage` binds the two so labels track the drawing in both modes. Placed LAST so it wins
   over the panel's `.chap .viz` reset, and scoped to `.chap` so its specificity matches hers. */
article .chap .graph{position:relative;padding:.6rem;cursor:zoom-in;outline:none}
article .chap .graph .stage{position:relative;width:100%;aspect-ratio:800/520}
article .chap .graph .stage svg{display:block;width:100%;height:100%}
article .chap .graph .labels{position:absolute;inset:0;pointer-events:none}
article .chap .graph .labels span{position:absolute;transform:translate(-50%,10px);font-size:var(--fs-xs,.72rem);color:var(--dark);white-space:nowrap;opacity:0;transition:opacity .7s ease;text-shadow:0 0 6px var(--light),0 0 2px var(--light);pointer-events:auto}
article .chap .graph.ready .labels span{opacity:1}
article .chap .graph .nodes .hub{cursor:pointer;transition:opacity .25s}
article .chap .graph .edges line{transition:opacity .25s,stroke .25s}
article .chap .graph figcaption{margin-top:.4rem}
article .chap .graph:focus-visible{box-shadow:0 0 0 2px var(--secondary)}
article .chap .graph.full{flex:1;min-width:0;margin:0;border:0;border-radius:0;padding:3vh 4vw;background:transparent;cursor:zoom-out;display:flex;flex-direction:column;align-items:center;justify-content:center}
article .chap .graph.full .stage{width:min(92vw,calc(84vh * 800 / 520))}
article .chap .graph.full .labels span{font-size:1rem}
article .chap .graph.full figcaption{text-align:center;margin-top:1rem;max-width:70ch}
</style>
