/**
 * =============================================================================
 *  design-system.css — Système graphique centralisé AMPIREZOYA (2026)
 * =============================================================================
 *  FR : NOUVEAU (8 septembre 2026) — PHASE 1 du chantier "Uniformisation
 *       du Design System + Modernisation visuelle 2026", validé avec
 *       Jérémie après analyse complète de l'existant (voir le diagnostic
 *       présenté dans la conversation).
 *
 *       CE FICHIER NE MODIFIE ENCORE AUCUNE PAGE — voir la demande
 *       explicite "ne pas encore modifier toutes les pages une par une".
 *       Il définit uniquement les variables et les composants de base ;
 *       aucune page ne l'inclut pour l'instant, donc RIEN ne change
 *       visuellement tant que la Phase 2 (migration page par page) n'a
 *       pas commencé.
 *
 *       PRINCIPE CENTRAL — RÉUTILISER, PAS RECRÉER :
 *       - Les couleurs (--bg, --text, --copper...) reprennent EXACTEMENT
 *         les noms et logique déjà utilisés sur 18 des ~24 pages du site
 *         (voir le diagnostic) — aucune couleur n'est renommée.
 *       - La police "Space Grotesk" est déjà chargée et utilisée comme
 *         police de titre sur une dizaine de pages (voir
 *         ampirezoya.html, ligne ~71, et grep "Space Grotesk" sur le
 *         projet) — adoptée ici comme police d'affichage OFFICIELLE du
 *         système plutôt que d'en choisir une nouvelle. À l'inverse,
 *         "Sora" est chargée sur ampirezoya.html mais n'est UTILISÉE
 *         NULLE PART (0 occurrence) — pur gaspillage de bande passante,
 *         à retirer lors d'une future phase de nettoyage (pas touché
 *         ici, cette phase ne modifie aucune page).
 *
 *       CE QUI CHANGE PAR RAPPORT À L'EXISTANT (sur demande explicite) :
 *       - Le mode sombre n'utilise plus un noir absolu (#000000) mais un
 *         noir légèrement remonté (#0a0b0d), avec PLUSIEURS niveaux de
 *         surfaces sombres pour donner de la profondeur (voir "Couleurs
 *         — Élévation" plus bas) — exactement la demande "évite le noir
 *         absolu partout, utilise plusieurs niveaux de surfaces
 *         sombres".
 *
 *  EN : NEW (September 8, 2026) — PHASE 1 of the "Design System
 *       Unification + 2026 Visual Modernization" project, validated
 *       with Jérémie after a complete analysis of the existing setup
 *       (see the diagnosis presented in the conversation).
 *
 *       THIS FILE DOES NOT MODIFY ANY PAGE YET — see the explicit
 *       request "don't modify every page one by one yet". It only
 *       defines the base variables and components; no page includes it
 *       for now, so NOTHING changes visually until Phase 2 (page-by-page
 *       migration) begins.
 *
 *       CENTRAL PRINCIPLE — REUSE, DON'T RECREATE:
 *       - The colors (--bg, --text, --copper...) reuse EXACTLY the
 *         names and logic already used on 18 of the ~24 pages of the
 *         site (see the diagnosis) — no color is renamed.
 *       - The "Space Grotesk" font is already loaded and used as the
 *         heading font on about ten pages (see ampirezoya.html, line
 *         ~71, and grep "Space Grotesk" across the project) — adopted
 *         here as the system's OFFICIAL display font rather than
 *         picking a new one. Conversely, "Sora" is loaded on
 *         ampirezoya.html but is USED NOWHERE (0 occurrences) — pure
 *         bandwidth waste, to be removed in a future cleanup phase (not
 *         touched here, this phase doesn't modify any page).
 *
 *       WHAT CHANGES COMPARED TO THE EXISTING SETUP (per explicit
 *       request):
 *       - Dark mode no longer uses absolute black (#000000) but a
 *         slightly raised black (#0a0b0d), with SEVERAL levels of dark
 *         surfaces to add depth (see "Colors — Elevation" further down)
 *         — exactly the request "avoid absolute black everywhere, use
 *         several levels of dark surfaces".
 *
 *  */

/* =============================================================================
   1. COULEURS — voir la note en haut de fichier : noms et logique repris
      tels quels de l'existant (18 pages), avec l'ajout des niveaux
      d'élévation demandés pour le mode sombre.
      1. COLORS — see the note at the top of the file: names and logic
      reused as-is from the existing setup (18 pages), with the addition
      of the elevation levels requested for dark mode.
   ============================================================================= */
