/* ============================================================
   Héritage Vivant, vitrine V1

   Une seule feuille pour les neuf pages. Écrite en mobile-first :
   les règles de base valent pour un téléphone, les `min-width`
   ajoutent ce que la place permet. La plupart des visiteurs
   arriveront par un lien partagé dans une conversation de famille,
   donc sur un téléphone : c'est cette largeur qui décide.

   Trois paliers seulement, choisis d'après le contenu et non
   d'après des noms d'appareils :
     34em (544px), les deux badges de boutique tiennent côte à côte
     48em (768px), les deux formules tiennent à deux colonnes
     64em (1024px), la démonstration passe téléphone à gauche,
                     repères à droite

   Le lecteur peut avoir 85 ans. Deux conséquences tenues partout :
   le corps de texte démarre à 18 px et non 16, et rien
   d'important ne repose sur la couleur seule.
   ============================================================ */

/* ---------- Polices, servies localement ---------- */
/*
   Recopiées de la vitrine actuelle avec leur raison : chargées depuis
   fonts.googleapis.com, chaque visiteur transmettait son adresse IP à Google
   avant d'avoir lu une ligne. Ce site ne fait AUCUNE requête vers un tiers, et
   c'est précisément ce qui lui permet de n'avoir ni cookie ni bandeau de
   consentement, une propriété à conserver, elle est un argument autant qu'une
   simplification.

   Fraunces et Inter sont VARIABLES : un fichier couvre les poids 400 à 700,
   d'où `font-weight: 400 700`. Six fichiers, 332 ko, deux familles, plus
   l'italique de Fraunces, chacune en latin et latin-ext. Le second couvre les
   caractères que le premier n'a pas.

   Licence SIL Open Font License 1.1 pour les deux : redistribution avec le
   site autorisée.
*/
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/fraunces-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/fraunces-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/fraunces-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/fraunces-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- Palette de marque ---------- */
/* Rapports de contraste déjà mesurés, repris tels quels. Toute nuance ajoutée
   hors de cette liste doit être CALCULÉE, pas estimée, et son rapport écrit
   à côté d'elle. */
:root {
  /* LA PALETTE DE MARQUE, telle qu'elle a été fournie. Ne pas la changer.

     Une refonte du 20 août 2026 lui a substitué une terre cuite, au motif que la
     page paraissait grise. C'était une erreur de diagnostic, et elle est
     annulée : la page ne paraissait pas grise à cause de ces couleurs, mais
     parce que le lie-de-vin ne servait qu'en filets de deux pixels. Ce qui a
     changé, et qui reste changé, c'est l'EMPLOI de la couleur, voir la section
     suivante, pas la couleur.

     Le calcul l'a confirmé au passage : en aplat plein, --voix porte du blanc à
     8,89:1, là où la terre cuite plafonnait à 6,03:1. La palette de marque est
     plus solide que celle qui prétendait la remplacer.

     Tous les rapports ci-dessous sont CALCULÉS, jamais estimés. */

  --papier:   #FBF9F6; /* fond principal, blanc chaud */
  --papier-2: #EAE2D6; /* bande alternée : 1,22:1 avec --papier */
  --encre:    #1B2A2E; /* texte principal ET unique surface sombre du site
                          14,10:1 sur --papier · 11,54:1 sur --papier-2 */
  --encre-doux: #4C5A5E; /* texte secondaire : 6,82:1 sur --papier, 5,58:1 sur --papier-2 */
  --voix:     #7C2F4A; /* accent : 8,46:1 sur --papier, 7,56:1 sur --papier-2.
                          En APLAT PLEIN : blanc dessus 8,89:1, --papier dessus 8,46:1. */

  /* LA SURFACE SOMBRE, et elle ne s'inverse JAMAIS.

     --encre servait à deux choses à la fois : la couleur du TEXTE et le fond
     de la bande d'emphase, du menu et du téléphone dessiné. En mode sombre,
     inverser --encre retournait donc aussi ces surfaces : le téléphone
     devenait blanc et la bande « L'application s'installe ici » devenait un
     grand aplat blanc au bas d'une page sombre. Personne ne veut ça.

     Les deux rôles sont séparés : --encre reste le texte, --surface-sombre est
     le fond. En mode sombre elle FONCE au lieu de s'inverser : #0D181D, plus
     profond que la page, et tout ce qui vit dessus garde ses couleurs
     claires. */
  --surface-sombre: #1B2A2E;

  /* La famille « sur la surface sombre ». Elle ne s'inverse pas non plus,
     puisque la surface qu'elle habille reste sombre dans les deux thèmes. */
  --papier-sur-encre: #FBF9F6; /* 14,10:1 sur --surface-sombre */
  --papier-dim:       #DAD3C8; /*  9,97:1 sur --encre */
  --voix-sur-encre:   #F0B9C7; /*  8,80:1 sur --encre, le pendant clair de --voix.
                                   Les deux ne servent JAMAIS sur le même fond. */

  /* Deux jetons AJOUTÉS, et seulement deux, parce que le nouvel emploi de la
     couleur en a besoin. Ils sont dérivés de --voix, ils n'introduisent pas de
     teinte nouvelle dans la marque.

     --voile : l'aplat très clair du lie-de-vin, pour une carte qui doit se
     détacher sans devenir une bande de plus. --voix-fonce : le survol d'un
     bouton plein. Le survol FONCE au lieu de changer de teinte, un bouton qui
     change de couleur au passage de la souris a l'air de changer de fonction. */
  --voile:      #F3E0E6; /* 1,20:1 sur --papier, encre 11,72:1, encre-doux 5,67:1,
                            voix 7,03:1 */
  --voix-fonce: #65253C; /* blanc dessus 11,15:1, --papier dessus 10,61:1 */

  /* Trois jetons ajoutés pour le mode sombre. Ils existaient déjà en valeurs
     écrites en dur dans le pied et dans l'en-tête ; les nommer était le
     préalable à l'inversion, sinon ces deux surfaces restaient en clair quand
     tout le reste basculait. */
  --voix-dim:    #E9CDD6;                   /* texte secondaire SUR une surface --voix
                                               6,00:1 sur --voix */
  --voix-filet:  rgba(251, 249, 246, 0.26); /* filet sur une surface --voix */
  --filet-sur-encre: rgba(218, 211, 200, 0.26); /* filet ou voile posé SUR la
                                surface d'emphase. En mode sombre cette surface
                                devient claire : le filet doit alors foncer, et
                                non s'éclaircir. Écrit en dur, il disparaissait. */
  --entete-voile: rgba(251, 249, 246, 0.5); /* la barre translucide au défilement,
                                               voir « L'en-tête qui se déleste » */

  --filet:      #DED6C8; /* 1,37:1 sur --papier, séparation légère */
  --filet-2:    #C4B9A6; /* 1,84:1 sur --papier, séparation structurante,
                            et le trait des encadrés */
  --bord-champ: #8A8073; /* 3,69:1 sur --papier, un champ dont on ne voit pas la limite
                            ne se remplit pas */
  --erreur:     #8A2C1B; /* 8,13:1 sur --papier */
  --succes:     #2C5B45; /* 7,43:1 sur --papier */
}

/* ---------- Mode sombre ----------

   ON NE RENOMME RIEN. Les jetons gardent leur SENS, --papier est le fond de
   page, --encre est le texte et la surface d'emphase, --voix est l'accent, et
   seules leurs VALEURS s'inversent. C'est ce qui fait que les mille lignes qui
   suivent n'ont pas une règle de plus à écrire : elles lisent déjà des jetons.

   Conséquence à connaître, et elle est voulue : la bande d'emphase
   `.section-encre` devient CLAIRE en mode sombre, et le pied passe au rose.
   L'emphase est toujours l'inverse de la page, c'est ce qui la rend
   emphatique. Une bande sombre sur une page sombre ne dirait plus rien.

   CE MODE EST OPTIONNEL, ET IL LE RESTE. Le brief du projet dit que le corps du
   texte reste sur fond clair, parce qu'un fond sombre fatigue un œil âgé. Un
   mode sombre contredit cette règle par définition, on ne la lève donc que
   pour quelqu'un qui l'a explicitement demandé. Le réglage du système n'est
   volontairement PAS suivi : un senior dont le téléphone est en sombre
   recevrait sinon un site sombre sans l'avoir choisi. Pour suivre le système,
   il suffirait d'ajouter une requête `prefers-color-scheme` ici, mais c'est
   une décision de produit, pas de style.

   Tous les rapports ci-dessous sont calculés. Le seul en dessous de 3:1 est
   --filet-2, qui est un filet décoratif et l'est déjà en clair (1,84:1). */
[data-theme="sombre"] {
  --papier:   #14252B; /* fond de page */
  --papier-2: #1C3138; /* bande alternée, texte principal 11,84:1 */
  --voile:    #33202A; /* surface teintée d'accent, texte principal 13,25:1 */

  --encre:    #F2EFE9; /* texte principal ET surface d'emphase, devenue claire
                          13,77:1 sur --papier · 11,84:1 sur --papier-2 */
  --encre-doux: #BFC5C4; /* 9,03:1 sur --papier, 7,76:1 sur --papier-2, 8,69:1 sur --voile */

  --voix:       #F0B9C7; /* accent : 9,38:1 sur --papier, 8,07:1 sur --papier-2.
                            En aplat plein : --papier dessus 9,38:1. */
  --voix-fonce: #F8D6DE; /* le survol ÉCLAIRCIT en sombre au lieu de foncer,
                            --papier dessus 11,78:1 */

  /* La surface sombre FONCE au lieu de s'inverser : #0D181D contre #14252B
     pour la page et #1C3138 pour la bande alternée. Les trois se distinguent
     (1,14:1 et 1,33:1), comme --papier et --papier-2 se distinguent en clair
     à 1,15:1. La bande d'emphase reste donc une bande, et le téléphone reste
     noir. */
  --surface-sombre:   #0D181D;
  --papier-sur-encre: #F2EFE9; /* 15,70:1 sur --surface-sombre */
  --papier-dim:       #BFC5C4; /* 10,29:1 sur --surface-sombre */
  --voix-sur-encre:   #F0B9C7; /* 10,70:1 sur --surface-sombre */

  --voix-dim:     #5E2338;               /* 7,03:1 sur --voix */
  --voix-filet:   rgba(20, 37, 43, 0.24);
  --filet-sur-encre: rgba(242, 239, 233, 0.22); /* clair : la surface qu'il
                                habille reste sombre dans les deux thèmes */
  --entete-voile: rgba(20, 37, 43, 0.5); /* la barre translucide, en sombre */

  --filet:      #26383F;
  --filet-2:    #35494F; /* 1,67:1 sur --papier, décoratif, comme en clair */
  --bord-champ: #8C9A9E; /* 5,44:1 sur --papier, meilleur qu'en clair (3,69:1) */
  --erreur:     #FFA694; /* 8,38:1 sur --papier */
  --succes:     #8BD9B7; /* 9,56:1 sur --papier */

  /* Indique au navigateur de dessiner ses propres surfaces en sombre :
     barres de défilement, champs de formulaire natifs, menus de sélection. */
  color-scheme: dark;
}

/* ---------- Emploi des couleurs ----------

   RÈGLE INVERSÉE LE 20 AOÛT 2026, et il faut savoir pourquoi avant d'y toucher.

   L'ancienne règle réservait l'accent à « ce qui vient de la bouche de
   quelqu'un », citations, liens, marqueurs, et mettait les boutons à l'encre.
   Elle était défendable et elle a produit une page grise : sur un écran de
   1400 px, l'accent n'apparaissait que par filets de deux pixels. Le site
   entier tenait en deux valeurs de gris sur du blanc cassé, et se lisait comme
   un document plutôt que comme un produit.

   La règle est maintenant celle-ci :

   --voix EST LA COULEUR PORTEUSE. Elle porte ce qu'on veut qu'on regarde et
   ce sur quoi on veut qu'on appuie : le bouton plein, la formule mise en avant,
   les liens de texte, le filet des citations, l'anneau de focus, le repère
   actif. Elle a le droit d'être un APLAT, pas seulement un trait.

   --encre garde les surfaces sombres et le texte. Elle ne sert plus de couleur
   de bouton : deux valeurs sombres qui se disputent l'attention en produisent
   zéro.

   Ce qui n'a pas changé : --voix et --voix-sur-encre ne se rencontrent jamais
   sur le même fond. L'une est faite pour le papier, l'autre pour l'encre. */

