/* ==========================================================================
   FINAMI - Composants
   Implementation CSS des composants releves dans Figma (page « DS » +
   les 7 gabarits de la page « Maquettes »), revalides le 2026-09-03.
   Depend de finami-tokens.css. Ecriture mobile-first : les valeurs desktop
   sont appliquees a partir de --fn-bp-md (768px) ou --fn-bp-lg (1024px).

   Arbitrage du 2026-09-03 : Figma fait foi contre le prototype Claude Design
   (cf. l'en-tete de finami-tokens.css). Version prototype dans
   archive/prototype/.
   ========================================================================== */

/* -------------------------------------------------------------------- BASE */

/* `width: 100%` plus un padding lateral, en content-box, deborde de la valeur
   du padding : c'est ce qui poussait toute la page 40 px hors de l'ecran en
   mobile. La remise a zero est portee par :where() pour ne primer sur rien. */
:where(.fn),
:where(.fn) *,
:where(.fn) *::before,
:where(.fn) *::after { box-sizing: border-box; }

body.fn {
  margin: 0;
  background: var(--fn-surface-page);
  color: var(--fn-text);
  font-family: var(--fn-font-body);
  font-size: var(--fn-size-14);
  font-weight: var(--fn-weight-regular);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
  -webkit-font-smoothing: antialiased;
}

/* :where() et non `.fn a` : la regle vaut heritage par defaut, elle ne doit
   pas primer sur l'intention d'un composant. Un `.fn-btn--primary` pose sur
   un `<a>` sortait sinon en texte sombre sur fond bleu nuit — invisible. */
:where(.fn) a { color: inherit; }
.fn img { max-width: 100%; display: block; }

.fn-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* ------------------------------------------------------------ TYPOGRAPHIE
   Chaque classe correspond a un style effectivement utilise dans Figma.    */

.fn-display-404,
.fn-hero-title,
.fn-page-title,
.fn-title,
.fn-article-title,
.fn-post-title,
.fn-menu-title {
  font-family: var(--fn-font-heading);
  font-weight: var(--fn-weight-xbold);
  line-height: var(--fn-leading-tight);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

/* Le titre du 404 est le seul style a passer de 52 a 92 : Figma le dessine a
   52 en mobile (400:3594) et a 92 en desktop (400:3450). */
.fn-display-404 { font-size: var(--fn-size-52); }        /* page 404, mobile */

/* ⚠️ **Ecart 32, trois emplois sur huit soldes le 2026-09-08.** L'index du blog
   donne enfin des boites pour `.fn-hero-title` et `.fn-title`, et la carte
   article pour `.fn-article-card__title` — c'etait la condition posee : « d'un
   seul mouvement et contre des boites, pas au fil de la page ».

     .fn-hero-title  387:1256   830 x 124 = 2 x 62 en Barlow 52  -> 1,1875
                     400:2724   350 x  76 = 2 x 38 en Barlow 32  -> 1,1875
     .fn-title       400:1736  1074 x  38 = 1 x 38 en Barlow 32  -> 1,1875
     .fn-article-card__title  400:1744  253 x 38 = 2 x 19 en Barlow 16 -> 1,1875

   Les trois passent donc a `--fn-leading-barlow`. **Cela deplace l'accueil et
   le tunnel**, qui les emploient : chiffre au chapitre 4.10 du README.

   ⚠️ **Les cinq derniers emplois mesurables ont ete soldes le 2026-09-08 au
   soir**, et trois d'entre eux sont du **Lato** : `.fn-menu-title` (552:3612,
   boite 36) et `.fn-feature-title` (216:2924, boite 19) passent a
   `--fn-leading-barlow` ; `.fn-card-title` (216:2687, boite 24),
   `.fn-subhead` (400:3332, boite 19) et `.fn-stat-card__value` (216:2661,
   boite 50) passent a `--fn-leading-lato`. Ne restent en 1,1 que
   `.fn-display-404` et `.fn-article-title`, faute de boite — plus
   `.fn-caption` et les deux lignes du raccourci de hero, non mesurees.    */
.fn-hero-title  { font-size: var(--fn-size-32); line-height: var(--fn-leading-barlow); }  /* hero mobile */

/* Le titre du hero est fait de deux lignes, chacune un bloc — c'est ainsi que
   Figma le construit, aux deux tailles d'ecran. Un <br> tenu en dur ferait
   deborder les 390 px du mobile, ou il doit s'enrouler sur trois lignes. */
.fn-hero-title span { display: block; }
.fn-title       { font-size: var(--fn-size-32); line-height: var(--fn-leading-barlow); }  /* titre de section */

/* Titre de page des gabarits interieurs : 36 en mobile, 52 en desktop.
   Le corps mobile ne se lit pas dans le fichier — `get_design_context` pend
   depuis le 2026-09-03 —, il se deduit de deux mesures concordantes :
   « Note legali » fait 236 x 62 en desktop (400:3374) et 164 x 43 en mobile
   (400:3420). Le **rapport des largeurs** de la meme chaine vaut 1,4390 et
   celui des hauteurs 1,4419 : 52 / 1,439 = 36,1. La premiere de ces deux
   mesures ne suppose aucun interlignage, et le gabarit « Formulaire »
   (216:3433) donnait deja 36 sur « Prestito Personale ». C'est ce qui solde
   l'ecart 22 du chapitre 5 du README, ouvert le 2026-09-03 faute d'une
   deuxieme mesure.                                                        */
.fn-page-title  {
  font-size: var(--fn-size-36);
  /* `--fn-leading-tight` (1,1) rendrait la boite du titre 5 px trop courte
     et l'en-tete entier 232 au lieu de 236 : c'est l'interlignage « auto »
     de Barlow qu'il faut ici, et c'est un rapport, donc il vaut aux deux
     corps. L'ecart entre 1,1 et 1,1875 vaut pour tous les titres du
     projet — ecart 32 du chapitre 5 du README, non traite ici. */
  line-height: var(--fn-leading-barlow);
}
.fn-article-title { font-size: var(--fn-size-22); }      /* intertitre editorial */
/* Titre d'un article : Barlow ExtraBold 26, interligne « auto » de Barlow, et
   **le meme corps aux deux largeurs** — 391 x 62 en desktop (400:1400, deux
   lignes) et 350 x 93 en mobile (400:1800, trois lignes), soit un pitch de 31
   de part et d'autre. Voir `--fn-size-26`.                                 */
.fn-post-title  { font-size: var(--fn-size-26); line-height: var(--fn-leading-barlow); }
/* Ecart 32, cinquieme emploi : les cinq liens du menu plein ecran font
   290 x **36** (552:3612 et suivants, ecartes de 20), et 30 x 1,1875 =
   35,625, que Figma arrondit a 36. A 1,1 ils rendaient 33, et le bloc des
   cinq 245 pour 260. */
.fn-menu-title  { font-size: var(--fn-size-30); line-height: var(--fn-leading-barlow); }

/* Titre de carte et intertitre de footer : Lato Bold, pas Barlow */
.fn-card-title {
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-20);
  /* Ecart 32, et le piege du lot : ce titre est du **Lato**, pas du Barlow —
     `--fn-leading-barlow` n'a donc rien a y faire. Sa boite est de 24 pour un
     corps de 20 (216:2687, « Prestito Personale »), soit 1,2 : l'interlignage
     « auto » de Lato. A 1,1 il rendait 22. */
  line-height: var(--fn-leading-lato);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

/* Ecart 32, cote Lato : la boite de « Navigazione » fait 85 x **19** pour un
   corps de 16 (400:3332 et 216:3353, identiques aux deux largeurs), soit
   16 x 1,2 = 19,2. A 1,1 elle rendait 17,59. */
.fn-subhead {                       /* « Navigazione » dans le footer */
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-16);
  line-height: var(--fn-leading-lato);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

.fn-lead {                          /* chapo du hero */
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-16);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

.fn-body      { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); }
.fn-body-lg   { font-size: var(--fn-size-15); line-height: var(--fn-leading-large); }
.fn-body-bold { font-weight: var(--fn-weight-bold); }
.fn-micro     { font-size: var(--fn-size-12); line-height: var(--fn-leading-body); }
.fn-caption   { font-size: var(--fn-size-10); line-height: var(--fn-leading-tight); }
.fn-eyebrow   {                     /* sur-titre vert des cartes produit */
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  color: var(--fn-text-accent);
  margin: 0;
}
.fn-meta      { font-size: var(--fn-size-14); color: var(--fn-text-muted); }

/* Contenu editorial : n'habiller que l'interieur de .fn-prose.

   Releve le 2026-09-07 dans le gabarit « Mentions legales » (400:2957) —
   colonne 400:2972 en desktop, 400:3389 en mobile. Les deux largeurs donnent
   les memes corps et les memes ecarts : une page editoriale n'a **aucune**
   bascule typographique.

   La hierarchie du fichier tient sur trois niveaux, et le troisieme n'est pas
   un titre :

     h2   Barlow ExtraBold 22 / 26   titre de bloc
     h3   Lato Bold 14 / 20          intertitre, au corps du texte courant
     p    Lato 400 14 / 20

   Ecarts mesures : 30 entre deux blocs, 10 d'un titre a son texte, 20 entre
   deux paragraphes, **0** sous un intertitre — son texte suit a la ligne
   suivante.

   Ces niveaux sont deduits, non lus : Figma coule chaque bloc dans un SEUL
   noeud de texte a runs mixtes (400:3071, 400:3077), ou les intertitres sont
   en gras et les lignes vides font les separations. Le balisage rend cette
   structure en elements ; l'aspect, lui, est mesure au pixel sur la capture
   (pitch des lignes de base : 26 sur les titres, 20 partout ailleurs, 40 la
   ou le fichier laisse une ligne vide).                                    */
.fn-prose { max-width: var(--fn-container-prose); }

.fn-prose h2 {
  font-family: var(--fn-font-heading);
  font-weight: var(--fn-weight-xbold);
  font-size: var(--fn-size-22);
  line-height: var(--fn-leading-barlow);
  letter-spacing: var(--fn-tracking);
}

/* Lato Bold au corps du texte courant : ce n'est pas un titre reduit, c'est
   une ligne de texte en gras. Mesure sur « Con ipoteca (per proprietari
   immobiliari) » (400:3405) : meme pitch de 20 que les lignes qui suivent, et
   aucun blanc entre les deux. Un h3 en Barlow 22, comme le portait la version
   prototype de cette feuille, donnait un troisieme niveau de titre que le
   fichier ne dessine pas. */
.fn-prose h3 {
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
}

.fn-prose p,
.fn-prose ul,
.fn-prose ol {
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
}
/* Le gabarit annonce deux listes — « Ecco i casi piu frequenti: », « Ecco i
   documenti generalmente richiesti » — et n'en dessine aucune (ecart 29).
   Les valeurs ci-dessous sont donc du prolongement d'echelle, pas un releve :
   le pas de la trame en retrait, l'interlignage du texte courant. */
.fn-prose ul,
.fn-prose ol { padding-left: var(--fn-space-20); }
.fn-prose li { margin: 0; }

.fn-prose strong { font-weight: var(--fn-weight-bold); }
.fn-prose a { color: var(--fn-text-link); text-decoration: underline; }

/* Le rythme vertical se pose **en haut** des elements, jamais en bas : c'est
   la seule facon de ne pas cumuler la marge basse d'un paragraphe avec la
   marge haute du titre suivant — 20 + 30 rendraient 50 la ou Figma pose 30 —
   et de laisser le dernier element du bloc a ras du fond sable.

   L'ordre des quatre regles compte, elles ont toutes le meme poids : c'est la
   derniere qui gagne. « Nouveau bloc » (30) doit donc passer apres
   « intertitre collant » (0), sinon un h2 pose juste apres un h3 perdrait sa
   respiration. */
.fn-prose > * { margin: 0; }
.fn-prose > * + *  { margin-top: var(--fn-space-20); }  /* ligne vide */
.fn-prose > h2 + * { margin-top: var(--fn-space-10); }  /* titre -> texte */
.fn-prose > h3 + * { margin-top: 0; }                   /* intertitre -> texte */
.fn-prose > * + h2 { margin-top: var(--fn-space-30); }  /* nouveau bloc */

@media (min-width: 768px) {
  .fn-hero-title { font-size: var(--fn-size-52); }
  .fn-page-title { font-size: var(--fn-size-52); }
  .fn-display-404 { font-size: var(--fn-size-92); }
  .fn-lead { font-size: var(--fn-size-18); }
}

/* ------------------------------------------------------------------ LAYOUT */

.fn-container {
  width: 100%;
  /* --fn-container est la largeur du *contenu* relevee dans Figma (1920 moins
     2 x 360) : la gouttiere s'ajoute par-dessus, sinon la page rend 40 px trop
     etroit. */
  max-width: calc(var(--fn-container) + 2 * var(--fn-gutter));
  margin-inline: auto;
  padding-inline: var(--fn-gutter);
}
.fn-container--prose { max-width: calc(var(--fn-container-prose) + 2 * var(--fn-gutter)); }
/* Troisieme mesure plus etroite que le conteneur, apres la carte des etapes
   (1025) et la grille des avantages (1078) : l'index du blog et la bande
   « Articoli correlati » posent leurs cartes dans **1074** = 4 x 253,33 +
   3 x 20 (387:1262 et 400:1737, tous deux a x = 423,33 dans 1920).       */
.fn-container--blog  { max-width: calc(var(--fn-container-blog) + 2 * var(--fn-gutter)); }

/* Rythme vertical : la valeur par defaut est celle de la section « produits »
   (40 en haut, 60 en bas). Les autres sections de l'accueil emploient des
   valeurs propres, d'ou les trois modificateurs. */
.fn-section {
  padding-block: var(--fn-space-40) var(--fn-space-60);
}
.fn-section--even  { padding-block: var(--fn-space-50); }  /* « Come funziona » */
/* Bandeau de chiffres cles : 40 aux deux bords, et aux deux largeurs —
   216:2659 et 216:3051 font 200 pour des cartes de 120 posees a y = 40. Il
   portait `--even` (50), qui est le retrait de « Come funziona » : +20 sur la
   bande. */
.fn-section--band  { padding-block: var(--fn-space-40); }
.fn-section--roomy { padding-block: var(--fn-space-70); }  /* « Perche scegliere » */
/* Encart legal. Le retrait bas est **desktop seulement** : le panneau remplit
   la section au pixel en mobile (216:3339 et 216:3340 font tous deux 506, et
   le pied de page suit sans intervalle), la ou le desktop lui reserve 50
   (216:2963 = 270 pour un panneau de 220). Les 50 rendus en mobile etaient
   tout l'ecart de la section. */
.fn-section--tail  { padding-block: 0; }
@media (min-width: 768px) {
  .fn-section--tail { padding-block: 0 var(--fn-space-50); }
}
.fn-section--sand  { background: var(--fn-surface-sand); }
/* Le tunnel y ramene le regard a chaque etape (`land()` de richiesta.js) :
   sans cette marge, le haut de l'etape — barre de progression, titre, ou
   l'anneau de l'ecran final — passait sous l'en-tete collant. */
.fn-section--sand  { scroll-margin-top: var(--fn-navbar-height); }

/* Pastille + titre + sous-titre centres. ⚠️ **Le fichier pose deux ecarts, pas
   un.** L'en-tete a pastille de « prodotti » (216:2674) espace la pastille du
   titre de 20 et le titre du sous-titre de **10** ; les deux en-tetes sans
   pastille — « Come funziona » (355:3095) et « Perche scegliere » (216:2915),
   tous deux 78 = 38 + 20 + 20 — espacent le titre du sous-titre de **20**.
   L'ecart de base est donc le grand, et un en-tete a pastille le resserre. La
   regle anterieure, deduite du seul « prodotti », rendait ces deux en-tetes
   10 px trop courts. */
.fn-section__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-20);
  text-align: center;
}
.fn-section__header:has(.fn-badge) { gap: var(--fn-space-10); }
/* ⚠️ **Cinquieme bascule typographique**, et la seule qui manquait : le titre
   de section mobile est du Barlow **28**, pas 32. Mesure par le rapport des
   largeurs de la meme chaine, la methode qui a solde l'ecart 22 — elle ne
   suppose aucun interlignage, et trois chaines concordent :

     « Quale soluzione fa per te? »  351 -> 307   = 0,8746
     « Come funziona il servizio »   338 -> 296   = 0,8757
     « Perche scegliere Finami »     327 -> 287   = 0,8777

   soit 0,875 = 28 / 32. Les trois boites mobiles font 34, et 28 x 1,1875 =
   33,25, que Figma arrondit a 34. A 32 le titre rendait 38 : +4 par en-tete.
   La bascule est portee par `.fn-section__header .fn-title` et non par
   `.fn-title`, parce que la mesure ne porte que sur des en-tetes de section :
   le « Articoli correlati » de l'article est un `.fn-title` nu, et le fichier
   le laisse a 38 en mobile (400:1906). */
