/* ==========================================================================
   Compagnon AI - Bundle CSS (genere par scripts/build-css.py)
   NE PAS MODIFIER DIRECTEMENT - editer les fichiers sources puis relancer le script
   Ordre de cascade : variables -> reset -> base -> layout -> utilities ->
   components -> header -> footer -> newsletter -> article -> guide -> overlays
   ========================================================================== */

/* ----- fonts.css ----- */
/* ==========================================================================
   Fonts self-hosted (Plus Jakarta Sans + Source Sans 3, subsets latin + latin-ext)
   Telechargees depuis Google Fonts et servies localement (scripts/download-fonts.py)
   pour supprimer la chaine de requetes externe et le FCP blocking.
   ========================================================================== */

@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-500-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: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-500-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;
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-700-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: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-700-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;
}

@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-800-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: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/plus-jakarta-sans-800-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;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/source-sans-3-400-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: 'Source Sans 3';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/source-sans-3-400-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;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/source-sans-3-600-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: 'Source Sans 3';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/source-sans-3-600-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;
}

/* ----- variables.css ----- */
/* ==========================================================================
   Variables — Custom Properties
   Toutes les couleurs, typos, espacements et rayons du site.
   Modifier ici pour changer l'identité visuelle globale.
   ========================================================================== */

:root {
  /* --- Couleurs de fond --- */
  --color-dark-bg: #1e1e1e;
  --color-dark-bg-alt: #1a1a2e;      /* variante bleutée */
  --color-dark-bg-elevated: #252540; /* cartes sur fond sombre */
  --color-light-bg: #f5f5fa;
  --color-light-bg-alt: #ffffff;

  /* --- Couleurs de texte --- */
  --color-text-on-dark: #e0e0e0;
  --color-text-on-dark-muted: #999999;
  --color-text-on-light: #1e1e1e;
  --color-text-on-light-muted: #666666;

  /* --- Dégradés --- */
  --gradient-signature: linear-gradient(135deg, #1e1e1e 0%, #2a1040 30%, #6a1b9a 55%, #d81b60 85%, #e84570 100%);
  --gradient-accent: linear-gradient(135deg, #6a1b9a 0%, #d81b60 50%, #e84570 100%);
  --gradient-accent-horizontal: linear-gradient(90deg, #6a1b9a 0%, #d81b60 60%, #e84570 100%);
  --gradient-logo-separator: linear-gradient(90deg, #6a1b9a, #e84570);

  /* --- Couleurs d'accent --- */
  --color-accent-purple: #6a1b9a;
  --color-accent-pink: #d81b60;
  --color-accent-pink-light: #e84570;

  /* Magenta point-milieu dans le gradient signature (entre purple #6a1b9a
     et pink #d81b60). Vocation structurante : tags sidebar (palier 17),
     liens body article via effet stabilo (palier 18), références futures.
     Le rose --pink-light reste réservé aux petites touches (fil d'ariane,
     accents ponctuels) — "too much" sur éléments structurants dark dominant. */
  --color-accent-magenta: #a01a7e;

  /* Variante éclaircie pour les contextes "fond très sombre serré"
     (typique : liens dans cellules de tableau .article-table sur fond
     #2a2a2a, où le magenta de base manque de contraste). Même teinte
     HSL 320°, luminosité +18 pts (36% → 55%). Palier 20. */
  --color-accent-magenta-light: #d147a5;

  /* --- Tags plateformes ---
     Couleurs alignées sur les marques (2026-04-29). Différenciation
     kindroid/nomi par luminosité (les deux marques sont dans le violet). */
  --color-tag-kindroid: #6a1b9a;   /* violet sombre, extrémité du dégradé Kindroid */
  --color-tag-nomi: #9c27b0;       /* violet vif, vrai branding Nomi */
  --color-tag-replika: #1d4ed8;    /* bleu vif Replika */
  --color-tag-general: #757575;    /* gris neutre, inchangé */
  --color-tag-character: #212121;  /* noir profond Character.AI */
  --color-tag-candy: #db2777;      /* rose-fuchsia Candy.AI (distinct du violet kindroid/nomi/character) */
  --color-tag-assistant-ia: #475569; /* slate (gris-bleu acier) pour Assistant IA (Claude/ChatGPT/Grok/Gemini) */

  /* --- Typographie --- */
  --font-heading: 'Plus Jakarta Sans', sans-serif;
  --font-body: 'Source Sans 3', sans-serif;
  --font-weight-logo: 500;
  --font-weight-heading: 700;
  --font-weight-heading-bold: 800;
  --font-weight-body: 400;
  --font-weight-body-semi: 600;

  /* --- Tailles de texte --- */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;
  --text-4xl: 2.5rem;

  /* --- Espacements --- */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;

  /* --- Layout --- */
  --container-max: 1300px; /* 1200 → 1300px (v1-dark, plus d'air sur grand écran) */
  --container-padding: 1.5rem;
  --section-padding-y: 4rem;
  --header-height: 72px; /* 64 → 72px (v1-dark, ratio header/hero plus équilibré) */

  /* --- Rayons --- */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-card: 12px;
  --radius-lg: 16px;
  --radius-full: 9999px;

  /* --- Ombres --- */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.2);
  --shadow-header: 0 2px 8px rgba(0, 0, 0, 0.3);

  /* --- Transitions --- */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
  --transition-slow: 400ms ease;
}

/* Breakpoints (pour référence, non utilisables en custom properties) :
   - Mobile    : 0 – 599px   (base, 1 colonne)
   - Tablet    : 600px+       (2 colonnes)
   - Desktop-s : 900px+       (3 colonnes, TOC latéral)
   - Desktop   : 1200px+      (max-width container, 4 colonnes listings)
*/

/* ----- reset.css ----- */
/* ==========================================================================
   Reset — Normalize minimal
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
}

h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

p {
  overflow-wrap: break-word;
}

table {
  border-collapse: collapse;
}

/* ----- base.css ----- */
/* ==========================================================================
   Base — Typographie globale, body, liens, headings
   ========================================================================== */

body {
  font-family: var(--font-body);
  font-weight: var(--font-weight-body);
  font-size: var(--text-base);
  color: var(--color-text-on-light);
  background-color: var(--color-light-bg);
}

/* --- Headings --- */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  line-height: 1.2;
}

h1 {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-heading-bold);
}

h2 {
  font-size: var(--text-2xl);
}

h3 {
  font-size: var(--text-xl);
}

h4 {
  font-size: var(--text-lg);
}

@media (min-width: 900px) {
  h1 {
    font-size: var(--text-4xl);
  }

  h2 {
    font-size: var(--text-3xl);
  }

  h3 {
    font-size: var(--text-2xl);
  }
}

/* --- Liens --- */

a {
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--color-accent-pink);
}

a:focus-visible {
  outline: 2px solid var(--color-accent-purple);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- Skip link (a11y) ---
   Lien "Aller au contenu" en haut du header, masque hors focus,
   apparait au Tab depuis le tout debut de la page. Cible <main id="main">.
   Ajoute 2026-05-19 dans le cadre du sous-bloc B accessibilite. */

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--space-md);
  z-index: 9999;
  padding: var(--space-sm) var(--space-md);
  background: var(--color-accent-magenta);
  color: #ffffff;
  text-decoration: none;
  font-weight: 600;
  border-radius: var(--radius-md);
  transition: top var(--transition-fast);
}

.skip-link:focus,
.skip-link:focus-visible {
  top: var(--space-sm);
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  color: #ffffff;
}

/* --- Texte courant --- */

p {
  margin-bottom: var(--space-md);
  line-height: 1.7;
}

strong {
  font-weight: var(--font-weight-body-semi);
}

/* --- Selection --- */

::selection {
  background-color: var(--color-accent-purple);
  color: #ffffff;
}

/* ----- layout.css ----- */
/* ==========================================================================
   Layout — Containers, grilles, sections dark/light, responsive
   ========================================================================== */

/* --- Container --- */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

/* --- Sections clair-obscur --- */

.section {
  padding-block: var(--section-padding-y);
}

.section--dark {
  background-color: var(--color-dark-bg);
  color: var(--color-text-on-dark);
}

.section--dark-alt {
  background-color: var(--color-dark-bg-alt);
  color: var(--color-text-on-dark);
}

.section--light {
  background-color: var(--color-light-bg);
  color: var(--color-text-on-light);
}

.section--light-alt {
  background-color: var(--color-light-bg-alt);
  color: var(--color-text-on-light);
}

.section--gradient {
  background: var(--gradient-signature);
  color: var(--color-text-on-dark);
}

.section--hero {
  position: relative;
  /* background-position: 30% pour pousser le cadrage vers la gauche et couper
     le cœur bokeh kitsch qui se trouve dans le tiers droit de l'image source. */
  background: url('/images/hero.avif') 30% center / cover no-repeat;
  color: var(--color-text-on-dark);
}

/* Hero mobile : variante 3:2 dediée (cropée du carré original AI, partie
   basse canapé/jambes virée car inutile narrativement). Image 1254×836,
   AVIF 63 KB. Le navigateur ne charge que l'image qui matche le media
   query courant — pas de double download.

   Approche STACK : image plein-largeur 100vw au sommet (ratio 3:2 donc
   hauteur = 100vw × 2/3 = 67vw), texte en-dessous sur fond sombre
   uniforme. Plus de collision possible entre visages et texte — chacun
   sa zone.

   Le gradient overlay ::before est désactivé sur mobile : il n'a plus
   d'utilité (le texte est sur du dark plein, pas sur l'image). */
@media (max-width: 599px) {
  .section--hero {
    background-image: url('/images/hero-portrait.avif');
    background-size: 100% auto;
    background-position: center top;
    background-color: var(--color-dark-bg);
    background-repeat: no-repeat;
    /* Override .section default padding-block: 4rem -> 0.
       Sinon 128px de dark band invisibles (64 top + 64 bottom)
       plombent le hero mobile. */
    padding-block: 0;
  }
  /* Gradient overlay restreint à la zone image (top, hauteur = ratio 3:2).
     L'anchor noir/dark du gradient desktop (rgba 30,30,30,0.7) est retiré
     en mobile : sur petite zone il écrase l'image au lieu de la réchauffer.
     On garde uniquement les couleurs chaudes (violet -> rose) à des alphas
     moyens pour la chaleur sans le darkening. */
  .section--hero::before {
    bottom: auto;
    height: calc(100vw * 2 / 3);
    background: linear-gradient(135deg,
      rgba(106, 27, 154, 0.38) 0%,
      rgba(216, 27, 96, 0.33) 55%,
      rgba(232, 69, 112, 0.24) 100%
    );
  }
  .section--hero .container {
    /* padding-top : hauteur image (100vw × 2/3) + petit gap (16px) avant le titre.
       padding-bottom : 16px seulement pour que les cards suivantes soient visibles
       above-the-fold sans avoir une grosse bande noire. */
    padding-block: calc(100vw * 2 / 3 + var(--space-md)) var(--space-md) !important;
  }
  /* Resserrer aussi le gap H1 -> excerpt (le style inline est var(--space-lg) = 24px) */
  .section--hero .container > p {
    margin-top: var(--space-sm) !important;
  }
}

.section--hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg,
    rgba(30,30,30,0.7) 0%,
    rgba(42,16,64,0.6) 30%,
    rgba(106,27,154,0.5) 55%,
    rgba(216,27,96,0.4) 85%,
    rgba(232,69,112,0.3) 100%
  );
}

.section--hero > .container {
  position: relative;
  z-index: 1;
}

/* --- Section header (titre de section + lien "voir tout") --- */

.section__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-2xl);
  flex-wrap: wrap;
}

.section__title {
  font-size: var(--text-2xl);
}

.section__link {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-sm);
  color: var(--color-accent-pink-light);
  transition: color var(--transition-fast);
}

.section__link:hover {
  color: var(--color-accent-pink);
}

.section--light .section__link {
  color: var(--color-accent-purple);
}

.section--light .section__link:hover {
  color: var(--color-accent-pink);
}

/* --- Grille de cartes --- */

.card-grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
}

@media (min-width: 600px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-xl);
  }
}

