/* ==========================================================================
   Skin Rationnelle pour Porto
   --------------------------------------------------------------------------
   Unique point de personnalisation du thème : on redéfinit les variables du
   skin Porto (mécanisme natif, cf. css/skins/*.css) et les polices de marque.
   AUCUN composant maison ici, toutes les pages utilisent les composants
   natifs de Porto (feature-box, pricing-table, toggle, process, card, etc.).
   Chargé APRÈS css/skins/default.css.
   ========================================================================== */

:root {
    /* --- Primaire : terracotta Rationnelle ---
       Le #c67139 d'origine ne donnait que **3,61:1** avec du texte blanc, sous
       le seuil AA de 4,5:1. Comme c'est la couleur de tous les boutons d'action
       du site (« Rejoindre en Solo », « Generer ma liste de courses »,
       « Accepter » du bandeau cookies), le defaut touchait chaque page.
       La teinte et la saturation sont conservees, seule la luminosite baisse de
       3 points : l'ecart est a peine perceptible, et le contraste passe a
       **4,54:1**. Toute l'echelle suit le meme decalage, pour que les nuances
       gardent leurs rapports. */
    --primary: #ae6332;
    --primary-100: #995427;
    --primary-200: #8c4c22;
    --primary-300: #723b15;
    --primary--100: #d06d2f;
    --primary--200: #db7d42;
    --primary--300: #f48d4e;
    --primary-rgba-0: rgba(174, 99, 50, 0);
    --primary-rgba-10: rgba(174, 99, 50, 0.1);
    --primary-rgba-20: rgba(174, 99, 50, 0.2);
    --primary-rgba-30: rgba(174, 99, 50, 0.3);
    --primary-rgba-40: rgba(174, 99, 50, 0.4);
    --primary-rgba-50: rgba(174, 99, 50, 0.5);
    --primary-rgba-60: rgba(174, 99, 50, 0.6);
    --primary-rgba-70: rgba(174, 99, 50, 0.7);
    --primary-rgba-80: rgba(174, 99, 50, 0.8);
    --primary-rgba-90: rgba(174, 99, 50, 0.9);

    /* --- Secondaire : olive (accent 2 de la charte) --- */
    --secondary: #7a8450;
    --secondary-100: #6b7446;
    --secondary-200: #626a40;
    --secondary-300: #58603a;
    --secondary--100: #8a945f;
    --secondary--200: #96a06c;
    --secondary--300: #a3ac7c;
    --secondary-rgba-10: rgba(122, 132, 80, 0.1);
    --secondary-rgba-20: rgba(122, 132, 80, 0.2);
    --secondary-rgba-40: rgba(122, 132, 80, 0.4);
    --secondary-rgba-60: rgba(122, 132, 80, 0.6);
    --secondary-rgba-80: rgba(122, 132, 80, 0.8);

    /* --- Tertiaire : crème de marque (accents doux) --- */
    --tertiary: #ebddc5;
    --tertiary-100: #e0cfb2;
    --tertiary-200: #dcc9a8;
    --tertiary-300: #d5c09b;
    --tertiary--100: #f0e6d3;
    --tertiary--200: #f5ead8;
    --tertiary--300: #f9f4ed;

    /* --- Gris de texte ---
       Le #969696 de Porto ne donne que 2,96:1 sur blanc, sous le seuil AA
       (4,5:1) : illisible pour les libellés secondaires. On l'assombrit à
       ~5,3:1. Sans effet sur les fonds, qui utilisent --grey-100. */
    --grey: #6b6b6b;

    /* Le #777 du texte courant Porto ne donne que 4,48:1 sur blanc et 4,13:1
       sur bg-color-grey (#f4f4f4), sous le seuil AA dans les deux cas. On
       l'aligne sur --grey : 5,3:1 sur blanc, 4,8:1 sur le gris clair. */
    --default: #6b6b6b;

    /* --- Couleurs de texte inverses ---
       Porto suppose des couleurs de marque sombres et met du blanc dessus.
       Notre tertiaire est un crème clair : son inverse doit être sombre,
       sinon les badges/boutons tertiaires sont blancs sur crème (illisible). */
    --tertiary-inverse: #201e1d;

    /* --- Quaternaire / dark : brun profond de la charte --- */
    --quaternary: #402310;
    --dark: #201e1d;
    --dark-100: #171514;
    --dark-200: #110f0f;
    --dark--100: #2f2c2a;
    --dark--200: #3a3634;
}

/* --- Lisibilité des composants tertiaires -------------------------------
   Porto ne pose que le background sur .badge-tertiary / .btn-tertiary et
   laisse Bootstrap mettre du texte blanc. Notre tertiaire étant un crème
   clair, il faut imposer le texte sombre. */
.badge-tertiary,
.btn-tertiary {
    color: var(--tertiary-inverse);
}

/* Même problème pour .badge-light : fond blanc + texte blanc par défaut. */
.badge-light {
    color: var(--dark);
}

.btn-tertiary:hover,
.btn-tertiary:focus,
.btn-tertiary:active {
    color: var(--tertiary-inverse);
    background-color: var(--tertiary-100);
    border-color: var(--tertiary-100);
}

/* --- Lisibilité sur les fonds primaires ---------------------------------
   Porto ne force la couleur inverse que sur p et h1..h6 : tout autre texte
   (li, span, strong…) hérite du gris par défaut et devient illisible sur
   l'orange. On applique la couleur inverse au conteneur ; les boutons et
   badges imposent la leur et ne sont donc pas affectés. */
section.section-primary,
section.section-primary p,
section.section-primary li,
.call-to-action.call-to-action-primary,
.alert-primary,
.alert-secondary,
.alert-quaternary,
.alert-primary p, .alert-primary li, .alert-primary strong,
.alert-secondary p, .alert-secondary li, .alert-secondary strong,
.alert-quaternary p, .alert-quaternary li, .alert-quaternary strong {
    color: var(--primary-inverse);
}

.alert-primary .alert-link,
.alert-secondary .alert-link,
.alert-quaternary .alert-link {
    color: var(--primary-inverse);
    text-decoration: underline;
}

/* Le tertiaire étant clair, son alerte garde un texte sombre. */
.alert-tertiary {
    color: var(--tertiary-inverse);
}

/* --- Comparatif : puces alignées d'une colonne à l'autre ----------------
   Les trois listes vivent dans des cartes indépendantes : sans hauteur de
   puce commune, un intitulé qui passe sur deux lignes décale toutes les
   puces suivantes de sa colonne et le tableau perd son alignement. On fixe
   la hauteur d'une puce à deux lignes (2 × 28 px de line-height) dès que
   les trois colonnes sont côte à côte. */
@media (min-width: 992px) {
    #comparison .list.list-icons li {
        min-height: 56px;
    }
}

/* --- Process : cercles un peu plus larges -------------------------------
   Les 50 px natifs de process-connecting-line laissent l'icône du caddie
   toucher le bord. On passe à 60 px sans toucher aux icônes, et on redescend
   la ligne de liaison d'autant : son `top` natif (25 px) est la moitié du
   diamètre, il doit suivre sinon la ligne ne coupe plus les cercles en leur
   milieu. */
.process-connecting-line .process-step-circle {
    width: 60px;
    height: 60px;
}

/* Moitié du diamètre, moins la moitié de l'épaisseur du trait (3 px), pour
   que la ligne soit centrée sur les cercles et non posée sous leur milieu. */
.process-connecting-line .connecting-line {
    top: 28.5px;
}

/* Porto centre verticalement le contenu de chaque étape (justify-content:
   center). Les colonnes ayant toutes la hauteur de la plus haute, l'étape au
   texte le plus court voit son contenu recentré : son cercle descend, alors
   que la ligne de liaison reste à hauteur fixe et ne le traverse plus en son
   milieu. On aligne donc les étapes par le haut : tous les cercles partent du
   même y, quelle que soit la longueur du texte qui les suit. */
.process-connecting-line .process-step {
    justify-content: flex-start;
}

/* --- Process : pastille du numéro écartée du cercle ---------------------
   Le translate-middle de Bootstrap centre la pastille sur le coin du cadre du
   cercle, à une douzaine de pixels seulement de son tracé : elle l'affleurait.
   On la repousse le long de la diagonale, hors du disque.
   Le recentrage reste exprimé en pourcentages de la pastille elle-même, et le
   déport en pixels : les trois numéros se posent ainsi sur le même point, quelle
   que soit la largeur du chiffre, un ancrage par `right` désalignerait le 1,
   plus étroit que le 2 et le 3 dans cette police. */
#features .process-step-circle .badge {
    transform: translate(-50%, -50%) translate(7px, -7px);
}

