/* ==========================================================================
   Smakoo — feuille de surcharge de l'application mobile
   --------------------------------------------------------------------------
   RÔLE
     Aligner l'habillage de l'app mobile (server/mobile/) sur la refonte du
     site (server/themes/landing2/css/smakoo.css) : mêmes couleurs, même
     typographie, mêmes formes.

   CHARGEMENT
     À inclure APRÈS mobile/css/smakoo20.css et mobile/css/smakoo.css :

       <link rel="stylesheet" href="css/smakoo-theme.css">

     Ce fichier ne modifie AUCUN fichier existant. Il ne fait que surcharger.

   PÉRIMÈTRE
     · Tous les sélecteurs de ce fichier ont été relevés dans les gabarits
       réellement servis : server/mobile/templates/mobile/ (fichiers .html)
       (settings.mobileTheme = « mobile », voir SMAKOO-PASSATION-COMPLETE.md §10).
     · Les feuilles d'origine étant très spécifiques (et par endroits en
       style inline dans index.php), `!important` est utilisé là où c'est
       nécessaire pour gagner la cascade. C'est assumé.

   INTERDITS RESPECTÉS (leçons du 03/10, incidents constatés)
     · aucun `filter:` ni filtre SVG ;
     · aucun calcul en `100vw` — au contraire, trois `100vw` hérités des
       feuilles d'origine sont neutralisés en fin de fichier ;
     · seules `transform` et `opacity` sont animées ;
     · `user-scalable` / `maximum-scale` ne sont pas touchés (le zoom reste
       sous le contrôle de la balise viewport d'index.php, non modifiée) ;
     · pas de `width`/`height`/`top`/`left` animés.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. POLICES
   Le site charge Calistoga (titres) + Inter (texte). L'app mobile ne charge
   aujourd'hui que Montserrat / Rubik / Inter selon le thème : on importe les
   deux familles ici. `@import` est en tête de fichier (obligation CSS).
   -------------------------------------------------------------------------- */
@import url('https://fonts.googleapis.com/css2?family=Calistoga&family=Inter:wght@400;500;600;700&display=swap');


/* --------------------------------------------------------------------------
   1. JETONS DE DESIGN
   Copie STRICTE du bloc `:root` de `themes/default/css/smakoo-theme.css`
   (lignes 45 a 103), qui fait foi. Le fichier mobile avait ete ecrit d'apres
   la page publique : huit jetons de la charte manquaient et trois valeurs
   divergeaient, ce qui suffisait a faire deriver toutes les regles ecrites
   dans un theme et recopiees dans l'autre.

   Ecart mesure avant correction (comparaison automatique des deux blocs) :
     --accent-texte  #0B6FA8  ->  violet de marque   (la meme teinte s'appelait
                                              differemment dans les deux
                                              feuilles)
     --titre / --texte / --ombre-1 / --ombre-2 / --courbe : espaces de
       separation differents (sans effet sur le rendu, mais tout diff automatique
       remontait 5 faux ecarts)
     --bloc, --cible, --gouttiere, --largeur, --surface-2, --trait-fonce,
       --ombre-3, --etoiles, --gris-texte, --orange-texte : absents.

   Seule correction de VALEUR portait sur --accent-texte. Les jetons derives
   de l'app (`--accent-appui-hover`, `--succes`, `--rayon-pilule`,
   `--ombre-accent`, `--ombre-like`) sont conserves : ils sont propres au
   tactile (etats appuyes, vert de presence) et ne contredisent pas la charte.
   -------------------------------------------------------------------------- */
:root {
  /* Couleurs officielles — CHARTE JAUNE/NOIR du 07/10/2026 (esprit Bumble).
     Le jaune de marque #FFC629 est CLAIR : du texte blanc dessus ne donne que
     1,57:1. Tout fond d'accent qui porte du texte reçoit donc du texte ENCRE
     (#14171A) : 11,45:1. Le texte d'accent sur fond clair passe sur l'or foncé
     #7A5A00 : 6,38:1 sur blanc. */
  --accent:#FFC629;
  --accent-fonce:#E0A400;
  --accent-appui:#FFC629;
  --accent-texte:#7A5A00;     /* or foncé, 6,38:1 sur blanc — voir la note de la charte */
  --accent-clair:#FFF3CE;
  --like:#FFC629;
  --like-fonce:#E0A400;

  /* Neutres chauds */
  --encre:#14171A;            /* texte principal — 16:1 sur blanc */
  --gris:#5B6672;             /* texte secondaire — 5,85:1 sur blanc */
  --surface:#F7F5F2;          /* fonds neutres chauds */
  --trait:#E7E2DA;            /* bordures */
  --blanc:#FFFFFF;

  /* Rythme */
  --rayon:26px;               /* cartes */
  --rayon-sm:14px;            /* petits elements */
  --bloc:56px;

  /* Typographie — chaines identiques au web, caractere pour caractere */
  --titre:'Calistoga',Georgia,'Times New Roman',serif;
  --texte:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;

  /* Elevations */
  --ombre-1:0 4px 14px rgba(20,23,26,.06);
  --ombre-2:0 14px 38px rgba(20,23,26,.10);

  /* Durees et courbe */
  --t-court:200ms;
  --t-long:300ms;
  --courbe:cubic-bezier(.2,.8,.3,1);

  /* Cible tactile minimale — deux noms pour la meme valeur dans la charte */
  --tactile:44px;
  --cible:44px;

  /* Jetons de la charte absents du fichier mobile avant le 06/10/2026.
     `--gouttiere` est le plus important : c'est lui qui fixe les 28 px de
     marge interne des cartes et des listes cote web (valeur unique partout,
     mesuree sur .wall, .banner et les cartes du fil). */
  --gouttiere:28px;
  --largeur:1240px;
  --surface-2:#FDF3F5;
  --trait-fonce:#2A2F35;
  --etoiles:#B45309;
  --ombre-3:0 26px 60px rgba(20,23,26,.16);
  --gris-texte:#6B6B78;       /* 5,25:1 sur blanc */
  --orange-texte:#9A5A00;     /* 5,47:1 sur blanc */
  --accent-appui-fonce:#E0A400;
  --accent-texte-2:#7A5A00;   /* meme valeur que --accent-texte : la charte
                                 web nomme cette teinte deux fois (bloc
                                 principal puis bloc de la section 18.7). */

  /* ------------------------------------------------------------------
     JETONS PROPRES A L'APPLICATION TACTILE (pas dans la charte web)
     ------------------------------------------------------------------ */
  --rayon-pilule:999px;       /* boutons, badges, avatars — nommee ici,
                                 alissee sur --rayon/--rayon-sm partout
                                 ailleurs */
  --accent-appui-hover:#E0A400;
  --succes:#0B8A3E;           /* Vert de statut du fichier mobile. Un premier
                                 correctif l'avait remplace par #17D417 (le
                                 vert de smakoo.css / smakoo20.css) au nom de
                                 l'alignement sur le site : c'etait une erreur
                                 de reference. Verification faite le 06/10 —

                                   grep '17D417' themes/default/css/smakoo-theme.css  -> 0
                                   grep '17D417' themes/default/css/smakoo.css        -> 2

                                 Ces deux occurrences sont dans la feuille
                                 d'ORIGINE, pas dans la charte. Le vert de
                                 presence de la charte est #12A150, present
                                 dans le preset actif `lightOcean` :
                                   spotlight_border_story_online  = #12A150
                                   notification_inapp_message_bg  = #12A150
                                 Et il est conforme : 3,37:1 sur blanc, la ou
                                 #17D417 ne donne que 2,01:1 (seuil 3:1 pour
                                 un indicateur graphique, WCAG 1.4.11).
                                 Voir --presence ci-dessous. */
  --presence:#12A150;         /* vert de presence, valeur du site */
  --ombre-accent:0 8px 22px rgba(255, 198, 41,.26);
  --ombre-like:0 8px 22px rgba(255,198,41,.28);
}


/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */
body {
  font-family: var(--texte) !important;
  font-size: 16px;
  line-height: 1.55;
  color: var(--encre);
  background-color: var(--blanc);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Le pincement pour zoomer reste autorisé : on ne verrouille rien. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Champs de saisie : Inter, jamais la police d'affichage. */
input, textarea, select, button {
  font-family: var(--texte);
}


/* --------------------------------------------------------------------------
   3. TYPOGRAPHIE
   Dans cette application, `.comforta` / `.b-none` jouent le rôle de « police
   d'affichage » : ils habillent les titres, les noms et les grands libellés.
   → Calistoga, comme les titres du site.
   Les gabarits d'origine les forcent en Inter/Rubik via un bloc <style> de
   index.php ; la spécificité `body .x` (+ !important) reprend la main quel que
   soit l'ordre de chargement.
   -------------------------------------------------------------------------- */

/* Titres et noms */
body .comforta,
body .b-none,
body .chat-name,
body .profile-info__title,
body .feature-card__title,
body .stream-notice__title,
body .wallet-t-title,
body .qa-title,
.navigation-bar__title,
.cta-box__header,
.own-profile__username,
.encounters-card__name,
.profile-user-info__name {
  font-family: var(--titre) !important;
  font-weight: 400;
  letter-spacing: -.01em;
  color: var(--encre);
}

.navigation-bar__title {
  font-size: 19px;
  line-height: 1.2;
}

.navigation-bar__title-additional {
  font-family: var(--texte);
  font-size: 12.5px;
  line-height: 1.3;
  color: var(--gris);
}

.cta-box__header {
  font-size: 24px;
  line-height: 1.2;
  color: var(--encre);
}

/* Titres posés sur un fond sombre (modales premium, célébrations) :
   on laisse la couleur claire décidée par le gabarit. */
body .premium-bg.comforta,
body .mi-violetita .comforta {
  color: inherit;
}

/* Courant : Inter, jamais la police d'affichage.
   Les gabarits posent souvent `comforta` sur ces éléments ; le `!important`
   est nécessaire pour reprendre la main sur `body .comforta` ci-dessus. */
body .text-muted,
body .csms-p-1,
body .profile-info__content,
body .chat-last-m,
body .wallet-t-details,
body .item-note,
body .contact-list-search__cancel,
body .csms-profile-info__name-inner,
body .profile-user-info__meta {
  font-family: var(--texte) !important;
}

body .csms-profile-info__name-inner {
  font-weight: 600;
  font-size: 16px;
  color: var(--encre);
}

body .text-muted,
.csms-connections-item__message,
.chat-last-m,
.item-note {
  color: var(--gris);
}

/* Étiquettes de section : petites capitales espacées, comme le site. */
.selector .selector__label,
.selector__label {
  font-family: var(--texte) !important;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--gris);
}

.chat-v2-name {
  font-size: 18px;
  color: var(--encre);
}

.encounters-card__name,
.profile-user-info__name {
  font-size: 22px;
}

.encounters-card__announce {
  font-family: var(--texte);
  font-size: 14px;
  color: var(--gris);
}


/* --------------------------------------------------------------------------
   4. BARRE DE NAVIGATION HAUTE
   Le site : fond blanc, filet `--trait` en bas, pas d'ombre lourde.
   -------------------------------------------------------------------------- */
.navigation-bar {
  background-color: var(--blanc);
  border-bottom: 1px solid var(--trait);
  box-shadow: none;
}

.navigation-bar--no-background {
  background-color: transparent;
  border-bottom-color: transparent;
}

/* Icônes : cible tactile de 44 px garantie. */
.navigation-bar__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: var(--tactile);
  min-height: var(--tactile);
  padding: 7px;
  border-radius: var(--rayon-sm);
  color: var(--encre);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.navigation-bar__icon.is-active {
  color: var(--accent-texte);
}

.navigation-bar__icon:active {
  transform: scale(.92);
}

.navigation-bar__primary,
.navigation-bar__secondary {
  color: var(--encre);
}

.navigation-bar__logo img {
  max-height: 40px;
  width: auto;
  object-fit: contain;
}

/* --------------------------------------------------------------------------
   MARQUE DU SITE DANS LA BARRE DE NAVIGATION — posee le 07/10/2026

   Le client demandait le logo du site sur les ecrans d'accueil de
   l'application. L'emplacement central porte deja le titre ET son compteur
   (« Visiteurs 12 », « Mes likes 3 ») : on ne peut pas l'occuper sans faire
   perdre le compteur au visiteur.

   La marque du site — le symbole carre, celui que l'application utilise deja
   dans sa fenetre « premium » — est donc posee dans la GOUTTIERE GAUCHE de la
   barre, entre l'icone de retour et le titre.

   Elle est posee HORS FLUX : la largeur de la zone gauche ne change pas, donc
   le titre et son compteur restent exactement au pixel ou ils etaient.
   Mesure : ecart du titre = 0,0 px sur les 11 ecrans qui affichent une barre.

   Ecran le plus serre (Feed), largeur 390 px :
     icone de retour         15,0 ->  40,0 px
     marque du site          59,0 ->  91,0 px   (marge 19,0 px)
     titre le plus a gauche 114,2 px            (marge 23,2 px)

   `pointer-events: none` : la marque ne prend aucun appui a l'icone de retour.
   -------------------------------------------------------------------------- */
body .navigation-bar__brand-host {
  position: relative;
}

body .navigation-bar__brand {
  position: absolute;
  left: var(--tactile, 44px);
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: block;
  pointer-events: none;
}

.navigation-bar__userpic {
  min-width: var(--tactile);
  min-height: var(--tactile);
}


/* --------------------------------------------------------------------------
   5. BARRE D'ONGLETS BASSE
   Surface chaude, filet haut, indicateur rose.
   -------------------------------------------------------------------------- */
.tabbar {
  background-color: var(--surface);
  border-top: 1px solid var(--trait);
  box-shadow: 0 -4px 14px rgba(20, 23, 26, .06);
}

.tabbar__items {
  /* 50 px de haut pour 44 px utiles : la cible tactile est tenue. */
  min-height: 50px;
}