.fn-section__header .fn-title { font-size: var(--fn-size-28); }
/* Le sous-titre est un `<p>` : en flux flex sa marge par defaut ne fusionne
   pas, elle s'ajoute au `gap` et se pose en fin de bloc — +28 par en-tete, sur
   les trois sections qui en portent un. Huitieme rencontre du piege, et la
   cause systematique de l'ecart 34. */
.fn-section__header > * { margin: 0; }
.fn-section__header .fn-badge + .fn-title { margin-top: var(--fn-space-10); }
.fn-section__header + * { margin-top: var(--fn-space-30); }
@media (min-width: 768px) {
  .fn-section__header .fn-title { font-size: var(--fn-size-32); }
}
.fn-section--roomy .fn-section__header + * { margin-top: var(--fn-space-50); }

.fn-divider {
  height: 1px;
  background: var(--fn-border-subtle);
  border: 0;
  margin: 0;
}

/* ------------------------------------------------------------------ NAVBAR */

.fn-navbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-20);
  padding: var(--fn-space-20) var(--fn-gutter);
  background: var(--fn-surface-page);
  /* Le filet en ombre interieure, et non en `border-bottom` : le fichier donne
     96 de navbar pour un contenu de 56 pose a y = 20 (216:2602 / 439:499),
     soit un retrait de 20 filet compris. Une bordure rendait 97. */
  box-shadow: inset 0 calc(-1 * var(--fn-border-width)) 0 var(--fn-surface-muted),
              var(--fn-shadow-sm);
}
/* Le logo occupe une boite de 117 x 56 dans les maquettes (439:499), le trace
   faisant 83,87 x 24,63 : la boite est donc plus grande que le dessin,
   volontairement. Le pied de page a la **meme** boite mais un mot plus grand —
   voir .fn-footer__brand img. */
.fn-navbar__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 117px;
  height: 56px;
}
.fn-navbar__logo img { width: auto; height: 25px; }

/* Desktop : les trois pilules produit. Mobile : le bouton burger. */
.fn-navbar__nav { display: none; gap: var(--fn-space-10); }

.fn-navbar__burger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fn-text);
  cursor: pointer;
}
.fn-navbar__burger svg { width: 30px; height: 30px; }

@media (min-width: 1024px) {
  .fn-navbar {
    padding-inline: max(var(--fn-gutter), calc((100% - var(--fn-container)) / 2));
  }
  .fn-navbar__nav { display: flex; }
  .fn-navbar__burger { display: none; }
}

/* Menu burger plein ecran (mobile).
   `display: flex` bat la regle `[hidden] { display: none }` du navigateur, qui
   n'a qu'une specificite d'attribut : sans la ligne ci-dessous, le panneau
   s'affiche par-dessus la page des le chargement. */
.fn-menu-mobile[hidden] { display: none; }
.fn-menu-mobile {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 150px;
  padding: 82px var(--fn-space-30) var(--fn-space-50);
  background: #ffffff;
}
.fn-menu-mobile__list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--fn-space-20);
  width: 100%;
  list-style: none;
  margin: 0; padding: 0;
}
.fn-menu-mobile__list a { text-decoration: none; }
.fn-menu-mobile__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fn-text);
  cursor: pointer;
}
.fn-menu-mobile__close svg { width: 30px; height: 30px; }

@media (min-width: 1024px) {
  .fn-menu-mobile { display: none; }
}

/* ----------------------------------------------------------------- BOUTONS
   Deux familles distinctes dans les maquettes :
   .fn-btn     -> action de page (CTA, navigation)
   .fn-choice  -> option de formulaire (composant Figma « bouton »)         */

.fn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Ecart 40. Le fichier pose un retrait de 14 autour d'une boite de texte
     **rognee a la hauteur de capitale** : 10 pour du Lato 14, donc
     14 + 10 + 14 = 38, et non 14 + 14 + 14 = 42. Le retrait vertical est
     porte par une hauteur plancher, comme le font depuis le 2026-09-08 les
     boutons de 40 et de 44 du fichier — un bouton sur deux lignes grandit
     alors de lui-meme. */
  min-height: 38px;
  padding-block: 0;
  padding-inline: var(--fn-space-16);
  border: 0;
  border-radius: var(--fn-radius-control);
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
  line-height: 1;
  letter-spacing: var(--fn-tracking);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--fn-duration) var(--fn-easing);
}
.fn-btn--primary {
  background: var(--fn-action-bg);
  color: var(--fn-action-fg);
}
.fn-btn--primary:hover  { background: var(--fn-action-bg-hover); }
.fn-btn--primary:active { background: var(--fn-action-bg-active); }

.fn-btn--neutral {                    /* pilule de navigation inactive */
  background: var(--fn-surface-muted);
  color: var(--fn-text);
}
.fn-btn--neutral:hover { background: var(--fn-blanc-600); }

.fn-btn--outline {
  background: transparent;
  color: var(--fn-text);
  box-shadow: inset 0 0 0 var(--fn-border-width) var(--fn-choice-border-secondary);
}
/* Meme dessin, borde de **bleu nuit** et non du vert accent. Releve dans le
   bouton WhatsApp de l'ecran de resultat du tunnel (206:1659) : fond clair,
   encre courante, bordure a la couleur d'action. `--outline` ci-dessus reste
   le borde vert du composant « bouton » de la page DS ; les deux coexistent
   parce que le fichier emploie les deux.                                   */
.fn-btn--bordered {
  background: transparent;
  color: var(--fn-text);
  box-shadow: inset 0 0 0 var(--fn-border-width) var(--fn-action-bg);
}
.fn-btn--bordered:hover { background: var(--fn-blanc-500); }   /* [PROPOSE] */
.fn-btn--block { width: 100%; }
.fn-btn[disabled], .fn-btn--disabled {
  background: var(--fn-disabled-bg);
  color: var(--fn-disabled-fg);
  cursor: not-allowed;
}
/* Les survols de variante sont plus specifiques que la regle ci-dessus
   (`.fn-btn--primary:hover` = deux classes contre une classe et un attribut) :
   sans ce rappel, un bouton eteint reprendrait sa couleur d'action des que la
   souris le frole, et se dirait cliquable. Depuis le 2026-09-21, le verrou du
   tunnel eteint « Avanti » tant que l'etape n'est pas renseignee — le cas
   n'etait pas atteignable avant.                                          */
.fn-btn[disabled]:hover,
.fn-btn[disabled]:active,
.fn-btn--disabled:hover,
.fn-btn--disabled:active {
  background: var(--fn-disabled-bg);
  color: var(--fn-disabled-fg);
}
.fn-btn:focus-visible,
.fn-choice:focus-visible,
.fn-input:focus-visible,
.fn-checkbox:focus-visible {
  outline: 2px solid var(--fn-focus-ring);
  outline-offset: 2px;
}

/* Pilule de nav : 160 de large dans les maquettes desktop, en **plancher** et
   non en largeur fixe. « Prestito Personale » et « Cessione del Quinto » font
   ~125 en Lato Bold 14 pour 128 de place (160 - 2 x 16) : le texte est en rem,
   la boite en px, et un corps de navigateur agrandi, un zoom ou un rendu de
   fonte un peu plus large les faisait passer sur deux lignes. Le libelle reste
   sur une ligne et la pilule s'elargit d'elle-meme au besoin.              */
.fn-nav-pill {
  flex-shrink: 0;
  min-width: 160px;
  white-space: nowrap;
}

/* Bouton icone (carrousel, navigation d'etapes) */
.fn-btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--fn-icon-tile);
  height: var(--fn-icon-tile);
  padding: var(--fn-space-10);
  border: 0;
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  box-shadow: var(--fn-shadow-sm);
  cursor: pointer;
}
.fn-btn-icon--soft {                  /* variante sur fond clair, sans ombre */
  background: var(--fn-surface-icon);
  box-shadow: none;
}
/* **Troisieme rencontre du meme piege** : `display: inline-flex` bat la regle
   `[hidden]` du navigateur — celle-ci vient de la feuille de l'agent, que toute
   declaration d'auteur prime, a specificite egale. Les deux fleches du
   carrousel d'articles correles sont ecrites `hidden` et revelees par le
   script ; sans cette ligne elles s'affichaient quand meme, en desktop ou elles
   n'ont rien a faire faire defiler. `.fn-menu-mobile` avait le meme defaut, et
   le menu plein ecran s'ouvrait au chargement.                             */
.fn-btn-icon[hidden] { display: none; }
.fn-btn-icon svg { width: var(--fn-icon-lg); height: var(--fn-icon-lg); }

/* Option de formulaire - composant Figma « bouton » (5 variantes) */
.fn-choice {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 59px;
  width: 100%;
  padding: var(--fn-space-14) var(--fn-space-16);
  border: 0;
  border-radius: var(--fn-radius-control);
  background: var(--fn-choice-bg);
  color: var(--fn-text);
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
  letter-spacing: var(--fn-tracking);
  cursor: pointer;
  transition: background-color var(--fn-duration) var(--fn-easing);
}
.fn-choice:hover                { background: var(--fn-choice-bg-hover); }
.fn-choice[aria-pressed="true"],
.fn-choice--selected            { background: var(--fn-choice-bg-selected); color: var(--fn-disabled-fg); }
.fn-choice--secondary           { box-shadow: inset 0 0 0 var(--fn-border-width) var(--fn-choice-border-secondary); }
/* ⚠️ Ce `--invalid`-ci reste **gris**, et ce n'est pas un oubli du passage au
   rouge du 2026-09-15 : la variante vient du fichier, partage sa regle avec
   `[disabled]` et porte `cursor: not-allowed`. Sous son nom, c'est un choix
   **indisponible**, pas un choix mal rempli. Aucun gabarit ne l'emploie. */
.fn-choice[disabled],
.fn-choice--invalid             { background: var(--fn-disabled-bg); color: var(--fn-disabled-fg); cursor: not-allowed; }

/* ------------------------------------------------------- PASTILLES / PUCES */

/* Pastille de section — **corrigee le 2026-09-08**, en relevant l'article et
   l'index du blog. Le fichier la dessine six fois, et toujours de la meme
   facon : 31 de haut, un retrait lateral de 20, du Lato Regular 16, **aux deux
   largeurs**.

     home desktop  216:2675  254 x 31   texte 214 x 11 a (20, 10)
     home mobile   216:3067  254 x 31   texte 214 x 11 a (20, 10)   -> identiques
     article       400:1396   98 x 31   texte  58 x 11 a (20, 10)
     index, tete   387:1254  152 x 31   texte 112 x 11 a (20, 10)
     index, carte  400:2846   75 x 26   texte  51 x 10 a (12,  8)   -> --sm
     etapes home   216:3176   78 x 30   texte  38 x 10 a (20, 10)   -> --bold

   Deux choses qu'il a fallu comprendre pour lire ces nombres :

   1. **les boites de texte du fichier sont rognees a la hauteur de capitale.**
      « Fase 1 » fait 10 de haut en Lato 14 (14 x 0,72 = 10,08), « Attualita »
      11 parce que son accent depasse. Une boite de 10 ou 11 ne dit donc pas
      « texte de 10 px » : elle dit « capitale de 10 px ». D'ou le retrait reel
      de 10, et une pastille de 31 et non de 38.
   2. **le corps est 16, pas 14.** Mesure d'encre a encre entre la capture 1:1
      et un rendu Chrome des memes chaines dans les memes fontes : « Mediatore
      creditizio autorizzato » fait 214 dans le fichier et 215 en Lato Regular
      16 (188 en 14, 221 en Bold 16) ; « Attualita » fait 58 contre 59. La
      methode est calibree sur deux styles connus — « Navigazione »
      (.fn-subhead, Lato Bold 16) et « Prestito Personale » (.fn-nav-pill, Lato
      Bold 14) — qu'elle retrouve tous les deux.

   La classe rendait donc 38 en mobile et 34 a partir de 768, pour 31 dessines,
   et portait une bascule de corps que le fichier n'a pas. Les deux sont
   corrigees ici. Cela **deplace l'accueil** — hero, produits, « Come funziona »
   — de 7 px en mobile et de 3 en desktop par pastille : c'est une part de
   l'ecart 34, mesuree au chapitre 4.10 du README.                          */
.fn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 31px;
  padding-inline: var(--fn-space-20);
  border-radius: var(--fn-radius-pill);
  background: var(--fn-surface-badge);
  color: var(--fn-text);
  /* 12 en mobile, 16 a partir de 1024 (demande du 2026-09-15). Le relevé
     Figma donne 16 aux deux tailles ; a 390 la pastille du hero
     (« Comparatore indipendente · Servizio gratuito ») y tenait sur deux
     lignes et pesait autant que le sous-titre. Le desktop reste sur le
     relevé — l'ecart est mobile, et lui seul. La bascule est plus bas, apres
     les deux modificateurs, pour ne pas les emporter : `--bold` (« Fase 1 »)
     et `--sm` (categories des cartes) gardent leurs 14 partout. */
  font-size: var(--fn-size-12);
  line-height: 1;
  letter-spacing: var(--fn-tracking);
}
/* « Fase 1 » du carrousel : Lato **Bold 14** dans une boite de 30. */
.fn-badge--bold {
  min-height: 30px;
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
}
/* Pastille de categorie des cartes de l'index : 26 de haut, retrait de 12,
   Lato Regular 14 (« Attualita » 51 contre 51 mesures). Elle venait de la
   feuille transitoire, ou elle n'etait qu'un « --sm » sans relevé.         */
.fn-badge--sm {
  min-height: 26px;
  padding-inline: var(--fn-space-12);
  font-size: var(--fn-size-14);
}
/* Retour aux 16 du relevé Figma en desktop. Le `:not()` vise les pastilles
   nues : sans lui la regle, plus tardive, ramenerait aussi `--bold` et `--sm`
   a 16 alors que le fichier les dessine a 14. */
@media (min-width: 1024px) {
  .fn-badge:not(.fn-badge--bold):not(.fn-badge--sm) { font-size: var(--fn-size-16); }
}
/* Les pastilles de **categorie** sont teintees, et les deux teintes du fichier
   sont deja dans la palette : « Attualita » sur `--fn-orange-100` (#ffe1b0) et
   « Guida » sur `--fn-vert-vitalite-100` (#c7e7d0), echantillonnes au pixel.
   Le bleu de `.fn-badge` reste la valeur par defaut — c'est celui que porte la
   pastille de tete de l'index, « Guida & Consigli ». `finami_badge_class()`
   fait tourner les trois sur les categories du site.                       */
/* La pastille de categorie est un lien vers l'archive : elle ne doit pas pour
   autant se souligner — le fichier n'en dessine aucun trait. */
.fn-badge { text-decoration: none; }
.fn-badge--ambre { background: var(--fn-orange-100); }
.fn-badge--vert  { background: var(--fn-vert-vitalite-100); }

/* Pastille « 8 min di lettura », posee en bas a droite du visuel d'une carte.

   ⚠️ **Elle n'est pas mesurable** : les visuels de carte sont des frames
   aplaties (« Slide 16:9 - 3 » et suivantes), et `get_metadata` les rend sans
   enfants — meme piege que le hero de l'accueil et que les deux corps du 404.
   Ce qui suit est donc **lu sur la capture 1:1**, pas releve : pastille de 23
   de haut environ, coins pleins, noir translucide, texte blanc, a 10 des bords
   du visuel. Le rayon et le voile avaient tous deux leur token depuis un
   relevé anterieur (`--fn-radius-chip`, `--fn-scrim`), sans avoir jamais
   servi.                                                                    */
.fn-chip {
  display: inline-flex;
  align-items: center;
  min-height: 23px;
  padding-inline: var(--fn-space-10);
  border-radius: var(--fn-radius-chip);
  background: var(--fn-scrim);
  backdrop-filter: blur(2px);
  color: var(--fn-text-inverse);
  font-size: var(--fn-size-12);
  line-height: 1;
  letter-spacing: var(--fn-tracking);
}

/* ------------------------------------------------------------------ CARTES */

.fn-card {
  background: var(--fn-surface-page);
  border: var(--fn-border-width) solid var(--fn-border-subtle);
  border-radius: var(--fn-radius-card);
  padding: var(--fn-space-20);
}
.fn-card__media {
  border-radius: var(--fn-radius-media);
  overflow: hidden;
}
.fn-card__media img { width: 100%; height: 100%; object-fit: cover; }

