/* Fichier produit par tools/build-css.mjs. Ne pas modifier :
   editer assets/css/main.css et les huit feuilles qu'il importe. */
@layer tokens, fonts, base, layout, components, patterns, app, utilities;

/* ==========================================================================
   tokens.css → @layer tokens
   ========================================================================== */
@layer tokens {
/* ============================================================================
   GLUB CONVENT 2027 : DESIGN SYSTEM « ORIENT »
   01 · tokens.css : Single source of truth for every design decision.
   ----------------------------------------------------------------------------
   Nothing in this file paints anything. It only declares custom properties.
   Every other stylesheet consumes these tokens and never hard-codes a value.
   Palette derived from the Comité mockups: navy profond + or + ivoire.
   ========================================================================== */

:root {
  /* Les contrôles natifs (ascenseurs, sélecteurs de date) suivent cette
     indication : sans elle, un système en thème sombre les peindrait en
     sombre au milieu d'une page claire. */
  color-scheme: light;

  /* --------------------------------------------------------------------------
     1. COULEURS : palette primitive
     Each ramp is perceptually stepped so 700/800/900 stay legible on ivory
     and 100/200/300 stay legible on navy (WCAG 2.2 AA verified pairs below).
     -------------------------------------------------------------------------- */

  /* Navy : couleur institutionnelle (logo GLUB, en-tête, sections solennelles) */
  --c-navy-50:  #EAF0F8;
  --c-navy-100: #CDDCED;
  --c-navy-200: #9DB6D4;
  --c-navy-300: #6B8DB8;
  --c-navy-400: #3F6699;
  --c-navy-500: #1B4E86;
  --c-navy-600: #123A66;
  --c-navy-700: #0B2545; /* navy de référence : issu des maquettes */
  --c-navy-800: #081B33;
  --c-navy-900: #061424;
  --c-navy-950: #030B16;

  /* Or, accent cérémoniel : titres, filets, CTA, QR, sceaux */
  --c-gold-50:  #FBF6E6;
  --c-gold-100: #F6EBC6;
  --c-gold-200: #EFD98F;
  --c-gold-300: #E7C85F;
  --c-gold-400: #DDB63C;
  --c-gold-500: #C9A227; /* or de référence */
  --c-gold-600: #A8861C;
  --c-gold-700: #826716;
  --c-gold-800: #5C4910;
  --c-gold-900: #3A2E0A;

  /* Ivoire : fond des panneaux clairs, papier de la lettre d'invitation */
  --c-ivory-50:  #FDFBF6;
  --c-ivory-100: #FAF6EC;
  --c-ivory-200: #F3ECDC;
  --c-ivory-300: #E9DFC8;
  --c-ivory-400: #D9CBAC;

  /* Neutres : texte et bordures sur fond clair */
  --c-ink-900: #0F1A28;
  --c-ink-800: #1B2836;
  --c-ink-700: #33414F;
  --c-ink-600: #4C5A69;
  /* Assombri de #6A7686 : sur l'ivoire de la page, le texte discret
     plafonnait à 4,28, sous le seuil AA de 4,5. Seul --fg-subtle le
     consomme, l'écart est imperceptible ailleurs. */
  --c-ink-500: #677282;
  --c-ink-400: #939DAB;
  --c-ink-300: #BCC4CF;
  --c-ink-200: #DAE0E7;
  --c-ink-100: #EDF1F5;
  --c-ink-050: #F7F9FB;
  --c-white: #FFFFFF;

  /* Sémantique : statuts d'inscription, files visa, alertes */
  --c-success-600: #14624A;
  --c-success-500: #1E7A55;
  --c-success-100: #DCF2E7;
  --c-warning-600: #8A5A0B;
  --c-warning-500: #B7791F;
  --c-warning-100: #FBEFD6;
  --c-danger-600:  #8F1D17;
  --c-danger-500:  #B3261E;
  --c-danger-100:  #FBE3E1;
  --c-info-600:    #14567F;
  --c-info-500:    #1D6FA5;
  --c-info-100:    #DDEEF9;

  /* --------------------------------------------------------------------------
     2. RÔLES SÉMANTIQUES : ce que les composants utilisent réellement
     -------------------------------------------------------------------------- */
  --bg-page:        var(--c-ivory-100);
  --bg-surface:     var(--c-white);
  --bg-surface-alt: var(--c-ivory-200);
  --bg-sunken:      var(--c-ivory-300);
  --bg-inverse:     var(--c-navy-700);
  --bg-inverse-alt: var(--c-navy-800);
  --bg-inverse-deep:var(--c-navy-900);

  --fg-strong:   var(--c-ink-900);
  --fg-default:  var(--c-ink-800);
  --fg-muted:    var(--c-ink-600);
  --fg-subtle:   var(--c-ink-500);
  --fg-on-dark:  var(--c-ivory-100);
  --fg-on-dark-muted: #B9C6D8; /* 7.1:1 sur --c-navy-700 */
  --fg-accent:   var(--c-gold-700);       /* or lisible sur ivoire (4.8:1) */
  --fg-accent-on-dark: var(--c-gold-300); /* or lisible sur navy (8.4:1)  */

  --border-subtle: var(--c-ink-200);
  --border-default:var(--c-ink-300);
  --border-strong: var(--c-ink-400);
  --border-gold:   rgba(201, 162, 39, .38);
  --border-on-dark:rgba(240, 214, 138, .22);

  --accent:        var(--c-gold-500);
  --accent-hover:  var(--c-gold-400);
  --accent-press:  var(--c-gold-600);
  --accent-contrast: var(--c-navy-900); /* texte sur bouton or : 9.6:1 */

  --focus-ring: var(--c-gold-500);
  --focus-ring-on-dark: var(--c-gold-300);

  /* Icônes décoratives : navy sur fond clair, or sur fond nuit. Sans ce rôle,
     une icône navy deviendrait invisible sur les surfaces du thème sombre. */
  --fg-icon: var(--c-navy-700);
  --bg-icon-badge: var(--c-navy-700);
  --fg-icon-badge: var(--c-gold-300);

  /* Fonds d'état : survol discret et aplat doré. Déclarés comme rôles parce
     qu'ils s'inversent en thème sombre : un aplat ivoire y serait aveuglant. */
  --bg-hover-soft: var(--c-ivory-100);
  --bg-accent-soft: var(--c-gold-50);
  --bg-selected-soft: var(--c-navy-50);
  /* Barre supérieure de la coque applicative : translucide, donc déclarée en
     rgba plutôt qu'en référence à un autre rôle. */
  --bg-topbar: rgba(250, 246, 236, .9);

  /* --------------------------------------------------------------------------
     3. TYPOGRAPHIE
     Display = Cormorant Garamond (solennel, éditorial)
     UI/Texte = Inter (lisibilité écran, chiffres tabulaires)
     Échelle fluide : clamp(min, préféré, max) : pas de media query nécessaire.
     -------------------------------------------------------------------------- */
  --font-display: "Cormorant Garamond", "Cormorant Fallback", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-sans: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, "Liberation Mono", monospace;

  --fs-3xs: .6875rem; /* 11px : sur-titres, mentions légales */
  --fs-2xs: .75rem;   /* 12px */
  --fs-xs:  .8125rem; /* 13px */
  --fs-sm:  .875rem;  /* 14px */
  --fs-base:1rem;     /* 16px */
  --fs-md:  1.0625rem;/* 17px : corps de texte long */
  --fs-lg:  clamp(1.125rem, .35vw + 1.05rem, 1.25rem);
  --fs-xl:  clamp(1.25rem, .6vw + 1.1rem, 1.5rem);
  --fs-2xl: clamp(1.5rem, 1vw + 1.25rem, 1.875rem);
  --fs-3xl: clamp(1.75rem, 1.6vw + 1.35rem, 2.5rem);
  --fs-4xl: clamp(2.125rem, 2.6vw + 1.5rem, 3.25rem);
  --fs-5xl: clamp(2.5rem, 4vw + 1.5rem, 4.25rem);
  --fs-6xl: clamp(3rem, 6.2vw + 1.25rem, 6rem);

  --lh-tight: 1.08;
  --lh-snug: 1.22;
  --lh-heading: 1.15;
  --lh-normal: 1.55;
  --lh-relaxed: 1.72;

  --ls-tighter: -.03em;
  --ls-tight: -.015em;
  --ls-normal: 0;
  --ls-wide: .04em;
  --ls-wider: .10em;
  --ls-widest: .22em; /* sur-titres capitales « ASSEMBLÉE GÉNÉRALE » */

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* Longueur de ligne confortable (65,75 caractères) */
  --measure: 68ch;
  --measure-narrow: 46ch;

  /* --------------------------------------------------------------------------
     4. ESPACEMENTS : échelle 4px, nommée en pas et non en pixels
     -------------------------------------------------------------------------- */
  --space-0: 0;
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: .75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-7: 1.75rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-14: 3.5rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* Rythme vertical des sections : fluide entre mobile et desktop */
  --section-y: clamp(3.5rem, 6vw, 7rem);
  --section-y-lg: clamp(4.5rem, 8vw, 9rem);

  /* --------------------------------------------------------------------------
     5. GRILLE ET GABARIT
     -------------------------------------------------------------------------- */
  --container-max: 1280px;
  --container-wide: 1440px;
  --container-narrow: 780px;
  --gutter: clamp(1.125rem, 4vw, 2.5rem);
  --grid-columns: 12;
  --grid-gap: clamp(1rem, 2vw, 2rem);

  /* --------------------------------------------------------------------------
     6. RAYONS, OMBRES, FILETS
     -------------------------------------------------------------------------- */
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-xl: 22px;
  --radius-2xl: 32px;
  --radius-pill: 999px;

  --shadow-xs: 0 1px 2px rgba(6, 20, 36, .06);
  --shadow-sm: 0 2px 6px rgba(6, 20, 36, .07), 0 1px 2px rgba(6, 20, 36, .05);
  --shadow-md: 0 8px 24px -8px rgba(6, 20, 36, .18), 0 2px 6px rgba(6, 20, 36, .06);
  --shadow-lg: 0 22px 48px -20px rgba(6, 20, 36, .28), 0 6px 14px rgba(6, 20, 36, .08);
  --shadow-xl: 0 40px 80px -32px rgba(6, 20, 36, .38), 0 10px 24px rgba(6, 20, 36, .10);
  --shadow-gold: 0 12px 32px -12px rgba(201, 162, 39, .55);
  --shadow-inset-hairline: inset 0 0 0 1px rgba(255, 255, 255, .06);

  /* --------------------------------------------------------------------------
     7. DÉGRADÉS SIGNATURE
     -------------------------------------------------------------------------- */
  --grad-navy: linear-gradient(160deg, var(--c-navy-700) 0%, var(--c-navy-900) 100%);
  --grad-navy-soft: linear-gradient(180deg, var(--c-navy-800) 0%, var(--c-navy-700) 60%, var(--c-navy-800) 100%);
  --grad-gold: linear-gradient(135deg, var(--c-gold-300) 0%, var(--c-gold-500) 45%, var(--c-gold-600) 100%);
  --grad-gold-line: linear-gradient(90deg, transparent, var(--c-gold-500) 22%, var(--c-gold-300) 50%, var(--c-gold-500) 78%, transparent);
  --grad-ivory: linear-gradient(180deg, var(--c-ivory-50) 0%, var(--c-ivory-200) 100%);
  --grad-glass: linear-gradient(150deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, .02));

  /* --------------------------------------------------------------------------
     8. MOUVEMENT : durées et courbes uniques, jamais improvisées
     -------------------------------------------------------------------------- */
  --dur-instant: 90ms;
  --dur-fast: 160ms;
  --dur-base: 260ms;
  --dur-slow: 420ms;
  --dur-slower: 720ms;
  --dur-ceremony: 1200ms; /* tracés de géométrie sacrée */

  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-in-out: cubic-bezier(.65, .05, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --ease-entrance: cubic-bezier(.16, 1, .3, 1);

  /* --------------------------------------------------------------------------
     9. PROFONDEUR (z-index) : une seule échelle pour tout le projet
     -------------------------------------------------------------------------- */
  --z-below: -1;
  --z-base: 1;
  --z-sticky: 100;
  --z-header: 200;
  --z-dropdown: 300;
  --z-offcanvas: 400;
  --z-overlay: 500;
  --z-modal: 600;
  --z-toast: 700;
  --z-skiplink: 900;

  /* --------------------------------------------------------------------------
     10. CIBLES TACTILES ET ACCESSIBILITÉ (WCAG 2.2 AA : 2.5.8 Target Size)
     -------------------------------------------------------------------------- */
  --tap-min: 44px;
  --focus-width: 3px;
  --focus-offset: 3px;

  /* Hauteurs de gabarit */
  --header-h: 74px;
  --header-h-scrolled: 62px;
  --announce-h: 40px;
}

/* ----------------------------------------------------------------------------
   MODE SOMBRE : appliqué aux surfaces claires uniquement.
   Les sections déjà navy restent identiques : l'identité ne change pas,
   seul le « papier » devient nuit.
   -------------------------------------------------------------------------- */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg-page: var(--c-navy-950);
  --bg-surface: #0A1526;
  --bg-surface-alt: #0D1B30;
  --bg-sunken: #071122;
  --bg-inverse: #0A1526;
  --bg-inverse-alt: #081120;

  --fg-strong: var(--c-ivory-50);
  --fg-default: #DCE5F0;
  --fg-muted: #9FAEC2;
  --fg-subtle: #7E8DA1;
  --fg-accent: var(--c-gold-300);

  --border-subtle: rgba(240, 214, 138, .12);
  --border-default: rgba(240, 214, 138, .20);
  --border-strong: rgba(240, 214, 138, .32);

  --fg-icon: var(--c-gold-300);
  --bg-icon-badge: rgba(201, 162, 39, .16);
  --fg-icon-badge: var(--c-gold-200);
  --bg-hover-soft: rgba(255, 255, 255, .06);
  --bg-accent-soft: rgba(201, 162, 39, .13);
  --bg-selected-soft: rgba(201, 162, 39, .18);
  --bg-topbar: rgba(10, 21, 38, .9);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .5);
  --shadow-md: 0 10px 28px -10px rgba(0, 0, 0, .65);
  --shadow-lg: 0 24px 52px -22px rgba(0, 0, 0, .75);
  --shadow-xl: 0 44px 88px -34px rgba(0, 0, 0, .8);
  --grad-ivory: linear-gradient(180deg, #0A1526 0%, #071122 100%);
}