/* ---------- Jetons de mise en page ---------- */
:root {
  --font-titre: "Fraunces", Georgia, serif;
  --font-texte: "Inter", system-ui, sans-serif;

  /* Typographie fluide, interpolée entre 375 px et 1280 px de large, puis
     figée aux deux bouts par clamp().

     Le corps démarre à 18 px et non à 16. C'est la seule décision de cette
     feuille prise entièrement pour l'âge du lecteur : deux points de plus
     coûtent quelques lignes de mise en page, et évitent le geste de zoom qui,
     lui, dérange tout le reste.

     LES TITRES, EUX, ONT ÉTÉ DESSERRÉS SUR TÉLÉPHONE — 21 août 2026. Mesuré
     à 375 px avant réglage : la page d'accueil faisait 12 737 px de haut, soit
     quinze écrans et demi, et le h1 tenait cinq lignes à 34 px. L'effet
     ressenti était celui d'une page zoomée, alors que rien n'était zoomé : la
     graisse était juste dessinée pour un grand écran et appliquée à un petit.

     Ce qui a baissé et ce qui n'a pas bougé, car la distinction est le fond de
     ce réglage : les PLANCHERS des titres et des espacements ont baissé, le
     corps de texte à 18 px et son interligne n'ont pas été touchés. Réduire le
     texte courant aurait rendu la page compacte en défaisant la seule décision
     prise pour l'âge du lecteur — c'est-à-dire en rétablissant exactement le
     geste de zoom qu'elle évite. Les valeurs hautes sont inchangées : sur
     grand écran, la page est celle qui a été validée.

     Les termes du milieu sont RECALCULÉS et non estimés : pente
     (haut − bas) / (1280 − 375), puis ordonnée à l'origine bas − pente × 375.
     Une pente laissée telle quelle en changeant le plancher déplace la courbe
     entière et change aussi le grand écran, sans que rien ne le signale. */
  --t-texte:   clamp(1.125rem, 1.0991rem + 0.1105vw, 1.1875rem);
  --t-chapeau: clamp(1.1875rem, 1.1098rem + 0.3315vw, 1.375rem);
  --t-h1:      clamp(1.875rem, 1.0981rem + 3.3149vw, 3.75rem);
  --t-h2:      clamp(1.4375rem, 0.9973rem + 1.8784vw, 2.5rem);
  --t-h3:      clamp(1.1875rem, 1.0839rem + 0.442vw, 1.4375rem);
  --t-prix:    clamp(2.125rem, 1.6588rem + 1.989vw, 3.25rem);
  --t-petit:   clamp(0.8125rem, 0.7866rem + 0.1105vw, 0.875rem);

  /* Espacements fluides, sans palier. Les valeurs hautes sont généreuses à
     dessein : laisser de l'air est ce qui distingue le plus sûrement une page
     composée d'une page remplie. Les basses restent serrées, la place étant
     rare sur un téléphone. */
  --espace-section: clamp(2.75rem, 0.9889rem + 7.5138vw, 7rem);
  --espace-bloc:    clamp(1.5rem, 0.7749rem + 3.0939vw, 3.25rem);
  --espace-grille:  clamp(1.25rem, 0.9392rem + 1.326vw, 2rem);
  --espace-carte:   clamp(1.25rem, 0.8356rem + 1.768vw, 2.25rem);
  --gouttiere:      clamp(1.25rem, 1.0428rem + 0.884vw, 1.75rem);

  --largeur: 71.25rem; /* 1140 px */
  --tap: 44px;         /* plancher de cible tactile, jamais franchi vers le bas */

  /* Hauteur de l'en-tête AU REPOS. Un seul chiffre pour deux usages qui doivent
     coïncider au pixel : la hauteur minimale de la barre, et le `padding-top`
     de <body> qui lui rend la place puisqu'elle est sortie du flux. Les écrire
     séparément, c'est les voir diverger au premier réglage.

     En `rem` et non en pixels : quand le texte est agrandi, la barre grandit,
     la réserve doit grandir avec elle. La valeur haute s'applique à partir de
     62em, là où la devise s'affiche sous le nom et ajoute une ligne. */
  --entete-h: 4.5rem;

  /* Arrondis discrets : la marque est du papier et de l'encre, pas une
     interface aux angles ronds. Seuls le téléphone dessiné et les cartes en
     prennent davantage, parce qu'ils imitent des objets qui en ont. */
  --arrondi: 4px;
  --arrondi-carte: 10px;

  --sortie: cubic-bezier(0.22, 1, 0.36, 1);
  --doux:   cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---------- Base ---------- */
* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Décale les ancres pour qu'elles ne passent pas sous l'en-tête collant.
     Sert aussi au clavier : sans cette réserve, un élément atteint par
     tabulation peut recevoir le focus caché derrière l'en-tête. */
  scroll-padding-top: 6rem;
  /* La place de la barre de défilement est réservée en permanence. À
     l'ouverture du menu, le script bloque le défilement de la page ; sans
     cette réserve, la barre disparaîtrait et toute la mise en page sauterait
     de quelques pixels sur le côté au moment précis où l'on regarde le menu. */
  scrollbar-gutter: stable;
  /* La barre de défilement fait partie du dessin. Laissée par défaut, elle
     arrive en gris système sur une page qui n'en a aucun. */
  scrollbar-color: var(--filet-2) transparent;
}

/* ---------- Les surfaces que le navigateur dessine — 27 août 2026 ----------

   Sélection de texte et curseur de saisie. Personne ne les dessine, et c'est
   exactement pour ça qu'elles trahissent : par défaut, sélectionner une phrase
   de ce site donnait le BLEU SYSTÈME au milieu d'une page lie-de-vin, et le
   curseur clignotant des formulaires était noir.

   Ce sont quatre lignes, et c'est le signal le moins cher qu'une page a été
   composée plutôt qu'assemblée. Le reste de cette famille était déjà traité
   ailleurs dans la feuille : `scrollbar-gutter` juste au-dessus,
   `text-underline-offset` sur les liens, les chiffres à chasse fixe sur les
   prix.

   Les deux valeurs sont des JETONS de marque, jamais des couleurs en dur :
   elles suivent donc le mode sombre sans une règle de plus. Le voile
   lie-de-vin porte le texte principal à 11,72:1, calculé, donc une phrase
   sélectionnée reste plus lisible que la même sur fond blanc. */
::selection {
  background: var(--voile);
  color: var(--encre);
}
/* Sur la bande d'emphase et le pied, la sélection s'inverse avec eux : le
   voile clair y serait invisible.

   LE TEXTE EST `--surface-sombre` ET NON `--encre`, et c'est le piège de cette
   règle. `--voix-sur-encre` ne s'inverse jamais, par construction : elle
   habille une surface qui reste sombre dans les deux thèmes. Mais `--encre`
   s'inverse, et devient donc CLAIRE en mode sombre — j'aurais posé du texte
   presque blanc sur du rose pâle. `--surface-sombre` reste foncée des deux
   côtés, c'est le seul jeton qui tienne ici. */
.section-encre ::selection,
.pied ::selection {
  background: var(--voix-sur-encre);
  color: var(--surface-sombre);
}
input, textarea { caret-color: var(--voix); }

/* Le seul endroit où le mouvement se coupe en bloc. Tout ce qui bouge ailleurs
   est de toute façon enfermé dans `no-preference` : cette règle-ci est la
   ceinture, l'autre est les bretelles. */