:root{
  /* FR : mode SOMBRE — valeurs par défaut. "bg" légèrement remonté
        (#0a0b0d au lieu de #000000 pur) — voir la note en haut de
        fichier. "bg-soft"/"bg-elevated" forment une VRAIE hiérarchie de
        profondeur : plus un élément est "au-dessus" des autres (carte
        sur la page, modale sur une carte, menu déroulant sur une
        modale), plus il utilise un niveau élevé.
     EN : DARK mode — default values. "bg" slightly raised (#0a0b0d
        instead of pure #000000) — see the note at the top of the file.
        "bg-soft"/"bg-elevated" form a REAL depth hierarchy: the more an
        element sits "above" others (a card on the page, a modal on a
        card, a dropdown on a modal), the higher the level it uses.
*/
  --bg: #0a0b0d;
  --bg-soft: #101317;
  --bg-elevated: #171b21;
  --surface: rgba(255,255,255,0.045);
  --surface-strong: rgba(255,255,255,0.07);
  --surface-hover: rgba(255,255,255,0.10);
  --border: rgba(255,255,255,0.08);
  --border-soft: rgba(255,255,255,0.05);
  --text: #eef0f2;
  --text-dim: #9aa1ab;
  --text-faint: #656c76;
  --copper: #3ab7f0;
  --copper-dim: #1e93d1;
  --copper-glow: rgba(58,183,240,0.35);
  --copper-ink: #001824;
  --green: #5fbf8f;
  --danger: #e5484d;
  --danger-ink: #ffffff;

  /* FR : ombres — voir section 6, valeurs propres au mode sombre
        (l'élévation se voit surtout via "bg-elevated" ci-dessus ; la
        vraie ombre reste discrète, jamais lourde).
     EN : shadows — see section 6, values specific to dark mode
        (elevation is mostly conveyed via "bg-elevated" above; the
        actual shadow stays discreet, never heavy).
*/
  --shadow-card: 0 4px 16px rgba(0,0,0,0.35);
  --shadow-elevated: 0 16px 40px rgba(0,0,0,0.45);

  color-scheme: dark;
}

html[data-theme="light"]{
  /* FR : mode CLAIR — inchangé par rapport à l'existant (aucun problème
        de "noir absolu" ne s'applique ici) — mêmes valeurs déjà en place
        sur les 18 pages, "bg-elevated" est la seule vraie nouveauté
        (léger gris pour distinguer un élément survolé du fond blanc).
     EN : LIGHT mode — unchanged compared to the existing setup (no
        "absolute black" issue applies here) — same values already in
        place on the 18 pages, "bg-elevated" is the only real novelty
        (light gray to distinguish a hovered element from the white
        background).
*/
  --bg: #f7f5f2;
  --bg-soft: #ffffff;
  --bg-elevated: #ffffff;
  --surface: rgba(20,16,10,0.035);
  --surface-strong: rgba(20,16,10,0.06);
  --surface-hover: rgba(20,16,10,0.09);
  --border: rgba(20,16,10,0.1);
  --border-soft: rgba(20,16,10,0.07);
  --text: #221d17;
  --text-dim: #6b6157;
  --text-faint: #948a7e;
  --copper: #1c1c1e;
  --copper-dim: #000000;
  --copper-glow: rgba(20,20,20,0.12);
  --copper-ink: #ffffff;
  --green: #2f9c66;
  --danger: #e5484d;
  --danger-ink: #ffffff;

  --shadow-card: 0 2px 10px rgba(20,16,10,0.06);
  --shadow-elevated: 0 16px 40px rgba(20,16,10,0.14);

  color-scheme: light;
}

/* =============================================================================
   2. TYPOGRAPHIE — voir la note en haut de fichier : "Space Grotesk"
      officialisée comme police d'affichage (déjà utilisée sur ~10
      pages), le texte courant reste sur la pile système déjà en place
      partout (aucun coût de chargement, déjà cohérente).
      2. TYPOGRAPHY — see the note at the top of the file: "Space
      Grotesk" made official as the display font (already used on ~10
      pages), body text stays on the system stack already in place
      everywhere (no loading cost, already consistent).
   ============================================================================= */
:root{
  --font-display: 'Space Grotesk', -apple-system, 'Segoe UI', Arial, sans-serif;
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* FR : 4 niveaux SEULEMENT, appliqués partout — voir le diagnostic :
        les "titres" variaient entre 19/20/22/28px sans logique. Le
        responsive peut réduire ces valeurs via clamp() au moment de la
        migration page par page (Phase 2), pas ici.
     EN : 4 levels ONLY, applied everywhere — see the diagnosis:
        "titles" varied between 19/20/22/28px with no logic. Responsive
        behavior can reduce these values via clamp() during the
        page-by-page migration (Phase 2), not here.
*/
  --text-h1: 700 22px/1.25 var(--font-display);
  --text-h2: 700 16px/1.3 var(--font-display);
  --text-body: 400 14px/1.5 var(--font-body);
  --text-small: 500 12.5px/1.4 var(--font-body);
  --text-tiny: 500 11px/1.3 var(--font-body);
}

