/* ============================================================
   SOLEM Studio — Thème global MediaCMS
   Surcharge les variables CSS + composants de MediaCMS.
   => Reskin COULEUR + TYPO + FORMES, SANS REBUILD du frontend.
   Chargé via templates/root.html (après le bundle => gagne).

   Palette = tokens EXACTS extraits de la maquette Figma
   (SOLEM Website, node 9064:5045).
   ============================================================ */

/* ============================================================
   POLICE — Inter AUTO-HÉBERGÉE (fiable même si Google Fonts
   est bloqué en prod). Fichiers : static/fonts/inter/.
   Police variable => couvre toutes les graisses 100–900.
   ============================================================ */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/static/fonts/inter/inter-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/static/fonts/inter/inter-latin-ext-wght-normal.woff2") format("woff2");
  unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   ICÔNES — Material Symbols Outlined AUTO-HÉBERGÉE (style outline
   comme la maquette). Fichier : static/fonts/material-symbols/.
   Fallback "Material Icons" (filled, local) => jamais de texte brut
   si un glyphe manque.
   ============================================================ */
@font-face {
  font-family: "Material Symbols Outlined";
  font-style: normal;
  font-weight: 100 700;   /* police VARIABLE => axe wght réglable */
  font-display: block;
  src: url("/static/fonts/material-symbols/material-symbols-outlined-var.woff2") format("woff2");
}
.material-icons {
  font-family: "Material Symbols Outlined", "Material Icons" !important;
  font-weight: normal;
  /* icônes fil de fer plus fines (comme la maquette) : wght 250 */
  font-variation-settings: "FILL" 0, "wght" 250, "GRAD" 0, "opsz" 24;
  font-feature-settings: "liga";
}

body {
  /* ---- Palette SOLEM (valeurs exactes Figma) ---- */
  --attentive-blue:       #2879B3;   /* bleu de marque (primaire)      */
  --attentive-blue-dark:  #2573AC;   /* variante foncée (hover/actif)  */
  --attentive-navy:       #051A26;   /* quasi-noir bleuté (texte)      */
  --attentive-hero-title: #001122;   /* titres hero très foncés        */
  --attentive-slate:      #46545C;   /* gris ardoise                   */
  --attentive-muted:      #6B7280;   /* gris texte secondaire          */
  --attentive-border:     #D9D9D9;   /* bordures / placeholders        */
  --attentive-blue-pale:  #E8F4FA;   /* fond bleu très clair (chips)   */
  --attentive-bg:         #F6F7F7;   /* fond général off-white         */
  --attentive-surface:    #FFFFFF;   /* surfaces (cartes, header)      */
  --attentive-red:        #E7333E;   /* accent rouge (alertes)         */

  /* ============================================================
     Couleur de marque globale (défaut MediaCMS = vert #009933).
     Remplacée par le bleu SOLEM.
     ============================================================ */
  --default-theme-color: var(--attentive-blue);
  --default-brand-color: var(--attentive-blue);
  --theme-color:         var(--attentive-blue);
  --brand-color:         var(--attentive-blue);
  --links-color:         var(--attentive-blue);
  --default-logo-height: 40px;

  /* Largeur de sidebar : une seule source de vérité (le bundle met 240px
     sur body mais custom.css met 250px sur .page-sidebar => le
     .page-main-wrap lisait 240 et le contenu passait 10px sous la sidebar).
     On aligne tout sur 250px ici (chargé après le bundle => gagne). */
  --sidebar-width: 250px;

  /* Gouttière horizontale de la page, portée par .page-main-wrap (voir la
     section « GOUTTIÈRE DE PAGE » plus bas). 20px = la valeur que le thème
     appliquait déjà à droite quand la sidebar était dépliée ; le rendu
     desktop dans cet état est donc inchangé. La section RESPONSIVE la
     redéfinit pour les petits écrans. */
  --attentive-page-gutter: 20px;

  /* ---- Grilles de vignettes : une seule source de vérité ----
     Les règles de largeur, plus bas, ne font que lire ces variables ; la
     section RESPONSIVE en fin de fichier les redéfinit par palier. Un seul
     endroit à toucher pour changer une densité. Valeurs desktop = celles de
     la maquette, inchangées (5 médias par ligne, 4 cartes de catégorie).

     La largeur est portée par la formule ENTIÈRE et non par un nombre de
     colonnes : `calc(... / var(--n))` (division par une variable) n'est
     évalué que par les moteurs récents — sur un Safari ancien la déclaration
     serait invalide et l'item retomberait à sa largeur native. */
  --attentive-item-width:     calc((100% - 5 * 22px) / 5);
  --attentive-item-width-cat: calc((100% - 4 * 22px) / 4);
  --attentive-gutter: 22px;   /* gouttière horizontale entre cartes   */
  --attentive-gutter-y: 30px; /* gouttière verticale entre cartes     */

  /* ---- Fond général + texte + en-tête ---- */
  --body-bg-color:   var(--attentive-bg);
  --body-text-color: var(--attentive-navy);
  --hr-color:        #ECEEF1;
  --dotted-outline-color: rgba(5, 26, 38, 0.4);

  --header-bg-color: var(--attentive-surface);
  --header-circle-button-color: var(--attentive-muted);
  --header-popup-menu-color: var(--attentive-navy);
  --header-popup-menu-icon-color: var(--attentive-muted);

  /* ---- Barre latérale (blanche dans la maquette) ---- */
  --sidebar-bg-color:            var(--attentive-surface);
  --sidebar-nav-border-color:    #ECEEF1;
  --sidebar-nav-item-text-color: var(--attentive-navy);
  --sidebar-nav-item-icon-color: var(--attentive-muted);
  --sidebar-bottom-link-color:   var(--attentive-muted);

  --nav-menu-active-item-bg-color: var(--attentive-blue-pale);
  --nav-menu-item-hover-bg-color:  rgba(40, 121, 179, 0.06);
  --in-popup-nav-menu-item-hover-bg-color: var(--attentive-blue-pale);

  /* ---- Champ de recherche ---- */
  --search-field-input-text-color:   var(--attentive-navy);
  --search-field-input-bg-color:      var(--attentive-surface);
  --search-field-input-border-color:  var(--attentive-border);
  --search-field-submit-text-color:   var(--attentive-slate);
  --search-field-submit-bg-color:     var(--attentive-surface);
  --search-field-submit-border-color: var(--attentive-border);
  --search-field-submit-hover-bg-color:      #EFF1F2;
  --search-field-submit-hover-border-color:  #C6CCD1;
  --search-results-item-content-link-title-text-color: var(--attentive-navy);

  /* ---- Cartes média ---- */
  --item-bg-color:                var(--attentive-surface);
  --item-title-text-color:        var(--attentive-navy);
  --item-thumb-bg-color:          #ECEEF1;
  --item-meta-text-color:         var(--attentive-muted);
  --item-meta-link-text-color:    var(--attentive-muted);
  --item-meta-link-hover-text-color: var(--attentive-navy);
  --media-list-row-border-color:  #ECEEF1;
  --media-list-header-title-link-text-color: var(--attentive-muted);

  /* ---- Popups / menus ---- */
  --popup-bg-color:      var(--attentive-surface);
  --popup-hr-bg-color:   #ECEEF1;
  --popup-top-text-color: var(--attentive-navy);
  --popup-top-bg-color:  #EFF1F2;

  --profile-page-bg-color:        var(--attentive-surface);
  --profile-page-nav-link-active-text-color: var(--attentive-navy);
  --profile-page-nav-link-hover-text-color:  var(--attentive-navy);

  --logged-in-user-thumb-bg-color: rgba(5, 26, 38, 0.07);
}

/* ============================================================
   TYPOGRAPHIE — Inter partout.
   Le bundle force "Roboto"/Arial sur certains éléments avec plus
   de spécificité : on réimpose Inter (jamais sur .material-icons).
   ============================================================ */
body,
input, button, textarea, select,
.page-sidebar, .nav-menu a, .nav-menu button, .nav-menu span,
.item-meta, .item-title, .media-list-header,
[class*="profile-page"] h1, [class*="profile-info"] {
  font-family: "Inter", "Helvetica Neue", Arial, sans-serif;
}

.media-list-header .media-list-header-title,
.page-main h1, .page-main h2 {
  font-weight: 700;
  color: var(--attentive-navy);
  letter-spacing: -0.01em;
}

/* Hors accueil, le titre de page est désormais dans le hero => on masque
   l'en-tête de liste redondant. (Sur l'accueil, .media-list-header sert de
   titres de rangées « Shorts », etc. => on le garde.) */
body:not(.attentive-home) .media-list-header {
  display: none !important;
}

/* Bouton « Filtres » de la recherche et des pages de catégorie.
   Le bundle le pose en absolu (`.mi-filters-toggle { top: 12px; right: 0 }`)
   dans `.media-list-row`, en comptant sur la hauteur de `.media-list-header`
   pour lui ménager sa place. Cet en-tête étant masqué juste au-dessus, le
   bouton retombait sur la 1re carte de la liste : le lien de la carte
   (`.item-main`, positionné, donc peint par-dessus) captait le clic. Le
   libellé restait lisible en transparence, mais le bouton ne répondait plus.
   On le remet dans le flux, au-dessus de la rangée de filtres. */
body:not(.attentive-home) .mi-filters-toggle {
  position: relative;
  top: auto;
  right: auto;
  z-index: 1;
  margin-bottom: 8px;
  text-align: right;
}

/* ============================================================
   GOUTTIÈRE DE PAGE — une seule, sur .page-main-wrap.

   `.page-main-wrap` est le seul conteneur commun à TOUT : les pages React
   (`> #page-<nom> > .page-main`), les pages rendues par Django
   (`> .page-main > .page-main-inner`, cf. templates/base.html) et les
   bandeaux de message, qui sont ses enfants directs. Poser la gouttière
   ailleurs en laisse forcément une partie dehors — `.page-main-inner`, par
   exemple, n'existe PAS sur les pages React : le bundle ne l'écrit jamais.

   Le thème ne posait cette gouttière que sous `body.visible-sidebar`. Résultat,
   sidebar repliée (et donc sur tout téléphone, où elle l'est toujours), le
   contenu touchait les deux bords de l'écran — hero compris. Elle s'applique
   désormais dans tous les états, et la sidebar dépliée ne fait qu'y ajouter
   sa largeur.

   ⚠️ Exception : la page média, qui ne suit pas les mêmes règles.
   `media.css` (chargé sur elle seule, après _commons.css) y impose
   `.visible-sidebar .page-main-wrap { padding-left: 0 }` : sur une page
   média, ouvrir la sidebar ne décale PAS le contenu, elle se superpose avec
   son voile noir, comme sur téléphone (cf. PageSidebarContentOverlay.scss,
   qui allume le voile sur #page-media à toute largeur). Le thème, lui,
   poussait quand même le contenu de 250 + 20px : le lecteur se retrouvait
   très en retrait des deux côtés alors que rien ne l'exigeait.
   Son `.viewer-section` porte par ailleurs déjà son propre retrait et se
   centre dans une largeur maximale de 1328px : il n'a besoin d'aucune
   gouttière de notre part. On lui rend donc entièrement la main.
   `:has()` est déjà employé plus bas dans ce fichier pour la colonne
   « À suivre ».

   ⚠️ Sous 768px, MediaCMS bascule la sidebar en tiroir superposé (voile noir
   .page-sidebar-content-overlay) et ne décale PLUS le contenu : le natif
   conditionne son `padding-left` à `@media (min-width: 768px)`. Sans la même
   condition, ouvrir le menu sur un téléphone poussait la page de 270px hors
   de l'écran (largeur de défilement mesurée : 730px pour 402px de viewport).
   ============================================================ */