@media (prefers-reduced-motion: reduce) {
  html, .points, .formules { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

body {
  margin: 0;
  /* Rend à la page la place de l'en-tête, qui est sorti du flux. Même variable
     que sa hauteur au repos : les deux ne peuvent pas diverger.

     Le pixel ajouté est la bordure basse de la barre, qui compte dans sa
     hauteur mais pas dans `--entete-h`. Sans lui, une ligne de texte passait
     sous la bordure, un pixel, invisible sur le hero qui a de la marge, mais
     pas sur une page légale dont le premier titre commence plus haut. */
  padding-top: calc(var(--entete-h) + 1px);
  font-family: var(--font-texte);
  font-size: var(--t-texte);
  line-height: 1.7;
  color: var(--encre);
  background: var(--papier);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Filet de sécurité contre le défilement latéral. `clip` et non `hidden` :
     `hidden` ferait de `body` un conteneur de défilement, et l'en-tête collant
     cesserait de coller. */
  overflow-x: clip;
}

/* Les titres resserrent leur interlettrage à mesure qu'ils grossissent : à
   l'espacement par défaut, une grande serif paraît lâche et mal composée. Le
   serrage est gradué par niveau, le plus discret des réglages, et le plus sûr
   signal d'une page composée avec soin. */
h1, h2, h3 {
  font-weight: 600;
  line-height: 1.14;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

/* Fraunces ne sert plus qu'aux DEUX plus grands niveaux, et aux citations.
   Auparavant elle portait aussi les h3, les sous-titres de bloc et les titres
   de carte : une serif à empattements sur chaque ligne de titre d'une page,
   c'est ce qui donnait l'air d'une revue littéraire plutôt que d'un produit.
   Réservée aux grands moments, elle redevient un geste ; posée partout, elle
   n'était plus qu'une texture. */
h1, h2 { font-family: var(--font-titre); }
h1 { font-size: var(--t-h1); letter-spacing: -0.026em; }
h2 { font-size: var(--t-h2); letter-spacing: -0.018em; }
h3 {
  font-family: var(--font-texte);
  font-size: var(--t-h3); font-weight: 650;
  letter-spacing: -0.008em; line-height: 1.35;
}

/* L'italique de Fraunces porte des formes calligraphiques que le romain n'a
   pas, c'est de là que vient l'ornement du logo, où seuls le H et le V sont
   en italique. La page reprend ce geste : UN mot par grand titre, celui qui
   porte l'idée, jamais deux. C'est la signature typographique du site, et elle
   ne coûte pas une famille de caractères de plus. */
h1 em, h2 em { font-style: italic; font-weight: 500; }

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
a { color: inherit; }
img, svg { max-width: 100%; }

/* Un lien de texte se signale par la couleur de la parole ET par son
   soulignement : la couleur seule ne porte jamais l'information. */
.lien {
  color: var(--voix);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}
.lien:hover { text-decoration-thickness: 2px; }
.section-encre .lien { color: var(--voix-sur-encre); }

/* Une adresse électronique est un mot de vingt-cinq caractères sans aucune
   coupure possible : elle impose sa largeur au bloc qui la porte, et à travers
   lui à la page. `anywhere`, et non `break-word`, qui ne réduit pas la largeur
   minimale, la laisse se couper. À poser partout où l'adresse est écrite en
   toutes lettres. */
.courriel { overflow-wrap: anywhere; }

/* Un lien qui n'est pas une navigation : « Changer d'adresse », doit être un
   `button` : il agit sur la page, il ne mène nulle part. Il en garde
   l'apparence, et récupère une cible tactile décente, qu'un simple mot souligné
   au milieu d'un paragraphe n'aurait pas. */
button.lien {
  display: inline-flex; align-items: center;
  min-height: var(--tap);
  background: none; border: 0; padding: 0;
  font: inherit; cursor: pointer;
  text-decoration: underline;
}

/* Un lien SEUL dans son paragraphe n'est pas un lien de phrase : c'est un
   bouton déguisé, et il doit se viser comme tel. La règle WCAG sur la taille
   des cibles dispense les liens noyés dans un texte, pas ceux-là.

   La hauteur vient d'un `padding`, PAS d'un `inline-flex` : le texte d'un
   `inline-flex` ne se coupe pas en fin de ligne, et un libellé un peu long
   élargissait alors tout son conteneur au lieu de passer à la ligne. Mesuré
   sur le pied de page à 200 % d'agrandissement. */
p > .lien:only-child {
  display: inline-block;
  padding-block: calc((var(--tap) - 1.7em) / 2);
}

/* ---------- Primitives de mise en page ---------- */
.wrap {
  max-width: var(--largeur);
  margin-inline: auto;
  padding-inline: var(--gouttiere);
}
/* Longueur de ligne plafonnée à environ 68 caractères au corps de ce site.
   Au-delà, l'œil retrouve mal le début de la ligne suivante, d'autant plus
   vite qu'il est âgé. Ce plafond n'est pas négociable.

   Ce qui l'était, et qui a été corrigé le 20 août : où la colonne se POSE.
   Alignée à gauche dans un conteneur de 1140 px, elle laissait la moitié droite
   de l'écran entièrement vide sur chaque section de texte. La page se lisait
   comme un document Word, c'est le défaut principal qu'on nous a signalé.

   La règle tient en une phrase : une colonne SEULE se centre, une colonne
   ACCOMPAGNÉE reste à gauche parce qu'un vis-à-vis occupe la droite. */
.colonne { max-width: 40rem; }
.colonne-centre {
  margin-inline: auto;
  text-align: center;
}
/* Le filet d'une colonne centrée se centre aussi, sinon il pend à gauche sous
   un titre centré. */
.colonne-centre .filet { margin-inline: auto; }
.colonne-centre .bloc-action,
.colonne-centre .badges { justify-content: center; }

.section { padding-block: var(--espace-section); }

/* La bande alternée est sur --voile, PAS sur --papier-2. Le crème a été écarté
   le 20 août : sur trois sections d'affilée il tirait la page vers le beige et
   ne se lisait plus comme un choix, seulement comme un fond fatigué.

   --voile est le même lie-de-vin que le reste du site, dilué. La page gagne
   ainsi une teinte de plus SANS gagner une couleur de plus, et l'alternance
   devient un rythme de marque au lieu d'un dégradé de papier. --papier-2 reste
   dans la palette : il sert encore aux surfaces internes, cartes et encadrés,
   là où une teinte colorée entrerait en concurrence avec son contenu. */
.section-bande { background: var(--voile); }

/* Texte d'un côté, pièce à conviction de l'autre, fiche de souvenir ou
   photographie. Une seule primitive pour les trois sections qui en ont besoin :
   trois grilles écrites séparément auraient fini par diverger de quelques
   pixels, et c'est ce genre d'écart qui fait qu'une page paraît assemblée
   plutôt que composée.

   En dessous de 64em, tout retombe en une colonne : sur un téléphone, deux
   colonnes de 160 px ne servent personne. */
.duo { display: grid; gap: var(--espace-bloc); align-items: center; }
.duo .colonne { max-width: none; }
@media (min-width: 64em) {
  .duo { grid-template-columns: 1fr 1fr; gap: var(--espace-section); }
  .duo-texte-large { grid-template-columns: 1.15fr 0.85fr; }
  /* La photo de la bande sombre passe à droite et déborde vers le bord :
     c'est ce qui la fait lire comme un fond, et non comme une vignette. */
  .duo-bande { grid-template-columns: 1fr 1fr; align-items: stretch; }
}

/* L'UNIQUE surface sombre du site, et une seule par page. Jamais sous du texte
   long : un fond sombre fatigue un œil âgé, et c'est la raison pour laquelle
   la section qui la porte tient en quelques phrases. */
.section-encre {
  background: var(--surface-sombre);
  color: var(--papier-sur-encre);
}
.section-encre h2,
.section-encre h3 { color: var(--papier-sur-encre); }

/* Filet court aligné sur la colonne de texte, plutôt qu'un trait qui traverse
   l'écran : il ponctue la lecture sans découper la page en tranches. */
.filet {
  border: 0;
  border-top: 2px solid var(--filet-2);
  width: 3.5rem;
  margin: 0 0 var(--espace-bloc);
}
.section-encre .filet { border-top-color: var(--voix-sur-encre); }

/* ---------- Accessibilité ---------- */
.saut {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--surface-sombre); color: var(--papier-sur-encre);
  padding: 0.75em 1.25em; border-radius: 0 0 var(--arrondi) 0;
}
.saut:focus { left: 0; top: 0; }

/* Un seul anneau de focus pour tout le site, épais et décalé : il doit se voir
   sans qu'on le cherche. Sur l'encre il passe au rose, les deux faces du même
   jeton, jamais sur le même fond. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--voix);
  outline-offset: 3px;
  border-radius: var(--arrondi);
}
.section-encre :where(a, button, input):focus-visible,
.menu :where(a, button):focus-visible {
  outline-color: var(--voix-sur-encre);
}

/* Réservé aux lecteurs d'écran : les libellés que le dessin rend évidents à
   l'œil mais qui manqueraient à l'oreille. */
.lecteur-seul {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- En-tête ---------- */
/* L'EN-TÊTE QUI SE DÉLESTE AU DÉFILEMENT

   Trois étages, posés par le script en `data-defilement` :

     0. En haut de page : le nom en grand, la devise dessous, fond plein.
     1. Après 40 px : la devise se replie et disparaît.
     2. Après 130 px : le nom se replie à son tour. Ne restent que « Menu » et
         « Télécharger », sur une barre translucide et floutée sous laquelle le
         contenu défile en transparence.

   Ce que Famileo fait vraiment, mesuré le 20 août : RIEN. Leur barre ne change
   jamais : 60 px, blanc à 90 %, `transition: all 0s`, logo à l'opacité 1, du
   premier au dernier pixel. Leur slogan est du contenu de page qui défile et
   sort, pas un effet ; leur logo paraît s'effacer parce qu'il est bleu pâle vu
   à travers 10 % de blanc avec une photo qui passe dessous. On construit donc
   l'effet qu'on croit voir chez eux, pas celui qu'ils ont.

   LA RÈGLE QUI GOUVERNE TOUT CECI : l'état au repos est l'état VISIBLE. Le nom
   et la devise sont affichés par défaut, et le défilement les retire. Script
   mort, JavaScript coupé, `prefers-reduced-motion` actif, attribut absent :
   l'en-tête reste complet. Aucune de ces pannes ne peut cacher le nom du site,
   c'est l'inverse de la façon habituelle d'écrire ce genre d'effet, où l'état
   par défaut est le vide. */
/* `fixed` ET NON `sticky`, et c'est la conséquence directe du repli.

   Un en-tête `sticky` participe au flux : il occupe sa hauteur en haut du
   document. Le rétrécir de 93 à 58 px remontait donc TOUT le contenu de 35 px,
   au moment précis où le visiteur lisait. Mesuré avant correction : 20 px de
   saut à l'étage 1, 35 px à l'étage 2. Un en-tête qui bouge est acceptable ; une
   page qui saute sous les yeux ne l'est pas, et le lecteur peut avoir 85 ans.

   Sorti du flux, il ne déplace plus rien. La place qu'il occupait est rendue par
   `padding-top` sur <body>, et les deux viennent de la MÊME variable, c'est ce
   qui garantit qu'elles ne divergent jamais. Toutes deux sont en `rem`, donc
   elles grandissent ensemble quand le texte est agrandi. */
.entete {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  background: var(--papier);
  border-bottom: 1px solid transparent;
  transition: background-color 0.3s var(--doux), border-color 0.3s var(--doux);
}

/* Étage 2 : la barre devient translucide et floute ce qui passe dessous.

   Le fond est --papier à 50 %, et ce chiffre est un POINT LIMITE calculé, pas
   un réglage à l'œil. Ne pas le baisser sans relire ce qui suit.

   Ce qu'on veut : deviner les lettres qui défilent sous la barre. Vu à travers
   un voile de --papier à 50 %, le texte du dessous se perçoit à 3,02:1 sur son
   fond, franchement discernable, tout en restant manifestement voilé. À 68 %
   il tombait à 1,93:1, soit à peine devinable ; à 38 % il remonte à 4,25:1 et
   la barre ne voile plus rien du tout.

   Ce qui empêche de descendre plus bas n'est PAS la lisibilité de la barre
   elle-même : à l'étage 2, son seul texte est celui des deux pilules, et
   celles-ci sont opaques (voir la règle plus bas). Leur texte repose sur
   --papier plein : 14,10:1 pour « Menu », 8,46:1 pour « Télécharger », quelle
   que soit la transparence du fond.

   C'est une prudence de STRUCTURE. Si quelqu'un ajoute un jour du texte
   directement sur la barre, il faut qu'il reste lisible : à 50 %, l'encre sur la
   composition donne 4,67:1, juste au-dessus du seuil. À 48 %, 4,40:1, et le
   défaut serait silencieux, puisque rien à l'écran ne le signalerait. 50 % est
   donc la valeur la plus transparente qui laisse la barre habitable.

   Le flou est un CONFORT, jamais une condition : les navigateurs qui ignorent
   `backdrop-filter` obtiennent une barre simplement translucide, qui reste
   parfaitement lisible. */
/* PAS DE `backdrop-filter`, et c'est une décision mesurée.

   La barre en portait un, `blur(14px)`, pour l'effet de verre dépoli. Retiré
   le 20 août après constatation : avec le filtre, le moteur de rendu de Chrome
   se bloquait plus de trente secondes à chaque capture de la page défilée ;
   sans lui, la capture est instantanée. Reproduit trois fois, puis vérifié en
   coupant le filtre seul, tout le reste inchangé.

   La capture d'écran est un cas extrême et non ce que fait un visiteur, donc ce
   n'est pas la preuve d'une gêne réelle. Mais `backdrop-filter` sur un élément
   FIXE oblige le navigateur à reprendre l'arrière-plan de tout l'écran à chaque
   image de défilement, et notre public arrive sur la 4G d'un téléphone qui a
   souvent cinq ans. Le même raisonnement a déjà écarté un moteur 3D de la
   démonstration : on ne paie pas un coût par image pour un ornement.

   Et le flou n'était pas nécessaire à ce qui a été demandé, voir le contenu
   passer sous la barre. La transparence seule le fait. Pour le récupérer, il
   suffit d'une ligne ici ; ne le faire qu'après un essai sur un vrai téléphone. */
.entete[data-defilement="2"] {
  background: var(--entete-voile);
  /* La bordure basse reste OPAQUE, et c'est elle qui fait que la barre existe
     encore à 50 %. Sans ce trait, un fond à demi transparent sans contour ne se
     lit plus comme une barre mais comme une zone floue en haut de l'écran. */
  border-bottom-color: var(--filet);
}

/* Les deux commandes deviennent OPAQUES quand la barre devient transparente.
   C'est ce qui libère le fond : leur texte repose sur --papier plein et non sur
   la composition, donc l'alpha de la barre ne peut plus rendre quoi que ce soit
   illisible. Elles se lisent alors comme deux pastilles posées sur du verre.

   Au repos, ce même --papier est invisible : la barre est déjà --papier plein.
   Aucune règle à ajouter pour les étages 0 et 1. */
.entete[data-defilement="2"] .menu-bouton,
.entete[data-defilement="2"] .entete-action {
  background: var(--papier);
}
/* La barre se resserre en deux temps : 96, 72, puis 56 px. C'est gratuit
   maintenant qu'elle est sortie du flux : seule la hauteur AU REPOS doit
   correspondre à la réserve de <body>, puisque c'est la seule qu'on voit quand
   on est en haut. Les deux autres ne déplacent rien. */
.entete[data-defilement="1"] .entete-rang { min-height: 4.5rem; }
.entete[data-defilement="2"] .entete-rang { min-height: 3.5rem; }
/* L'en-tête est le SEUL endroit du site qui ignore la largeur plafonnée.

   Partout ailleurs, `.wrap` plafonne à 1140 px et centre : c'est ce qui tient
   la longueur de ligne et le rythme des sections. Mais un en-tête n'est pas du
   contenu, c'est un cadre. Plafonné, il laissait plus de trois cents pixels de
   vide de chaque côté sur un grand écran, et les deux commandes, les trois
   tirets, le bouton de téléchargement, flottaient au milieu au lieu de tenir
   les coins.

   Le `padding-inline` de `.wrap` est conservé : les commandes vont aux bords,
   elles ne les touchent pas. Un bouton collé au bord de l'écran est aussi
   difficile à viser qu'un bouton trop petit. */
.entete .wrap { max-width: none; }

.entete-rang {
  display: flex; align-items: center; gap: 0.75rem;
  /* Généreux au repos, resserré à l'étage 2. La barre respire là où on la
     regarde, et s'efface là où on lit. */
  min-height: var(--entete-h);
  padding-block: 0.5rem;
  transition: min-height 0.28s var(--doux);
  /* L'en-tête se replie sur deux lignes plutôt que de déborder. Cas réel,
     mesuré : à 200 % d'agrandissement du texte sur un écran de 640 px, le nom
     du site et le bouton ne tiennent plus côte à côte. Sans ce repli, c'est
     toute la page qui prend une barre de défilement horizontale. */
  flex-wrap: wrap;
}

/* TROIS ZONES : le menu à gauche, le nom AU CENTRE, le téléchargement à droite.

   La grille `1fr auto 1fr` centre le nom par rapport à l'ÉCRAN, et non par
   rapport à la place qui reste. C'est toute la différence avec un `margin-inline:
   auto` en flex : là, le nom se serait décalé dès que le bouton de gauche ou de
   droite change de largeur, ce qui arrive à chaque traduction et à chaque
   agrandissement du texte. Les deux colonnes `1fr` étant toujours égales, le
   centre reste le centre quoi qu'elles contiennent.

   `minmax(0, 1fr)` et non `1fr` : sans le zéro, une colonne de grille refuse de
   descendre sous la taille de son contenu et pousse la ligne hors de l'écran au
   lieu de laisser le nom passer à la ligne.

   Le seuil est 34em, le MÊME que celui qui fait apparaître « Télécharger » :
   au-dessous il n'y a que deux éléments, et la mise en page en flex, testée à
   200 % d'agrandissement, reprend la main. Comme la requête est en `em`, un
   agrandissement du texte repasse tout seul sous le seuil et récupère le repli
   sur deux lignes. Rien à maintenir de ce côté. */
@media (min-width: 34em) {
  .entete-rang {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 1rem;
  }
  .entete-rang > .menu-bouton { justify-self: start; }
  .entete-rang > .marque-bloc { justify-self: center; }
  /* `margin-left` remis à zéro : il servait à pousser le bouton à droite en
     flex, et il fausserait le centrage de la colonne en grille. */
  .entete .entete-action { justify-self: end; margin-left: 0; }
}

/* Le nom du site est du VRAI TEXTE, pas `logo/nom.svg`, le README du logo le
   demande explicitement : du texte reste sélectionnable, lisible par un lecteur
   d'écran, et net à toutes les tailles. Le H et le V italiques colorés
   reproduisent exactement le dessin du fichier, puisque c'est la même police. */
.marque {
  font-family: var(--font-titre);
  font-weight: 600;
  /* Nettement plus grand qu'avant : 28 px en grand écran contre 20. C'est le
     défilement qui le permet : le nom n'occupe cette place qu'en haut de page,
     là où il n'y a rien d'autre à regarder, et il se replie dès qu'on descend.
     Sans le repli, 28 px auraient poussé la barre collante à quatre-vingts
     pixels sur toute la hauteur du site. */
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.75rem);
  letter-spacing: -0.015em;
  text-decoration: none;
  display: inline-flex; align-items: center;
  min-height: var(--tap);
  /* `overflow: hidden` avec `max-height` : c'est ce couple qui fait que le nom
     REPREND SA PLACE en se retirant, au lieu de laisser un trou de la taille
     d'un nom. `visibility` n'est pas transitionnée ici, le retour est
     instantané, mais l'est dans la règle de l'étage 2, avec un retard, pour
     que le lien ne devienne inatteignable au clavier qu'une fois replié. */
  max-height: 3.5rem; overflow: hidden;
  transition: max-height 0.28s var(--doux), min-height 0.28s var(--doux),
              opacity 0.2s linear;
  /* Volontairement PAS de `white-space: nowrap`, et pas d'espace insécable
     entre les deux mots : aux tailles normales le nom tient sur une ligne de
     toute façon, et à 200 % d'agrandissement il vaut mieux qu'il passe à la
     ligne que de pousser l'en-tête hors de l'écran. */
}
.marque-cap { font-style: italic; font-weight: 500; color: var(--voix); }

/* Le nom et la devise forment un BLOC, empilés et centrés.

   La devise vit HORS du lien, à côté de lui et non dedans : un lien de
   navigation qui embarquerait une phrase de marque dans sa zone cliquable
   donnerait une cible de deux lignes dont la moitié ne mène nulle part. */
.marque-bloc {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 0.1rem;
  min-width: 0;
}

/* La devise n'apparaît qu'à partir de 62em, et le seuil est mesuré, pas choisi.

   Entre 34em et 62em, l'en-tête est déjà en trois zones mais la colonne centrale
   ne fait que deux cents pixels : la devise s'y coupait en trois lignes et
   poussait la barre à quatre-vingt-dix pixels de haut. Une devise qui casse la
   mise en page de l'en-tête ne sert plus la marque, elle l'abîme.

   Elle reste dans le pied de page à toutes les largeurs, là, la place ne
   manque pas. */
.marque-devise {
  display: none;
  font-family: var(--font-texte);
  /* 17 px en grand écran contre 13 : même raison que le nom, c'est le repli au
     défilement qui paie cette place. */
  font-size: clamp(0.8125rem, 0.72rem + 0.42vw, 1.0625rem);
  font-weight: 400; line-height: 1.35;
  color: var(--encre-doux);
  text-align: center;
  white-space: nowrap;
  max-height: 2.5rem; overflow: hidden;
  transition: max-height 0.28s var(--doux), opacity 0.2s linear,
              transform 0.28s var(--doux);
}
@media (min-width: 62em) {
  .marque-devise { display: block; }
  /* La devise ajoute une ligne sous le nom : la barre au repos, et la réserve
     qui lui correspond dans <body>, prennent 24 px de plus. */
  :root { --entete-h: 6rem; }
}

/* ÉTAGE 1, la devise part la première. C'est la bonne dans cet ordre : elle
   est secondaire, et son départ suffit à récupérer assez de hauteur pour que la
   barre cesse de peser sur la lecture. */
.entete[data-defilement="1"] .marque-devise,
.entete[data-defilement="2"] .marque-devise {
  max-height: 0; opacity: 0; transform: translateY(-4px);
}

/* ÉTAGE 2, le nom part à son tour.

   `visibility: hidden` est RETARDÉE de 0,28 s, le temps du repli : un lien
   d'une hauteur nulle reste focalisable au clavier, et on tabulerait alors sur
   un lien invisible. Le retard est déclaré ici et non dans la règle de base,
   pour que le retour en haut de page le fasse réapparaître sans délai.

   « Accueil » reste atteignable : le panneau du menu le porte, et le menu ne
   disparaît jamais. */
.entete[data-defilement="2"] .marque {
  min-height: 0; max-height: 0; opacity: 0; visibility: hidden;
  transition: max-height 0.28s var(--doux), min-height 0.28s var(--doux),
              opacity 0.2s linear, visibility 0s 0.28s;
}

/* PAS DE SIGNE H DANS L'EN-TÊTE, et c'est une décision, pas un oubli.

   `logo/README.md` range `marque-h.svg` sous « pour l'en-tête du site », et il
   y a été posé le 20 août avant d'être retiré le même jour. La raison est
   simple et se voit d'un coup d'œil : le nom de la marque COMMENCE par un H,
   écrit en italique et en couleur juste à côté. Le signe donnait « H Héritage
   Vivant », la même lettre deux fois, à deux tailles, à deux styles.

   Le signe garde tout son sens là où le nom écrit n'existe pas : la tuile de
   l'application, le favicon, une boutique, une signature de courriel. Dans un
   en-tête qui porte déjà le nom en toutes lettres, il est redondant. Ne pas le
   remettre sans regarder le rendu. */

/* Bouton du menu, à GAUCHE, comme demandé, et il porte le MOT « Menu ».

   Le mot est DANS le bouton, pas à côté. Posé à côté, il n'aurait pas été
   cliquable : on aurait eu un mot qui annonce une commande et une commande qui
   n'est pas le mot, le genre de détail qui fait qu'on appuie deux fois. Ici,
   les trois tirets et le mot sont une seule cible, plus large et plus sûre à
   viser qu'un carré de 44 px.

   `aria-label` reste piloté par le script et alterne « Ouvrir le menu » /
   « Fermer le menu ». Il contient bien le mot visible, ce que WCAG demande d'un
   nom accessible qui remplace un libellé affiché. */
.menu-bouton {
  flex: 0 0 auto;
  min-width: var(--tap); height: var(--tap);
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.55rem;
  background: transparent;
  border: 1px solid var(--filet-2);
  border-radius: 999px;
  color: inherit;
  cursor: pointer;
  padding-inline: 0.85rem;
}
.menu-bouton:hover { border-color: var(--encre); }
.menu-mot {
  font-family: var(--font-texte);
  font-size: 1rem; font-weight: 600; line-height: 1;
}

/* Trois barres tracées en CSS : trois éléments auraient demandé trois nœuds
   pour une décoration. Elles pivotent en croix à l'ouverture. */
.menu-barres, .menu-barres::before, .menu-barres::after {
  display: block; width: 20px; height: 2px;
  background: currentColor; border-radius: 2px;
  transition: transform 0.25s var(--doux), opacity 0.15s linear;
}
.menu-barres { position: relative; }
.menu-barres::before, .menu-barres::after { content: ""; position: absolute; left: 0; }
.menu-barres::before { top: -6px; }
.menu-barres::after  { top: 6px; }

.menu-bouton[aria-expanded="true"] .menu-barres { opacity: 0; }
.menu-bouton[aria-expanded="true"] .menu-barres::before { transform: translateY(6px) rotate(45deg); }
.menu-bouton[aria-expanded="true"] .menu-barres::after  { transform: translateY(-6px) rotate(-45deg); }

/* Le lien de téléchargement de l'en-tête n'apparaît qu'à partir de 34em : en
   dessous, il pousserait le nom du site contre le bouton de menu. Sa
   disparition ne coûte rien, les badges de boutique sont dans le hero, et
   ce même lien est dans le menu. */
/* Sélecteur en DEUX classes, à dessein : `.entete-action` seul perdait contre
   le `display: inline-flex` de `.btn`, déclaré plus bas dans cette feuille et
   de spécificité égale. Le bouton restait donc affiché à 320 px et poussait
   l'en-tête hors de l'écran. C'est le piège classique de deux règles de même
   poids qui parlent de la même propriété : celle du bas gagne, quel que soit
   l'ordre où on les a écrites dans sa tête. */
.entete .entete-action { margin-left: auto; display: none; }
@media (min-width: 34em) {
  .entete .entete-action { display: inline-flex; }
}

/* ---------- Menu ---------- */
/* Un seul menu à toutes les largeurs, y compris sur grand écran : c'est ce que
   demande le brief, et c'est cohérent avec le reste du site, une seule façon
   de naviguer, apprise une fois. Contrepartie assumée : rien d'essentiel ne
   vit UNIQUEMENT derrière ce bouton. Les tarifs, le téléchargement et les
   pages légales se rejoignent aussi depuis le corps de la page et le pied. */

/* EMPILEMENT, l'ordre compte, et il a déjà produit un défaut.

   Le panneau du menu était en 58 et l'en-tête en 60 : l'en-tête passait DONC
   par-dessus le menu et interceptait les clics sur ses premiers pixels, le
   bouton de fermeture, le nom du site et le premier lien étaient inatteignables.

   Le défaut existait depuis toujours mais restait invisible : en haut de page
   l'en-tête est opaque, on ne cherche pas à cliquer ce qu'on ne voit pas. Le
   jour où la barre est devenue translucide au défilement, elle a montré le
   bouton de fermeture à travers elle sans le laisser cliquer. Un défaut qu'on
   ne voit pas n'est pas un défaut qui n'existe pas.

   L'ordre juste, et la règle qui le gouverne : RIEN NE PASSE AU-DESSUS D'UN
   PANNEAU MODAL. Le voile monte donc au-dessus de l'en-tête, et le panneau
   au-dessus du voile.

     60, l'en-tête
     70, le voile, qui recouvre tout y compris l'en-tête
     75, le panneau du menu
    200, le lien d'évitement, qui doit rester atteignable en toutes
          circonstances

   Effet de bord assumé : l'en-tête passe sous le voile quand le menu est
   ouvert, donc les trois barres, devenues une croix, ne sont plus cliquables.
   Un clic à cet endroit atteint le voile, qui ferme le menu. Le geste donne
   exactement le même résultat. */
.menu-voile {
  position: fixed; inset: 0; z-index: 70;
  background: rgba(27, 42, 46, 0.5); /* --encre à 50% : assombrit sans noircir */
  border: 0; padding: 0; margin: 0;
  cursor: pointer;
}
.menu-voile[hidden] { display: none; }

.menu {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 75;
  width: min(22rem, 88vw);
  background: var(--surface-sombre);
  color: var(--papier-sur-encre);
  padding: 1rem var(--gouttiere) 2rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: 24px 0 60px -40px rgba(27, 42, 46, 0.9);
}
.menu[hidden] { display: none; }

.menu-tete {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; min-height: 3rem; margin-bottom: 1.25rem;
}
.menu-tete .marque { color: var(--papier-sur-encre); }
.menu-tete .marque-cap { color: var(--voix-sur-encre); }

.menu-fermer {
  width: var(--tap); height: var(--tap);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: inherit; cursor: pointer;
  border: 1px solid var(--papier-dim); border-radius: var(--arrondi);
  font-size: 1.25rem; line-height: 1;
}
.menu-fermer:hover { border-color: var(--voix-sur-encre); color: var(--voix-sur-encre); }

/* ---------- La bascule de thème ---------- */
/* Elle vit dans le menu, donc sur la surface d'emphase : ses couleurs viennent
   de --papier-sur-encre et --voix-sur-encre, qui s'inversent avec le thème.

   Le mot est à GAUCHE de la piste dans le code mais l'ordre visuel est piste
   puis mot : c'est volontaire, la piste sert de puce et l'œil descend la liste
   du menu sur une seule colonne. */
.menu-reglage {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--filet-sur-encre);
}
.bascule {
  display: flex; align-items: center; gap: 0.85rem;
  width: 100%; min-height: var(--tap);
  padding: 0.35rem 0;
  background: none; border: 0;
  color: inherit; font: inherit; cursor: pointer;
  text-align: left;
}
.bascule-mot { font-weight: 550; }

/* La piste et sa pastille. Bordure franche plutôt qu'un simple aplat : à l'état
   inactif, un interrupteur sans contour se confond avec le fond et ne se lit
   pas comme une commande. */
.bascule-piste {
  flex: 0 0 auto; position: relative;
  width: 3.1rem; height: 1.7rem;
  border: 1px solid var(--papier-dim);
  border-radius: 999px;
  background: transparent;
  transition: background-color 0.2s var(--doux), border-color 0.2s var(--doux);
}
.bascule-pastille {
  position: absolute; top: 3px; left: 3px;
  width: 1.2rem; height: 1.2rem;
  border-radius: 50%;
  background: var(--papier-sur-encre);
  transition: transform 0.2s var(--doux), background-color 0.2s var(--doux);
}
.bascule[aria-pressed="true"] .bascule-piste {
  background: var(--voix-sur-encre);
  border-color: var(--voix-sur-encre);
}
.bascule[aria-pressed="true"] .bascule-pastille {
  transform: translateX(1.4rem);
  background: var(--surface-sombre);
}
.bascule:hover .bascule-piste { border-color: var(--voix-sur-encre); }

/* L'état ne dépend JAMAIS de la seule position de la pastille : le mot est là,
   et `aria-pressed` le dit à l'oreille. Un interrupteur dont l'état ne se lit
   qu'à la place d'un point est illisible pour qui distingue mal les contrastes
  , et notre lecteur peut avoir 85 ans. */
.bascule-etat { font-size: var(--t-petit); color: var(--papier-dim); }

.menu-liens { display: flex; flex-direction: column; }
.menu-liens a {
  display: flex; align-items: center;
  min-height: 3.25rem; /* 52px, au-delà du plancher de 44 : ce menu est la
                          navigation principale, elle mérite d'être franche */
  font-family: var(--font-titre);
  font-size: 1.25rem;
  text-decoration: none;
  border-bottom: 1px solid var(--filet-sur-encre);
}
.menu-liens a:hover { color: var(--voix-sur-encre); }

/* La page en cours se signale par un filet ET par le mot « page actuelle »
   pour l'oreille : jamais par la couleur seule. */
.menu-liens a[aria-current="page"] {
  color: var(--voix-sur-encre);
  border-left: 3px solid var(--voix-sur-encre);
  padding-left: 0.75rem;
  margin-left: -0.75rem;
}

.menu-pied { margin-top: 1.75rem; }
.menu-pied .badges { margin-top: 0.75rem; }
/* Même correction que pour `.points` plus bas : le panneau est sur l'encre,
   --encre-doux y donne 2,07:1. Mesuré. */
.menu .note { color: var(--papier-dim); }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.5rem;
  min-height: var(--tap);
  padding: 0.7em 1.4em;
  font-family: var(--font-texte);
  font-size: 1rem; font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  border: 1.5px solid transparent;
  /* La pilule est le seul emprunt de forme fait à famileo.com, et le seul
     endroit du site qui s'écarte de `--arrondi`. Un bouton est un objet qu'on
     presse, pas une feuille de papier : il a le droit d'en avoir la forme, et
     c'est ce qui le distingue au premier coup d'œil du reste de la page.

     Ce qu'on ne leur emprunte PAS, et c'est délibéré : leurs libellés sont en
     capitales avec un interlettrage ouvert. Un texte en capitales se lit
     mesurablement plus lentement, la silhouette du mot disparaît, et le
     lecteur de ce site peut avoir 85 ans. Casse basse, graisse tenue. */
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.2s var(--doux), color 0.2s var(--doux),
              border-color 0.2s var(--doux);
}