/* =============================================================================
   3. ESPACEMENTS — échelle unique, basée sur un multiple de 4px (déjà la
      logique implicite la plus fréquente dans le code existant).
      3. SPACING — single scale, based on a multiple of 4px (already the
      most frequent implicit logic in the existing code).
   ============================================================================= */
:root{
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
}

/* =============================================================================
   4. RAYONS — voir le diagnostic : 10/12/16/18/20/22/24px utilisés sans
      catégorie claire. Ramené à 5 valeurs, chacune avec un usage précis.
      4. RADIUS — see the diagnosis: 10/12/16/18/20/22/24px used with no
      clear category. Brought down to 5 values, each with a precise use.
   ============================================================================= */
:root{
  --radius-sm: 8px;       /* FR : petits éléments, badges | EN : small elements, badges */
  --radius-input: 12px;   /* FR : champs de formulaire | EN : form fields */
  --radius-card: 16px;    /* FR : cartes, panneaux | EN : cards, panels */
  --radius-modal: 20px;   /* FR : fenêtres modales | EN : modal windows */
  --radius-button: 999px; /* FR : boutons "pilule" | EN : "pill" buttons */
}

/* =============================================================================
   5. AVATARS ET BANNIÈRES — voir le diagnostic : 104px vs 84px pour
      l'avatar principal, ratio 16/6.2 vs 16/6 pour la bannière. Une
      seule valeur officielle par catégorie, choisie parmi celles déjà
      utilisées (jamais une valeur totalement nouvelle) — la plus
      généreuse gagne, pour ne jamais RÉDUIRE un composant déjà en place
      lors de la migration (Phase 2).
      5. AVATARS AND BANNERS — see the diagnosis: 104px vs 84px for the
      main avatar, 16/6.2 vs 16/6 ratio for the banner. A single official
      value per category, chosen among those already in use (never a
      brand new value) — the more generous one wins, so a component
      already in place is never SHRUNK during migration (Phase 2).
   ============================================================================= */
:root{
  --avatar-xs: 32px;       /* FR : commentaire, petite liste | EN : comment, small list */
  --avatar-sm: 40px;       /* FR : publication dans le fil | EN : post in the feed */
  --avatar-md: 56px;       /* FR : messagerie, suggestions | EN : messaging, suggestions */
  --avatar-profile: 104px; /* FR : grand avatar — profil ET Espace, désormais unifiés | EN : large avatar — profile AND Space, now unified */

  --banner-ratio: 16 / 6.2; /* FR : bannière — profil ET Espace, désormais unifiés | EN : banner — profile AND Space, now unified */
}

/* =============================================================================
   6. OMBRES — voir "--shadow-card"/"--shadow-elevated" définies section 1
      (une valeur par thème, jamais la même en clair et en sombre — une
      ombre sombre est invisible sur fond déjà sombre). Rendu VOLONTAIREMENT
      discret — jamais de grosse ombre portée.
      6. SHADOWS — see "--shadow-card"/"--shadow-elevated" defined in
      section 1 (one value per theme, never the same in light and dark —
      a dark shadow is invisible on an already-dark background).
      DELIBERATELY subtle result — never a heavy drop shadow.
   ============================================================================= */

/* =============================================================================
   7. TRANSITIONS — voir la demande explicite : "transform et opacity",
      "150 à 300 ms", "discrètes", support de "prefers-reduced-motion".
      7. TRANSITIONS — see the explicit request: "transform and
      opacity", "150 to 300 ms", "discreet", "prefers-reduced-motion"
      support.
   ============================================================================= */
:root{
  --transition-fast: 150ms ease;                        /* FR : survol bouton/icône | EN : button/icon hover */
  --transition-base: 220ms cubic-bezier(0.4,0,0.2,1);    /* FR : cartes, apparition de contenu | EN : cards, content appearing */
  --transition-modal: 260ms cubic-bezier(0.16,1,0.3,1);  /* FR : ouverture de modale | EN : modal opening */
}