.page-main-wrap:not(:has(> [id^="page-media"])) {
  padding-left: var(--attentive-page-gutter) !important;
  padding-right: var(--attentive-page-gutter) !important;
}

@media (min-width: 768px) {
  body.visible-sidebar .page-main-wrap:not(:has(> [id^="page-media"])) {
    padding-left: calc(var(--sidebar-width) + var(--attentive-page-gutter)) !important;
  }

  /* Page média, sidebar dépliée : on garde le décalage de la largeur de la
     sidebar, mais SANS y ajouter la gouttière — le lecteur porte déjà son
     propre retrait de 24px, si bien qu'il démarrait à 294px du bord pour une
     sidebar large de 250.
     Pourquoi ne pas laisser simplement faire `media.css`, qui met 0 ici :
     parce qu'il compte sur la sidebar comme calque modal, et qu'elle
     recouvrirait alors le bord gauche du lecteur (vérifié). Le voile noir
     s'affiche de toute façon par-dessus, comme aujourd'hui. */
  body.visible-sidebar .page-main-wrap:has(> [id^="page-media"]) {
    padding-left: var(--sidebar-width) !important;
    padding-right: 0 !important;
  }
}

/* Les listes verticales portent un retrait natif (`.items-list-ver
   { padding: 0 16px }`, 24px au-delà de 1220px) qui s'ajoutait à la gouttière :
   sur la page Catégories, les cartes démarraient 24px plus à droite que le
   hero juste au-dessus. Le thème le neutralisait déjà sur l'accueil ; on
   généralise pour que tous les blocs partagent le même bord gauche. */
.media-list-wrapper.items-list-ver,
.search-results-wrap.media-list-wrapper {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* ============================================================
   FORMES — cartes 10px, recherche pilule.
   ============================================================ */
.item-thumb,
a.item-thumb,
.video-thumb,
.playlist-thumb {
  border-radius: 10px !important;
}

/* Lecteur vidéo : couper le contenu à la forme du conteneur.
   `.player-container` porte `border-radius: 10px` (media.css, à partir de
   480px) mais AUCUN `overflow: hidden`. Or le lecteur qu'il contient est
   rectangulaire et noir (`.video-js { background-color: #000 }`, CSS de
   video.js) : ses quatre coins carrés dépassaient de l'arrondi et se lisaient
   comme un liseré noir autour de l'image, surtout en haut où rien ne les
   recouvre — en bas, la barre de contrôle masquait en partie le défaut.
   Rien dans le lecteur ne sort volontairement de ce cadre (menus de réglages
   et infobulles s'ouvrent à l'intérieur), la coupe est donc sans effet de
   bord. Hors requête média : le défaut ne dépend pas de la largeur. */
.viewer-container .player-container {
  overflow: hidden;
}

/* Champ de recherche : pilule UNIQUE avec loupe intégrée (maquette).
   Structure : .search-field-wrap > form > .text-field-wrap > input
               + button[submit] en absolu à droite. */
/* Largeur fixe réservée au desktop : sous 1024px, MediaCMS masque ce champ et
   réutilise la MÊME classe pour la recherche plein écran déclenchée par la
   loupe (`.mobile-search-field .search-field-wrap`, positionnée en absolu
   entre le bouton retour et le bord droit). Le `width: 620px !important`
   l'emportait sur le `width: auto` natif et faisait déborder l'en-tête de
   ~60px. D'où la borne à 1024px, exactement celle du natif. */
@media (min-width: 1024px) {
  .search-field-wrap {
    width: 620px !important;
    max-width: 60% !important;
  }
}
.search-field-wrap .text-field-wrap {
  padding-right: 0 !important;   /* input pleine largeur, loupe par-dessus */
}
.search-field-wrap input[type="text"] {
  border-radius: 999px !important;
  border-width: 1px !important;
  height: 28px !important;
  font-size: 13px !important;
  padding: 0 16px 0 40px !important;   /* place la loupe à GAUCHE */
}
/* Loupe (bouton submit) déplacée à GAUCHE, avant le texte */
.search-field-wrap button[type="submit"],
.search-field-wrap button[type="submit"]:hover,
.search-field-wrap button[type="submit"]:focus {
  left: 0 !important;
  right: auto !important;
  border: 0 !important;
  background: transparent !important;
  width: 40px !important;
  color: var(--attentive-muted) !important;
}
.search-field-wrap button[type="submit"] .material-icons {
  font-size: 16px !important;
}

/* Bouton de repli/dépli de la sidebar : réintroduit, en CHEVRON,
   placé à DROITE du logo (comme la maquette).
   Le header-left interne passe en flex pour réordonner logo -> toggle. */
.page-header-left > div {
  display: flex !important;
  align-items: center !important;
  height: var(--header-height, 56px) !important;
}
/* Logo + toggle : nativement display:table-cell + height:100% => en flex
   leur contenu reste collé en haut. On annule (height:auto) pour laisser
   align-items centrer. Ciblé sur logo+toggle uniquement : .close-search-field
   (bouton retour mobile) garde son display natif (masqué). */
.page-header-left > div > .logo,
.page-header-left > div > .toggle-sidebar {
  display: inline-flex !important;
  align-items: center !important;
  height: auto !important;
}
.page-header-left > div > .logo {
  order: 1;
}
.page-header-left > div > .toggle-sidebar {
  order: 2;
  margin-left: 16px;
}
/* Icône native = ligature texte "menu" (hamburger) : on la masque
   et on affiche un chevron via ::before (police Material Symbols). */
.toggle-sidebar .material-icons {
  font-size: 0 !important;
}
.toggle-sidebar .material-icons::before {
  content: "chevron_left";   /* navbar dépliée : chevron vers la gauche */
  font-size: 22px;
}
/* Navbar repliée (body sans .visible-sidebar) : chevron inversé (droite) */
body:not(.visible-sidebar) .toggle-sidebar .material-icons::before {
  content: "chevron_right";
}

/* ============================================================
   NAVIGATION — item actif : chip bleu pâle + texte bleu.
   ============================================================ */
/* Petit espace vertical entre les items */
.nav-menu li.link-item {
  margin: 3px 0;
}
.nav-menu li.link-item a {
  border-radius: 10px;
  font-weight: 350;
  /* bordure transparente dès le repos => même hauteur qu'au :hover/.active
     (sinon +2px au survol => le menu "saute"). */
  border: solid 1px transparent;
  padding-left: 31px;   /* 32 - 1px de bordure => icône alignée à 32px */
  white-space: nowrap;  /* jamais de retour à la ligne (pastille plus étroite au survol) */
}
/* Écart icône <-> texte (natif 24px) */
.nav-menu .menu-item-icon {
  margin-right: 12px;
}

/* Items masqués (hors maquette) : À propos, Langue, et « En vedette »
   (doublon avec l'accueil). Masqué en CSS et non via le drapeau
   config-enabled.pages.featured.enabled, car ce dernier pilote aussi la
   section « En vedette » de l'accueil (cf. HomePage.tsx). */
.nav-item-about,
.nav-item-language,
.nav-item-featured {
  display: none !important;
}

/* Séparateur avant la section « Autres contenus » */
.nav-menu li.attentive-nav-section-title[data-attentive-title="autres"] {
  border-top: 1px solid var(--sidebar-nav-border-color, #eceef1);
  margin-top: 10px;
  padding-top: 24px !important;
}

/* ============================================================
   Bloc « À la une » (média featured en une ligne, façon maquette)
   injecté par attentive-custom.js sur l'accueil.
   ============================================================ */
.attentive-featured {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  margin: 0 0 28px;
  /* Pas de carte blanche : le bloc se fond dans la page (comme la maquette). */
  background: transparent;
  text-decoration: none;
  color: inherit;
}
/* Vignette : largeur fixe et ratio 16/9, seule la vignette est arrondie. */
.attentive-featured-thumb {
  position: relative;   /* référentiel du badge de durée (.item-duration) */
  flex: 0 0 320px;
  max-width: 320px;
  border-radius: 12px;
  overflow: hidden;
}
.attentive-featured-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  object-fit: cover;
}
.attentive-featured-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0;
  min-width: 0;
}
.attentive-featured-badge {
  align-self: flex-start;
  /* inline-flex : l'étoile (::before) reste centrée verticalement sur le texte. */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--attentive-blue-pale);
  color: var(--attentive-blue);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 16px;
}
/* Étoile à 4 branches devant « À la une ». Rendue en masque SVG + currentColor :
   elle hérite donc du bleu du label et reste nette à toute taille / en mode sombre. */