/* --- Process : la ligne de liaison n'a de sens qu'en 3 colonnes ---------
   Porto pose .connecting-line sans media query : sous 992 px les étapes
   s'empilent et la ligne devient un trait horizontal parasite en travers
   du premier cercle. */
@media (max-width: 991px) {
    .process-connecting-line .connecting-line {
        display: none;
    }
}

/* --- Accessibilité : préférence système « moins d'animations » ----------
   Le plugin d'apparition de Porto n'écoute pas prefers-reduced-motion. On
   neutralise le mouvement en garantissant que le contenu reste visible. */
@media (prefers-reduced-motion: reduce) {
    .appear-animation {
        animation: none !important;
        opacity: 1 !important;
    }
}

/* --- Footer : copyright trop sombre sur le fond sombre de Porto --------- */
#footer .footer-copyright p {
    color: var(--light-rgba-70);
}

/* --- Typographie de marque (Inter + Plus Jakarta Sans) -------------------
   Porto démarre à 14 px (13 px sous 576 px) et TOUTES ses classes de taille
   sont des multiplicateurs em qui en découlent : listes, chapôs, liens,
   cartes tarifaires se retrouvaient donc à 14 px. On relève la base une
   seule fois ici plutôt que de poser une classe de taille page par page.
   La racine html reste à 16 px : les valeurs en rem de Porto (le prix des
   cartes à 2,7 rem) sont déjà bien dimensionnées et ne doivent pas bouger. */
body {
    font-family: 'Inter', 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 16px;
    line-height: 28px;
}

@media (max-width: 575px) {
    body {
        font-size: 15px;
    }
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'Plus Jakarta Sans', 'Inter', sans-serif;
    font-weight: 700;
}

/* --- Mise en valeur d'une expression dans un titre ----------------------
   Convention du site : tous les titres sont en gras, et l'expression mise en
   avant se distingue par la couleur de marque doublée d'un soulignement
   zigzag. La mise en valeur ne passe donc plus par une graisse supérieure :
   sur un titre déjà en gras, le passage de 700 à 800 ne se voyait quasiment
   pas. L'offset est en em pour que le trait conserve la même distance
   relative quelle que soit la taille du titre. */
.title-highlight {
    color: var(--primary);
    text-decoration: underline wavy var(--primary);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.2em;
}

/* Porto met les boutons à 0,8 em, soit 12,8 px même après le passage de la
   base à 16 px, trop petit pour un bouton d'achat. */
.btn {
    font-size: 0.95em;
}

/* Autre conséquence du passage à 16 px : Porto centre le glyphe des puces
   list-icons-style-3 dans leur pastille avec un padding de 5 px et un
   line-height de 1,3, valeurs calées sur sa base de 14 px. À 16 px, la boîte
   de ligne (0,8 em × 1,3 ≈ 16,6 px) déborde la zone de contenu de la pastille
   (25 px − 10 px de padding = 15 px) et le glyphe décroche vers le bas. On
   remplace ce centrage typographique par un centrage flex, indépendant de la
   taille de police. La pastille garde ses 25 px : box-sizing est en
   border-box, retirer le padding ne change donc pas son diamètre. */
.list.list-icons.list-icons-style-3 li > [class*="fa-"]:first-child,
.list.list-icons.list-icons-style-3 li > .icons:first-child,
.list.list-icons.list-icons-style-3 li a:first-child > [class*="fa-"]:first-child,
.list.list-icons.list-icons-style-3 li a:first-child > .icons:first-child {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
}

/* ============================================================
   Largeur du conteneur sur grands écrans
   ------------------------------------------------------------
   Deux défauts successifs se sont produits ici. Il faut les connaître tous les
   deux, sinon la correction de l'un ramène l'autre.

   **Le premier était un plafond figé trop bas.** Porto plafonne .container à
   1140 px dès 1200 px (theme.css, règle
   « .container:not(.container-bs):not(.container-xl-custom):not(.container-xxl-custom) »),
   ce qui écrase le 1320 px que Bootstrap applique au-delà de 1400 px. Sur un
   écran 1920, le contenu ne faisait que 1140 px et laissait près de 400 px de
   vide de chaque côté, très visible depuis que le hero des pages
   d'atterrissage est composé de deux cartes blanches aux bords nets.

   **Le second est né de la correction du premier.** Le plafond avait été levé à
   1630 px avec 2 rem de gouttière. Mais une fenêtre plus étroite que 1630 px,
   c'est-à-dire la quasi-totalité des portables, 1366 et 1440 en tête, laissait
   alors le conteneur occuper toute la largeur : la marge tombait à 32 px et le
   contenu venait presque toucher les bords. Ce n'est pas ce que fait un SaaS,
   qui garde une respiration franche de chaque côté à toutes les tailles.

   **La réponse est une marge proportionnelle, pas un plafond figé.** 84vw laisse
   8 % de fenêtre de chaque côté, donc une marge qui grandit avec l'écran : 109 px
   à 1366, 115 px à 1440, 128 px à 1600. Le plafond de 1440 px, la largeur que
   Porto réserve à .container-xl-custom, arrête la course pour que les lignes de
   texte ne s'allongent pas indéfiniment : au-delà de 1715 px c'est lui qui
   commande, et la marge continue de croître d'elle-même, 240 px à 1920 px.

   Pas de rembourrage ajouté ici : la marge de 8 % rend le conteneur incapable de
   toucher les bords, donc les 12 px de gouttière de Bootstrap suffisent. En
   remettre 2 rem retirerait 64 px au contenu sans rien protéger.

   Gain collatéral : la discontinuité de 1200 px disparaît. Le conteneur sautait
   de 960 à 1200 px en un pixel de fenêtre ; il passe désormais de 960 à 1008 px
   et croît ensuite régulièrement.

   On reprend le sélecteur du thème à l'identique pour rester à spécificité
   égale : ce fichier étant chargé après theme.css, c'est cette valeur qui gagne.
   Le header (base.html, « header-container container ») et le pied de page
   suivent automatiquement, donc logo, menu et contenu restent alignés.
   L'espace client, lui, est en `container-fluid` et garde sa pleine largeur :
   il porte des tableaux et des graphiques qui profitent de la place.
   ============================================================ */
@media (min-width: 1200px) {
    .container:not(.container-bs):not(.container-xl-custom):not(.container-xxl-custom) {
        max-width: min(1440px, 84vw);
    }
}

/* ============================================================
   BASCULE MENSUEL / ANNUEL : le panneau masque ne doit pas
   intercepter les clics
   ============================================================
   Le content-switcher de Porto empile ses panneaux en position
   absolue et masque l'inactif avec opacity: 0, sans toucher a
   pointer-events. Le panneau annuel, dernier dans le DOM et sans
   z-index, etait donc peint par-dessus le bouton mensuel visible
   et captait le clic : « Rejoindre en Solo » a 4,99 EUR / mois
   envoyait vers le checkout annuel, dans les deux positions de
   l'interrupteur. Les formules mensuelles etaient inachetables.
   ============================================================ */
.content-switcher-wrapper .content-switcher:not(.active) {
    pointer-events: none;
}

.content-switcher-wrapper .content-switcher.active {
    /* Le panneau actif passe devant : sans cela, l'ordre du DOM
       decide seul lequel recoit le clic. */
    z-index: 1;
}

/* ============================================================
   TÉLÉPHONE : l'en-tête et les badges débordaient de l'écran
   ============================================================
   Mesuré à 390 px de large, la taille d'un iPhone courant et le cas d'usage
   principal du site : le document faisait 428 px, donc **toutes les pages**
   glissaient horizontalement sous le doigt. Deux causes, additionnées :

   1. Le logo est fixé à 220 px par ses attributs `width`/`height`. Porto ne
      contraint pas sa taille en CSS. Avec les boutons de session (120 px) et
      le bouton de menu (50 px), la ligne d'en-tête réclamait 428 px pour
      390 px disponibles : le bouton de menu sortait du cadre, à demi coupé.
   2. Sur l'accueil, le badge « Conforme aux normes vétérinaires FEDIAF 2024
      & NRC » reste sur une seule ligne (Porto pose `white-space: nowrap` sur
      `.badge`), et réclamait à lui seul 440 px.

   Le logo passe donc à 150 px sous 576 px (le ratio est conservé par
   `height: auto`, sans quoi l'image serait étirée), et un badge trop long
   s'autorise à passer à la ligne plutôt qu'à pousser la page.
   ============================================================ */
@media (max-width: 575.98px) {
    .header-logo img {
        width: 150px;
        height: auto;
    }

    .badge {
        white-space: normal;
        max-width: 100%;
    }
}

