@charset "UTF-8";
/* =====================================================================
   SYSTÈME DE STYLES — APPLICATION MOBILE
   =====================================================================

   Remplace Materialize CSS, dont le développement est arrêté depuis
   2018 et qui est classé « maintenance inactive » : aucune version
   publiée depuis plus d'un an, aucune correction de sécurité à
   attendre.

   CE QUI CHANGE
   -------------
   Les composants utilisés se réécrivent en CSS natif :

     carrousel   -> scroll-snap        (défilement natif, accéléré)
     modale      -> <dialog>           (piège de focus et Échap inclus)
     accordéon   -> <details>          (aucun JavaScript)
     menu        -> translate + <dialog>
     grille      -> CSS grid
     ondes       -> états :active

   Conséquence : jQuery ne sert plus qu'aux appels AJAX. Environ
   200 ko de moins à charger, et des animations natives — donc plus
   fluides sur les appareils anciens.

   PERSONNALISATION PAR CLIENT
   ---------------------------
   Tout passe par les variables de :root. Un client aux couleurs
   vertes surcharge trois lignes dans theme.css, rien d'autre.
   ===================================================================== */


/* ---------------------------------------------------------------------
   1. VARIABLES
   --------------------------------------------------------------------- */

:root {
    /* --- Couleurs, surchargées par theme.css --- */
    --primary:        #25378b;
    --primary-clair:  #3d52b0;
    --primary-fonce:  #1a2761;
    --accent:         #ffba01;
    --danger:         #e94437;
    --succes:         #23af47;
    --info:           #02abfe;

    --texte:          #1e293b;
    --texte-doux:     #64748b;
    --texte-inverse:  #ffffff;

    --fond:           #f6f7fb;
    --surface:        #ffffff;
    --bordure:        #e2e8f0;

    /* --- Rayons --- */
    --r-sm: 6px;
    --r-md: 12px;
    --r-lg: 20px;
    --r-full: 999px;

    /* --- Ombres --- */
    --ombre-1: 0 1px 3px rgba(16, 24, 40, .08);
    --ombre-2: 0 4px 12px rgba(16, 24, 40, .10);
    --ombre-3: 0 12px 28px rgba(16, 24, 40, .16);

    /* --- Espacements --- */
    --e-1: 4px;
    --e-2: 8px;
    --e-3: 12px;
    --e-4: 16px;
    --e-5: 24px;
    --e-6: 32px;

    /* --- Barres --- */
    --h-entete: 56px;
    --h-pied:   64px;

    /* --- Zones sûres de l'appareil ---
       Indispensable en webview : sans elles, le contenu passe sous
       l'encoche de l'iPhone et sous la barre de navigation Android.
       env() renvoie 0 sur les appareils sans encoche. */
    --safe-haut:   env(safe-area-inset-top, 0px);
    --safe-bas:    env(safe-area-inset-bottom, 0px);
    --safe-gauche: env(safe-area-inset-left, 0px);
    --safe-droite: env(safe-area-inset-right, 0px);

    --transition: .2s cubic-bezier(.4, 0, .2, 1);
}


/* ---------------------------------------------------------------------
   2. BASE
   --------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* --- Police --- */