.attentive-featured-badge::before {
  content: "";
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2c.6 5.5 4.5 9.4 10 10-5.5.6-9.4 4.5-10 10-.6-5.5-4.5-9.4-10-10 5.5-.6 9.4-4.5 10-10z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2c.6 5.5 4.5 9.4 10 10-5.5.6-9.4 4.5-10 10-.6-5.5-4.5-9.4-10-10 5.5-.6 9.4-4.5 10-10z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.attentive-featured-title {
  margin: 0;
  font-size: 22px;
  font-weight: 500;
  font-variation-settings: "wght" 500;
  line-height: 1.2;
  color: var(--attentive-navy);
}
.attentive-featured-desc {
  margin: 0;
  color: var(--attentive-muted);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Créateur + vues/date : exactement la même typographie (la seule
   différence visible auparavant était la couleur), et espacement resserré
   entre les deux lignes (le gap de 8px du body est neutralisé). */
.attentive-featured-author,
.attentive-featured-meta {
  font-family: inherit;
  font-size: 13px;
  font-weight: 400;
  font-variation-settings: "wght" 400;
  line-height: 1.35;
  letter-spacing: normal;
  color: var(--attentive-muted);
}
.attentive-featured-author + .attentive-featured-meta {
  margin-top: -6px;
}

/* ============================================================
   CARTES de catégories (page /categories, comme la maquette) :
   boîte arrondie, en-tête dégradé bleu + titre, pied blanc
   (description + nombre de médias).
   ============================================================ */
/* La liste prend tout l'espace dispo (comme le hero), au lieu d'être
   capée à 5×item-width et centrée. Item plus large => ~5 par ligne. */
#page-categories {
  --default-item-width: 300px;
  --default-max-item-width: 360px;
}
/* Toutes les listes verticales remplissent l'espace dispo (comme /categories) :
   on retire le plafond (item-width × max-row-items) et le centrage. Les sliders
   horizontaux de l'accueil (items-list-hor) ne sont pas touchés. */
/* Toutes les listes HORS ACCUEIL (ver ET hor : catégories, en vedette,
   recommandé, dernier, tags, membres, recherche/catégorie, historique,
   médias aimés…) remplissent l'espace dispo. L'accueil garde ses rangées. */
body:not(.attentive-home) .media-list-wrapper {
  max-width: 100% !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
/* Grille verticale : on force width:100% sur la rangée (sinon le bundle la
   fige à 5×item-width au-delà de 1170px et elle ne remplit pas). */
body:not(.attentive-home) .media-list-wrapper.items-list-ver .media-list-row {
  max-width: 100% !important;
  width: 100% !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
/* Grilles (items-list-ver, hors accueil) : --attentive-cols items par ligne
   (5 sur desktop), avec la gouttière à droite et en bas. Largeur en % => vrai
   n-max responsive. (Les listes horizontales ne sont pas concernées.) */
body:not(.attentive-home) .media-list-wrapper.items-list-ver .media-list-row .item {
  width: var(--attentive-item-width) !important;
  max-width: none !important;
  margin: 0 var(--attentive-gutter) var(--attentive-gutter-y) 0 !important;
}
body:not(.attentive-home) .media-list-wrapper.items-list-ver .media-list-row .item .item-content {
  margin-right: 0 !important;
}
/* Page Catégories : --attentive-cols-cat par ligne (4 sur desktop, au lieu de 5). */
#page-categories .media-list-wrapper.items-list-ver .media-list-row .item {
  width: var(--attentive-item-width-cat) !important;
}
/* Boîtes de hauteur égale : plutôt que de passer la rangée en flex (ce qui
   casse la mise en page native en inline-block), on rend le CONTENU de hauteur
   constante — l'en-tête est déjà fixe à 100px, il suffit de réserver un nombre
   de lignes fixe pour la description. `vertical-align: top` évite en plus
   l'alignement sur la ligne de base propre à inline-block. */
#page-categories .media-list-wrapper.items-list-ver .media-list-row .item {
  vertical-align: top;
}

/* ------------------------------------------------------------------
   Sections de catégories sur l'accueil (« Afficher sur l'accueil ») :
   injectées par attentive-custom.js. Les règles de grille ci-dessus sont en
   body:not(.attentive-home), il faut donc les répliquer ici.
   ------------------------------------------------------------------ */
body.attentive-home .attentive-cat-row {
  margin: 0 0 8px !important;
}
/* Séparateur entre « À la une » et la 1re section de catégorie. Le natif ne le
   pose qu'entre deux .media-list-row consécutives
   (`.media-list-row + .media-list-row`) : le bloc « À la une » étant un <a>,
   la règle ne s'appliquait pas. Même trait, même variable de couleur. */
body.attentive-home .attentive-featured + .attentive-cat-row {
  border-top: 1px solid var(--media-list-row-border-color);
}
body.attentive-home .attentive-cat-row .media-list-wrapper.items-list-ver .media-list-row {
  display: flex;
  flex-wrap: wrap;
  width: 100% !important;
  max-width: 100% !important;
}
body.attentive-home .attentive-cat-row .media-list-wrapper.items-list-ver .media-list-row .item {
  width: var(--attentive-item-width) !important;
  max-width: none !important;
  margin: 0 var(--attentive-gutter) var(--attentive-gutter-y) 0 !important;
}
body.attentive-home .attentive-cat-row .media-list-wrapper.items-list-ver .media-list-row .item .item-content {
  margin-right: 0 !important;
}
/* En-tête de section : titre + lien « VOIR TOUT » alignés. */
/* En-tête de section : titre + « Tout voir » sur une 1re ligne, description en
   dessous (comme la maquette). L'en-tête empile, la ligne reste horizontale. */
body.attentive-home .attentive-cat-row .media-list-header {
  display: block !important;
  margin: 0 0 14px;
}
body.attentive-home .attentive-cat-row .attentive-cat-headline {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 14px;
}
/* Description de la catégorie : valeurs relevées dans la maquette. */
body.attentive-home .attentive-cat-row .attentive-cat-desc {
  margin: -4px 0 0;
  font-size: 13px;
  font-weight: 400;
  line-height: 24px;
  color: #46545c;
}
/* Le gris de la maquette est illisible sur fond sombre. */
body.dark_theme .attentive-cat-row .attentive-cat-desc {
  color: #a7b0b6;
}
body.attentive-home .attentive-cat-row .media-list-header h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--attentive-navy);
}
body.attentive-home .attentive-cat-row .media-list-header h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: normal;
}
body.attentive-home .attentive-cat-row .media-list-header h3 a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: -10px;
  color: var(--attentive-blue);
  text-decoration: none;
}
body.attentive-home .attentive-cat-row .media-list-header h3 a:hover {
  text-decoration: underline;
}
/* Flèche entourée d'un cercle, tracé exporté tel quel depuis la maquette
   (node « P_arrow circle 2 »). Rendue en masque pour hériter de currentColor. */
body.attentive-home .attentive-cat-row .media-list-header h3 a::before {
  content: "";
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M10.875 6C10.875 7.29293 10.3614 8.53291 9.44715 9.44715C8.53291 10.3614 7.29293 10.875 6 10.875C4.70707 10.875 3.46709 10.3614 2.55285 9.44715C1.63861 8.53291 1.125 7.29293 1.125 6C1.125 4.70707 1.63861 3.46709 2.55285 2.55285C3.46709 1.63861 4.70707 1.125 6 1.125C7.29293 1.125 8.53291 1.63861 9.44715 2.55285C10.3614 3.46709 10.875 4.70707 10.875 6ZM0 6C0 7.5913 0.632141 9.11742 1.75736 10.2426C2.88258 11.3679 4.4087 12 6 12C7.5913 12 9.11742 11.3679 10.2426 10.2426C11.3679 9.11742 12 7.5913 12 6C12 4.4087 11.3679 2.88258 10.2426 1.75736C9.11742 0.632141 7.5913 0 6 0C4.4087 0 2.88258 0.632141 1.75736 1.75736C0.632141 2.88258 0 4.4087 0 6ZM6.90469 3.54375C6.80625 3.43594 6.66797 3.375 6.52031 3.375C6.23438 3.375 6 3.60938 6 3.89766V4.875H3.75C3.33516 4.875 3 5.21016 3 5.625V6.375C3 6.78984 3.33516 7.125 3.75 7.125H6V8.10234C6 8.39062 6.23437 8.625 6.52266 8.625C6.66797 8.625 6.80625 8.56406 6.90703 8.45625L8.87578 6.32344C8.95781 6.23437 9.00234 6.11953 9.00234 5.99766C9.00234 5.87578 8.95781 5.76094 8.87578 5.67188L6.90703 3.53906L6.90469 3.54375Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M10.875 6C10.875 7.29293 10.3614 8.53291 9.44715 9.44715C8.53291 10.3614 7.29293 10.875 6 10.875C4.70707 10.875 3.46709 10.3614 2.55285 9.44715C1.63861 8.53291 1.125 7.29293 1.125 6C1.125 4.70707 1.63861 3.46709 2.55285 2.55285C3.46709 1.63861 4.70707 1.125 6 1.125C7.29293 1.125 8.53291 1.63861 9.44715 2.55285C10.3614 3.46709 10.875 4.70707 10.875 6ZM0 6C0 7.5913 0.632141 9.11742 1.75736 10.2426C2.88258 11.3679 4.4087 12 6 12C7.5913 12 9.11742 11.3679 10.2426 10.2426C11.3679 9.11742 12 7.5913 12 6C12 4.4087 11.3679 2.88258 10.2426 1.75736C9.11742 0.632141 7.5913 0 6 0C4.4087 0 2.88258 0.632141 1.75736 1.75736C0.632141 2.88258 0 4.4087 0 6ZM6.90469 3.54375C6.80625 3.43594 6.66797 3.375 6.52031 3.375C6.23438 3.375 6 3.60938 6 3.89766V4.875H3.75C3.33516 4.875 3 5.21016 3 5.625V6.375C3 6.78984 3.33516 7.125 3.75 7.125H6V8.10234C6 8.39062 6.23437 8.625 6.52266 8.625C6.66797 8.625 6.80625 8.56406 6.90703 8.45625L8.87578 6.32344C8.95781 6.23437 9.00234 6.11953 9.00234 5.99766C9.00234 5.87578 8.95781 5.76094 8.87578 5.67188L6.90703 3.53906L6.90469 3.54375Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Titre de carte resserré sur sa ligne de méta. Deux règles natives sont en
   jeu : `.item-main h3 {margin-top:12px;margin-bottom:8px}` et surtout
   `.items-list-ver.media-list-wrapper .media-list-row .item-main h3
   {margin:.5714285em 0}` (4 classes) qui l'emporte. D'où ce sélecteur long,
   et le margin-top conservé à la valeur native pour ne changer que le bas. */
body.attentive-home .attentive-cat-row .media-list-wrapper.items-list-ver .media-list-row .item-main h3 {
  margin-top: 0.5714285em;
  margin-bottom: 2px;
}
/* La vignette d'un média injecté a besoin de son ratio (image en background).
   `position: relative` : référentiel du badge de durée (.item-duration, en
   absolu). Le natif le fournit déjà, on le rend explicite car ces cartes sont
   construites à la main. */
body.attentive-home .attentive-cat-row .item-thumb {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background-size: cover;
  background-position: center;
  border-radius: 8px;
  overflow: hidden;
}

/* Pas de fond blanc derrière le titre des items */
.item-content h3 span {
  background: transparent !important;
}

/* Méta des items (vues, date, nb médias…) un peu plus petites */
.item-meta,
.item-meta * {
  font-size: 12px;
}

/* Recherche / consultation catégorie : pas de padding sur le wrapper. */
.search-results-wrap.items-list-hor.media-list-wrapper {
  padding: 0 !important;
}
/* Accueil : les rangées prennent toute la largeur, sans marge ni padding L/R. */
body.attentive-home .media-list-wrapper,
body.attentive-home .media-list-row {
  max-width: 100% !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
#page-categories .item {
  border-radius: 14px !important;
  overflow: hidden;
  background: var(--attentive-surface) !important;
  box-shadow: 0 4px 16px rgba(5, 26, 38, 0.08);
  /* Gouttières entre les cartes. Mêmes variables que la largeur juste
     au-dessus : une marge en dur (22px) contredisait la largeur calculée dès
     que la gouttière changeait de palier, et il ne tenait plus qu'une carte
     par ligne. Valeurs desktop identiques (22px / 30px). */
  margin: 0 var(--attentive-gutter) var(--attentive-gutter-y) 0 !important;
}
/* .item-content = conteneur global : sans padding, plein largeur. */
#page-categories .item .item-content {
  display: block !important;
  padding: 0 !important;
  margin: 0 !important;
  background: var(--attentive-surface);
}
/* Le lien unique qui encapsule tout le contenu de la carte. */
#page-categories .item .attentive-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
/* En-tête dégradé : titre blanc, plein largeur, jusqu'aux bords. */
#page-categories .item .item-header {
  display: flex;
  align-items: center;          /* titre centré verticalement */
  width: 100%;
  height: 100px;
  min-height: 100px;
  background: linear-gradient(120deg, #0A2A45 0%, #16507D 58%, #2E76B0 100%);
}
#page-categories .item .item-header h3 {
  margin: 0;
  padding: 0 20px;
  color: #fff;
  font-weight: 700;
  font-size: 18px;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