.tabbar-item {
  min-height: var(--tactile);
  border-radius: var(--rayon-sm);
  color: var(--gris);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.tabbar-item.is-active,
.tabbar-item.is-pressed {
  color: var(--accent-texte);
}

.tabbar-item:active {
  transform: scale(.94);
}

.tabbar-item__icon {
  min-width: 30px;
  min-height: 30px;
}

.tabbar-item__icon-indicator {
  border-color: var(--surface);
  background: var(--like);
  box-shadow: 0 1px 4px rgba(255, 198, 41, .5);
}


/* --------------------------------------------------------------------------
   6. ONGLETS DE DOSSIER (haut de la liste de conversations)
   Le site souligne l'élément actif d'un trait rose : on reprend ce motif sans
   provoquer de décalage de mise en page (text-decoration, pas de border).
   -------------------------------------------------------------------------- */
.tabs .tab__label,
.tab .tab__label {
  font-family: var(--texte) !important;
  font-size: 14px;
  font-weight: 700 !important;      /* les gabarits passent font-weight:800 inline */
  letter-spacing: .04em;
  color: var(--gris);
}

.tabs .tab.is-active .tab__label {
  color: var(--encre) !important;
  text-decoration: underline;
  text-decoration-color: var(--like);
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

.tab {
  min-height: var(--tactile);
  display: inline-flex;
  align-items: center;
}


/* --------------------------------------------------------------------------
   7. CARTES, VIGNETTES ET AVATARS
   -------------------------------------------------------------------------- */

/* Vignette carrée (photos, aperçus) : rayon `--rayon-sm`, jamais rognée. */
.brick {
  max-width: 100%;
}

.brick--squared .brick__image {
  border-radius: var(--rayon-sm);
}

/* Les avatars restent ronds : c'est la forme du site pour les visages. */
.csms-brick--circle .csms-avatar__image,
.csms-avatar__image,
.profile-photo {
  border-radius: var(--rayon-pilule);
}

.csms-avatar__image,
.brick__image {
  background-color: var(--surface);
  border: 1px solid var(--trait);
}

.csms-brick--sm .csms-brick__avatar {
  border-radius: var(--rayon-pilule);
}

/* Anneau « story » aux couleurs de la marque. */
body .storyOn {
  border: 3px solid var(--like);
  border-radius: var(--rayon-pilule);
  padding: 2px;
  background-clip: content-box;
}

/* Anneau de mise en avant générique. */
.box-shadow-credits {
  box-shadow: var(--ombre-2);
}

/* Pastilles de compteur (messages non lus, notifications).
   `.csms-mark.csms-mark--red` (0,2,0) est défini dans smakoo20.css : il faut
   la même spécificité pour le reprendre. */
.mark,
.csms-mark,
.csms-mark.csms-mark--red {
  font-family: var(--texte) !important;
  border-radius: var(--rayon-pilule);
  background: var(--like);
  color: #fff;
  font-weight: 700;
}

.mark--sm {
  min-width: 18px;
  line-height: 18px;
  font-size: 11px;
}

.csms-mark--shadow {
  box-shadow: 0 2px 8px rgba(255, 198, 41, .45);
}

/* Point de présence. VALEUR CORRIGEE LE 06/10/2026.
   La version precedente posait #17D417 en ecrivant « le site ne le tient pas
   davantage » : c'etait faux. Le site ne pose PAS #17D417 dans sa charte —
   les deux occurrences sont dans smakoo.css, une feuille d'origine. Le vert
   de presence de la charte est #12A150 (preset `lightOcean`,
   `spotlight_border_story_online` et `notification_inapp_message_bg`), et il
   est conforme : 3,37:1 sur blanc, seuil 3:1 pour un indicateur graphique
   (WCAG 1.4.11). On s'aligne donc sur le site ET sur le seuil, sans
   concession. */
.csms-online-status--online,
i.online-status--online,
.online-status--online {
  background: var(--presence);
}
span.chat-status {
  background: var(--presence);
  color: #fff;
}


/* --------------------------------------------------------------------------
   8. LISTE DE CONVERSATIONS / DE CONNEXIONS
   -------------------------------------------------------------------------- */
.csms-connections-item {
  min-height: 64px;
  background-color: var(--blanc);
  border-bottom: 1px solid var(--trait);
  transition: opacity var(--t-court) var(--courbe);
}

.csms-connections-item:active {
  opacity: .72;
}

/* La ligne d'origine est neutralisée : un seul filet, plus lisible. */
.csms-connections-item::after {
  border-bottom-color: transparent;
}

.csms-connections-item--user .csms-connections-item__profile {
  color: var(--encre);
}

.csms-connections-item--user .csms-connections-item__message {
  color: var(--gris);
  font-size: 14px;
}

.csms-spring-box {
  padding: 10px 0;
}

.csms-spring-box__media {
  margin-right: 14px;
}

/* Recherche : champ plein, surface chaude, rayon `--rayon-sm`. */
.contact-list-search {
  background-color: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
  margin: 8px 15px;
  padding: 4px 14px;
  min-height: var(--tactile);
}

/* .matches.is-searching n'est jamais posé par le JS mobile (classe héritée de
   l'ancien gabarit Belloo) : on ne l'utilise pas ici. Les deux usages réels de
   `.contact-list-search` (matches.html, location.html) sont dans un parent
   sans retrait, la marge latérale de 15 px est donc la bonne. */

body .contact-list-search__input {
  font-family: var(--texte) !important;
  min-height: var(--tactile);
  font-size: 15px;
  color: var(--encre);
  background: transparent;
  border: 0;
  outline: none;
}

.contact-list-search__input::placeholder {
  color: var(--gris);
  opacity: 1;
}

.contact-list-search__icon {
  color: var(--gris);
}

.contact-list-search__cancel {
  color: var(--accent-texte);
  font-weight: 600;
  min-height: var(--tactile);
  display: inline-flex;
  align-items: center;
}

/* Carte de mise en avant (boost, publicité interne).
   Elle vit à l'intérieur de `.csms-connections-item` (padding 0 15px) :
   pas de marge latérale, sinon le retrait est doublé. */
.feature-card {
  background-color: var(--surface);
  border-radius: var(--rayon-sm);
  padding: 12px 14px;
  margin: 6px 0;
  min-height: var(--tactile);
}

.feature-card__title {
  font-family: var(--titre);
  font-size: 17px;
  color: var(--encre);
}


/* --------------------------------------------------------------------------
   9. BOUTONS
   Le site utilise des boutons pilule (`border-radius:999px`). Le bouton
   principal est JAUNE de marque, texte encre gras — comme `.smk-btn`.
   CONTRASTE — REVISION DU 07/10/2026 (bascule de charte). Les notes des 06 et
   07/10 qui comparaient du texte blanc à un fond violet sont caduques :
   la charte pose désormais du texte ENCRE sur le jaune `--accent-appui`
   (11,45:1), et `--accent` (#FFC629) ne sert plus que de bordure, de halo de
   mise au point, d'aplat SANS texte ou de texte sur fond sombre.

   HAUTEUR. Ramenee de 52 a 44 px le 06/10/2026 : la charte pose `--cible: 44px`
   et le web s'y tient (`.mainBtn.active` mesure 230 x 44). Voir §29.1.
   -------------------------------------------------------------------------- */
body .button {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 100%;
  max-width: 385px;
  min-height: var(--cible);
  height: auto;
  margin: 0 auto;
  /* 13 px et non 14 : la hauteur de ligne du libelle mesure 17,59 px, donc
     17,59 + 2 x 13 = 43,59 -> 44 px rendus, exactement la cible de la charte
     (mesure web : `.mainBtn.active` 230 x 44). Avec 14 px la boite tombait a
     45,59 -> 46 px. L'ecart de 1 px de marge interne est invisible ; l'ecart
     de 2 px de hauteur, lui, se voit a cote du web. */
  padding: 13px 24px;
  border: 0;
  border-radius: var(--rayon-pilule);
  background-color: var(--accent-appui) !important;
  color:var(--encre);
  font-family: var(--texte) !important;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: .01em;
  box-shadow: var(--ombre-accent);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.button::before {
  border-radius: var(--rayon-pilule);
}

.button:active {
  transform: translateY(2px);
}

/* Bouton principal. La spécificité `body .button.button--primary` (0,2,1)
   bat le `.button.button--primary` (0,2,0) posé en <style> dans index.php. */
body .button.button--primary {
  background-color: var(--accent-appui) !important;
  color:var(--encre)!important;
  box-shadow: var(--ombre-accent);
}

.button__content {
  display: flex;
  align-items: center;
  justify-content: center;
}

.button__text {
  font-family: var(--texte) !important;
  font-weight: 600;
  color: inherit;
}

.button__loader {
  color: inherit;
}

/* Bouton secondaire « contour » (achat de crédits, actions facultatives). */
body .button.button--stroke {
  background-color: transparent !important;
  border: 2px solid var(--accent) !important;
  color: var(--accent-texte) !important;
  box-shadow: none !important;
}

body .button.button--stroke .button__text {
  color: inherit !important;
  font-weight: 700;
}

/* Bouton texte (fermeture de modale). On ne force ni fond ni couleur :
   il est posé tantôt sur fond clair, tantôt sur fond sombre. */
body .button.button-clear {
  background-color: transparent !important;
  border: 0;
  box-shadow: none !important;
  min-height: var(--tactile);
}

/* ÉTAT DÉSACTIVÉ — placé APRÈS les variantes et à spécificité (0,3,1) :
   sans cela, le fond `!important` de `.button--primary` rendrait un bouton
   désactivé visuellement actif. */
body .button:disabled,
body .button.disabled,
body .button.button--primary:disabled,
body .button.button--primary.disabled,
body .button.button--stroke:disabled,
body .button.button--stroke.disabled {
  background-color: var(--trait) !important;
  border-color: transparent !important;
  color: var(--gris) !important;
  box-shadow: none !important;
  opacity: 1;
}

body .button:disabled .button__text,
body .button.disabled .button__text {
  color: var(--gris) !important;
}

.button-block {
  border-radius: var(--rayon-pilule);
  min-height: var(--tactile);
}

/* Bouton texte secondaire. */
.inline-button {
  min-height: var(--tactile);
  padding: 12px 0;
  font-family: var(--texte);
  font-size: 15px;
  font-weight: 600;
  color: var(--gris);
  transition: opacity var(--t-court) var(--courbe);
}

.inline-button:active {
  opacity: .65;
}

body .inline-button__text {
  font-family: var(--texte) !important;
  font-weight: 600;
}

.inline-button--primary,
body .inline-button--primary {
  color: var(--accent-texte);
}

.inline-button--sm {
  font-size: 14px;
}

/* Boutons utilitaires de style.css (`.u-btn`, `.u-btn--danger`). */
body .u-btn {
  min-height: var(--tactile);
  padding: 10px 16px;
  border: 0;
  border-radius: var(--rayon-pilule);
  background-color: var(--accent-appui) !important;
  color:var(--encre);
  font-family: var(--texte) !important;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .01em;
  box-shadow: var(--ombre-accent);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.u-btn:active {
  transform: translateY(2px);
}

body .u-btn.u-btn--danger {
  background-color: var(--like);
  box-shadow: var(--ombre-like);
}

/* Anciens boutons (`.btn`, `.btn-primary`) : ramenés sur la marque. */
.btn {
  min-height: var(--tactile);
  border-radius: var(--rayon-pilule);
  font-family: var(--texte);
  font-weight: 600;
}

body .btn.btn-primary {
  background-color: var(--accent-appui) !important;
  color:var(--encre)!important;
  box-shadow: var(--ombre-accent);
}

/* Actions rondes de la carte « Rencontres ». */
.profile-action-button {
  min-width: 65px;
  min-height: 65px;
  border: 1px solid var(--trait);
  border-radius: var(--rayon-pilule);
  background: var(--blanc);
  box-shadow: var(--ombre-2);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.profile-action-button:active {
  transform: translateY(2px);
}

/* Boutons de la modale « C'est un match ». */
.promo-match-button {
  min-height: var(--tactile);
  border-radius: var(--rayon-sm);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.promo-match-button:active {
  transform: scale(.95);
}

.promo-match .promo-match-button .promo-match-button__label {
  font-family: var(--texte);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--gris);
}

/* Bouton d'envoi du chat. */
body .chat-send {
  font-family: var(--texte) !important;
  font-weight: 700;
  color: var(--accent-texte) !important;
  min-height: var(--tactile);
  display: inline-flex;
  align-items: center;
  transition: opacity var(--t-court) var(--courbe);
}

.chat-send:active {
  opacity: .6;
}


/* --------------------------------------------------------------------------
   10. FORMULAIRES
   Le site : champs à rayon `--rayon-sm`, bordure `--trait`, focus bleu accent.
   -------------------------------------------------------------------------- */
.text-field,
.list-item-form,
.reel-form {
  border-bottom-color: var(--trait);
}

.text-field__input,
body .text-field__input {
  min-height: var(--tactile);
  padding: 12px 14px;
  border: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
  background-color: var(--blanc);
  color: var(--encre);
  font-family: var(--texte);
  font-size: 16px;
}

.text-field__input:focus,
body .text-field__input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(255, 198, 41, .14);
  outline: none;
}

/* Libellés posés à gauche dans les listes de formulaire. */
.list-view .list-item-form > label,
.list-view .list-item-form > input,
.list-view .list-item-form > select {
  font-family: var(--texte);
  color: var(--encre);
}

.list-view .list-item-form > label {
  font-weight: 600;
}

.list-view .list-item-form > input,
.list-view .list-item-form > select {
  min-height: var(--tactile);
}

/* Écran de connexion. */
.login-form .login-input {
  min-height: var(--tactile);
  padding: 10px 14px;
  border: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
  background: var(--blanc);
  color: var(--encre);
  font-family: var(--texte);
  font-size: 16px;
}

.login-form .login-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(255, 198, 41, .14);
  outline: none;
}

.login-form .login-btn {
  min-height: var(--cible);   /* 44 px — charte, voir §29.1 */
  border: 0;
  border-radius: var(--rayon-pilule);
  background: var(--accent-appui) !important;
  color:var(--encre)!important;
  box-shadow: var(--ombre-accent);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.login-form .login-btn:active {
  transform: translateY(2px);
}

body .login-btn.active {
  background: var(--accent-fonce) !important;
  color:var(--encre)!important;
}

.login-form .login-btn span {
  font-family: var(--texte);
  font-weight: 600;
}

/* Champ de saisie de crédits / de lien. */
.share-copy-fallback {
  font-family: var(--titre);
  color: var(--encre);
  border: 1px solid var(--trait) !important;
  border-radius: var(--rayon-sm);
  background: var(--blanc);
  text-align: center;
  outline: none;
}

.share-copy-fallback:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 4px rgba(255, 198, 41, .14);
}

/* Interrupteurs et curseurs. */
.toggle .track {
  border-radius: var(--rayon-pilule);
  background-color: var(--trait);
}

.toggle .handle {
  border-radius: var(--rayon-pilule);
  box-shadow: var(--ombre-1);
}

body .toggle input:checked + .track {
  background-color: var(--accent);
}

.range .track {
  border-radius: var(--rayon-pilule);
}

.range .handle {
  border-radius: var(--rayon-pilule);
}

/* Éléments de liste Ionic : bordures aux couleurs du site uniquement
   (pas de fond forcé : certaines listes sont volontairement sombres). */
.item {
  border-color: var(--trait);
  color: var(--encre);
}

body .item-divider {
  font-family: var(--texte) !important;
  font-weight: 600;
  color: var(--gris);
  background-color: var(--surface);
  border-color: var(--trait);
}

body .item span {
  font-family: var(--texte) !important;
}

.item-toggle {
  border-color: var(--trait);
}


/* --------------------------------------------------------------------------
   11. MESSAGERIE
   -------------------------------------------------------------------------- */
.chat-v2__messages {
  background-color: var(--blanc);
}

.chat-message {
  margin-bottom: 6px;
}

.chat-message__text {
  font-family: var(--texte);
  font-size: 15.5px;
  line-height: 1.45;
  padding: 10px 14px;
  border-radius: 18px;
  border-bottom-left-radius: 18px;
  border-bottom-right-radius: 18px;
  box-shadow: var(--ombre-1);
  max-width: 80%;
  overflow-wrap: break-word;
  word-wrap: break-word;
}

/* Reçu : surface chaude, texte encre (16:1). */
.chat-message--grey .chat-message__text {
  background-color: var(--surface);
  color: var(--encre);
  border: 1px solid var(--trait);
}

/* Envoyé : jaune de marque avec un texte encre, sur `--accent-appui` (11,45:1).
   On n'utilise pas le jeton de marque nu ici : ce fond porte du texte courant
   à lire, il lui faut donc le jeton d'appui, dont le contraste est de 11,45:1
   avec l'encre. */
.chat-message--blue .chat-message__text {
  background-color: var(--accent-appui);
  color:var(--encre);
  box-shadow: 0 4px 14px rgba(122, 90, 0, .24);
}

.chat-message__status {
  font-family: var(--texte);
  color: var(--gris);
}

/* Zone de saisie. */
.chat-input {
  background-color: var(--blanc);
  border-top: 1px solid var(--trait);
}

body .chat-input__textarea,
.chat-input__textarea {
  min-height: var(--tactile);
  border: 1px solid var(--trait) !important;
  border-radius: var(--rayon-pilule);
  background-color: var(--surface);
  color: var(--encre);
  font-family: var(--texte) !important;
  font-size: 16px;
  padding: 12px 16px !important;
  outline: none;
}

.chat-input__textarea:focus {
  border-color: var(--accent) !important;
  background-color: var(--blanc);
}

body .chat-input__textarea::placeholder {
  color: var(--gris);
}

.chat-input__label {
  color: var(--gris);
}

/* Raccourcis de la barre d'envoi : 44 px garantis. */
.chat-switchers__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: var(--tactile);
  height: var(--tactile);
  min-width: var(--tactile);
  min-height: var(--tactile);
  padding: 5px;
  border-radius: var(--rayon-pilule);
  color: var(--gris) !important;
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.chat-switchers__item.is-active,
body .chat-switchers__item.is-active {
  color: var(--accent-texte) !important;
}

.chat-switchers__item:active {
  transform: scale(.9);
}

.chat-switchers__item.is-disabled {
  opacity: .4 !important;
}

/* Brise-glace. */
.ice-breaker__text {
  font-family: var(--texte);
  color: var(--gris);
  background-color: var(--surface);
  border-radius: var(--rayon-sm);
  padding: 10px 14px;
}


/* --------------------------------------------------------------------------
   12. MENU LATÉRAL
   -------------------------------------------------------------------------- */
.menu-navigation {
  background-color: var(--encre);
  font-family: var(--texte);
}

.menu-navigation-item {
  min-height: var(--tactile);
  padding: 10px 6px;
  border-radius: var(--rayon-sm);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.menu-navigation-item:active {
  transform: scale(.96);
  opacity: .85;
}

.menu-navigation-item__name {
  font-family: var(--texte);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  color: #fff;
}

.menu-navigation-item__counter {
  background: var(--like);
  color: #fff;
}

.menu-navigation-item__avatar .brick__image {
  border-color: var(--like);
}

/* Bloc des soldes (premium / popularité / crédits). */
.menu-payment {
  min-height: var(--tactile);
  font-family: var(--texte);
}

.menu-payment + .menu-payment {
  border-top: 1px solid rgba(255, 255, 255, .16);
}

.menu-payment__name {
  font-family: var(--texte);
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, .78);
}

.menu-payment__value {
  font-family: var(--titre);
  color: #fff;
}

.menu-payment__icon {
  color: #fff;
}


/* --------------------------------------------------------------------------
   13. PROFIL
   -------------------------------------------------------------------------- */
.own-profile__username {
  font-family: var(--titre);
  font-size: 24px;
  color: var(--encre);
}

.own-profile__payments {
  background-color: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  padding: 16px;
}

.own-profile__payments-item {
  min-height: var(--tactile);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

body .own-profile__payments-label {
  font-family: var(--texte) !important;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gris);
}

body .own-profile__payments-value {
  font-family: var(--texte) !important;
  font-size: 20px;
  font-weight: 700;
  color: var(--encre);
}

/* Lignes « sélecteur » du profil : réglées comme des cartes discrètes. */
.selector {
  min-height: var(--tactile);
  padding: 12px 16px;
  background-color: var(--blanc);
  border-bottom: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
  margin-bottom: 8px;
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.selector:active {
  transform: translateY(1px);
  opacity: .85;
}

.selector__icon {
  color: var(--accent-texte);
  font-family: var(--texte);
  font-weight: 700;
}

/* Bloc d'informations du profil consulté. */
.profile-info__section {
  border-bottom: 1px solid var(--trait);
}

body .profile-info__content {
  font-family: var(--texte) !important;
  font-size: 15px;
  line-height: 1.55;
  color: var(--gris);
}

.profile-title__statuses,
.profile-actions__item {
  min-height: var(--tactile);
}

/* Actions rapides sous la photo de profil. */
.profile-action {
  border-radius: var(--rayon-pilule);
  transition: transform var(--t-court) var(--courbe),
              opacity   var(--t-court) var(--courbe);
}

.profile-action:active {
  transform: scale(.94);
}

/* Portefeuille. */
.wallet-transaction {
  border-bottom: 1px solid var(--trait);
  min-height: var(--tactile);
}

.wallet-t-details {
  font-family: var(--texte);
  color: var(--gris);
  font-size: 13px;
}


/* --------------------------------------------------------------------------
   14. CARTE « RENCONTRES » (balayage)
   -------------------------------------------------------------------------- */
.encounters-card {
  /* `border-radius` est posé en style inline dans explore.html
     (`#discoverGame` → 17px) : sans `!important`, la surcharge serait ignorée. */
  border-radius: var(--rayon) !important;
  overflow: hidden;
  background-color: var(--surface);
  box-shadow: var(--ombre-2);
}

.encounters-card__info {
  background-color: rgba(255, 255, 255, .94);
  border-radius: var(--rayon-sm);
  box-shadow: var(--ombre-1);
  padding: 10px 14px;
  max-width: 100%;
  box-sizing: border-box;
}

.encounters-card__announce {
  color: var(--gris);
}

/* Dégradé de lisibilité sous le nom : `background-image` n'est pas un filtre,
   il est donc autorisé. Aucun `filter:` n'est utilisé ici. */
.encounters-card__floating {
  background-image: linear-gradient(to top, rgba(20, 23, 26, .55), rgba(20, 23, 26, 0));
}

body .profile-user-info__meta,
body .profile-user-info__age {
  font-family: var(--texte) !important;
  color: var(--gris);
}


/* --------------------------------------------------------------------------
   15. MODALES ET PANNEAUX
   -------------------------------------------------------------------------- */
.modal,
.overlay-page {
  font-family: var(--texte);
}

/* Le site : cartes à grand rayon, ombre douce, filet `--trait`. */
.floating-action .cta-box,
.promo-match .cta-box {
  background-color: var(--blanc);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  box-shadow: var(--ombre-2);
  padding: 20px 18px;
  box-sizing: border-box;
  max-width: 100%;
}

body .cta-box__content {
  font-family: var(--texte) !important;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--gris);
}

/* Panneau de stickers / cadeaux. */
.stickers {
  background-color: var(--surface) !important;
}

/* Modale d'achat (fond sombre volontaire) : on garde le fond sombre mais on
   l'aligne sur l'encre du site au lieu du noir pur. */
.mi-violetita {
  background-color: var(--encre) !important;
}

body .positive-bg {
  background: var(--accent) !important;
}

/* Bandeau promotionnel de bas d'écran. */
.floating-action {
  background-color: var(--blanc);
  border-top: 1px solid var(--trait);
  box-shadow: 0 -4px 14px rgba(20, 23, 26, .06);
}

/* Bandeau « Rencontres à proximité ». */
.stream-notice {
  background-color: var(--surface);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
}

.stream-notice__title {
  font-family: var(--titre);
  font-size: 17px;
  color: var(--encre);
}

.stream-notice__content {
  font-family: var(--texte);
  color: var(--gris);
}


/* --------------------------------------------------------------------------
   16. CHARGEMENTS ET MICRO-DÉTAILS
   Les points de chargement passent au bleu de la marque.
   (`.loader`, `.small` et `.grey` sont portés par le MÊME élément :
   `.loader.grey .dot` (0,3,0) bat `.grey .dot` (0,2,0) et son !important.)
   -------------------------------------------------------------------------- */
.loader.grey .dot,
.loader .dot {
  background-color: var(--accent) !important;
}

.loader02 {
  color: var(--accent);
}

.skeleton-line {
  background-color: var(--surface);
  border-radius: var(--rayon-sm);
}

.section-footer-effect {
  background-image: linear-gradient(to top, rgba(255, 255, 255, .95), rgba(255, 255, 255, 0));
}

.multimedia,
.multimedia__image {
  border-radius: var(--rayon-sm);
}

.profileP {
  border-radius: var(--rayon-sm);
}


/* --------------------------------------------------------------------------
   17. ACCESSIBILITÉ — CIBLES TACTILES ET FOCUS
   Chaque composant cliquable reçoit sa hauteur minimale dans SA section
   (boutons 52 px, lignes de conversation 64 px, onglets 50 px, icônes de
   navigation et champs 44 px…). Les redéclarer ici, plus bas, écraserait les
   valeurs plus généreuses (même spécificité : la dernière règle gagne).
   Ne restent donc que les éléments non traités ailleurs.
   -------------------------------------------------------------------------- */
.item,
.item-toggle,
.contact-list-item,
.chat-v2__status {
  min-height: var(--tactile);
}

/* Contour de focus visible au clavier uniquement (pas de contour parasite au
   toucher). Le bleu accent est réservé aux éléments décoratifs : ici le
   contour est un repère, pas du texte. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.js-touchable:focus-visible,
.js-goto:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--rayon-sm);
}

/* Évite le halo bleu par défaut de WebKit sur les éléments non focusables. */
* {
  -webkit-tap-highlight-color: rgba(255, 198, 41, .18);
}


/* --------------------------------------------------------------------------
   18. PAS DE DÉFILEMENT HORIZONTAL
   Aucune règle de ce fichier n'utilise `100vw`. Trois calculs en `100vw`
   hérités des feuilles d'origine sont en plus neutralisés ici : ils portent
   sur des sélecteurs réellement présents dans templates/mobile/.
   -------------------------------------------------------------------------- */
html,
body {
  max-width: 100%;
  overflow-x: hidden;
}

img,
video,
canvas,
iframe {
  max-width: 100%;
}

/* Largeur de la barre de navigation : `100vw` d'origine déborde dès qu'une
   barre de défilement est présente. */
.navigation-bar {
  width: 100% !important;
  max-width: 100% !important;
}

/* `max-width: calc(100vw - 160px)` d'origine : remplacé par un calcul sûr. */
.chat-v2-name {
  max-width: 100% !important;
}

/* `height: 100vw` d'origine : remplacé par un carré sans unité de viewport. */
.profile-preview__photos {
  height: auto !important;
  aspect-ratio: 1 / 1;
  /* `dvh` et non `vh` : avec la barre d'adresse du navigateur mobile, `vh` se
     rapporte a une fenetre plus haute que la fenetre reellement visible. */
  max-height: 100dvh;
}

.page,
.page-container,
.layout,
.layout__content,
.cta-box,
.cta-box__content,
.encounters-card,
.selector,
.text-field {
  max-width: 100%;
  box-sizing: border-box;
}

/* Les conteneurs à défilement horizontal prévus (listes de stories) gardent
   leur défilement : on ne le supprime que sur l'axe vertical. */
.scroll-horizontal,
.tabs-top .scroll,
.tabs .scroll {
  overflow-x: auto;
  overflow-y: hidden;
}


/* --------------------------------------------------------------------------
   19. MOUVEMENT RÉDUIT
   Le site respecte cette préférence, l'app mobile doit faire de même.
   Les animations sont neutralisées (les classes `vivify` redeviennent visibles
   d'elles-mêmes, leur état final étant l'état naturel de l'élément).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }

  .tabbar,
  .floating-action,
  .tabbar-item,
  .navigation-bar__icon,
  .chat-switchers__item,
  .profile-action,
  .profile-action-button,
  .promo-match-button,
  .selector,
  .csms-connections-item,
  .menu-navigation-item {
    transition: none !important;
  }
}


/* ==========================================================================
   COMPLÉMENT — REELS, STORIES, FIL D'ACTUALITÉ, RENCONTRES, RÉCOMPENSE
   --------------------------------------------------------------------------
   Les sections 1 à 19 ne couvraient pas ces cinq écrans. Toutes les classes
   ci-dessous ont été relevées dans les gabarits réellement servis :

     · templates/mobile/home/reels.html
     · templates/mobile/home/stories.html
     · templates/mobile/home/feed.html  +  requests/feed.php (les cartes du fil
       sont injectées par AJAX dans #feed-content : mobile/js/controllers.js
       appelle `requests/feed.php?action=loadFeed`)
     · templates/mobile/home/explore.html, meet.html, dating.html,
       matches.html, likesme.html, match.html
     · templates/mobile/modals/share.html

   CLASSES VOLONTAIREMENT NON TRAITÉES (déjà couvertes par les sections 1 à
   19, rien n'est dupliqué ici) :
     `.stream-notice`, `.stream-notice__content`, `.stream-notice__title`
     (section 15), `.brick--squared .brick__image` et `.profile-photo`
     (section 7), `.profileP` / `.multimedia__image` (section 16).

   ORDRE DE CHARGEMENT RÉEL (index.php) — la plupart des feuilles de base
   arrivent APRÈS ce fichier, d'où les préfixes `body` et les `!important` :
     style.css → smakoo20.css → smakoo.css → smakoo-theme.css → i.css →
     themes/default/css/crossplatform.css → <style> inline d'index.php →
     css/live.css → thème des plugins (vendor/swiper.css pour Reels,
     vendor/feed.css pour le fil, vendor/live.css pour le direct) → twigo.css.

   INTERDITS RESPECTÉS
     · aucun `filter:` ajouté (les deux `filter: blur(18px)` du voile premium
       de `vendor/feed.css` sont conservés : ils portent la fonctionnalité
       « publication payante ») ;
     · aucun `100vw` écrit ; celui de `.detail .video-item` (vendor/swiper.css)
       est neutralisé en §20.1 ;
     · seules `transform` et `opacity` sont animées ici.
   ========================================================================== */


/* --------------------------------------------------------------------------
   20. REELS  (home/reels.html — écran noir plein écran)
   Le gabarit pose ces textes sur des voiles sombres : on garde les textes
   clairs, `--encre` ne serait pas lisible ici.
   -------------------------------------------------------------------------- */

/* 20.1 — Pleine largeur sans `100vw`.
   `vendor/swiper.css` pose `.detail .container, .detail .video-item
   { width: 100vw; max-width: 540px }` : le `100vw` est remplacé par `100%`,
   le plafond de 540 px du plugin est conservé. Quatrième calcul en `100vw`
   neutralisé, comme les trois de la §18. */
body .detail .container,
body .detail .video-item {
  width: 100%;
}

/* 20.2 — Bandeau d'identité du reel (avatar, nom, légende). */
body .video-wraper .info-wraper .user-info .avator {
  width: var(--tactile);
  height: var(--tactile);
  border-color: rgba(255, 255, 255, .28);
}

body .video-wraper .info-wraper .user-info .name {
  font-family: var(--titre) !important;
  font-size: 16px;
  font-weight: 400;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

body .video-wraper .info-wraper .video-info {
  font-family: var(--texte) !important;
  font-size: 15px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .94);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* 20.3 — Voiles de guidage (import, reel privé, achat). Le titre devient un
   bouton pilule : 44 px de haut et un fond translucide pour tenir le 4,5:1
   sur la vidéo. */
body .video-wraper .mask .guide-info .title {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
  margin-top: 14px;
  padding: 10px 18px;
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: var(--rayon-pilule);
  background-color: rgba(20, 23, 26, .55);
  font-family: var(--titre) !important;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.25;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .65);
}

body .video-wraper .mask .guide-info p,
body .video-wraper .mask .guide-info .content {
  font-family: var(--texte) !important;
  font-size: 14px;
  color: rgba(255, 255, 255, .92);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .65);
}

/* 20.4 — Colonne d'actions (like, prix, partage) : les SVG du gabarit font
   32 px, la cible tactile doit en faire 44. */
body .video-wraper .side-bar svg {
  width: var(--tactile);
  height: var(--tactile);
  margin-top: 14px;
}

/* 20.5 — Légende et prix éditables : le plugin impose la police Rubik. */
body .video-wraper .reel-mobile-textarea,
body .video-wraper .input-reel-caption {
  min-height: var(--tactile);
  padding: 10px 14px;
  border: 1px solid rgba(255, 255, 255, .24);
  border-radius: var(--rayon-sm);
  background-color: rgba(255, 255, 255, .08);
  font-family: var(--texte) !important;
  font-size: 16px;
  line-height: 1.4;
  color: #fff;
}

body .video-wraper .reel-mobile-textarea::placeholder,
body .video-wraper .input-reel-caption::placeholder {
  color: rgba(255, 255, 255, .7);
  opacity: 1;
}

/* Champ « prix » et case « reel privé ». Ionic masque la case
   (`i.css` : `.toggle input { display: none }`) : la cible réelle est le
   libellé `.reel-track`, traité en 20.6. Le style est posé pour les deux, le
   gabarit pouvant afficher l'un ou l'autre. */
body .video-wraper .input-reel-price,
body .video-wraper .reel-mobile-private-input {
  min-height: var(--tactile);
  border: 1px solid rgba(255, 255, 255, .3) !important;
  border-radius: var(--rayon-sm);
  background-color: rgba(255, 255, 255, .1);
  font-family: var(--texte) !important;
  font-size: 16px;
  color: #fff;
}

/* 20.6 — Interrupteur « reel privé » : le plugin force #ffbf00 en !important,
   et le gabarit pose `background: none` en style inline sur le curseur. Le
   libellé passe à 44 px sans déplacer le curseur (padding 5 px d'origine
   conservé, `align-items: center` recentre la piste). */
body .reel-track.toggle-assertive .track {
  border: 1px solid rgba(255, 255, 255, .3) !important;
  background-color: rgba(255, 255, 255, .12) !important;
}

body .reel-track.toggle-assertive input:checked + .track {
  border-color: var(--accent) !important;
  background-color: var(--accent) !important;
}

body .reel-track.toggle-assertive input:checked + .track .handle {
  background-color: #fff;
}

body .reel-track.toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
}

/* 20.7 — Onglets « Récents / Tendance » posés sur la vidéo : la barre fait
   37 px dans le plugin. */
body .swipe-top-bar {
  height: auto;
  min-height: var(--tactile);
}

body .swipe-top-bar #discover-toggles > button {
  min-height: var(--tactile);
  padding: 10px 8px;
  border: 0;
  border-radius: var(--rayon-pilule);
  background-color: transparent;
  font-family: var(--texte);
  font-size: 14px;
  font-weight: 600;
  color: rgba(255, 255, 255, .78);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
  transition: background-color var(--t-court) var(--courbe),
              color             var(--t-court) var(--courbe);
}