@media (min-width: 1200px) {
  .card-grid--4cols {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* --- Featured card (prend toute la largeur) --- */

.card-grid .card--featured {
  grid-column: 1 / -1;
}

@media (min-width: 600px) {
  .card-grid .card--featured {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
  }
}

/* --- Main content layout --- */

.main-content {
  /* padding-top retiré le 2026-04-23 : le header est en position:static (pas fixed),
     donc pas besoin de compenser sa hauteur. Si le header devient un jour sticky/fixed,
     remettre : padding-top: var(--header-height). */
}

/* --- Article layout avec sidebar --- */

.article-layout {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .article-layout {
    grid-template-columns: 1fr 280px;
  }
}

@media (min-width: 1200px) {
  .article-layout {
    grid-template-columns: 1fr 320px;
  }
}

/* ==========================================================================
   PALIERS v1-dark migrés depuis lab/v1-dark/dark.css (2026-05-19, Phase F)
   --------------------------------------------------------------------------
   Bloc absorbe les paliers 1, 6 du sandbox dark.css.
   Les règles ci-dessous OVERRIDENT les définitions prod historiques plus
   haut dans ce fichier (CSS lit dans l'ordre).
   ========================================================================== */

/* --------------------------------------------------------------------------
   PALIER 1 — Bascule dark dominant (zone Actu/Tests/Guides)
   -------------------------------------------------------------------------- */

/* Fond body en dark : evite les bugs de "transparence" qui laisseraient
   voir le fond clair par defaut (cas reel constate avec le mask du bandeau
   10M qui montrait le body #f5f5fa au lieu du noir attendu). */
body {
  background-color: #1e1e1e;
}

.section--light {
  background-color: #1e1e1e;
  color: var(--color-text-on-dark);
}

/* --- Hero : nouvelle image cinema crop (1671x519 = ~29:9)
   Source : images-sources/hero/hero-crop.png cropee par l'utilisateur.
   Image deja recadree verticalement -> on n'a plus besoin du 30% 30% qui
   compensait le mauvais cadrage du hero 16:9 d'origine ; center center
   suffit pour que le sujet soit a sa place sur la zone hero.
   IMPORTANT : conditionne a min-width 600px pour ne PAS ecraser la regle
   mobile qui a son propre background-image (hero-portrait.avif) et son
   propre background-position (center top). */
@media (min-width: 600px) {
  .section--hero {
    background-image: url('/images/hero.avif') !important;
    background-position: center center !important;
  }
}

/* --- Padding entre Hero et premiere section (A la une)
   Iterations : 24 -> 48 -> 64. Le hero compacte cinema appelle plus de
   respiration que ce que les valeurs intermediaires donnaient. */
.section--hero + .section--light {
  padding-top: var(--space-3xl);
}

/* --- Mobile : reduction des paddings de sections (palier phase A)
   Le user a constate trop d'espace entre les sections sur mobile (entre
   Hero et A la une, autour du bandeau 10M, entre Tests/Dossiers/Guides).
   Sur desktop on garde les paddings genereux ; sur mobile on resserre. */
@media (max-width: 599px) {
  .section {
    padding-block: var(--space-lg);
  }
  /* Le bandeau 10M a son propre padding inline reduit ; pas a override. */
  /* User retour S24 : 32px (16+16) entre fin sous-titre hero et "A LA UNE"
     trop large, demande de retirer ~1/4-1/3. Padding-top section suivante
     16 -> 8px : total 24px. */
  .section--hero + .section--light {
    padding-top: var(--space-sm);
  }

  /* --- Hero mobile : nouvelle image cropee user (palier 4 mobile)
     Source : images-sources/hero/cover-mobile-crope-max.png 1200x537
     (ratio 2.235 ≈ 20:9). Crop "max" agressif demande par le user en test 1
     pour reduire au maximum la hauteur du hero mobile.
     - Image hero-portrait : ratio 537/1200 = 44.75% du viewport en hauteur
       (vs 67% du 3:2 d'origine, vs 56% du 16:9 intermediaire). Gain ~50%.
     - Sous-titre : passe de text-lg (1.125rem) a text-base (1rem) pour gagner
       quelques px de plus sans toucher au message editorial.
     Override aussi le background-image vers la version sandbox. */
  .section--hero {
    background-image: url('/images/hero-portrait.avif') !important;
  }
  .section--hero::before {
    height: calc(100vw * 537 / 1200) !important;
  }
  /* padding-block bottom : passe de var(--space-md) (16px) a 13px custom pour
     viser ~-33% sur la marge noire totale (16+16=32 -> 13+8=21). */
  .section--hero .container {
    padding-block: calc(100vw * 537 / 1200 + var(--space-md)) 13px !important;
  }
  .section--hero .container > p {
    font-size: var(--text-base) !important;
  }
}

/* Sections light consecutives : annule le padding-top de la suivante.
   Sans ca, on cumule 64+64 = 128px de vide entre la fin de "A la une" et
   le titre "Dernieres actus" alors que les deux sections partagent le meme
   fond dark et sont editorialement liees. Avec padding-top: 0, on garde
   les 64px de padding-bottom de la 1re comme respiration unique.
   IMPORTANT : conditionne au desktop ≥600px. En mobile, le user a remonte
   que l'eyebrow de la section suivante (Guides, Tests) etait trop proche
   du bouton CTA precedent. En mobile on laisse le padding-top normal pour
   avoir 24+24 = 48px de respiration entre CTA et eyebrow. */
@media (min-width: 600px) {
  .section--light + .section--light {
    padding-top: 0;
  }
}

.section--light .section__title { color: var(--color-text-on-dark); }
.section--light .section__link { color: var(--color-accent-pink-light); }
.section--light .section__link:hover { color: var(--color-accent-pink); }

/* Cards par defaut sur fond dark : surface + filet light fin (palier 10 bis
   2026-05-14 : l'ombre noire est invisible sur dark, on la remplace par une
   bordure 1px rgba(255,255,255,0.08) qui detache visuellement la card du
   fond presque-noir. L'ombre noire reste pour le hover/transition. */
.section--light .card {
  background-color: #262626;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.section--light .card__title,
.section--light .card__title a { color: var(--color-text-on-dark); }
.section--light .card__excerpt { color: var(--color-text-on-dark-muted); }
.section--light .card__date { color: var(--color-text-on-dark-muted); }

/* Harmonisation cards section--dark existante : meme filet light fin. */
.section--dark .card,
.section--dark-alt .card {
  background-color: #262626;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

/* --------------------------------------------------------------------------
   PALIER 6 — Listing categorie : aeration des marges
   --------------------------------------------------------------------------
   User feedback 2560@125 sur /actu/ :
   - Marge filtres -> 1er rang de cards trop serree (paraissait colle)
   - Marge derniere card -> footer trop serree
   Solution : margin-top supplementaire sur la grille apres les filtres,
   et padding-bottom de section plus genereux en desktop.
   -------------------------------------------------------------------------- */

/* Espace filtres -> grille de cards : +32px d'air. Sans collapsing margins
   sur grid containers, c'est additionnel au margin-bottom des filtres. */
.filters + .card-grid {
  margin-top: var(--space-xl);
}

/* Padding-bottom plus genereux pour la derniere section avant footer.
   Selector universel : peu importe le type de section (--light, --dark,
   --dossiers, --gradient...), la derniere de .main-content gagne un
   padding-bottom plus genereux (vs 64px par defaut).
   Couvre :
   - Home (derniere section = Dossiers)
   - Listing categorie (derniere section = .section--light avec card-grid)
   - Article (derniere section = .section--dark avec related-section)
   - Toutes pages futures */
@media (min-width: 600px) {
  .main-content > section:last-child {
    padding-bottom: 5rem;  /* 80px desktop */
  }
}

/* Mobile : palier 1 phase A passe .section a padding-block 24px. Manquait
   d'air entre la derniere card et le trait gradient du footer. Iterations
   24 -> 32 (insuffisant) -> 48px. */
@media (max-width: 599px) {
  .main-content > section:last-child {
    padding-bottom: var(--space-2xl);
  }

  /* Listing mobile : le hero gradient termine au-dessus, les boutons filtres
     paraissaient un peu colles au bord (24+24=48px). On augmente le top
     de la section listing a 32px pour aerer (28+24=56px effectifs). */
  .section--light:has(> .container > .filters) {
    padding-top: var(--space-xl);
  }

  /* Footer-newsletter mobile : 48px (--space-2xl) en padding-block pour
     matcher le 48px du padding-bottom de la derniere section. Symetrie
     autour du trait gradient avec assez d'air pour respirer. */
  .footer-newsletter {
    padding-block: var(--space-2xl);
  }

  /* Site-footer mobile : footer.css impose padding-block: var(--space-3xl)
     var(--space-xl) = 64px en haut, ce qui ajouterait 64px supplementaires.
     On annule le top, laissant .footer-newsletter gerer son propre espacement.
     Resultat : 48px sous derniere card -> trait gradient -> 48px (footer-newsletter
     padding-top) -> texte 10M. */
  .site-footer {
    padding-top: 0;
  }
}

/* ----- utilities.css ----- */
/* ==========================================================================
   Utilities — Gradient text, placeholder images, helpers
   ========================================================================== */

/* --- Texte en dégradé --- */

.gradient-text {
  background: var(--gradient-accent-horizontal);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* --- Image placeholder (CSS pur) --- */

.placeholder-img {
  background: var(--gradient-accent);
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.25);
  font-size: var(--text-xs);
  font-family: var(--font-body);
  overflow: hidden;
}

.placeholder-img--rounded {
  border-radius: var(--radius-card);
}

/* --- Accessibilité : texte invisible visuellement --- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* --- Texte tronqué (multiline) --- */

.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.line-clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- Texte muted --- */

.text-muted {
  opacity: 0.7;
}

/* ----- components.css ----- */
/* ==========================================================================
   Components — Cards, tags, boutons, breadcrumbs, badges
   ========================================================================== */

/* --- Card --- */

.card {
  position: relative; /* ancre pour le pseudo-element "::before" du lien (card cliquable en entier) */
  background-color: var(--color-light-bg-alt);
  border-radius: var(--radius-card);
  overflow: hidden;
  transition: transform var(--transition-base), box-shadow var(--transition-base);
  cursor: pointer;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

/* Zone cliquable étendue à toute la card via le pseudo-element du lien du titre :
   accessibilité préservée (screen readers = lien avec texte du titre),
   SEO-friendly (le texte d'ancre reste le titre), pas de <a> imbriqués. */
.card__title a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Card sur fond sombre : fond #252540 + ombre projetée + bordure subtile.
   La combinaison ombre+bordure garantit que la carte ressort à la fois sur
   écran contrasté (l'ombre ajoute de la profondeur) et sur écran peu
   contrasté (la bordure 1px garantit une frontière géométrique visible).
   Pattern éprouvé sur Stripe / Vercel / Linear en dark mode. */
.section--dark .card,
.section--dark-alt .card {
  background-color: var(--color-dark-bg-elevated);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.card__image {
  width: 100%;
}

.card__body {
  padding: var(--space-lg);
}

/* Tweaks 2026-04-29 : font-size, weight, padding et letter-spacing
   reduits pour alleger visuellement (~20% d'emprise en moins) sans
   sacrifier l'identite. Le titre reprend l'avantage visuel.
   L'idee "tag a droite" testee a ete reculee : padding-right fixe
   tassait trop les titres courts. A retravailler avec une approche
   differente (tag en bas avec la date, a la NYT). */
.card__tag {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 0.6875rem;           /* 11px (vs 12) */
  font-weight: 600;               /* semi-bold (vs 700) */
  text-transform: uppercase;
  letter-spacing: 0.4px;          /* 0.4px (vs 0.5) */
  padding: 3px 8px;               /* vertical resserre 3 (vs 4) */
  border-radius: var(--radius-full);
  color: #ffffff;
  margin-bottom: var(--space-sm);
}

.card__tag--kindroid {
  background-color: var(--color-tag-kindroid);
}

.card__tag--nomi {
  background-color: var(--color-tag-nomi);
}

.card__tag--replika {
  background-color: var(--color-tag-replika);
}

.card__tag--general {
  background-color: var(--color-tag-general);
}

.card__tag--character {
  background-color: var(--color-tag-character);
}

.card__tag--candy {
  background-color: var(--color-tag-candy);
}

.card__tag--assistant-ia {
  background-color: var(--color-tag-assistant-ia);
}

.card__title {
  font-size: var(--text-lg);
  line-height: 1.3;
  margin-bottom: var(--space-sm);
}

/* Limite les titres à 2 lignes max pour aligner les hauteurs des cards
   dans la grille (sinon un titre long bombe sa card). Featured exempté
   parce qu'elle a son propre design large. Le H3 reste complet en HTML
   (SEO préservé), c'est juste l'affichage qui est tronqué avec ellipsis. */
.card:not(.card--featured) .card__title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card__title a {
  display: block;
}

.card__title a:hover {
  color: var(--color-accent-pink);
}

.section--dark .card__title a:hover,
.section--dark-alt .card__title a:hover {
  color: var(--color-accent-pink-light);
}

.card__excerpt {
  font-size: var(--text-sm);
  color: var(--color-text-on-light-muted);
  margin-bottom: var(--space-sm);
  line-height: 1.5;
}

.section--dark .card__excerpt,
.section--dark-alt .card__excerpt {
  color: var(--color-text-on-dark-muted);
}

.card__date {
  font-size: var(--text-xs);
  color: var(--color-text-on-light-muted);
}

.section--dark .card__date,
.section--dark-alt .card__date {
  color: var(--color-text-on-dark-muted);
}

/* --- Card featured (grande carte à la une) --- */

.card--featured .card__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-xl);
}

/* Featured card : badge plein-largeur en gradient = signal éditorial
   "à la une". Le badge stretch naturellement dans le flex column, on
   en fait une feature plutôt qu'un bug. Le gradient signature renforce
   visuellement et l'override fond plein de couleur de plateforme.
   Espace insécable fine (\202F) avant le ":" pour la typo française. */
.card--featured .card__body .card__tag {
  background: var(--gradient-accent-horizontal);
}

.card--featured .card__body .card__tag::before {
  content: 'À LA UNE\202F: ';
}

.card--featured .card__title {
  font-size: var(--text-2xl);
}

.card--featured .card__excerpt {
  font-size: var(--text-base);
}

@media (min-width: 600px) {
  .card--featured .placeholder-img {
    border-radius: var(--radius-card) 0 0 var(--radius-card);
    height: 100%;
    aspect-ratio: auto;
  }

  .card--featured .card__img {
    border-radius: var(--radius-card) 0 0 var(--radius-card);
    height: 100%;
    aspect-ratio: auto;
    object-fit: cover;
  }
}

/* --- Image réelle dans les cartes --- */

.card__img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  display: block;
}

/* --- Séparateur gradient (entre sections sombres) ---
   Petit trait centré en dégradé signature (violet -> rose), cohérent avec
   l'identité visuelle. À insérer entre deux sections de même fond foncé
   pour créer une respiration élégante sans bloc de couleur opposé. */

.gradient-separator {
  width: 80%;
  max-width: 600px;
  height: 2px;
  margin: var(--space-2xl) auto;
  border: none;
  border-radius: 1px;
  background: linear-gradient(90deg, #6a1b9a, #e84570);
}

/* --- Image hero dans les articles ---
   La classe .article-hero-img historique a été retirée le 2026-04-25.
   Voir .article-hero dans article.css pour le nouveau pattern (image
   dans la section sombre, aspect-ratio 16/9 natif). */

/* --- Boutons --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  font-size: var(--text-sm);
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--radius-full);
  border: none;
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  text-decoration: none;
}

.btn:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn--primary {
  background: var(--gradient-accent);
  color: #ffffff;
}

.btn--outline {
  background: transparent;
  border: 2px solid var(--color-accent-pink-light);
  color: var(--color-accent-pink-light);
}

.section--light .btn--outline {
  border-color: var(--color-accent-purple);
  color: var(--color-accent-purple);
}

/* --- Breadcrumbs --- */

.breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  font-size: var(--text-sm);
  margin-bottom: var(--space-xl);
}

.breadcrumbs a {
  color: var(--color-accent-pink-light);
}

.breadcrumbs a:hover {
  text-decoration: underline;
}

.section--light .breadcrumbs a {
  color: var(--color-accent-purple);
}

.breadcrumbs__separator {
  opacity: 0.5;
}

.breadcrumbs__current {
  opacity: 0.7;
}

/* --- Filtres plateformes --- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-2xl);
}

/* Compensation listings SANS filtres : ajoute un padding-top au card-grid
   pour préserver l'alignement vertical avec les listings qui ont des filtres.
   Sinon le grid colle direct au header gradient quand le listing n'a pas de
   zone .filters (cas /dossiers/, /guides/, /tests/ qui ont 1-2 cards seul
   sans filtrage utile). Feedback user 19/5 ("décalage de marge quand on
   switch sur un page avec/sans capsules").
   La compensation = hauteur filtres (~50px) + margin-bottom filtres (--space-2xl
   = 48px) ≈ var(--space-3xl) (64px). Un peu sous l'écart réel mais ça donne
   un alignement suffisamment proche pour ne plus voir le saut visuel. */
.section--light:not(:has(> .container > .filters)) > .container > .card-grid {
  margin-top: var(--space-3xl);
}

.filter-btn {
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-semi);
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-text-on-light-muted);
  background: transparent;
  color: var(--color-text-on-light-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.filter-btn:hover {
  border-color: var(--color-accent-purple);
  color: var(--color-accent-purple);
  background-color: rgba(106, 27, 154, 0.08);
}

.filter-btn.active {
  border-color: var(--color-accent-purple);
  color: #ffffff;
  background-color: var(--color-accent-purple);
}

/* --- Transition fade sur les cartes filtrées --- */

.card[data-platform] {
  transition: opacity 0.3s ease;
}

.section--dark .filter-btn {
  border-color: var(--color-text-on-dark-muted);
  color: var(--color-text-on-dark-muted);
}

.section--dark .filter-btn:hover {
  border-color: var(--color-accent-pink-light);
  color: var(--color-accent-pink-light);
  background-color: rgba(232, 69, 112, 0.1);
}

.section--dark .filter-btn.active {
  border-color: var(--color-accent-pink-light);
  color: #ffffff;
  background-color: var(--color-accent-pink-light);
}

/* --- Empty state (grilles vides en attente de contenu) --- */

.empty-state {
  text-align: center;
  color: var(--color-text-muted);
  margin-top: var(--space-xl);
  font-style: italic;
}

.empty-state--on-dark {
  color: var(--color-text-on-dark-muted);
}

/* ==========================================================================
   PALIERS v1-dark migrés depuis lab/v1-dark/dark.css (2026-05-19, Phase F)
   --------------------------------------------------------------------------
   Bloc absorbe les paliers 2, 3, 9, 9b, 10, 11, 12, 16, 19 du sandbox dark.css.
   Les règles ci-dessous OVERRIDENT les définitions prod historiques plus
   haut dans ce fichier (CSS lit dans l'ordre).
   ========================================================================== */

/* --------------------------------------------------------------------------
   PALIER 2 — Composants pour la refonte structure
   -------------------------------------------------------------------------- */

/* --- Eyebrow : label uppercase au-dessus de chaque section --- */

.section-eyebrow {
  /* font-size 0.75 -> 0.875 (14px) + weight 500 -> 600 : le label kicker
     paraissait trop discret par rapport au reste de la page (titres de
     cards en 1.125-1.5rem, body en 1rem). 14px en 600 garde le cote
     "eyebrow" sans disparaitre. */
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: var(--space-lg);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: var(--space-sm);
  font-weight: 600;
}

/* --- Card-hero : 1 carte pleine largeur (zone "A la une") --- */

.card-hero {
  position: relative;
  background-color: #262626;
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.card-hero:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}

/* Layout horizontal sur desktop : pattern "lead story" type The Verge / NYT
   Top Story. Image a gauche 50%, texte a droite 50%. Hierarchie visuelle
   distincte de la grille 3x3 en-dessous (qui est image-en-haut). Resout :
   - hauteur excessive de la card en pleine largeur
   - effet "deux grosses images qui se suivent" (hero -> featured)
   - plus de crop editorial par article (l'image garde son ratio natif et
     se cale via object-fit: cover sur la moitie de la card). */

.card-hero picture {
  display: block;
  position: relative;
}

.card-hero__img {
  width: 100%;
  height: auto;
  /* Mobile <600px : ratio 16/9 pour matcher le natif des covers
     (cover-mobile.avif est en 688x384 = 16/9). Evite le crop disgracieux
     hauteur ~30% qu'on avait en 24/9. Desktop >=600px override via media
     query (passage en grid 2 cols, aspect-ratio: auto). Bug identifie
     user 22/5 nuit cover dossier IA Mon amour. */
  aspect-ratio: 16 / 9;
  max-height: 380px;
  object-fit: cover;
  display: block;
}

.card-hero__body {
  padding: var(--space-lg) var(--space-xl);
}

/* Desktop ≥600px : passage en grid 2 colonnes 50/50.
   L'image prend la hauteur du body (decidee par le contenu titre+excerpt),
   ce qui donne une card naturellement compacte (~280-320px de haut au lieu
   de 400+). Le body est centre verticalement pour eviter du vide. */
@media (min-width: 600px) {
  .card-hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }
  .card-hero picture {
    height: 100%;
  }
  .card-hero__img {
    aspect-ratio: auto;
    max-height: none;
    height: 100%;
  }
  .card-hero__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--space-xl) var(--space-2xl);
  }
}

.card-hero__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-md);
}

.card-hero__date {
  color: var(--color-text-on-dark-muted);
  font-size: var(--text-sm);
}

.card-hero__title {
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  font-weight: var(--font-weight-heading-bold);
  line-height: 1.3;
  margin-bottom: var(--space-md);
  color: var(--color-text-on-dark);
}

.card-hero__title a { color: inherit; }

.card-hero__title a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card-hero__excerpt {
  color: var(--color-text-on-dark-muted);
  margin-bottom: 0;
  line-height: 1.6;
}

/* --- Card grid 3 colonnes (Dernieres actus, 9 cards en 3x3) --- */

@media (min-width: 600px) {
  .card-grid--3col {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .card-grid--3col {
    grid-template-columns: repeat(3, 1fr);
    /* Override du gap par defaut (32px = --space-xl herite de .card-grid).
       Sur la grille 3col, 32px paraissent disproportionnes par rapport aux
       cards (effet "fragmente"), surtout quand le viewport grandit et que
       les marges laterales container->ecran s'agrandissent. 24px resserre
       la grille en bloc plus compact, sans coller. */
    gap: var(--space-lg);
  }
}

/* Image en 16:9 sur les cards 3col (cards plus etroites, image moins haute) */
.card-grid--3col .card__img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.card-grid--3col .card__body {
  padding: var(--space-md) var(--space-lg) var(--space-lg);
}

/* Excerpt 2 lignes max pour homogeneite visuelle des 9 cards */
.card-grid--3col .card__excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  margin-top: var(--space-xs);
  margin-bottom: 0;
  line-height: 1.5;
}

/* --- Card meta : ligne tag plateforme + date alignes --- */

.card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-sm);
}

.card__meta .card__date {
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
}

.card__meta .card__tag { margin-bottom: 0; }

/* --- Cat-badge : badges categorie discrets en overlay sur image
   Couleurs adoucies (alpha 0.92 sur background) pour respecter l'image
   en arriere-plan tout en restant lisibles. */