/* Corps blanc : description puis nombre de médias. */
#page-categories .item .item-body {
  padding: 14px 18px 16px;
  background: var(--attentive-surface);
}
/* Deux lignes réservées pour la description : sans cela, une description sur
   1 ligne et une sur 2 donneraient des hauteurs différentes d'une LIGNE de
   cartes à l'autre (l'étirement flex n'égalise qu'au sein d'une même ligne).
   Au-delà de 2 lignes, on tronque avec des points de suspension. */
#page-categories .item .item-body .item-description {
  margin: 0 0 6px;
  color: var(--attentive-navy);
  font-weight: 500;
  line-height: 1.35;
  min-height: calc(2 * 1.35em);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
#page-categories .item .item-body .item-media-count {
  color: var(--attentive-muted);
  font-size: 13px;
}

/* En-têtes de sections sur la page Catégories (Vidéos / Documentations),
   injectés par attentive-custom.js. Pleine largeur pour casser la grille. */
.attentive-cat-head {
  flex-basis: 100% !important;
  width: 100% !important;
  grid-column: 1 / -1 !important;
  font-size: 20px;
  font-weight: 700;
  color: var(--body-text-color);
  margin: 18px 0 14px;
  padding: 0 2px;
}

/* Titres de sections (injectés par attentive-custom.js) */
.nav-menu li.attentive-nav-section-title {
  list-style: none;
  padding: 18px 20px 8px;
  margin: 0;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  /* couleur adaptative (clair = navy, sombre = clair) */
  color: var(--sidebar-nav-item-text-color);
  pointer-events: none;
  cursor: default;
  background: none;
}

/* Logo SOLEM STUDIO : adapté au mode sombre (passe en blanc). */
body.dark_theme .logo img {
  filter: brightness(0) invert(1);
}

/* Popup du menu utilisateur (haut-droite) : uniformisé avec les
   boîtes login/logout (coins arrondis + ombre douce). */
.page-header-right .popup {
  border-radius: 16px !important;
  box-shadow: 0 10px 30px rgba(5, 26, 38, 0.12) !important;
  overflow: hidden;
}
/* Item actif : pastille bleu pâle INSET (marges 20px), portée par le <a>
   + bordure fine bleue (box-shadow => pas de décalage) + texte bleu.
   Le fond est retiré du <li> pour ne pas doubler la pastille. */
/* Fond retiré du <li> (actif ET survol) pour ne pas doubler la pastille. */
.nav-menu li.link-item.active,
.nav-menu li.link-item:hover {
  background-color: transparent !important;
}
/* Pastille INSET identique pour :hover ET .active (uniformisés) :
   marges 20px, fond bleu pâle, bordure bleue, texte/icône bleus.
   padding-left 11px = 32 (non-actif) - 20 (margin) - 1 (border) => icône alignée. */
.nav-menu li.link-item a:hover,
.nav-menu li.link-item.active > a,
.nav-menu li.link-item a.active {
  width: calc(100% - 40px);
  margin-left: 20px;
  margin-right: 20px;
  background-color: var(--nav-menu-active-item-bg-color);
  color: var(--attentive-blue);
  font-weight: 350;
  box-shadow: none;
  /* bordure transparente partagée => même géométrie (pas de saut d'icône) ;
     seule la version .active la colore. */
  border: solid 1px transparent;
  padding-left: 11px;
  padding-right: 12px;   /* un peu plus de place pour les libellés longs */
}
.nav-menu li.link-item.active > a,
.nav-menu li.link-item a.active {
  border-color: var(--attentive-blue);
}
.nav-menu li.link-item a:hover .material-icons,
.nav-menu li.link-item.active > a .material-icons,
.nav-menu li.link-item a.active .material-icons {
  color: var(--attentive-blue);
}

/* ---- Icônes de menu : remap pour coller à la maquette ----
   Les icônes sont rendues via ::after { content: attr(data-icon) }
   avec la police "Material Icons" (auto-hébergée). On remappe le
   glyphe en surchargeant le content (React ne touche pas au ::after). */
.nav-item-categories .material-icons[data-icon]::after {
  content: "layers";   /* calques empilés, comme la maquette */
}

/* Liens d'admin « Gérer les… » : icônes spécifiques (au lieu du même
   miscellaneous_services partout). */
.nav-item-manage-media .material-icons[data-icon]::after {
  content: "video_settings";
}
.nav-item-manage-users .material-icons[data-icon]::after {
  content: "manage_accounts";
}
/* Gérer les commentaires : SVG vectorisé fidèle au PNG fourni (bulle
   outline + engrenage plein à dents pointues avec trou), en mask =>
   suit la couleur courante (grise / bleue à l'actif-survol). */
.nav-item-manage-comments .material-icons[data-icon]::after {
  content: "" !important;
}
.nav-item-manage-comments .material-icons {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-left: 4px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='256.000000pt' height='256.000000pt' viewBox='0 0 256.000000 256.000000' preserveAspectRatio='xMidYMid meet'%3E %3Cg transform='translate(0.000000,256.000000) scale(0.100000,-0.100000)' fill='%23000000' stroke='none'%3E %3Cpath d='M226 2415 c-49 -17 -103 -68 -127 -120 -18 -38 -19 -82 -19 -830 l0 -790 223 222 222 223 631 2 631 3 42 30 c24 16 47 39 52 52 5 13 13 23 18 23 28 0 32 85 29 565 l-3 490 -34 49 c-24 34 -48 55 -85 72 l-51 24 -745 -1 c-608 0 -752 -2 -784 -14z m1522 -161 l22 -15 0 -461 c0 -415 -2 -463 -17 -480 -15 -17 -49 -18 -657 -18 l-641 0 -100 -100 c-55 -55 -103 -100 -107 -100 -5 0 -8 259 -8 575 0 562 0 575 20 595 20 20 33 20 743 20 638 0 725 -2 745 -16z'/%3E %3Cpath d='M1895 1178 c-3 -18 -9 -55 -13 -82 -7 -49 -8 -50 -59 -70 -28 -12 -71 -35 -95 -53 l-43 -31 -58 23 c-98 40 -91 42 -128 -22 -19 -32 -34 -61 -34 -64 0 -4 26 -28 58 -53 l57 -47 -6 -77 c-4 -44 -2 -93 4 -114 11 -40 12 -39 -111 -139 -6 -4 59 -129 67 -129 1 0 31 11 66 25 35 14 70 25 77 25 7 0 38 -16 67 -36 30 -20 72 -42 93 -49 35 -12 38 -17 45 -62 4 -26 10 -63 13 -80 l6 -33 74 0 73 0 7 74 c4 40 10 77 14 82 3 5 24 15 46 23 22 7 61 29 88 47 26 19 54 34 62 34 9 0 43 -11 77 -25 34 -14 63 -25 64 -25 1 0 19 28 40 61 32 53 35 64 23 73 -9 6 -35 27 -60 48 l-44 36 1 120 0 121 57 47 c31 25 57 48 57 50 0 6 -73 124 -77 124 -2 0 -36 -14 -75 -30 l-70 -30 -47 34 c-25 18 -67 41 -93 51 -53 19 -54 22 -64 118 l-6 67 -74 0 -73 0 -6 -32z m190 -296 c108 -55 159 -181 124 -306 -14 -52 -103 -141 -155 -155 -103 -29 -188 -8 -260 63 -165 166 -42 437 191 423 34 -3 78 -13 100 -25z'/%3E %3C/g%3E %3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='256.000000pt' height='256.000000pt' viewBox='0 0 256.000000 256.000000' preserveAspectRatio='xMidYMid meet'%3E %3Cg transform='translate(0.000000,256.000000) scale(0.100000,-0.100000)' fill='%23000000' stroke='none'%3E %3Cpath d='M226 2415 c-49 -17 -103 -68 -127 -120 -18 -38 -19 -82 -19 -830 l0 -790 223 222 222 223 631 2 631 3 42 30 c24 16 47 39 52 52 5 13 13 23 18 23 28 0 32 85 29 565 l-3 490 -34 49 c-24 34 -48 55 -85 72 l-51 24 -745 -1 c-608 0 -752 -2 -784 -14z m1522 -161 l22 -15 0 -461 c0 -415 -2 -463 -17 -480 -15 -17 -49 -18 -657 -18 l-641 0 -100 -100 c-55 -55 -103 -100 -107 -100 -5 0 -8 259 -8 575 0 562 0 575 20 595 20 20 33 20 743 20 638 0 725 -2 745 -16z'/%3E %3Cpath d='M1895 1178 c-3 -18 -9 -55 -13 -82 -7 -49 -8 -50 -59 -70 -28 -12 -71 -35 -95 -53 l-43 -31 -58 23 c-98 40 -91 42 -128 -22 -19 -32 -34 -61 -34 -64 0 -4 26 -28 58 -53 l57 -47 -6 -77 c-4 -44 -2 -93 4 -114 11 -40 12 -39 -111 -139 -6 -4 59 -129 67 -129 1 0 31 11 66 25 35 14 70 25 77 25 7 0 38 -16 67 -36 30 -20 72 -42 93 -49 35 -12 38 -17 45 -62 4 -26 10 -63 13 -80 l6 -33 74 0 73 0 7 74 c4 40 10 77 14 82 3 5 24 15 46 23 22 7 61 29 88 47 26 19 54 34 62 34 9 0 43 -11 77 -25 34 -14 63 -25 64 -25 1 0 19 28 40 61 32 53 35 64 23 73 -9 6 -35 27 -60 48 l-44 36 1 120 0 121 57 47 c31 25 57 48 57 50 0 6 -73 124 -77 124 -2 0 -36 -14 -75 -30 l-70 -30 -47 34 c-25 18 -67 41 -93 51 -53 19 -54 22 -64 118 l-6 67 -74 0 -73 0 -6 -32z m190 -296 c108 -55 159 -181 124 -306 -14 -52 -103 -141 -155 -155 -103 -29 -188 -8 -260 63 -165 166 -42 437 191 423 34 -3 78 -13 100 -25z'/%3E %3C/g%3E %3C/svg%3E") center / contain no-repeat;
}

/* Icônes fidèles à la maquette */
.nav-item-my-playlists .material-icons[data-icon]::after {
  content: "account_circle";   /* personne dans un cercle (maquette) */
}
.nav-item-contact .material-icons[data-icon]::after {
  content: "help";             /* ? dans un cercle (maquette) */
}

/* Liens régionaux (Europe/USA/MEA) : picto SOLEM rond à la place
   de l'icône Material (item marqué .attentive-region via la config). */