/* FR : RESPECT DE "prefers-reduced-motion" — voir la demande explicite.
      Raccourcit TOUTES les transitions/animations du système à une
      valeur quasi instantanée pour les personnes ayant activé ce
      réglage d'accessibilité sur leur appareil — ne les DÉSACTIVE pas
      complètement (certains changements d'état restent utiles à voir),
      juste beaucoup plus courts.
   EN : RESPECTING "prefers-reduced-motion" — see the explicit request.
      Shortens ALL of the system's transitions/animations to a
      near-instant value for people who have enabled this accessibility
      setting on their device — does NOT disable them entirely (some
      state changes remain useful to see), just much shorter.
*/
@media (prefers-reduced-motion: reduce){
  :root{
    --transition-fast: 1ms linear;
    --transition-base: 1ms linear;
    --transition-modal: 1ms linear;
  }
}

/* =============================================================================
   8. FOCUS STATES — anneau de mise au point visible au clavier
      (accessibilité), voir la demande explicite. Utilise
      ":focus-visible" plutôt que ":focus" — n'apparaît qu'à la
      navigation clavier (Tab), jamais au clic à la souris, pour ne pas
      surcharger visuellement l'interface pour la majorité des visiteurs.
      8. FOCUS STATES — visible keyboard focus ring (accessibility), see
      the explicit request. Uses ":focus-visible" rather than ":focus" —
      only appears on keyboard navigation (Tab), never on mouse click, so
      as not to visually clutter the interface for most visitors.
   ============================================================================= */
:root{
  --focus-ring: 0 0 0 3px var(--copper-glow);
}
.ds-btn:focus-visible,
.ds-input:focus-visible,
.ds-textarea:focus-visible,
.ds-select:focus-visible,
a:focus-visible,
button:focus-visible{
  outline: none;
  box-shadow: var(--focus-ring);
}

/* =============================================================================
   9. COMPOSANTS DE BASE — voir la note en haut de fichier : préfixe
      "ds-" (Design System) choisi précisément pour NE JAMAIS entrer en
      collision avec une classe déjà utilisée sur une page existante
      (ex : ".btn-pill", ".carte") — permet d'inclure ce fichier sur
      N'IMPORTE QUELLE page dès maintenant SANS RIEN CASSER, une page ne
      changeant visuellement QUE lorsqu'elle adopte explicitement une
      classe "ds-*" (Phase 2, page par page).
      9. BASE COMPONENTS — see the note at the top of the file: "ds-"
      (Design System) prefix chosen specifically to NEVER collide with a
      class already used on an existing page (e.g. ".btn-pill", ".carte")
      — allows including this file on ANY page right now WITHOUT
      BREAKING ANYTHING, a page only changing visually WHEN it explicitly
      adopts a "ds-*" class (Phase 2, page by page).
   ============================================================================= */

/* ---------- Boutons | Buttons ---------- */
.ds-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  font: 700 13.5px/1 var(--font-body);
  padding:11px 20px; border-radius:var(--radius-button); border:none;
  cursor:pointer; white-space:nowrap;
  transition:transform var(--transition-fast), background-color var(--transition-fast), box-shadow var(--transition-fast), opacity var(--transition-fast);
}
/* FR : légère élévation au survol — "transform" uniquement (jamais
      width/height/margin), comme demandé, pour rester fluide même sur
      petit appareil.
   EN : slight elevation on hover — "transform" only (never
      width/height/margin), as requested, to stay smooth even on a
      small device.
*/
.ds-btn:hover{ transform:translateY(-1px); }
.ds-btn:active{ transform:translateY(0); }
.ds-btn:disabled{ opacity:0.5; cursor:default; transform:none; }

.ds-btn-primary{ background:var(--copper); color:var(--copper-ink); }
.ds-btn-primary:hover{ background:var(--copper-dim); }
.ds-btn-secondary{ background:var(--surface-strong); color:var(--text); }
.ds-btn-secondary:hover{ background:var(--surface-hover); }
.ds-btn-outline{ background:transparent; color:var(--text); border:1.5px solid var(--border); }
.ds-btn-outline:hover{ background:var(--surface); }
.ds-btn-danger{ background:transparent; color:var(--danger); border:1.5px solid rgba(229,72,77,0.4); }
.ds-btn-danger:hover{ background:rgba(229,72,77,0.1); }

/* FR : bouton icône seule (carré, coins arrondis) — ex : partager,
      paramètres... voir ".btn-icon-square" déjà utilisé sur le profil
      personnel, généralisé ici.
   EN : icon-only button (square, rounded corners) — e.g. share,
      settings... see ".btn-icon-square" already used on the personal
      profile, generalized here.
*/
.ds-btn-icon{
  width:40px; height:40px; border-radius:var(--radius-input);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  background:var(--surface-strong); color:var(--text); border:none; cursor:pointer;
  transition:background-color var(--transition-fast), transform var(--transition-fast);
}
.ds-btn-icon:hover{ background:var(--surface-hover); transform:translateY(-1px); }
.ds-btn-icon svg{ width:19px; height:19px; }