/* Le bouton plein porte --voix en APLAT, voir « Emploi des couleurs ».
   --papier sur --voix : 8,46:1, calculé. Aucune couleur en dur ici : le survol
   passe par --voix-fonce, dérivé de l'accent, pour que la marque tienne dans un
   seul endroit de la feuille. */
.btn-plein {
  background: var(--voix);
  color: var(--papier);
  border-color: var(--voix);
}
.btn-plein:hover { background: var(--voix-fonce); border-color: var(--voix-fonce); }

.btn-clair {
  background: transparent;
  color: var(--voix);
  border-color: var(--voix);
}
.btn-clair:hover { background: var(--voile); }

/* Sur l'encre, c'est le pendant clair qui prend le relais : 8,80:1 avec le
   texte à l'encre. --voix elle-même sur l'encre serait illisible. */
.section-encre .btn-plein {
  background: var(--voix-sur-encre); color: var(--surface-sombre);
  border-color: var(--voix-sur-encre);
}
.section-encre .btn-plein:hover { background: var(--papier-sur-encre); border-color: var(--papier-sur-encre); }
.section-encre .btn-clair { color: var(--papier-sur-encre); border-color: var(--papier-dim); }
.section-encre .btn-clair:hover { background: var(--filet-sur-encre); }

.btn-grand { font-size: 1.0625rem; padding: 0.85em 1.7em; }
.btn-large { width: 100%; }

/* ---------- Badges de boutique ---------- */
/* Servis en <img> et non intégrés dans la page : le jour du lancement, écraser
   les deux fichiers par ceux d'Apple et de Google suffit, aucun HTML à
   toucher. Hauteur commune de 47 px, c'est elle qui doit s'aligner à l'œil,
   les largeurs diffèrent comme dans les fichiers officiels. */
.badges { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0; padding: 0; list-style: none; }
.badges li { margin: 0; }
.badge { display: inline-flex; border-radius: 8px; }
.badge img { height: 47px; width: auto; display: block; }

/* Adresse pas encore connue : le badge RESTE AFFICHÉ et devient inerte.
   Ce projet a déjà mis en ligne un bouton dont l'adresse valait
   « #a-configurer » : sur un vrai domaine, le bouton disparaissait purement et
   simplement de la page, et la vitrine n'offrait plus aucun accès au produit.
   Un lien vide doit être un lien mort, jamais un lien absent.
   Sans attribut `href`, l'élément n'est plus un lien : il ne prend pas le
   focus, il n'annonce rien de faux, et un texte pour lecteur d'écran dit
   pourquoi. */
.badge[aria-disabled="true"] { cursor: default; opacity: 0.55; }

/* ---------- Chapeaux et paragraphes de tête ---------- */
/* L'intertitre est une étiquette, pas une parole : il reste à l'encre douce.
   Lui donner --voix aurait dilué l'accent sur toute la page. */
.chapeau {
  font-family: var(--font-texte);
  font-weight: 600;
  font-size: var(--t-petit);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--encre-doux);
  margin: 0 0 0.9rem;
}
.section-encre .chapeau { color: var(--papier-dim); }

.lede {
  font-size: var(--t-chapeau);
  line-height: 1.55;
  color: var(--encre-doux);
  max-width: 38rem;
}
.section-encre .lede { color: var(--papier-dim); }

.note {
  font-size: var(--t-petit);
  line-height: 1.6;
  color: var(--encre-doux);
}
.section-encre .note { color: var(--papier-dim); }