.attentive-region .material-icons[data-icon]::after {
  content: "" !important;
}
.attentive-region .material-icons {
  width: 24px;
  height: 24px;
  background: url("/static/favicons/android-chrome-192x192.png") center/cover no-repeat;
  border-radius: 50%;
}

/* ============================================================
   CARTES CATÉGORIES — dégradé marine -> bleu (maquette)
   ============================================================ */
.categories-page .item .item-thumb,
.category-item .item-thumb {
  background-image: linear-gradient(160deg, var(--attentive-navy) 0%, var(--attentive-blue) 100%) !important;
}

/* Logo SOLEM Studio (haut à gauche) : décalage vers la droite.
   .logo a margin:0 (bundle) et le layout du header neutralise le margin
   => on décale via le PADDING du wrapper interne du header-left. */
.page-header-left > div {
  padding-left: 20px !important;
}

/* ============================================================
   LOGO ROND SOLEM en haut à droite (favicon auto-hébergé).
   Ajouté en pseudo-élément à la fin de la zone header-right.
   ============================================================ */
/* L'avatar du header EST le logo rond SOLEM (remplace le silhouette
   par défaut ; pas de logo séparé en doublon).
   Ciblé sur le header uniquement (.user-thumb) => l'avatar du menu
   déroulant reste inchangé. */
.page-header-right .user-thumb .thumbnail.small-thumb {
  background: #FFFFFF url("/static/favicons/android-chrome-192x192.png") center / cover no-repeat !important;
}
.page-header-right .user-thumb .thumbnail.small-thumb img,
.page-header-right .user-thumb .thumbnail.small-thumb .material-icons {
  display: none !important;
}

/* ============================================================
   HERO d'accueil « Toute la puissance de nos solutions »
   Le hero est injecté par le bundle avec son propre <style>
   (chargé APRÈS ce fichier) => on surcharge avec plus de
   spécificité (body .attentive-hero) + !important.
   - marges autour (comme la maquette, carte insérée)
   - vraies couleurs SOLEM Figma
   ============================================================ */
body .attentive-hero {
  /* Mise en page autonome (le <style> baké n'existe QUE sur l'accueil ;
     ici on couvre toutes les pages). */
  position: relative;
  display: flex !important;
  align-items: center;
  min-height: 132px;
  padding: 30px 36px;
  /* Marge haute = gouttière de page : l'écart sous l'en-tête doit valoir
     celui des côtés, sinon le hero paraît collé à la barre. Pas de marge
     horizontale, elle est gérée par .page-main-wrap. */
  margin: var(--attentive-page-gutter) 0 28px !important;
  border-radius: 16px !important;
  overflow: hidden;
  /* Fond + illustration RÉELLE de la maquette (raster Figma).
     L'image EST le fond complet du hero => cover pour couvrir toute
     la largeur (plus aucune zone de repli / pas de raccord de teinte),
     ancrée à droite pour garder l'illustration visible. */
  background: #E8F4FA url("/static/images/hero-attentive.png") right center / cover no-repeat !important;
}
body .attentive-hero .attentive-hero-content {
  position: relative;
  z-index: 2;
  max-width: 66%;
}
/* Masquer la déco SVG approximative bakée dans le bundle */
body .attentive-hero .attentive-hero-deco {
  display: none !important;
}
body .attentive-hero .attentive-hero-eyebrow {
  display: block;
  color: var(--attentive-blue) !important;
  font-weight: 500 !important;
  font-size: 15px;
  line-height: 1.2;
  margin: 0 0 6px;
}
/* Titre en dégradé bleu -> marine (valeurs exactes Figma).
   Le texte reste réel (traduisible / accessible). */