/* ============================================================
   ACCESSIBILITÉ : le texte orange, et la bannière de consentement
   ============================================================
   Deux corrections mesurées sur la production le 11 septembre 2026.

   1. **Le texte orange.** Assombrir `--primary` suffit aux boutons, où le blanc
      se pose *sur* la couleur. Mais l'orange sert aussi de couleur de texte
      (`text-color-primary`, 98 usages), liens, titres d'accordéon des CGV,
      fils d'Ariane. Sur le gris `#f4f4f4` des pages légales, `--primary` ne
      donne que 4,12:1, encore sous le seuil. Le texte prend donc la nuance
      immédiatement plus sombre : 5,75:1 sur blanc, 5,23:1 sur le gris. L'écart
      à l'œil est minime, et c'est un usage courant qu'un lien soit un ton plus
      sombre que l'aplat.

   2. **La bannière de consentement** affichait le gris de texte `#6b6b6b` sur
      son fond ardoise `#383f45` : **2,01:1**, pratiquement illisible. C'est le
      texte qui recueille un consentement, sa lisibilité n'est pas une question
      de confort. Le gris clair ci-dessous donne 8,2:1.
   ============================================================ */
.text-color-primary,
a.text-color-primary:not(.btn),
.text-color-primary a:not(.btn) {
    /* `--lien` et non `--primary-100` : c'est le meme role (de l'orange pose en
       texte), et il doit donc s'eclaircir en mode sombre comme les liens. */
    color: var(--lien) !important;
}

/* Porto colore tous les liens en `var(--primary)` (`theme-elements.css`, regle
   `a`). Les liens ordinaires, fils d'Ariane, titres d'accordeon des CGV,
   heritent donc de la couleur des boutons, qui n'est pas assez sombre pour du
   texte sur le gris clair. On ne touche ni aux boutons, ni a ce qui est pose
   sur un fond sombre : ces regles-la sont plus specifiques et continuent de
   gagner. */
/* Porto colore tous les liens en `var(--primary)` (`theme-elements.css`, regle
   `a`), couleur trop claire pour du texte sur le gris des pages legales.

   Cette regle a d'abord ete ecrite avec une liste de `:not()` (`:not(.btn)`,
   `:not(.badge)`, et ainsi de suite) pour epargner les composants. C'etait une
   erreur : **chaque exclusion ajoutee augmentait la specificite**, si bien que la
   regle finissait par battre les composants qu'elle pretendait epargner. Elle a
   mordu trois fois : le titre d'accordeon ouvert (orange sombre sur orange,
   1,27:1), les entrees de la barre laterale, puis l'onglet de l'animal
   selectionne, invisible lui aussi, a 1,27:1.

   Elle est donc ecrite au plus bas : un simple `a`, specificite (0,0,1). Toute
   regle de composant, qui porte au moins une classe, l'emporte naturellement.
   C'est ainsi qu'il fallait faire des le depart. */
a {
    color: var(--primary-100);
}

/* Les accordeons, seulement quand ils sont fermes : ouvert, le titre passe en
   blanc sur un aplat orange, et c'est Porto qui s'en charge. Exclure
   `.toggle-title` de la regle generique ci-dessus est indispensable, sans quoi
   ses quatre `:not()` la rendent plus specifique que la regle d'etat de Porto,
   et le titre ouvert se retrouve en orange sombre sur orange : 1,27:1. */
/* L'accordeon ferme : Porto le colore en `--primary`, trop clair sur le gris
   des pages legales. Ouvert, il passe en blanc sur aplat orange et c'est Porto
   qui s'en charge, d'ou le `:not(.active)`. */
.toggle-primary .toggle:not(.active) > label,
.toggle-primary .toggle:not(.active) > .toggle-title {
    color: var(--lien);
}

#cookieBanner .alert-dark,
#cookieBanner .alert-dark p {
    color: #dee2e6;
}

#cookieBanner .alert-dark .alert-link {
    color: #fff;
    text-decoration: underline;
}

/* ============================================================
   CIBLES TACTILES : 44 px au doigt
   ============================================================
   Mesuré à 390 px : 19 éléments cliquables par page sous 44 × 44, dont les
   liens de pied de page à **16 px de haut**, sous le minimum de 24 px du
   critère AA lui-même. La règle ne s'applique qu'aux pointeurs grossiers, pour
   ne pas gonfler l'interface à la souris.
   ============================================================ */
@media (pointer: coarse) {
    #footer .footer-nav a,
    #footer ul a,
    .footer-links a {
        display: inline-block;
        min-height: 44px;
        line-height: 44px;
    }

    .form-select,
    .form-control:not(textarea),
    .btn-sm,
    .header-btn-collapse-nav {
        min-height: 44px;
    }
}

/* ============================================================
   IMPRESSION, FLOUTAGE ET JAUGES : règles partagées
   ============================================================
   Ces règles vivaient dans le bloc `<style>` de `shopping_list.html`, la page
   publique. Or les partiels qui les utilisent (`_complements.html` pour les
   jauges de dose, `_transition.html` pour les barres jour par jour) sont
   **aussi** inclus par l'espace client, qui descend de `espace/_base.html` et
   ne charge jamais ce bloc.

   Résultat, vérifié à l'écran : sur « Compléments vitaux » de l'espace membre,
   les jauges étaient **totalement invisibles**. Le client qui paie voyait moins
   que le visiteur gratuit. Les règles vivent donc ici, où les deux enveloppes
   les trouvent.

   `.no-print` était dans le même cas : utilisé par quatre fichiers qui ne
   définissaient pas la règle.
   ============================================================ */
@media print {
    .no-print,
    #header,
    #footer,
    .paywall-overlay {
        display: none !important;
    }

    .print-sheet {
        box-shadow: none !important;
        border: none !important;
    }

    .tab-pane {
        display: block !important;
        opacity: 1 !important;
    }

    a[href]:after {
        content: none !important;
    }
}

/* Masquage visuel du contenu payant. Le serveur n'envoie de toute façon jamais
   les vraies valeurs quand `is_locked` est vrai : ce flou n'est qu'un habillage,
   il ne protège rien à lui seul. */
.locked-blur {
    filter: blur(6px);
    pointer-events: none;
    user-select: none;
}

/* L'echantillon de la page publique : une preuve, pas un mur.

   La page verrouillee floutait deux mille pixels de contenu, soit trois onglets
   entiers. Le message dominant devenait « tout est verrouille » la ou il fallait
   dire « voici ce que vous recevez », et sur telephone la page atteignait
   5 300 px de haut pour une seule decision a prendre.

   On n'en garde qu'un extrait, plafonne en hauteur et fondu au bas : de quoi
   reconnaitre la forme du livrable, les cartes d'articles et leurs barquettes,
   sans faire defiler du flou. Le degrade evite la coupe nette, qui laissait
   croire a un contenu tronque par un defaut d'affichage. */
.echantillon-verrouille {
    max-height: 320px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, #000 50%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 50%, transparent 100%);
}

/* Les six categories du teaser, sur une rangee reguliere.

   Les libelles et les noms d'aliments ne font pas la meme longueur, et de loin :
   « FOIE » contre « AUTRE ABAT SECRETEUR », « Rognons de porc » contre
   « Puree / Mix Legumes & Fruits BARF (Courgette, Carotte, Pomme) ». Sans
   hauteur reservee, chaque colonne se terminait a une hauteur differente et la
   rangee prenait un air de brouillon. On reserve deux lignes a chacun des deux
   libelles et on tronque au-dela : le nom exact de l'aliment se retrouve de
   toute facon dans la liste de courses. */
.teaser-categorie-nom,
.teaser-categorie-aliment {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    min-height: 2.6em;
}

/* Jauges de dose des compléments */
.supp-bar {
    height: 6px;
    border-radius: 3px;
    background: #eee7db;
    overflow: hidden;
}

.supp-bar-fill {
    height: 100%;
    border-radius: 3px;
}

/* Barres jour par jour du protocole de transition */
.day-bar {
    height: 48px;
    background: #eee7db;
    border-radius: 4px;
    position: relative;
    overflow: hidden;
}

.day-bar-fill {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--primary);
    opacity: .85;
}

/* ============================================================
   ÉCHELLE TYPOGRAPHIQUE FLUIDE
   ============================================================
   Deux défauts mesurés au navigateur motivent ce bloc.

   **Le texte ne grandissait jamais.** Le titre de l'accueil faisait 44 px à
   768 px de fenêtre comme à 3440 px : sur un grand écran, la page se lisait
   comme un design de 1440 px posé au centre d'un cadre trop grand. Il ne
   descendait qu'à 41 px sur mobile : 6 % d'écart entre le plus petit et le plus
   grand écran.

   **Vingt et une tailles distinctes, dont aucune n'avait été choisie.** Les
   classes `text-N` de Porto sont des multiplicateurs `em`, qui se composent
   quand on les imbrique : un `text-2` dans un `text-2` donnait 12,96 px, un
   `text-1` dans un `text-3` 12,24 px. Personne n'avait décidé ces valeurs et
   aucune ne se retient.

   Les mêmes classes sont donc redéfinies en `rem` absolus (ce qui supprime la
   composition) et en `clamp()`, qui interpole entre 390 px et 1920 px de
   fenêtre. Les 346 usages de `text-N` dans les gabarits en héritent sans qu'un
   seul soit modifié.

   Repères : le corps passe de 15,5 à 17 px, un titre de section de 30 à 44 px,
   le titre de l'accueil de 34 à 64 px.
   ============================================================ */