.cat-badge {
  display: inline-block;
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* Variantes par categorie : memes valeurs visuelles (blanc minimal sur fond
   dark 40%). On ne distingue plus les categories par couleur — le texte du
   badge fait foi (TEST, GUIDE, DOSSIER). Pattern volontaire : universel,
   resiste aux images claires (Replika lumineuse) comme aux cinema sombre. */
.cat-badge--test,
.cat-badge--guide,
.cat-badge--dossier {
  /* heritent du base, pas d'override */
}

/* --- Section CTA : bouton style avec gradient signature en bordure --- */

.section-cta {
  display: block;
  /* margin-top 32 -> 48 : le CTA paraissait colle a la derniere ligne de
     cards, manque de respiration entre la grille et le bouton final. */
  margin-top: var(--space-2xl);
  padding: var(--space-md);
  text-align: center;
  background: linear-gradient(135deg, rgba(106, 27, 154, 0.12), rgba(216, 27, 96, 0.12), rgba(232, 69, 112, 0.12));
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  position: relative;
  color: #ffffff;
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-sm);
  text-decoration: none;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

/* Bordure gradient signature via mask trick (fonctionne sur Chrome/Safari/FF recent) */
.section-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: var(--gradient-accent-horizontal);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

.section-cta:hover {
  background: linear-gradient(135deg, rgba(106, 27, 154, 0.25), rgba(216, 27, 96, 0.25), rgba(232, 69, 112, 0.25));
  transform: translateY(-1px);
}

/* --- Section "10 millions" : bandeau full-width avec fade lateral
   Le gradient signature couvre toute la largeur visuellement, mais s'estompe
   aux extremites laterales pour reveler le fond dark de la page derriere.
   Implementation : pseudo-element avec mask, par-dessus un fond solide dark.
   Sans le fond solide, le mask laisserait voir le body (#f5f5fa par defaut)
   et donnait un fade vers blanc (bug initial). */

.section--ten-million {
  position: relative;
  /* padding-block 24 -> 32 : le texte 2 lignes paraissait tasse entre le
     haut et le bas du gradient. 32 donne plus de presence au message sans
     transformer le bandeau en grosse section. */
  padding-block: var(--space-xl);
  text-align: center;
  background-color: #1e1e1e; /* fond solide derriere le gradient mask */
}

.section--ten-million::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Gradient symetrique : pic au centre, retour aux couleurs douces aux bords.
     Resoud l'asymetrie visuelle de gradient-signature qui finit sur #e84570
     (saturation max a droite) avec un fade insuffisant pour compenser. */
  background: linear-gradient(90deg,
    #2a1040 0%,
    #6a1b9a 25%,
    #d81b60 50%,
    #6a1b9a 75%,
    #2a1040 100%
  );
  -webkit-mask-image: linear-gradient(90deg,
    transparent 0%,
    black 15%,
    black 85%,
    transparent 100%
  );
          mask-image: linear-gradient(90deg,
    transparent 0%,
    black 15%,
    black 85%,
    transparent 100%
  );
  pointer-events: none;
}

.section--ten-million .container {
  position: relative;
  z-index: 1;
}

.section--ten-million p {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.125rem, 2.5vw, 1.625rem);
  color: #ffffff;
  max-width: 680px;
  margin: 0 auto;
  line-height: 1.35;
}

.ten-million-highlight {
  background: linear-gradient(90deg, #c084fc, #f472b6);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* --- Section Dossiers : fond plus sombre --- */

.section--dossiers {
  background-color: #171717;
  color: var(--color-text-on-dark);
  padding-block: var(--section-padding-y);
}

/* --- Card Dossier : style editorial avec filet gradient signature vertical
   Le bug precedent : border-image avec gradient horizontal sur border-left
   donne couleur uniforme. Fix : pseudo-element ::before en gradient vertical. */

.card-dossier {
  position: relative;
  padding: var(--space-lg) var(--space-xl);
  margin-bottom: var(--space-md);
  background-color: rgba(255, 255, 255, 0.02);
  transition: background-color var(--transition-fast);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.card-dossier::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 3px;
  /* Gradient avec fade aux extremites (style trait du footer) : commence et
     finit en transparent, intensite max au centre. Stops resserres pour
     que le filet "respire" plus dans la card (fade plus precoce
     bas et haut). */
  background: linear-gradient(180deg,
    transparent 0%,
    #6a1b9a 15%,
    #d81b60 40%,
    #e84570 60%,
    transparent 80%
  );
}

.card-dossier:hover {
  background-color: rgba(255, 255, 255, 0.04);
}

/* Meta line : label "Dossier" a gauche + date a droite (format harmonise
   avec le reste du site : "JJ mois" sans annee). */
.card-dossier__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: var(--space-sm);
}

.card-dossier__label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #c084fc;
  font-weight: 600;
}

.card-dossier__date {
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
}

.card-dossier__title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-heading-bold);
  line-height: 1.3;
  margin-bottom: var(--space-sm);
  color: var(--color-text-on-dark);
}

.card-dossier__title a { color: inherit; }

.card-dossier__title a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card-dossier__excerpt {
  color: var(--color-text-on-dark-muted);
  line-height: 1.6;
  margin-bottom: 0;
}

/* --- Card-list-item featured : grand item liste avec image (Tests/Guides) --- */

.card-list-item--featured {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--space-lg);
  background-color: #262626;
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  margin-bottom: var(--space-md);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
  position: relative;
}

.card-list-item--featured:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}

.card-list-item--featured .card-list-item__media {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 140px;
  background-color: #1a1a1a;
}

.card-list-item--featured .card-list-item__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-list-item--featured .card-list-item__body {
  padding: var(--space-lg) var(--space-lg) var(--space-lg) 0;
}

.card-list-item__title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-heading-bold);
  line-height: 1.3;
  margin-bottom: var(--space-sm);
  color: var(--color-text-on-dark);
}

.card-list-item__title a { color: inherit; }

.card-list-item__title a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card-list-item__excerpt {
  color: var(--color-text-on-dark-muted);
  font-size: var(--text-sm);
  line-height: 1.5;
  margin-bottom: 0;
}

@media (max-width: 599px) {
  .card-list-item--featured {
    grid-template-columns: 1fr;
  }
  .card-list-item--featured .card-list-item__body {
    padding: var(--space-md) var(--space-lg) var(--space-lg);
  }
}

/* --- Card-list-item compact : vignette image + titre --- */

.card-list-item--compact {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  margin-bottom: var(--space-sm);
  text-decoration: none;
  color: var(--color-text-on-dark);
  border-radius: var(--radius-md);
  transition: background-color var(--transition-fast);
}

.card-list-item--compact:hover {
  background-color: rgba(255, 255, 255, 0.04);
}

.card-list-item__thumb {
  display: block;
  flex-shrink: 0;
  width: 80px;
  height: 50px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background-color: #1a1a1a;
}

.card-list-item__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-list-item__title-compact {
  font-size: var(--text-base);
  line-height: 1.4;
  color: var(--color-text-on-dark);
}

/* --------------------------------------------------------------------------
   PALIER 3 — Layout "lead story" 2 colonnes pour Tests/Guides
   --------------------------------------------------------------------------
   Inspire The Verge : 1 featured grand a gauche (image au-dessus, texte
   fort en dessous) + 4 side items a droite (texte gauche, vignette droite,
   avec excerpt et date). Resout le sentiment "trop petit / manque de texte"
   du layout precedent (1 featured + 2 vignettes minuscules sans excerpt).
   -------------------------------------------------------------------------- */

.card-list-grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: var(--space-2xl);
  align-items: start;
}

@media (max-width: 899px) {
  .card-list-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Featured large (gauche) : image au-dessus, texte en dessous ----- */

.card-list-item--featured-large {
  display: block;
  background-color: #262626;
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  position: relative;
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.card-list-item--featured-large:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55);
}

.card-list-item--featured-large .card-list-item__media {
  display: block;
  position: relative;
  aspect-ratio: 16 / 9;
}

.card-list-item--featured-large .card-list-item__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-list-item--featured-large .card-list-item__body {
  padding: var(--space-lg) var(--space-xl) var(--space-xl);
}

.card-list-item--featured-large .card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-sm);
}

.card-list-item--featured-large .card-list-item__title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-heading-bold);
  line-height: 1.3;
  margin-bottom: var(--space-md);
  color: var(--color-text-on-dark);
}

.card-list-item--featured-large .card-list-item__title a {
  color: inherit;
}

.card-list-item--featured-large .card-list-item__title a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card-list-item--featured-large .card-list-item__excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--color-text-on-dark-muted);
  font-size: var(--text-sm);
  line-height: 1.6;
  margin-bottom: 0;
}

/* ----- Side items (droite) : texte gauche, vignette droite ----- */

.card-list-side {
  display: flex;
  flex-direction: column;
}

.card-list-item--side {
  display: grid;
  grid-template-columns: 1fr 110px;
  gap: var(--space-lg);
  align-items: center;
  padding: var(--space-md) 0;
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  transition: opacity var(--transition-fast);
}

.card-list-item--side:first-child {
  padding-top: 0;
}

.card-list-item--side:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.card-list-item--side:hover {
  opacity: 0.85;
}

.card-list-item__body-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.card-list-item__meta-side {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.card-list-item__platform-tag {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-accent-pink-light);
}

.card-list-item__date-side {
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
}

.card-list-item__title-side {
  font-size: var(--text-base);
  font-weight: var(--font-weight-heading-bold);
  line-height: 1.4;
  color: var(--color-text-on-dark);
  margin: 0;
}

.card-list-item__excerpt-side {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  line-height: 1.5;
  margin: 0;
}

.card-list-item__thumb-side {
  display: block;
  aspect-ratio: 1;
  border-radius: var(--radius-md);
  overflow: hidden;
  background-color: #1a1a1a;
}

.card-list-item__thumb-side img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* --------------------------------------------------------------------------
   PALIER 9 — Pattern Tests/Guides featured-solo (2026-05-11)
   --------------------------------------------------------------------------
   Quand une zone home (Tests, Guides, ou autre utilisant .card-list-grid)
   ne contient qu'un seul article (pas de .card-list-side a cote), on
   bascule en layout horizontal pleine largeur type "card-hero" : image
   gauche 50%, body droit 50%. Evite l'effet "carte mise en avant qui flotte
   toute seule dans une grid 2 cols a moitie vide".

   Le selecteur :has() detecte automatiquement l'absence des side items, donc
   pas besoin de classe specifique cote HTML : le bascule se fait quand le
   pipeline genere une section avec un seul article.
   -------------------------------------------------------------------------- */

/* Quand la grid n'a pas de .card-list-side : passer en 1 col pleine largeur */
.card-list-grid:not(:has(.card-list-side)) {
  grid-template-columns: 1fr;
}

/* Desktop ≥600px : layout horizontal media gauche / body droite, type
   "card-hero". On reprend le pattern existant de .card-hero pour homogeneite. */
@media (min-width: 600px) {
  .card-list-grid:not(:has(.card-list-side)) .card-list-item--featured-large {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }

  .card-list-grid:not(:has(.card-list-side)) .card-list-item--featured-large .card-list-item__media {
    aspect-ratio: auto;
    height: 100%;
  }

  .card-list-grid:not(:has(.card-list-side)) .card-list-item--featured-large .card-list-item__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--space-xl) var(--space-2xl);
  }
}

/* --------------------------------------------------------------------------
   PALIER 21 — Reequilibrage home featured + sides (2026-05-23)
   --------------------------------------------------------------------------
   Pendant du palier 9 : quand .card-list-grid contient des sides (cas
   Dossiers avec 2-3 dossiers, ou Tests/Guides quand ils s'etofferont), on
   tasse la cover featured pour ne pas qu'elle ecrase visuellement les sides
   (qui sont plus petits). Sinon le featured a l'air disproportionne et
   monopolise l'oeil au detriment du sentiment "section riche en contenu".

   Strategie validee 23/5 par feedback user en mockup lab/dossiers-layout/
   puis ajustee sur capture prod-like apres 2 iterations :
   - Tentative 1 : grille 1fr/1fr + cover 24/9 (cover letterboxee). Probleme :
     incoherence visuelle avec les autres cards (toutes en 16/9 sur le site).
   - Tentative 2 : grille 1fr/1fr + cover 32/9. Probleme : crop sale, perte
     de lisibilite de l'image.
   - Approche finale : on casse la symetrie 50/50. Grille 0.8fr/1fr (~44/56)
     donne plus de place aux sides et reduit naturellement la featured sans
     toucher au ratio. On garde le cover 16/9 par defaut (coherent avec le
     reste du site), c'est la GRILLE qui equilibre, pas le crop.

   Resultat : featured Dossiers visuellement contenue, sides plus larges
   donc plus presents, ratio cover 16/9 preserve partout. Hierarchie
   editoriale alignee : Guides solo plein format (porte d'entree FR) >
   Dossiers featured+sides en split asymetrique (climax SEO + densite
   editoriale).
   -------------------------------------------------------------------------- */

/* IMPORTANT : enveloppe @media desktop. La regle palier 21 a une specificite
   plus haute (0,2,0 via :has()) que le break mobile natif (0,1,0 ligne 932),
   donc sans cette enveloppe, le `grid-template-columns: 0.8fr 1fr` ecrasait
   le `1fr` mobile et produisait 2 colonnes etroites sur mobile (featured
   compressee en bande verticale ~40% de viewport, illisible).
   Bug detecte 23/5 par user sur S24. Fix : ne s'applique qu'a >=900px. */
@media (min-width: 900px) {
  .card-list-grid:has(.card-list-side) {
    grid-template-columns: 0.8fr 1fr;
  }

  /* Tant que la colonne sides n'est pas remplie (cas 1 side seul, transitoire
     avant le 3e dossier), on la centre verticalement dans sa cellule pour
     eviter l'effet "side colle en haut + desert en bas". Quand 2 sides sont
     presents et remplissent la hauteur de la featured, align-self: center n'a
     plus d'effet visible. */
  .card-list-grid:has(.card-list-side) .card-list-side {
    align-self: center;
  }
}

/* --------------------------------------------------------------------------
   PALIER 9b — Dossiers : vignette a droite + section deplacee entre G/T
   --------------------------------------------------------------------------
   La section Dossiers est maintenant entre Guides et Tests (cf swap dans le
   HTML). Pour la differencier visuellement et casser le rythme "deux grandes
   cartes hero qui se suivent", on ajoute une petite vignette a DROITE de
   chaque card-dossier (alternance visuelle gauche/droite vs Guides/Tests qui
   ont leur image a gauche).

   Layout cible (≥600px) :
     [ Meta + Titre + Excerpt ] [ Petite vignette 180×100 ]

   Sur mobile (<600px) : on cache la vignette, on garde juste le texte pour
   rester sobre et eviter le texte trop tasse en 2 colonnes etroites.
   -------------------------------------------------------------------------- */

.section--dossiers .card-dossier {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-lg);
  align-items: center;
}

/* Wrapper du contenu textuel (meta + titre + excerpt). min-width: 0 evite
   les overflow en flex/grid lorsque le contenu est long. */
.section--dossiers .card-dossier__body {
  min-width: 0;
}

/* Vignette a droite : taille fixe pour rester compacte (pas grande image
   hero), bords arrondis pour adoucir. 140px (au lieu de 180px) pour garder
   le format "accroche visuelle" sans dominer le bloc texte.

   Bordure light + ombre douce : sur fond sombre, les covers a teintes
   noires (ex. "C'est quoi un compagnon IA") se fondaient dans le fond.
   On les detache via 1px de contour clair + ombre flottante. */
.section--dossiers .card-dossier__media {
  display: block;
  width: 140px;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.02);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Meta line des dossiers : on passe de "label gauche / date droite" (qui
   ecrasait la date contre la vignette) a "label + date inline a gauche"
   avec un separateur ·. Plus compact et lisible. */
.section--dossiers .card-dossier__meta {
  justify-content: flex-start;
  gap: var(--space-sm);
}

.section--dossiers .card-dossier__date::before {
  content: "·";
  margin-right: var(--space-sm);
  color: var(--color-text-on-dark-muted);
}

.section--dossiers .card-dossier__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--transition-base);
}

.section--dossiers .card-dossier:hover .card-dossier__media img {
  transform: scale(1.04);
}

/* Mobile : pattern type Korben.info — petite image CARREE a GAUCHE +
   titre uniquement a droite. On cache la meta et l'excerpt pour rester
   compact (le clic ouvre le dossier, l'info detaillee est sur la page
   dossier elle-meme). */
@media (max-width: 599px) {
  .section--dossiers .card-dossier {
    grid-template-columns: 64px 1fr;
    gap: var(--space-md);
    align-items: center;
  }

  /* Inversion ordre HTML (body, media) -> visuel (media, body).
     On renforce bordure + ombre par rapport au desktop : sur mobile les
     vignettes carrees 64×64 ont besoin de plus de relief pour bien se
     detacher du fond sombre, alors qu'en desktop le 140×~80 16/9 suffit. */
  .section--dossiers .card-dossier__media {
    display: block;
    width: 64px;
    height: 64px;
    aspect-ratio: 1;
    order: 1;
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.28);
  }

  .section--dossiers .card-dossier__body {
    order: 2;
  }

  /* On cache meta + excerpt, on garde uniquement le titre */
  .section--dossiers .card-dossier__meta,
  .section--dossiers .card-dossier__excerpt {
    display: none;
  }

  /* Titre compact, plus de margin-bottom (rien en-dessous) */
  .section--dossiers .card-dossier__title {
    font-size: var(--text-base);
    line-height: 1.35;
    margin-bottom: 0;
  }
}