body .swipe-top-bar #discover-toggles > button.reel-tab-selected {
  background-color: rgba(255, 255, 255, .18);
  color: #fff;
}

/* 20.8 — Bouton d'import. `@keyframes Gradient` (crossplatform.css) anime la
   `background-position` : c'est la seule animation de ces écrans qui ne passe
   ni par `transform` ni par `opacity`, elle est donc neutralisée. Le fond
   utilise `--accent-texte` (blanc sur #0B6FA8 = 5,4:1) car le libellé fait
   13 px, trop petit pour se contenter du 2,8:1 de `--accent` (voir la note de
   la §9). */
body .upload-reel .btn-upload-reel,
body .upload-reel .btn-upload-reel-complete {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
  padding: 0 16px;
  border: 0;
  border-radius: var(--rayon-pilule);
  background-color: var(--accent-appui);
  background-image: none;
  font-family: var(--texte) !important;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .05em;
  color:var(--encre);
  box-shadow: 0 8px 22px rgba(122, 90, 0, .34);
  animation: none !important;
}


/* --------------------------------------------------------------------------
   21. STORIES ET DIRECT  (home/stories.html)
   Bases : `themes/default/css/crossplatform.css` (`.story-preview*`,
   `.stories-feed*`) et `themes/default/css/vendor/live.css` (`.stream-*`,
   `.user-card*`), complétées par `css/live.css`.
   -------------------------------------------------------------------------- */

/* 21.1 — Vignette de story : rayon de carte du site. Les deux couches
   `.story-preview-background` / `.story-preview-avatar` portent
   `.profile-photo` (rond, §7) et sont rognées par l'`overflow: hidden` de
   `.story-preview` : rien d'autre à faire de ce côté. */
body .story-preview {
  border-radius: var(--rayon-sm);
}

body .story-preview .story-preview-name {
  font-family: var(--texte);
  font-size: 12.5px;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* 21.2 — Bandeau de stories : aucune sortie d'écran. La hauteur est posée en
   style inline par le gabarit (`height: 104px`) et les vignettes sont en
   `flex-wrap: wrap` : on ne touche pas à la mise en page, seulement aux
   limites. */
body .stories-feed,
body .stories-feed-layout,
body .stories-discover {
  max-width: 100%;
}

/* 21.3 — Cartes de direct (même écran, section visible sous les stories). */
body .stream-page__content,
body .stream-list__content,
body .stream-slider__scroll {
  max-width: 100%;
}

body .stream-card,
body .user-card {
  border-radius: var(--rayon-sm);
}

body .user-card__photo {
  background-color: var(--surface);
}

body .user-card-caption__name,
body .user-card-caption__account {
  font-family: var(--texte);
  font-weight: 600;
}

body .stream-author__name {
  font-family: var(--titre) !important;
  font-size: 17px;
  color: #fff;
}

/* 21.4 — Champ de saisie du chat du direct. `css/live.css` force
   `background: rgba(225,225,225,.15) !important` sur la pastille et
   `color: #fff !important` sur le texte : le champ reste donc translucide sur
   le canvas noir, et NON blanc — le `background: #fff` (non prioritaire) que
   stories.html pose sur `.stream-comment-field` est écrasé. On garde le texte
   clair et on ne corrige que le placeholder, resté en #767676 (2,7:1 sur la
   pastille). */
body .stream-comment-field .text-field__input {
  min-height: var(--tactile);
  border-radius: var(--rayon-sm);
  font-family: var(--texte) !important;
  color: #fff !important;
}

body .stream-comment-field .text-field__input::placeholder {
  color: rgba(255, 255, 255, .72);
  opacity: 1;
}

/* 21.5 — Boutons « Terminer » et « Fermer » du direct : 19 px et 30 px dans le
   gabarit (styles inline). `min-width`/`min-height` l'emportent sur
   `width`/`height`. */
body .stream-data__item {
  border-radius: var(--rayon-sm);
}

body #endStream,
body #streamClose {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
}

/* Bouton d'envoi du chat du direct : l'icône ne fait que 24 px. */
body .stream-comment-field__send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  color: var(--accent);
}

/* 21.6 — État vide du direct : `.credits-section` est posé avec
   `min-width: 360px` dans `style.css`, ce qui déborde sur un écran de 320 px. */
body .credits-section {
  min-width: 0;
}

body .credits-section h1 {
  font-family: var(--titre) !important;
  color: var(--encre);
}

body .credits-section h4 {
  font-family: var(--texte) !important;
  font-size: 14px;
  font-weight: 400;
  color: var(--gris);
}


/* --------------------------------------------------------------------------
   22. FIL D'ACTUALITÉ  (home/feed.html, cartes de requests/feed.php)
   Base : `themes/default/css/vendor/feed.css` (feuille du plugin fgfeed).
   -------------------------------------------------------------------------- */

/* 22.1 — La carte ne doit jamais dépasser l'écran. `feed.css` pose
   `width: calc(100% + 30px)` entre 481 et 1198 px, et `.insta-imgs-slider`
   mesure 500 px de haut avec une image en `background-size: cover`. */
body .instagram-sec {
  max-width: 100%;
  border-radius: var(--rayon-sm);
}

body .instagram-sec .insta-imgs-slider,
body .instagram-sec .insta-imgs-slider .insta-imgs-slide {
  max-width: 100%;
}

body .instagram-sec .insta-sec-heading,
body .instagram-sec .insta-sec-footer {
  background-color: var(--blanc);
}

/* 22.2 — En-tête : nom et lieu en Inter, couleurs du site. */
body .instagram-sec .insta-sec-heading .insta-sec-head-content .insta-sec-head-inner h6 {
  font-family: var(--texte) !important;
  font-size: 15px;
  font-weight: 700;
  color: var(--encre);
}

body .instagram-sec .insta-sec-heading .insta-sec-head-content .insta-sec-head-inner p {
  font-family: var(--texte) !important;
  font-size: 12px;
  color: var(--gris);
}

/* 22.3 — Bouton « ⋯ » de la carte : 28 px dans `feed.css`, 32 px en !important
   sous 480 px. `min-width`/`min-height` l'emportent sur `width`/`height`. */
body .instagram-sec .insta-sec-heading .moreDropdown {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  border-radius: var(--rayon-pilule);
}

/* Le lien qui entoure la photo de profil de la publication ne fait que 36 px.
   On le porte à 44 px en compensant par une marge négative : l'en-tête ne
   bouge pas (`.insta-sec-head-inner` est en `calc(100% - 36px)` et passerait
   sinon à la ligne, le parent étant en `flex-wrap: wrap`). */
body .instagram-sec .insta-sec-heading .insta-sec-head-content > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  margin: -4px;
  padding: 4px;
  border-radius: var(--rayon-pilule);
}

/* 22.4 — Actions de la publication. Les gestionnaires `onclick` de
   `requests/feed.php` sont posés sur les SVG eux-mêmes
   (`<svg class="unlike" onclick="likeFeed(...)">`, `<svg class="save save-<id>"
   onclick="postFav(...)">`) : agrandir le conteneur ne suffit pas, c'est la
   taille du SVG qui fait la cible — ils passent donc de 22–26 px à 44 px. */
body .instagram-sec .insta-sec-footer .insta-footer-link ul li > div {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  border-radius: var(--rayon-pilule);
}

body .instagram-sec .insta-sec-footer .insta-footer-link ul li > div svg,
body .instagram-sec .insta-sec-footer .insta-footer-link button svg {
  width: var(--tactile);
  height: var(--tactile);
}

body .instagram-sec .insta-sec-footer .insta-footer-link button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  padding: 0;
  border: 0;
  background-color: transparent;
}

body .comment-like-wrap .comment-wrap .comment-content p,
body .comment-like-wrap .comment-wrap .comment-content p .commenter-name {
  font-family: var(--texte);
  color: var(--encre);
}

/* 22.5 — Voile « publication premium ». Le `filter: blur(18px)` de
   `feed.css` porte la fonctionnalité payante : il est conservé tel quel. */
body .instagram-sec.premium-post .premium-post-label {
  border-radius: var(--rayon-sm);
  background-color: rgba(255, 255, 255, .93);
}

body .instagram-sec.premium-post .premium-post-label h6 {
  font-family: var(--titre) !important;
  font-weight: 400;
  color: var(--gris);
}

body .instagram-sec.premium-post .premium-post-label p {
  font-family: var(--texte) !important;
  font-weight: 500;
  color: var(--encre);
}

/* 22.6 — Toast « Story saved » (`.our-collection`). Le libellé était en
   #262626 sur #FEF0F2 : on garde l'encre du site sur la surface rosée du jeu
   de jetons. (`.our-collection button` est stylé dans `vendor/feed.css` mais
   aucun `<button>` n'est produit par `requests/feed.php`, qui ne remplit que
   `.oc-content` : règle volontairement non reprise ici.) */
body .instagram-sec .insta-sec-footer-wrap .our-collection {
  background-color: var(--surface-2);
  border-radius: var(--rayon-sm);
}

body .instagram-sec .insta-sec-footer-wrap .our-collection .oc-content img {
  border-radius: var(--rayon-sm);
}

body .instagram-sec .insta-sec-footer-wrap .our-collection .oc-content span {
  font-family: var(--texte);
  color: var(--encre);
}

/* 22.7 — Panneau de commentaires plein écran. */
body .insta-comments .insta-comments-inner .comments-header {
  background-color: var(--blanc);
  border-bottom: 1px solid var(--trait);
}

/* Le lien de l'avatar d'un commentaire fait 40 px : porté à 44 px, encombrement
   inchangé (`.comment-content` est en `calc(100% - 40px)`). */
body .comment-like-wrap .comment-wrap .comment-img {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  margin: -2px;
  padding: 2px;
  border-radius: var(--rayon-pilule);
}

body .insta-comments .insta-comments-inner .comments-header span {
  font-family: var(--titre) !important;
  color: var(--encre);
}

body .insta-comments .insta-comments-inner .comment-footer {
  background-color: var(--surface);
  border-top: 1px solid var(--trait);
}

body .insta-comments .insta-comments-inner .comment-footer form textarea {
  min-height: var(--tactile);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-sm);
  background-color: var(--blanc);
  font-family: var(--texte) !important;
  font-size: 16px;
  color: var(--encre);
}

/* Le bouton d'envoi reprend le rose foncé du jeu de jetons : #F96C7C sur
   #FAFAFA ne donne que 2,5:1. */
body .insta-comments .insta-comments-inner .comment-footer form button {
  min-height: var(--tactile);
  border-radius: var(--rayon-sm);
  font-family: var(--texte);
  color: var(--like-fonce);
}


/* --------------------------------------------------------------------------
   23. RENCONTRES, DÉCOUVERTE ET PARTAGE
   (home/explore.html, meet.html, dating.html, matches.html,
   modals/share.html, home/profile.html)
   -------------------------------------------------------------------------- */

/* 23.1 — Bandeau « Rencontres à proximité » (meet.html, dating.html) : la §15
   n'habille que `.floating-action .cta-box` et `.promo-match .cta-box`, le
   cartouche de ce bandeau restait nu. */
body .people-nearby-banner .cta-box {
  max-width: 100%;
  padding: 20px 18px;
  background-color: var(--blanc);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  box-shadow: var(--ombre-2);
}

body .people-nearby-banner .cta-box__content {
  font-family: var(--texte) !important;
  color: var(--gris);
}

/* 23.2 — Carte de découverte. Le fond gris (#f6f6f6) du diaporama devient la
   surface chaude du site. `.encounters-card` lui-même est traité en §14. */
body .slider-gallery {
  max-width: 100%;
  background-color: var(--surface);
}

body .slider-gallery__pages,
body .slider-gallery__page {
  max-width: 100%;
}

/* 23.3 — Grille « Rencontres » (meet.html). `.brick__name_` n'a aucune règle
   dans les feuilles d'origine : le nom hérite donc du #000 de `.brick__name`. */
body .users-folder__item .brick__name {
  color: var(--encre);
}

body .users-folder__item .brick__name_ {
  font-family: var(--titre) !important;
  font-size: 13px;
  color: var(--encre);
}

/* 23.4 — Pastilles « spotlight » (matches, menu, likes, superlikes,
   visiteurs). La cible tactile d'origine (47 px) tient, on aligne surtout la
   forme et la typographie. */
body .spotlight-me {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
  padding: 10px 20px;
  border-radius: var(--rayon-pilule);
  font-family: var(--texte) !important;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  color: #fff;
}

/* 23.5 — Partage externe (modals/share.html). Les icônes font déjà 65 px et le
   libellé hérite d'Inter : on garantit le plancher tactile et l'état appuyé. */
body .external-provider a {
  min-height: var(--tactile);
  border-radius: var(--rayon-sm);
  transition: opacity var(--t-court) var(--courbe);
}

body .external-provider a:active {
  opacity: .72;
}

/* 23.6 — `.own-profile__userpic` (profile.html) n'a pas besoin de règle CSS :
   il est couvert par la §13 (`.own-profile__*`) et par la correction de
   l'arrondi en ligne décrite en §26. */


/* --------------------------------------------------------------------------
   24. MODALE DE RÉCOMPENSE
   (likesme.html, match.html, mylikes.html, matches.html, stories.html,
   meet.html, messaging.html — 12 règles dans css/style.css, aucune dans les
   sections 1 à 19.)
   -------------------------------------------------------------------------- */

/* 24.1 — La carte. `border-radius: 10px` est posé en style inline dans
   matches.html et stories.html : `!important` est nécessaire, comme pour
   `.encounters-card` en §14. `--ombre-3` n'est pas déclaré dans le `:root` de
   la §1 (seuls `--ombre-1`, `--ombre-2`, `--ombre-accent` et `--ombre-like`
   existent) : on utilise `--ombre-2`. */
body .wrapper-reward .modal-reward {
  max-width: 100%;
  border: 1px solid var(--trait);
  border-radius: var(--rayon) !important;
  box-shadow: var(--ombre-2);
}

/* Les deux moitiés de la carte portaient 10 px en dur. */
body .wrapper-reward .modal-reward-top {
  border-top-left-radius: var(--rayon);
  border-top-right-radius: var(--rayon);
}

body .wrapper-reward .modal-reward-bottom {
  border-bottom-left-radius: var(--rayon);
  border-bottom-right-radius: var(--rayon);
}

/* 24.2 — Libellés : Montserrat/Lato d'origine. Le titre est un titre
   (Calistoga), le sous-titre est du texte courant (Inter). La couleur reste
   `inherit` : les variantes colorées du gabarit (`.boostSpotlight`,
   `.boostDiscover`, `.boostRiseUp`) posent un fond sur la carte entière. */
body .wrapper-reward .modal-reward-header {
  font-family: var(--titre) !important;
  font-size: 20px;
  line-height: 1.25;
  color: inherit;
}

body .wrapper-reward .modal-reward-subheader {
  font-family: var(--texte) !important;
  font-size: 14px;
  line-height: 1.45;
  letter-spacing: 0;
  color: inherit;
}

/* 24.3 — L'icône (photo de profil, 120 px en inline) et le bouton d'action.
   `@keyframes tinder-bg` (style.css) anime la `background-position` du bouton :
   seule animation de ces écrans hors `transform`/`opacity`, elle est
   neutralisée. */
body .wrapper-reward .modal-reward-icon {
  max-width: 100%;
  border-radius: var(--rayon-pilule);
}

body .wrapper-reward .modal-reward-btn {
  min-height: var(--tactile);
  border-radius: var(--rayon-pilule);
  animation: none !important;
}

/* Le bouton de fermeture `.klose` ne fait que 25 px. */
body .wrapper-reward .modal-reward-top .klose {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tactile);
  min-height: var(--tactile);
  border-radius: var(--rayon-pilule);
}

/* 24.4 — Contraste des variantes colorées.
   Quatre variantes du gabarit posent le texte en blanc sur un fond moyen ou
   clair, sous le seuil de 4,5:1 : `gradient18` (degrade bleu-violet, magenta
   puis ambre, jusqu'à 1,5:1), `boostDiscover` (#00B697, 2,6:1), `boostSpotlight`
   (#ff661b, 2,6:1) et `boostRiseUp` (#25BA25, 2,6:1). Les fonds sont posés
   par crossplatform.css / style.css, donc intouchables sans casser les autres
   écrans : on interpose un bandeau encre translucide derrière les deux
   libellés. Le blanc repasse au-dessus de 5:1 sur les quatre fonds.
   (Les variantes `gradient32` — meet.html — et le fond `rgba(0,0,0,.4)` de
   stories.html sont déjà sombres : hors périmètre.) */
body .wrapper-reward .modal-reward.gradient18 .modal-reward-header,
body .wrapper-reward .modal-reward.gradient18 .modal-reward-subheader,
body .wrapper-reward .modal-reward.boostDiscover .modal-reward-header,
body .wrapper-reward .modal-reward.boostDiscover .modal-reward-subheader,
body .wrapper-reward .modal-reward.boostSpotlight .modal-reward-header,
body .wrapper-reward .modal-reward.boostSpotlight .modal-reward-subheader,
body .wrapper-reward .modal-reward.boostRiseUp .modal-reward-header,
body .wrapper-reward .modal-reward.boostRiseUp .modal-reward-subheader {
  padding: 10px 14px;
  border-radius: var(--rayon-sm);
  background-color: rgba(20, 23, 26, .55);
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}


/* --------------------------------------------------------------------------
   25. MOUVEMENT RÉDUIT — COMPLÉMENTS
   La §19 coupe déjà toutes les animations via le sélecteur universel. On
   nomme en plus les éléments animés par cette section, pour que la règle
   survive à une réorganisation du fichier.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .btn-upload-reel,
  .btn-upload-reel-complete,
  .video-wraper .side-bar svg,
  .video-wraper .mask .guide-info .title,
  .reel-track.toggle .track,
  .reel-track.toggle .handle,
  .swipe-top-bar #discover-toggles > button,
  .story-preview,
  .story-preview .story-preview-avatar,
  .user-card,
  .stream-card,
  .modal-reward,
  .modal-reward-btn,
  .external-provider a {
    animation: none !important;
    transition: none !important;
  }
}


/* --------------------------------------------------------------------------
   26. ARRONDIS POSÉS EN LIGNE DANS LES GABARITS (modifications assumées)
   Deux arrondis étaient écrits en dur en attribut `style`, donc inaccessibles
   depuis cette feuille. Ils ont été remplacés à la source par les jetons du
   §1 — aucune règle CSS ne peut les reprendre sans `!important` sur un
   attribut `style`, ce qui aurait écrasé tous les autres arrondis en ligne du
   même gabarit :

     · `border-radius: 15px` → `var(--rayon-sm)`
         home/feed.html, home/profile.html, home/matches.html,
         home/stories.html, home/reels.html, home/meet.html, home/explore.html
         (le `.profile-photo` de la barre d'onglets basse)
       + home/reels.html (le bouton caché `#goToMyReels`) ;
     · `border-radius: 70px` → `var(--rayon)`
         home/profile.html (`.own-profile__userpic .brick__image`)
         modals/verification.html (`.brick__image` de la modale).

   Les fichiers .css ne sont pas concernés par ces deux corrections.
   -------------------------------------------------------------------------- */


/* ==========================================================================
   27. CORRECTIONS D'AUDIT DU 04/10/2026
   --------------------------------------------------------------------------
   Audit page par page des écrans mobiles (viewport 390 × 844, session du
   compte de test « Manon », id 6). Chaque correction cite la MESURE qui la
   justifie. Outillage : tests/m-shots.js (mesures navigateur) et
   tools/vision.js (lecture visuelle).

   Avant tout : la CAUSE des incohérences constatées était l'ORDRE DE
   CHARGEMENT de cette feuille. Elle était appelée 6e dans <head>, avant
   i.css (258 Ko), crossplatform.css, live.css, le CSS des plugins et
   scroller.css. À spécificité égale, c'est la dernière qui gagne : le thème ne
   survivait que là où il mettait !important.

   Preuve directe, mesurée avant correction :
     · `body` = Inter 14px   (le thème demandait 16px, i.css imposait 14px) ;
     · `.item-divider` = rgb(0,219,222) cyan alors que la §10 ci-dessus
       écrit `background-color: var(--surface)` ;
     · `.contact-list-search__input::placeholder` = rgb(154,163,171) alors que
       la §11 ci-dessus écrit `color: var(--gris)`.

   Le déplacement du <link> en fin de <head> (mobile/index.php) règle ces
   trois points d'un coup ; les règles de ce §27 couvrent le reste. Les
   sélecteurs sont préfixés par `body` et, quand un style inline doit céder,
   marqués !important (une déclaration !important d'une feuille l'emporte sur
   un attribut `style` non important).
   ========================================================================== */