/* Carte produit (home) : visuel + sur-titre + titre + liste + CTA */
.fn-product-card {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-20);
  background: var(--fn-surface-page);
  /* Le fichier donne 380 de carte pour 340 de contenu (216:2681 / 216:2682),
     soit un retrait de 20 **filet compris** : dans Figma un contour interieur
     ne change pas la boite. Une `border` le ferait — 2 de plus en hauteur
     comme en largeur —, d'ou le filet en ombre interieure, l'idiome que la
     feuille emploie deja pour `.fn-btn--outline` et `.fn-btn--bordered`. */
  box-shadow: inset 0 0 0 var(--fn-border-width) var(--fn-border-card);
  border-radius: var(--fn-radius-card);
  padding: var(--fn-space-20);
}
/* Le visuel fait **211 de haut aux deux largeurs** : 340 x 211 en desktop
   (216:2682) et 310 x 211 en mobile (216:3074). Ce n'est donc pas un rapport
   — `aspect-ratio: 380 / 211` etait celui du fichier image (760 x 422), et il
   confondait la largeur de la **carte** avec celle du visuel : le visuel
   rendait 191,36 pour 211. */
.fn-product-card__media { height: 211px; }

/* Trois niveaux d'imbrication dans les maquettes, chacun avec son ecart :
   corps 10, bloc interne 20, sur-titre et titre 10. Le texte est centre,
   sauf la liste de controles, qui est un bloc centre a lignes alignees a
   gauche. */
.fn-product-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}
.fn-product-card__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-20);
  padding-block: var(--fn-space-10) var(--fn-space-20);
  text-align: center;
}
/* Meme piege que l'en-tete de section : le `<p>` du corps de carte gardait ses
   14 en haut et en bas. +28 par carte, et les trois cartes etant cote a cote,
   +28 sur la section. */
.fn-product-card__inner > * { margin: 0; }
.fn-product-card__head {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
  width: 100%;
}
.fn-product-card__list { text-align: left; }
.fn-product-card__list {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
  list-style: none;
  margin: 0; padding: 0;
}
.fn-product-card__list li {
  display: flex;
  align-items: flex-start;
  gap: var(--fn-space-10);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
}
.fn-product-card__list svg { flex: 0 0 auto; width: var(--fn-icon-md); height: var(--fn-icon-md); }

/* Tuile d'icone 40x40 + libelle (raccourcis du hero) */
.fn-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--fn-icon-tile);
  height: var(--fn-icon-tile);
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-icon);
  /* Le fond de la tuile reste clair meme sur une carte sombre : l'icone doit
     donc reposer sa couleur, sinon elle herite du blanc et disparait — c'est
     le cas de la derniere carte de « Perche scegliere Finami ». */
  color: var(--fn-text);
}
.fn-tile svg { width: var(--fn-icon-md); height: var(--fn-icon-md); }

/* Tuile large : cartes « avantage » de la home, 48 px avec une icone de 24. */
.fn-tile--lg {
  width: var(--fn-icon-tile-lg);
  height: var(--fn-icon-tile-lg);
}
.fn-tile--lg svg { width: var(--fn-icon-lg); height: var(--fn-icon-lg); }

/* Carte « avantage » : tuile d'icone, titre et texte. Sert la grille
   « Perché scegliere Finami » (Figma 216:2919).
   Rayon 4 et non 10 : cette grille n'emploie pas le rayon des cartes produit.
   La variante --inverse (dernière carte de la grille) garde sa bordure claire
   dans la maquette, ce qui est volontaire : elle n'est pas neutralisee ici. */
.fn-feature-card {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-20);
  padding: var(--fn-space-20);
  background: var(--fn-surface-page);
  /* Filet en ombre interieure : 346 de carte pour 306 de contenu (216:2919 /
     216:2923), soit 20 de retrait filet compris. Voir `.fn-product-card`. */
  box-shadow: inset 0 0 0 var(--fn-border-width) var(--fn-border-card);
  border-radius: var(--fn-radius-control);
}

/* Titre de carte « avantage » : Barlow ExtraBold 16, seul titre de ce corps
   dans les maquettes. */
.fn-feature-title {
  font-family: var(--fn-font-heading);
  font-weight: var(--fn-weight-xbold);
  font-size: var(--fn-size-16);
  /* Ecart 32 : boite de 19 pour un corps de 16 (216:2924, « Completamente
     gratuito »), soit 1,1875 exactement. */
  line-height: var(--fn-leading-barlow);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

.fn-feature-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}

/* Le fichier reserve **trois lignes** au texte, quelle que soit sa longueur :
   les six boites de « Perche scegliere » font 306 x 60 (216:2925, 216:2939,
   216:2946, 216:2962…), y compris celles dont le texte tient sur deux. Le
   README l'annoncait — « texte a hauteur fixe de 60 » — sans que la feuille le
   porte : en desktop la grille egalisait ses rangees et le defaut ne se voyait
   pas, en mobile trois cartes sur six rendaient 177 pour 197. `min-height`
   plutot que `height`, pour qu'un texte plus long ne se coupe pas. */
.fn-feature-card p { margin: 0; min-height: calc(3 * var(--fn-leading-body)); }

.fn-feature-card--inverse {
  background: var(--fn-surface-dark);
  color: var(--fn-text-inverse);
}

.fn-quick-link {
  display: flex;
  align-items: center;
  gap: var(--fn-space-17);
  width: 300px;
  max-width: 100%;
  padding: var(--fn-space-10) var(--fn-space-14);
  border-radius: var(--fn-radius-tile);
  background: var(--fn-surface-raised);
  /* La carte est posée sur le panneau du hero, qui passe la couleur en
     inverse : il faut donc rétablir la couleur de texte explicitement. */
  color: var(--fn-text);
  text-decoration: none;
}
.fn-quick-link__text {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-6);
  text-align: left;
}
.fn-quick-link__title {
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-tight);
}
.fn-quick-link__hint {
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-10);
  line-height: var(--fn-leading-tight);
  color: var(--fn-text-link);
}

/* Carte chiffre cle (bandeau de preuve) */
.fn-stat-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--fn-space-10);
  flex: 1 1 0;
  /* Retrait de 20 : le fichier donne 285 de carte pour 245 de contenu
     (216:2660 / 216:2662). Le filet dessine par Figma est retire depuis le
     2026-09-30, a la demande — le retrait, lui, reste. Sans filet la carte ne
     ressortait plus : elle prend un fond sable clair [PROPOSE], meme jour. */
  padding: var(--fn-space-20);
  background: var(--fn-surface-sand-soft);
  border-radius: var(--fn-radius-control);
  text-align: center;
}
.fn-stat-card__value {
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-style: italic;
  font-size: var(--fn-size-42);
  /* Ecart 32 : boite de 50 pour un corps de 42 (216:2661, « -60% »), soit
     l'interlignage « auto » de Lato. A 1,1 la valeur rendait 46,2 et la carte
     118,19 pour 120. */
  line-height: var(--fn-leading-lato);
  letter-spacing: var(--fn-tracking);
  color: var(--fn-border-strong);
  margin: 0;
  /* Le compteur de `home.js` y loge la valeur lue en `.fn-visually-hidden`,
     donc en position absolue. Sans ancetre positionne elle s'accrochait a la
     page : le defilement mobile de `.fn-stats` ne la rognait plus, et la
     derniere carte comptee elargissait le document a 1125 (2026-10-19). */
  position: relative;
}
.fn-stat-card__label { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); margin: 0; }

/* Carte article — releveee le 2026-09-08. Elle sert deux endroits, et le
   fichier la dessine avec le **meme ecart de 10 entre tous ses elements**,
   quel que soit leur nombre. C'est ce qui permet de n'ecrire qu'une classe :
   les enfants sont a plat, le `gap` fait le reste.

     « Articoli correlati »  400:1738  253,33 x 270,5
       visuel 142,5 · 10 · titre 38 · 10 · chapo 40 · 10 · date 20   = 270,5
     grille de l'index       387:1287  253,33 x 276,5
       visuel 142,5 · 10 · pastille+date 26 · 10 · titre 38 · 10 · chapo 40 = 276,5

   Le titre est en **Barlow ExtraBold 16**, interligne « auto » de Barlow : la
   boite fait 38 pour deux lignes dans 253,33, et 16 x 1,1875 x 2 = 38 au
   pixel. La classe portait 700 et `--fn-leading-tight` : deux erreurs, et la
   premiere se voyait — le thema n'auto-heberge Barlow qu'en 800, une demande
   de 700 tombait sur une graisse synthetique.                              */
.fn-article-card { display: flex; flex-direction: column; gap: var(--fn-space-10); }
/* **Cinquieme rencontre du meme piege**, et la premiere qu'un outil ait
   attrapee au lieu d'un oeil : la marge par defaut des deux <p> de la carte
   — le chapo et la ligne de date — s'ajoutait au `gap` au lieu de s'y
   fondre, en flux flex les marges ne fusionnant pas. La carte rendait
   298,59 pour 270,5 dessines, soit **+28** par carte, et la bande
   « Articoli correlati » entiere en heritait. Les quatre precedentes :
   `.fn-404__inner`, `.fn-page-intro`, l'en-tete du tunnel et
   `.fn-footer__disclaimer`.                                              */
.fn-article-card > * { margin: 0; }
.fn-article-card__media {
  display: block;
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--fn-radius-card);
  overflow: hidden;
  background: var(--fn-surface-muted);
}
.fn-article-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fn-article-card__media .fn-chip { position: absolute; right: var(--fn-space-10); bottom: var(--fn-space-10); }
/* Rangee pastille de categorie / date : la date est calee a droite, et la
   rangee fait 26 — la hauteur de la pastille, pas celle de la date.        */
.fn-article-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-10);
  min-height: 26px;
}
.fn-article-card__title {
  font-family: var(--fn-font-heading);
  font-weight: var(--fn-weight-xbold);
  font-size: var(--fn-size-16);
  line-height: var(--fn-leading-barlow);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}
.fn-article-card__title a { text-decoration: none; }
.fn-article-card__title a:hover { text-decoration: underline; }
/* Le chapo tient sur **deux lignes** dans le fichier, et la quatrieme carte de
   « Articoli correlati » y est coupee par des points de suspension : c'est un
   ecretage, pas un extrait court. */
.fn-article-card__excerpt {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  margin: 0;
}
.fn-article-card__footer { display: flex; justify-content: flex-end; }

/* ---------------------------------------------------- GRILLES DE L'ACCUEIL
   Chaque section de la home a sa propre trame ; elles ne se ramenent pas a
   une grille commune sans deformer les maquettes.                          */

/* Chiffres cles : quatre colonnes egales en desktop. En mobile les maquettes
   figent les cartes a 285 px dans un cadre de 390 — la quatrieme deborde, et
   la troisieme depasse a peine du bord : c'est un defilement horizontal, pas
   une grille repliee. On le rend comme tel, avec accroche au defilement. */
.fn-stats {
  display: flex;
  gap: var(--fn-space-20);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Le defilement va d'un bord a l'autre de l'ecran, la gouttiere etant
     rendue par le padding : sans quoi la derniere carte se coupe net. */
  margin-inline: calc(-1 * var(--fn-gutter));
  padding-inline: var(--fn-gutter);
  /* Sans cette ligne la premiere carte se colle au bord de l'ecran, et elle
     seule : l'accroche cale le debut de la carte sur le bord du *padding-box*,
     donc le navigateur defile de 20 des le chargement et mange la gouttiere
     que le `padding-inline` venait de poser. Le retrait n'etait pas perdu — il
     restait a droite, hors de vue. `scroll-padding` deplace le bord auquel
     l'accroche se refere ; c'est le seul reglage que le padding ne suffit pas
     a donner. Mesure a 390 : la carte « -60% » passe de 0 a 20, comme le
     conteneur. */
  scroll-padding-inline: var(--fn-gutter);
  scrollbar-width: none;
}
.fn-stats::-webkit-scrollbar { display: none; }
.fn-stats > * {
  flex: 0 0 285px;
  scroll-snap-align: start;
}

/* Cartes produit : 380 de large dans les maquettes, une par ligne en mobile. */
.fn-products {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--fn-space-20);
}

/* Cartes « avantage » : 346 de large, trois colonnes au-dela de 1024. */
.fn-features {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--fn-space-20);
}

@media (min-width: 768px) {
  .fn-stats {
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
  }
  .fn-stats > * { flex: 1 1 0; }
  .fn-features { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  /* Figma pose 10 de retrait autour de la rangee (216:2680, 1200 x 663) :
     c'est ainsi qu'il centre 3 x 380 + 2 x 20 = 1180 dans les 1200 du
     conteneur, et cela vaut 20 en hauteur. Le cadre mobile (216:3072) n'en a
     pas — d'ou le retrait ici et non dans la regle de base. */
  .fn-products { grid-template-columns: repeat(3, minmax(0, 1fr)); padding: var(--fn-space-10); }
  .fn-features {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    /* 3 x 346 + 2 x 20 : la grille des avantages est plus etroite que le
       conteneur, elle ne remplit pas la ligne. */
    max-width: 1078px;
    margin-inline: auto;
  }
}

/* Panneau sable (informations legales, encarts) */
.fn-panel-sand {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
  padding: var(--fn-space-30) var(--fn-space-20);
  border-radius: var(--fn-radius-card);
  background: var(--fn-surface-sand);
}
.fn-panel-sand__body { flex: 1 1 0; }
/* Un element flex ouvre un contexte de formatage : les marges de son premier
   et de son dernier enfant n'en sortent pas et s'ajoutent a sa hauteur. Les
   trois `<p>` gardaient donc leurs 14 par defaut en haut et en bas — +28 sur
   la section, tout l'ecart 34 pour « informativa » (216:2963). Septieme
   rencontre du meme piege. */
.fn-panel-sand__body > * { margin: 0; }
.fn-panel-sand__body p + p { margin-top: var(--fn-space-20); }
.fn-panel-sand .fn-title { flex: 0 0 auto; }

@media (min-width: 768px) {
  .fn-panel-sand { flex-direction: row; align-items: center; gap: var(--fn-space-50); padding: var(--fn-space-30) var(--fn-space-50); }
}

/* -------------------------------------------------------------------- HERO */

.fn-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--fn-space-50) var(--fn-gutter);
  overflow: hidden;
}
/* Le fond est le composite Figma deja aplati (deux photographies melangees
   en « hard light », plus le voile noir a 20 %) : aucun calque a superposer
   ici, sans quoi le voile serait applique deux fois. Voir
   assets/figma/flatten-hero.py. */
.fn-hero__bg { position: absolute; inset: 0; pointer-events: none; }
.fn-hero__bg picture,
.fn-hero__bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fn-hero__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-30);
  width: 100%;
  padding: var(--fn-space-20);
  border-radius: var(--fn-radius-card);
  background: var(--fn-surface-glass);
  box-shadow: var(--fn-shadow-md);
  text-align: center;
  color: var(--fn-text-inverse);
}
.fn-hero__panel .fn-lead { color: var(--fn-text-on-dark-soft); }
.fn-hero__links {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-10);
}
.fn-hero__trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--fn-space-10) var(--fn-space-30);
}
.fn-hero__trust li {
  display: flex;
  align-items: center;
  gap: var(--fn-space-10);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-12);
  /* La ligne vaut **l'icone**, soit 16, et non les 20 de `--fn-leading-body`.
     Releve sur `home_mobile-v3.png`, capture 1:1 du cadre 216:2997 : les deux
     lignes de reassurance y sont a 30 et a 56 du bas du bloc de raccourcis,
     soit 16 + 10 + 16 = 42 et non 20 + 10 + 20 = 50. Le heros etant aplati,
     c'est la capture qui mesure et non le releve. -4 en desktop (une ligne),
     -8 en mobile (deux). */
  line-height: var(--fn-icon-sm);
  color: var(--fn-text-on-dark-soft);
}
.fn-hero__trust svg { width: var(--fn-icon-sm); height: var(--fn-icon-sm); }
/* Les maquettes n'ordonnent pas les trois reassurances pareil selon la taille
   d'ecran : le mobile place le cadenas en deuxieme pour tenir sur deux lignes,
   le desktop garde les etincelles. Le balisage suit le mobile, le desktop
   remet l'ordre par `order`. */
@media (min-width: 768px) {
  .fn-hero__trust li:nth-child(2) { order: 3; }
}
.fn-hero__trust { list-style: none; margin: 0; padding: 0; }

@media (min-width: 768px) {
  .fn-hero__links { flex-direction: row; justify-content: center; }
  .fn-hero__panel { width: auto; max-width: 960px; }
  .fn-hero__panel .fn-hero-title { max-width: 830px; }
  .fn-hero__panel .fn-lead { max-width: 674px; }
}

