/* ==========================================================================
   CHARTE DU SITE PUBLIC
   ==========================================================================

   CE FICHIER N'EST PAS CELUI DE LA CONSOLE, ET C'EST VOLONTAIRE

   `templates/console/fragments/mise-en-page.html` porte un bloc <style> de
   cent lignes, et il doit le garder. La console a deux écrans et un seul
   utilisateur ; l'étude (§2.3) dit que chaque heure passée à l'embellir est
   prise sur GestionEcole.

   Le site public est l'inverse exact (étude §2.1) : c'est le seul écran du
   dispositif dont la qualité visuelle a un effet direct sur le chiffre
   d'affaires. Les deux n'ont donc pas à partager une charte -- les fusionner
   obligerait à arbitrer entre « sobre parce qu'interne » et « soigné parce
   que vendeur » sur chaque règle, et l'arbitrage se ferait toujours au
   détriment du second.

   ---------------------------------------------------------------------------
   AUCUNE POLICE TÉLÉCHARGÉE
   ---------------------------------------------------------------------------

   L'étude fixe un budget chiffré (§3.6) : moins de 150 Ko avant les images,
   premier affichage utile sous 2,5 s en 3G, sur un Android d'entrée de gamme.

   Une police auto-hébergée coûte 15 à 40 Ko par graisse ET retarde l'affichage
   du texte. Les piles système ci-dessous coûtent ZÉRO octet et s'affichent au
   premier rendu. L'étude recommandait l'auto-hébergement contre Google Fonts ;
   ne rien charger du tout est simplement meilleur sur son propre critère.

   Le caractère du site vient donc du TRAITEMENT -- échelle, graisses,
   interlignage, chiffres tabulaires -- et non de fontes exotiques. C'est aussi
   ce qui le rend lisible sur un téléphone qui n'a que ses polices d'origine.

   ---------------------------------------------------------------------------
   ET UN MOT SUR JAVASCRIPT, PARCE QUE CE FICHIER A DIT LE CONTRAIRE
   ---------------------------------------------------------------------------

   Une version antérieure de cet en-tête affirmait « pas une ligne de JavaScript
   non plus », en s'appuyant sur le §3.6. VÉRIFICATION FAITE, L'ÉTUDE NE DIT PAS
   CELA. Le §3.6 proscrit des effets nommés -- animations au défilement,
   carrousels, vidéo de fond, curseur personnalisé, chargeur animé -- et le §7.2
   écarte Angular pour la vitrine, avec deux motifs précis : la page blanche le
   temps qu'un paquet s'exécute, et un référencement qui fonctionne mal sur une
   page dont le contenu n'existe qu'après exécution de JavaScript.

   Les deux visent JavaScript comme COUCHE DE RENDU, pas un script qui s'ajoute à
   une page déjà complète. L'interdiction était une extrapolation présentée comme
   une citation ; elle est remplacée par la règle qu'elle voulait servir :

       LE SITE DOIT ÊTRE COMPLET, LISIBLE ET INDEXABLE SANS JAVASCRIPT.
       Un script ajoute du confort ; il ne porte jamais de contenu et ne
       conditionne jamais une action.

   `static/site/site.js` applique cette règle, et le §14 ci-dessous porte ce qui
   n'existe que grâce à lui. Le menu déroulant animé, en revanche, reste écarté --
   sur ce point l'en-tête d'origine avait raison : cinq liens qui tiennent à
   l'écran n'ont rien à gagner à se cacher derrière un geste.

   ---------------------------------------------------------------------------
   CLAIR UNIQUEMENT, MAIS PEINT EXPLICITEMENT
   ---------------------------------------------------------------------------

   Le parti pris est le papier. Une variante sombre n'est pas fournie : elle
   doublerait le travail de mise au point pour un site de six pages dont le
   sujet même est le document imprimé. En revanche CHAQUE fond est peint --
   jamais de `transparent` implicite -- pour qu'un navigateur en mode sombre
   n'aille pas poser sa propre couleur derrière un texte prévu pour du papier.
   ========================================================================== */


/* ==========================================================================
   1. JETONS
   ==========================================================================
   Six couleurs, et CHACUNE A UN SEUL MÉTIER. C'est la règle qui tient la
   charte : le jour où l'ocre sert à autre chose qu'un sceau, plus personne ne
   sait ce qu'un ocre veut dire sur cette page.
   ========================================================================== */

:root {
    /* --- Les deux fonds, tirés du monde du produit : l'encre et le papier. */
    --encre:        #17233a;  /* Texte courant, et fond des blocs pleins.     */
    --papier:       #fcfbf8;  /* Fond de page. Chaud, mais très clair.        */

    /* --- La réglure du registre : filets, séparateurs, remplissages calmes. */
    --registre:     #e8e3d7;
    --registre-pale:#f4f1e9;

    /* --- Encre de tampon. LA couleur d'action : liens, boutons, focus.
           Volontairement pas le bleu des interfaces web -- celui-ci est celui
           des cachets de l'administration, plus violacé et plus grave. */
    --tampon:       #3b4fa0;
    --tampon-fonce: #2c3c7d;

    /* --- Ocre de sceau. UNIQUEMENT les marques de signature et de garantie
           (§ la licence signée, le titulaire scellé). Jamais un bouton. */
    --sceau:        #b08528;

    /* --- Vert de preuve. UNIQUEMENT l'état « sauvegarde restaurée avec
           succès ». C'est l'argument de vente n° 1 de l'étude (§3.1) : lui
           donner une couleur à lui seul, c'est s'interdire de la diluer. */
    --preuve:       #1f6b4a;

    /* --- Gris tirés de l'encre, pour ne pas introduire une septième teinte. */
    --encre-70:     #4d566b;
    --encre-45:     #7b8291;

    /* --- Échelle typographique.
           clamp() plutôt que des paliers : un titre doit être grand sur un
           portable de 360 px sans écraser la page, et grand sur un écran de
           bureau sans devenir une affiche. */
    --t-xs:   0.8125rem;
    --t-sm:   0.9375rem;
    --t-base: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);
    --t-md:   clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
    --t-lg:   clamp(1.5rem, 1.3rem + 1vw, 2rem);
    --t-xl:   clamp(1.875rem, 1.5rem + 1.8vw, 2.75rem);
    --t-2xl:  clamp(2.25rem, 1.6rem + 3.2vw, 4rem);

    /* --- Rythme vertical. Une seule échelle, multiples de 4. */
    --e-1: 0.25rem;  --e-2: 0.5rem;   --e-3: 0.75rem;  --e-4: 1rem;
    --e-6: 1.5rem;   --e-8: 2rem;     --e-12: 3rem;    --e-16: 4rem;
    --e-24: 6rem;

    /* --- Largeurs. `--mesure` plafonne les paragraphes autour de 68
           caractères : au-delà, l'œil rate la ligne suivante (§3.6.3). */
    --page: 72rem;
    --mesure: 34rem;

    --rayon: 3px;      /* Presque droit : on est dans le document, pas l'appli. */
    --filet: 1px solid var(--registre);

    /* --- Les trois rôles typographiques.
           DISPLAY : le sérif du système. C'est lui qui donne le registre
           « document officiel » plutôt que « page d'accueil de start-up ».
           TEXTE   : le sans du système, pour la lecture à petit corps.
           CHIFFRE : une chasse fixe pour les montants FCFA, les dates et les
                     numéros de version -- alignés en colonne, comme dans un
                     registre. `tabular-nums` sur les deux autres ne suffit
                     pas : c'est la chasse fixe qui fait la colonne. */
    --f-display: ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino,
                 Cambria, Georgia, "Noto Serif", "Times New Roman", serif;
    --f-texte:   system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
                 Arial, "Noto Sans", sans-serif;
    --f-chiffre: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono",
                 Menlo, Consolas, monospace;
}


/* ==========================================================================
   2. SOCLE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--papier);
    color: var(--encre);
    font-family: var(--f-texte);
    font-size: var(--t-base);
    line-height: 1.6;
    /* Sur les fonds clairs de cette charte, l'antialiasing par défaut de
       macOS épaissit le texte au point de fermer les contrepoinçons. */
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    font-family: var(--f-display);
    font-weight: 600;
    /* Un sérif à grand corps a besoin d'un interlignage plus serré que le
       texte courant, sinon les lignes de titre flottent. */
    line-height: 1.12;
    letter-spacing: -0.015em;
    margin: 0;
    text-wrap: balance;      /* Évite le mot orphelin en fin de titre. */
}

p { margin: 0; max-width: var(--mesure); }
p + p { margin-top: var(--e-4); }

a { color: var(--tampon); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--tampon-fonce); }

img { max-width: 100%; height: auto; display: block; }

strong { font-weight: 650; }

/* LES MOTS QU'ON NE PEUT PAS COUPER SONT CEUX QUI CASSENT UN TÉLÉPHONE.
   Une adresse électronique de quarante caractères, une référence de commande,
   un nom d'établissement en un seul mot : sans cette règle, le mot impose sa
   largeur à son conteneur, le conteneur à la page, et la page défile
   latéralement. Le défaut ne se voit jamais sur le poste du développeur --
   il apparaît chez le premier client dont l'adresse est longue. */
p, li, dt, dd, td, th, figcaption, address, blockquote { overflow-wrap: break-word; }

/* Accessibilité : un contour visible au clavier, sur toutes les cibles.
   Posé une fois ici plutôt que composant par composant, faute de quoi il
   manquera sur celui qu'on ajoutera demain. */
:focus-visible {
    outline: 3px solid var(--tampon);
    outline-offset: 3px;
    border-radius: 2px;
}

/* Un utilisateur qui a demandé moins d'animation en reçoit zéro. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Le texte réservé aux lecteurs d'écran.
   ATTENTION AU BLOC CONTENEUR : cette règle est `position: absolute`, donc
   elle se positionne par rapport au premier ancêtre POSITIONNÉ. Placée dans
   un conteneur à défilement horizontal dont aucun ancêtre ne l'est, elle se
   cale sur le bloc conteneur initial -- c'est-à-dire sur le document -- et
   allonge la largeur défilable de la PAGE entière. C'est exactement ce qui
   est arrivé aux « inclus / non inclus » du tableau comparatif : la page des
   offres défilait latéralement de 190 px sur un téléphone, alors que le
   tableau était censé défiler seul. D'où le `position: relative` posé sur les
   cellules du comparatif (§9). */
.pour-lecteur-decran {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
}


/* ==========================================================================
   3. GABARIT
   ========================================================================== */

.page { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--e-6); }

/* Sur un écran de 320 px -- un Android d'entrée de gamme, celui que l'étude
   (§3.6) prend pour cible -- 24 px de marge de chaque côté prennent 15 % de la
   largeur utile. La gouttière se resserre plutôt que d'étrangler le texte. */
@media (max-width: 25.999rem) {
    .page { padding-inline: var(--e-4); }
}

/* L'ŒIL DE SECTION ET LES ÉTIQUETTES À 13 px NE SE LISENT PAS SUR UN
   TÉLÉPHONE. Le corps le plus petit de la charte remonte d'un cran sous
   30 rem : 14 px en capitales espacées reste discret et devient lisible en
   plein soleil, sur un écran que personne n'essuie. */
@media (max-width: 29.999rem) {
    :root { --t-xs: 0.875rem; }
}