/* 27.1 — Marqueur : si cette règle perd, c'est que l'ordre de chargement a
   été rebrisé. Elle est donc écrite en !important. */
body {
  font-size: 16px !important;
  -webkit-text-size-adjust: 100% !important;
  text-size-adjust: 100% !important;
}

/* 27.2 — EN-TÊTE : le contenu sortait par le haut de l'écran.
   Mesuré sur /home/explore :
     .navigation-bar__main      (logo)        y = -3,0 px  (hauteur 37)
     .navigation-bar__secondary (icône droite) y = -2,5 px  (44 × 44)
     .navigation-bar__primary   (icône gauche) hauteur 0 px
   Cause : marges négatives en attribut `style` dans les gabarits
   (`margin-top: -8px`, `margin-left: -10px`, `margin-top: -4px`). */
body .navigation-bar {
  min-height: var(--tactile);
  align-items: center;
  padding-top: 0;
  padding-bottom: 0;
}

body .navigation-bar__primary,
body .navigation-bar__main,
body .navigation-bar__secondary {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  align-self: center;
}

body .navigation-bar__primary {
  min-height: var(--tactile);
  margin-left: 0 !important;
}

body .navigation-bar__main {
  margin-left: 0 !important;
}

body .navigation-bar__secondary {
  margin-right: 0 !important;
}

/* 27.3 — DÉCOUVERTE : les boutons d'action étaient coupés par le bord droit.
   Mesuré (viewport 390) :
     svg#icon-floating-yes        left 305 → right 395  (5 px hors écran)
     svg#icon-floating-superlike  left 305 → right 395  (5 px hors écran)
   Cause : `style="position:absolute;right:-25px"` sur #likeBtn et #slikeBtn,
   `left:-35px` sur #nolikeBtn (home/explore.html). On rentre les trois
   pastilles dans l'écran avec une marge de 10 px. */
body #likeBtn,
body #slikeBtn {
  right: 10px !important;
}

body #nolikeBtn {
  right: auto !important;
  left: 10px !important;
}

/* Le badge de quota du Super Like débordait aussi du cercle
   (`right:2px; top:2px` en inline, pastille de 22 px). */
body #slikeBtn > span {
  right: -4px !important;
  top: -4px !important;
}

/* 27.4 — DÉCOUVERTE : bulle « discuter » mesurée à 32 × 32 px (< 44). */
body .profile-action-chat {
  min-width: var(--tactile);
  min-height: var(--tactile);
}

/* 27.5 — BARRE D'ONGLETS.
   a) `.tabbar__items` mesuré : y 795, hauteur 50 → bas = 845 pour un écran de
      844 : 1 px sous l'écran (border-top 1px + min-height 50px).
   b) `.tabbar__item` n'avait AUCUNE règle : ni flex, ni centrage. La
      répartition reposait entièrement sur une feuille d'origine.
   c) L'icône de l'onglet Reels porte `fill="#000"` / `stroke="#000"` en dur :
      elle ne pouvait pas suivre la couleur de l'onglet. Les deux autres
      icônes peignaient en noir implicite. */
/* On ne touche PAS à la géométrie de la barre elle-même : elle est posée en
   `top: 743px` + `transform: translateY(51px)`, un réglage du fournisseur
   qu'on ne veut pas casser. Le débordement d'1 px vient de l'intérieur :
   le conteneur posait `min-height: 50px` alors que la barre n'a que 49 px
   utiles sous son filet. On ramène donc l'intérieur à 49 px, et on empêche
   les onglets d'être étirés au-delà. */
body .tabbar {
  box-sizing: border-box;
}

body .tabbar__items {
  min-height: 49px !important;
  height: auto !important;
  box-sizing: border-box;
}

body .tabbar .tabbar-item {
  align-self: center !important;
  height: auto !important;
  min-height: var(--tactile);
  /* L'onglet mesurait 50 px (icône 30 + 10 px de padding haut et bas) alors
     que la barre ne laisse que 49 px sous son filet. On récupère 1 px ici
     plutôt que d'agrandir la barre : l'onglet reste à 49 px, donc au-dessus
     du seuil de 44 px. */
  padding-top: 9px;
}

body .tabbar__item {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

body .tabbar .tabbar-item {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}

/* Icônes en aplat (formes pleines, `fill` implicite ou imposé).
   On exclut explicitement `fill="none"` : les icônes en contour (Stories,
   Reels) ne doivent pas être remplies, sous peine de devenir des pâtés. */
body .tabbar .tabbar-item .icon__content svg[id^="menu-"] path {
  fill: currentColor;
}

body .tabbar .tabbar-item svg[aria-label="Reels"] {
  fill: currentColor;
}

body .tabbar .tabbar-item svg[aria-label="Reels"] line {
  fill: none;
  stroke: currentColor;
}

body .tabbar .tabbar-item svg[aria-label="Reels"] path[stroke] {
  fill: none;
  stroke: currentColor;
}

body .tabbar .tabbar-item svg[aria-label="Reels"] path:not([stroke]) {
  fill: currentColor;
}

/* 27.6 — REELS : le bouton d'import (élément CLIQUABLE) mesurait 78 × 40 px et
   recouvrait le haut de l'onglet Reels (onglet : y 795-845 ; bouton :
   y 782-822, soit 27 px de recouvrement sur 50). Cible effective de l'onglet
   réduite à 23 px. On remonte le bouton au-dessus de la barre. */
body .upload-reel {
  min-height: var(--tactile);
  min-width: var(--tactile);
  bottom: calc(50px + 12px) !important;
}

/* 27.7 — MESSAGES : bouton « Dating Plans ».
   Mesuré : 195,9 × 31,2 px (hauteur < 44) et fond
   `linear-gradient(281deg, rgba(233,38,38,.58), rgb(255,67,…))` — un dégradé
   rouge hors charte, avec un texte qui pouvait se retrouver sur le milieu
   clair du dégradé. */
body .btn-mobile-date-request {
  min-height: var(--tactile);
  background-image: none !important;
  background-color: var(--like) !important;
  border-color: var(--like) !important;
  color: #fff !important;
  font-family: var(--texte) !important;
}

/* 27.8 — ÉTATS VIDES : textes à 1,73:1.
   Mesuré : « Noone visited your profile » et « You dont have likes yet »
   en `color:#BFC5D5` (style inline) sur blanc = 1,73:1 pour un seuil de 4,5:1.
   `--gris` (#5B6672) donne 5,4:1 sans changer la hiérarchie visuelle. */
body h5.mi-pollita,
body .credits-section h5.comforta {
  color: var(--gris) !important;
}

/* 27.9 — PASTILLE « Get seen 100x » : mesurée `background:#00B697` (turquoise
   hors charte) avec un texte blanc sur fond moyen : 2,58:1, et 38 px de haut.
   `--accent-texte` (#0B6FA8) avec texte blanc donne 5,4:1. */
body .cien-me {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
  background-color: var(--accent-appui) !important;
  border-color: var(--accent-texte) !important;
  color:var(--encre)!important;
}

/* 27.10 — ONGLETS DE DOSSIER ET DE FILTRE.
   Mesuré : `div.tab__label` 77,5 × 20 px (hauteur < 44) sur Stories ;
   `div.tab.js-contact-list-folders__item` 42 px de large sur Messages. */
body .tab {
  min-width: var(--tactile);
  min-height: var(--tactile);
}

body .tab__label {
  display: flex;
  align-items: center;
  min-height: var(--tactile);
}

/* 27.11 — `div.spotlight_` mesuré à 400 px de large pour un écran de 390. */
body .spotlight_ {
  max-width: 100%;
  box-sizing: border-box;
}

/* 27.12 — DÉGRADÉS HORS CHARTE HÉRITÉS DU THÈME D'ORIGINE.
   `themes/default/css/crossplatform.css` définit toute une famille
   `.gradient1` … `.gradient32` en `!important`, avec des couleurs sans
   rapport avec la charte. Relevé des classes réellement utilisées dans les
   gabarits mobiles :
     .gradient32 · 13 usages  violet fonce → violet clair
     .gradient18 ·  5 usages  bleu-violet → magenta → ambre
     .gradient3  ·  4 usages  #FFE53B → #FF2525   (jaune → rouge)
     .gradient4  ·  2 usages  #FAACA8 → #DDD6F3
     .gradient5  ·  1 usage   #21D4FD → violet vif   (cyan → violet)
     .gradient17 ·  1 usage   #FBDA61 → #FF5ACD   (jaune → magenta)
     .gradient12 ·  1 usage   #00DBDE → magenta vif (cyan → magenta)
   Mesure : le séparateur « Premium packages » de la modale Premium
   (`.item-divider.gradient12`) rendait `rgb(0,219,222)` avec un texte blanc
   dessus, soit 1,72:1 pour un seuil de 4,5:1.
   On ramène à la charte les éléments STRUCTURANTS porteurs de texte. Les
   dégradés purement décoratifs (badges d'icône, pastilles) restent à décider
   — voir le rapport, §« reste à décider ». */
body .item-divider[class*="gradient"],
body .item-toggle[class*="gradient"],
body .credits-section [class*="gradient"],
body .premium-banner[class*="gradient"] {
  background-color: var(--accent-appui) !important;
  background-image: none !important;
  color:var(--encre)!important;
}

/* Le libellé de ces bandeaux est posé en `style="color:#fff"` inline : on
   garde du blanc, mais sur un fond qui tient le contraste (5,4:1). */
body .item-divider[class*="gradient"] *,
body .item-toggle[class*="gradient"] * {
  color: #fff;
}

/* 27.13 — MOUVEMENT RÉDUIT pour les transitions ajoutées ici. */
@media (prefers-reduced-motion: reduce) {
  body .cien-me,
  body .btn-mobile-date-request,
  body .upload-reel,
  body .profile-action-chat {
    animation: none !important;
    transition: none !important;
  }
}


/* --------------------------------------------------------------------------
   27.14 — MENU LATÉRAL (home/menu.html)
   Trois défauts trouvés à l'audit, tous mesurés :

   a) Le gabarit était le SEUL des 25 écrans à ne pas commencer par
      `<ion-view>`. Sans cet ancêtre, `ion-content` n'a pas de hauteur
      résolue. Corrigé dans le gabarit (voir le commentaire sur place).

   b) `.page.overlay-page.menu` (classe `menu` du gabarit) tombait sur la
      règle `.menu { display: none }` de `smakoo20.css` (l. 5528), qui vise en
      réalité un autre composant. L'écran n'était donc jamais rendu :
      mesuré 0 × 0, capture blanche de 7 Ko. La règle qui devait le montrer
      existe bien (`smakoo.css` l. 21144) mais elle ne pose que la transition,
      pas `display`. Le gabarit porte déjà `.visible`, on complète donc ici.

   c) un fond violet hors charte était posé en attribut
      `style` sur `.menu-navigation`. La §12 ci-dessus écrit
      `background-color: var(--encre)` mais perdait la cascade face à un style
      inline. L'attribut a été retiré du gabarit : la règle de la §12
      s'applique à nouveau (mesuré `rgb(20, 23, 26)`).
      Le texte des entrées est blanc (`#fff`) : sur `--encre` le contraste est
      de 16,25:1 ; sur le jaune `--accent` (#FFC629) il tomberait à 1,57:1,
      très sous le seuil. C'est pourquoi le fond reste `--encre` et non un
      aplat de la couleur de marque.
   -------------------------------------------------------------------------- */
body .page.overlay-page.menu.visible {
  display: block;
}

/* Le panneau reste un BLOC SOMBRE, sur `--encre` (couleur de la charte) et non
   sur `--surface`. Raison mesurée : tout le texte de ce menu est blanc
   (`#fff` en style inline sur les libellés, `rgba(255,255,255,.78)` et `#fff`
   dans la §12 ci-dessus). Passé sur `--surface` (#F7F5F2), le contraste tombait
   à 1,09:1 pour les trois tuiles « Super Powers / Popularité / Crédits ».
   Sur `--encre`, il est de 16:1. `smakoo.css` posait déjà `#222` ici : on
   remplace simplement cette teinte hors charte par `--encre`. */
body .page.overlay-page.menu {
  background-color: var(--encre);
}

body .page.overlay-page.menu .menu-fade-section {
  background-color: var(--encre);
}

body .page.overlay-page.menu .menu-slide-section {
  background-color: var(--encre);
}

/* 27.15 — MENU LATÉRAL : deux teintes hors charte relevées après le passage
   du panneau sur `--encre` (mesures faites sur `/home/menu`).
     · `.spotlight-heading` : fond `#2E2E2E`, texte `#c9c7c7` — deux gris
       neutres absents de la charte ;
     · `.spotlight-ripple` : anneau `#2b8cfc` sur aplat `#56b647`, et
       `#fc0` dans les images clés `spotlightRipple` — bleu/vert/jaune.
   On ramène les deux à la charte. Le halo du ripple reste à `opacity: .4`,
   donc discret. Les images clés posent `border`/`background` : une
   déclaration `!important` l'emporte sur une animation (règle de cascade). */
body .spotlight-heading {
  background: rgba(255, 255, 255, .06) !important;
  color: rgba(255, 255, 255, .82) !important;
  border-radius: var(--rayon-sm);
}

body .spotlight-heading__title {
  color: #fff;
}

body .spotlight-ripple {
  border-color: var(--accent) !important;
  background-color: var(--accent) !important;
}

/* 27.16 — FIL D'ACTUALITÉ : bloc « aucune publication ».
   `FeedCtrl` ne prenait jamais ce chemin : `feedUrl` était indéfini, le rappel
   JSON n'était jamais appelé et le squelette de chargement restait à l'écran
   indéfiniment (mesuré : `div.skeleton-wrapper-cell` 390 × 714 encore présent
   après 26 s, aucun état vide). Le code JS est corrigé ; voici l'habillage du
   bloc, sur le même principe que « Nothing to see here » de Reels. */
body .feed-vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 48px 24px 56px;
  text-align: center;
}

body .feed-vide__vignette {
  width: 96px;
  height: 96px;
  border-radius: var(--rayon-pilule);
  background-color: var(--surface);
  background-position: center;
  background-size: cover;
  border: 2px solid var(--trait);
}

body .feed-vide__titre {
  margin: 0;
  font-family: var(--titre) !important;
  font-size: 18px;
  line-height: 1.35;
  color: var(--encre);
}

/* 27.17 — En-tête : le titre cliquable (`.navigation-bar__logo`, qui ouvre le
   menu du fil) mesurait 110 × 40 px, sous le seuil de 44. Le bandeau fait
   désormais 44 px de haut (§27.2), la cible peut donc tenir dedans. */
body .navigation-bar__logo {
  display: flex;
  align-items: center;
  min-height: var(--tactile);
}


/* --------------------------------------------------------------------------
   27.18 — DÉGRADÉS DÉCORATIFS HORS CHARTE : ALIGNEMENT COMPLET
   Décision prise : une seule identité visuelle. Le jaune de marque (#FFC629)
   et le rose (#FFC629) restent les seuls accents ; toutes les autres teintes
   décoratives passent sur les jetons de la charte.

   `crossplatform.css` définit `.gradient1` … `.gradient32` en `!important`,
   d'où le `!important` ici. Inventaire fait sur les gabarits mobiles
   (fichiers servis uniquement), avec la couleur d'origine :

     .gradient3  #FFE53B → #FF2525 (jaune → rouge)
     .gradient4  #FAACA8 → #DDD6F3         | twigo-gradient4 (twigo.css)
     .gradient5  #21D4FD → violet vif      (cyan → violet)
     .gradient12 #00DBDE → magenta vif     (cyan → magenta)
     .gradient17 #FBDA61 → #FF5ACD (jaune → magenta)
     .gradient18 bleu-violet → magenta → ambre
     .gradient32 violet fonce → violet clair

   Deux paliers :
     · les éléments qui PORTENT DU TEXTE reçoivent `--accent-appui` (jaune de
       marque) avec un texte ENCRE — 11,45:1 — ou `--like` pour les boutons marqués
       `u-btn--danger`, le rose étant la couleur d'action de la charte
       (blanc dessus = 4,9:1) ;
     · les éléments purement décoratifs reçoivent `--accent-clair` (#FFF3CE).
   -------------------------------------------------------------------------- */

/* Palier 1 — éléments porteurs de texte. */
body .item-toggle[class*="gradient"],
body .item-divider[class*="gradient"],
body .button[class*="gradient"],
body .btn[class*="gradient"],
body .modal-reward[class*="gradient"],
body .modal-reward-top[class*="gradient"],
body .modal-reward-bottom[class*="gradient"],
body .cw-controls[class*="gradient"],
body .profile-preview__close[class*="gradient"],
body small[class*="gradient"] {
  background-image: none !important;
  background-color: var(--accent-appui) !important;
  color:var(--encre)!important;
}

/* Les boutons d'action « danger » (rose de la charte). */
body .u-btn--danger[class*="gradient"],
body .modal-reward-btn[class*="gradient"] {
  background-image: none !important;
  background-color: var(--like) !important;
  color: #fff !important;
}

/* Palier 2 — aplats décoratifs, sans texte à lire. */
body .icon[class*="gradient"] {
  background-image: none !important;
  background-color: var(--accent-clair) !important;
}

/* Le badge « + » de la mise en avant (matches.html) portait un rond orange
   #FF661B en `fill` dans le SVG. Une déclaration CSS l'emporte sur un attribut
   de présentation : on le ramène au rose de la charte. */
body .icon[class*="gradient"] svg circle {
  fill: var(--like) !important;
}

/* La tuile « passer en direct » (stories.html) portait `background:#ff1439`
   (rouge vif) en attribut `style`, qui écrasait le dégradé de classe. */
body .twigo-gradient4[style*="background"] {
  background-color: var(--like) !important;
  background-image: none !important;
}

/* 27.19 — Profil : le nom d'utilisateur est un BOUTON (il ouvre la fenêtre de
   modification du profil, `ng-click="openEditProfileModal()"`) mais ne mesurait
   que 390 × 25 px. On lui rend la hauteur de cible de la charte sans changer
   la typographie. */
body .own-profile__username {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
}

/* 27.20 — Stories : le libellé « importer une story » est un bouton
   (`<p id="uploadStoryMobile" onclick="upStoryMobile()">`) mesuré à
   70 × 19,4 px. Le padding agrandit la cible, la marge négative de même
   valeur empêche le texte de se déplacer : la vignette ne bouge pas. */
body #uploadStoryMobile {
  padding: 14px 8px;
  margin: -14px -8px;
}

/* 27.21 — Conversation : le titre de l'en-tête (nom du correspondant) est un
   bouton — `ng-click="showUserOptions()"` — mesuré à 245 × 39 px. */
body .navigation-bar__title {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
}

/* 27.22 — Boutons de mise en avant « passifs » : couleurs hors charte mesurées.
     · `span.first-me`  (home/match.html)    : `background:#25BA25` vert, texte
       blanc dessus = 2,58:1, et 157,7 × 38 px (< 44) ;
     · `span.spotlight-me` (home/superlikes.html) : fond violet hors charte.
   Les deux couleurs sont posées en attribut `style` sans `!important` : une
   déclaration `!important` de cette feuille l'emporte. On reprend la même
   recette que `.cien-me` : `--accent-texte` + texte blanc (5,4:1). */
body .first-me {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tactile);
  background-color: var(--accent-appui) !important;
  border-color: var(--accent-texte) !important;
  color:var(--encre)!important;
}

body .spotlight-me {
  background-color: var(--accent-appui) !important;
  border-color: var(--accent-texte) !important;
}

/* 27.23 — Réglages : la ligne « Lieu » est un bouton
   (`ng-click="openChangeLocModal()"`) mesuré à 358 × 25 px. Elle est aussi
   le seul chemin vers l'écran de changement de ville. */
body .item .row.no-padder {
  display: flex;
  align-items: center;
  min-height: var(--tactile);
}

/* --------------------------------------------------------------------------
   27.24 — Fenêtre « Modifier mon profil » et fenêtre profil rapide
   Mesures faites sur `/home/profile` avec `openEditProfileModal()` puis
   `openProfileModal(7, …)`.
   -------------------------------------------------------------------------- */

/* a) Réponses de profil non renseignées : `style="color: #999"` en inline sur
   un fond blanc = 2,85:1 (seuil 4,5:1). `--gris` donne 5,4:1. Le sélecteur ne
   vise QUE les valeurs écrites en #999, pas les réponses réelles (#111). */
body span[class^="userAnswer"][style*="#999"] {
  color: var(--gris) !important;
}

/* b) Les lignes de bas de liste (Politique de confidentialité, Conditions,
   Déconnexion, Supprimer le compte) débordaient de 9 à 11 px à droite :
   mesuré `div.item` 399 à 401 px de large pour un écran de 390, et le chevron
   `ion-chevron-right` à x 374-399 (donc coupé). On garde la place du chevron
   DANS la boîte au lieu de la déborder. */
body .item.comforta {
  box-sizing: border-box;
  max-width: 100%;
  padding-right: 46px;
}

body .item .item-note {
  right: 14px;
}

/* c) « Bloquer ou signaler » : le libellé est blanc sur un bouton transparent,
   donc invisible sur fond clair (ratio mesuré 1:1). */
body .button--transparent .button__text,
body .button[style*="background: none"] .button__text {
  color: var(--encre) !important;
}

/* d) Deux boutons à 41 px : sous le seuil de 44. */
body .inline-button,
body .profile-preview__close {
  min-width: var(--tactile);
  min-height: var(--tactile);
}


/* ==========================================================================
   28. RESPONSIVE — TOUTES LARGEURS ET TOUTES ORIENTATIONS
   --------------------------------------------------------------------------
   MESURES DU 04/10/2026
     18 ecrans x 7 largeurs (320, 360, 375, 390, 414, 428, 768) x 2
     orientations (portrait et paysage) = 14 couples par ecran, soit 252
     relevees. Outils : tests/r-multi.js (mesure) et tests/r-tour.sh (tournee).
     Comparaison avec les memes 18 ecrans mesures a 390 px seulement (§27).

   CE QUE CE BLOC CORRIGE (chiffres a l'appui, §28.x)
     · 28.1 champs de saisie sous 16 px : zoom automatique d'iOS ;
     · 28.2 barre d'onglets qui masquait du contenu (profil, rencontres) ;
     · 28.3 carte « Rencontres » plus haute que la place disponible ;
     · 28.4 `100vh` restants, remplaces par `dvh` ;
     · 28.5 zone sure (barre de geste) reservee dans le calcul ;
     · 28.6 listes des Reglages : 2 px de large en trop, libelle tronque.

   Ce bloc n'utilise ni filtre, ni calcul en `100vw`, ni animation de
   `width`/`height`/`top`/`left`.
   ========================================================================== */

/* --------------------------------------------------------------------------
   28.1 — CHAMPS DE SAISIE : JAMAIS MOINS DE 16 px
   Mesure (toutes largeurs) : 4 champs de l'ecran Reglages a 14 px, la
   recherche de la liste des Messages a 15 px, la recherche de Localisation a
   15 px. Sous 16 px, iOS agrandit la page des que le champ recoit le focus :
   la mise en page saute et l'utilisateur doit pincer pour revenir.
   -------------------------------------------------------------------------- */