@font-face {
    font-family: 'Roboto';
    src: url('/assets/fonts/roboto/Roboto-Regular.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;   /* le texte s'affiche avec une police de
                             repli plutôt que de rester invisible */
}

@font-face {
    font-family: 'Roboto';
    src: url('/assets/fonts/roboto/Roboto-Medium.woff2') format('woff2');
    font-weight: 600;
    font-display: swap;
}

html {
    -webkit-text-size-adjust: 100%;
    /* Empêche le zoom par double-tap, qui gêne dans une application */
    touch-action: manipulation;
}

body {
    margin: 0;
    font-family: 'Roboto', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-size: 15px;
    line-height: 1.5;
    color: var(--texte);
    background: var(--fond);

    /* Défilement fluide sur iOS */
    -webkit-overflow-scrolling: touch;

    /* Le rebond du défilement révèle le fond blanc du navigateur en
       haut et en bas : dans une application, c'est visible et ça fait
       « page web ». */
    overscroll-behavior-y: none;
}

/* Le texte de l'interface ne doit pas être sélectionnable : un appui
   long fait apparaître le menu de copie, ce qui trahit la webview.
   Les zones de contenu rétablissent la sélection. */
body { -webkit-user-select: none; user-select: none; }
.selectionnable, .contenu-article, input, textarea {
    -webkit-user-select: text;
    user-select: text;
}

/* Supprime le flash gris au toucher sur iOS */
a, button { -webkit-tap-highlight-color: transparent; }

h1, h2, h3, h4, h5, h6 { margin: 0 0 var(--e-3); line-height: 1.25; font-weight: 600; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.2rem; }
h4 { font-size: 1.05rem; }
h5 { font-size: 1rem; }

p { margin: 0 0 var(--e-3); }

a { color: var(--primary); text-decoration: none; }

img { max-width: 100%; height: auto; display: block; }


/* ---------------------------------------------------------------------
   3. MISE EN PAGE
   --------------------------------------------------------------------- */

.app {
    min-height: 100vh;
    /* dvh suit la barre d'adresse mobile, contrairement à vh qui
       provoque un décalage à l'apparition du clavier. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

.contenu {
    flex: 1;
    padding-top: calc(var(--h-entete) + var(--safe-haut));
    padding-bottom: calc(var(--h-pied) + var(--safe-bas) + var(--e-4));
}

.conteneur {
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    padding-inline: var(--e-4);
}

.grille { display: grid; gap: var(--e-3); }
.grille-2 { grid-template-columns: repeat(2, 1fr); }
.grille-3 { grid-template-columns: repeat(3, 1fr); }

.pile { display: flex; flex-direction: column; gap: var(--e-3); }
.ligne { display: flex; align-items: center; gap: var(--e-3); }
.entre  { justify-content: space-between; }
.centre { justify-content: center; }

.section-titre {
    font-size: .8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--texte-doux);
    margin: var(--e-5) 0 var(--e-3);
}


/* ---------------------------------------------------------------------
   4. EN-TÊTE
   --------------------------------------------------------------------- */

.entete {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    height: calc(var(--h-entete) + var(--safe-haut));
    padding-top: var(--safe-haut);
    background: var(--primary);
    color: var(--texte-inverse);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: var(--e-4);
    box-shadow: var(--ombre-1);
}

.entete__logo img { height: 32px; width: auto; }

.entete__action {
    background: none;
    border: 0;
    color: inherit;
    padding: var(--e-2);
    cursor: pointer;
    display: flex;
    /* 44 px : la cible tactile minimale recommandée */
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
}


/* ---------------------------------------------------------------------
   5. BARRE INFÉRIEURE
   --------------------------------------------------------------------- */

.pied {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    z-index: 100;
    height: calc(var(--h-pied) + var(--safe-bas));
    padding-bottom: var(--safe-bas);
    background: var(--surface);
    border-top: 1px solid var(--bordure);
    display: flex;
}

.pied__item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--texte-doux);
    font-size: .68rem;
    padding: var(--e-1);
    transition: color var(--transition);
}

.pied__item i { font-size: 22px; }
.pied__item.actif { color: var(--primary); }
.pied__item:active { background: rgba(0, 0, 0, .04); }


/* ---------------------------------------------------------------------
   6. MENU LATÉRAL
   -----------------------------------------------------------------------
   <dialog> plutôt qu'une div : le piège de focus, la fermeture par
   Échap et le fond assombri sont natifs. Materialize réimplémentait
   tout cela en JavaScript.
   --------------------------------------------------------------------- */

.menu {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(300px, 82vw);
    max-width: none;
    max-height: none;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: var(--surface);
    transform: translateX(-100%);
    transition: transform var(--transition);
    overflow-y: auto;
}

.menu[open] { transform: translateX(0); }
.menu::backdrop { background: rgba(0, 0, 0, .45); }

.menu__entete {
    background: var(--primary);
    color: var(--texte-inverse);
    padding: calc(var(--safe-haut) + var(--e-5)) var(--e-4) var(--e-4);
}