/* --------------------------------------------------------------------------
   PALIER 10 — Cards mobile : marges reduites (variante B validee S24)
   2026-05-14
   --------------------------------------------------------------------------
   Sur mobile <600px, le --container-padding de 24px laissait 13% de la
   largeur ecran perdue en marge laterale pour la zone listing. Trop pour
   des cards listing qui doivent dominer visuellement.

   Solution : on reduit le padding effectif uniquement sur les grilles de
   cards (margin-inline negatif partiel : -24 + 12 = -12). Le titre de
   section et le reste du container gardent leurs 24px (lisibilite typo).
   Coins arrondis conserves puisque les cards restent off-edge.

   La featured .card-hero (A la une) reste a 24px pour l'instant : test
   edge-to-edge non concluant le 14/5, autre piste de differenciation a
   trouver.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
  .card-grid,
  .card-list-grid,
  .card-hero {
    margin-inline: calc(-1 * var(--container-padding) + 0.75rem);
  }
}

/* --------------------------------------------------------------------------
   PALIER 11 — Eyebrow "A LA UNE" : texte en gradient signature (2026-05-14)
   --------------------------------------------------------------------------
   La featured (.card-hero) est maintenant alignee sur le format listing
   (12px lateral, meme look general). Pour la differencier en tant que
   vedette editoriale, on applique le gradient signature directement sur
   le texte de l'eyebrow (meme gradient que le logo "AI" du header pour
   coherence visuelle marque).

   Choix : pas de trait gradient sous le texte (le logo header utilise
   deja un gradient, ajouter un 2eme trait gradient en eyebrow creerait
   un double-gradient visuel quand le header sticky est visible). Le
   texte en gradient seul = signature graphique forte et coherente.

   Les autres eyebrows (Dernieres actus, Guides, Dossiers, Tests) restent
   gris discret pour preserver la hierarchie.

   Ciblage via :has() : on cible l'eyebrow de la section qui contient
   .card-hero (pattern unique sur la home actuelle).
   -------------------------------------------------------------------------- */

.section:has(> .container > .card-hero) .section-eyebrow {
  /* Choix de simplicite (2026-05-14) : blanc franc plutot que gradient.
     Les essais gradient (3-couleurs puis 2-couleurs rose) ne passaient pas
     sur 5 lettres uppercase (~85px) : une couleur dominait toujours, pas
     de degrade lisible. Le blanc franc ressort fort sur dark, garde une
     hierarchie nette avec les autres eyebrows en gris 55%. Retoucher
     plus tard si on veut affiner la signature (5 min de boulot). */
  color: #fff;
}

/* --------------------------------------------------------------------------
   PALIER 12 — Cards dossiers : liseret light en mobile (2026-05-14)
   --------------------------------------------------------------------------
   On aligne la perception des cards dossiers sur celle des cards actu :
   meme filet light 1px rgba(255,255,255,0.08) pour detacher du fond dark.
   Applique sur 3 cotes (haut, droite, bas) uniquement : le cote gauche
   reste reserve au filet gradient signature ::before (palier 9b).

   Scope : mobile only. Desktop est fige selon consigne user 14/5.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
  .card-dossier {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    border-right: 1px solid rgba(255, 255, 255, 0.08);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  }
}

/* --------------------------------------------------------------------------
   PALIER 16 — Filtres capsules mobile : alléger l'amas (2026-05-17)
   --------------------------------------------------------------------------
   Audit user 17/5 sur listing-mockup S24 : 7 filtres bordés font visuellement
   "un peu tas" sur le hero gradient (chacun avec border 1.5px muted franc).
   Comparaison de 3 variantes (A fond discret, B bordure douce, C texte +
   pastille active) → user choisit C pour mobile uniquement. Sur desktop
   les 7 capsules tiennent sur une ligne aérée, le pattern actuel fonctionne
   très bien (et faudra de toute façon le revoir quand on ajoutera des
   catégories — pour le moment on évite de "faire vide").

   Pattern : inactifs en simple texte muted (pas de fond, pas de bordure),
   actif garde la pastille violette pleine + padding plus large pour
   accentuer le contraste. L'underline n'apparaît qu'au hover sur inactif
   (:not(.active)) → l'actif n'a jamais d'underline parasite redondant
   avec la pastille.

   Note : violet retenu (--color-accent-purple) car le rose --pink-light
   testé en premier "trop fort" selon user, le violet ressort mieux.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
  .section--dark .filter-btn,
  .filter-btn {
    border: none;
    background: transparent;
    color: var(--color-text-on-dark-muted);
    padding-left: var(--space-sm);
    padding-right: var(--space-sm);
    border-radius: 0;
  }

  .section--dark .filter-btn:not(.active):hover,
  .filter-btn:not(.active):hover {
    background: transparent;
    color: #ffffff;
    text-decoration: underline;
    text-underline-offset: 6px;
    text-decoration-thickness: 1.5px;
  }

  .section--dark .filter-btn.active,
  .filter-btn.active {
    border: none;
    background-color: var(--color-accent-purple);
    color: #ffffff;
    padding-left: var(--space-md);
    padding-right: var(--space-md);
    border-radius: var(--radius-full);
  }
}

/* --------------------------------------------------------------------------
   PALIER 19 — Badge "Mis à jour" overlay (2026-05-17 retour user soir)
   --------------------------------------------------------------------------
   Réactivation du pattern overlay sur cover (anciennement .cat-overlay
   "EN PAUSE" depuis 14/5) avec sémantique différente : signal de
   fraîcheur "↻ Mis à jour".

   Pourquoi pas que la home : le pattern doit être réutilisable sur
   plusieurs contextes (cf exemple Kindroid mars-avril où une grosse MAJ
   plateforme a forcé à réécrire le soir de la publi). À dégainer sur :
   - featured home (card-hero) → pour signaler une refonte importante
   - card listing (card-dossier, card normale) → pour signaler la même
     chose côté liste
   - éventuellement card-list-item--featured (sections Guides/Tests)

   Choix visuels (arbitrage user) :
   - Position : top-right (zone "alerte/info récente" classique web,
     pattern Netflix/Disney+/Amazon), marge --space-md depuis le coin
   - Forme : "↻ Mis à jour", glyphe rotation horloge texte (U+21BB),
     pas de date dans le marker (la date reste dans la meta de la card)
   - Couleur : fond noir 55% semi-transparent + backdrop-filter blur
     + bordure BLANCHE rgba(255,255,255,0.75) + texte blanc.
     Bordure magenta testée en v1 et rejetée par user : risque de se
     confondre avec covers contenant du rose/magenta + couleur magenta
     réservée aux interactions structurelles paliers 17/18, pas aux
     markers système qui doivent être universels (monochromes).
   - Taille : font-size 13px, padding 6/14 — corps suffisant pour être
     repérable sans dominer la cover

   Le pattern remplace définitivement l'ancien .cat-overlay (les blocs
   commentés "EN PAUSE" lignes ~227 et ~624 ont été supprimés en même
   temps). La catégorie est portée par le tag meta sous l'image, le
   marker overlay porte uniquement la sémantique "fraîcheur".

   Containers à passer en position: relative (déjà le cas pour la plupart
   mais on s'assure) : .card-hero picture, .card-dossier__media. Les
   cards normales (.card) ont déjà position: relative par défaut via
   leur règle de base.
   -------------------------------------------------------------------------- */

.card-hero picture,
.card-dossier__media {
  position: relative;
}

/* Note effet de bord intentionnel validé user 19/5 sur .card.card--featured
   (featured "À LA UNE" home) : ce sélecteur ne match PAS cette card car elle
   utilise .card pas .card-hero. Du coup, son <picture> n'est pas relative et
   le .update-badge s'ancre sur .card (relative par défaut). En mobile la
   card est étroite → badge sur image ; en desktop la card est en grid 2 cols
   → badge en haut-droite de la zone TEXTE (col droite), ce qui rend bien sans
   surcharger la cover. À NE PAS modifier sans validation explicite. */

.update-badge {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  /* Capitalize standard (M majuscule, reste minuscule) : "Mise à jour"
     sans uppercase forcé. Décision user après test 2 séries de variantes :
     - série 1 G/H/I (avec glyphe ↻) écartée car ↻ Unicode rend mal
       cross-platform et ne ressort pas
     - série 2 J/K/L (texte seul) → J retenue ("Mise à jour" capitalize 13px)
       L'uppercase + letter-spacing fort de la version initiale faisait pâté */
  font-size: 0.8125rem; /* 13px */
  font-weight: 500;
  letter-spacing: 0.2px;
  padding: 6px 14px;
  border-radius: var(--radius-full);
  color: #ffffff;
  background-color: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

/* Variante inline : palier 19 adapté aux contextes où la cover image est
   trop petite pour accueillir un badge overlay sans masquer l'illustration
   (typique : .card-dossier zone Dossiers home, vignette à droite ~120px).
   Le badge devient un span inline qui s'insère dans le flow du card-meta
   à côté de la date. Taille réduite + sans backdrop-filter + sans box-shadow
   (qui ne servent pas en flow normal). Conserve le fond noir + bordure
   blanche subtile pour cohérence visuelle avec la version overlay.
   Feedback user 19/5. */
.update-badge--inline {
  position: static;
  display: inline-block;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  color: #ffffff;
  background-color: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  pointer-events: auto;
  vertical-align: middle;
}

/* ----- header.css ----- */
/* ==========================================================================
   Header — Sticky, logo typographique, nav, burger mobile
   ========================================================================== */

/* --- Header container --- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  height: var(--header-height);
  background-color: var(--color-dark-bg);
  transition: box-shadow var(--transition-base);
}

.site-header.scrolled {
  box-shadow: var(--shadow-header);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

/* --- Logo typographique --- */

.logo {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
  text-decoration: none;
  line-height: 1;
  flex-shrink: 0;
}

.logo:hover {
  color: inherit;
}

.logo__text {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-logo);
  font-size: 28px;
  color: #ffffff;
  letter-spacing: 0.3px;
}

/* Sur fond clair (footer clair éventuel) */
.logo--light .logo__text {
  color: #1e1e1e;
}

.logo__separator {
  display: inline-block;
  width: 18px;
  height: 2.5px;
  border-radius: 1.5px;
  background: var(--gradient-logo-separator);
  margin: 0 4px;
  flex-shrink: 0;
  vertical-align: middle;
}

.logo__accent {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading-bold);
  font-size: 36px;
  letter-spacing: 2px;
  background: linear-gradient(90deg, #6a1b9a 0%, #d81b60 60%, #e84570 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* --- Navigation desktop --- */

.nav {
  display: none;
  align-items: center;
  gap: var(--space-xl);
}

.nav__link {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-base);
  color: var(--color-text-on-dark-muted);
  transition: color var(--transition-fast);
  position: relative;
}

.nav__link:hover,
.nav__link.active {
  color: #ffffff;
}

.nav__link.active::after {
  content: '';
  position: absolute;
  bottom: -6px;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 1px;
  background: var(--gradient-accent-horizontal);
}

@media (min-width: 769px) {
  .nav {
    display: flex;
  }

  .burger {
    display: none !important;
  }
}

/* --- Burger mobile --- */

.burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.burger__line {
  display: block;
  width: 100%;
  height: 2px;
  background-color: #ffffff;
  border-radius: 1px;
  transition: transform var(--transition-base), opacity var(--transition-base);
}

.burger.open .burger__line:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.burger.open .burger__line:nth-child(2) {
  opacity: 0;
}

.burger.open .burger__line:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* --- Menu mobile --- */

.mobile-menu {
  display: none;
  position: fixed;
  top: var(--header-height);
  left: 0;
  right: 0;
  background-color: var(--color-dark-bg);
  padding: var(--space-xl) var(--container-padding);
  box-shadow: var(--shadow-lg);
  z-index: 999;
}

.mobile-menu.open {
  display: block;
}

.mobile-menu__link {
  display: block;
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-xl);
  color: var(--color-text-on-dark-muted);
  padding: var(--space-md) 0;
  border-bottom: 1px solid var(--color-dark-bg-elevated);
  transition: color var(--transition-fast);
}

.mobile-menu__link:hover,
.mobile-menu__link.active {
  color: #ffffff;
}

@media (min-width: 769px) {
  .mobile-menu {
    display: none !important;
  }
}

/* --- Placeholder hauteur min (éviter le saut avant injection JS) --- */

#site-header {
  min-height: var(--header-height);
}

/* ----- footer.css ----- */
/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  background-color: var(--color-dark-bg);
  color: var(--color-text-on-dark);
  padding-block: var(--space-3xl) var(--space-xl);
  /* Trait dégradé en haut du footer : sombre à gauche → rose à droite.
     Présent sur toutes les pages (s'applique au footer global, pas à la home
     uniquement). Restauré 2026-04-29 (avait été retiré par erreur dans
     le commit 9304f80, remplacé par un <hr> dans la home seulement). */
  border-top: 3px solid transparent;
  border-image: linear-gradient(90deg, #1e1e1e, #2a1040, #6a1b9a, #d81b60, #e84570) 1;
}

.site-footer__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

.site-footer__top {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  margin-bottom: var(--space-2xl);
}

@media (min-width: 600px) {
  .site-footer__top {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
  }
}

/* --- Logo dans le footer --- */

.site-footer .logo {
  flex-shrink: 0;
}

/* --- Navigation footer --- */

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xl);
}

.footer-nav__group h4 {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #ffffff;
  margin-bottom: var(--space-md);
}

.footer-nav__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.footer-nav__link {
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  transition: color var(--transition-fast);
}

.footer-nav__link:hover {
  color: #ffffff;
}

/* --- Brand block (logo + lien social standalone) --- */

.site-footer__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2xl);
}

/* --- Lien social en icône standalone (sous le logo) --- */

.footer-social-link {
  display: inline-flex;
  color: #ffffff;
  transition: color var(--transition-fast);
}

.footer-social-link:hover {
  color: var(--color-text-on-dark-muted);
}

.footer-social-link svg {
  width: 32px;
  height: 32px;
}

/* --- Bas du footer --- */

.site-footer__bottom {
  padding-top: var(--space-xl);
  border-top: 1px solid var(--color-dark-bg-elevated);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
}

@media (min-width: 600px) {
  .site-footer__bottom {
    flex-direction: row;
    justify-content: space-between;
  }
}

.site-footer__bottom a {
  color: var(--color-text-on-dark-muted);
  transition: color var(--transition-fast);
}

.site-footer__bottom a:hover {
  color: #ffffff;
}

/* ==========================================================================
   PALIERS v1-dark migrés depuis lab/v1-dark/dark.css (2026-05-19, Phase F)
   --------------------------------------------------------------------------
   Bloc absorbe les paliers 4, 8, 13 du sandbox dark.css.
   Les règles ci-dessous OVERRIDENT les définitions prod historiques plus
   haut dans ce fichier (CSS lit dans l'ordre).
   ========================================================================== */

/* --------------------------------------------------------------------------
   PALIER 4 — Zone Newsletter dans le footer
   --------------------------------------------------------------------------
   Reintegration du message "10 millions" supprime de la home + formulaire
   NL (single opt-in conforme RGPD : consent explicite, lien politique conf,
   desinscription 1 clic dans chaque mail). Honeypot anti-bots + Turnstile
   prevu pour la bascule prod.
   -------------------------------------------------------------------------- */

.footer-newsletter {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3xl);
  align-items: center;
  padding-block: var(--space-2xl);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: var(--space-2xl);
}

@media (max-width: 899px) {
  .footer-newsletter {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
}

/* ----- Pitch (gauche) : stat 10M + tagline ----- */

.footer-newsletter__stat {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.125rem, 2vw, 1.375rem);
  line-height: 1.35;
  color: #ffffff;
  margin-bottom: var(--space-sm);
}

.footer-newsletter__tagline {
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  line-height: 1.6;
  margin-bottom: 0;
}

/* ----- Form (droite) : titre + email + bouton + consent ----- */

.footer-newsletter__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.footer-newsletter__title {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.55);
  font-weight: 600;
  margin: 0;
}

/* Honeypot : cache aux humains (visuellement + lecteurs d'ecran via aria-hidden
   sur le wrapper). Position absolue hors viewport pour eviter les detections
   par bots qui regardent display:none. */
.footer-newsletter__honeypot {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Row : email + bouton cote a cote sur desktop, empile sur mobile */
.footer-newsletter__row {
  display: flex;
  gap: var(--space-sm);
}

@media (max-width: 599px) {
  .footer-newsletter__row {
    flex-direction: column;
  }
}

.footer-newsletter__input {
  flex: 1;
  padding: var(--space-sm) var(--space-md);
  background-color: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-md);
  color: #ffffff;
  font-family: var(--font-body);
  font-size: var(--text-base);
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.footer-newsletter__input::placeholder {
  color: rgba(255, 255, 255, 0.35);
}

.footer-newsletter__input:focus {
  outline: none;
  border-color: var(--color-accent-pink-light);
  background-color: rgba(255, 255, 255, 0.08);
}

.footer-newsletter__input:invalid:not(:placeholder-shown) {
  border-color: rgba(216, 27, 96, 0.6);
}

/* Bouton submit : gradient signature pour pousser l'inscription */
.footer-newsletter__submit {
  padding: var(--space-sm) var(--space-lg);
  background: var(--gradient-accent-horizontal);
  border: none;
  border-radius: var(--radius-md);
  color: #ffffff;
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-base);
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  white-space: nowrap;
}

.footer-newsletter__submit:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(216, 27, 96, 0.35);
}

.footer-newsletter__submit:active {
  transform: translateY(0);
}

/* Consent : checkbox + texte legal en petit gris */
.footer-newsletter__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
  line-height: 1.5;
  cursor: pointer;
}

.footer-newsletter__consent input[type="checkbox"] {
  flex-shrink: 0;
  margin-top: 2px;
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent-pink);
  cursor: pointer;
}

.footer-newsletter__consent a {
  color: var(--color-accent-pink-light);
  text-decoration: underline;
  text-decoration-color: rgba(232, 69, 112, 0.4);
}

.footer-newsletter__consent a:hover {
  color: #ffffff;
  text-decoration-color: #ffffff;
}

/* Message de retour (succès / erreur après soumission) */
.footer-newsletter__message {
  font-size: var(--text-sm);
  line-height: 1.5;
  margin: 0;
  min-height: 1.4em; /* évite le saut de layout quand le message apparait */
}

.footer-newsletter__message--success {
  color: #a3e8b1; /* vert subtil */
}

.footer-newsletter__message--error {
  color: #f7a3a3; /* rouge subtil */
}

/* Widget Turnstile : centrage + marge cohérente avec le reste du form */
.cf-turnstile {
  margin-block: var(--space-sm);
}