/* Le thème CLAIR est le défaut du portail, quel que soit le réglage du
   système d'exploitation. Le thème sombre reste disponible, mais seulement
   sur choix explicite du visiteur via le bouton de l'en-tête, qui pose
   data-theme="dark" sur <html>. C'est pourquoi il n'y a volontairement
   aucune règle @media (prefers-color-scheme: dark) ici. */

/* ----------------------------------------------------------------------------
   MOUVEMENT RÉDUIT : WCAG 2.2 · 2.3.3 Animation from Interactions
   Les durées passent à ~0 : les animations existent toujours dans le CSS,
   elles ne s'exécutent simplement plus. Aucune règle à dupliquer ailleurs.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-instant: 1ms;
    --dur-fast: 1ms;
    --dur-base: 1ms;
    --dur-slow: 1ms;
    --dur-slower: 1ms;
    --dur-ceremony: 1ms;
  }
}

/* ----------------------------------------------------------------------------
   CONTRASTE ÉLEVÉ (forced-colors / Windows High Contrast)
   -------------------------------------------------------------------------- */
@media (forced-colors: active) {
  :root {
    --border-subtle: CanvasText;
    --border-default: CanvasText;
    --border-gold: CanvasText;
  }
}

}

/* ==========================================================================
   fonts.css → @layer fonts
   ========================================================================== */
@layer fonts {
/* ============================================================================
   GLUB CONVENT 2027 : 02 · fonts.css
   ----------------------------------------------------------------------------
   Polices auto-hébergées (aucune requête tierce : RGPD + performance).
   Deux fichiers variables par famille, découpés par plage Unicode :
     · latin      → chargé par tous les visiteurs
     · latin-ext  → chargé uniquement si la page contient un caractère concerné
   `font-display: swap` évite le texte invisible (FOIT) ; le fallback métrique
   ci-dessous limite le décalage de mise en page (CLS) pendant le swap.
   Le préchargement du fichier critique se fait dans le <head> de chaque page.
   ========================================================================== */

/* --- Inter (variable 100→900) : interface, corps de texte, chiffres --------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Cormorant Garamond (variable 300→700) : titres, hero, documents ------- */
@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Fallbacks à métrique ajustée -----------------------------------------
   Utilisés pendant le swap : mêmes proportions apparentes que la police finale,
   donc quasiment aucun saut de texte au moment du remplacement.            */
@font-face {
  font-family: "Inter Fallback";
  src: local("Segoe UI"), local("Helvetica Neue"), local("Arial");
  size-adjust: 107%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Cormorant Fallback";
  src: local("Georgia"), local("Times New Roman"), local("Times");
  size-adjust: 88%;
  ascent-override: 105%;
  descent-override: 28%;
  line-gap-override: 0%;
}

}

/* ==========================================================================
   base.css → @layer base
   ========================================================================== */
@layer base {
/* ============================================================================
   GLUB CONVENT 2027 : 03 · base.css
   ----------------------------------------------------------------------------
   Reset moderne + styles d'éléments HTML natifs + socle d'accessibilité.
   Aucune classe ici : uniquement des sélecteurs d'éléments. Un <h2> non stylé
   doit déjà être correct.
   ========================================================================== */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Compense l'en-tête fixe lors des ancres internes (#programme, etc.). */
  scroll-padding-top: calc(var(--header-h) + var(--space-6));
  -moz-tab-size: 2;
  tab-size: 2;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  min-height: 100svh;
  margin: 0;
  background-color: var(--bg-page);
  color: var(--fg-default);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-regular);
  line-height: var(--lh-normal);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Verrou de défilement posé par les modales et l'offcanvas (voir core.js). */
body[data-scroll-locked] {
  overflow: hidden;
  /* La barre de défilement disparaît : on compense pour éviter le saut. */
  padding-right: var(--scrollbar-gap, 0px);
}

/* --- Média ---------------------------------------------------------------- */
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Les attributs width/height du HTML réservent la place : aucun fond opaque
   n'est nécessaire ici, et il masquerait la transparence des SVG (sceau,
   logos, illustrations détourées). Le fond de réservation est posé au niveau
   des conteneurs de média (.card__media, .mosaic__tile). */
img { color: transparent; }

/* Aucune règle globale de remplissage sur les <svg> : en CSS, une déclaration
   l'emporte sur l'attribut de présentation `fill="none"` que portent les
   icônes, ce qui remplirait tous les tracés fermés (cercles, losanges).
   Chaque SVG déclare donc lui-même son remplissage. */

/* --- Formulaires ---------------------------------------------------------- */
input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

button { background: none; border: 0; cursor: pointer; }

textarea { resize: vertical; min-height: 8rem; }

::placeholder { color: var(--fg-subtle); opacity: 1; }

/* Chiffres tabulaires partout où l'alignement compte : les colonnes de
   nombres et les dates restent alignées d'une ligne à l'autre. */
input[type="number"],
input[type="tel"],
input[type="date"],
table,
time { font-variant-numeric: tabular-nums; }

/* --- Typographie ---------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-tight);
  color: var(--fg-strong);
  text-wrap: balance; /* évite les veuves sur les titres courts */
}

h1 { font-size: var(--fs-5xl); line-height: var(--lh-tight); }
h2 { font-size: var(--fs-4xl); }
h3 { font-size: var(--fs-2xl); }
h4 { font-size: var(--fs-xl); }
h5 { font-size: var(--fs-lg); font-family: var(--font-sans); font-weight: var(--fw-semibold); }
h6 { font-size: var(--fs-base); font-family: var(--font-sans); font-weight: var(--fw-semibold); }

p, li, dd, dt, blockquote figcaption { text-wrap: pretty; }

p { max-width: var(--measure); }

a {
  color: var(--fg-accent);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  transition: color var(--dur-fast) var(--ease-out);
}
a:hover { color: var(--c-gold-600); }

strong, b { font-weight: var(--fw-semibold); color: var(--fg-strong); }

/* Sur fond sombre, `--fg-strong` est une encre presque noire : la signature
   « Le Grand Maître » se peignait en #0F1A28 sur le bleu nuit, donc invisible.
   Dans ces zones, le renforcement ne change que la graisse et laisse la
   couleur au contexte. Même piège que le titre de bannière, qui avait dû être
   forcé en blanc pour la même raison. */
:where(.on-dark, .section--navy, .site-footer, .page-hero, .hero) :is(strong, b) {
  color: inherit;
}

small { font-size: var(--fs-sm); }

hr {
  border: 0;
  height: 1px;
  background: var(--border-subtle);
  margin-block: var(--space-8);
}

blockquote {
  margin: 0;
  padding-left: var(--space-5);
  border-left: 2px solid var(--accent);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  line-height: var(--lh-snug);
  color: var(--fg-strong);
}

code, kbd, samp, pre { font-family: var(--font-mono); font-size: .9em; }

code {
  background: var(--bg-surface-alt);
  padding: .12em .38em;
  border-radius: var(--radius-xs);
}

abbr[title] { text-decoration: underline dotted; cursor: help; }

ul, ol { padding-left: var(--space-5); }

:is(ul, ol) :is(ul, ol) { margin-top: var(--space-2); }

li + li { margin-top: var(--space-2); }

dl { margin: 0; }

figure { margin: 0; }

address { font-style: normal; }

/* --- Tableaux ------------------------------------------------------------- */
table { border-collapse: collapse; width: 100%; }
caption { text-align: left; }
th { text-align: left; font-weight: var(--fw-semibold); }

/* --- Détails natifs ------------------------------------------------------- */
summary { cursor: pointer; }
summary::-webkit-details-marker { display: none; }

/* --- Sélection ------------------------------------------------------------ */
::selection {
  background: var(--c-gold-200);
  color: var(--c-navy-900);
}

/* --- Barre de défilement (WebKit + Firefox) -------------------------------- */
html {
  scrollbar-color: var(--c-navy-300) transparent;
  scrollbar-width: thin;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--c-navy-200);
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--c-navy-400); background-clip: content-box; }

/* ============================================================================
   ACCESSIBILITÉ : socle commun (WCAG 2.2 AA)
   ========================================================================== */

/* Anneau de focus unique, visible sur toutes les surfaces.
   :focus-visible seulement → pas d'anneau au clic souris, toujours au clavier. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-xs);
}

/* Sur fond navy, l'or clair garde 8:1 de contraste. */
:where(.on-dark, .site-header, .site-footer, .section--navy)
  :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline-color: var(--focus-ring-on-dark);
}

/* Contenu réservé aux lecteurs d'écran. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Variante qui redevient visible au focus (liens d'évitement). */
.sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Lien d'évitement : WCAG 2.4.1 Bypass Blocks */
.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: var(--z-skiplink);
  padding: var(--space-3) var(--space-5);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  transform: translateY(-160%);
  transition: transform var(--dur-base) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

/* Cibles tactiles : minimum 44×44 px (WCAG 2.2 · 2.5.8). */
:where(nav, .site-footer) a,
:where(button, [role="button"]) {
  min-height: var(--tap-min);
}
:where(nav, .site-footer) a { display: inline-flex; align-items: center; }

/* L'utilisateur a demandé moins d'animation : on neutralise aussi les
   animations infinies déclarées ailleurs, que les durées seules n'arrêtent pas. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Impression ----------------------------------------------------------- */
@media print {
  :root { --bg-page: #fff; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .site-header,
  .site-footer,
  .no-print,
  .announce-bar { display: none !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; }
  .print-only { display: block !important; }
  h1, h2, h3 { break-after: avoid-page; }
  img, table, figure { break-inside: avoid; }
}
.print-only { display: none; }

}

/* ==========================================================================
   utilities.css → @layer utilities
   ========================================================================== */
@layer utilities {
/* ============================================================================
   GLUB CONVENT 2027 : 04 · utilities.css
   ----------------------------------------------------------------------------
   Couche utilitaire de convention Tailwind, écrite à la main et limitée aux
   classes réellement employées dans le projet (« zéro code mort »).
   Les noms sont identiques à Tailwind : la migration vers un build Tailwind
   se ferait sans toucher au HTML.

   Points d'arrêt (mobile first, min-width) :
     sm  ≥ 640px   téléphone large
     md  ≥ 768px   tablette
     lg  ≥ 1024px  laptop
     xl  ≥ 1280px  desktop
     2xl ≥ 1536px  grand écran
   ========================================================================== */

/* ---------------------------------------------------------------- CONTENEUR */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container-wide { max-width: var(--container-wide); }
.container-narrow { max-width: var(--container-narrow); }

/* ---------------------------------------------------------------- AFFICHAGE */
.block { display: block; }
.flex { display: flex; }
.grid { display: grid; }

/* ------------------------------------------------------------------ FLEXBOX */
.flex-wrap { flex-wrap: wrap; }

.items-center { align-items: center; }

.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }


/* --------------------------------------------------------------------- GRID */
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }


.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.gap-5 { gap: var(--space-5); }
.gap-6 { gap: var(--space-6); }
.gap-8 { gap: var(--space-8); }
.gap-10 { gap: var(--space-10); }
.gap-12 { gap: var(--space-12); }

/* --------------------------------------------------------------- POSITIONS */


/* ------------------------------------------------------------------- MARGES */
.mx-auto { margin-inline: auto; }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mt-10 { margin-top: var(--space-10); }
.mt-12 { margin-top: var(--space-12); }
.mt-16 { margin-top: var(--space-16); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-8 { margin-bottom: var(--space-8); }
.mb-10 { margin-bottom: var(--space-10); }
.mb-12 { margin-bottom: var(--space-12); }
.ml-auto { margin-left: auto; }

/* Rythme vertical d'un flux d'éléments : remplace les marges individuelles. */
.stack > * + * { margin-top: var(--stack-gap, var(--space-4)); }
.stack-2 { --stack-gap: var(--space-2); }
.stack-3 { --stack-gap: var(--space-3); }
.stack-4 { --stack-gap: var(--space-4); }
.stack-6 { --stack-gap: var(--space-6); }

/* ---------------------------------------------------------------- REMPLISSAGE */
.p-5 { padding: var(--space-5); }
.p-6 { padding: var(--space-6); }
.pt-0 { padding-top: 0; }

/* ------------------------------------------------------------------ TAILLES */

/* -------------------------------------------------------------- TYPOGRAPHIE */
.font-display { font-family: var(--font-display); }

.text-2xs { font-size: var(--fs-2xs); }
.text-xs { font-size: var(--fs-xs); }
.text-sm { font-size: var(--fs-sm); }
.text-md { font-size: var(--fs-md); }
.text-lg { font-size: var(--fs-lg); }
.text-xl { font-size: var(--fs-xl); }
.text-2xl { font-size: var(--fs-2xl); }
.text-3xl { font-size: var(--fs-3xl); }
.text-4xl { font-size: var(--fs-4xl); }
.text-5xl { font-size: var(--fs-5xl); }

.font-bold { font-weight: var(--fw-bold); }




.text-left { text-align: left; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.no-underline { text-decoration: none; }

/* Coupe le texte après N lignes (titres de cartes, extraits d'articles). */
.line-clamp-3 {
  -webkit-line-clamp: 3;
  line-clamp: 3;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}


/* ------------------------------------------------------------------ COULEUR */
.text-subtle { color: var(--fg-subtle); }
.text-inherit { color: inherit; }


/* Bloc sur fond sombre : bascule automatiquement les couleurs de texte. */
.on-dark { color: var(--fg-on-dark); }
.on-dark :is(h1, h2, h3, h4, h5, h6) { color: var(--fg-on-dark); }
.on-dark :is(p, li, dd) { color: var(--fg-on-dark-muted); }
.on-dark a:not([class*="btn"]) { color: var(--fg-accent-on-dark); }
.on-dark hr { background: var(--border-on-dark); }

/* ---------------------------------------------------------------- BORDURES */
.border-t { border-top: 1px solid var(--border-subtle); }


/* ------------------------------------------------------------------- OMBRES */

/* -------------------------------------------------------------------- DIVERS */
.list-none { list-style: none; padding-left: 0; }
.list-none > li + li { margin-top: 0; }


/* ============================================================================
   VARIANTES RESPONSIVES
   Seules les propriétés qui changent réellement d'un écran à l'autre sont
   déclinées : c'est ce qui garde la feuille de style courte.
   ========================================================================== */

@media (min-width: 640px) {
  .sm\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sm\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
  .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .md\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .lg\:hidden { display: none; }
  .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .lg\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .lg\:col-span-4 { grid-column: span 4 / span 4; }
  .lg\:col-span-5 { grid-column: span 5 / span 5; }
  .lg\:col-span-6 { grid-column: span 6 / span 6; }
  .lg\:col-span-7 { grid-column: span 7 / span 7; }
  .lg\:col-span-8 { grid-column: span 8 / span 8; }
  .lg\:sticky { position: sticky; }
}

@media (min-width: 1280px) {
}

/* Utilitaires « jusqu'à » : utilisés par le menu burger et les tableaux. */
/* Le bouton d'inscription de l'en-tête ne s'affiche qu'à partir de 1400 px :
   en dessous, le parcours passe par le hero, le menu mobile et la barre
   d'action fixe : jamais par un bouton tronqué. */
@media (max-width: 1339.98px) {
  .max-xl\:hidden { display: none; }
}
@media (max-width: 1023.98px) {
  .max-lg\:hidden { display: none; }
}
@media (max-width: 767.98px) {
  .max-md\:hidden { display: none; }
}

}

/* ==========================================================================
   layout.css → @layer layout
   ========================================================================== */
@layer layout {
/* ============================================================================
   GLUB CONVENT 2027 : 05 · layout.css
   ----------------------------------------------------------------------------
   Ossature partagée par toutes les pages : bandeau d'annonce, en-tête,
   navigation (desktop + offcanvas), fil d'Ariane, sections, pied de page.
   ========================================================================== */

/* ============================================================================
   BANDEAU D'ANNONCE : rappel permanent de la gratuité (§21 « Alerte »)
   ========================================================================== */
.announce-bar {
  position: relative;
  z-index: var(--z-header);
  background: var(--grad-gold);
  color: var(--c-navy-900);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
}
.announce-bar__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: var(--announce-h);
  padding-block: var(--space-2);
  text-align: center;
}
.announce-bar a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: .2em;
}
.announce-bar__icon { flex: none; width: 15px; height: 15px; }