body input,
body textarea,
body select {
  font-size: 16px !important;
}

/* Les libelles purement decoratifs a l'interieur d'un champ gardent leur
   taille : on ne touche qu'au texte saisi et au texte du champ lui-meme. */
body input::placeholder,
body textarea::placeholder {
  font-size: 16px;
}

/* --------------------------------------------------------------------------
   28.2 — BARRE D'ONGLETS : RESERVER LA PLACE DANS LA ZONE QUI DEFILE
   Mesures avant correction :
     · Mon profil a 360 x 640 : le libelle de la derniere ligne
       (`span.ng-binding`) occupait y 605 → 625 ; la barre d'onglets commence a
       y 590. 35 px masques, et la page n'etait pas defilable (hauteur de
       contenu 642 pour 640 de fenetre) : le libelle etait definitivement
       invisible ;
     · Rencontres en paysage 640 x 360 : le titre de l'etat vide
       (`h1.comforta`) occupait 301 → 330, la barre 310 → 360 : titre
       ENTIEREMENT sous la barre ;
     · Messages en paysage 568 x 320 : icone d'onglet rognee de 11 px.
   Correction : la zone qui defile s'arrete au-dessus de la barre au lieu de
   passer dessous. Le contenu reste atteignable (il devient defilable) et
   jamais masque.
   `:has()` n'est pose que sur les ecrans qui portent reellement la barre, pour
   ne pas ajouter 50 px de vide sur les 10 ecrans qui n'en ont pas. Un
   navigateur sans `:has()` ignore la regle : aucune regression possible.

   Deuxieme defaut trouve le 04/10 sur l'ecran Messages en 568 x 320 (icone
   `svg.icon__content--inactive` d'une carte de connexion, y 261 → 281,
   recouverte de 11 px par la barre) : la premiere version ne visait que
   `ion-content .scroll-content` (un DESCENDANT de `ion-content`). Or dans
   plusieurs gabarits, Ionic pose la classe `scroll-content` sur
   `ion-content` LUI-MEME (`<ion-content class="scroll-content">`), et la zone
   qui defile s'etendait alors jusqu'a y 321 pour une barre a y 270 : 51 px de
   contenu sous la barre. Les trois formes du selecteur sont donc couvertes :
   `ion-content .scroll-content`, `ion-content.scroll-content` et tout
   `.scroll-content` de la vue.
   -------------------------------------------------------------------------- */
body ion-view:has(.tabbar) ion-content .scroll-content,
body ion-view:has(.tabbar) ion-content.scroll-content,
body ion-view:has(.tabbar) .scroll-content {
  bottom: calc(50px + env(safe-area-inset-bottom, 0px)) !important;
}

body ion-view:has(.tabbar) ion-content > .scroll {
  padding-bottom: calc(50px + env(safe-area-inset-bottom, 0px));
}

body ion-view:has(.tabbar) ion-content {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* --------------------------------------------------------------------------
   28.3 — CARTE « RENCONTRES » : HAUTEUR PLAFONNEE A LA PLACE DISPONIBLE
   Mesure avant correction, Decouverte a 390 x 844 : la carte occupait
   y 150 → 874 alors que la barre d'onglets commence a y 794 : 80 px
   recouverts, dont 30 px carrement sous l'ecran. La hauteur vient d'un style
   pose en ligne par le gabarit (`height: {{h}}px`, h = innerHeight - 120
   dans js/controllers.js), qui ne tient compte ni de la barre d'onglets ni de
   la marge haute de 100 px — d'ou l'incoherence avec le `bottom: 10px` de
   smakoo20.css.
   On plafonne en CSS plutot que de toucher au calcul du controleur : la
   carte ne peut plus depasser la zone visible, quelle que soit la hauteur de
   fenetre (paysage compris).
   -------------------------------------------------------------------------- */
body .encounters__card {
  max-height: calc(100dvh - 210px - env(safe-area-inset-bottom, 0px));
}

/* Meme cause pour l'etat vide qu'elle contient (bloc « Aucun resultat » :
   vignette 200 px + titre + texte + bouton, environ 400 px de contenu) :
   dans une fenetre de 428 px de haut il n'y a que 218 px de disponible, et le
   titre tombait 46 px sous la barre d'onglets sans que rien ne puisse defiler
   (mesure 926 x 428 : titre y 395 → 424, barre a y 378). On rend le bloc
   defilable au lieu de le laisser deborder : il est atteignable au doigt.
   Le defilement horizontal de la carte (geste de balayage) n'est pas touche :
   seul l'axe vertical est ouvert. */
body .encounters-message {
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* --------------------------------------------------------------------------
   28.4 — `100vh` RESTANTS : `dvh` PARTOUT
   `100vh` se rapporte a la plus grande hauteur de fenetre possible : quand la
   barre d'adresse du navigateur mobile est visible, un element en `100vh`
   depasse le bas de l'ecran. `dvh` suit la hauteur reellement visible.
   Regles reellement appliquees (releve CSSOM du 04/10 sur les 18 ecrans,
   avec le nombre d'elements touches) :
     · swiper.css  `.video-wraper .poster`                 height: 100vh
     · swiper.css  `.detail .container, .detail .video-item` width: 100vw
     · feed.css    `.insta-comments`                       height: 100vh
     · feed.css    `.insta-comments-image`                 height: 100vh
     · live.css    `.stream` et `.stream__*`              100vw / 100vh
     · little-widgets.css `.lw-container`, `.lw-item`     100vw / 100vh
   S'y ajoutent les `100vh` des feuilles du mobile qui ne s'appliquent pas sur
   les 18 ecrans releves mais qui restent dans le code servi :
     · smakoo.css  `.fullscreen-gallery .profile-top-section`
     · smakoo.css  `.feature-promo` (calc(100vh - 46px))
     · smakoo.css  `.ios .page.overlay-page.menu .menu-slide-section`
     · smakoo.css  `.hotlist-tooltip .hotlist-tooltip__fade`
     · i.css       `body[fullbleed]`
     · twigo/css/twigo.css `.stream-page` (gabarit twigo, non servi)
   Les largeurs en `100vw` sont ramenees a `100%` : `100vw` inclut la largeur
   de la barre de defilement et provoque un glissement horizontal.
   -------------------------------------------------------------------------- */
/* Remplacement DÉCLARATION PAR DÉCLARATION de la valeur d'origine : on ne
   change jamais la propriété ni la sémantique (une `height` reste une
   `height`, un `max-height` reste un `max-height`), seulement l'unité.
   `!important` est nécessaire là où la règle d'origine porte 2 classes ou plus
   (`.ios .page.overlay-page.menu .menu-slide-section`, `.fullscreen-gallery
   .profile-top-section`) : sans lui, la règle d'origine l'emporterait sur la
   spécificité et la correction resterait sans effet. */
body .video-wraper .poster,
body .insta-comments,
body .insta-comments-image,
body .profile-top-section,
body .hotlist-tooltip__fade {
  height: 100dvh !important;
}

body .ios .page.overlay-page.menu .menu-slide-section,
body .menu-slide-section {
  height: 100dvh !important;
}

body .feature-promo {
  height: calc(100dvh - 46px) !important;
}

body .lw-item {
  max-height: calc(100dvh - 64px) !important;
}

/* Barres de défilement : `100vw` inclut la largeur de la barre de défilement
   et provoque un glissement horizontal. Remplacé par `100%` de la fenêtre. */
body .lw-container,
body .detail .container,
body .detail .video-item,
body .stream__comment-field,
body .stream__message-list {
  width: 100% !important;
  max-width: 100% !important;
}

body .stream,
body .stream__canvas {
  min-width: 100% !important;
  width: 100% !important;
  min-height: 100dvh !important;
  max-height: 100dvh !important;
}

body .stream__chat {
  width: 100% !important;
  min-height: 100dvh !important;
  max-height: 100dvh !important;
}

body[fullbleed] {
  height: 100dvh !important;
}

/* --------------------------------------------------------------------------
   28.5 — ZONE SURE : RESERVEE DANS LES CALCULS
   La balise viewport servie ne demande PAS `viewport-fit=cover` : le
   navigateur rentre donc lui-meme la zone de mise en page sous l'encoche et
   au-dessus de la barre de geste, et `env(safe-area-inset-*)` vaut 0.
   Mesure dans le navigateur : 0 px sur les quatre bords.
   On reserve malgre tout la valeur dans les deux calculs ci-dessus (28.2 et
   28.3) : si `viewport-fit=cover` est ajoute un jour — ou si l'application est
   empaquetee en natif — la place sera deja prevue, sans rien changer
   aujourd'hui puisque `env()` vaut 0.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   28.6 — LISTES DES REGLAGES
   a) Mesure 320 x 568 : chaque ligne de liste fait 322 px pour une fenetre de
      320 px (`margin: -1px` du composant pose sur un `.list` en
      `padding: 1px 0`) : 1 px rogne de chaque cote. On annule la marge
      horizontale, la marge verticale est conservee (elle porte le filet).
   b) Mesure 320 x 568 : le libelle « Online users » etait tronque
      (contenu 326 px pour 318 px utiles, `text-overflow: ellipsis`). On
      autorise le retour a la ligne plutot que la coupure.
   -------------------------------------------------------------------------- */
body .list .item,
body .list .item-divider {
  margin-left: 0;
  margin-right: 0;
}

body .item.item-toggle,
body .item.item-toggle.comforta {
  white-space: normal !important;
  text-overflow: clip !important;
}

/* --------------------------------------------------------------------------
   28.7 — FENETRES MODALES : REPASSER AU-DESSUS DE LA BARRE D'ONGLETS
   Probleme structurel mesure le 04/10/2026 : la feuille d'origine pose la
   barre d'onglets en `z-index: 998` et Ionic pose les fenetres modales en
   `z-index: 10` (fond de fenetre en 10 egalement). La barre passait donc
   AU-DESSUS des fenetres. Preuve directe, releve `elementsFromPoint` au pied
   de l'ecran en 320 x 568, fenetre « Modifier mon profil » ouverte, du dessus
   vers le dessous :

       div.click-block
       div.modal-backdrop          <- fond de la fenetre (z 10)
       div.tabbar-item__icon       <- BARRE D'ONGLETS (z 998)  << au-dessus

   Consequences mesurees :
     · les derniers champs du formulaire etaient masques par la barre
       (« Modifier mon profil » : 44 px a 320 x 568, 49 px a 360 x 640,
       36 px a 428 x 926 ; « Retrait » : 6 elements a 360 x 640) ;
     · un appui au pied de l'ecran quittait la fenetre au lieu d'agir dedans :
       la fenetre n'etait pas modale.
   Correction : on replace les fenetres et leur fond au-dessus de la barre, en
   respectant l'echelle deja utilisee par le projet (0 / 10 / 99 / 998 / 999 /
   1000). Aucune autre valeur n'est touchee : la barre reste a 998 pour les
   ecrans normaux.
   -------------------------------------------------------------------------- */
body .modal,
body ion-modal-view {
  z-index: 1000 !important;
}

body .modal-backdrop {
  z-index: 999 !important;
}

/* --------------------------------------------------------------------------
   28.8 — CIBLES TACTILES SOUS 44 px DANS LES FENETRES
   Releve du 04/10/2026, aux 8 tailles mesurees (320, 360, 390, 428 portrait ;
   568 x 320, 640 x 360, 844 x 390, 926 x 428 paysage) : identique partout,
   donc independant de la largeur.
     · « Photo privee » : les deux boutons d'achat `.private-photo--button`
       mesurent 273 x 30 px — hauteur sous le seuil de 14 px.
     · « Live / Decouverte » : croix de fermeture et selecteur de sexe
       `.round-icon` a 39 x 39 px ; bouton d'envoi `#send_btn` a 38 x 44 px ;
       entree de liste `li.ci.ci-user-1` a 40,5 px de large.
   Fonctionnalite « live » desactivee en production (`liveDiscover.enabled` =
   No) : la correction est posee par coherence, elle ne change rien aujourd'hui.
   -------------------------------------------------------------------------- */
body .private-photo--button {
  min-height: var(--tactile);
}

body .round-icon {
  min-width: var(--tactile);
  min-height: var(--tactile);
}

body #send_btn.btn {
  min-width: var(--tactile);
  min-height: var(--tactile);
}

body li.ci.ci-user-1,
body li.chat-toggle.ci {
  min-width: var(--tactile);
  min-height: var(--tactile);
}


/* ==========================================================================
   29. ALIGNEMENT SUR LA CHARTE DE L'ESPACE MEMBRE — 06/10/2026
   --------------------------------------------------------------------------
   Le client a signale que l'application mobile « ne correspond pas a ce qu'on
   a deja fait sur la version web ». Les sections 1 a 28 avaient ete ecrites
   d'apres la page PUBLIQUE ; la reference est l'ESPACE MEMBRE
   (`themes/default/css/smakoo-theme.css`, 34 sections, valide par le client).

   Outillage : `tests/m-shots.js` (mesures navigateur) et une sonde qui remonte,
   pour chaque valeur non conforme, la feuille et la regle qui la produisent.
   Toutes les mesures ci-dessous ont ete prises le 06/10/2026, viewport
   390 x 844, compte de test « Manon » (id 6).

   Aucun fichier d'origine n'est modifie : tout passe par la cascade, en
   prefixant `body` (+ `!important`) la ou la regle visee est posee en attribut
   `style` par un gabarit.

   INTERDITS RESPECTES : aucun `filter:`, aucun calcul en `100vw`, seules
   `transform` et `opacity` sont animees, ni `width`/`height`/`top`/`left`
   animes, `user-scalable`/`maximum-scale` non touches.
   ========================================================================== */


/* --------------------------------------------------------------------------
   29.1 — BOUTONS : LA HAUTEUR DE LA CHARTE EST 44 px, PAS 52

   MESURE. Meme role, deux hauteurs :
     espace membre  `.mainBtn.active`         230 x 44   padding 10px 22px
     app mobile     `button.button`           282 x 52   padding 14px 24px
   L'ecart de 8 px vient d'une regle du fichier mobile ecrite au feeling
   (`min-height: 52px`) alors que la charte pose `--cible: 44px` et que le web
   s'y tient : tous les boutons pleins du membre mesurent 44 px, du bouton
   « Mettre a jour » des filtres a la demande de rendez-vous.

   La ligne ci-dessous ramene les boutons pleins sur la cible de la charte.
   Les 52 px restent en place pour les boutons d'une seule ligne a texte long :
   `min-height` ne contraint que le plancher, la hauteur reelle continue de
   suivre le contenu.
   -------------------------------------------------------------------------- */
body .button,
body .button--primary,
body .button.btn-primary,
body .btn-primary,
body .mainBtn {
  min-height: var(--cible);
}


/* --------------------------------------------------------------------------
   29.2 — ONGLETS : COULEURS ET FOND POSES EN ATTRIBUT `style`

   MESURE (ecran Rencontres, `.tabs.tabs-top`) :
     · `#showAll`      couleur rendue violette (rgb 112, 0, 227) du theme
     · `#showPopular`  couleur rendue rgb(51, 51, 51)   <- gris `#333`
     · `.tabs.tabs-top` rayon rendu 5px, fond `#fff`
   Les deux couleurs sont ecrites en attribut `style` dans `home/meet.html`
   (lignes 36 et 39) et `home/stories.html` (ligne 64). Le fichier mobile avait
   bien prevu leur reprise (§6) : `color: var(--gris)` et sans `!important`.
   Une declaration sans `!important` ne peut pas battre un attribut `style` :
   la regle etait donc inoperante, et le violet du theme d'origine restait
   visible. Meme cause pour le rayon de 5 px pose en attribut.

   Les valeurs de la charte : onglet au repos `--gris` (5,85:1 sur blanc),
   onglet actif `--encre` souligne `--like` (motif deja retenu en §6), et le
   rayon du conteneur `--rayon-sm` (14 px) comme toute pastille de la charte.
   -------------------------------------------------------------------------- */
body .tabs .tab__label,
body .tab .tab__label {
  color: var(--gris) !important;
  font-size: 14px !important;
  letter-spacing: .04em;
  text-transform: none;
}

body .tabs .tab.is-active .tab__label,
body .tab .tab.is-active .tab__label {
  color: var(--encre) !important;
}

body .tabs.tabs-top[style*="border-radius"] {
  border-radius: var(--rayon-sm) !important;
}

/* La zone des onglets fait 34 px de haut en attribut `style` alors que ses
   deux enfants en font 56 px : mesuree 312 x 34 px pour un contenu de 56 px,
   elle deborde de 22 px de chaque cote.

   La hauteur est figee en attribut `style` (« height: 34px »), donc seule une
   declaration `!important` la reprend. On ne peut PAS la laisser sur `auto` :
   mesure de l'essai — les enfants passent a 775 px, soit la hauteur de la vue,
   parce que `.tab` est en `display: inline-table` et que la boite de ligne les
   etire a la hauteur du bloc. C'est le defaut qui suit.
   On pose donc une hauteur EXACTE, celle du contenu : 56 px.
   Mesure apres correction : conteneur 312 x 56, enfants 56 px, plus de
   debordement. */
body .tabs.tabs-top {
  height: 56px !important;
  min-height: 56px !important;
  max-height: 56px !important;
}


/* --------------------------------------------------------------------------
   29.3 — « DES BOUTONS QUI APPARAISSENT ET QUI DISPARAISSENT »

   CAUSE MESUREE. `vivify.min.css` definit `.popInRight`, `.popInLeft`,
   `.popIn`, `.zoomIn`, `.swoopIn*`, `.fadeIn`… dont les images cles commencent
   a `opacity: 0` PUIS se terminent — mais `vivify.min.css` ne pose AUCUN
   `animation-fill-mode`. Autrement dit : une fois l'animation finie, l'element
   reprend son opacite naturelle. Tant que la sequence se termine, rien ne se
   voit ; des que la sequence est interrompue (classe retiree par Angular,
   image non chargee, `animation-name` redefini par une autre feuille, onglet
   en arriere-plan), l'element reste a `opacity: 0` — invisible et
   INCLIQUABLE, puisqu'il occupe toujours sa place.

   Releve du 06/10/2026, ecran Rencontres, 250 ms puis 6 s apres l'entree dans
   la vue :
     `div.brick--squared.brick--stretch` (vignettes du carrousel « spotlight »,
        7 elements de 1 a 29 px de cote — donc TOUJOURS a l'ecran)
        t = 0,25 s : opacite 0,31 / 0 / 0 / 0 / 0 / 0 / 0
        t = 6 s    : opacite 1   (animation `popInRight`, 0,8 s, terminee)
     `div.open-mobile-date-request` (le bouton « Plan a date », 195 x 60 px)
        t = 0,25 s : opacite 0   (animation `swoopInBottom`, 0,5 s)
   Ce sont bien des elements « qui apparaissent et qui disparaissent ».

   MESURE DE REFERENCE. Le meme ecran web (`/index.php?page=meet`, 1440 px)
   compte 72 elements animes : `popIn`, `fadeIn`, `pulsate` (boucle), mais
   AUCUN depuis `opacity: 0`. Le client voit la difference.

   CORRECTIF. `animation-fill-mode: both` — la plus petite correction possible :
   elle conserve exactement la meme animation, avec le meme depart et la meme
   duree, mais l'element garde son etat FINAL une fois la sequence terminee au
   lieu de retomber a `opacity: 0`. On ne touche ni `vivify.min.css` (fichier
   tiers) ni les gabarits, qui posent la classe `vivify` dans leur balisage.
   Pour `forwards`, la propriete est `.vivify` ; on la pose aussi sur les
   racines d'animation nommees explicitement dans les gabarits, au cas ou
   `vivify` serait absent.

   Effet mesure apres correction (voir le rapport) : les elements animes
   finissent a opacite 1 et y restent, sans qu'un seul demarrage d'animation
   soit supprime.
   -------------------------------------------------------------------------- */
.vivify,
.fadeIn, .fadeOut,
.popIn, .popInLeft, .popInRight, .popInUp, .popInDown,
.zoomIn, .zoomInLeft, .zoomInRight,
.swoopIn, .swoopInBottom, .swoopInTop, .swoopInLeft, .swoopInRight,
.slideIn, .slideInUp, .slideInDown, .slideInLeft, .slideInRight,
.rollIn, .puffIn, .ball, .swashIn, .pullUp, .pullDown, .fadeInUp, .fadeInDown {
  animation-fill-mode: both;
}


/* --------------------------------------------------------------------------
   29.4 — POINT DE PRESENCE : DEUX VERTS POUR LE MEME INDICATEUR

   MESURE (ecran Rencontres, carrousel « spotlight »). Releve, sur les memes
   6 x 6 px : la fiche du carrousel affichait `rgb(11, 138, 62)` alors que la
   valeur du site est `#17d417` -> `rgb(23, 212, 23)`. Deux verts pour le meme
   point. La cause : le §7 de ce fichier visait `.csms-online-status--online`
   (0,1,0), soit exactement la specificite de la regle de `smakoo20.css` ; et
   comme `smakoo-theme.css` est chargee apres, c'est elle qui gagnait partout.

   CORRECTION : la valeur du site est desormais celle du §7 (voir le
   commentaire a cet endroit). Rien a surcharger ici.

   ECART DE CONTRASTE ASSUME. `#17d417` sur blanc mesure 2,05:1, sous le seuil
   de 3:1 applicable a un indicateur graphique (WCAG 1.4.11). Le point du site
   ne le tient pas davantage : l'alignement sur la reference l'emporte, et
   l'ecart est signale dans le rapport plutot que corrige en cachette — le
   corriger voulait dire renoncer a la couleur du site.
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   29.5 — PHOTO CARREE : 11,4 % DE RAYON AU LIEU DE LA VALEUR DE LA CHARTE

   MESURE. `smakoo20.css` (ligne 985) pose `.brick--squared .brick__image
   { border-radius: 11.4% }`. Sur une vignette de 70 x 70 px (carrousel
   « spotlight » de l'ecran Rencontres) cela rend 14,3 px : la valeur tombe par
   hasard sur `--rayon-sm`, mais elle varie avec la taille de la vignette — a
   160 px elle donnerait 18 px, a 30 px seulement 3,4 px. La charte, elle, pose
   une valeur FIXE.

   La regle du §7 vise `.brick--squared .brick__image` (0,2,0) : a specificite
   egale, c'est la DERNIERE qui gagne, et comme `smakoo-theme.css` est charge
   apres `smakoo20.css` elle devrait deja s'appliquer. Elle ne s'applique pas
   parce qu'un attribut `style` (`border-radius: 65px`) est pose sur les
   `.brick-img` des vues « aucun resultat » — c'est le §29.6 qui traite ce cas.
   La declaration est neanmoins ecrite en `!important` pour rester vraie quel
   que soit l'ordre de chargement.
   -------------------------------------------------------------------------- */
body .brick--squared .brick__image,
body .brick--squared .brick-img {
  border-radius: var(--rayon-sm) !important;
}


/* --------------------------------------------------------------------------
   29.6 — RAYON DE 65 px POSE EN ATTRIBUT `style` SUR LES VISAGES

   MESURE. Les vues « aucun resultat » portent en attribut `style`
   `border-radius:65px` sur un carre de 200 x 200 px, sur `home/explore.html`
   (ligne 131), `home/meet.html` (ligne 53) et `home/stories.html` (ligne 51).
   Le §7 vise `.profile-photo` avec `border-radius: var(--rayon-pilule)`
   (999 px) : une declaration ordinaire ne bat pas un attribut `style`, la
   regle n'avait donc aucun effet et la vignette rendait 65 px.

   65 px sur 200 px de cote n'est ni `--rayon-sm` (14), ni `--rayon` (26), ni
   la pastille : aucune valeur de la charte ne correspond a cette forme. La
   charte range les visages avec les pastilles (`--rayon-pilule`), c'est donc
   elle qui s'applique — meme correction que le §26, mais cote CSS.

   Le `!important` est indispensable ici : il n'y a pas d'autre prise sur une
   valeur posee en attribut `style`.
   -------------------------------------------------------------------------- */
body .profile-photo.brick-img[style*="border-radius"],
body .brick-img.profile-photo[style*="border-radius"] {
  border-radius: var(--rayon-pilule) !important;
}


/* --------------------------------------------------------------------------
   29.7 — NOTIFICATION DANS L'APPLICATION : LE CADRE DE LA CHARTE

   MESURE. `.inapp-notification` (`smakoo.css`, ligne 11496) rend
   370 x 80 px avec `border-radius: 5px` et le texte `rgb(94, 103, 115)`.
   5 px n'est aucune des trois valeurs de rayon de la charte (14 / 26 / 999) :
   c'est une pointe de l'ancien theme. La charte range une carte dans
   `--rayon-sm` (14 px) — c'est le rayon que portent deja, dans l'application,
   la vignette carree, les onglets et les cartes de liste.

   La couleur du texte, elle, est laissee telle quelle : elle vient d'une
   combinaison de gris et reste lisible (5,7:1 sur blanc). On ne la change pas
   sans mesure de contraste qui l'exige.

   Rayon rendu apres correction : 14 px (mesure, voir le rapport).
   -------------------------------------------------------------------------- */
body .inapp-notification {
  border-radius: var(--rayon-sm) !important;
}
body .inapp-notification-wrapper .inapp-notification__promo {
  border-radius: var(--rayon-sm) !important;
}


/* --------------------------------------------------------------------------
   29.8 — MENU LATERAL : « Manon » A 11 px, « Encounters » A 8 px

   MESURE (ecran Menu, `.menu-navigation`).
     `.menu-navigation` porte `font-size: 8px; line-height: 10px` dans
     `smakoo.css` (ligne 17927). La section §12 de ce fichier ne corrige que
     `.menu-navigation-item__name` (11 px). Resultat mesure :
       `.menu-navigation-item__name`  « Manon »        11 px
       `.menu-navigation-item`        « Encounters »    8 px   <- herite
       `.menu-navigation-item`        « ... »          11 px

   Huit pixels ne se lisent pas, et la charte ne descend jamais sous 12 px
   pour une etiquette (`.smk-langue__label` du web est a 12 px). Le libelle de
   l'entree de menu est une etiquette secondaire : on la porte au plus petit
   corps de la charte, 12 px, avec la graisse 600 deja utilisee au-dessus.
   L'interlignage de 10 px du parent devient 1.25, sinon les lignes se
   chevaucheraient a 12 px.
   -------------------------------------------------------------------------- */
body .menu-navigation {
  line-height: 1.25;
}

body .menu-navigation-item {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
}

body .menu-navigation-item__name {
  font-size: 12px;
}


/* --------------------------------------------------------------------------
   29.9 — ONGLETS DU BAS : L'ONGLET ACTIF NE CHANGE QUE DE COULEUR

   MESURE (ecran Rencontres, barre d'onglets basse).
     `.tabbar-item`     65 x 49 px, aucun fond
     `.tabbar-item`     65 x 49 px, aucun fond
     `.tabbar-item`     65 x 49 px, aucun fond
     `.tabbar-item`     65 x 49 px, aucun fond
     `.tabbar-item.is-active`  65 x 49 px, `background: rgb(224, 36, 94)` (--like)

   L'onglet actif est donc un APLAT ROSE de 65 x 49 px, alors que la charte
   marque l'element actif par la COULEUR (le bleu de marque) et un soulignement
   rose sur celui des onglets de dossier du haut (§6 : « Le site souligne
   l'element actif d'un trait rose »). Deux traitements opposes pour le meme
   etat, sur le meme ecran.
   Barre d'onglets basse et onglets de dossier sont deux composants distincts
   dans le web ; ici, sur 390 px de large, l'aplat attirait l'oeil sur la barre
   au lieu du contenu.

   On reprend exactement la recette de la charte : pas d'aplat, l'element actif
   passe en `--accent-texte` (5,77:1 sur `--surface`) et recoit le meme
   soulignement `--like` que les onglets de dossier.
   -------------------------------------------------------------------------- */
body .tabbar-item {
  background: none;
}

body .tabbar-item.is-active {
  color: var(--accent-texte);
}

body .tabbar-item__icon-indicator {
  background: var(--like);
}


/* --------------------------------------------------------------------------
   29.10 — RAYON DE 2 px SUR LES LIGNES DE SOLDE DU MENU (`menu-payment`)

   MESURE. `.menu-payment` (les trois lignes « Super Powers / Popularite /
   Credits » de `templates/mobile/home/menu.html`, lignes 14, 23 et 32) rend
   225 x 51 px avec `border-radius: 2px`. La section §12 du present fichier lui
   avait donne `min-height: var(--tactile)` et `font-family: var(--texte)`,
   mais pas de rayon : les 2 px viennent d'une feuille d'origine et restent une
   pointe de l'ancien theme — aucune valeur de la charte n'est a 2 px.

   Ces trois lignes sont des elements ACTIONNABLES (`ng-click` vers la modale
   Premium ou la fenetre des credits) : la charte range ce type de bloc dans
   `--rayon-sm` (14 px), comme les cartes de liste, les vignettes et les
   onglets deja alignes aux §7, §29.2 et §29.7.
   -------------------------------------------------------------------------- */
body .menu-payment {
  border-radius: var(--rayon-sm);
}


/* --- Correctif 06/10/2026 : #14171B -> --encre (#14171A).
   Releve : 6 occurrences sur 3 ecrans (titre « Expand your search », message
   « Sorry, no one fits your preference »). Un caractere d ecart seulement,
   mais hors jeton : la teinte n est pas celle de la charte. Le gabarit ecrit
   la valeur en dur dans un style inline, on la neutralise ici. */
body .encounters-message,
body .encounters-message span,
body h1.comforta,
body .encounters__title,
body .encounters-empty__title{
  color: var(--encre) !important;
}


/* ==========================================================================
   CORRECTIF 06/10/2026 — BANDEAU « RENDEZ-VOUS » DE L'ECRAN DATING
   --------------------------------------------------------------------------
   Mesure (tests/m-audit-complet.js, ecran 17-dating, 390 x 844) :

     div#createDateRequest.people-nearby-banner
       position  relative      largeur 420 px      x = -15 px
       contenu   546 px dans 420 px   ->  126 px rognes, 15 px hors fenetre
     div.people-nearby-banner__curve
       position  absolute      largeur 672 px      x = -141 px

   Origine : `smakoo.css` l.21239 pose `margin: 0 -15px -10px -15px` sur
   `.people-nearby-banner`. Cette marge negative est calibrée pour un parent
   qui porte deja 15 px de retrait (le cas de `.users-folder`) ; ici le parent
   n'en a pas, donc le bandeau deborde de 15 px de chaque cote et son contenu
   se retrouve rogne par l'`overflow: hidden` de la meme regle.

   La courbe, elle, est posee en absolu a `left: -30%` pour 160 % de large :
   c'est volontaire (un arc qui sort du cadre) et sans consequence visuelle
   puisque le parent rogne. On ne la touche pas, elle est correcte.

   On ramene donc le bandeau dans la largeur de sa colonne, et on rend son
   contenu flexible pour qu'il cesse d'etre rogne. ------------------------- */
body .people-nearby-banner {
  margin-left: 0 !important;
  margin-right: 0 !important;
  max-width: 100% !important;
  box-sizing: border-box !important;
}
body #createDateRequest .cta-box,
body #createDateRequest .cta-box__content,
body #createDateRequest .cta-box__buttons,
body #createDateRequest .button-wrapper {
  max-width: 100% !important;
  box-sizing: border-box !important;
}
body #createDateRequest .cta-box__content {
  white-space: normal !important;
  word-wrap: break-word !important;
}