.menu__nom  { font-weight: 600; font-size: 1.05rem; }
.menu__role { opacity: .8; font-size: .85rem; }

.menu__item {
    display: flex;
    align-items: center;
    gap: var(--e-4);
    padding: var(--e-4);
    color: var(--texte);
    border-bottom: 1px solid var(--bordure);
    width: 100%;
    background: none;
    border-left: 0; border-right: 0; border-top: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.menu__item.actif { color: var(--primary); background: rgba(37, 55, 139, .06); }
.menu__item:active { background: rgba(0, 0, 0, .05); }

/* ---------------------------------------------------------------------
   MENU — compléments
   --------------------------------------------------------------------- */

.menu {
    display: flex;
    flex-direction: column;
}

.menu__entete {
    background: var(--surface);
    color: var(--texte);
    padding: calc(var(--safe-haut) + var(--e-5)) var(--e-4) var(--e-4);
    text-align: center;
    border-bottom: 1px solid var(--bordure);
}

.menu__logo { max-width: 120px; margin: 0 auto var(--e-3); }
.menu__nom  { font-weight: 600; }
.menu__role { color: var(--texte-doux); font-size: .82rem; }

/* La liste occupe l'espace disponible : le contact et le pied
   restent visibles même sur un petit écran. */
.menu__liste { flex: 1; overflow-y: auto; }

.menu__contact {
    padding: var(--e-4);
    border-top: 1px solid var(--bordure);
}

.menu__pied {
    border-top: 1px solid var(--bordure);
    padding-bottom: var(--safe-bas);
}

.menu__pied .menu__item { border-bottom: 0; padding-block: var(--e-3); }


/* ---------------------------------------------------------------------
   TUILES DE L'ACCUEIL
   --------------------------------------------------------------------- */

.tuiles {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--e-3);
    padding: var(--e-4) 0;
}

.tuile {
    position: relative;
    aspect-ratio: 1 / .85;
    border-radius: var(--r-md);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--e-4);
    color: #fff;
    box-shadow: var(--ombre-1);
    transition: transform var(--transition);
}

.tuile:active { transform: scale(.96); }

/* Certaines tuiles ont un fond clair : le texte blanc y serait
   illisible. */
.tuile--sombre { color: var(--texte); }

.tuile__icone { font-size: 2.2rem; opacity: .95; }

.tuile__label {
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.15;
    /* Les libellés peuvent contenir un retour à la ligne volontaire,
       pour équilibrer « Annuaire / adhérents » sur deux lignes. */
    white-space: pre-line;
}

.tuile__image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    opacity: .9;
}

.tuile__contenu { position: relative; z-index: 1; }

/* Une tuile peut occuper toute la largeur */
.tuile--large { grid-column: span 2; aspect-ratio: 2 / .7; }
/* ---------------------------------------------------------------------
   7. CARTES
   --------------------------------------------------------------------- */

.carte {
    background: var(--surface);
    border-radius: var(--r-md);
    box-shadow: var(--ombre-1);
    overflow: hidden;
    display: block;
    color: inherit;
    transition: transform var(--transition), box-shadow var(--transition);
}

.carte:active { transform: scale(.985); box-shadow: var(--ombre-2); }

.carte__image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    background: var(--bordure);
}

.carte__corps { padding: var(--e-4); }
.carte__titre { font-weight: 600; margin-bottom: var(--e-1); }
.carte__meta  { font-size: .8rem; color: var(--texte-doux); }

/* Carte horizontale, pour les événements */
.carte--horizontale { display: flex; align-items: stretch; }

.carte__date {
    background: var(--primary);
    color: var(--texte-inverse);
    padding: var(--e-3);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 68px;
}

.carte__date .jour { font-size: 1.5rem; font-weight: 700; line-height: 1; }
.carte__date .mois { font-size: .72rem; text-transform: uppercase; }

/* Carte OpenStreetMap */
.carte-osm {
    height: 240px;
    width: 100%;
    /* Leaflet pose ses propres z-index élevés : sans cette limite,
       la carte passe au-dessus de l'en-tête fixe. */
    z-index: 0;
}