/* Le rythme entre sections est porté par UNE classe et une seule.
   Poser des marges sur les <section> ou sur les titres ferait se cumuler
   deux sources d'espacement, et l'écart entre deux blocs dépendrait alors de
   leur contenu -- le défaut le plus courant d'une feuille de style qui a
   grossi. */
.bande { padding-block: clamp(var(--e-16), 9vw, var(--e-24)); }
.bande--serree { padding-block: clamp(var(--e-12), 6vw, var(--e-16)); }
.bande--encre { background: var(--encre); color: var(--papier); }
.bande--registre { background: var(--registre-pale); }
.bande + .bande--registre, .bande--registre + .bande { border-top: var(--filet); }

/* L'œil de section : une étiquette courte au-dessus du titre. Elle ne décore
   pas, elle situe -- « où suis-je dans la page ». */
.oeil {
    font-family: var(--f-chiffre);
    font-size: var(--t-xs);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--encre-45);
    margin: 0 0 var(--e-4);
}
.bande--encre .oeil { color: #8d97ad; }

.titre-section { font-size: var(--t-xl); max-width: 22ch; }
.chapeau { font-size: var(--t-md); color: var(--encre-70); margin-top: var(--e-4); }
.bande--encre .chapeau { color: #c3cad8; }


/* ==========================================================================
   4. EN-TÊTE ET PIED
   ==========================================================================
   PAS DE MENU HAMBURGER, donc pas de JavaScript. Six entrées tiennent sur
   deux lignes en 360 px de large. Un menu qui s'ouvre exigerait un script, un
   état, un piège de focus et une gestion du clavier -- pour cacher six liens
   qui tiennent à l'écran.

   EN REVANCHE CHAQUE ENTRÉE DOIT FAIRE 44 px DE HAUT. C'est la contrepartie
   du choix précédent : des liens de navigation posés à même le texte mesuraient
   34 px, soit sous le pouce d'un adulte. Le rembourrage vertical ci-dessous
   n'est donc pas de l'aération -- c'est la surface de frappe. Le filet de la
   page courante descend d'autant, ce qui est le comportement attendu d'un
   onglet.
   ========================================================================== */

/* L'EN-TÊTE SUIT LE DÉFILEMENT.

   L'accueil compte six sections et la page des offres davantage : le visiteur qui
   se décide au milieu devait remonter jusqu'en haut pour trouver une porte. Sur
   mobile, la barre d'action collante du bas (§14.2) ne le sauvait qu'à partir de
   la page d'accueil et seulement pour le téléchargement.

   `z-index: 30` LE PLACE AU-DESSUS DE LA BARRE D'ACTION (20), et l'ordre compte
   dans ce sens-là : quand le menu déplié et la barre du bas se rencontrent sur un
   petit écran, c'est le menu — que le visiteur vient d'ouvrir — qui doit passer
   devant, jamais l'inverse. */
.entete {
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--papier);
    border-bottom: var(--filet);
    padding-block: var(--e-4);
}
.entete__inner { display: flex; flex-wrap: wrap; gap: var(--e-4) var(--e-8); align-items: baseline; }

/* ---------------------------------------------------------------------------
   LE BANDEAU D'OFFRE
   ---------------------------------------------------------------------------

   PEINT EN ENCRE, ET SURTOUT PAS DANS UNE SEPTIÈME COULEUR. La tentation d'un
   rouge de promotion est exactement ce que la palette de ce site interdit : six
   teintes, chacune avec un seul métier. Sur une page qui vend un logiciel de
   registre à des directeurs d'établissement, le rouge des sites de déstockage
   coûterait en crédibilité ce qu'il gagnerait en attention -- et la crédibilité
   est le seul actif que cette vitrine possède.

   L'URGENCE VIENT DONC DU CONTRASTE ET DU CHIFFRE, pas de la teinte : une bande
   d'encre pleine sous un fond papier se voit sans crier, et le taux en ocre de
   sceau y est le seul élément coloré. Le sceau est réservé aux marques de
   garantie ; un rabais daté et tenu en est une.

   IL EST DANS L'EN-TÊTE COLLANT, ET IL COLLE DONC AVEC LUI. C'est voulu : une
   échéance qui disparaît au premier défilement ne pèse plus sur la décision
   prise en bas de page. Il reste compact pour ne pas manger l'écran d'un
   téléphone -- c'est le parc de ce marché.

   AUCUNE ANIMATION, PAS MÊME UN CLIGNOTEMENT. Le §3.6 de l'étude proscrit les
   effets décoratifs, et un bandeau qui clignote est le premier élément qu'un
   visiteur apprend à ignorer. */
.promo {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--e-2) var(--e-4);
    margin-block-end: var(--e-4);
    padding: var(--e-3) var(--e-4);
    background: var(--encre);
    color: var(--papier);
    border-radius: var(--rayon);
    text-decoration: none;
    font-size: var(--t-sm);
    line-height: 1.35;
}
.promo:hover,
.promo:focus-visible { color: var(--papier); }

/* LE TAUX EST PEINT, ET NON SEULEMENT COLORÉ.

   En ocre sur l'encre, il se lisait comme un mot de plus dans une phrase.
   Rempli, il devient un objet -- une étiquette de prix -- et c'est le premier
   élément que l'oeil accroche en arrivant sur la page. L'encre revient comme
   couleur de texte : de l'ocre sur du blanc ne tiendrait pas le contraste, et
   c'est le seul endroit du site où ces deux-là se touchent. */
.promo__taux {
    font-family: var(--f-chiffre);
    font-size: var(--t-md);
    font-weight: 700;
    color: var(--encre);
    background: var(--sceau);
    padding: 0.15em 0.5em;
    border-radius: var(--rayon);
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.promo__texte { display: flex; flex-wrap: wrap; gap: 0 var(--e-2); align-items: baseline; }

/* Le décompte est en chiffres tabulaires : sans eux, chaque seconde qui passe
   change la largeur du nombre et fait sauter tout ce qui le suit sur la ligne.
   Un bandeau qui tressaute une fois par seconde est un bandeau qu'on ferme. */
/* LA COULEUR EST PORTÉE PAR LE CONTENANT, ET NON PAR `.promo__reste`.

   La classe sert deux fonds opposés : l'encre du bandeau et le papier du bloc du
   héros. Peinte en dur ici, elle rendait le décompte du héros en papier sur
   fond clair -- c'est-à-dire invisible, sur le seul élément de la page dont le
   travail est d'être vu. `currentColor` le fait hériter de son bloc, et il ne
   peut plus se retrouver de la couleur de son propre fond. */
.promo__reste {
    font-family: var(--f-chiffre);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: currentColor;
}

.promo__echeance { color: var(--registre); }


/* ---------------------------------------------------------------------------
   L'OFFRE DANS LE HÉROS DE LA PAGE D'ACCUEIL
   ---------------------------------------------------------------------------

   UN ENCADRÉ CLAIR, ET NON UN SECOND BLOC D'ENCRE. La bande de l'en-tête est
   déjà pleine ; deux aplats sombres empilés sur le premier écran feraient de la
   page d'accueil une affiche de déstockage, ce qui est exactement ce que cette
   charte évite -- la crédibilité est le seul actif de cette vitrine, et c'est
   elle qu'on vend avant le logiciel.

   LE FILET EST EN OCRE DE SCEAU, ET C'EST SON MÉTIER. La palette lui réserve les
   marques de signature et de garantie ; un rabais daté et tenu en est une. Le
   bloc se lit comme un tampon apposé sur la page, pas comme une réclame collée
   dessus.

   IL EST DANS LE FLUX, ENTRE LE TITRE ET L'ARGUMENT. Un encadré flottant ou
   collant serait refermé d'un geste ; celui-ci se lit parce qu'il est sur le
   chemin. */
.heros__offre {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--e-2) var(--e-3);
    margin-top: var(--e-6);
    padding: var(--e-3) var(--e-4);
    border: 2px solid var(--sceau);
    border-radius: var(--rayon);
    background: var(--registre-pale);
    max-width: var(--mesure);
    font-size: var(--t-sm);
}
.heros__offre-taux {
    font-family: var(--f-chiffre);
    font-size: var(--t-lg);
    font-weight: 700;
    line-height: 1;
    color: var(--encre);
    background: var(--sceau);
    padding: 0.15em 0.4em;
    border-radius: var(--rayon);
    white-space: nowrap;
}
.heros__offre-dit { flex: 1 1 14rem; color: var(--encre); }
/* Le décompte du héros hérite de `.promo__reste` -- même classe, donc même
   graisse et mêmes chiffres tabulaires que dans la bande, et surtout même
   valeur : `site.js` écrit dans les deux. */
.heros__offre-dit a { font-weight: 600; }


/* ---------------------------------------------------------------------------
   LA BANDE D'AFFICHE DE L'OFFRE

   DEUX COLONNES SUR GRAND ÉCRAN, L'IMAGE D'ABORD SUR PETIT. C'est l'inverse de
   l'ordre du document, et c'est délibéré : sur un téléphone tenu à bout de bras,
   l'image se reconnaît avant que le titre ne se lise. Sur un écran large, le
   regard part de la gauche et l'image y est déjà.

   L'IMAGE EST PLAFONNÉE À 420 px. Le fichier en fait 840 — le double, pour
   rester net sur un écran à forte densité. La laisser s'afficher à sa taille
   réelle en ferait le plus gros élément de la page d'accueil, devant le titre,
   ce qui n'est pas ce qu'on vend. */
.affiche-offre__grille {
    display: grid;
    gap: var(--e-6) var(--e-12);
    align-items: center;
}
@media (min-width: 48rem) {
    .affiche-offre__grille {
        grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
    }
}

.affiche-offre__vue {
    display: block;
    justify-self: center;
    max-width: 420px;
    width: 100%;
    border-radius: var(--rayon);
    overflow: hidden;
    /* Un filet d'ocre plutôt qu'une ombre : le sceau est la couleur des marques
       de garantie, et cette bande en est une. Une ombre portée ferait flotter
       l'image au-dessus du papier, ce que cette charte ne fait nulle part. */
    border: 2px solid var(--sceau);
}
.affiche-offre__vue img { display: block; width: 100%; height: auto; }

.affiche-offre__dit > * + * { margin-top: var(--e-4); }
/* Le décompte hérite d'ici, et non de la bande d'en-tête : `.promo__reste` ne
   peint plus sa couleur en dur, précisément pour servir les deux fonds. */
.affiche-offre__dit .promo__reste { color: var(--sceau); font-size: var(--t-md); }



/* L'appel à l'action s'efface avant le reste quand la place manque : sur 360 px,
   le taux et l'échéance valent mieux que le mot « Tarifs » -- la bande entière
   est de toute façon cliquable. */
.promo__action {
    margin-inline-start: auto;
    font-family: var(--f-chiffre);
    font-size: var(--t-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--sceau);
    border-bottom: 1px solid currentColor;
}
/* SUR TÉLÉPHONE, LE BANDEAU REND DEUX LIGNES SUR TROIS.

   Mesuré sur 375 x 812 : le bandeau complet occupait 215 px au-dessus d'un
   en-tête déjà collant, soit un quart de l'écran mangé avant le premier mot de
   la page -- sur les appareils d'où vient l'essentiel du trafic. Ce qui part est
   ce qui se déduit : « sur les trois éditions » n'apprend rien à qui va cliquer
   sur un bandeau qui mène à la grille. Le taux, le décompte et la date restent,
   et ce sont les trois seules choses qui font agir. */