.text-1  { font-size: clamp(0.7812rem, 0.7653rem + 0.0654vw, 0.8438rem) !important; line-height: 1.5; }
.text-2  { font-size: clamp(0.875rem, 0.8591rem + 0.0654vw, 0.9375rem) !important;  line-height: 1.55; }
.text-3  { font-size: clamp(0.9688rem, 0.9449rem + 0.098vw, 1.062rem) !important;   line-height: 1.6; }
.text-4  { font-size: clamp(1.125rem, 1.077rem + 0.196vw, 1.312rem) !important;     line-height: 1.45; }
.text-5  { font-size: clamp(1.312rem, 1.233rem + 0.327vw, 1.625rem) !important;     line-height: 1.35; }
.text-6  { font-size: clamp(1.5rem, 1.373rem + 0.523vw, 2rem) !important;           line-height: 1.25; }
.text-7  { font-size: clamp(1.688rem, 1.512rem + 0.719vw, 2.375rem) !important;     line-height: 1.2; }
.text-8  { font-size: clamp(1.875rem, 1.652rem + 0.915vw, 2.75rem) !important;      line-height: 1.15; }
.text-9  { font-size: clamp(2rem, 1.681rem + 1.31vw, 3.25rem) !important;           line-height: 1.1; }
.text-10 { font-size: clamp(2.125rem, 1.647rem + 1.96vw, 4rem) !important;          line-height: 1.08; }
.text-11 { font-size: clamp(2.375rem, 1.833rem + 2.22vw, 4.5rem) !important;        line-height: 1.05; }
.text-12 { font-size: clamp(2.625rem, 2.02rem + 2.48vw, 5rem) !important;           line-height: 1.05; }

/* Les titres nus : ceux qui ne portent pas de classe `text-N`. L'interlignage
   est sans unité : Porto le fixait en pixels (44 px sur un `h1`), ce qui écrase
   un titre dès qu'il grandit. */
h1 { font-size: clamp(2.125rem, 1.647rem + 1.96vw, 4rem);   line-height: 1.08; }
h2 { font-size: clamp(1.75rem, 1.495rem + 1.05vw, 2.75rem); line-height: 1.15; }
h3 { font-size: clamp(1.5rem, 1.341rem + 0.654vw, 2.125rem); line-height: 1.2; }
h4 { font-size: clamp(1.188rem, 1.092rem + 0.392vw, 1.562rem); line-height: 1.3; }
h5 { font-size: clamp(1.062rem, 1.015rem + 0.196vw, 1.25rem); line-height: 1.35; }
h6 { font-size: clamp(1rem, 0.9841rem + 0.0654vw, 1.062rem); line-height: 1.4; }

/* ============================================================
   ARRONDIS ET ÉLÉVATION : un seul régime pour chacun
   ============================================================
   **Trois régimes d'arrondi cohabitaient sur la même page** : `border-radius-0`
   posé à la main 78 fois dans 27 gabarits, le 4 px de Porto partout où la
   classe avait été oubliée, et `rounded-pill` 47 fois. Le jeton passe à 12 px
   et les `border-radius-0` sont retirés des gabarits ; les pilules restent, ce
   sont les badges.

   **Deux systèmes d'élévation concurrents** : `box-shadow-N` de Porto (88
   usages) et `shadow` de Bootstrap (92), dont une ombre à 45 % d'opacité et
   60 px de flou. Les deux familles retombent ici sur trois niveaux réels, plus
   doux et cohérents. Aucun gabarit n'est touché.
   ============================================================ */
:root {
    --border-radius: 12px;
    --border-radius2x: 20px;

    /* Trois niveaux, nommés par usage plutôt que par valeur. */
    --ombre-1: 0 1px 2px rgba(32, 30, 29, .06), 0 2px 8px rgba(32, 30, 29, .06);
    --ombre-2: 0 2px 4px rgba(32, 30, 29, .05), 0 8px 24px rgba(32, 30, 29, .08);
    --ombre-3: 0 4px 8px rgba(32, 30, 29, .05), 0 16px 40px rgba(32, 30, 29, .10);
}

.card,
.form-control,
.form-select,
.btn,
.alert,
.feature-box-icon,
.input-group > :first-child,
.input-group > :last-child {
    border-radius: var(--border-radius);
}

.box-shadow-1, .shadow-sm { box-shadow: var(--ombre-1) !important; }
.box-shadow-2, .box-shadow-3, .shadow { box-shadow: var(--ombre-2) !important; }
.box-shadow-4, .box-shadow-5, .box-shadow-6, .shadow-lg { box-shadow: var(--ombre-3) !important; }
.box-shadow-1-hover:hover { box-shadow: var(--ombre-2) !important; }
[class*="box-shadow-"]:before,
[class*="box-shadow-"]:after {
    pointer-events: none !important;
}


/* ============================================================
   NAVIGATION : casse normale
   ============================================================
   Les entrées du menu étaient en capitales à 12,8 px : la signature visuelle
   des thèmes de 2019-2021, et la casse la moins lisible qui soit sur un libellé
   de trois mots comme « Comment ça marche ».
   ============================================================ */
#header .header-nav-main nav > ul > li > a {
    text-transform: none;
    font-size: 0.95rem;
    letter-spacing: 0;
}


/* ============================================================
   NAVIGATION : le menu se repliait sur deux lignes de 992 a 1250 px
   ============================================================
   Porto garde le menu complet jusqu'a 991 px, ou il le range derriere un
   bouton. Entre 992 et 1250 px il l'affiche donc en entier dans un conteneur
   qui ne fait que 960 a 1050 px, et les cinq entrees n'y tiennent pas : « FAQ »
   passait a la ligne et venait chevaucher le logo. Mesure a 1100 px : les
   entrees reclamaient 481 px pour 471 disponibles, il en manquait dix.

   Ce defaut existait avant les marges laterales du conteneur, sur toute la plage
   992-1199 px. Les marges l'ont simplement etendu jusqu'a 1250 px, en ramenant
   le conteneur de 1200 a 1008 px a 1200 px de fenetre.

   La correction porte sur le rembourrage et la taille des entrees, pas sur la
   largeur du conteneur : l'alignement du logo, du menu et du contenu est un
   acquis a ne pas defaire. Apres correction, les entrees reclament 456 px pour
   471 disponibles a 1100 px.
   ============================================================ */
@media (min-width: 992px) and (max-width: 1249.98px) {
    /* `!important` parce que Porto pose ce rembourrage avec une regle plus
       forte que le selecteur d'origine, comme pour ses utilitaires de taille. */
    #header .header-nav-main nav > ul > li > a {
        font-size: 0.9rem;
        padding-left: 0.45rem !important;
        padding-right: 0.45rem !important;
    }
}

/* ============================================================
   RYTHME DES SECTIONS : l'alternance n'existait pas
   ============================================================
   Porto donne déjà `--grey-100` de fond à `section.section`, et
   `.bg-color-grey` rend exactement la même couleur. Résultat mesuré :
   **huit des neuf sections de l'accueil partageaient le même `#f4f4f4`**, et
   trois d'entre elles se succédaient sans la moindre séparation visible. Un
   commentaire du gabarit annonçait pourtant l'intention d'alterner.

   Le défaut devient donc le blanc, et `bg-color-grey` reprend son sens : il ne
   colore plus que les sections qui doivent vraiment se détacher, une sur deux.
   ============================================================ */
section.section:not([class*="bg-color-"]):not(.section-primary) {
    background-color: #fff;
}

/* ============================================================
   JETONS ORPHELINS : le corail et le turquoise de Porto fuyaient encore
   ============================================================
   Le skin d'origine déclare 122 variables ; le fichier n'en surchargeait que 44.
   Les 78 autres gardaient les couleurs du thème vendu (corail, turquoise, gris
   ardoise) et restaient adressables par les classes de Porto.

   Le cas concret : `--secondary` est bien olive, mais `--secondary-rgba-50`,
   qu'utilisent les ombres et les états de survol, rendait le corail `#e36159`
   du thème. La palette n'était donc cohérente que sur les chemins effectivement
   redéclarés.

   Les séries manquantes sont complétées ici à partir des couleurs de la charte.
   ============================================================ */