/* --------------------------------------------------------------- FORMULAIRE
   Tunnel en 7 etapes, releve le 2026-09-03 dans le composant Figma
   « formulaire » (196:1041, page DS) et ses **huit** variantes : les sept
   etapes et l'ecran de resultat. Le gabarit « Formulaire » (216:3373) ne
   dessine que la premiere etape — c'est la page DS qui porte les autres.

   Le squelette est un empilement de 550 de large, a 30 d'ecart : progression,
   question, corps d'etape, navigation. A l'interieur d'un bloc, l'ecart tombe
   a 10.

   Le formulaire se pose sur la section beige et **chaque surface de saisie est
   claire** : c'est le contraste de fond qui dessine les champs et les options.
   Il n'y a aucune bordure dans le fichier — echantillonnage au pixel des huit
   variantes : #ffffff pour les options, #fefefe pour les champs, la case et
   les cartes, et du transparent partout ailleurs.                          */

/* En-tete de gabarit : nom du produit et accroche, centres a 20 d'ecart.
   Releve dans « Formulaire » (216:3388 desktop, 216:3432 mobile) : 50 de
   respiration au-dessus et au-dessous, comme la section beige qui suit.

   Le meme en-tete sert aux pages editoriales, ou il prend un fil d'ariane
   devant le titre : « Mentions legales » (400:3373 desktop, 400:3419 mobile)
   pose 50 + 14 + 20 + 62 + 20 + 20 + 50 = 236, exactement la hauteur du cadre,
   et 50 + 14 + 20 + 43 + 20 + 40 + 50 = 237 en mobile. Trois elements a 20
   d'ecart dans une section a 50 : c'est cette classe, pas une autre.       */
.fn-page-intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-20);
  text-align: center;
}
/* Troisieme rencontre du meme piege : `.fn-body` et `.fn-lead` n'annulent pas
   la marge par defaut du <p>, qui s'ajoute au gap au lieu de s'y fondre — en
   flux flex les marges ne fusionnent pas. L'en-tete du tunnel rendait donc 34
   d'ecart pour 20 dessines, et 14 de trop sous le bloc. Corrige ici plutot
   qu'au cas par cas : le 404 avait deja `.fn-404__inner > *`.              */
.fn-page-intro > * { margin: 0; }

/* Fil d'ariane des gabarits interieurs — instance « fil d'ariane », 400:3377
   en desktop et 400:3423 en mobile, boite de 14 de haut, Lato 12 sur le gris
   #545f65. Le fichier ne distingue **pas** le lien de la page courante : meme
   corps, meme couleur, meme graisse. Il est le seul element non centre de
   l'en-tete, a gauche du conteneur aux deux largeurs.                      */
.fn-page-intro > .fn-breadcrumb { align-self: flex-start; text-align: left; }

.fn-breadcrumb {
  font-size: var(--fn-size-12);
  line-height: var(--fn-leading-badge);
  color: var(--fn-text-secondary);
}
.fn-breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fn-space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Le separateur mesure 4 x 6 px sur la capture. A cette taille un glyphe et
   un trace Lucide sont indiscernables, et aucun export « chevron » n'est en
   magasin : le glyphe est retenu parce qu'il suit le corps du texte et ne
   demande aucun asset. Si le composant se relit un jour au MCP et qu'il porte
   bien une icone, c'est cette declaration seule qui change.                */
.fn-breadcrumb li + li::before {
  content: "\203A";          /* › */
  margin-right: var(--fn-space-6);
}
.fn-breadcrumb a { text-decoration: none; }
.fn-breadcrumb a:hover { text-decoration: underline; }

.fn-form {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
  width: 100%;
  max-width: 550px;
  margin-inline: auto;
}
/* Les **huit** variantes du composant Figma font 592 de haut, la plus courte
   comme la plus longue, et le gabarit leur reserve 692 (592 + 2 x 50 de
   section) : la zone du formulaire est une boite fixe, pas une boite qui suit
   son contenu. D'ou ce plancher, qui reproduit le blanc sous les tuiles de la
   variante 1 et, accessoirement, empeche le pied de page de sauter d'une
   etape a l'autre. Un plancher et non une hauteur : une etape qui deborde
   (un libelle qui s'enroule, un message d'erreur) doit pouvoir grandir.
   Desktop seulement — en 390, les 592 de Figma sont deja depasses par le
   contenu (606) et le plancher ne servirait a rien.

   La huitieme variante etant l'ecran de resultat, `.fn-outcome` porte le meme
   plancher : c'est la meme zone de page, avec un autre contenu. */
@media (min-width: 768px) {
  .fn-form,
  .fn-outcome { min-height: 592px; }
}

/* --- Progression -------------------------------------------------------
   Piste de 10 de haut, remplissage = passo / 7. Figma pose 550/7 = 78,57
   dans la variante 1 et 549,99 dans la septieme : c'est bien une fraction
   du total, et non un pas fixe.                                          */
.fn-form__progress { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-progress {
  height: 10px;
  border-radius: var(--fn-radius-full);
  background: var(--fn-surface-page);
  overflow: hidden;
}
.fn-progress__bar {
  height: 100%;
  border-radius: var(--fn-radius-full);
  background: var(--fn-action-bg);
}
.fn-form__count { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); }

/* --- Question : titre Barlow 32, sous-titre Lato 14 --- */
.fn-form__question { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-form__sub { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); margin: 0; }

/* --- Corps d'etape : sous-blocs a 30 d'ecart.
   Porte par un <fieldset> quand l'etape est un choix, d'ou la remise a zero
   de ses trois proprietes d'agent utilisateur. `min-width: 0` est
   indispensable : un fieldset refuse de se retrecir sans lui, et la grille
   d'options deborderait en 390.                                           */
.fn-form__block {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

/* --- Options : une colonne, deux a partir de 768 --- */
.fn-form__options {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--fn-space-10);
}
@media (min-width: 768px) {
  .fn-form__options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Second membre d'un libelle d'option — « 12 mesi  (1 anno) » : meme corps,
   graisse normale, a 10 du premier. */
.fn-choice { gap: var(--fn-space-10); }
.fn-choice__note { font-weight: var(--fn-weight-regular); }

/* Le bouton radio d'une option est masque : c'est le <label> qui doit porter
   la selection et le focus. `--selected` vient du serveur au rechargement,
   `:has()` donne le meme reflet immediatement, avant la soumission. */
.fn-choice:has(input:checked) {
  background: var(--fn-choice-bg-selected);
  color: var(--fn-disabled-fg);
}
.fn-choice:has(input:focus-visible),
.fn-consent:has(input:focus-visible) {
  outline: 2px solid var(--fn-focus-ring);
  outline-offset: 2px;
}

/* Sous-groupe d'etape : un intertitre et son contenu, a 10 d'ecart. Le tunnel
   en a besoin la ou il reunit deux etapes de Figma en une (la duree a l'etape
   2) ou la ou Figma ne dessine rien (la date de naissance). */
.fn-form__group {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

/* --- Champs ------------------------------------------------------------
   Trois composants Figma : `input-prix` (259:1063, 200 x 52),
   `compteur-age` (204:1348, 130 x 52) et le champ de contact pleine largeur
   (550 x 50, variante 7). Le fond, le rayon et le retrait de 20 sont portes
   par la **boite** : un champ nu la porte lui-meme, un champ a unite la
   delegue a son enveloppe .fn-money et devient transparent.

   Aucun libelle visible dans le fichier : c'est le placeholder qui nomme le
   champ. Le <label> reste ecrit, en .fn-visually-hidden — un placeholder
   n'est pas un nom accessible.                                            */
.fn-fields { display: flex; flex-direction: column; gap: var(--fn-space-10); }

.fn-input,
.fn-money {
  border: 0;
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  padding-inline: var(--fn-space-20);
  font-family: var(--fn-font-body);
  letter-spacing: var(--fn-tracking);
  color: var(--fn-text);
}
.fn-input--text {
  width: 100%;
  height: 50px;
  font-size: var(--fn-size-14);
  font-weight: var(--fn-weight-regular);
}
/* Le placeholder est en #acacac dans les huit variantes, et non dans le gris
   bleute de --fn-text-disabled : c'est --fn-blanc-700. */
.fn-input::placeholder { color: var(--fn-blanc-700); opacity: 1; }

.fn-money {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-10);
  height: 52px;
  margin-inline: auto;
}
.fn-money--price   { width: 200px; }
/* 130 dans Figma, sans unite. « anni », ajoute a la demande le 2026-10-15,
   demande 20 de plus ; le placeholder « Es: 35 » passe en 20 pour y tenir
   (190 de large d'abord, juge trop large le meme jour). */
.fn-money--counter { width: 150px; }
.fn-money--counter .fn-input::placeholder { font-size: var(--fn-size-20); }
.fn-money .fn-input {
  width: 100%;
  min-width: 0;
  padding: 0;
  background: transparent;
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-30);
}
/* L'anneau de focus entoure la boite, et non le champ nu qu'elle contient :
   sinon il se dessinait a l'interieur, sans l'unite. */
.fn-money .fn-input:focus-visible { outline: none; }
.fn-money:has(.fn-input:focus-visible) {
  outline: 2px solid var(--fn-focus-ring);
  outline-offset: 2px;
}
/* La valeur de l'age se cale contre son unite et se lit « 35 anni ». */
.fn-money--counter .fn-input { text-align: right; }
.fn-input__unit {
  flex: 0 0 auto;
  font-weight: var(--fn-weight-regular);
  font-size: var(--fn-size-16);
  color: var(--fn-blanc-700);
}

/* --- Raccourcis de montant (variante 2) --------------------------------
   Pastilles de 30 de haut, retrait de 20, bordees de #acacac et **sans
   fond**. Figma ne dessine ni survol ni etat actif : les deux sont
   [PROPOSE].                                                              */
.fn-form__presets { display: flex; flex-wrap: wrap; gap: var(--fn-space-10); }
.fn-preset {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 var(--fn-space-20);
  border: var(--fn-border-width) solid var(--fn-blanc-700);
  border-radius: var(--fn-radius-full);
  background: transparent;
  color: var(--fn-text);
  font-family: var(--fn-font-body);
  font-size: var(--fn-size-14);
  letter-spacing: var(--fn-tracking);
  cursor: pointer;
  transition: background-color var(--fn-duration) var(--fn-easing);
}
.fn-preset:hover { background: var(--fn-choice-bg); }          /* [PROPOSE] */
.fn-preset.is-active {                                          /* [PROPOSE] */
  border-color: var(--fn-action-bg);
  background: var(--fn-action-bg);
  color: var(--fn-action-fg);
}

/* --- Case a cocher (check-box 204:1432) et consentement --- */
.fn-checkbox {
  appearance: none;
  flex: 0 0 auto;
  display: inline-grid;
  place-content: center;
  width: 24px; height: 24px;
  border: 0;
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  cursor: pointer;
}
.fn-checkbox:checked { background: var(--fn-action-bg); }
.fn-checkbox:checked::after {
  content: "";
  width: 16px; height: 16px;
  background: currentColor;
  color: var(--fn-text-inverse);
  clip-path: polygon(14% 48%, 0 62%, 38% 100%, 100% 22%, 86% 8%, 38% 72%);
}
.fn-consents { display: flex; flex-direction: column; gap: var(--fn-space-20); }
.fn-consent {
  display: flex;
  align-items: flex-start;
  gap: var(--fn-space-10);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  cursor: pointer;
}
.fn-consent a { text-decoration: underline; }
.fn-form__legal { font-size: var(--fn-size-12); line-height: var(--fn-leading-body); margin: 0; }

/* --- Erreurs -----------------------------------------------------------
   Figma ne definit **aucune** couleur d'erreur (ecart 7 du README) : sa
   variante « invalid » se contente du gris desactive, et le message n'existe
   nulle part dans le fichier. Tout ce bloc est donc [PROPOSE].

   ⚠️ **Refait le 2026-09-15 : encart rouge, et non plus champ grise.**
   `.is-invalid` posait `--fn-disabled-bg` (#acacac) en fond de champ, soit
   l'aspect exact d'un champ **desactive** — le tunnel disait « on ne peut plus
   y toucher » la ou il voulait dire « corrigez ceci ». Le gris ne dit pas non
   plus *lequel* des deux sens il porte, et il effacait la valeur saisie sous
   un aplat. Le champ garde desormais son fond et prend un filet rouge ; le
   message devient un encart, lui aussi rouge.

   La couleur ne porte pas le sens toute seule : le message reste ecrit, le
   champ garde `aria-invalid` et son `aria-describedby`, et l'encart tient sans
   couleur — filet, retrait et graisse suffisent a le detacher. C'est ce qui
   le rend lisible en daltonisme comme en impression noir et blanc.          */
.fn-error {
  display: block;
  border: 1px solid var(--fn-error-border);
  border-radius: var(--fn-radius-control);
  background: var(--fn-error-bg);
  padding: var(--fn-space-10) var(--fn-space-12);
  font-size: var(--fn-size-12);
  line-height: var(--fn-leading-body);
  font-weight: var(--fn-weight-bold);
  color: var(--fn-error-fg);
}
/* Le filet, et non un fond : la valeur saisie doit rester lisible — c'est elle
   qu'on demande de corriger. `box-sizing: border-box` est global (en tete de
   feuille), donc les 50 et 52 de hauteur des champs ne bougent pas.

   `.fn-money` est l'enveloppe (montant, age) et porte deja la boite ; son
   `.fn-input` interieur est transparent et n'a rien a reprendre.            */
.fn-input.is-invalid,
.fn-money.is-invalid {
  border: 1px solid var(--fn-error-border);
  background: var(--fn-surface-page);
}
/* La case a cocher du consentement n'a pas de classe : le gabarit n'y pose que
   `aria-invalid`. Le selecteur d'attribut la rattrape, et vaut pour tout champ
   marque invalide qui aurait echappe a `.is-invalid`.                       */
.fn-checkbox[aria-invalid="true"] { border: 1px solid var(--fn-error-border); }

/* --- Navigation d'etape ------------------------------------------------
   « Indietro » a gauche, 93 de large, fond clair ; l'action a droite. Elle
   est a sa largeur de contenu aux etapes intermediaires (variante 2 :
   85 colle a 550) et occupe toute la place restante au dernier passo
   (variante 7 : 447 = 550 - 93 - 10). Les icones sont a 16.               */
.fn-form__nav { display: flex; align-items: center; gap: var(--fn-space-10); }
.fn-form__nav .fn-btn { min-height: 40px; padding-block: 0; gap: var(--fn-space-10); }
.fn-form__nav .fn-btn svg { width: var(--fn-icon-sm); height: var(--fn-icon-sm); }
.fn-form__nav .fn-btn--back { background: var(--fn-surface-page); color: var(--fn-text); }
.fn-form__nav .fn-btn--back:hover { background: var(--fn-blanc-500); }  /* [PROPOSE] */
.fn-form__nav .fn-btn--primary { margin-inline-start: auto; }
.fn-form__nav .fn-btn--grow { flex: 1 1 auto; }
/* Au dernier passo, tant que la destination des demandes n'est pas branchee,
   une mention prend la place du bouton d'envoi. */
.fn-form__nav .fn-form__legal { flex: 1 1 auto; }

/* Le bouton d'avance des quatre etapes de choix -------------------------
   Figma ne dessine pas de bouton « Avanti » aux etapes de choix : cliquer
   une tuile fait avancer (ecart 14). Le bouton reste pourtant **ecrit** dans
   le balisage — c'est le repli, sans lequel le tunnel se bloquerait des que
   le script ne charge pas.

   Il n'est donc masque qu'ici, sous `.fn-js` — une classe que
   `assets/js/richiesta.js` pose sur <html> lui-meme, et seulement apres avoir
   branche l'avance au clic. Si le script ne charge pas, la classe n'existe pas
   et le bouton s'affiche. A l'etape 1 la rangee entiere se retire : Figma n'y
   dessine ni « Indietro » — il n'y a rien derriere — ni « Avanti ».         */
.fn-js .fn-form--choice .fn-form__nav .fn-btn--next { display: none; }
.fn-js .fn-form--choice .fn-form__nav--solo { display: none; }

/* Le bouton d'avance des etapes a saisie -------------------------------
   Demande du 2026-09-30 : plutot que grise puis actif, le bouton « Avanti »
   (et « Invia la richiesta ») **apparait** une fois l'etape renseignee.
   `assets/js/richiesta.js` pose `hidden` ; `display: inline-flex` de `.fn-btn`
   battrait la regle `[hidden]` du navigateur, d'ou la regle explicite.
   L'animation rejoue a chaque passage de `display: none` a visible. */
.fn-form__nav .fn-btn--next[hidden] { display: none; }
.fn-form__nav .fn-btn--next { animation: fn-appear var(--fn-duration) var(--fn-easing); }
@keyframes fn-appear {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .fn-form__nav .fn-btn--next { animation: none; }
}