@media (max-width: 30rem) {
    .promo__action,
    .promo__quoi { display: none; }
    .promo { padding: var(--e-2) var(--e-3); gap: var(--e-1) var(--e-3); }
    .promo__taux { font-size: var(--t-base); }
}


/* Une ancre visée depuis un lien (`/produit` renvoie à `#documents` sur
   l'accueil) se posait sous l'en-tête collant, qui recouvrait le titre de la
   section qu'on venait chercher. La réserve vaut la hauteur de la barre plus une
   respiration. */
html { scroll-padding-top: 5.5rem; }

.marque {
    display: inline-block;
    padding-block: 0.35rem;                    /* Porte la marque à 44 px de haut. */
    font-family: var(--f-display);
    font-size: 1.375rem;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--encre);
    text-decoration: none;
}
/* Le point de tampon : la seule marque graphique de l'identité, et elle tient
   en un pseudo-élément. */
.marque::after {
    content: "";
    display: inline-block;
    width: 0.42em; height: 0.42em;
    margin-left: 0.28em;
    border-radius: 50%;
    background: var(--tampon);
}

.nav { display: flex; flex-wrap: wrap; gap: 0 var(--e-6); margin-left: auto; }
.nav a {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;                       /* 44 px de cible tactile. */
    color: var(--encre-70);
    text-decoration: none;
    font-size: var(--t-sm);
    padding-block: var(--e-2);
    border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--encre); border-bottom-color: var(--registre); }
.nav a[aria-current="page"] { color: var(--encre); border-bottom-color: var(--tampon); }

/* --- Les boutons d'action de l'en-tête ------------------------------------
   Ils sont plus petits que les boutons de la page, et c'est voulu : un bouton
   d'en-tête à la taille d'un appel à l'action de section écraserait le titre du
   héros, qui est ce que le visiteur doit lire en premier. Il doit être
   trouvable, pas dominant. */
.entete__actions { display: flex; gap: var(--e-3); }
/* LA TAILLE EST POSÉE SUR `.entete .entete__action`, ET LA SPÉCIFICITÉ EST LE
   SUJET. `.bouton` déclare `font: inherit` — un raccourci, donc il RÉINITIALISE
   `font-size` — et il est déclaré plus bas dans cette feuille. À spécificité
   égale (0,1,0), c'est lui qui gagnait : les boutons d'en-tête sortaient à
   18,5 px au lieu de 15, chacun une cinquantaine de pixels trop large, et la
   barre passait à deux lignes bien avant qu'elle n'aurait dû. Le défaut ne se
   voyait pas — un bouton un peu gros ne ressemble pas à un bug — mais c'est lui
   qui a fait croire que la barre réclamait 815 px.

   `.entete` en préfixe suffit à passer devant, sans `!important` : la règle dit
   ce qu'elle veut, à l'endroit où elle le veut. */
.entete .entete__action { font-size: var(--t-sm); }

.entete__action {
    /* `align-self` ET NON un changement d'`align-items` sur le conteneur :
       `.entete__inner` aligne la marque et la navigation sur leur ligne de base,
       ce qui est juste pour deux textes et faux pour un bouton, dont la base
       typographique est décalée par son rembourrage. Corriger le conteneur
       casserait l'alignement des deux autres pour en réparer un. */
    align-self: center;
    font-size: var(--t-sm);
    /* En `em` comme `.bouton`, et non en jeton d'espacement : le rembourrage
       suit alors la reduction de `font-size` au lieu de la contredire. */
    padding: 0.7em 1.2em;
    white-space: nowrap;
}


/* --- 4.1 Le menu replié -----------------------------------------------------
   Le `<details>` est le menu sur petit écran et n'est plus rien au-delà de
   48 rem, où la CSS masque son déclencheur et force l'affichage de son panneau.
   Deux états, une seule structure HTML : la navigation n'est écrite qu'une fois.

   `list-style: none` ET `::-webkit-details-marker` : le triangle par défaut du
   `<summary>` se retire différemment selon les moteurs, et il faut les deux
   déclarations pour qu'aucun ne le laisse dépasser à côté du mot « Menu ». */
/* LA MARGE AUTOMATIQUE N'EST PORTÉE QUE PAR UN SEUL ÉLÉMENT DE LA LIGNE.

   Deux marges automatiques dans un même conteneur flex se partagent l'espace
   libre : la pastille se retrouverait au milieu de la barre au lieu d'être
   contre le bord droit avec le menu. C'est donc la pastille qui pousse, et le
   menu qui la suit — sauf quand elle n'existe pas (numéro non configuré), auquel
   cas le sélecteur d'adjacence rend la marge au menu, qui devient alors le
   premier élément après la marque. */
.entete__pastille { margin-left: auto; }
.marque + .menu { margin-left: auto; }
/* LA PASTILLE ET « MENU » SE TIENNENT, AU LIEU DE FLOTTER SÉPARÉMENT.
   La gouttière de la barre vaut 2 rem — juste pour séparer la marque du reste.
   Entre ces deux-là, qui sont les deux commandes du même coin, elle produit un
   trou qui les fait lire comme deux éléments sans rapport. La marge négative la
   ramène à 0,75 rem sans toucher à la gouttière générale. */