:root {
    --secondary-rgba-0: rgba(122, 132, 80, 0);
    --secondary-rgba-30: rgba(122, 132, 80, 0.3);
    --secondary-rgba-50: rgba(122, 132, 80, 0.5);
    --secondary-rgba-70: rgba(122, 132, 80, 0.7);
    --secondary-rgba-90: rgba(122, 132, 80, 0.9);

    --tertiary-rgba-0: rgba(235, 221, 197, 0);
    --tertiary-rgba-10: rgba(235, 221, 197, 0.1);
    --tertiary-rgba-20: rgba(235, 221, 197, 0.2);
    --tertiary-rgba-30: rgba(235, 221, 197, 0.3);
    --tertiary-rgba-40: rgba(235, 221, 197, 0.4);
    --tertiary-rgba-50: rgba(235, 221, 197, 0.5);
    --tertiary-rgba-60: rgba(235, 221, 197, 0.6);
    --tertiary-rgba-70: rgba(235, 221, 197, 0.7);
    --tertiary-rgba-80: rgba(235, 221, 197, 0.8);
    --tertiary-rgba-90: rgba(235, 221, 197, 0.9);

    /* Quaternaire : brun profond de la charte, là où Porto posait un gris ardoise. */
    --quaternary-100: #351d0d;
    --quaternary-200: #2c180b;
    --quaternary-300: #221309;
    --quaternary--100: #55301a;
    --quaternary--200: #6a3d23;
    --quaternary--300: #7f4a2c;
    --quaternary-inverse: #fff;
    --quaternary-rgba-0: rgba(64, 35, 16, 0);
    --quaternary-rgba-10: rgba(64, 35, 16, 0.1);
    --quaternary-rgba-20: rgba(64, 35, 16, 0.2);
    --quaternary-rgba-30: rgba(64, 35, 16, 0.3);
    --quaternary-rgba-40: rgba(64, 35, 16, 0.4);
    --quaternary-rgba-50: rgba(64, 35, 16, 0.5);
    --quaternary-rgba-60: rgba(64, 35, 16, 0.6);
    --quaternary-rgba-70: rgba(64, 35, 16, 0.7);
    --quaternary-rgba-80: rgba(64, 35, 16, 0.8);
    --quaternary-rgba-90: rgba(64, 35, 16, 0.9);

    /* ------------------------------------------------------------
       Jetons de RÔLE : la préparation du mode sombre
       ------------------------------------------------------------
       Ceux-ci ne remplacent rien aujourd'hui : ils nomment ce que les couleurs
       *font* plutôt que ce qu'elles *sont*. Le jour où le mode sombre sera
       ajouté, il suffira de redéclarer ces six lignes dans un bloc
       `@media (prefers-color-scheme: dark)`, sans retoucher un seul gabarit,
       ce qui serait impossible avec des couleurs nommées par leur teinte.
       ------------------------------------------------------------ */
    --surface: #fff;
    --surface-basse: #f4f4f4;
    --surface-haute: #fff;
    --texte: #201e1d;
    --texte-secondaire: #6b6b6b;
    --bordure: #e3e1de;
}

/* ============================================================
   ESPACE CLIENT : barre latérale fixe sur fond de marque
   ============================================================
   L'ancien menu était une `aside.sidebar` de Porto posée dans une colonne de
   grille, repliée derrière un bouton sous 992 px : le motif d'un thème de site
   vitrine, pas d'un espace applicatif. Il devient une barre fixe, et un tiroir
   coulissant sur téléphone.

   **Le fond est `--primary-300`, pas `--primary`.** Sur le terracotta clair, le
   blanc plein donne 4,54:1, il passe, mais sans marge : un libellé translucide
   ou un survol éclairci repassaient aussitôt sous le seuil. Sur le terracotta
   profond, le blanc plein monte à 8,93:1 et **tous les états restent conformes** :
   6,4:1 pour les sous-sections, 6,9:1 au survol, 5,5:1 sur l'entrée active.
   Mesuré avant d'être écrit.
   ============================================================ */
:root {
    --espace-largeur: 264px;
    --espace-fond: var(--primary-300);
}

.espace-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--espace-largeur);
    background: var(--espace-fond);
    color: #fff;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
    z-index: 1040;
}

.espace-sidebar-tete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1.25rem 1.25rem 1rem;
}

.espace-logo img {
    display: block;
    width: 176px;
    height: auto;
}

.espace-fermer {
    background: none;
    border: 0;
    color: #fff;
    font-size: 1.25rem;
    line-height: 1;
    padding: .25rem .5rem;
}

.espace-compte {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0 1rem 1rem;
    padding: .625rem .75rem;
    background: rgba(255, 255, 255, .10);
    border-radius: var(--border-radius);
    font-size: .875rem;
    /* Une adresse e-mail longue ne doit pas élargir la barre. */
    overflow: hidden;
}

.espace-compte-icone {
    flex: 0 0 auto;
    opacity: .85;
}

.espace-compte-nom {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.espace-nav {
    flex: 1 1 auto;
    padding: 0 .75rem;
}

.espace-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.espace-lien,
.espace-lien-discret {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .625rem .75rem;
    margin-bottom: .125rem;
    border-radius: var(--border-radius);
    color: #fff;
    font-size: .9375rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color .15s ease;
}

.espace-lien i,
.espace-lien-discret i {
    width: 1.125rem;
    text-align: center;
    flex: 0 0 auto;
    opacity: .9;
}

.espace-lien:hover,
.espace-lien-discret:hover,
.espace-lien:focus-visible,
.espace-lien-discret:focus-visible {
    background: rgba(255, 255, 255, .10);
    color: #fff;
}

.espace-lien.actif {
    background: rgba(255, 255, 255, .18);
    font-weight: 700;
}

.espace-sous-nav {
    margin: .125rem 0 .5rem 2.1rem !important;
    border-left: 1px solid rgba(255, 255, 255, .22);
}

.espace-sous-lien {
    display: block;
    padding: .375rem .75rem;
    color: rgba(255, 255, 255, .8);
    font-size: .875rem;
    text-decoration: none;
    border-radius: 0 var(--border-radius) var(--border-radius) 0;
}

.espace-sous-lien:hover,
.espace-sous-lien:focus-visible {
    background: rgba(255, 255, 255, .10);
    color: #fff;
}

.espace-sous-lien.actif {
    color: #fff;
    font-weight: 700;
    box-shadow: inset 2px 0 0 #fff;
}

.espace-sidebar-pied {
    padding: .75rem;
    border-top: 1px solid rgba(255, 255, 255, .16);
}

.espace-lien-discret {
    font-size: .875rem;
    font-weight: 400;
    color: rgba(255, 255, 255, .82);
}

/* --- La colonne de contenu, et le bandeau du haut --------------------------- */
.espace-contenu {
    margin-left: var(--espace-largeur);
}

.espace-topbar {
    display: none;
}

.espace-voile {
    position: fixed;
    inset: 0;
    background: rgba(32, 30, 29, .45);
    z-index: 1035;
}

/* --- Téléphone et tablette : le tiroir ------------------------------------- */
@media (max-width: 991.98px) {
    .espace-sidebar {
        transform: translateX(-100%);
        transition: transform .22s ease;
        box-shadow: var(--ombre-3);
    }

    .espace-sidebar.ouvert {
        transform: translateX(0);
    }

    .espace-contenu {
        margin-left: 0;
    }

    .espace-topbar {
        display: flex;
        align-items: center;
        gap: .75rem;
        padding: .625rem .75rem;
        background: var(--surface, #fff);
        border-bottom: 1px solid var(--bordure, #e3e1de);
        position: sticky;
        top: 0;
        z-index: 1020;
    }

    .espace-topbar-espace {
        flex: 1 1 auto;
    }

    .espace-topbar-logo img {
        display: block;
        height: auto;
    }

    .espace-burger {
        background: none;
        border: 1px solid var(--bordure, #e3e1de);
        border-radius: var(--border-radius);
        color: var(--texte, #201e1d);
        /* 44 px au doigt, comme toutes les cibles tactiles du site. */
        min-width: 44px;
        min-height: 44px;
    }

    /* Le défilement de la page est bloqué tant que le tiroir est ouvert : sinon
       le doigt fait glisser le contenu au lieu du menu. */
    body.espace-fige {
        overflow: hidden;
    }
}

@media (min-width: 992px) {
    .espace-voile {
        display: none;
    }
}

/* ============================================================
   MODE SOMBRE
   ============================================================
   Les jetons de rôle (surface, texte, bordure) avaient été posés en
   préparation. Ils prennent ici leurs deux jeux de valeurs, et **les règles de
   composants ci-dessous sont écrites une seule fois** : elles lisent les jetons,
   donc elles ne font rien en clair (où les valeurs sont celles d'aujourd'hui) et
   basculent d'elles-mêmes en sombre. C'est ce qui évite d'avoir deux feuilles à
   maintenir en parallèle.

   Trois règles de conduite :

   · **Le choix du visiteur l'emporte sur celui de son système.** `prefers-color-scheme`
     donne le défaut ; l'attribut `data-theme` sur `<html>`, posé par le sélecteur
     et gardé en mémoire locale, le remplace dans les deux sens.
   · **L'orange de lien change de valeur.** Le `#995427` du mode clair ne donne que
     2,91:1 sur une surface sombre. En sombre il remonte à `#c67139`, l'orange
     d'origine du site, trop clair sur blanc, exactement juste sur noir : 4,64:1.
   · **Les boutons ne bougent pas.** Le blanc sur `--primary` donne 4,54:1 quel que
     soit ce qu'il y a derrière.

   Contrastes du texte en sombre, mesurés : 13,6:1 sur une carte, 15,1:1 sur le
   fond de page, 6,8:1 pour le texte secondaire.
   ============================================================ */
:root {
    --lien: var(--primary-100);
    /* Le vert et le rouge de Porto sont codes en dur dans son theme, hors du
       jeu de jetons, et ne passent ni l'un ni l'autre : #0cc485 donne 2,27:1
       sur blanc et #ff5b5b 3,04:1. Ils deviennent des jetons, avec leurs deux
       valeurs, assombris sur fond clair, eclaircis sur fond sombre. */
    --succes-texte: #08875b;
    --danger-texte: #eb0000;
    color-scheme: light;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="clair"]) {
        --surface: #16130f;
        --surface-basse: #0f0d0b;
        --surface-haute: #211d19;
        --texte: #ece7e1;
        --texte-secondaire: #aca49c;
        --bordure: #382f28;
        --lien: #c67139;
        /* Les deux gris de texte de Porto suivent le theme : sans cela, tout le
           corps de texte du site restait en #6b6b6b, soit 3,1:1 sur une surface
           sombre, de loin la premiere cause de faute au releve. */
        --grey: #aca49c;
        --default: #aca49c;
        --succes-texte: #0cc082;
        --danger-texte: #ff5757;
        color-scheme: dark;
    }
}

:root[data-theme="sombre"] {
    --surface: #16130f;
    --surface-basse: #0f0d0b;
    --surface-haute: #211d19;
    --texte: #ece7e1;
    --texte-secondaire: #aca49c;
    --bordure: #382f28;
    --lien: #c67139;
    --grey: #aca49c;
    --default: #aca49c;
    --succes-texte: #0cc082;
    --danger-texte: #ff5757;
    color-scheme: dark;
}

/* --- Les règles, écrites une fois, valables dans les deux thèmes ------------ */
body,
.body {
    background-color: var(--surface);
    color: var(--texte);
}

a {
    color: var(--lien);
}

section.section:not([class*="bg-color-"]):not(.section-primary) {
    background-color: var(--surface);
}

.bg-color-light,
.bg-color-light-scale-1 {
    background-color: var(--surface-haute) !important;
}

.bg-color-grey {
    background-color: var(--surface-basse) !important;
}

.card,
.modal-content,
.toggle > .toggle-content,
.list-group-item {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
    color: var(--texte);
}

.card-header {
    border-color: var(--bordure);
}

#header .header-body {
    background-color: var(--surface-haute);
    border-color: var(--bordure) !important;
}

.espace-topbar {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
}

.form-control,
.form-select,
.input-group-text {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
    color: var(--texte);
}

.form-control::placeholder {
    color: var(--texte-secondaire);
    opacity: 1;
}

.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--texte);
    --bs-table-striped-color: var(--texte);
    border-color: var(--bordure);
}