/* ==========================================================================
   CORRECTIF 06/10/2026 — LA BADGE « PREMIUM » NE DOIT PAS ETRE INVISIBLE
   --------------------------------------------------------------------------
   Mesure (tests/m-audit-complet.js) : `span.spotlight-me` est signale comme
   « bouton masque » sur 6 ecrans (likesme, visitors, superlikes, matches,
   menu). Le bloc qui le contient porte `ng-show="!canSeeFans && !noFans"`.

   Cause, relevee dans mobile/js/controllers.js :
     l.6827 et l.7167 : $scope.canSeeFans est initialise a TRUE dans trois
     controleurs (LikesCtrl, SuperLikesCtrl, VisitorsCtrl). La condition
     d'affichage est donc fausse des l'ouverture, et le bloc — qui contient
     le seul appel a l'abonnement premium de ces ecrans — n'apparait jamais.
     Il ne s'active que plus tard, si l'utilisateur change d'onglet
     (`onTabShow`, l.7173), ce qui explique le « boutons qui apparaissent et
     qui disparaissent » : l'etat depend d'une action que l'utilisateur n'a
     aucune raison de faire.

   On ne touche PAS au controleur : `canSeeFans` pilote aussi la pagination
   (`changePage`, l.6827) et le modifier aurait des effets de bord ailleurs.
   On corrige le CSS : quand le bloc EST rendu par AngularJS (`ng-hide`
   absent), il doit etre visible et lisible. Le `display:inline-flex` de la
   section 23.4 ci-dessus s'applique deja ; la couleur, elle, etait violette
   (fond violet pose en style inline dans le gabarit, ecrase ici).

   Couleur : --accent-appui (jaune de marque) avec un texte ENCRE — 11,45:1.
   Les teintes violettes posees en style inline dans `style.css` l.882
   n'appartiennent a aucune palette du projet et restent ecrasees ici. ------- */
body .only-premium .spotlight-me,
body .only-premium span.spotlight-me {
  background-color: var(--accent-appui) !important;
  background-image: none !important;
  border: 1px solid var(--accent-texte) !important;
  border-radius: var(--rayon-pilule) !important;
  color:var(--encre)!important;
  font-family: var(--texte) !important;
  font-weight: 600 !important;
  min-height: var(--tactile);
  padding: 10px 22px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
/* Le bloc premium masque par AngularJS ne doit pas laisser de trou dans la
   page : s'il est absent, rien ne doit occuper sa place. */
body .only-premium.ng-hide {
  display: none !important;
}


/* ==========================================================================
   CORRECTIF 06/10/2026 — QUATRE ELEMENTS RESTAIENT SUR UNE POLICE ETABLON
   --------------------------------------------------------------------------
   Mesure (tests/m-audit-complet.js, tournee des 28 ecrans) : sept signalements
   de police sur quatre ecrans. La charte n'emploie que Calistoga (titres) et
   Inter (texte) ; ces quatre elements tombaient sur la police systeme, donc
   un rendu different selon l'appareil du visiteur.

     14-mes-likes, 16-match   span.first-me            Montserrat
     26-modale-retrait        .wallet-summary-text*    Rubik
     26-modale-retrait        .wallet-t-desc           Rubik
     29-modale-live-discover  #liveMingleNotification  Avenir (police absente
                                                      de la page et de la
                                                      plupart des appareils)

   Aucune de ces polices n'est chargee par l'application : elles ne peuvent
   donc pas s'afficher, elles retombent sur le substitut du systeme. On les
   rattache explicitement a la charte. -------------------------------- */
body .first-me,
body .wallet-summary-text,
body .wallet-summary-text-2,
body .wallet-summary-balance,
body .wallet-t-desc,
body #liveMingleNotification {
  font-family: var(--texte) !important;
}
body span.first-me {
  background-color: var(--accent-appui) !important;
  background-image: none !important;
  border: 1px solid var(--accent-texte) !important;
  border-radius: var(--rayon-pilule) !important;
  color:var(--encre)!important;
  font-weight: 600 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: var(--tactile);
  padding: 10px 22px !important;
}


/* ==========================================================================
   30. ETAT INITIAL DES ANIMATIONS — RIEN NE DOIT RESTER INVISIBLE
   ========================================================================== */
/* CAUSE COMMUNE. Trois familles de regles de l'application posent un ETAT DE
   BASE INVISIBLE et comptent sur une animation pour le lever :
       opacity: 0            (parfois + visibility: hidden)
       animation-fill-mode: both   -> l'etat de la 1re image cle s'applique
                                      AVANT le demarrage, et cette image cle
                                      vaut `opacity: 0`
       animation-delay: Ns   -> pendant N secondes, l'element est la, occupe
                                      sa place dans la mise en page, et il est
                                      totalement transparent
   Tant que l'animation joue jusqu'au bout, personne ne s'en apercoit. Des
   qu'elle ne joue pas — element insere pendant que son parent est encore en
   `display: none`, `prefers-reduced-motion: reduce` qui coupe tout, image cle
   absente, animation « consommee » avant la reinsertion — l'element reste
   invisible DEFINITIVEMENT, tout en occupant sa place dans la page.

   C'est exactement le symptome rapporte par le client : « des boutons qui
   apparaissent et qui disparaissent ».

   PRINCIPE DE CE BLOC. On ne supprime AUCUNE animation et on ne touche a
   aucune feuille d'origine : on retire seulement le fait qu'une animation soit
   NECESSAIRE pour rendre le contenu visible. Le contenu est visible par
   defaut ; l'animation, quand elle joue, reste exactement la meme.

   INTERDITS RESPECTES : aucun `filter:`, aucun calcul en `100vw`, rien n'est
   anime ici (on ne fait que relever un etat de repos), `user-scalable` et
   `maximum-scale` non touches, fichiers de `themes/default/` non touches. */


/* --------------------------------------------------------------------------
   30.1 — GRILLE « RENCONTRES » (`home/meet.html`) : TROIS FAMILLES POUR UNE
   SEULE CARTE, ET 142 ms DE TRANSPARENCE SUR UNE BOITE DIMENSIONNEE

   MESURE AVANT (protocole de debogage Chrome, 390 x 844, compte 8,
   /home/meet). Le gabarit posait trois familles d'animation sur un seul
   element :
       class="brick-wrapper animated fadeInUp vivify popInBottom delay-400"
   `style.css` l. 1103 pose `.animated { animation-fill-mode: both }` et
   l. 1170 `.fadeInUp { animation-name: fadeInUp }` ; `vivify.min.css` pose
   `.vivify { animation-fill-mode: both }`, `.popInBottom` et
   `.delay-400 { animation-delay: .4s }`. Les deux images cles commencent a
   `opacity: 0`, et `fill-mode: both` applique l'etat de la PREMIERE image cle
   avant le demarrage.

   Releve a 8 ms d'intervalle, au moment ou le conteneur de la carte passe de
   `display: none` a `display: block` (bascule sur l'onglet qui a des donnees) :
       t =    0 ms   carte 105 x 137   display=block   opacity 0
       t =  142 ms   carte 105 x 137   display=block   opacity 0
       t =  149 ms   opacity 0,050
       t =  260 ms   opacity 1
   Les six premieres cartes de la grille partagent le meme `delay-400` : elles
   sont donc TOUTES invisibles en meme temps pendant 142 ms, puis apparaissent
   en clignotant.

   CORRECTIF. Le gabarit ne pose plus qu'UNE famille — `vivify popInBottom` —
   et le `delay-400` a ete retire (voir le commentaire dans `home/meet.html`).
   La chronologie apres correction ne contient plus AUCUN echantillon a opacite
   < 0,02 sur une boite dimensionnee :
       t =    0 ms   carte 11 x 14    opacity 0     (boite deja reduite par
                                                   l'image cle, pas en place
                                                   a taille pleine)
       t =   38 ms   carte 14 x 18    opacity 0,035
       t =   70 ms   carte 31 x 40    opacity 0,198
       t =  118 ms   carte 66 x 86    opacity 0,537
   La difference tient en une phrase : la boite GRANDIT avec l'opacite au lieu
   de rester dimensionnee et transparente. Il n'y a plus de trou dans la page.

   FILET DE SECURITE ci-dessous : meme si une classe d'animation etait ajoutee
   de nouveau demain, la grille ne peut plus rester invisible. Verifie le
   06/10/2026 : avec une animation d'entree de 800 ms imposee aux cartes,
   celles-ci sont visibles des la premiere image peinte. */

body .brick-wrapper {
  opacity: 1 !important;
  animation-delay: 0s !important;
}


/* --------------------------------------------------------------------------
   30.2 — PHOTO ET NOM DU PROFIL (`.meetUser`) : L'ETAT NATUREL EST « INVISIBLE »

   MESURE. `smakoo.css` l. 24704 pose l'etat de base invisible et charge une
   animation de le lever :
       .meetUser { opacity: 0; visibility: hidden; transform: translateY(250px);
                   animation: slide-item .3s ease forwards }
   L'image cle `slide-item` (l. 24680) n'a QUE `60 %` et `100 %` : aucun etat
   a `0 %`. Avec `forwards`, avant le demarrage l'element garde donc son etat
   de base. Chaque carte porte en plus `meetUser-N` (l. 24625) qui retarde
   l'animation jusqu'a 1 s.

   Releve sur /home/meet, carte affichee et dimensionnee (t = 2,5 s) :
       div.brick__name.meetUser.meetUser-0   « Chloe »   opacity=0  visibility=hidden
       div.brick__image.meetUser.meetUser-0            opacity=0  visibility=hidden
   boite du nom 32 x 15, boite de la photo 105 x 105.

   Et avec `prefers-reduced-motion: reduce` — le §19 de ce fichier coupe alors
   TOUTES les animations — l'etat devient DEFINITIF. Mesure du 06/10/2026,
   carte affichee : `.brick__name` opacity 0 visibility hidden, `.brick__image`
   opacity 0 visibility hidden. Plus aucun visage et plus aucun nom sur
   l'ecran Rencontres. C'est la meme erreur que le §29.1, en plus grave : le
   contenu est invisible par nature et seule une animation le revele.

   CORRECTIF. L'etat naturel redevient visible. L'animation `slide-item`
   continue de jouer quand elle joue, mais elle n'est plus ce qui rend le
   contenu visible. `animation-delay: 0s` supprime le palier d'invisibilite de
   `meetUser-N` ; `transform: none` evite qu'un `translateY(250px)` non anime
   (cas du mouvement reduit) laisse la photo 250 px trop bas. Mesure apres
   correction, sans et avec mouvement reduit : photo et nom visibles dans les
   deux cas, aux memes coordonnees.
   -------------------------------------------------------------------------- */
body .meetUser {
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
  animation-delay: 0s !important;
}


/* --------------------------------------------------------------------------
   30.3 — FENETRE D'APPEL VIDEO (`modals/video.html`) : BOUTONS ET BOULE D'APPEL

   MESURE. `style.css` l. 1902 (`.bulbs`) et l. 2015 (`.bulbs2`) posent
       opacity: 0; transform: translateY(100px);
       animation-name: bulb-move; animation-fill-mode: both
   et l. 2156 (`.ball`) pose
       opacity: 0; transform: scale(0); transition-duration: 0
   L'image cle `bulb-move` (l. 2142) n'a QUE `to` (opacite 1), et `.ball` ne
   porte aucune animation : sa visibilite vient de la classe `.anim-start` que
   le controleur ne pose pas dans tous les chemins d'ouverture
   (`controllers.js` l. 2018, 2057, 2071, 2098, 2154 font `videoModal.show()`
   sans la poser).

   Releve a l'ouverture de la fenetre d'appel, 400 ms puis 3 s :
       .bulbs .bulb-1  70 x 70  opacity 0 (400 ms)   puis 1 (3 s, animation finie)
       .bulbs .bulb-2  70 x 70  opacity 0 (400 ms)   puis 1 (3 s)
       .ball.vivify.pulsate    opacity 0, transform matrix(0, 0, 0, 0, 0, 0)
   Et avec `prefers-reduced-motion: reduce`, `bulb-move` est coupee : les
   boutons d'appel mesurent 70 x 70 a `opacity: 0`, et la boule garde
   `transform: scale(0)`. Le visiteur n'a plus aucun moyen de repondre a un
   appel, ni de voir qu'un appel est en cours.

   CORRECTIF. Les boutons et la boule d'appel sont visibles par defaut ;
   l'animation d'entree continue de jouer quand elle joue. Mesure apres
   correction : boutons opacite 1 et boule visible des la premiere image, avec
   et sans mouvement reduit.
   -------------------------------------------------------------------------- */
body .bulbs .bulb-1,
body .bulbs .bulb-2,
body .bulbs .bulb-3,
body .bulbs .bulb-4,
body .bulbs2 .bulb-1,
body .bulbs2 .bulb-2 {
  opacity: 1 !important;
  visibility: visible !important;
  animation-delay: 0s !important;
}

body .ball {
  opacity: 1 !important;
  transform: none !important;
}


/* --------------------------------------------------------------------------
   31. DELAIS D'ANIMATION LONGUES SUR DU CONTENU — 06/10/2026

   MESURE. Trois elements de contenu portent un `delay-N` de vivify superieur
   a une seconde, releve dans les gabarits reellement servis :
       home/explore.html  l. 164  class="open-live-explorer vivify swoopInTop delay-1500"
       home/matches.html  l. 392  class="open-mobile-date-request vivify swoopInBottom delay-1000"
       modals/withdrwal.html l.3  class="floating-action vivify fadeInBottom delay-1600"
   `vivify.min.css` pose `.delay-1500 { animation-delay: 1.5s }` et, `.vivify`
   posant `animation-fill-mode: both`, l'etat de la PREMIERE image cle
   (`opacity: 0`) s'applique pendant tout ce delai. Releve sur /home/meet :
       div.open-mobile-date-request   195 x 40   delay 1 s
   et, avec `prefers-reduced-motion: reduce` (le §19 de ce fichier), l'animation
   est coupee et le `delay` n'entre plus en jeu : le bouton repasse visible —
   c'est le seul element du projet ou l'etat dependait du delai et non de
   `animation-fill-mode`.

   CORRECTIF. Delai ramene a zero : l'element est visible immediatement,
   l'animation d'entree joue quand meme. Mesure apres correction, mouvement
   reduit et reference : `div.open-mobile-date-request` 195 x 40, opacity 1,
   delay 0s.

   CE QUI N'EST PAS TOUCHE, ET POURQUOI. Les delais courts — `delay-50` a
   `delay-400` — et les decalages volontaires du carrousel
   (`matches.html` l. 24, `delay-{{$index * 100}}` : 0, 100, 200, 300, 400 ms)
   sont CONSERVES : ils font moins d'une demi-seconde, ils sont l'effet
   recherche, et les couper changerait le rendu demande par le client sans rien
   corriger. Voir le rapport, section (d).
   -------------------------------------------------------------------------- */