body .attentive-hero .attentive-hero-title {
  display: block;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
  font-weight: 500 !important;
  font-size: 28px !important;
  background: linear-gradient(90deg, #2573AC 0%, #00365C 40%, #051A26 90%) !important;
  -webkit-background-clip: text !important;
  background-clip: text !important;
  -webkit-text-fill-color: transparent !important;
  color: transparent !important;
}

/* ============================================================
   MESSAGES (.alert) — uniformisés avec le hero :
   arrondis + marges horizontales alignées, style SOLEM.
   ("Connexion avec X réussie", etc.)
   ============================================================ */
.alert {
  display: flex !important;
  align-items: center !important;        /* texte centré verticalement */
  min-height: 56px !important;
  width: auto !important;
  /* Marges verticales alignées sur la gouttière de page : la bulle se
     détache de l'en-tête comme du bloc qui la suit, de la même distance que
     les bords latéraux. Pas de marge horizontale, .page-main-wrap s'en
     charge. */
  margin: var(--attentive-page-gutter) 0 var(--attentive-page-gutter) !important;
  border-radius: 12px !important;
  padding: 12px 56px 12px 24px !important;
  color: var(--attentive-navy) !important;
  font-weight: 500;
}
.alert.success {
  background-color: var(--attentive-blue-pale) !important;
}
/* Disparition automatique (cf. autoDismissAlerts dans attentive-custom.js).
   Le natif anime `.alert.hiding` par un `margin-top: -4rem`, mais notre marge
   est en !important ci-dessus : elle neutraliserait ce glissement. On ajoute
   donc un fondu, qui fonctionne quelles que soient les marges. */
.alert {
  transition: margin-top 0.3s ease, opacity 0.3s ease !important;
}
.alert.hiding {
  opacity: 0;
}
.alert .close {
  position: absolute;
  top: 50%;
  right: 18px;
  transform: translateY(-50%);
  margin: 0;
}

/* ============================================================
   BOÎTES SIGN IN / SIGN OUT (templates account/login.html &
   account/logout.html — même structure .user-action-form-inner,
   donc stylées et uniformisées ensemble).
   ============================================================ */
.user-action-form-wrap {
  padding-right: 0 !important;         /* recentrer la carte */
  margin: 3.5em 1em 2em !important;
}
.user-action-form-inner {
  max-width: 460px !important;
  padding: 2.5em 2.5em 2em !important;
  border-radius: 16px !important;
  box-shadow: 0 10px 30px rgba(5, 26, 38, 0.10) !important;
}
/* Picto SOLEM rond en haut de la carte */
.user-action-form-inner::before {
  content: "";
  display: block;
  width: 56px;
  height: 56px;
  margin: 0 auto 1.2em;
  border-radius: 50%;
  background: url("/static/favicons/android-chrome-192x192.png") center/cover no-repeat;
}
.user-action-form-inner h1 {
  text-align: center;
  font-weight: 700 !important;
  color: var(--attentive-navy);
  border-bottom: 0 !important;
  padding-bottom: 0 !important;
  margin-bottom: 0.25em !important;
}
.user-action-form-inner h1 + p,
.user-action-form-inner > p {
  text-align: center;
  color: var(--attentive-muted);
}
/* Champs de saisie arrondis */
.user-action-form-inner input[type="text"],
.user-action-form-inner input[type="email"],
.user-action-form-inner input[type="password"] {
  height: 44px;
  padding: 0 16px !important;
  border: 1px solid var(--attentive-border) !important;
  border-radius: 10px !important;
  background: var(--attentive-surface) !important;
}
.user-action-form-inner input[type="text"]:focus,
.user-action-form-inner input[type="email"]:focus,
.user-action-form-inner input[type="password"]:focus {
  border-color: var(--attentive-blue) !important;
  outline: none !important;
  box-shadow: 0 0 0 3px rgba(40, 121, 179, 0.15) !important;
}
/* Bouton principal : bleu SOLEM plein, arrondi, pleine largeur */
.user-action-form-inner form *[type="submit"],
.user-action-form-inner form .primaryAction {
  width: 100%;
  background-color: var(--attentive-blue) !important;
  color: #fff !important;
  border: 0 !important;
  border-radius: 10px !important;
  font-weight: 600;
  padding: 0.9em 2em !important;
}
.user-action-form-inner form *[type="submit"]:hover,
.user-action-form-inner form .primaryAction:hover {
  background-color: var(--attentive-blue-dark) !important;
}
/* Bouton secondaire (Cancel) : fantôme, pour uniformiser Sign Out */
.user-action-form-inner form .secondaryAction {
  display: block;
  float: none !important;   /* natif = float:right => sortait de la carte */
  width: 100%;
  text-align: center;
  background: transparent !important;
  color: var(--attentive-muted) !important;
  border: 1px solid var(--attentive-border) !important;
  border-radius: 10px !important;
  margin: 0.5em 0 0 !important;
}

/* ============================================================
   PAGE DE CONNEXION — maquette Attentive.
   Carte sombre centrée : logo, « Bienvenue », deux champs en pilule à
   étiquette flottante (technique fieldset/legend, qui interrompt la bordure
   au lieu de la masquer — indispensable sur un fond translucide), lien mot de
   passe oublié, bouton pleine largeur, sélecteur de langue.
   ============================================================ */
body.attentive-auth-page {
  min-height: 100vh;
  background:
    radial-gradient(90% 75% at 90% 100%,
      #1c6ca4 0%, #18649a 10%, #0f5383 20%, #064069 30%,
      #013254 40%, #002844 50%, #002137 60%, #021d2e 70%,
      rgba(5, 26, 38, 0) 88%),
    #060c18;
  background-attachment: fixed;
  color: #fff;
}
body.attentive-auth-page .page-main-wrap {
  padding: 0 !important;
  margin: 0 !important;
  min-height: 100vh;
}
.attentive-auth {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 40px 20px;
  box-sizing: border-box;
}
/* --- la carte --- */
.attentive-auth-card {
  width: 100%;
  max-width: 520px;
  box-sizing: border-box;
  padding: 48px 56px 40px;
  background: rgba(9, 16, 30, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 32px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.attentive-auth-logo {
  display: block;
  width: 70%;
  max-width: 340px;
  height: auto;
  margin: 0 auto 52px;
}
.attentive-auth-title {
  margin: 0 0 30px;
  font-size: 40px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: #fff;
}
.attentive-auth-errors {
  margin: 0 0 20px;
  padding: 12px 18px;
  border-radius: 16px;
  background: rgba(220, 38, 38, 0.14);
  border: 1px solid rgba(248, 113, 113, 0.5);
  color: #fecaca;
  font-size: 14px;
}
.attentive-auth-errors p { margin: 0; }
.attentive-auth-errors p + p { margin-top: 4px; }

/* --- champ en pilule à étiquette flottante --- */
.att-field {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  height: 58px;
  padding: 0 22px;
  margin: 0 0 18px;
}
.att-field-icon {
  font-family: "Material Symbols Outlined";
  font-variation-settings: "wght" 300;
  font-size: 24px;
  line-height: 1;
  color: #e3ecf8;
  flex: 0 0 auto;
  z-index: 1;
}
.att-field input {
  flex: 1 1 auto;
  min-width: 0;
  /* Pas de height:100% : l'input couvrirait toute la hauteur du champ et son
     fond (notamment le remplissage automatique du navigateur) masquerait la
     bordure et l'étiquette. Il se dimensionne sur sa ligne de texte. */
  border: 0;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 17px;
  font-weight: 400;
  outline: none;
  z-index: 1;
}
.att-field input::placeholder { color: transparent; }
.att-field input:-webkit-autofill,
.att-field input:-webkit-autofill:focus {
  -webkit-text-fill-color: #fff;
  -webkit-box-shadow: 0 0 0 1000px #0b1220 inset;
  caret-color: #fff;
}
/* La bordure est un <fieldset> : sa <legend> « perce » le trait pour laisser
   passer l'étiquette, ce qu'un fond opaque ne pourrait pas faire ici. */
.att-field fieldset {
  position: absolute;
  /* Décalage de -6px : le <legend> réserve 11px en haut du fieldset et le
     navigateur trace le trait supérieur au MILIEU de cette bande. Sans cette
     compensation, la bordure descend sous l'étiquette flottante au lieu de
     passer derrière elle. */
  inset: -6px 0 0 0;
  margin: 0;
  /* 26px et non 14 : avec un rayon de 29px, la bordure est encore dans l'arc
     du coin avant cette abscisse. Une encoche placée plus à gauche découpe la
     courbe, et le trait semble alors passer sur l'étiquette. */
  padding: 0 26px;
  pointer-events: none;
  border: 1px solid #5c86c4;
  border-radius: 29px;
  background: rgba(8, 13, 24, 0.55);
  transition: border-color 0.15s ease;
}
.att-field fieldset legend {
  /* `display:block`, `float:unset` et `overflow:hidden` sont indispensables :
     sans eux, le moteur ignore le max-width et l'encoche reste ouverte en
     permanence — la bordure paraît alors trouée en haut à gauche. */
  display: block;
  float: unset;
  overflow: hidden;
  width: auto;
  max-width: 0.01px;              /* replié tant que le champ est vide */
  padding: 0;
  height: 11px;
  line-height: 11px;
  font-size: 13px;
  visibility: hidden;
  white-space: nowrap;
  transition: max-width 0.12s ease;
}
.att-field fieldset legend span {
  display: inline-block;
  padding: 0 7px;
  opacity: 0;
  color: #cddcef;
  transition: opacity 0.12s ease;
}
/* L'étiquette flottante EST le texte du <legend>. C'est le navigateur qui le
   positionne et qui interrompt la bordure autour : alignement exact par
   construction, sans valeur magique à ajuster. L'élément <label> ne sert plus
   qu'à l'état « champ vide », où il joue le rôle de placeholder. */
.att-field input:focus ~ fieldset legend span,
.att-field input:not(:placeholder-shown) ~ fieldset legend span {
  visibility: visible;
  opacity: 1;
}
/* Placeholder dans le champ, qui s'efface dès que le legend prend le relais */
.att-field label {
  position: absolute;
  left: 58px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 17px;
  color: #9fb3cd;
  pointer-events: none;
  transition: opacity 0.12s ease;
  z-index: 1;
}
.att-field input:focus ~ label,
.att-field input:not(:placeholder-shown) ~ label {
  opacity: 0;
}
.att-field input:focus ~ fieldset legend,
.att-field input:not(:placeholder-shown) ~ fieldset legend {
  max-width: 100%;
}
.att-field input:focus ~ fieldset { border-color: #8fb6ea; }
/* bouton œil du mot de passe */
.att-eye {
  flex: 0 0 auto;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;   /* toute la hauteur du champ => centrage fiable */
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: #cddcef;
  cursor: pointer;
  font-family: "Material Symbols Outlined";
  font-variation-settings: "wght" 300;
  font-size: 24px;
  line-height: 1;
}
.att-eye:hover { color: #fff; }

.att-forgot {
  display: inline-block;
  margin: 4px 0 30px;
  color: #7fb3f5;
  font-size: 15px;
  text-decoration: none;
}
.att-forgot:hover { text-decoration: underline; }

.attentive-auth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 58px;
  box-sizing: border-box;
  border: 0;
  border-radius: 29px;
  background: #0f6fe5;
  color: #fff;
  font-family: inherit;
  font-size: 17px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.attentive-auth-btn:hover { background: #1a7cf0; }
/* Bouton secondaire (Annuler) : même gabarit, en contour */
.attentive-auth-btn--ghost {
  margin-top: 14px;
  background: transparent;
  border: 1px solid #5c86c4;
  color: #cddcef;
  font-weight: 500;
  text-decoration: none;
}
.attentive-auth-btn--ghost:hover { background: rgba(92, 134, 196, 0.14); color: #fff; }
/* Paragraphe d'explication sous le titre */
.att-lead {
  margin: -14px 0 28px;
  font-size: 15px;
  font-weight: 300;
  line-height: 1.5;
  color: #9fb3cd;
}
.att-lead a { color: #7fb3f5; }
.att-lead--footer {
  margin: 26px 0 0;
  text-align: center;
}

/* --- sélecteur de langue --- */
.att-lang {
  display: flex;
  justify-content: center;
  margin: 40px 0 0;
}
.att-lang-inner {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 16px;
  border: 1px solid #5c86c4;
  border-radius: 22px;
}
.att-lang select {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 15px;
  padding-right: 18px;
  outline: none;
  cursor: pointer;
}
.att-lang select option { background: #0b1220; color: #fff; }
.att-lang-chevron {
  position: absolute;
  right: 14px;
  pointer-events: none;
  font-family: "Material Symbols Outlined";
  font-variation-settings: "wght" 300;
  font-size: 20px;
  color: #cddcef;
}

/* --- bulles de messages ---
   Elles sont injectées par root.html AVANT le bloc de contenu, donc dans le
   flux : elles décalaient la carte vers le bas. On les sort du flux
   (position: fixed) pour que la carte reste centrée quoi qu'il arrive.
   Les rares cas à plusieurs messages sont décalés à la main. */
body.attentive-auth-page .alert {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  width: calc(100% - 40px);
  max-width: 520px;
  margin: 0 !important;
  background: rgba(9, 16, 30, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: #fff;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
body.attentive-auth-page .alert + .alert { top: 88px; }
body.attentive-auth-page .alert + .alert + .alert { top: 160px; }
/* .hiding conserve son fondu : la marge négative du natif est neutralisée
   par le margin:0 ci-dessus, l'opacité suffit. */
body.attentive-auth-page .alert.hiding { transform: translateX(-50%); }

@media (max-width: 560px) {
  .attentive-auth-card { padding: 32px 24px 28px; border-radius: 24px; }
  .attentive-auth-title { font-size: 32px; }
  .attentive-auth-logo { margin-bottom: 36px; }
}

/* « À suivre » : retirer la colonne quand elle n'a rien à montrer
   ---------------------------------------------------------------
   Un média en mode « À suivre » désactivé, ou en sélection manuelle vide,
   renvoie `related_media: []`. Les composants AutoPlay et RelatedMedia ne
   rendent alors rien, mais leur conteneur `.viewer-sidebar` reste en place et
   garde son tiers de largeur : le média se retrouve collé à une colonne vide.

   Fait ici en CSS, et non dans le bundle React comme sur SOLEM : ce dépôt ne
   versionne pas le bundle (cf. la fin de .gitignore), donc une modification de
   `frontend/src` n'atteindrait jamais la production. `:empty` ne vise que le
   cas voulu — avec une playlist en cours, la sidebar contient PlaylistView. */
.viewer-sidebar:empty {
  display: none;
}

.viewer-section:has(.viewer-sidebar:empty) .viewer-container,
.viewer-section:has(.viewer-sidebar:empty) .viewer-info {
  width: 100%;
}

/* Sans colonne, on revient à la largeur « normale » : le mode large (1754px)
   étirerait le lecteur sur toute la page. Le mode cinéma garde la sienne. */
.viewer-section:has(.viewer-sidebar:empty):not(.theater-mode) {
  max-width: 1328px;
}

/* Retraits d'interface faits en CSS, faute de bundle versionné
   -----------------------------------------------------------
   Les trois blocs ci-dessous sont codés en dur dans le bundle React : aucun
   drapeau de `templates/config/installation/` ne les pilote. Ce dépôt ne
   versionne pas `static/js/_commons.js` (cf. la fin de .gitignore), donc une
   modification de `frontend/src` n'atteindrait jamais la production — même
   raisonnement que pour la colonne « À suivre » plus haut. */

/* 1. Sidebar : retirer « Contact ».
   Le lien est poussé sans condition par CustomMenuSection
   (SidebarNavigationMenu.jsx), au même titre qu'« À propos », « Conditions »
   et « Langue ». La page /contact reste servie : seule l'entrée de menu part.
   Le nœud demeure dans le DOM, ce qui laisse intact le réordonnancement
   Contact → Conditions d'attentive-custom.js (arrange()). */
.page-sidebar .nav-item-contact {
  display: none;
}

/* 2. Page de profil : ne garder que l'onglet « Playlists ».
   ProfilePagesHeader rend chaque onglet via InlineTab, qui ignore la prop `id`
   et ne pose ni classe ni identifiant sur le <li> : le seul discriminant est
   le href. Plutôt que d'énumérer « À propos », « Médias que je possède »,
   « Partagé par moi » et « Partagé avec moi » — dont le premier n'a pour URL
   que la racine du profil, /user/<nom>, sans suffixe à cibler — on masque tout
   onglet dont le lien ne mène pas aux playlists. La règle couvre donc aussi
   les onglets qu'une version ultérieure ajouterait.
   `> li:has(> a)` épargne les <li> sans lien direct : la loupe de recherche
   (.media-search) et le bouton de filtres (.media-filters-toggle).
   ⚠️ S'applique aussi au profil d'un autre membre, où il ne restera donc que
   ses playlists — la liste de ses médias reste atteignable par son URL et par
   les liens d'auteur des cartes. */
.profile-nav .items-list-wrap > li:has(> a):not(:has(> a[href*="/playlists"])) {
  display: none;
}

/* 3. Page média : retirer les commentaires.
   CommentsList est monté sans condition par ViewerInfoContent, et le
   formulaire ne dépend que de `media.enable_comments`, drapeau posé média par
   média — rien ne le coupe globalement. `.comments-list` est le conteneur
   unique du bloc (en-tête, formulaire et fil) et n'est employé nulle part
   ailleurs. Le POST, lui, est refusé côté serveur par CAN_COMMENT
   (deploy/docker/local_settings.py) : ce masquage n'est que la moitié
   visible. */
.comments-list {
  display: none;
}

/* 4. Pages de profil : retirer l'en-tête quand le hero dit déjà la même chose.
   `.profile-page-header` (bannière, avatar, nom, barre d'onglets) est monté
   sans condition par ProfilePagesHeader. Or la règle 2 ci-dessus a réduit la
   barre à un seul onglet, « Playlists », et attentive-custom.js pose au-dessus
   un hero qui annonce déjà « Vos contenus / Mes playlists » : le bloc ne fait
   plus que répéter, pour 193px de hauteur sur téléphone et 396px sur desktop.

   Le `:has()` est ce qui rend le masquage sûr. Le hero n'est injecté que si un
   item de la sidebar est actif, c'est-à-dire sur SES propres pages. Sur le
   profil d'un autre membre (/user/<nom>/playlists, atteignable par le lien
   d'auteur d'une carte), il n'y en a pas : l'en-tête reste, et avec lui
   l'avatar et le nom — la seule indication de qui on regarde. Le hero est bien
   enfant direct de .page-main : `.page-main-inner` n'existe pas sur les pages
   React, et injectHero() retombe alors sur .page-main (insertBefore firstChild).

   Sur l'onglet Playlists, le bloc ne porte aucun contrôle : la barre de
   recherche est exclue pour `type === 'playlists'`, et les bascules filtres /
   partage / tags / tri sont réservées à media, shared_by_me et shared_with_me.
   Le `ref` React du conteneur n'est lu par aucun calcul de position.

   ⚠️ Il porte en revanche le crayon d'édition de la bannière et du profil, qui
   n'a pas d'autre accès visible : le menu utilisateur ne propose que « My
   media », le thème et la déconnexion. Retrait assumé — à rétablir ailleurs si
   l'édition de profil redevient utile. */
.page-main:has(> .attentive-hero) .profile-page-header {
  display: none;
}

/* 3. Pages de profil : rendre le fond de contenu au reste de la page.
   MediaCMS peint `.page-main` en blanc sur ces pages (_commons.css, via
   `--profile-page-bg-color`, que ce thème fixe plus haut à la couleur de
   surface) parce qu'elles y posaient la bannière, l'avatar et les onglets.
   Le bloc 2 ci-dessus les ayant retirés, il ne reste qu'un grand aplat blanc
   sur lequel le hero flotte — et ses coins arrondis laissent voir ce blanc au
   lieu du fond de page, ce qui les fait lire comme des coins carrés.
   On reprend ici le choix que MediaCMS fait déjà lui-même en mode sombre, où
   la variable retombe sur `var(--body-bg-color)`.

   C'est bien la VARIABLE qu'on redéfinit, et non la seule `background-color` :
   `--profile-page-bg-color` sert aussi à `.profile-page-content` (le
   conteneur interne), à son `:before` — qui prolonge l'aplat vers la gauche
   pendant l'animation de la sidebar — et au fond des titres de cartes. Une
   surcharge de `background-color` sur le seul `.page-main` laissait donc un
   rectangle blanc au milieu. Posée sur `.page-main`, la variable est héritée
   par tous ces descendants.

   Même condition que le bloc 2 : uniquement là où le hero a remplacé
   l'en-tête. Sur le profil d'un autre membre, l'en-tête reste affiché et
   l'aplat blanc garde son rôle. Un ID + deux classes l'emportent sur la règle
   native (un ID, une classe), sans !important. */
#page-profile-about .page-main:has(> .attentive-hero),
#page-profile-media .page-main:has(> .attentive-hero),
#page-profile-playlists .page-main:has(> .attentive-hero),
#page-profile-shared-by-me .page-main:has(> .attentive-hero),
#page-profile-shared-with-me .page-main:has(> .attentive-hero),
#page-liked.profile-page-liked .page-main:has(> .attentive-hero),
#page-history.profile-page-history .page-main:has(> .attentive-hero) {
  --profile-page-bg-color: var(--body-bg-color);
}

/* ============================================================
   ============================================================
   RESPONSIVE — tablette et téléphone
   ============================================================

   Tout ce bloc est en `max-width` : à 1024px et au-delà, rien n'y déclenche.
   Le rendu desktop validé avec la maquette est donc inchangé, y compris sur
   les petits portables (1280px garde ses 5 vignettes par ligne). Vérifié par
   comparaison des rendus, identiques au pixel près à 1024, 1280, 1440 et
   1920px — accueil, catégories, et sidebar ouverte.

   Points de rupture — ceux de MediaCMS, pas des nouveaux, pour que le thème
   bascule en même temps que le bundle :
     1023px  le natif masque la recherche du header (loupe + champ plein
             écran) et cesse d'ouvrir la sidebar automatiquement ;
      767px  le natif passe la sidebar en tiroir superposé et supprime le
             décalage du contenu.
   Deux paliers propres au thème complètent la série :
      559px  une seule carte de catégorie par ligne (voir § 1) ;
      400px  très petits écrans — logo et titre du hero encore réduits.

   Le thème desktop était écrit sans aucune requête média : toutes ses
   largeurs fixes (5 colonnes, vignette « À la une » de 320px, hero à 66%,
   recherche à 620px) s'appliquaient telles quelles à un écran de 402px.
   ============================================================ */

/* ------------------------------------------------------------
   1. GRILLES — densité par palier.
   Les règles de largeur (haut du fichier) ne font que lire ces variables :
   il n'y a qu'ici à toucher pour changer un nombre de colonnes.
   5 → 3 → 2 pour les médias ; 4 → 3 → 2 → 1 pour les cartes de catégorie.
   La gouttière se resserre en même temps, sinon elle mangerait la moitié
   de la largeur utile sur un téléphone.
   ------------------------------------------------------------ */
@media (max-width: 1023px) {
  body {
    --attentive-item-width:     calc((100% - 3 * 16px) / 3);
    --attentive-item-width-cat: calc((100% - 3 * 16px) / 3);
    --attentive-gutter: 16px;
    --attentive-gutter-y: 22px;
  }
}
@media (max-width: 767px) {
  body {
    --attentive-item-width:     calc((100% - 2 * 12px) / 2);
    --attentive-item-width-cat: calc((100% - 2 * 12px) / 2);
    --attentive-gutter: 12px;
    --attentive-gutter-y: 18px;
  }
}
/* Sous 560px, les cartes de catégorie (en-tête dégradé de 100px + titre 18px
   + deux lignes de description) deviennent illisibles à deux par ligne : on
   repasse à une carte pleine largeur. Les vignettes de médias, elles, restent
   à deux — un 16/9 de ~170px reste confortable et évite une page à rallonge. */
@media (max-width: 559px) {
  body { --attentive-item-width-cat: 100%; }
  /* Une seule colonne : la gouttière de droite n'a plus rien à séparer et
     décalait la carte de 12px vers la gauche. (`#page-categories .item`
     redéclare la marge en dur, d'où le sélecteur avec l'ID.) */
  #page-categories .media-list-wrapper.items-list-ver .media-list-row .item,
  #page-categories .item {
    margin-right: 0 !important;
  }
  /* Sans gouttière de fin à rattraper, la rangée reprend sa largeur exacte —
     sinon la compensation d'une gouttière (voir plus bas) élargirait la carte
     unique d'autant. L'ID l'emporte sur la règle générale, quel que soit
     l'ordre des deux blocs. */
  #page-categories .media-list-wrapper.items-list-ver .media-list-row {
    width: 100% !important;
    max-width: 100% !important;
  }
}

/* Gouttières de grille symétriques.
   Chaque carte porte sa marge à droite, y compris la dernière de la ligne :
   la grille se retrouve décalée vers la gauche d'une gouttière entière
   (mesuré : 16px à gauche, 28px à droite). Sur desktop l'écart de 22px fait
   partie du rendu validé et n'est pas touché ; sur téléphone, où la gouttière
   utile est déjà réduite à 12px, on rattrape le débord en élargissant la
   rangée d'une gouttière : elle mord sur la gouttière de page, jamais au-delà
   (20px de gouttière pour 12px de débord ; 16px pour 12px sous 400px).
   Une marge négative ne suffirait pas : ces rangées ont `width: 100%` ET
   `max-width: 100%` en !important plus haut — il faut relever les deux.
   Les sélecteurs reprennent ceux de ces règles, sans quoi elles l'emporteraient. */
@media (max-width: 767px) {
  /* MediaCMS ne rend les items `inline-block` qu'à partir de 600px
     (`@media(min-width: 600px)` dans _commons.css) : en dessous ils sont
     `display: block` et occupent une ligne entière, quelle que soit la
     largeur qu'on leur calcule. Entre 560 et 599px, les cartes de catégorie
     se retrouvaient donc seules sur leur ligne ET à demi-largeur ; les
     grilles de médias hors accueil avaient le même sort en dessous de 600px.
     On passe la rangée en flex — ce que le thème fait déjà pour les rangées
     de l'accueil — et le display des enfants cesse de compter.
     `align-items: flex-start` conserve la hauteur naturelle des cartes :
     l'égalisation, quand elle est utile, vient du `min-height` réservé sous
     la description. */
  body:not(.attentive-home) .media-list-wrapper.items-list-ver .media-list-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
  }

  body:not(.attentive-home) .media-list-wrapper.items-list-ver .media-list-row,
  body.attentive-home .attentive-cat-row .media-list-wrapper.items-list-ver .media-list-row {
    width: calc(100% + var(--attentive-gutter)) !important;
    max-width: calc(100% + var(--attentive-gutter)) !important;
  }
}

/* ------------------------------------------------------------
   2. EN-TÊTE — logo, menu, recherche.
   ------------------------------------------------------------ */
@media (max-width: 1023px) {
  /* Le natif réserve 104px à droite du bloc de gauche ; le thème ajoutait
     20px à gauche, ce qui suffisait à faire chevaucher le lockup
     « ATTENTIVE studio » et le bouton de menu.
     Sous 768px, le § 3 reprend ce retrait pour l'aligner sur la gouttière
     de page — ne pas régler la valeur ici sans y regarder. */
  .page-header-left > div {
    padding-left: 8px !important;
    min-width: 0;
  }
  .logo,
  .logo a,
  .logo a span {
    min-width: 0;
  }
  .logo img {
    max-width: 100%;
  }
}

@media (max-width: 767px) {
  /* Logo plus compact : les 40px du desktop (déclarés plus haut dans ce
     fichier — ils l'emportent sur les 36px de custom.css, chargé avant)
     débordaient de la barre une fois le bouton de menu à gauche et les deux
     boutons de droite en place. */
  body { --default-logo-height: 30px; }

  /* Le bouton devient le SEUL moyen d'ouvrir le menu (plus de sidebar
     permanente) : on lui rend le hamburger, affordance attendue sur
     téléphone, et on le place AVANT le logo comme partout ailleurs.
     Le chevron du desktop (replier/déplier) n'a plus de sens ici : le
     tiroir se ferme en touchant le voile noir. */
  .page-header-left > div > .toggle-sidebar {
    order: 0;
    margin-left: 0;
    margin-right: 2px;
  }
  .page-header-left > div > .logo {
    order: 1;
  }
  .toggle-sidebar .material-icons::before,
  body:not(.visible-sidebar) .toggle-sidebar .material-icons::before {
    content: "menu";
  }
}

@media (max-width: 400px) {
  /* iPhone SE / petits Android : le lockup complet ne tient plus à côté des
     trois boutons. On réduit encore plutôt que de tronquer. */
  body { --default-logo-height: 26px; }
}

/* ------------------------------------------------------------
   3. GOUTTIÈRE DE PAGE sur petits écrans.
   La gouttière elle-même est posée bien plus haut, sur .page-main-wrap :
   ici on ne fait que redéfinir sa valeur, et aligner l'en-tête dessus.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  body { --attentive-page-gutter: 20px; }

  /* Écart sous l'en-tête égal à la gouttière des côtés. Posé sur
     .page-main-wrap et non sur le hero : les pages sans hero (page média,
     recherche générale) démarraient sinon collées à la barre. Le
     `padding-top: var(--header-height)` natif est ce qui pousse le contenu
     sous l'en-tête fixe : on lui ajoute la gouttière, sans le remplacer. */
  .page-main-wrap {
    padding-top: calc(var(--header-height) + var(--attentive-page-gutter)) !important;
  }
  /* La marge haute du hero ferait doublon. Idem pour les bandeaux de
     message, premiers enfants de .page-main-wrap. */
  body .attentive-hero {
    margin-top: 0 !important;
  }
  /* Seule la marge HAUTE part : elle ferait doublon avec le padding ci-dessus.
     La marge basse, posée avec la règle générale, reste indispensable — le
     hero qui suit a vu la sienne annulée juste en dessous, la bulle se
     retrouverait sinon collée à lui. */
  .alert {
    margin-top: 0 !important;
  }

  /* En-tête aligné sur la même gouttière. Les pastilles rondes portent leur
     propre retrait optique (glyphe de 22px centré dans un bouton de 40px,
     vignette de 32px pour l'avatar) : on vise l'alignement du DESSIN, pas
     celui de la boîte, d'où des valeurs plus faibles que la gouttière. */
  .page-header-left > div {
    padding-left: 11px !important;
  }
  .page-header-right {
    padding-right: 16px !important;
  }
}
@media (max-width: 400px) {
  body { --attentive-page-gutter: 16px; }

  .page-header-left > div {
    padding-left: 7px !important;
  }
  .page-header-right {
    padding-right: 12px !important;
  }
}

/* ------------------------------------------------------------
   4. HERO.
   Le bandeau porte son propre `@media (max-width: 700px)` (injecté par
   attentive-hero.js), mais le thème le neutralisait : `body .attentive-hero
   .attentive-hero-content` (0,2,1) l'emporte sur `.attentive-hero
   .attentive-hero-content` (0,2,0), et le titre est en !important. Le texte
   restait donc bridé à 66 % et se superposait à l'illustration.
   On reprend la main ici, avec la même spécificité que le reste du thème.
   (Le fond — propre à la marque — est traité dans custom.css.)
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  body .attentive-hero {
    /* Même hauteur minimale que sur desktop : réduite à 0, la bande se
       refermait sur son texte et faisait maigre en tête de page. */
    min-height: 132px;
    padding: 26px 22px;
    margin-bottom: 20px !important;
    border-radius: 14px !important;
  }
  body .attentive-hero .attentive-hero-content {
    max-width: 100%;
  }
  body .attentive-hero .attentive-hero-eyebrow {
    font-size: 14px;
    margin-bottom: 5px;
  }
  body .attentive-hero .attentive-hero-title {
    font-size: 24px !important;
  }
}
@media (max-width: 400px) {
  body .attentive-hero {
    min-height: 118px;
    padding: 22px 18px;
  }
  body .attentive-hero .attentive-hero-title {
    font-size: 21px !important;
  }
}

/* ------------------------------------------------------------
   5. BLOC « À LA UNE ».
   En ligne, sa vignette fixe de 320px ne laissait que ~50px au texte : le
   titre tombait à un mot par ligne. On empile vignette puis texte.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .attentive-featured {
    flex-direction: column;
    gap: 12px;
    margin-bottom: 22px;
  }
  .attentive-featured-thumb {
    flex: 0 0 auto;
    max-width: none;
    width: 100%;
  }
  .attentive-featured-title {
    font-size: 19px;
  }
  .attentive-featured-desc {
    font-size: 14px;
    -webkit-line-clamp: 2;
  }
}

/* ------------------------------------------------------------
   6. EN-TÊTES DE SECTION (accueil).
   « Tout voir » passait à la ligne mot par mot faute d'espace : on le sort
   du flux du titre (poussé à droite, jamais coupé) et le titre garde le
   reste. Le `min-width: 0` autorise le titre à se couper lui-même plutôt
   qu'à imposer sa largeur minimale au conteneur flex.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  body.attentive-home .attentive-cat-row .media-list-header {
    margin-bottom: 10px;
  }
  body.attentive-home .attentive-cat-row .attentive-cat-headline {
    gap: 10px;
  }
  body.attentive-home .attentive-cat-row .media-list-header h2 {
    font-size: 17px;
    line-height: 1.25;
    min-width: 0;
  }
  body.attentive-home .attentive-cat-row .media-list-header h3 {
    flex: 0 0 auto;
    margin-left: auto;
  }
  body.attentive-home .attentive-cat-row .media-list-header h3 a {
    margin-left: 0;
    white-space: nowrap;
  }
  body.attentive-home .attentive-cat-row .attentive-cat-desc {
    margin-top: 2px;
    line-height: 1.4;
  }
  /* En-têtes de la page Catégories (Vidéos / Documentations). */
  .attentive-cat-head {
    font-size: 17px;
    margin: 10px 0 12px;
  }
}

/* ------------------------------------------------------------
   7. MÉTA DES CARTES DE MÉDIA.
   Le titre n'a rien à corriger : le natif le rend déjà en 14px/18px borné à
   deux lignes (--item-title-font-size / --item-title-line-height /
   --item-title-max-lines), ce qui reste juste à deux colonnes.
   Seule la ligne de méta demande un réglage : à 12px (valeur du thème), un
   « 63 vues • il y a 3 mois » ne tenait plus dans ~170px.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .item-meta,
  .item-meta * {
    font-size: 11px;
    line-height: 1.35;
  }
  /* Sur l'accueil, le créateur est le même pour toutes les vidéos du
     portail : il prenait une ligne entière pour une information nulle.
     Retiré des seules rangées de l'accueil — ailleurs (recherche, profil
     d'un membre) il peut distinguer deux comptes. */
  body.attentive-home .attentive-cat-row .item-meta .item-author {
    display: none;
  }
}

/* ------------------------------------------------------------
   8. PAGE CATÉGORIES — cartes plus basses sur téléphone.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  #page-categories .item .item-header {
    height: 76px;
    min-height: 76px;
  }
  #page-categories .item .item-header h3 {
    font-size: 16px;
    padding: 0 16px;
  }
  #page-categories .item .item-body {
    padding: 12px 16px 14px;
  }
  #page-categories .item .item-body .item-description {
    font-size: 14px;
  }
}
/* En colonne unique, la réserve de deux lignes sous la description n'a plus
   d'objet : elle sert à égaliser la hauteur des cartes d'une MÊME ligne. Une
   catégorie sans description gardait sinon un grand blanc. */
@media (max-width: 559px) {
  #page-categories .item .item-body .item-description {
    min-height: 0;
  }
  #page-categories .item .item-body .item-description:empty {
    margin-bottom: 0;
  }
}