.table > :not(caption) > * > * {
    border-color: var(--bordure);
    color: var(--texte);
}

.text-color-dark {
    color: var(--texte) !important;
}

.text-color-grey,
.text-color-default {
    color: var(--texte-secondaire) !important;
}

hr,
.border-top,
.border-bottom,
.border {
    border-color: var(--bordure) !important;
}

/* Le bouton clair est blanc sur blanc en mode sombre : il prend la surface
   haute et la couleur de texte du theme. */
.btn-light {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
    color: var(--texte);
}

.btn-light:hover,
.btn-light:focus-visible {
    background-color: var(--surface-basse);
    color: var(--texte);
}

.badge-light {
    background-color: var(--surface-basse);
    color: var(--texte);
}

.nav-pills .nav-link:not(.active) {
    color: var(--texte);
}

/* --- Le sélecteur de thème -------------------------------------------------- */
.bascule-theme {
    background: none;
    border: 1px solid var(--bordure);
    border-radius: var(--border-radius);
    color: var(--texte);
    min-width: 44px;
    min-height: 44px;
    line-height: 1;
    padding: .25rem .625rem;
}

.bascule-theme:hover,
.bascule-theme:focus-visible {
    background-color: var(--surface-basse);
}

/* L'icône affichée dépend du thème actif : on montre ce vers quoi on bascule. */
.bascule-theme .icone-sombre { display: inline; }
.bascule-theme .icone-clair { display: none; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="clair"]) .bascule-theme .icone-sombre { display: none; }
    :root:not([data-theme="clair"]) .bascule-theme .icone-clair { display: inline; }
}

:root[data-theme="sombre"] .bascule-theme .icone-sombre { display: none; }
:root[data-theme="sombre"] .bascule-theme .icone-clair { display: inline; }

/* La barre latérale de l'espace garde son terracotta profond dans les deux
   thèmes : c'est une surface de marque, pas une surface de contenu. */
.bascule-theme-espace .icone-sombre { display: inline; }
.bascule-theme-espace .icone-clair { display: none; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="clair"]) .bascule-theme-espace .icone-sombre { display: none; }
    :root:not([data-theme="clair"]) .bascule-theme-espace .icone-clair { display: inline; }
}

:root[data-theme="sombre"] .bascule-theme-espace .icone-sombre { display: none; }
:root[data-theme="sombre"] .bascule-theme-espace .icone-clair { display: inline; }

/* --- Ce que Porto peint en clair sans passer par une variable ---------------
   Relevé en interrogeant le DOM rendu en mode sombre, surface par surface,
   plutôt qu'en devinant : ces six-là sont tout ce qui restait clair.
   `.badge-tertiary` et `.bg-color-tertiary` ne sont pas dans la liste et c'est
   voulu : le crème de la charte reste un accent lisible sur fond sombre, avec
   son texte foncé. */
h1, h2, h3, h4, h5, h6 {
    color: var(--texte);
}

.text-dark,
.text-color-dark {
    color: var(--texte) !important;
}

.nav-link {
    color: var(--texte);
}

.featured-box,
.featured-box .box-content {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
}

.toggle > label,
.toggle > .toggle-title {
    background-color: var(--surface-basse);
}

.process-step-circle {
    background-color: var(--surface-haute);
    border-color: var(--bordure);
}

/* Le pied de page est déjà sombre en clair : en sombre il doit se détacher du
   fond de page, plus sombre encore, par une bordure plutôt qu'un aplat. */
#footer {
    border-top: 1px solid var(--bordure);
}

/* --- Ce que le balayage des deux thèmes a encore trouvé ---------------------
   Le relevé est fait sur le DOM rendu, en remontant la chaîne des fonds jusqu'au
   premier opaque. Il a mis au jour deux défauts qui existaient **déjà en mode
   clair** et qu'un balayage plus grossier manquait : la mise en valeur d'un
   titre restait orange sur l'aplat orange du dernier appel à l'action (donc
   invisible), et le surtitre de la même section, en crème sur orange, ne donnait
   que 3,39:1. */

/* Sur un aplat de marque, la mise en valeur et les surtitres passent au blanc :
   l'orange sur l'orange ne se voit pas. */
.bg-color-primary .title-highlight,
.bg-color-primary-200 .title-highlight,
.section-primary .title-highlight,
.call-to-action-primary .title-highlight,
[class*="bg-color-primary"] .text-color-tertiary,
.call-to-action-primary .text-color-tertiary {
    color: #fff !important;
    text-decoration-color: rgba(255, 255, 255, .65);
}

/* Le crème de la charte est une surface claire dans les deux thèmes : ce qui se
   pose dessus reste sombre, sinon le mode sombre y écrit en clair sur clair. */
.bg-color-tertiary,
.bg-color-tertiary h1, .bg-color-tertiary h2, .bg-color-tertiary h3,
.bg-color-tertiary h4, .bg-color-tertiary h5, .bg-color-tertiary h6,
.bg-color-tertiary p, .bg-color-tertiary span, .bg-color-tertiary li,
.bg-color-tertiary strong {
    color: var(--tertiary-inverse) !important;
}