/* FR : bouton d'action flottant (ex : "+" pour composer) — voir la
      demande "FLOATING ACTION BUTTON".
   EN : floating action button (e.g. "+" to compose) — see the
      "FLOATING ACTION BUTTON" request.
*/
.ds-btn-fab{
  width:56px; height:56px; border-radius:50%; position:fixed; z-index:40;
  display:flex; align-items:center; justify-content:center;
  background:var(--copper); color:var(--copper-ink); border:none; cursor:pointer;
  box-shadow:var(--shadow-elevated);
  transition:transform var(--transition-fast);
}
.ds-btn-fab:hover{ transform:scale(1.05); }
.ds-btn-fab:active{ transform:scale(0.97); }

/* ---------- Cartes | Cards ---------- */
.ds-card{
  background:var(--bg-soft); border:1px solid var(--border-soft); border-radius:var(--radius-card);
  padding:var(--space-4); box-shadow:var(--shadow-card);
  transition:transform var(--transition-base), box-shadow var(--transition-base);
}
/* FR : légère élévation au survol, réservée aux cartes CLIQUABLES (voir
      la classe combinée) — une carte purement informative ne bouge pas
      au survol, ce serait un mouvement sans signification.
   EN : slight elevation on hover, reserved for CLICKABLE cards (see the
      combined class) — a purely informational card doesn't move on
      hover, that would be a meaningless motion.
*/
.ds-card-interactive:hover{ transform:translateY(-2px); box-shadow:var(--shadow-elevated); }

/* ---------- Champs de formulaire | Form fields ---------- */
.ds-input, .ds-textarea, .ds-select{
  width:100%; background:var(--surface-strong); border:1.5px solid var(--border-soft);
  border-radius:var(--radius-input); padding:11px 14px; color:var(--text);
  font:var(--text-body); transition:border-color var(--transition-fast), background-color var(--transition-fast);
}
.ds-input::placeholder, .ds-textarea::placeholder{ color:var(--text-faint); }
.ds-input:hover, .ds-textarea:hover, .ds-select:hover{ border-color:var(--border); }
.ds-input:focus, .ds-textarea:focus, .ds-select:focus{ border-color:var(--copper); background:var(--bg-soft); }
.ds-textarea{ resize:vertical; min-height:90px; }
.ds-label{ display:block; font:var(--text-small); color:var(--text-dim); margin-bottom:var(--space-2); }

/* ---------- Badges ---------- */
.ds-badge{
  display:inline-flex; align-items:center; gap:4px; font:var(--text-tiny);
  padding:3px 10px; border-radius:var(--radius-sm); text-transform:uppercase; letter-spacing:0.02em;
  background:var(--surface-strong); color:var(--text-dim);
}
.ds-badge-accent{ background:var(--copper-glow); color:var(--copper); }
.ds-badge-success{ background:rgba(95,191,143,0.15); color:var(--green); }
.ds-badge-danger{ background:rgba(229,72,77,0.15); color:var(--danger); }

/* ---------- Avatars ---------- */
.ds-avatar{
  border-radius:50%; object-fit:cover; flex-shrink:0; background:var(--surface-strong);
  display:inline-block;
}
.ds-avatar-xs{ width:var(--avatar-xs); height:var(--avatar-xs); }
.ds-avatar-sm{ width:var(--avatar-sm); height:var(--avatar-sm); }
.ds-avatar-md{ width:var(--avatar-md); height:var(--avatar-md); }
.ds-avatar-profile{ width:var(--avatar-profile); height:var(--avatar-profile); }

/* ---------- Bannières ---------- */
.ds-banner{
  width:100%; aspect-ratio:var(--banner-ratio); object-fit:cover;
  background:var(--surface-strong); display:block;
}