/* Helper sr-only standardise */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   PALIER 8 — Refonte footer 3 colonnes (2026-05-09)
   --------------------------------------------------------------------------
   Le palier 7 (zone newsletter dediee 2 colonnes au-dessus du footer) est
   abandonne au profit d'une structure unifiee 3 colonnes :

     [ Logo + baseline 10M ] [ Newsletter form ] [ Rubriques + Categories ]
                          [ Copyright + mentions + Bluesky ]

   Avantages : supprime le sapin de Noel (1 seul gradient utile dans le
   bandeau au lieu de 4-5 sources rose/violet), elimine le vide vertical,
   reequilibre le footer-bottom (Bluesky descendu en zone copyright).

   La "fine ligne grise claire" (border-bottom du .footer-newsletter de
   newsletter.css) disparait naturellement puisqu'on a sorti le form de
   ce wrapper dans le HTML sandbox.
   -------------------------------------------------------------------------- */

/* Layout 3 colonnes principal (desktop). Sur mobile, on retombe en stack
   vertical via media query plus bas. */
.site-footer__top--3col {
  display: grid;
  grid-template-columns: 1fr 1.5fr 1fr;
  gap: var(--space-2xl);
  align-items: start;
}

/* Brand reste en colonne mais on enleve le gap 2xl (qui creait un trou
   geant entre logo et Bluesky avant). Maintenant il n'y a plus que logo
   + baseline, gap modere. */
.site-footer__top--3col .site-footer__brand {
  gap: var(--space-md);
}

/* Baseline 10M sous le logo. Iteration finale (2026-05-11) : taille montee
   a 1.125rem (egalite avec titre form, presence renforcee pour la stat de
   social proof) MAIS max-width ramene a 28ch pour eviter que la baseline
   empiete sur la colonne form a sa droite. Compromis : 3 lignes courtes
   sous le logo (au lieu de 2 lignes qui debordent). */
.footer-brand-tagline {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.5;
  color: var(--color-text-on-dark-muted);
  margin: 0;
  max-width: 28ch;
}

.footer-brand-tagline .accent-gradient {
  background: var(--gradient-accent-horizontal);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  font-weight: 700;
  color: transparent;
}

/* Form newsletter au centre. Plus de wrapper .footer-newsletter, donc on
   redresse directement le form pour qu'il occupe sa colonne proprement. */
.site-footer__top--3col .footer-newsletter__form {
  margin: 0;
}

/* Title du form : style editorial. Taille montee de --text-base (16px) a
   ~18px pour qu'il ait un peu plus de presence visuelle, MAIS sans gradient
   sur "vendredi" (decision 2026-05-09 : le gradient devenait du bruit
   visuel sur un mot tout petit, et avec le 10M discret en baseline + le
   bouton CTA en gradient, on a deja les bons accents). */
.site-footer__top--3col .footer-newsletter__title {
  font-size: 1.125rem;
  text-transform: none;
  letter-spacing: normal;
  color: rgba(255, 255, 255, 0.92);
  font-weight: 600;
  font-family: var(--font-heading);
  line-height: 1.4;
  margin: 0;
}

/* Neutralisation du gradient sur "vendredi" dans le title (la regle generique
   .accent-gradient definie ailleurs ne nous touche pas vraiment ici, mais on
   force pour etre certains que le mot herite la couleur du title). */
.site-footer__top--3col .footer-newsletter__title .accent-gradient {
  background: none;
  -webkit-text-fill-color: inherit;
  color: inherit;
  font-weight: inherit;
}

/* Rapprocher tagline du title (sinon le gap: space-md du form les separe trop). */
.site-footer__top--3col .footer-newsletter__form .footer-newsletter__tagline {
  margin-top: calc(var(--space-md) * -0.6);
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
}

/* Nav 3e colonne : poussee au bord droit de sa cellule grid (justify-self:
   end) pour aerer entre form et nav. Gap 2xl pour separer Rubriques de
   Categories (au lieu du --space-xl precedent qui les serrait trop). */
.site-footer__top--3col .footer-nav {
  justify-self: end;
  gap: var(--space-2xl);
}

/* Bluesky descendu dans le bottom : on garde la taille visuelle du SVG
   mais on le pose en fin de la ligne copyright (justify-content:
   space-between herite de footer.css gere deja l'espacement). */
.site-footer__bottom .footer-social-link svg {
  width: 22px;
  height: 22px;
}

/* Bouton "S'inscrire" sous l'input. Iteration finale (2026-05-11) :
   - Input pleine largeur du form (confort de saisie)
   - Bouton a largeur NATURELLE (taille de son texte + padding, ~130px)
     aligne A DROITE sous l'input (equilibre visuel : son gradient violet/
     rose contrebalance le gradient "10 millions" de la baseline a gauche) */
.site-footer__top--3col .footer-newsletter__row {
  flex-direction: column;
  align-items: flex-end;
}

.site-footer__top--3col .footer-newsletter__input {
  width: 100%;
}

.site-footer__top--3col .footer-newsletter__submit {
  width: auto;
}

/* Mobile / tablette etroite : 1 col stack. */
@media (max-width: 899px) {
  .site-footer__top--3col {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }

  .footer-brand-tagline {
    max-width: none;
  }

  /* Override le justify-self: end qui colle la nav au bord droit en
     desktop : sur mobile on veut tout aligne a gauche comme le logo. */
  .site-footer__top--3col .footer-nav {
    justify-self: start;
  }
}

/* --------------------------------------------------------------------------
   PALIER 13 — Footer mobile : faire respirer (2026-05-14, premiere passe)
   --------------------------------------------------------------------------
   Audit user 14/5 : "rien ne respire". Diagnostic : footer tasse a
   l'interieur des blocs (gaps 8px entre liens, entre lignes footer
   bottom) ET vide aere entre blocs (~80px entre nav et copyright). Le
   rythme est inverse : ca etouffe ou cela.

   Premiere passe : on reinjecte du souffle DANS les blocs et on resserre
   les transitions ENTRE blocs (notamment le grand vide avant footer
   bottom).

   Scope : mobile only. Desktop fige selon consigne user.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
  /* Liens nav (Rubriques + Categories) : 8px -> 16px entre items */
  .footer-nav__list {
    gap: var(--space-md);
  }

  /* Footer base (copyright, mentions, Bluesky) : 8px -> 16px entre lignes
     + reduction du padding-top pour limiter le vide avant. */
  .site-footer__bottom {
    gap: var(--space-md);
    padding-top: var(--space-lg);
  }

  /* Site-footer mobile : le palier 8 met padding-top: 0 (suppose que
     .footer-newsletter gere l'air via son padding-block, mais le sandbox
     3-col n'a plus ce wrapper en mobile). Resultat : la barre gradient
     du border-top du footer colle au logo. On reinjecte 32px d'air. */
  .site-footer {
    padding-top: var(--space-xl);
  }

  /* Rythme entre blocs principaux (brand / form newsletter / nav) :
     Base = gap 48px parent, MAIS rythme decroissant via margins
     individuels pour compenser la hauteur variable du bloc brand
     selon viewport (baseline 10M tient sur 2 ou 3 lignes selon
     largeur). Resultat effectif :
       - brand -> form : 48 + 16 = 64px (compense densite brand block sur S24)
       - form  -> nav  : 48 - 16 = 32px (remonte la nav, moins "perdue" sur S25)
     L'oeil descend de "gros gap" -> "gap moyen" (rythme magazine).
     margin-bottom 48 -> 32 limite le vide avant footer bottom. */
  .site-footer__top {
    gap: var(--space-2xl);
    margin-bottom: var(--space-xl);
  }

  .site-footer__brand {
    margin-bottom: var(--space-md);
  }

  .site-footer__top--3col .footer-nav {
    margin-top: calc(-1 * var(--space-md));
  }
}

/* ----- newsletter.css ----- */
/* ==========================================================================
   Newsletter (zone footer)
   ==========================================================================
   Zone newsletter integree en haut du footer global. Pitch editorial a gauche
   + formulaire d'inscription a droite (desktop). Sur mobile (<900px), les
   deux colonnes s'empilent verticalement.

   Backend : Cloudflare Worker `compagnon-ai-api.y-holstein.workers.dev`
   - anti-bombing : honeypot + Turnstile + rate limit IP/email cote Worker
   - single opt-in, desinscription HMAC-SHA256
   ========================================================================== */

.footer-newsletter {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3xl);
  align-items: start;
  padding-block: var(--space-2xl);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: var(--space-2xl);
}

@media (max-width: 899px) {
  .footer-newsletter {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
}

/* ----- Pitch (gauche) : accroche editoriale ----- */

.footer-newsletter__stat {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.92);
  margin-bottom: var(--space-sm);
}

/* Highlight gradient signature pour le mot fort dans la stat (ex: "vendredi") */
.footer-newsletter__stat .accent-gradient {
  background: linear-gradient(90deg, #c084fc, #f472b6);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  font-weight: 700;
}

.footer-newsletter__tagline {
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  line-height: 1.6;
  margin-bottom: 0;
}

/* ----- Form (droite) : titre + email + bouton + consent ----- */

.footer-newsletter__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.footer-newsletter__title {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.55);
  font-weight: 600;
  margin: 0;
}

/* Honeypot : cache aux humains (visuellement + lecteurs d'ecran via aria-hidden
   sur le wrapper). Position absolue hors viewport pour eviter les detections
   par bots qui regardent display:none. */
.footer-newsletter__honeypot {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Row : email + bouton cote a cote sur desktop, empile sur mobile */
.footer-newsletter__row {
  display: flex;
  gap: var(--space-sm);
}

@media (max-width: 599px) {
  .footer-newsletter__row {
    flex-direction: column;
  }
}

.footer-newsletter__input {
  flex: 1;
  padding: var(--space-sm) var(--space-md);
  background-color: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-md);
  color: #ffffff;
  font-family: var(--font-body);
  font-size: var(--text-base);
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.footer-newsletter__input::placeholder {
  color: rgba(255, 255, 255, 0.35);
}

.footer-newsletter__input:focus {
  outline: none;
  border-color: var(--color-accent-pink-light);
  background-color: rgba(255, 255, 255, 0.08);
}

.footer-newsletter__input:invalid:not(:placeholder-shown) {
  border-color: rgba(216, 27, 96, 0.6);
}

/* Bouton submit : gradient signature pour pousser l'inscription */
.footer-newsletter__submit {
  padding: var(--space-sm) var(--space-lg);
  background: var(--gradient-accent-horizontal);
  border: none;
  border-radius: var(--radius-md);
  color: #ffffff;
  font-family: var(--font-heading);
  font-weight: var(--font-weight-body-semi);
  font-size: var(--text-base);
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  white-space: nowrap;
}

.footer-newsletter__submit:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(216, 27, 96, 0.35);
}

.footer-newsletter__submit:active {
  transform: translateY(0);
}

/* Consent : checkbox + texte legal en petit gris */
.footer-newsletter__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: var(--text-xs);
  color: var(--color-text-on-dark-muted);
  line-height: 1.5;
  cursor: pointer;
}

.footer-newsletter__consent input[type="checkbox"] {
  flex-shrink: 0;
  margin-top: 2px;
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent-pink);
  cursor: pointer;
}

.footer-newsletter__consent a {
  color: var(--color-accent-pink-light);
  text-decoration: underline;
  text-decoration-color: rgba(232, 69, 112, 0.4);
}

.footer-newsletter__consent a:hover {
  color: #ffffff;
  text-decoration-color: #ffffff;
}

/* Message de retour (succes / erreur apres soumission) */
.footer-newsletter__message {
  font-size: var(--text-sm);
  line-height: 1.5;
  margin: 0;
  min-height: 1.4em; /* evite le saut de layout quand le message apparait */
}

.footer-newsletter__message--success {
  color: #a3e8b1; /* vert subtil */
}

.footer-newsletter__message--error {
  color: #f7a3a3; /* rouge subtil */
}

/* Widget Turnstile : marge coherente avec le reste du form */
.cf-turnstile {
  margin-block: var(--space-sm);
}

/* ----- article.css ----- */
/* ==========================================================================
   Article — Styles spécifiques aux pages d'actu
   ========================================================================== */

/* --- En-tête article --- */

.article-header {
  margin-bottom: var(--space-2xl);
}

.article-header__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

/* Date muted : recede visuellement vs le titre, posture "metadata supportive". */
.article-header__meta time {
  color: var(--color-text-on-dark-muted);
}

.section--light .article-header__meta time {
  color: var(--color-text-on-light-muted);
}

/* Pill plus compact dans l'article-header (vs cards listing où le padding
   d'origine reste pertinent pour le contraste d'identification plateforme). */
.article-header__meta .card__tag {
  font-size: 11px;
  padding: 2px 8px;
}

.article-header__title {
  margin-bottom: var(--space-md);
}

.article-header__excerpt {
  font-size: var(--text-lg);
  color: var(--color-text-on-dark-muted);
  line-height: 1.6;
}

.section--light .article-header__excerpt {
  color: var(--color-text-on-light-muted);
}

/* --- Bloc papier (article sans sommaire) --- */