.leaflet-container { font-family: inherit; }

/* ---------------------------------------------------------------------
   8. CARROUSEL
   -----------------------------------------------------------------------
   scroll-snap remplace le carrousel JavaScript de Materialize.

   Le défilement est traité par le compositeur du navigateur, pas par
   un script : il reste fluide même quand le fil principal est occupé,
   ce qui se remarque nettement sur les appareils anciens.
   --------------------------------------------------------------------- */

.carrousel {
    display: flex;
    gap: var(--e-3);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding: var(--e-1) var(--e-4) var(--e-4);
    margin-inline: calc(var(--e-4) * -1);

    /* Masque la barre de défilement, sans empêcher le geste */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.carrousel::-webkit-scrollbar { display: none; }

.carrousel__item {
    flex: 0 0 86%;
    scroll-snap-align: center;
    border-radius: var(--r-md);
    overflow: hidden;
    position: relative;
    box-shadow: var(--ombre-2);
}

.carrousel__item img {
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
}

.carrousel__legende {
    position: absolute;
    inset: auto 0 0 0;
    padding: var(--e-5) var(--e-4) var(--e-4);
    color: #fff;
    /* Dégradé plutôt qu'un fond plein : le texte reste lisible quelle
       que soit l'image, sans masquer le sujet. */
    background: linear-gradient(transparent, rgba(0, 0, 0, .82));
}

.carrousel__legende h5 { margin: 0 0 var(--e-1); font-size: 1rem; }
.carrousel__legende p  { margin: 0; font-size: .82rem; opacity: .9; }

/* Points indicateurs */
.carrousel-points {
    display: flex;
    justify-content: center;
    gap: var(--e-2);
    margin-top: calc(var(--e-3) * -1);
    margin-bottom: var(--e-3);
}

.carrousel-point {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--bordure);
    transition: all var(--transition);
}

.carrousel-point.actif { background: var(--primary); width: 18px; border-radius: 3px; }


/* ---------------------------------------------------------------------
   9. BOUTONS
   --------------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    /* 48 px de haut : confortable au doigt */
    min-height: 48px;
    padding: 0 var(--e-5);
    border: 0;
    border-radius: var(--r-full);
    background: var(--primary);
    color: var(--texte-inverse);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: transform var(--transition), filter var(--transition);
    text-align: center;
}

/* Retour tactile immédiat, sans les 200 ko d'animation « waves » */
.btn:active { transform: scale(.97); filter: brightness(.92); }

.btn:disabled { opacity: .45; pointer-events: none; }

.btn--bloc    { width: 100%; }
.btn--fantome { background: transparent; color: var(--primary);
                border: 1.5px solid currentColor; }
.btn--plat    { background: transparent; color: var(--primary); min-height: 40px; }
.btn--accent  { background: var(--accent); color: var(--texte); }
.btn--danger  { background: var(--danger); }


/* ---------------------------------------------------------------------
   10. FORMULAIRES
   -----------------------------------------------------------------------
   Le libellé flottant se fait entièrement en CSS, via
   :placeholder-shown. Materialize le pilotait en JavaScript, avec des
   décalages visibles au chargement.
   --------------------------------------------------------------------- */

.champ { position: relative; margin-bottom: var(--e-5); }

.champ input,
.champ textarea,
.champ select {
    width: 100%;
    /* 16 px minimum : en dessous, iOS zoome automatiquement à la mise
       au point, ce qui décale toute la page. */
    font-size: 16px;
    font-family: inherit;
    padding: var(--e-5) var(--e-3) var(--e-2);
    border: 0;
    border-bottom: 2px solid var(--bordure);
    border-radius: var(--r-sm) var(--r-sm) 0 0;
    background: rgba(0, 0, 0, .03);
    color: var(--texte);
    transition: border-color var(--transition);
}

.champ input:focus,
.champ textarea:focus,
.champ select:focus {
    outline: none;
    border-bottom-color: var(--primary);
}

.champ label {
    position: absolute;
    left: var(--e-3);
    top: var(--e-2);
    font-size: .72rem;
    color: var(--texte-doux);
    pointer-events: none;
    transition: all var(--transition);
}