/* ---------- États vides | Empty states ---------- */
/* FR : généralise ".empty-state/.empty-icon/.empty-title" déjà en place
      sur ampirezoya.html (la version la plus aboutie trouvée dans le
      diagnostic) — remplace les 2 autres variantes plus pauvres
      (".empty-block", ".empty-hint") lors de la migration (Phase 2).
   EN : generalizes ".empty-state/.empty-icon/.empty-title" already in
      place on ampirezoya.html (the most polished version found in the
      diagnosis) — replaces the 2 other, poorer variants
      (".empty-block", ".empty-hint") during migration (Phase 2).
*/
.ds-empty-state{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; padding:var(--space-7) var(--space-4); gap:var(--space-2);
}
.ds-empty-icon{
  width:48px; height:48px; border-radius:50%; background:var(--surface-strong);
  display:flex; align-items:center; justify-content:center; color:var(--text-faint); margin-bottom:var(--space-2);
}
.ds-empty-icon svg{ width:22px; height:22px; }
.ds-empty-title{ font:var(--text-h2); color:var(--text-dim); }
.ds-empty-text{ font:var(--text-small); color:var(--text-faint); max-width:280px; }

/* ---------- Skeletons (chargement) | Skeletons (loading) ---------- */
/* FR : NOUVEAU — voir le diagnostic : 0 skeleton/shimmer sur tout le
      site actuellement, uniquement du texte "Chargement…". Animation
      "shimmer" en "background-position" — n'anime QUE des propriétés
      composite-friendly (pas de repaint coûteux), respecte
      "prefers-reduced-motion" via la variable "--transition-base"
      utilisée pour sa durée.
   EN : NEW — see the diagnosis: 0 skeleton/shimmer across the whole
      site currently, only "Loading…" text. "shimmer" animation on
      "background-position" — only animates composite-friendly
      properties (no costly repaint), respects "prefers-reduced-motion"
      via the "--transition-base" variable used for its duration.
*/
.ds-skeleton{
  background:linear-gradient(90deg, var(--surface-strong) 25%, var(--surface-hover) 37%, var(--surface-strong) 63%);
  background-size:400% 100%;
  animation:ds-shimmer 1.6s ease-in-out infinite;
  border-radius:var(--radius-input);
}
@media (prefers-reduced-motion: reduce){
  .ds-skeleton{ animation:none; background:var(--surface-strong); }
}
@keyframes ds-shimmer{
  0%{ background-position:100% 50%; }
  100%{ background-position:0% 50%; }
}

/* ---------- Modales | Modals ---------- */
/* FR : NOUVEAU — voir le diagnostic : aucune animation d'ouverture de
      modale nulle part sur le site actuellement (apparition instantanée
      via display:none/block). Utilise UNIQUEMENT "transform"/"opacity"
      comme demandé — jamais "top"/"height"/"width", qui forceraient un
      recalcul de mise en page coûteux à chaque image de l'animation.
   EN : NEW — see the diagnosis: no modal opening animation anywhere on
      the site currently (instant appearance via display:none/block).
      Uses ONLY "transform"/"opacity" as requested — never
      "top"/"height"/"width", which would force a costly layout
      recalculation on every animation frame.
*/
.ds-modal-backdrop{
  position:fixed; inset:0; background:rgba(0,0,0,0.6); z-index:100;
  display:flex; align-items:flex-start; justify-content:center; overflow-y:auto;
  opacity:0; pointer-events:none;
  transition:opacity var(--transition-modal);
}
.ds-modal-backdrop.open{ opacity:1; pointer-events:auto; }
.ds-modal{
  background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius-modal);
  padding:var(--space-5); margin:30px auto; max-width:480px; width:calc(100% - 32px);
  box-shadow:var(--shadow-elevated);
  transform:translateY(16px) scale(0.98); opacity:0;
  transition:transform var(--transition-modal), opacity var(--transition-modal);
}
.ds-modal-backdrop.open .ds-modal{ transform:translateY(0) scale(1); opacity:1; }

/* =============================================================================
   10. SIDEBAR DESKTOP — voir nav-globale.js. Masquée par défaut (mobile/
       tablette utilisent la barre basse existante) — n'apparaît qu'à
       partir de 1024px, ET seulement sur les pages qui l'incluent
       explicitement (voir nav-globale.js) — sans effet sur les pages qui
       ne l'utilisent pas encore.
       10. DESKTOP SIDEBAR — see nav-globale.js. Hidden by default
       (mobile/tablet use the existing bottom nav) — only appears from
       1024px up, AND only on pages that explicitly include it (see
       nav-globale.js) — no effect on pages that don't use it yet.
   ============================================================================= */
