/* Pour la vie — design system MVP.
   Direction : flat, épuré, premium discret, catholique contemporain.
   Ivoire, encre, bleu marial profond, or discret, sobriété. */

:root {
  --background: #FBFAF6;
  --foreground: #16202B;
  --muted: #F1EEE7;
  --muted-foreground: #6B7280;
  --primary: #223E63;         /* bleu marial du logo */
  --primary-deep: #1A2F4C;
  --primary-foreground: #FFFFFF;
  --secondary: #ECEEF3;
  --secondary-foreground: #1E1E1E;
  --accent: #B08A4F;          /* or discret */
  --rose: #E48BB2;            /* rose du logo, en touche */
  --rose-soft: #F6E4EC;
  --accent-foreground: #171717;
  --success: #3F6B4E;
  --danger: #B0453B;
  --border: #E7E3D9;
  --hairline: rgba(34, 62, 99, .1);
  --card: #FFFFFF;
  --card-foreground: #16202B;
  --radius: 20px;
  --shadow-sm: 0 1px 2px rgba(16,32,39,.05);
  --shadow-md: 0 10px 30px -12px rgba(16,32,39,.18);
  --shadow-lg: 0 24px 60px -18px rgba(16,32,39,.28);
  --glass-bg: rgba(255,255,255,.72);
  --glass-border: rgba(255,255,255,.55);
  --glass-blur: saturate(180%) blur(20px);
  --font-ui: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-brand: 'Cormorant Garamond', Georgia, serif;
  --font-round: 'Nunito', 'Inter', system-ui, sans-serif;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

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

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.6;
  color: var(--foreground);
  background: var(--background);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
/* Garde-fou anti-défilement horizontal — MOBILE UNIQUEMENT. En desktop, poser overflow-x sur
   html/body change la racine de défilement : `body.modal-open{overflow:hidden}` ne masque alors
   plus la scrollbar, et le backdrop d'une modale laisse une bande claire (la gouttière). En mobile,
   les scrollbars sont en overlay (0 px) → aucune bande, et le garde-fou protège du scroll latéral
   parasite sur les moteurs qui confinent mal le carrousel. */
@media (max-width: 899px) {
  html, body { overflow-x: hidden; overflow-x: clip; }
}

main { flex: 1; }

h1, h2, h3 { line-height: 1.25; margin: 0 0 .6em; }
h1 { font-size: 1.9rem; font-weight: 700; }
h2 { font-size: 1.45rem; font-weight: 700; }
h3 { font-size: 1.1rem; font-weight: 600; }
p { margin: 0 0 1em; }
a { color: var(--primary); }
.muted { color: var(--muted-foreground); font-size: .95rem; }
.center-text { text-align: center; }

.container {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 20px;
}
.container-narrow { max-width: 460px; }

/* ---- Header (glass) ---- */

.site-header {
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--hairline);
  position: sticky;
  top: 0;
  z-index: 50;
}
.page-landing .site-header { background: transparent; border-bottom-color: transparent; transition: background .3s ease, border-color .3s ease; }
.page-landing .site-header.scrolled { background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); border-bottom-color: var(--hairline); }
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 13px;
  padding-bottom: 13px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  white-space: nowrap;
}
.brand-logo { display: block; height: 30px; width: auto; }
.brand-name {
  font-family: var(--font-brand);
  font-size: 1.55rem;
  font-weight: 600;
  color: var(--primary);
  letter-spacing: .01em;
}
.header-nav { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

/* ---- Boutons ---- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 11px 20px;
  /* ⚠️ SANS CETTE LIGNE, UN <button> ET UN <a> N'ONT PAS LA MÊME HAUTEUR. La règle posait la police
     et sa taille, mais pas l'interligne : un <a> héritait celui du corps (1,6) tandis qu'un <button>
     recevait le `normal` de l'agent utilisateur. Mesuré côte à côte dans les Réglages : 37,8 px
     contre 32,5 — cinq pixels d'écart, invisibles seuls, criants une fois empilés.
     (Signalé par Gabriel le 28/08, sur une carte où les deux se suivaient.) */
  line-height: 1.6;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-ui);
  font-size: .95rem;
  font-weight: 600;
  letter-spacing: -.01em;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: transform .15s ease, background .2s ease, color .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--primary); color: var(--primary-foreground); box-shadow: 0 6px 18px -6px rgba(34,62,99,.55); }
.btn-primary:hover { background: var(--primary-deep); box-shadow: 0 10px 24px -8px rgba(34,62,99,.6); }
.btn-outline { background: transparent; color: var(--primary); border-color: var(--hairline); }
.btn-outline:hover { background: var(--muted); }
.btn-approve { background: var(--success); color: #fff; box-shadow: 0 6px 18px -6px rgba(63,107,78,.5); }
.btn-approve:hover { background: #355C43; }
.btn-reject { background: #C9772B; color: #fff; box-shadow: 0 6px 18px -6px rgba(201,119,43,.5); }
.btn-reject:hover { background: #B0691F; }
.btn-approve-reco { background: #2F8F86; color: #fff; box-shadow: 0 6px 18px -6px rgba(47,143,134,.5); }
.btn-approve-reco:hover { background: #26766E; }
.btn-ghost { background: transparent; color: var(--primary); }
.btn-ghost:hover { background: var(--muted); }
.btn-lg { padding: 14px 30px; font-size: 1.02rem; }
.btn-block { display: flex; width: 100%; }

/* Header transparent sur la landing (au-dessus du hero sombre) */
.page-landing .site-header:not(.scrolled) .brand-name { color: #fff; text-shadow: 0 1px 12px rgba(0,0,0,.35); }
.page-landing .site-header:not(.scrolled) .brand-logo { filter: drop-shadow(0 1px 6px rgba(0,0,0,.4)); }
.page-landing .site-header:not(.scrolled) .btn-ghost { color: rgba(255,255,255,.92); }
.page-landing .site-header:not(.scrolled) .btn-ghost:hover { background: rgba(255,255,255,.14); }
.page-landing .site-header:not(.scrolled) .btn-primary {
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.5);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: none; color: #fff;
}
.page-landing .site-header:not(.scrolled) .btn-primary:hover { background: rgba(255,255,255,.26); }
/* Icône Instagram du header (même effet « glass » sur le hero que les boutons) */
.nav-ig, .nav-auth, .nav-account, .nav-install { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px; color: var(--primary); background: transparent; cursor: pointer; transition: opacity .15s ease; }
.nav-ig:hover, .nav-auth:hover, .nav-account:hover, .nav-install:hover { opacity: .65; }
.page-landing .site-header:not(.scrolled) .nav-ig,
.page-landing .site-header:not(.scrolled) .nav-auth,
.page-landing .site-header:not(.scrolled) .nav-account,
.page-landing .site-header:not(.scrolled) .nav-install { color: #fff; }
/* Sur grand écran, c'est le lien TEXTE qui parle : l'icône n'apparaît qu'en dessous de 560 px. */
.nav-auth, .nav-account { display: none; }
/* ⚠️ L'INSTALLATION SE MONTRE EN DEUX CONDITIONS, JAMAIS UNE SEULE : la largeur (elle partage le
   rang de la flèche de sortie, qui n'existe que sur téléphone et fold) ET `is-ready`, posée par
   app.js quand le navigateur a réellement quelque chose à installer. Un `display:none` sec ici
   garantit qu'aucun des deux oublis ne la fait apparaître pour rien : ni sur un poste de bureau,
   ni chez quelqu'un qui a déjà l'application sur son écran d'accueil. */
.nav-install { display: none; }

/* ---- Hero plein écran ---- */

.hero {
  position: relative;
  min-height: 100svh;
  margin-top: calc(-1 * (26px + 30px + 13px));  /* remonte sous le header transparent */
  /* ⚠️ PADDING HAUT OBLIGATOIRE, à toute largeur. Le hero est remonté de 69 px sous l en-tête
     transparent et aligne son contenu EN BAS : tant que la fenêtre est haute, le contenu flotte
     au-dessus du pli et ce padding ne se voit pas. Mais dès que le contenu dépasse la hauteur
     disponible — fold déplié, large et BAS ; petit portable ; fenêtre réduite — il déborde vers
     le HAUT et passe sous l en-tête : mesuré à 600×540, le bandeau était à y=0 pour un en-tête
     descendant à 75. Ce garde-fou n existait qu en dessous de 560 px, où le cas se présente tout
     le temps ; il manquait partout ailleurs, où il ne se présente que sur écran bas. */
  padding: 96px 0 44px;
  display: flex;
  align-items: flex-end;
  color: #fff;
  /* Pas d'overflow:hidden : le fond est un background-image auto-clippé (aucun enfant ne déborde), et le menu
     déroulant du sélecteur de pays doit pouvoir s'ouvrir VERS LE BAS sans être rogné. z-index:1 : le hero (donc
     le menu) passe au-dessus de la section suivante quand le menu déborde. */
  z-index: 1;
  isolation: isolate;
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-color: #2c3a4a;
  background-image:
    linear-gradient(160deg, #34506e 0%, #223e63 55%, #4a3a52 100%);
  background-size: cover;
  background-position: center 30%;
}
.hero-media.has-img {
  /* Cadrage sur le couple (à droite de la photo), pour rester visible même en portrait */
  /* le ?v force le rafraîchissement quand on remplace la photo (cache image = 7 j) — incrémenter à chaque swap */
  background-image: url('/assets/img/hero.jpg?v=2');
  /* Mobile/portrait : cadrage sur le couple, appuyé vers la femme (partie droite de la photo). */
  background-position: 91% center;
}
@media (min-width: 900px) {
  .hero-media.has-img { background-position: center 42%; }
}
.hero::after {  /* voile pour lisibilité du texte */
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgba(12,20,30,.82) 0%, rgba(12,20,30,.35) 42%, rgba(12,20,30,.15) 70%, rgba(12,20,30,.35) 100%);
}
.hero .container { width: 100%; }
.hero-inner { max-width: 640px; }
.hero-kicker {
  display: inline-block;
  text-transform: uppercase;
  letter-spacing: .18em;
  font-size: .74rem;
  font-weight: 600;
  color: rgba(255,255,255,.85);
  margin-bottom: 14px;
  padding: 7px 14px;
  border: 1px solid rgba(255,255,255,.28);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.hero h1 {
  font-family: var(--font-brand);
  font-weight: 600;
  font-size: clamp(2.6rem, 7vw, 4.4rem);
  line-height: 1.04;
  letter-spacing: -.01em;
  margin: 0 0 .3em;
  text-wrap: balance;
  text-shadow: 0 2px 30px rgba(0,0,0,.3);
}
.hero h1 em { font-style: italic; color: #fff; }
.hero-sub {
  font-size: clamp(1rem, 1.9vw, 1.15rem);
  line-height: 1.45;
  color: rgba(255,255,255,.9);
  max-width: 520px;
  margin: 0 0 26px;
  font-weight: 400;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.hero-actions.center { margin-top: 30px; justify-content: center; }
.hero .btn-outline { color: #fff; border-color: rgba(255,255,255,.5); background: rgba(255,255,255,.08); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.hero .btn-outline:hover { background: rgba(255,255,255,.2); }
.hero-note { margin-top: 22px; font-size: .9rem; color: rgba(255,255,255,.78); }
.hero-scroll { position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: 1; color: rgba(255,255,255,.75); display: flex; animation: floaty 2s ease-in-out infinite; }
.hero-scroll svg { width: 30px; height: 30px; }
@keyframes floaty { 0%,100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 7px); } }

/* ---- Sections ---- */

.section { padding: 84px 0; }
.section-alt { background: linear-gradient(180deg, var(--muted), var(--background)); }
.section-head { text-align: center; max-width: 620px; margin: 0 auto 44px; }
.section-head--wide { max-width: 900px; }
.section h2 { font-size: clamp(1.7rem, 4vw, 2.3rem); letter-spacing: -.02em; margin-bottom: 12px; }
/* Sur très petit écran, on laisse le navigateur gérer le retour à la ligne du titre */
@media (max-width: 480px) { .section-head--wide h2 br { display: none; } }
.section-head p { color: var(--muted-foreground); font-size: 1.05rem; margin: 0; }
.eyebrow { text-transform: uppercase; letter-spacing: .16em; font-size: .74rem; font-weight: 700; color: var(--accent); margin-bottom: 12px; }

.cards-3, .cards-2 { display: grid; gap: 18px; }
.cards-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.cards-2 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); max-width: 720px; margin: 0 auto; }

.card {
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 28px 26px;
  box-shadow: var(--shadow-sm);
}
.card h3 { color: var(--primary); font-size: 1.2rem; }
.card p:last-child { margin-bottom: 0; }

/* Cartes « glass » de la landing */
.card.glass {
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-md);
  transition: transform .25s ease, box-shadow .25s ease;
}
.card.glass:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.feat-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  margin-bottom: 16px;
  border-radius: 14px;
  font-size: 1.3rem;
  color: var(--primary);
  background: linear-gradient(150deg, var(--secondary), var(--rose-soft));
  border: 1px solid var(--glass-border);
}

.price-card { text-align: center; }
.price {
  font-family: var(--font-brand);
  font-size: 2.4rem;
  color: var(--primary);
  margin: 0 0 .3em;
}

.steps {
  max-width: 620px;
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
}
.steps li {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 22px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.steps li strong { color: var(--foreground); }
.step-n {
  flex-shrink: 0;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px;
  font-family: var(--font-brand);
  font-size: 1.2rem; font-weight: 600;
  color: #fff;
  background: var(--primary);
}

.checklist {
  list-style: none;
  padding: 0;
  max-width: 620px;
  margin: 0 auto;
  display: grid;
  gap: 12px;
}
.checklist li {
  padding: 16px 20px 16px 52px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  position: relative;
  font-weight: 500;
}
.checklist li::before {
  content: '';
  position: absolute;
  left: 20px;
  top: 50%;
  transform: translateY(-60%) rotate(45deg);
  width: 7px;
  height: 13px;
  border-right: 2.5px solid var(--success);
  border-bottom: 2.5px solid var(--success);
}

/* Bande CTA finale */
.cta-band {
  padding: 88px 0;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-deep) 60%, #3a2f47 100%);
  color: #fff;
  text-align: center;
}
.cta-band h2 { font-family: var(--font-brand); font-weight: 600; font-size: clamp(1.9rem, 4.5vw, 2.8rem); max-width: 640px; margin: 0 auto .4em; }
.cta-band p { color: rgba(255,255,255,.85); max-width: 480px; margin: 0 auto 28px; font-size: 1.08rem; }
.cta-band .btn-primary { background: #fff; color: var(--primary); box-shadow: 0 10px 30px -8px rgba(0,0,0,.4); }
.cta-band .btn-primary:hover { background: rgba(255,255,255,.9); }

/* ---- FAQ (accordéon natif, SEO) ---- */
.faq { max-width: 760px; margin: 0 auto; display: grid; gap: 12px; }
.faq-item { background: var(--card); border: 1px solid var(--hairline); border-radius: 14px; padding: 2px 22px; box-shadow: var(--shadow-sm); }
.faq-item summary { list-style: none; cursor: pointer; font-weight: 700; color: var(--primary); padding: 18px 0; display: flex; justify-content: space-between; align-items: center; gap: 14px; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; font-size: 1.5rem; font-weight: 400; line-height: 1; color: var(--muted-foreground); }
.faq-item[open] summary::after { content: '\2212'; }
.faq-item p { margin: 0 0 18px; color: var(--foreground); line-height: 1.6; }

/* ---- Formulaires / auth ---- */

.auth-section { padding: 48px 0 64px; }
.auth-card { padding: 30px 26px; }
/* Mobile : réduit le titre des cartes auth pour qu'il tienne sur une ligne (ex. « Merci, c'est noté ! »). */
@media (max-width: 480px) { .auth-card h1 { font-size: 1.6rem; } }
.auth-intro { color: var(--muted-foreground); margin-bottom: 4px; }
.auth-alt { margin-top: 18px; font-size: .95rem; text-align: center; }
/* Deux lignes d'alternatives à la suite (ex. « Se connecter » puis « Mot de passe oublié ? ») : la 1re annule
   son margin-bottom (sinon le `p { margin: 0 0 1em }` global fusionne avec le margin-top et impose ~1em). */
/* ⚠️ PAS DE SOULIGNEMENT SUR UNE LIGNE QUI N'EST QU'UN LIEN (demande de Gabriel, 25/08 :
   « Mot de passe oublié ? » sous le bouton de connexion). Ces lignes-là se lisent comme des
   actions : centrées, seules sous un formulaire, leur nature de lien va de soi.
   ⚠️ `> a:only-child` et NON `.auth-alt a` : la même classe porte aussi des liens AU MILIEU D'UNE
   PHRASE — « Déjà un compte ? Se connecter », « Tu n'as rien reçu ? … ». Là, le soulignement est
   le seul repère qui distingue le lien du texte autour ; l'enlever laisserait la couleur pour
   unique indice, ce qu'un daltonien ne verrait pas. Le sélecteur trie exactement ces deux cas.
   Au survol il revient : la ligne se confirme sous le curseur sans s'annoncer au repos. */
.auth-alt > a:only-child { text-decoration: none; }
.auth-alt > a:only-child:hover,
.auth-alt > a:only-child:focus-visible { text-decoration: underline; }
.auth-alt-tight { margin-bottom: 0; }
.auth-alt + .auth-alt { margin-top: 6px; }
.auth-cgu { margin: 10px 0 0; font-size: .78rem; color: var(--muted-foreground); text-align: center; line-height: 1.4; }
.auth-cgu a { color: inherit; text-decoration: underline; }
.auth-alt-form { margin: 0; }
.otp-input { text-align: center; font-size: 1.6rem; letter-spacing: .5em; font-weight: 700; padding-left: .5em !important; }
.link-btn { background: none; border: none; padding: 0; font: inherit; color: var(--primary); font-weight: 600; text-decoration: underline; cursor: pointer; }

.form { display: grid; gap: 16px; margin-top: 8px; }
/* Un peu d'air avant le bouton de validation : 16 px de grille + 8 px ici = 24 px. */
.form > .btn-block { margin-top: 8px; }
.form label { font-weight: 600; font-size: .92rem; display: block; }
.form input[type="email"],
.form input[type="password"],
.form input[type="date"],
.form input[type="number"],
.form input[type="tel"],
.form input[type="text"] {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 12px 14px;
  font: inherit;
  font-weight: 400;
  color: var(--foreground);
  background: var(--background);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 8px);
}
/* Champ date : même allure que les autres, indicateur calendrier aux couleurs de la marque */
.form input[type="date"] { min-height: 46px; accent-color: var(--primary); }
.form input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .55; }
.form input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }
.form input:focus {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
  border-color: var(--primary);
}
/* Curseur de distance : pas de contour à la souris (on garde le focus clavier pour l'accessibilité). */
.form input[type="range"] { outline: none; }
.form input[type="range"][data-dist-slider] { vertical-align: -2.5px; }
.form input[type="range"]:focus:not(:focus-visible) { outline: none; }
.form .checkbox { display: flex; gap: 10px; align-items: flex-start; font-weight: 400; font-size: .9rem; }
.form .checkbox input { margin-top: 3px; }

.hp-field { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; opacity: 0; }

.form-errors {
  background: #FBEDEB;
  border: 1px solid var(--danger);
  color: var(--danger);
  border-radius: calc(var(--radius) - 8px);
  padding: 12px 16px;
  font-size: .92rem;
}
.form-errors ul { margin: 0; padding-left: 1.2em; }
.page-onboarding .form-errors { margin-bottom: 14px; }

/* ---- Flashes ---- */

.flash {
  max-width: 1080px;
  margin: 16px auto 0;
  padding: 12px 18px;
  border-radius: calc(var(--radius) - 8px);
  font-size: .95rem;
}
.flash-success { background: #EBF2EC; border: 1px solid var(--success); color: var(--success); }
.flash-error   { background: #FBEDEB; border: 1px solid var(--danger); color: var(--danger); }
.flash-info    { background: var(--secondary); border: 1px solid var(--border); color: var(--secondary-foreground); }
/* Pages app en desktop : la notif ne doit pas passer sous la barre latérale (260px). */
@media (min-width: 900px) {
  .has-appnav main > .flash { margin: 16px 48px 0 308px; max-width: 760px; }
}

/* ---- Metrics admin ---- */

.metric-card { text-align: center; }
.metric-value {
  font-family: var(--font-brand);
  font-size: 2.6rem;
  color: var(--primary);
  margin: 0;
}
.metric-label { color: var(--muted-foreground); font-size: .9rem; margin: 0; }

/* ---- Tableau de bord : cartes stats ---- */
.dash-h2 { font-family: var(--font-round); font-size: 1.3rem; font-weight: 800; letter-spacing: -.01em; color: var(--primary); margin: 26px 0 12px; }
.dash-h2:first-of-type { margin-top: 4px; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.stat { display: flex; align-items: center; gap: 14px; background: var(--card); border: 1px solid var(--hairline); border-radius: 16px; padding: 16px 18px; box-shadow: var(--shadow-sm); text-decoration: none; color: var(--foreground); }
a.stat { transition: border-color .15s ease, box-shadow .15s ease; }
a.stat:hover { border-color: var(--primary); box-shadow: var(--shadow-md); }
.stat-ic { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 12px; background: var(--secondary); color: var(--primary); flex-shrink: 0; }
.stat-ic svg { width: 22px; height: 22px; }
.stat-body { display: flex; flex-direction: column; min-width: 0; }
.stat-value { font-family: var(--font-round); font-size: 1.85rem; font-weight: 800; letter-spacing: -.01em; color: var(--primary); line-height: 1.05; }
.stat-label { font-size: .82rem; color: var(--muted-foreground); margin-top: 3px; }
.stat-alert { background: #FBF3E8; border-color: #E7C9A0; }
.stat-alert .stat-ic { background: #F1DCBB; color: #9A6A1F; }
.stat-alert .stat-value, .stat-alert .stat-label { color: #9A6A1F; }
.stat-cta { margin-left: auto; align-self: center; color: var(--primary); font-weight: 700; font-size: 1.2rem; }
.stat-alert .stat-cta { color: #9A6A1F; }
/* Camemberts & courbe du tableau de bord */
.dash-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 16px; }
.pie-card { padding: 20px 24px; }
.pie-title { font-family: var(--font-round); font-size: 1.05rem; font-weight: 800; color: var(--primary); margin: 0 0 16px; }
.pie-wrap { display: flex; align-items: center; gap: 24px; }
.pie { width: 128px; height: 128px; flex-shrink: 0; }
.pie-num { fill: var(--primary); font-family: var(--font-round); font-weight: 800; font-size: 28px; }
.pie-sub { fill: var(--muted-foreground); font-size: 11px; letter-spacing: .02em; }
.pie-legend { display: flex; flex-direction: column; gap: 12px; flex: 1; min-width: 0; }
.pie-leg { display: flex; align-items: center; gap: 10px; font-size: .95rem; }
.pie-dot { width: 12px; height: 12px; border-radius: 4px; flex-shrink: 0; }
.pie-leg-lbl { color: var(--muted-foreground); }
.pie-leg-val { margin-left: auto; font-weight: 800; color: var(--primary); font-family: var(--font-round); }
@media (max-width: 480px) { .pie-wrap { flex-direction: column; align-items: flex-start; } .pie-legend { width: 100%; } }
/* KPI cards (À traiter, Activité & revenus) — 4 colonnes pour une largeur identique entre sections */
.kpi-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 900px) { .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .kpi-grid { grid-template-columns: 1fr; } }
.kpi-card { position: relative; display: block; background: var(--card); border: 1px solid var(--hairline); border-radius: 18px; padding: 20px 22px; box-shadow: var(--shadow-sm); overflow: hidden; transition: box-shadow .15s ease, transform .15s ease; }
.kpi-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.kpi-link { text-decoration: none; color: inherit; }
.kpi-cta { position: absolute; bottom: 16px; right: 18px; color: var(--kpi-c); font-weight: 700; font-size: 1.3rem; line-height: 1; opacity: .8; }
.kpi-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--kpi-c); }
.kpi-ic { position: absolute; top: 18px; right: 18px; display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 12px; background: var(--kpi-bg); color: var(--kpi-c); }
.kpi-ic svg { width: 22px; height: 22px; }
.kpi-val { display: block; margin-top: 6px; font-family: var(--font-round); font-size: 2rem; font-weight: 800; letter-spacing: -.01em; color: var(--primary); line-height: 1; }
.kpi-lbl { display: block; font-size: .85rem; color: var(--muted-foreground); margin-top: 6px; }
.dash-curves { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 16px; margin-top: 16px; }
.curve-card { padding: 20px 24px; }
.curve-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.curve-head .pie-title { margin: 0; }
.curve-max { font-size: .82rem; font-weight: 700; color: var(--muted-foreground); white-space: nowrap; }
.curve-plot { position: relative; }
.curve { display: block; width: 100%; height: auto; cursor: crosshair; }
.curve-x { display: flex; justify-content: space-between; font-size: .78rem; color: var(--muted-foreground); margin-top: 6px; }
.curve-guide { stroke: currentColor; stroke-width: 1; stroke-dasharray: 3 3; opacity: 0; }
.curve-guide.on { opacity: .4; }
.curve-hoverdot { fill: currentColor; opacity: 0; }
.curve-hoverdot.on { opacity: 1; }
.curve-tip { position: absolute; top: 0; transform: translateX(-50%); background: var(--primary); color: #fff; font-size: .78rem; font-weight: 700; padding: 5px 10px; border-radius: 8px; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .08s ease; z-index: 5; box-shadow: var(--shadow-sm); }
.curve-tip.on { opacity: 1; }

/* ---- Footer ---- */

.site-footer {
  border-top: 1px solid var(--hairline);
  padding: 40px 0;
  text-align: center;
  background: var(--background);
}
.footer-brand {
  font-family: var(--font-brand);
  font-size: 1.4rem;
  color: var(--primary);
  margin: 0 0 4px;
}
.footer-tagline { color: var(--muted-foreground); font-size: .92rem; font-style: italic; margin: 0 0 14px; }
.footer-links { font-size: .88rem; margin: 0; }
.footer-links a { color: var(--muted-foreground); text-decoration: none; }
.footer-links a:hover { color: var(--primary); }

/* ---- Fold déplié et tablette en portrait (jusqu'à 900 px) ---- */
/* ⚠️ L'ACCÈS AU COMPTE PASSE EN ICÔNE (demande de Gabriel, d'abord sur téléphone puis étendue au
   fold). « Se connecter » / « Se déconnecter » est remplacé par .nav-auth — une silhouette si l'on
   est déconnecté, une flèche sortante sinon — rendue à droite d'Instagram et à son gabarit.
   On masque les DEUX libellés : sans cela l'en-tête porterait le texte ET l'icône.
   ⚠️ 900 px est la zone « fold » déjà retenue ailleurs dans ce projet. Elle englobe aussi les
   TABLETTES EN PORTRAIT, et c'est assumé : aucune requête média ne distingue un pliable déplié
   d'une tablette — seule la largeur est connue.
   ⚠️ « Créer un compte » reste en toute lettre ici, contrairement au téléphone : la place ne manque
   pas à cette largeur, et c'est l'appel à l'action de la page. */
@media (max-width: 900px) {
  .header-nav .nav-login,
  .header-nav .nav-logout { display: none; }
  .header-nav .nav-auth,
  .header-nav .nav-account { display: inline-flex; }
  .header-nav .nav-install.is-ready { display: inline-flex; }
}

/* ---- Mobile ---- */

@media (max-width: 560px) {
  /* padding-top ≥ 69px (= le margin-top négatif du hero) pour que, quand le contenu est haut,
     le kicker passe SOUS le header sticky au lieu d'être rogné derrière lui. */
  .hero { padding: 88px 0 40px; }
  .section { padding: 40px 0; }
  .header-inner { gap: 8px; }
  .brand-logo { height: 26px; }
  .brand-name { font-size: 1.25rem; }
  .header-nav { gap: 6px; }
  .header-nav .btn { padding: 8px 12px; font-size: .85rem; }
  /* Mobile : on masque le bouton fantôme du header (le bottom-nav / les liens en carte suffisent) */
  .header-nav .btn-ghost { display: none; }
  /* …sauf pour un visiteur NON CONNECTÉ, où c'est l'inverse qu'il faut garder : le hero porte déjà
     l'inscription (champ e-mail + bouton, à trois centimètres sous le header). Répéter « Créer un compte »
     en haut n'apporte rien, alors qu'il n'existe aucun moyen de REVENIR chez soi. On garde donc
     « Se connecter » et on masque « Créer un compte ». Même spécificité que la règle ci-dessus (0,2,0) :
     c'est l'ordre d'écriture qui tranche — ne pas remonter ce bloc. */
  .header-nav .nav-signup { display: none; }
  /* (L'accès au compte en icône est traité plus haut, jusqu'à 900 px : voir le bloc « fold ».) */
  /* (L'ancien « verre dépoli » du bouton texte est retiré : sur téléphone ce bouton n'existe plus,
     c'est .nav-auth qui prend sa place — et elle suit déjà la couleur d'Instagram sur le hero.) */
}

/* ===================================================================
   Composants applicatifs (onboarding, app, messages, admin)
   =================================================================== */

.btn-sm { padding: 7px 13px; font-size: .85rem; }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { background: #8f342c; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.hint { font-size: .82rem; color: var(--muted-foreground); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Autocomplétage des communes (API adresse) */
.geo-autocomplete { position: relative; }
.ob-cancel { text-align: center; margin: 14px 0 0; }
.ob-cancel-link { background: none; border: 0; padding: 4px 6px; font: inherit; font-size: .9rem; color: var(--muted-foreground); text-decoration: underline; cursor: pointer; }
.ob-cancel-link:hover { color: var(--foreground); }
.geo-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 22px; }
.geo-head .admin-h1 { margin: 0; }
/* Interrupteur des deux volets de la page Cohérence. ⚠️ PAS `.seg-links` : ce nom est DÉJÀ pris
   par la bascule courte/longue de la page Prières, où il modifie un `.seg-toggle` à pouce coulissant.
   Le réutiliser aurait cassé cette page-là, et la règle la plus basse dans le fichier l'aurait emporté. */
.coh-tabs { display: inline-flex; gap: 4px; background: var(--muted); border: 1px solid var(--hairline); border-radius: 999px; padding: 3px; margin: 4px 0 18px; max-width: 100%; flex-wrap: wrap; }
.coh-tab { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 999px; font-size: .9rem; font-weight: 600; color: var(--muted-foreground); text-decoration: none; transition: color .2s ease, background .2s ease; }
.coh-tab:hover { color: var(--primary); }
.coh-tab.is-on { background: var(--card); color: var(--primary); box-shadow: var(--shadow-sm); }
.coh-tab-n { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: rgba(34, 62, 99, .1); font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.coh-tab.is-on .coh-tab-n { background: var(--primary); color: #fff; }
/* Les motifs sont des phrases, pas des étiquettes d'un mot : sans largeur MINIMALE la colonne se
   réduisait à trois caractères et chaque pastille s'étirait sur huit lignes (capture du 29/08). */
.geo-flags { min-width: 300px; max-width: 340px; }
.geo-flag { display: inline-block; font-size: .78rem; line-height: 1.3; padding: 3px 9px; border-radius: 999px; margin: 0 4px 4px 0; }
.geo-sev2 { background: #fdecea; color: #b71c1c; border: 1px solid #f5c6c2; }
.geo-sev1 { background: #fff4e0; color: #9a6100; border: 1px solid #f3dcae; }
.geo-actions { white-space: nowrap; }
.geo-actions .btn { margin-right: 6px; }
.geo-verdict { display: block; margin-top: 6px; font-size: .82rem; line-height: 1.35; }
.geo-verdict.ok { color: #1b7f4b; }
.geo-verdict.bad { color: #b71c1c; font-weight: 600; }
.geo-check { font: inherit; font-size: .8rem; font-weight: 600; padding: 5px 12px; border-radius: 999px; border: 1px solid #f5c6c2; background: #fdecea; color: #b71c1c; cursor: pointer; white-space: nowrap; transition: background .12s, color .12s, border-color .12s; }
.geo-check:hover { filter: brightness(.98); }
.geo-check.is-checked { border-color: #b6e0c8; background: #e7f6ee; color: #1b7f4b; }
/* La phrase qui a déclenché le signalement du volet « enfants ». Elle est montrée parce que c'est
   elle, et non l'étiquette, qui permet de trancher d'un coup d'œil — sans ouvrir la fiche. */
.kids-cite { display: block; margin: 4px 0 2px; font-size: .78rem; line-height: 1.45; color: var(--muted-foreground); font-style: italic; max-width: 46ch; }
.geo-allsum { font-size: .88rem; margin-left: 8px; }
.geo-allsum.ok { color: #1b7f4b; font-weight: 600; }
.geo-allsum.bad { color: #b71c1c; font-weight: 600; }
/* « Ce pays a son propre choix, juste au-dessus » : l'avertissement qui empêche un second chemin
   vers un pays déjà desservi. Discret — c'est une aide, pas une erreur : la personne n'a rien fait
   de mal, elle a juste tapé au mauvais endroit. */
.world-served { margin: 6px 0 0; font-size: .82rem; line-height: 1.45; color: var(--muted-foreground); }
.world-served-go { display: inline; padding: 0; border: 0; background: none; font: inherit; font-weight: 600; color: var(--primary); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.world-served-go:hover { color: var(--primary-strong, var(--primary)); }
.geo-suggest {
  list-style: none; margin: 6px 0 0; padding: 6px;
  position: absolute; left: 0; right: 0; top: 100%; z-index: 40;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(16,32,43,.14); max-height: 264px; overflow-y: auto;
}
.geo-suggest li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 13px; border-radius: 9px; cursor: pointer; font-size: .96rem;
}
.geo-suggest li:hover, .geo-suggest li[aria-selected="true"] { background: var(--secondary); }
.geo-suggest .geo-cp { color: var(--muted-foreground); font-variant-numeric: tabular-nums; white-space: nowrap; }
.origin-autocomplete { position: relative; }
.origin-suggest {
  list-style: none; margin: 4px 0 0; padding: 6px;
  position: absolute; left: 0; right: 0; top: 100%; z-index: 40;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(16,32,43,.14); max-height: 264px; overflow-y: auto;
}
.origin-suggest li { padding: 11px 13px; border-radius: 9px; cursor: pointer; font-size: .96rem; }
.origin-suggest li:hover, .origin-suggest li[aria-selected="true"] { background: var(--secondary); }
.view-title { margin-bottom: 14px; }
/* ⚠️ RETIRÉ DE L'ÉCRAN, PAS DE LA PAGE (demande de Gabriel, 24/08 : « on peut s'en passer »).
   Sur « Côté cœur », « Messages » et « Réglages », le menu dit déjà où l'on est — l'élément actif
   porte le nom de la page, sur grand écran comme dans la barre du bas sur téléphone. Le titre est
   donc redondant À L'ŒIL. Il reste dans le document pour qui navigue au lecteur d'écran : sans
   aucun titre, la page ne s'annonce plus du tout, et rien dans le menu ne remplace cela à l'oreille.
   `display: none` l'aurait retiré aussi de la lecture — d'où le décalage hors cadre. */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* Lien de retour en tête d'une page interne ouverte depuis une autre (ex. Réglages → Mes informations). */
.app-back { margin: 0 0 10px; }
.app-back a { color: var(--muted-foreground); font-weight: 600; font-size: .92rem; text-decoration: none; }
.app-back a:hover { color: var(--primary); }
.form textarea, .form select {
  width: 100%; margin-top: 6px; padding: 12px 14px; font: inherit; font-weight: 400;
  color: var(--foreground); background: var(--background);
  border: 1px solid var(--border); border-radius: calc(var(--radius) - 8px);
}
.form textarea:focus, .form select:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.field-group { border: none; padding: 0; margin: 0; }
.field-group legend { font-weight: 600; font-size: .92rem; margin-bottom: 6px; padding: 0; }
/* Deux questions à la suite dans un même bloc : sans air entre elles, la réponse de la première
   touche l'intitulé de la seconde et l'on croit lire une seule question. ⚠️ Ciblé sur ce bloc,
   pas sur tous les `.field-group` : ailleurs, ce sont des cases à cocher qui se suivent, et elles
   doivent rester serrées. */
.kids-group label + label { display: block; margin-top: 18px; }

/* ---- « Mes critères » : un sujet par carte ------------------------------------------------
   ⚠️ Les cartes valent sur TOUS les écrans, pas seulement en desktop : sur téléphone, les quatre
   sujets se suivaient sans rien qui les sépare, et l'on ne savait plus à quoi se rapportait un
   champ. Le panneau unique du desktop est donc neutralisé pour ce formulaire (voir plus bas). */
.crit-card { background: var(--card); border: 1px solid var(--hairline); border-radius: 16px;
  box-shadow: 0 1px 2px rgba(16,32,43,.04); padding: 18px 18px 16px; }
.crit-card > legend { float: left; width: 100%; margin-bottom: 12px; font-weight: 700;
  font-size: .95rem; color: var(--foreground); }
/* ⚠️ `float` + ce dégagement : un `<legend>` ne se laisse pas mettre en page comme un bloc ordinaire
   dans un `<fieldset>` — sans lui, le titre chevauche le premier champ. */
.crit-card > legend + * { clear: both; }
.crit-card > :last-child { margin-bottom: 0; }
/* La précision suit immédiatement le champ qu'elle explique : sans air, elle s'y accroche et se lit
   comme une partie de la réponse choisie. Une seule classe pour TOUTES les précisions de cette page
   (l'âge, les enfants) : elles jouent le même rôle, elles doivent se ressembler.
   ⚠️ `.crit-card` devant, sinon rien ne bouge : `.field-help` (même spécificité) est déclaré PLUS
   LOIN dans le fichier et remet `margin: 0`. Mesuré au navigateur : 0 px avant ce correctif. */
.crit-card .crit-note { margin-top: 12px; }
/* La case « ouverture internationale » suit le curseur de distance : sans air, elle lui colle. */
.crit-card .intl-field { margin-top: 14px; }

/* --- Réglages admin --- */
.settings-form { column-count: 2; column-gap: 20px; margin-top: 4px; }
.settings-form > .settings-card { break-inside: avoid; margin: 0 0 20px; }
.settings-card { display: grid; gap: 16px; padding: 24px 26px; }
.settings-head { display: grid; gap: 3px; }
.settings-head h3 { margin: 0; color: var(--primary); font-size: 1.15rem; }
.settings-head p { margin: 0; font-size: .88rem; color: var(--muted-foreground); }
.settings-form .field { display: grid; gap: 6px; }
.settings-form .field > label { font-weight: 600; font-size: .9rem; color: var(--foreground); }
/* Bouton « danger » (suppression) */
.btn-danger { background: #c0392b; color: #fff; border-color: #c0392b; }
.btn-danger:hover { background: #a93226; }
/* Carte « Comptes managers » (Réglages) */
.mgr-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.mgr-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--card); }
.mgr-info { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.mgr-email { font-weight: 600; word-break: break-all; }
.mgr-badge { font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--primary); background: var(--muted); border-radius: 999px; padding: 2px 8px; }
.mgr-meta { font-size: .82rem; color: var(--muted-foreground); }
.mgr-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.mgr-create-actions { margin-top: 10px; }
.settings-form input[type="text"],
.settings-form input[type="password"],
.settings-form input[type="email"],
.settings-form input[type="tel"],
.settings-form input[type="number"],
.settings-form input[type="date"] {
  width: 100%; padding: 11px 14px; font: inherit; font-weight: 400;
  color: var(--foreground); background: var(--background);
  border: 1px solid var(--border); border-radius: 10px;
}
.settings-form input:focus { outline: 2px solid var(--primary); outline-offset: 1px; border-color: var(--primary); }
.settings-form .field-sm input { max-width: 220px; }
.settings-form .field-xs input { max-width: 150px; }
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.settings-readout { display: flex; align-items: center; min-height: 46px; padding: 11px 14px; font-weight: 700; font-size: 1.15rem; color: var(--primary); background: var(--muted); border: 1px solid var(--border); border-radius: 10px; box-sizing: border-box; }
.settings-readout-btn { width: 100%; font-family: inherit; text-align: left; cursor: pointer; transition: border-color .15s, background .15s; }
.settings-readout-btn:hover { border-color: var(--primary); background: var(--card); }
.pack-elig-body { max-height: 60vh; overflow-y: auto; margin-top: 6px; }
.pack-elig-list { display: flex; flex-direction: column; }
.pack-elig-row { display: flex; align-items: center; gap: 10px; padding: 8px 6px; border-bottom: 1px solid var(--hairline); }
.pack-elig-row:last-child { border-bottom: 0; }
.pack-elig-row:hover { background: var(--muted); }
.pack-elig-link { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; color: inherit; text-decoration: none; }
.pack-elig-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pack-elig-loc { color: var(--muted-foreground); font-size: .86rem; text-align: right; flex-shrink: 1; min-width: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pastille « +X au-dessus du seuil » : nb de profils pertinents au-delà du minimum requis. */
.pack-elig-above { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; min-width: 34px; padding: 3px 9px; border-radius: 999px; background: #E6F3EC; color: #2E8F6B; font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.pack-elig-row .icon-rank { flex-shrink: 0; }
/* Symbole de genre à côté d'un prénom (fiche profil) : ♂ bleu / ♀ rose */
.gender-mark { font-weight: 700; margin-left: 8px; }
.gender-m { color: #2f7ed8; }
.gender-f { color: #e0559b; }
.gender-flag { margin-left: 6px; font-size: .82em; vertical-align: middle; }
.settings-toggle { display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; background: var(--muted); border: 1px solid var(--hairline); border-radius: 12px; font-size: .92rem; cursor: pointer; }
.settings-toggle > input { margin-top: 2px; width: 16px; height: 16px; accent-color: var(--primary); flex-shrink: 0; }
.settings-toggle > span { display: grid; gap: 2px; }
.settings-toggle-sub { color: var(--muted-foreground); font-size: .84rem; font-weight: 400; }
.settings-form .hint { margin: 0; }
.settings-actions { column-span: all; margin: 2px 0 0; }
.settings-actions .btn { padding: 13px 40px; }
@media (max-width: 900px) {
  .settings-form { column-count: 1; }
}
@media (max-width: 560px) {
  .settings-grid { grid-template-columns: 1fr; }
  .settings-actions .btn { width: 100%; }
}

/* ---- Onboarding ---- */
.ob-section { padding: 28px 0 60px; }
.ob-intro-head { text-align: center; margin-bottom: 22px; }
.ob-intro-head .ob-lead { margin-bottom: 0; }
.ob-progress { height: 6px; background: var(--muted); border-radius: 99px; overflow: hidden; margin-bottom: 10px; }
.ob-progress span { display: block; height: 100%; background: var(--accent); border-radius: 99px; transition: width .3s ease; }
.ob-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.ob-step { font-size: .8rem; color: var(--muted-foreground); }
.ob-back { font-size: .9rem; font-weight: 600; color: var(--muted-foreground); text-decoration: none; padding: 4px 2px; }
.ob-back:hover { color: var(--primary); }
.ob-section h1 { font-size: 1.6rem; }
.ob-lead { color: var(--muted-foreground); margin-bottom: 20px; }
.radio-cards { display: grid; gap: 10px; }
.radio-card { display: flex; align-items: center; gap: 10px; padding: 13px 16px; border: 1px solid var(--border); border-radius: calc(var(--radius) - 6px); cursor: pointer; background: var(--background); }
/* ⚠️ LA PUCE S'ALIGNE SUR LE TEXTE, ET IL FAUT `vertical-align` POUR ÇA (Gabriel, 01/09 : « le point
   à cocher n'est pas parfaitement aligné »). Le piège : `.radio-card` se déclare `display:flex`
   ci-dessus, mais `.form label{display:block}` est PLUS SPÉCIFIQUE (0,1,1 contre 0,1,0) — dans un
   formulaire, donc partout où ces cartes servent vraiment, le flex n'a jamais pris. La puce et le
   texte sont deux boîtes en ligne alignées sur la LIGNE DE BASE, d'où un décalage mesuré à 2,5 px
   vers le bas. `vertical-align:middle` sur les deux les recale (mesuré : 0,27 px, soit sous le
   pixel), et la marge verticale doit être SYMÉTRIQUE sinon elle réintroduit le décalage.
   ⚠️ NE PAS « réparer » en forçant le flex : sur un libellé qui passe à la ligne (« En plus, je vais
   parfois à la messe en semaine. »), le centrage flex descend la puce au milieu du bloc — mesuré à
   12 px de la première ligne, bien pire que le défaut d'origine. En ligne, elle reste sur la
   première ligne, ce qui est le rendu voulu.
   ⚠️ Sur les cartes réellement flex (hors formulaire : .scroll-list, la modale « oui »),
   `vertical-align` est inerte sur un enfant flex — ce correctif y est donc sans effet. */
.radio-card input { accent-color: var(--primary); vertical-align: middle; margin: 0 3px 0 5px; }
.radio-card span { vertical-align: middle; }
/* ⚠️ Les cases ci-dessous restent des `type="checkbox"` : « Mon intention » et le détail de pratique
   acceptent PLUSIEURS réponses. Choix de Gabriel : les dessiner comme les choix uniques, pour que
   l'écran soit homogène. Ne PAS « corriger » le type en radio en croyant réparer l'incohérence —
   ce serait une perte de fonction. Dimensions calquées sur le rond natif de Chrome (mesuré). */
.radio-card input[type="checkbox"] { -webkit-appearance: none; appearance: none; box-sizing: border-box; width: 13px; height: 13px; margin: 0 3px 0 5px; flex: none; border: 1px solid #767676; border-radius: 50%; background: #fff; display: inline-grid; place-content: center; }
.radio-card input[type="checkbox"]::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); transform: scale(0); }
.radio-card input[type="checkbox"]:checked { border: 2px solid var(--primary); }
.radio-card input[type="checkbox"]:checked::before { transform: scale(1); }
.radio-card input[type="checkbox"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.radio-card:has(input:checked) { border-color: var(--primary); background: var(--secondary); }
.upload-btn { display: block; text-align: center; padding: 14px; border: 1.5px dashed var(--border); border-radius: calc(var(--radius) - 6px); cursor: pointer; font-weight: 600; color: var(--primary); }
/* Champ masqué mais ATTEIGNABLE. `display:none` le sortait de l'ordre de tabulation : la boîte
   « Ajouter une photo » n'étant qu'un <label>, l'étape photo devenait infranchissable au clavier.
   Ce masquage-là est invisible à l'identique, mais le champ reste focalisable et activable. */
.upload-btn { position: relative; }
.upload-btn input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; padding: 0; border: 0; }
/* Halo de focus réservé au CLAVIER : :focus-visible exclut le focus donné par un clic, donc l'apparence
   à la souris ne change pas d'un pixel. Sur un navigateur qui ignore :has(), il ne s'affiche pas —
   dégradation sans conséquence, c'est le comportement actuel. */
.upload-btn:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.photo-grid, .gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 16px; }
.photo-thumb, .gal-item { position: relative; aspect-ratio: 3/4; border-radius: 12px; overflow: hidden; background: var(--muted); }
.photo-thumb img, .gal-item img { width: 100%; height: 100%; object-fit: cover; }
.thumb-x { position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; border: none; border-radius: 99px; background: rgba(0,0,0,.6); color: #fff; font-size: 1.1rem; cursor: pointer; }
.photo-del { position: absolute; top: 0; right: 0; }
.photo-thumb.is-main { outline: 2px solid var(--primary); outline-offset: -2px; }
.photo-main-badge { position: absolute; left: 5px; bottom: 5px; background: var(--primary); color: #fff; font-size: .66rem; font-weight: 700; letter-spacing: .02em; padding: 3px 8px; border-radius: 999px; }
.photo-main-set { position: absolute; left: 5px; bottom: 5px; margin: 0; }
.btn-set-main { border: 0; cursor: pointer; background: rgba(16,32,43,.72); color: #fff; font-size: .66rem; font-weight: 600; padding: 4px 9px; border-radius: 999px; }
.btn-set-main:hover { background: rgba(16,32,43,.92); }
.review-card { text-align: left; }
.review-photo { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 12px; margin-bottom: 12px; }

/* ---- Espace membre : nav (bottom bar mobile / sidebar droite desktop) ---- */
.has-appnav .site-header, .has-appnav .site-footer,
.page-conv .site-header, .page-conv .site-footer { display: none; }
.page-app { background:
  radial-gradient(1100px 520px at 100% -60px, var(--secondary), transparent 60%),
  radial-gradient(900px 500px at -10% 10%, var(--rose-soft), transparent 55%),
  var(--background); }
.app-view { padding: 26px 0 16px; }

.app-nav {
  position: fixed; z-index: 60;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.nav-item { display: flex; align-items: center; text-decoration: none; color: var(--muted-foreground); transition: background .15s ease, color .15s ease; }
.nav-item.active { color: var(--primary); }
.nav-icon { position: relative; display: inline-flex; }
.nav-icon svg { width: 24px; height: 24px; }
.nav-badge { position: absolute; top: -5px; right: -8px; background: var(--danger); color: #fff; font-size: .6rem; font-weight: 700; min-width: 16px; height: 16px; line-height: 16px; text-align: center; border-radius: 99px; padding: 0 3px; }

/* Mobile : barre du bas */
@media (max-width: 899px) {
  .app-nav { bottom: 0; left: 0; right: 0; display: flex; border-top: 1px solid var(--hairline); padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); }
  .app-nav-brand, .app-nav-logout { display: none; }
  .app-nav-items { display: flex; flex: 1; align-items: flex-start; }
  /* Icônes toutes alignées en haut (labels de longueur variable dessous, centrés) */
  .nav-item { flex: 1 1 0; min-width: 0; flex-direction: column; align-items: center; justify-content: flex-start; gap: 3px; padding: 5px 2px 0; font-size: .62rem; font-weight: 600; text-align: center; line-height: 1.12; }
  .nav-item .nav-label { flex: none; width: 100%; }
  .nav-item .nav-icon svg { width: 22px; height: 22px; }
  .has-appnav { padding-bottom: 78px; }
  /* ⚠️ LA BARRE S'EFFACE PENDANT LA SAISIE — mobile uniquement, où elle est fixée en bas.
     Le clavier ouvert la colle juste au-dessus de lui : elle recouvrait le champ qu'on remplit
     (signalé le 31/08). On retire aussi la marge basse qu'elle réservait, sinon un vide de
     78 px pousserait le champ hors de l'écran — le défaut qu'on vient de corriger, à l'envers.
     Sur ordinateur (>= 900 px) la barre est une colonne latérale : rien à masquer. */
  html.saisie-en-cours .app-nav { display: none; }
  html.saisie-en-cours .has-appnav { padding-bottom: 0; }
  /* Écrans d'état (prière, « aucun profil », profil en relecture…) : centrés verticalement dans
     l'espace laissé par la barre du bas — le desktop le faisait déjà, le mobile les collait en haut
     avec un grand vide dessous.
     ⚠️ `margin-block: auto` et NON `justify-content: center` : quand le contenu dépasse la hauteur
     de l'écran, les marges automatiques retombent à 0 et rien n'est rogné en haut, alors qu'un
     centrage par flex rendrait le début du contenu inatteignable.
     `dvh` plutôt que `vh` : sur mobile la barre d'adresse se rétracte, `vh` fige la hauteur haute. */
  .has-appnav .app-view:has(.state-card) { display: flex; flex-direction: column; box-sizing: border-box;
    min-height: calc(100dvh - 78px); }
  .has-appnav .app-view:has(.state-card) > .container { width: 100%; margin-block: auto; }
}

/* Desktop : barre latérale fixe à gauche */
@media (min-width: 900px) {
  .app-nav { top: 0; left: 0; height: 100vh; width: 260px; display: flex; flex-direction: column; border-right: 1px solid var(--hairline); padding: 26px 16px; }
  .has-appnav .app-shell { padding-left: 260px; }
  /* Contenu aligné juste après le menu, largeur adaptée à chaque page */
  .has-appnav .app-view { padding: 46px 48px 40px; }
  .has-appnav .app-view-center .empty-day { margin-top: 0; }   /* le centrage est porté par la règle :has(.state-card) plus bas */
  .has-appnav .app-view > .container { max-width: 720px; margin: 0; padding: 0; }
  /* ⚠️ CE SONT LES TUILES QU'ON CENTRE, PAS LA PAGE. Ma première version donnait au conteneur
     entier des marges automatiques : les tuiles se centraient bien, mais le TITRE partait avec
     elles, loin de la place qu'il occupe sur toutes les autres pages. Le conteneur reprend donc
     toute la largeur — le titre retrouve son bord gauche — et seul le bloc des tuiles est centré. */
  .has-appnav .app-view > .container.coeur-hub { max-width: none; }
  /* ⚠️ `width: 100%` N'EST PAS DÉCORATIF. Le conteneur est devenu un flex en colonne pour le
     centrage vertical (plus bas) ; dans un flex, une marge automatique en travers RÉTRÉCIT
     l'élément à la largeur de son contenu au lieu de l'étirer. Les tuiles étaient ainsi tombées
     de 720 à 433 px sans que rien ne le signale — elles restaient centrées, seulement plus
     étroites. La largeur explicite leur rend toute la place, la marge ne fait plus que centrer. */
  .coeur-hub .coeur-tiles { width: 100%; max-width: 720px; margin-inline: auto; }
  /* Même traitement pour « Premiers pas » (demande de Gabriel, 24/08) : le titre, le retour et
     l'intro gardent leur bord gauche, comme sur toutes les pages ; seul le PLATEAU — la carte, le
     bouton et le compte — se centre. `container-narrow` plafonne à 460 px, d'où le `max-width` ici,
     sinon la carte resterait étroite au milieu d'une page large. */
  .has-appnav .app-view > .container.pp-view { max-width: none; }
  /* Concours et parrainage : même principe encore (demande de Gabriel, 26/08). Les cartes portent
     leur largeur et se centrent d'elles-mêmes ; le conteneur ne doit pas les caler à gauche. */
  .has-appnav .app-view > .container.cc-view,
  .has-appnav .app-view > .container.pa-view { max-width: none; }
  /* Plus large sur grand écran (demande de Gabriel, 26/08) : 460 px laissait beaucoup de vide de
     part et d'autre. Le débordement reste impossible — sur téléphone, on est sous ce seuil. */
  .cc-view .cc-card, .cc-view .cc-periode-head,
  .pa-view .cc-card { max-width: 560px; }
  .cc-ticket { max-width: 380px; }
  .pp-view .pp-plateau { width: 100%; max-width: 720px; margin-inline: auto; }
  /* Même traitement pour « Mes prières enregistrées » (demande de Gabriel, 24/08) : la liste était
     centrée dans un conteneur de 720 px lui-même calé à gauche — mesuré 148 px du menu contre 512
     du bord droit. Le conteneur reprend toute la largeur, le titre garde sa place, la liste se
     centre. ⚠️ `width: 100%` indispensable : voir la note du sommaire Côté cœur. */
  .has-appnav .app-view > .container.priere-view { max-width: none; }
  .priere-view .priere-liste { width: 100%; max-width: 520px; margin-inline: auto; }
  /* ⚠️ CENTRÉ DANS LA ZONE DE CONTENU, PAS DANS LA FENÊTRE (choix de Gabriel, 24/08, après essai
     de l'autre). J'avais un temps ramené cette liste au centre de l'écran entier, menu compris ;
     essayé à l'écran, Gabriel a préféré revenir à la référence commune. LES TROIS PAGES DE CÔTÉ
     CŒUR partagent donc le même repère — le sommaire, « Premiers pas » et les prières — et le bloc
     ne saute plus quand on passe de l'une à l'autre. Ne recentrer qu'une seule d'entre elles
     rouvrirait ce défaut. */
  /* ⚠️ ET CENTRÉ DANS LA HAUTEUR (demande de Gabriel, 24/08), sans toucher au retour, au titre ni
     à l'intro : eux gardent le haut de la page, c'est le PLATEAU qui se centre dans ce qui reste.
     Marges automatiques, jamais `justify-content` : sur un écran bas, un centrage rigide pousserait
     la carte sous l'intro et la rognerait sans qu'on puisse défiler pour la rattraper. */
  .has-appnav .app-view:has(> .container.pp-view) {
    display: flex; flex-direction: column; box-sizing: border-box; min-height: 100vh;
  }
  .has-appnav .app-view > .container.pp-view { display: flex; flex-direction: column; flex: 1 1 auto; }
  .pp-view .pp-plateau { margin-block: auto; }
  /* La marge basse de l'intro tombait DANS l'espace à partager : le plateau était centré au calcul
     mais paraissait 22 px trop bas. Retirée, elle laisse les deux écarts se valoir à l'œil. */
  .pp-view .pp-intro { margin-bottom: 0; }
  /* ⚠️ CENTRAGE VERTICAL DES SEULES TUILES (demande de Gabriel, 24/08 : « dans le sens de la
     hauteur aussi »). Le titre garde sa place en haut — c'est le bloc de tuiles qui se centre
     dans l'espace qui reste. Fait avec des marges automatiques, PAS avec justify-content :
     quand le contenu devient plus haut que l'écran, une marge auto retombe à zéro et la page
     défile normalement, là où un centrage rigide rognerait la première tuile. */
  .has-appnav .app-view:has(> .container.coeur-hub) {
    display: flex; flex-direction: column; box-sizing: border-box; min-height: 100vh;
  }
  .has-appnav .app-view > .container.coeur-hub { display: flex; flex-direction: column; flex: 1 1 auto; }
  .coeur-hub .coeur-tiles { margin-block: auto; }
  .has-appnav .profil-view > .container,
  .has-appnav .reglages-view > .container { max-width: none; }
  /* ---- Pages d'édition ouvertes depuis les Réglages (Mes informations / Mes critères) — DESKTOP ----
     La page occupe toute la largeur (comme Profil/Réglages) mais le formulaire est posé dans une CARTE
     de largeur lisible : au-delà de ~900 px, des champs pleine largeur deviennent pénibles à lire et le
     bouton d'envoi paraît démesuré. Le formulaire lui-même n'est pas modifié : tout est fait en CSS. */
  .has-appnav .edit-view > .container { max-width: none; }
  .has-appnav .edit-view .form {
    max-width: 900px;
    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 26px 28px 24px;
    /* ⚠️ `auto` DE CHAQUE CÔTÉ : la carte était calée à gauche (marge 0), et comme `.app-view` a
       48 px de rembourrage mais que la carte plafonne à 900 px, il restait 48 px à gauche pour 72 à
       droite — un décalage de 24 px, mesuré au navigateur, sur les DEUX pages d'édition. */
    margin: 14px auto 0;
    gap: 18px;
  }
  /* ⚠️ « Mes critères » porte ses PROPRES cartes (une par sujet) : le panneau unique ci-dessus y
     ferait une boîte dans une boîte. On lui retire son fond, on lui garde sa largeur lisible.
     ⚠️ SÉLECTEUR PLUS PRÉCIS QUE `.has-appnav .crit-form` : la règle du dessus vaut 0,3,0 et
     l'emportait — la carte blanche restait, mesurée au navigateur (fond rgb(255,255,255)). */
  .has-appnav .edit-view .form.crit-form {
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
  }
  /* Champs courts côte à côte : la ligne du haut respire au lieu de s'étirer sur toute la largeur. */
  .has-appnav .edit-identity .form { grid-template-columns: 1fr 1fr; align-items: start; }
  .has-appnav .edit-identity .form > * { grid-column: 1 / -1; }
  .has-appnav .edit-identity .form > label:first-of-type,
  .has-appnav .edit-identity .form > .birth-field { grid-column: span 1; }
  /* Paires de choix (Un homme/Une femme, Ouverte au mariage/Pas forcément) côte à côte : plus compact
     et plus lisible que deux barres empilées sur toute la largeur de la carte. */
  .has-appnav .edit-view .form .radio-cards { grid-template-columns: 1fr 1fr; }
  /* Bouton d'envoi : taille normale, aligné à droite du bloc (au lieu d'une barre pleine largeur). */
  .has-appnav .edit-view .form .btn-block {
    width: auto;
    min-width: 240px;
    justify-self: end;
    margin-top: 6px;
  }
  .has-appnav .messages-view > .container { max-width: 660px; }
  .has-appnav .today-view > .container,
  .has-appnav .match-view > .container { max-width: 460px; margin: 0 auto; }
  .has-appnav .today-view .profile-card { max-width: 100%; margin: 0; }
  .has-appnav .conv-list, .has-appnav .settings-card, .has-appnav .profil-view .card { max-width: none; }
  /* Écrans « état » (relecture, vide…) centrés */
  .has-appnav .app-view:has(.state-card) { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding-top: 0; padding-bottom: 0; }   /* 100vh : la sidebar fait déjà 100vh, rien à retrancher (sinon la carte remonte de ~43 px) */
  .has-appnav .app-view:has(.state-card) > .container { max-width: 500px; margin: 0 auto; }
  .app-nav-brand { display: flex; align-items: center; gap: 10px; padding: 4px 12px 26px; text-decoration: none; white-space: nowrap; }
  .app-nav-brand img { height: 30px; width: auto; }
  .app-nav-brand span { font-family: var(--font-brand); font-size: 1.4rem; font-weight: 600; color: var(--primary); }
  .app-nav-items { display: flex; flex-direction: column; gap: 4px; flex: 1; }
  .nav-item { flex-direction: row; justify-content: flex-start; gap: 14px; padding: 12px 16px; border-radius: 14px; font-size: 1rem; font-weight: 600; }
  .nav-item .nav-label { line-height: 1; }
  .nav-item:hover { background: rgba(34,62,99,.06); color: var(--primary); }
  .nav-item.active { background: var(--card); color: var(--primary); box-shadow: var(--shadow-sm); }
  .app-nav-logout { display: flex; align-items: center; gap: 14px; padding: 12px 16px; border-radius: 14px; color: var(--muted-foreground); text-decoration: none; font-weight: 600; font-size: .98rem; margin-top: 6px; }
  .app-nav-logout svg { width: 22px; height: 22px; }
  .app-nav-logout:hover { background: rgba(176,69,59,.08); color: var(--danger); }
}

/* Bandeau « profil en pause » — barre latérale desktop uniquement (mobile = barre d'icônes en bas, sans « Se déconnecter ») */
.nav-paused { display: none; }
@media (min-width: 900px) {
  .nav-paused { display: block; margin: 0 4px 8px; padding: 12px; border-radius: 14px; background: var(--muted); border: 1px solid var(--hairline); }
  .nav-paused-head { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: .9rem; color: var(--primary); }
  .nav-paused-head svg { width: 18px; height: 18px; flex-shrink: 0; }
}

/* ---- Carte profil (Aujourd'hui) ---- */
.today-view { padding-top: 14px; }
.today-head { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 12px; }
.today-count { font-size: .82rem; color: var(--muted-foreground); background: var(--muted); padding: 5px 14px; border-radius: 99px; }
.today-back-form { display: inline-flex; margin: 0; }
.today-back { border: 0; background: none; cursor: pointer; font: inherit; font-size: .82rem; color: var(--muted-foreground); padding: 5px 4px; transition: color .15s ease; }
.today-back:hover { color: var(--primary); }
.today-sep { color: var(--muted-foreground); opacity: .45; font-size: .82rem; }
.today-more-wrap { text-align: center; margin-top: 16px; }
.today-more { border: 0; cursor: pointer; transition: background .15s ease, color .15s ease; }
.today-more:hover { background: var(--secondary); color: var(--primary); }
.profile-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: 0 8px 30px rgba(16,32,39,.06); }
.card-photo { position: relative; }
.card-slides { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.card-slides::-webkit-scrollbar { display: none; }
.card-slide { flex: 0 0 100%; height: clamp(400px, 56vh, 560px); background-size: cover; background-position: center 20%; scroll-snap-align: center; }
.card-photo-empty { height: clamp(400px, 56vh, 560px); background: linear-gradient(160deg, var(--secondary), var(--muted)); }
.card-dots { position: absolute; bottom: 12px; left: 0; right: 0; display: flex; justify-content: center; gap: 6px; pointer-events: none; }
.card-dots span { width: 7px; height: 7px; border-radius: 99px; background: rgba(255,255,255,.55); box-shadow: 0 1px 3px rgba(16,32,39,.35); transition: width .2s ease, background .2s ease; }
.card-dots span.active { background: #fff; width: 18px; }
.card-arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; border: 1px solid rgba(255,255,255,.4); border-radius: 999px; background: rgba(255,255,255,.15); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); color: #fff; cursor: pointer; opacity: .8; transition: opacity .18s ease, background .18s ease; }
.card-arrow:hover { opacity: 1; background: rgba(255,255,255,.28); }
.card-arrow svg { width: 18px; height: 18px; }
.card-arrow-prev { left: 10px; }
.card-arrow-next { right: 10px; }
.card-arrow[hidden] { display: none; }
/* Visionneuse plein écran des photos (clic sur une photo → plein écran, croix + flèches + swipe). */
.card-slide { cursor: zoom-in; }
/* Couche de PREMIER PLAN : la visionneuse peut être ouverte depuis une fiche déjà affichée dans une modale
   (contrôle des matchs `.rv-modal` z1000, aperçu `.mod-preview-modal` z200…) — elle doit donc passer AU-DESSUS
   de toutes les modales, sinon la photo agrandie s'ouvre derrière le pop-up. */
.photo-lightbox { position: fixed; inset: 0; z-index: 1500; background: rgba(0,0,0,.94); display: flex; align-items: center; justify-content: center; }
.photo-lightbox[hidden] { display: none !important; }
/* Mobile : le cadre est transparent (ses enfants remplissent le plein écran comme avant). Desktop : il devient le pop-up. */
.pl-frame { display: contents; }
.pl-img { max-width: 100vw; max-height: 100vh; object-fit: contain; -webkit-user-select: none; user-select: none; }
.pl-close, .pl-nav { position: fixed; z-index: 3; display: flex; align-items: center; justify-content: center; border: 0; border-radius: 999px; background: rgba(255,255,255,.16); color: #fff; cursor: pointer; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); transition: background .15s ease; }
.pl-close:hover, .pl-nav:hover { background: rgba(255,255,255,.3); }
.pl-close { top: calc(env(safe-area-inset-top, 0px) + 14px); right: 14px; width: 44px; height: 44px; }
.pl-nav { top: 50%; transform: translateY(-50%); width: 46px; height: 46px; }
.pl-prev { left: 12px; }
.pl-next { right: 12px; }
.pl-nav[hidden] { display: none; }
.pl-dots { position: fixed; bottom: calc(env(safe-area-inset-bottom, 0px) + 18px); left: 0; right: 0; display: flex; justify-content: center; gap: 6px; pointer-events: none; }
.pl-dots span { width: 7px; height: 7px; border-radius: 99px; background: rgba(255,255,255,.45); transition: width .2s ease, background .2s ease; }
.pl-dots span.active { background: #fff; width: 18px; }
body.pl-open { overflow: hidden; }
/* Desktop (souris + large écran) : la visionneuse devient un POP-UP encadré sur une page assombrie/floutée,
   plus esthétique que le plein écran noir. Le mobile (hover:none) garde le plein écran (parfait au tactile). */
@media (min-width: 700px) and (hover: hover) {
  .photo-lightbox { background: rgba(12, 22, 30, .74); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); padding: 48px; }
  /* Le cadre devient le pop-up (dimensionné à l'image) et sert de repère pour placer les contrôles. */
  .pl-frame { position: relative; display: inline-block; line-height: 0; max-width: 100%; }
  /* max-width/height réduites pour laisser la place aux contrôles À L'EXTÉRIEUR du cadre (flèches sur les côtés, croix au-dessus). */
  .pl-img { display: block; max-width: min(80vw, 880px); max-height: 82vh; width: auto; height: auto; border-radius: 16px; box-shadow: 0 30px 80px rgba(0, 0, 0, .55); }
  .pl-close, .pl-nav { position: absolute; padding: 0; width: 40px; height: 40px; background: rgba(255, 255, 255, .92); color: #16202b; box-shadow: 0 4px 14px rgba(0, 0, 0, .3); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .pl-close:hover, .pl-nav:hover { background: #fff; }
  /* Flèches : sur les CÔTÉS, juste à l'extérieur des bords gauche/droit, centrées verticalement. */
  .pl-nav { top: 50%; bottom: auto; transform: translateY(-50%); }
  .pl-prev { right: calc(100% + 8px); left: auto; }
  .pl-next { left: calc(100% + 8px); right: auto; }
  /* Recentrage OPTIQUE du chevron : géométriquement centré, un « ‹ » paraît décalé (le point dépasse
     d'un côté) → on le pousse de 2px vers l'intérieur pour qu'il paraisse bien centré dans le rond. */
  .pl-prev svg { transform: translateX(2px); }
  .pl-next svg { transform: translateX(-2px); }
  /* Croix : juste au-dessus du coin haut-droit, hors du cadre. */
  .pl-close { top: auto; bottom: calc(100% + 10px); left: auto; right: 0; transform: none; }
  .pl-dots { position: absolute; bottom: 14px; left: 0; right: 0; }
  .pl-dots span { background: rgba(255, 255, 255, .6); }
  .pl-dots span.active { background: #fff; }
}
.card-why { margin: 12px; background: rgba(16,32,39,.62); color: #fff; font-size: .8rem; font-weight: 600; padding: 6px 12px; border-radius: 99px; backdrop-filter: blur(4px); }
.card-compat { position: absolute; top: 12px; right: 12px; display: flex; flex-direction: column; align-items: center; line-height: 1; background: rgba(255,255,255,.92); color: var(--primary); padding: 8px 12px; border-radius: 14px; box-shadow: 0 4px 14px rgba(16,32,39,.18); backdrop-filter: blur(4px); }
.card-compat strong { font-size: 1.15rem; font-weight: 700; }
.card-compat span { font-size: .62rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); margin-top: 2px; }
.card-body { padding: 20px; }
.card-name { font-size: 1.5rem; margin: 0 0 2px; }
.card-loc { color: var(--muted-foreground); margin: 0 0 12px; }
.card-origin { color: var(--muted-foreground); font-size: .92rem; margin: -6px 0 12px; }
/* ⚠️ LA LIGNE DU LIEU PEUT MANQUER (v1243 : elle n'est plus rendue quand il n'y a ni lieu ni âge),
   et c'était ELLE qui portait les 12 px sous le prénom — .card-name n'en a que 2. Sans cette règle,
   « Attaché·e à … » venait chevaucher le prénom de 4 px (le -6px ci-dessus n'avait plus rien à
   compenser), et les pastilles se collaient dessous. Mesuré au navigateur, avant/après.
   Un navigateur sans :has() retombe simplement sur l'ancien resserrement — jamais sur pire. */
.card-name:not(:has(+ .card-loc)) { margin-bottom: 12px; }
.field-help.origin-consent { font-size: .8rem; margin-top: 12px; }
.origin-consent input[type="checkbox"] { vertical-align: -2px; margin: 0 7px; width: 15px; height: 15px; accent-color: var(--primary); cursor: pointer; }
.card-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.badge { font-size: .78rem; font-weight: 600; padding: 5px 12px; border-radius: 99px; background: var(--muted); color: var(--secondary-foreground); }
.badge-faith { background: var(--secondary); color: var(--primary); }
.badge-practice { background: #E7EEF4; color: var(--primary); }
.card-bio { margin-bottom: 16px; }
.answer-block { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 12px; }
.answer-label { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--accent); font-weight: 700; margin: 0 0 3px; }
.answer-text { margin: 0; }
/* Dépliage du reste du profil. Discret : c'est une invitation à lire, pas un appel à l'action —
   les vrais boutons de la fiche restent « oui / passer / non ». */
.card-more { display: flex; align-items: center; justify-content: center; gap: 7px; width: 100%; margin-top: 14px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: transparent;
  color: var(--accent); font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer;
  transition: background .15s ease, border-color .15s ease; }
/* La flèche pointe vers le bas quand c'est fermé, vers le haut quand c'est ouvert : l'état se lit sans
   avoir à relire le libellé. */
.card-more-chev { flex: 0 0 auto; transition: transform .18s ease; }
.card-more.is-open .card-more-chev { transform: rotate(180deg); }
.card-more:hover { background: var(--muted); border-color: var(--accent); }
.card-more.is-open { color: var(--muted-foreground); font-weight: 500; }
/* « +N » en bout de rangée de pastilles : même gabarit qu'une pastille, mais en pointillé pour qu'on
   comprenne qu'il en reste dessous plutôt que d'y lire une sensibilité de plus. */
.badge-more { border: 1px dashed var(--border); background: transparent; color: var(--muted-foreground);
  font: inherit; font-size: .78rem; font-weight: 700; cursor: pointer; padding: 4px 10px; border-radius: 999px;
  transition: border-color .12s ease, color .12s ease; }
.badge-more:hover { border-color: var(--accent); color: var(--accent); }

/* Fiche admin — « qui lui a dit oui » : pastille de compte sur l'icône, puis la liste dans la pop-up. */
.mod-preview-btn { position: relative; }
.mod-btn-count { position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 999px; background: var(--accent); color: #fff; font-size: .66rem; font-weight: 800;
  line-height: 17px; text-align: center; }
.oui-list { display: flex; flex-direction: column; gap: 6px; max-height: min(56vh, 460px); overflow-y: auto;
  margin-top: 10px; text-align: left; }
.oui-row { display: flex; align-items: center; gap: 11px; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: 11px; color: inherit; text-decoration: none; transition: background .12s ease, border-color .12s ease; }
.oui-row:hover { background: var(--muted); border-color: var(--accent); }
.oui-av { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 10px; background: var(--muted) center/cover no-repeat; }
.oui-av-empty { background: linear-gradient(160deg, var(--secondary), var(--muted)); }
.oui-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.oui-info .muted { font-size: .8rem; }
.oui-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; }
.oui-tag { font-size: .7rem; font-weight: 700; padding: 1px 7px; border-radius: 999px;
  background: var(--muted); color: var(--muted-foreground); }
.oui-tag-match { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.oui-tag-off { background: color-mix(in srgb, #B0453B 14%, transparent); color: #B0453B; }
.oui-go { flex: 0 0 auto; color: var(--muted-foreground); font-size: 1.2rem; }
.card-actions { display: flex; gap: 9px; padding: 14px 20px 20px; align-items: stretch; }
.card-actions > form { display: flex; }
/* Le « Oui » qui ouvre directement la conversation est enveloppé dans un <form> : c'est donc LUI qui
   doit prendre la place que le bouton occupait comme enfant direct de la rangée. Sans ça, `flex:1`
   s'applique au bouton à l'intérieur du formulaire et le « Oui » se réduit à la largeur de son texte. */
.card-actions > .card-yes-direct { flex: 1; }
.btn-action { padding: 11px 12px; border-radius: 99px; font-weight: 700; font-size: .95rem; cursor: pointer; border: 1px solid var(--border); background: var(--card); position: relative; }
/* Non (croix) + Passer (flèche) = boutons FINS, icône seule ; Oui = bouton principal texte qui remplit. */
.btn-no, .btn-pass { width: 54px; padding: 11px 0; color: var(--muted-foreground); display: inline-flex; align-items: center; justify-content: center; line-height: 0; }
.btn-no:hover { background: #fbebeb; border-color: #e3b7b7; color: #b23a3a; }
.btn-pass:hover { background: var(--muted); color: var(--foreground); }
.btn-yes { flex: 1; background: var(--primary); color: #fff; border-color: var(--primary); padding: 15px 12px; font-size: 1.08rem; font-weight: 800; }
.btn-yes:hover { background: #16304F; }
.btn-like { background: var(--primary); color: #fff; border-color: var(--primary); flex: 1.6; }
.btn-like:hover { background: #16304F; }
/* Infobulle explicative au survol (desktop) ; sur mobile → aria-label + icônes (pas de survol tactile). */
.btn-action[data-tip]:hover::after, .btn-action[data-tip]:focus-visible::after {
  content: attr(data-tip); position: absolute; bottom: calc(100% + 9px); left: 50%; transform: translateX(-50%);
  background: var(--foreground); color: #fff; padding: 8px 11px; border-radius: 9px; font-size: .77rem; font-weight: 500;
  line-height: 1.35; width: max-content; max-width: 200px; text-align: center; z-index: 30; pointer-events: none;
  box-shadow: 0 8px 22px rgba(16, 32, 43, .22);
}
/* Boutons de bord : la carte a overflow:hidden → une infobulle centrée déborde et se fait rogner.
   On l'ancre vers l'INTÉRIEUR de la carte (à droite du ✕, à gauche du →) pour qu'elle reste visible en entier. */
.btn-no[data-tip]:hover::after, .btn-no[data-tip]:focus-visible::after { left: 0; right: auto; transform: none; }
.btn-pass[data-tip]:hover::after, .btn-pass[data-tip]:focus-visible::after { left: auto; right: 0; transform: none; }

/* ---- State cards / empty states ---- */
.state-card { padding: 34px 26px; }
.state-emoji { font-size: 2.6rem; margin-bottom: 8px; }
/* Illustrations dessinées à la main, à la place des emojis. Même emprise que ceux qu'elles remplacent,
   et `height:auto` pour qu'un visuel non carré ne soit jamais écrasé. */
/* La largeur est posée en ligne par plv_illu() : chaque illustration a la sienne. */
.state-illu { display: block; height: auto; margin: 0 auto 10px; }
.buy-card { margin-top: 16px; background: var(--secondary); border-color: var(--accent); }
.buy-detail { text-align: center; }

/* ---- Modales ---- */
.modal-open { overflow: hidden; }
.like-modal { position: fixed; inset: 0; z-index: 100; background: rgba(16,32,39,.5); display: flex; align-items: flex-end; justify-content: center; }
.like-modal-inner { background: var(--card); width: 100%; max-width: 460px; border-radius: var(--radius) var(--radius) 0 0; padding: 24px 22px calc(24px + env(safe-area-inset-bottom)); position: relative; animation: slideUp .22s ease; }
@keyframes slideUp { from { transform: translateY(30px); opacity: .6; } to { transform: none; opacity: 1; } }
.modal-close { position: absolute; top: 12px; right: 14px; border: none; background: none; font-size: 1.6rem; line-height: 1; color: var(--muted-foreground); cursor: pointer; }
.like-modal h2 { font-size: 1.2rem; padding-right: 20px; }
.touch-opts { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
.touch-opt { border: 1px solid var(--border); border-radius: 99px; padding: 8px 14px; cursor: pointer; font-size: .88rem; }
.touch-opt input { display: none; }
.touch-opt:has(input:checked) { background: var(--primary); color: #fff; border-color: var(--primary); }
.like-modal textarea { width: 100%; padding: 12px 14px; font: inherit; border: 1px solid var(--border); border-radius: 12px; }
.modal-hint { font-size: .8rem; color: var(--muted-foreground); margin: 8px 0 14px; }
/* Desktop : popups centrés dans la colonne de contenu, à droite de la nav (260px). Mobile garde le bottom-sheet. */
@media (min-width: 900px) {
  .like-modal { align-items: center; left: 260px; } /* décalé de la barre latérale MEMBRE (.app-nav = 260px) */
  /* Back-office : la barre latérale admin fait 232px (pas 260) → on aligne le grisé sur SON bord,
     sinon une bande de contenu reste non grisée juste à droite du menu. */
  body.admin-shell .like-modal { left: 232px; }
  .like-modal-inner { border-radius: var(--radius); padding-bottom: 24px; }
}
/* Modale de signalement : champs empilés + menu déroulant stylé (chevron custom) */
.report-modal .report-label { display: block; font-weight: 600; font-size: .9rem; color: var(--foreground); margin: 16px 0 6px; }
.report-modal .report-opt { color: var(--muted-foreground); font-weight: 400; font-size: .85rem; }
.report-modal .select-wrap { position: relative; }
.report-modal .select-wrap::after { content: ''; position: absolute; right: 16px; top: calc(50% - 5px); width: 8px; height: 8px; border-right: 2px solid var(--muted-foreground); border-bottom: 2px solid var(--muted-foreground); transform: rotate(45deg); pointer-events: none; }
.report-modal select { -webkit-appearance: none; appearance: none; width: 100%; padding: 12px 40px 12px 14px; font: inherit; color: var(--foreground); background: var(--card); border: 1px solid var(--border); border-radius: 12px; cursor: pointer; }
.report-modal select:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.report-modal .btn-block { margin-top: 20px; }

/* ---- Modale de suppression de compte ---- */
.del-modal { max-width: 480px; }
.del-step h2 { font-size: 1.35rem; margin: 0 0 6px; padding-right: 24px; }
.del-step p { font-size: .96rem; line-height: 1.5; margin: 0 0 12px; }
.del-reasons { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.del-reason { display: flex; align-items: center; gap: 10px; text-align: left; padding: 14px 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--card); font: inherit; font-weight: 600; color: var(--foreground); cursor: pointer; line-height: 1.3; }
.del-reason:hover { border-color: var(--primary); background: var(--muted); }
.del-reason span { font-size: 1.15rem; }
.del-reason-happy { border-color: var(--primary); background: #E7EEFB; }
.del-reason-happy:hover { border-color: var(--primary); background: #DCE7F8; }
.del-emoji { font-size: 2.4rem; text-align: center; margin-bottom: 4px; }
.del-step[data-del-step="donation"] > h2 { text-align: center; padding-right: 0; }
.del-rib { background: var(--muted); border-radius: 12px; padding: 4px 16px; margin: 14px 0; }
.del-rib > div { display: flex; justify-content: space-between; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--hairline); font-size: .92rem; }
.del-rib > div:last-child { border-bottom: none; }
.del-rib span { color: var(--muted-foreground); }
.del-rib strong { font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.del-step .btn { width: 100%; margin-top: 10px; }

/* ---- Match ---- */
.match-view { padding-top: 40px; }
.match-rings img { width: 84px; height: auto; }
.match-celebration h1 { font-family: var(--font-brand); font-size: 2rem; color: var(--primary); margin-top: 14px; }
.match-photo { width: 120px; height: 120px; border-radius: 99px; object-fit: cover; margin: 14px auto; display: block; border: 3px solid var(--accent); }
.match-name { font-weight: 700; font-size: 1.2rem; }
.match-actions { display: grid; gap: 10px; margin-top: 22px; }

/* ---- Messages ---- */
.conv-list { display: flex; flex-direction: column; }
.conv-row { display: flex; align-items: center; gap: 14px; padding: 12px 4px; border-bottom: 1px solid var(--border); text-decoration: none; color: var(--foreground); }
.conv-avatar { width: 54px; height: 54px; border-radius: 99px; background: var(--muted); background-size: cover; background-position: center; flex-shrink: 0; }
.conv-avatar.sm { width: 38px; height: 38px; }
.conv-avatar-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
.conv-meta { flex: 1; min-width: 0; }
.conv-name { display: block; font-weight: 700; }
.conv-preview { display: block; color: var(--muted-foreground); font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.conv-unread { background: var(--primary); color: #fff; font-size: .72rem; font-weight: 700; min-width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 99px; padding: 0 5px; }
/* Fiches « Mes coups de cœur » — cartes verticales en grille */
.fav-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: 18px; }
.fav-card { display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--hairline); border-radius: 18px; overflow: hidden; box-shadow: var(--shadow-sm); text-decoration: none; color: var(--foreground); }
.fav-card { cursor: pointer; transition: box-shadow .15s ease, transform .15s ease; }
.fav-card:hover { box-shadow: var(--shadow-md); transform: translateY(-3px); }
.fav-card:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.fav-photo { width: 100%; aspect-ratio: 4 / 5; background: var(--muted); background-size: cover; background-position: center; }
.fav-photo-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
.fav-body { padding: 14px 16px 16px; flex: 1; min-width: 0; }
.fav-name { font-size: 1.15rem; margin: 0 0 2px; }
.fav-loc { color: var(--muted-foreground); margin: 0 0 6px; font-size: .92rem; }
/* ⚠️ MÊME PIÈGE QUE .card-name : le lieu et l'âge partagent désormais cette ligne, qui n'est
   rendue que si l'un des deux existe. C'est elle qui porte les 6 px sous le prénom — .fav-name
   n'en a que 2. Sans cette règle, un membre sans lieu NI âge verrait « Tu as dit oui… » collé
   sous son prénom. Cas rare (la date de naissance est demandée à l'inscription), pas impossible. */
.fav-name:not(:has(+ .fav-loc)) { margin-bottom: 6px; }
/* Carte « Visibilité » (Réglages) : l'état, dit avant le bouton.
   ⚠️ TROIS ÉTATS QUI NE SE VALENT PAS — en pause (choisi), en validation (subi, temporaire),
   visible. La carte les taisait tous les trois : une personne en validation y lisait le même
   écran qu'une personne visible, et concluait que le bouton de reprise n'avait rien fait. */
.vis-etat { margin: 0 0 12px; padding: 10px 12px; border-radius: 10px; font-size: .92rem; line-height: 1.45; }
.vis-pause   { background: var(--muted); color: var(--foreground); }
.vis-attente { background: rgba(176, 138, 79, .12); color: var(--foreground); }
.vis-ok      { background: rgba(46, 125, 83, .10); color: var(--foreground); }
/* La ligne « Statut » de la fiche admin : une pastille qui OUVRE UN MENU (v1262).
   ⚠️ ELLE DOIT SE VOIR COMME UN CONTRÔLE, sinon c'est un mot de plus — d'où le fond, le curseur
   et le chevron. Le ton dit l'état d'un coup d'œil : un « Profil validé » sur le fond ambre de
   l'ancienne pastille « En pause » se serait lu comme un avertissement. */
.statut-menu { position: relative; display: inline-block; }
.statut-menu > summary { list-style: none; }
.statut-menu > summary::-webkit-details-marker { display: none; }
.statut-pastille { display: inline-flex; align-items: center; gap: 8px; font: inherit; font-weight: 700;
  font-size: .95rem; color: var(--foreground); background: var(--muted); border: 1px solid var(--border);
  border-radius: 99px; padding: 3px 12px; cursor: pointer; user-select: none;
  transition: background .12s ease, border-color .12s ease; }
.statut-pastille.st-ok      { background: rgba(46, 125, 83, .12);  border-color: rgba(46, 125, 83, .34); }
.statut-pastille.st-attente { background: rgba(176, 138, 79, .16); border-color: rgba(176, 138, 79, .38); }
.statut-pastille:hover,
.statut-menu[open] > .statut-pastille { border-color: var(--primary); }
.statut-pastille:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.statut-caret { font-size: .78em; opacity: .65; transition: transform .15s ease; }
.statut-menu[open] .statut-caret { transform: rotate(180deg); }
/* ⚠️ LE MENU S'OUVRE VERS LE BAS, dans une carte SANS overflow:hidden (`.card` n'en pose pas) et
   la ligne Statut est la première de la carte : rien à rogner. Vérifié au navigateur. */
.statut-menu-pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 208px; display: flex; flex-direction: column; gap: 2px; padding: 6px;
  border-radius: 14px; background: var(--card); border: 1px solid var(--border);
  box-shadow: 0 14px 38px rgba(16, 32, 39, .16); }
.statut-menu-pop form { margin: 0; }
.statut-opt { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  font: inherit; font-weight: 600; font-size: .9rem; line-height: 1.3; color: var(--foreground);
  background: none; border: 0; border-radius: 10px; padding: 9px 10px; cursor: pointer; }
button.statut-opt:hover { background: var(--muted); }
button.statut-opt:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.statut-opt.is-on { background: rgba(46, 125, 83, .12); cursor: default; }
.statut-opt.is-stop { color: var(--muted-foreground); cursor: not-allowed; }
.statut-coche { flex: none; width: 13px; color: #2E7D53; font-weight: 800; }
.fav-sub { color: var(--muted-foreground); margin: 0; font-size: .82rem; }
.fav-foot { padding: 4px 14px 14px; }
.fav-status { display: block; text-align: center; font-size: .84rem; font-weight: 700; padding: 9px 12px; border-radius: 12px; white-space: nowrap; }
.fav-match { background: #E6F3EC; color: #2E7D53; }
.fav-pending { background: var(--muted); color: var(--muted-foreground); }
@media (max-width: 560px) { .fav-list { grid-template-columns: 1fr 1fr; gap: 12px; } .fav-name { font-size: 1.04rem; } .fav-body { padding: 12px 13px 6px; } .fav-foot { padding: 2px 13px 12px; } }
/* Coups de cœur : conteneur pleine largeur, calé à gauche comme les autres pages (padding 48px),
   d'où une marge gauche = celle du site et une marge droite identique (symétrique) */
@media (min-width: 900px) { .has-appnav .app-view.favoris-view > .container { max-width: none; margin: 0; } }
/* Popup d'achat de pack : paiement Stripe embarqué (Embedded Checkout) dans la modale */
.buy-modal-inner { max-height: 92vh; overflow-y: auto; }
.buy-checkout-wrap { margin-top: 6px; min-height: 320px; }
#plv-embedded-checkout { min-height: 320px; }
.buy-error { color: #c0392b; }

/* Badge « clé enregistrée » dans les Réglages Stripe */
.key-set { display: inline-block; font-size: .72rem; font-weight: 700; color: #1c7c46; background: #e6f6ec; padding: 1px 8px; border-radius: 99px; vertical-align: middle; margin-left: 2px; }

/* Popup « revoir le profil » depuis une fiche coup de cœur */
.fav-modal .like-modal-inner { max-width: 440px; max-height: 92vh; overflow-y: auto; }
.fav-modal .modal-close { z-index: 4; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; border-radius: 99px; background: rgba(16,32,39,.5); color: #fff; }
.fav-modal .profile-card-view { box-shadow: none; margin-top: 6px; }
/* Popup profil : même recadrage plein cadre (cover) que la fiche du jour */
.fav-modal .profile-card-view .card-slide, .fav-modal .profile-card-view .card-photo-empty { height: clamp(300px, 44vh, 430px); }
.fav-modal-foot { margin-top: 16px; }

/* ---- Conversation ---- */
.page-conv main { display: flex; flex-direction: column; }
/* ⚠️ DEUX HAUTEURS, ET C EST VOULU. `100dvh` est la règle ; `--vvh` la remplace quand le navigateur
   sait dire la hauteur réelle qui reste sous le clavier (voir app.js). Une déclaration qu un vieux
   navigateur ne comprend pas est ignorée, et il garde la première : le repli est gratuit.
   ⚠️ NE PAS remplacer 100dvh par --vvh seul : hors clavier la variable n existe pas, et la
   conversation n aurait plus de hauteur du tout. */
.conv-view { display: flex; flex-direction: column; height: 100dvh; height: var(--vvh, 100dvh); padding: 0; background: #ECE5DD; }
.conv-header { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--card); z-index: 5; box-shadow: 0 1px 3px rgba(16,32,39,.05); }
.conv-back { font-size: 1.9rem; line-height: 1; text-decoration: none; color: var(--primary); margin-right: -4px; }
.conv-title { font-weight: 700; flex: 1; font-size: 1.05rem; }
.conv-menu-btn { border: none; background: none; font-size: 1.5rem; cursor: pointer; color: var(--muted-foreground); }
.conv-menu { position: absolute; top: 54px; right: 14px; background: var(--card); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 8px 30px rgba(16,32,39,.12); z-index: 20; overflow: hidden; }
.conv-menu button { display: block; width: 100%; text-align: left; padding: 12px 20px; border: none; background: none; cursor: pointer; font: inherit; }
.conv-menu button:hover { background: var(--muted); }
.conv-menu .danger { color: var(--danger); }
/* Blocage : badge (liste + en-tête), ligne grisée, bandeau « supprimée sous 48 h » à la place du composeur */
.conv-blocked-tag { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; background: var(--muted); color: var(--muted-foreground); font-size: .68rem; font-weight: 700; letter-spacing: .02em; vertical-align: middle; border: 1px solid var(--hairline); }
.conv-blocked-tag.sm { margin-left: 6px; font-size: .6rem; padding: 0 6px; }
/* Avertissement d'expiration (conversation muette depuis ≥ 12 j, disparaît à 15 j) : pastille ambre discrète. */
.conv-expiry-tag { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px; background: #FBF3E1; color: #9A6A00; font-size: .6rem; font-weight: 700; letter-spacing: .02em; vertical-align: middle; border: 1px solid rgba(154,106,0,.22); white-space: nowrap; }
.conv-row.is-blocked .conv-avatar { filter: grayscale(1); opacity: .65; }
.conv-row.is-blocked .conv-name { color: var(--muted-foreground); }
.conv-row.is-blocked .conv-preview { font-style: italic; }
.conv-blocked-note { padding: 16px 18px calc(16px + env(safe-area-inset-bottom)); border-top: 1px solid var(--border); background: var(--muted); }
.conv-blocked-note p { margin: 0 0 12px; font-size: .9rem; line-height: 1.5; color: var(--foreground); }
.conv-blocked-note .btn { margin: 0; }
/* Fil de discussion type messagerie (fond chaud, bulles avec heure, séparateurs de date) */
.conv-thread { flex: 1; overflow-y: auto; padding: 14px 12px 20px; display: flex; flex-direction: column; gap: 9px; }
.conv-empty { text-align: center; color: var(--muted-foreground); margin: auto; max-width: 260px; background: rgba(255,255,255,.7); padding: 14px 18px; border-radius: 14px; }
.msg-daysep { align-self: center; margin: 12px 0 8px; }
.msg-daysep span { background: rgba(255,255,255,.9); color: var(--muted-foreground); font-size: .72rem; font-weight: 700; letter-spacing: .01em; padding: 4px 12px; border-radius: 10px; box-shadow: 0 1px 1px rgba(16,32,39,.08); }
.msg-wrap { display: flex; flex-direction: column; max-width: 78%; position: relative; }
.msg-out-wrap { align-self: flex-end; align-items: flex-end; }
.msg-in-wrap { align-self: flex-start; align-items: flex-start; }
.msg { display: flow-root; position: relative; max-width: 100%; padding: 6px 10px 6px; border-radius: 12px; font-size: .95rem; line-height: 1.38; word-wrap: break-word; overflow-wrap: anywhere; box-shadow: 0 1px 1px rgba(16,32,39,.12); }
.msg-body { white-space: pre-wrap; }
.msg-time { float: right; font-size: .62rem; color: rgba(16,32,39,.42); margin: 8px 0 -1px 10px; line-height: 1; }
.msg-in { background: #fff; border-top-left-radius: 4px; }
.msg-out { background: #DCE9FB; border-top-right-radius: 4px; }
/* Petit déclencheur de réaction (icône emoji en bout de message, révélé au survol) */
.msg-react-trigger { position: absolute; top: 50%; margin-top: -14px; display: none; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 99px; border: 1px solid var(--hairline); background: var(--card); color: var(--muted-foreground); cursor: pointer; box-shadow: 0 2px 8px rgba(16,32,39,.18); z-index: 7; padding: 0; }
.msg-react-trigger svg { width: 17px; height: 17px; }
/* Collé à la bulle (léger chevauchement) → pas d'écart, le survol reste continu jusqu'au clic */
.msg-out-wrap .msg-react-trigger { right: calc(100% - 4px); }
.msg-in-wrap .msg-react-trigger { left: calc(100% - 4px); }
.msg-wrap:hover .msg-react-trigger, .msg-wrap.react-open .msg-react-trigger { display: flex; }
.msg-react-trigger:hover { background: var(--muted); color: var(--primary); }
@media (hover: none) { .msg-react-trigger { display: flex; opacity: .6; } }
/* Panneau d'emojis de réaction (flottant, même jeu que le composeur) */
.msg-react-picker { position: fixed; z-index: 120; max-width: 300px; max-height: 220px; overflow-y: auto; background: var(--card); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 10px 34px rgba(16,32,39,.22); padding: 8px; display: grid; grid-template-columns: repeat(auto-fill, minmax(36px, 1fr)); gap: 2px; }
.msg-react-picker[hidden] { display: none; }
.msg-react-picker button { border: none; background: none; font-size: 1.4rem; padding: 4px; cursor: pointer; border-radius: 8px; line-height: 1.2; }
.msg-react-picker button:hover { background: var(--muted); }
/* Réactions posées (pastilles sous la bulle) */
.msg-reactions { display: flex; gap: 3px; margin-top: 3px; }
.msg-reactions:empty { display: none; }
.msg-reaction { background: var(--card); border: 1px solid var(--hairline); border-radius: 99px; padding: 0 7px; font-size: .8rem; line-height: 1.6; box-shadow: 0 1px 1px rgba(16,32,39,.1); cursor: default; }
.msg-reaction.mine { border-color: var(--primary); background: #EEF3FB; cursor: pointer; }
.msg-reaction.mine:hover { border-color: var(--danger); background: #FBEDEB; }
/* Indicateur « en train d'écrire » (façon WhatsApp) : bulle blanche alignée à gauche, trois points qui rebondissent. */
.msg-typing { align-self: flex-start; max-width: 78%; }
.msg-typing[hidden] { display: none; }
.msg-typing-bubble { display: inline-flex; align-items: center; gap: 4px; padding: 10px 12px; background: #fff; border-radius: 12px; border-top-left-radius: 4px; box-shadow: 0 1px 1px rgba(16,32,39,.12); }
.msg-typing-bubble span { width: 7px; height: 7px; border-radius: 50%; background: rgba(16,32,39,.32); animation: msgTyping 1.2s infinite ease-in-out both; }
.msg-typing-bubble span:nth-child(2) { animation-delay: .18s; }
.msg-typing-bubble span:nth-child(3) { animation-delay: .36s; }
@keyframes msgTyping { 0%, 80%, 100% { opacity: .3; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .msg-typing-bubble span { animation: none; opacity: .6; } }
/* Note d'échec d'envoi (hors-ligne, compte en pause…) : discrète, au-dessus du composeur, disparaît seule. */
.conv-send-note { margin: 0; padding: 8px 14px; font-size: .85rem; color: #B3261E; background: #FDECEA; border-top: 1px solid rgba(179,38,30,.18); text-align: center; }
.conv-send-note[hidden] { display: none; }
.conv-composer { position: relative; display: flex; align-items: flex-end; gap: 6px; padding: 8px 10px calc(8px + env(safe-area-inset-bottom)); border-top: 1px solid var(--border); background: var(--card); }
.conv-emoji-btn { flex-shrink: 0; width: 42px; height: 42px; border: none; background: none; font-size: 1.4rem; cursor: pointer; border-radius: 99px; line-height: 1; }
.conv-emoji-btn:hover { background: var(--muted); }
.conv-composer textarea { flex: 1; resize: none; padding: 10px 16px; font: inherit; border: 1px solid var(--border); border-radius: 22px; max-height: 120px; background: var(--card); }
.conv-send { flex-shrink: 0; width: 46px; height: 46px; border: none; border-radius: 99px; background: var(--primary); color: #fff; font-size: 1.15rem; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.conv-send:hover { background: #1a3050; }
.emoji-panel { position: absolute; left: 8px; right: 8px; bottom: calc(100% + 6px); max-height: 244px; overflow-y: auto; background: var(--card); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 -6px 24px rgba(16,32,39,.16); padding: 10px; display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 2px; z-index: 20; }
.emoji-panel[hidden] { display: none; }
.emoji-panel button { border: none; background: none; font-size: 1.5rem; padding: 5px; cursor: pointer; border-radius: 8px; line-height: 1.2; }
.emoji-panel button:hover { background: var(--muted); }
/* Conversation dans la coquille membre : menu latéral conservé sur desktop, plein écran sur mobile */
@media (min-width: 900px) { .has-appnav .app-view.conv-view { padding: 0; } }
@media (max-width: 899px) { .page-conv .app-nav { display: none; } .page-conv.has-appnav { padding-bottom: 0; } }
.page-conv main > .flash, .page-msg2 main > .flash { position: fixed; top: 14px; left: 50%; transform: translateX(-50%); margin: 0; z-index: 80; box-shadow: var(--shadow-md); }
/* Messagerie 2 volets : liste à gauche, conversation à droite */
.conv-row.active { background: var(--muted); border-radius: 10px; }
.msg-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; text-align: center; color: var(--muted-foreground); height: 100%; padding: 24px; }
.msg-empty .state-emoji { font-size: 2.4rem; }
/* Encadré de prudence en bas de la colonne des conversations */
.msg-safety { margin-top: 14px; flex-shrink: 0; padding: 12px 14px; border-radius: 12px; background: var(--muted); border: 1px solid var(--hairline); font-size: .8rem; line-height: 1.45; color: var(--muted-foreground); }
/* ⚠️ Le chevron est À GAUCHE, avant le texte (demande de Gabriel, 27/08) : c'est lui qui ouvre et
   ferme, il doit se voir avant qu'on lise. Il pivote pour dire dans quel sens ça va.
   ⚠️ `<details>` natif plutôt qu'un bouton et du JavaScript : ça s'ouvre au clavier, ça survit à un
   script en panne, et la page n'a aucun script en ligne à faire autoriser. */
.msg-safety-title { display: flex; align-items: center; gap: 8px; font-weight: 700;
  color: var(--primary); margin: 0 0 5px; font-size: .82rem; cursor: pointer; list-style: none; }
.msg-safety-title::-webkit-details-marker { display: none; }
/* ---- Le chevron des dépliants -------------------------------------------------------------
   ⚠️ UN VRAI TRACÉ, pas deux bordures pivotées. Un carré CSS dont on ne garde que deux côtés
   donne des bouts coupés net et un angle vif : à petite taille, ça ressemble à un crochet, pas
   au chevron des autres icônes de l'application. Celui-ci est dessiné comme elles — 1,8 px,
   extrémités et angle ARRONDIS — et il leur ressemble enfin.
   ⚠️ SENS NATIF : fermé, il pointe à DROITE (« ça s'ouvre par là ») ; ouvert, il pointe en BAS,
   vers le texte qu'il vient de déplier. C'est le triangle de `<details>`, du Finder et de tous
   les arbres de fichiers — l'inverse se lit à contresens. */
.dep-chev { flex: none; width: 12px; height: 12px; transition: transform .18s ease;
  /* ⚠️ ALIGNEMENT OPTIQUE, pas géométrique : les boîtes étaient déjà centrées à 0,3 px près
     (mesuré), mais la ligne inclut l'espace des jambages tandis que l'œil compare le chevron aux
     MAJUSCULES, plus hautes. Un pixel vers le haut, et il se pose enfin sur le mot. */
  position: relative; top: -1px; }
details:not([open]) > summary .dep-chev { transform: rotate(-90deg); }
/* Replié, le titre est seul : il ne doit pas traîner une marge sous lui. */
.msg-safety:not([open]) .msg-safety-title { margin-bottom: 0; }
.msg-safety p { margin: 0 0 6px; }
.msg-safety p:last-child { margin-bottom: 0; }
@media (min-width: 900px) {
  .page-msg2 .app-view.msg-2pane { padding: 0; height: 100dvh; display: flex; }
  .msg-pane-list { width: 340px; flex-shrink: 0; border-right: 1px solid var(--hairline); overflow: hidden; padding: 30px 20px 20px; display: flex; flex-direction: column; }
  .msg-pane-list .view-title { margin-bottom: 14px; }
  .msg-pane-list .conv-list { flex: 1; min-height: 0; overflow-y: auto; }
  .msg-pane-chat { flex: 1; min-width: 0; }
  .page-msg2 .msg-pane-chat .conv-view { height: 100%; }
  .page-msg2 .msg-pane-chat .conv-back { display: none; }
  .msg-empty { background: #ECE5DD; }
}
@media (max-width: 899px) {
  .msg-2pane { display: block; }
  /* Colonne pleine hauteur + marges latérales : titre « Messages » et encadré « conseil » calés comme les autres pages (20px), encadré collé en bas au-dessus de la barre.
     padding-haut 0 : le titre s'aligne sur les 26px de .app-view (comme « Mes coups de cœur »), sans cumul de padding */
  .msg-2pane .msg-pane-list { padding: 0 20px 16px; display: flex; flex-direction: column; min-height: calc(100dvh - 104px); }
  /* Fils de conversation en pleine largeur : on annule la marge du volet, le contenu reste aligné sur le titre */
  .msg-2pane .conv-list { margin: 0 -20px; }
  .msg-2pane .conv-row { padding: 12px 20px; }
  .msg-2pane .msg-safety { margin-top: auto; }
  .msg-2pane .msg-pane-chat { display: none; }
  .msg-2pane.has-active .msg-pane-list { display: none; }
  .msg-2pane.has-active .msg-pane-chat { display: block; }
  .page-msg2-active .app-nav { display: none; }
  .page-msg2-active.has-appnav { padding-bottom: 0; }
  .page-msg2-active .app-view.msg-2pane { padding: 0; }
  /* ⚠️ Parité avec /app/conversation (audit du 31/08) : sur Android la meta resizes-content fait
   suivre 100dvh au clavier, mais iOS — où la meta n'existe pas — ne suit que var(--vvh). */
  .page-msg2-active .msg-pane-chat .conv-view { height: 100dvh; height: var(--vvh, 100dvh); }
}

/* ---- Profil / réglages ---- */
.profil-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ph-tag { position: absolute; top: 6px; left: 6px; font-size: .68rem; font-weight: 700; padding: 3px 8px; border-radius: 6px; color: #fff; }
.ph-tag.pending { background: var(--accent); }
.ph-tag.rejected { background: var(--danger); }
.ph-tag.approved, .ph-tag.ok { background: var(--success); }
.settings-card { margin-bottom: 14px; }
.settings-card h2 { font-size: 1.1rem; margin: 0 0 2px; color: var(--primary); }
/* Interrupteur segmenté coulissant Test / Production (réglages Stripe) */
.seg-toggle { position: relative; display: inline-flex; width: 260px; max-width: 100%; background: var(--muted); border: 1px solid var(--hairline); border-radius: 999px; padding: 3px; touch-action: manipulation; }
.seg-radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.seg-opt { position: relative; z-index: 1; flex: 1 1 0; display: flex; align-items: center; justify-content: center; padding: 8px 12px; border-radius: 999px; font-size: .9rem; font-weight: 600; color: var(--muted-foreground); cursor: pointer; user-select: none; transition: color .25s ease; }
.seg-thumb { position: absolute; z-index: 0; top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px); border-radius: 999px; background: var(--card); box-shadow: var(--shadow-sm); transition: transform .3s cubic-bezier(.34, 1.4, .5, 1); }
#sm-test:checked ~ .seg-thumb { transform: translateX(0); }
#sm-live:checked ~ .seg-thumb { transform: translateX(100%); }
#sm-test:checked ~ label[for="sm-test"] { color: var(--primary); }
#sm-live:checked ~ label[for="sm-live"] { color: var(--danger); }
.seg-radio:focus-visible + .seg-opt { outline: 2px solid var(--primary); outline-offset: 2px; }
.danger-zone h2 { color: var(--danger); }
.logout-link { text-align: center; margin-top: 20px; }

/* ---- Réglages membre : cartes en maçonnerie ---- */
.member-settings-grid { column-count: 1; column-gap: 16px; }
.member-settings-grid .settings-card { margin: 0 0 16px; break-inside: avoid; }
@media (min-width: 900px) {
  .member-settings-grid { column-count: 2; }
}

/* ---- Profil membre — mise en page « canon » ---- */
.pf-banner { display: flex; align-items: flex-start; gap: 10px; padding: 14px 18px; border-radius: 16px; font-size: .95rem; line-height: 1.45; margin-bottom: 24px; }
.pf-banner a { color: inherit; font-weight: 700; }
.pf-banner.info { background: var(--rose-soft); color: var(--primary); }
.pf-banner.reject { background: #FBEDEB; color: var(--danger); }
.pf-banner-ic { font-size: 1.15rem; line-height: 1.3; }
.pf-validated { display: flex; width: fit-content; margin-left: auto; align-items: center; gap: 6px; padding: 5px 13px; border-radius: 999px; background: #E6F3EC; color: #2E8F6B; font-size: .82rem; font-weight: 700; margin-bottom: 22px; }
.pf-validated span { font-size: .95rem; }

.pf-layout { display: grid; gap: 22px; }
.pf-hero-photo { position: relative; border-radius: 22px; overflow: hidden; aspect-ratio: 4/5; background: linear-gradient(160deg, var(--secondary), var(--muted)); box-shadow: var(--shadow-md); }
.pf-hero-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pf-photo-empty { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--muted-foreground); font-size: .9rem; }
.pf-photo-tag { position: absolute; top: 12px; left: 12px; font-size: .72rem; font-weight: 700; padding: 4px 10px; border-radius: 8px; color: #fff; }
.pf-photo-tag.pending { background: var(--accent); }
.pf-photo-tag.rejected { background: var(--danger); }
.pf-info { display: flex; flex-direction: column; padding-top: 2px; min-width: 0; }
.pf-info > .pf-section:first-of-type { margin-top: 26px; }
.pf-headrow { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
/* ---- Titres de « Mon profil » en géométrique (25/08) ----
   Prolonge la v933 (titre du hero) et la v1019 (titres d'article) : Poppins tient lieu d'ITC Avant
   Garde Gothic, sous licence commerciale. Demande de Gabriel : le nom et les titres de section.
   ⚠️ SEULES les graisses 500 et 600 sont chargées (voir le lien Google Fonts) : en demander une
   autre ferait graisser la police par le navigateur, avec le rendu épais et sale que cela donne.
   ⚠️ CORPS RÉDUIT en passant du serif à la géométrique — 2,5rem → 2,25rem. C'est la leçon des deux
   essais précédents : une géométrique est plus LARGE à corps égal, et « Marie-Bénédicte, 38 ans »
   passait sur deux lignes là où le serif tenait sur une.
   ⚠️ `--font-brand` (Cormorant) reste le serif PARTOUT AILLEURS — fiches des autres, back-office,
   e-mails. Ces deux règles ne servent qu'à cette page. */
.pf-name { font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
  font-weight: 600; letter-spacing: -.01em; font-size: clamp(1.8rem, 5.4vw, 2.25rem);
  line-height: 1.06; color: var(--foreground); margin: 0; }
.pf-loc { display: inline-flex; align-items: center; gap: 6px; color: var(--muted-foreground); margin: 10px 0 0; font-size: 1rem; }
.pf-loc svg { width: 16px; height: 16px; flex-shrink: 0; }
.pf-badges { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 0; }
.pf-badges .badge { font-size: .82rem; padding: 7px 14px; }
.pf-bio { font-size: 1.12rem; line-height: 1.6; color: var(--foreground); padding-left: 16px; border-left: 3px solid var(--accent); margin: 20px 0 0; }
.pf-edit { flex-shrink: 0; }

.pf-section { margin-top: 30px; }
/* ⚠️ 1,5rem → 1,32rem, même raison : « En quelques mots » et « Ma description » se lisent à corps
   plus petit en géométrique, et gardent l'équilibre avec le nom au-dessus. */
.pf-section-title { font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
  font-size: 1.32rem; font-weight: 600; letter-spacing: -.005em; color: var(--primary); margin: 0 0 14px; }
/* En-tête de section avec lien d'édition (ex. « Ma description » + ✎ Modifier). */
.pf-section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.pf-section-head .pf-section-title { margin: 0; }
.pf-section-edit { flex-shrink: 0; display: inline-flex; align-items: center; gap: 5px; font-size: .92rem; font-weight: 600; color: var(--accent); text-decoration: none; white-space: nowrap; }
.pf-section-edit:hover { text-decoration: underline; }
.pf-bio-insection { margin-top: 0; }
.pf-card { background: var(--card); border: 1px solid var(--hairline); border-radius: 18px; padding: 6px 24px; box-shadow: var(--shadow-sm); }
.pf-faith-row { display: grid; gap: 10px; padding: 16px 0; border-bottom: 1px solid var(--hairline); }
.pf-faith-row:last-child { border-bottom: none; }
.pf-faith-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); font-weight: 700; }
.pf-faith-tags { display: flex; flex-wrap: wrap; gap: 8px; }

.pf-prompts { display: grid; gap: 14px; }
.pf-prompt { background: var(--card); border: 1px solid var(--hairline); border-radius: 18px; padding: 20px 22px; box-shadow: var(--shadow-sm); }
.pf-prompt-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); font-weight: 700; margin: 0 0 6px; }
.pf-prompt-text { font-size: 1.1rem; line-height: 1.5; color: var(--foreground); margin: 0; }

.pf-photo-cta { margin: 12px 2px 0; font-size: .9rem; color: var(--danger); line-height: 1.45; }
.pf-photo-cta a { color: var(--primary); font-weight: 700; }
.pf-gallery { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.pf-gallery .gal-item { position: relative; aspect-ratio: 3/4; border-radius: 14px; overflow: hidden; background: var(--muted); }
.pf-gallery .gal-item img { width: 100%; height: 100%; object-fit: cover; }
.pf-del { position: absolute; top: 6px; right: 6px; margin: 0; }
.pf-del button { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: none; border-radius: 999px; background: rgba(16,32,39,.6); color: #fff; font-size: 1.15rem; line-height: 1; cursor: pointer; }
.pf-del button:hover { background: var(--danger); }
.pf-add-form { margin: 0; }
.pf-add-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; width: 100%; aspect-ratio: 3/4; border: 1.5px dashed var(--border); border-radius: 14px; cursor: pointer; color: var(--primary); font-weight: 600; font-size: .86rem; text-align: center; padding: 8px; background: var(--card); }
.pf-add-tile:hover { border-color: var(--primary); background: var(--muted); }
.pf-add-tile .plus { font-size: 1.8rem; line-height: 1; }
/* Même masquage accessible que .upload-btn : visible à l'identique, mais atteignable au clavier. */
.pf-add-tile { position: relative; }
.pf-add-tile input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; padding: 0; border: 0; }
.pf-add-tile:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Photo hero cliquable → popup « Mes photos » */
.pf-hero-clickable { border: 0; padding: 0; font: inherit; width: 100%; cursor: pointer; display: block; }
.pf-hero-edit { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; gap: 7px; padding: 16px 12px 12px; font-size: .85rem; font-weight: 600; color: #fff; background: linear-gradient(to top, rgba(16,32,39,.78), rgba(16,32,39,0)); }
/* Popup galerie + drag & drop */
.pf-photos-modal { max-width: 520px; width: 92vw; }
.pf-photos-modal h2 { margin: 0 0 4px; }
.pf-photos-modal .pf-gallery { margin-top: 14px; max-height: 62vh; overflow-y: auto; padding: 2px; }
.pf-gallery .gal-item { cursor: grab; }
/* La vignette saisie reste dans le flux : c'est elle qui matérialise LA PLACE où la photo
   retombera. On la vide donc au lieu de l'effacer à moitié — le contenu part dans le fantôme. */
.pf-gallery .gal-item.dragging { cursor: grabbing; }
/* .drag-over n'a jamais été posée par le code (le classement se fait en direct) : retirée. */
/* La poignée était décorative (pointer-events:none). Elle devient la prise du glissé TACTILE :
   touch-action:none pour que le doigt déplace la photo au lieu de faire défiler la page, et une
   cible d'au moins 34 px pour être attrapable au pouce. À la souris, toute la vignette reste prenable. */
.gal-drag { position: absolute; bottom: 6px; left: 6px; color: #fff; background: rgba(16,32,39,.5);
  border-radius: 7px; padding: 4px 10px; font-size: .82rem; line-height: 1.5; min-width: 34px; min-height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  pointer-events: auto; touch-action: none; cursor: grab; }
.gal-drag:active { cursor: grabbing; }

@media (min-width: 900px) {
  .pf-layout { grid-template-columns: 300px minmax(0, 1fr); gap: 40px; align-items: start; }
  .pf-media { position: sticky; top: 46px; }
  .pf-prompts { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
  .pf-gallery { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}

/* ---- Admin ---- */
.admin-shell { background: var(--muted); }
.admin-layout { display: flex; min-height: 100vh; }
.admin-side { width: 232px; flex-shrink: 0; background: var(--primary); color: #fff; display: flex; flex-direction: column; padding: 20px 14px; position: sticky; top: 0; height: 100vh; overflow-x: hidden; overflow-y: auto; }
.admin-brand { display: flex; align-items: center; gap: 10px; font-family: var(--font-brand); font-size: 1.2rem; padding: 0 8px 20px; white-space: nowrap; flex-shrink: 0; }
.admin-brand img { width: 42px; height: auto; }
.admin-side nav { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.side-link { display: flex; align-items: center; gap: 11px; padding: 11px 14px; border-radius: 10px; color: rgba(255,255,255,.82); text-decoration: none; font-weight: 600; font-size: .92rem; }
.side-link:hover { background: rgba(255,255,255,.1); color: #fff; }
.side-link.active { background: rgba(255,255,255,.16); color: #fff; }
.side-ic { width: 18px; height: 18px; flex-shrink: 0; opacity: .9; }
.side-label { flex: 1; min-width: 0; }
.side-badge { background: var(--accent); color: var(--primary); font-size: .72rem; font-weight: 700; min-width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 99px; padding: 0 5px; }
.side-logout { display: flex; align-items: center; gap: 11px; color: rgba(255,255,255,.7); text-decoration: none; padding: 12px 14px; font-size: .88rem; flex-shrink: 0; }
.side-logout svg { flex-shrink: 0; }
.side-logout:hover { color: #fff; }
.admin-main { flex: 1; min-width: 0; padding: 32px 40px; }
.admin-h1 { font-family: var(--font-round); font-weight: 800; letter-spacing: -.01em; color: var(--primary); font-size: 1.75rem; margin-bottom: 22px; }
/* Grille KPI qui se remplit pour les pages à 2-3 cartes (dashboard = 4 col fixe). */
.kpi-grid.auto { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
/* Barre d'actions au-dessus d'un tableau (export, filtres…). */
.admin-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0 0 14px; }
.admin-toolbar .dash-h2 { margin: 0; margin-right: auto; }
.admin-back { margin-bottom: 8px; }
.admin-back a { color: var(--muted-foreground); text-decoration: none; }
/* Fiche modération : titre + bouton « rendu final » à droite, et son pop-up */
.mod-titlerow { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.mod-titlerow .admin-h1 { margin-bottom: 22px; }
.mod-preview-btn { flex-shrink: 0; width: 42px; height: 42px; margin-bottom: 22px; display: inline-flex; align-items: center; justify-content: center; border-radius: 12px; border: 1px solid var(--border); background: var(--card); color: var(--primary); cursor: pointer; box-shadow: 0 1px 2px rgba(16,32,39,.06); }
.mod-preview-btn:hover { background: #F4F1EA; }
/* Dans une modale, un bouton d'action collé au dernier choix : on l'aère. */
.like-modal-inner .radio-cards { margin-bottom: 18px; }
/* Icône « Profil atypique » (en-tête de modération) : bouton neutre comme ses voisins tant que rien n'est
   renseigné, FOND PLEIN dès qu'un degré d'atypie est posé — repérable d'un coup d'œil dans la liste. */
.mod-preview-btn.is-on { background: var(--primary); border-color: var(--primary); color: #fff; }
.mod-preview-btn.is-on:hover { background: #16273a; }
/* Le fantôme a quitté l'en-tête en v1264 (il se pose depuis le menu de la ligne Statut) : ses trois
   règles — le <form> aligné dans la rangée, la couleur active grise, la taille de l'icône — sont
   parties avec lui. L'icône elle-même (plv_ghost_icon) sert toujours à la marque « invisible à
   tous », qui a ses propres dimensions dans `.prof-ghost svg`. */
/* Pop-up « Envoyer un e-mail » : l'aperçu et l'envoi côte à côte, l'envoi à droite. */
.envoi-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 4px; }
.envoi-actions .btn { margin: 0; }
.mod-preview-modal { position: fixed; inset: 0; z-index: 200; background: rgba(16,32,39,.55); display: flex; align-items: center; justify-content: center; padding: 20px; }
.mod-preview-inner { background: var(--card); border-radius: 20px; width: 100%; max-width: 420px; max-height: 90vh; overflow-y: auto; padding: 16px; position: relative; }
.mod-preview-close { position: absolute; top: 12px; right: 12px; z-index: 5; width: 34px; height: 34px; border-radius: 99px; border: 0; background: rgba(16,32,39,.5); color: #fff; font-size: 20px; line-height: 1; cursor: pointer; }
.mod-preview-label { font-size: .8rem; color: var(--muted-foreground); text-align: center; margin: 2px 0 12px; }
.admin-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; margin-bottom: 24px; }
.admin-metrics .metric-value a { text-decoration: none; }
.admin-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.admin-table th, .admin-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.admin-table th { color: var(--muted-foreground); font-weight: 600; }
.admin-table .ph-tag { position: static; display: inline-block; }
.admin-td-action { text-align: right; width: 1%; white-space: nowrap; }
.admin-td-action form { margin: 0; }
.icon-del { background: none; border: 0; cursor: pointer; color: var(--muted-foreground); padding: 6px; border-radius: 8px; line-height: 0; }
.icon-del:hover { color: var(--danger); background: rgba(176, 69, 59, .1); }
.icon-resend { background: none; border: 0; cursor: pointer; color: var(--muted-foreground); padding: 6px; border-radius: 8px; line-height: 0; }
.icon-resend:hover { color: var(--primary); background: rgba(34, 62, 99, .08); }
/* Menu déroulant « Envoyer un e-mail » (liste de relances). Le menu est déplacé sous <body> et positionné en fixed par JS. */
.acct-send { position: relative; display: inline-flex; }
.acct-send-menu { position: fixed; z-index: 1300; min-width: 210px; background: #fff; border: 1px solid var(--hairline); border-radius: 12px; box-shadow: 0 14px 34px rgba(16, 32, 43, .16); padding: 6px; display: grid; gap: 2px; }
.acct-send-menu[hidden] { display: none; }
.acct-send-menu form { margin: 0; }
.acct-send-item { display: block; width: 100%; text-align: left; background: transparent; border: 0; border-radius: 8px; padding: 9px 12px; font-size: .9rem; line-height: 1.3; color: var(--foreground); cursor: pointer; font-family: inherit; }
.acct-send-item:hover { background: var(--muted); }
/* Pop-up d'aperçu d'e-mail (voir le mail réel avant envoi) */
.mail-preview { position: fixed; inset: 0; z-index: 1400; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(16, 24, 32, .55); }
.mail-preview[hidden] { display: none !important; }
.mail-preview-box { background: #fff; border-radius: 16px; width: min(680px, 100%); max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 22px 60px rgba(0, 0, 0, .38); }
/* Le formulaire peut devenir long (statuts + message + objet + texte). Sans min-height:0 un élément flex
   refuse de descendre sous la hauteur de son contenu : la boîte dépassait alors 90vh et son overflow
   hidden mangeait le pied — les boutons Envoyer / Recevoir un test devenaient inatteignables.
   Ici l'en-tête DÉFILE, l'aperçu cède de la place, et le pied reste toujours visible. */
.mail-preview-head { display: flex; align-items: flex-start; gap: 12px; padding: 15px 18px; border-bottom: 1px solid var(--hairline); flex: 0 1 auto; min-height: 0; overflow-y: auto; }
.mail-preview-meta { flex: 1; min-width: 0; }
.mp-choices { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 11px; }
.mp-choice { font: inherit; font-size: .82rem; font-weight: 600; line-height: 1.2; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--hairline); background: #fff; color: var(--foreground); cursor: pointer; transition: background .15s, border-color .15s, color .15s; }
.mp-choice:hover { border-color: var(--primary); }
.mp-choice.is-active { background: var(--primary); border-color: var(--primary); color: #fff; }
.bulk-open { display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 15px; font: inherit; font-size: .9rem; font-weight: 600; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 12px; cursor: pointer; }
.bulk-open:hover { border-color: var(--primary); color: var(--primary); }
.bulk-open svg { flex: 0 0 auto; color: var(--primary); }
/* Statuts d'une campagne : menu déroulant pour ajouter + puces à croix pour retirer — exactement le
   composant du menu « Filtrer » (.filter-multi / .filter-chip / .filter-select), donc rien à restyler.
   Seul l'alignement change : le libellé « STATUTS » se cale en haut quand plusieurs puces s'empilent. */
/* Règle du fil, sous la fiche du jour : discrète mais lisible — c'est elle qui explique pourquoi aucun
   nouveau profil n'arrive tant qu'on n'a pas tranché. */
.today-rule { max-width: 34rem; margin: 14px auto 0; text-align: center; font-size: .86rem; line-height: 1.5; color: var(--muted-foreground); }
/* « oui », « passer », « non » dans la couleur de « Voir tout le profil » (--accent) : ce sont les
   trois gestes de la carte, ils se rattachent visuellement à elle plutôt qu'au texte courant. */
.today-rule strong { color: var(--accent); font-weight: 700; }
.bulk-segs { align-items: flex-start; }
/* Bannière de campagne en cours : progression + reprise automatique du lot suivant. */
.bulk-resume { margin: 0 0 18px; padding: 14px 16px; border: 1px solid var(--primary); border-radius: 14px; background: var(--card); box-shadow: var(--shadow-sm); }
.bulk-resume-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.bulk-resume-num { font-family: var(--font-round); font-weight: 800; color: var(--primary); font-variant-numeric: tabular-nums; }
.bulk-resume-bar { height: 8px; margin: 10px 0 12px; border-radius: 999px; background: var(--muted); overflow: hidden; }
.bulk-resume-bar span { display: block; height: 100%; border-radius: 999px; background: var(--primary); transition: width .3s ease; }
.bulk-resume-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: .88rem; }
.bulk-resume-actions .muted { margin-right: auto; }
.bulk-multi { min-width: 0; }
.bulk-select { display: flex; align-items: center; gap: 10px; margin: 4px 0 12px; }
.bulk-select select { flex: 1 1 auto; min-width: 0; font: inherit; font-size: .92rem; padding: 9px 11px; border-radius: 10px; border: 1px solid var(--hairline); background: #fff; color: var(--foreground); }
.mail-preview-meta .mp-title { font-size: 1.02rem; margin-bottom: 8px; white-space: normal; }
.mail-preview-meta .mp-seg, .mail-preview-meta .mp-seg .muted { white-space: normal; }
.bulk-custom { margin: 2px 0 10px; }
.bulk-field { display: block; margin: 0 0 9px; }
.bulk-field .mp-k { display: block; margin-bottom: 4px; }
.bulk-field input, .bulk-field textarea { width: 100%; box-sizing: border-box; font: inherit; font-size: .92rem; padding: 9px 11px; border-radius: 10px; border: 1px solid var(--hairline); background: #fff; color: var(--foreground); }
.bulk-field textarea { resize: vertical; min-height: 96px; line-height: 1.5; }
.mail-preview-meta .mp-line { margin: 0; font-size: .92rem; line-height: 1.5; color: var(--foreground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mail-preview-meta .mp-line + .mp-line { margin-top: 2px; }
.mail-preview-meta .mp-k { display: inline-block; min-width: 44px; color: var(--muted-foreground); font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.mail-preview .modal-close { position: static; flex: 0 0 auto; }
/* L'iframe doit REMPLIR sa zone : en hauteur indéterminée (élément flex), son height:100% retombait sur
   la hauteur par défaut de 150 px et laissait une bande de fond visible sous l'aperçu. En faisant du
   conteneur un flex, l'iframe s'étire d'elle-même. */
.mail-preview-body { flex: 1 1 auto; min-height: 260px; display: flex; background: #f4efe6; }
.mail-preview-body iframe { flex: 1 1 auto; width: 100%; height: auto; min-height: 0; border: 0; display: block; background: #f4efe6; }
/* Message : le menu et le bouton « Modifier » sur une même ligne. */
.bulk-msgrow { display: flex; align-items: center; gap: 8px; }
.bulk-msgrow select { flex: 1 1 auto; min-width: 0; }
.bulk-edit { flex: 0 0 auto; white-space: nowrap; }
.bulk-editnote { margin: 0 0 9px; font-size: .78rem; line-height: 1.4; color: var(--muted-foreground); }
/* Quand le message s'édite dans l'aperçu, l'aperçu doit respirer : il devient la zone de travail. */
.bulk-inline-hint { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 4px; font-size: .82rem; line-height: 1.4; color: var(--primary); }
.bulk-inline-hint span { flex: 1 1 200px; min-width: 0; }
.bulk-apply { flex: 0 0 auto; white-space: nowrap; }
/* Brouillon repris : discret, mais avec la date — pour ne jamais envoyer un vieux texte sans le savoir. */
.bulk-draft-note { margin: 0 0 6px; font-size: .78rem; line-height: 1.4; color: var(--muted-foreground); }
.bulk-draft-clear { background: none; border: 0; padding: 0; font: inherit; font-size: .78rem; color: var(--primary); text-decoration: underline; cursor: pointer; }
/* Résultat du test, affiché DANS la modale (elle ne se referme plus pour si peu). */
/* Le message occupe sa PROPRE ligne, au-dessus des boutons : coincé entre eux, il les comprimait
   jusqu'à faire tenir « Envoyer à 1 personne » sur trois lignes. */
.bulk-test-status { flex: 1 1 100%; order: -1; font-size: .78rem; line-height: 1.35; }
.bulk-test-status:empty { display: none; }
.bulk-test-status.is-ok { color: #2E7355; }
.bulk-test-status.is-ko { color: #A4433A; }
/* Le texte reste redimensionnable à la main, mais ne s'impose pas au chargement. */
.bulk-custom textarea { max-height: 34vh; }
.mail-preview-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 14px 18px; border-top: 1px solid var(--hairline); background: #fff; flex: 0 0 auto; }
.mail-preview-actions-right { display: flex; align-items: center; gap: 10px; }
.mail-preview-actions .btn { padding: 9px 18px; }
.mail-preview-actions .btn-test { font-size: .88rem; }
.mail-preview-actions .btn-test:disabled, .mail-preview-actions [data-bulk-send]:disabled { opacity: .5; cursor: not-allowed; }
.icon-hist { background: none; border: 0; cursor: pointer; color: var(--muted-foreground); padding: 6px; border-radius: 8px; line-height: 0; }
.icon-hist:hover { color: var(--primary); background: rgba(34, 62, 99, .08); }
.icon-rank { background: none; border: 0; cursor: pointer; color: var(--muted-foreground); padding: 6px; border-radius: 8px; line-height: 0; }
.icon-rank:hover { color: var(--primary); background: rgba(34, 62, 99, .08); }
/* Popup « Classement de compatibilité » : profils dans l'ordre de proposition. */
/* Popup « Classement » : fiche du membre à GAUCHE, classement à DROITE. */
.rank-modal-inner { max-width: 820px; max-height: 88vh; overflow-y: auto; }
/* Colonne de gauche FLUIDE et pistes autorisées à rétrécir (minmax(0,…)) : à 290px fixes, dès que le
   popup se rétrécit (il passe à left:232px au-delà de 900px), la colonne de droite tombait sous 120px
   et les pastilles sortaient de la carte. Passer en une seule colonne réglait le débordement mais
   reléguait le classement sous la fiche, hors écran — c'est pourtant lui qu'on vient lire. */
.rank-split { display: grid; grid-template-columns: clamp(190px, 34%, 290px) minmax(0, 1fr); gap: 22px; align-items: start; margin-top: 6px; }
.rank-profile { min-width: 0; }
.rank-profile .profile-card { margin: 0; box-shadow: none; max-width: 100%; }
.rank-right { min-width: 0; }
.rank-list { margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.rank-item { display: grid; grid-template-columns: 26px 40px 1fr auto; gap: 11px; align-items: center; padding: 9px 12px; border: 1px solid var(--border); border-radius: 12px; text-decoration: none; color: var(--foreground); background: var(--card); }
.rank-item:hover { border-color: var(--primary); }
/* Pastille de rang colorée par pertinence (vert/orange/rouge). */
.rank-num { width: 24px; height: 24px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; justify-self: center; color: #fff; font-family: var(--font-round); font-weight: 800; font-size: .76rem; }
.rank-av { width: 40px; height: 40px; border-radius: 10px; background: var(--muted); background-size: cover; background-position: center; }
.rank-av-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
.rank-pct { font-family: var(--font-round); font-weight: 800; color: var(--primary); font-size: 1rem; text-align: right; white-space: nowrap; }
.rank-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* Prénom + pastilles sur une seule ligne : dans .rank-info (flex colonne) une pastille posée en frère
   du <strong> s'étirerait sur toute la largeur et se lirait comme une barre, plus comme une étiquette. */
/* min-width:0 sur la ligne NE SUFFIT PAS : ses enfants gardent min-width:auto, donc leur largeur
   min-content reste le plancher. Un prénom long et insécable débordait alors sur la colonne « % ». */
.rank-name-line { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; min-width: 0; }
.rank-name-line > * { min-width: 0; }
.rank-name-line strong { overflow-wrap: anywhere; }
.rank-info strong { font-weight: 700; }
/* Pictogramme « a déjà des enfants » derrière le prénom, dans le classement de compatibilité.
   ⚠️ PAS DE BOUTON ICI, contrairement à la fiche, et la raison est MESURÉE : la bulle de la
   fiche (.card-kid-mot, absolute, bottom:100%+8px) sort par le haut de son bouton, or ce
   panneau défile (.rank-modal-inner{overflow-y:auto} → overflow-x calcule à auto, il rogne donc
   des deux côtés). Reproduit au navigateur : sur la PREMIÈRE ligne, la bulle se pose 13 px
   au-dessus du bord du panneau, invisible. C'est donc un <span role="img"> avec title +
   aria-label ; la phrase complète se lit sur la fiche, où la ligne mène de toute façon.
   ⚠️ `flex: 0 0 auto` : .rank-name-line est un flex qui enveloppe, et sans cela le dessin se
   laissait écraser à quelques pixels de large quand le prénom était long. */
.rank-kid { display: inline-flex; align-items: center; flex: 0 0 auto; margin-left: 6px;
  color: var(--muted-foreground); }
.rank-kid img { width: 16px; height: 16px; display: block; }
.rank-kid-neutre svg { width: 15px; height: 15px; }
.rank-loc, .rank-why { font-size: .82rem; line-height: 1.32; }
.rank-why { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.rank-rep { font-size: .7rem; color: var(--accent); font-weight: 700; }
/* « Sous le seuil » : listé dans le classement, mais que le fil ne proposera jamais. */
.rank-under { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: .66rem; font-weight: 700; background: #fdecec; color: #a4343a; max-width: 100%; }
.rank-rescued { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: .66rem; font-weight: 700; background: #e6f3ec; color: #2E8F6B; max-width: 100%; }
/* Pastilles de séquence : profil du jour (en cours) / profil passé (J-X). */
.rank-badge { display: inline-block; margin-left: 7px; padding: 1px 8px; border-radius: 999px; font-size: .67rem; font-weight: 700; letter-spacing: .01em; background: var(--muted); color: var(--muted-foreground); vertical-align: middle; white-space: nowrap; }
.rank-badge-today { background: rgba(176, 138, 79, .16); color: #8a6d3b; }
.rank-dot { display: block; width: 13px; height: 13px; border-radius: 999px; justify-self: center; }
/* Codes couleur de pertinence, appliqués à la pastille-numéro (à venir/jour) ou au point (jour/passé). */
.rank-rel-green { background: #3F6B4E; }
.rank-rel-orange { background: #C6852B; }
.rank-rel-red { background: #C0392B; }
/* Lignes « à venir » réordonnables (glisser-déposer) : une colonne de poignée en plus. */
.rank-item[data-cid] { grid-template-columns: 16px 26px 40px 1fr auto; }
.rank-grip { justify-self: center; cursor: grab; color: #b3bcc6; font-size: 1rem; line-height: 1; user-select: none; }
.rank-grip:active { cursor: grabbing; }
.rank-grip-off { cursor: default; }
.rank-item.rank-dragging { opacity: .5; outline: 2px dashed var(--primary); outline-offset: -2px; }
.rank-sort-hint { font-size: .8rem; margin: 6px 0 8px; }
.rank-num-btn { cursor: pointer; transition: box-shadow .12s, transform .06s; }
.rank-num-btn:hover { box-shadow: 0 0 0 3px rgba(16, 32, 39, .16); }
.rank-num-btn:active { transform: scale(.93); }
/* Point coloré cliquable (jour / déjà proposé) : le disque reste à 13 px, mais le padding + background-clip
   lui donnent une zone de clic de 25 px — sinon la cible est trop fine et le clic part sur le lien de la ligne. */
.rank-dot-btn { box-sizing: content-box; padding: 6px; background-clip: content-box; cursor: pointer; transition: box-shadow .12s, transform .06s; }
.rank-dot-btn:hover { box-shadow: 0 0 0 2px rgba(16, 32, 39, .16); }
.rank-dot-btn:active { transform: scale(.93); }
/* Contrôleur de match d'une paire (ouvert depuis une pastille du classement). Il réutilise la mise en page
   du contrôleur de /admin/algorithme (.rv-modal / .rv-card / .ctrl-*) : seul le lien « effacer » est propre
   à cette vue, le contrôleur global enchaînant une file au lieu de juger une paire isolée. */
.rank-pair-clear { background: none; border: 0; padding: 2px 4px; font: inherit; font-size: .78rem; color: var(--muted-foreground); text-decoration: underline; cursor: pointer; }
.rank-pair-clear:hover { color: var(--foreground); }
/* Page « Contrôleur » : les 3 files à juger (n°1 / repêchages / autres). Les boutons reprennent la carte
   KPI du back-office (.kpi-card) — même liseré coloré, même pastille d'icône — pour rester dans le
   vocabulaire visuel du tableau de bord. Compteur = restants, total en gris à côté. */
.ctrl-cats { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin: 18px 0 4px; }
.ctrl-cat-btn { font: inherit; text-align: left; cursor: pointer; padding-right: 76px; } /* place réservée à l'icône */
.ctrl-cat-word { font-size: .9rem; font-weight: 600; color: var(--muted-foreground); margin: 0 5px 0 6px; }
.ctrl-cat-tot { font-size: 1.15rem; font-weight: 700; color: var(--muted-foreground); margin-left: 1px; }
.ctrl-cat-lbl { display: block; margin-top: 7px; font-weight: 700; font-size: .95rem; color: var(--foreground); }
.ctrl-cat-desc { display: block; margin-top: 4px; font-size: .78rem; line-height: 1.35; color: var(--muted-foreground); }
/* File vide : la carte reste lisible mais s'efface et ne réagit plus. */
.ctrl-cat-btn.is-done { opacity: .58; cursor: default; }
.ctrl-cat-btn.is-done:hover { transform: none; box-shadow: var(--shadow-sm); }
/* La chasse des emoji avale l'espace qui suit : sans ce petit écart, « 👍 pertinent » se lit collé. */
.ctrl-emo { margin-right: .18em; }
/* En-tête de la page Contrôleur : titre à gauche, fraîcheur du calcul + « Recalculer » à droite. */
/* Le h1 perd sa marge basse pour s'aligner avec le bouton : elle est reportée sur le conteneur,
   sinon la page se retrouve plus serrée que le reste du back-office. */
.admin-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 22px; }
.admin-head .admin-h1 { margin-bottom: 0; }
.ctrl-rebuild { display: flex; align-items: center; gap: 10px; }
.ctrl-built { font-size: .8rem; color: var(--muted-foreground); }
@media (max-width: 600px) { .admin-head { align-items: flex-start; flex-direction: column; gap: 10px; } }
.rank-item.rank-today { border-color: rgba(176, 138, 79, .5); background: rgba(176, 138, 79, .06); }
.rank-item.rank-past { opacity: .68; }

/* Lien discret sous le formulaire du hero : la version pré-lancement n'avait pas de bouton « Comment ça
   marche » (l'accueil ouvert, si) — ce lien conserve l'accès à la section sans casser la ligne du hero. */
.hero-note-link { color: inherit; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
.hero-note-link:hover { opacity: .78; }

/* --- Popup Classement : trois encarts (Déblocable / Débloqué aujourd’hui / Déjà proposés) ---------
   Chaque encart est une boîte autonome avec son titre et son compteur : sans cette séparation, la
   file à venir (réordonnable) et l’historique se lisaient comme une seule liste, et on ne savait plus
   ce qui était encore déplaçable. Le liseré gauche coloré rappelle la nature de chaque bloc. */
.rank-sec { margin-top: 16px; padding: 13px 14px 14px; border: 1px solid var(--border); border-left: 3px solid var(--border); border-radius: 13px; background: var(--card); }
.rank-sec:first-of-type { margin-top: 10px; }
.rank-sec-head { display: flex; align-items: center; gap: 9px; }
.rank-sec-title { margin: 0; font-family: var(--font-round); font-size: .95rem; font-weight: 800; letter-spacing: .01em; color: var(--foreground); }
.rank-sec-count { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 21px; padding: 0 7px; border-radius: 999px; background: var(--secondary); color: var(--muted-foreground); font-family: var(--font-round); font-weight: 800; font-size: .74rem; }
.rank-sec-sub { margin: 6px 0 0; font-size: .79rem; line-height: 1.42; color: var(--muted-foreground); }
.rank-sec .rank-list { margin-top: 10px; }
/* Déblocable = ce qui va partir : liseré bleu, compteur affirmé. Débloqué aujourd’hui = l’or du
   « profil du jour » déjà utilisé ailleurs dans le popup. Historique = gris, volontairement en retrait. */
.rank-sec-next { border-left-color: var(--primary); }
.rank-sec-next .rank-sec-count { background: rgba(34, 62, 99, .12); color: var(--primary); }
.rank-sec-today { border-left-color: var(--accent); background: rgba(176, 138, 79, .045); }
.rank-sec-today .rank-sec-count { background: rgba(176, 138, 79, .18); color: #8a6d3b; }
.rank-sec-past { border-left-color: #C9CDD4; background: #FBFBFA; }
/* Dans l’historique la ligne est déjà en retrait par son encart : inutile de la pâlir une 2e fois. */
.rank-sec-past .rank-item.rank-past { opacity: 1; }
.rank-empty { margin: 9px 0 1px; font-size: .82rem; line-height: 1.45; color: var(--muted-foreground); }
.rank-order-err { margin: 8px 0 6px; padding: 8px 11px; border-radius: 10px; background: #FBEDEB; color: #A4433A; font-size: .8rem; line-height: 1.4; }
/* Issue de la proposition : Oui / Passer / Non / Sans réponse / En attente. */
/* Pas de nowrap sur les deux libellés longs (« En attente de réponse », « non proposé · sous le seuil
   de 30 % ») : une pastille insécable plus large que sa colonne sort de la carte au lieu de se plier. */
.rank-out { display: inline-block; margin-left: 7px; padding: 1px 8px; border-radius: 999px; font-size: .67rem; font-weight: 700; letter-spacing: .01em; vertical-align: middle; max-width: 100%; }
.rank-out-yes { background: #E6F3EC; color: #2E7355; }
.rank-out-skip { background: #F1F2F4; color: #6B7280; }
.rank-out-no { background: #FBEDEB; color: #A4433A; }
/* « bonus possible » : cette personne s'est déclarée depuis le refus, elle peut être rappelée. La
   couleur du bonus (l'accent doré) et non celle d'une issue — ce n'est pas ce qu'il a répondu. */
.rank-out-bonus { background: rgba(176, 138, 79, .16); color: #8C6722; }
/* « oui avant le refus » : elle s'est déclarée, mais il a tranché APRÈS, en le sachant. Ni une issue
   ni une possibilité — une explication. Gris, donc, et non la couleur du bonus. */
.rank-out-avant { background: rgba(34, 62, 99, .07); color: #5D6673; }
.rank-out-wait { background: #FBF0DC; color: #96692A; }
.rank-out-none { background: #F1F2F4; color: #8A8F98; }
/* Date de proposition / heure de déblocage, sous la ligne. */
.rank-when { font-size: .76rem; color: var(--muted-foreground); }
.rank-when-d { border-bottom: 1px dotted rgba(107, 114, 128, .45); }
.rank-again { display: block; font-size: .73rem; color: var(--accent); font-weight: 700; }
.rank-src { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: .64rem; font-weight: 700; background: rgba(34, 62, 99, .08); color: var(--primary); white-space: nowrap; }
/* Origine d'une fiche : « pack payant », « bonus », « rappel » — un seul aspect, celui de
   .rank-src, et le MOT porte la distinction. Deux raisons de ne pas les colorer : le doré de
   --accent tombait à 2,8:1 de contraste sur 0,64 rem (illisible), et surtout une pastille dorée
   « bonus » aurait été le sosie de « bonus possible » (.rank-out-bonus) qui, elle, dit l'inverse —
   non pas d'où vient cette fiche, mais qu'une AUTRE pourrait être offerte. Rien n'est peint pour le
   fil du jour : c'est le cas ordinaire, et l'absence de pastille est déjà l'information. */
@media (max-width: 700px) { .rank-split { grid-template-columns: 1fr; gap: 16px; } }
.icon-edit { display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; cursor: pointer; color: var(--muted-foreground); padding: 6px; border-radius: 8px; line-height: 0; }
.icon-edit:hover { color: var(--primary); background: rgba(34, 62, 99, .08); }
.acct-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
/* Historique d'un compte (modale AJAX) : timeline des mouvements */
.history-modal-inner { max-width: 520px; max-height: 88vh; overflow-y: auto; }
/* HISTORIQUE DU COMPTE — une frise, pas un tableau (refonte du 01/09).
   Chaque événement porte l'icône de sa famille (plv_admin_history_famille) : d'un coup d'œil on
   distingue une modération d'un achat ou d'un match, sans lire une seule ligne. */
.hist-list { list-style: none; margin: 12px 0 0; padding: 0; position: relative; }
/* Le fil qui relie les pastilles : c'est lui qui fait lire la colonne comme une chronologie.
   ⚠️ Il passe DERRIÈRE les pastilles, que leur halo de la couleur du fond vient détourer. */
.hist-list::before { content: ''; position: absolute; left: 15px; top: 10px; bottom: 10px;
  width: 2px; background: var(--hairline); border-radius: 2px; }
.hist-item { position: relative; display: grid; grid-template-columns: 32px 92px 1fr;
  align-items: start; gap: 12px; padding: 8px 0; text-align: left; }
.hist-ico { position: relative; z-index: 1; width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: #EEF1F6; color: #4A5A73; box-shadow: 0 0 0 3px var(--card); }
/* ⚠️ Le JOUR ne s'écrit qu'une fois par journée (côté PHP) : sur les lignes suivantes, seule
   l'heure reste, et c'est bien elle qu'on vient lire. */
.hist-when { display: flex; flex-direction: column; gap: 1px; padding-top: 6px;
  font-variant-numeric: tabular-nums; }
.hist-when b { font-size: .78rem; font-weight: 700; color: var(--foreground); }
.hist-when i { font-style: normal; font-size: .78rem; color: var(--muted-foreground); }
.hist-body { display: flex; flex-direction: column; gap: 2px; padding-top: 5px; min-width: 0; }
.hist-body strong { font-size: .94rem; line-height: 1.3; }
.hist-detail { font-size: .85rem; color: var(--muted-foreground); line-height: 1.4; }

/* Les familles. Teintes sourdes : la couleur doit trier le regard, pas décorer la page. */
.hist-f-compte .hist-ico, .hist-f-attente .hist-ico { background: #EEF1F6; color: #4A5A73; }
.hist-f-suppression .hist-ico  { background: #FBEAE8; color: #B0453B; }
.hist-f-restauration .hist-ico { background: #E7F4EC; color: #2C7A4B; }
.hist-f-moderation .hist-ico   { background: #E9EEF9; color: #223E63; }
.hist-f-photo .hist-ico        { background: #F1EAF8; color: #6B46A8; }
.hist-f-connexion .hist-ico    { background: #F0F2F5; color: #6B7280; }
.hist-f-quotidien .hist-ico    { background: #FDF2DC; color: #9A6B12; }
.hist-f-match .hist-ico        { background: #FCE9EF; color: #B93B63; }
.hist-f-blocage .hist-ico      { background: #F6E7E4; color: #9B4A34; }
.hist-f-signalement .hist-ico  { background: #FDEDE0; color: #A65A16; }
.hist-f-achat .hist-ico        { background: #E4F3F1; color: #1F6F68; }
.hist-f-pause .hist-ico        { background: #EDEFF2; color: #5A6570; }
.hist-f-notification .hist-ico { background: #E9EAF9; color: #46499B; }
.hist-f-concours .hist-ico     { background: #FBF0D4; color: #8A6A10; }
.hist-f-email .hist-ico        { background: #E6F0FA; color: #2A5E8F; }

/* Le compte des gestes, en pastilles : la phrase unique devenait illisible dès le cinquième chiffre. */
.hist-stats { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.hist-stat { display: inline-flex; align-items: baseline; gap: 5px; padding: 5px 11px;
  border-radius: 999px; background: #EDF1FB; color: #223E63; font-size: .82rem; }
.hist-stat b { font-size: .95rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.hist-email-line { display: flex; align-items: center; gap: 8px; }
.hist-info-link { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--primary); padding: 4px; margin: -4px 0; border-radius: 7px; line-height: 0; }
.hist-info-link:hover { background: rgba(34, 62, 99, .1); }
/* Sur téléphone la colonne de date ne tient pas : elle passe au-dessus du libellé, en une ligne,
   et la pastille garde sa colonne pour que le fil reste lisible. */
@media (max-width: 560px) {
  .hist-item { grid-template-columns: 28px 1fr; grid-template-areas: "ico when" "ico body"; gap: 3px 10px; }
  .hist-ico { grid-area: ico; width: 28px; height: 28px; }
  .hist-when { grid-area: when; flex-direction: row; gap: 6px; padding-top: 4px; }
  .hist-body { grid-area: body; padding-top: 0; }
  .hist-list::before { left: 13px; }
}
/* Entête Comptes + bouton corbeille (restauration des suppressions) */
.accounts-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; } /* wrap : sur écran étroit / fold déplié, les actions passent sous le titre au lieu de déborder */
.accounts-trash-btn { position: relative; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border: 1px solid var(--hairline); background: var(--card); color: var(--muted-foreground); border-radius: 12px; cursor: pointer; transition: background .15s, color .15s; }
.accounts-trash-btn:hover { color: var(--primary); background: var(--muted); }
.accounts-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; row-gap: 10px; }
.accounts-filter { position: relative; display: inline-block; }
.accounts-filter::after { content: ''; position: absolute; right: 13px; top: calc(50% - 4px); width: 7px; height: 7px; border-right: 2px solid var(--muted-foreground); border-bottom: 2px solid var(--muted-foreground); transform: rotate(45deg); pointer-events: none; }
.accounts-filter select { -webkit-appearance: none; appearance: none; height: 40px; padding: 0 34px 0 13px; font: inherit; font-size: .9rem; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 12px; cursor: pointer; }
.accounts-filter select:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
/* Menu « Filtrer » multi-sections (remplace le select de statut) */
.accounts-filter2 { position: relative; display: inline-block; }
.accounts-filter2-btn { display: inline-flex; align-items: center; gap: 7px; height: 40px; padding: 0 14px; font: inherit; font-size: .9rem; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 12px; cursor: pointer; }
.accounts-filter2-btn:hover { background: var(--muted); }
.accounts-filter2-btn.is-active { border-color: var(--primary); color: var(--primary); }
.accounts-filter2-btn svg { opacity: .8; }
.filter-count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; font-size: .72rem; font-weight: 700; color: #fff; background: var(--primary); border-radius: 999px; }
.filter-panel { position: absolute; top: calc(100% + 8px); left: 0; z-index: 60; width: 300px; max-width: calc(100vw - 40px); max-height: min(70vh, 560px); overflow-y: auto; padding: 4px 6px; background: var(--card); border: 1px solid var(--hairline); border-radius: 14px; box-shadow: 0 12px 34px rgba(16, 24, 40, .16); }
.filter-section { padding: 9px 8px 11px; border-bottom: 1px solid var(--hairline); }
.filter-section:last-of-type { border-bottom: 0; }
.filter-section-title { margin: 0 0 7px; font-size: .7rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted-foreground); }
.filter-opts { display: flex; flex-wrap: wrap; gap: 6px; }
.filter-opt { display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px; font-size: .85rem; border: 1px solid var(--hairline); border-radius: 999px; cursor: pointer; user-select: none; }
.filter-opt input { margin: 0; accent-color: var(--primary); }
.filter-opt:has(input:checked) { border-color: var(--primary); background: var(--muted); color: var(--primary); font-weight: 600; }
.filter-range { display: flex; align-items: flex-end; gap: 8px; }
.filter-range-field { display: flex; flex-direction: column; gap: 3px; font-size: .78rem; color: var(--muted-foreground); }
.filter-range-field input { width: 72px; padding: 7px 9px; font: inherit; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 9px; }
.filter-range-sep { padding-bottom: 8px; color: var(--muted-foreground); }
.filter-select { width: 100%; padding: 8px 10px; font: inherit; font-size: .85rem; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 9px; }
.filter-multi { display: flex; flex-direction: column; gap: 7px; }
.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.filter-chips:empty { display: none; }
.filter-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 5px 4px 11px; font-size: .84rem; font-weight: 600; color: var(--primary); background: var(--muted); border: 1px solid var(--primary); border-radius: 999px; }
.filter-chip button { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; padding: 0; font-size: 15px; line-height: 1; color: var(--primary); background: rgba(0, 0, 0, .07); border: 0; border-radius: 999px; cursor: pointer; }
.filter-chip button:hover { background: rgba(0, 0, 0, .16); }
.filter-actions { position: sticky; bottom: 0; display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 2px; padding: 10px 8px 8px; background: var(--card); border-top: 1px solid var(--hairline); }
.accounts-search { position: relative; display: inline-flex; align-items: center; }
.accounts-search svg { position: absolute; left: 11px; color: var(--muted-foreground); pointer-events: none; }
.accounts-search input { height: 40px; width: 210px; max-width: 46vw; padding: 0 12px 0 34px; font: inherit; font-size: .9rem; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 12px; }
.accounts-search input:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.accounts-search-form { display: inline-flex; align-items: center; gap: 10px; }
.accounts-date { height: 40px; padding: 0 11px; font: inherit; font-size: .9rem; color: var(--foreground); background: var(--card); border: 1px solid var(--hairline); border-radius: 12px; cursor: pointer; }
.accounts-date:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.accounts-more { display: flex; justify-content: center; padding: 18px 6px 4px; }
.accounts-more .btn:disabled { opacity: .6; cursor: default; }
/* Contrôleur de matchs (page Algorithme) */
.ctrl-list { display: flex; flex-direction: column; gap: 8px; }
.ctrl-match { display: flex; flex-direction: column; gap: 8px; padding: 9px 12px; border: 1px solid var(--hairline); border-radius: 12px; }
.ctrl-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 10px; }
.ctrl-count { text-align: center; font-size: .95rem; color: var(--foreground); margin: 0 0 4px; }
.ctrl-stats { text-align: center; font-size: .9rem; color: var(--muted-foreground); margin: 0 0 14px; }
.ctrl-rate { display: flex; justify-content: center; gap: 8px; }
.ctrl-thumb { border: 1px solid var(--hairline); background: var(--card); border-radius: 999px; padding: 2px 15px; font-size: 1rem; line-height: 1.5; cursor: pointer; opacity: .5; filter: grayscale(1); }
.ctrl-thumb:hover, .ctrl-thumb.on { opacity: 1; filter: none; }
.ctrl-thumb.up.on { background: #E6F3EC; border-color: #b6ddc4; }
.ctrl-thumb.down.on { background: #FBEDEB; border-color: #f0c3bd; }
.ctrl-thumb.meh.on { background: #F1EFE9; border-color: #d9d3c5; }
.ctrl-person { display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--foreground); min-width: 0; }
.ctrl-person.right { flex-direction: row-reverse; text-align: right; }
.ctrl-av { width: 40px; height: 40px; border-radius: 10px; background: var(--muted); background-size: cover; background-position: center; flex-shrink: 0; overflow: hidden; }
/* La vignette est une <img loading="lazy"> (voir plv_ctrl_person_html) : le cadrage repasse donc par
   object-fit, l'ancien background-size ne s'appliquant plus qu'au repli sans photo. */
.ctrl-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ctrl-av-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
.ctrl-txt { display: flex; flex-direction: column; min-width: 0; }
.ctrl-name { font-weight: 700; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ctrl-loc { font-size: .8rem; color: var(--muted-foreground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ctrl-person:hover .ctrl-name { text-decoration: underline; }
.ctrl-pct { flex-shrink: 0; font-weight: 800; color: var(--primary); background: var(--rose-soft); padding: 4px 11px; border-radius: 999px; font-size: .88rem; white-space: nowrap; }
.ctrl-center { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.ctrl-rep { font-size: .72rem; font-weight: 700; color: #8a5a12; background: #FBF0DA; border: 1px solid #ecd6a8; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.ctrl-match.is-rep { border-style: dashed; border-color: #e6cfa0; background: #fefbf4; }
.ctrl-rep-inline { font-weight: 700; color: #8a5a12; background: #FBF0DA; padding: 1px 6px; border-radius: 6px; white-space: nowrap; }
@media (max-width: 560px) { .ctrl-loc { display: none; } }
/* --- Statistiques --- */
.stat-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.stat-head .admin-h1 { margin: 0; }
/* Sélecteur de période : un seul contrôle (bouton + calendrier de plage) */
.stat-range { position: relative; display: inline-block; }
.stat-range-btn { display: inline-flex; align-items: center; gap: 8px; background: var(--muted); border: 1px solid var(--hairline); border-radius: 10px; padding: 8px 13px; font-family: inherit; font-size: .84rem; font-weight: 700; color: var(--primary); cursor: pointer; }
.stat-range-btn:hover { background: var(--card); border-color: var(--primary); }
.stat-range-caret { font-size: .66rem; color: var(--muted-foreground); }
.rp { position: absolute; right: 0; top: calc(100% + 6px); z-index: 60; background: var(--card); border: 1px solid var(--hairline); border-radius: 14px; box-shadow: 0 14px 36px rgba(16,42,67,.2); padding: 12px; width: 272px; }
.rp[hidden] { display: none !important; }
.rp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.rp-month { font-weight: 700; font-size: .86rem; color: var(--primary); text-transform: capitalize; }
.rp-nav { border: 0; background: none; font-size: 1.25rem; line-height: 1; cursor: pointer; color: var(--muted-foreground); padding: 0 9px; border-radius: 6px; }
.rp-nav:hover { background: var(--muted); color: var(--primary); }
.rp-dow, .rp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.rp-dow span { text-align: center; font-size: .67rem; font-weight: 700; color: var(--muted-foreground); padding: 3px 0; }
.rp-day { border: 0; background: none; font-family: inherit; font-size: .78rem; padding: 6px 0; border-radius: 7px; cursor: pointer; color: var(--foreground); }
.rp-day:hover:not(:disabled) { background: var(--muted); }
.rp-day:disabled, .rp-day.rp-off { color: #c9ced4; cursor: default; }
.rp-day.rp-in { background: var(--rose-soft); border-radius: 0; }
.rp-day.rp-start, .rp-day.rp-end { background: var(--primary); color: #fff; font-weight: 700; }
.rp-hint { font-size: .72rem; color: var(--muted-foreground); text-align: center; margin: 9px 0 0; }
.stat-list { display: flex; flex-direction: column; gap: 13px; }
.stat-row + .stat-row { margin-top: 11px; }
.stat-row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 5px; }
.stat-row-lbl { font-weight: 600; font-size: .9rem; color: var(--foreground); display: inline-flex; align-items: center; gap: 7px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat-row-val { font-weight: 800; font-size: .92rem; color: var(--foreground); white-space: nowrap; flex-shrink: 0; }
.stat-row-extra { font-weight: 500; font-size: .78rem; color: var(--muted-foreground); }
.stat-track { height: 8px; background: var(--muted); border-radius: 999px; overflow: hidden; }
.stat-fill { height: 100%; border-radius: 999px; min-width: 3px; transition: width .3s ease; }
.src-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
/* Écart uniforme au-dessus de chaque bloc : neutralise .dash-h2:first-of-type (qui vaut par parent,
   et donnait donc 4px au 1er titre de la page comme au 1er titre de chaque colonne). */
.stats-page .dash-h2:first-of-type { margin-top: 26px; }
/* Deux colonnes continues : les blocs s'empilent dans leur colonne sans se caler sur la hauteur du voisin. */
.stat-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; align-items: start; }
.stat-cols > div, .stat-col { min-width: 0; }
@media (max-width: 599px) { .stat-cols { grid-template-columns: 1fr; } } /* fold déplié = desktop (2 colonnes) */
/* Table « par pays » : libellé du pays à gauche, effectifs alignés à droite en chiffres tabulaires. */
.stat-country-table td:first-child { font-weight: 600; }
.stat-country-table th.stat-num, .stat-country-table td.stat-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Revue des matchs : pop-up plein écran, une fiche de chaque côté, % + boutons au centre */
.rv-modal { position: fixed; inset: 0; z-index: 1000; background: rgba(16,32,43,.55); display: flex; align-items: center; justify-content: center; padding: 18px; }
.rv-modal[hidden] { display: none !important; }
.rv-inner { background: var(--card); border-radius: 18px; width: min(1180px, 100%); max-height: 92vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 60px rgba(16,32,43,.32); }
.rv-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 16px; border-bottom: 1px solid var(--hairline); flex-shrink: 0; }
.rv-pos { font-weight: 800; color: var(--primary); font-size: .9rem; }
.rv-close { background: none; border: 0; font-size: 1.6rem; line-height: 1; cursor: pointer; color: var(--muted-foreground); padding: 0 4px; }
.rv-close:hover { color: var(--foreground); }
.rv-body { display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px; padding: 14px; overflow: hidden; align-items: start; }
.rv-body[hidden] { display: none !important; }
.rv-card { overflow-y: auto; max-height: calc(92vh - 110px); min-width: 0; }
/* Contrôleur / comparaison de matchs : photo raccourcie (vs 400–560 px plein cadre) pour laisser voir,
   sans scroller, les éléments clés de la fiche. En DESKTOP (fenêtre large), hauteur généreuse ; en zone
   fold/téléphone (≤900), version compacte — les 2 fiches côte à côte laissent peu de hauteur. */
.rv-card .card-slide, .rv-card .card-photo-empty { height: clamp(320px, 44vh, 460px); }
@media (max-width: 900px) {
  .rv-card .card-slide, .rv-card .card-photo-empty { height: clamp(200px, 30vh, 290px); }
}
.rv-center { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 10px 4px; align-self: center; }
.rv-rate { flex-wrap: wrap; justify-content: center; }
.rv-hint { font-size: .74rem; color: var(--muted-foreground); text-align: center; max-width: 150px; margin: 2px 0 0; line-height: 1.4; }
.rv-err { font-size: .76rem; color: #b71c1c; font-weight: 600; text-align: center; max-width: 170px; margin: 6px 0 0; line-height: 1.35; }
.rv-done { padding: 56px 20px; text-align: center; }
.rv-done[hidden] { display: none !important; }
.rv-done-txt { font-size: 1.15rem; font-weight: 800; color: #2E8F6B; margin: 0 0 8px; }
/* Historique dépliable des matchs contrôlés */
.ctrl-hist { margin-top: 18px; border-top: 1px solid var(--hairline); padding-top: 12px; }
.ctrl-hist > summary { cursor: pointer; font-weight: 700; color: var(--primary); font-size: .95rem; padding: 6px 0; list-style: none; }
.ctrl-hist > summary::-webkit-details-marker { display: none; }
.ctrl-hist > summary::before { content: "▸ "; color: var(--muted-foreground); }
.ctrl-hist[open] > summary::before { content: "▾ "; }
.ctrl-hist .ctrl-list { margin-top: 12px; }
/* Contrôleur de matchs — fold déplié (600–900) : les deux profils CÔTE À CÔTE (gauche/droite) avec la barre
   de vote 👍🤨👎 EN DESSOUS sur toute la largeur, au lieu de l'empilement vertical (qui obligeait à scroller
   d'un profil à l'autre). Chaque fiche défile en interne ; les boutons restent visibles sous les deux. */
@media (min-width: 600px) and (max-width: 900px) {
  .rv-body {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "a b" "center center";
    gap: 12px 14px;
  }
  .rv-body > [data-rv-a] { grid-area: a; }
  .rv-body > [data-rv-b] { grid-area: b; }
  .rv-body > .rv-center { grid-area: center; align-self: start; padding-top: 12px; border-top: 1px solid var(--hairline); }
  .rv-card { max-height: 54vh; }
  .rv-hint, .rv-err { max-width: none; }
}
/* Téléphone (≤599) : empilé (comparaison verticale) */
@media (max-width: 599px) { .rv-body { grid-template-columns: 1fr; } .rv-card { max-height: 38vh; } }
/* Contrôleur — mobile/fold : barre du bas compacte sur UNE seule ligne (%, repêchage, votes) ; le sous-texte
   « Ton choix… » est retiré (gain de place, l'action est évidente). */
@media (max-width: 900px) {
  .rv-center { flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px 12px; }
  .rv-center .rv-hint { display: none; }
  .rv-center .rv-err { flex-basis: 100%; margin: 4px 0 0; }
}
/* Motifs de refus pré-rédigés */
.reject-presets { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin: 0 0 12px; }
.reject-preset, .reco-preset { font-size: .8rem; font-weight: 600; color: var(--primary); background: var(--muted); border: 1px solid var(--hairline); border-radius: 999px; padding: 5px 12px; cursor: pointer; transition: background .12s, border-color .12s; }
.reject-preset:hover, .reco-preset:hover { background: var(--card); border-color: var(--primary); }
.reject-final { display: flex; align-items: center; gap: 8px; text-align: left; font-size: .88rem; margin: 4px 0 12px; color: var(--foreground); cursor: pointer; }
.reject-final input { width: 16px; height: 16px; accent-color: var(--primary); flex-shrink: 0; margin: 0; }
.accounts-trash-count { position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; background: var(--danger); color: #fff; font-size: .68rem; font-weight: 700; border-radius: 999px; }
.trash-list { display: flex; flex-direction: column; gap: 8px; max-height: 52vh; overflow-y: auto; }
.trash-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--muted); }
.trash-meta { display: flex; flex-direction: column; min-width: 0; }
.trash-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.trash-email { font-weight: 600; font-size: .9rem; overflow-wrap: anywhere; }
.trash-sub { font-size: .76rem; color: var(--muted-foreground); }
.role-badge { display: inline-block; background: var(--primary); color: #fff; font-size: .72rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
.role-badge-wait { background: var(--accent); }
.role-badge-ok { background: #2E8F6B; }        /* validé → vert */
.role-badge-draft { background: #C0873A; }     /* brouillon / en attente → orange */
.role-badge-rejected { background: #8F2F28; }  /* refusé → rouge foncé */
.mod-list { display: flex; flex-direction: column; gap: 8px; }
.mod-row { display: flex; align-items: center; gap: 14px; padding: 12px 16px; background: var(--card); border: 1px solid var(--border); border-radius: 14px; text-decoration: none; color: var(--foreground); }
.mod-flag { font-size: 16px; line-height: 1; flex-shrink: 0; margin-right: -4px; }
.mod-av { width: 52px; height: 52px; border-radius: 12px; background: var(--muted); background-size: cover; background-position: center; flex-shrink: 0; }
.mod-av-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
/* Vignette photo en tête de ligne du tableau Comptes */
.admin-table th.acct-flag, .admin-table td.acct-flag { width: 24px; padding: 0 2px 0 6px; text-align: center; font-size: 15px; line-height: 1; }
.admin-table th.acct-thumb, .admin-table td.acct-thumb { width: 46px; padding-right: 4px; }
.admin-table th.col-prenom { width: 100px; }
.admin-table td.acct-prenom { font-weight: 600; color: var(--foreground); white-space: nowrap; max-width: 100px; overflow: hidden; text-overflow: ellipsis; }
.acct-av { display: block; width: 34px; height: 34px; border-radius: 9px; background: var(--muted); background-size: cover; background-position: center; }
.acct-av-empty { background: linear-gradient(150deg, var(--secondary), var(--muted)); }
.mod-info { flex: 1; }
.mod-cta { color: var(--primary); font-weight: 600; font-size: .9rem; }
/* Ligne de modération : zone cliquable (avatar+infos) + actions (historique · examiner) à droite. */
.mod-row-main { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.mod-row-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.mod-detail { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
.mod-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.mod-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
.mod-photo { position: relative; aspect-ratio: 3/4; border-radius: 10px; overflow: hidden; background: var(--muted); cursor: grab; user-select: none; touch-action: none; }
.mod-photo:active { cursor: grabbing; }
.mod-photo.dragging { cursor: grabbing; }

/* Fiche de validation : les trois thèmes de foi se corrigent d'un clic (pop-up par thème). */
.kv-editable .kv-edit-btn { display: inline-flex; align-items: baseline; gap: 6px; max-width: 100%; padding: 2px 6px;
  margin: -2px -6px; border: 0; border-radius: 7px; background: transparent; font: inherit; text-align: inherit;
  color: inherit; cursor: pointer; transition: background .12s ease; }
.kv-editable .kv-edit-btn:hover { background: var(--muted); }
.kv-editable .kv-edit-btn svg { flex: 0 0 auto; opacity: .45; align-self: center; }
.kv-editable .kv-edit-btn:hover svg { opacity: .9; color: var(--accent); }
.foi-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 6px;
  max-height: min(52vh, 420px); overflow-y: auto; margin: 10px 0 14px; padding-right: 4px; text-align: left; }
/* ⚠️ Depuis que .foi-opt est un <div> (le <label> aurait transmis au menu de note le clic destiné à
   la case), le padding de la boîte n'est plus cliquable — mais il gardait cursor:pointer et le survol,
   soit la moitié de la surface qui promettait un clic sans rien faire. On rend le padding au <label>
   intérieur et on l'étire sur toute la hauteur : la cible redevient la boîte entière, sans reprendre
   le menu de note, qui reste son frère. */
.foi-opt { display: flex; align-items: stretch; gap: 8px; padding: 0 10px 0 0; border: 1px solid var(--border);
  border-radius: 9px; font-size: .88rem; line-height: 1.35; cursor: default; }
.foi-opt:hover { background: var(--muted); }
/* L'état vient de la CASE, pas d'une classe posée au rendu : sans ça, cocher ou décocher ne
   changeait rien à l'écran et l'admin ne voyait pas ce qu'il était en train de modifier.
   Même motif que les autres cartes à cocher du back-office (:has plus haut dans ce fichier). */
.foi-opt:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.foi-opt input { margin: 0; flex: 0 0 auto; }
/* Le libellé cliquable et le menu d'importance vivent côte à côte : le <label> ne couvre QUE la case
   et son texte, sinon un clic sur le menu basculerait la case. */
.foi-opt-main { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer;
  padding: 8px 0 8px 10px; }
.foi-note { flex: 0 0 auto; align-self: center; padding: 2px 4px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--card); color: var(--card-foreground); font: inherit; font-size: .82rem; line-height: 1.3; cursor: pointer; }
.foi-note:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Case décochée : la note ne s'applique pas — on l'estompe plutôt que de la masquer, pour qu'on
   comprenne qu'elle reprendra effet si on coche. */
.foi-opt:not(:has(input:checked)) .foi-note { opacity: .35; }
.mod-photo img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.ph-reject { position: absolute; bottom: 6px; right: 6px; border: none; background: rgba(166,64,55,.9); color: #fff; font-size: .72rem; padding: 4px 8px; border-radius: 6px; cursor: pointer; }
/* Rejet réversible : la photo refusée reste visible mais grisée (sera supprimée à la réouverture) ; bouton « Annuler » pour ré-accepter. */
.mod-photo.is-rejected img { opacity: .38; filter: grayscale(1); }
.ph-unreject { position: absolute; bottom: 6px; right: 6px; border: none; background: rgba(20,32,43,.92); color: #fff; font-size: .72rem; padding: 4px 8px; border-radius: 6px; cursor: pointer; }
/* Contrôle anti-catfishing (recherche inversée + réutilisation de photos) */
.cf-card h3 { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.cf-card h3 svg { flex-shrink: 0; }
.cf-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.cf-row:last-child { border-bottom: 0; }
.cf-thumb { width: 44px; height: 56px; border-radius: 8px; background: var(--muted); background-size: cover; background-position: center; flex-shrink: 0; }
.cf-links { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; font-size: .85rem; min-width: 0; }
.cf-links a { color: var(--primary); font-weight: 600; text-decoration: none; }
.cf-links a:hover { text-decoration: underline; }
.cf-dup { flex-basis: 100%; color: var(--danger); font-weight: 700; font-size: .8rem; }
a.cf-dup { text-decoration: none; cursor: pointer; } /* le libellé ouvre le profil concerné dans un nouvel onglet */
a.cf-dup:hover { text-decoration: underline; }
.cf-dup-strong { color: var(--danger); }               /* ≤4 : quasi la même image */
.cf-dup-weak { color: #9A6A00; font-weight: 600; }      /* 5-8 : ressemblance à vérifier (ambre, moins alarmant) */
/* Lightbox d'agrandissement d'une photo en modération (clic sur la vignette) */
/* ⚠️ « Fichier manquant » : la ligne existe en base, l'image a disparu du serveur. La tuile
   restait une case grise muette — un modérateur ne pouvait pas distinguer un chargement lent,
   un fichier cassé et une absence de photo. On l'écrit, avec le chemin attendu. */
/* ⚠️ La tuile fait 3/4 de large sur une rangée de cinq, et elle rogne ce qui dépasse : le message
   tient donc en deux lignes, et le chemin complet vit dans l'infobulle (attribut title). */
.mod-photo-gone { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 4px; padding: 6px; text-align: center; }
.mod-photo-gone .mpg-x { font-size: 1.4rem; line-height: 1; color: #b23c3c; opacity: .75; }
.mod-photo-gone strong { font-size: .72rem; font-weight: 600; color: #b23c3c; line-height: 1.2; }
.cf-thumb-gone { display: flex; align-items: center; justify-content: center; color: #b23c3c;
  font-size: 1.1rem; background: rgba(178,60,60,.07); }
.cf-gone-note { font-size: .78rem; color: var(--muted-foreground); font-style: italic; }
.mod-photo { cursor: zoom-in; }
.img-lightbox { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; padding: 32px; background: rgba(16,32,39,.82); backdrop-filter: blur(2px); }
.img-lightbox[hidden] { display: none; }
.img-lightbox img { max-width: 92vw; max-height: 88vh; border-radius: 14px; box-shadow: 0 24px 70px rgba(0,0,0,.55); cursor: default; }
.img-lightbox-close { position: absolute; top: 20px; right: 24px; width: 44px; height: 44px; border-radius: 999px; border: none; background: rgba(255,255,255,.16); color: #fff; font-size: 1.7rem; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.img-lightbox-close:hover { background: rgba(255,255,255,.3); }
.img-lightbox-tools { position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%); display: flex; gap: 12px; z-index: 2; }
.lb-rotate { width: 48px; height: 48px; border-radius: 999px; border: none; background: rgba(255,255,255,.92); color: #16202B; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 18px rgba(0,0,0,.3); }
.lb-rotate:hover { background: #fff; }
.lb-rotate:disabled { opacity: .5; cursor: default; }
.lb-restore { background: #FBEAD2; color: #8A5A12; } /* « rétablir l'original » : ambre, pour se distinguer des rotations/recadrage */
.lb-restore:hover { background: #F7DFBE; }
/* Recadrage : la scène épouse l'image, le calque de crop se superpose, la sélection masque l'extérieur. */
.lb-stage { position: relative; display: inline-block; line-height: 0; }
.lb-crop { position: absolute; inset: 0; }
.lb-crop-box { position: absolute; box-sizing: border-box; border: 1px solid rgba(255, 255, 255, .95); box-shadow: 0 0 0 9999px rgba(16, 32, 39, .62); cursor: move; touch-action: none; }
.lb-crop-h { position: absolute; width: 18px; height: 18px; background: #fff; border-radius: 999px; box-shadow: 0 1px 5px rgba(0, 0, 0, .45); touch-action: none; }
.lb-crop-h.tl { top: -9px; left: -9px; cursor: nwse-resize; }
.lb-crop-h.tr { top: -9px; right: -9px; cursor: nesw-resize; }
.lb-crop-h.bl { bottom: -9px; left: -9px; cursor: nesw-resize; }
.lb-crop-h.br { bottom: -9px; right: -9px; cursor: nwse-resize; }
.img-lightbox-crop-actions { position: absolute; bottom: 24px; left: 50%; transform: translateX(-50%); display: flex; gap: 12px; z-index: 3; }
.lb-act { border: none; border-radius: 999px; padding: 11px 22px; font-size: .92rem; font-weight: 700; cursor: pointer; background: var(--primary); color: #fff; font-family: inherit; box-shadow: 0 6px 18px rgba(0, 0, 0, .3); }
.lb-act:hover { background: var(--primary-deep); }
.lb-act:disabled { opacity: .6; cursor: default; }
.lb-act.ghost { background: rgba(255, 255, 255, .92); color: #16202B; }
.lb-act.ghost:hover { background: #fff; }
.mod-detail-card { display: flex; flex-direction: column; }
.mod-detail-card h3 { margin-bottom: 6px; }
.kv { display: grid; gap: 4px; padding: 12px 0; border-bottom: 1px solid var(--hairline); }
.kv:first-of-type { padding-top: 4px; }
.kv:last-child { border-bottom: none; padding-bottom: 2px; }
.kv > span { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); font-weight: 600; }
.kv > strong, .kv-editable .kv-edit-btn > strong { font-weight: 500; font-size: .95rem; line-height: 1.5; color: var(--card-foreground); overflow-wrap: anywhere; }
.mod-actions-card { display: flex; flex-direction: column; gap: 10px; }
/* Carte « Niveau de pratique » (fiche de modération) : les 5 paliers cliquables, celui du membre surligné. */
.mod-practice-card h3 { margin-bottom: 10px; }
.practice-scale { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.practice-step { font: inherit; font-size: .8rem; font-weight: 600; padding: 5px 11px; border-radius: 999px; background: var(--muted); color: var(--muted-foreground); border: 1px solid transparent; cursor: pointer; transition: background .12s, color .12s, box-shadow .12s; }
.practice-step:hover { background: #E4DECF; }
.practice-step.is-active { background: var(--primary); color: #fff; border-color: var(--primary); box-shadow: 0 2px 8px rgba(34, 62, 99, .22); }
.practice-step.is-active:hover { background: var(--primary-deep); }
.practice-hint { font-size: .78rem; color: var(--muted-foreground); margin: 9px 0 0; }
.mod-act { display: flex; gap: 8px; margin: 0; }
/* Les 4 boutons de décision passent à la ligne dès que la place manque — indispensable dans la colonne
   étroite de la vue fold (le média sur la LARGEUR D'ÉCRAN ne voyait pas que la CARTE est étroite). Chaque
   bouton garde sa taille naturelle (flex:0 0 auto) au lieu de se comprimer et de chevaucher son voisin. */
.mod-decision { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.mod-decision > * { flex: 0 0 auto; }
.mod-decision .btn { gap: 6px; padding: 9px 14px; font-size: .92rem; white-space: nowrap; }
.mod-decision .btn svg { flex-shrink: 0; }
.report-card { margin-bottom: 12px; }
.report-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.report-details { background: var(--muted); padding: 10px 14px; border-radius: 10px; font-size: .9rem; }
.report-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.admin-shell code { background: var(--muted); padding: 2px 6px; border-radius: 5px; font-size: .82rem; }

/* ===== Back-office : layout à 3 niveaux ====================================================
   • Téléphone (≤599)      : sidebar en icônes + contenus EMPILÉS (vraie vue mobile).
   • Fold déplié (600–900) : sidebar en icônes RABATTABLE (bouton pour déplier les libellés en
     overlay) + contenus DESKTOP multi-colonnes. La sidebar-icônes rend ~170 px de largeur → ça
     respire (ni tassé, ni mobile). Un fold déplié est indistinguable d'une tablette en CSS, donc
     on cible la ZONE 600–900 px (entre téléphone et desktop) — desktop et téléphone non touchés.
   • Desktop (≥901)        : sidebar pleine avec libellés (inchangé).
   =========================================================================================== */

/* Sidebar en icônes : téléphone ET fold */
@media (max-width: 900px) {
  .admin-side { width: 64px; padding: 16px 8px; }
  .admin-brand span, .side-link .side-label, .side-logout .side-label { display: none; }
  .admin-brand { justify-content: center; padding-left: 0; padding-right: 0; }
  .side-link, .side-logout { justify-content: center; gap: 0; }
  .side-link { position: relative; }
  .side-badge { position: absolute; top: 4px; right: 6px; margin: 0; }
  .admin-main { padding: 22px 20px; }
}

/* Téléphone UNIQUEMENT (≤599) : contenus empilés */
@media (max-width: 599px) {
  .mod-detail { grid-template-columns: 1fr; }
  .admin-main { padding: 20px 16px; }
}

/* Tables larges défilables dans leur carte (les menus de ligne .acct-send-menu sont position:fixed,
   aucun ancêtre ne les piège → non rognés). :has(> .admin-table) = uniquement les cartes-tables.
   ⚠️ SANS PLAFOND DE LARGEUR, et c'est le correctif : la règle était bornée à 900 px, comme si une
   table ne pouvait déborder que sur téléphone. La page Comptes la dépasse pourtant sur un écran
   ordinaire — dix colonnes, des adresses longues, cinq boutons par ligne, et depuis le filtre par
   pays une colonne de drapeau en plus. La dernière colonne (la corbeille) sortait alors de la carte
   et flottait à côté. `overflow-x: auto` ne fait rien tant que rien ne dépasse : l'appliquer partout
   ne coûte donc rien aux tables étroites, et rattrape toutes les autres — y compris celles qu'on
   élargira demain sans y penser. */
body.admin-shell .card:has(> .admin-table) { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Bouton « rabattre / déplier » le menu — caché par défaut, visible SEULEMENT en zone fold */
.admin-nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 38px; flex-shrink: 0; margin: 2px auto 12px; padding: 0;
  border: 0; border-radius: 10px; cursor: pointer;
  background: rgba(255, 255, 255, .1); color: #fff;
}
.admin-nav-toggle:hover { background: rgba(255, 255, 255, .2); }
.admin-nav-toggle svg { transition: transform .2s ease; }
.admin-nav-backdrop { display: none; position: fixed; inset: 0; z-index: 150; background: rgba(16, 24, 40, .42); }
.admin-side { transition: width .18s ease; }

/* Zone FOLD (600–900) : le menu icônes se déplie en overlay au clic sur le bouton */
@media (min-width: 600px) and (max-width: 900px) {
  .admin-nav-toggle { display: flex; }
  body.admin-nav-open .admin-side {
    position: fixed; top: 0; left: 0; height: 100vh;
    width: 232px; padding: 20px 14px; z-index: 200;
    box-shadow: 0 0 44px rgba(0, 0, 0, .35);
  }
  body.admin-nav-open .admin-brand span,
  body.admin-nav-open .side-link .side-label,
  body.admin-nav-open .side-logout .side-label { display: inline; }
  body.admin-nav-open .admin-brand { justify-content: flex-start; padding-left: 8px; padding-right: 8px; }
  body.admin-nav-open .side-link,
  body.admin-nav-open .side-logout { justify-content: flex-start; gap: 12px; }
  body.admin-nav-open .side-badge { position: static; margin-left: auto; }
  /* ⚠️ Le chevron doit rester CENTRÉ dans son carré : justify-content:flex-end le collait au bord
     droit du bouton (11 px hors axe, mesuré), ce qui se voyait immédiatement. Et margin-right:4px
     ne neutralisait que la marge droite — la gauche restant à auto, le bouton partait à l'extrême
     droite du panneau, désaligné de tout le reste du menu. On le place explicitement : collé au
     bord droit du panneau, à la même distance que les entrées de menu, icône centrée. */
  body.admin-nav-open .admin-nav-toggle { margin-left: auto; margin-right: 0; }
  body.admin-nav-open .admin-nav-toggle svg { transform: rotate(180deg); }
  body.admin-nav-open .admin-nav-backdrop { display: block; }
}


/* ===================================================================
   Pré-inscription + questionnaire catholique
   =================================================================== */

/* Formulaire de pré-inscription (hero + bande CTA) */
.waitlist-form { display: flex; gap: 10px; max-width: 460px; margin-top: 6px; flex-wrap: wrap; }
.waitlist-form input[type="email"] {
  flex: 1; min-width: 200px; padding: 14px 18px; font: inherit; color: var(--foreground);
  background: rgba(255,255,255,.92); border: 1px solid rgba(255,255,255,.5); border-radius: 999px;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.waitlist-form input[type="email"]:focus { outline: 2px solid #fff; }
.waitlist-form .btn { white-space: nowrap; }
.waitlist-form-dark { margin: 0 auto; justify-content: center; }
.waitlist-form-dark input[type="email"] { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.4); color: #fff; }
.waitlist-form-dark input::placeholder { color: rgba(255,255,255,.7); }

.hero-badge {
  display: inline-block; margin-bottom: 18px; padding: 8px 16px;
  background: rgba(180,138,79,.28); border: 1px solid rgba(228,139,178,.5);
  border-radius: 999px; font-size: .86rem; font-weight: 600; color: #fff;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
/* Aperçu multi-pays : deux pastilles côte à côte + sélecteur de pays cliquable (page /apercu-pays). */
.hero-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 18px; }
.hero-badges .hero-badge { margin-bottom: 0; }
.hero-pick { position: relative; }
.hero-pick > summary { cursor: pointer; list-style: none; user-select: none; margin-bottom: 0; }
.hero-pick > summary::-webkit-details-marker { display: none; }
.hero-badge-pick { display: inline-flex; align-items: center; gap: 6px; }
.hero-pick-caret { font-size: .8em; opacity: .85; transition: transform .15s; }
.hero-pick[open] .hero-pick-caret { transform: rotate(180deg); }
.hero-pick-menu {
  /* Ouverture VERS LE BAS (le hero n'a plus overflow:hidden et est en z-index:1 → pas de rognage). */
  position: absolute; top: calc(100% + 6px); bottom: auto; left: 0; z-index: 40; min-width: 190px;
  max-height: 60vh; overflow-y: auto;
  display: flex; flex-direction: column; padding: 6px; border-radius: 14px;
  background: rgba(24,32,46,.92); border: 1px solid rgba(255,255,255,.14);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); box-shadow: 0 12px 34px rgba(0,0,0,.35);
}
.hero-pick-opt { display: flex; align-items: center; padding: 9px 12px; border-radius: 9px; color: #fff; text-decoration: none; font-size: .9rem; font-weight: 600; }
.hero-pick-opt:hover { background: rgba(255,255,255,.12); }
.hero-pick-opt.is-active { background: rgba(228,139,178,.32); }
.hero-pick-flag { margin-right: 8px; font-size: 1.05em; }

/* Questionnaire foi : aide de champ + listes de chips */
.field-help { font-size: .88rem; color: var(--muted-foreground); margin: 0 0 12px; }
.field-opt { font-weight: 400; font-size: .82em; color: var(--muted-foreground); }
.photo-warn {
  display: flex; gap: 8px; align-items: flex-start;
  margin: 18px 0; padding: 10px 13px;
  background: rgba(176, 69, 59, .08); border: 1px solid rgba(176, 69, 59, .28);
  border-radius: 12px; font-size: .86rem; line-height: 1.45; color: #8F3A31;
}
.scroll-list { max-height: 320px; overflow-y: auto; padding: 4px; margin: -4px; -webkit-overflow-scrolling: touch; }
.scroll-list .radio-card { padding: 11px 14px; }

.chip-group { display: flex; flex-wrap: wrap; gap: 8px; }
/* Case « ouverture internationale » (étape préférences de l'onboarding, multi-pays). */
.intl-check { display: flex; align-items: flex-start; gap: 11px; cursor: pointer; }
.intl-check input { width: 15px; height: 15px; position: relative; top: 2px; flex-shrink: 0; accent-color: var(--primary, #223E63); cursor: pointer; }
.intl-check span { line-height: 1.45; font-weight: 400; }
.intl-check span strong { font-weight: 600; }

/* Sélecteur de pays : petit drapeau discret DEVANT les champs de localisation (page test /apercu-ville). */
.geo-country-row { display: flex; align-items: flex-end; gap: 10px; }
.geo-country-row [hidden] { display: none !important; }
.geo-fields { flex: 1 1 auto; min-width: 0; }
.geo-cflag { position: relative; flex-shrink: 0; }
.geo-cflag > summary { list-style: none; }
.geo-cflag > summary::-webkit-details-marker { display: none; }
.geo-cflag-btn { display: inline-flex; align-items: center; gap: 4px; height: 46px; padding: 0 2px; border: 0; background: transparent; cursor: pointer; font-size: 22px; line-height: 1; }
.geo-cflag-btn:hover .geo-cflag-caret { color: var(--primary, #223E63); }
.geo-cflag-caret { font-size: 10px; color: #9aa0a6; }
.geo-cflag-menu { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; min-width: 200px; background: #fff; border: 1px solid var(--hairline, #E3E7EC); border-radius: 12px; box-shadow: 0 14px 34px rgba(16,32,43,.16); padding: 6px; max-height: 280px; overflow-y: auto; }
.geo-cflag-opt { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; padding: 8px 10px; border: 0; border-radius: 8px; background: transparent; font: inherit; font-size: .92rem; color: var(--foreground, #16202B); cursor: pointer; }
.geo-cflag-opt:hover { background: var(--muted, #F2F0EA); }
.geo-cflag-opt.is-active { background: var(--primary, #223E63); color: #fff; }
.geo-cflag-opt-flag { font-size: 17px; line-height: 1; }
.ob-demo-note { font-size: .82rem; color: #7a6a45; background: #FBF3E1; border: 1px solid rgba(154,106,0,.22); border-radius: 10px; padding: 9px 12px; margin: 0 0 16px; }
.ob-demo-status { font-size: .85rem; color: var(--muted-foreground, #6b7480); margin: 12px 0 0; }
.chip-check { cursor: pointer; }
.chip-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip-check span {
  display: inline-block; padding: 9px 15px; border: 1px solid var(--border);
  border-radius: 999px; font-size: .9rem; background: var(--card); transition: all .15s ease;
}
.chip-check input:checked + span { background: var(--primary); color: #fff; border-color: var(--primary); }
.chip-check input:checked + span::before { content: '\2713'; margin-right: 6px; font-weight: 700; }
.chip-check input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }
.chip-check.chip-disabled span { opacity: .4; cursor: not-allowed; }

/* Tags sur la fiche profil (sensibilité / communautés) */
.tag-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 6px 0 4px; }
.tag-label { font-size: .74rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: var(--accent); margin-right: 2px; }
.tag { display: inline-block; padding: 6px 12px; border-radius: 999px; font-size: .84rem; background: var(--secondary); color: var(--primary); }

@media (max-width: 560px) {
  .waitlist-form { flex-direction: column; }
  .waitlist-form .btn, .waitlist-form input[type="email"] { width: 100%; }
}

/* ---- Onboarding foi : sur-titre d'étape + cartes d'importance ---- */
.ob-eyebrow { text-transform: uppercase; letter-spacing: .14em; font-size: .72rem; font-weight: 700; color: var(--accent); margin: 0 0 8px; }
.ob-section h1 { margin-bottom: .2em; }

.imp-cards { display: grid; gap: 12px; margin-top: 6px; }
.imp-card {
  display: flex; align-items: center; gap: 16px;
  padding: 18px 20px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow-sm);
  transition: border-color .15s ease, background .15s ease, transform .1s ease;
}
.imp-card:active { transform: scale(.99); }
.imp-card input { position: absolute; opacity: 0; width: 0; height: 0; }
.imp-sym { font-size: 1.5rem; line-height: 1; color: var(--accent); width: 28px; text-align: center; flex-shrink: 0; }
.imp-body { display: flex; flex-direction: column; }
.imp-label { font-weight: 700; font-size: 1.05rem; }
.imp-desc { color: var(--muted-foreground); font-size: .9rem; }
.imp-card:has(input:checked) { border-color: var(--primary); background: var(--secondary); box-shadow: 0 0 0 2px var(--primary) inset; }
.imp-card:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Bloc consentements sur l'étape identité */
.consent-block { padding-top: 10px; margin-top: 4px; margin-bottom: 12px; display: grid; gap: 12px; }

/* Carte d'intro de l'onboarding */
.intro-card { text-align: left; border-left: 4px solid var(--accent); margin: 4px 0 4px; }
.intro-card + .form { margin-top: 30px; }
.intro-card p { color: var(--foreground); }
.intro-card p:last-of-type { margin-bottom: 0; }
.intro-points { list-style: none; padding: 0; margin: 18px 0 0; display: grid; gap: 10px; border-top: 1px solid var(--hairline); padding-top: 16px; }
.intro-points li { position: relative; padding-left: 26px; font-size: .95rem; }
.intro-points li::before { content: '✓'; position: absolute; left: 0; top: 0; color: var(--success); font-weight: 700; }

/* ---- Pages légales (CGU / Confidentialité) ---- */
/* ---- Pages de contenu (SEO) ---- */
.page-article .article { padding: 40px 0 20px; }
.container-article { max-width: 720px; margin: 0 auto; padding: 0 20px; }
.article-crumb { font-size: .85rem; color: var(--muted-foreground); margin: 0 0 14px; }
.article-crumb a { color: var(--muted-foreground); text-decoration: none; }
.article-crumb span { margin: 0 4px; }
.container-article h1 { font-family: var(--font-brand); font-size: clamp(1.9rem, 4.5vw, 2.6rem); line-height: 1.1; color: var(--foreground); margin: 0 0 .35em; }
.article-lead { font-size: 1.18rem; line-height: 1.6; color: var(--muted-foreground); margin: 0 0 1.6em; }
/* Contrôleur de matchs : lien « Voir la fiche du compte » sous chaque carte de la modale de revue. */
.ctrl-card-account { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 10px; padding: 9px 12px; border: 1px solid var(--border, rgba(34,62,99,.16)); border-radius: 10px; color: #223E63; font-weight: 600; font-size: .9rem; text-decoration: none; transition: background .12s, border-color .12s; }
.ctrl-card-account:hover { background: #F1F4F9; border-color: rgba(34,62,99,.32); }
/* En-têtes de colonnes triables (admin Comptes) : lien discret, flèche sur la colonne active. */
.admin-table th a.th-sort { color: inherit; text-decoration: none; white-space: nowrap; cursor: pointer; }
.admin-table th a.th-sort:hover { text-decoration: underline; }
.admin-table th a.th-sort.is-active { color: #223E63; font-weight: 700; }
.th-sort-arrow { font-size: .72em; vertical-align: 1px; }
/* Sélecteur de pays de la carte (tableau de bord admin) : pastilles cliquables avec effectif. */
.map-layout { display: flex; align-items: flex-start; gap: 22px; }
.map-svg-wrap { flex: 1 1 auto; min-width: 0; }
/* Cartes pays (contour + points membres) sur le tableau de bord — Belgique (be-map) et tous les autres (geo-map). */
.be-map-wrap, .geo-map-wrap { max-width: 520px; margin: 0 auto; text-align: center; }
/* max-height borne les pays très verticaux (Bénin) ; max-width les pays larges (Sénégal) — l'aspect est préservé. */
.be-map, .geo-map { display: block; margin: 0 auto; max-width: 100%; max-height: 440px; width: auto; height: auto; }
.be-map path, .geo-map path { fill: #dde5ee; stroke: #90a3ba; stroke-width: 1; stroke-linejoin: round; transition: fill .12s; }
.be-map path:hover, .geo-map path:hover { fill: #c6d4e4; }
.be-dot, .geo-dot { fill: var(--primary, #223E63); stroke: #fff; stroke-width: 2.5; }
.map-country-picker { display: flex; flex-direction: column; gap: 8px; margin: 0; flex: 0 0 auto; min-width: 190px; }
.map-country-pill { display: flex; align-items: center; justify-content: space-between; gap: 7px; padding: 8px 13px; border-radius: 999px; border: 1px solid var(--border, rgba(34,62,99,.16)); color: var(--foreground, #223E63); text-decoration: none; font-size: .9rem; font-weight: 600; transition: background .12s, border-color .12s; }
@media (max-width: 599px) { .map-layout { flex-direction: column; } .map-country-picker { flex-direction: row; flex-wrap: wrap; min-width: 0; } } /* fold déplié = desktop (carte + liste côte à côte) */
.map-country-pill:hover { background: #F1F4F9; border-color: rgba(34,62,99,.3); }
.map-country-pill.is-active { background: #223E63; color: #fff; border-color: #223E63; }
.map-country-n { min-width: 18px; padding: 0 6px; border-radius: 999px; background: rgba(34,62,99,.1); font-size: .78rem; text-align: center; }
.map-country-pill.is-active .map-country-n { background: rgba(255,255,255,.22); }
/* « Reste du monde » : liste des pays saisis en toutes lettres. Même langage visuel que les
   pastilles de gauche (pilule + compteur), mais SANS lien ni survol — il n'y a pas de carte à
   ouvrir derrière, et un élément qui a l'air cliquable sans l'être est une promesse en l'air. */
.world-list { list-style: none; margin: 22px auto 0; padding: 0; display: flex; flex-direction: column; gap: 8px; max-width: 320px; text-align: left; }
.world-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 13px; border-radius: 999px; border: 1px solid var(--border, rgba(34,62,99,.16)); color: var(--foreground, #223E63); font-size: .9rem; font-weight: 600; }
/* Vidéo intégrée dans un article (YouTube nocookie) : player 16/9 arrondi + légende discrète. */
/* Illustration d'article. width/height sont posés dans le HTML : le navigateur réserve la place
   avant le chargement, la page ne saute donc pas sous les yeux du lecteur. */
.article-illu { margin: 0 0 2em; }
.article-illu img { display: block; width: 100%; height: auto; border-radius: 14px; box-shadow: 0 10px 30px rgba(34, 62, 99, .12); }
.article-video { margin: 1.4em 0 1.8em; }
.article-video iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 14px; box-shadow: 0 10px 30px rgba(34, 62, 99, .12); background: #000; }
.article-video-caption { margin: 10px 2px 0; font-size: .88rem; color: var(--muted-foreground); }
.container-article h2 { font-family: var(--font-brand); font-size: 1.5rem; color: var(--primary); margin: 1.6em 0 .4em; }
.container-article p { font-size: 1.05rem; line-height: 1.7; color: var(--foreground); margin: 0 0 1.1em; }
/* Listes d'article : chaque puce porte une explication entière, pas un mot-clé. Sans respiration
   entre elles, le bloc se lit comme un pavé. Même graisse et même interligne que les paragraphes. */
.container-article ul { margin: 1.1em 0 1.5em; padding-left: 1.4em; }
.container-article li { font-size: 1.05rem; line-height: 1.7; color: var(--foreground); margin-bottom: .9em; }
.container-article li:last-child { margin-bottom: 0; }
/* :not(.btn) — sinon cette règle (0,1,1) bat .btn-primary (0,1,0) et le CTA devient navy sur navy. */
.container-article a:not(.btn) { color: var(--primary); font-weight: 600; }
.article-cta { margin: 2.4em 0 1.6em; padding: 28px; background: var(--secondary); border: 1px solid var(--hairline); border-radius: 18px; text-align: center; }
.article-cta h2 { margin: 0 0 16px; }
.article-cta .waitlist-form { justify-content: center; margin: 0 auto; }
.article-cta .hero-note { margin: 16px 0 0; color: rgba(22,32,43,.6); font-size: .9rem; }
.article-related { margin-top: 2em; border-top: 1px solid var(--hairline); padding-top: 1.2em; }
.article-related h2 { font-size: 1.15rem; margin: 0 0 .4em; }
.article-related ul { margin: 0; padding-left: 1.1em; }
.article-related li { margin: .3em 0; }

.legal-body { max-width: 720px; margin: 0 auto; }
.legal-body h1 { font-size: clamp(1.7rem, 4vw, 2.2rem); }
.legal-date { color: var(--muted-foreground); font-size: .9rem; margin: -.4em 0 2em; }
.legal-body h2 { font-size: 1.25rem; margin: 1.8em 0 .5em; color: var(--primary); }
.legal-body p, .legal-body li { color: var(--foreground); line-height: 1.65; }
.legal-body ul { padding-left: 1.3em; display: grid; gap: 6px; margin: 0 0 1em; }
.legal-body a { color: var(--primary); }
.legal-body .note {
  background: var(--secondary); border-left: 4px solid var(--accent);
  border-radius: 12px; padding: 16px 20px; margin-bottom: 2em; color: var(--foreground);
}
.legal-back { margin-top: 2.5em; border-top: 1px solid var(--hairline); padding-top: 1.5em; }
.legal-back a { color: var(--muted-foreground); text-decoration: none; font-weight: 600; }
.legal-back a:hover { color: var(--primary); }

/* Landing : deux sections côte à côte (Comment ça marche / Un espace de confiance) */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; }
.col-block .eyebrow { text-align: left; }
.col-block h2 { text-align: left; font-size: clamp(1.5rem, 3vw, 1.9rem); margin-bottom: 22px; }
.two-col .steps, .two-col .checklist { max-width: none; margin: 0; }
@media (max-width: 760px) {
  .two-col { grid-template-columns: 1fr; gap: 40px; }
}

/* ---- Onboarding : note 1-3 par case cochée ---- */
.rate-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: .85rem; color: var(--muted-foreground); margin-bottom: 14px; }
.rate-legend strong { color: var(--primary); }
.rate-list { display: grid; gap: 10px; }
.rate-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--card); }
.rate-label { flex: 1; font-size: .95rem; }
.rate-opts { display: flex; gap: 6px; flex-shrink: 0; }
.rate-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.rate-opt span { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--border); font-weight: 700; cursor: pointer; color: var(--muted-foreground); background: var(--background); transition: all .12s ease; }
.rate-v1 input:checked + span { background: #9aa0ab; border-color: #9aa0ab; color: #fff; }
.rate-v2 input:checked + span { background: var(--accent); border-color: var(--accent); color: #fff; }
.rate-v3 input:checked + span { background: var(--primary); border-color: var(--primary); color: #fff; }
.rate-opt input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Message « Pas forcément » (préférence mariage) */
.marriage-note { display: none; font-size: .9rem; color: var(--danger); background: #FBEDEB; border: 1px solid var(--danger); border-radius: 12px; padding: 11px 15px; margin-top: 12px; }
.form:has(input[name="marriage_pref"][value="non"]:checked) .marriage-note { display: block; }
/* « Pas forcément » choisi : on empêche de continuer (l'appli est en vue du mariage). */
.form:has(input[name="marriage_pref"][value="non"]:checked) .btn-block { opacity: .45; pointer-events: none; filter: grayscale(.35); }

/* --- Gestionnaire des domaines jetables (modale Réglages) --- */
.disp-inner { width: min(560px, 100%); }
.disp-body { padding: 16px; overflow-y: auto; }
.disp-lead { color: var(--muted-foreground); font-size: .88rem; margin: 0 0 14px; line-height: 1.5; }
.disp-add { display: flex; gap: 8px; }
.disp-add input { flex: 1; min-width: 0; }
.disp-err { color: #C0392B; font-size: .82rem; margin: 8px 0 0; }
.disp-err[hidden] { display: none !important; }
.disp-h { margin: 18px 0 8px; font-size: .9rem; color: var(--foreground); }
.disp-chips { display: flex; flex-wrap: wrap; gap: 8px; min-height: 30px; max-height: 300px; overflow-y: auto; align-content: flex-start; padding: 2px; }
.disp-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--muted); border: 1px solid var(--hairline); border-radius: 999px; padding: 4px 6px 4px 12px; font-size: .85rem; color: var(--foreground); }
.disp-chip-x { background: none; border: 0; cursor: pointer; font-size: 1.15rem; line-height: 1; color: var(--muted-foreground); padding: 0 3px; }
.disp-chip-x:hover { color: #C0392B; }
.disp-empty { color: var(--muted-foreground); font-size: .85rem; font-style: italic; }
.disp-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 16px; border-top: 1px solid var(--hairline); flex-shrink: 0; }
.disp-note { font-size: .78rem; color: var(--muted-foreground); }
@media (max-width: 560px) { .disp-foot { flex-direction: column; align-items: stretch; } }

/* --- Carte « Envoi d'e-mails » : sélecteur 3 voies + config conditionnelle --- */
.seg-toggle.seg-3 { width: 440px; }
.seg-toggle.seg-3 .seg-thumb { width: calc(33.333% - 2px); }
/* Trois libellés : ils doivent tenir sur une seule ligne, sinon le curseur se décale. */
.seg-toggle.seg-3 .seg-opt { white-space: nowrap; padding: 8px 6px; }
#mt-api:checked ~ .seg-thumb { transform: translateX(0); }
#mt-smtp:checked ~ .seg-thumb { transform: translateX(100%); }
#mt-mail:checked ~ .seg-thumb { transform: translateX(200%); }
#mt-api:checked ~ label[for="mt-api"],
#mt-smtp:checked ~ label[for="mt-smtp"],
#mt-mail:checked ~ label[for="mt-mail"] { color: var(--primary); }
/* Seule la config de la voie choisie est affichée ; les champs masqués restent soumis
   (display:none n'empêche pas l'envoi), donc les réglages des autres voies sont conservés. */
.mail-card .mt-cfg, .mail-card .mt-why { display: none; }
.mail-card:has(#mt-api:checked) .mt-cfg-api,
.mail-card:has(#mt-smtp:checked) .mt-cfg-smtp,
.mail-card:has(#mt-mail:checked) .mt-cfg-mail { display: block; }
.mail-card:has(#mt-api:checked) .mt-why-api,
.mail-card:has(#mt-smtp:checked) .mt-why-smtp,
.mail-card:has(#mt-mail:checked) .mt-why-mail { display: block; }
.mt-tests { display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 560px) { .seg-toggle.seg-3 { width: 100%; } .mt-tests .btn { flex: 1 1 auto; } }

/* --- Accueil : composition asymétrique de la section « Pourquoi » ---------------------------
   Remplace la grille de 3 cartes identiques : l'argument différenciant (« un profil par jour »)
   occupe un grand bloc, les deux autres sont secondaires. La symétrie parfaite des 3 colonnes
   était le principal marqueur de mise en page générique. */
.feat-grid { display: grid; gap: 18px; grid-template-columns: 1fr 1fr; align-items: stretch; }
.feat-side-col { display: flex; flex-direction: column; gap: 18px; }
.feat-side-col > .feat-side { flex: 1; }
.feat-lead { display: flex; flex-direction: column; justify-content: center; padding: 44px 40px; }
.feat-lead .feat-ic { width: 60px; height: 60px; border-radius: 18px; margin-bottom: 22px; }
.feat-lead h3 { font-size: 1.85rem; line-height: 1.2; margin-bottom: 12px; }
.feat-lead p { font-size: 1rem; line-height: 1.62; }
.feat-side h3 { margin-bottom: 8px; }
.feat-side p { font-size: 1rem; line-height: 1.62; margin-bottom: 0; }
/* Icônes au trait : la taille du SVG suit la pastille qui le contient. */
.feat-svg { width: 55%; height: 55%; }
@media (max-width: 860px) {
  /* minmax(0,1fr) (et non 1fr) : le minimum d'une piste `1fr` est `auto` = min-content, or
     .feat-lead contient le carrousel en largeur fixe (288px) + padding → min-content ~340px, ce qui
     gonflait la colonne au-delà du conteneur (cases 342px, 2px hors écran, pas de marge à droite).
     minmax(0,1fr) borne la colonne à la largeur de la grille ; le carrousel rétrécit via max-width:100%. */
  .feat-grid { grid-template-columns: minmax(0, 1fr); }
  .feat-lead { grid-row: auto; padding: 30px 26px; }
  .feat-lead h3 { font-size: 1.5rem; }
  /* En pleine largeur mobile, la bande réservée par l'icône crée un grand vide
     au-dessus du titre. On repasse en ligne : titre à gauche, icône à droite,
     texte pleine largeur en dessous — plus de trou. */
  .feat-side { display: grid; grid-template-columns: 1fr auto; grid-template-areas: "title icon" "text text"; align-items: center; column-gap: 14px; }
  /* Spécificité +1 (.feat-side-col) pour battre la règle de base `margin-bottom:-34px`
     (qui, restée active sur mobile, écrasait la ligne à 48px et faisait déborder
     l'icône 82px sur le paragraphe). Ici la ligne 1 fait toute la hauteur de l'icône
     → le paragraphe passe bien en dessous, sans chevauchement. */
  .feat-side-col .feat-side .feat-ic { grid-area: icon; margin: 0; align-self: center; }
  /* Chaque illustration est centrée dans un PNG carré 260×260 avec une marge transparente
     de largeur DIFFÉRENTE selon l'icône (croix étroite, carte large) → leur bord VISIBLE
     ne s'alignait pas (36–51px selon l'icône). `object-fit`/`object-position` sont inopérants
     ici (image carrée dans cadre carré, pas de letterbox). On décale donc chaque icône de la
     quantité exacte pour que son bord visible tombe à 23px = la marge du texte des cases de la
     section du dessous. Mobile uniquement ; le bureau garde son décalage vers le coin. */
  .feat-side-col .feat-side .feat-ic .feat-img[src*="feat-croix"]   { transform: translateX(28px); }
  .feat-side-col .feat-side .feat-ic .feat-img[src*="feat-anneaux"] { transform: translateX(22px); }
  .feat-side-col .feat-side .feat-ic .feat-img[src*="feat-lieu"]    { transform: translateX(13px); }
  .feat-side h3 { grid-area: title; margin: 0; }
  .feat-side p { grid-area: text; margin-top: 12px; }
}

/* --- Accueil : prévisualisation de profils au-dessus de « Un profil par jour » --- */
.pp-row { display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; margin-bottom: 26px; }
.pp-card { width: 300px; max-width: 100%; background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); text-align: left; }
.pp-photo-wrap { position: relative; }
.pp-photo { aspect-ratio: 4 / 5; background-size: cover; background-position: center 22%; }
.pp-photo-empty { display: flex; align-items: center; justify-content: center; background: linear-gradient(160deg, var(--secondary), var(--muted)); }
.pp-photo-empty span { font-family: "Cormorant Garamond", Georgia, serif; font-size: 4rem; font-weight: 600; color: var(--primary); opacity: .5; }
.pp-tag { position: absolute; top: 12px; left: 12px; background: rgba(255,255,255,.92); color: var(--primary); font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 5px 11px; border-radius: 99px; box-shadow: 0 3px 10px rgba(16,32,39,.14); }
.pp-body { padding: 16px 18px 18px; }
.pp-name { font-size: 1.28rem; margin: 0 0 1px; color: var(--card-foreground); }
.pp-loc { color: var(--muted-foreground); margin: 0 0 12px; font-size: .92rem; }
.pp-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.pp-badges .badge { font-size: .72rem; padding: 4px 10px; }
.pp-mot { margin: 0; font-size: .92rem; line-height: 1.5; color: var(--card-foreground); }

/* Icônes en image (illustrations à fond transparent) : posées directement, sans tuile.
   Alignées à droite sur leur propre ligne ; le texte reste en dessous, pleine largeur (pas de contournement).
   ⚠️ On cible `.feat-side .feat-ic` en DUR (pas `.feat-ic:has(.feat-img)`) : `:has()` n'existe qu'à partir
   de Chromium 105, et certains navigateurs de téléphones (ex. navigateur Honor) sont plus anciens → les règles
   :has() y étaient ignorées (pastille dégradée réapparue + icône non alignée). `.feat-ic` n'est utilisé QUE dans
   les cartes `.feat-side`, donc le ciblage direct est équivalent et fonctionne partout. */
.feat-side .feat-ic { display: flex; align-items: center; justify-content: flex-end; width: auto; height: auto; padding: 0; background: transparent; border: 0; border-radius: 0; margin-left: auto; margin-right: 0; }
.feat-img { display: block; width: 82px; height: 82px; object-fit: contain; }
/* L'icône est en haut à droite : on remonte le titre à côté d'elle pour resserrer la carte. */
.feat-side .feat-ic { margin-bottom: -34px; }
/* Image collée dans le coin haut-droit via transform (hors flux visuel seulement :
   le texte, lui, garde exactement sa position). */
.feat-side .feat-ic .feat-img { transform: translate(13px, -14px); }

/* --- Accueil : « Un profil par jour » en bloc large, avec les 2 aperçus de profils à côté --- */
.feat-wrap { display: flex; flex-direction: column; gap: 18px; }
.feat-lead--wide { display: grid; grid-template-columns: minmax(220px, .82fr) auto; gap: 34px; align-items: center; padding: 38px 40px; }
.feat-lead-copy .feat-ic { margin-bottom: 20px; }
.feat-lead-copy h3 { font-size: 1.85rem; line-height: 1.2; margin-bottom: 10px; }
.feat-lead-copy p { font-size: 1.04rem; line-height: 1.6; margin: 0; }
.pp-row--in { margin: 0; gap: 16px; flex-wrap: nowrap; }
.pp-row--in .pp-card { width: 234px; box-shadow: var(--shadow-sm); }
.feat-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 980px) {
  .feat-lead--wide { grid-template-columns: 1fr; gap: 24px; }
  .pp-row--in { flex-wrap: wrap; justify-content: center; }
}
@media (max-width: 600px) {
  .feat-sides { grid-template-columns: 1fr; }
  .pp-row--in .pp-card { width: 100%; max-width: 300px; }
}

/* --- Accueil : carrousel d'aperçu (une fiche visible, swipe) --- */
/* `overflow-x: clip` sur le carrousel : si le `.pp-track` (scroll interne) déborde sur un moteur qui
   ne le confine pas, le débordement est coupé ici et n'atteint pas la page. `clip` ne crée pas de
   conteneur de défilement → le swipe du `.pp-track` (overflow-x:auto) reste intact. */
.pp-carousel { position: relative; width: 288px; max-width: 100%; margin: 0 auto; overflow-x: clip; }
.pp-track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; border-radius: var(--radius); }
.pp-track::-webkit-scrollbar { display: none; }
.pp-track > .pp-card { flex: 0 0 100%; scroll-snap-align: center; width: auto; }
.pp-dots { display: flex; justify-content: center; gap: 7px; margin-top: 13px; }
.pp-dots span { width: 7px; height: 7px; border-radius: 99px; background: var(--hairline); cursor: pointer; transition: width .2s ease, background .2s ease; }
.pp-dots span.active { width: 20px; background: var(--primary); }
.pp-arrow { position: absolute; top: 36%; transform: translateY(-50%); z-index: 2; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; padding: 0 0 3px; border: 1px solid rgba(255,255,255,.45); border-radius: 999px; background: rgba(16,32,43,.4); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); color: #fff; cursor: pointer; font-size: 1.5rem; line-height: 1; }
.pp-arrow-prev { left: 8px; }
.pp-arrow-next { right: 8px; }
.pp-arrow[hidden] { display: none; }
/* Prénoms plus petits — .pp-card .pp-name (0,2,0) pour battre « .feat-lead h3 » (0,1,1). */
.pp-card .pp-name { font-size: 1.05rem; line-height: 1.25; }

/* --- Accueil : carte profil compacte (photo + prénom + ville) au-dessus du titre du bloc lead --- */
/* Centrage du carrousel dans le bloc lead (flex colonne). On centre via `align-self: center`
   (flex natif, supporté partout) et NON via `margin: 0 auto` : certains moteurs de téléphones
   (ex. navigateur Honor) gèrent mal les marges auto dans un conteneur flex → carte décentrée. */
.feat-lead .pp-carousel { margin: 0 0 24px; align-self: center; }
.pp-card--compact .pp-photo { aspect-ratio: 1 / 1; }
.pp-card--compact .pp-photo-empty span { font-size: 3rem; }
.pp-card--compact .pp-body { padding: 13px 18px 15px; text-align: center; }
.pp-card--compact .pp-loc { margin: 0; }

/* --- Fiche admin : crayon « éditer » (à gauche de l'œil) + modale de correction manuelle --- */
.mod-titlerow-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.edit-modal .like-modal-inner { max-width: 540px; max-height: 90vh; overflow-y: auto; text-align: left; }
.edit-form { text-align: left; }
.edit-field { display: block; margin: 14px 0 0; text-align: left; }
.edit-field > span { display: block; font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted-foreground); margin-bottom: 5px; }
.edit-field input, .edit-field select, .edit-field textarea { width: 100%; padding: 10px 12px; font: inherit; color: inherit; border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-sizing: border-box; }
.edit-field textarea { resize: vertical; }
/* Attache non reconnue (saisie libre) : champ surligné ambre + note explicative. */
.edit-field.is-manual input { border-color: #d98a1f; background: #fff8ec; box-shadow: 0 0 0 3px rgba(217, 138, 31, .14); }
.origin-manual-note { display: block; margin-top: 7px; font-size: .8rem; line-height: 1.45; color: #a56511; }
.origin-manual-note[hidden] { display: none; }
.edit-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* Bloc localisation adaptatif de la modale de correction : conteneur relatif pour le dropdown de suggestions ;
   en mode hors-France la ville prend toute la largeur (le code postal est masqué). */
.edit-geo { position: relative; }
.edit-geo-grid.is-intl { grid-template-columns: 1fr; }
.edit-subhead { margin: 22px 0 2px; font-weight: 700; color: var(--primary); border-top: 1px solid var(--border); padding-top: 16px; }
.edit-form .btn-block { margin-top: 22px; }
@media (max-width: 560px) { .edit-grid2 { grid-template-columns: 1fr; } }
/* Date de naissance en 3 menus Jour / Mois / Année (inscription + fiche admin) */
.birth-selects { display: flex; gap: 8px; }
.birth-selects select { flex: 1 1 0; min-width: 0; width: auto; margin-top: 0; }
.birth-caption { display: block; font-weight: 600; font-size: .92rem; margin-bottom: 6px; }

/* --- Accueil (refonte « Comment ça marche / Un espace de confiance ») : parcours + carte de confiance --- */
.how-grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: 60px; align-items: start; }
.how-journey .eyebrow, .trust-card .eyebrow { text-align: left; }
.how-journey h2 { text-align: left; font-size: clamp(1.6rem, 3vw, 2.05rem); margin-bottom: 4px; }
/* Parcours en timeline connectée */
.journey { list-style: none; margin: 28px 0 0; padding: 0; }
.journey-step { position: relative; display: grid; grid-template-columns: 46px 1fr; gap: 22px; padding-bottom: 34px; }
.journey-step:last-child { padding-bottom: 0; }
.journey-step::before { content: ''; position: absolute; left: 22px; top: 54px; bottom: -2px; width: 2px; background: linear-gradient(rgba(176,138,79,.55), rgba(176,138,79,.12)); }
.journey-step:last-child::before { display: none; }
/* Pastille « médaillon » : dégradé marial + fin liseré doré + chiffre serif crème. */
.journey-badge { position: relative; z-index: 1; width: 46px; height: 46px; border-radius: 999px; display: flex; align-items: center; justify-content: center; font-family: var(--font-round); font-size: 1.2rem; font-weight: 800; line-height: 1; text-align: center; letter-spacing: 0; color: #f4e9d2; background: linear-gradient(155deg, #33578c, #1a2f4c); box-shadow: 0 0 0 1.5px rgba(176,138,79,.5), inset 0 1px 1px rgba(255,255,255,.18), 0 7px 18px rgba(34,62,99,.28); }
.journey-body { padding-top: 3px; }
.journey-body strong { display: block; color: var(--foreground); font-size: 1.08rem; margin-bottom: 3px; }
.journey-body span { display: block; color: var(--muted-foreground); line-height: 1.6; }
/* Carte de confiance distincte, image de sécurité en haut à droite (sans contour) */
.trust-card { position: sticky; top: 100px; background: var(--card); border: 1px solid var(--border); border-radius: 22px; padding: 32px 30px; box-shadow: 0 20px 46px rgba(34,62,99,.10); }
.trust-badge-img { position: absolute; top: 22px; right: 22px; width: 72px; height: 72px; object-fit: contain; pointer-events: none; }
@media (max-width: 600px) { .trust-badge-img { width: 54px; height: 54px; top: 18px; right: 18px; } }
/* On aère l'eyebrow de la carte (gap au-dessus + en-dessous) : ça descend le titre juste ce qu'il faut pour dégager le bouclier. */
.trust-card .eyebrow { margin-top: 26px; margin-bottom: 34px; color: #243e62; }
.trust-title { text-align: left; font-size: 1.5rem; margin-bottom: 22px; }
.trust-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 15px; }
.trust-list li { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: start; font-weight: 500; line-height: 1.45; color: var(--foreground); }
.trust-check { display: inline-flex; color: var(--success); margin-top: 1px; }
@media (max-width: 860px) {
  .how-grid { grid-template-columns: 1fr; gap: 40px; }
  .trust-card { position: relative; top: auto; } /* relative (pas static) : garde le contexte pour l'image en absolu */
}

/* Section « réseau de prière » (accueil) : texte + visuel du réseau d'avatars reliés par la prière. */
/* Fonds de la zone claire de l'accueil : progression monotone (clair → crème chaud vers la FAQ) avec un fondu
   TRÈS RESSERRÉ aux jointures (~8 px en haut/bas de chaque section, en px → indépendant de la hauteur) → joint
   doux mais visible, sans rupture franche. Le bas de chacune = le haut de la suivante (moyenne) → raccord
   invisible. Le hero et le cta-band restent des blocs contrastés voulus. */
#pourquoi { background: linear-gradient(180deg, #FBFAF6 0%, #FBFAF6 calc(100% - 8px), #F9F6F0 100%); }
#comment { background: linear-gradient(180deg, #F9F6F0 0, #F7F2E9 8px, #F7F2E9 calc(100% - 8px), #F5EFE4 100%); }
#reseau-priere { background: linear-gradient(180deg, #F5EFE4 0, #F2ECDF 8px, #F2ECDF calc(100% - 8px), #F0EADB 100%); }
#faq { background: linear-gradient(180deg, #F0EADB 0, #EEE7D6 8px, #EEE7D6 100%); }
.pray-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 52px; align-items: center; }
.pray-copy .eyebrow { margin-bottom: 12px; }
.pray-copy h2 { margin-bottom: 16px; }
.pray-copy p:not(.eyebrow) { font-size: 1.05rem; line-height: 1.66; margin: 0 0 14px; }
.pray-copy p:last-child { margin-bottom: 0; }
.pray-visual { display: flex; justify-content: center; }
.pray-visual img { width: 100%; max-width: 540px; height: auto; }
@media (max-width: 860px) {
  .pray-grid { grid-template-columns: 1fr; gap: 26px; }
  .pray-visual { order: 1; } /* mobile : l'image passe SOUS le texte (desktop inchangé) */
  .pray-visual img { max-width: 430px; }
}

/* Comptes : repère « recréé » sur un compte actif dont l'adresse avait été supprimée puis ré-inscrite. */
.acct-recreated {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: #8a6d3b;
  background: rgba(176, 138, 79, .14);
  border: 1px solid rgba(176, 138, 79, .30);
  vertical-align: middle;
  white-space: nowrap;
}

/* Modération : deux files distinctes — « Profils à valider » (relecture complète) vs « Photos à valider » (photo seule). */
.mod-section { margin-bottom: 30px; }
.mod-section:last-child { margin-bottom: 0; }
.mod-section-head { display: flex; align-items: center; gap: 10px; margin: 0 0 3px; }
.mod-section-title { font-size: 1.12rem; margin: 0; }
.mod-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 22px; padding: 0 8px; border-radius: 999px;
  background: var(--primary); color: #fff; font-size: .78rem; font-weight: 700;
}
.mod-section-hint { color: var(--muted-foreground); font-size: .88rem; margin: 0 0 12px; max-width: 640px; }
/* Fiche de modération : rappel « seule la photo est à vérifier » sur un profil déjà publié. */
.mod-photo-only {
  background: rgba(176, 138, 79, .12); border: 1px solid rgba(176, 138, 79, .30);
  color: #6b4f22; border-radius: 12px; padding: 10px 13px; margin: 0 0 14px;
  font-size: .9rem; line-height: 1.45;
}
.mod-photo-only strong { color: #5a4118; }

/* Repli sans JavaScript du curseur de distance (étape Préférences) : un <select> dans <noscript>. */
.distance-fallback { display: block; margin: 8px 0 4px; font-weight: 600; }
.distance-fallback select { display: block; width: 100%; margin-top: 6px; padding: 10px 12px; }

/* Réglages → lien-outil « Parcourir les profils » */
/* Les quatre raccourcis des Réglages, en grille : ils remplacent le menu de gauche pour ces pages.
   `margin: 0` sur les cartes — c'est la grille qui espace, sinon les 20px de marge basse d'origine
   s'ajoutaient au gap et décalaient les rangées. */
.settings-tools { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 4px 0 22px; }
.settings-tools .settings-tool-link { margin: 0; }
@media (max-width: 700px) { .settings-tools { grid-template-columns: 1fr; } }
.settings-tool-link { display: flex; align-items: center; gap: 14px; padding: 15px 18px; margin: 4px 0 20px; background: var(--card); border: 1px solid var(--hairline); border-radius: 14px; text-decoration: none; color: var(--foreground); box-shadow: 0 1px 3px rgba(16,32,43,.05); transition: border-color .12s, box-shadow .12s; }
.settings-tool-link:hover { border-color: var(--primary); box-shadow: 0 6px 20px rgba(34,62,99,.12); }
.settings-tool-ic { font-size: 1.5rem; flex-shrink: 0; }
.settings-tool-txt { display: flex; flex-direction: column; gap: 2px; }
.settings-tool-txt strong { font-size: 1.02rem; }
.settings-tool-arrow { margin-left: auto; font-size: 1.3rem; color: var(--primary); flex-shrink: 0; }

/* Parcours des profils : navigation + dossier lecture seule */
.browse-nav { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 0 0 18px; flex-wrap: wrap; }
.browse-count { font-weight: 800; color: var(--primary); font-size: 1.02rem; min-width: 120px; text-align: center; }
.btn.is-disabled { opacity: .4; pointer-events: none; }
.browse-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.browse-dossier .practice-step { cursor: default; }
.browse-dossier .practice-step:hover { background: var(--muted); }
.browse-dossier .practice-step.is-active:hover { background: var(--primary); }

/* ---- Comptes d'accès (Réglages) : rôles + rangées harmonisées ---- */
/* .settings-card est en display:grid → sans min-width:0, .mgr-list (item de grille, min-width:auto)
   refuse de rétrécir sous la largeur de son contenu et DÉBORDE de la carte à droite. */
.mgr-list, .mgr-row, .mgr-info { min-width: 0; }
/* Rangée : e-mail + badges à gauche (2 lignes), actions alignées à droite, tailles unifiées. */
.mgr-row { align-items: center; }
.mgr-info { flex: 1 1 220px; flex-direction: column; align-items: flex-start; gap: 5px; }
.mgr-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mgr-role { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; border-radius: 999px; padding: 3px 9px; white-space: nowrap; }
.mgr-role-admin { background: var(--primary); color: #fff; }
.mgr-role-manager { background: #E7EEF4; color: var(--primary); }
.mgr-role-moderator { background: var(--muted); color: var(--muted-foreground); }
/* Boutons d'action : même hauteur (32 px), icône + libellé, écarts réguliers. */
.mgr-actions { flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.mgr-actions .btn { height: 32px; padding: 0 13px; gap: 6px; font-size: .82rem; white-space: nowrap; }
.mgr-actions .btn svg { flex-shrink: 0; }
/* Historique / Supprimer : boutons-icônes carrés (le libellé vit dans title + aria-label). */
.mgr-ic-btn { width: 32px; min-width: 32px; padding: 0; }
.mgr-ic-btn svg { width: 15px; height: 15px; }
.mgr-role-edit { display: inline-flex; align-items: center; gap: 8px; }
.mgr-role-select {
  height: 32px; padding: 0 28px 0 12px; border: 1px solid var(--hairline); border-radius: 999px;
  font: inherit; font-size: .82rem; font-weight: 600; color: var(--primary); background-color: var(--card);
  -webkit-appearance: none; -moz-appearance: none; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%236B7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 8px;
}
.mgr-role-select:hover { background-color: var(--muted); }
/* Séparateur discret + section « Créer un compte » repliable (<details> natif, fermée par défaut). */
.settings-sep { border: 0; border-top: 1px solid var(--hairline); margin: 16px 0 14px; }
.mgr-create { margin: 0; }
.mgr-create > summary {
  list-style: none; display: flex; align-items: center; gap: 9px; height: 42px; padding: 0 14px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--card);
  font-weight: 600; font-size: .92rem; color: var(--primary);
  cursor: pointer; user-select: none; transition: background .2s ease, border-color .2s ease;
}
.mgr-create > summary:hover { background: var(--muted); }
.mgr-create > summary::-webkit-details-marker { display: none; }
.mgr-create > summary::marker { content: ""; }
.mgr-create > summary svg { flex-shrink: 0; }
.mgr-create-chev { margin-left: auto; display: inline-flex; color: var(--muted-foreground); transition: transform .2s ease; }
.mgr-create[open] .mgr-create-chev { transform: rotate(180deg); }
.mgr-create-body { padding-top: 14px; }
.mgr-create-fields { display: grid; gap: 12px; margin-bottom: 14px; }
.mgr-create-actions { margin-top: 0; }
.mgr-create-actions .btn { gap: 7px; }
/* Le <select> du formulaire de création s'habille comme les inputs (un <select> natif a pour largeur
   intrinsèque sa plus longue <option>, non rétrécissable → width:100% obligatoire contre le débordement). */
.settings-form .field select {
  width: 100%; max-width: 100%; padding: 11px 38px 11px 14px; font: inherit; font-weight: 400;
  color: var(--foreground); background-color: var(--background);
  border: 1px solid var(--border); border-radius: 10px;
  -webkit-appearance: none; -moz-appearance: none; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%236B7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; background-size: 12px 8px;
  text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
}
.settings-form .field select:focus { outline: 2px solid var(--primary); outline-offset: 1px; border-color: var(--primary); }

/* Envoi groupé : adresse de test personnalisable à côté du bouton « Recevoir un test ». */
.bulk-test-wrap { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.bulk-test-to { width: 210px; max-width: 40vw; padding: 8px 12px; font: inherit; font-size: .85rem; border: 1px solid var(--hairline); border-radius: 999px; background: var(--card); }

/* Doublons d'e-mails : correction d'adresse inline (fantômes) */
.dup-fix { display: flex; align-items: center; gap: 6px; margin-top: 7px; flex-wrap: wrap; }
.dup-fix input[type="email"] { flex: 1 1 210px; max-width: 300px; padding: 6px 10px; font: inherit; font-size: .85rem; border: 1px solid var(--border); border-radius: 8px; background: var(--background); }

/* --- Page de don (/don) : formulaire montant libre + bouton du popup (v666) --- */
.don-form { margin: 14px 0 6px; }
.don-form-libre { margin-top: 0; }   /* 2e formulaire (montant libre) : pas de double écart */
.don-presets { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; }
.don-presets .btn { flex: 1 1 90px; min-width: 0; }
.don-libre { display: flex; gap: 10px; align-items: stretch; }
.don-libre input { flex: 1 1 auto; min-width: 0; border: 1px solid var(--hairline); border-radius: 12px; padding: 12px 14px; font: inherit; background: var(--card, #fff); }
.don-libre .btn { flex: 0 0 auto; }
.don-hint { font-size: .88rem; color: var(--muted-foreground); margin-top: 10px; }
.don-note-ok { border-color: #2e7d5b; }
.del-step .don-cta { margin: 4px 0 14px; }
@media (max-width: 420px) { .don-libre { flex-direction: column; } }

/* --- Carte « Débloquer mon profil du jour » : avatar du sexe opposé (v673) --- */
.unlock-avatar { width: 112px; height: 112px; border-radius: 50%; display: block; margin: 0 auto 14px; }

/* --- Bandeau « t'a envoyé un mot » sur la fiche du jour (v677) --- */

/* --- En-tête de la fiche du jour : 2 ou 3 bulles sur mobile étroit (v682) --- */
@media (max-width: 420px) {
  .today-head { flex-wrap: wrap; row-gap: 6px; }
  .today-head .today-count { font-size: .78rem; padding: 4px 11px; }
}

/* --- Écran « aucun profil aujourd'hui » (v688) --- */
.empty-day { padding-top: 30px; padding-bottom: 26px; margin-top: 18px; }   /* la carte ne colle plus au haut de l'écran */
.empty-avatar { width: 104px; height: 104px; border-radius: 50%; display: block; margin: 0 auto 18px; }
.empty-day h1 { font-size: 1.42rem; line-height: 1.25; margin: 0 0 10px; }
.empty-lead { color: var(--muted-foreground); margin: 0 auto 20px; max-width: 30ch; }
.empty-note { background: var(--muted); border-radius: 14px; padding: 16px 18px; text-align: left;
  font-size: .93rem; line-height: 1.6; color: var(--foreground); margin: 0 0 22px; }
.empty-note-link { display: block; margin: 12px 0; font-weight: 600; }

/* --- Alerte « préviens-moi dès qu'un profil correspond » (v689) --- */
.empty-alert-form { margin: 0 0 18px; }
.empty-alert { display: flex; gap: 11px; text-align: left; background: #eef6f0; border: 1px solid #cfe6d8;
  border-radius: 14px; padding: 14px 16px; margin: 0 0 18px; font-size: .92rem; line-height: 1.5; }
.empty-alert-ic { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; background: #2e7d5b; color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: .8rem; font-weight: 700; }
.empty-alert-off { background: none; border: 0; padding: 0; margin-top: 6px; font: inherit; font-size: .85rem;
  color: var(--muted-foreground); text-decoration: underline; cursor: pointer; }
/* Dernier recours de l'écran « aucun profil » : revoir quelqu'un qu'on avait passé. Même bouton que les
   deux du dessus (btn-outline pleine largeur), simplement placé après la ligne du périmètre. */
.empty-revoir { margin: 0; }


/* --- Comptes : la recherche « dans les profils » a fusionné avec la recherche principale (v711).
   Le champ unique reprend la largeur des deux, tout en restant borné sur petit écran (max-width: 46vw). --- */
.accounts-search input { width: 320px; }

/* --- Tableau de bord : matchs du jour et messages échangés (v704) --- */
.dash-matches { margin: 4px 0 26px; }
.dash-matches .pie-title { margin: 0 0 12px; }
.dash-matches-empty { margin: 2px 0 26px; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   GLISSER-DÉPOSER LISIBLE — « ce qu'on saisit, là où on relâche » (demande de Gabriel, 16/08)
   Deux repères, jamais confondus :
     · .plv-drag-ghost — la copie qui suit le doigt : CE QU'ON TIENT. Soulevée (échelle + ombre
       portée + légère inclinaison) pour se détacher nettement de la grille restée à plat.
     · .dragging — la vignette d'origine, laissée dans le flux : LÀ OÙ ÇA RETOMBERA. Creusée en
       pointillés, son contenu effacé (il est déjà dans le fantôme).
   Vaut pour les deux grilles qui utilisent plvReordonnable : les photos du membre (.gal-item)
   et celles de la modération (.mod-photo).
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
.plv-drag-ghost {
  position: fixed; z-index: 1200; margin: 0;
  pointer-events: none;            /* ⚠️ sinon elementFromPoint ne verrait que lui : plus aucun classement */
  border-radius: 12px; overflow: hidden;
  box-shadow: 0 16px 34px rgba(16, 32, 39, .34), 0 2px 6px rgba(16, 32, 39, .18);
  transform: scale(1.06) rotate(-1.6deg);
  transition: none;                /* il suit le doigt : toute transition le mettrait en retard */
  opacity: .97;
}
.plv-drag-ghost img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* La poignée et les boutons n'ont plus de sens sur une copie inerte. */
.plv-drag-ghost .gal-drag, .plv-drag-ghost button, .plv-drag-ghost a { display: none; }

.pf-gallery .gal-item.dragging, .mod-photo.dragging {
  outline: 2px dashed var(--primary); outline-offset: -2px;
  background: color-mix(in srgb, var(--primary) 9%, transparent);
}
/* Contenu effacé — mais l'élément garde sa taille, donc la grille ne saute pas. */
.pf-gallery .gal-item.dragging > *, .mod-photo.dragging > * { opacity: 0; }

/* Pendant le geste : pas de sélection de texte parasite, et le curseur reste cohérent partout. */
body.plv-dragging { user-select: none; -webkit-user-select: none; cursor: grabbing; }

@media (prefers-reduced-motion: reduce) {
  .plv-drag-ghost { transform: none; }
}

/* ═══ Ordre fixé à la main — bandeau en tête du popup « Classement de compatibilité » ═══════
   Un ordre posé au glisser-déposer prime sur l'algorithme, indéfiniment et sans le dire. Le
   bandeau le rend visible, et offre la seule façon de le défaire. Teinte ambre : c'est un état
   à connaître, pas une erreur — d'où ni rouge ni vert. */
.rank-manual { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 12px 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent); }
.rank-manual-txt { flex: 1 1 260px; min-width: 0; font-size: .9rem; line-height: 1.45; color: var(--foreground); }
.rank-manual-txt strong { display: block; }
.rank-manual-txt span { color: var(--muted-foreground); }
.rank-manual-btn { flex: 0 0 auto; padding: 8px 14px; border-radius: 999px; cursor: pointer;
  font-size: .86rem; font-weight: 700; color: #fff; background: var(--accent); border: 0; }
.rank-manual-btn:hover { filter: brightness(.94); }
.rank-manual-btn[disabled] { opacity: .6; cursor: default; }

/* Bonus épinglé par l'admin (« Classement de compatibilité »). Un simple volet : le bouton n'existe
   que s'il y a quelqu'un à proposer — sans candidat, aucun bloc n'est rendu du tout. */
.rank-bonus { margin-top: 12px; border: 1px solid var(--border); border-radius: 13px;
  background: var(--card); padding: 10px 12px; }
.rank-bonus[open] { border-color: var(--accent); }
.rank-bonus-sum { cursor: pointer; list-style: none; font-size: .9rem; font-weight: 700;
  color: var(--primary); }
.rank-bonus-sum::-webkit-details-marker { display: none; }
.rank-bonus-sum:hover { text-decoration: underline; }
.rank-bonus[open] .rank-bonus-sum { color: var(--foreground); font-weight: 600; }
.rank-bonus[open] .rank-bonus-sum strong { color: var(--accent); }
.rank-bonus-body { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.rank-bonus-sel { flex: 1 1 200px; min-width: 0; padding: 8px 10px; font: inherit; font-size: .88rem;
  color: inherit; border: 1px solid var(--border); border-radius: 10px; background: var(--card); }
.rank-bonus-btn { flex: 0 0 auto; padding: 8px 14px; border-radius: 999px; cursor: pointer;
  font-size: .82rem; font-weight: 700; color: #fff; background: var(--primary); border: 0; white-space: nowrap; }
.rank-bonus-btn:hover { filter: brightness(.94); }
.rank-bonus-btn.is-off { background: transparent; color: var(--muted-foreground); border: 1px solid var(--border); }
.rank-bonus-btn[disabled] { opacity: .6; cursor: default; }
.rank-manual .rank-order-err { flex: 1 1 100%; margin: 6px 0 0; }

/* Popup « Historique des modérations » — les décisions déjà prises, la plus récente en tête.
   Réutilise .admin-head (déjà défini plus haut) pour le bouton en tête de page. */
.modhist-modal-inner { max-width: 860px; width: min(94vw, 860px); }
.modhist-modal-inner h2 { margin: 0 0 14px; }
.modhist-modal-inner [data-modhist-body] { max-height: 68vh; overflow-y: auto; }
/* Le bouton porte `btn btn-outline btn-sm` : fond, bordure, rayon et alignement en viennent.
   Ne reste ici que ce qui lui est propre : l'écart entre l'icône et le libellé, et le refus
   de passer à la ligne (le libellé est long et l'en-tête est étroit sur petit écran). */
.modhist-btn { gap: 8px; white-space: nowrap; }

/* Filtre « pays » de la file de modération. Un <details> natif : la CSP interdit les gestionnaires
   en ligne, et le navigateur sait déjà ouvrir, fermer et parcourir ce composant au clavier.
   Même langage visuel que le sélecteur de pays de l'inscription (.geo-cflag), sans son câblage JS. */
/* Les actions d'en-tête voyagent ensemble : .admin-head répartit ses enfants avec `space-between`, si
   bien que deux boutons posés séparément se retrouvaient à 300 px l'un de l'autre, le titre les
   poussant chacun vers un bord. Ce groupe les garde adjacents, à droite. */
.admin-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.modc { position: relative; flex-shrink: 0; }
.modc > summary { list-style: none; cursor: pointer; }
.modc > summary::-webkit-details-marker { display: none; }
.modc-btn { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
/* Le chevron dit que ça s'ouvre, et pivote quand c'est ouvert : sans lui, un bouton qui déplie ne
   se distingue pas d'un bouton qui agit. */
.modc-btn::after { content: ''; width: 7px; height: 7px; border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor; transform: rotate(45deg) translate(-1px, -1px); opacity: .55; }
.modc[open] > .modc-btn::after { transform: rotate(-135deg) translate(-1px, -1px); }
.modc-btn-flag { font-size: 15px; line-height: 1; }
.modc-panel { position: absolute; z-index: 30; top: calc(100% + 6px); right: 0; min-width: 230px;
  background: #fff; border: 1px solid var(--hairline, #E3E7EC); border-radius: 12px;
  box-shadow: 0 14px 34px rgba(16,32,43,.16); padding: 6px; max-height: 320px; overflow-y: auto; }
.modc-opt { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 8px;
  font-size: .92rem; color: var(--foreground, #16202B); text-decoration: none; }
.modc-opt:hover { background: var(--muted, #F3F5F8); }
.modc-opt.is-active { background: var(--muted, #F3F5F8); font-weight: 600; }
.modc-opt-flag { font-size: 16px; line-height: 1; }
/* Le nom pousse le compteur à droite : la colonne de chiffres reste alignée quelle que soit la
   longueur du pays, ce qui permet de lire « où est le travail » d'un seul coup d'œil. */
.modc-opt-nom { flex: 1 1 auto; }
.modc-opt-n { flex: 0 0 auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .82rem; color: var(--muted-foreground, #667085); font-variant-numeric: tabular-nums; }
/* Sous 600 px l'en-tête passe en colonne (voir .admin-head) : le panneau s'aligne alors à gauche,
   sinon il sortirait de l'écran par la droite. */
@media (max-width: 600px) { .modc-panel { right: auto; left: 0; } }
.modhist-table { font-size: .92rem; }
.modhist-table td { vertical-align: top; }
.modhist-when { white-space: nowrap; color: var(--muted-foreground); }
.modhist-detail { display: block; margin-top: 3px; font-weight: 400; color: var(--muted-foreground); font-size: .88rem; line-height: 1.4; }
.modhist-note { margin: 12px 2px 0; font-size: .85rem; }


/* --- Seconde chance (v804) : quelqu'un que le membre avait écarté s'est déclaré depuis --- */
/* Le rose du logo, en touche : cette carte est une bonne nouvelle, pas une alerte. Elle ne doit pas
   non plus crier plus fort que la prière au-dessus d'elle — d'où le fond doux et la bordure fine. */
.seconde-chance { background: transparent; border: 1px solid var(--hairline); border-radius: 18px;
  padding: 22px 20px; margin-top: 18px; text-align: center; }
.seconde-chance .state-emoji { margin-bottom: 6px; }
.sc-lead { font-weight: 700; color: var(--primary); margin: 0 0 16px; line-height: 1.45; }
/* La mise en garde est due, mais elle ne doit pas dissuader : discrète, jamais rouge. */
.sc-note { font-size: .86rem; color: var(--muted-foreground); margin: 14px 0 0; }
.seconde-chance form { margin: 0; }
/* Sur l'écran « aucun profil », l'invitation prend la place du rappel à l'aveugle : elle vient donc
   déjà dans un conteneur, sans la carte blanche. */
.sc-bouton { margin: 0; }
/* Le bonus de la page de fin de journée : un petit bouton qui déplie la carte. `<details>` natif —
   la flèche par défaut est retirée sur les deux moteurs (list-style pour Firefox, le pseudo-élément
   pour WebKit), sinon elle s'ajoute au libellé. */
.sc-bonus { margin-top: 18px; }
.sc-bonus > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 18px; border-radius: 999px; border: 1px solid var(--hairline); background: transparent;
  color: var(--primary); font-weight: 650; font-size: .95rem; }
.sc-bonus > summary::-webkit-details-marker { display: none; }
.sc-bonus > summary::marker { content: ""; }
.sc-bonus > summary:hover { background: var(--muted); }
.sc-bonus > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.sc-bonus[open] > summary { margin-bottom: 14px; }
/* Le chevron pointe vers le bas (« il y a quelque chose dessous ») et se retourne à l'ouverture,
   comme celui de « Voir tout le profil ». */
.sc-bonus-chev { flex: 0 0 auto; transition: transform .18s ease; }
.sc-bonus[open] > summary .sc-bonus-chev { transform: rotate(180deg); }
.sc-bonus .seconde-chance { margin-top: 0; }

/* Paiements — les deux accès directs de chaque ligne (fiche du membre, sélection livrée).
   ⚠️ Colonne étroite : `width:1%` + `nowrap` la réduisent à leur contenu, sinon le tableau lui
   donnerait une part égale et écraserait la colonne Client.
   ⚠️ Jetons réels de cette palette (--card, --border, --primary…) : `--surface`, `--surface-2` et
   `--ink-soft` n'existent pas ici, et une couleur qui ne résout pas est simplement ignorée —
   l'icône serait restée sans style, sans la moindre erreur pour le signaler. */
.admin-table td.pay-actions { width: 1%; white-space: nowrap; text-align: right; }
.pay-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin-left: 6px; padding: 0;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--card); color: var(--primary);
  cursor: pointer; text-decoration: none;
  transition: background .15s, color .15s, border-color .15s;
}
.pay-ic:hover { background: var(--secondary); border-color: var(--primary); }
.pay-ic:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Contrôle de facturation (page Paiements) — un bandeau sobre quand tout va bien, une alerte sinon.
   ⚠️ La version verte doit rester DISCRÈTE : elle s'affiche à chaque visite, elle ne doit pas prendre
   la place des chiffres. La version rouge, elle, doit se voir immédiatement. */
.pay-check { margin: 4px 0 18px; padding: 12px 16px; font-size: .93rem; border-left: 3px solid transparent; }
.pay-check-ok { color: var(--muted, #64748B); border-left-color: #2E8F6B; }
.pay-check-ok strong { color: #2E8F6B; }
.pay-check-alerte { border-left-color: #C0392B; }
.pay-check-alerte strong { color: #C0392B; }
.pay-check-alerte .admin-table { margin-top: 4px; }
.pay-check-alerte .ph-tag { margin-left: 6px; }

/* Comptes : les dates ne se cassent jamais sur deux lignes — la carte défile horizontalement quand
   il le faut (règle .card:has(> .admin-table) ci-dessus), une date pliée ne fait gagner que du
   désordre. Idem pour l'en-tête « Dernière connexion ». */
body.admin-shell td.acct-date { white-space: nowrap; }

/* Comptes : la table doit tenir SANS défilement sur un écran ordinaire (~1512 logiques). Deux
   resserrements, scopés à CETTE table (.acct-table — .admin-table est partagée par tout l'admin) :
   marges internes 12→8 px (dix colonnes : ~80 px rendus), et colonne e-mail plafonnée — le surplus
   partait s'y loger en espace mort, et les adresses très longues forçaient le défilement. L'adresse
   complète reste lisible au survol (title posé sur la cellule). */
body.admin-shell .acct-table th, body.admin-shell .acct-table td { padding-left: 8px; padding-right: 8px; }
/* v855 : l'ellipse vit dans .acct-mailtxt (le TEXTE de l'adresse), plus dans la cellule — sinon le
   badge « recréé », placé après l'adresse, disparaissait en premier sous la troncature : l'admin
   perdait une information de sécurité. Le badge est hors du texte clippé et ne rétrécit jamais. */
body.admin-shell td.acct-email { max-width: 250px; overflow: hidden; white-space: nowrap; }
body.admin-shell td.acct-email .acct-mailwrap { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; vertical-align: middle; }
body.admin-shell td.acct-email .acct-mailtxt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
body.admin-shell td.acct-email .acct-mailwrap > *:not(.acct-mailtxt) { flex-shrink: 0; }


/* v856 — bandeau « compte à la corbeille » en tête de fiche membre. La fiche ne signalait NULLE PART
   qu'un compte était supprimé : on pouvait le valider sans le savoir, ce qui le remettait dans le vivier. */
body.admin-shell .trash-banner { margin: 0 0 14px; padding: 12px 14px; border: 1px solid #E7C9C4; border-left: 4px solid #C0392B; border-radius: 10px; background: #FDF4F2; color: #6B3A33; font-size: 14px; line-height: 1.55; }
body.admin-shell .trash-banner strong { color: #C0392B; }


/* v857 — fiche d'un signalement (liste, échange avec le signalant) + page de réponse du membre. */
body.admin-shell .rep-h2 { font-size: 1.05rem; margin: 22px 0 10px; color: #223E63; }
body.admin-shell .rep-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
body.admin-shell .rep-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
@media (max-width: 980px) { body.admin-shell .rep-grid { grid-template-columns: 1fr; } }
body.admin-shell .rep-row { display: flex; gap: 12px; padding: 7px 0; border-bottom: 1px solid rgba(34,62,99,.08); }
body.admin-shell .rep-row:last-child { border-bottom: 0; }
body.admin-shell .rep-row-block { flex-direction: column; gap: 6px; }
body.admin-shell .rep-k { flex: 0 0 150px; color: #6b7580; font-size: .9rem; }
body.admin-shell .rep-v { flex: 1 1 auto; min-width: 0; }
body.admin-shell .rep-table td { vertical-align: middle; }
body.admin-shell .rep-open { text-align: right; white-space: nowrap; }
.rep-badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: .78rem; font-weight: 700; }
.rep-badge.is-open { background: #FDECEA; color: #C0392B; }
.rep-badge.is-review { background: #FFF3DC; color: #9A6B10; }
.rep-badge.is-done { background: #E8F3EC; color: #2F6B45; }
.rep-badge-new { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: .78rem; font-weight: 700; background: #223E63; color: #fff; }
.rep-quote { background: #F1EEE7; border-radius: 12px; padding: 12px 14px; line-height: 1.55; }
.rep-thread { display: flex; flex-direction: column; gap: 10px; margin: 10px 0 16px; }
.rep-msg { border-radius: 12px; padding: 10px 14px; line-height: 1.55; }
.rep-msg.is-admin { background: #EDF1FB; }
.rep-msg.is-member { background: #F1EEE7; }
.rep-msg-head { font-size: .82rem; font-weight: 700; color: #223E63; margin-bottom: 4px; }
.rep-msg-body { white-space: normal; word-break: break-word; }
body.admin-shell .rep-ask label { font-weight: 700; }
body.admin-shell .rep-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
body.admin-shell .rep-actions form { margin: 0; }
/* v858 — formulaires des signalements (question de la modération, réponse du membre). */
.rep-form { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.rep-form label { font-weight: 700; font-size: .95rem; }
.rep-form textarea { width: 100%; box-sizing: border-box; padding: 12px 14px; font: inherit; line-height: 1.5; border: 1px solid var(--border); border-radius: 12px; background: var(--card); color: inherit; resize: vertical; }
.rep-form textarea:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.rep-form .hint { font-size: .86rem; color: #6b7580; margin: 0; }
.rep-form button { align-self: flex-start; }
/* La ligne « Précisions » passe en colonne : sans cette remise à zéro, le `flex: 0 0 150px` du libellé
   devient une hauteur de 150 px et creuse un trou entre le titre et le texte. */
body.admin-shell .rep-row-block .rep-k { flex: none; }
/* v859 — conversation versée au dossier + pièces jointes des signalements. */
.rep-conv { display: flex; flex-direction: column; gap: 8px; max-height: 460px; overflow-y: auto; padding-right: 4px; }
.rep-bubble { border-radius: 12px; padding: 9px 13px; line-height: 1.5; font-size: .94rem; max-width: 92%; }
.rep-bubble.is-them { background: #F1EEE7; align-self: flex-start; }
.rep-bubble.is-reporter { background: #EDF1FB; align-self: flex-end; }
.rep-bubble.is-flag { box-shadow: inset 0 0 0 2px #C0392B; }
.rep-bubble-head { font-size: .78rem; font-weight: 700; color: #223E63; margin-bottom: 3px; }
.rep-files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.rep-thumb { display: block; width: 92px; height: 92px; border-radius: 10px; overflow: hidden; border: 1px solid var(--hairline, rgba(34,62,99,.15)); }
.rep-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rep-file { display: inline-flex; align-items: center; gap: 6px; padding: 7px 11px; border-radius: 999px; background: #fff; border: 1px solid var(--hairline, rgba(34,62,99,.15)); font-size: .88rem; text-decoration: none; color: inherit; }
.rep-form input[type="file"] { font: inherit; font-size: .9rem; }
.rep-warn { background: #FDF4F2; border-left: 4px solid #C0392B; border-radius: 10px; padding: 10px 12px; color: #6B3A33; font-size: .9rem; margin: 0 0 12px; }
/* v862 — verrou de la conversation d'un signalement (ouverture explicite, tracée au journal). */
.rep-lock { background: #FDF9F2; border: 1px solid #E8DCC4; border-left: 4px solid #C89B3C; border-radius: 12px; padding: 14px 16px; }
.rep-lock p { margin: 0 0 10px; line-height: 1.55; font-size: .94rem; }
.rep-lock form { margin: 0; }
.rep-relock { margin: 12px 0 0; text-align: right; }
/* v868 — état de la tâche quotidienne (tableau de bord) et filtres écartés (liste des comptes). */
body.admin-shell .cron-state { margin: 14px 0; font-size: .9rem; color: #6b7580; }
body.admin-shell .cron-state.is-ko { background: #FDF4F2; border-left: 4px solid #C0392B; border-radius: 10px; padding: 10px 12px; color: #6B3A33; }
body.admin-shell .cron-state code { background: rgba(34,62,99,.07); padding: 1px 5px; border-radius: 5px; }

/* v872 — corbeille : de vraies lignes, la photo en bout de ligne, le motif du départ. */
body.admin-shell .trash-list { max-height: 62vh; overflow-y: auto; }
body.admin-shell .trash-table { width: 100%; }
body.admin-shell .trash-table td { vertical-align: middle; }
body.admin-shell .trash-table .trash-who { min-width: 0; }
body.admin-shell .trash-email { display: block; font-weight: 600; word-break: break-all; }
body.admin-shell .trash-name { display: block; font-size: .86rem; color: #6b7580; }
body.admin-shell .trash-when { white-space: nowrap; font-size: .9rem; }
body.admin-shell .trash-when .trash-sub { display: block; font-size: .8rem; color: #8A8F98; }
body.admin-shell .trash-motif { display: inline-block; padding: 3px 10px; border-radius: 999px; background: #F1EEE7; font-size: .85rem; }
body.admin-shell .trash-motif.is-happy { background: #E8F3EC; color: #2F6B45; font-weight: 600; }
body.admin-shell .trash-pic { width: 52px; }
body.admin-shell .trash-avatar { display: block; width: 44px; height: 44px; border-radius: 50%; background-size: cover; background-position: center; border: 1px solid rgba(34,62,99,.12); }
body.admin-shell .trash-avatar.is-empty { background: #EDEFF3; }
body.admin-shell .trash-table .trash-actions { white-space: nowrap; text-align: right; }
body.admin-shell .trash-table .trash-actions form { display: inline-block; margin: 0 0 0 6px; }

/* v872b — la corbeille est un tableau : il lui faut la largeur, sinon les adresses se coupent
   lettre par lettre et les boutons sortent de la boîte. */
.trash-modal-inner { max-width: min(1000px, 94vw); max-height: 88vh; overflow-y: auto; text-align: left; }
body.admin-shell .trash-table th, body.admin-shell .trash-table td { padding: 10px 12px; }
body.admin-shell .trash-table .trash-who { width: 38%; }
body.admin-shell .trash-email { word-break: break-word; overflow-wrap: anywhere; }
body.admin-shell .trash-table .trash-why { width: 26%; }
body.admin-shell .trash-table .trash-actions { width: 1%; }

/* v873 — ⚠️ L'ANCIEN STYLE « CARTE » DE LA CORBEILLE SURVIVAIT SUR LES <tr>. `.trash-row` était un
   `display:flex` (liste de cartes empilées) : appliqué aux lignes du tableau, il cassait l'alignement
   — les en-têtes « Supprimé le » et « Motif du départ » flottaient au-dessus des boutons. On le remet
   en ligne de tableau ici, sans toucher aux autres usages. */
body.admin-shell .trash-table tr.trash-row { display: table-row; border: 0; border-radius: 0; background: none; padding: 0; gap: 0; }
body.admin-shell .trash-table tr.trash-row td { border-top: 1px solid var(--hairline); background: none; }
body.admin-shell .trash-table tr.trash-row:hover td { background: rgba(34,62,99,.03); }
body.admin-shell .trash-table td.trash-actions { display: table-cell; }

/* v878 — récapitulatif des gestes quotidiens, en tête de l'historique d'un compte. */

.rep-encours { display: flex; flex-direction: column; gap: 3px; margin: 0 0 18px; padding: 12px 14px; border-radius: 12px;
  background: var(--secondary); border: 1px solid var(--border); }
.rep-encours-k { font-size: .74rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted-foreground); }
.rep-encours-v { font-size: 1.02rem; line-height: 1.3; }
.rep-encours-vide { color: var(--muted-foreground); font-weight: 500; }
.rep-encours-meta { font-size: .84rem; color: var(--muted-foreground); }
.rep-encours-etat { margin-top: 5px; font-size: .88rem; font-weight: 600; color: #b45309; }

/* Décisions d'un signalement : une option par ligne, son bouton et la phrase qui dit ce qu'elle fait.
   ⚠️ Chaque option est un <form> distinct — un seul formulaire à boutons multiples aurait rendu la
   décision dépendante du bouton cliqué, donc invisible à la relecture du code. */
.rep-etat { margin: 0 0 12px; font-weight: 600; color: #b45309; }
/* ⚠️ CÔTE À CÔTE, MAIS CHACUN GARDE SA PHRASE. Ce sont des gestes lourds — suspendre quelqu'un,
   fermer définitivement la porte entre deux personnes — et la ligne sous le bouton dit ce qui va
   se passer. Les aligner en retirant ces phrases aurait raccourci l'écran en supprimant justement
   ce qui évite l'erreur. Chaque colonne porte donc son bouton ET son explication.
   `auto-fit` + `minmax` : une seule rangée quand la place le permet, repli en deux puis en une
   colonne sur écran étroit — sans point de rupture à maintenir. */
.rep-decisions { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 18px 16px; align-items: start; }
.rep-opt { display: flex; flex-direction: column; padding: 0; border-bottom: 0; }
.rep-opt-line { display: flex; align-items: stretch; gap: 10px; flex-wrap: wrap; }
/* Le bouton prend toute sa colonne : sans cela, quatre boutons de largeurs différentes donnent une
   rangée en dents de scie. `white-space: normal` parce que « Réactiver, sans possibilité de se
   revoir » ne tient pas sur une ligne de 190 px — et un libellé tronqué sur une action
   irréversible serait pire que deux lignes. */
.rep-opt-line .btn { width: 100%; white-space: normal; line-height: 1.25; text-align: center; }
/* Le seul qui ne décide rien : on le pose à part par la couleur, pas par la position. */
.rep-opt-nav .rep-opt-hint { font-style: italic; }
.rep-opt-hint { margin: 6px 0 0; font-size: .86rem; line-height: 1.4; color: var(--muted-foreground); }
.rep-opt-days { font-size: .88rem; color: var(--muted-foreground); display: inline-flex; align-items: center; gap: 6px; }
.rep-opt-days input { width: 66px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; font: inherit; text-align: center; }
/* Accusé de lecture, sous le dernier message envoyé. Discret : il ne doit pas peser autant
   qu'un message, ni décaler le fil quand il apparaît. */
.msg-receipt { align-self: flex-end; margin: -2px 2px 6px; font-size: .74rem; line-height: 1.2; text-align: right; }
/* ⚠️ MÊME GRIS DANS LES DEUX ÉTATS (choix de Gabriel) : c'est une mention de service, elle ne
   doit pas peser plus que les messages qu'elle accompagne. Seule la coche distingue « lu » —
   d'où « ✓ » en caractère de TEXTE, qui hérite du gris, et non « ✔️ » que le système rend en
   emoji noir quoi qu'on demande. Les deux classes restent : elles portent l'état, pas le style. */
.msg-receipt.is-read, .msg-receipt.is-unread { color: var(--muted-foreground); }

/* Le fantôme : discret tant qu'il dort, franc quand il veille. */
.rep-ghost-form { display: inline; }
.rep-ghost { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  margin-left: 8px; padding: 0; vertical-align: -8px; border: 1px solid var(--border); border-radius: 9px;
  background: transparent; color: #9aa3ad; cursor: pointer; transition: color .12s, border-color .12s, background .12s; }
.rep-ghost svg { width: 17px; height: 17px; }
.rep-ghost:hover { color: #6b7480; border-color: #c8ced6; background: var(--secondary); }
.rep-ghost.is-on { color: #6d28d9; border-color: #c9b6f2; background: #f4efff; }
.rep-ghost-tag { display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 999px;
  background: #f4efff; color: #6d28d9; font-size: .74rem; font-weight: 600; }

/* Le fantôme sur la fiche d'un compte : une marque, pas un bouton. */
.prof-ghost { display: inline-flex; align-items: center; gap: 5px; margin-left: 9px; padding: 2px 9px 2px 7px;
  border-radius: 999px; background: #f4efff; color: #6d28d9; font-size: .74rem; font-weight: 600;
  vertical-align: 2px; cursor: help; }
.prof-ghost svg { width: 14px; height: 14px; flex: none; }

/* Les deux faits de la page Paiements : le cumul et le contrôle, deux lignes d'une même carte.
   ⚠️ Le libellé a une largeur FIXE : sans elle, les deux valeurs ne s'alignaient pas et la carte
   retombait dans le désordre qu'elle est censée corriger. */
.pay-facts { display: flex; flex-direction: column; gap: 14px; margin: 14px 0; }
.pay-fact { display: flex; align-items: center; gap: 12px; padding: 15px 18px; font-size: .92rem; }
.pay-fact-ic { flex: none; display: inline-flex; width: 26px; height: 26px; align-items: center; justify-content: center;
  border-radius: 8px; background: var(--secondary); color: var(--muted-foreground); }
.pay-fact-ic svg { width: 15px; height: 15px; }
.pay-fact-k { flex: none; width: 178px; font-weight: 600; color: var(--foreground); }
.pay-fact-v { color: var(--muted-foreground); }
.pay-fact-v strong { color: var(--foreground); font-weight: 600; }
.pay-fact-sep { opacity: .45; margin: 0 2px; }
.pay-fact.is-ok .pay-fact-ic { background: #E6F3EC; color: #2E8F6B; }
@media (max-width: 720px) {
  .pay-fact { align-items: flex-start; flex-wrap: wrap; }
  .pay-fact-k { width: auto; }
  .pay-fact-v { flex-basis: 100%; padding-left: 38px; }
}

/* Barre de la maquette « enfants » (/apercu-enfants) : visible NULLE PART ailleurs. */

/* Compteur du champ « Ma présentation » : discret par défaut, il ne se signale que lorsqu'il a
   quelque chose à dire — minimum pas atteint, ou plafond en vue. */
.bio-count { display: block; margin-top: 5px; text-align: right; font-size: .78rem; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
.bio-count.is-short { color: #C0873A; }
.bio-count.is-near { color: #C0574B; }

/* ---- En-tête : verrouillage complet, variante selon le fond (v931) ----
   ⚠️ La version BLANCHE ne s'affiche que là où l'en-tête est transparent par-dessus la photo
   d'accueil. Partout ailleurs — accueil défilé, et toutes les autres pages — le fond est clair
   et c'est la version foncée qui s'affiche. Un blanc unique y serait invisible, sans erreur. */
.brand-logo-light { display: none; }
.page-landing .site-header:not(.scrolled) .brand-logo-dark { display: none; }
.page-landing .site-header:not(.scrolled) .brand-logo-light { display: block; }

/* Verrouillage complet : plus haut que l'ancien symbole (v932). */
.site-header .brand-logo { height: 44px; }
@media (max-width: 640px) { .site-header .brand-logo { height: 34px; } }

/* ---- ESSAI (v933) : titre du hero en géométrique, pour l'accorder au logo ----
   Poppins tient lieu d'ITC Avant Garde Gothic, qui est sous licence commerciale.
   ⚠️ Portée volontairement étroite : ce seul titre. `--font-brand` reste le serif partout ailleurs. */
.hero h1 { font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
           font-weight: 500; letter-spacing: -.005em; font-size: clamp(2.05rem, 5.2vw, 3.35rem); }
/* ⚠️ Plafond 3,35rem (≈54px) et non 3,7 : MESURÉ au navigateur, au-delà le titre passe de DEUX
   à TROIS lignes et pousse tout le hero vers le bas. Le serif d'origine tenait en 2 lignes à
   70px — une géométrique est plus large à corps égal, d'où le plafond plus bas. */
.hero h1 em { font-style: italic; font-weight: 500; }

/* ---- Hero : composition (v935) ----
   ⚠️ Le contenu est ancré EN BAS (`align-items: flex-end`) : pour le REMONTER, on augmente le
   padding du BAS. Agir sur le padding du haut n'aurait aucun effet — piège non intuitif.
   Mesuré à 1280×800 : espace au-dessus du bloc 155 px → ~100 px. */
.page-landing .hero { padding-bottom: 100px; }
/* ⚠️ Marge négative recalée sur la hauteur RÉELLE de l'en-tête (75 px, imposée par le bouton et
   non par le logo). L'ancienne formule (26+30+13=69) laissait 6 px de fond de page visibles
   au-dessus de la photo — défaut PRÉ-EXISTANT, constaté aussi en production. */
.page-landing .hero { margin-top: -75px; }
/* ⚠️ PAS de règle mobile : MESURÉ, le padding du bas n'y a AUCUN effet sur la position du bloc.
   Sous 640 px le contenu est plus haut que l'écran, il n'y a donc aucun jeu à répartir — le
   padding ne fait qu'allonger le hero sous le bloc. Les 13 px sous l'en-tête y sont structurels. */

/* ---- Back-office : bloc marque (v940) ----
   Logo COMPLET centré quand la barre est large ; marque seule quand elle est repliée.
   ⚠️ La règle générique `.admin-brand img { width: 42px }` s'applique aux DEUX images :
   on la surcharge par une sélection plus spécifique, sans la modifier (elle sert ailleurs). */
.admin-brand { justify-content: center; }
.admin-brand .brand-full { display: block; width: 158px; height: auto; }
.admin-brand .brand-mark { display: none;  width: 40px;  height: auto; }
@media (max-width: 900px) {
  .admin-brand .brand-full { display: none; }
  .admin-brand .brand-mark { display: block; }
}
/* ⚠️ Le volet rabattu REDONNE 232 px à la barre : le logo complet doit y revenir, sinon on
   garderait une petite marque perdue dans une barre large. */
@media (min-width: 600px) and (max-width: 900px) {
  body.admin-nav-open .admin-brand { justify-content: center; }
  body.admin-nav-open .admin-brand .brand-full { display: block; }
  body.admin-nav-open .admin-brand .brand-mark { display: none; }
}

/* ---- Back-office : logo + bouton de repli sur une rangée (v941) ---- */
/* ⚠️ `wrap` indispensable : barre repliée (64 px), la marque et le bouton ne tiennent pas
   côte à côte — le bouton retombe sous la marque, comme avant. Sans wrap, ils se chevauchent. */
.admin-brand { flex-wrap: wrap; position: relative; }
/* ⚠️ Le logo n'est réduit QUE là où le bouton de repli existe (zone fold 600-900) : il faut
   lui faire de la place sur la rangée. Sur desktop il n'y a pas de bouton, donc pas de raison
   de rapetisser — le logo y garde sa taille pleine (règle v940, 158px). */
@media (min-width: 600px) and (max-width: 900px) {
  /* Logo réduit ICI SEULEMENT : il faut faire de la place au bouton sur la rangée. */
  .admin-brand .brand-full { width: 128px; }
  /* Volet ouvert : logo et bouton sur UNE rangée, alignés l'un sur l'autre.
     ⚠️ Pas de calage absolu avec un `top` magique : le bloc porte 20 px de padding BAS, donc un
     `top: 50%` viserait le centre de la BOÎTE et non celui du logo — mesuré, cela décalait le
     bouton de 11 px vers le bas. `align-items: center` s'auto-corrige si le logo change de taille. */
  body.admin-nav-open .admin-brand { flex-wrap: nowrap; align-items: center; }
  /* ⚠️ Remontée OPTIQUE de 2 px, demandée par Gabriel. Les boîtes sont déjà centrées l'une sur
     l'autre (écart mesuré : 0), et l'encre du fichier n'est décalée que de 0,4 px à cette
     taille — le déséquilibre perçu vient du contraste entre un bouton plein et un lettrage fin.
     `position: relative` et non une marge : ne déplace QUE le rendu, sans toucher à la mise en page. */
  body.admin-nav-open .admin-brand .brand-full { margin-left: auto; margin-right: auto; position: relative; top: -2px; }
  body.admin-nav-open .admin-brand .admin-nav-toggle { position: static; margin: 0; flex: none; }
}

/* ---- Espace membre : logo complet et centré (v945) ----
   ⚠️ Barre de 260 px avec 16 px de marge : 228 px utiles. 170 px laissent 29 px de chaque côté.
   ⚠️ La règle générique `.app-nav-brand img { height: 30px }` s'appliquerait aussi : on la
   surcharge par une sélection plus spécifique, sans la modifier (elle peut servir ailleurs). */
.app-nav-brand { justify-content: center; }
.app-nav-brand .app-brand-full { width: 170px; height: auto; }

/* ---- Bandeau d'environnement (v946) ----
   ⚠️ Hauteur FIGÉE : c'est elle qui permet de réserver la place. Un bandeau qui passe à deux
   lignes rend tout décalage faux — d'où le texte raccourci sous 600 px. */
:root { --env-banner-h: 26px; }
.env-banner { position: fixed; left: 0; right: 0; bottom: 0; z-index: 99999;
  height: var(--env-banner-h); line-height: var(--env-banner-h); overflow: hidden;
  background: #8A1C1C; color: #fff; font: 600 12px/1 system-ui, sans-serif;
  text-align: center; letter-spacing: .03em; pointer-events: none; white-space: nowrap; }
.env-banner-shared { background: #7A1010; }
@media (max-width: 599px) { .env-banner-long { display: none; } }
/* ⚠️ Ce qui est fixé en bas remonte d'autant : sinon le bandeau le masque. La barre de
   navigation du membre est dans ce cas sur mobile. */
body.plv-dev .app-nav { bottom: var(--env-banner-h); }
/* ⚠️ À TOUTES les largeurs, pas seulement en mobile : sur grand écran le bandeau masquait la
   dernière ligne du pied de page (constaté sur les captures du site public). */
body.plv-dev { padding-bottom: var(--env-banner-h); }
/* ⚠️ MAIS CETTE RÈGLE REMPLAÇAIT CELLE DE LA BARRE DE NAVIGATION AU LIEU DE S'Y AJOUTER. Sur les
   écrans membre, `.has-appnav` réserve 78 px pour la barre du bas ; `body.plv-dev` (0,2,0) l'emporte
   sur `.has-appnav` (0,1,0) et ramenait ce dégagement à 26 px. Il manquait donc 52 px, et le dernier
   élément de la page — le bouton « Valider » — passait sous la barre. Mesuré : 38 px du bouton
   recouverts, en simulant le bandeau. ⚠️ DÉFAUT DU DEV UNIQUEMENT (la production n'a pas de
   bandeau), mais c'est là que tout se relit : il valait la peine d'être corrigé.
   ⚠️ Les deux `:not()` préservent les écrans qui suppriment volontairement ce dégagement (la
   conversation et la messagerie en plein écran) : sans eux, cette règle plus précise le leur
   réimposerait. */
@media (max-width: 899px) {
  body.plv-dev.has-appnav:not(.page-conv):not(.page-msg2-active) {
    padding-bottom: calc(78px + var(--env-banner-h));
  }
}
/* ⚠️ LA CONVERSATION NE SE LAISSE PAS RECOUVRIR NON PLUS. Elle se dimensionne en `100dvh` — la
   hauteur de l'écran, sans rien savoir du bandeau — si bien que celui-ci se posait sur la zone de
   saisie : la moitié du bouton d'envoi passait dessous (constaté sur le dev). Le `padding-bottom`
   du body ne l'atteint pas, puisqu'elle ne suit pas le flux. On lui retranche donc la hauteur du
   bandeau, aux TROIS endroits où cette hauteur est posée : pleine page, volet de droite du mode
   deux colonnes, et conversation ouverte sur téléphone.
   ⚠️ En dev UNIQUEMENT (`body.plv-dev`) : en production, il n'y a pas de bandeau à compenser. */
/* ⚠️ `page-msg2` est posée sur le <body> LUI-MÊME, pas sur un descendant : il faut donc
   `body.plv-dev.page-msg2` (sans espace). Écrit avec une espace, le sélecteur cherche un enfant
   portant cette classe — il n'en existe aucun, et la règle ne s'applique jamais. Mesuré. */
body.plv-dev .conv-view { height: calc(100dvh - var(--env-banner-h)); }
body.plv-dev.page-msg2 .app-view.msg-2pane { height: calc(100dvh - var(--env-banner-h)); }
body.plv-dev.page-msg2-active .msg-pane-chat .conv-view { height: calc(100dvh - var(--env-banner-h)); }
body.plv-dev .msg-2pane .msg-pane-list { min-height: calc(100dvh - 104px - var(--env-banner-h)); }

/* ---- Bande d'appel : la promesse dans la police du titre (v956) ----
   Même géométrique que `.hero h1` : c'est une PHRASE DE MARQUE, pas du texte courant.
   ⚠️ La largeur maximale passe de 480 à 720 px. À ce corps, « chaque jour, quelqu'un priera pour
   toi. » se cassait en deux à 480 px : le <br> voulu après le deux-points doit rester la SEULE
   coupure, sinon la phrase tombe sur trois lignes et perd son balancement. */
/* ⚠️ Cantonné à `.cta-punchline`, et NON à tout `.cta-band p` : la bande porte un SECOND texte,
   bien plus long, quand le site repasse en pré-lancement (marche arrière d'urgence de l'admin).
   Agrandi à ce corps, il tomberait sur trois lignes de 25 px. Il garde donc sa taille d'origine. */
.cta-band .cta-punchline {
  font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
  font-weight: 500;
  /* ⚠️ Le terme central est GROS (4.5vw) à dessein : sur téléphone c'est lui qui commande, et
     la taille décroît avec l'écran. MESURÉ à 390 px : il ne reste que 350 px de large et la
     seconde ligne demande 343 px à 18 px — un plancher fixe à 20 px la cassait en trois. */
  font-size: clamp(1rem, 4.5vw, 1.55rem);
  line-height: 1.42;
  letter-spacing: -.005em;
  max-width: 720px;
  color: rgba(255, 255, 255, .92);
}

/* Seconde ligne de l'infobulle des courbes : le mouvement du jour (« +18 −5 »).
   ⚠️ `display:block` est nécessaire — l'infobulle est un conteneur en ligne, sans quoi les deux
   informations se colleraient sur la même ligne. */
.curve-tip .curve-tip-mv {
  display: block;
  margin-top: 2px;
  font-size: .78em;
  opacity: .78;
  letter-spacing: .02em;
}

/* Corbeille : la vignette est passée en tête de ligne et ouvre la fiche du membre.
   ⚠️ `display:block` sur le lien — sans lui, la zone cliquable se limite à la ligne de texte
   du <a> (vide ici) et la photo, qui est un fond de <span>, ne réagirait pas au clic. */
body.admin-shell .trash-pic a { display: block; width: 44px; border-radius: 50%; }
body.admin-shell .trash-pic a:hover .trash-avatar { border-color: rgba(34,62,99,.45); }
body.admin-shell .trash-pic a:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Paiements — « Option du jour » : carte à la demande, à côté des faits de facturation.
   ⚠️ Classe distincte de `.pay-fact` : les deux faits de facturation forment un invariant
   (une carte chacun) que cette carte-ci ne doit pas venir troubler. */
body.admin-shell .pay-option {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  /* ⚠️ MARGE EN BAS AUSSI. Le titre « Derniers paiements » n'a que 4 px de marge haute (la règle
     `.dash-h2:first-of-type`, puisque c'est le premier de la page) : la barre lui était donc collée.
     14 px des DEUX côtés, comme `.pay-facts` — c'est le pas de tout ce bloc, et le même en haut
     qu'en bas. Les marges adjacentes fusionnent : le 4 px du titre disparaît dans ces 14. */
  padding: 15px 18px; margin: 14px 0; font-size: .92rem;
}
body.admin-shell .pay-option .btn { padding: 5px 12px; font-size: .82rem; line-height: 1.3; }
/* ⚠️ L'override de libellé (700 / --primary) est RETIRÉ : c'est lui qui faisait de cette ligne un
   dessin à part. `.pay-fact-k` s'applique déjà — même graisse, même couleur, même colonne de
   178 px que « Depuis le lancement » et « Contrôle de facturation ». */
body.admin-shell .pay-option .pay-fact-v { flex: 1 1 260px; }
body.admin-shell .pay-option .btn { margin-left: auto; }
/* ⚠️ SUR TÉLÉPHONE, LA MÊME BASCULE QUE `.pay-fact` — et elle DOIT être écrite ici, après le bloc
   ci-dessus. Placée dans la requête média partagée (l. ~3197), elle avait la même spécificité mais
   venait AVANT : `align-items: center` la reprenait aussitôt. Une requête média n'ajoute aucune
   spécificité ; seul l'ordre départage. Mesuré au navigateur : `center` au lieu de `flex-start`,
   alors que le commentaire promettait le contraire. */
@media (max-width: 720px) {
  body.admin-shell .pay-option { align-items: flex-start; }
}

/* Paiements — icône d'historique des décomptes, dans la carte « Option du jour ». */
body.admin-shell .pay-option-hist {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; margin-left: auto; padding: 0;
  background: none; border: 1px solid rgba(34,62,99,.16); border-radius: 8px;
  color: var(--primary); cursor: pointer;
}
body.admin-shell .pay-option-hist svg { width: 16px; height: 16px; }
body.admin-shell .pay-option-hist:hover { border-color: rgba(34,62,99,.45); }
/* ⚠️ Le bouton d'historique prend le `margin-left:auto` : le suivant ne doit plus le reprendre,
   sinon les deux se repousseraient aux deux bouts de la carte. */
body.admin-shell .pay-option .pay-option-hist + .btn { margin-left: 8px; }


/* Champ libre de « Une autre raison » (modale de suppression) : même trait que le reste de l'app. */
.del-reason-text { width: 100%; box-sizing: border-box; border: 1px solid var(--border); border-radius: 12px;
  padding: 12px 14px; font: inherit; color: var(--foreground); background: var(--card); resize: vertical; }
.del-reason-text:focus { outline: none; border-color: var(--primary); }
/* Ce que la personne a écrit, sous son motif, dans la corbeille. */
.trash-motif-text { display: block; margin-top: 4px; font-size: .85rem; line-height: 1.35;
  color: var(--muted-foreground); font-style: italic; }
/* « Match le … avec … » sous un départ heureux. Même famille que .trash-motif-text (bloc, petit,
   discret) mais NON italique : ce n'est pas une citation du membre, c'est une donnée de la base.
   Plusieurs matchs s'empilent, d'où la marge sur chaque ligne plutôt qu'un espacement de conteneur. */
.trash-match { display: block; margin-top: 4px; font-size: .85rem; line-height: 1.35; color: var(--muted-foreground); }
.trash-match a { color: var(--primary); font-weight: 600; text-decoration: none; }
.trash-match a:hover { text-decoration: underline; }
/* Message libre à UN membre : panneau de rédaction au-dessus de l'aperçu (pop-up d'envoi par compte).
   Réutilise .bulk-field, déjà défini pour le message libre de l'envoi groupé — même trait, un seul style. */
.mp-compose { padding: 14px 18px 4px; border-bottom: 1px solid var(--border); display: grid; gap: 10px; }
.mp-compose textarea { resize: vertical; min-height: 120px; }
.mp-compose-hint { margin: 0 0 10px; font-size: .82rem; line-height: 1.4; color: var(--muted-foreground); }

/* ⚠️ L'EN-TÊTE DE LA FENÊTRE D'ENVOI NE RÉTRÉCIT PLUS. Il était en `flex: 0 1 auto` : dès qu'un
   troisième onglet a fait passer la rangée sur deux lignes, il est descendu sous sa hauteur
   naturelle et a rogné les lignes « Objet » et « À ». Le destinataire disparaissait juste avant
   d'envoyer — l'information qu'on veut lire à ce moment-là plus que toute autre. */
.mail-preview-head { flex-shrink: 0; }
.mp-compose { flex-shrink: 0; }
/* En rédaction, la fenêtre prend TOUTE la hauteur permise : sinon elle se dimensionne sur son
   contenu, il ne reste aucun espace à distribuer, et l'aperçu tombe à une centaine de pixels —
   on n'y voit plus l'e-mail qu'on est en train d'écrire. */
.mail-preview.is-composing .mail-preview-box { height: 90vh; }
.mail-preview.is-composing .mail-preview-body { min-height: 120px; }

/* ---- Titres d'article en géométrique (v1019) ----
   Prolonge l'essai de la v933 : le titre du hero était passé en Poppins pour s'accorder au logo,
   avec une portée volontairement étroite (« ce seul titre »). Gabriel l'étend aux articles.
   ⚠️ SEULES les graisses 500 et 600 sont chargées (voir le lien Google Fonts) : en demander une
   autre ferait graisser la police par le navigateur, avec le rendu épais et sale que cela donne.
   ⚠️ `--font-brand` (Cormorant) reste le serif PARTOUT AILLEURS — pages, back-office, e-mails. */
.container-article h1 { font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
  font-weight: 500; letter-spacing: -.01em;
  /* ⚠️ Corps réduit par rapport au serif d'origine (2,6rem → 2,3rem). Une géométrique est plus
     LARGE à corps égal : le titre le plus long du site passait sur trois lignes. Même raison que
     le plafond abaissé du titre du hero en v933. */
  font-size: clamp(1.75rem, 4vw, 2.3rem); }
.container-article h2 { font-family: 'Poppins', 'Avant Garde', 'Century Gothic', system-ui, sans-serif;
  font-weight: 600; letter-spacing: -.005em; }

/* ---- Carte « pas encore de match » dans les coups de cœur (v1021) ----
   Elle prend la place d'une fiche dans la même grille : `.fav-photo` est déjà en 4/5, exactement
   le format de l'image, donc elle s'aligne au pixel près avec les profils voisins.
   ⚠️ Un liseré d'accent la distingue d'un profil — sans quoi on croirait à une personne. */
.fav-tip .fav-photo { background-size: cover; background-position: center; }
/* ⚠️ La carte n'a pas de titre : son corps ne contient qu'une ligne. Laissé au gabarit des fiches
   voisines (nom + lieu + état), il ouvrait 69 px de blanc sous l'image — mesuré. On inverse donc
   les rôles : le corps se réduit à son contenu, et c'est l'IMAGE qui prend tout le reste.
   ⚠️ L'alignement avec la ligne d'état des profils est CONSERVÉ (mesuré à 2 px près) : le corps
   fait 14 + 21 + 16 px, soit exactement la place que la ligne occupait déjà.
   ⚠️ L'image est en `cover` : elle est donc RECADRÉE en grandissant. Le visuel a été composé avec
   de la marge pour l'admettre — ne pas y mettre une image cadrée serré. */
.fav-tip .fav-photo { aspect-ratio: auto; flex: 1 1 auto; min-height: 0; }
.fav-tip .fav-body { flex: 0 0 auto; }

/* Carte « pas encore de match » servie SEULE, sur la page vide : la grille des coups de cœur
   n'existe pas là, il faut donc lui donner sa largeur et la centrer soi-même. */
.fav-tip-seule { max-width: 260px; margin: 22px auto 0; text-align: left; }

/* Les deux réponses à l'invitation à prier (carte « Aujourd'hui »). Essai en cours — v1035.
   ⚠️ `wrap` et non `nowrap` : « Belle prière pour plus tard » ne tient pas sur une ligne à côté de
   l'autre sur un téléphone, et un bouton tronqué serait pire que deux boutons empilés. */
.prayer-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 18px 0 22px; }
.prayer-actions .btn { flex: 0 1 auto; }
/* Sur large écran, les deux boutons tiennent côte à côte — il ne manquait que 5 px (mesuré :
   carte 446, boutons 451). On resserre le gap et les marges internes plutôt que de rétrécir le
   texte. Seuil 900 px : c'est là que la carte atteint sa largeur pleine (366 → 446 px), donc en
   dessous rien ne change et `flex-wrap` continue d'empiler tout seul. Aucune largeur n'est
   forcée : si un libellé s'allonge un jour, les boutons repassent l'un sous l'autre au lieu
   d'être tronqués. */
@media (min-width: 900px) {
  .prayer-actions { gap: 8px; }
  .prayer-actions .btn { padding-left: 16px; padding-right: 16px; }
}
.like-modal .prayer-modal-title { margin: 2px 0 12px; padding: 0 34px; font-size: 1.15rem; font-weight: 700; color: var(--primary); }
.prayer-author { margin: -6px 0 14px; font-size: .86rem; font-style: italic; color: var(--muted-foreground); }
/* Les fenêtres de PRIÈRE sont centrées, pas posées en bas comme les autres : on s'y arrête pour
   lire, on n'y fait pas un geste rapide. Réservé à elles — la popup d'achat et celle des coups de
   cœur gardent leur feuille montante.
   ⚠️ `padding` sur le conteneur ET `max-height` sur la feuille : une prière longue dépasse l'écran
   d'un petit téléphone, elle doit défiler à l'intérieur sans jamais toucher les bords. */
.like-modal[data-modal] { align-items: center; padding: 18px; }
.like-modal[data-modal] .like-modal-inner {
  max-height: calc(100vh - 36px); overflow-y: auto;
  border-radius: var(--radius);
  padding-bottom: 24px;                 /* centrée : plus de marge d'encoche à réserver en bas */
  animation: prayerIn .2s ease;         /* la feuille ne monte plus : elle paraît sur place */
}
@keyframes prayerIn { from { transform: scale(.97); opacity: 0; } to { transform: none; opacity: 1; } }

/* Le formulaire emprunte le style de champs des Réglages (`.settings-form`) mais PAS leur mise en
   deux colonnes : deux textes de prière côte à côte seraient illisibles. */
.prayer-form { display: grid; gap: 16px; }
.prayer-form textarea {
  width: 100%; padding: 11px 14px; font: inherit; font-weight: 400; line-height: 1.55;
  color: var(--foreground); background: var(--background);
  border: 1px solid var(--border); border-radius: 10px; resize: vertical;
}
.prayer-form textarea:focus { outline: 2px solid var(--primary); outline-offset: 1px; border-color: var(--primary); }

/* Page Prières du back-office. La colonne « Texte » porte deux paragraphes (lui / elle) : c'est
   elle qui doit prendre la place, les trois autres restent au plus juste. */
.prayer-table td { vertical-align: top; }
.prayer-table th:nth-child(3), .prayer-table td:nth-child(3) { white-space: nowrap; }
.prayer-cell p { margin: 0 0 6px; line-height: 1.5; }
.prayer-cell p:last-child { margin-bottom: 0; }
.prayer-actions-cell { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.prayer-actions-cell .btn { white-space: nowrap; width: 100%; }
/* Jeu des cartes : les actions se rangent EN LIGNE, pas en colonne. Les prières ont des textes de
   plusieurs lignes qui laissent de la place à une pile de boutons ; une carte tient sur une ligne,
   et trois boutons empilés y feraient des rangées trois fois trop hautes pour rien. */
.cards-table .prayer-actions-cell { flex-direction: row; flex-wrap: wrap; justify-content: flex-end; align-items: center; }
.cards-table .prayer-actions-cell .btn { width: auto; }
.cards-table td { vertical-align: middle; }

/* ---- Jeu des cartes « Premiers pas », dans la conversation ---------------------------------
   La pile vit à côté des emojis : c'est une façon de dire quelque chose quand on ne sait pas par
   où commencer, pas une fonctionnalité à part. Même gabarit que le bouton emoji, donc. */
/* La pile vit dans l'EN-TÊTE, à gauche des points (demande de Gabriel, 24/08). Gabarit calé sur
   son voisin : c'est la même rangée, les deux doivent peser pareil à l'œil. */
.conv-cards-btn { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; flex: 0 0 auto; padding: 0; border: 0; background: transparent; cursor: pointer; border-radius: 999px; transition: opacity .12s, background .12s; }
.conv-cards-btn:hover { background: rgba(34,62,99,.07); }
.conv-cards-img { display: block; width: 22px; height: 22px; }

/* L'invitation reçue : au-dessus de la zone de saisie, là où on la lit. */
/* Les deux réponses vivent DANS la bulle d'invitation, là où on la lit. */
/* ⚠️ LA RANGÉE PASSE À LA LIGNE. Le panneau porte TROIS boutons depuis la v1119 (« À mon tour »,
   « À ton tour », « Arrêter le jeu ») : à 132 px de large minimum chacun, ils débordaient de la
   carte sur téléphone — les deux boutons des bords étaient tranchés par le cadre. Ils s'enroulent
   désormais, et la coupure tombe au bon endroit : les deux tirages ensemble, l'arrêt en dessous. */
.msg-invite-actions { display: flex; gap: 8px; justify-content: center; margin: 10px 0 4px; flex-wrap: wrap; }

/* En attente de réciprocité : la pile reste là, mais éteinte. Elle dit qu'il se passe quelque
   chose, sans laisser croire qu'un clic servirait à quoi que ce soit. */
.conv-cards-btn.is-waiting { opacity: .35; cursor: default; }
.conv-cards-btn.is-waiting:hover { background: transparent; }

/* La phrase d'état, sous la zone de saisie : c'est elle qui apprend la règle sans l'expliquer. */
.conv-game-note { margin: 0 0 6px; padding: 0 6px; font-size: .82rem; text-align: center; color: var(--muted-foreground, #6b7a90); }
.conv-game-note[hidden] { display: none; }

/* Une carte tirée garde son allure dans l'historique : centrée, ni à gauche ni à droite —
   elle n'est le mot de personne, c'est le jeu qui parle. */
/* ⚠️ `align-self`, PAS `justify-content` : .msg-wrap est une colonne flex, où justify-content
   gouverne l'axe VERTICAL. C'est align-self qui centre la carte entre les deux bords, et
   align-items qui centre son contenu. */
.msg-card-wrap { align-self: center; align-items: center; max-width: 88%; margin: 10px 0; }
/* ⚠️ MÊME AIR EN HAUT ET EN BAS (demande de Gabriel, 24/08). Le rembourrage seul ne suffisait
   pas : mesuré, l'écart réel était de 16 px en haut contre 9 en bas sur l'invitation, et de 20
   contre 9 sur une question tirée. Deux fuites invisibles s'y ajoutaient — l'INTERLIGNE au-dessus
   de la pastille de titre (posée en `inline-block`, elle repose sur une ligne plus haute qu'elle)
   et la marge basse de l'heure. Les trois sont traitées ensemble, sinon l'égalité est fausse. */
.msg-card, .msg-invite { position: relative; width: 100%; padding: 16px; border-radius: 16px; text-align: center; }
.msg-card .msg-card-tag, .msg-invite .msg-card-tag { display: block; }
/* ⚠️ L'HEURE SORT DU FLUX (demande de Gabriel, 24/08 : « que ce soit vraiment centré »). Posée
   dans le flux, elle ajoutait 18 px SOUS le dernier bouton — mesuré : 15 px au-dessus de l'icône
   contre 37 en dessous du bouton. Le rembourrage avait beau être symétrique, l'œil voyait le
   contenu remonter. Reléguée dans le coin, elle ne pousse plus rien : les deux écarts s'égalisent. */
.msg-card .msg-time, .msg-invite .msg-time {
  position: absolute; right: 14px; bottom: 4px; float: none; margin: 0; text-align: right;
}
/* ⚠️ Et la marge basse du DERNIER élément dans le flux, qui remettait 4 px sous les boutons.
   Visé par `nth-last-child(2)` parce que l'heure, désormais hors flux, est toujours le dernier
   enfant : ce qui la précède est donc toujours le dernier bloc visible — bloc de boutons sur une
   invitation, question sur une carte tirée, ligne « annulée » sur une invitation retirée. Nommer
   ces trois-là un par un aurait laissé le quatrième, le jour où il arrive, casser le centrage. */
.msg-card > *:nth-last-child(2), .msg-invite > *:nth-last-child(2) { margin-bottom: 0; }
.msg-card { border: 1px solid rgba(34,62,99,.18); background: #fff; box-shadow: 0 1px 0 rgba(34,62,99,.06), 0 6px 14px -10px rgba(34,62,99,.4); }
.msg-invite { border: 1px dashed rgba(34,62,99,.28); background: #F7F9FC; }
.msg-card-tag { display: inline-block; font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted-foreground, #6b7a90); }
.msg-card-q { margin: 6px 0 4px; font-size: 1rem; font-weight: 600; line-height: 1.45; color: var(--foreground, #223E63); }
.msg-card .msg-time, .msg-invite .msg-time { display: block; }
/* L'invitation : l'icône du jeu, le nom du jeu en titre, puis la phrase EN TEXTE ORDINAIRE.
   ⚠️ Le gras de `.msg-card-q` est fait pour les QUESTIONS TIRÉES — là, il est juste : c'est la
   question qu'on lit. Sur l'invitation il criait, alors qu'elle se lit comme une phrase dite. */
.msg-invite-icon { display: block; width: 46px; height: 46px; margin: 0 auto 8px; }
/* Un balancement à peine perceptible : la pile respire, elle n'attire pas l'œil à elle.
   ⚠️ LES DEUX PILES BALANCENT DU MÊME PAS (relevé par Gabriel, 24/08 : celle de la fenêtre ne
   bougeait pas). C'est le même objet vu à deux endroits — l'une immobile à côté de l'autre qui
   respire, on croit à une image cassée. Les deux sélecteurs partagent donc une seule déclaration :
   séparés, ils auraient fini par diverger. */
.msg-invite-icon, .cards-modal-deck img {
  animation: cardsSway 3.8s ease-in-out infinite; transform-origin: 50% 70%; }
@keyframes cardsSway { 0%, 100% { transform: translateY(0) rotate(-2.5deg); } 50% { transform: translateY(-3px) rotate(2.5deg); } }
@media (prefers-reduced-motion: reduce) {
  .msg-invite-icon, .cards-modal-deck img { animation: none; transform: none; } }
.msg-invite .msg-invite-text { font-weight: 400; color: var(--muted-foreground, #55647a); }
/* Le nom du jeu en tête de l'invitation : à l'encre, pas en gris (demande de Gabriel, 24/08).
   ⚠️ Sur la carte d'une QUESTION TIRÉE la pastille reste grise : là, c'est la question qu'on lit,
   et un second titre à l'encre lui disputerait le regard. */
.msg-invite .msg-card-tag { color: var(--foreground, #16202B); }
/* ⚠️ LES DEUX RÉPONSES SE VALENT (demande de Gabriel, 24/08). « Jouer » ne porte plus le bouton
   plein : accepter et remettre à plus tard s'offrent du même pas, sans que la mise en page pousse
   à l'un. Même largeur minimale, sinon « Jouer » ferait la moitié de son voisin. */
.msg-invite-btn { min-width: 132px; }
/* Invitation retirée : il ne reste qu'une ligne, en gris, sans icône ni bouton. */

/* La pile dessinée en tête de la fenêtre : elle dit de quoi il s'agit avant le moindre mot. */
/* ---- « Côté cœur » : le sommaire et ses rubriques ------------------------------------------
   Une rubrique se lit d'un coup d'œil : de quoi il s'agit, ce qu'elle contient, et si elle est
   prête. Même gabarit pour toutes — c'est un sommaire, pas une vitrine. */
.coeur-tiles { display: flex; flex-direction: column; gap: 12px; }
.coeur-tile { display: flex; align-items: center; gap: 15px; padding: 16px 18px; background: var(--card, #fff); border: 1px solid var(--hairline, rgba(34,62,99,.12)); border-radius: 16px; text-decoration: none; color: var(--foreground, #223E63); box-shadow: 0 1px 3px rgba(16,32,43,.05); transition: border-color .12s, box-shadow .12s; }
a.coeur-tile:hover { border-color: var(--primary, #223E63); box-shadow: 0 6px 20px rgba(34,62,99,.12); }
/* ⚠️ Une rubrique à venir ne se survole pas et n'attire pas l'œil : elle est annoncée, pas offerte. */
.coeur-tile.is-soon { opacity: .62; box-shadow: none; }
.coeur-tile-ic { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: 0 0 auto; border-radius: 13px; background: rgba(34,62,99,.06); color: var(--primary, #223E63); }
.coeur-tile-ic svg { width: 23px; height: 23px; }
/* ⚠️ 30 px et non 26 : ces icônes sont des ILLUSTRATIONS, pas des tracés d'un seul trait. Une
   bougie ou une tasse dessinée demande plus de surface qu'un contour pour se lire à cette taille.
   `object-fit: contain` est une ceinture : les cinq fichiers sont carrés, mais un remplacement mal
   recadré déformerait le dessin au lieu de le laisser respirer. */
.coeur-tile-ic img { display: block; width: 30px; height: 30px; object-fit: contain; }
.coeur-tile-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.coeur-tile-sub { font-size: .88rem; font-weight: 400; color: var(--muted-foreground, #6b7a90); line-height: 1.35; }
.coeur-tile-n { flex: 0 0 auto; min-width: 24px; padding: 2px 8px; border-radius: 999px; background: rgba(34,62,99,.09); font-size: .8rem; font-weight: 700; text-align: center; }
.coeur-tile-soon { flex: 0 0 auto; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--hairline, rgba(34,62,99,.14)); font-size: .74rem; font-weight: 700; letter-spacing: .03em; color: var(--muted-foreground, #6b7a90); }
.coeur-tile-arrow { flex: 0 0 auto; color: var(--muted-foreground, #6b7a90); font-size: 1.15rem; }

/* Le retour au sommaire, au-dessus du titre d'une rubrique. */
.coeur-back { display: inline-flex; align-items: center; gap: 5px; margin: 0 0 12px; font-size: .9rem; font-weight: 600; text-decoration: none; color: var(--muted-foreground, #6b7a90); }
.coeur-back:hover { color: var(--primary, #223E63); }
.coeur-back span { font-size: 1.25rem; line-height: 1; }

/* ---- « Premiers pas » en face à face : une carte, seule, au milieu de la table --------------
   Elle doit se lire à deux, depuis l'autre côté d'une table de café : grand corps, beaucoup d'air,
   rien autour. C'est la seule chose à regarder. */
.pp-intro { margin: -6px 0 22px; color: var(--muted-foreground, #6b7a90); }
.pp-carte { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; min-height: 230px; padding: 30px 26px; margin: 0 0 22px; background: var(--card, #fff); border: 1px solid var(--hairline, rgba(34,62,99,.14)); border-radius: 22px; box-shadow: 0 2px 4px rgba(16,32,43,.05), 0 14px 34px -22px rgba(34,62,99,.5); text-align: center; }
.pp-carte-tag { font-size: .7rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-foreground, #6b7a90); }
.pp-carte-q { margin: 0; font-size: 1.5rem; font-weight: 700; line-height: 1.35; color: var(--foreground, #223E63); }
/* Le dos du paquet, avant le premier tirage : il invite, il n'annonce rien. */
.pp-carte-dos { border-style: dashed; background: transparent; box-shadow: none; }
.pp-carte-dos img { opacity: .85; }
.pp-carte-invite { margin: 0; font-size: .95rem; color: var(--muted-foreground, #6b7a90); }
.pp-form { margin: 0; text-align: center; }
.pp-form .btn { min-width: 220px; }
.pp-reste { margin: 14px 0 0; text-align: center; font-size: .85rem; color: var(--muted-foreground, #6b7a90); }

/* La règle du jeu, en tête de la rubrique « Premiers pas ». */
.coeur-explain { display: flex; align-items: flex-start; gap: 16px; padding: 18px; margin: 0 0 18px; }
.coeur-explain img { flex: 0 0 auto; }
.coeur-explain h2 { margin: 0 0 4px; font-size: 1.05rem; }
.coeur-explain p { margin: 0; font-size: .92rem; line-height: 1.5; color: var(--muted-foreground, #6b7a90); }

/* Les conversations où l'on peut jouer. */
.coeur-convs { display: flex; flex-direction: column; gap: 10px; }
.coeur-conv { display: flex; align-items: center; gap: 14px; padding: 12px 16px; background: var(--card, #fff); border: 1px solid var(--hairline, rgba(34,62,99,.12)); border-radius: 14px; text-decoration: none; color: var(--foreground, #223E63); transition: border-color .12s; }
.coeur-conv:hover { border-color: var(--primary, #223E63); }
.coeur-conv-photo { width: 44px; height: 44px; flex: 0 0 auto; border-radius: 999px; background-size: cover; background-position: center; }
.coeur-conv-photo-vide { background: rgba(34,62,99,.08); }
.coeur-conv-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }

/* La ligne fine laissée là où la partie a commencé, une fois le panneau parti vers la dernière
   carte tirée. Elle reprend la forme du séparateur de jour — même famille, même discrétion — mais
   sans gras ni majuscules : c'est un repère dans le fil, pas un titre. */
.msg-gamestart span { font-weight: 500; text-transform: none; letter-spacing: 0;
  background: rgba(255,255,255,.75); box-shadow: none; border: 1px solid rgba(34,62,99,.10); }
.cards-modal-deck { display: flex; justify-content: center; margin: 2px 0 6px; }
.cards-modal-deck img { display: block; width: 56px; height: 56px; }
/* Le contenu de la fenêtre du jeu est centré (demande de Gabriel, 24/08) : une icône centrée
   surmontant un titre et un texte calés à gauche donnait un bloc de travers. */
.cards-modal .like-modal-inner { text-align: center; }
.cards-modal .like-modal-inner h2 { margin: 0 0 6px; }
/* ⚠️ PAS DE LARGEUR BRIDÉE ICI. Mon `max-width: 34ch` resserrait le texte à 274 px dans une carte
   qui en offre 404 : avec un prénom un peu long, la phrase tombait sur quatre lignes dont un
   « tour ! » tout seul à la fin — un bloc de travers, qu'on lit comme « mal centré » (relevé par
   Gabriel, 24/08). Sans le bridage et avec des lignes équilibrées : deux lignes de même longueur. */
.cards-modal .modal-hint, .cards-modal .like-modal-inner h2 { text-wrap: balance; }
.prayer-del { color: #c0392b; border-color: rgba(192, 57, 43, .35); }
.prayer-del:hover { background: #c0392b; border-color: #c0392b; color: #fff; }
.prayer-off td { opacity: .55; }
/* La prière elle-même, dans la fenêtre servie au membre. */
.prayer-text { margin: 6px 0 14px; line-height: 1.65; }
.prayer-text:last-child { margin-bottom: 4px; }

/* Mains jointes en place de l'emoji 🙏 (carte de prière et fenêtres).
   `line-height: 0` : la boîte d'une image en ligne traîne sinon quelques pixels de blanc sous elle,
   qui désalignent l'écart avec le texte réglé par `.state-emoji`. */
.state-icon { line-height: 0; }
.state-icon { margin-bottom: 18px; }
.state-icon img { height: 78px; width: auto; }
/* Pastille de type dans la liste des prières. */
.prayer-kind { display: inline-block; margin-top: 4px; padding: 1px 8px; border-radius: 999px; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.prayer-kind-courte { background: var(--muted); color: var(--primary); }
.prayer-kind-longue { background: #e7edf6; color: #2f4a73; }
.prayer-form select { width: 100%; padding: 11px 14px; font: inherit; color: var(--foreground); background: var(--background); border: 1px solid var(--border); border-radius: 10px; }

/* Bascule courte/longue en LIENS (filtre d'URL) : mêmes formes que .seg-toggle, sans radio.
   Le « thumb » se déplace via une classe sur le conteneur au lieu d'un :checked. */
.seg-links { width: 300px; }
.seg-links .seg-opt { text-decoration: none; }
.seg-links .seg-opt.is-on { color: var(--primary); }
.seg-links.is-second .seg-thumb { transform: translateX(100%); }
/* Les tuiles de synthèse remplacent les deux paragraphes d'explication. */
.prayer-kpis { margin: 0 0 22px; }

/* Entête de la page Prières : titre à gauche, bouton « Ajouter une prière » à droite (repli). */
.prayer-page-head .admin-h1 { margin: 0; margin-right: auto; }
.prayer-add-toggle { display: inline-flex; align-items: center; gap: 7px; }
.prayer-add-chevron { transition: transform .18s ease; }
.prayer-add-toggle[aria-expanded="true"] .prayer-add-chevron { transform: rotate(180deg); }
/* Partage d'une prière longue. Bouton discret, sous les vers : il ne doit pas concurrencer la
   prière elle-même. */
.prayer-share { margin-top: 16px; display: flex; flex-direction: column; align-items: center; gap: 6px; }
/* Pictogramme seul : la cible de doigt reste large (40 px) même si le dessin est petit. */
/* ⚠️ Le signet reprend EXACTEMENT le gabarit du partage : ils sont côte à côte, ils doivent peser
   pareil. Une seule déclaration pour les deux — recopiée, elle aurait divergé à la 1re retouche. */
.prayer-save-btn,
.prayer-share-btn { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 1px solid var(--hairline); border-radius: 50%; background: transparent; color: var(--primary); cursor: pointer; transition: background .15s, border-color .15s; }
/* Enregistrée : le signet se remplit. C'est le seul état à montrer, et il se voit d'un coup d'œil. */
/* La rangée des deux boutons, sous la prière. */
.prayer-actions { display: flex; align-items: center; justify-content: center; gap: 10px; }
/* ⚠️ DANS LA FENÊTRE DE PRIÈRE SEULEMENT (demande de Gabriel, 24/08 : moins d'air autour des
   boutons, et le MÊME écart en haut et en bas). Mesuré avant : 25 px au-dessus du titre contre
   45 px sous les boutons — trois marges empilées (celle du paragraphe, celle de `.prayer-share`,
   celle de `.prayer-actions`) plus le rembourrage du bas. On retire les deux marges propres aux
   boutons : il ne reste sous eux que le rembourrage de la fenêtre, égal à celui du haut.
   ⚠️ Scopé à `.like-modal` : `.prayer-actions` sert AUSSI aux deux boutons de la carte
   « Aujourd'hui », dont l'espacement n'est pas en cause. */
/* Et les marges propres du premier et du dernier bloc — 2 px en haut, 4 en bas sur la variante
   sans boutons : peu de chose, mais assez pour rompre l'égalité demandée.
   ⚠️ Visé par `:has(.prayer-text)`, donc les fenêtres de PRIÈRE seulement : la trentaine d'autres
   `.like-modal` de l'application n'a pas à changer d'aplomb pour autant. */
.like-modal-inner:has(.prayer-text) > .prayer-modal-title:first-of-type { margin-top: 0; }
.like-modal-inner:has(.prayer-text) > *:last-child { margin-bottom: 0; }
.like-modal .prayer-share { margin-top: 12px; }
.like-modal .prayer-share .prayer-actions { margin: 0; }
.prayer-save-btn.is-on { color: var(--primary, #223E63); }
.prayer-save-btn.is-on svg { fill: currentColor; }
.prayer-save-btn[disabled] { opacity: .5; cursor: default; }

/* La page « Mes prières enregistrées ». */
/* « Mes prières enregistrées » : une liste de BOUTONS, plus un mur de texte (demande de Gabriel,
   24/08). Le titre en gras, l'auteur dessous ; le texte s'ouvre dans une fenêtre. Les cartes
   dépliées (`.prieres-gardees`, `.priere-gardee`) n'ont plus d'emploi et sont retirées. */
.priere-liste { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 520px; margin-inline: auto; }
.priere-choix { display: flex; flex-direction: column; align-items: center; gap: 2px;
  width: 100%; padding: 16px 20px; border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--card); color: inherit; cursor: pointer; text-align: center;
  transition: border-color .15s, box-shadow .15s, transform .15s; }
.priere-choix:hover { border-color: rgba(34,62,99,.28); box-shadow: 0 6px 18px -12px rgba(34,62,99,.5); }
.priere-choix:active { transform: scale(.995); }
.priere-choix-t { font-weight: 700; font-size: 1.04rem; color: var(--foreground); }
.priere-choix-a { font-size: .88rem; font-style: italic; color: var(--muted-foreground); }
.prayer-save-btn svg,
.prayer-share-btn svg { width: 20px; height: 20px; }
.prayer-save-btn:hover,
.prayer-share-btn:hover { background: var(--muted); border-color: var(--primary); }
.prayer-share-note { font-size: .82rem; color: var(--muted-foreground); }
.prayer-share-note:empty { display: none; }
/* Aperçu d'une prière depuis le back-office : rendu réel, sans annotation. */
.prayer-pv { display: inline-flex; align-items: center; gap: 6px; }
.prayer-pv svg { width: 15px; height: 15px; flex-shrink: 0; }

/* Relevé « Santé des photos » (Réglages) : la liste des membres touchés peut être longue et large.
   ⚠️ La classe `.table-wrap` que j'avais d'abord écrite N'EXISTAIT PAS dans cette feuille — un nom
   inventé ne met rien en forme, et le tableau serait sorti de la carte sur une fenêtre étroite. */
.photos-sante-table { overflow-x: auto; margin: 10px 0 4px; }
.photos-sante-table table { min-width: 520px; }

/* Chiffres du Jeu des cartes : mêmes cases que le tableau de bord, avec de l'air autour.
   ⚠️ Jumelle de `.prayer-kpis` (l. 3686) : deux pages d'administration posent la même grille sous
   un en-tête sans marge basse. Deux règles d'une ligne valent mieux qu'un nom de page mensonger
   appliqué à l'autre — si une troisième arrive, il sera temps de les réunir. */
.cards-kpis { margin: 18px 0 22px; }

/* Symbole « a déjà des enfants », à côté de la ville sur la fiche profil.
   ⚠️ `vertical-align: -3px` et non `middle` : la ligne de la ville est du texte, l'icône un bloc
   inline — `middle` la posait 2 px trop haut, l'œil voyait un symbole qui flotte. */
/* Symbole « a déjà des enfants », sur la ligne du prénom. C'est un BOUTON : au survol le `title`
   suffit sur ordinateur, mais sur téléphone il n'existe pas — et c'est là que la fiche se lit. Le
   clic ouvre la même phrase, posée juste à côté. */
.card-kid { position: relative; display: inline-flex; align-items: center; margin-left: 10px;
  vertical-align: middle; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--muted-foreground); }
.card-kid img { width: 20px; height: 20px; display: block; }
/* Repli sans genre : un trait, pas un dessin plein — il n'a pas la pastille claire des deux autres,
   donc il se lit mieux un poil plus petit. */
.card-kid-neutre svg { width: 18px; height: 18px; }
/* La phrase, repliée par défaut. ⚠️ `white-space: nowrap` + `position: absolute` : posée dans le
   flux, elle poussait le prénom et faisait sauter la ligne à chaque survol. */
.card-kid-mot { position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
  white-space: nowrap; background: var(--primary); color: #fff; font: 500 .78rem/1.3 inherit;
  padding: 6px 10px; border-radius: 8px; opacity: 0; visibility: hidden; transition: opacity .12s ease;
  pointer-events: none; z-index: 5; }
.card-kid:hover .card-kid-mot, .card-kid:focus-visible .card-kid-mot,
.card-kid.is-open .card-kid-mot { opacity: 1; visibility: visible; }
/* Sur écran étroit, la bulle peut sortir de la carte : on la cale à gauche du bouton. */
@media (max-width: 520px) {
  .card-kid-mot { left: auto; right: 0; transform: none; }
}

/* Corbeille → « Répondre » : lettre libre à quelqu'un qui vient de partir. */
.treply-inner { max-width: 560px; }
.treply-cible { margin: 4px 0 0; }
.treply-motif { margin: 8px 0 0; padding: 10px 12px; border-radius: 10px; background: var(--muted);
  color: var(--muted-foreground); font-size: .9rem; line-height: 1.45; }
.treply-alerte { margin: 10px 0 0; padding: 10px 12px; border-radius: 10px; background: #FBF0DC;
  color: #7A5A1F; font-size: .88rem; line-height: 1.45; }
.treply-text { width: 100%; box-sizing: border-box; margin: 14px 0 0; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 12px; font: inherit; line-height: 1.5; resize: vertical; }
.treply-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; flex-wrap: wrap; }

/* ---- Concours : le cadeau du moment (côté membre) ---- */
/* ---- Le concours, côté membre -------------------------------------------------------------
   Trois temps, trois cartes : ce qu'il y a à gagner, où j'en suis, comment en gagner. La colonne
   est étroite et centrée — c'est une page qu'on lit d'un coup d'œil, pas un tableau de bord. */
/* ⚠️ CE SONT LES CARTES QU'ON CENTRE, PAS LE CONTENEUR — même choix que pour « Premiers pas » et
   « Mes prières » plus haut. Une largeur posée sur le conteneur perd de toute façon contre
   `.has-appnav .app-view > .container` (0,3,0), qui le fige à 720 px collé à gauche : la colonne
   se retrouvait à 48 px du bord gauche pour 72 à droite. Mesuré au navigateur, pas deviné.
   Les cartes portent donc leur propre largeur et leurs marges automatiques (voir `.cc-card`) ;
   le conteneur, lui, reprend toute la place et laisse tout se centrer sur le même axe. */
.cc-view { text-align: center; }
.cc-title { margin-bottom: 12px; }
/* Jusqu'à quand court le concours : ça se lit sous le titre, avant de regarder le lot. Les dates
   à gauche, le compte à rebours à droite — l'une situe, l'autre presse. */
.cc-periode-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px 12px; margin: 0 auto 18px; max-width: 460px; }
.cc-card { background: var(--card); border: 1px solid var(--hairline); border-radius: 22px;
  padding: 26px 24px; margin: 0 auto 14px; max-width: 460px;
  box-shadow: 0 1px 3px rgba(16,32,43,.05), 0 16px 40px -28px rgba(34,62,99,.45); }

/* Le cadeau posé sur un halo doré : il a l'air offert, pas déposé là. */
.cc-gift { width: 178px; height: 178px; margin: 2px auto 16px; display: grid; place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 46%, rgba(176,138,79,.22) 0%, rgba(176,138,79,.10) 48%, rgba(176,138,79,0) 70%); }
.cc-gift img { width: 150px; height: 150px; object-fit: contain; }
.cc-gift-label { font-size: 1.18rem; font-weight: 700; line-height: 1.4; color: var(--foreground); margin: 0; }
.cc-gift-details { color: var(--muted-foreground); line-height: 1.55; margin: 10px 0 0; font-size: .95rem; }

/* Ce qui presse porte la pastille ; les dates exactes la suivent, en retrait. */
.cc-compte { display: inline-block; margin: 0; padding: 5px 14px; border-radius: 999px; order: 2;
  background: rgba(34,62,99,.07); color: var(--primary); font-size: .84rem; font-weight: 700;
  letter-spacing: .01em; }
.cc-compte.is-urgent { background: var(--rose-soft); color: #A6416E; }
.cc-periode { color: var(--muted-foreground); font-size: .84rem; margin: 0; order: 1; }

/* ---- Le ticket ----------------------------------------------------------------------------
   C'est un OBJET qu'on envoie, pas un solde qu'on consulte : une souche, une perforation, deux
   encoches. ⚠️ Les encoches sont peintes de la couleur de la CARTE qui le porte — c'est ce qui
   donne l'illusion du papier découpé ; sur un autre fond, il faudrait les repeindre. */
.cc-ticket { position: relative; display: inline-flex; align-items: center; text-align: left;
  max-width: 330px; margin: 0 auto; padding: 16px 20px; border-radius: 16px; color: #fff;
  background: linear-gradient(135deg, #2C4E7C 0%, var(--primary-deep) 100%);
  /* ⚠️ LES ENCOCHES SONT DE VRAIS TROUS, découpés dans le ticket par un masque — et non deux
     cercles peints de la couleur du fond. Les peindre supposait un fond uni : la carte blanche
     retirée (26/08), il ne reste que l'ivoire de la page ET son dégradé, sur lequel deux pastilles
     blanches se verraient. Un masque, lui, laisse passer ce qu'il y a derrière, quel qu'il soit.
     ⚠️ Le masque rogne aussi l'ombre portée : elle est donc retirée, pas seulement invisible. */
  -webkit-mask:
    radial-gradient(circle 11px at 0 50%, transparent 98%, #000 100%) left / 50.5% 100% no-repeat,
    radial-gradient(circle 11px at 100% 50%, transparent 98%, #000 100%) right / 50.5% 100% no-repeat;
  mask:
    radial-gradient(circle 11px at 0 50%, transparent 98%, #000 100%) left / 50.5% 100% no-repeat,
    radial-gradient(circle 11px at 100% 50%, transparent 98%, #000 100%) right / 50.5% 100% no-repeat; }
.cc-ticket-n { flex: 0 0 auto; padding-right: 18px; margin-right: 18px; text-align: center;
  border-right: 2px dashed rgba(255,255,255,.38); }
.cc-ticket-n strong { display: block; font-family: var(--font-round); font-size: 2.5rem; font-weight: 800;
  line-height: 1; }
.cc-ticket-n span { display: block; margin-top: 3px; font-size: .7rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; opacity: .82; }
.cc-ticket-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cc-ticket-t { font-size: 1rem; font-weight: 700; line-height: 1.3; }
.cc-ticket-s { font-size: .8rem; line-height: 1.35; opacity: .78; }
/* Déjà parti : le ticket est une souche, plus une promesse. (Pas de bordure : le masque la
   couperait au milieu des encoches, ce qui donnerait deux traits pendants.) */
.cc-ticket.is-sent { background: var(--muted); color: var(--foreground); }
.cc-ticket.is-sent .cc-ticket-n { border-right-color: var(--border); }
.cc-ticket.is-sent .cc-ticket-n strong { color: var(--primary); }
.cc-ticket.is-sent .cc-ticket-txt { color: var(--muted-foreground); }
.cc-tickets-vide { margin: 0; font-size: .98rem; line-height: 1.55; color: var(--muted-foreground); }
.cc-tickets-sub { color: var(--muted-foreground); font-size: .9rem; line-height: 1.5; margin: 12px 0 0; }
/* ⚠️ PAS DE CARTE AUTOUR DU TICKET (demande de Gabriel, 26/08) : le ticket est déjà un objet
   dessiné, l'enfermer dans une seconde boîte blanche faisait un cadre dans un cadre.
   ⚠️ L'AIR AU-DESSUS EST À REFAIRE À LA MAIN : la carte apportait 26 px de rembourrage, et sans
   elle le ticket se retrouvait collé sous la carte du cadeau — « un peu serré », dit Gabriel. */
.cc-card-play { background: none; border: 0; box-shadow: none; padding: 14px 0 6px; margin-top: 8px; }
/* Le bouton porte le geste : large, mais pas d'un bord à l'autre — il reste un objet, pas une barre. */
.cc-jouer { margin: 20px 0 0; }
.cc-jouer .btn { width: 100%; max-width: 300px; }
/* ⚠️ La bordure générique de `.btn-outline` est une hairline (10 % d'opacité) : sur l'action
   principale d'une page, elle disparaissait presque. On la marque, sans revenir à l'aplat. */
.cc-jouer .btn-outline { border-color: rgba(34,62,99,.32); font-weight: 700; }
.cc-jouer .btn-outline:hover { border-color: var(--primary); background: var(--muted); }
.cc-jouer-sub { color: var(--muted-foreground); font-size: .88rem; margin: 10px 0 0; }
.cc-total { color: var(--muted-foreground); font-size: .82rem; margin: 16px 0 0; opacity: .8; }

/* ---- « Comment gagner des tickets ? » : un dépliant, fermé au départ -----------------------
   ⚠️ `<details>` natif plutôt qu'un bouton et du JavaScript : ça s'ouvre au clavier, ça reste
   ouvrable si un script échoue, et la page n'a aucun script en ligne à faire autoriser. */
.cc-gestes { text-align: left; padding: 16px 22px; }
.cc-gestes-t { display: flex; align-items: center; gap: 10px; font-weight: 700; color: var(--foreground);
  margin: 0; font-size: .95rem; cursor: pointer; list-style: none; }
/* Safari dessine sinon son propre triangle, en plus du nôtre. */
.cc-gestes-t::-webkit-details-marker { display: none; }
/* Le chevron (`.dep-chev`, défini une seule fois plus haut) est ici poussé à droite du titre. */
.cc-gestes-t .dep-chev { margin-left: auto; color: var(--muted-foreground); }
.cc-gestes ul { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 12px; }
.cc-geste { display: flex; align-items: center; gap: 11px; color: var(--foreground);
  font-size: .95rem; line-height: 1.45; }
/* La pastille dit d'un coup d'œil si c'est fait aujourd'hui — un point creux, ou une coche pleine. */
.cc-geste-mark { flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  border-radius: 50%; background: var(--muted); color: var(--muted-foreground);
  font-size: .78rem; font-weight: 700; line-height: 1; }
.cc-geste-mark svg { width: 14px; height: 14px; }
.cc-geste.is-done .cc-geste-mark { background: #DCEFE4; color: #2E8F6B; }
.cc-geste-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cc-geste-txt a { color: var(--primary); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.cc-geste-note { font-size: .82rem; color: var(--muted-foreground); line-height: 1.35; }
.cc-geste-gain { margin-left: auto; padding: 3px 9px; border-radius: 999px; background: var(--muted);
  font-size: .76rem; font-weight: 600; color: var(--muted-foreground); white-space: nowrap; }

/* ---- Parrainer un ami ---------------------------------------------------------------------
   Une seule chose à faire : partager son lien. Le reste rend compte. */
.pa-view { text-align: center; }
/* ⚠️ SON PROPRE TITRE, et pas celui du dépliant : `.cc-gestes-t` porte désormais un chevron, qui
   s'était invité ici sur un bloc qui ne s'ouvre pas — il promettait un pli inexistant. */
.pa-titre { font-weight: 700; color: var(--foreground); margin: 0; font-size: .95rem; }
.pa-intro { margin: 0 0 14px; line-height: 1.55; color: var(--foreground); }
/* Le lien doit se lire ET se sélectionner à la main : il se coupe où il peut, jamais hors de la carte. */
.pa-lien { margin: 0 0 16px; padding: 12px 14px; border-radius: 14px; background: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .86rem; line-height: 1.45;
  color: var(--foreground); overflow-wrap: anywhere; user-select: all; }
/* ⚠️ La bordure générique de `.btn-outline` est une hairline à 10 % : sur les deux seules actions
   de la page, elle disparaissait presque. Même traitement que le bouton d'envoi du concours. */
.pa-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.pa-actions .btn-outline { border-color: rgba(34,62,99,.32); font-weight: 700; }
.pa-actions .btn-outline:hover { border-color: var(--primary); background: var(--muted); }
.pa-actions .btn { flex: 1 1 auto; min-width: 150px; }
.pa-chiffres { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 14px 0 0; }
.pa-chiffre { padding: 12px 6px; border-radius: 14px; background: var(--muted); }
.pa-chiffre strong { display: block; font-family: var(--font-round); font-size: 1.7rem; font-weight: 800;
  line-height: 1; color: var(--primary); }
.pa-chiffre span { display: block; margin-top: 5px; font-size: .78rem; line-height: 1.3;
  color: var(--muted-foreground); }
/* Ce qui a été gagné se distingue de ce qui a été compté. */
.pa-chiffre-fort { background: rgba(176,138,79,.14); }
.pa-chiffre-fort strong { color: #8A6A34; }
.pa-vide { margin: 14px 0 0; font-size: .9rem; line-height: 1.55; color: var(--muted-foreground); }

/* Le résultat, une fois tiré : c'est la seule chose que le membre vient chercher. */
.cc-win { background: #E6F3EC; border-color: rgba(46,143,107,.22); color: #1F6B4E; }
.cc-win-emoji { font-size: 2.6rem; line-height: 1; margin: 0 0 10px; }
.cc-win-t { font-size: 1.32rem; font-weight: 800; margin: 0; line-height: 1.3; }
.cc-win-s { margin: 8px 0 0; font-size: .95rem; line-height: 1.55; opacity: .88; }
.cc-win-other { background: var(--card); border-color: var(--hairline); color: var(--foreground); }
.cc-win-other .cc-win-t { font-size: 1.15rem; font-weight: 700; }
.cc-win-other .cc-win-s { color: var(--muted-foreground); opacity: 1; }
/* ⚠️ DE L'AIR SOUS LE DERNIER ÉLÉMENT : la barre de navigation du membre est FIXÉE en bas, et sur
   une fenêtre étroite le lien se retrouvait à quelques dizaines de pixels d'elle — assez pour qu'on
   le croie coupé. (Mesuré : jamais recouvert, mais la marge était mince.) */
.cc-legal { margin: 20px 0 28px; font-size: .84rem; }
.cc-legal a { color: var(--muted-foreground); text-decoration: underline; text-underline-offset: 3px; }
.cc-legal a:hover { color: var(--primary); }

@media (max-width: 480px) {
  .cc-card { padding: 22px 18px; border-radius: 20px; }
  .cc-gift { width: 150px; height: 150px; }
  .cc-gift img { width: 126px; height: 126px; }
  .cc-tickets strong { font-size: 2.8rem; }
}
/* Concours — back-office */
.cc-adm-head { margin-bottom: 20px; }
.cc-adm-head .admin-h1 { margin-bottom: 5px; }
.cc-adm-sub { margin: 0; color: var(--muted-foreground); font-size: .92rem; }
.cc-adm-kpis { margin-bottom: 14px; }
.cc-adm-export { margin: 0 0 22px; }
/* Le contenu à gauche, la période et l'état à droite. `align-items: start` n'est pas décoratif :
   sans lui la colonne de droite s'étire sur toute la hauteur et son `sticky` n'a pas de place où
   glisser — le bouton d'enregistrement redeviendrait inatteignable pendant qu'on écrit. */
.cc-adm-cols { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 20px; align-items: start; }
.cc-adm-main { min-width: 0; display: grid; gap: 20px; }
.cc-adm-side { position: sticky; top: 24px; min-width: 0; }
.cc-adm-cols .settings-card { margin-bottom: 0; }
.cc-adm-cols .edit-field { margin-top: 0; }
.cc-adm-save { margin-top: 4px; }
.cc-adm-voir { margin: 0; text-align: center; }
.cc-adm-voir a { color: var(--primary); font-weight: 600; text-decoration: none; }
.cc-adm-voir a:hover { text-decoration: underline; }
/* Aperçu de la page membre (modale du back-office).
   ⚠️ PLUS LARGE QUE LES AUTRES MODALES : .like-modal-inner est calée sur 460 px, taille d'une
   fenêtre de décision. Ici on regarde une PAGE — au format du téléphone, mais avec la place de
   la lire. `min()` avec la hauteur d'écran pour que le cadre ne dépasse jamais le pli. */
.cc-apercu-inner { max-width: 560px; }
.cc-apercu-frame { border: 1px solid var(--hairline); border-radius: 14px; overflow: hidden;
  background: var(--muted); height: min(70vh, 760px); }
.cc-apercu-frame iframe { display: block; width: 100%; height: 100%; border: 0; }
/* Le bandeau qui coiffe l'aperçu — dans le cadre, pas autour : c'est la page qui est un aperçu,
   et l'information doit rester avec elle si on ouvre l'adresse directement. */
.cc-apercu-bar { background: var(--primary); color: #fff; font-size: .78rem; line-height: 1.45;
  padding: 9px 14px; text-align: center; }
/* ⚠️ APERÇU INERTE, ET C'EST UNE GARDE, PAS UNE FINITION. La page rendue est la VRAIE page : ses
   liens de navigation mèneraient hors de l'aperçu au premier clic distrait, et le cadre
   afficherait alors une redirection de connexion — on croirait l'aperçu cassé. Le formulaire
   d'envoi de tickets, lui, n'est même pas émis (plv_contest_view_inner($apercu = true)) : deux
   gardes, parce qu'une règle de style ne doit jamais être la seule chose qui empêche une
   écriture. */
body.is-apercu a, body.is-apercu button, body.is-apercu input, body.is-apercu summary,
body.is-apercu details { pointer-events: none; }
body.is-apercu .cc-apercu-bar { pointer-events: auto; }
/* Le détail « Comment gagner des tickets ? » est replié par défaut : dans un aperçu figé, on ne
   pourrait plus l'ouvrir — donc on le montre déplié, puisque c'est aussi ce que le membre lit. */
body.is-apercu details.cc-gestes > ul { display: block; }
@media (max-width: 1080px) {
  .cc-adm-cols { grid-template-columns: 1fr; }
  .cc-adm-side { position: static; }
}
.cc-adm-table { overflow-x: auto; margin: 8px 0 0; }
.cc-adm-img { display: flex; gap: 16px; align-items: flex-start; margin-top: 6px; }
.cc-adm-img img { width: 96px; height: 96px; padding: 6px; box-sizing: border-box; border-radius: 14px;
  object-fit: contain; background: var(--muted); flex: 0 0 auto; }
.cc-adm-img-body { min-width: 0; flex: 1; }
/* Le champ de fichier brut du navigateur ne dit ni ce qu'il attend ni ce qu'on a choisi : on
   reprend le bouton du téléversement de photo, et le nom du fichier s'affiche dessous. */
.cc-adm-upload { display: inline-block; width: auto; padding: 10px 18px; margin-bottom: 9px; font-size: .92rem; }
.cc-adm-fname { margin: 0 0 6px; font-weight: 700; color: var(--primary); overflow-wrap: anywhere; }
/* ⚠️ `.edit-field input { width: 100% }` VISE AUSSI LES CASES À COCHER : la case s'étirait sur
   toute la largeur (mesuré : 1 018 px) et écrasait son propre libellé, réduit à un mot par ligne.
   Le sélecteur d'attribut (0,2,1) reprend la main sans toucher aux champs texte. */
.cc-check { display: flex; align-items: flex-start; gap: 10px; margin-top: 0; text-align: left; }
.cc-check input[type="checkbox"] { flex: 0 0 auto; width: 18px; height: 18px; margin: 1px 0 0;
  padding: 0; accent-color: var(--primary); cursor: pointer; }
.cc-check > span { display: block; min-width: 0; font-size: .9rem; }
.cc-check strong { display: block; color: var(--foreground); }
.cc-check em { display: block; margin-top: 3px; font-style: normal; font-size: .82rem;
  line-height: 1.45; color: var(--muted-foreground); }
.cc-adm-img-body .cc-check { margin-top: 10px; }
.cc-adm-clear { font-size: .88rem; color: var(--muted-foreground); }
.cc-adm-gagnant { margin-bottom: 20px; }
.cc-adm-tirage { margin-bottom: 20px; }
.cc-adm-urne { margin: 0; }
.cc-adm-urne strong { font-family: var(--font-round); font-size: 1.5rem; color: var(--primary); }
/* Reconduire et supprimer ne sont pas le sujet de la page : côte à côte, ils cessent d'occuper
   deux pleines largeurs sous le contenu. */
.cc-adm-bas { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 6px; }
.cc-adm-bas > form { display: flex; margin: 0; }
.cc-adm-bas .settings-card { width: 100%; margin: 0; }
@media (max-width: 900px) { .cc-adm-bas { grid-template-columns: 1fr; } }
/* Sur un téléphone, la vignette et son bouton côte à côte ne laissent que ~116 px au bouton :
   « Choisir une image » passait sur deux lignes et l'explication devenait un ruban. On empile. */
@media (max-width: 560px) {
  .cc-adm-img { flex-direction: column; align-items: stretch; }
  .cc-adm-img-body { flex: 0 0 auto; }
  .cc-adm-upload { display: block; width: 100%; text-align: center; }
}
/* L'envoi au gagnant est un acte : il a sa propre carte, séparée du suivi. */
.cc-adm-notify { padding: 14px 16px; margin: 10px 0 16px; border-radius: 14px; background: var(--muted); }
.cc-adm-notify .hint { margin: 0 0 10px; }
/* ⚠️ PAS `.settings-form` : celui-ci est un `column-count: 2`, et une carte seule s'y rangerait
   dans la colonne de gauche, sur la moitié de la largeur. Le concours n'a qu'une carte. */
.cc-adm-form { margin: 4px 0 20px; }
/* L'état d'un concours se lit d'un coup d'œil dans la liste : « à tirer » demande une action, il
   ne doit pas ressembler à « terminé ». */
.cc-etat { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: .74rem;
  font-weight: 700; letter-spacing: .02em; vertical-align: middle; background: var(--muted);
  color: var(--muted-foreground); }
.cc-etat-en_cours { background: #DCEFE4; color: #2E6B4F; }
.cc-etat-a_tirer  { background: #FBEBD2; color: #8A5B12; }
.cc-etat-a_venir  { background: #E4ECF6; color: #2C4E7C; }
.cc-etat-tire     { background: rgba(34,62,99,.10); color: var(--primary); }
.cc-etat-inactif, .cc-etat-neuf { background: var(--muted); color: var(--muted-foreground); }
.cc-histo { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; font-size: .9rem; }
.cc-histo li { padding-bottom: 8px; border-bottom: 1px solid var(--hairline); }
.cc-histo li:last-child { border-bottom: 0; }
/* Un règlement se relit : la saisie doit respirer, en largeur comme en interligne. */
.cc-adm-regl { width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .86rem; line-height: 1.6; }

/* Page « Signaler quelqu'un » — la porte de secours quand la conversation est fermée (v1225).
   ⚠️ Chaque personne est un <details> : la liste reste lisible même avec cent rencontres, et le
   formulaire ne s'ouvre que pour celle qu'on vise. */
.signaler-item { padding: 0; margin-bottom: 10px; }
.signaler-item > summary { cursor: pointer; padding: 14px 18px; list-style: none; }
.signaler-item > summary::-webkit-details-marker { display: none; }
.signaler-item > summary::after { content: '+'; float: right; color: var(--muted, #6b7480); font-weight: 600; }
.signaler-item[open] > summary::after { content: '−'; }
.signaler-item > summary:hover { background: rgba(34, 62, 99, .04); }
.signaler-form { padding: 4px 18px 18px; }
.signaler-form .report-label { display: block; margin: 10px 0 4px; font-weight: 600; font-size: .92rem; }
/* ⚠️ `font: inherit` sur les DEUX : un <textarea> hérite de la police à chasse fixe du navigateur,
   et un <select> d'Arial — mesuré sur cette page, où ils juraient avec l'Inter de tout le reste. */
.signaler-form textarea,
.signaler-form select { font: inherit; width: 100%; }
.signaler-form textarea { min-height: 78px; padding: 10px 12px; }

/* Outil « flouter un visage » de la visionneuse de modération. Le disque montre EN DIRECT le rendu :
   backdrop-filter floute la photo derrière lui, et le masque radial reproduit le fondu du serveur
   (plein jusqu'à 55 % du rayon, nul au bord). Le liseré n'existe QUE dans l'éditeur — il ne part
   jamais dans le fichier — mais sans lui un disque posé sur un aplat serait introuvable à l'œil. */
.lb-blur { position: absolute; inset: 0; cursor: crosshair; touch-action: none; }
.lb-blur-dot { position: absolute; transform: translate(-50%, -50%); border-radius: 50%; cursor: move; touch-action: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .38);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  -webkit-mask-image: radial-gradient(circle closest-side, #000 55%, rgba(0, 0, 0, 0) 100%);
  mask-image: radial-gradient(circle closest-side, #000 55%, rgba(0, 0, 0, 0) 100%); }
.lb-blur-actions { align-items: center; flex-wrap: wrap; justify-content: center; }
/* Sur un panneau étroit, « Valider le flou » se coupait en deux lignes : la barre a le droit de
   passer à la ligne, le libelle d'un bouton non. */
.lb-blur-actions .lb-act { white-space: nowrap; }
.lb-blur-size { display: flex; align-items: center; gap: 9px; padding: 9px 16px; border-radius: 999px;
  background: rgba(255, 255, 255, .92); color: #16202B; font-size: .82rem; font-weight: 700;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .3); }
.lb-blur-size input[type="range"] { width: 120px; accent-color: var(--primary); cursor: pointer; }

/* Messagerie — audit du 31/08 : le bouton qui charge le passé, et la note de session expirée. */
.conv-older { text-align: center; padding: 10px 0 4px; }
.conv-session-expiree { margin: 8px 12px; padding: 10px 14px; border-radius: 12px; background: #FBEFDD;
  border: 1px solid #E8CFA6; color: #6B4E1F; font-size: .92rem; text-align: center; }
.conv-session-expiree a { color: inherit; font-weight: 700; }

/* Encadré « Et la messe ? » de l'étape Ma Foi : il descend sous les autres cases et respire un peu
   (demande de Gabriel, 01/09). La grille interne est déjà portée par .radio-cards. */
.ob-messe { margin: 18px 0 22px; }
.ob-messe .field-help { margin: -4px 0 12px; }

/* Le rythme de messe manquant, dit dans l'encadré même — la question est en bas d'un long
   formulaire, un message en tête de page serait hors de vue (01/09). */
.ob-messe .field-error { margin: -4px 0 12px; color: var(--danger, #b3261e); font-size: .92rem; font-weight: 600; }

/* La précision d'une pastille (« geste non enregistré ») : lue, jamais survolée — un écran tactile
   n'a pas de survol, et cette nuance change la lecture du chiffre qu'elle suit. */
.hist-stat i { font-style: normal; font-size: .74rem; opacity: .72; }
.hist-stat i::before { content: '· '; }

/* Panneau « Campagnes » de la page E-mails : où en est un envoi groupé, et une relance ferait-elle
   des doublons. L'état de la fenêtre anti-doublon est la seule information colorée — c'est la seule
   sur laquelle on peut se tromper de façon coûteuse. */
.camp-sub { display: block; font-size: .8rem; color: var(--muted-foreground); margin-top: 2px; }
.camp-num { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.camp-ok, .camp-go, .camp-danger { display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-size: .82rem; font-weight: 600; }
.camp-ok     { background: #E6F3EC; color: #2E8F6B; }
.camp-go     { background: #EDF1FB; color: #223E63; }
.camp-danger { background: #FBEDEB; color: #B0453B; }
.camp-muted  { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: .82rem;
  font-weight: 600; background: #F0F2F5; color: #6B7280; }

/* Le champ « Pays (saisi librement) » a son propre menu, sous la case — comme la ville. Il lui faut
   son conteneur positionné : .geo-suggest se place en `top:100%` de son ancêtre positionné, et sans
   ce span il serait tombé sous TOUT le bloc géo (donc sous la ville), pas sous le champ. */
.world-autocomplete { position: relative; display: block; }