/* ============================================================================
   EN-TÊTE
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--c-navy-700);
  color: var(--fg-on-dark);
  border-bottom: 1px solid rgba(240, 214, 138, .14);
  transition: background var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
/* État « défilé » : fond translucide + ombre, posé par ui-nav.js. */
.site-header[data-scrolled="true"] {
  background: rgba(8, 27, 51, .88);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  box-shadow: 0 10px 30px -18px rgba(0, 0, 0, .8);
}
/* L'en-tête porte la classe `container-wide` dans le balisage : six entrées
   de menu, le sélecteur de langue et le bouton d'inscription ne tiennent pas
   dans les 1280 px du gabarit de contenu. Le réglage vit dans le HTML et non
   ici, parce que la couche `utilities` l'emporterait sur la couche `layout`. */

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--header-h);
  transition: min-height var(--dur-base) var(--ease-out);
}
.site-header[data-scrolled="true"] .site-header__inner { min-height: var(--header-h-scrolled); }

/* --- Logo ----------------------------------------------------------------- */
/* `flex: 0 1 auto` avec `min-width: 0` : c'est le logotype qui se retire
   lorsque la place manque, jamais les actions. Sans cela, la somme des trois
   blocs dépasse la largeur d'un téléphone et, `overflow-x: hidden` étant posé
   sur <body>, le bouton burger se trouvait rogné donc inatteignable. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  color: inherit;
  text-decoration: none;
  flex: 0 1 auto;
}
.brand__mark {
  width: 42px;
  height: 42px;
  flex: none;
  transition: transform var(--dur-slow) var(--ease-spring);
}
.brand:hover .brand__mark { transform: rotate(-6deg) scale(1.04); }
.brand__text { display: flex; flex-direction: column; min-width: 0; line-height: 1; }
.brand__name {
  font-family: var(--font-sans);
  font-size: 1.45rem;
  font-weight: var(--fw-bold);
  letter-spacing: .06em;
  color: var(--c-white);
}
.brand__tagline {
  margin-top: 3px;
  font-size: .625rem;
  letter-spacing: .07em;
  color: var(--fg-accent-on-dark);
  white-space: nowrap;
}

/* Filet de sécurité : si le logotype devait malgré tout manquer de place, il
   se tronque proprement au lieu de pousser les actions hors de l'écran. */
.brand__name,
.brand__tagline { overflow: hidden; text-overflow: ellipsis; }

/* Sur téléphone, la signature est le plus large des éléments de l'en-tête
   (147 px mesurés) alors que le nom suffit à identifier l'Obédience. On la
   retire, et on resserre le sélecteur de langue : l'en-tête tient alors dans
   324 px, la largeur utile d'un écran de 360 px. */
@media (max-width: 479.98px) {
  .brand__tagline { display: none; }
  .lang-switch__btn { padding-inline: var(--space-2); }
}

/* En deçà de 360 px, même le nom devient de trop : l'emblème seul identifie
   l'Obédience et reste un lien vers l'accueil. Ce qui compte à cette largeur,
   c'est que le bouton du menu demeure atteignable. */
@media (max-width: 359.98px) {
  .brand__name { display: none; }
}

/* --- Navigation principale (desktop) --------------------------------------- */
.nav-primary { margin-inline: auto; }
.nav-primary__list {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}
.nav-primary__list > li + li { margin-top: 0; }

.nav-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--fg-on-dark);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}
.nav-link:hover { color: var(--fg-accent-on-dark); background: rgba(255, 255, 255, .05); }

/* Soulignement or animé : signature de la navigation. */
.nav-link::after {
  content: "";
  position: absolute;
  left: var(--space-2);
  right: var(--space-2);
  bottom: 2px;
  height: 2px;
  background: var(--grad-gold);
  border-radius: var(--radius-pill);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav-link:hover::after { transform: scaleX(1); }
.nav-link[aria-current="page"] { color: var(--fg-accent-on-dark); }
.nav-link[aria-current="page"]::after { transform: scaleX(1); }

.nav-link__chevron {
  width: 12px;
  height: 12px;
  transition: transform var(--dur-fast) var(--ease-out);
}
.nav-item[data-open="true"] .nav-link__chevron { transform: rotate(180deg); }

/* --- Sous-menu déroulant --------------------------------------------------- */
.nav-item { position: relative; }
.nav-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: var(--z-dropdown);
  min-width: 16rem;
  padding: var(--space-3);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  list-style: none;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -8px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out),
              visibility 0s linear var(--vis-delay, var(--dur-base));
}
.nav-dropdown > li + li { margin-top: 2px; }
.nav-item[data-open="true"] .nav-dropdown {
  --vis-delay: 0s;
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
/* Pointe décorative du menu. */
.nav-dropdown::before {
  content: "";
  position: absolute;
  top: -6px;
  left: 50%;
  width: 12px;
  height: 12px;
  background: var(--bg-surface);
  border-left: 1px solid var(--border-subtle);
  border-top: 1px solid var(--border-subtle);
  transform: translateX(-50%) rotate(45deg);
}
.nav-dropdown__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-default);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.nav-dropdown__link:hover,
.nav-dropdown__link[aria-current="page"] {
  background: var(--bg-hover-soft);
  color: var(--fg-accent);
}
.nav-dropdown__link svg { width: 18px; height: 18px; color: var(--accent); flex: none; }
.nav-dropdown__desc {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-regular);
  color: var(--fg-muted);
}

/* Sous 1400 px, l'espacement entre les trois blocs de l'en-tête se resserre
   encore : c'est la plage la plus disputée en largeur. */
@media (max-width: 1399.98px) {
  .site-header__inner { gap: var(--space-3); }
}

/* Entre 1024 et 1280 px la navigation de bureau apparaît mais le bouton
   « S'inscrire » est encore masqué : c'est la largeur où l'en-tête est le plus
   à l'étroit. Mesuré sans correction, les six liens (677 px), le logotype
   (201 px) et les actions (137 px) réclament 1039 px pour 944 px utiles.
   On retire donc la signature, qui double une information déjà portée par le
   nom, et on resserre les liens : il reste alors une cinquantaine de pixels
   de marge, de quoi absorber un intitulé plus long qu'aujourd'hui. */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  .brand__tagline { display: none; }
  .nav-link {
    padding-inline: var(--space-1);
    letter-spacing: .01em;
  }
}

/* --- Actions à droite de l'en-tête ----------------------------------------- */
.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: none;
  margin-left: auto;
}

/* Sélecteur de langue FR / EN (§13 : visible dans l'en-tête). */
.lang-switch {
  display: inline-flex;
  padding: 3px;
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(240, 214, 138, .22);
  border-radius: var(--radius-sm);
}
.lang-switch__btn {
  padding: var(--space-1) var(--space-3);
  min-height: 32px;
  border-radius: var(--radius-xs);
  color: var(--fg-on-dark-muted);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.lang-switch__btn:hover { color: var(--c-white); }
.lang-switch__btn[aria-current="true"] {
  background: var(--accent);
  color: var(--accent-contrast);
}

/* Bouton thème clair/sombre. */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  color: var(--fg-on-dark);
  border: 1px solid rgba(240, 214, 138, .22);
  background: rgba(255, 255, 255, .07);
  transition: background-color var(--dur-fast) var(--ease-out);
}
.theme-toggle:hover { background: rgba(255, 255, 255, .14); }
.theme-toggle svg { width: 18px; height: 18px; }
.theme-toggle__sun { display: none; }
:root[data-theme="dark"] .theme-toggle__sun { display: block; }
:root[data-theme="dark"] .theme-toggle__moon { display: none; }

/* --- Bouton burger --------------------------------------------------------- */
.burger {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(240, 214, 138, .22);
  background: rgba(255, 255, 255, .07);
}
.burger__box { position: relative; width: 20px; height: 14px; }
.burger__bar {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--fg-on-dark);
  border-radius: var(--radius-pill);
  transition: transform var(--dur-base) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out),
              width var(--dur-base) var(--ease-out);
}
.burger__bar:nth-child(1) { top: 0; }
.burger__bar:nth-child(2) { top: 6px; width: 70%; }
.burger__bar:nth-child(3) { top: 12px; }
.burger[aria-expanded="true"] .burger__bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bar:nth-child(2) { opacity: 0; transform: translateX(-8px); }
.burger[aria-expanded="true"] .burger__bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ============================================================================
   OFFCANVAS : menu mobile plein écran
   ========================================================================== */
.offcanvas-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: rgba(3, 11, 22, .62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-out),
              visibility 0s linear var(--vis-delay, var(--dur-base));
}
.offcanvas-backdrop[data-open="true"] { --vis-delay: 0s; opacity: 1; visibility: visible; }

.offcanvas {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-offcanvas);
  display: flex;
  flex-direction: column;
  width: min(420px, 92vw);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  border-left: 1px solid rgba(240, 214, 138, .18);
  box-shadow: -30px 0 70px -40px rgba(0, 0, 0, .9);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-entrance),
              visibility 0s linear var(--vis-delay, var(--dur-slow));
}
.offcanvas[data-open="true"] { --vis-delay: 0s; transform: translateX(0); visibility: visible; }

.offcanvas__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid rgba(240, 214, 138, .16);
}
.offcanvas__close {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(240, 214, 138, .22);
  color: var(--fg-on-dark);
  transition: background-color var(--dur-fast) var(--ease-out);
}
.offcanvas__close:hover { background: rgba(255, 255, 255, .1); }
.offcanvas__close svg { width: 18px; height: 18px; }

.offcanvas__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-5) var(--space-6) var(--space-8);
}
.offcanvas__footer {
  padding: var(--space-5) var(--space-6);
  border-top: 1px solid rgba(240, 214, 138, .16);
  background: rgba(0, 0, 0, .18);
}

/* Navigation mobile en accordéon. */
.nav-mobile { list-style: none; margin: 0; padding: 0; }
.nav-mobile > li { border-bottom: 1px solid rgba(255, 255, 255, .07); }
.nav-mobile > li + li { margin-top: 0; }
.nav-mobile__link,
.nav-mobile__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-4) 0;
  color: var(--fg-on-dark);
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: var(--fw-semibold);
  text-align: left;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out), padding-left var(--dur-base) var(--ease-out);
}
.nav-mobile__link:hover,
.nav-mobile__toggle:hover { color: var(--fg-accent-on-dark); padding-left: var(--space-2); }
.nav-mobile__link[aria-current="page"] { color: var(--fg-accent-on-dark); }
.nav-mobile__toggle svg { width: 16px; height: 16px; transition: transform var(--dur-base) var(--ease-out); }
.nav-mobile__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

.nav-mobile__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
}
.nav-mobile__panel[data-open="true"] { grid-template-rows: 1fr; }
.nav-mobile__panel > div { overflow: hidden; }
.nav-mobile__sublist {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-4) var(--space-4);
  border-left: 1px solid rgba(240, 214, 138, .28);
}
.nav-mobile__sublist a {
  display: block;
  padding: var(--space-3) 0;
  color: var(--fg-on-dark-muted);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.nav-mobile__sublist a:hover { color: var(--fg-accent-on-dark); }

/* ============================================================================
   SECTIONS
   ========================================================================== */
.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(2rem, 4vw, 3.5rem); }
.section--navy {
  background: var(--grad-navy);
  color: var(--fg-on-dark);
}
.section--ivory { background: var(--bg-surface-alt); }

/* En-tête de section : sur-titre + filet or + titre + chapeau. */
.section-head { max-width: 62ch; margin-bottom: var(--space-10); }
.section-head--center { max-width: 72ch; margin-inline: auto; text-align: center; }
.section-head--center .section-head__rule { margin-inline: auto; }
.section-head--center p { margin-inline: auto; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--fg-accent);
}
/* Le pied de page est sombre sans porter la classe `.on-dark` : sans lui, la
   sur-titre de la lettre d'information restait en or foncé sur le fond
   presque noir, à 3,44 pour un seuil AA de 4,5, et cela sur les 50 pages
   publiques. */
:is(.on-dark, .site-footer, .section--navy) .eyebrow { color: var(--fg-accent-on-dark); }