/* ============================================================
   La citation mot pour mot, la signature du site

   C'est l'argument le plus solide du produit : une citation qui ne se retrouve
   pas dans les paroles de la personne est rejetée, et c'est vérifié par le
   programme. Le site lui donne donc une FORME, toujours la même, reconnaissable
   d'une page à l'autre : un filet à la couleur de la parole, la phrase en
   Fraunces italique, et au-dessus une étiquette qui dit d'où elle vient.

   Le filet est le seul motif du site à se répéter partout. C'est voulu : c'est
   à lui qu'on doit reconnaître Héritage Vivant.
   ============================================================ */
.citation {
  position: relative;
  margin: 0;
  padding-left: 1.15rem;
  font-family: var(--font-titre);
  font-style: italic;
  font-size: 1.15em;
  line-height: 1.5;
}
.citation::before {
  content: "";
  position: absolute; left: 0; top: 0.15em; bottom: 0.15em;
  width: 3px; border-radius: 3px;
  background: var(--voix);
}
/* L'écran du téléphone est du PAPIER, pas de l'encre : le filet y reste en
   --voix. Le rose y donnerait 1,60:1, un filet qu'on ne voit pas, sur
   l'écran qui porte justement l'argument le plus fort du produit. Les deux
   faces du jeton ne servent jamais sur le même fond. */
.section-encre .citation::before { background: var(--voix-sur-encre); }

.citation-source {
  display: block;
  font-family: var(--font-texte);
  font-style: normal;
  font-size: var(--t-petit);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--encre-doux);
  margin-bottom: 0.4rem;
}
.section-encre .citation-source { color: var(--papier-dim); }

/* Marqueurs « dit » et « déduit ».
   Ils se distinguent par le TRAIT autant que par la couleur : plein pour ce
   qui a été dit, pointillé pour ce qui a été déduit. Un daltonien lit la
   différence, et la différence reste lisible imprimée en noir et blanc. */
.marqueur {
  display: inline-flex; align-items: center;
  font-size: var(--t-petit); font-weight: 600;
  letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0.2em 0.7em;
  border-radius: 999px;
  /* Pas de `white-space: nowrap` : « Ce qui a été déduit » en capitales
     espacées mesure large, et à texte agrandi cette étiquette imposait sa
     ligne entière à la fiche du hero, puis à la page. Elle passe donc à la
     ligne quand il le faut, un peu moins joli, mais lisible. */
}
.marqueur-dit { border: 1.5px solid var(--voix); color: var(--voix); }
.marqueur-deduit { border: 1.5px dashed var(--bord-champ); color: var(--encre-doux); }
/* Seule la surface d'encre inverse les deux marqueurs. L'écran du téléphone
   est clair : il garde les couleurs de base. */
.section-encre .marqueur-dit { border-color: var(--voix-sur-encre); color: var(--voix-sur-encre); }
.section-encre .marqueur-deduit { border-color: var(--papier-dim); color: var(--papier-dim); }

/* ---------- Photographies ---------- */
/* Ce que ces images sont, et ce qu'elles ne sont pas.

   Elles montrent des personnes âgées AU TÉLÉPHONE, en train de parler. C'est
   le geste du produit, et c'est pour cela qu'elles ont été retenues. Aucune
   n'est présentée comme une utilisatrice d'Élise : pas de prénom, pas d'âge,
   pas de légende qui raconte une histoire. Une photographie d'illustration
   sans affirmation attachée n'est pas un faux témoignage ; une photographie
   légendée « Jeanne, 84 ans » en serait un, et le site s'interdit les deux
   secondes.

   Elles sont PROVISOIRES, des images de calage, à remplacer par les
   photographies des essais. Tout est écrit pour que ce remplacement soit un
   remplacement de fichiers : les rapports d'affichage sont fixés ici, jamais
   déduits de l'image, donc un cliché d'un autre format ne déforme pas la page.

   La règle d'imagerie du projet, pour le jour du remplacement : ce qu'on
   montre est l'AGENTIVITÉ, pas l'absence de signes d'âge. Une canne, des
   rides, un fauteuil ne disqualifient pas une image, un regard vide, oui. */
.photo {
  margin: 0;
  border-radius: var(--arrondi-carte);
  overflow: hidden;
  background: var(--papier-2); /* ce qu'on voit pendant le chargement */
}
/* `aspect-ratio` posé ici et non hérité du fichier : la place est réservée
   avant que l'image arrive, donc rien ne saute pendant le chargement, et un
   remplaçant d'un autre format sera recadré au lieu de déplacer la page. */