/* Porto colore la navigation principale par un sélecteur bien plus spécifique
   que `.nav-link` : il faut le reprendre à l'identique. */
/* `!important` assume : Porto empile plusieurs regles concurrentes sur ces deux
   composants (Bootstrap, theme.css et theme-elements.css), et le sombre doit
   gagner sur toutes. C'est le seul endroit du fichier ou la surcharge de theme
   le justifie ; ailleurs, une specificite correcte suffit. */
#header .header-nav-main nav > ul > li > a,
#header .header-nav-main nav > ul > li > a:focus,
.nav-pills .nav-link:not(.active) {
    color: var(--texte) !important;
}

.price,
.plan-price .price,
.pricing-block .plan-price .price {
    color: var(--texte) !important;
}

/* --- Les deux boutons que Porto peint en dur ------------------------------- */
.btn-light {
    background-color: var(--surface-haute) !important;
    border-color: var(--bordure) !important;
    color: var(--texte) !important;
}

.btn-light:hover,
.btn-light:focus-visible {
    background-color: var(--surface-basse) !important;
}

/* Le bouton « contour sombre » : son trait et son texte sont le `--dark` de
   Porto, invisible sur une surface sombre. */
.btn-dark.btn-outline,
.btn-dark.btn-outline:focus {
    color: var(--texte) !important;
    border-color: var(--texte) !important;
    background-color: transparent !important;
}

.btn-dark.btn-outline:hover {
    color: var(--surface) !important;
    background-color: var(--texte) !important;
}

/* --- Les couleurs de statut, et le pied de page de l'espace ---------------- */
.text-color-success {
    color: var(--succes-texte) !important;
}

.text-color-danger {
    color: var(--danger-texte) !important;
}

/* Le badge secondaire posait du blanc sur l'olive de la charte : 4,00:1, sous le
   seuil. La nuance immédiatement plus sombre donne 4,99:1 sans changer la teinte. */
.badge-secondary {
    background-color: var(--secondary-100) !important;
}

/* Le pied de page de l'espace client héritait du pied sombre du site public,
   tout en portant le gris de texte du mode clair : 3,12:1 sur ses propres liens.
   Dans l'espace, il suit le thème comme le reste de la colonne de contenu. */
#footer.espace-contenu {
    background-color: var(--surface-basse);
    color: var(--texte-secondaire);
}

#footer.espace-contenu a {
    color: var(--texte-secondaire);
}

/* --- Les deux derniers cas relevés sur les quinze écrans ------------------- */

/* Porto colore ces titres par `.feature-box.feature-box-style-2 h4`, soit deux
   classes : un sélecteur à une seule classe perdait, et j'ai dû le mesurer pour
   m'en apercevoir. On reprend donc deux classes. On ne bascule pas `--dark` pour
   autant : cette variable sert aussi de **fond** (au pied de page, aux boutons
   sombres), et l'inverser les éclaircirait. */
.feature-box .feature-box-info h1, .feature-box .feature-box-info h2,
.feature-box .feature-box-info h3, .feature-box .feature-box-info h4,
.feature-box .feature-box-info h5, .feature-box .feature-box-info h6 {
    color: var(--texte);
}

/* Les variantes d'alerte de Bootstrap sont des surfaces **teintées claires** dans
   les deux thèmes : rose pâle pour un danger, vert pâle pour un succès. Leur
   texte doit donc rester sombre, sinon le mode sombre y écrit en clair sur clair :
   1,84:1 sur l'avertissement « ne jamais mélanger croquettes et viande crue ».
   `alert-dark` et `alert-default` sont exclues : celles-là sont bien sombres. */
.alert-danger, .alert-danger *,
.alert-success, .alert-success *,
.alert-warning, .alert-warning *,
.alert-info, .alert-info * {
    color: #201e1d;
}

.alert-danger a, .alert-success a, .alert-warning a, .alert-info a {
    color: #723b15;
}

/* `.alert-primary` et `.alert-secondary` sont expressement exclues de la regle
   ci-dessus, et ce n'est pas un oubli.

   Elles figuraient dans la liste, par assimilation aux autres variantes. C'etait
   faux : Porto leur donne un fond **terracotta plein**
   (`theme-elements.css` : `background-color: var(--primary)`), la ou danger,
   succes, avertissement et info sont des surfaces **teintees claires**. Ecrire
   #201e1d dessus donnait le titre gris fonce sur orange du bandeau « Protocole
   de transition securise » : signale a l'ecran, pas trouve dans le code.

   Le blanc sur `--primary` donne 4,54:1, au-dessus du seuil AA de 4,5:1 pour du
   texte courant, et le titre du bandeau est en gras et en grand corps. */
.alert-primary, .alert-primary *,
.alert-secondary, .alert-secondary * {
    color: var(--primary-inverse);
}

/* Un lien nu dans ces bandeaux heriterait sinon de `a { color: var(--lien) }`,
   c'est-a-dire du terracotta sur du terracotta. */
.alert-primary a, .alert-secondary a {
    color: var(--primary-inverse);
    text-decoration: underline;
}

/* ============================================================
   CASSE ET INTERLETTRAGE DES TITRES
   ============================================================
   Porto force `text-transform: uppercase` sur **h3 et h5 uniquement**, et laisse
   h1, h2, h4 et h6 en casse normale. Le titre d'accueil est donc en bas de casse
   et un titre de carte juste en dessous en capitales, sans qu'aucune intention
   ne le justifie : c'est une incohérence du thème, pas un parti pris.

   Plus gênant, et c'est la vraie cause du malaise : Porto applique
   `letter-spacing: -0.05em` à **tous** les titres. Un interlettrage négatif est
   fait pour du bas de casse en grand corps. Appliqué à des capitales, il les
   colle, « CRUIMPROVISÉ » au lieu de « CRU IMPROVISÉ ». En typographie, des
   capitales se composent toujours avec un interlettrage **positif**.

   Les titres passent donc en casse normale, avec un resserrement dégressif :
   marqué sur les grands corps, presque nul sur les petits, où il nuirait à la
   lisibilité. Les capitales délibérées (surtitres, libellés de statistique,
   badges) les gardent, mais avec l'espacement qui leur revient.
   ============================================================ */
h1, h2, h3, h4, h5, h6 {
    text-transform: none;
}

h1 { letter-spacing: -0.025em; }
h2 { letter-spacing: -0.02em; }
h3 { letter-spacing: -0.015em; }
h4, h5, h6 { letter-spacing: -0.005em; }

/* Les capitales voulues : surtitres, libellés de statistique, badges, boutons. */
.text-uppercase {
    letter-spacing: 0.045em;
}

/* Un badge est déjà serré dans sa pilule : un interlettrage plus mesuré y suffit
   et évite de l'élargir inutilement. */
.badge.text-uppercase {
    letter-spacing: 0.03em;
}

/* Les boutons `btn-modern` sont en capitales avec un interlettrage nul. Des
   capitales sans espacement restent trop serrées, même si c'est moins criant
   qu'un espacement négatif. La casse, elle, n'est pas touchée : c'est une
   convention défendable pour un appel à l'action, et ce n'est pas ce qui avait
   été signalé. */
.btn-modern {
    letter-spacing: 0.04em;
}


/* ══════════════════════════════════════════════════════════════════════
   Les captures d'écran du produit
   ══════════════════════════════════════════════════════════════════════
   Ajoutées le 11 septembre avec la section « Ce que vous recevez ».

   Elles sont volontairement capturées en thème clair uniquement : produire
   un second jeu en sombre aurait coûté 150 Kio de plus sur une page qui
   n'en avait pas besoin. La contrepartie est qu'en mode sombre une capture
   devient une tache blanche posée sur un fond profond. Ce filet la fait
   lire comme **un écran** plutôt que comme un trou dans la page : c'est le
   même procédé qu'une photographie encadrée sur un mur foncé.

   En thème clair le filet est presque invisible et sert seulement à
   détacher la capture du fond gris de la section. */
.capture-produit {
    border: 1px solid var(--bordure);
}


/* L'entete de la section produit, entre 992 et 1199 px.

   Le conteneur de Bootstrap passe a 960 px des 992 px et n'y bouge plus jusqu'a
   1200 px, ou il saute a 1140. Mais l'echelle typographique de Porto, elle,
   continue de grandir avec la fenetre : a 1199 px le titre est rendu a 32,8 px
   et reclame 1012 px de large pour 960 disponibles. Il manque 52 px au titre et
   24 px au chapeau, et les deux se replient sur deux lignes, precisement sur la
   taille d'ecran d'un portable courant.

   La reponse n'est pas de raccourcir les phrases : elles ont ete choisies. On
   fige la taille du texte dans cette seule plage, juste assez pour que la ligne
   rentre. La largeur utile n'est pas 960 px mais 936 : la colonne de Bootstrap
   garde 12 px de rembourrage de chaque cote. Le titre perd donc 9 % et tombe a
   918 px, le chapeau 8 % et tombe a 901 px.

   La borne haute est passee de 1200 a 1250 px le meme jour, quand le conteneur
   du site a recu ses marges laterales de 8 % : a 1200 px de fenetre il ne fait
   plus 1200 px mais 1008, et le titre y redebordait. Mesure a l'appui, il tient
   des 1250 px. En dessous de 992 px le repli sur deux lignes est voulu. */