/* --- Bandeau de reassurance sous le titre du tunnel — 2026-10-15 ---------
   Trois pastilles, d'apres le prototype : icone de 16 et texte Lato Bold 14,
   centrees, a 10 d'ecart, qui passent a la ligne en mobile. Fond des
   pastilles du design system (`--fn-surface-badge`) et non le vert du
   prototype. [PROPOSE] — Figma n'en dessine pas. */
.fn-page-trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--fn-space-10);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fn-page-trust li {
  display: inline-flex;
  align-items: center;
  gap: var(--fn-space-6);
  min-height: 36px;
  padding-inline: var(--fn-space-16);
  border-radius: var(--fn-radius-pill);
  background: var(--fn-surface-badge);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-tight);
  font-weight: var(--fn-weight-bold);
}
.fn-page-trust svg { flex: none; width: var(--fn-icon-sm); height: var(--fn-icon-sm); }
/* En mobile, les trois pastilles s'empilaient et repoussaient la premiere
   question sous la ligne de flottaison (simulation 390 x 844, 2026-10-15).
   Reduites, elles tiennent sur deux lignes. */
@media (max-width: 767px) {
  .fn-page-trust { gap: var(--fn-space-6); }
  .fn-page-trust li {
    gap: var(--fn-space-4);
    min-height: 28px;
    padding-inline: var(--fn-space-10);
    font-size: var(--fn-size-12);
  }
  .fn-page-trust svg { width: var(--fn-icon-xs); height: var(--fn-icon-xs); }
}

/* --- Colonne de droite : « La tua richiesta » — 2026-10-15 ---------------
   Reprise du prototype du 2026-10-15, **pas de Figma**, qui n'en dessine
   pas : formulaire de 550 + 40 d'ecart + colonne de 300, centres. Les
   valeurs viennent du prototype ; les couleurs, du design system (le
   prototype mettait le compteur en vert). Pas d'avis clients — consigne du
   meme jour. Voir `template-parts/richiesta/recap.php`.
   Sous 1024 la colonne disparait et le formulaire reste seul et centre,
   exactement comme avant. */
.fn-recap { display: none; }

@media (min-width: 1024px) {
  .fn-funnel {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: var(--fn-space-40);
  }
  .fn-funnel > .fn-form { margin-inline: 0; }

  .fn-recap {
    display: flex;
    flex-direction: column;
    gap: var(--fn-space-16);
    flex: none;
    width: 300px;
    position: sticky;
    top: calc(var(--fn-navbar-height) + var(--fn-space-20));
    padding: var(--fn-space-20);
    border: var(--fn-border-width) solid var(--fn-border-card);
    border-radius: var(--fn-radius-card);
    background: var(--fn-surface-raised);
  }
}

.fn-recap__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-10);
}
.fn-recap__title {
  margin: 0;
  font-family: var(--fn-font-body);
  font-size: var(--fn-size-16);
  line-height: var(--fn-leading-body);
  font-weight: var(--fn-weight-bold);
}
.fn-recap__count {
  padding: 2px var(--fn-space-10);
  border-radius: var(--fn-radius-pill);
  background: var(--fn-surface-badge);
  font-size: var(--fn-size-12);
  line-height: 16px;
  font-weight: var(--fn-weight-bold);
  font-variant-numeric: tabular-nums;
}

.fn-recap__rows { margin: 0; }
/* Filets en tirets entre les lignes, aucun sous la derniere. */
.fn-recap__row {
  display: flex;
  justify-content: space-between;
  gap: var(--fn-space-10);
  padding-block: var(--fn-space-10);
  border-bottom: var(--fn-border-width) dashed var(--fn-border-subtle);
  font-size: var(--fn-size-12);
  line-height: 18px;
}
.fn-recap__row:last-child { border-bottom: 0; }
.fn-recap__row dt { color: var(--fn-text-secondary); }  /* muted ferait 3,0:1 en 12 px */
.fn-recap__row dd {
  margin: 0;
  text-align: right;
  font-weight: var(--fn-weight-bold);
}
.fn-recap__row.is-empty dd { color: var(--fn-text-muted); font-weight: var(--fn-weight-regular); }

/* La ligne de l'etape qu'on vient de franchir s'allume une fois : l'accent
   puis l'encre, avec un court glissement. `flash` du prototype (0,9 s). */
.fn-recap__row.is-fresh dd { animation: fn-recap-fresh 900ms var(--fn-easing) both; }
@keyframes fn-recap-fresh {
  from { color: var(--fn-text-accent); transform: translateX(-4px); }
  to   { color: inherit; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .fn-recap__row.is-fresh dd { animation: none; }
}

/* --- Mouvements du tunnel — 2026-10-15 -----------------------------------
   Repris du prototype du 2026-10-15 : **les mouvements, pas les couleurs**.
   La tuile choisie reste bleu nuit comme dans Figma ; la pastille ✓ prend
   l'accent vert, que le design system reserve deja aux coches.
   Tout est coupe sous `prefers-reduced-motion`, en fin de bloc.

   1. Entree d'etape : la question et le corps glissent de 24 px, depuis la
      droite a l'avance, depuis la gauche au retour. Classes posees par
      `wizard.php`, d'apres le sens du dernier mouvement (`state['moved']`).
      Ni la progression ni la navigation ne bougent : elles ne changent pas
      de place d'une etape a l'autre. */
.fn-form--enter > .fn-form__question,
.fn-form--enter > .fn-form__block {
  animation: fn-step-in var(--fn-duration-step) var(--fn-easing-out) both;
}
.fn-form--enter-back > .fn-form__question,
.fn-form--enter-back > .fn-form__block {
  animation: fn-step-in-back var(--fn-duration-step) var(--fn-easing-out) both;
}
@keyframes fn-step-in {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fn-step-in-back {
  from { opacity: 0; transform: translateX(-24px); }
  to   { opacity: 1; transform: none; }
}

/* 2. Progression : la barre repart de la position de l'etape d'ou l'on
      vient (`--fn-progress-from`, ecrit par `wizard.php`) et glisse jusqu'a
      la sienne. Sans mouvement, les deux valeurs sont egales et rien ne
      bouge. */
.fn-form--enter .fn-progress__bar,
.fn-form--enter-back .fn-progress__bar {
  animation: fn-progress var(--fn-duration-progress) var(--fn-easing-out) both;
}
@keyframes fn-progress {
  from { width: var(--fn-progress-from); }
}

/* 2 bis. Etape en route (2026-10-15) : `richiesta.js` poste l'etape sans
      recharger la page et pose `aria-busy` le temps de la reponse. Le titre
      de l'etape recue prend le focus (pour les lecteurs d'ecran) : il n'a pas
      a s'entourer d'un cadre, ce n'est pas un controle. */
.fn-form[aria-busy="true"] { cursor: progress; }
.fn-form .fn-title[tabindex="-1"]:focus,
.fn-section--sand h1[tabindex="-1"]:focus,
.fn-section--sand h2[tabindex="-1"]:focus { outline: none; }

/* 3. Pastille ✓ : tuiles et champs de contact. Ronde, accent vert, coche
      blanche ; elle ressort (`--fn-easing-spring`) quand l'etat s'allume. */
.fn-tick {
  position: absolute;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--fn-radius-full);
  background: var(--fn-text-accent);
  color: var(--fn-text-inverse);
  transform: scale(0);
  transition: transform 350ms var(--fn-easing-spring);
  pointer-events: none;
}
.fn-tick svg { width: 12px; height: 12px; }

/* 4. Tuiles : soulevement au survol (pointeur seulement : sur ecran tactile
      le survol reste colle apres le toucher), tassement a l'appui, rebond a
      la selection (`.is-pop`, pose par `richiesta.js`), pastille au coin. */
.fn-form .fn-choice {
  position: relative;
  transition:
    background-color var(--fn-duration) var(--fn-easing),
    transform 200ms var(--fn-easing-out),
    box-shadow 200ms var(--fn-easing);
}
@media (hover: hover) {
  .fn-form .fn-choice:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 22px rgba(0, 16, 25, 0.08);  /* [PROPOSE] prototype */
  }
}
.fn-form .fn-choice:active { transform: scale(0.98); }
.fn-form .fn-choice.is-pop { animation: fn-pop 400ms var(--fn-easing-out); }
@keyframes fn-pop {
  40%  { transform: scale(1.03); }
  100% { transform: none; }
}
.fn-choice .fn-tick { top: -8px; right: -8px; }
.fn-choice--selected .fn-tick,
.fn-choice:has(input:checked) .fn-tick { transform: scale(1); }

/* 5. Champs de contact : filet vert et pastille quand le format est bon
      (`.is-valid`, pose par `richiesta.js` d'apres les memes regles que le
      serveur). Le filet est une ombre interieure : le champ n'a pas de
      bordure, il ne doit pas grandir d'un pixel. Un champ refuse par le
      serveur garde son filet rouge tant qu'il n'est pas corrige. */
.fn-field {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}
.fn-field .fn-input--text {
  padding-inline-end: 50px;
  transition: box-shadow var(--fn-duration) var(--fn-easing);
}
.fn-field__tick { top: 14px; right: 14px; }
.fn-field.is-valid .fn-input--text { box-shadow: inset 0 0 0 2px var(--fn-text-accent); }
.fn-field.is-valid .fn-field__tick { transform: scale(1); }
/* Corrige apres un refus du serveur : le filet rouge et le message tombent
   des que le format est bon, sans attendre la soumission suivante. */
.fn-field.is-valid .fn-input.is-invalid { border-color: transparent; }
.fn-field.is-valid .fn-error { display: none; }

@media (prefers-reduced-motion: reduce) {
  .fn-form--enter > .fn-form__question,
  .fn-form--enter > .fn-form__block,
  .fn-form--enter-back > .fn-form__question,
  .fn-form--enter-back > .fn-form__block,
  .fn-form--enter .fn-progress__bar,
  .fn-form--enter-back .fn-progress__bar,
  .fn-form .fn-choice.is-pop { animation: none; }
  .fn-form .fn-choice,
  .fn-tick { transition: none; }
  .fn-form .fn-choice:hover,
  .fn-form .fn-choice:active { transform: none; }
}

/* --- Contenus repris du prototype — 2026-10-15 ---------------------------
   Tuiles enrichies, age a -/+, encouragements, ecran final en trois phases.
   Valeurs du prototype, couleurs du design system. Figma ne dessine aucun de
   ces elements : tout ce bloc est [PROPOSE].

   1. Une colonne a toutes les tailles quand l'etape le demande
      (`columns => 1` dans le schema) : libelles longs. */
@media (min-width: 768px) {
  .fn-form__options--one { grid-template-columns: minmax(0, 1fr); }
}

/* 2. Tuile enrichie : pastille d'icone a gauche, texte aligne a gauche,
      ligne de precision dessous. A la selection, la pastille passe a
      l'accent et pivote un peu (prototype). */
.fn-choice--rich {
  justify-content: flex-start;
  gap: var(--fn-space-12);
  text-align: left;
}
.fn-choice__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-icon);
  color: var(--fn-text);
  transition:
    background-color 200ms var(--fn-easing),
    color 200ms var(--fn-easing),
    transform 300ms var(--fn-easing-out);
}
.fn-choice__icon svg { width: 18px; height: 18px; }
.fn-choice--selected .fn-choice__icon,
.fn-choice:has(input:checked) .fn-choice__icon {
  background: var(--fn-text-accent);
  color: var(--fn-text-inverse);
  transform: rotate(-6deg);
}
.fn-choice__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fn-choice__label { display: inline; }
.fn-choice__label .fn-choice__note { margin-left: var(--fn-space-6); }
.fn-choice__hint {
  font-size: var(--fn-size-12);
  line-height: 16px;
  font-weight: var(--fn-weight-regular);
  color: var(--fn-text-secondary);
}
.fn-choice--selected .fn-choice__hint,
.fn-choice:has(input:checked) .fn-choice__hint { color: inherit; opacity: 0.8; }
/* Badge au coin haut gauche, a cheval sur le bord. Vert fonce et non bleu
   nuit comme dans le prototype : sur une tuile choisie, donc bleu nuit, il
   s'y fondrait. Blanc sur #286239 : 7,25:1. */
.fn-choice__badge {
  position: absolute;
  top: -9px;
  left: var(--fn-space-12);
  padding: 2px var(--fn-space-6);
  border-radius: var(--fn-radius-pill);
  background: var(--fn-vert-vitalite-800);
  color: var(--fn-text-inverse);
  font-size: var(--fn-size-10);
  line-height: 14px;
  font-weight: var(--fn-weight-bold);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* 3. Age : boutons -/+ de part et d'autre de la boite (reveles par
      `richiesta.js`), pastille quand l'age est dans les bornes. */
.fn-eta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--fn-space-20);
}
.fn-eta .fn-money { margin-inline: 0; }
.fn-eta__step {
  display: grid;
  place-items: center;
  flex: none;
  width: 52px;
  height: 52px;
  border: var(--fn-border-width) solid var(--fn-border-subtle);
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  color: var(--fn-text);
  font-family: var(--fn-font-body);
  font-size: 24px;
  font-weight: var(--fn-weight-bold);
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--fn-duration) var(--fn-easing), transform 150ms var(--fn-easing);
}
.fn-eta__step[hidden] { display: none; }
.fn-eta__step:hover { border-color: var(--fn-text-accent); }
.fn-eta__step:active { transform: scale(0.94); }
.fn-money--counter { position: relative; transition: box-shadow var(--fn-duration) var(--fn-easing); }
.fn-money--counter .fn-tick { top: -10px; right: -10px; }
.fn-money--counter.is-valid { box-shadow: inset 0 0 0 2px var(--fn-text-accent); }
.fn-money--counter.is-valid .fn-tick { transform: scale(1); }
.fn-money--counter.is-valid.is-invalid { border-color: transparent; }
.fn-eta .fn-money--counter.is-valid ~ .fn-error,
.fn-form__block:has(.fn-money--counter.is-valid) > .fn-error { display: none; }

/* 4. Encouragement a droite de « Passo X di Y ». Vert fonce : l'accent ne
      fait que 2,8:1 sur le sable, le 800 fait 6,3:1. */
.fn-form__status {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--fn-space-10);
}
.fn-form__cheer {
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  font-weight: var(--fn-weight-bold);
  color: var(--fn-vert-vitalite-800);
  text-align: right;
}
.fn-form--enter .fn-form__cheer,
.fn-form--enter-back .fn-form__cheer { animation: fn-appear 300ms var(--fn-easing) both; }

/* 5. Ecran final : cercle qui ressort, coche qui se trace, puis la suite en
      trois phases (une colonne en mobile, trois a partir de 768). */
.fn-outcome__ring {
  display: grid;
  place-items: center;
  align-self: center;
  width: 88px;
  height: 88px;
  margin-top: var(--fn-space-10);
  border-radius: var(--fn-radius-full);
  background: var(--fn-text-accent);
  color: var(--fn-text-inverse);
  box-shadow: 0 0 0 12px var(--fn-vert-vitalite-100);
  animation: fn-ring 700ms var(--fn-easing-spring) both;
}
.fn-outcome__ring path {
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
  animation: fn-draw 500ms 400ms ease forwards;
}
@keyframes fn-ring { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes fn-draw { to { stroke-dashoffset: 0; } }

.fn-outcome__next { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-phases {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--fn-space-10);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 768px) {
  .fn-phases { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.fn-phases__item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--fn-space-6);
  padding: var(--fn-space-14);
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
}
.fn-phases__item .fn-badge { margin-bottom: var(--fn-space-4); }
.fn-phases__title { font-weight: var(--fn-weight-bold); }
.fn-phases__text { color: var(--fn-text-secondary); }

@media (prefers-reduced-motion: reduce) {
  .fn-choice__icon,
  .fn-eta__step,
  .fn-money--counter { transition: none; }
  .fn-choice--selected .fn-choice__icon,
  .fn-choice:has(input:checked) .fn-choice__icon { transform: none; }
  .fn-form--enter .fn-form__cheer,
  .fn-form--enter-back .fn-form__cheer,
  .fn-outcome__ring { animation: none; }
  .fn-outcome__ring path { animation: none; stroke-dashoffset: 0; }
}

/* --- Ecran de resultat (variante 8, 204:1460) --------------------------
   Pas de barre de progression : un titre Barlow 32, un chapo, une carte
   claire a 30 d'ecart, puis la barre de retour a l'accueil. La carte est
   pleine largeur, retrait de 20, sans bordure.                            */
.fn-outcome {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
  width: 100%;
  max-width: 550px;
  margin-inline: auto;
}
.fn-outcome__head { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-outcome__lead { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); margin: 0; }
.fn-outcome__card {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-20);
  padding: var(--fn-space-20);
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
}
.fn-outcome__card p { margin: 0; font-size: var(--fn-size-14); line-height: var(--fn-leading-body); }
/* Les actions de la carte (206:1668) : pleine largeur, empilees a 10 d'ecart,
   40 de haut. Chacune ne s'affiche que si sa destination est renseignee — voir
   `finami_richiesta_contatti()` et `finami_richiesta_partner()`.
   Figma n'en dessine que deux, WhatsApp borde et le rappel en bleu nuit. Le
   bloc en porte une troisieme depuis le 2026-09-22, la redirection partenaire,
   qui prend le bouton plein et renvoie le rappel au bouton borde — deux
   boutons pleins dans une meme carte ne designent plus d'action principale.
   Sans URL partenaire, l'ecran reste celui de Figma.                        */