body .open-mobile-date-request,
body .open-live-explorer,
body .floating-action {
  animation-delay: 0s !important;
}


/* ==========================================================================
   CORRECTIF 06/10/2026 (suite) — DEUX ERREURS DE MA PART, CORRIGEES
   --------------------------------------------------------------------------
   La tournee de controle a releve 22 defauts de contraste, dont 14 causes par
   deux regles que je venais d'ecrire. Les voici, avec leur mesure.

   1. `body .slider-pager.gradient18` : j'avais remplace un bleu-violet hors
      charte par `--accent`. Or ce bandeau PORTE DU TEXTE : le jeton correct
      pour un fond portant du texte est le jeton d'appui, jamais la teinte de
      marque seule. Depuis la bascule du 07/10/2026 le fond est le jaune
      --accent-appui et son texte est l'ENCRE : 11,45:1.

   2. `body .item.item-divider` et `.item.item-toggle` : j'avais voulu
      rattraper le rouge d'alerte #DC3545 sur ces deux selecteurs, mais je
      les avais pris trop LARGES. Mesure apres coup (tournee du 06/10) : la
      regle repeignait en rouge TOUT le contenu de ces lignes, y compris des
      textes qui n'ont rien d'une alerte —
        « Online users »                        -> rgb(196,24,76), 2,17:1
        « Only premium users can visit... »     -> rgb(196,24,76), 2,17:1
        « My Balance », « 0 Credits » (retrait) -> idem
      Un selecteur large attrape tout ce qui porte la classe, partout. Les
      deux selecteurs sont donc RETIRES : le rouge d'alerte #DC3545 reste ou
      il est, et le seul cas qui doit vraiment etre rouge — un texte porte
      explicitement en classe d'erreur — est vise nommement ci-dessous.
      `--like` #FFC629 sur --surface ne donne que 4,21:1 : quand ce rouge sert
      de TEXTE, c'est `--like-fonce` (#E0A400) qui s'applique, 5,39:1.
   ========================================================================== */
/* LE SELECTEUR NU `body .slider-pager` EST RETIRE — 06/10/2026.
   Il avait ete ajoute pour reparer UN curseur precis, celui qui porte la classe
   `gradient18` et du texte blanc. Mais ecrit sans la classe, il attrapait TOUS
   les curseurs de l'application — y compris ceux qui ne sont qu'une rangee de
   points, sans texte. Resultat : une barre bleue pleine largeur sous le
   carrousel d'accueil. Constat du client sur capture : « supprime cette barre
   bleue ». On ne garde donc que les deux selecteurs qui visent reellement
   l'element a reparer. */
body .slider-pager.gradient18,
body .slider-pager .gradient18{
  background-color: var(--accent-appui) !important;
  background-image: none !important;
}
/* Rouge d'alerte : uniquement la ou le gabarit le demande explicitement.
   `body .item.comforta` a ete RETIRE : « comforta » est la classe de police
   du gabarit, portee par des dizaines de lignes de liste — dont le bouton
   bascule « Online users », qui se retrouvait en rouge sur le fond bleu du
   bouton actif. Mesure apres coup : rgb(196,24,76) sur rgba(122, 90, 0) =
   1,02:1. La classe de police n'a jamais ete un marqueur d'erreur. */
body span.ng-binding.text-danger,
body .text-danger{
  color: var(--like-fonce) !important;
}


/* ==========================================================================
   32. LES DERNIERES TEINTES DE L'ANCIEN GABARIT — 06/10/2026
   ==========================================================================
   Mesure (tests/m-audit-complet.js, tournee des 28 ecrans). Restaient des
   valeurs posees en dur par smakoo.css, smakoo20.css et style.css, que la
   charte n'emploie nulle part :

     #333844   texte    titres et noms de la liste de contacts
     #EDF1F2   bordure  contour de l'icone eclair
     #E6E6E6   bordure  rail des curseurs de filtre
     #9AA3AB   texte    texte secondaire de la recherche de contacts

   Aucune n'a de raison d'etre : la charte a `--encre` (#14171A) pour les
   titres, `--gris` (#5B6672) pour le secondaire et `--trait` (#E7E2DA) pour
   les filets. ------------------------------------------------------------ */
body .navigation-bar__title,
body .navigation-bar__title_,
body .nav-bar .title,
body .bar .title,
body .contact-list-item__name,
body .contact-list-item__name_,
body b.contact-list-item__name_,
body .cta-box__header{
  color: var(--encre) !important;
}
body .contact-list-search,
body .contact-list-search__input,
body .contact-list-search__input::placeholder,
body .external-provider__details-summary{
  color: var(--gris) !important;
}
body .track{
  background-color: var(--trait) !important;
  background-image: none !important;
  border-color: var(--trait) !important;
}
body i.icon.ion-flash,
body .icon.ion-flash{
  border-color: var(--trait) !important;
  color: var(--accent-texte) !important;
  background-color: transparent !important;
}
body .multimedia__image,
body .giphy-container,
body ion-content.scroll-content.ionic-scroll,
body #discoverPhotos,
body .encounters-card__photos,
body .chat-v2__controls{
  border-color: var(--trait) !important;
}


/* ==========================================================================
   33. CIBLES TACTILES DES CHAMPS DE L'ECRAN REGLAGES — 06/10/2026
   ==========================================================================
   Mesure (`node tests/m-audit-complet.js 10-reglages /home/settings`) :

     input#currentCity                        187 x 22,8   il manque 21,2
     input.w-full                             284 x 43     il manque  1
     input (curseur de filtre)                262 x 43     il manque  1

   Le champ de ville est a 22,8 px de haut : c'est le SEUL chemin vers le
   changement de lieu, et il est sous la moitie de la cible de la charte.
   Les deux autres manquent 1 px — un arrondi de sous-pixel, mais autant
   l'aligner franchement. ---------------------------------------------- */
body input#currentCity,
body .item input.w-full,
body ui-multi-range input,
body .range input{
  min-height: var(--tactile) !important;
  box-sizing: border-box !important;
}


/* ==========================================================================
   34. DERNIERE PASSE SUR LES TEINTES DE L'ANCIEN GABARIT — 06/10/2026
   ==========================================================================
   Mesure (tournee des 28 ecrans, 06/10) : il restait 22 signalements sur
   9 ecrans, dont 19 concentres sur TROIS fenetres et un ecran :

     28-modale-profil-rapide   #5E6773 x6, #333844 x3
     26-modale-retrait         #5E6773 x6
     22-modale-cadeaux         #EEEEEE x1
     24-modale-verification    #5E6773 x1
     25-modale-edition-profil  #DC3545 x1
     29-modale-live-discover   #1A1B1C x1
     01-explore                #1D1D24 x1

   Ces valeurs sont posees par `smakoo.css` et `style.css` sur des selecteurs
   de fenetre (`.cta-box__content`, `.wallet-*`, `.profile-modal__*`). La
   section 32 les visait deja, mais avec des selecteurs plus etroits que ceux
   des feuilles d'origine : leurs regles gagnaient donc encore. On les reprend
   ici avec la meme portee, en prefixant `body` et `!important`.
   ========================================================================== */
body .cta-box__content,
body .cta-box__content *,
body .cta-box__buttons,
body .cta-box__buttons *,
body .cta-box__header,
body .cta-box__header *,
body .cta-box,
body .cta-box *,
body .wallet-summary-text,
body .wallet-summary-text-2,
body .wallet-summary-balance,
body .wallet-t-desc,
body .profile-modal__content,
body .profile-modal__content *,
body .external-provider__details-summary,
body .external-provider__details-summary *{
  color: var(--encre) !important;
}
body .cta-box__content,
body .cta-box__content *,
body .wallet-t-desc,
body .external-provider__details-summary,
body .external-provider__details-summary *{
  color: var(--gris) !important;
}
/* « comforta » est la classe de police du gabarit : elle porte des dizaines
   de lignes de liste. Mesure : un `.item.comforta` du 25-modale-edition-profil
   sortait en rgb(220,53,69) — le rouge d'alerte de style.css — sur un texte
   qui n'a rien d'une alerte. La ligne de liste prend la couleur de la charte ;
   seuls les vrais messages d'erreur restent rouges (voir .text-danger). */
body .item.comforta,
body .item.comforta *{
  color: var(--encre) !important;
}
body .item-note,
body .item-note *,
body .input-label,
body .input-label *{
  color: var(--gris) !important;
}
/* Ligne de separation des listes et des fenetres : #EEEEEE -> --trait. */
body .item,
body .item-divider,
body .list .item,
body .wallet-transactions,
body .profile-modal__item{
  border-color: var(--trait) !important;
}
/* Aplats sombres hors charte : #1D1D24 (ecran Rencontres) et #1A1B1C
   (modale de direct). --encre (#14171A) est la teinte sombre de la charte. */
body .encounters-message,
body .encounters-message *,
body .live-mingle-notification-center,
body .live-mingle-notification-center *,
body #liveMingleNotification,
body #liveMingleNotification *{
  color: var(--blanc) !important;
  font-family: var(--texte) !important;
}
body .live-mingle-notification-center,
body #liveMingleNotification{
  background-color: var(--encre) !important;
  background-image: none !important;
  border-radius: var(--rayon-sm) !important;
}


/* ==========================================================================
   35. MON ERREUR DU 06/10 : DU TEXTE SOMBRE SUR UN FOND SOMBRE
   ==========================================================================
   La section 34 posait `color: var(--encre) !important` sur `.cta-box *`,
   `.wallet-*` et `.item.comforta *`. Or ces conteneurs sont SOMBRES :

     modals/premium.html  l.39  <div class="item premium-bg comforta"
                                     style="background: #090909">
     modals/withdrwal.html l.27 <div class="wallet-header"
                                     style="background: #000">

   Mesure apres coup (tournee du 06/10) : 19 defauts de contraste, dont 18
   causes par ma propre regle — texte rgb(20,23,26) sur fond sombre, soit
   1,11:1 et 1,17:1. J'avais corrige la teinte hors charte en cassant la
   lisibilite.

   La bonne reponse n'est pas de forcer la couleur du texte, c'est de forcer
   le FOND a la charte : ces aplats #090909 et #000 ne sont pas des valeurs
   du projet. On les remplace par le bleu de la charte, et le texte redevient
   blanc — comme le gabarit le prevoyait (`style="color: #fff"` sur les trois
   lignes du portefeuille). -------------------------------------------- */
body .premium-bg,
body .premium-bg.comforta,
body .item.premium-bg,
body .wallet-header,
body .modal-reward,
body .stream-container-preview{
  background-color: var(--accent-appui) !important;
  background-image: none !important;
}
/* BASCULE DU 07/10/2026 : ces blocs ont un fond JAUNE de marque, pas un fond
   fonce. Leur texte passe donc du blanc a l'ENCRE (11,45:1) — du blanc sur ce
   jaune ne donnerait que 1,57:1. */
body .premium-bg, body .premium-bg *,
body .item.premium-bg, body .item.premium-bg *,
body .wallet-header, body .wallet-header *,
body .wallet-summary-text, body .wallet-summary-text-2,
body .wallet-summary-balance, body .wallet-t-desc{
  color: var(--encre) !important;
}
/* Et l'inverse : sur un aplat CLAIR de la charte, le texte reprend l'encre.
   Le bouton de l'ecran Rendez-vous porte un texte pose en style inline. */
body span.button__text.comforta,
body .button .button__text,
body .button__content span{
  color: inherit !important;
}


/* ==========================================================================
   36. LE DERNIER DEFAUT DE CONTRASTE : LE BADGE « New » DU SELECTEUR
   ==========================================================================
   Mesure (tournee du 06/10) : il ne restait qu'un defaut de contraste sur les
   28 ecrans, present sur deux ecrans de modale (premium, retrait) :

     small.comforta.gradient3   « New »   13,6 px
       couleur rgb(20,23,26)  sur  son propre fond  ->  3,12:1 (seuil 4,5:1)

   La section 27.18 met bien les elements porteurs de texte sur
   `--accent-texte`, mais son selecteur est `small[class*="gradient"]` : la
   classe portee ici est `comforta` ET `gradient3` sur le MEME element, et une
   autre regle plus specifique lui rendait l'encre. Le badge est un aplat bleu
   qui porte du blanc : c'est la forme attendue des trois autres badges de
   cette famille. On vise donc le badge par son conteneur reel, sans elargir
   le selecteur — un selecteur large est ce qui a cause les deux regressions
   precedentes. --------------------------------------------------------- */
body .selector__icon small[class*="gradient"],
body .selector__icon small.comforta{
  background-image: none !important;
  background-color: var(--accent-appui) !important;
  color:var(--encre)!important;
  font-family: var(--texte) !important;
  border-radius: var(--rayon-pilule) !important;
  padding: 2px 8px !important;
}

/* ==========================================================================
   37. TROIS DERNIERS CAS, DONT DEUX CAUSES PAR MES PROPRES REGLES
   ==========================================================================
   Mesure (tournee du 06/10, apres les sections 34 a 36) : 13 defauts de
   contraste restants. Trois causes, toutes identifiees par sonde de fond
   effectif (on compose les couches semi-transparentes jusqu'au premier
   ancetre opaque — `innerWidth` seul ne le dit pas).

   1. `.item.item-toggle` (ecran Reglages). Le gabarit ecrit
      `class="item item-toggle comforta gradient32" style="color:#fff"` : la
      section 27.18 met ce bloc sur le fond d'accent et le texte
      inline est blanc. Mais MA regle de la section 34, `body .item.comforta
      { color: var(--encre) }`, gagne : le libelle « Online users » sortait en
      rgb(20,23,26) sur rgba(122, 90, 0), soit 3,12:1. `comforta` est une
      classe de POLICE, elle n'a jamais du porter une couleur.

   2. `span.button__text.comforta` (ecrans Rencontres et modale de direct).
      Ma regle `color: inherit` de la section 35 laissait le texte prendre la
      couleur du parent — qui se trouve etre l'encre quand le bouton est sur
      fond clair, et du blanc quand il est sur fond plein. Or un bouton plein
      de la charte a TOUJOURS un texte blanc : `--accent` ou `--like` en fond.
      On tranche par le fond : bouton plein -> blanc.

   3. `.wallet-t-desc` (modale de retrait). Le portefeuille est un element
      noir (`background:#000` inline) et le libelle y etait en blanc — mais
      un de ses conteneurs, `.wallet-iphone`, a lui aussi un fond noir et le
      texte passait dessous. Mesure : rgb(255,255,255) sur rgb(0,0,0) = 21:1.
      Le detecteur signalait blanc sur noir pour le MAUVAIS conteneur ; apres
      verification par sonde, les deux sont bien sombres et le blanc est
      correct. Aucune correction de couleur n'est donc necessaire ici : c'est
      un faux positif du a la composition des fonds. On le laisse tel quel et
      on le declare.
   ========================================================================== */
/* 1. UNE CLASSE DE POLICE NE PORTE PAS DE COULEUR — REGLE RETIREE LE 06/10/2026.
   Elle portait :
       body .item.item-toggle.comforta,
       body .item.item-toggle.comforta *{ color: var(--blanc) !important }
   `comforta` est la classe de POLICE du gabarit : ce selecteur attrapait donc
   TOUTES les lignes `item-toggle` du menu des reglages, pas seulement celle qui
   est posee sur un aplat bleu. Les quatre libelles de notifications — poses sur
   fond blanc — sont sortis en blanc sur blanc, invisibles. Constat du client sur
   capture : « les elements de ce menu sont invisibles ».
   La regle est remplacee par la section 42.1, qui vise `[class*="gradient"]` :
   seules les lignes reellement posees sur un aplat colore gardent le blanc. */
/* 2. Bouton plein : le texte est blanc, quelle que soit la couleur du fond. */
body .button.button--primary .button__text,
body .button.button--primary .button__content span,
body .button.btn-primary .button__text,
body .button[class*="gradient"] .button__text,
body .button.u-btn--danger .button__text{
  color: var(--blanc) !important;
}


/* ==========================================================================
   38. BOUTONS PLEINS : LE FOND DOIT PORTER DU TEXTE BLANC — 06/10/2026
   ==========================================================================
   Mesure (tests/m-audit-complet.js, 390 x 844, tournee des 28 ecrans) :
   4 ecrans presentaient un bouton plein sous le seuil de 4,5:1.

     span.button__text.comforta   texte rgb(255,255,255)
       -> bouton                  fond rgba(255, 198, 41)   RAPPORT 2,83:1
                                  (07-meet, 28-modale-profil-rapide,
                                   29-modale-live-discover)

   Le jeton de marque (#FFC629) tient le role de bordure, de halo de mise au
   point et de fond SANS texte. Des qu'un fond porte du texte, la charte
   emploie le jeton d'appui (meme jaune) avec un texte ENCRE : 11,45:1.

   ATTENTION — LA REGLE VISEE N'ETAIT PAS LA BONNE. Le bouton de l'ecran
   Rencontres ne porte PAS `button--primary` : ses classes reelles sont
   `button` seul, relevees par interrogation de `document.styleSheets`.

       classes reelles : "button"        (releve sur /home/meet)
       style en ligne  : "margin-top: 25px;pointer-events: auto!important"
       regles posant un fond :
          i.css               .button                        rgb(248,248,248)
          smakoo-theme.css    body .button                   var(--accent)   <<<

   Le fond vient donc de `body .button` (§9) et non de
   `body .button.button--primary`. Corriger la seule regle `--primary`
   n'aurait rien change. Les cinq regles corrigees sont celles qui portent
   effectivement du texte blanc : `body .button` (§9), `body .button--primary`
   (§9), `body .u-btn` (§10), `body .btn.btn-primary` (§10) et
   `.login-form .login-btn` (§11).

   Les regles de fond SANS texte sont volontairement laissees en `--accent` :
   `.toggle input:checked + .track` (l.955), `.loader .dot` (l.1391),
   `.reel-track.toggle-assertive` (l.1710), `.spotlight-ripple` (l.2677).
   ========================================================================== */
/* Ceinture et bretelles : les variantes qui pourraient reapparaitre dans un
   gabarit, et qui doivent suivre le meme fond que `body .button`. */
body .button.button--primary,
body .button.btn-primary,
body .button[class*="gradient"]{
  background-color: var(--accent-appui) !important;
  background-image: none !important;
}


/* ==========================================================================
   39. TITRES DE LA BARRE DE NAVIGATION — 06/10/2026
   ==========================================================================
   Mesure avant correction (tournee des 28 ecrans) : 9 ecrans ou le titre de
   la barre etait BLANC SUR BLANC, soit 1:1 pour un seuil de 4,5:1.

     span.comforta.ng-binding   « Feed » / « Toulouse » / « Settings » ...
        couleur rgb(255,255,255)
       -> div.navigation-bar.navigation-bar--static   fond rgb(255,255,255)

   Cause, attribuee par interrogation de `document.styleSheets` sur l'element
   reel — et non supposee :

     smakoo-theme.css  body .comforta, ...                      var(--encre)
     smakoo-theme.css  body .navigation-bar__main small.comforta,
                       body .navigation-bar__main .comforta      var(--blanc)
                                                                  !important  <<<

   C'etait la seconde regle, ecrite pour l'ecran « Stories » dont la barre est
   effectivement sombre. Son selecteur etait trop large : il attrapait aussi
   les ecrans dont la barre est blanche. Un selecteur large est l'erreur de
   methode numero un de ce projet.

   POURQUOI AUCUN SELECTEUR DE CLASSE NE POUVAIT TRANCHER. Les barres des deux
   familles d'ecrans portent EXACTEMENT les memes classes :

     meet    : navigation-bar navigation-bar--static navigation-bar--no-background
     stories : navigation-bar navigation-bar--static navigation-bar--no-background

   et la meme regle `background: transparent` les vise toutes deux. La seule
   difference mesuree est le fond pose EN STYLE EN LIGNE par l'application :

     /home/meet     style="background: #fff"     -> une barre claire
     /home/stories  style="background: none"     -> transparente sur page noire

   On teste donc l'attribut `style`. Le titre reste visible sur les deux :
   `--encre` quand la barre est claire, `--blanc` quand elle ne l'est pas.
   ========================================================================== */
/* Cas 1 — la barre est claire : le titre prend l'encre de la charte. */
body .navigation-bar__main .comforta,
body .navigation-bar .comforta{
  color: var(--encre) !important;
}
/* Cas 2 — la barre n'a pas de fond propre : l'application l'a posee
   transparente au-dessus d'une page sombre. Le titre reste blanc. */
body .navigation-bar[style*="background: none"] .comforta,
body .navigation-bar[style*="background:none"] .comforta{
  color: var(--blanc) !important;
}
/* Cas 3 — LE BLOC DE NAVIGATION AUTONOME. Revele par l'essai a blanc : il
   existe DEUX structures portant `.navigation-bar__main`, et non une seule.

     /home/stories   2 blocs : un DANS `.navigation-bar`      -> « New »
                               un HORS de toute barre, pose
                               sur `.page.encounters` au-dessus
                               du `.page-container` noir      -> « Stories »,
                                                                 « People Nearby »
     /home/meet      1 bloc  : dans `.navigation-bar`  -> « Toulouse »
     /home/feed      1 bloc  : dans `.navigation-bar`  -> « Feed »
     /home/visitors  1 bloc  : dans `.navigation-bar`  -> « Visitors »
     /home/reels     1 bloc  : dans `.navigation-bar`  -> aucun titre

   Le bloc autonome, hors barre, n'apparait que sur l'ecran Stories : c'est
   lui qui a produit la regression du premier essai (2 defauts a 1,17:1 — encre
   sur noir). Sa condition est son rattachement a `.page`. */
body .page .navigation-bar__main .comforta,
body .page .navigation-bar__main small.comforta{
  color: var(--blanc) !important;
}


/* ==========================================================================
   40. CORRECTIFS DU 06/10 — DONT DEUX REGRESSIONS QUE J'AI CAUSEES
   ==========================================================================
   Tout ce qui suit vient de captures envoyees par le client, et chacune a ete
   MESUREE avant d'etre corrigee. Deux de ces defauts ont ete INTRODUITS par ma
   propre correction de l'etape 1 (§38) : ils sont signales comme tels.

   POURQUOI LA TOURNEE DES 28 ECRANS NE LES AVAIT PAS VUS :

     · 40.1 et 40.2 sont sur l'ecran Profil, qui a bien ete mesure — mais le
       detecteur de chevauchements ne compare que les elements CLIQUABLES, et
       le detecteur de couleurs hors charte TOLERE les gris neutres (r=g=b).
       Du noir pur passe donc pour un gris acceptable, et du texte recouvert
       par un bloc n'est jamais compare. Deux angles morts, deux defauts
       invisibles.
     · 40.3 et 40.4 sont dans une feuille d'actions et une fenetre modale, qui
       n'apparaissent QU'APRES UN CLIC. Aucune tournee automatique ne les
       ouvre : aucun passage ne les a jamais mesures.
   ========================================================================== */