.article-paper {
  max-width: 900px;
  margin: var(--space-2xl) auto;
  background: var(--color-light-bg-alt);
  padding: 2.5rem 3rem 4rem;
  border-radius: var(--radius-card);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* --- Contenu article (prose) --- */

.article-content {
  max-width: none;
}

.article-content h2 {
  margin-top: var(--space-2xl);
  margin-bottom: var(--space-md);
}

/* Date complémentaire dans un H2 (ex: "Ember (27 mars)"), plus petite et discrète */
.article-content h2 .h2-date {
  font-size: 0.55em;
  font-weight: 400;
  color: var(--color-text-muted);
  margin-left: 0.5em;
  letter-spacing: normal;
  vertical-align: middle;
}

.article-content h3 {
  margin-top: var(--space-xl);
  margin-bottom: var(--space-sm);
}

.article-content p {
  margin-bottom: var(--space-md);
  line-height: 1.6;
}

/* Bold dans le corps d'article : 700 (vs 600 par défaut sur strong global)
   pour que les emphases ressortent vraiment, notamment les listes type
   "V3 : ... / V4 : ... / V5 : ..." où le label porte tout le sens. */
.article-content strong {
  font-weight: var(--font-weight-heading);
}

/* --- Liens dans le corps des articles (gras + accent rose) --- */

.article-content a {
  color: var(--color-accent-pink);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

.article-content a:hover,
.article-content a:focus-visible {
  color: var(--color-accent-pink-light);
  text-decoration-thickness: 2px;
}

/* --- Encart "Mise à jour" en tête d'article --- */

.article-content .article-update {
  margin-block: var(--space-xl);
  padding: var(--space-lg) var(--space-xl);
  background: linear-gradient(135deg, rgba(216, 27, 96, 0.06), rgba(106, 27, 154, 0.06));
  border-left: 3px solid var(--color-accent-pink);
  border-radius: var(--radius-md);
}

.article-content .article-update p {
  margin: 0;
  line-height: 1.7;
}

.article-content .article-update__label {
  display: inline-block;
  margin-right: 0.4em;
  font-weight: 800;
  background: linear-gradient(90deg, var(--color-accent-purple), var(--color-accent-pink), var(--color-accent-pink-light));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.article-content ul,
.article-content ol {
  margin-bottom: var(--space-md);
  padding-left: var(--space-xl);
}

.article-content ul {
  list-style: disc;
}

.article-content ol {
  list-style: decimal;
}

.article-content li {
  margin-bottom: var(--space-sm);
  line-height: 1.7;
}

.article-content blockquote {
  background-color: #2a2a3a;
  border-left: 3px solid transparent;
  border-image: linear-gradient(180deg, #6a1b9a, #e84570) 1;
  padding: var(--space-lg) var(--space-xl);
  margin-block: var(--space-xl);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-style: italic;
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.7;
}

.section--light .article-content blockquote {
  background-color: #f0edf5;
  color: var(--color-text-on-light-muted);
}

.article-content img {
  border-radius: var(--radius-md);
  margin-block: var(--space-lg);
}

/* --- Logo plateforme inline (dans H3, à côté du texte) --- */

/* Flexbox sur le H3 qui contient un logo : centre verticalement le logo
   et le texte peu importe la hauteur relative (cap-height vs x-height).
   Évite les ajustements optiques fragiles (vertical-align, margin). */
.article-content h3:has(.platform-logo) {
  display: flex;
  align-items: center;
  gap: 0.6em;
  /* Margin-top compensé pour les H3 avec logo : le logo (2em = ~38px)
     "dépasse" verticalement le texte H3 (~22px line-height) car le flex
     align-items: center centre les deux. → Le logo déborde de ~8px en
     haut et bas, ce qui visuellement TASSE l'espace entre le paragraphe
     précédent et le haut du logo. Compensation : 48px → 64px pour
     restaurer la respiration visuelle. Feedback user 19/5 ("nos marges
     fonctionnent texte à texte, mais avec le logo ça fausse les quotes"). */
  margin-top: 4rem;
}

.article-content h3 .platform-logo {
  /* Taille augmentée à 2em pour compenser la réduction font-size H3 par
     palier 14c v1-dark (24px → 19px). Donne un logo ~38px qui colle au
     rendu prod historique (cf capture référence user 19/5). Sans cette
     compensation, les logos étaient à ~25px (1.3em × 19px) = trop discrets
     dans un H3 d'identité plateforme. */
  width: 2em;
  height: 2em;
  flex-shrink: 0;
  object-fit: contain;
  /* CRITIQUE : neutralisation des margins parasites héritées de
     .article-content img (border-radius + margin-block lg de l'article.css
     ligne 178+) et surtout du palier 14b qui pose margin-top: 4rem +
     margin-bottom: 2.5rem sur toutes les <img> de la prose. Sans ce reset,
     les logos plateformes héritent de 64px + 40px de vide vertical autour
     d'eux dans le H3 → décalage massif que user a flag 19/5. */
  margin: 0;
  border-radius: 0; /* override .article-content img { border-radius: --radius-md } */
  /* Fallback alignement si :has() ne match pas (rare mais arrive sur
     vieux navigateurs). */
  vertical-align: middle;
}

/* --- Figures inline (captures écran, illustrations) --- */

.article-content figure {
  display: table; /* la figure shrink à la largeur de l'image, le figcaption hérite */
  margin-block: var(--space-xl);
  margin-inline: auto;
  max-width: 600px;
}

/* Captures écran inline (.article-screen) : pattern "habillage" simple
   sans figure/lightbox (décision 14/5). Même cap visuel que figure
   (600px max, centrée) pour pas occuper toute la largeur de prose qui
   donnerait l'effet "écran géant" sur une illustration de capture.
   User feedback 19/5 : 870px (prose full) trop grand pour ce type
   d'illustration. */
.article-content .article-screen {
  display: block;
  max-width: 600px;
  width: 100%;
  height: auto;
  margin-inline: auto;
  border-radius: var(--radius-md);
}

.article-content figure img {
  display: block;
  max-width: 100%;
  max-height: 400px;
  width: auto;
  height: auto;
  margin-block: 0;
  border-radius: var(--radius-md);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.article-content figcaption {
  display: table-caption;
  caption-side: bottom;
  margin-top: var(--space-sm);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-style: italic;
  line-height: 1.5;
  text-align: center;
}

/* --- Comparaison multi-images (token {{COMPARE: ...}}) ---
   2 ou 3 images côte à côte avec étiquette overlay (V3 / V4 / V5, etc.)
   et caption globale en bas. Cible un usage type "comparatif visuel"
   où le visiteur va cliquer chaque image pour la voir en grand
   via la lightbox. */
.article-content .article-compare {
  display: block;          /* override le display:table des figures simples */
  max-width: none;          /* laisse prendre toute la largeur du paper */
  margin-block: var(--space-xl);
}

.article-compare__grid {
  display: grid;
  gap: var(--space-md);
}

.article-compare--2 .article-compare__grid {
  grid-template-columns: repeat(2, 1fr);
}

.article-compare--3 .article-compare__grid {
  grid-template-columns: repeat(3, 1fr);
}

.article-compare__item {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Container relatif autour de l'img : ancre le label sur l'image elle-même
   (pas sur la cellule de grille, qui peut être plus haute si le ratio des
   images du compare diffère). */
.article-compare__media {
  position: relative;
}

.article-content .article-compare__item img {
  display: block;
  width: 100%;
  height: auto;
  max-height: none;
  margin-block: 0;
  border-radius: var(--radius-md);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.article-compare__label {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  background: rgba(0, 0, 0, 0.75);
  color: #ffffff;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  font-family: var(--font-heading);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-heading);
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

.article-compare__label--right {
  left: auto;
  right: var(--space-sm);
}

.article-compare > figcaption {
  display: block;
  caption-side: unset;
  margin-top: var(--space-md);
  text-align: center;
}

/* --- Mobile <600px : labels SOUS l'image au lieu d'overlay ---
   Sur petit écran avec grille 2 ou 3 colonnes, chaque image fait
   ~100-180px de large. Un label overlay avec fond noir bouffe trop
   de la zone visuelle. On le sort de l'image, sans fond, en gris
   discret. L'image reprend 100% de sa surface, le label reste lisible. */
@media (max-width: 599px) {
  .article-compare__label,
  .article-compare__label--right {
    position: static;
    display: block;
    margin-top: var(--space-xs);
    background: transparent;
    color: var(--color-text-on-light-muted);
    padding: 0;
    border-radius: 0;
    font-size: 11px;
    text-align: center;
    letter-spacing: 0.3px;
  }
}

/* --- Image principale article (hero magazine, dans la section sombre) ---
   Pattern type "magazine édito" : l'image vient APRÈS le titre/excerpt
   et fait office de transition entre le bloc sombre (header) et le bloc
   clair (paper avec body text). Position dans le HTML :
       <section class="section section--dark">
         <div class="container">
           <nav class="breadcrumbs">...</nav>
           <div class="article-header">...</div>
           <figure class="article-hero">
             <img src="cover.avif" ...>
           </figure>
         </div>
       </section>

   En desktop : centrée, max-width 900px (cohérence avec .article-paper).
   En mobile (<600px) : edge-to-edge (casse le container parent), pas de
   radius pour effet immersif.
*/
.article-hero {
  margin: 0 auto;
  max-width: 900px;
  border-radius: var(--radius-card) var(--radius-card) 0 0;  /* haut arrondi, bas plat */
  overflow: hidden;
  aspect-ratio: 21 / 9;  /* crop "cinéma" : les covers ont été composées pour ce ratio */
  box-shadow: var(--shadow-md);
}

.article-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (max-width: 599px) {
  .article-hero {
    margin-inline: calc(-1 * var(--container-padding));
    border-radius: 0;
  }
}

/* --- Fond gris pour section light contenant un article-paper --- */

.section--light:has(.article-paper) {
  background-color: #f0f0f5;
}

/* --- Articles liés (dans section--dark, pas de border-top) --- */

.related-articles {
  /* La section--dark apporte déjà le fond et la couleur de texte */
}

.related-articles h2 {
  margin-bottom: var(--space-xl);
}

/* --- Encart de série (lien part 1 ↔ part 2 dans une série d'articles) ---
   S'utilise comme <aside class="article-series"> à l'intérieur de
   .article-content. Style sobre : fond légèrement teinté, trait gradient
   à gauche, label discret + lien en accent violet. */

.article-series {
  margin: var(--space-2xl) 0;
  padding: 1rem 1.25rem;
  background: rgba(106, 27, 154, 0.05);
  border-left: 3px solid;
  border-image: linear-gradient(180deg, #6a1b9a, #d81b60) 1;
  border-radius: 0 4px 4px 0;
}

/* Quand l'encart est en première position de l'article (lien part 2 → part 1
   en tête), on retire la margin-top : le padding du paper donne déjà l'espace
   nécessaire avec le bord. La margin-bottom reste pour aérer le texte qui suit. */
.article-content > .article-series:first-child {
  margin-top: 0;
}

/* Symétrique : encart en dernière position (lien part 1 → part 2 en bas).
   La margin-top reste pour aérer le texte qui précède, on retire juste celle
   du bas qui doublonne avec le padding-bottom du paper. */
.article-content > .article-series:last-child {
  margin-bottom: 0;
}

.article-series__label {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-on-light-muted);
  margin: 0 0 0.25rem 0;
  font-weight: 600;
}

.article-series__link {
  margin: 0;
  font-weight: 600;
}

.article-series__link a {
  color: var(--color-accent-purple);
  text-decoration: none;
}

.article-series__link a:hover {
  text-decoration: underline;
}

/* ==========================================================================
   Mobile responsive — Axe 2 (article-paper allégée) + justification desktop
   Ajouté 2026-04-25 (chantier mobile)
   ========================================================================== */

/* --- Césure auto sur tous les écrans (aide la lisibilité même non justifié) --- */
.article-content p,
.article-content li {
  hyphens: auto;
  -webkit-hyphens: auto;
}

/* --- Justification du texte uniquement sur desktop (>=900px) ---
   Sur mobile/tablette la colonne est trop étroite : justifier en français
   crée des "rivières blanches" entre les mots (mots longs comme
   "intelligence", "compagnon", "personnalité"). On garde left-align en
   dessous de 900px, on justifie au-dessus avec hyphens auto pour le rendu
   "magazine" sans gaps. */
@media (min-width: 900px) {
  .article-content p,
  .article-content li {
    text-align: justify;
  }
}

/* --- Mode "lecture immersive" mobile (<600px) ---
   Pour le confort de lecture (notamment dyslexie) sur petit écran :
   - Section light passe de gris clair à blanc (carte invisible)
   - Container padding retiré (paper edge-to-edge)
   - Paper sans shadow ni radius (plus de "boîte")
   - Body text à 18px (vs 16, alignement Medium / NYT / Le Monde)
   Surface utile texte : 360 - 40 (.paper x2) = 320px (vs 216 d'origine, +48%). */
@media (max-width: 599px) {
  /* Fond de section blanc → la paper-card se fond dans le fond */
  .section--light:has(.article-paper) {
    background-color: var(--color-light-bg-alt);
  }

  /* Container ne rogne plus l'article : paper plein viewport */
  .section--light:has(.article-paper) > .container {
    padding-inline: 0;
  }

  /* Paper "invisible" : pas de shadow, pas de radius, marges nulles */
  .article-paper {
    padding: 1.5rem 1.25rem 2.5rem;
    margin-block: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* Texte article 18px pour le confort de lecture mobile */
  .article-content p,
  .article-content li {
    font-size: 1.125rem;
  }
}

/* ==========================================================================
   Espacement compact pour le pattern hero magazine
   (cover dans la section sombre, fait office de pont vers le paper)
   Ajouté 2026-04-25 (chantier mobile axe 3)
   ========================================================================== */

/* Quand la section sombre porte un .article-hero, son padding-bottom passe
   à 0 : l'image touche directement la section claire, plus de zone vide. */
.section--dark:has(.article-hero) {
  padding-bottom: 0;
}

/* La section claire qui suit immédiatement perd son padding-top pour la
   même raison. */
.section--dark:has(.article-hero) + .section--light {
  padding-top: 0;
}

/* Breadcrumbs dans la section sombre d'article : marge du bas réduite. */
.section--dark:has(.article-hero) .breadcrumbs {
  margin-bottom: var(--space-md);
}

/* Article-header (badge + date + h1 + excerpt) : marge du bas réduite
   quand suivi d'une article-hero. L'image ne nécessite pas un grand
   blanc avant elle. */
.article-header:has(+ .article-hero) {
  margin-bottom: var(--space-md);
}

/* Sur desktop, le paper-card peut perdre sa marge top puisque la section
   light commence pile sous l'image (plus de zone tampon). */
@media (min-width: 600px) {
  .section--light:has(.article-paper) > .container > .article-paper {
    margin-top: 0;
  }
}

/* Sur mobile, on resserre encore le padding-top de la section sombre
   (header est déjà très proche, pas besoin de 64px de respiration). */
@media (max-width: 599px) {
  .section--dark:has(.article-hero) {
    padding-top: var(--space-lg);
  }
}

/* Sur desktop, padding-top moyen (32px). */
@media (min-width: 600px) {
  .section--dark:has(.article-hero) {
    padding-top: var(--space-xl);
  }

  /* Continuité visuelle image → paper : le paper qui suit une article-hero
     n'a que ses coins du bas arrondis. Combiné au top arrondi de la hero,
     ça forme un seul "rectangle magazine" continu. */
  .section--dark:has(.article-hero) + .section--light .article-paper {
    border-radius: 0 0 var(--radius-card) var(--radius-card);
  }
}

/* ==========================================================================
   Pattern continuité : article-paper → related-section ("À lire aussi")
   Ajouté 2026-04-29.

   Sans ces règles, ~150-200px de vide entre la fin du paper et le titre
   "À lire aussi", qui faisait croire que l'article était terminé.
   On resserre via :has() comme pour le hero magazine.
   ========================================================================== */

/* La section light du paper perd son padding-bottom quand suivie de related */
.section--light:has(.article-paper):has(+ .related-section) {
  padding-bottom: 0;
}

/* Le paper lui-même perd sa margin-bottom (pour coller au bord de la section) */
.section--light:has(+ .related-section) .article-paper {
  margin-bottom: 0;
}

/* La section related démarre serrée, juste un padding modéré pour respiration */
.related-section {
  padding-top: var(--space-xl);
}

/* Titre "À lire aussi" : trait accent gradient à gauche (style magazine).
   Pattern Korben : marquer "nouvelle section" sans rompre la continuité. */
.related-section__title {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-xl);
  font-size: 1.5rem;
  line-height: 1.2;
}

.related-section__title::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 1.5em;
  background: var(--gradient-signature);
  border-radius: 2px;
  flex-shrink: 0;
}

/* ==========================================================================
   PALIERS v1-dark migrés depuis lab/v1-dark/dark.css (2026-05-19, Phase F)
   --------------------------------------------------------------------------
   Bloc absorbe les paliers article (5, 5b, 14, 14b, 14c, 15, 17, 18, 20)
   du sandbox dark.css. Les règles ci-dessous OVERRIDENT les définitions
   prod historiques plus haut dans ce fichier (CSS lit dans l'ordre).
   ========================================================================== */

/* --------------------------------------------------------------------------
   PALIER 5 — Article : mode lecture immersif full dark
   --------------------------------------------------------------------------
   Choix structurant valide user :
   - Paper invisible (#1e1e1e identique au fond) -> mode lecture pleine
     immersion, plus de "carte papier" qui flotte. Pattern Korben recent /
     blogs tech modernes / mode lecture immersive.
   - Texte off-white (#e0e0e0 = --color-text-on-dark) pour lecture longue
     duree confortable.
   - Font-size body 18px (1.125rem) desktop + mobile (deja 18px en mobile
     via article.css palier 4 d'avril). Convention FR/EU lecture longue
     dark : Korben 17.6px, Clubic 18px, Numerama 18px.
   - Image hero : encapsulee proprement (radius all corners + shadow plus
     marquee) pour ressortir comme element distinct sur fond dark.
   -------------------------------------------------------------------------- */

/* --- Section qui contient un article-paper : fond #1e1e1e (override le
   #f0f0f5 d'article.css). Specificite identique mais dark.css est apres
   main.css dans la cascade donc gagne. Aussi pour le mode mobile. */
.section--light:has(.article-paper) {
  background-color: #1e1e1e;
}

@media (max-width: 599px) {
  .section--light:has(.article-paper) {
    background-color: #1e1e1e;
  }
  .article-paper {
    background-color: #1e1e1e;
  }
}

/* --- Paper desktop : subtle nuance #252525 (vs fond extérieur #1e1e1e).
   Effet "Korben" valide user : carte qui flotte tres legerement sans casser
   l'immersion. Donne un effet "zone de lecture" delimitee subtilement.
   Mobile : reste #1e1e1e uniforme (paper edge-to-edge, pas de zone hors-paper
   visible, mode lecture immersif total sur petit ecran). */
.article-paper {
  background: #252525;
  color: var(--color-text-on-dark);
  box-shadow: none;
  border-radius: 0;
}

/* --- Continuite magazine : neutralise le radius bas du paper qui suit une
   image hero. Avec paper invisible, ce radius n'a plus de sens visuel. */
@media (min-width: 600px) {
  .section--dark:has(.article-hero) + .section--light .article-paper {
    border-radius: 0;
  }
}

/* --- Image hero : encapsulee proprement sur fond dark. Radius all corners
   + shadow plus marquee pour qu'elle ressorte comme element distinct
   (l'option a validee par le user en discussion). */
.article-hero {
  border-radius: var(--radius-card);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

/* --- Texte article body : 18px desktop (etait 16px), 1.6 line-height
   (deja dans article.css). Mobile a deja 18px (via palier mobile axe 2
   d'article.css du chantier mobile d'avril). */
@media (min-width: 600px) {
  .article-content p,
  .article-content li {
    font-size: 1.125rem;
  }
}

/* --- Headings article : couleur off-white pour ressortir sur fond dark. */
.article-content h2,
.article-content h3,
.article-content h4 {
  color: var(--color-text-on-dark);
}

/* --- Bold dans le corps : reste off-white (heritage du parent suffit
   normalement, mais on rend explicite). */
.article-content strong {
  color: var(--color-text-on-dark);
}

/* --- Liens article : test user proposition. Sur fond dark, le pink-light
   en couleur principale des liens etait trop voyant ("trop rose dans le
   contexte black"). On inverse : texte blanc au repos, hover en pink-light
   pour reveiller au survol.
   L'affordance "c'est un lien" reste garantie par le font-weight 600 +
   text-decoration: underline (deja dans article.css). */
.article-content a {
  color: #ffffff;
}

.article-content a:hover,
.article-content a:focus-visible {
  color: var(--color-accent-pink-light);
}

/* --- Blockquote : article.css a un mode dark par defaut + un override
   pour .section--light qui passe en clair. Avec paper invisible (toujours
   sur .section--light), il faut neutraliser cet override clair. */
.section--light .article-content blockquote {
  background-color: #2a2a3a;
  color: rgba(255, 255, 255, 0.75);
}

/* --- Article-header meta (date, excerpt) : article.css surcharge en
   color-text-on-light-muted sur .section--light. Inverser pour dark. */
.section--light .article-header__meta time {
  color: var(--color-text-on-dark-muted);
}

.section--light .article-header__excerpt {
  color: var(--color-text-on-dark-muted);
}

/* --- Wrapper article-magazine-top (palier 5d, option A) :
   Box magazine unique continue : breadcrumbs + article-header + article-hero
   dans une seule boite #252525. Le paper en dessous continue la boite via
   radius (haut plat ici, bas plat sur paper).
   Option A : image hero edge-to-edge horizontal (compensation du
   padding-inline) MAIS avec marges verticales equilibrees (32px en bas du
   wrapper pour matcher le 32px margin-bottom de l'article-header). */
.article-magazine-top {
  background-color: #252525;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  /* 48 haut, 48 droite, 32 bas, 48 gauche : symetrise les marges verticales
     autour de l'image hero (32 au-dessus via margin de l'header, 32 en bas
     via le padding bas du wrapper). */
  padding: var(--space-2xl) var(--space-2xl) var(--space-xl);
  max-width: 900px;
  margin: 0 auto;
}

/* Annule margin-bottom par defaut de l'article-header (article.css le met
   a 48px), on uniformise a 32px dans la box. */
.article-magazine-top .article-header {
  margin-bottom: var(--space-xl);
}

/* Image hero (option A) : edge-to-edge horizontal via margin negatif qui
   compense le padding-inline du wrapper. Retire radius/shadow propres
   (la box parent encadre). */
.article-magazine-top .article-hero {
  border-radius: 0;
  box-shadow: none;
  max-width: none;
  margin: 0 calc(-1 * var(--space-2xl));
  aspect-ratio: 21 / 9;  /* ratio cinema d'origine */
}

/* Continuite avec le paper : radius bas seulement (haut plat pour fondu
   avec le bas de la magazine-top). */
.section--dark:has(.article-magazine-top) + .section--light .article-paper {
  border-radius: 0 0 var(--radius-card) var(--radius-card);
  max-width: 900px;
}

@media (max-width: 599px) {
  .article-magazine-top {
    padding: var(--space-lg) var(--space-lg) var(--space-md);
    border-radius: 0;  /* mode immersif edge-to-edge sur mobile */
  }
  .article-magazine-top .article-hero {
    margin: 0 calc(-1 * var(--space-lg));
  }
}

/* --- Figure caption : couleur muted ambigue (--color-text-muted) en dark,
   on force off-white-muted. */
.article-content figcaption {
  color: var(--color-text-on-dark-muted);
}

/* --- Figures inline + COMPARE images : shadow plus marquee pour delimiter
   visuellement les images sur fond dark (la shadow d'origine est trop
   subtile en dark). */
.article-content figure img,
.article-content .article-compare__item img {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}

/* --- Article-series encart (lien part 1 ↔ part 2)
   Fond violet 5% etait invisible sur paper #252525 (mix donne ~#262433,
   trop proche du fond). On passe a 15% pour que le bloc soit visible
   tout en restant subtle. Label inverse pour dark. */
.article-content .article-series {
  background: rgba(106, 27, 154, 0.15);
}

.article-series__label {
  color: var(--color-text-on-dark-muted);
}

/* --- Article-update encart "Mise a jour" (anticipation pour Kindroid
   mars-avril ou tout article futur avec update). Meme probleme que
   article-series : fond gradient 6% opacite invisible sur #252525.
   On renforce a 15% chacun pour un effet subtle mais visible. */
.article-content .article-update {
  background: linear-gradient(
    135deg,
    rgba(216, 27, 96, 0.15),
    rgba(106, 27, 154, 0.15)
  );
}

/* --- Compare label mobile (sous l'image en mobile) : article.css le passe
   en color-text-on-light-muted, inverser pour dark. */
@media (max-width: 599px) {
  .article-compare__label,
  .article-compare__label--right {
    color: var(--color-text-on-dark-muted);
  }
}

/* --------------------------------------------------------------------------
   PALIER 5b — Neutralisation du hover pink global sur les liens de cards
   --------------------------------------------------------------------------
   base.css a un `a:hover { color: var(--color-accent-pink) }` global qui
   met tous les liens en pink classique #d81b60 au survol. Sur les titres
   de cards (home + related + listings), ce pink est trop agressif et
   degrade la lisibilite. Le hover de la card elle-meme (translateY + shadow
   accentuee) donne deja le feedback visuel suffisant.
   On neutralise donc le hover des liens DANS les cards en gardant la
   couleur d'origine du titre (off-white).
   -------------------------------------------------------------------------- */

/* Cards home (À LA UNE, Dernieres actus) */
.card-hero__title a:hover,
.card-hero__title a:focus-visible,
.card__title a:hover,
.card__title a:focus-visible,
/* Cards lead story (Guides + Tests featured + side) */
.card-list-item--featured-large .card-list-item__title a:hover,
.card-list-item--featured-large .card-list-item__title a:focus-visible,
.card-list-item--side:hover .card-list-item__title-side,
.card-list-item--side:focus-visible .card-list-item__title-side,
/* Cards Dossiers */
.card-dossier__title a:hover,
.card-dossier__title a:focus-visible,
/* Related cards (en bas d'article) */
.related-section .card a:hover,
.related-section .card a:focus-visible {
  color: var(--color-text-on-dark);
}

/* --------------------------------------------------------------------------
   PALIER 14 — Article layout 2 cols : prose gauche + sidebar droite
   (2026-05-17, desktop only)
   --------------------------------------------------------------------------
   Décision user 17/5 après essais option B/C "paper rétréci" : la zone
   "vide" autour du paper (effet colonnade) n'avait pas de raison d'être.
   Solution : occuper la largeur container 1200px (cohérence home) avec
   layout 2 cols dans le paper :
     - À GAUCHE : prose (.article-content, ~870px utiles)
     - À DROITE : sidebar (.article-sidebar, 280px sticky) destinée à
       maillage SEO (4 derniers contenus par type) + future pub + futur
       lien annuaire des plateformes

   Sidebar à droite (convention web LTR) plutôt que gauche pour ne pas
   interrompre le flux de lecture. Pubs à droite seulement (= non intrusif).

   Le wrapper .article-magazine-top reste à 1200px (cohérence) mais son
   contenu textuel (breadcrumbs + h1 + meta) reste centré à 900px max
   (lisibilité titre). L'image hero s'étend en pleine largeur 1200px.

   Mobile non touché : conserve le mode immersif edge-to-edge existant.
   Sidebar masquée < 900px (mode lecture pur).
   -------------------------------------------------------------------------- */

@media (min-width: 600px) {
  /* Wrapper magazine élargi à la largeur du container (1200px) */
  .article-magazine-top {
    max-width: none;
  }

  /* Contenu textuel du magazine top centré à 900px (lisibilité h1) */
  .article-magazine-top .breadcrumbs,
  .article-magazine-top .article-header {
    max-width: 900px;
    margin-inline: auto;
  }

  /* Paper élargi à largeur container + layout grid 2 cols prose + sidebar */
  .section--dark:has(.article-magazine-top) + .section--light .article-paper {
    max-width: none;
    display: grid;
    grid-template-columns: 1fr 280px;
    gap: var(--space-2xl); /* 48px entre prose et sidebar */
  }

  /* Prose : occupe la 1ère colonne (~870px utiles). On retire le centrage
     forcé à 900px qui n'a plus de sens dans un layout grid contraint. */
  .article-paper > .article-content {
    max-width: none;
    min-width: 0; /* prévient overflow horizontal du grid item */
  }

  /* Sidebar sticky sous le header (qui est lui-même sticky). Visible tout
     au long de la lecture. */
  .article-paper > .article-sidebar {
    position: sticky;
    top: calc(var(--header-height) + var(--space-md));
    align-self: start; /* requis pour sticky en grid item */
  }
}

/* Sidebar : styles communs (mobile + desktop).
   Gap entre sections (Derniers contenus / Espace réservé) : 40px
   (--space-2xl + qq) pour vraie séparation visuelle. */
.article-sidebar {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.article-sidebar__title {
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.55);
  margin: 0 0 var(--space-sm);
  font-weight: 600;
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.article-sidebar__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg); /* 24px : respiration entre items (pattern Verge) */
}

.article-sidebar__list li {
  margin: 0;
}

.article-sidebar__list a {
  display: block;
  color: var(--color-text-on-dark);
  text-decoration: none;
  line-height: 1.4;
  font-size: 0.9375rem;
  transition: color var(--transition-fast);
}

.article-sidebar__list a:hover {
  /* Palier 17 — hover en magenta intermédiaire (cohérent avec sidebar tag).
     Rose --pink-light "too much" sur éléments structurants. */
  color: var(--color-accent-magenta);
}

.article-sidebar__list .sidebar-tag {
  /* PALIER 17 — Couleur sidebar tag (2026-05-17, retour user soirée)
     -------------------------------------------------------------------
     Tag sur sa propre ligne (block) + taille plus grosse :
     bascule la hiérarchie visuelle → tag devient l'accroche, titre
     devient le détail.

     Historique des essais (rejetés) :
     - rose --pink-light (#e84570) : "trop fort", "too much" en gros
     - blanc #fff (essai 1) : "pas terrible", manque de couleur de marque
     - violet --accent-purple (#6a1b9a) : "pas top", trop sombre
     - D #9d4edd violet éclairci : trop "néon", sort du gradient
     - F #b8336e rose désaturé : retenu en v1 puis user bascule (recul)

     Choix retenu (v2) : E = magenta point-milieu #a01a7e, vrai magenta
     franc à mi-chemin entre violet et rose dans le gradient signature.
     "Plus dans nos couleurs" selon user. Référencé via la variable
     --color-accent-magenta pour pouvoir réutiliser ailleurs (liens body
     palier 18, hover sidebar liens, futurs accents structurels).

     Règle générale : rose --pink-light réservé aux petites touches
     (fil d'ariane, accents ponctuels), pas pour structurer. */
  display: block;
  font-size: 1rem; /* 16px (au lieu de 0.6875rem = 11px) */
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--color-accent-magenta);
  font-weight: 700;
  margin-bottom: 6px;
}

/* Placeholder zone pub future : caché en prod jusqu'à avoir du contenu réel.
   À RÉACTIVER : retirer `display: none` quand on a du contenu pub ou autre
   à mettre. Le markup HTML reste en place dans les articles via
   build_sidebar_html (new-article.py) + patch-articles-v1-dark.py. */
.article-sidebar__ad-slot {
  display: none; /* À retirer quand contenu réel dispo */
  margin-top: var(--space-lg);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-md);
  text-align: center;
  font-size: 0.75rem;
  color: var(--color-text-on-dark-muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}

/* Mobile : sidebar masquée (mode lecture pur < 900px) */
@media (max-width: 899px) {
  .article-sidebar {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   PALIER 14b — Respiration prose article desktop (2026-05-17)
   --------------------------------------------------------------------------
   Audit user 17/5 (références Verge + Clubic) : la prose article paraît
   tassée. On augmente les marges verticales des éléments structurants.

   Asymétrie h2 préservée : plus d'air AVANT le h2 (pour bien marquer la
   transition de section) que APRÈS (= titre lié à son paragraphe suivant).
   -------------------------------------------------------------------------- */

@media (min-width: 600px) {
  /* Paragraphes : 16 -> 20px de margin-bottom */
  .article-content p {
    margin-bottom: 1.25rem;
  }

  /* H2 : margin-top 48 -> 64px (vraie respiration avant section)
     margin-bottom 16 -> 20px (asymétrie préservée). */
  .article-content h2 {
    margin-top: 4rem;
    margin-bottom: 1.25rem;
  }

  /* H3 : margin-top 32 -> 48px ET margin-bottom 8 -> 16px.
     - Le 8px d'article.css convenait quand H3 était à 24px (gros poids
       visuel). Avec H3 réduit à 19px (palier 14c), 8px devient trop serré
       sous le H3. → 16px (--space-md) redonne sa fonction "sous-titre".
     - Le 32px de margin-top (hérité de --space-xl ligne 82) tassait les
       H3 quand ils séparent des sections plateforme distinctes (cf
       feedback user 19/5 "un peu trop tassé"). → 48px (--space-2xl) pour
       mieux détacher chaque section H3 du paragraphe qui précède. */
  .article-content h3 {
    margin-top: var(--space-2xl);
    margin-bottom: var(--space-md);
  }

  /* Images / figures / grilles COMPARE : asymétrie volontaire. 64px
     AU-DESSUS (décolle bien de la prose qui précède) et 40px EN DESSOUS
     (reste lié à la légende ou au paragraphe suivant). Validation user 17/5.

     Note spécificité (correctif 17/5) : .article-content .article-compare
     (spec 0,2,0) battait .article-content figure (spec 0,1,1) hérité de
     article.css ligne 237 (margin-block: 32px). On l'inclut explicitement
     dans le sélecteur pour que toutes les illustrations reçoivent le
     même rythme. */
  .article-content img,
  .article-content figure,
  .article-content .article-compare {
    margin-top: 4rem;
    margin-bottom: 2.5rem;
  }
}

/* --------------------------------------------------------------------------
   PALIER 14c — Hiérarchie typo H2/H3 article compressée (2026-05-17)
   --------------------------------------------------------------------------
   Décision user 17/5 : avec les marges d'images généreuses, l'espace blanc
   fait déjà le travail de hiérarchie visuelle → on baisse le contraste
   typographique des titres (pattern Medium/Substack mode immersif).

     H2 : 32px → 24px (= taille H3 actuelle, --text-2xl)
     H3 : 24px → 20px (intermédiaire H3-actuel/P, --text-xl)

   Le contraste visuel reste assuré par le font-weight (H2 bold, H3 semi-bold)
   pour préserver la fonction "navigation visuelle" du H2 au scan.

   Scope : desktop only (>=900px = breakpoint où base.css définit les tailles
   grandes). Mobile non touché.
   -------------------------------------------------------------------------- */

@media (min-width: 900px) {
  .article-content h2 {
    font-size: var(--text-2xl); /* 24px (au lieu de --text-3xl 32px) */
  }

  .article-content h3 {
    /* 19px : un cran sous 20 (--text-xl). Validation user 17/5 : à 20 le H3
       paraissait encore trop proche du H2 24, à 18 (= taille texte) on
       perdait la fonction sous-titre. 19px = compromis lisible. */
    font-size: 1.1875rem;
  }
}

/* --------------------------------------------------------------------------
   PALIER 15 — Article mobile : feuille pleine largeur (2026-05-17)
   --------------------------------------------------------------------------
   Audit user 17/5 sur S24 : l'article mobile gardait ~24px de marge
   latérale autour du wrapper magazine-top + image hero, alors que la home
   mobile (palier 10) a réduit ses marges à 12px sur les cards. Manque de
   cohérence + texte article trop étriqué sur petits écrans.

   Pattern cible (Korben/Le Monde/Verge mobile) :
   - Wrapper magazine + paper occupent toute la largeur viewport (edge-to-edge)
   - Image hero touche franchement les bords écran
   - Texte interne (breadcrumbs, h1, meta, excerpt, prose) avec 16px de
     padding interne → un peu d'air sans étouffer

   Note : la section paper avait déjà son container à padding-inline: 0 en
   mobile (article.css ligne 474). Le palier 15 fait pareil pour la section
   magazine-top + réduit les paddings internes pour cohérence.
   -------------------------------------------------------------------------- */

@media (max-width: 599px) {
  /* Container de la section magazine : 0 padding-inline → wrapper pleine
     largeur viewport. */
  .section--dark:has(.article-magazine-top) > .container {
    padding-inline: 0;
  }

  /* Magazine-top : padding interne 24 -> 16px latéral. Override le palier
     5d mobile qui mettait var(--space-lg) = 24px. */
  .article-magazine-top {
    padding-inline: var(--space-md);
  }

  /* Image hero : margin négatif réduit à -16px pour annuler le nouveau
     padding-inline du magazine-top → edge-to-edge total. */
  .article-magazine-top .article-hero {
    margin-inline: calc(-1 * var(--space-md));
  }

  /* Paper : padding latéral 20 -> 16px pour cohérence avec le magazine-top.
     Override article.css ligne 480 (1.5rem 1.25rem 2.5rem). */
  .article-paper {
    padding-left: var(--space-md);
    padding-right: var(--space-md);
  }
}

.article-sidebar {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.article-sidebar__title {
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: rgba(255, 255, 255, 0.55);
  margin: 0 0 var(--space-sm);
  font-weight: 600;
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.article-sidebar__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg); /* 24px : respiration entre items (pattern Verge) */
}

.article-sidebar__list li {
  margin: 0;
}

.article-sidebar__list a {
  display: block;
  color: var(--color-text-on-dark);
  text-decoration: none;
  line-height: 1.4;
  font-size: 0.9375rem;
  transition: color var(--transition-fast);
}

.article-sidebar__list a:hover {
  /* Palier 17 — hover en magenta intermédiaire (cohérent avec sidebar tag).
     Rose --pink-light "too much" sur éléments structurants. */
  color: var(--color-accent-magenta);
}

.article-sidebar__list .sidebar-tag {
  /* PALIER 17 — Couleur sidebar tag (2026-05-17, retour user soirée)
     -------------------------------------------------------------------
     Tag sur sa propre ligne (block) + taille plus grosse :
     bascule la hiérarchie visuelle → tag devient l'accroche, titre
     devient le détail.

     Historique des essais (rejetés) :
     - rose --pink-light (#e84570) : "trop fort", "too much" en gros
     - blanc #fff (essai 1) : "pas terrible", manque de couleur de marque
     - violet --accent-purple (#6a1b9a) : "pas top", trop sombre
     - D #9d4edd violet éclairci : trop "néon", sort du gradient
     - F #b8336e rose désaturé : retenu en v1 puis user bascule (recul)

     Choix retenu (v2) : E = magenta point-milieu #a01a7e, vrai magenta
     franc à mi-chemin entre violet et rose dans le gradient signature.
     "Plus dans nos couleurs" selon user. Référencé via la variable
     --color-accent-magenta pour pouvoir réutiliser ailleurs (liens body
     palier 18, hover sidebar liens, futurs accents structurels).

     Règle générale : rose --pink-light réservé aux petites touches
     (fil d'ariane, accents ponctuels), pas pour structurer. */
  display: block;
  font-size: 1rem; /* 16px (au lieu de 0.6875rem = 11px) */
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--color-accent-magenta);
  font-weight: 700;
  margin-bottom: 6px;
}

/* Placeholder zone pub future : caché en prod jusqu'à avoir du contenu réel.
   À RÉACTIVER : retirer `display: none` quand on a du contenu pub ou autre
   à mettre. Le markup HTML reste en place dans les articles via
   build_sidebar_html (new-article.py) + patch-articles-v1-dark.py. */
.article-sidebar__ad-slot {
  display: none; /* À retirer quand contenu réel dispo */
  margin-top: var(--space-lg);
  padding: var(--space-md);
  background: rgba(255, 255, 255, 0.02);
  border: 1px dashed rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-md);
  text-align: center;
  font-size: 0.75rem;
  color: var(--color-text-on-dark-muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}

/* Mobile : sidebar masquée (mode lecture pur < 900px) */
@media (max-width: 899px) {
  .article-sidebar {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   PALIER 18 — Liens corps article (2026-05-17 retour user soir, v3)
   --------------------------------------------------------------------------
   Pattern The Verge / NYT en référence : repos neutre au max (texte
   souligné couleur héritée du body), tout le poids visuel passe sur le
   hover qui révèle un effet "stabilo" highlight animé avec la couleur
   de marque.

   Itérations :
   - v1 (rejeté user) : magenta+bold au repos, hover juste underline 2px
     → trop d'attention sur les liens au repos, casse la lecture
   - v2 (rejeté user) : repos neutre OK mais hover = fond plein magenta
     → fond rectangle qui couvre tout le texte = trop brut visuellement
   - v3 (référence Verge) : repos neutre, hover = stabilo animé
     (background-image gradient qui glisse de gauche à droite, ne couvre
     que la moitié basse du texte → vraie sensation de surligneur fluo)

   Technique : background-image avec linear-gradient couleur uniforme
   posé en bottom-left, animé via background-size 0% → 100% (largeur).
   Hauteur 45% (un peu sous la moitié) pour rester sous la x-height des
   minuscules et donner l'illusion "surligneur authentique" qui passerait
   un peu en-dessous de la ligne de base.

   Animation 280ms ease : assez rapide pour ne pas faire attendre, assez
   lente pour qu'on perçoive le geste "peinture".

   Mobile/tactile : pas de hover, le lien reste neutre souligné. OK :
   sur mobile l'utilisateur tape pour suivre, pas besoin d'effet
   anticipatoire. :focus-visible déclenche aussi l'effet pour navigation
   clavier.
   -------------------------------------------------------------------------- */

.article-content a {
  color: inherit; /* couleur du <p> parent : #e0e0e0 sur dark */
  font-weight: inherit; /* pas de bold, le souligné suffit */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  background-image: linear-gradient(
    var(--color-accent-magenta),
    var(--color-accent-magenta)
  );
  background-size: 0% 45%;
  background-position: left bottom;
  background-repeat: no-repeat;
  transition: background-size 0.28s ease,
              text-decoration-color 0.28s ease;
}

.article-content a:hover,
.article-content a:focus-visible {
  /* color: inherit override la règle prod article.css ligne 111 qui force
     --pink-light au hover. Décision user : le texte garde sa couleur body
     d'origine (#e0e0e0), l'effet stabilo magenta se suffit à lui-même. */
  color: inherit;
  background-size: 100% 45%; /* l'animation glisse jusqu'à pleine largeur */
  text-decoration-color: transparent; /* le trait disparaît dans le stabilo */
}

/* --------------------------------------------------------------------------
   PALIER 20 — Tableau dark (.article-table) (2026-05-18)
   --------------------------------------------------------------------------
   Premier style dédié aux tableaux markdown rendus par new-article.py
   (parser tables MD GitHub-flavored, en working tree depuis 8/5, sera
   commité avec la publi dossier V2 du jour).

   Structure générée par md_to_html() :
     <div class="article-table">
       <table>
         <thead><tr><th>...</th></tr></thead>
         <tbody><tr><td>...</td></tr></tbody>
       </table>
     </div>

   Choix de design dark dominant :
   - Cellules sur fond #252525 (un cran plus clair que le paper #1e1e1e,
     lisible mais ne sort pas du registre dark)
   - Header row plus marqué via background-color + font-weight 600
   - Border subtile entre cellules (rgba(255,255,255,0.08), cohérent
     avec le palier card border posé 14/5)
   - Padding généreux pour la respiration (8-12px V, 14-18px H)
   - Mobile : overflow-x scroll automatique + min-width sur la table
     pour forcer le scroll horizontal quand le viewport est trop étroit
     (cas typique : tableau 6 colonnes du dossier comparatif sur S24)
   - Margin block 2.5rem pour aérer le tableau du texte autour
     (cohérent avec le rythme images palier 14b)
   -------------------------------------------------------------------------- */

.article-content .article-table {
  margin-block: 2.5rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Indicateur visuel de scroll possible : gradient subtil sur le bord droit
     qui s'estompe quand on a tout scrollé (via background-attachment local) */
  background:
    linear-gradient(to right, transparent, transparent),
    linear-gradient(to right, transparent, rgba(255, 255, 255, 0.05)),
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.4), transparent);
  background-position: 0 0, 100% 0, 100% 0;
  background-repeat: no-repeat;
  background-size: 20px 100%, 20px 100%, 14px 100%;
  background-attachment: local, scroll, scroll;
}

.article-content .article-table table {
  width: 100%;
  min-width: 600px; /* force scroll-x si viewport < 600px */
  /* Pattern "tuiles" type CC console (inspiration directe user 18/5) :
     chaque cellule a son propre fond, des gaps fins entre cellules
     laissent passer le fond paper derrière → effet bulle/tuile. */
  border-collapse: separate;
  border-spacing: 3px;
  background-color: transparent;
  font-size: 0.9375rem; /* 15px, légèrement plus petit que body */
  line-height: 1.5;
}

.article-content .article-table th,
.article-content .article-table td {
  padding: 14px 16px;
  text-align: left;
  vertical-align: middle; /* centrage vertical pour cellules wrap (texte 2 lignes) */
  color: var(--color-text-on-dark);
  background-color: #2a2a2a; /* fond de tuile cellule corps */
  border: none;
  border-radius: 3px; /* effet "vraies tuiles" léger, pas d'arrondi excessif */
}

.article-content .article-table thead th {
  background-color: #3a3a3a; /* header franc, contraste net avec corps #2a2a2a */
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  font-size: 0.8125rem; /* 13px : header dense */
  color: #ffffff;
}

/* Première colonne : nom de plateforme/d'entrée principale.
   Taille augmentée (1rem au lieu de 0.9375rem hérité) + gras pour vraiment
   dominer la cellule comme "accroche" de ligne. L'uppercase letter-spacing
   du header crée une fausse présence visuelle qu'il faut contrebalancer. */
.article-content .article-table tbody td:first-child {
  font-size: 1rem; /* 16px (au lieu de 15px hérité) */
  font-weight: 600;
  color: #ffffff;
}

/* Liens dans les cellules : font-weight 500 pour appui + couleur magenta
   éclaircie pour ressortir sur fond sombre serré. Réactive l'effet stabilo
   du palier 18 (sur les noms courts type plateforme, ça passe bien). */
.article-content .article-table a {
  color: var(--color-accent-magenta-light);
  font-weight: 700; /* bold franc pour ressortir comme accroche de ligne */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  /* Stabilo réactivé : même pattern que palier 18 mais utilise la couleur
     éclaircie (cohérent avec le contraste de fond du tableau) */
  background-image: linear-gradient(
    var(--color-accent-magenta-light),
    var(--color-accent-magenta-light)
  );
  background-size: 0% 45%;
  background-position: left bottom;
  background-repeat: no-repeat;
  transition: background-size 0.28s ease,
              text-decoration-color 0.28s ease;
}

.article-content .article-table a:hover,
.article-content .article-table a:focus-visible {
  color: inherit; /* le texte garde sa couleur de cellule, l'effet stabilo
                     prend le relais (cohérent palier 18) */
  background-size: 100% 45%;
  text-decoration-color: transparent;
}

/* ----- guide.css ----- */
/* ==========================================================================
   Guide — TOC sticky, sections structurées
   ========================================================================== */

/* --- Layout guide (contenu + sidebar TOC) --- */

.guide-layout {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .guide-layout {
    grid-template-columns: 1fr 260px;
  }
}

/* --- Table des matières --- */

.toc {
  background-color: var(--color-dark-bg-elevated);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  margin-bottom: var(--space-xl);
}

@media (min-width: 900px) {
  .toc {
    position: sticky;
    top: calc(var(--header-height) + var(--space-lg));
    align-self: start;
    margin-bottom: 0;
  }
}

.section--light .toc {
  background-color: #ffffff;
  border: 1px solid #e0e0e0;
}

.toc__title {
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-heading);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: var(--space-md);
  color: #ffffff;
}

.section--light .toc__title {
  color: var(--color-text-on-light);
}

.toc__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.toc__link {
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  transition: color var(--transition-fast);
  line-height: 1.4;
}

.toc__link:hover {
  color: var(--color-accent-pink-light);
}

.section--light .toc__link {
  color: var(--color-text-on-light-muted);
}

.section--light .toc__link:hover {
  color: var(--color-accent-purple);
}

/* --- Contenu guide (prose enrichie) --- */

.guide-content h2 {
  margin-top: var(--space-3xl);
  margin-bottom: var(--space-md);
  padding-top: var(--space-lg);
}

.guide-content h2:first-child {
  margin-top: 0;
  padding-top: 0;
}

.guide-content h3 {
  margin-top: var(--space-xl);
  margin-bottom: var(--space-sm);
}

.guide-content p {
  margin-bottom: var(--space-md);
  line-height: 1.8;
  max-width: 720px;
}

.guide-content ul,
.guide-content ol {
  margin-bottom: var(--space-md);
  padding-left: var(--space-xl);
  max-width: 720px;
}

.guide-content ul {
  list-style: disc;
}

.guide-content ol {
  list-style: decimal;
}

.guide-content li {
  margin-bottom: var(--space-sm);
  line-height: 1.7;
}

/* --- Callout / encadré conseil --- */

.guide-callout {
  background-color: rgba(106, 27, 154, 0.1);
  border-left: 3px solid var(--color-accent-purple);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--space-lg);
  margin-block: var(--space-xl);
  max-width: 720px;
}

.guide-callout__title {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  font-size: var(--text-sm);
  color: var(--color-accent-purple);
  margin-bottom: var(--space-sm);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.section--dark .guide-callout {
  background-color: rgba(106, 27, 154, 0.15);
}

.section--dark .guide-callout__title {
  color: var(--color-accent-pink-light);
}

/* ----- overlays.css ----- */
/* ==========================================================================
   Overlays — Bannière cookies RGPD + Age gate 18+
   ========================================================================== */

/* --------------------------------------------------------------------------
   Bannière cookies RGPD
   -------------------------------------------------------------------------- */

.cookie-banner {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 8000;
  background-color: var(--color-dark-bg);
  border-top: 1px solid var(--color-dark-bg-elevated);
  padding: var(--space-lg) var(--container-padding);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.4);
}

@media (min-width: 769px) {
  .cookie-banner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xl);
  }
}

.cookie-banner__text {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--color-text-on-dark-muted);
  line-height: 1.6;
  margin: 0;
  flex: 1;
}