/* Filet or avec losange central : motif signature repris partout. */
.section-head__rule {
  position: relative;
  width: 130px;
  height: 1px;
  margin-block: var(--space-4) var(--space-5);
  background: var(--grad-gold-line);
}
.section-head__rule::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7px;
  height: 7px;
  background: var(--accent);
  transform: translate(-50%, -50%) rotate(45deg);
}
.section-head__title { margin-bottom: var(--space-4); }
.section-head__lead {
  font-size: var(--fs-lg);
  line-height: var(--lh-relaxed);
  color: var(--fg-muted);
}
.on-dark .section-head__lead { color: var(--fg-on-dark-muted); }

/* ============================================================================
   EN-TÊTE DE PAGE INTÉRIEURE
   ========================================================================== */
.page-hero {
  position: relative;
  isolation: isolate;
  padding-block: clamp(3rem, 7vw, 6rem);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  overflow: hidden;
}
.page-hero__pattern {
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  opacity: .3;
  background-image: url("../img/patterns/geometry-grid.svg");
  background-size: 620px;
  background-position: center;
  mask-image: radial-gradient(ellipse 80% 70% at 70% 30%, #000 10%, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 70% 30%, #000 10%, transparent 72%);
}
/* Le fond est toujours navy : le titre doit être blanc, quel que soit le
   thème. Sans cette règle il héritait de --fg-strong, encre sombre en thème
   clair : donc illisible sur le navy. */
.page-hero__title { margin-bottom: var(--space-4); color: var(--c-white); }
.page-hero :is(h2, h3) { color: var(--c-white); }
.page-hero__lead {
  max-width: 58ch;
  font-size: var(--fs-lg);
  color: var(--fg-on-dark-muted);
}

/* ============================================================================
   FIL D'ARIANE : couplé au JSON-LD BreadcrumbList de chaque page
   ========================================================================== */
.breadcrumb { padding-block: var(--space-4); }
.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}
.breadcrumb__list > li { display: flex; align-items: center; gap: var(--space-2); margin: 0; }
.breadcrumb__list a { color: var(--fg-muted); text-decoration: none; }
.breadcrumb__list a:hover { color: var(--fg-accent); text-decoration: underline; }
.breadcrumb__sep { color: var(--border-strong); }
.breadcrumb [aria-current="page"] { color: var(--fg-strong); font-weight: var(--fw-semibold); }
.page-hero .breadcrumb__list a { color: var(--fg-on-dark-muted); }
.page-hero .breadcrumb [aria-current="page"] { color: var(--fg-accent-on-dark); }
.page-hero .breadcrumb__sep { color: rgba(240, 214, 138, .4); }

/* ============================================================================
   PIED DE PAGE
   ========================================================================== */
.site-footer {
  position: relative;
  background: var(--c-navy-900);
  color: var(--fg-on-dark);
  padding-top: var(--space-16);
  border-top: 1px solid rgba(240, 214, 138, .18);
}
.site-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--grad-gold-line);
}
.site-footer__grid {
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  .site-footer__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .site-footer__grid { grid-template-columns: 1.5fr 1fr 1fr 1.4fr; gap: var(--space-12); }
}
.site-footer h2,
.site-footer h3 {
  font-family: var(--font-sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--fg-accent-on-dark);
  margin-bottom: var(--space-5);
}
.footer-links { list-style: none; margin: 0; padding: 0; }
.footer-links li + li { margin-top: var(--space-1); }
/* Comme `.footer-contact`, cette liste sert aussi au plan du site, sur fond
   clair : la couleur de contexte sombre est donc réservée au pied de page. */
.footer-links a {
  display: inline-flex;
  align-items: center;
  color: inherit;
  font-size: var(--fs-sm);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.site-footer .footer-links a { color: var(--fg-on-dark-muted); }
.footer-links a:hover { color: var(--fg-accent-on-dark); transform: translateX(3px); }

.footer-contact { list-style: none; margin: 0; padding: 0; font-size: var(--fs-sm); }
/* La liste sert aussi sur la page « Contact », posée sur une carte claire.
   La couleur revient donc au contexte, et le pied de page impose la sienne. */
.footer-contact li {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  color: inherit;
}
.site-footer .footer-contact li { color: var(--fg-on-dark-muted); }
.footer-contact li + li { margin-top: var(--space-3); }
.footer-contact svg { width: 17px; height: 17px; flex: none; margin-top: 3px; color: var(--accent); }
.footer-contact a { color: inherit; text-decoration: none; }
.footer-contact a:hover { color: var(--fg-accent-on-dark); text-decoration: underline; }

.social-list { display: flex; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.social-list li + li { margin-top: 0; }
.social-list a {
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid rgba(240, 214, 138, .26);
  border-radius: var(--radius-pill);
  color: var(--fg-on-dark);
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.social-list a:hover {
  background: var(--accent);
  color: var(--accent-contrast);
  transform: translateY(-3px);
}
.social-list svg { width: 17px; height: 17px; }

.site-footer__bottom {
  margin-top: var(--space-12);
  padding-block: var(--space-6);
  border-top: 1px solid rgba(255, 255, 255, .08);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--fs-2xs);
  color: var(--c-navy-200);
}
.legal-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.legal-links li + li { margin-top: 0; }
.legal-links a { color: var(--c-navy-200); text-decoration: none; font-size: var(--fs-2xs); }
.legal-links a:hover { color: var(--fg-accent-on-dark); text-decoration: underline; }

/* ============================================================================
   BOUTON « RETOUR EN HAUT »
   ========================================================================== */
.to-top {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: var(--z-sticky);
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-pill);
  background: var(--c-navy-700);
  color: var(--fg-accent-on-dark);
  border: 1px solid var(--border-gold);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out),
              visibility 0s linear var(--vis-delay, var(--dur-base)),
              background-color var(--dur-fast) var(--ease-out);
}
.to-top[data-visible="true"] { --vis-delay: 0s; opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: var(--accent); color: var(--accent-contrast); }
.to-top svg { width: 18px; height: 18px; }

/* ============================================================================
   BARRE DE PROGRESSION DE LECTURE (pages longues : programme, articles)
   ========================================================================== */
.read-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-toast);
  height: 3px;
  width: 100%;
  transform-origin: left;
  transform: scaleX(0);
  background: var(--grad-gold);
  pointer-events: none;
}

/* ============================================================================
   BARRE D'ACTION MOBILE : CTA toujours atteignable au pouce
   ========================================================================== */
.mobile-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background: rgba(8, 27, 51, .95);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid rgba(240, 214, 138, .2);
  transform: translateY(110%);
  transition: transform var(--dur-slow) var(--ease-entrance);
}
.mobile-cta[data-visible="true"] { transform: translateY(0); }
.mobile-cta .btn { flex: 1; }
@media (min-width: 768px) { .mobile-cta { display: none; } }
/* Évite que la barre masque le pied de page sur mobile. */
@media (max-width: 767.98px) {
  body:has(.mobile-cta) .site-footer__bottom { padding-bottom: var(--space-16); }
}

/* ============================================================================
   INFOLETTRE DU PIED DE PAGE
   ----------------------------------------------------------------------------
   Le bloc vivait auparavant sur la seule page d'accueil ; installé ici, il
   accompagne le visiteur sur les 79 pages. Fond navy oblige, il reprend les
   couleurs de contexte sombre plutôt que celles de la carte claire d'origine.
   ========================================================================== */
.footer-newsletter {
  display: grid;
  gap: var(--space-6);
  align-items: center;
  grid-template-columns: 1fr;
  margin-top: var(--space-12);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  border: 1px solid rgba(240, 214, 138, .28);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, .04);
}
@media (min-width: 900px) {
  .footer-newsletter { grid-template-columns: 1.15fr 1fr; }
}

.footer-newsletter__title {
  margin-top: var(--space-3);
  font-size: var(--fs-2xl);
  color: var(--c-white);
}
.footer-newsletter__text {
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--fg-on-dark-muted);
}

/* `flex-start` empêche le bouton de s'étirer sur toute la hauteur du champ,
   étiquette et zone d'erreur comprises. */
.footer-newsletter__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-3);
}
.footer-newsletter__form .field { flex: 1 1 14rem; }
.footer-newsletter__form .btn {
  flex: 0 0 auto;
  min-height: var(--tap-min);
  height: var(--tap-min);
}
@media (max-width: 479.98px) {
  .footer-newsletter__form .btn { flex: 1 1 100%; }
}

/* Le champ est posé sur un fond sombre : il lui faut ses propres couleurs. */
.footer-newsletter .input {
  background: rgba(0, 0, 0, .28);
  border-color: rgba(240, 214, 138, .3);
  color: var(--c-white);
}
.footer-newsletter .input::placeholder { color: var(--c-navy-200); }
.footer-newsletter .input-group__icon { color: var(--c-gold-300); }

.footer-newsletter__legal {
  grid-column: 1 / -1;
  max-width: none;
  font-size: var(--fs-2xs);
  color: var(--c-navy-200);
}
.footer-newsletter__legal a { color: var(--fg-accent-on-dark); }

}

/* ==========================================================================
   components.css → @layer components
   ========================================================================== */
@layer components {
/* ============================================================================
   GLUB CONVENT 2027 : 06 · components.css
   ----------------------------------------------------------------------------
   Composants réutilisables : boutons, pastilles, cartes, formulaires, alertes,
   modales, accordéons, onglets, notifications, pagination, tableaux, étapes.
   Chaque composant est autonome : il ne dépend d'aucune classe de page.
   ========================================================================== */

/* ============================================================================
   BOUTONS
   Base commune `.btn` + variantes de couleur + variantes de taille.
   ========================================================================== */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--fg-strong);
  --btn-border: transparent;
  --btn-shadow: none;

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: var(--tap-min);
  padding: var(--space-3) var(--space-6);
  border: 1px solid var(--btn-border);
  border-radius: var(--radius-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  box-shadow: var(--btn-shadow);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
  pointer-events: none;
}
.btn svg { width: 18px; height: 18px; flex: none; }

/* Reflet doré qui traverse le bouton au survol : signature « premium ». */
.btn--shine::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .55) 50%, transparent 62%);
  transform: translateX(-120%);
  transition: transform var(--dur-slower) var(--ease-out);
}
.btn--shine:hover::before { transform: translateX(120%); }

/* --- Variantes ------------------------------------------------------------ */
.btn--primary {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-contrast);
  --btn-shadow: var(--shadow-gold);
}
.btn--primary:hover { --btn-bg: var(--accent-hover); }
.btn--primary:active { --btn-bg: var(--accent-press); }

.btn--navy {
  --btn-bg: var(--c-navy-700);
  --btn-fg: var(--c-ivory-50);
  --btn-shadow: var(--shadow-md);
}
.btn--navy:hover { --btn-bg: var(--c-navy-600); }

.btn--outline {
  --btn-fg: var(--fg-strong);
  --btn-border: var(--border-default);
}
.btn--outline:hover {
  --btn-border: var(--accent);
  --btn-fg: var(--fg-accent);
  --btn-bg: var(--bg-accent-soft);
}

/* Sur fond navy : contour or, remplissage au survol. */
.btn--ghost-gold {
  --btn-fg: var(--fg-accent-on-dark);
  --btn-border: rgba(240, 214, 138, .45);
}
.btn--ghost-gold:hover {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-contrast);
  --btn-border: var(--accent);
}

.btn--quiet {
  --btn-fg: var(--fg-muted);
  padding-inline: var(--space-3);
}
.btn--quiet:hover { --btn-bg: var(--bg-surface-alt); --btn-fg: var(--fg-strong); }

.btn--danger {
  --btn-bg: var(--c-danger-500);
  --btn-fg: #fff;
}
.btn--danger:hover { --btn-bg: var(--c-danger-600); }

.btn--success {
  --btn-bg: var(--c-success-500);
  --btn-fg: #fff;
}
.btn--success:hover { --btn-bg: var(--c-success-600); }

/* --- Tailles -------------------------------------------------------------- */
.btn--sm { min-height: 38px; padding: var(--space-2) var(--space-4); font-size: var(--fs-2xs); }
.btn--lg { min-height: 56px; padding: var(--space-4) var(--space-8); font-size: var(--fs-base); }
.btn--block { display: flex; width: 100%; }

/* Bouton à double ligne (comme sur les maquettes : libellé + précision). */
.btn--stacked { flex-direction: column; gap: 2px; padding-block: var(--space-3); }
.btn__hint {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-regular);
  letter-spacing: var(--ls-normal);
  text-transform: none;
  opacity: .85;
}

/* État de chargement : le libellé reste lisible pour les lecteurs d'écran. */
.btn[data-loading="true"] { color: transparent; pointer-events: none; }
.btn[data-loading="true"]::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: var(--btn-fg);
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Groupe de boutons (barres d'outils, filtres). */
.btn-group { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); }

/* ============================================================================
   PASTILLES ET ÉTIQUETTES
   ========================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--bg-surface-alt);
  color: var(--fg-muted);
}
.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.badge--no-dot::before { display: none; }
.badge--gold { background: var(--c-gold-100); color: var(--c-gold-800); }
.badge--success { background: var(--c-success-100); color: var(--c-success-600); }
.badge--warning { background: var(--c-warning-100); color: var(--c-warning-600); }
.badge--danger { background: var(--c-danger-100); color: var(--c-danger-600); }
.badge--info { background: var(--c-info-100); color: var(--c-info-600); }
.badge--navy { background: var(--c-navy-100); color: var(--c-navy-700); }
.on-dark .badge--gold { background: rgba(201, 162, 39, .18); color: var(--c-gold-200); }

/* Chip filtrante (tableaux de bord, listes filtrables). */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  color: var(--fg-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease-out);
}
.chip:hover { border-color: var(--accent); color: var(--fg-strong); }
.chip[aria-pressed="true"] {
  background: var(--c-navy-700);
  border-color: var(--c-navy-700);
  color: var(--c-ivory-50);
}
.chip__count {
  padding-inline: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--bg-surface-alt);
  color: var(--fg-muted);
  font-size: var(--fs-3xs);
  font-variant-numeric: tabular-nums;
}
.chip[aria-pressed="true"] .chip__count { background: rgba(255, 255, 255, .16); color: var(--c-gold-200); }

/* ============================================================================
   CARTES
   ========================================================================== */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.card__body { padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-3); flex: 1; }
.card__title { font-size: var(--fs-xl); }
.card__text { color: var(--fg-muted); font-size: var(--fs-sm); line-height: var(--lh-relaxed); }
.card__footer {
  margin-top: auto;
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.card__media { position: relative; overflow: hidden; background: var(--bg-surface-alt); }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slower) var(--ease-out); }
.card__media--16-9 { aspect-ratio: 16 / 9; }