/* Champ vide et non actif : le libellé occupe la place du texte */
.champ input:placeholder-shown:not(:focus) + label,
.champ textarea:placeholder-shown:not(:focus) + label {
    top: var(--e-4);
    font-size: 1rem;
}

.champ input:focus + label { color: var(--primary); }

.champ__aide   { font-size: .76rem; color: var(--texte-doux); margin-top: var(--e-1); }
.champ__erreur { font-size: .76rem; color: var(--danger); margin-top: var(--e-1); }

/* Case à cocher */
.case { display: flex; align-items: flex-start; gap: var(--e-3); padding: var(--e-2) 0; }
.case input { width: 22px; height: 22px; accent-color: var(--primary); flex-shrink: 0; margin-top: 2px; }
.case label { font-size: .9rem; }

/* Champ de code à usage unique */
.champ-code input {
    text-align: center;
    font-size: 1.7rem;
    letter-spacing: .5rem;
    font-variant-numeric: tabular-nums;
    padding: var(--e-4);
}


/* ---------------------------------------------------------------------
   11. ÉTIQUETTES
   --------------------------------------------------------------------- */

.puce {
    display: inline-flex;
    align-items: center;
    gap: var(--e-1);
    padding: 3px var(--e-3);
    border-radius: var(--r-full);
    font-size: .72rem;
    font-weight: 600;
    background: var(--bordure);
    color: var(--texte);
}