.nav-sidebar{ display:none; }
@media (min-width:1024px){
  .nav-sidebar{
    display:flex; flex-direction:column; gap:4px;
    position:fixed; top:0; left:0; bottom:0; width:240px; z-index:55;
    background:var(--bg-soft); border-right:1px solid var(--border-soft);
    padding:20px 12px;
    transition:width var(--transition-base);
  }
  .nav-sidebar-logo{ font-family:var(--font-display); font-size:15px; padding:8px 12px 20px; white-space:nowrap; overflow:hidden; }
  .nav-sidebar-group{ display:flex; flex-direction:column; gap:2px; }
  .nav-sidebar-sep{ height:1px; background:var(--border-soft); margin:12px 4px; }
  .nav-sidebar-item{
    display:flex; align-items:center; gap:14px; padding:11px 12px; border-radius:var(--radius-input);
    background:none; border:none; color:var(--text); font-size:13.5px; font-weight:600; text-align:left;
    cursor:pointer; transition:background-color var(--transition-fast);
    white-space:nowrap; overflow:hidden;
    /* FR : NOUVEAU (15 septembre 2026) — point 7 de la demande
         "Connexion/Inscription" : menus en majuscules, y compris le
         menu latéral. Taille de police légèrement réduite (14.5px ->
         13.5px) pour compenser visuellement les majuscules, plus larges
         que le texte normal.
       EN : NEW (September 15, 2026) — point 7 of the "Login/Signup"
         request: menus in uppercase, including the side menu. Font
         size slightly reduced (14.5px -> 13.5px) to visually offset
         uppercase text, which reads wider than normal case. */
    text-transform:uppercase; letter-spacing:.02em;
  }
  .nav-sidebar-item:hover{ background:var(--surface); }
  .nav-sidebar-item.active{ background:var(--copper-glow); color:var(--copper); }
  .nav-sidebar-item svg{ flex-shrink:0; }

  /* FR : NOUVEAU (10 septembre 2026) — sur demande explicite, la
       sidebar doit pouvoir se refermer/se rouvrir (repérée grâce à une
       capture d'écran) — repliée à 68px (icônes seules, libellés
       masqués), le choix est mémorisé (comme le thème clair/sombre) et
       s'applique automatiquement sur toutes les pages qui utilisent
       cette sidebar. "body.sidebar-repliee" utilise "!important" pour
       primer sur la règle "padding-left:240px" que chaque page définit
       elle-même dans son propre <style>.
     EN : NEW (September 10, 2026) — per explicit request, the sidebar
       must be able to close/reopen (spotted via a screenshot) —
       collapsed to 68px (icons only, labels hidden), the choice is
       remembered (like the light/dark theme) and automatically applies
       on every page using this sidebar. "body.sidebar-repliee" uses
       "!important" to override the "padding-left:240px" rule that each
       page defines itself in its own <style>. */
  .nav-sidebar-toggle{
    display:flex; align-items:center; justify-content:center; gap:8px;
    width:100%; padding:9px 0; margin-bottom:10px; border-radius:var(--radius-input);
    background:var(--surface); border:none; color:var(--text-dim); cursor:pointer;
  }
  .nav-sidebar-toggle:hover{ background:var(--surface-strong); }
  .nav-sidebar-toggle svg{ transition:transform var(--transition-base); flex-shrink:0; }

  body.sidebar-repliee .nav-sidebar{ width:68px; }
  body.sidebar-repliee .nav-sidebar-logo,
  body.sidebar-repliee .nav-sidebar-item span,
  body.sidebar-repliee .nav-sidebar-toggle span{ display:none; }
  body.sidebar-repliee .nav-sidebar-item{ justify-content:center; padding:11px 0; }
  body.sidebar-repliee .nav-sidebar-toggle svg{ transform:rotate(180deg); }
  body.sidebar-repliee{ padding-left:68px !important; }
}

/* =============================================================================
   11. BARRE BASSE MOBILE — voir nav-globale.js. BUG CORRIGÉ (9 septembre
       2026) : ce composant injecte le HTML de la barre basse sur les
       pages qui n'en avaient aucune (voir le chantier "Navigation
       globale unifiée"), mais son apparence (position fixe, couleurs,
       icônes) n'avait jamais été définie nulle part — repéré par ma
       propre vérification visuelle, corrigé ici. Reprend EXACTEMENT le
       même style déjà utilisé ailleurs sur le site (voir
       ampirezoya-espace-profil.html) — "var(--bottomnav-h, 64px)" avec
       repli à 64px pour les pages qui n'auraient pas défini cette
       variable elles-mêmes.
       11. MOBILE BOTTOM NAV — see nav-globale.js. BUG FIXED (September
       9, 2026): this component injects the bottom nav's HTML on pages
       that had none (see the "Unified global navigation" project), but
       its appearance (fixed position, colors, icons) had never been
       defined anywhere — caught by my own visual check, fixed here.
       Reuses EXACTLY the same style already used elsewhere on the site
       (see ampirezoya-espace-profil.html) — "var(--bottomnav-h, 64px)"
       falling back to 64px for pages that wouldn't have defined that
       variable themselves.
   ============================================================================= */