/* Carte interactive : toute la carte est cliquable grâce au lien étiré. */
.card--interactive:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-gold);
}
.card--interactive:hover .card__media img { transform: scale(1.05); }
.card--interactive:focus-within { box-shadow: var(--shadow-lg); border-color: var(--accent); }
.stretched-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card--navy {
  background: rgba(255, 255, 255, .04);
  border-color: rgba(240, 214, 138, .18);
  color: var(--fg-on-dark);
}
.card--navy .card__text { color: var(--fg-on-dark-muted); }
.card--navy .card__title { color: var(--fg-on-dark); }
.card--navy .card__footer { border-top-color: rgba(240, 214, 138, .16); }
.card--navy.card--interactive:hover { background: rgba(255, 255, 255, .07); }

/* Bord supérieur doré révélé au survol. */
.card--accent-top::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--grad-gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease-out);
  z-index: 2;
}
.card--accent-top:hover::before { transform: scaleX(1); }

/* Icône ronde en tête de carte. */
.card__icon {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-pill);
  background: var(--bg-icon-badge);
  color: var(--fg-icon-badge);
  flex: none;
}
.card__icon svg { width: 24px; height: 24px; }
.card--navy .card__icon { background: rgba(201, 162, 39, .16); }

   FORMULAIRES
   ========================================================================== */
.form-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 639.98px) { .form-grid { grid-template-columns: 1fr; } }
.form-grid > .field--full { grid-column: 1 / -1; }

.fieldset {
  border: 0;
  padding: 0;
  margin: 0;
}
.fieldset + .fieldset { margin-top: var(--space-10); }
.fieldset__legend {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: 0 0 var(--space-5);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  color: var(--fg-strong);
}
.fieldset__num {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--c-navy-700);
  color: var(--c-gold-300);
  font-family: var(--font-sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
}

.field { display: flex; flex-direction: column; gap: var(--space-2); }

.label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--fg-strong);
}
.label__required { color: var(--c-danger-500); }
.label__optional {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-regular);
  color: var(--fg-subtle);
  text-transform: none;
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--fg-strong);
  font-size: var(--fs-base);
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out);
}
.input:hover,
.select:hover,
.textarea:hover { border-color: var(--border-strong); }
.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(201, 162, 39, .22);
}
.input[readonly] { background: var(--bg-surface-alt); color: var(--fg-muted); }
.input[disabled],
.select[disabled] { background: var(--bg-surface-alt); color: var(--fg-subtle); cursor: not-allowed; }

/* Le chevron du <select> est dessiné en CSS : pas d'image à charger. */
.select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-10);
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:
    calc(100% - 20px) calc(50% + 2px),
    calc(100% - 14px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* Champ avec icône à gauche (recherche, e-mail, téléphone). */
.input-group { position: relative; display: flex; align-items: center; }
.input-group__icon {
  position: absolute;
  left: var(--space-4);
  width: 18px;
  height: 18px;
  color: var(--fg-subtle);
  pointer-events: none;
}
.input-group .input { padding-left: calc(var(--space-4) * 2 + 18px); }
.input-group__action {
  position: absolute;
  right: var(--space-2);
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-xs);
  color: var(--fg-muted);
}
.input-group__action:hover { background: var(--bg-surface-alt); color: var(--fg-strong); }
.input-group__action svg { width: 18px; height: 18px; }
.input-group:has(.input-group__action) .input { padding-right: calc(36px + var(--space-4)); }

.hint { font-size: var(--fs-2xs); color: var(--fg-muted); }

/* Message d'erreur : rendu seulement quand le champ est marqué invalide.
   Le lien aria-describedby est posé dans le HTML, pas en JavaScript. */
.error-text {
  display: none;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-medium);
  color: var(--c-danger-600);
}
.error-text svg { width: 14px; height: 14px; flex: none; }
.field[data-invalid="true"] .error-text { display: flex; }
.field[data-invalid="true"] :is(.input, .select, .textarea) {
  border-color: var(--c-danger-500);
  background: var(--c-danger-100);
}
.field[data-invalid="true"] :is(.input, .select, .textarea):focus {
  box-shadow: 0 0 0 3px rgba(179, 38, 30, .2);
}
.field[data-valid="true"] :is(.input, .select) { border-color: var(--c-success-500); }

/* --- Cases et boutons radio ------------------------------------------------ */
.check {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.check:hover { background: var(--bg-surface-alt); }
.check input {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  flex: none;
  accent-color: var(--c-navy-700);
  cursor: pointer;
}
.check__label { font-size: var(--fs-sm); line-height: var(--lh-normal); }
.check__label small { display: block; margin-top: 2px; color: var(--fg-muted); font-size: var(--fs-2xs); }

/* Radio « carte » : choix visuellement lisible (Oui / Non visa, par exemple). */
.radio-cards { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr)); }
.radio-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease-out);
}
.radio-card:hover { border-color: var(--accent); background: var(--bg-accent-soft); }
.radio-card input { width: 20px; height: 20px; margin: 1px 0 0; flex: none; accent-color: var(--c-navy-700); }
.radio-card__title { display: block; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--fg-strong); }
.radio-card__desc { display: block; margin-top: 2px; font-size: var(--fs-2xs); color: var(--fg-muted); }
.radio-card:has(input:checked) {
  border-color: var(--accent);
  background: var(--bg-selected-soft);
  box-shadow: 0 0 0 1px var(--accent);
}

/* --- Interrupteur ---------------------------------------------------------- */
.switch { display: inline-flex; align-items: center; gap: var(--space-3); cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track {
  position: relative;
  width: 46px;
  height: 26px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--border-strong);
  transition: background-color var(--dur-base) var(--ease-out);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-spring);
}
.switch input:checked + .switch__track { background: var(--c-success-500); }
.switch input:checked + .switch__track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch__track { outline: var(--focus-width) solid var(--focus-ring); outline-offset: var(--focus-offset); }

/* --- Zone de dépôt de fichier ---------------------------------------------- */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-8);
  border: 2px dashed var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface-alt);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.dropzone:hover,
.dropzone[data-dragover="true"] { border-color: var(--accent); background: var(--bg-accent-soft); }
.dropzone svg { width: 32px; height: 32px; color: var(--fg-subtle); }
.dropzone input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }

/* --- Bloc conditionnel (affiché selon une réponse précédente) --------------- */
.conditional {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows var(--dur-slow) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.conditional > div { overflow: hidden; }
.conditional[data-open="true"] { grid-template-rows: 1fr; opacity: 1; }

/* ============================================================================
   ÉTAPES DU FORMULAIRE (assistant multi-étapes)
   ========================================================================== */
.steps {
  display: flex;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: step;
}
.steps > li { flex: 1; margin: 0; }
.step {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: 3px solid var(--border-subtle);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-subtle);
  transition: border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.step__index {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  font-size: var(--fs-3xs);
}
.step[data-state="current"] { border-top-color: var(--accent); color: var(--fg-strong); }
.step[data-state="current"] .step__index { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.step[data-state="done"] { border-top-color: var(--c-success-500); color: var(--c-success-600); }
.step[data-state="done"] .step__index { background: var(--c-success-500); border-color: var(--c-success-500); color: #fff; }
.step__label { display: none; }
@media (min-width: 640px) { .step__label { display: block; } }

/* ============================================================================
   ALERTES ET ENCADRÉS
   ========================================================================== */
.alert {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--c-info-500);
  background: var(--c-info-100);
  color: var(--c-info-600);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
.alert__icon { width: 22px; height: 22px; flex: none; margin-top: 1px; }
.alert__title { font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: var(--fw-bold); margin-bottom: var(--space-1); color: inherit; }
.alert p { color: inherit; max-width: none; }
/* `:not(.btn)` : sans cette exclusion, la règle l'emportait sur `.btn` par sa
   spécificité (0,1,1 contre 0,1,0) et un bouton or posé dans une alerte
   ambrée héritait de l'ambre, soit un libellé à 2,45 contre le fond or. */
.alert a:not(.btn) { color: inherit; font-weight: var(--fw-semibold); }
.alert--success { border-left-color: var(--c-success-500); background: var(--c-success-100); color: var(--c-success-600); }
.alert--warning { border-left-color: var(--c-warning-500); background: var(--c-warning-100); color: var(--c-warning-600); }
.alert--danger { border-left-color: var(--c-danger-500); background: var(--c-danger-100); color: var(--c-danger-600); }
.alert--gold { border-left-color: var(--accent); background: var(--bg-accent-soft); color: var(--fg-accent); }

/* Encadré légal réutilisé partout où la lettre d'invitation est proposée. */
.legal-note {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: var(--bg-accent-soft);
}
.legal-note__icon { width: 26px; height: 26px; flex: none; color: var(--fg-accent); }
.legal-note__title {
  font-family: var(--font-sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--fg-accent);
  margin-bottom: var(--space-2);
}
.legal-note p { font-size: var(--fs-sm); color: var(--fg-default); max-width: none; }
.on-dark .legal-note { background: rgba(201, 162, 39, .1); border-color: rgba(240, 214, 138, .3); }
.on-dark .legal-note p { color: var(--fg-on-dark-muted); }
.on-dark .legal-note__title,
.on-dark .legal-note__icon { color: var(--c-gold-300); }

/* ============================================================================
   MODALE
   ========================================================================== */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  padding: var(--space-4);
  background: rgba(3, 11, 22, .68);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-out),
              visibility 0s linear var(--vis-delay, var(--dur-base));
}
.modal-backdrop[data-open="true"] { --vis-delay: 0s; opacity: 1; visibility: visible; }

.modal {
  position: relative;
  z-index: var(--z-modal);
  width: min(640px, 100%);
  max-height: min(86svh, 900px);
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  transform: translateY(18px) scale(.98);
  opacity: 0;
  transition: transform var(--dur-slow) var(--ease-entrance), opacity var(--dur-base) var(--ease-out);
}
.modal-backdrop[data-open="true"] .modal { transform: none; opacity: 1; }

.modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-6);
  border-bottom: 1px solid var(--border-subtle);
}
.modal__title { font-size: var(--fs-2xl); }
.modal__close {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.modal__close:hover { background: var(--bg-surface-alt); color: var(--fg-strong); }
.modal__close svg { width: 18px; height: 18px; }
.modal__body { padding: var(--space-6); overflow-y: auto; overscroll-behavior: contain; }
.modal__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-6);
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-surface-alt);
}

/* ============================================================================
   ACCORDÉON (FAQ)
   ========================================================================== */
.accordion { border-top: 1px solid var(--border-subtle); }
.accordion__item { border-bottom: 1px solid var(--border-subtle); }
.accordion__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  width: 100%;
  padding: var(--space-5) 0;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  color: var(--fg-strong);
  text-align: left;
  transition: color var(--dur-fast) var(--ease-out);
}
.accordion__trigger:hover { color: var(--fg-accent); }
.accordion__icon {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
/* Croix « + » qui devient « − » : dessinée en CSS, aucune icône chargée. */
.accordion__icon::before,
.accordion__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: currentColor;
  border-radius: 2px;
  transform: translate(-50%, -50%);
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.accordion__icon::before { width: 13px; height: 1.5px; }
.accordion__icon::after { width: 1.5px; height: 13px; }
.accordion__trigger[aria-expanded="true"] .accordion__icon {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}
.accordion__trigger[aria-expanded="true"] .accordion__icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }

.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
}
.accordion__panel[data-open="true"] { grid-template-rows: 1fr; }
.accordion__panel > div { overflow: hidden; }
.accordion__content { padding-bottom: var(--space-6); color: var(--fg-muted); line-height: var(--lh-relaxed); }
.accordion__content > * + * { margin-top: var(--space-4); }

.on-dark .accordion { border-color: rgba(240, 214, 138, .18); }
.on-dark .accordion__item { border-color: rgba(240, 214, 138, .18); }
.on-dark .accordion__trigger { color: var(--fg-on-dark); }
.on-dark .accordion__icon { border-color: rgba(240, 214, 138, .35); }
.on-dark .accordion__content { color: var(--fg-on-dark-muted); }

/* ============================================================================
   ONGLETS
   ========================================================================== */
.tabs__list {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-8);
}
.tabs__list::-webkit-scrollbar { display: none; }
.tabs__tab {
  position: relative;
  padding: var(--space-4) var(--space-5);
  white-space: nowrap;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease-out);
}
.tabs__tab::after {
  content: "";
  position: absolute;
  left: var(--space-4);
  right: var(--space-4);
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform var(--dur-base) var(--ease-out);
}
.tabs__tab:hover { color: var(--fg-strong); }
.tabs__tab[aria-selected="true"] { color: var(--fg-accent); }
.tabs__tab[aria-selected="true"]::after { transform: scaleX(1); }
.tabs__panel[hidden] { display: none; }

/* ============================================================================
   NOTIFICATIONS (toasts)
   ========================================================================== */
.toast-stack {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: min(380px, calc(100vw - 2rem));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--accent);
  background: var(--c-navy-800);
  color: var(--c-ivory-50);
  box-shadow: var(--shadow-xl);
  font-size: var(--fs-sm);
  pointer-events: auto;
  animation: toast-in var(--dur-slow) var(--ease-entrance);
}
.toast[data-leaving="true"] { animation: toast-out var(--dur-base) var(--ease-out) forwards; }
.toast--success { border-left-color: var(--c-success-500); }
.toast--danger { border-left-color: var(--c-danger-500); }
.toast__icon { width: 20px; height: 20px; flex: none; color: var(--accent); }
.toast--success .toast__icon { color: #6ee7b7; }
.toast--danger .toast__icon { color: #fca5a5; }
.toast__close { margin-left: auto; color: var(--c-navy-200); }
.toast__close:hover { color: #fff; }
.toast__close svg { width: 15px; height: 15px; }
@keyframes toast-in { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateX(24px); } }

/* ============================================================================
   TABLEAUX DE DONNÉES
   ========================================================================== */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  -webkit-overflow-scrolling: touch;
}
.table { min-width: 46rem; font-size: var(--fs-sm); }
.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--space-4) var(--space-5);
  background: var(--bg-surface-alt);
  border-bottom: 1px solid var(--border-default);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  white-space: nowrap;
}
.table tbody td { padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-subtle); vertical-align: middle; }
.table tbody tr { transition: background-color var(--dur-fast) var(--ease-out); }
.table tbody tr:hover { background: var(--bg-hover-soft); }
.table tbody tr:last-child td { border-bottom: 0; }
.table__id { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--fg-muted); white-space: nowrap; }
.table__actions { display: flex; gap: var(--space-1); justify-content: flex-end; }