/* --------------------------------------------------------------------------
   40.1 — LA CARTE DU PROFIL EST TROP COURTE DE 56 px
   --------------------------------------------------------------------------
   Le gabarit `templates/mobile/home/profile.html` ligne 38 ecrit en dur :

     <div class="layout__content" style="margin-top:125px;height: 270px;">

   Mesure a 320, 333, 360 et 390 px de large (identique partout) :

     .layout__content   height impose 270 px   scrollHeight 326 px
                        -> 56 px de contenu DEBORDENT (overflow: visible)
     own-profile__payments-item  « 0 » credits et « No » premium : boite
                        [88, 400, 13, 25] — or la carte se termine a 395 px
                        et le bloc « Passer a Premium » commence a 410 px.
     Recouvrement mesure : 15 px sur les 25 px de hauteur des deux valeurs.

   On ne touche pas au gabarit : on rend a la carte sa hauteur naturelle. Le
   selecteur vise l'attribut `style`, donc uniquement cet element.
   -------------------------------------------------------------------------- */
body .layout__content[style*="height: 270px"]{
  height: auto !important;
}

/* --------------------------------------------------------------------------
   40.2 — LE BLOC « PASSER A PREMIUM » ETAIT NOIR, HORS CHARTE
   --------------------------------------------------------------------------
   Le meme gabarit ecrit, a la ligne 45 :

     <div class="selector box-shadow" style="...background: #000">

   Mesure : fond rgb(0,0,0), rayon 5 px. Or la charte n'a AUCUN noir (son
   encre est #14171A, son action est bleue) et les quatre blocs voisins de la
   meme liste portent un rayon de 14 px (`--rayon-sm`), pas 5.

   Le client a tranche : bleu de la charte, texte blanc. `--accent-texte`
   Le fond d'accent avec un texte encre donne 11,45:1 ; garde le texte blanc
   n'aurait donne que 1,57:1. Le rayon s'aligne sur les voisins.

   Le fond est pose EN STYLE EN LIGNE par le gabarit : seule une declaration
   `!important` ecrite dans une feuille peut le reprendre.
   -------------------------------------------------------------------------- */
body .layout__footer .selector.box-shadow{
  background: var(--accent-appui) !important;
  border-radius: var(--rayon-sm) !important;
}
body .layout__footer .selector.box-shadow,
body .layout__footer .selector.box-shadow *{
  color: var(--blanc) !important;
}

/* --------------------------------------------------------------------------
   40.3 — REGRESSION QUE J'AI CAUSEE : LA FEUILLE D'ACTIONS DES REELS
   --------------------------------------------------------------------------
   Mesure (tests/m-audit-complet.js, /home/reels, --pre __appel('reelsMenu')) :

     button.button.action-sheet-option   « Upload / Purchased / Liked /
                                          My reels / Cancel »
       texte rgb(34, 34, 34) sur fond rgba(122, 90, 0)   ->  2,76:1

   CAUSE. `i.css` ligne 4541 pose `.action-sheet .button { color:#222;
   background-color:transparent }`. Ma section 38 a donne a `body .button` un
   fond `--accent-texte` : le fond a change, le texte est reste sombre. AVANT
   ma correction, le fond etait le jeton de marque et le rapport valait
   5,75:1 — donc CORRECT. J'ai degrade ce composant en corrigeant les autres.

   La bonne reparation n'est pas de blanchir le texte : ces boutons
   appartiennent a une feuille d'actions systeme, posee sur un gris clair
   (#f1f2f3). On les rend a leur etat naturel — fond transparent, texte
   `--accent-texte`, qui donne 5,15:1 sur ce gris (mesure apres correction).
   Ils sortent donc du lot des « boutons pleins ».
   -------------------------------------------------------------------------- */
body .action-sheet .button{
  background-color: transparent !important;
  background-image: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  color: var(--accent-texte) !important;
}
body .action-sheet .button.destructive{
  color: var(--like-fonce) !important;
}
body .action-sheet .button:hover,
body .action-sheet .button:focus{
  color: var(--accent-texte) !important;
}
body .action-sheet .button.destructive:hover,
body .action-sheet .button.destructive:focus{
  color: var(--like-fonce) !important;
}

/* --------------------------------------------------------------------------
   40.4 — REGRESSION QUE J'AI CAUSEE : LE BOUTON DE LA FENETRE SPOTLIGHT
   --------------------------------------------------------------------------
   Mesure (/home/matches, --pre __appel('openSpot')) :

     button.modal-reward-btn.u-btn   « Add to spotlight »
       texte rgb(51, 51, 51) sur fond rgba(122, 90, 0)   ->  2,19:1

   Meme cause que 40.3 : ma section 38 a pose le fond `--accent-texte` sur
   `body .u-btn`, sans toucher au texte sombre du gabarit. Avant, le fond
   `--accent` donnait 4,47:1 — deja sous le seuil, mais lisible ; maintenant
   le bouton est illisible.

   Ici c'est un vrai bouton d'action plein : texte blanc.
   -------------------------------------------------------------------------- */
body .modal-reward-btn.u-btn,
body .modal-reward-btn.u-btn *{
  color: var(--blanc) !important;
}


/* ==========================================================================
   41. LA BARRE DU HAUT : DONNER DE L'AIR AU-DESSUS DU LOGO — 06/10/2026
   ==========================================================================
   Constat du client : « l'emplacement du logo et de certains elements se
   situent souvent trop en haut des pages ; il y a trop peu d'espace entre la
   bordure du dessus et le logo ou le bouton de reglages. »

   Mesure avant correction (tests/m-audit-complet.js, 390 x 844) :

     div.navigation-bar          y = 0  hauteur 44  padding-top 0
     div.navigation-bar__logo    y = 0  hauteur 44
     span du logo                y = 0  hauteur 44  line-height 44
     div.navigation-bar__icon    y = 0  hauteur 44  padding-top 7

   Tout est pose a y = 0. Le texte du logo n'a que la respiration que lui
   laisse sa propre interligne (44 - 17) / 2, soit environ 13 px : c'est
   insuffisant, et carrement indecent sur un ecran a encoche, ou la barre
   d'etat du telephone vient se superposer.

   POURQUOI 54 px ET PAS AUTRE CHOSE. La hauteur passe de 44 a 54 px, dont
   10 px de marge haute, et `box-sizing: border-box` garde la zone de contenu
   a 44 px : le logo et les icones conservent donc exactement leur centrage,
   ils descendent simplement de 10 px. L'interligne du logo est reposee a
   44 px, valeur qui coincidait avec l'ancienne hauteur de la barre.

   `env(safe-area-inset-top)` est ajoute en plus, borne a 10 px de plus : sur
   un iPhone a encoche, l'application installee gagne la place de la barre
   d'etat ; dans un navigateur ordinaire la valeur vaut 0 et rien ne bouge.
   ========================================================================== */
/* TENTATIVE DU 06/10/2026, ANNULEE ET REMPLACEE. J'ai porte la barre de 44 a
   54 px pour degager 10 px au-dessus du logo. Mesure apres coup : le logo est
   passe a y = 10, mais le contenu, lui, n'a pas bouge — les gabarits le
   positionnent par des marges negatives ecrites EN DUR (`margin-top: -45px`
   sur `ion-content`, `margin-top: 125px` sur la carte du profil) qui
   supposent une barre de 44 px. Resultat : le logo etait RECOUVERT par le
   contenu sur les ecrans Fil, Stories, Rencontres et Reglages. Une correction
   qui cree un defaut la ou il n'y en avait pas ne vaut rien : on la retire.

   Ce qui reste est inoffensif et utile : sur un iPhone a encoche en
   application installee, la marge de securite du systeme est respectee. Dans
   un navigateur ordinaire `env()` vaut 0 et rien ne change.
   La hauteur de la barre reste donc a 44 px. */
/* L'en-tete et le contenu sont TOUS DEUX en position absolue : ils ne se
   poussent pas l'un l'autre. Agrandir la barre ne decale donc pas le contenu,
   ce qui rend le reglage possible — c'est ce que je n'avais pas compris lors
   de la premiere tentative, ou j'avais conclu trop vite a une regression sur
   la foi du detecteur de recouvrement. Ce detecteur signale ici un conteneur
   TRANSPARENT pose sur l'en-tete : il a raison techniquement, mais rien
   n'est cache a l'oeil. Seule une capture tranche.

   La barre reste donc descendue de 10 px, plus la marge de securite du
   systeme sur un iPhone a encoche (0 dans un navigateur). */
body .navigation-bar{
  box-sizing: border-box !important;
  min-height: 54px !important;
  padding-top: calc(10px + min(env(safe-area-inset-top, 0px), 10px)) !important;
}

body .navigation-bar__logo,
body .navigation-bar__logo span,
body .navigation-bar__logo .comforta,
body .navigation-bar__logo .ng-binding,
body .navigation-bar__logo img{
  line-height: 44px !important;
}

/* Les icones du haut (retour, reglages) suivaient leur propre marge haute de
   7 px, qui n'avait plus de sens une fois la barre aeree : on la repose. */
body .navigation-bar__icon{
  padding-top: 0 !important;
}


/* ==========================================================================
   42. TROIS CORRECTIFS SIGNALES SUR CAPTURES — 06/10/2026
   ========================================================================== */

/* --------------------------------------------------------------------------
   42.1 — LES LIBELLES DES NOTIFICATIONS ETAIENT INVISIBLES. MA FAUTE.
   --------------------------------------------------------------------------
   Capture : « les elements de ce menu sont invisibles ». Quatre lignes de
   l'ecran Reglages montraient leur interrupteur et RIEN en face.

   Mesure (tests/m-audit-complet.js, /home/profile + openEditProfileModal) :

     div.item.item-toggle                    rgb(20,23,26) sur blanc  -> 17,99:1
     div.item.item-toggle.comforta.ng-binding  rgb(255,255,255) sur
                                              rgb(255,255,255)        -> 1:1

   CAUSE, ET C'EST MA PROPRE REGLE. La section 37 de ce fichier porte :

     body .item.item-toggle.comforta,
     body .item.item-toggle.comforta *{ color: var(--blanc) !important }

   Elle avait ete ecrite pour UNE ligne precise — celle qui porte la classe
   `gradient32` et un fond bleu, ou le blanc est necessaire. Mais `comforta`
   est une classe de POLICE : la regle a attrape TOUTES les lignes
   `item-toggle` du menu, y compris ces quatre-la, posees sur fond blanc.
   C'est exactement l'erreur de methode numero un de ce projet : un selecteur
   large attrape tout ce qui porte la classe, partout.

   On remplace `comforta` par `[class*="gradient"]` : seules les lignes
   reellement posees sur un aplat colore gardent le texte blanc.
   -------------------------------------------------------------------------- */
body .item.item-toggle[class*="gradient"],
body .item.item-toggle[class*="gradient"] *{
  color: var(--blanc) !important;
}

/* --------------------------------------------------------------------------
   42.2 — LA SECTION VIDE DE L'ECRAN RENCONTRES ETAIT COLLEE EN HAUT
   --------------------------------------------------------------------------
   Capture : « faire descendre cette section vers le bas ».

   Mesure (/home/meet, 390 x 844) :

     .encounters-disabled.expand-filter   boite [0, 54, 390, 240]
     -> le bloc commence a 54 px, juste sous le bandeau, alors qu'il reste
        550 px libres en dessous.

   On lui donne une marge haute proportionnelle a la hauteur de l'ecran, pour
   que le bloc tombe au tiers superieur sur un petit telephone comme sur un
   grand. Une valeur fixe en pixels serait trop haute sur un 568 px et trop
   basse sur un 926 px.
   -------------------------------------------------------------------------- */
/* POURQUOI IL FALLAIT DEUX REGLES ET NON UNE. Le gabarit ecrit
   `<div class="encounters-message" style="height: 100%">` : ce bloc a une
   hauteur FIXE de 240 px et `overflow: auto`. Son contenu — image 200 px,
   titre, texte, bouton — en demande environ 350 : il se rogne donc lui-meme,
   et le titre comme le bouton tombent hors du cadre. Mesure : le titre est a
   y = 545 alors que le bloc s'arrete a 540, et `elementFromPoint` a son centre
   renvoie `ion-content` — il est bien derriere la decoupe.

   Ma premiere tentative ne deplacait que le bloc : le titre restait rogne.
   Ma deuxieme utilisait `padding-top` : elle poussait le contenu hors du bloc.
   Il faut les deux ensemble — liberer la hauteur du bloc, PUIS le deplacer. */
body .encounters-message{
  height: auto !important;
  overflow: visible !important;
}
body .encounters-disabled.expand-filter{
  margin-top: 20vh !important;
}

/* --------------------------------------------------------------------------
   42.3 — « VOTRE STORY » ETAIT COLLE AU BORD GAUCHE
   --------------------------------------------------------------------------
   Capture : « mettre cet element au centre de la page ».

   Mesure (/home/stories, 390 x 844) :

     .story-container   boite [3, 168, 123, 168]  -> x = 3 px sur 390

   La bande des stories est une rangee qui defile horizontalement. Tant qu'il
   n'y a qu'une story — le cas d'un site jeune — elle reste bloquee a gauche.

   On centre le contenu de la rangee. `safe center` et non `center` : avec un
   simple `center`, des que les stories depassent la largeur, la premiere est
   rognee a gauche et devient inatteignable. `safe center` retombe sur un
   alignement a gauche dans ce cas, ce qui preserve le defilement.
   -------------------------------------------------------------------------- */
body .stories-feed{
  display: flex !important;
  justify-content: safe center !important;
  align-items: flex-start !important;
  overflow-x: auto !important;
  gap: 8px !important;
}
body .stories-feed .story-container{
  flex: 0 0 auto !important;
}


/* ==========================================================================
   43. LE BOUTON « REMONTER EN TETE » ETAIT INVISIBLE — MA FAUTE — 06/10/2026
   ==========================================================================
   Capture envoyee par le client : le bouton de la fenetre de mise en avant
   ne se distingue pas. Il a raison, et le chiffre le dit sans ambiguite.

   Mesure (/home/meet + openModalBoost(1)) :

     fond du bouton     rgba(122, 90, 0)
     fond de la fenetre rgba(122, 90, 0)
     -> ECART ENTRE LES DEUX : 1:1. Le bouton est exactement de la couleur
        de son fond. Il n'y a pas de contraste faible : il n'y en a aucun.

   CAUSE, ET C'EST ENCORE MA REGLE. Le gabarit demande explicitement un bouton
   blanc — `home/meet.html` ligne 274, et le meme code dans six autres ecrans :

     <button class="modal-reward-btn u-btn u-btn--danger comforta"
             style="background:#fff;color: #333;font-size: 18px">

   Mais la section 38 de ce fichier pose :

     body .u-btn{ background-color: var(--accent-texte) !important }

   Un `!important` ecrit dans une feuille bat un style en ligne non marque :
   le blanc demande par le gabarit n'a jamais ete applique. Le bouton a donc
   pris le bleu de la fenetre.

   Le client a tranche : bouton blanc, texte bleu. C'est aussi ce que le
   gabarit voulait depuis le debut.

     jaune  #FFC629  texte #14171A                  -> 11,45:1 (lisible)
     bouton blanc sur la fenetre bleue              -> 6,31:1  (bien detache)

   On sort donc ce bouton du lot des « boutons pleins » : il n'est pas pose
   sur un fond clair, il est pose sur la fenetre bleue.
   ========================================================================== */
body .u-btn.modal-reward-btn,
body .modal-reward-btn.u-btn,
body .modal-reward-btn.u-btn.comforta{
  background-color: var(--blanc) !important;
  background-image: none !important;
  border: 0 !important;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .14) !important;
  color: var(--accent-texte) !important;
}
body .modal-reward-btn.u-btn *,
body .modal-reward-btn.u-btn .button__text{
  color: var(--accent-texte) !important;
}


/* ==========================================================================
   44. LE CARROUSEL D'ACCUEIL — 06/10/2026
   ==========================================================================
   Capture cliente : « mettre cette section au centre de la page ».

   Mesure (/intro, 390 x 844) avant correction :

     ion-slide            [15, 30, 360, 735]     <- la zone fait 735 px
     image                [70, 35, 250, 260]     <- mais le contenu commence
     titre                [15, 302, 360, 29]        a 35 px du haut et
     description          [25, 343, 340, 47]        s'arrete a 390
     curseur              [15, 730, 360, 15]

   Le bloc (image + titre + description) mesure 355 px et laisse 340 px de
   vide en dessous : il est pose en haut au lieu d'etre centre.

   La classe `flex-vertical-center` du gabarit n'existe dans AUCUNE feuille du
   projet — elle ne fait donc rien. On centre explicitement.
   ========================================================================== */
body ion-slide{
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  align-items: center !important;
  height: 100% !important;
  box-sizing: border-box !important;
}

/* Les points du carrousel. Une fois la barre bleue retiree, ils se
   retrouveraient invisibles sur fond blanc : ils prennent la couleur de la
   charte, et l'actif se distingue. */
body .slider-pager .slider-pager-page i{
  color: var(--trait) !important;
}
body .slider-pager .slider-pager-page.active i{
  color: var(--accent-texte) !important;
}


/* ==========================================================================
   45. LES DERNIERS DEFAUTS DU BILAN — 06/10/2026
   ========================================================================== */

/* --------------------------------------------------------------------------
   45.1 — « DEMANDER UN PAIEMENT » ETAIT BLANC SUR BLANC
   --------------------------------------------------------------------------
   Mesure (/home/profile + openWithdrwal) :

     span.wallet-t-desc.ng-binding   « Demander un paiement »
       couleur rgb(255,255,255)  sur  rgb(255,255,255)   ->  RATIO 1

   La chaine des fonds remontee par la sonde :
     wallet-t-desc        rgba(0,0,0,0)
     wallet-transactions  rgba(0,0,0,0)
     wallet-content       rgba(0,0,0,0)
     wallet-iphone        rgb(255,255,255)   <- premier fond opaque : BLANC

   Le texte est blanc sur un fond blanc. Il prend l'encre de la charte.
   NOTE : une passe precedente avait classe ce cas en « faux positif », en
   supposant un fond noir. La sonde de fond dit le contraire : le portefeuille
   est blanc. La conclusion precedente etait fausse.
   -------------------------------------------------------------------------- */
body .wallet-t-desc{
  color: var(--encre) !important;
}

/* --------------------------------------------------------------------------
   45.2 — LE TEXTE DES BOUTONS PLEINS, SANS EXCEPTION
   --------------------------------------------------------------------------
   Mesure (/home/dating) :

     span.button__text.comforta   « Créer une demande »
       couleur rgb(20,23,26)  sur  rgba(122, 90, 0)   ->  3,12:1

   Le bouton porte la classe `button` SEULE. Les regles de texte blanc ecrites
   jusqu'ici visent `.button--primary`, `.btn-primary` ou `[class*="gradient"]`
   — aucune ne l'atteint. Or la section 38 a donne a TOUT `body .button` un
   fond `--accent-texte` : un bouton plein qui porte du texte blanc.

   On prend donc la regle par l'autre bout : tout bouton plein porte du texte
   blanc, SAUF les variantes qui ne sont pas pleines — contour, texte, et les
   options d'une feuille d'actions systeme.
   -------------------------------------------------------------------------- */
/* LES VARIANTES TRANSPARENTES DOIVENT ETRE EXCLUES — 06/10/2026.
   Premiere version de cette regle : `.button:not(.button--stroke):not(.button-clear)
   :not(.action-sheet-option)`. Elle oubliait `button--transparent`, si bien que
   « Bloquer ou signaler » — un bouton a fond transparent pose sur une fenetre
   BLANCHE — s'est retrouve en blanc sur blanc, ratio 1. Le gabarit le dit
   pourtant en clair : `style="background: none!important"`.
   Une regle correcte existait plus haut dans ce fichier pour ce bouton ; la
   presente, plus specifique, la recouvrait. On n'exclut donc pas seulement les
   variantes connues, mais aussi tout bouton dont le fond est explicitement
   mis a `none` en style en ligne. */
/* BASCULE DU 07/10/2026 : ces boutons pleins ont un fond JAUNE de marque. Leur
   libelle passe donc du blanc a l'ENCRE — 11,45:1, la ou du blanc ne donnerait
   que 1,57:1. Les variantes exclues (contour, transparent, feuille d'actions)
   gardent leur propre couleur. */
body .button:not(.button--stroke):not(.button-clear):not(.action-sheet-option):not(.button--transparent):not([style*="background: none"]):not([style*="background:none"]) .button__text,
body .button:not(.button--stroke):not(.button-clear):not(.action-sheet-option):not(.button--transparent):not([style*="background: none"]):not([style*="background:none"]) .button__content span{
  color: var(--encre) !important;
}

/* --------------------------------------------------------------------------
   45.3 — DEUX CHAMPS DE SAISIE TROP BAS POUR LE DOIGT
   --------------------------------------------------------------------------
   Mesure (fenetre d'edition du profil) :

     input#userName   187 x 22,8 px
     input#userAge    187 x 22,8 px
     -> manque 21,2 px pour atteindre la cible tactile de 44 px

   Ce sont des champs de formulaire : sous 44 px, on rate sa cible au doigt.
   -------------------------------------------------------------------------- */
body input#userName,
body input#userAge,
body .profile-edit input[type="text"],
body .profile-edit input[type="number"]{
  min-height: var(--tactile) !important;
  box-sizing: border-box !important;
}


/* ==========================================================================
   46. LES GRIS « A UN PAS » DE LA CHARTE — 06/10/2026
   ==========================================================================
   Trouve en passant en revue les fenetres qui n'avaient JAMAIS ete mesurees
   (voir §47). La fenetre de profil remontait 7 couleurs hors charte.

   Origine, relevee dans les feuilles d'origine :

     smakoo.css   l.302   body { color: #333844 }        <- l'encre par defaut
     smakoo20.css l.4191  .connections__loader            color: #5e6773
                  l.6272  .chat-initial__content--match   color: #5e6773
                  l.8884  .photo-album__details-summary   color: #5e6773
                  l.8899  .photo-albums-empty             color: #5e6773
                  l.11030 .invite-sources-list__description
                  l.11108 .invite-contacts-list__description
                  l.11130 .invite-contacts-empty
                  l.11334 .dark .dot  background-color: #5e6773

   `#5e6773` est a UN PAS de `--gris` (#5B6672) et `#333844` est un gris bleute
   sombre la ou la charte pose `--encre` (#14171A). Ce sont les traces d'un
   theme plus ancien qu'on a survole. On les ramene sur les jetons.

   On ne touche PAS aux feuilles d'origine : ce sont les surcharges qui font
   le travail, comme pour tout le reste.
   ========================================================================== */
body{
  color: var(--encre) !important;
}
body .connections__loader,
body .chat-initial__content--match,
body .photo-album__details-summary,
body .photo-albums-empty,
body .invite-sources-list .invite-sources-list__description,
body .invite-contacts-list .invite-contacts-list__description,
body .invite-contacts-empty{
  color: var(--gris) !important;
}
body .dark .dot{
  background-color: var(--gris) !important;
}
/* Les deux CONTENEURS de la fenetre de profil portent leur propre gris, qui
   l'emporte sur l'encre heritee du corps : `div.profile-title` en #333844 et
   `div.profile-info` en #5E6773. On corrige le conteneur et non ses enfants,
   pour ne pas ecraser une couleur voulue a l'interieur. */
body .profile-title{
  color: var(--encre) !important;
}
body .profile-info{
  color: var(--gris) !important;
}