.photo img {
  display: block;
  width: 100%; height: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* La photo du hero. Le léger débord sous la colonne de texte, en grand écran
   seulement, évite le rendu « deux blocs posés côte à côte » sans rien coûter
   à la lecture. */
.hero-photo { box-shadow: 0 30px 60px -45px rgba(22, 48, 58, 0.7); }
@media (min-width: 64em) {
  /* 5:4 en grand écran : la colonne de texte est haute, une image en 3:2 à côté
     paraissait une vignette posée là. Le recadrage reste raisonnable, et l'image
     gagne assez de hauteur pour tenir tête au titre.
     `object-position` à 58 % parce que le sujet des trois photographies est
     légèrement à droite du centre ; recentrer sur 50 % coupait un bras. */
  .hero-photo img { aspect-ratio: 5 / 4; object-position: 58% center; }
}

/* La photographie de la bande sombre.

   `profil-lumiere` est photographiée sur un fond presque noir : posée sur
   --encre, elle se fond d'elle-même. Le dégradé de masque prolonge ce fondu du
   côté du texte, ce qui donne l'effet de photo de fond de famileo.com sans
   poser une seule ligne de texte SUR l'image, donc sans le problème de
   contraste que leur hero, lui, ne résout pas. */
.bande-photo {
  margin: 0;
  -webkit-mask: linear-gradient(to right, transparent, #000 38%);
  mask: linear-gradient(to right, transparent, #000 38%);
}
.bande-photo img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* ---------- Questions fréquentes ---------- */
/* En <details>/<summary>, pas en JavaScript : le navigateur donne l'ouverture
   au clavier, l'annonce au lecteur d'écran et la recherche dans la page sans
   qu'on écrive une ligne. Aucun script ne doit être responsable de l'accès à
   du texte. */
.faq { max-width: 46rem; margin: var(--espace-bloc) auto 0; }
.faq details { border-top: 1px solid var(--filet); }
.faq details:last-of-type { border-bottom: 1px solid var(--filet); }
.faq summary {
  display: flex; align-items: baseline; gap: 1rem;
  min-height: var(--tap);
  padding-block: 1.1rem;
  font-family: var(--font-titre);
  font-size: var(--t-h3); font-weight: 600; line-height: 1.3;
  cursor: pointer;
  list-style: none; /* Firefox */
}
.faq summary::-webkit-details-marker { display: none; }
/* Le repère change de GLYPHE et ne tourne pas : une rotation serait un
   mouvement de plus à neutraliser sous `prefers-reduced-motion`, pour un
   signal que « + » et « − » donnent déjà sans ambiguïté. */
.faq summary::after {
  content: "+";
  margin-left: auto;
  font-family: var(--font-texte);
  font-size: 1.5rem; font-weight: 400; line-height: 1;
  color: var(--voix);
}
.faq details[open] summary::after { content: "\2212"; }
.faq summary:hover { color: var(--voix); }
.faq-reponse { padding-bottom: 1.4rem; color: var(--encre-doux); }
.faq-reponse p { margin-bottom: 0.8em; }
.faq-reponse p:last-child { margin-bottom: 0; }

/* ---------- Hero ---------- */
/* Le hero a un SOL, et c'est le correctif le plus important de la refonte.

   Sans fond, la page s'ouvrait sur du blanc cassé : une colonne de texte à
   gauche, une image qui flottait à droite, et rien qui tienne les deux
   ensemble. Un visiteur n'y voyait pas un produit, il y voyait un document qui
   commence.

   Le sable pleine largeur fait trois choses d'un coup : il donne un bord haut à
   la page, il pose l'image sur quelque chose au lieu de la laisser en l'air, et
   il rend la première bande claire : #elise, respirante par contraste. Le
   rythme sable / papier / sable qui suit reste juste. */
.hero {
  background: var(--voile);
  border-bottom: 1px solid var(--filet-2);
  /* Haut resserré : l'ancien réglage laissait près de cent pixels de vide
     au-dessus du premier mot, sur un écran où tout se joue en trois secondes.
     Resserré une seconde fois sur téléphone le 21 août : sous une barre
     d'en-tête de 73 px, quarante pixels de plus repoussaient le premier mot
     au tiers de l'écran. */
  padding-block: clamp(1.75rem, 0.6105rem + 4.8619vw, 4.5rem) var(--espace-section);
}
.hero-grille {
  display: grid;
  gap: var(--espace-bloc);
  align-items: center;
}
.hero h1 { margin-bottom: 0.5em; }
.hero .lede { margin-bottom: var(--espace-bloc); }
.hero-actions { display: flex; flex-direction: column; gap: 1.1rem; align-items: flex-start; }

@media (min-width: 64em) {
  /* L'image prend la moitié pleine, et non 0,95 d'une moitié. Elle porte
     autant que le texte : c'est elle qui dit à qui ce produit s'adresse. */
  .hero-grille { grid-template-columns: 1fr 1fr; gap: var(--espace-section); }
}

/* La fiche de souvenir, ce que le produit fabrique, montré plutôt que promis.

   Elle a d'abord servi d'image de hero, faute de photographie. Elle a été
   déplacée dans la section « mot pour mot » : c'est là qu'elle argumente, à
   côté du texte qui explique le contrôle de la citation. Un exemple posé sous
   l'affirmation qu'il illustre vaut mieux que le même exemple posé deux écrans
   plus haut. */
.fiche {
  background: var(--papier);
  border: 1px solid var(--filet-2);
  border-radius: var(--arrondi-carte);
  padding: var(--espace-carte);
  box-shadow: 0 24px 50px -40px rgba(27, 42, 46, 0.55);
}
.section-bande .fiche { background: var(--papier); }
.fiche-tete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem; flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.fiche-tete .chapeau { margin-bottom: 0; }
.fiche h2, .fiche h3 { margin-bottom: 0.8rem; }
/* Le titre du souvenir n'est pas un titre de document : il nomme une fiche
   d'exemple. Il en a donc la taille et la police, sans entrer dans le plan de
   la page, un `h2` ici brouillerait la structure lue par un lecteur d'écran. */
.fiche-titre {
  font-family: var(--font-titre);
  font-size: var(--t-h3);
  font-weight: 600; line-height: 1.25;
  margin: 0 0 1.1rem;
}
.fiche-bloc { margin-top: 1.25rem; }
.fiche-deduit {
  margin-top: 1.25rem; padding-top: 1.25rem;
  border-top: 1px solid var(--filet);
}
.fiche-deduit p { margin: 0.5rem 0 0; color: var(--encre-doux); }

/* Mention de démonstration. Elle n'est PAS pilotée par le mode chantier : le
   contenu de ces écrans restera inventé même le jour de la mise en ligne, et
   rien ne doit pouvoir être pris pour la vraie vie de quelqu'un. */
.mention-demo {
  display: block;
  margin-top: 0.9rem;
  font-size: var(--t-petit);
  color: var(--encre-doux);
}
.section-encre .mention-demo { color: var(--papier-dim); }

/* Sous-titre d'un bloc à l'intérieur d'une section, et action qui la referme.
   Deux respirations nommées plutôt qu'une marge posée au cas par cas : c'est
   ce qui garde le rythme vertical identique d'une page à l'autre. */
.bloc-titre {
  margin-top: var(--espace-bloc);
  margin-bottom: var(--espace-grille);
  font-size: var(--t-h3);
}
.bloc-action { margin-top: var(--espace-bloc); }

/* ---------- Points de voix ---------- */
/* Des lignes séparées par un filet plutôt que trois cartes à icône : le site
   n'a rien à mettre dans une icône ici, et trois cartes vides de sens sont
   la marque d'une page faite au gabarit. */
/* Centré comme bloc, aligné à gauche comme texte : il suit un titre de
   section centré, et une liste centrée ne se lit pas. */
/* SUR TÉLÉPHONE, LES POINTS DÉFILENT DE CÔTÉ — 21 août 2026.

   Le reproche à l'origine de ce réglage : « on a l'impression que c'est une
   seule colonne ». C'en est une, et à 375 px il ne peut pas y en avoir deux —
   un texte de 18 px demande de quarante à soixante-quinze caractères par ligne
   pour rester lisible, une demi-largeur d'iPhone en donne quinze. Deux colonnes
   de texte sur un téléphone ne sont pas un réglage serré, elles sont illisibles.

   Ce qui se corrige en revanche, c'est la monotonie, qui est le vrai défaut
   ressenti : neuf sections où tout a la même largeur et se lit de haut en bas.
   Un rail qui défile latéralement donne au pouce un SECOND AXE sans réduire une
   seule lettre. Les trois points passent de 521 px empilés à la hauteur d'une
   carte, et la carte suivante dépasse volontairement du bord — c'est ce
   débord, et lui seul, qui dit qu'il y a une suite.

   Il ne s'applique qu'au téléphone : au-delà de 34em, la liste verticale
   validée revient telle quelle. Un rail sur grand écran cacherait du contenu là
   où la place ne manque pas.

   Limite connue, à honorer si le rail est gardé : une zone qui défile doit être
   atteignable au clavier, ce qu'un `div` sans `tabindex` n'est pas. */
.points {
  display: flex;
  gap: var(--espace-grille);
  margin: var(--espace-bloc) calc(var(--gouttiere) * -1) 0;
  padding-inline: var(--gouttiere);
  /* Ces 0,9 rem ne sont pas un blanc décoratif, ils réparent un effet de bord
     mesuré : dès qu'un seul axe déborde, `overflow-y: visible` prend la valeur
     `auto`, donc le rail CLIPPE ce qui dépasse en bas. Or l'animation
     d'apparition tient justement les cartes 14,4 px plus bas — le bord
     inférieur de chaque carte était rogné pendant les trois quarts de seconde
     de la cascade. La réserve vaut exactement le décalage. */
  padding-block: 0 0.9rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: var(--gouttiere);
  /* Sans lui, un mouvement de pouce un peu vif fait défiler la PAGE une fois le
     rail arrivé au bout, et la lecture saute. */
  overscroll-behavior-x: contain;
  /* Pour les fleches de la commande : `scroll-behavior` ne s'herite pas,
     la valeur posee sur <html> ne descend donc pas jusqu'ici. */
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.points::-webkit-scrollbar { width: 0; height: 0; }
.points > div {
  /* Le pourcentage se calcule sur la boîte de contenu du rail, gouttières
     déduites, et non sur l'écran : 88 % de 335 px donnent une carte de 295 px,
     donc une ligne de texte de 255 px, soit environ vingt-huit caractères. Les
     quarante pixels qui restent sont le débord de la carte suivante. Aller plus
     bas élargit le débord mais hache le paragraphe. */
  flex: 0 0 88%;
  scroll-snap-align: start;
  padding: var(--espace-carte);
  border: 1px solid var(--filet);
  border-radius: var(--arrondi-carte);
}
.points h3 { margin-bottom: 0.3rem; }
.points p { color: var(--encre-doux); margin: 0; }

@media (min-width: 34em) {
  .points {
    display: block;
    max-width: 42rem;
    margin: var(--espace-bloc) auto 0;
    padding: 0;
    overflow: visible;
  }
  .points > div {
    padding: 1.2rem 0;
    border: 0;
    border-top: 1px solid var(--filet);
    border-radius: 0;
  }
  .points > div:first-child { border-top: 0; padding-top: 0; }
}

/* Sur l'encre, --encre-doux tombe à 2,07:1 : illisible. Mesuré, pas estimé,
   c'est le piège d'une couleur de texte secondaire posée en dur dans un
   composant qu'on réemploie ensuite sur fond sombre. Le pendant clair du même
   jeton donne 9,97:1. Le filet aussi s'inverse : à --filet sur l'encre, la
   ligne de séparation devenait plus visible que le texte. */
.section-encre .points p { color: var(--papier-dim); }
/* Le rail borde ses cartes sur quatre cotes, la liste seulement en haut : les
   deux ont besoin de la meme correction sur fond sombre. */
.section-encre .points > div { border-color: var(--filet-sur-encre); }

/* ============================================================
   LA COMMANDE DES RAILS — « 2 sur 3 » et deux flèches

   Posée le 21 août 2026, parce qu'un rail qui défile de côté ne se signale
   qu'au pouce de quelqu'un qui en a déjà l'habitude. Le débord de la carte
   suivante y aide, mais il ne se lit qu'après coup : il faut avoir compris
   qu'on peut glisser pour comprendre ce que ce bord veut dire. Or le public est
   une famille dont le membre le plus âgé ouvrira la page — une consigne VISIBLE
   vaut mieux qu'un geste devinable.

   Trois choses en une, et c'est ce qui la justifie plutôt qu'un simple jeu de
   pastilles :

   1. Elle DIT qu'il y a une suite, et combien. « 1 sur 3 » ne s'apprend pas.
   2. Elle donne une CIBLE TACTILE à qui ne fait pas le geste : les deux flèches
      font exactement ce que le doigt ferait.
   3. Elle règle la dette d'accessibilité des rails. Une zone qui défile doit
      être atteignable au clavier ; deux boutons le sont par nature, là où un
      `tabindex` posé sur le rail aurait ajouté un arrêt de tabulation sur du
      texte, y compris sur grand écran où le rail n'existe pas.

   Elle est construite par le script, donc absente sans JavaScript : sans lui le
   rail reste glissable au doigt, on perd la consigne, pas le contenu. Elle
   disparaît là où chaque rail s'arrête — 34em pour les points, 48em pour les
   formules, d'où deux règles et non une.
   ============================================================ */
.rail-barre {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 0.9rem;
}
.rail-bouton {
  /* Le plancher de cible tactile du site, jamais franchi vers le bas. */
  width: var(--tap); height: var(--tap);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.375rem; line-height: 1;
  color: var(--encre);
  background: transparent;
  border: 1px solid var(--filet-2);
  border-radius: 999px;
  cursor: pointer;
}
/* Désactivé et non retiré : un bouton qui disparaît au bout du rail déplace
   l'autre sous le doigt qui allait le toucher. */
.rail-bouton[disabled] { opacity: 0.35; cursor: default; }
.rail-compteur {
  /* `tabular-nums` et une largeur plancher : sans elles, passer de « 1 » à
     « 2 » fait respirer les flèches d'un pixel à chaque glissement. */
  font-variant-numeric: tabular-nums;
  min-width: 5rem;
  text-align: center;
  font-size: var(--t-petit);
  color: var(--encre-doux);
  margin: 0;
}
.section-encre .rail-compteur { color: var(--papier-dim); }
.section-encre .rail-bouton { color: var(--papier); border-color: var(--filet-sur-encre); }

@media (min-width: 34em) { .points + .rail-barre { display: none; } }
@media (min-width: 48em) { .formules + .rail-barre { display: none; } }

/* ============================================================
   La démonstration, le téléphone

   Dessiné en CSS, écrans en HTML réel. Ni 3D ni bibliothèque : le public
   arrive sur la 4G d'un téléphone, et 500 ko de moteur 3D pour faire tourner
   un objet ne se défendent pas.

   Écrire les écrans en HTML plutôt qu'en image a un second effet, plus
   important que le poids : leur texte est lu par un lecteur d'écran, se
   sélectionne, et grossit avec le zoom du navigateur.
   ============================================================ */
.demo-grille { display: grid; gap: var(--espace-bloc); margin-top: var(--espace-bloc); }

@media (min-width: 64em) {
  .demo-grille {
    grid-template-columns: 20rem minmax(0, 1fr);
    gap: var(--espace-section);
    align-items: start;
  }
  /* Le téléphone reste en vue pendant qu'on parcourt les repères : c'est ce
     qui rend le changement d'écran lisible plutôt que subi. */
  .demo-telephone { position: sticky; top: 6rem; }
}

.telephone {
  width: min(20rem, 100%);
  margin-inline: auto;
  background: var(--surface-sombre);
  border-radius: 2.4rem;
  padding: 0.65rem;
  box-shadow: 0 30px 60px -45px rgba(27, 42, 46, 0.9);
}
.telephone-ecran {
  position: relative;
  background: var(--papier);
  border-radius: 1.9rem;
  overflow: hidden;
  /* Hauteur plancher plutôt que proportion fixe : à proportion fixe, un écran
     un peu plus bavard que les autres déborderait du cadre, et le zoom à 200 %
     couperait le texte. Ici le téléphone s'allonge au lieu de rogner. */
  min-height: 33rem;
  display: flex; flex-direction: column;
}
/* L'encoche. Purement décorative, donc dessinée et non balisée. */
.telephone-ecran::before {
  content: "";
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 6.5rem; height: 1.1rem;
  background: var(--surface-sombre);
  border-radius: 0 0 0.8rem 0.8rem;
  z-index: 2;
}

.ecran { display: flex; flex-direction: column; flex: 1; }
.ecran[hidden] { display: none; }

.ecran-barre {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 1.6rem 1.1rem 0.75rem;
  border-bottom: 1px solid var(--filet);
}
/* La tuile de l'application, reproduite en texte : c'est le même H de Fraunces
   que `logo/icone-app.svg`, donc rien à recopier ni à tenir à jour. */
.ecran-tuile {
  width: 1.75rem; height: 1.75rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-sombre); color: var(--voix-sur-encre);
  border-radius: 6px;
  font-family: var(--font-titre); font-weight: 700; font-size: 1rem;
  line-height: 1;
}
.ecran-nom { font-size: var(--t-petit); font-weight: 600; letter-spacing: 0.04em; }

.ecran-corps {
  flex: 1;
  padding: 1.1rem;
  display: flex; flex-direction: column; gap: 0.9rem;
}
.ecran-corps p { margin: 0; }
.ecran-titre { font-family: var(--font-titre); font-size: 1.15rem; font-weight: 600; line-height: 1.25; }
.ecran-petit { font-size: 0.8125rem; color: var(--encre-doux); line-height: 1.5; }

/* Écran d'accueil : UN bouton, et un seul. C'est la promesse de l'application
  , quelqu'un de 88 ans ne doit pas avoir à choisir. */
.ecran-centre { justify-content: center; align-items: center; text-align: center; gap: 1.5rem; }
.ecran-parler {
  width: 11rem; height: 11rem;
  border-radius: 50%;
  background: var(--surface-sombre); color: var(--papier-sur-encre);
  border: 0;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.4rem;
  font-family: var(--font-titre); font-size: 1.2rem; font-weight: 600;
  cursor: default;
}

/* Bulles de conversation. Élise à gauche sur fond papier bordé, la personne à
   droite sur fond encre : la différence de côté ET de fond, jamais la couleur
   seule. */
.bulle { padding: 0.75rem 0.9rem; border-radius: 12px; font-size: 0.9375rem; line-height: 1.5; max-width: 92%; }
.bulle-elise { background: var(--papier-2); border-bottom-left-radius: 3px; }
.bulle-personne {
  background: var(--surface-sombre); color: var(--papier-sur-encre);
  align-self: flex-end; border-bottom-right-radius: 3px;
}
.bulle-qui {
  display: block; font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--encre-doux); margin-bottom: 0.2rem;
}
.bulle-personne .bulle-qui { color: var(--papier-dim); }

/* Témoin d'écoute. Les barres montent et descendent : l'unique animation en
   boucle du site, et elle dit quelque chose, le produit écoute.
   Au repos (mouvement réduit, JavaScript coupé) elles gardent leur hauteur du
   HTML : le témoin reste visible et lisible, il ne bouge simplement plus. */
.ecoute { display: flex; align-items: center; gap: 0.75rem; padding: 0.25rem 0; }
.ecoute-barres { display: flex; align-items: center; gap: 3px; height: 1.5rem; }
.ecoute-barres span {
  display: block; width: 3px; border-radius: 2px;
  background: var(--voix);
  height: var(--h, 40%);
}
.ecoute-texte { font-size: 0.8125rem; color: var(--encre-doux); }

@media (prefers-reduced-motion: no-preference) {
  .ecran:not([hidden]) .ecoute-barres span {
    animation: ecoute 1.1s var(--doux) infinite alternate;
    animation-delay: var(--d, 0s);
  }
}
@keyframes ecoute {
  from { transform: scaleY(0.55); }
  to   { transform: scaleY(1.35); }
}

/* Écran du récit : le seul endroit de l'interface où le texte est en Fraunces.
   Le récit de vie est un texte de livre, pas une donnée d'application. */
.ecran-recit p { font-family: var(--font-titre); font-size: 0.9375rem; line-height: 1.6; }

/* ---------- Les repères de la démonstration ---------- */
/* De vrais onglets : `role="tablist"`, flèches du clavier, un seul arrêt de
   tabulation pour le groupe. Le clic, jamais un carrousel qui repart tout
   seul, le lecteur peut avoir 85 ans et n'a pas à courir après le texte. */
.reperes { display: flex; flex-direction: column; gap: 0; margin: 0; }
.repere {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 0;
  border-top: 1px solid var(--filet);
  padding: 1.1rem 0 1.1rem 2.6rem;
  position: relative;
  color: inherit; font: inherit;
  cursor: pointer;
  min-height: var(--tap);
}
.repere:first-child { border-top: 0; }
.repere-num {
  position: absolute; left: 0; top: 1.15rem;
  font-family: var(--font-titre); font-size: 1rem; font-weight: 600;
  color: var(--encre-doux);
}
.repere-titre { font-family: var(--font-titre); font-size: var(--t-h3); font-weight: 600; line-height: 1.3; display: block; }
.repere-texte { color: var(--encre-doux); font-size: 1rem; margin: 0.25rem 0 0; }

/* Le repère actif se signale par un filet à gauche ET par le poids du texte,
   pas seulement par la couleur. `aria-selected` le dit à l'oreille. */
.repere[aria-selected="true"] { color: var(--encre); }
.repere[aria-selected="true"] .repere-titre { color: var(--voix); }
.repere[aria-selected="true"] .repere-num { color: var(--voix); }
.repere[aria-selected="true"]::before {
  content: "";
  position: absolute; left: -0.75rem; top: 0.9rem; bottom: 0.9rem;
  width: 3px; border-radius: 3px; background: var(--voix);
}
.repere:hover .repere-titre { color: var(--voix); }

/* ---------- Tarifs ---------- */
/* LES DEUX FORMULES DÉFILENT DE CÔTÉ SOUS 48em — 21 août 2026, même raison que
   le rail des points, mais un gain plus gros : empilées, les deux cartes
   faisaient 1 294 px, soit un écran et demi pour comparer deux prix qu'on ne
   peut justement pas comparer sans les voir ensemble. Côte à côte dans un rail,
   la seconde dépasse du bord : on sait qu'elle existe et on l'atteint d'un
   pouce.

   Le seuil est 48em et non 34em : c'est là que la grille à deux colonnes prend
   le relais, et le rail s'arrête exactement où elle commence.

   CE QU'IL FAUT SAVOIR ET QUI EST UNE DÉCISION, PAS UN DÉTAIL : la formule mise
   en avant est la SECONDE dans le HTML, c'est donc celle qu'il faut faire
   glisser pour voir en entier. L'ordre n'a pas été changé ici — il se décide
   avec les prix, pas avec la mise en page. */
.formules {
  display: flex;
  gap: var(--espace-grille);
  margin: var(--espace-bloc) calc(var(--gouttiere) * -1) 0;
  /* Réserve du bas : voir le rail des points. L'animation d'apparition décale
     les cartes vers le bas, et un rail clippe ce qui dépasse. */
  padding: 0 var(--gouttiere) 0.9rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: var(--gouttiere);
  overscroll-behavior-x: contain;
  /* Pour les fleches de la commande : `scroll-behavior` ne s'herite pas,
     la valeur posee sur <html> ne descend donc pas jusqu'ici. */
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.formules::-webkit-scrollbar { width: 0; height: 0; }
.formules > .formule { flex: 0 0 88%; scroll-snap-align: start; }

@media (min-width: 48em) {
  .formules {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    margin: var(--espace-bloc) 0 0;
    padding: 0;
    overflow: visible;
  }
  .formules > .formule { flex: none; }
}

.formule {
  background: var(--papier);
  border: 1px solid var(--filet-2);
  border-radius: var(--arrondi-carte);
  padding: var(--espace-carte);
  display: flex; flex-direction: column;
}
.section-bande .formule { background: var(--papier); }

/* La formule haute prend un cadre plus franc. Aucun mot de vantardise, aucun
   « la plus choisie » : rien n'a encore été choisi par personne. Ce qui la
   met en avant est une arithmétique vraie, écrite en toutes lettres dans la
   carte, deux fois plus de conversations pour 60 % de plus. */
/* Le cadre est à la BRAISE, pas à l'encre. Une carte bordée d'encre dont le
   bouton est terre cuite fait cohabiter deux accents sur le même objet, et le
   regard ne sait plus lequel des deux le désigne. Un seul système d'accent par
   page, tenu jusqu'au bout. */
.formule-mise-en-avant { border: 2px solid var(--voix); }

.formule h3 { font-size: var(--t-h3); margin-bottom: 0.15rem; }
/* Le RYTHME d'abord, le nombre ensuite : « chaque semaine » se comprend,
   « 4 par mois » se compte. Le nombre vit dans le détail, jamais dans le
   titre de la formule. */
.formule-rythme { font-size: var(--t-petit); color: var(--encre-doux); margin: 0 0 1.25rem; }

.formule-prix {
  font-family: var(--font-titre);
  font-size: var(--t-prix);
  font-weight: 600; line-height: 1;
  letter-spacing: -0.02em;
  display: block;
}
.formule-periode { font-size: var(--t-petit); color: var(--encre-doux); display: block; margin-top: 0.35rem; }

/* Le mensuel est l'OPTION, pas une colonne de force égale : plus petit, sous
   un filet, avec le total annuel écrit à côté. C'est cet écart de 20 % qui
   pousse vers l'annuel, il doit donc être lisible sans calcul. */
.formule-mensuel {
  margin-top: 1.1rem; padding-top: 1.1rem;
  border-top: 1px solid var(--filet);
  font-size: 1rem; color: var(--encre-doux);
}
.formule-mensuel strong { color: var(--encre); font-weight: 600; }

.formule-liste { list-style: none; margin: 1.4rem 0 0; padding: 0; display: grid; gap: 0.6rem; }
.formule-liste li { position: relative; padding-left: 1.4rem; font-size: 1rem; }
.formule-liste li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--voix);
}
.formule-note {
  margin-top: 1.2rem; font-size: var(--t-petit); color: var(--encre-doux);
}
.formule-action { margin-top: auto; padding-top: 1.5rem; }

/* Les deux options que l'offre n'a pas encore : le livre relié et la première
   conversation gratuite. Elles ne sont pas une ligne de plus dans une liste,
   le jour où l'une passe à `true`, elle devient un argument à part entière,
   et sa place est réservée ici, en pleine largeur, avant les formules. */
.offre-plus {
  border: 1px solid var(--filet-2);
  border-left: 3px solid var(--voix);
  border-radius: var(--arrondi);
  background: var(--papier);
  padding: var(--espace-carte);
  margin-bottom: var(--espace-grille);
}
.offre-plus h3 { margin-bottom: 0.35rem; }
.offre-plus p { margin: 0; color: var(--encre-doux); }
.offre-plus[hidden] { display: none; }

/* ---------- Grille de témoignages ---------- */
/* Colonnes plafonnées et centrées : à un seul élément, la grille ne l'étire
   pas sur toute la largeur, à deux elle ne laisse pas de trou à droite, à
   trois elle fait une ligne pleine. Les trois cas ont été vérifiés à l'écran,
   c'est le piège classique d'une grille à trois colonnes fixes. */
.temoignages {
  display: grid;
  /* `min(15rem, 100%)` et non `15rem` : c'est l'idiome qui empêche une grille
     `auto-fit` de déborder. Écrite en dur, la largeur minimale d'une colonne
     s'impose même quand le conteneur est plus étroit qu'elle, ce qui arrive
     sur un écran de 320 px, et à coup sûr dès que le texte est agrandi. */
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 20rem));
  justify-content: center;
  gap: var(--espace-grille);
  margin-top: var(--espace-bloc);
}
/* 20rem et non 22 : mesuré à 1280 px, trois colonnes de 22rem plus leurs
   gouttières demandaient 1120 px pour 1084 disponibles. La troisième carte
   passait à la ligne et s'y retrouvait seule, calée à gauche, la grille
   paraissait cassée alors qu'elle faisait exactement ce qu'on lui demandait. */