.fn-outcome__actions { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-outcome__actions .fn-btn { min-height: 40px; padding-block: 0; gap: var(--fn-space-10); }
.fn-outcome__actions .fn-btn svg { width: 22px; height: 22px; }
/* Le sigle WhatsApp garde le vert de **sa** marque, et non l'accent Finami :
   c'est le seul endroit du site ou une couleur ne vient pas de la palette.
   Elle n'est donc pas un token — l'inscrire dans `finami-tokens.css` la
   ferait entrer dans la palette de l'editeur WordPress via `theme.json`.
   Le tracé est plein (`finami_icon_filled_paths()`), sa couleur passe donc
   par `color`, que le `fill="currentColor"` du sprite reprend.             */
.fn-u-whatsapp { color: #25d366; }
.fn-outcome__rows { display: flex; flex-direction: column; gap: var(--fn-space-10); margin: 0; }
.fn-outcome__row { display: flex; justify-content: space-between; gap: var(--fn-space-20); }
.fn-outcome__row dt { font-size: var(--fn-size-14); line-height: var(--fn-leading-body); }
.fn-outcome__row dd {
  margin: 0;
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  font-weight: var(--fn-weight-bold);
}
/* Carte de l'ecran repris de finami.it (2026-10-20) : centree, coche plus
   petite, verdict en vert 800 (l'accent ne tient pas le contraste), un seul
   bouton vers le partenaire.                                              */
.fn-outcome__card--esito {
  align-items: center;
  padding: var(--fn-space-30) var(--fn-space-20);
  text-align: center;
}
.fn-outcome__card--esito .fn-outcome__ring {
  width: 64px;
  height: 64px;
  margin: var(--fn-space-10) 0 0;
  box-shadow: 0 0 0 8px var(--fn-vert-vitalite-100);
}
.fn-outcome__verdict {
  margin: 0;
  font-size: var(--fn-size-18);
  line-height: var(--fn-leading-body);
  font-weight: var(--fn-weight-bold);
  color: var(--fn-vert-vitalite-800);
}
.fn-outcome__cta { min-height: 48px; gap: var(--fn-space-10); }
/* Renvoi vers le partenaire, sous le bouton : demande du 2026-10-27, « environ
   la moitie » des 14px de la carte, puis « encore plus petit » que les 10px
   de l'echelle. 8px hors echelle, voulu ; en dessous, la mention ne se lit
   plus. */
.fn-outcome__card .fn-outcome__note { font-size: 0.5rem; }
.fn-outcome__cta svg { width: var(--fn-icon-sm); height: var(--fn-icon-sm); }
.fn-outcome__back {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--fn-space-10);
  min-height: 40px;
  border-radius: var(--fn-radius-control);
  background: var(--fn-surface-page);
  font-size: var(--fn-size-14);
  font-weight: var(--fn-weight-bold);
  text-decoration: none;
}
.fn-outcome__back svg { width: var(--fn-icon-sm); height: var(--fn-icon-sm); }

/* ------------------------------------------------------------------ ETAPES
   Carousel « Fase 1..4 » : carte blanche large, texte a gauche, visuel a droite. */

.fn-steps {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
  padding: var(--fn-space-20);
  border-radius: var(--fn-radius-card);
  background: var(--fn-surface-raised);
  box-shadow: var(--fn-shadow-lg);
}
.fn-steps__body { display: flex; flex-direction: column; gap: var(--fn-space-30); }
.fn-steps__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--fn-space-20);
}
.fn-steps__text { font-size: var(--fn-size-15); line-height: var(--fn-leading-large); margin: 0; }
/* Le visuel est une **boite**, pas une image posee : sans la regle ci-dessous
   les attributs `width="784" height="640"` du balisage s'appliquent tels
   quels comme hauteur, `max-width: 100%` ne rabat que la largeur, et l'image
   sort etiree — 392 x **640** dans une boite de 392 x 320, soit un facteur
   deux en vertical et la moitie basse coupee par l'`overflow`. Les quatre
   fases etaient touchees, pas seulement celles qui changent de fichier.
   C'est l'idiome des quatre autres visuels de la feuille
   (`.fn-card__media`, `.fn-article-card__media`, `.fn-hero__bg`,
   `.fn-article__media`) ; le carrousel etait le seul a ne pas l'avoir.

   `aspect-ratio` tient la boite en mobile, ou aucune hauteur n'est imposee :
   les fichiers n'ont pas tous le meme rapport — step.jpg fait 784 x 640
   (1,225) et les trois prod*.jpg 760 x 422 (1,80) —, et la carte changeait
   donc de hauteur a chaque etape. En desktop la largeur et la hauteur sont
   toutes deux fixees plus bas, le rapport y est sans effet — il vaut de
   toute facon 392 / 320.                                                   */
.fn-steps__media {
  border-radius: var(--fn-radius-media);
  overflow: hidden;
  aspect-ratio: 392 / 320;
  /* Le rapport de 1,225 est celui du visuel desktop, presque carre : tenu seul,
     il donne un pave de 913 x **745** sur la plage 768-1023, ou la carte est
     encore en colonne et le visuel pleine largeur. Le plafond est la hauteur
     dessinee (320) : la boite garde son rapport tant qu'elle est etroite — a
     390 elle rend environ 318 x 260 — et cesse de grandir au-dela. */
  max-height: 320px;
}
.fn-steps__media img { width: 100%; height: 100%; object-fit: cover; }
/* La rangee prend toute la largeur de la carte (le corps est une colonne
   flex, donc etiree) : sans consigne, fleches et puces se tassent a gauche et
   laissent un grand vide a droite. Centrees en mobile, ou la carte est une
   seule colonne (demande du 2026-09-15) ; remises a gauche a partir de 1024,
   ou elles s'alignent sous le texte du relevé Figma. */
.fn-steps__controls { display: flex; align-items: center; justify-content: center; gap: var(--fn-space-30); }
.fn-steps__dots { display: flex; align-items: center; gap: var(--fn-space-10); }
.fn-steps__dots i {
  width: 12px; height: 12px;
  border-radius: var(--fn-radius-full);
  background: var(--fn-surface-sand);
}
.fn-steps__dots i.is-active { background: var(--fn-action-bg); }

@media (min-width: 1024px) {
  .fn-steps {
    flex-direction: row;
    align-items: center;
    gap: var(--fn-space-60);
    padding: var(--fn-space-30);
    /* 1025 dans les maquettes, et non toute la largeur du conteneur. */
    max-width: 1025px;
    margin-inline: auto;
  }
  .fn-steps__body { flex: 1 1 0; }
  .fn-steps__controls { justify-content: flex-start; }
  .fn-steps__media { flex: 0 0 392px; height: 320px; }
}

/* ------------------------------------------------------------------ FOOTER */

.fn-footer {
  padding: var(--fn-space-50) var(--fn-gutter) var(--fn-space-30);
  background: var(--fn-gradient-footer);
  color: var(--fn-text-inverse);
}
/* Fond blanc, texte sombre.

   ⚠️ **Cette variante n'est plus posee sur aucune page depuis le 2026-09-15.**
   Le pied de page de l'accueil — degrade sombre, logo blanc, texte clair — est
   desormais servi partout : uniformisation demandee ce jour-la.

   La regle reste dans la feuille parce que c'est elle que **Figma** dessine, et
   que l'aller-retour doit rester d'une ligne. Releve le 2026-09-03 avec le
   gabarit « Formulaire » : six gabarits sur six portent le pied de page clair
   — Formulaire (216:3393), Qui sommes-nous (310:772), Article (387:914),
   Mentions legales (400:3127), 404 (400:3475) et index du blog (316:255) —,
   seul l'accueil (216:2967) portant le degrade. Y revenir tient en un
   `add_filter( 'finami_footer_light', ... )` ; l'en-tete de footer.php donne la
   ligne exacte.

   Le modificateur ne porte que le fond et la couleur du texte : les filets
   (#dcdcdc) et les liens, qui heritent de la couleur, tiennent sur les deux
   fonds. Le logo, lui, change de variante — c'est footer.php qui le choisit,
   un SVG blanc ne se recolorant pas. */
.fn-footer--light {
  background: var(--fn-surface-raised);
  color: var(--fn-text);
}
.fn-footer__inner {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-16);
  max-width: var(--fn-container);
  margin-inline: auto;
}
/* Ecart 33 : le fichier espace les deux colonnes de **16** en mobile
   (400:3326 finit a 241, 400:3344 commence a 257), la ou la feuille mettait
   30. Le desktop passe a 50, plus bas. */
.fn-footer__cols { display: flex; flex-direction: column; gap: var(--fn-space-16); }
/* La colonne de marque empile le logo et le bloc de navigation a 30 d'ecart —
   a toutes les largeurs. Reservee au desktop, la regle laissait « Navigazione »
   coller au logo en mobile. */
.fn-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
/* Le logo du pied de page a la meme **boite** que celui de la navbar — 117 x 56
   (216:2972) — mais pas la meme taille de mot : Figma y dessine 94,89 x 27,87,
   contre 83,87 x 24,63 dans la navbar. Le fichier est inconstant sur ce point ;
   les deux tailles sont reproduites, d'ou ces 28 la ou la navbar met 25.
   Ecart 21 du chapitre 5 du README.                                        */
.fn-footer__brand img { width: auto; height: 28px; }
/* La colonne de marque empile **deux blocs** a 30 d'ecart — la boite du logo
   et le bloc « Navigazione » —, et non ses trois elements. Figma : logo
   117 x **56** (400:3327), puis a 30 un bloc de 155 ou « Navigazione » (19)
   est a **10** de ses liens (400:3331 / 400:3333). La feuille espacait les
   trois de 30 et laissait la boite du logo a la hauteur de l'image : la
   colonne rendait 195,59 pour 241. Les deux `<div>` du balisage sont les
   memes dans les cinq fichiers qui portent ce pied de page. */
.fn-footer__brand > div {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}
/* ⚠️ `align-items: flex-start` n'est pas un reglage d'alignement : c'est ce
   qui **empeche le logo de s'etirer sur toute la colonne**. Un `<img>` pose
   dans un conteneur flex en colonne est un element flex comme un autre, donc
   `align-items: stretch` par defaut, donc large de tout l'axe transversal —
   et `width: auto` se resout alors a cette largeur, pas au rapport de
   l'image. Le logo rendait **394 x 28** en desktop et **350 x 28** a 390,
   pour 95 x 28 dessines. Le mot etait etire d'un facteur quatre.

   Deux raisons pour lesquelles ca ne se voyait pas dans la navbar et ne
   s'attrapait pas a la lecture : `.fn-navbar__logo` porte
   `align-items: center`, qui annule l'etirement sans le dire ; et les trois
   SVG sortaient de Figma avec `preserveAspectRatio="none"`, qui **autorise**
   la deformation au lieu de la caler dans la boite. L'attribut a ete retire
   des trois fichiers le 2026-09-10 : desormais, une boite fausse laisse du
   vide — visible et sans consequence — au lieu de deformer le mot.

   Le mot est cale a **gauche**, aligne sur « Navigazione » : la capture
   `_captures/logo-contexte-footer.png` montre les deux bords a la meme
   abscisse. Il n'est donc pas centre dans la boite de 117 de Figma, a la
   difference de la navbar.                                                */
.fn-footer__brand > div:first-child {
  height: 56px;
  justify-content: center;
  align-items: flex-start;
}
.fn-footer__nav { display: flex; gap: var(--fn-space-40); }
.fn-footer__nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
/* Quatre liens de 30 poses a 32 d'intervalle (400:3335 et suivants) : la
   colonne fait 126 et non 120. */
.fn-footer__nav li { line-height: var(--fn-leading-list); }
.fn-footer__nav a { text-decoration: none; font-size: var(--fn-size-14); }
/* ⚠️ `:not(.fn-card-title)` n'est pas decoratif : ecrite `.fn-footer__legal p`,
   la regle primait sur `.fn-card-title` et rendait « Informazioni legali » en
   Lato 14/22 au lieu de 20/24 — le fichier lui donne 156 x **24** (400:3345),
   c'est bien un titre de carte. */
.fn-footer__legal p:not(.fn-card-title) { font-size: var(--fn-size-14); line-height: var(--fn-leading-prose); margin: 0 0 var(--fn-space-16); }
/* « Informazioni legali » se collait au paragraphe : la regle ci-dessus ne pose
   qu'une marge **basse**, et `.fn-card-title` porte `margin: 0`. Le fichier met
   16 sous le titre, exactement comme entre deux paragraphes — et il le met sur
   les **dix-sept** pieds de page de la page « Maquettes », desktop et mobile,
   tous gabarits : titre a y=0 h=24, paragraphe a y=40 (releve du 2026-09-01,
   `outils/figma-maquettes-metadata.txt`). Ce n'etait donc pas un choix de
   composition mais un oubli de code, et il valait 16 de moins a la colonne. */
.fn-footer__legal .fn-card-title { margin-bottom: var(--fn-space-16); }
/* La marge du dernier paragraphe tombait dans le vide en bout de colonne : la
   colonne est un element flex, elle ne la laisse pas sortir. +16.

   ⚠️ Le `p` n'est pas decoratif, et cette regle a ete **inoperante du
   2026-09-08 au 2026-09-15**. Ecrite `> :last-child`, elle pesait 0,2,0 quand
   `.fn-footer__legal p:not(.fn-card-title)` pese 0,2,1 : la marge basse du
   dernier paragraphe passait devant, et les 16 qu'on croyait retires etaient
   toujours la. C'est la **troisieme** fois que ce piege se presente dans la
   feuille, et la deuxieme dans ce seul bloc, apres `.fn-footer__legal p` qui
   primait sur `.fn-card-title`. Le `p` remonte la regle a 0,2,1 et sa place
   plus tardive tranche l'egalite.

   Decouvert en posant les 16 sous le titre : le pied de page desktop passait
   de 432 a 448 pour 438 dessines. Les deux defauts se compensaient a -6, et
   ce -6 etait mis au compte du mou du fichier (ecart 45). */
.fn-footer__legal > p:last-child { margin-bottom: 0; }
.fn-footer__legal a { text-decoration: underline; }
/* `margin: 0` n'est pas decoratif : quatrieme rencontre du meme piege, et la
   plus couteuse — la marge par defaut de ce <p> (12 de corps, donc 12 en haut
   et 12 en bas, qui ne fusionnent pas en flux flex) rendait le pied de page
   **20 px trop haut sur toutes les pages du site**, l'accueil comprise :
   +24 de marge, -4 de l'ecart corrige juste en dessous. Releve le 2026-09-07
   en mesurant la bande contre 400:3127 — 438 dessines, 458 rendus. */
/* Interligne **14** et retrait de 20 : le fichier donne 1140 x 28 en desktop
   (216:2996, deux lignes) et 310 x 70 en mobile (400:3351, cinq lignes), tous
   deux poses a x = 20 dans un cadre pleine largeur. La feuille laissait
   l'interligne herite de 20 : 20 rendu pour 28 en desktop, ce qui **masquait**
   les +8 de la colonne legale et faisait tomber le pied de page desktop sur
   438 par compensation. C'est precisement ce que l'ecart 33 interdisait —
   « ne pas compenser une cause par l'autre ». */
.fn-footer__disclaimer {
  font-size: var(--fn-size-12);
  line-height: var(--fn-leading-badge);
  padding-inline: var(--fn-space-20);
  margin: 0;
}
/* Figma espace le **premier** filet du bloc de 20 et les deux suivants de 16 :
   400:3128 finit a 51 et 400:3129 commence a 71, quand 400:3154 finit a 293
   et 400:3155 commence a 309. Un seul ecart sur trois differe, d'ou ce
   complement plutot qu'un `gap` pose element par element. */
.fn-footer__inner > .fn-divider:first-child { margin-bottom: var(--fn-space-4); }