/* En-tête triable : l'état est porté par aria-sort. */
.table th[aria-sort] .th-sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}
.th-sort__arrow { width: 12px; height: 12px; opacity: .35; transition: opacity var(--dur-fast), transform var(--dur-fast); }
.table th[aria-sort="ascending"] .th-sort__arrow { opacity: 1; }
.table th[aria-sort="descending"] .th-sort__arrow { opacity: 1; transform: rotate(180deg); }

/* Barre d'outils : recherche, filtres, nombre de lignes, export. */
.datatable__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.datatable__search { flex: 1 1 15rem; min-width: 12rem; }
.datatable__filter { flex: 0 1 11rem; }
/* Une base de 11 rem sans croissance laisse, sur téléphone, des listes à
   demi-largeur alignées à gauche sous un champ de recherche pleine largeur.
   Chaque contrôle prend donc sa propre ligne entière. */
@media (max-width: 639.98px) {
  .datatable__search,
  .datatable__filter { flex: 1 1 100%; }
}
.datatable__filter .label,
.datatable__search .label { margin-bottom: var(--space-1); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--fg-muted); }
.datatable__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-5);
  font-size: var(--fs-xs);
  color: var(--fg-muted);
}
.datatable__empty { padding: var(--space-12) var(--space-6); text-align: center; color: var(--fg-muted); }
.datatable__empty svg { width: 44px; height: 44px; margin: 0 auto var(--space-4); color: var(--border-strong); }

/* ============================================================================
   PAGINATION
   ========================================================================== */
/* Au maximum la pagination affiche neuf commandes : précédent, cinq numéros,
   des points de suspension, la dernière page et suivant. À 40 px chacune elle
   réclame 392 px, soit davantage que la largeur utile d'une carte sur un
   téléphone de 360 px. Elle passe donc à la ligne plutôt que d'être rognée :
   le bouton « suivant » doit rester atteignable. */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  margin: 0;
  padding: 0;
}
.pagination li { margin: 0; }
.pagination__link {
  display: inline-grid;
  place-items: center;
  min-width: 40px;
  height: 40px;
  padding-inline: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.pagination__link:hover { background: var(--bg-surface-alt); color: var(--fg-strong); }
.pagination__link[aria-current="page"] { background: var(--c-navy-700); color: var(--c-ivory-50); }
.pagination__link[aria-disabled="true"] { opacity: .4; pointer-events: none; }
.pagination__link svg { width: 16px; height: 16px; }

@media (max-width: 479.98px) {
  .pagination__link { min-width: 36px; height: 36px; padding-inline: var(--space-1); }
}

/* ============================================================================
   BARRES DE PROGRESSION
   ========================================================================== */
.progress {
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--bg-sunken);
  overflow: hidden;
}
.progress__bar {
  height: 100%;
  width: var(--value, 0%);
  border-radius: inherit;
  background: var(--grad-gold);
  transition: width var(--dur-slower) var(--ease-out);
}

/* ============================================================================
   AVATARS ET LISTES DESCRIPTIVES
   ========================================================================== */
.avatar {
  display: inline-grid;
  place-items: center;
  width: var(--avatar-size, 44px);
  height: var(--avatar-size, 44px);
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--c-navy-700);
  color: var(--c-gold-300);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .04em;
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }

.data-list { display: grid; gap: var(--space-4); }
.data-list__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px dashed var(--border-subtle);
}
.data-list__row:last-child { border-bottom: 0; padding-bottom: 0; }
.data-list__key { font-size: var(--fs-2xs); font-weight: var(--fw-semibold); letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--fg-muted); }
.data-list__val { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--fg-strong); text-align: right; }

/* ============================================================================
   ÉTAT VIDE / CHARGEMENT
   ========================================================================== */
.skeleton {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--bg-surface-alt) 25%, var(--bg-sunken) 37%, var(--bg-surface-alt) 63%);
  background-size: 400% 100%;
  animation: skeleton 1.4s ease infinite;
}
@keyframes skeleton { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

}

/* ==========================================================================
   patterns.css → @layer patterns
   ========================================================================== */
@layer patterns {
/* ============================================================================
   GLUB CONVENT 2027 : 07 · patterns.css
   ----------------------------------------------------------------------------
   Assemblages de composants propres au portail : hero, compte à rebours,
   compteurs, programme, piliers, bandeau anti-fraude, témoignages, badge,
   lettre d'invitation, cartes pratiques, pages d'authentification, erreurs.
   ========================================================================== */

/* ============================================================================
   HERO D'ACCUEIL
   ========================================================================== */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(560px, 82svh, 860px);
  padding-block: clamp(3rem, 7vw, 6rem);
  background: var(--c-navy-800);
  color: var(--fg-on-dark);
  overflow: hidden;
}

/* Couches du décor, du fond vers l'avant : ciel → ville → voile → géométrie */
.hero__scene { position: absolute; inset: 0; z-index: var(--z-below); }
.hero__scene img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 62%;
}
.hero__veil {
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  background:
    linear-gradient(90deg, var(--c-navy-900) 4%, rgba(11, 37, 69, .88) 42%, rgba(11, 37, 69, .35) 72%, rgba(11, 37, 69, .55) 100%),
    linear-gradient(180deg, rgba(6, 20, 36, .72) 0%, transparent 34%, rgba(6, 20, 36, .78) 100%);
}
.hero__geometry {
  position: absolute;
  top: 50%;
  right: -6%;
  z-index: var(--z-below);
  width: min(760px, 78vw);
  transform: translateY(-50%);
  opacity: .16;
  pointer-events: none;
  color: var(--c-gold-300);
}

.hero__inner { position: relative; width: 100%; }
.hero__content { max-width: 44rem; }

.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--c-gold-300);
}
.hero__eyebrow::after {
  content: "";
  flex: 1;
  max-width: 120px;
  height: 1px;
  background: var(--grad-gold-line);
}
/* Sur téléphone le texte occupe presque toute la largeur : il ne reste qu'une
   dizaine de pixels au filet, qui se lit alors comme un tiret égaré à la fin
   de la ligne. Mieux vaut pas de filet du tout qu'un moignon de filet. */
@media (max-width: 639.98px) {
  .hero__eyebrow::after { display: none; }
}

.hero__title {
  margin-top: var(--space-4);
  font-size: var(--fs-6xl);
  font-weight: var(--fw-bold);
  line-height: .95;
  letter-spacing: var(--ls-tighter);
  color: var(--c-white);
}
/* « GLUB 2027 » se lit d'un seul tenant, comme sur les maquettes du Comité :
   l'année n'est pas un sous-titre, elle fait partie du nom de l'événement. */
.hero__title em {
  font-style: normal;
  color: var(--c-gold-300);
}

/* Ligne date + lieu, avec pictogrammes. */
.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-8);
  margin-top: var(--space-6);
  padding: 0;
  list-style: none;
}
.hero__facts li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: var(--fw-medium);
  color: var(--c-white);
}
.hero__facts svg { width: 22px; height: 22px; color: var(--c-gold-400); flex: none; }

.hero__lead {
  margin-top: var(--space-6);
  max-width: 34rem;
  font-size: var(--fs-lg);
  line-height: var(--lh-relaxed);
  color: var(--c-navy-100);
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-8);
}
@media (max-width: 480px) { .hero__cta .btn { width: 100%; } }

/* Sceau « événement officiel » (repris de la maquette 2). */
.hero__seal {
  position: absolute;
  top: clamp(1rem, 4vw, 3rem);
  right: clamp(1rem, 4vw, 3rem);
  width: clamp(88px, 11vw, 132px);
  animation: seal-rotate 34s linear infinite;
}
@keyframes seal-rotate { to { transform: rotate(360deg); } }
@media (max-width: 767.98px) { .hero__seal { display: none; } }

/* ============================================================================
   BANDE DE PILIERS (les 5 promesses du Convent)
   ========================================================================== */
.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  background: var(--bg-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.pillar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-5);
  text-align: center;
  transition: background-color var(--dur-base) var(--ease-out);
}
.pillar + .pillar { border-left: 1px solid var(--border-subtle); }
@media (max-width: 767.98px) {
  .pillar + .pillar { border-left: 0; border-top: 1px solid var(--border-subtle); }
}
.pillar:hover { background: var(--bg-hover-soft); }
.pillar__icon {
  width: 46px;
  height: 46px;
  color: var(--fg-icon);
  transition: transform var(--dur-slow) var(--ease-spring), color var(--dur-base) var(--ease-out);
}
.pillar:hover .pillar__icon { transform: translateY(-4px) scale(1.06); color: var(--accent); }
.pillar__title {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--fg-strong);
}
.pillar__text { font-size: var(--fs-2xs); color: var(--fg-muted); line-height: var(--lh-normal); }

/* ============================================================================
   PROGRAMME : chronologie verticale
   ========================================================================== */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline > li { margin: 0; }
.timeline__item {
  position: relative;
  display: grid;
  grid-template-columns: 68px 1fr;
  gap: var(--space-5);
  padding-block: var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
  transition: padding-left var(--dur-base) var(--ease-out);
}
.timeline__item:hover { padding-left: var(--space-3); }
.timeline__item:last-child { border-bottom: 0; }
.on-dark .timeline__item { border-color: rgba(240, 214, 138, .16); }

.timeline__date {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--space-2);
  height: fit-content;
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-sm);
  background: rgba(201, 162, 39, .08);
}
.timeline__day {
  font-family: var(--font-sans);
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  line-height: 1;
  color: var(--fg-accent);
}
.on-dark .timeline__day { color: var(--c-gold-300); }
.timeline__month {
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.on-dark .timeline__month { color: var(--fg-on-dark-muted); }
.timeline__title { font-family: var(--font-display); font-size: var(--fs-xl); margin-bottom: var(--space-1); }
.on-dark .timeline__title { color: var(--fg-on-dark); }
.timeline__desc { font-size: var(--fs-sm); color: var(--fg-muted); }
.on-dark .timeline__desc { color: var(--fg-on-dark-muted); }
.timeline__tag { margin-top: var(--space-3); }

/* ============================================================================
   COMPTEURS « DÉJÀ INSCRITS »
   ========================================================================== */
.counters {
  display: grid;
  gap: var(--space-6);
  align-items: center;
  grid-template-columns: 1fr;
  padding: var(--space-8) clamp(1.5rem, 4vw, 3rem);
  border: 1px solid rgba(240, 214, 138, .28);
  border-radius: var(--radius-lg);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
}
@media (min-width: 900px) { .counters { grid-template-columns: auto 1fr auto; gap: var(--space-10); } }

.counters__globe { width: 74px; height: 74px; color: var(--c-gold-400); justify-self: center; }
.counters__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
  text-align: center;
}
.counters__list > li { margin: 0; }
.counters__list > li + li { border-left: 1px solid rgba(240, 214, 138, .22); }
.counter__value {
  display: block;
  font-family: var(--font-sans);
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--c-gold-300);
}
.counter__label {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--c-navy-100);
}
.counters__note { font-size: var(--fs-3xs); color: var(--c-navy-200); text-align: center; }

/* ============================================================================
   BANDEAU ANTI-FRAUDE (§14 : message public obligatoire)
   ========================================================================== */
.fraud-band {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  align-items: center;
  padding: var(--space-6) clamp(1.25rem, 4vw, 2.5rem);
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-lg);
  background: var(--bg-accent-soft);
}
@media (min-width: 768px) { .fraud-band { grid-template-columns: auto 1fr; gap: var(--space-8); } }
.fraud-band__mark { display: flex; align-items: center; gap: var(--space-4); }
.fraud-band__mark svg { width: 40px; height: 40px; color: var(--fg-accent); flex: none; }
.fraud-band__title {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-accent);
}
.fraud-band__list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.fraud-band__list li {
  position: relative;
  margin: 0;
  padding-left: var(--space-5);
  font-size: var(--fs-sm);
  color: var(--fg-default);
}
.fraud-band__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 6px;
  height: 6px;
  background: var(--accent);
  transform: rotate(45deg);
}
.on-dark .fraud-band { background: rgba(201, 162, 39, .1); border-color: rgba(240, 214, 138, .3); }
.on-dark .fraud-band__title { color: var(--c-gold-300); }
.on-dark .fraud-band__mark svg { color: var(--c-gold-300); }
.on-dark .fraud-band__list li { color: var(--fg-on-dark-muted); }

/* ============================================================================
   PORTRAIT DU GRAND MAÎTRE
   ----------------------------------------------------------------------------
   Il accompagne son propre message, sur fond bleu nuit. Le filet or reprend
   celui de l'invocation, juste en face.
   ========================================================================== */
.gm-portrait {
  margin: 0 0 var(--space-6);
  width: min(13.75rem, 100%);
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(240, 214, 138, .38);
  box-shadow: var(--shadow-lg);
  background: var(--c-navy-800);
}
.gm-portrait img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 20%; }

/* ============================================================================
   MEMBRES DU COMITÉ D'ORGANISATION
   ========================================================================== */
.member-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 768px) { .member-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Trois colonnes sur toute la largeur du conteneur donneraient des portraits
   de 384 px de large, soit 480 px de haut : ils écraseraient le reste de la
   page. La grille est donc bornée et centrée. */
@media (min-width: 1024px) {
  .member-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: 58rem;
    margin-inline: auto;
  }
}

.member { margin: 0; text-align: center; }
.member__portrait {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
  background: var(--bg-surface-alt);
  aspect-ratio: 4 / 5;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.member__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 22%; }
/* Un filet or au survol, comme sur les autres cartes de la page. */
.member:hover .member__portrait {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent);
}
.member__body { margin-top: var(--space-4); }
.member__role {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-accent);
}
.member__name {
  margin-top: var(--space-1);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--fg-strong);
  text-wrap: balance;
}

/* ============================================================================
   RUBAN DES PARTENAIRES
   ----------------------------------------------------------------------------
   Défilement continu, sans pastilles ni flèches : la liste est écrite deux
   fois et le ruban translate d'exactement la moitié de sa largeur, si bien que
   l'image de fin coïncide avec l'image de départ et que la boucle est
   invisible. `width: max-content` laisse la rangée prendre sa largeur réelle
   au lieu de se comprimer dans le conteneur.
   ========================================================================== */