.cookie-banner__link {
  color: var(--color-accent-pink-light);
  text-decoration: underline;
  margin-left: var(--space-xs);
  white-space: nowrap;
  transition: color var(--transition-fast);
}

.cookie-banner__link:hover {
  color: #ffffff;
}

.cookie-banner__actions {
  display: flex;
  gap: var(--space-sm);
  flex-shrink: 0;
  flex-wrap: wrap;
}

/* --------------------------------------------------------------------------
   Age gate 18+
   -------------------------------------------------------------------------- */

.age-gate {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background-color: rgba(30, 30, 30, 0.97);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xl) var(--container-padding);
  overflow: hidden;
}

.age-gate__box {
  background-color: var(--color-dark-bg-alt);
  border: 1px solid var(--color-dark-bg-elevated);
  border-radius: var(--radius-lg);
  padding: var(--space-3xl) var(--space-2xl);
  max-width: 540px;
  width: 100%;
  text-align: center;
  box-shadow: 0 8px 48px rgba(0, 0, 0, 0.6);
}

/* Mini logo dans l'age gate */
.age-gate__logo {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
  margin-bottom: var(--space-xl);
  line-height: 1;
}

.age-gate__logo .logo__text {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-logo);
  font-size: 22px;
  color: #ffffff;
  letter-spacing: 0.3px;
}