/* Une vidéo n'a pas la même largeur utile qu'une citation : à 20rem, l'affiche
   16:9 tombe à 180 px de haut et ne montre plus rien. */
.temoignages-large { grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 32rem)); }
.temoignage {
  background: var(--papier);
  border: 1px solid var(--filet-2);
  border-radius: var(--arrondi-carte);
  padding: var(--espace-carte);
}

/* ---------- Emplacements de contenu à venir ---------- */
/* Visibles et étiquetés en mode « chantier » pour juger la mise en page,
   entièrement retirés en mode « reel ». Le cadre est franchement dessiné,
   un emplacement discret finirait par être oublié en ligne. */
.emplacement {
  border: 2px dashed var(--filet-2);
  border-radius: var(--arrondi-carte);
  background: var(--papier-2);
  padding: var(--espace-carte);
  display: flex; flex-direction: column; justify-content: center;
  gap: 0.5rem;
  min-height: 11rem;
}
.emplacement-video { aspect-ratio: 16 / 9; min-height: 0; }
.emplacement-etiquette {
  font-size: var(--t-petit); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--encre-doux);
}
.emplacement-titre { font-family: var(--font-titre); font-size: 1.125rem; font-weight: 600; }
.emplacement-specs { font-size: var(--t-petit); color: var(--encre-doux); line-height: 1.55; margin: 0; }

/* Un emplacement posé SUR LA BANDE SOMBRE. C'est la page « Pour les résidences »
   qui a révélé le manque : le mécanisme avait toujours vécu sur fond clair, donc
   sa boîte en --papier-2 recevait le texte clair de la bande, soit 1,22:1.

   Le cadre devient un simple contour, sans fond : ce qui doit se lire sur
   l'encre, c'est le texte, pas la boîte. */
.section-encre .emplacement {
  background: transparent;
  border-color: var(--papier-dim);
}
.section-encre .emplacement-etiquette,
.section-encre .emplacement-specs { color: var(--papier-dim); }

/* Un lien de texte DANS LE MENU. Le panneau est sur la surface sombre, donc
   --voix y tombe à 1,67:1. La règle existait pour .section-encre, pas pour le
   menu : aucun lien de texte n'y avait jamais été posé avant celui de la page
   des résidences. */
.menu .lien { color: var(--voix-sur-encre); }

/* L'affiche cliquable d'une vidéo. AUCUN <iframe> au chargement : un lecteur
   YouTube dépose des traceurs avant même qu'on ait cliqué, et rendrait
   obligatoire le bandeau de consentement que ce site refuse. Le lecteur ne se
   chargera qu'au clic, et le script accepte aussi bien un fichier auto-hébergé
   qu'une adresse youtube-nocookie, ce choix se tranchera quand la vidéo
   existera, sans refaire ce code. */
.affiche {
  position: relative; display: block; width: 100%;
  padding: 0; border: 1px solid var(--filet-2);
  border-radius: var(--arrondi-carte);
  overflow: hidden; background: var(--papier-2);
  cursor: pointer; aspect-ratio: 16 / 9;
}
.affiche img { width: 100%; height: 100%; object-fit: cover; display: block; }
.affiche-lecture {
  position: absolute; inset: 0; margin: auto;
  width: 4.5rem; height: 4.5rem; border-radius: 50%;
  background: var(--surface-sombre); color: var(--papier-sur-encre);
  display: flex; align-items: center; justify-content: center;
}
.affiche:hover .affiche-lecture { background: var(--voix); }
.affiche-legende { padding: 0.75rem 1rem; font-size: var(--t-petit); color: var(--encre-doux); text-align: left; }

/* ---------- Formulaires ---------- */
.carte-formulaire {
  background: var(--papier);
  border: 1px solid var(--filet-2);
  border-radius: var(--arrondi-carte);
  padding: var(--espace-carte);
  max-width: 30rem;
}
.section-bande .carte-formulaire { background: var(--papier); }
/* Le titre d'une carte de formulaire ouvre la carte : pas de marge au-dessus,
   c'est le rembourrage de la carte qui la donne. */
.carte-formulaire h2 { margin-top: 0; }
.carte-formulaire > .note { margin-top: 1.5rem; }

.champ { display: grid; gap: 0.4rem; margin-bottom: 1.25rem; }
/* Étiquette VISIBLE, toujours. Un texte d'exemple dans le champ disparaît dès
   qu'on tape : la personne ne sait plus ce qu'elle est en train de remplir,
   et c'est un des tout premiers motifs d'abandon d'un formulaire. */
.champ label { font-weight: 600; font-size: 1rem; }
.champ input {
  /* Un `input` porte une largeur intrinsèque héritée de son attribut `size`,
     une vingtaine de caractères, que le navigateur impose même à l'intérieur
     d'une grille. À taille de texte agrandie, elle poussait la carte, puis la
     page, hors de l'écran. Ces deux lignes la neutralisent. */
  width: 100%; min-width: 0;
  min-height: 3.25rem; /* 52 px : au-dessus du plancher, un doigt âgé vise moins bien */
  padding: 0.6rem 0.85rem;
  font-family: inherit;
  /* 1rem au minimum, jamais moins : en dessous de 16 px, iOS zoome tout seul
     au moment de la saisie et la page part de travers. */
  font-size: 1.0625rem;
  color: var(--encre);
  background: var(--papier);
  border: 1.5px solid var(--bord-champ);
  border-radius: var(--arrondi);
}
.champ input:hover { border-color: var(--encre-doux); }
.champ input[aria-invalid="true"] { border-color: var(--erreur); border-width: 2px; }

/* LA CASE À COCHER DES CONDITIONS. Deux colonnes plutôt que la grille d'une
   seule du `.champ` ordinaire : la case à gauche, la phrase à droite, et
   l'erreur en dessous sur toute la largeur.

   `width` et `min-height` sont REPRIS à la règle `.champ input`, qui étire
   toute entrée sur 100 % et lui impose 52 px de haut : appliquées à une case
   à cocher, elles donnaient une case étalée sur toute la ligne.

   24 px de côté est le plancher WCAG 2.2 pour une cible, et l'étiquette
   entière reste cliquable — c'est elle, en pratique, qui sert de cible. */
.champ-case { grid-template-columns: auto 1fr; align-items: start; gap: 0.75rem; }
/* 28 px depuis le 27 août 2026, pour la même raison que les boutons radio
   plus bas : 24 était le plancher exact de WCAG 2.2, et cette case est celle
   qui accepte les conditions de vente. */
.champ-case input[type="checkbox"] {
  width: 1.75rem; min-width: 1.75rem;
  height: 1.75rem; min-height: 1.75rem;
  margin: 0.1rem 0 0; padding: 0;
  accent-color: var(--voix);
  cursor: pointer;
}
/* Une case invalide ne montre pas sa bordure comme un champ de texte : le
   navigateur dessine la case lui-même. L'anneau extérieur est donc le seul
   signal visible, et il double le mot d'erreur, jamais il ne le remplace. */
.champ-case input[aria-invalid="true"] { outline: 2px solid var(--erreur); outline-offset: 3px; }
.champ-case label { font-weight: 400; font-size: 1rem; line-height: 1.5; cursor: pointer; }
.champ-case .champ-erreur { grid-column: 1 / -1; }

.champ-aide { font-size: var(--t-petit); color: var(--encre-doux); }
/* L'erreur est SOUS le champ concerné et rattachée à lui par
   `aria-describedby` : un récapitulatif en haut de page ne dit pas lequel des
   champs est en cause. Elle se signale aussi par un mot, pas par la seule
   couleur du cadre. */
.champ-erreur { font-size: var(--t-petit); color: var(--erreur); font-weight: 600; }
.champ-erreur:empty { display: none; }

.separateur {
  display: flex; align-items: center; gap: 1rem;
  margin: 1.5rem 0;
  color: var(--encre-doux); font-size: var(--t-petit);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.separateur::before, .separateur::after {
  content: ""; flex: 1; height: 1px; background: var(--filet-2);
}

.identites { display: grid; gap: 0.75rem; }

/* Message d'état du formulaire. `aria-live` dans le HTML : ce qui apparaît ici
   doit être entendu, pas seulement vu. */
.message { margin-top: 1.25rem; font-size: 1rem; font-weight: 600; }
.message:empty { display: none; }
.message[data-etat="erreur"] { color: var(--erreur); }
.message[data-etat="info"] { color: var(--encre-doux); }

/* L'étape du code n'est pas montée tant que l'adresse n'est pas donnée :
   le parcours réel se fait en deux temps, et le montrer d'un bloc mentirait
   sur l'écran qu'aura la personne. */
.etape[hidden] { display: none; }
.etape-rappel {
  background: var(--papier-2);
  border-radius: var(--arrondi);
  padding: 0.75rem 0.9rem;
  font-size: 1rem;
  margin-bottom: 1.25rem;
}

/* Choix de la formule à la création du compte. De vrais boutons radio, agrandis
   et rendus visibles : un choix qui ne se voit pas ne se fait pas. */
/* Un groupe de boutons radio est un `fieldset` avec sa `legend` : c'est ce qui
   fait annoncer « Votre rythme, 1 sur 2 » à un lecteur d'écran au lieu de deux
   choix isolés dont on ne sait pas ce qu'ils comparent.
   `min-inline-size: 0` retire la largeur minimale héritée que `fieldset` porte
   depuis toujours, et qui l'empêche de se resserrer sur un téléphone. */
.choix-groupe {
  border: 0; padding: 0; margin: 0 0 var(--espace-grille);
  min-inline-size: 0;
}
.choix-groupe legend {
  padding: 0; margin-bottom: 0.75rem;
  font-family: var(--font-titre); font-size: var(--t-h3); font-weight: 600;
}

.choix { display: grid; gap: 0.75rem; margin-bottom: 1.5rem; }
.choix label {
  display: grid; grid-template-columns: auto 1fr; gap: 0.85rem; align-items: start;
  border: 1.5px solid var(--bord-champ);
  border-radius: var(--arrondi);
  padding: 1rem;
  cursor: pointer;
}
/* 28 px, relevé du plancher le 27 août 2026. La règle WCAG 2.2 sur la taille
   des cibles s'arrête à 24, et ces boutons y étaient EXACTEMENT : conformes,
   mais au minimum absolu. Le commentaire d'origine avait déjà nommé la gêne
   sans la corriger — « un bouton radio qu'on vise mal reste un bouton radio
   qu'on vise mal ». Or cette page est celle où une fille de 55 ans souscrit,
   et parfois le senior lui-même. Quatre pixels de plus ne coûtent rien à la
   mise en page et sortent la cible du plancher.

   L'étiquette entière reste cliquable, et c'est elle qui sert de cible en
   pratique. Ce relèvement vise la personne qui vise le petit cercle. */
.choix input { width: 1.75rem; height: 1.75rem; margin: 0.1rem 0 0; accent-color: var(--voix); }
.choix label:hover { border-color: var(--encre-doux); }
.choix input:checked + span { font-weight: 600; }
/* Le cadre suit la sélection. `:has()` est une amélioration : sans lui, le
   bouton radio coché reste la marque de la sélection, ce qui suffit. */
.choix label:has(input:checked) { border-color: var(--encre); border-width: 2px; padding: calc(1rem - 0.5px); }
.choix-detail { display: block; font-size: var(--t-petit); color: var(--encre-doux); font-weight: 400; }

/* ---------- Étapes numérotées (comment ça marche) ---------- */
/* Le numéro est ici légitime : ce sont des étapes qui s'enchaînent vraiment,
   dans cet ordre, et le lecteur a besoin de l'ordre. Ailleurs sur ce site il
   n'y a pas de « 01 / 02 / 03 » décoratif. */
.etapes { display: grid; gap: var(--espace-bloc); margin-top: var(--espace-bloc); counter-reset: etape; }
.etape-bloc {
  position: relative;
  padding-left: 3.25rem;
  counter-increment: etape;
}
.etape-bloc::before {
  content: counter(etape);
  position: absolute; left: 0; top: -0.1em;
  width: 2.4rem; height: 2.4rem;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--filet-2);
  border-radius: 50%;
  font-family: var(--font-titre); font-weight: 600; font-size: 1.05rem;
  color: var(--voix);
}
.etape-bloc p { color: var(--encre-doux); }
.etape-bloc p:first-of-type { margin-top: 0; }