.partner-marquee {
  position: relative;
  overflow: hidden;
  /* Les extrémités s'effacent : le ruban entre et sort du champ au lieu de se
     couper net sur le bord de la section. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.partner-marquee__track {
  display: flex;
  align-items: flex-start;
  width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
  animation: partner-scroll 48s linear infinite;
}
.partner-marquee__track > li + li { margin-top: 0; }
.partner-marquee:hover .partner-marquee__track,
.partner-marquee:focus-within .partner-marquee__track { animation-play-state: paused; }

/* La liste est écrite QUATRE fois : il faut qu'après avoir défilé d'un
   exemplaire, la piste couvre encore tout l'écran, sinon un vide apparaît en
   fin de cycle. Quatre exemplaires de quatre partenaires font 3072 px pour un
   cycle de 768 px : il en reste 2304, davantage que le plus large des écrans
   visés.

   La gouttière est portée par `.partner-marquee__item` et non par un `gap` du
   conteneur : chaque élément occupe alors exactement un quart de la piste, et
   la translation de 25 % retombe au pixel près sur l'exemplaire suivant. Avec
   un `gap`, il manquerait une gouttière sur quatre et le ruban dériverait. */
@keyframes partner-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-25%); }
}

.partner-marquee__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  width: 9.5rem;
  margin-right: var(--space-10);
}
.partner {
  display: grid;
  place-items: center;
  width: 9.5rem;
  height: 9.5rem;
  padding: var(--space-3);
  /* Le logotype garde l'aplat sur lequel il a été fourni : la tuile reprend
     cette couleur, le remplissage devient invisible et la marque reste intacte. */
  background: var(--tile, var(--bg-surface));
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.partner img { width: 100%; height: 100%; object-fit: contain; }
.partner-marquee__item:hover .partner {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.partner__name {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
  text-align: center;
}

/* Un défilement perpétuel est exactement ce que ce réglage vise : on l'arrête
   et la rangée redevient une liste qui se parcourt à la main. */
@media (prefers-reduced-motion: reduce) {
  .partner-marquee { -webkit-mask-image: none; mask-image: none; overflow-x: auto; }
  .partner-marquee__track { animation: none; }
}

/* ============================================================================
   CARTES PRATIQUES (Venir, Hébergement, Transport, Visa, FAQ, Contacts)
   ========================================================================== */
/* Six rubriques, demandées en trois colonnes sur deux rangées en bureau.
   `auto-fit` donnait cinq colonnes à 1440 px, donc une seconde rangée
   orpheline d'une seule carte : on fixe donc le nombre de colonnes. */
.practical-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .practical-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .practical-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.practical-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  text-align: center;
  align-items: center;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.practical-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); border-color: var(--border-gold); }
.practical-card__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background: var(--bg-icon-badge);
  color: var(--fg-icon-badge);
  transition: transform var(--dur-slow) var(--ease-spring);
}
.practical-card:hover .practical-card__icon { transform: rotate(-8deg) scale(1.07); }
.practical-card__icon svg { width: 26px; height: 26px; }
.practical-card__title {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--fg-strong);
}
.practical-card__text { font-size: var(--fs-xs); color: var(--fg-muted); line-height: var(--lh-relaxed); }
.practical-card__more {
  margin-top: auto;
  padding-top: var(--space-3);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-accent);
  text-decoration: none;
}
.practical-card__more svg { width: 13px; height: 13px; transition: transform var(--dur-fast) var(--ease-out); }
.practical-card:hover .practical-card__more svg { transform: translateX(4px); }

/* ============================================================================
   GALERIE / MOSAÏQUE COTONOU
   ========================================================================== */
.mosaic { display: grid; gap: var(--space-4); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) { .mosaic { grid-template-columns: repeat(3, 1fr); } }
.mosaic__tile {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--radius-md);
  aspect-ratio: 4 / 3;
  background: var(--bg-surface-alt);
}
.mosaic__tile--tall { grid-row: span 2; aspect-ratio: 4 / 6; }
@media (max-width: 767.98px) { .mosaic__tile--tall { grid-row: span 1; aspect-ratio: 4 / 3; } }
.mosaic__tile img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slower) var(--ease-out); }
.mosaic__tile:hover img { transform: scale(1.06); }
.mosaic__caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--space-8) var(--space-4) var(--space-4);
  background: linear-gradient(180deg, transparent, rgba(6, 20, 36, .9));
  color: var(--c-white);
}
.mosaic__caption strong {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--c-gold-300);
}
.mosaic__caption span { font-size: var(--fs-2xs); color: var(--c-navy-100); }

/* ============================================================================
   TÉMOIGNAGES
   ========================================================================== */
.testimonial {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-8);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  height: 100%;
}
.testimonial__quote {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  line-height: var(--lh-snug);
  color: var(--fg-strong);
}
.testimonial__quote::before { content: "« "; color: var(--accent); }
.testimonial__quote::after { content: " »"; color: var(--accent); }
.testimonial__author { display: flex; align-items: center; gap: var(--space-3); margin-top: auto; }
.testimonial__name { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--fg-strong); }
.testimonial__role { font-size: var(--fs-2xs); color: var(--fg-muted); }

/* Carrousel accessible : défilement natif + points de repère. */
.carousel { position: relative; }
.carousel__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(88%, 30rem);
  gap: var(--space-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-bottom: var(--space-2);
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track > * { scroll-snap-align: start; }
@media (min-width: 1024px) { .carousel__track { grid-auto-columns: min(46%, 32rem); } }
.carousel__nav { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-6); }
.carousel__btn {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  color: var(--fg-muted);
  transition: all var(--dur-fast) var(--ease-out);
}
.carousel__btn:hover { border-color: var(--accent); color: var(--fg-accent); background: var(--bg-accent-soft); }
.carousel__btn svg { width: 17px; height: 17px; }
.carousel__dots { display: flex; gap: var(--space-2); margin-left: auto; }
.carousel__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border-strong);
  transition: width var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.carousel__dot[aria-current="true"] { width: 26px; border-radius: var(--radius-pill); background: var(--accent); }

/* ============================================================================
   BANDEAU D'APPEL À L'ACTION
   ========================================================================== */
.cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(2.5rem, 6vw, 4.5rem);
  border-radius: var(--radius-xl);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  text-align: center;
}
.cta-band__pattern {
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  opacity: .22;
  background-image: url("../img/patterns/geometry-grid.svg");
  background-size: 480px;
  mask-image: radial-gradient(ellipse at center, #000 5%, transparent 68%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 5%, transparent 68%);
}
.cta-band__title { font-size: var(--fs-4xl); color: var(--c-white); margin-bottom: var(--space-4); }
.cta-band__lead { max-width: 46rem; margin-inline: auto; color: var(--c-navy-100); font-size: var(--fs-lg); }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: center; margin-top: var(--space-8); }

/* ============================================================================
   BADGE PARTICIPANT + QR
   ========================================================================== */
.badge-card {
  position: relative;
  width: min(340px, 100%);
  border-radius: var(--radius-lg);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  border: 1px solid rgba(240, 214, 138, .3);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}
.badge-card__header {
  padding: var(--space-5);
  text-align: center;
  border-bottom: 1px solid rgba(240, 214, 138, .2);
  background: rgba(0, 0, 0, .22);
}
.badge-card__event {
  font-family: var(--font-sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--c-gold-300);
}
.badge-card__dates { margin-top: var(--space-1); font-size: var(--fs-3xs); letter-spacing: var(--ls-wide); color: var(--c-navy-100); }
.badge-card__body { padding: var(--space-6) var(--space-5); text-align: center; display: grid; gap: var(--space-2); }
.badge-card__name { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: var(--fw-bold); color: var(--c-white); line-height: 1.1; }
.badge-card__org { font-size: var(--fs-xs); color: var(--c-navy-100); }
.badge-card__qr {
  margin: var(--space-4) auto 0;
  padding: var(--space-3);
  width: fit-content;
  background: #fff;
  border-radius: var(--radius-sm);
}
.badge-card__qr canvas,
.badge-card__qr svg { display: block; width: 148px; height: 148px; image-rendering: pixelated; }
.badge-card__id {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: .1em;
  color: var(--c-gold-300);
}
.badge-card__footer {
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid rgba(240, 214, 138, .2);
  background: rgba(0, 0, 0, .22);
  font-size: var(--fs-3xs);
  text-align: center;
  color: var(--c-navy-200);
}

/* Rappel de minimisation des données affiché sous le badge. */
.qr-note {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  font-size: var(--fs-2xs);
  color: var(--fg-muted);
  max-width: 34rem;
}
.qr-note svg { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--accent); }

/* ============================================================================
   APERÇU DE LA LETTRE D'INVITATION
   ========================================================================== */
.letter {
  position: relative;
  /* Le filigrane « SPÉCIMEN » est posé en absolu, tourné et large de 484 px :
     sans cette coupe il sortait de la feuille, de sa colonne et jusqu'à rendre
     le document 108 px plus large que l'écran sur un portable de 1280 px.
     Un filigrane doit de toute façon rester sur la feuille. */
  overflow: hidden;
  padding: clamp(1.75rem, 4vw, 3rem);
  background: var(--c-ivory-50);
  border: 1px solid var(--c-ivory-400);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  color: var(--c-ink-800);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
}
.letter::after {
  /* Filigrane discret : jamais un tampon officiel sur un prototype. */
  content: "SPÉCIMEN";
  position: absolute;
  top: 50%;
  left: 50%;
  font-family: var(--font-display);
  font-size: clamp(3rem, 12vw, 7rem);
  font-weight: var(--fw-bold);
  letter-spacing: .1em;
  color: rgba(11, 37, 69, .06);
  transform: translate(-50%, -50%) rotate(-24deg);
  pointer-events: none;
  user-select: none;
}
.letter__head { display: flex; justify-content: space-between; gap: var(--space-6); flex-wrap: wrap; align-items: flex-start; padding-bottom: var(--space-5); border-bottom: 1px solid var(--c-ivory-400); }
.letter__ref { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--c-ink-600); }
.letter__body { padding-block: var(--space-6); display: grid; gap: var(--space-4); }
.letter__body p { max-width: none; }
.letter__sign { margin-top: var(--space-6); display: flex; justify-content: space-between; align-items: flex-end; gap: var(--space-6); flex-wrap: wrap; }

/* ============================================================================
   CARTE HÔTEL / TRANSPORT
   ========================================================================== */
.hotel-card { display: grid; grid-template-columns: 1fr; }
@media (min-width: 640px) { .hotel-card { grid-template-columns: 15rem 1fr; } }
.hotel-card__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--bg-surface-alt); }
.hotel-card__media img { width: 100%; height: 100%; object-fit: cover; }
.hotel-card__meta { display: flex; flex-wrap: wrap; gap: var(--space-4); font-size: var(--fs-2xs); color: var(--fg-muted); }
.hotel-card__meta span { display: inline-flex; align-items: center; gap: var(--space-2); }
.hotel-card__meta svg { width: 14px; height: 14px; color: var(--accent); }

/* ============================================================================
   CONSTELLATION DES PAYS (bloc « 37 pays représentés »)
   ========================================================================== */
@keyframes node-pulse {
  0%, 100% { opacity: .45; r: 3; }
  50% { opacity: 1; r: 5; }
}

/* ============================================================================
   PAGES D'AUTHENTIFICATION
   ========================================================================== */
.auth {
  display: grid;
  min-height: 100svh;
  grid-template-columns: 1fr;
}
@media (min-width: 1024px) { .auth { grid-template-columns: 1.05fr 1fr; } }

.auth__aside {
  position: relative;
  display: none;
  isolation: isolate;
  padding: var(--space-12);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  overflow: hidden;
}
@media (min-width: 1024px) { .auth__aside { display: flex; flex-direction: column; justify-content: space-between; } }
.auth__aside-pattern {
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  opacity: .2;
  background-image: url("../img/patterns/geometry-grid.svg");
  background-size: 420px;
}
.auth__main { display: flex; flex-direction: column; justify-content: center; padding: clamp(2rem, 6vw, 4rem) var(--gutter); background: var(--bg-page); }
.auth__card { width: min(30rem, 100%); margin-inline: auto; }

/* Jauge de robustesse du mot de passe. */
.pw-meter { display: flex; gap: 4px; margin-top: var(--space-2); }
.pw-meter__seg { flex: 1; height: 4px; border-radius: var(--radius-pill); background: var(--bg-sunken); transition: background-color var(--dur-base) var(--ease-out); }
.pw-meter[data-score="1"] .pw-meter__seg:nth-child(1) { background: var(--c-danger-500); }
.pw-meter[data-score="2"] .pw-meter__seg:nth-child(-n+2) { background: var(--c-warning-500); }
.pw-meter[data-score="3"] .pw-meter__seg:nth-child(-n+3) { background: var(--c-gold-500); }
.pw-meter[data-score="4"] .pw-meter__seg { background: var(--c-success-500); }

/* Champ de code à usage unique (double authentification du Comité). */
.otp { display: flex; gap: var(--space-2); }
/* Les six cases se partagent la largeur disponible plutôt que d'imposer
   6 x 3 rem : à 360 px, la rangée fixe débordait de quatre pixels. */
.otp input {
  flex: 1 1 0;
  min-width: 0;
  max-width: 3.5rem;
  height: 3.5rem;
  padding-inline: 0;
  text-align: center;
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   PAGES D'ERREUR
   ========================================================================== */
.error-page {
  display: grid;
  place-items: center;
  min-height: 78svh;
  padding-block: var(--section-y);
  text-align: center;
}
.error-page__code {
  font-family: var(--font-display);
  font-size: clamp(6rem, 22vw, 14rem);
  font-weight: var(--fw-bold);
  line-height: .82;
  letter-spacing: var(--ls-tighter);
  background: var(--grad-gold);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.error-page__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: center; margin-top: var(--space-8); }

/* ============================================================================
   ARTICLE / ACTUALITÉ
   ========================================================================== */
.article-body { max-width: 68ch; font-size: var(--fs-md); line-height: var(--lh-relaxed); }
.article-body > * + * { margin-top: var(--space-5); }
.article-body h2 { margin-top: var(--space-12); font-size: var(--fs-3xl); }
.article-body h3 { margin-top: var(--space-8); }
.article-body figure { margin-block: var(--space-8); }
.article-body figcaption { margin-top: var(--space-3); font-size: var(--fs-2xs); color: var(--fg-muted); }
.article-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-5); font-size: var(--fs-2xs); color: var(--fg-muted); }
.article-meta > * { display: inline-flex; align-items: center; gap: var(--space-2); }
.article-meta svg { width: 14px; height: 14px; color: var(--accent); }