.bottom-nav{
  display:flex; position:fixed; left:0; right:0; bottom:0; z-index:60;
  height:var(--bottomnav-h, 64px); padding-bottom:env(safe-area-inset-bottom, 0);
  background:var(--bg); border-top:1px solid var(--border-soft);
  align-items:stretch; justify-content:space-between;
}
.bottom-nav button{ background:none; border:none; color:var(--text); display:flex; align-items:center; justify-content:center; flex:1 1 0; height:100%; cursor:pointer; }
.bottom-nav button svg{ width:25px; height:25px; }
.bottom-nav button.active{ color:var(--copper); }
.bottom-nav .nav-avatar{ width:26px; height:26px; border-radius:50%; background:var(--surface-strong); display:flex; align-items:center; justify-content:center; color:var(--text-faint); overflow:hidden; }
.bottom-nav .nav-avatar img{ width:100%; height:100%; object-fit:cover; }
@media (min-width:1024px){ .bottom-nav{ display:none; } }

/* =============================================================================
   AVATARS SANS PHOTO — style centralisé (voir avatar-utils.js)
   ============================================================================= */
/* FR : NOUVEAU (15 septembre 2026) — déplacé ici depuis 6 fichiers HTML
     séparés, où cette même règle était recopiée à l'identique — un seul
     endroit désormais, comme demandé ("centralise... le style CSS").
     La couleur de fond n'est plus fixée ici : elle vient directement de
     "avatar-utils.js" (le dégradé bleu métallique), passée en style
     inline par "avatarInitialesHtml(...)".
   EN : NEW (September 15, 2026) — moved here from 6 separate HTML
     files, where this same rule was copied identically — a single
     place now, as requested ("centralize... the CSS style"). The
     background color is no longer fixed here: it comes directly from
     "avatar-utils.js" (the metallic blue gradient), passed as inline
     style by "avatarInitialesHtml(...)".
   ============================================================================= */
.avatar-initiales{
  position:absolute; inset:0; border-radius:50%; color:#fff; font-weight:700;
  display:flex; align-items:center; justify-content:center; font-size:16px;
  text-transform:uppercase; line-height:1;
}
/* FR : état "en chargement" (voir avatarChargementHtml() dans
     avatar-utils.js) — un pouls discret plutôt qu'un texte ou une
     icône, tant que les vraies données du compte n'ont pas encore
     répondu.
   EN : "loading" state (see avatarChargementHtml() in
     avatar-utils.js) — a discreet pulse rather than text or an icon,
     while the account's real data hasn't answered yet. */
.avatar-en-chargement{ position:relative; inset:auto; animation:avatarPouls 1.4s ease-in-out infinite; }
@keyframes avatarPouls{ 0%,100%{ opacity:0.65; } 50%{ opacity:1; } }
/* FR : NOUVEAU (15 septembre 2026) — corrige un vrai défaut visuel
     signalé : ".avatar-initiales" impose toujours un cercle parfait
     (border-radius:50%), ce qui donnait un rond visible À L'INTÉRIEUR
     du carré arrondi ".comm-avatar" (communautés, groupes) — pas
     propre. Les initiales épousent maintenant EXACTEMENT la forme de
     leur conteneur ("border-radius:inherit"), qu'il s'agisse d'un
     cercle (personnes) ou d'un carré arrondi (communautés, groupes).
   EN : NEW (September 15, 2026) — fixes a real visual flaw that was
     reported: ".avatar-initiales" always forced a perfect circle
     (border-radius:50%), which showed a visible circle INSIDE the
     rounded square ".comm-avatar" (communities, groups) — not clean.
     Initials now match their container's shape EXACTLY
     ("border-radius:inherit"), whether that's a circle (people) or a
     rounded square (communities, groups). */
.comm-avatar .avatar-initiales{ border-radius:inherit; }
/* FR : NOUVEAU (15 septembre 2026) — même correction que ".comm-avatar"
     ci-dessus, appliquée aux avatars d'Espaces (".space-avatar" sur la
     liste "Mes Espaces", ".espace-avatar" sur le profil d'un Espace) —
     évite le même défaut (cercle visible dans un carré arrondi).
   EN : NEW (September 15, 2026) — same fix as ".comm-avatar" above,
     applied to Space avatars (".space-avatar" on the "My Spaces" list,
     ".espace-avatar" on a Space's profile) — avoids the same flaw (a
     circle visible inside a rounded square). */
.space-avatar .avatar-initiales, .espace-avatar .avatar-initiales{ border-radius:inherit; }