@media (min-width: 1024px) {
  .fn-footer__cols { flex-direction: row; align-items: center; gap: var(--fn-space-50); }
  .fn-footer__brand { flex: 0 0 394px; }
  .fn-footer__legal { flex: 1 1 0; padding: var(--fn-space-14); }
}

/* ----------------------------------------------------------------- 404
   Gabarit « Template 404 » (400:3433), releve le 2026-09-07. Corps
   400:3448 en desktop (1920 x 800) et 400:3593 en mobile (390 x 600).

   Les deux frames sont APLATIES : `get_metadata` les rend vides, et leur
   fond photographique est une garniture de calque que `get_design_context`
   n'emet pas non plus. Le dessin s'est donc lu sur les captures
   (outils/_captures/404/), et le texte sur le code de reference.

   Ce que le fichier dessine, et rien d'autre : un titre et un sous-titre
   blancs sur la photographie. Ni pastille, ni bouton — ecart 23 du
   chapitre 5 du README. La sortie de la page reste le logo et les trois
   pilules de la navbar, qui est collante.

   La classe existait depuis un relevé antérieur et n'avait jamais été
   posée. Elle etait juste sur trois points (couleur inverse, plancher de
   800 a 768, gap de 20) et fausse sur deux : `min-height: 480px` en
   mobile, la ou Figma dessine 600, et `text-align: center` avec
   `align-items: flex-start`. Cette contradiction venait du fichier :
   Figma emet bien `text-center` sur un conteneur `items-start` et
   `whitespace-nowrap`, ou il ne peut rien faire. Le desktop est donc
   aligne a gauche, et c'est le mobile qui est centre.                     */

.fn-404 {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Figma ne centre pas le bloc en mobile : il le pose a une position
     absolue, `top: 300` pour le titre et `top: 380` pour le sous-titre
     (groupe 425:189, 350 x 120) — la moitie exacte des 600 du cadre.
     Centre, le bloc tomberait a 239 et recouvrirait le visage du sujet.
     D'ou ce retrait haut, et le centrage reserve au desktop.              */
  justify-content: flex-start;
  min-height: 600px;
  padding-block: 300px var(--fn-space-50);
  overflow: hidden;
  /* Le fond reste sous la photographie : il tient la lisibilite pendant le
     chargement, et c'est lui qu'on voit si ni l'image ni la video ne sont
     encore la. */
  background: var(--fn-noir-500);
  color: var(--fn-text-inverse);
}

/* Meme construction que le hero : la photographie est une <img> en
   « cover » et non un `background-image`, ce qui laisse <picture> faire
   l'art direction entre le cadrage desktop et le cadrage mobile. */
.fn-404__bg { position: absolute; inset: 0; pointer-events: none; }
.fn-404__bg picture,
.fn-404__bg img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- La video de fond -------------------------------------------------
   Depuis le 2026-09-10 le fond bouge : `404.mp4` / `404-mobile.mp4`, les
   memes cadrages que les trois affiches, fabriques par `build-video.py`
   depuis le rush dont Figma avait tire son image fixe.

   Elle se **superpose** a la photographie, elle ne la remplace pas. La
   photographie reste la couche du dessous et sert seule dans quatre cas :
   mouvement reduit, economiseur de donnees, JavaScript coupe, et la
   seconde ou deux que la video met a demarrer. C'est aussi pour ca que
   l'affiche est la premiere image du rush — le passage de l'une a l'autre
   ne bouge pas d'un pixel.

   L'element est ecrit `hidden` et **sans `src`** : c'est le script qui
   choisit le fichier selon la largeur, parce que l'attribut `media` d'un
   `<source>` dans un `<video>` n'est plus honore par les navigateurs —
   contrairement a `<picture>`, ou il l'est. Sans script, rien n'est
   telecharge du tout.                                                    */
.fn-404__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Le fondu d'apparition, une fois la premiere image jouee. */
  opacity: 0;
  transition: opacity 600ms ease-out;
}
.fn-404__video.is-playing { opacity: 1; }
/* La regle du dessus est un `display: block` d'auteur : elle bat le
   `[hidden] { display: none }` du navigateur, qui vient de la feuille de
   l'agent. Meme piege que `.fn-menu-mobile` et `.fn-btn-icon`.            */
.fn-404__video[hidden] { display: none; }

/* --- Le voile ---------------------------------------------------------
   ⚠️ **Il ne figure pas dans Figma, et il n'est pas negociable.**

   Le fichier montre une image fixe assez sombre pour porter du texte
   blanc. Le rush, lui, est en plein soleil : la tribune du fond est
   presque blanche, et « Pagina 404 » y disparait par endroits. Le voile
   rend au titre le contraste que l'image fixe avait de naissance.

   Il suit le texte, pas le sujet — degrade vers le bas en mobile, ou le
   bloc est pose a 300 sur 600 ; vers la droite en desktop, ou il est cale
   a gauche. L'homme au polo vert, qui est a droite aux deux largeurs,
   reste ainsi le moins couvert.

   Ni `--fn-overlay-hero` ni `--fn-scrim` n'y servent, et c'est pour cette
   raison : un aplat unique voilerait le sujet autant que le texte. Trois
   opacites par largeur, qu'aucun des deux tokens ne porte. C'est l'ecart
   26 du chapitre 5 du README, a faire confirmer par le design.           */
.fn-404__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.25) 0%,
    rgba(0, 0, 0, 0.62) 45%,
    rgba(0, 0, 0, 0.78) 100%
  );
}

/* Se pose sur le meme element que `.fn-container`, qui fournit le retrait
   lateral : 20 en mobile — Figma pose le sous-titre a `left: 20 right: 20`,
   soit 350 de large, exactement ce que rend le conteneur — et 360 a 1920,
   la ou Figma met 370 (ecart 5, les trois retraits unifies sur 360).      */
.fn-404__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fn-space-20);
  text-align: center;
}
/* C'est le `gap` qui porte l'ecart de 20, et lui seul. `.fn-display-404` est
   deja a zero, mais `.fn-body` n'annule pas la marge par defaut du <p> : elle
   s'ajoutait au gap et descendait tout le bloc de 28. Reset local, pour ne
   pas deplacer les huit autres emplois de `.fn-body`. */
.fn-404__inner > * { margin: 0; }

@media (min-width: 768px) {
  .fn-404 {
    min-height: 800px;
    padding-block: var(--fn-space-50);
    justify-content: center;
  }
  .fn-404__inner { align-items: flex-start; text-align: left; }
  /* Le texte passe a gauche : le voile tourne avec lui. */
  .fn-404__bg::after {
    background: linear-gradient(
      to right,
      rgba(0, 0, 0, 0.78) 0%,
      rgba(0, 0, 0, 0.58) 40%,
      rgba(0, 0, 0, 0.18) 100%
    );
  }
}

/* ------------------------------------------------------- ARTICLE ET BLOG
   Releves le 2026-09-08 dans la section « Template Article » (316:198), qui
   contient les **quatre** cadres du chantier :

     article seul   387:850   1920 x 3766,5   /  387:944   390 x 5087,375
     index du blog  387:1238  1920 x 1684,5   /  316:244   390 x 3497,375

   Le gabarit n'est pas aplati : `get_metadata` en rend l'arbre entier, texte
   par texte. Tout ce qui suit est donc **mesure**, sauf ce qui est signale.

   Les quatre bandes de premier niveau :

                    navbar   corps        correles   pied de page
     article 1920      96    2794           438,5      438
     article  390     158    3601,875       508,5      819
     index   1920      96    1150,5           —        438
     index    390     158    2458,375         —        881

   La navbar mobile fait 158 parce que le cadre porte la barre d'etat de
   l'iPhone (62 + 96) : elle ne se reproduit pas.                           */

/* --- L'article ---------------------------------------------------------
   Le corps est une colonne de 800 (350 en mobile) posee dans 50 de
   respiration, et **tout y est a 30 d'ecart** — fil d'ariane, en-tete, visuel,
   puis les blocs de prose. Les positions du fichier le disent d'elles-memes :
   50 · 14 · 30 · 237 · 30 · 605 · 30 · [prose] · 50 = 2794.                */
.fn-article {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
.fn-article > * { margin: 0; }

/* En-tete : trois blocs a 30 d'ecart — 31 + 30 + 112 + 30 + 34 = 237 en
   desktop, 31 + 30 + 183 + 30 + 64 = 338 en mobile.                        */
.fn-article__head {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
.fn-article__head > * { margin: 0; }

/* Rangee « pastille de categorie + date » : la date suit la pastille a 10,
   toutes deux calees a gauche (400:1395, 184 = 98 + 10 + 76).              */
.fn-article__cat {
  display: flex;
  align-items: center;
  gap: var(--fn-space-10);
  min-height: 31px;
}

/* Titre et chapo : 10 d'ecart (400:1399).

   ⚠️ **Et tous deux sur une mesure plus etroite que la colonne.** Le corps de
   l'article est une colonne de 800 ; le titre y tient dans **391**
   (400:1400) et le chapo dans **614** (400:1401). Ce n'est pas un hasard
   d'enroulement : a 26 px le titre entier ferait 651,75 sur une seule ligne,
   et le fichier le montre sur deux, coupe apres « consolidazione » — donc
   quelque chose le retient. C'est ce qui a fait rendre l'en-tete 205,88 au
   lieu de 237 au premier controle : le titre s'y etalait sur toute la
   colonne.

   En 390 les deux boites valent 350, soit la colonne entiere : les deux
   mesures ne mordent qu'a partir de 768, sans avoir besoin d'une bascule. */
.fn-article__titles {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}
.fn-article__titles > * { margin: 0; }
.fn-article__titles .fn-post-title  { max-width: 391px; }
.fn-article__titles .fn-article__lead { max-width: 614px; }

/* Le chapo est en **Lato Regular**, et non dans le `.fn-lead` gras du hero :
   la densite d'encre mesuree sur la capture 1:1 vaut 0,33 px par pixel de
   hauteur de glyphe, contre 0,58 pour le Lato Bold 14 des intertitres voisins.

   Son corps est **14 aux deux largeurs** — corrige le 2026-09-10, au chantier
   du gabarit « Guide ». Il valait 16, deduit des boites : « 350 x 80 en mobile
   (quatre lignes) exclut 14, qui n'en ferait que trois ». **La premisse etait
   fausse** — a 14, le chapo mobile de l'article fait bien quatre lignes, donc
   80 —, et une boite de 614 x 40 en desktop est satisfaite par 14 comme par
   18 : les boites ne tranchaient rien. Ce sont les **coupes de ligne** qui
   tranchent, et elles se lisent sur les captures 1:1 (methode de l'ecart 47) :

     ligne 2 du chapo desktop    fichier  47   rendu a 14 :  52   a 16 : 146
     4 lignes du chapo mobile    fichier 258 / 320 / 281 / 79
                                 rendu a 14 : 256 / 318 / 284 / 79
     2 lignes du chapo du guide  fichier 336 / 299
                                 rendu a 14 : 332 / 300   a 16 : trois lignes

   Six lignes reproduites a moins de 4 px sur deux gabarits ; a 16, aucune ne
   tombe. La hauteur de tete, elle, ne bouge pas d'un pixel entre les deux
   corps (2 lignes x 20 dans les deux cas) : c'est pourquoi le controle du
   2026-09-08, qui ne mesurait que des bandes, ne pouvait pas le voir.
   Ecart 50 du README. La regle « aucune bascule typographique sur une page
   editoriale » (2.10) tient toujours : 14 vaut aux deux largeurs.       */
.fn-article__lead {
  font-size: var(--fn-size-14);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
}

/* Ligne de signature : l'auteur a gauche, la duree de lecture a droite.

   Figma y met **deux** signatures (« Scritto da : Vicenzo L. — Revisionato
   da : Valentina M. ») et deux vignettes de 34. Ni l'une ni l'autre ne sont
   reprises : WordPress ne connait qu'un auteur (decision du 2026-09-01,
   maintenue), et une vignette d'auteur passerait par Gravatar, donc par une
   requete vers un tiers — ce que le theme s'interdit partout ailleurs, jusqu'a
   auto-heberger ses quatre fontes. Ecarts 37 et 38.                        */
.fn-article__byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-10);
  min-height: 34px;
}
.fn-article__byline > span { display: inline-flex; align-items: center; gap: var(--fn-space-6); }

/* Visuel : 16:9 au rayon des cartes — 800 x 450 en desktop, 350 x 196,875 en
   mobile, soit exactement le rapport dans les deux cas.                     */
.fn-article__media {
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: var(--fn-radius-card);
  overflow: hidden;
  background: var(--fn-surface-muted);
}
.fn-article__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Le visuel et la rangee de services forment un bloc a **20** d'ecart, et non
   30 (400:1465 / 400:1812) : c'est le seul endroit du corps ou l'ecart change.

   Figma glisse entre les deux une **bande de lecture audio** de 90 — « Ascolta
   l'articolo », bouton de lecture, piste, `00:00/04:00` — et un lien « Scarica
   l'articolo in PDF ». Ni fichier son ni generateur de PDF n'existent dans le
   projet : les deux sont retires, et consignes aux ecarts 35 et 36. Le bloc
   perd donc 110 (la bande et son ecart) aux deux largeurs.                  */
.fn-article__figure {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-20);
}
.fn-article__figure > * { margin: 0; }

/* Rangee de services. En mobile, « Copia il link » a gauche et les reseaux a
   droite (400:1820) ; a partir de 768 les deux sont groupes a droite, a 20
   d'ecart (400:1441, x = 556 dans 800).                                     */
.fn-article__share {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-20);
  min-height: 25px;
}
.fn-article__copy {
  display: inline-flex;
  align-items: center;
  gap: var(--fn-space-6);
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--fn-font-body);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-15);
  line-height: var(--fn-leading-body);
  letter-spacing: var(--fn-tracking);
  color: var(--fn-text);
  text-decoration: underline;
  cursor: pointer;
}
/* Meme piege : le bouton est ecrit `hidden` et n'est revele que si
   `navigator.clipboard` existe — hors contexte securise, il n'existe pas. */
.fn-article__copy[hidden] { display: none; }
.fn-article__copy svg { width: var(--fn-icon-lg); height: var(--fn-icon-lg); }
/* Bande de partage : quatre marques de 25 dans 122 (400:1826), soit un ecart
   de 7,33 — ramene a 7, ce qui rend 121 pour 122.                           */
.fn-article__socials { display: flex; align-items: center; gap: 7px; }
.fn-article__socials a {
  display: inline-flex;
  width: 25px;
  height: 25px;
  color: var(--fn-text);
}
.fn-article__socials svg { width: 100%; height: 100%; }

@media (min-width: 768px) {
  .fn-article__share { justify-content: flex-end; }
}

/* --- « Articoli correlati » --------------------------------------------
   Bande entiere que le theme ne rendait pas du tout : 438,5 en desktop
   (400:1624), 508,5 en mobile (400:1905), entre le corps et le pied de page.

     desktop  50 · titre 38 · 30 · piste 270,5 · 50                = 438,5
     mobile   50 · titre 38 · 30 · piste 270,5 · 30 · nav 40 · 50  = 508,5

   Les quatre cartes tiennent dans **1074** (4 x 253,33 + 3 x 20), la troisieme
   grille plus etroite que le conteneur apres celle des etapes (1025) et celle
   des avantages (1078). Les deux boutons fleches occupent ce qui reste des
   1200 : (1200 - 1074 - 2 x 40) / 2 = 23 de chaque cote, ce que rend le
   `space-between`. En mobile la piste deborde et defile, comme les chiffres
   cles de l'accueil, et les deux boutons passent dessous, a gauche.

   Les fleches sont centrees sur la **piste entiere** et non sur le visuel :
   Figma les pose a y = 115 dans 270,5, soit 135 au centre du bouton pour
   135,25 au centre de la piste.                                             */