.entete__pastille { margin-right: calc(var(--e-3) - var(--e-8)); }
.menu__declencheur {
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    min-height: 2.75rem;                       /* 44 px de cible tactile. */
    padding: var(--e-2) var(--e-3);
    font-size: var(--t-sm);
    color: var(--encre-70);
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.menu__declencheur::-webkit-details-marker { display: none; }
.menu__declencheur:hover { color: var(--encre); }

/* Les trois barres, dessinées en bordures plutôt qu'en SVG : trois traits
   valent une déclaration, et une image de plus à charger n'en vaut pas la
   peine. La barre du milieu est le fond de l'élément. */
.menu__barres {
    width: 1.15rem; height: 0.72rem;
    border-top: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    box-shadow: inset 0 0 0 1px transparent;
    position: relative;
}
.menu__barres::after {
    content: "";
    position: absolute; left: 0; right: 0; top: calc(50% - 1px);
    border-top: 2px solid currentColor;
}
/* Ouvert, le déclencheur porte la couleur d'encre pleine : c'est le seul retour
   visuel qui distingue un menu qu'on vient d'ouvrir d'un menu qu'on survole. */
.menu[open] > .menu__declencheur { color: var(--encre); }

/* Le panneau se pose SOUS la barre, en pleine largeur, plutôt qu'en flottant
   au-dessus du contenu : l'en-tête étant collant, un panneau flottant se
   superposerait au texte pendant tout le défilement qui suit un menu qu'on
   aurait oublié de refermer. Posé dans le flux, il repousse la page et se voit.

   IL EST LE FRÈRE DU `<details>`, JAMAIS SON ENFANT — voir le commentaire du
   gabarit. Son affichage se pilote donc par adjacence sur l'état `[open]`, et
   non en le laissant à la boîte `::details-content`, dont le masquage par
   `content-visibility` ne se contredit pas de façon portable. */
.menu__panneau {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
    flex-basis: 100%;
    padding-top: var(--e-4);
    margin-top: var(--e-3);
    border-top: var(--filet);
}
.menu:not([open]) + .menu__panneau { display: none; }
.menu__panneau .nav { flex-direction: column; margin-left: 0; gap: 0; }
.menu__panneau .nav a { border-bottom: none; border-left: 2px solid transparent; padding-left: var(--e-3); }
.menu__panneau .nav a[aria-current="page"] { border-left-color: var(--tampon); }
.menu__panneau .entete__actions { flex-direction: column; }
.menu__panneau .entete__action { align-self: stretch; text-align: center; padding-block: var(--e-3); }

/* La pastille WhatsApp : 44 px de cible tactile pour une icône de 22 px. */
.entete__pastille {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: center;
    width: 2.75rem; height: 2.75rem;
    border-radius: 50%;
    color: var(--tampon);
    background: var(--registre);
}
.entete__pastille:hover { color: var(--papier); background: var(--tampon); }

/* --- 4.2 Au-delà de 58 rem, le menu n'existe plus ---------------------------
   Le `<details>` et la pastille disparaissent, et le panneau s'affiche QUEL QUE
   SOIT l'état plié — c'est-à-dire y compris pour le visiteur qui a replié le
   menu sur son téléphone puis a pivoté en paysage. Sans cette reprise, il se
   retrouverait sans navigation.

   LE SÉLECTEUR EST RECOPIÉ À L'IDENTIQUE, et ce n'est pas une maladresse :
   `.menu:not([open]) + .menu__panneau` pèse plus lourd que `.menu__panneau`
   seul, et une simple redéclaration de la classe perdrait la cascade.

   TROIS PALIERS, ET LE PALIER DU MILIEU EXISTE POUR UNE RAISON PRÉCISE.

   Un seul seuil à 58 rem laissait toutes les fenêtres de 832 à 928 px avec le
   menu replié et la pastille — c'est-à-dire une petite icône ronde et un
   « Menu » sur un écran d'ordinateur portable, là où il y a visiblement la
   place. Ça se lit comme un défaut, et ç'en était un.

   LES CHIFFRES SONT MESURÉS, PAS CHOISIS. La barre réclame 815 px pour tenir
   sur une ligne avec ses DEUX boutons : marque 143, navigation 378, boutons
   230, plus les gouttières. Avec un seul bouton, il lui en faut environ 750.
   D'où :

     — sous 52 rem (832 px) : menu replié et pastille. En dessous de 750 px de
       besoin, la navigation viendrait se poser SUR la marque, et c'est le pire
       endroit du site où offrir un chevauchement puisque c'est le premier ;
     — de 52 à 64 rem : navigation en ligne, et le seul bouton WhatsApp.
       « Essayer gratuitement » s'efface parce qu'il est déjà deux fois dans le
       héros, à deux centimètres — alors que la conversation, elle, n'est nulle
       part ailleurs sur cette bande ;
     — au-delà de 64 rem : les deux boutons.

   Chaque seuil garde une marge au-dessus du besoin mesuré, de quoi absorber un
   libellé un peu plus long sans que la barre se casse. */
@media (min-width: 52rem) {
    .menu { display: none; }
    .entete__pastille { display: none; }
    .menu__panneau,
    .menu:not([open]) + .menu__panneau {
        display: flex;
        flex-direction: row;
        align-items: baseline;
        gap: var(--e-8);
        flex-basis: auto;
        margin-left: auto;
        margin-top: 0;
        padding-top: 0;
        border-top: none;
    }
    .menu__panneau .nav { flex-direction: row; gap: 0 var(--e-6); }
    .menu__panneau .nav a {
        border-left: none;
        padding-left: 0;
        border-bottom: 2px solid transparent;
    }
    .menu__panneau .nav a[aria-current="page"] { border-bottom-color: var(--tampon); }
    .menu__panneau .entete__actions { flex-direction: row; align-items: center; }
    .menu__panneau .entete__action { align-self: center; padding-block: var(--e-2); }
    /* Palier du milieu : un seul bouton. Voir le commentaire ci-dessus. */
    .menu__panneau .bouton--principal.entete__action { display: none; }
}

/* LE SECOND BOUTON N'ARRIVE QU'À 64 rem, ET LE CHIFFRE EST MESURÉ.
   Marque 143 + navigation 378 + « Essayer gratuitement » 192 + « Poser une
   question » 179 + deux gouttières de 32 = 956 px, auxquels s'ajoutent les
   48 px de marge de la page : 1004 px avant que la barre ne se casse en deux
   lignes. 1024 px passe, 1000 non — et une barre d'en-tête sur deux lignes est
   exactement ce qu'on venait de corriger. */
@media (min-width: 64rem) {
    .menu__panneau .bouton--principal.entete__action { display: inline-block; }
}

.pied { background: var(--encre); color: #c3cad8; padding-block: var(--e-16) var(--e-8); }
.pied a { color: #fff; text-decoration-color: rgba(255, 255, 255, .4); }
.pied__cols { display: grid; gap: var(--e-8); grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
.pied h2 { font-family: var(--f-texte); font-size: var(--t-xs); letter-spacing: 0.09em;
           text-transform: uppercase; color: #8d97ad; margin-bottom: var(--e-3); }
/* Les liens du pied mesuraient 20 px de haut, empilés à 8 px d'écart : sur un
   téléphone, viser « Confidentialité » sans toucher « Sécurité » relevait de
   l'adresse. Le rembourrage remplace la gouttière -- les surfaces de frappe
   sont alors jointives et font chacune 44 px, au lieu d'être minuscules et
   séparées par du vide inatteignable. */
.pied ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.pied ul a { display: inline-block; padding-block: var(--e-3); }
.pied__bas { margin-top: var(--e-12); padding-top: var(--e-6);
             border-top: 1px solid rgba(255,255,255,.14);
             font-size: var(--t-xs); color: #8d97ad; }


/* ==========================================================================
   5. BOUTONS
   ==========================================================================
   Deux niveaux, pas trois. Un troisième niveau n'existe que pour héberger une
   action qu'on n'a pas su hiérarchiser.
   ========================================================================== */

.bouton {
    display: inline-block;
    font: inherit;
    font-weight: 600;
    line-height: 1.2;
    padding: 0.85em 1.5em;
    border-radius: var(--rayon);
    border: 2px solid transparent;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.bouton--principal { background: var(--tampon); color: #fff; border-color: var(--tampon); }
.bouton--principal:hover { background: var(--tampon-fonce); border-color: var(--tampon-fonce); color: #fff; }

.bouton--second { background: transparent; color: var(--encre); border-color: var(--registre); }
.bouton--second:hover { border-color: var(--encre); color: var(--encre); }

.bande--encre .bouton--principal { background: #fff; color: var(--encre); border-color: #fff; }
.bande--encre .bouton--principal:hover { background: var(--registre); border-color: var(--registre); }
.bande--encre .bouton--second { color: var(--papier); border-color: rgba(255,255,255,.35); }
.bande--encre .bouton--second:hover { border-color: #fff; color: #fff; }

.actions { display: flex; flex-wrap: wrap; gap: var(--e-3); margin-top: var(--e-8); }

/* SUR UN TÉLÉPHONE, LES BOUTONS PRENNENT TOUTE LA LARGEUR.
   Empilés à leur largeur naturelle, ils forment un escalier -- « Essayer
   gratuitement » large, « Voir les offres » court -- qui donne à la page
   l'aspect d'un gabarit de bureau rétréci. Pleine largeur, ils se lisent comme
   deux choix de rang égal et se frappent sans viser. Au-delà de 30 rem, la
   largeur naturelle reprend : c'est là qu'ils tiennent côte à côte. */
@media (max-width: 29.999rem) {
    .actions > .bouton,
    .actions > button.bouton { flex: 1 1 100%; text-align: center; }
}

/* La mention sous les boutons : ce que le visiteur veut savoir AVANT de
   cliquer (« est-ce que ça m'engage ? »). */
.actions-note { font-size: var(--t-sm); color: var(--encre-45); margin-top: var(--e-4); }
.bande--encre .actions-note { color: #8d97ad; }


/* ==========================================================================
   6. HÉROS ET PANNEAU D'ÉTAT  -- l'élément signature
   ==========================================================================

   Le panneau met en scène la seule affirmation qu'aucun concurrent en ligne
   ne peut écrire : la connexion est absente, ET le logiciel fonctionne, ET la
   sauvegarde a été réellement restaurée.

   Il ressemble volontairement à un écran de panne, et n'en est pas un. C'est
   le pari visuel de la page : au lieu d'annoncer « fonctionne hors ligne »
   dans une liste d'arguments, on montre l'instant où les autres s'arrêtent.

   Les trois lignes reprennent des données qui existent réellement
   (`verdict_verification`, `date_verification_reussie`, migration V6) -- ce
   n'est pas une illustration inventée, c'est ce que le produit sait dire.
   ========================================================================== */

.heros { padding-block: clamp(var(--e-16), 10vw, var(--e-24)) clamp(var(--e-12), 8vw, var(--e-16)); }
.heros__grille {
    display: grid;
    gap: clamp(var(--e-12), 6vw, var(--e-16));
    align-items: start;
}
@media (min-width: 62rem) {
    .heros__grille { grid-template-columns: 1.05fr 0.95fr; gap: var(--e-16); align-items: center; }
}

.heros__titre { font-size: var(--t-2xl); max-width: 15ch; }
.heros__texte { font-size: var(--t-md); color: var(--encre-70); margin-top: var(--e-6); max-width: 38ch; }

.etat {
    background: var(--encre);
    color: var(--papier);
    border-radius: var(--rayon);
    padding: var(--e-6);
    /* L'ombre est portée par l'encre elle-même plutôt que par du noir : une
       ombre neutre sur un fond papier chaud vire au gris sale. */
    box-shadow: 0 1px 2px rgba(23,35,58,.18), 0 12px 32px -12px rgba(23,35,58,.35);
}
@media (min-width: 30rem) { .etat { padding: var(--e-8); } }

.etat__entete {
    display: flex; flex-wrap: wrap; gap: var(--e-2) var(--e-4);
    justify-content: space-between; align-items: baseline;
    padding-bottom: var(--e-4);
    border-bottom: 1px solid rgba(255,255,255,.16);
}
.etat__lieu { font-family: var(--f-texte); font-size: var(--t-sm); color: #c3cad8; margin: 0; }
.etat__horloge { font-family: var(--f-chiffre); font-size: var(--t-xs); color: #8d97ad; }

.etat__liste { margin: 0; padding: 0; }
.etat__ligne {
    display: grid;
    gap: var(--e-1) var(--e-4);
    padding-block: var(--e-4);
    border-bottom: 1px solid rgba(255,255,255,.1);
}
.etat__ligne:last-child { border-bottom: 0; padding-bottom: 0; }
/* La colonne d'étiquettes n'apparaît qu'à 34 rem, et non 26 rem.
   À 26 rem (416 px), 11 rem d'étiquette plus les marges du panneau laissaient
   moins de 120 px à la valeur : « absente depuis 3 jours » s'y cassait en trois
   lignes contre une étiquette d'une seule. Deux colonnes qui déséquilibrent
   ainsi valent moins qu'une colonne unique -- d'où le report du palier.
   `minmax(0, 1fr)` sur la seconde piste : sans lui, une valeur insécable
   imposerait sa largeur à la grille, et le panneau déborderait. */
@media (min-width: 34rem) {
    .etat__ligne { grid-template-columns: 10rem minmax(0, 1fr); align-items: baseline; }
}
.etat__ligne dt { font-size: var(--t-sm); color: #8d97ad; margin: 0; }
.etat__ligne dd { margin: 0; font-weight: 600; display: flex; align-items: baseline; gap: 0.55em; }

/* La pastille. `flex: none` sinon elle s'écrase quand le libellé passe à la
   ligne, et une pastille ovale a l'air d'un défaut d'affichage. */
.pastille { width: 0.6em; height: 0.6em; border-radius: 50%; flex: none;
            transform: translateY(-0.08em); }
.pastille--eteinte { background: transparent; border: 1.5px solid #6d7790; }
.pastille--marche  { background: var(--papier); }
.pastille--preuve  { background: #46b581; }

.etat__valeur--absente { color: #8d97ad; font-weight: 400; }
.etat__valeur--preuve  { color: #7fd7ac; }
.etat__date { font-family: var(--f-chiffre); font-size: 0.92em; }

.etat__note {
    margin-top: var(--e-6); padding-top: var(--e-4);
    border-top: 1px solid rgba(255,255,255,.16);
    font-size: var(--t-sm); color: #8d97ad; max-width: none;
}


/* ==========================================================================
   7. LES TROIS PREUVES
   ========================================================================== */

.preuves { display: grid; gap: var(--e-12); margin-top: var(--e-12); }
@media (min-width: 52rem) { .preuves { grid-template-columns: repeat(3, 1fr); gap: var(--e-8); } }

.preuve__titre { font-size: var(--t-lg); max-width: 16ch; }
.preuve__texte { margin-top: var(--e-3); color: var(--encre-70); font-size: var(--t-sm); }
.preuve__appui {
    margin-top: var(--e-4); padding-left: var(--e-4);
    border-left: 2px solid var(--sceau);
    font-size: var(--t-sm); color: var(--encre-70);
}


/* ==========================================================================
   8. L'ANNÉE SCOLAIRE  -- le dispositif de structure de la page produit
   ==========================================================================

   L'étude (§3.3) impose d'organiser la page produit PAR MOMENT DE L'ANNÉE, et
   non par liste de fonctionnalités -- « gestion des inscriptions, gestion des
   paiements » ne distingue GestionEcole d'aucun concurrent, puisque tous
   écrivent ces mêmes lignes.

   D'où la colonne de gauche : elle porte le MOIS, pas un numéro d'étape.
   Numéroter 01/02/03 n'apprendrait rien -- une directrice sait déjà qu'il y a
   cinq blocs. « Septembre », « Décembre · Mars · Juin », « Juillet » situent
   l'écran dans son année à elle. La structure porte une information vraie,
   elle ne décore pas.
   ========================================================================== */

.annee { display: grid; gap: var(--e-16); margin-top: var(--e-16); }

.moment { display: grid; gap: var(--e-4); }
@media (min-width: 48rem) {
    .moment { grid-template-columns: 12rem 1fr; gap: var(--e-8); }
}

.moment__quand {
    font-family: var(--f-chiffre);
    font-size: var(--t-xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--encre-45);
    padding-top: 0.55em;                       /* Aligne sur la 1re ligne du titre. */
    border-top: 2px solid var(--encre);
    align-self: start;
}
.moment__titre { font-size: var(--t-lg); }
.moment__texte { margin-top: var(--e-3); color: var(--encre-70); }

/* ==========================================================================
   8 bis. LES CAPTURES D'ÉCRAN
   ==========================================================================

   DEUX FAMILLES, ET LES HABILLER PAREIL SE VERRAIT.

   Les captures livrées ne sont pas homogènes, et c'est une propriété du
   produit, pas un défaut du lot : GestionEcole montre tantôt une FENÊTRE
   (thème sombre, 16:9), tantôt un DOCUMENT qu'il imprime (fond blanc, format
   d'une feuille). Les deux ne se présentent pas de la même façon.

   - `.capture--ecran` : coins arrondis et ombre portée douce. Le sombre
     tranche sur le papier du site ; c'est un atout, on l'assume au lieu de
     l'atténuer par un cadre pâle.
   - `.capture--document` : un filet fin, AUCUNE OMBRE. Ce sont des feuilles de
     papier -- un reçu, un bulletin, un emploi du temps exporté. Les faire
     flotter comme des fenêtres brouille exactement ce qu'elles démontrent :
     que ce papier-là sort de l'imprimante de l'école.

   AUCUN RECADRAGE À UN FORMAT COMMUN. Les documents ont des ratios inégaux
   (le reçu ≈ 1,4:1, le bulletin ≈ 1,1:1, l'emploi du temps ≈ 2:1). Un bulletin
   tronqué pour tenir dans une grille ne prouve plus rien. Largeur contrainte,
   hauteur libre, alignement en haut.

   `width` et `height` sont déclarés sur chaque `<img>` du gabarit, et non ici :
   ils réservent la place avant l'arrivée de l'image et suppriment le décalage
   de mise en page -- celui qui fait cliquer à côté sur un téléphone lent. */

.capture { margin: var(--e-6) 0 0; }

.capture img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--rayon);
}

.capture--ecran img {
    border: 1px solid rgba(23, 35, 58, 0.18);
    box-shadow: 0 1px 2px rgba(23, 35, 58, 0.08),
                0 14px 34px -10px rgba(23, 35, 58, 0.30);
}

/* UN DOCUMENT NE S'AGRANDIT JAMAIS AU-DELÀ DE SA TAILLE RÉELLE.

   `width: 100%` convient à un écran capturé en 1365 px, qu'on réduit. Il ruine
   un document : le bulletin fait 728 px de large, et l'étirer à 1100 px rend
   floues précisément les moyennes et les appréciations qu'il est là pour
   montrer. Une preuve illisible cesse d'être une preuve.

   `width: auto` + `max-width: 100%` : taille réelle sur grand écran, réduction
   sur téléphone, agrandissement jamais. */
.capture--document img {
    width: auto;
    max-width: 100%;
    border: var(--filet);
    background: #fff;
    box-shadow: none;
}

/* LA LÉGENDE VEND, LE TEXTE ALTERNATIF DÉCRIT. Elle dit ce que l'écran
   ÉPARGNE, jamais ce qu'il contient : le visiteur voit déjà que c'est un
   tableau de bord. */
.capture__legende {
    margin-top: var(--e-3);
    font-size: var(--t-sm);
    color: var(--encre-70);
    max-width: var(--mesure);
}

/* UNE CAPTURE DANS UNE COLONNE DE TEXTE DÉBORDE SA MESURE, EXPRÈS.

   `.prose` est bornée à 34rem parce que c'est la largeur à laquelle un
   paragraphe se lit sans que l'œil perde sa ligne. Cette contrainte est juste
   pour du texte et fausse pour une capture : un écran de 1365 px réduit à
   34rem devient un timbre-poste, et une preuve qu'on ne peut pas lire ne
   prouve rien.

   Elle déborde donc vers la droite, dans la marge que `.page` laisse déjà --
   sans jamais dépasser la fenêtre, faute de quoi la page entière défilerait
   horizontalement sur un téléphone. */
.prose .capture { max-width: none; }
@media (min-width: 64rem) {
    .prose .capture { width: min(48rem, calc(100vw - 4rem)); }
}

/* Deux captures côte à côte -- la page des offres met les dépenses et la paie
   en regard de Premium. Une seule colonne en dessous de 52rem : deux écrans
   d'application réduits de moitié sur un téléphone ne se lisent plus. */
.captures-paire { display: grid; gap: var(--e-8); margin-top: var(--e-12); }
@media (min-width: 52rem) { .captures-paire { grid-template-columns: 1fr 1fr; } }

/* Emplacement d'une capture non encore livrée. Le cadre annonce ce qu'il
   attend au lieu d'afficher un rectangle gris : l'étude (§3.3) interdit de
   montrer un écran non livré, et un emplacement vide et daté vaut mieux qu'un
   faux visuel. Conservé bien que les douze captures soient aujourd'hui posées
   -- la prochaine page écrite en aura besoin avant son image. */
.capture--attendue {
    border: 1px dashed var(--registre);
    border-radius: var(--rayon);
    background: var(--registre-pale);
    padding: var(--e-8) var(--e-6);
    text-align: center;
    color: var(--encre-45);
    font-size: var(--t-sm);
}


/* ==========================================================================
   9. OFFRES
   ==========================================================================
   Trois cartes, et la carte du milieu est mise en avant -- pas par un ruban
   « populaire » inventé, mais parce que l'étude désigne « Sérénité » comme le
   cas normal (§3.4).
   ========================================================================== */

.offres { display: grid; gap: var(--e-6); margin-top: var(--e-12); align-items: start; }
@media (min-width: 56rem) { .offres { grid-template-columns: repeat(3, 1fr); } }
/* Deux cartes et non trois : l'édition en ligne ne vend que Pro et Premium
   (D-0047), et deux cartes dans une grille de trois laisseraient un tiers vide
   qui se lit comme une offre manquante. */
@media (min-width: 46rem) { .offres--deux { grid-template-columns: repeat(2, 1fr); } }

.offre {
    background: var(--papier);
    border: var(--filet);
    border-radius: var(--rayon);
    padding: var(--e-6);
    display: flex; flex-direction: column; gap: var(--e-4);
    height: 100%;
}
.offre--phare { border-color: var(--encre); border-width: 2px; }

.offre__bandeau {
    font-family: var(--f-chiffre); font-size: var(--t-xs);
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--tampon);
}
.offre__nom { font-size: var(--t-lg); }
.offre__cible { font-size: var(--t-sm); color: var(--encre-45); }

.offre__prix { font-family: var(--f-chiffre); font-size: var(--t-lg); font-weight: 600;
               line-height: 1.2; }
.offre__prix small { display: block; font-family: var(--f-texte); font-size: var(--t-xs);
                     font-weight: 400; color: var(--encre-45); margin-top: var(--e-1);
                     letter-spacing: 0; }
/* Le prix barré et le taux, sous le grand nombre.

   LE PRIX BARRÉ RESTE LISIBLE, ET CE N'EST PAS UN DÉTAIL DE GOÛT. Un ancien prix
   grisé au point de ne plus se lire ne prouve plus rien : c'est lui qui donne sa
   valeur au nouveau, et un visiteur qui doit plisser les yeux pour le retrouver
   conclut qu'on lui cache quelque chose. `--encre-45` est le gris le plus clair
   de la palette qui tienne encore le contraste AA sur le papier. */
.offre__remise {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--e-2);
    margin-top: var(--e-2); font-size: var(--t-sm);
}
.offre__remise s { font-family: var(--f-chiffre); color: var(--encre-45); }
/* SUR LA CARTE, LE TAUX EST UNE PASTILLE ET LA DATE RESTE DU TEXTE.

   En ocre sur papier, la ligne entière disparaissait sous le grand prix qui la
   surplombe -- elle disait la remise à qui la cherchait déjà. La pastille donne
   au taux le seul poids visuel qui tienne à côté d'un nombre en corps 24, et la
   date garde la discrétion qui lui va : c'est le taux qui fait s'arrêter, c'est
   la date qui fait décider. */
.offre__gain {
    display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: var(--e-2);
    font-family: var(--f-chiffre); font-size: var(--t-xs); font-weight: 600;
    letter-spacing: 0.04em; color: var(--encre-70);
}
.offre__gain-taux {
    font-size: var(--t-sm); font-weight: 700; letter-spacing: 0.02em;
    color: var(--encre); background: var(--sceau);
    padding: 0.1em 0.45em; border-radius: var(--rayon);
    white-space: nowrap;
}

/* Prix non arrêté : l'étude (§3.4) laisse les montants à la décision
   commerciale. On l'écrit lisiblement plutôt que d'afficher un zéro. */
.offre__prix--consulter { font-family: var(--f-display); font-weight: 600; }

.offre__inclus { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e-2);
                 font-size: var(--t-sm); }
.offre__inclus li { display: grid; grid-template-columns: 1.4em 1fr; align-items: baseline; }
.offre__inclus li::before { content: "✔"; color: var(--preuve); font-size: 0.9em; }
.offre__inclus li[data-absent]::before { content: "—"; color: var(--encre-45); }
.offre__inclus li[data-absent] { color: var(--encre-45); }

.offre .bouton { margin-top: auto; text-align: center; }

/* --- Le tableau comparatif ------------------------------------------------
   Il défile dans son propre cadre plutôt que de déborder la page : quatre
   colonnes ne tiennent pas en 360 px, et une page qui défile latéralement est
   le défaut le plus visible d'un site mal porté sur mobile.

   ET IL LE FAISAIT QUAND MÊME. `overflow-x: auto` contenait bien le tableau,
   mais les mentions « inclus / non inclus » destinées aux lecteurs d'écran sont
   `position: absolute` : faute d'ancêtre positionné, elles se calaient sur le
   document et portaient sa largeur défilable à 549 px. Résultat exact du défaut
   qu'on prétendait éviter -- 190 px de vide à droite de chaque section, sur la
   page qui porte les prix. `position: relative` sur le cadre ET sur les
   cellules rend à ce défilement son conteneur. Ne pas les retirer.

   L'OMBRE PORTÉE EST L'AFFORDANCE. Rien n'indiquait qu'on pouvait faire glisser
   ce tableau : un visiteur voyait trois colonnes et concluait qu'il n'y en avait
   que trois. Les deux dégradés en `background-attachment: local` restent collés
   au contenu et s'effacent en bout de course -- le voile n'apparaît que du côté
   où il reste quelque chose à voir. Zéro octet de JavaScript. */
.comparatif {
    position: relative;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    margin-top: var(--e-12);
    border: var(--filet);
    border-radius: var(--rayon);
    background:
        linear-gradient(to right, var(--papier), rgba(252, 251, 248, 0)) left center,
        linear-gradient(to left,  var(--papier), rgba(252, 251, 248, 0)) right center,
        radial-gradient(farthest-side at 0    50%, rgba(23, 35, 58, .22), rgba(23, 35, 58, 0)) left center,
        radial-gradient(farthest-side at 100% 50%, rgba(23, 35, 58, .22), rgba(23, 35, 58, 0)) right center;
    background-color: var(--papier);
    background-repeat: no-repeat;
    background-size: 2.5rem 100%, 2.5rem 100%, 1rem 100%, 1rem 100%;
    background-attachment: local, local, scroll, scroll;
}
/* Le cadre est focalisable au clavier (`tabindex="0"` dans le gabarit) : sans
   contour visible, un utilisateur au clavier ne saurait pas qu'il vient d'y
   entrer, ni qu'il peut le parcourir aux flèches. */
.comparatif:focus-visible { outline: 3px solid var(--tampon); outline-offset: 2px; }

.comparatif table { border-collapse: collapse; width: 100%; min-width: 34rem;
                    font-size: var(--t-sm); }
.comparatif th, .comparatif td { position: relative;
                                 text-align: left; padding: var(--e-3) var(--e-4);
                                 border-bottom: var(--filet); }
.comparatif thead th { font-family: var(--f-texte); font-size: var(--t-xs);
                       letter-spacing: 0.06em; text-transform: uppercase;
                       color: var(--encre-45); white-space: nowrap;
                       border-bottom: 2px solid var(--encre); }
/* `<small>` par défaut vaut 0,83 em, soit 12,5 px hérité du corps du tableau --
   et ce qu'il porte ici n'est pas une note de bas de page : « au lieu de
   350 000 F », « et vous ne possédez rien » sont les mentions qui font pencher
   la décision. Elles reprennent le plus petit corps de la charte, pas moins. */
.comparatif small { font-size: var(--t-xs); }

.comparatif tbody tr:last-child td, .comparatif tbody tr:last-child th { border-bottom: 0; }
.comparatif td { text-align: center; }
.comparatif tbody th { font-weight: 400; }
.comparatif .oui { color: var(--preuve); font-weight: 700; }
.comparatif .non { color: var(--encre-45); }


/* ==========================================================================
   9 bis. SERVICE EN LIGNE  -- le second axe du modèle
   ==========================================================================

   Volontairement DIFFÉRENT d'une carte d'offre, et non une quatrième colonne.

   Un service ne se compare pas à une édition : il s'y ajoute. Lui donner
   l'apparence d'une carte d'offre le placerait en concurrence avec Essentiel,
   Pro et Premium, et rouvrirait exactement la confusion qui a valu à cette
   page une réécriture — l'édition dit ce que le logiciel ouvre, le service dit
   ce que l'éditeur héberge.

   D'où le filet ocre : c'est la couleur du sceau, réservée à ce qui est
   garanti. Elle ne sert nulle part ailleurs sur cette page.
   ========================================================================== */

.service {
    display: grid;
    gap: var(--e-8);
    margin-top: var(--e-12);
    padding: var(--e-8) var(--e-6);
    background: var(--papier);
    border: var(--filet);
    border-left: 3px solid var(--sceau);
    border-radius: 0 var(--rayon) var(--rayon) 0;
}
@media (min-width: 52rem) {
    .service { grid-template-columns: 1fr 1fr; gap: var(--e-16); padding: var(--e-8); }
}

.service__nom { font-size: var(--t-lg); }
.service__promesse { margin-top: var(--e-3); color: var(--encre-70); }

.service__prix {
    font-family: var(--f-chiffre);
    font-size: var(--t-xl);
    font-weight: 600;
    line-height: 1.1;
    margin-top: var(--e-6);
}
.service__prix small {
    display: block; margin-top: var(--e-1);
    font-family: var(--f-texte); font-size: var(--t-sm); font-weight: 400;
    color: var(--encre-45); letter-spacing: 0;
}

.service__inclus { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e-3);
                   font-size: var(--t-sm); }
.service__inclus li { display: grid; grid-template-columns: 1.4em 1fr; align-items: baseline; }
.service__inclus li::before { content: "✔"; color: var(--preuve); font-size: .9em; }


/* ==========================================================================
   10. BLOCS DE TEXTE LONG  (sécurité, mentions légales, CGV)
   ========================================================================== */

.prose { max-width: var(--mesure); }
.prose h2 { font-size: var(--t-lg); margin-top: var(--e-12); }
.prose h3 { font-family: var(--f-texte); font-size: var(--t-base); font-weight: 650;
            margin-top: var(--e-8); letter-spacing: 0; }
.prose p, .prose li { color: var(--encre-70); }
.prose ul { padding-left: 1.15em; display: grid; gap: var(--e-2); margin: var(--e-4) 0 0; }
.prose > * + h2 { margin-top: var(--e-16); }

/* Encadré « à compléter » : signale un contenu qui ATTEND une décision
   humaine (raison sociale, montants, adresse). Il est voyant exprès -- une
   mention légale incomplète mise en ligne discrètement est une mention légale
   qu'on oublie de compléter. */
.a-completer {
    border-left: 3px solid var(--sceau);
    background: #fdf8ec;
    padding: var(--e-4) var(--e-6);
    margin-top: var(--e-6);
    font-size: var(--t-sm);
    border-radius: 0 var(--rayon) var(--rayon) 0;
}
.a-completer p { max-width: none; }
.a-completer strong { color: #7a5b12; }

/* CE QUE TOUTES LES ÉDITIONS CONTIENNENT — du contenu de vente, et non une
   note interne. Il empruntait la forme de `.a-completer` en écrasant ses
   couleurs en style en ligne : même dessin, intention inverse. Le filet est
   ici celui du tampon, la couleur de ce qui est acquis, jamais celle du sceau
   qui signale ce qui manque. */
.socle-commun {
    border-left: 3px solid var(--tampon);
    background: var(--registre-pale);
    padding: var(--e-4) var(--e-6);
    margin-top: var(--e-8);
    font-size: var(--t-sm);
    border-radius: 0 var(--rayon) var(--rayon) 0;
}
.socle-commun p { max-width: none; }


/* ==========================================================================
   11. APPEL FINAL
   ========================================================================== */

.final { text-align: center; }
.final .titre-section, .final .chapeau { margin-inline: auto; }
.final .chapeau { max-width: 42ch; }
.final .actions { justify-content: center; }


/* ==========================================================================
   12. FORMULAIRES  (tunnel de commande — T-055)
   ==========================================================================
   Le premier formulaire du site. Il est rempli sur un téléphone, souvent en
   connexion mobile, par quelqu'un qui s'apprête à verser 250 000 F : la
   priorité est la lisibilité des libellés et la taille des cibles tactiles,
   pas la densité.

   AUCUN `placeholder` EN GUISE D'ÉTIQUETTE. Un placeholder disparaît à la
   saisie : l'utilisateur qui revient sur un champ ne sait plus ce qu'on lui
   demandait, et un lecteur d'écran ne l'annonce pas de façon fiable. Chaque
   champ porte donc un vrai <label>.
   ========================================================================== */

.formulaire { max-width: var(--mesure); display: grid; gap: var(--e-6); }

.champ { display: grid; gap: var(--e-2); }

.champ > label {
    font-family: var(--f-texte);
    font-size: var(--t-sm);
    font-weight: 650;
    color: var(--encre);
}

/* La précision sous l'étiquette, jamais à la place. */
.champ__aide { font-size: var(--t-xs); color: var(--encre-45); margin: 0; }

.champ input,
.champ select,
.champ textarea {
    font: inherit;
    font-size: var(--t-base);
    /* 0.75em de haut : au moins 44px de cible tactile sur un téléphone. */
    padding: 0.75em 0.9em;
    border: 1px solid var(--encre-45);
    border-radius: var(--rayon);
    background: #fff;
    color: var(--encre);
    width: 100%;
}

.champ input:focus-visible,
.champ select:focus-visible,
.champ textarea:focus-visible {
    outline: 3px solid var(--tampon);
    outline-offset: 1px;
    border-color: var(--tampon);
}

/* Le choix de l'édition : des cartes cliquables plutôt qu'une liste
   déroulante. Sur un téléphone, une liste déroulante cache les options
   derrière un geste, et le prix — qui est l'information décisive — n'y est
   pas visible au moment du choix. */
.choix-edition { display: grid; gap: var(--e-4); }

.choix-edition__option {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--e-4);
    align-items: start;
    border: 1px solid var(--registre);
    border-radius: var(--rayon);
    padding: var(--e-4) var(--e-6);
    background: #fff;
    cursor: pointer;
}

.choix-edition__option:hover { border-color: var(--encre-45); }

.choix-edition__option:has(input:checked) {
    border-color: var(--tampon);
    box-shadow: inset 0 0 0 1px var(--tampon);
}

.choix-edition__option:has(input:focus-visible) {
    outline: 3px solid var(--tampon);
    outline-offset: 2px;
}

/* Le bouton radio natif fait 13 px. L'étiquette entière est cliquable, donc la
   cible réelle est la carte -- mais la pastille reste ce que l'œil vise, et une
   pastille de 13 px sur un écran tactile se lit comme « pas encore chargé ». */
.choix-edition__option input {
    width: 1.25rem; height: 1.25rem;
    margin-top: 0.3em;
    accent-color: var(--tampon);
    flex: none;
}

/* LE NOM ET LE PRIX SUR UNE LIGNE, LA NOTE SOUS ELLE.
   Ces trois-là sont des <span> : une marge verticale ne s'applique pas à un
   élément en ligne, si bien que la note se poursuivait dans la même phrase que
   le prix -- « 100 000 F la première année Encaisser et inscrire, proprement.
   Louée à l'année. » -- soit un paragraphe illisible à l'endroit précis où le
   client choisit ce qu'il va payer. Les passer en bloc rétablit les trois
   niveaux de lecture. */
.choix-edition__entete {
    display: flex; flex-wrap: wrap; align-items: baseline;
    gap: 0 0.45em;
}
.choix-edition__nom { font-weight: 650; font-size: var(--t-md); }
.choix-edition__prix { font-family: var(--f-chiffre); color: var(--tampon-fonce); }
.choix-edition__note { display: block; font-size: var(--t-sm); color: var(--encre-70);
                       margin: var(--e-1) 0 0; }

/* ==========================================================================
   13. RÉCAPITULATIF ET PAIEMENT
   ========================================================================== */

.recap {
    max-width: var(--mesure);
    border: var(--filet);
    border-radius: var(--rayon);
    background: #fff;
}

/* DEUX COLONNES SEULEMENT QUAND IL Y A LA PLACE POUR DEUX COLONNES.
   `grid-template-columns: auto 1fr` était la pire forme possible ici : `1fr`
   vaut `minmax(auto, 1fr)`, donc la piste refuse de descendre sous le
   contenu insécable qu'elle porte -- et ce qu'elle porte, c'est l'adresse
   électronique du client. Une adresse de 38 caractères poussait la grille à
   536 px, la grille poussait la page, et la PAGE DE CONFIRMATION DE COMMANDE
   défilait latéralement sur tous les téléphones : le nom de l'établissement
   tronqué, le montant coupé en deux, les fonds de section s'arrêtant au milieu
   de l'écran. Sur l'écran qui doit rassurer quelqu'un qui s'apprête à verser
   400 000 F.

   D'où : une seule colonne par défaut, l'étiquette au-dessus de sa valeur, et
   la seconde piste en `minmax(0, 1fr)` -- la forme qui autorise le rétrécissement
   -- lorsque les deux colonnes reviennent à 30 rem. */
.recap dl { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--e-1);
            margin: 0; padding: var(--e-6); }
.recap dt { font-size: var(--t-sm); color: var(--encre-45); }
.recap dd { margin: 0; overflow-wrap: anywhere; }
.recap dd + dt { margin-top: var(--e-4); }

@media (min-width: 30rem) {
    .recap dl { grid-template-columns: auto minmax(0, 1fr); gap: var(--e-3) var(--e-6);
                align-items: baseline; }
    .recap dd + dt { margin-top: 0; }
}

.recap__total {
    border-top: var(--filet);
    padding: var(--e-4) var(--e-6);
    display: flex; flex-wrap: wrap;
    justify-content: space-between; align-items: baseline; gap: var(--e-2) var(--e-4);
    background: var(--registre-pale);
}
/* Un montant ne se coupe jamais. « 400 000 F / CFA » sur deux lignes se lit une
   fraction de seconde comme deux nombres, et c'est la seule ligne de la page
   qu'on ne peut pas laisser hésiter. */
.recap__total .montant { font-family: var(--f-chiffre); font-size: var(--t-lg); font-weight: 650;
                         white-space: nowrap; }

/* La référence à recopier dans le paiement. En chiffres monospacés et
   sélectionnable d'un geste : c'est la seule chose que le client doit
   transcrire sans se tromper. */
.reference {
    font-family: var(--f-chiffre);
    font-size: var(--t-md);
    letter-spacing: 0.04em;
    max-width: 100%;
    background: var(--registre-pale);
    border: var(--filet);
    border-radius: var(--rayon);
    padding: var(--e-2) var(--e-4);
    display: inline-block;
    user-select: all;
}

/* Un message qui interrompt : panne, refus, quota. Distinct de `.a-completer`,
   qui s'adresse à l'éditeur ; celui-ci s'adresse au client. */
.avis {
    max-width: var(--mesure);
    border-left: 3px solid var(--sceau);
    background: #fdf8ec;
    padding: var(--e-4) var(--e-6);
    border-radius: 0 var(--rayon) var(--rayon) 0;
}

/* L'empreinte SHA-256 de l'installateur, sur le panneau sombre — T-082.

   `break-all` et non `break-word` : une empreinte n'a pas de mots. Sans lui,
   soixante-quatre caractères insécables imposent leur largeur au panneau, et
   la page déborde horizontalement sur un téléphone — la seule chose que cette
   charte n'autorise nulle part.

   `user-select: all` d'un seul geste, comme `.reference` : le bouton Copier
   n'existe que si `site.js` tourne, et une empreinte qu'on ne peut ni copier
   ni sélectionner proprement ne se vérifie pas. */
.empreinte {
    font-family: var(--f-chiffre);
    font-size: var(--t-sm);
    letter-spacing: 0.02em;
    word-break: break-all;
    user-select: all;
}

/* La commande à retaper. Plus claire que le texte de la note qui la porte :
   c'est la seule ligne de ce paragraphe que le lecteur doit recopier. */
.commande {
    font-family: var(--f-chiffre);
    font-size: 0.95em;
    word-break: break-all;
    color: #c3cad8;
}


/* ==========================================================================
   14. CE QUI N'EXISTE QUE SI `site.js` TOURNE
   ==========================================================================

   RIEN ICI NE MASQUE QUOI QUE CE SOIT, ET C'EST CE QUI REND LA CHUTE PROPRE.

   L'état à éviter n'est pas « sans amélioration », il est « à moitié améliorée » :
   un tableau masqué par la charte au profit de cartes que le script n'a jamais
   construites, et c'est la grille tarifaire qui disparaît. Une coupure au milieu
   du téléchargement, une extension qui bloque, un navigateur d'un autre âge
   suffisent.

   D'où la discipline : LES BASCULES SONT FAITES PAR LE SCRIPT, en posant
   `hidden` sur les éléments -- jamais par une requête de média dans ce fichier.
   Un script qui ne tourne pas ne pose rien, donc ne cache rien, et la page reste
   exactement celle d'avant, tableau défilant compris.

   Tout le reste ci-dessous ne fait qu'habiller des éléments que le script CRÉE :
   ils n'existent pas sans lui, ces règles n'ont donc rien à garder. `site.js`
   pose tout de même `.js` sur <html> -- pour la règle qui, un jour, devra
   vraiment masquer quelque chose. Qu'elle passe par là, et par rien d'autre.
   ========================================================================== */

/* Le défilement doux ne concerne que les ancres du sommaire. Le bloc
   `prefers-reduced-motion` du §2 le remet à `auto` d'autorité. */
html { scroll-behavior: smooth; }

/* Une ancre qui atterrit collée au bord haut se lit comme une page mal chargée. */
.prose h2[id], .prose h3[id] { scroll-margin-top: var(--e-8); }


/* --- 14.1 Le comparatif en cartes ----------------------------------------
   Le tableau reste dans le document -- il est la source des cartes, et c'est lui
   que les moteurs lisent. Sous 48 rem le script les échange ; au-dessus, le
   tableau reprend sa place, parce qu'à cette largeur comparer en colonnes est
   plus efficace que trois cartes à faire défiler verticalement. */
.comparatif-cartes { display: grid; gap: var(--e-4); margin-top: var(--e-12); }

.comparatif-carte {
    background: var(--papier);
    border: var(--filet);
    border-radius: var(--rayon);
    padding: var(--e-6);
}
/* La première carte porte le filet d'encre : dans le tableau, l'ordre des
   colonnes disait l'ordre des éditions ; en cartes, il faut le redire. */
.comparatif-carte:first-child { border-top: 2px solid var(--encre); }

.comparatif-carte__nom {
    font-size: var(--t-lg);
    padding-bottom: var(--e-3);
    border-bottom: var(--filet);
}

/* DEUX COLONNES, ET C'EST CE QUI REND LA CARTE LISIBLE.

   Empilées -- l'intitulé sur une ligne, l'état sur la suivante -- sept lignes
   font une carte de quatorze lignes, et trois cartes deviennent un défilement
   interminable là où l'on voulait justement supprimer le geste. « inclus » fait
   six caractères : il tient à droite de son intitulé.

   L'intitulé prend `minmax(0, 1fr)` -- la forme qui accepte de rétrécir -- et
   l'état `auto`, sa largeur propre : c'est l'état qui est court et fixe, l'intitulé
   qui peut passer à la ligne. L'inverse tronquerait « inclus ». */
.comparatif-carte__liste {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    /* GOUTTIÈRE À ZÉRO, ET L'ÉCART PORTÉ PAR UN REMBOURRAGE.
       Le filet de séparation est posé sous chacune des deux cellules ; une
       gouttière l'aurait interrompu entre elles, et sept traits coupés au même
       endroit se lisent comme un défaut d'affichage plutôt que comme une
       réglure. Le rembourrage de `dt` fait le même écart, sans le trou. */
    column-gap: 0;
    margin: 0;
}
.comparatif-carte__liste dt {
    font-size: var(--t-sm);
    color: var(--encre-70);
    padding-block: var(--e-3);
    padding-right: var(--e-4);
    border-bottom: 1px solid var(--registre-pale);
}
.comparatif-carte__liste dd {
    margin: 0;
    padding-block: var(--e-3);
    border-bottom: 1px solid var(--registre-pale);
    font-size: var(--t-sm);
    font-weight: 600;
    text-align: right;
    display: flex; align-items: baseline; justify-content: flex-end;
    gap: 0.4em; flex-wrap: wrap;
}
/* Le dernier COUPLE, pas la dernière cellule : `dd:last-child` laisserait le
   filet sous le dernier intitulé, et une carte se terminerait par un demi-trait. */
.comparatif-carte__liste dt:nth-last-of-type(1),
.comparatif-carte__liste dd:nth-last-of-type(1) { border-bottom: 0; }

/* --- La variante « phrases » ---------------------------------------------
   Posée par `site.js` quand une valeur dépasse dix-huit caractères, c'est-à-dire
   quand elle n'est plus un état mais une réponse. Là, l'intitulé reprend sa ligne
   entière et la valeur s'affiche dessous, en corps de lecture : « Première année »
   puis « 100 000 F, déductibles de l'achat ». Deux colonnes auraient réduit
   l'intitulé à une lettre par ligne. */
.comparatif-cartes--phrases .comparatif-carte__liste { grid-template-columns: minmax(0, 1fr); }
.comparatif-cartes--phrases .comparatif-carte__liste dt {
    padding-right: 0; padding-bottom: 0; border-bottom: 0;
    font-size: var(--t-xs); letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--encre-45);
}
.comparatif-cartes--phrases .comparatif-carte__liste dd {
    text-align: left; justify-content: flex-start;
    padding-top: var(--e-1);
    font-size: var(--t-base);
}
/* LES CHIFFRES TABULAIRES PLUTÔT QUE LA CHASSE FIXE, ET C'EST UN CHOIX DE
   COHÉRENCE.

   Dans ce tableau, « 250 000 F » est en <strong> et « 150 000 F » ne l'est pas --
   le balisage suit l'emphase commerciale, pas la nature de la valeur. Réserver
   `--f-chiffre` au <strong> donnait donc deux montants en machine à écrire et
   deux en sans, dans la même carte : le lecteur y voyait une distinction qui
   n'existe pas.

   `tabular-nums` traite tous les montants pareil et aligne leurs chiffres, ce
   qui est le seul service que la chasse fixe rendait ici -- les cartes sont
   empilées, il n'y a plus de colonne à tenir. Et « plus rien à payer », qui
   occupe la même place que les montants, cesse d'avoir l'air d'un code. */
.comparatif-cartes--phrases .comparatif-carte__liste dd { font-variant-numeric: tabular-nums; }

/* La mention rendue visible par le script (« inclus », « non inclus »). Le
   tableau ne pouvait afficher qu'une coche faute de largeur ; la carte écrit le
   mot, et la convention cesse d'être à deviner. */
.comparatif-carte__etat { font-weight: 400; color: var(--encre-70); }
.comparatif-carte__liste dd .oui + .comparatif-carte__etat { color: var(--preuve); }
.comparatif-carte__liste dd .non + .comparatif-carte__etat { color: var(--encre-45); }
.comparatif-carte__liste dd small { display: block; flex: 1 1 100%;
                                    font-size: var(--t-xs); font-weight: 400;
                                    color: var(--encre-45); }


/* --- 14.2 La barre d'action collante -------------------------------------
   Elle ne s'affiche que sur mobile, et seulement quand l'appel à l'action de la
   page est hors champ (§2 de `site.js`). Deux détails la rendent supportable
   plutôt qu'envahissante : elle ne dépasse jamais la hauteur d'un bouton, et
   elle glisse depuis le bas au lieu d'apparaître d'un coup -- une apparition
   sèche en bas d'écran se lit comme une publicité. */
.barre-action {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 20;
    background: var(--papier);
    border-top: var(--filet);
    /* L'ombre est portée vers le haut : elle détache la barre du contenu qui
       défile dessous, sans quoi les deux se confondent sur un fond clair. */
    box-shadow: 0 -2px 12px -4px rgba(23, 35, 58, .22);
    padding: var(--e-3) var(--e-4);
    /* La barre système d'un iPhone mange le bas de l'écran : sans cette marge,
       le bouton se retrouve sous la barre de gestes et devient intouchable. */
    padding-bottom: calc(var(--e-3) + env(safe-area-inset-bottom, 0px));
    transform: translateY(110%);
    transition: transform .22s cubic-bezier(.4, 0, .2, 1);
}
.barre-action[data-visible="oui"] { transform: translateY(0); }

/* Hors mobile la barre n'a pas lieu d'être : les boutons de la page sont à
   portée de souris, et une barre fixe y volerait de la hauteur utile. */
@media (min-width: 48rem) { .barre-action { display: none; } }

.barre-action__inner {
    display: flex; gap: var(--e-3);
    max-width: var(--page); margin-inline: auto;
}
/* Deux boutons de rang égal se partagent la largeur ; un seul la prend toute.

   `min-width: 0` N'EST PAS DÉCORATIF. Un élément flexible refuse par défaut de
   descendre sous sa largeur de contenu minimale : « Demander une démonstration »
   imposait 145 px là où 138 px étaient disponibles, et le second bouton sortait
   de l'écran à 320 px. `flex: 1 1 0` ne suffit donc pas -- il faut lever aussi
   ce plancher, sans quoi la barre censée aider à convertir déborde sur le
   téléphone le plus répandu du parc visé. */
.barre-action .bouton { flex: 1 1 0; min-width: 0; text-align: center; padding: 0.8em 1em; }

/* La barre ne contient qu'un bouton (voir `site.js` §2) : `flex: 1 1 0` lui fait
   donc prendre toute la largeur, ce qui est la forme la plus facile à frapper. */

/* Le pied de page doit pouvoir être atteint : sans cette réserve, la barre
   recouvre définitivement les deux dernières lignes du document. */
body.a-barre-action { padding-bottom: 5.5rem; }


/* --- 14.3 Les panneaux dépliants -----------------------------------------
   `<details>` natif : il se déplie sans script, son contenu est dans le HTML
   source donc indexé, et le clavier vient du navigateur. `site.js` n'ajoute que
   le glissement. */
.questions { display: grid; gap: var(--e-3); margin-top: var(--e-12); }

.question {
    background: var(--papier);
    border: var(--filet);
    border-radius: var(--rayon);
}
/* Ouverte, la question s'appuie sur le filet de tampon : on voit d'un coup
   d'œil laquelle on a ouverte dans une liste de six. */
.question[open] { border-left: 3px solid var(--tampon); }

.question > summary {
    display: flex; align-items: baseline; gap: var(--e-4);
    justify-content: space-between;
    padding: var(--e-4) var(--e-6);
    cursor: pointer;
    /* Le marqueur natif -- triangle sur Chrome, flèche sur Safari -- n'a pas la
       même forme d'un navigateur à l'autre. Le chevron ci-dessous est dessiné en
       bordures, donc identique partout et sans image. */
    list-style: none;
    min-height: 2.75rem;
}
.question > summary::-webkit-details-marker { display: none; }
.question > summary:hover { background: var(--registre-pale); }
.question > summary:focus-visible { outline: 3px solid var(--tampon); outline-offset: -3px; }

.question__titre {
    font-family: var(--f-display); font-size: var(--t-md); font-weight: 600;
    line-height: 1.25; margin: 0; letter-spacing: -0.01em;
}

.question__chevron {
    flex: none; width: 0.6em; height: 0.6em;
    border-right: 2px solid var(--tampon);
    border-bottom: 2px solid var(--tampon);
    transform: rotate(45deg) translateY(-0.1em);
    transition: transform .2s ease;
}
.question[open] > summary .question__chevron { transform: rotate(-135deg) translateY(-0.15em); }

/* `overflow: hidden` n'est pas cosmétique : c'est lui qui permet au script
   d'animer la hauteur sans que le texte déborde pendant le trajet. */
.question__corps { overflow: hidden; }
.question__corps > * { padding-inline: var(--e-6); }
.question__corps > *:last-child { padding-bottom: var(--e-6); }
.question__corps p { color: var(--encre-70); max-width: var(--mesure); }
.question__corps p + p { margin-top: var(--e-3); }


/* --- 14.4 Le sommaire des pages longues ----------------------------------
   Il ORIENTE sans rien replier : les mentions légales et les CGV restent
   entières à l'écran, imprimables et trouvables au `Ctrl+F`. Un texte
   contractuel qu'il faut déplier pour lire est un texte qu'on pourra soutenir
   n'avoir pas lu. */
.sommaire {
    background: var(--registre-pale);
    border-left: 3px solid var(--encre);
    border-radius: 0 var(--rayon) var(--rayon) 0;
    padding: var(--e-4) var(--e-6);
    margin-bottom: var(--e-12);
}
.sommaire__titre {
    font-family: var(--f-chiffre); font-size: var(--t-xs);
    letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--encre-45); margin: 0 0 var(--e-2);
}
.sommaire ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.sommaire a { display: inline-block; padding-block: var(--e-2); font-size: var(--t-sm); }


/* --- 14.5 Le bouton « Copier » -------------------------------------------
   Il vit à côté de la référence, jamais à sa place : la référence reste lisible
   et sélectionnable si la copie échoue. */
.avec-copie { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-2) var(--e-3); }

/* Le bloc autonome sous la phrase de paiement. `:empty` est ce qui évite un
   trou dans la page quand `site.js` n'a pas tourné : le bloc est livré vide, et
   il ne prend de place qu'une fois rempli. */
div.avec-copie { margin-top: var(--e-4); }
div.avec-copie:empty { display: none; }

.copier {
    font: inherit; font-size: var(--t-sm); font-weight: 600;
    /* 44 px de cible tactile, comme tout ce qui se frappe sur ce site. */
    min-height: 2.75rem;
    padding: 0.5em 1em;
    color: var(--tampon);
    background: var(--papier);
    border: 1px solid var(--registre);
    border-radius: var(--rayon);
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.copier:hover { border-color: var(--tampon); }
.copier--fait { color: var(--preuve); border-color: var(--preuve); background: #f2f9f5; }
.copier--echec { color: #8a3a2c; border-color: #c07a68; background: #fdf3f0; }

/* Le retour est un texte, pas une couleur seule : une pastille verte ne dit rien
   à qui ne distingue pas le vert, et rien du tout à un lecteur d'écran. */
.copier__etat { font-size: var(--t-sm); color: var(--encre-70); }
.copier--echec ~ .copier__etat { color: #8a3a2c; }


/* --- 14.6 Les messages du formulaire ------------------------------------
   Ils s'affichent SOUS le champ concerné, jamais en tête de formulaire : un
   récapitulatif d'erreurs en haut d'écran oblige à faire l'aller-retour entre la
   liste et les champs, sur un téléphone où les deux ne tiennent pas ensemble. */
.champ__erreur {
    margin: 0;
    font-size: var(--t-sm);
    font-weight: 600;
    color: #8a3a2c;
    display: flex; gap: 0.45em;
}
/* `[hidden]` NE SUFFIT PAS QUAND UNE CLASSE POSE `display`.
   La règle du navigateur pour `[hidden]` est `display: none` à très faible
   spécificité : le `display: flex` ci-dessus la bat. Sans cette ligne, chaque
   champ valide affichait le triangle d'un message vide -- des marques d'erreur
   orphelines sous « Ville » et « Votre nom », sur un formulaire correctement
   rempli. C'est le piège classique de `hidden` face à une classe qui peint
   `display` ; il coûte une ligne et se paie en confiance perdue. */
.champ__erreur[hidden] { display: none; }
/* Le triangle est décoratif et le reste : le message porte déjà l'information,
   et `aria-invalid` porte l'état. */
.champ__erreur::before { content: "▲"; font-size: 0.7em; line-height: 1.9; flex: none; }

.champ input[aria-invalid="true"],
.champ select[aria-invalid="true"],
.champ textarea[aria-invalid="true"] { border-color: #a4503c; border-width: 2px; }

.formulaire button[disabled] { opacity: .6; cursor: progress; }


/* --- 15. Le calculateur d'impayés ------------------------------------------
   La page `/recuperer-les-impayes`. Elle n'a que deux besoins propres : un
   formulaire plus compact que les autres, et deux nombres qui se lisent de
   loin.

   LE FORMULAIRE EST PLUS ÉTROIT QUE `.formulaire` NE LE FAIT (34 rem) et passe
   sur trois colonnes dès qu'il y a la place. Ce n'est pas de l'esthétique : ces
   trois champs sont une seule question posée en trois morceaux, et les empiler
   sur trois lignes pleine largeur les fait lire comme trois étapes — un
   formulaire, c'est-à-dire ce que le visiteur est venu éviter. */
.calculateur { max-width: none; }
@media (min-width: 46rem) {
    .calculateur {
        grid-template-columns: repeat(3, 1fr);
        align-items: start;
        gap: var(--e-6) var(--e-8);
    }
    /* La rangée d'action reprend toute la largeur sous les trois champs. */
    .calculateur > .actions { grid-column: 1 / -1; }
}

/* Les nombres sont dans la police à chiffres, comme tous les montants du site :
   c'est elle qui rend un « 1 » et un « 7 » distincts d'un coup d'œil, et une
   colonne de francs alignée. */
.resultat {
    display: grid;
    gap: var(--e-6);
    margin-bottom: var(--e-8);
}
@media (min-width: 40rem) {
    .resultat { grid-template-columns: 1fr 1.4fr; gap: var(--e-12); align-items: end; }
}

.resultat__chiffre {
    font-family: var(--f-chiffre);
    font-size: var(--t-lg);
    font-weight: 600;
    line-height: 1.05;
    margin: 0 0 var(--e-2);
    /* `tabular-nums` fige la largeur des chiffres : sans lui, le montant
       « saute » latéralement d'une simulation à l'autre, ce qui se lit comme un
       défaut d'affichage sur la seule page du site qui annonce de l'argent. */
    font-variant-numeric: tabular-nums;
}

/* LE SECOND BLOC EST LE PLUS GROS, ET C'EST L'ARGUMENT.
   « 540 000 F qui dorment » vaut mieux que « 36 familles en retard » : le
   premier chiffre situe, le second frappe. Les mettre à la même taille les
   rendrait interchangeables. */
.resultat__bloc--fort .resultat__chiffre { font-size: var(--t-2xl); color: #fff; }

.resultat__libelle {
    margin: 0;
    font-size: var(--t-sm);
    color: #c3cad8;
    max-width: 24ch;
}
.resultat__libelle strong { color: var(--papier); font-weight: 600; }


/* --- 16. Le lecteur vidéo --------------------------------------------------
   Une façade — image plus bouton — qui ne devient une `<iframe>` qu'au clic
   (§7 de `site.js`). Voir le fragment `lecteurVideo` pour le pourquoi.

   `aspect-ratio` RÉSERVE LA PLACE AVANT TOUT CHARGEMENT, et le fait tenir après
   la substitution : sans lui, l'`<iframe>` qui remplace l'image au clic
   n'aurait aucune hauteur propre et la page sauterait au moment précis où le
   visiteur vient de cliquer. C'est le même métier que les `width`/`height`
   obligatoires des captures, appliqué à un élément qui n'existe pas encore. */
.video__facade,
.video__cadre {
    display: block;
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--rayon);
}
.video__facade img,
.video__cadre iframe {
    display: block;
    width: 100%; height: 100%;
    object-fit: cover;
    border: 0;
}

/* Le voile assombrit la capture juste assez pour que le bouton blanc s'en
   détache. Sans lui, un tableau de bord clair avale un libellé blanc — et le
   seul élément de la page dont dépend le clic devient invisible. */
.video__facade::after {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(23, 35, 58, .12), rgba(23, 35, 58, .46));
    transition: background-color .15s ease;
}

.video__bouton {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;                                /* Au-dessus du voile. */
    display: inline-flex;
    align-items: center;
    gap: var(--e-3);
    padding: var(--e-3) var(--e-6) var(--e-3) var(--e-4);
    border-radius: 999px;
    background: rgba(255, 255, 255, .94);
    color: var(--encre);
    font-weight: 600;
    font-size: var(--t-sm);
    line-height: 1.2;
    text-align: left;
    box-shadow: 0 6px 24px -8px rgba(23, 35, 58, .55);
    transition: background-color .15s ease, transform .15s ease;
}
.video__facade:hover .video__bouton,
.video__facade:focus-visible .video__bouton {
    background: #fff;
    transform: translate(-50%, -50%) scale(1.03);
}

/* SOUS 30 rem, LE LIBELLÉ TOMBE ET LE TRIANGLE RESTE. Une pastille portant
   « Voir la démonstration — 2 min 19 » occupe presque toute la largeur d'un
   écran de 360 px et recouvre la capture qu'elle est censée donner envie de
   regarder. La durée reste annoncée par la légende, juste dessous. */
@media (max-width: 29.999rem) {
    .video__mot { position: absolute; width: 1px; height: 1px;
                  overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
    .video__bouton { padding: var(--e-4); }
}

/* Le mouvement d'agrandissement se retire pour qui l'a demandé ; le changement
   de fond suffit à marquer le survol. */
@media (prefers-reduced-motion: reduce) {
    .video__facade:hover .video__bouton,
    .video__facade:focus-visible .video__bouton { transform: translate(-50%, -50%); }
}

/* La porte de secours du lecteur — voir §8 de `site.js`. Discrète : elle ne
   doit pas concurrencer la vidéo quand celle-ci s'affiche normalement, et rester
   trouvable du premier coup d'œil quand elle ne s'affiche pas. */
.video__secours { margin: var(--e-3) 0 0; font-size: var(--t-xs); color: var(--encre-45); }