.puce--primaire { background: var(--primary); color: #fff; }
.puce--accent   { background: var(--accent); }


/* ---------------------------------------------------------------------
   12. MODALE
   -----------------------------------------------------------------------
   <dialog> apporte nativement : piège de focus, fermeture par Échap,
   fond assombri, et retrait du reste de la page pour les lecteurs
   d'écran.
   --------------------------------------------------------------------- */

.modale {
    border: 0;
    border-radius: var(--r-lg);
    padding: 0;
    width: min(440px, 90vw);
    box-shadow: var(--ombre-3);
    /* Le clavier virtuel réduit la hauteur utile : sans limite, la
       modale déborde et ses boutons deviennent inatteignables. */
    max-height: 85dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.modale::backdrop {
    background: rgba(0, 0, 0, .5);
    backdrop-filter: blur(2px);
}

.modale__corps { padding: var(--e-5); overflow-y: auto; }
.modale__titre { font-size: 1.1rem; font-weight: 600; margin-bottom: var(--e-3); }

.modale__pied {
    display: flex;
    gap: var(--e-3);
    padding: var(--e-4) var(--e-5) var(--e-5);
    border-top: 1px solid var(--bordure);
}

.modale__pied .btn { flex: 1; }

/* Ouverture animée */
.modale[open] { animation: modale-entree .22s cubic-bezier(.4, 0, .2, 1); }

@keyframes modale-entree {
    from { opacity: 0; transform: translateY(16px) scale(.97); }
    to   { opacity: 1; transform: none; }
}


/* ---------------------------------------------------------------------
   13. ACCORDÉON
   -----------------------------------------------------------------------
   <details> remplace le composant JavaScript de Materialize.
   Fonctionne sans script, et reste utilisable si le JS échoue.
   --------------------------------------------------------------------- */

.accordeon {
    background: var(--surface);
    border-radius: var(--r-md);
    box-shadow: var(--ombre-1);
    margin-bottom: var(--e-3);
    overflow: hidden;
}

.accordeon > summary {
    padding: var(--e-4);
    font-weight: 600;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Retire le triangle par défaut, remplacé par une icône */
    list-style: none;
}

.accordeon > summary::-webkit-details-marker { display: none; }

.accordeon > summary::after {
    content: 'expand_more';
    font-family: 'Material Icons';
    transition: transform var(--transition);
    color: var(--texte-doux);
}

.accordeon[open] > summary::after { transform: rotate(180deg); }
.accordeon__corps { padding: 0 var(--e-4) var(--e-4); }


/* ---------------------------------------------------------------------
   14. MESSAGES ÉPHÉMÈRES
   --------------------------------------------------------------------- */

.toasts {
    position: fixed;
    left: 0; right: 0;
    bottom: calc(var(--h-pied) + var(--safe-bas) + var(--e-4));
    z-index: 200;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-2);
    padding-inline: var(--e-4);
    pointer-events: none;
}

.toast {
    background: #23324d;
    color: #fff;
    padding: var(--e-3) var(--e-5);
    border-radius: var(--r-full);
    font-size: .88rem;
    box-shadow: var(--ombre-2);
    animation: toast-entree .25s ease;
    max-width: 100%;
}

.toast--succes { background: var(--succes); }
.toast--erreur { background: var(--danger); }
.toast--sortie { animation: toast-sortie .25s ease forwards; }

@keyframes toast-entree {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}

@keyframes toast-sortie {
    to { opacity: 0; transform: translateY(14px); }
}


/* ---------------------------------------------------------------------
   15. ÉTATS VIDES ET CHARGEMENT
   --------------------------------------------------------------------- */

.vide {
    text-align: center;
    padding: var(--e-6) var(--e-4);
    color: var(--texte-doux);
}

.vide i { font-size: 3rem; opacity: .3; margin-bottom: var(--e-3); }

/* Squelette de chargement : mieux qu'un tourniquet, l'utilisateur
   voit la forme de ce qui arrive. */
.squelette {
    background: linear-gradient(90deg, #eef1f6 25%, #f7f9fc 50%, #eef1f6 75%);
    background-size: 200% 100%;
    animation: squelette 1.4s infinite;
    border-radius: var(--r-sm);
}

@keyframes squelette {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}


/* ---------------------------------------------------------------------
   16. CONTENU D'ARTICLE
   -----------------------------------------------------------------------
   Le corps vient de l'éditeur riche : on ne maîtrise pas son balisage,
   d'où des règles défensives.
   --------------------------------------------------------------------- */

.contenu-article { line-height: 1.65; }
.contenu-article img { border-radius: var(--r-sm); margin: var(--e-3) 0; }

.contenu-article a {
    color: var(--primary);
    text-decoration: underline;
    /* Une URL collée sans espaces déborderait du conteneur */
    overflow-wrap: anywhere;
}

.contenu-article ul,
.contenu-article ol { padding-left: var(--e-5); margin-bottom: var(--e-3); }

.contenu-article blockquote {
    border-left: 3px solid var(--primary);
    padding-left: var(--e-4);
    margin: var(--e-4) 0;
    color: var(--texte-doux);
    font-style: italic;
}

/* Un tableau collé depuis Word casse la mise en page : on le rend
   défilable plutôt que de laisser déborder. */
.contenu-article table { display: block; overflow-x: auto; max-width: 100%; }


/* ---------------------------------------------------------------------
   17. UTILITAIRES
   --------------------------------------------------------------------- */

.txt-centre { text-align: center; }
.txt-doux   { color: var(--texte-doux); }
.txt-petit  { font-size: .82rem; }
.mb-0 { margin-bottom: 0; }
.mt-4 { margin-top: var(--e-4); }
.mt-5 { margin-top: var(--e-5); }

/* Masqué visuellement, mais lu par les lecteurs d'écran */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ---------------------------------------------------------------------
   18. PRÉFÉRENCES SYSTÈME
   --------------------------------------------------------------------- */

/* Certaines personnes désactivent les animations pour raisons
   médicales — vertiges, migraines. Le système transmet ce réglage. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Mode sombre : uniquement si un thème le déclare. Sans styles
   dédiés, l'inversion automatique donne un résultat illisible. */
@media (prefers-color-scheme: dark) {
    :root.theme-sombre {
        --texte:      #e8eaf0;
        --texte-doux: #9aa3b5;
        --fond:       #12161f;
        --surface:    #1b202b;
        --bordure:    #2a3140;
    }
}


/* ---------------------------------------------------------------------
   19. ÉLÉMENTS DE CONTENU
   --------------------------------------------------------------------- */

/* Filtres par rubrique : défilement horizontal plutôt qu'un select.
   Les rubriques sont visibles d'un coup d'œil, et le choix se fait en
   un appui au lieu de trois. */
.filtres {
    display: flex;
    gap: var(--e-2);
    overflow-x: auto;
    padding: var(--e-3) var(--e-4);
    margin-inline: calc(var(--e-4) * -1);
    scrollbar-width: none;
}

.filtres::-webkit-scrollbar { display: none; }
.filtres .puce { flex-shrink: 0; padding: var(--e-2) var(--e-4); }

/* Bandeau d'article : pleine largeur, hors du conteneur */
.article__bandeau {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    background: var(--bordure);
}

.article__video {
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 0;
    border-radius: var(--r-md);
    background: #000;
}

/* Signature de fin d'article */
.bloc-auteur {
    display: flex;
    align-items: center;
    gap: var(--e-4);
    margin-top: var(--e-6);
    padding: var(--e-4);
    border-top: 3px solid var(--primary);
    background: var(--surface);
    border-radius: 0 0 var(--r-md) var(--r-md);
}

.bloc-auteur__photo {
    width: 64px; height: 64px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 2px solid #fff;
}

.bloc-auteur__label    { font-weight: 700; font-size: .8rem; margin: 0 0 var(--e-1); }
.bloc-auteur__nom      { font-weight: 600; margin: 0; }
.bloc-auteur__fonction { color: var(--texte-doux); font-size: .82rem; margin: 0 0 var(--e-2); }

.bloc-auteur__contact {
    margin: 0;
    font-size: .84rem;
    /* Une adresse longue ne doit pas déborder sur un petit écran */
    overflow-wrap: anywhere;
}

.txt-succes { color: var(--succes); }
.txt-erreur { color: var(--danger); }

/* =====================================================================
   ÉCRANS D'AUTHENTIFICATION
   =====================================================================

   Chargé uniquement sur les écrans de connexion et de récupération.

   Le fond aléatoire reprend le principe du backoffice : l'image est
   injectée par une variable CSS, et non par un bloc <style> avec un
   chemin relatif comme dans l'ancienne version.
   ===================================================================== */

.ecran-auth {
    /* Dégradé plutôt qu'une image de fond : plus léger, et l'écran de
       connexion s'affiche instantanément même sur réseau lent. Une
       image peut être ajoutée par --fond-auth dans theme.css. */
    background: var(--fond-auth,
        linear-gradient(160deg, var(--primary) 0%, var(--primary-fonce) 100%));
    background-size: cover;
    background-position: center;
    min-height: 100dvh;
}

.auth {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: calc(var(--safe-haut) + var(--e-5))
             var(--e-4)
             calc(var(--safe-bas) + var(--e-5));
}

.auth__logo {
    text-align: center;
    margin-bottom: var(--e-6);
}

.auth__logo img {
    max-width: 190px;
    margin: 0 auto;
}

.auth__carte {
    background: var(--surface);
    border-radius: var(--r-lg);
    padding: var(--e-5);
    box-shadow: var(--ombre-3);
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
}

.auth__titre {
    text-align: center;
    font-size: 1.15rem;
    margin-bottom: var(--e-2);
}

.auth__intro {
    text-align: center;
    color: var(--texte-doux);
    font-size: .9rem;
    margin-bottom: var(--e-5);
}

.auth__liens {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-2);
    margin-top: var(--e-5);
    padding-top: var(--e-4);
    border-top: 1px solid var(--bordure);
}

.auth__liens a {
    font-size: .86rem;
    padding: var(--e-2);
}

/* Champ mot de passe avec bouton d'affichage */
.champ--mdp { display: flex; align-items: flex-end; gap: var(--e-2); }
.champ--mdp .champ { flex: 1; margin-bottom: 0; }

.voir-mdp {
    background: none;
    border: 0;
    color: var(--texte-doux);
    cursor: pointer;
    /* 44 px : cible tactile minimale */
    min-width: 44px;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.voir-mdp[aria-pressed="true"] { color: var(--primary); }

/* Icône d'en-tête des écrans de récupération */
.auth__icone {
    text-align: center;
    margin-bottom: var(--e-3);
}

.auth__icone i {
    font-size: 3rem;
    color: var(--primary);
    opacity: .35;
}