/* ------------------------------------------------------------
   9. SIDEBAR EN TIROIR.
   Sous 768px elle se superpose au contenu : elle a besoin d'une largeur
   qui laisse voir le voile derrière (repère « je peux fermer en touchant
   à côté »), et de cibles tactiles d'au moins 44px.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .page-sidebar {
    --sidebar-width: min(280px, 82vw);
    width: var(--sidebar-width);
  }
  /* 46px de haut : au-dessus des 44px recommandés pour une cible tactile, et
     assez proche des 42px natifs pour que la liste complète (13 entrées)
     tienne encore sans défilement sur un écran de 874pt. Le `min-height`
     natif n'est pas contraignant — la hauteur vient de la `line-height` —
     d'où le passage en flex, qui recentre le libellé et l'icône. */
  .nav-menu li.link-item a {
    display: flex;
    align-items: center;
    min-height: 46px;
    line-height: 1.2;
  }
  .nav-menu li.attentive-nav-section-title {
    padding: 14px 20px 6px;
  }
}

/* ------------------------------------------------------------
   10. GARDE-FOU — pas de débordement horizontal.
   Un seul élément trop large rend TOUTE la page décalable latéralement, et
   l'en-tête, lui, est fixe : on obtient le contenu coupé à gauche des
   captures d'origine. Les deux causes ici étaient des largeurs fixes (§ 1,
   § 2, § 5) ; ce qui suit ne traite que le reste, les textes sans espace
   (titres de médias, noms de fichiers) et les boîtes flex qui refusent de
   passer sous leur largeur minimale de contenu.

   Volontairement PAS d'`overflow-x: hidden` sur html/body : il masquerait un
   futur débordement au lieu de le corriger, et surtout il rendrait
   inatteignables les tableaux larges des pages d'administration, qui ont
   besoin, eux, de défiler horizontalement.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .page-main,
  .page-main-inner,
  .attentive-featured-body {
    min-width: 0;
    max-width: 100%;
  }
  .media-list-wrapper,
  .media-list-row {
    min-width: 0;
  }
  .attentive-featured-title,
  .item-main h3,
  .media-list-header h2 {
    overflow-wrap: anywhere;
  }
}

/* ------------------------------------------------------------
   11. PAGE MÉDIA sur téléphone.
   Sur desktop la page média est exclue de la gouttière : son
   `.viewer-section` se centre dans 1328px et porte ses propres retraits
   (cf. « GOUTTIÈRE DE PAGE »). Sur téléphone il n'y a ni centrage ni
   largeur maximale : le lecteur touchait les deux bords alors que tout le
   reste du site est à --attentive-page-gutter, et le titre juste en dessous
   s'alignait sur 16px. On lui applique donc la même gouttière qu'ailleurs.
   Le lecteur y gagne ses coins arrondis (border-radius: 10px natif), qui ne
   se voyaient pas bord à bord.

   ⚠️ C'est un choix : un lecteur pleine largeur est la convention sur
   téléphone (il gagne ici ~22px de hauteur d'image). Pour y revenir, retirer
   le seul bloc `.page-main-wrap:has(...)` ci-dessous — le reste des règles
   ne fait que neutraliser des retraits natifs qui doubleraient la gouttière.
   ------------------------------------------------------------ */
@media (max-width: 767px) {
  .page-main-wrap:has(> [id^="page-media"]) {
    padding-left: var(--attentive-page-gutter) !important;
    padding-right: var(--attentive-page-gutter) !important;
  }

  /* MediaCMS ne pose l'arrondi du lecteur qu'à partir de 480px
     (`@media screen and (min-width: 480px)` dans media.css) : en dessous, il
     restait à angles vifs au milieu d'une page où tout le reste est arrondi.
     Le `overflow` qui le rend effectif est posé plus haut, hors requête. */
  .viewer-container .player-container {
    border-radius: 10px;
  }

  /* Retraits natifs qui s'ajouteraient à la gouttière :
     .media-title-banner = 20px 12px 0 16px, .viewer-sidebar = 12px 16px 24px. */
  .media-title-banner {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .viewer-sidebar {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
}