.age-gate__logo .logo__separator {
  display: inline-block;
  width: 14px;
  height: 2px;
  border-radius: 1px;
  background: linear-gradient(90deg, #6a1b9a, #e84570);
  margin: 0 3px;
  flex-shrink: 0;
  vertical-align: middle;
}

.age-gate__logo .logo__accent {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading-bold);
  font-size: 28px;
  letter-spacing: 2px;
  background: linear-gradient(90deg, #6a1b9a 0%, #d81b60 60%, #e84570 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.age-gate__title {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading-bold);
  font-size: var(--text-xl);
  color: #ffffff;
  margin: 0 0 var(--space-md);
}

.age-gate__text {
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-text-on-dark-muted);
  line-height: 1.7;
  margin: 0 0 var(--space-2xl);
}

.age-gate__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  align-items: center;
}

@media (min-width: 480px) {
  .age-gate__actions {
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
  }
}

/* --------------------------------------------------------------------------
   Lightbox — image fullscreen au click sur une figure d'article
   -------------------------------------------------------------------------- */

.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(0, 0, 0, 0.95);
  align-items: center;
  justify-content: center;
  padding: var(--space-md);
}

.lightbox--open {
  display: flex;
}

/* Quand la lightbox est ouverte, on cache le header sticky.
   Le bg lightbox 0.95 laisse passer 5% et le logo blanc transparaissait
   par-dessus l'image (visible surtout à luminosité écran haute). */
body.lightbox-active .site-header {
  visibility: hidden;
}

.lightbox__img {
  max-width: 95vw;
  max-height: 95vh;
  object-fit: contain;
  display: block;
  user-select: none;
}

.lightbox__btn {
  position: absolute;
  background: rgba(0, 0, 0, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #ffffff;
  font-family: var(--font-heading);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.5rem 0.85rem;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast);
  z-index: 1;
}

.lightbox__btn:hover,
.lightbox__btn:focus-visible {
  background: rgba(0, 0, 0, 0.85);
  outline: none;
}

.lightbox__close { top: 1rem; right: 1rem; }
.lightbox__prev  { left: 1rem;  top: 50%; transform: translateY(-50%); }
.lightbox__next  { right: 1rem; top: 50%; transform: translateY(-50%); }

.lightbox__counter {
  position: absolute;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 1px;
}

@media (max-width: 599px) {
  .lightbox__prev,
  .lightbox__next {
    top: auto;
    bottom: 1rem;
    transform: none;
  }
  .lightbox__prev { left: 1rem; }
  .lightbox__next { right: 1rem; }
  .lightbox__counter { bottom: 4rem; }
}

/* ----- audio-player.css ----- */
/* ==========================================================================
   Lecteur audio article (Web Speech API)
   --------------------------------------------------------------------------
   Sous-bloc B3 accessibilité chantier #2 ROADMAP (2026-05-20).
   Réf checklist : news_features/checklist-accessibilite-v1.md §8.

   Design validé en mockup (lab/audio-player-positions/) :
   - Position A retenue : sticky dans le body article (top: 80px sous le header)
   - Style discret : pas de border colorée, magenta UNIQUEMENT sur le bouton play
   - Hauteur compacte ~32px, inspiré Medium / Substack
   - Surlignage paragraphe en cours = bordure latérale + léger fond
   ========================================================================== */

/* --- Conteneur dans la sidebar (au-dessus de "Derniers contenus")
       Pas de sticky : la sidebar entiere accompagne le scroll dans son flux
       parent. Width auto = prend la largeur de la colonne sidebar (palier 14).
       Masque < 900px car .article-sidebar est masque (cf. palier 14). --- */

.audio-player {
  background: rgba(20, 12, 25, 0.5);
  padding: 6px 10px 6px 6px;
  border-radius: 4px;

  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 12px;
}

/* La sidebar parent a `gap: 2.5rem` (40px) entre ses flex children. Pour
   resserrer l'espacement vers "Derniers contenus" sans casser le gap global
   des autres blocs sidebar, on applique un margin negatif compense. Resultat
   visuel : ~24px d'air entre le widget et le titre suivant. */
.article-sidebar > .audio-player {
  margin-bottom: -1rem;
}

/* État caché après clic close */
.audio-player.is-hidden {
  display: none;
}

/* --- Bouton play/pause : seul élément en magenta signature --- */

.audio-player__play {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-accent-magenta);
  border: none;
  color: #ffffff;
  font-size: 9px;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 1px; /* compense l'asymétrie visuelle du triangle play */
  transition: background-color var(--transition-fast);
}

.audio-player__play:hover {
  background: var(--color-accent-magenta-light, var(--color-accent-pink));
}

.audio-player__play:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
}

/* Quand en lecture : on garde le magenta mais on indique l'état pause via
   le contenu du bouton (géré en JS, le ⏸ remplace ▶) */
.audio-player.is-playing .audio-player__play {
  /* hook potentiel pour effet pulse subtil — pour l'instant rien */
}

/* --- Barre de progression : grise discrète, pas magenta --- */

.audio-player__progress {
  flex: 0 1 140px;
  height: 2px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 1px;
  overflow: hidden;
  position: relative;
}

.audio-player__progress-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0%;
  background: rgba(255, 255, 255, 0.5);
  transition: width 0.3s ease-out;
}

/* --- Temps : tabular pour éviter saut visuel des chiffres --- */

.audio-player__time {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* --- Vitesse : bouton texte minimaliste --- */

.audio-player__speed {
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  font-family: inherit;
  transition: color var(--transition-fast);
}

.audio-player__speed:hover {
  color: #ffffff;
}

.audio-player__speed:focus-visible {
  outline: 2px solid var(--color-accent-magenta);
  outline-offset: 2px;
  border-radius: 2px;
}

/* --- Close : x très discret en bout de widget --- */

.audio-player__close {
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.3);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  flex-shrink: 0;
  padding: 0 2px;
  transition: color var(--transition-fast);
}

.audio-player__close:hover {
  color: rgba(255, 255, 255, 0.7);
}

.audio-player__close:focus-visible {
  outline: 2px solid var(--color-accent-magenta);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ==========================================================================
   Surlignage du paragraphe en cours de lecture
   --------------------------------------------------------------------------
   Q3 validée : bordure latérale magenta + fond très subtil.
   Appliqué dynamiquement via classe `.is-reading` posée par le JS sur
   l'élément (p, h2, h3, blockquote, li) en train d'être lu.
   ========================================================================== */

.article-content .is-reading {
  border-left: 3px solid var(--color-accent-magenta);
  padding-left: var(--space-md);
  background: rgba(160, 26, 126, 0.05); /* magenta très dilué */
  transition: background-color 0.3s ease, padding-left 0.2s ease;
}

/* ==========================================================================
   Mobile / tablette etroite : la sidebar est masquee (palier 14, <900px)
   donc le widget aussi. V1 : on accepte. Si on veut le widget mobile plus
   tard, on duplique en debut de body article via media query.
   ========================================================================== */