/* Sommaire ancré (maillage interne + confort de lecture). */
.toc { position: sticky; top: calc(var(--header-h) + var(--space-6)); }
.toc__list { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--border-subtle); }
.toc__list li { margin: 0; }
.toc__list a {
  display: block;
  padding: var(--space-2) var(--space-4);
  margin-left: -1px;
  border-left: 2px solid transparent;
  color: var(--fg-muted);
  font-size: var(--fs-xs);
  text-decoration: none;
  transition: all var(--dur-fast) var(--ease-out);
}
.toc__list a:hover { color: var(--fg-strong); }
.toc__list a[aria-current="true"] { border-left-color: var(--accent); color: var(--fg-accent); font-weight: var(--fw-semibold); }

/* ============================================================================
   ANIMATIONS D'APPARITION AU DÉFILEMENT
   Posées par ui-reveal.js : sans JavaScript le contenu reste visible.
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-slower) var(--ease-out),
              transform var(--dur-slower) var(--ease-entrance);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal="left"] { transform: translateX(-24px); }
[data-reveal="right"] { transform: translateX(24px); }
/* Tant qu'un bloc « depuis la droite » n'est pas entré dans le champ, il reste
   décalé de 24 px et dépasse donc son conteneur. Mesuré sur un téléphone de
   390 px, cela rendait la page large de 396 px. La coupe est portée par la
   section : `clip` ne crée pas de conteneur de défilement, contrairement à
   `hidden`, et laisse donc `position: sticky` fonctionner à l'intérieur. */
.section,
.app-section { overflow-x: clip; }
[data-reveal="scale"] { transform: scale(.96); }
[data-reveal][data-revealed="true"] { opacity: 1; transform: none; }

/* Tracé progressif des géométries SVG. */
.draw-path {
  stroke-dasharray: var(--path-length, 1200);
  stroke-dashoffset: var(--path-length, 1200);
  transition: stroke-dashoffset var(--dur-ceremony) var(--ease-out);
}
[data-revealed="true"] .draw-path { stroke-dashoffset: 0; }

}

/* ==========================================================================
   app-shell.css → @layer app
   ========================================================================== */
@layer app {
/* ============================================================================
   GLUB CONVENT 2027 : 08 · app-shell.css
   ----------------------------------------------------------------------------
   Coque applicative partagée par l'espace participant ET le tableau de bord du
   Comité : barre latérale, barre supérieure, indicateurs, graphiques SVG.
   Un seul squelette, deux jeux de contenus : aucun style dupliqué.
   ========================================================================== */

.app-shell {
  display: grid;
  min-height: 100svh;
  grid-template-columns: 1fr;
  background: var(--bg-page);
}
@media (min-width: 1024px) {
  .app-shell { grid-template-columns: 274px 1fr; }
}

/* ============================================================================
   BARRE LATÉRALE
   ========================================================================== */
.app-sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: var(--z-offcanvas);
  display: flex;
  flex-direction: column;
  width: 274px;
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  border-right: 1px solid rgba(240, 214, 138, .16);
  transform: translateX(-100%);
  visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-entrance),
              visibility 0s linear var(--vis-delay, var(--dur-slow));
}
.app-sidebar[data-open="true"] { --vis-delay: 0s; transform: none; visibility: visible; }
@media (min-width: 1024px) {
  .app-sidebar { position: sticky; height: 100svh; transform: none; visibility: visible; }
}

.app-sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5);
  border-bottom: 1px solid rgba(240, 214, 138, .16);
}
.app-sidebar__body { flex: 1; overflow-y: auto; padding: var(--space-5) var(--space-3); }
.app-sidebar__foot { padding: var(--space-4) var(--space-5); border-top: 1px solid rgba(240, 214, 138, .16); }

.side-nav { list-style: none; margin: 0; padding: 0; }
.side-nav li { margin: 0; }
.side-nav__group {
  padding: var(--space-5) var(--space-3) var(--space-2);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(240, 214, 138, .6);
}
.side-nav__link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--c-navy-100);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.side-nav__link:hover { background: rgba(255, 255, 255, .07); color: var(--c-white); }
.side-nav__link svg { width: 18px; height: 18px; flex: none; }
.side-nav__link[aria-current="page"] {
  background: rgba(201, 162, 39, .16);
  color: var(--c-gold-200);
}
.side-nav__link[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: 0;
  top: 20%;
  bottom: 20%;
  width: 3px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}
.side-nav__count {
  margin-left: auto;
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .12);
  font-size: var(--fs-3xs);
  font-variant-numeric: tabular-nums;
}
.side-nav__count--alert { background: var(--c-danger-500); color: #fff; }

/* ============================================================================
   ZONE PRINCIPALE
   ========================================================================== */
.app-main { display: flex; flex-direction: column; min-width: 0; }

.app-topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) clamp(1rem, 3vw, 2rem);
  background: var(--bg-topbar);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border-subtle);
}
.app-topbar__title {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  /* Sans cela, le titre ne descend pas sous la largeur de son mot le plus long
     (« automatiques » mesure 105 px) et pousse les actions hors de l'écran sur
     un téléphone de 320 px. */
  min-width: 0;
}

/* La barre est collante : chaque ligne gagnée par le titre est une ligne perdue
   pour le contenu, à toutes les pages et pendant tout le défilement. Sur
   téléphone, le titre le plus long (« Bonjour, Frère Amadou Karim ») retombe
   sur deux lignes ; on l'y laisse mais on l'y arrête, et on réduit légèrement
   le corps pour que la plupart des titres tiennent sur une seule. */
@media (max-width: 639.98px) {
  .app-topbar { gap: var(--space-3); }
  .app-topbar__title {
    font-size: var(--fs-lg);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
  }
}
.app-topbar__actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }

.app-content { flex: 1; padding: clamp(1.25rem, 3vw, 2.25rem) clamp(1rem, 3vw, 2rem) var(--space-16); }
.app-section + .app-section { margin-top: var(--space-10); }
.app-section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.app-section__title { font-family: var(--font-display); font-size: var(--fs-2xl); }

/* Bouton d'ouverture de la barre latérale sur mobile. */
.app-burger {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--fg-strong);
}
.app-burger svg { width: 20px; height: 20px; }
@media (min-width: 1024px) { .app-burger { display: none; } }

/* Menu utilisateur du bandeau supérieur. */
.user-menu { position: relative; }
.user-menu__trigger {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  transition: border-color var(--dur-fast) var(--ease-out);
}
.user-menu__trigger:hover { border-color: var(--accent); }
.user-menu__name { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--fg-strong); }
.user-menu__role { font-size: var(--fs-3xs); color: var(--fg-muted); }
.user-menu__panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: var(--z-dropdown);
  min-width: 15rem;
  padding: var(--space-2);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out),
              visibility 0s linear var(--vis-delay, var(--dur-base));
}
.user-menu[data-open="true"] .user-menu__panel { --vis-delay: 0s; opacity: 1; visibility: visible; transform: none; }
.user-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-default);
  font-size: var(--fs-sm);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.user-menu__item:hover { background: var(--bg-surface-alt); }
.user-menu__item svg { width: 16px; height: 16px; color: var(--fg-muted); }
.user-menu__sep { height: 1px; margin: var(--space-2) 0; background: var(--border-subtle); }

/* ============================================================================
   INDICATEURS CLÉS
   ========================================================================== */
.kpi-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
}
.kpi {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.kpi:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.kpi__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.kpi__label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--fg-muted);
}
.kpi__icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--bg-icon-badge);
  color: var(--fg-icon-badge);
}
.kpi__icon svg { width: 18px; height: 18px; }
.kpi__value {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--fg-strong);
}
.kpi__delta { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-2xs); font-weight: var(--fw-semibold); }
.kpi__delta svg { width: 13px; height: 13px; }
.kpi__delta--up { color: var(--c-success-600); }
.kpi__delta--down { color: var(--c-danger-600); }
.kpi__foot { font-size: var(--fs-2xs); color: var(--fg-subtle); }
.kpi--accent { background: var(--grad-navy); border-color: rgba(240, 214, 138, .3); }
.kpi--accent .kpi__label { color: var(--c-gold-300); }
.kpi--accent .kpi__value { color: var(--c-white); }
.kpi--accent .kpi__foot { color: var(--c-navy-100); }
.kpi--accent .kpi__icon { background: rgba(201, 162, 39, .18); color: var(--c-gold-300); }

/* ============================================================================
   GRAPHIQUES (SVG maison : aucune bibliothèque externe)
   ========================================================================== */
.chart-card {
  padding: var(--space-6);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}
.chart-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); }
.chart-card__title { font-family: var(--font-display); font-size: var(--fs-xl); }
.chart-card__sub { font-size: var(--fs-2xs); color: var(--fg-muted); }

.chart { width: 100%; overflow: visible; }
.chart__grid-line { stroke: var(--border-subtle); stroke-width: 1; }
.chart__axis-label { fill: var(--fg-subtle); font-size: 10px; font-family: var(--font-sans); }
.chart__bar { fill: var(--c-navy-600); transition: fill var(--dur-fast) var(--ease-out); }
.chart__bar:hover { fill: var(--accent); }
.chart__area { fill: url(#areaGradient); }
.chart__line { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.chart__point { fill: var(--bg-surface); stroke: var(--accent); stroke-width: 2.5; }

/* Barres horizontales (répartition par obédience / pays). */
.bar-list { display: grid; gap: var(--space-4); }
.bar-list__row { display: grid; grid-template-columns: minmax(6rem, 10rem) 1fr auto; gap: var(--space-4); align-items: center; font-size: var(--fs-xs); }
.bar-list__label { color: var(--fg-default); font-weight: var(--fw-medium); }
.bar-list__track { height: 10px; border-radius: var(--radius-pill); background: var(--bg-sunken); overflow: hidden; }
.bar-list__fill {
  height: 100%;
  width: var(--value, 0%);
  border-radius: inherit;
  background: var(--grad-gold);
  transition: width var(--dur-ceremony) var(--ease-out);
}
.bar-list__value { font-variant-numeric: tabular-nums; color: var(--fg-muted); min-width: 3rem; text-align: right; }

/* Anneau de progression (file visa, badges scannés). */
.donut { display: grid; place-items: center; position: relative; }
.donut svg { transform: rotate(-90deg); }
.donut__track { fill: none; stroke: var(--bg-sunken); stroke-width: 14; }
.donut__value {
  fill: none;
  stroke: var(--accent);
  stroke-width: 14;
  stroke-linecap: round;
  stroke-dasharray: var(--circumference, 314);
  stroke-dashoffset: var(--offset, 314);
  transition: stroke-dashoffset var(--dur-ceremony) var(--ease-out);
}
.donut__center { position: absolute; text-align: center; }
.donut__pct { font-size: var(--fs-2xl); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; color: var(--fg-strong); }
.donut__caption { font-size: var(--fs-3xs); letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--fg-muted); }

/* ============================================================================
   PANNEAU LATÉRAL DE DÉTAIL (fiche participant)
   ========================================================================== */
.detail-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-offcanvas);
  display: flex;
  flex-direction: column;
  width: min(520px, 94vw);
  background: var(--bg-surface);
  border-left: 1px solid var(--border-subtle);
  box-shadow: -30px 0 70px -40px rgba(0, 0, 0, .5);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform var(--dur-slow) var(--ease-entrance),
              visibility 0s linear var(--vis-delay, var(--dur-slow));
}
.detail-panel[data-open="true"] { --vis-delay: 0s; transform: none; visibility: visible; }
.detail-panel__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-6);
  border-bottom: 1px solid var(--border-subtle);
}
.detail-panel__body { flex: 1; overflow-y: auto; padding: var(--space-6); display: grid; gap: var(--space-6); }
.detail-panel__foot { padding: var(--space-5) var(--space-6); border-top: 1px solid var(--border-subtle); background: var(--bg-surface-alt); display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* ============================================================================
   ESPACE PARTICIPANT : bloc de statut
   ========================================================================== */
.status-card {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  border-radius: var(--radius-lg);
  background: var(--grad-navy);
  color: var(--fg-on-dark);
  border: 1px solid rgba(240, 214, 138, .28);
}
@media (min-width: 768px) { .status-card { grid-template-columns: 1fr auto; align-items: center; } }
.status-card__id {
  font-family: var(--font-mono);
  font-size: var(--fs-2xl);
  letter-spacing: .12em;
  color: var(--c-gold-300);
}
.status-card__label { font-size: var(--fs-2xs); letter-spacing: var(--ls-wider); text-transform: uppercase; color: var(--c-navy-100); }

/* Suivi d'avancement du dossier (reçue → en cours → validée). */
.tracker { display: grid; gap: var(--space-1); grid-auto-flow: column; grid-auto-columns: 1fr; margin-top: var(--space-6); }
.tracker__step { display: flex; flex-direction: column; gap: var(--space-2); }
.tracker__bar { height: 4px; border-radius: var(--radius-pill); background: rgba(255, 255, 255, .16); }
.tracker__step[data-state="done"] .tracker__bar { background: var(--c-success-500); }
.tracker__step[data-state="current"] .tracker__bar { background: var(--accent); }
.tracker__label { font-size: var(--fs-3xs); letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--c-navy-200); }
.tracker__step[data-state="current"] .tracker__label { color: var(--c-gold-300); font-weight: var(--fw-semibold); }
.tracker__step[data-state="done"] .tracker__label { color: #8fdcbc; }

/* Liste de notifications du Comité. */
.notif-list { list-style: none; margin: 0; padding: 0; }
.notif-list li { margin: 0; }
.notif {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-subtle);
}
.notif__dot { width: 9px; height: 9px; margin-top: 7px; flex: none; border-radius: 50%; background: var(--border-strong); }
.notif[data-unread="true"] .notif__dot { background: var(--accent); box-shadow: 0 0 0 4px rgba(201, 162, 39, .18); }
.notif__title { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--fg-strong); }
.notif__text { font-size: var(--fs-xs); color: var(--fg-muted); }
.notif__time { margin-left: auto; font-size: var(--fs-3xs); color: var(--fg-subtle); white-space: nowrap; }

}