@media (min-width: 992px) and (max-width: 1249.98px) {
    /* `!important` parce que les utilitaires de taille de Porto le portent
       eux-memes (voir `.text-7` plus haut) : sans lui, la regle perd. */
    .entete-produit h2 {
        font-size: 1.86rem !important;
    }

    .entete-produit p {
        font-size: 1.12rem !important;
    }
}


/* Une page qui verrouille son theme n'offre pas de bascule : elle ne ferait que
   contredire le verrou. Voir `{% block theme_impose %}` dans index.html : la
   page d'accueil est en clair par decision, parce qu'elle porte les captures du
   produit et qu'elle recoit des visiteurs qui ne connaissent pas la marque. */
[data-theme-verrouille] .bascule-theme {
    display: none !important;
}


/* ══════════════════════════════════════════════════════════════════════
   L'appel a l'action de fin de page : le texte n'etait pas centre
   ══════════════════════════════════════════════════════════════════════
   Porto pose `padding: 35px 0 0` sur `.call-to-action-content`. La colonne,
   elle, est bien en `display:flex; align-items:center` : la BOITE du contenu
   est donc parfaitement centree. Mais son rembourrage haut fait descendre le
   texte de 35 px a l'interieur de cette boite : mesure sur la page, le titre
   et son chapeau tombaient 17 px sous le centre, tandis que le bouton, lui,
   etait centre. D'ou l'impression de deux blocs desalignes.

   On ne retire ce rembourrage qu'au-dessus de 992 px. En dessous, les deux
   colonnes s'empilent : le centrage vertical n'a plus de sens, et ces 35 px
   sont alors le seul espace entre le bord du bloc et le titre : la section
   n'en laisse que 10 de son cote. */
@media (min-width: 992px) {
    /* Trois classes, pas deux. La regle de Porto qu'on neutralise ici s'ecrit
       `.call-to-action.button-centered .call-to-action-content`, soit une
       specificite de (0,3,0) ; une version a deux classes perdait en silence et
       le texte restait 20 px sous le centre, mesure a l'appui. La lecon est la
       meme que pour la couleur de lien plus haut dans ce fichier : on verifie
       QUELLE regle gagne dans le navigateur, on ne deduit pas. */
    .call-to-action.button-centered .call-to-action-content {
        padding-top: 0;
    }
}


/* ══════════════════════════════════════════════════════════════════════
   Les deux cartes d'abonnement : leurs boutons s'alignent en bas
   ══════════════════════════════════════════════════════════════════════
   Consequence directe du 11 septembre, quand la liste de P'tits Amours est
   passee de six puces a quatre : elle ne redit plus ce que P'tit Filou
   contient deja. Les cartes ont la meme hauteur (`h-100`), mais leur contenu
   restait cale en haut : le bouton « Rejoindre en Famille » flottait alors au
   milieu de sa carte, un grand vide sous lui, tandis que celui d'a cote
   tombait bien plus bas. Deux appels a l'action desalignes dans une grille
   tarifaire donnent l'impression que l'offre la plus chere est la plus maigre.

   La colonne devient donc un flux vertical et le dernier bloc (celui du
   bouton) prend l'espace restant par `margin-top: auto`. Les listes gardent
   leur longueur reelle : c'est l'espace vide qui se deplace, pas le contenu. */
/* `flex: 1 1 auto` et non `height: 100%` : le pourcentage ne se resout pas
   contre un parent dont la hauteur vient elle-meme du flux flex, et il restait
   78 px d'ecart entre les deux boutons : mesure, pas suppose. */
.card > .card-body > .pricing-block {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

.card > .card-body:has(> .pricing-block) {
    display: flex;
    flex-direction: column;
}

/* `!important` a contrecoeur, et pour une raison precise : le bloc du bouton
   porte la classe utilitaire `mt-4` de Bootstrap, dont la declaration est
   elle-meme `!important`. Aucune specificite, si haute soit-elle, ne la bat,
   seul un `!important` le peut. Retirer `mt-4` du gabarit marcherait aussi,
   mais priverait la carte de son espacement quand elle est seule sur sa
   ligne, sur telephone. */
.card > .card-body > .pricing-block > div:last-child {
    margin-top: auto !important;
}


/* ══════════════════════════════════════════════════════════════════════
   La légende du camembert de répartition
   ══════════════════════════════════════════════════════════════════════
   Elle était dessinée dans le canvas par Chart.js, qui la rognait sans rien
   dire entre 992 et 1300 px de large : la carte est en `col-lg-4`, donc au
   plus étroite juste au-dessus du seuil `lg`, et la hauteur du canvas suit sa
   largeur. Mesuré à 1200 px : canvas de 214 px, dernière ligne de légende à
   251 px. « Abats » et « Fruits & Légumes » étaient invisibles, soit 15 % de
   la ration, sur la page que le client paie.

   En HTML, elle se replie au lieu d'être coupée, suit le thème sombre par
   `--texte`, se sélectionne, et se lit à voix haute. La pastille de couleur
   reçoit sa teinte du script, qui la prend aux jetons de la charte. */
.donut-legende {
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.35rem 0.9rem;
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--texte);
}

.donut-legende li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    /* Un libellé ne se coupe jamais au milieu : il passe entier à la ligne. */
    white-space: nowrap;
}

.donut-puce {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    flex: 0 0 auto;
}

/* Sur la page publique, le graphique ne s'initialise qu'à l'ouverture de
   l'onglet Nutrition : la liste reste vide jusque-là et ne doit pas réserver
   d'espace pour rien. */
.donut-legende:empty {
    margin: 0;
}


/* ══════════════════════════════════════════════════════════════════════
   La carte du camembert s'aligne sur la grille de tuiles voisine
   ══════════════════════════════════════════════════════════════════════
   Depuis que la légende est passée sous le graphique, la carte valait le
   titre + un canvas carré + la légende. Elle dépassait donc la grille des
   quatre tuiles placées à côté, la rangée s'alignait sur la plus haute des
   deux, et un vide imposant s'ouvrait sous les tuiles.

   Le canvas n'a plus de hauteur propre : `.donut-boite` occupe l'espace
   restant (`flex: 1 1 auto`) une fois le titre et la légende placés, et
   `maintainAspectRatio: false` laisse Chart.js s'y conformer. Le camembert
   reste un cercle : il se centre sur la plus petite dimension.

   Le `min-height` sert au cas où la carte n'a pas de voisine pour lui donner
   sa hauteur : sur téléphone les colonnes s'empilent, et sans lui le
   graphique s'effondrerait à zéro. */
.carte-camembert {
    display: flex;
    flex-direction: column;
}

.donut-boite {
    position: relative;
    flex: 1 1 auto;
    min-height: 190px;
}

.donut-boite > canvas {
    position: absolute;
    inset: 0;
}


/* La grille de tuiles de la page « Mon plan » remplit sa colonne.

   Les deux colonnes de la rangée ont déjà la même hauteur, Bootstrap les
   étirant ; c'est le CONTENU de celle de droite qui se calait en haut et
   laissait un vide sous les quatre tuiles, d'autant plus visible que la carte
   du camembert a grandi en recevant sa légende.

   `align-content: stretch` répartit les deux lignes de tuiles sur toute la
   hauteur disponible, et le `h-100` posé sur chaque carte leur fait occuper
   leur cellule. Sous 576 px les tuiles passent en pleine largeur et se
   suivent : la répartition n'a plus lieu d'être, la hauteur redevient celle du
   contenu. */
@media (min-width: 576px) {
    /* `flex` et non `height: 100%` : le pourcentage ne se resout pas contre un
       parent dont la hauteur vient elle-meme du flux flex, et la premiere
       version n'a rien change du tout : mesure identique au pixel pres. C'est
       le meme piege que sur les cartes tarifaires. */
    .tuiles-ration {
        display: flex;
        flex-direction: column;
    }

    .tuiles-ration > .row {
        flex: 1 1 auto;
        align-content: stretch;
    }

    /* Une tuile etiree garde sinon son chiffre colle en haut : le vide qu'on
       vient de retirer sous la grille reapparaitrait a l'interieur de chaque
       carte. Le libelle, le chiffre et l'unite se centrent donc dans la
       hauteur disponible. */
    .tuiles-ration .card-body {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }
}