/* ---------- Fondateurs ---------- */
.fondateurs { display: grid; gap: var(--espace-bloc); margin-top: var(--espace-bloc); }
@media (min-width: 48em) {
  .fondateurs { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: var(--espace-grille); }
}
/* Un filet plutôt qu'une carte : la section est claire, et deux cartes posées
   là feraient un tableau de trombinoscope. */
.fondateur { border-left: 3px solid var(--filet-2); padding-left: var(--espace-carte); }
.fondateur .chapeau { margin-bottom: 0.35rem; }
.fondateur p { color: var(--encre-doux); }

/* ---------- Ce qui viendra ensuite ---------- */
/* Même grille et même filet que les fondateurs, et c'est le fond de l'affaire :
   une carte encadrée ferait ressembler une piste à une fonctionnalité livrée.
   Un filet à gauche pose une note en marge, ce que ces paragraphes sont. */
.suites { display: grid; gap: var(--espace-bloc); margin-top: var(--espace-bloc); }
@media (min-width: 48em) {
  .suites { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: var(--espace-grille); }
}
.suite { border-left: 3px solid var(--filet-2); padding-left: var(--espace-carte); }
.suite p { color: var(--encre-doux); }

/* ---------- Pages légales ---------- */
.legal { max-width: 44rem; }
.legal h2 { font-size: var(--t-h3); margin-top: var(--espace-bloc); }
.legal h2:first-of-type { margin-top: 0; }
.legal ul { padding-left: 1.25rem; }
.legal li { margin-bottom: 0.5rem; }

/* Emplacement d'une valeur juridique manquante.

   VOLONTAIREMENT HORS DU MODE « chantier » : ces trous-là ne disparaissent
   jamais tout seuls. Un faux numéro SIREN sur un site marchand n'est pas du
   texte de remplissage, c'est une fausse mention légale, et un cadre gris
   oublié serait moins grave que le contraire. Tant qu'il en reste un, le site
   ne peut pas être mis en ligne. */
.a-fournir {
  display: inline;
  background: var(--papier-2);
  border-bottom: 2px solid var(--voix);
  padding: 0.1em 0.4em;
  font-family: var(--font-texte);
  font-size: 0.9em; font-weight: 600;
  color: var(--voix);
}

/* ---------- Pied de page ---------- */
/* EN COULEUR PLEINE, demandé le 20 août. C'est le bas de page qui porte les
   mentions légales, les conditions de vente et la confidentialité, autrement
   dit ce qu'on cherche exprès quand on le cherche. Un aplat de marque le rend
   trouvable d'un coup d'œil au lieu de le laisser se dissoudre dans un crème.

   Les jetons sont redéfinis LOCALEMENT plutôt que dans une liste de règles
   descendantes : tout ce qui vit ici lit déjà var(--encre-doux) et var(--filet),
   donc il suffit de changer ce que ces noms désignent à l'intérieur du pied.
   Une seule redéfinition, et le pied entier suit, titres, notes, liens, filets.

   Rapports calculés sur --voix #7C2F4A : --papier 8,46:1, le secondaire
   #E9CDD6 6,00:1. */
.pied {
  background: var(--voix);
  color: var(--papier);
  /* Resserré le 27 août 2026 : `--espace-bloc` donnait 52 px en haut et en
     bas au bureau, le réglage d'une SECTION de contenu. Le pied n'est pas une
     section, c'est une fin de page. */
  padding-block: clamp(1.25rem, 0.8rem + 1.4vw, 1.75rem);

  /* LA CIBLE TACTILE DU PIED, ET SEULEMENT DU PIED : 36 px au lieu des 44 du
     reste du site. C'est le seul vrai levier sur la hauteur — six rangées de
     liens à 44 px font 264 px à elles seules, et aucune réduction de police
     n'y change quoi que ce soit.

     Pourquoi c'est défendable ici et nulle part ailleurs : 44 px est la
     recommandation d'Apple et le niveau AAA ; le minimum exigé par WCAG 2.2 au
     niveau AA est de 24 px. À 36 on reste 50 % au-dessus de l'obligation, sur
     onze liens qu'on clique rarement et qui ne sont pas dans un parcours
     d'achat. Les boutons, les champs de formulaire et les cases à cocher
     gardent leurs 44 px : `--tap` global n'est pas touché, celui-ci ne vit
     que dans le pied. */
  --tap-pied: 32px;

  --encre: var(--papier);
  --encre-doux: var(--voix-dim);
  --filet: var(--voix-filet);
  --filet-2: var(--voix-filet);
}

/* Le H et le V du nom sont en --voix partout ailleurs. Sur un pied EN --voix,
   ils disparaissaient purement et simplement : le nom se lisait « éritage
   ivant ». C'est le défaut que le README du logo décrit pour le rose sur le
   papier, rencontré ici en miroir, la preuve qu'une couleur de marque posée
   sans regarder son fond casse le nom de la marque elle-même.

   Le geste est donc inversé plutôt que supprimé : sur la couleur, les capitales
   sont ce qu'il y a de plus CLAIR, --papier à 8,46:1, et le reste du nom
   passe au ton secondaire à 6,00:1. Les deux lettres continuent de se détacher,
   par l'autre bout de l'échelle. */
.pied .marque-cap { color: var(--papier); }
.pied-mot { color: var(--encre-doux); }
.pied-rang { display: grid; gap: var(--espace-grille); }
@media (min-width: 48em) {
  .pied-rang { grid-template-columns: 1.4fr 1fr 1fr; }
}
/* 13 px depuis le 27 août 2026, contre 17 avant. Un intitulé de colonne du
   pied est une ÉTIQUETTE : il nomme une liste, il ne se lit pas. En capitales
   à 17 px il pesait presque autant que les liens qu'il annonçait. */
.pied h2 { font-size: 0.8125rem; font-family: var(--font-texte); letter-spacing: 0.07em; text-transform: uppercase; color: var(--encre-doux); margin-bottom: 0.6rem; }
.pied ul { list-style: none; margin: 0; padding: 0; }
/* Chaque lien du pied garde sa hauteur de cible tactile : c'est là que se
   trouvent les mentions légales, et on les cherche souvent au doigt. */
/* Hauteur obtenue par un `padding` et non par un `inline-flex` : le texte d'un
   `inline-flex` ne se coupe jamais en fin de ligne, et « Conditions générales
   de vente » élargissait alors la colonne du pied, puis la page entière,
   dès que le texte était agrandi. */
.pied li a {
  display: inline-block;
  /* 16 px depuis le 27 août 2026, contre 19 avant. Ils héritaient du corps de
     texte de la page, ce qui les rendait PLUS GROS que les intitulés de
     colonne au-dessus d'eux et aussi gros que le texte courant : une
     navigation secondaire dominait ce qu'elle sert. Mesuré, pas ressenti.

     Le plancher de 18 px du brief vise le texte qu'on LIT, un paragraphe
     entier, et le lecteur âgé qui le lit. Ici ce sont onze libellés de deux à
     quatre mots qu'on cherche du regard, sur la seule surface du site où la
     hiérarchie doit descendre. La cible tactile, elle, ne bouge pas d'un
     pixel : le `padding` ci-dessous se calcule en `em`, donc il grandit
     exactement de ce que la police perd, et le lien garde ses 44 px. */
  font-size: 1rem;
  padding-block: calc((var(--tap-pied) - 1.7em) / 2);
  text-decoration: none;
  /* `anywhere` et non `break-word` : seul le premier réduit aussi la largeur
     minimale du bloc. Sans lui, « contact@heritagevivant.fr », un mot de
     vingt-cinq caractères sans aucune coupure possible, imposait 442 px à la
     colonne du pied, donc à la page entière, dès que le texte était agrandi. */
  overflow-wrap: anywhere;
}
/* Le survol ne peut plus passer à --voix : le pied EST sur --voix, le lien
   deviendrait invisible. Il passe au papier plein et se souligne. */
.pied li a:hover { color: var(--papier); text-decoration: underline; }
.pied-mot { font-family: var(--font-titre); font-size: 1.25rem; font-weight: 600; margin-bottom: 0.2rem; }
/* La devise, juste sous le nom, avant la note d'hébergement. Elle est ici à
   TOUTES les largeurs, contrairement à l'en-tête, où la place manque sous
   62em. Le pied est la seule surface du site où une phrase de marque a de la
   place et du calme autour d'elle. */
.pied-devise { font-size: 0.9375rem; color: var(--encre-doux); margin-bottom: 0.6rem; }
/* La note s'élargit à 34 rem depuis le 27 août 2026. Elle ne change pas de
   corps : elle passe simplement de TROIS lignes à deux dans la colonne de
   marque, ce qui retire une ligne à la hauteur du pied sans retirer un mot au
   texte. La mention de l'hébergement européen n'a pas à rétrécir. */
.pied-note { font-size: var(--t-petit); color: var(--encre-doux); max-width: 34rem; line-height: 1.55; }

/* L'identification de l'éditeur, ajoutée le 30 août 2026. Ce n'est PAS une page
   de mentions légales et cela n'en tient pas lieu : celles-ci exigent aussi une
   adresse, et publier le domicile du fondateur est une décision qui n'est pas
   prise — voir `docs/PAGES_LEGALES.md`. Cette ligne referme le seul trou qu'on
   pouvait fermer sans rien exposer : jusqu'ici, rien sur le site ne disait qui
   l'édite.

   Exactement la même couleur et le même corps que .pied-note au-dessus, dont le
   contraste est déjà validé sur ce fond. Une mention d'identification n'a pas à
   être pâle : la pâlir pour la ranger visuellement lui retirerait la lisibilité
   qui est sa seule raison d'être. Seule la marge la sépare. */
.pied-editeur { font-size: var(--t-petit); color: var(--encre-doux); max-width: 34rem; line-height: 1.55; margin-top: 0.6rem; }

/* ============================================================
   Mouvement

   Deux règles non négociables, tenues partout dans ce bloc :

   1. `prefers-reduced-motion` respecté, tout ce qui bouge est enfermé dans
      `no-preference`.

   2. L'ÉTAT AU REPOS EST L'ÉTAT VISIBLE. Aucune apparition ne part
      d'`opacity: 0` sur un bloc : dans un onglet dont le rendu est suspendu,
      l'animation ne progresse pas et la page reste blanche. Ce projet s'est
      déjà fait prendre. On anime donc la POSITION, jamais l'existence, et
      même si le script meurt, le pire qui puisse arriver est un bloc décalé
      de vingt pixels, lisible.
   ============================================================ */

/* Enchaînement d'une page à l'autre. Amélioration progressive : les
   navigateurs qui ignorent la règle rechargent comme avant. Les neuf pages
   partagent cette feuille, donc l'accord est déclaré des deux côtés. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.35s;
  animation-timing-function: var(--doux);
}
/* Ces pseudo-éléments vivent hors de l'arbre du document : la coupure globale
   du mouvement, plus haut, ne les atteint pas. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* Apparition d'un bloc, un décalage qui se résorbe, sans fondu.
   Le préfixe `.js-reveal` est posé sur <html> par un script en tête de page :
   rien ne se décale s'il n'y a personne pour remettre en place. */
@media (prefers-reduced-motion: no-preference) {
  .js-reveal .reveal {
    transform: translateY(1.25rem);
    transition: transform 0.9s var(--sortie);
  }
  .js-reveal .reveal.est-visible { transform: none; }

  /* Cascade : les enfants arrivent l'un après l'autre. Le pas est court,
     un décalage trop marqué fait traîner la lecture au lieu de l'ouvrir. */
  .js-reveal .cascade > * {
    transform: translateY(0.9rem);
    transition: transform 0.75s var(--sortie);
  }
  .js-reveal .cascade.est-visible > * { transform: none; }
  .js-reveal .cascade.est-visible > :nth-child(2) { transition-delay: 0.07s; }
  .js-reveal .cascade.est-visible > :nth-child(3) { transition-delay: 0.14s; }
  .js-reveal .cascade.est-visible > :nth-child(4) { transition-delay: 0.21s; }
  .js-reveal .cascade.est-visible > :nth-child(5) { transition-delay: 0.28s; }

  /* Le filet de citation se déploie de haut en bas quand le bloc arrive : le
     geste de la parole qu'on remonte à sa source. Il part de 0,15 et non de 0
    , au repos il reste donc une marque visible, jamais un filet absent. */
  .js-reveal .reveal .citation::before,
  .js-reveal .cascade .citation::before {
    transform: scaleY(0.15);
    transform-origin: top center;
    transition: transform 1s var(--sortie) 0.1s;
  }
  .js-reveal .est-visible .citation::before { transform: scaleY(1); }
}