/* Le titre et la piste sont a 30 d'ecart (400:1624 : titre a 50, piste a 118). */
.fn-related .fn-container {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
/* Figma dessine la fleche a 19,2 dans une tuile de 40, et non a 24. */
.fn-related .fn-btn-icon svg { width: var(--fn-icon-md); height: var(--fn-icon-md); }

.fn-related__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--fn-space-30) var(--fn-space-10);
}
.fn-related__viewport {
  order: -1;
  flex: 1 0 100%;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x mandatory;
}
.fn-related__viewport::-webkit-scrollbar { display: none; }
.fn-related__track {
  display: flex;
  gap: var(--fn-space-20);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fn-related__track > li { flex: 0 0 253.33px; scroll-snap-align: start; }

@media (min-width: 768px) {
  /* `center` et non `space-between` : les deux boutons sont masques en desktop,
     ou les quatre cartes tiennent, et un `space-between` laisserait alors la
     piste calee a gauche avec 126 px de vide a droite. L'ecart de 23 est
     exactement celui du fichier — (1200 - 1074 - 2 x 40) / 2 —, de sorte que la
     rangee rende la meme chose que les boutons soient la ou non. */
  .fn-related__row { flex-wrap: nowrap; justify-content: center; gap: 23px; }
  .fn-related__viewport {
    order: 0;
    flex: 0 1 var(--fn-container-blog);
    overflow: visible;
  }
  /* ⚠️ **Largeur fixe, et non `1 1 0`.** Avec `flex: 1 1 0` les cartes se
     partageaient les 1074 : a trois cartes chacune passait de 253,5 a 344,67,
     la vignette 16:9 gagnait 51,28 et la bande entiere avec elle — 438,59 a
     quatre cartes, 489,88 a trois, ~592 a deux. La hauteur de la bande
     dependait donc du nombre d'articles publies sur le site, et le 438,5 du
     fichier n'etait juste que pour un compte exact. Reproduit le 2026-09-10
     sur deux Playground identiques a un article pres (5 puis 4 publies) :
     438,59 -> 489,88 sur le meme article, au centieme de la preprod.

     Figma ne dessine que le cas a quatre cartes ; le comportement en dessous
     a ete tranche le 2026-09-10 — **garder la largeur dessinee et centrer**,
     de sorte que la bande vaille 438,5 quel que soit le nombre de cartes. En
     mobile la question ne se posait pas : `flex: 0 0 253.33px` y est deja
     fixe, et les deux etats mesurent 508,48 l'un comme l'autre.

     ⚠️ **253,3333 et non 253,5.** `--fn-container-blog` vaut 1074, mais la
     piste du fichier (`400:1737`) fait **1073,3334** et chaque carte
     (`400:1738`) **253,3333** — 4 x 253,3333 + 3 x 20 s'y referme exactement.
     Le 253,5 que donnait `(1074 - 60) / 4` est l'arrondi du token, et c'est
     lui qui traînait le **+0,09** porte par toutes les tables de controle
     depuis le 2026-09-08 : bande 438,59 pour 438,5, carte 270,59 pour 270,5,
     vignette 142,59 pour 142,5. Avec la largeur du fichier les trois tombent
     juste.

     `0 1` et non `0 0` : entre 768 et 1200 la piste est plus large que le
     conteneur, et les cartes doivent pouvoir se retrecir pour tenir. Un
     `0 0` y ferait deborder la piste hors de la fenetre, `overflow` valant
     `visible` a cette largeur.                                            */
  .fn-related__track { justify-content: center; }
  .fn-related__track > li { flex: 0 1 253.3333px; }
}

/* --- L'index du blog ---------------------------------------------------
   Trois blocs a **50** d'ecart dans 50 de respiration :
     desktop  50 · 215 · 50 · 785,5 · 50                 = 1150,5
     mobile   50 · 187 · 50 · 38 · 50 · 2033,375 · 50    = 2458,375          */
.fn-blog {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-50);
}

/* Le bandeau de tete a exactement la composition de `.fn-page-intro` — trois
   elements centres a 20 d'ecart —, a ceci pres que le premier est une pastille
   et non un fil d'ariane, et que le titre est celui du hero et non celui d'une
   page interieure : Barlow **32 en mobile et 52 en desktop** (2 x 38 = 76 dans
   350, 2 x 62 = 124 dans 830). C'est donc `.fn-hero-title`, et non
   `.fn-page-title` (36 / 52). Le fichier le pose dans une mesure de 830, plus
   etroite que le conteneur.                                                 */
.fn-blog__intro { max-width: 830px; margin-inline: auto; }

/* Rangee « Articoli in primo piano ». Le titre est en **Lato Regular 20 / 24**
   — la graisse se voit sur la capture, les jambages sont fins ; le corps se
   lit sur la boite de 24 et sur une encre de 190 (184 attendus en Regular 20,
   152 en Bold 16 : c'est la graisse qui tranche, pas la largeur).

   Le bouton « Filtri » du fichier n'est pas repris — il n'ouvre rien que
   WordPress sache faire, et un filtre qui ne filtre rien est le defaut que
   l'ecart 23 avait deja releve sur le 404. Les pastilles de categorie, elles,
   filtrent pour de bon. Ecart 39.                                           */
.fn-blog__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-20);
  min-height: 38px;
}
.fn-list-title {
  font-size: var(--fn-size-20);
  line-height: var(--fn-leading-large);
  letter-spacing: var(--fn-tracking);
  margin: 0;
}

/* Article en vedette : le texte et le visuel s'empilent en mobile (le texte
   d'abord, 269 · 30 · 196,875) et se rangent cote a cote a partir de 768 —
   colonne de 423,33, ecart de 50, visuel de 600 x 337, le tout centre
   verticalement (387:1348).                                                 */
.fn-blog__featured {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
/* Le visuel est un <figure>, dont la marge par defaut du navigateur vaut
   « 1em 40px » : sans cette remise a zero il rend la bande 15 de trop et se
   retrecit de 80 en largeur. Meme famille que les cinq marges de <p> deja
   rencontrees — c'est le `gap` d'un conteneur flex qui ne fusionne rien.   */
.fn-blog__featured > * { margin: 0; }
.fn-blog__featured-text {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
.fn-blog__featured-text > * { margin: 0; }
.fn-blog__featured-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fn-space-10);
  min-height: 31px;
}
/* Figma n'ecrit la duree de lecture qu'en desktop (180 contre 76 en mobile). */
.fn-blog__featured-meta .fn-meta__reading { display: none; }
.fn-blog__featured-titles {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
}
.fn-blog__featured-titles > * { margin: 0; }
/* Le titre de la vedette est un titre de carte agrandi : Barlow 20, deux
   lignes de 24 dans 423,33 comme dans 350 — le meme corps aux deux largeurs. */
.fn-article-card__title--lg { font-size: var(--fn-size-20); }
/* « Leggi l'articolo » : 148 x 40 (387:1355). `.fn-btn` seul rendrait 42 —
   voir l'ecart 40, qui vaut pour tous les boutons du projet.                */
.fn-blog__featured .fn-btn { min-height: 40px; padding-block: 0; align-self: flex-start; }
.fn-blog__featured .fn-btn svg { width: var(--fn-icon-md); height: var(--fn-icon-md); }

@media (min-width: 768px) {
  .fn-blog__featured { flex-direction: row; align-items: center; gap: var(--fn-space-50); }
  .fn-blog__featured-text { flex: 0 1 423.33px; }
  .fn-blog__featured-media { flex: 1 1 0; }
  .fn-blog__featured-meta .fn-meta__reading { display: inline; }
}

/* Pastilles de filtre : hauteur 44, retrait lateral 10, Lato Bold 16, et la
   courante bordee de bleu (441:202, 126 x 44 ; l'encre de « Visualizza tutto »
   fait 106 pour 107 en Bold 16). La bordure est posee transparente sur toutes
   pour qu'aucune ne saute de 2 px en devenant courante.                     */
.fn-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fn-space-10);
  margin: 0;
  padding: 0;
  list-style: none;
}
.fn-filters a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--fn-space-10);
  border: var(--fn-border-width) solid transparent;
  border-radius: var(--fn-radius-control);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-16);
  line-height: 1;
  letter-spacing: var(--fn-tracking);
  text-decoration: none;
}
.fn-filters a[aria-current] { border-color: var(--fn-text-link); }

/* Le bloc « pastilles de filtre + grille » : 30 d'ecart en mobile (400:2884),
   20 en desktop (387:1286).                                                 */
.fn-blog__list {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-30);
}
/* La grille des cartes est une liste : elle perd ses puces et ses marges.
   Et son ecart vaut **30 en mobile** (400:2884 et suivantes) contre 20 en
   desktop (387:1286) — la grille de l'accueil, elle, garde ses 20 aux deux
   largeurs, d'ou cette surcharge locale plutot qu'une retouche de
   `.fn-grid-4`.                                                         */
.fn-blog .fn-blog__grid { margin: 0; padding: 0; list-style: none; gap: var(--fn-space-30); }

/* Pagination — le fichier n'en dessine aucune (ecart 40). Elle emprunte le
   langage des pastilles de filtre, sans rien inventer de neuf.             */
.fn-blog .pagination { margin: 0; }
.fn-blog .nav-links { display: flex; flex-wrap: wrap; gap: var(--fn-space-10); }
.fn-blog .page-numbers {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding-inline: var(--fn-space-14);
  border: var(--fn-border-width) solid transparent;
  border-radius: var(--fn-radius-control);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
  line-height: 1;
  letter-spacing: var(--fn-tracking);
  text-decoration: none;
}
.fn-blog .page-numbers.current { border-color: var(--fn-text-link); }

@media (min-width: 768px) {
  .fn-blog__list { gap: var(--fn-space-20); }
  .fn-blog .fn-blog__grid { gap: var(--fn-space-20); }
  /* La rangee « Articoli in primo piano » est une bande a part en mobile, a 50
     de la vedette comme du bandeau (400:2663) ; en desktop elle appartient au
     bloc de la vedette et n'en est plus qu'a 20 (400:2878). Le `gap` de
     `.fn-blog` vaut 50 : la difference se rattrape ici, une fois, plutot que
     de dedoubler la structure. */
  .fn-blog__bar { margin-bottom: calc(var(--fn-space-20) - var(--fn-space-50)); }
}

/* --- Deux motifs que Figma dessine **dans le corps** de l'article -------
   Ce sont des blocs de contenu, pas du gabarit : c'est la redaction qui les
   pose. Ils sont habilles ici pour que le corps puisse rendre ce que le
   fichier montre — quatre etapes numerotees sur fond sable (400:1512 et
   suivantes) et un encart d'appel bleu nuit (400:1550).                     */
.fn-prose .fn-steps-list {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-10);
  padding: 0;
  list-style: none;
  counter-reset: fn-step;
}
.fn-prose .fn-steps-list > li {
  display: flex;
  align-items: flex-start;
  gap: var(--fn-space-20);
  padding: var(--fn-space-10) var(--fn-space-20);
  border-radius: var(--fn-radius-card);
  background: var(--fn-surface-sand);
}
.fn-prose .fn-steps-list > li::before {
  counter-increment: fn-step;
  content: counter(fn-step);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 37px;
  height: 37px;
  border-radius: var(--fn-radius-full);
  background: var(--fn-surface-dark);
  color: var(--fn-text-inverse);
  font-weight: var(--fn-weight-bold);
  font-size: var(--fn-size-14);
}
.fn-prose .fn-steps-list p { margin: 0; }
.fn-prose .fn-steps-list p + p { margin-top: var(--fn-space-10); }
@media (min-width: 768px) {
  .fn-prose .fn-steps-list > li { align-items: center; }
}

.fn-prose .fn-cta {
  display: flex;
  flex-direction: column;
  gap: var(--fn-space-20);
  padding: var(--fn-space-30) var(--fn-space-20) var(--fn-space-20);
  border-radius: var(--fn-radius-card);
  background: var(--fn-surface-dark);
  color: var(--fn-text-inverse);
}
.fn-prose .fn-cta > div { display: flex; flex-direction: column; gap: var(--fn-space-10); }
.fn-prose .fn-cta p { margin: 0; }
.fn-prose .fn-cta .fn-btn {
  min-height: 44px;
  padding-block: 0;
  background: var(--fn-surface-page);
  color: var(--fn-text);
  gap: var(--fn-space-10);
}
.fn-prose .fn-cta .fn-btn svg { width: var(--fn-icon-sm); height: var(--fn-icon-sm); }
@media (min-width: 768px) {
  .fn-prose .fn-cta {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: var(--fn-space-30) var(--fn-space-20);
  }
  .fn-prose .fn-cta .fn-btn { flex: 0 0 auto; }
}

/* ------------------------------------------------- MOUVEMENTS DE L'ACCUEIL
   2026-10-15, repris du prototype apporte ce jour-la : **les mouvements, pas
   les couleurs**. Figma n'en specifie aucun : tout ce bloc est [PROPOSE].

   1. Survols : les cartes se soulevent de 3 ou 4 px et prennent une ombre
      douce ; la photo de la carte produit grossit de 4 %. Pointeur seulement
      (`hover: hover`) : sur ecran tactile, le survol reste colle apres le
      toucher. Les cartes produit et « avantage » ont leur filet en ombre
      interieure : l'ombre portee s'y ajoute, elle ne le remplace pas. */
.fn-quick-link,
.fn-stat-card,
.fn-product-card,
.fn-feature-card {
  transition:
    transform 250ms var(--fn-easing-out),
    box-shadow 250ms var(--fn-easing);
}
.fn-product-card__media img { transition: transform 500ms var(--fn-easing-out); }

@media (hover: hover) {
  .fn-quick-link:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
  }
  .fn-stat-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 24px rgba(0, 16, 25, 0.08);
  }
  .fn-product-card:hover {
    transform: translateY(-4px);
    box-shadow:
      inset 0 0 0 var(--fn-border-width) var(--fn-border-card),
      0 18px 40px rgba(0, 16, 25, 0.08);
  }
  .fn-product-card:hover .fn-product-card__media img { transform: scale(1.04); }
  .fn-feature-card:hover {
    transform: translateY(-3px);
    box-shadow:
      inset 0 0 0 var(--fn-border-width) var(--fn-border-card),
      0 12px 28px rgba(0, 16, 25, 0.07);
  }
}

/* 2. Apparition au defilement. `.fn-reveal` et `.is-seen` sont poses par
      `home.js`, jamais par le gabarit : sans script, rien n'est masque. Un
      bloc deja a l'ecran au chargement n'est pas masque non plus. */
.fn-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 600ms var(--fn-easing-out),
    transform 600ms var(--fn-easing-out),
    box-shadow 250ms var(--fn-easing);
}
.fn-reveal.is-seen { opacity: 1; transform: none; }
/* Une carte apparue retrouve la transition courte du survol : sans quoi le
   soulevement prendrait les 600 ms de l'apparition. */
.fn-stat-card.fn-reveal.is-seen,
.fn-product-card.fn-reveal.is-seen,
.fn-feature-card.fn-reveal.is-seen {
  transition:
    opacity 600ms var(--fn-easing-out),
    transform 250ms var(--fn-easing-out),
    box-shadow 250ms var(--fn-easing);
}

/* 3. Carrousel : chaque changement d'etape fond le texte et le visuel
      (`.is-switching`, rejoue par `home.js`). Le prototype faisait glisser
      une piste de cartes ; ici une seule carte change de contenu, le fondu
      en tient lieu. */
.fn-steps__body.is-switching,
.fn-steps__media.is-switching { animation: fn-steps-swap 400ms var(--fn-easing-out); }
@keyframes fn-steps-swap {
  from { opacity: 0.2; transform: translateX(12px); }
  to   { opacity: 1; transform: none; }
}
.fn-steps__dots i { transition: background-color 300ms var(--fn-easing); }

@media (prefers-reduced-motion: reduce) {
  .fn-quick-link,
  .fn-stat-card,
  .fn-product-card,
  .fn-feature-card,
  .fn-product-card__media img,
  .fn-steps__dots i { transition: none; }
  .fn-quick-link:hover,
  .fn-stat-card:hover,
  .fn-product-card:hover,
  .fn-feature-card:hover,
  .fn-product-card:hover .fn-product-card__media img { transform: none; }
  .fn-reveal { opacity: 1; transform: none; transition: none; }
  .fn-steps__body.is-switching,
  .fn-steps__media.is-switching { animation: none; }
}

/* -------------------------------------------------------------- UTILITAIRES */

.fn-grid-3 { display: grid; grid-template-columns: 1fr; gap: var(--fn-space-20); }
.fn-grid-4 { display: grid; grid-template-columns: 1fr; gap: var(--fn-space-20); }
@media (min-width: 768px) {
  .fn-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fn-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .fn-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fn-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Toute icone du sprite porte .fn-u-icon : elle ne doit jamais se laisser
   etirer par le flex qui l'entoure. .fn-u-flip retourne la fleche « suivant »
   en fleche « precedent » — les maquettes n'exportent que la premiere. */
.fn-u-icon { flex: 0 0 auto; }
.fn-u-flip { transform: scaleX(-1); }

.fn-u-shadow-sm { box-shadow: var(--fn-shadow-sm); }
.fn-u-shadow-md { box-shadow: var(--fn-shadow-md); }
.fn-u-shadow-lg { box-shadow: var(--fn-shadow-lg); }
.fn-u-gradient  { background: var(--fn-gradient-brand); }
.fn-u-sand      { background: var(--fn-surface-sand); }
.fn-u-dark      { background: var(--fn-surface-dark); color: var(--fn-text-inverse); }
.fn-u-accent    { color: var(--fn-text-accent); font-style: normal; }
